驅動文件位置 driver/phy/rockchip/phy-rockchip-mipi-rx.c
1 重要結構體
struct mipidphy_priv {struct device *dev;//表示與驅動程序關聯的設備。它用于設備管理,如設備注冊、注銷等。struct regmap *regmap_grf;//用于映射和訪問通用寄存器文件(General Register File,GRF)的寄存器。regmap 提供了一種靈活的寄存器訪問接口const struct dphy_reg *grf_regs;//包含了GRF寄存器的定義和布局const struct txrx_reg *txrx_regs;//包含了TX/RX通道寄存器的定義和布局const struct csiphy_reg *csiphy_regs;//包含了CSI PHY寄存器的定義和布局void __iomem *csihost_base_addr;//這是一個指向內存映射I/O區域的指針,表示CSI主機接口的基地址struct clk *clks[MAX_DPHY_CLK];//這是一個指向時鐘結構體數組的指針,用于管理設備的所有時鐘資源。const struct dphy_drv_data *drv_data;//包含了驅動程序特定的數據和配置信息u64 data_rate_mbps;//表示設備支持的最大數據傳輸速率,單位是Mbps。struct v4l2_async_notifier notifier;//用于V4L2異步通知機制,允許設備在連接或斷開時發送通知。struct v4l2_subdev sd;//表示一個V4L2子設備,用于V4L2框架中的設備管理和媒體流控制。struct mutex mutex; /* lock for updating protection */struct media_pad pads[MIPI_DPHY_RX_PADS_NUM];//表示媒體設備的連接端口。MIPI_DPHY_RX_PADS_NUM 是端口數量的宏定義。struct mipidphy_sensor sensors[MAX_DPHY_SENSORS];//用于存儲和管理連接到MIPI DPHY的sensors信息int num_sensors;//表示當前連接到MIPI DPHY的sensors數量int phy_index;//bool is_streaming;//指示設備是否正在處理媒體流void __iomem *txrx_base_addr;//這是一個指向內存映射I/O區域的指針,表示TX/RX通道的基地址。int (*stream_on)(struct mipidphy_priv *priv, struct v4l2_subdev *sd);//該函數在開始媒體流傳輸時被調用int (*stream_off)(struct mipidphy_priv *priv, struct v4l2_subdev *sd);//該函數在停止媒體流傳輸時被調用
};
struct dphy_drv_data {const char * const *clks;//包含了設備所需的時鐘名稱。這些時鐘名稱用于在設備初始化時請求相應的時鐘資源。int num_clks;//表示 clks 數組中時鐘名稱的數量。const struct hsfreq_range *hsfreq_ranges;//包含了設備支持的高速頻率范圍。這些范圍定義了設備在不同工作模式下可以支持的時鐘頻率。int num_hsfreq_ranges;//表示 hsfreq_ranges 數組中高速頻率范圍的數量。const struct dphy_reg *grf_regs;//包含了設備通用寄存器(GRF)的定義和布局const struct txrx_reg *txrx_regs;//包含了設備TX/RX通道寄存器的定義和布局。const struct csiphy_reg *csiphy_regs;//包含了設備CSI PHY寄存器的定義和布局enum mipi_dphy_ctl_type ctl_type;//表示MIPI DPHY的控制類型。這個成員指示了設備應該如何被控制,例如,是通過硬件控制還是軟件控制void (*individual_init)(struct mipidphy_priv *priv);//這個函數在設備初始化時被調用,用于執行設備特定的初始化操作。enum mipi_dphy_chip_id chip_id;//表示MIPI DPHY芯片的ID。這個成員用于標識設備的具體型號或版本
};
2 rockchip_mipidphy_probe(struct platform_device *pdev)函數
??
?1 分配內存,匹配設備樹。
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);if (!priv)return -ENOMEM;priv->dev = dev;of_id = of_match_device(rockchip_mipidphy_match_id, dev);if (!of_id)return -EINVAL;
2 獲取 GRF(全局復用寄存器)
嘗試從父設備獲取 GRF 寄存器映射。
如果失敗,在當前設備的設備樹節點中查找一個名為 "rockchip,grf" 的 phandle。
將找到的 regmap 保存到 priv->regmap_grf 中。
形如:
some_device: some-device@... {
rockchip,grf = <&grf>;
};
grf = syscon_node_to_regmap(dev->parent->of_node);if (IS_ERR(grf)) {grf = syscon_regmap_lookup_by_phandle(dev->of_node,"rockchip,grf");if (IS_ERR(grf)) {dev_err(dev, "Can't find GRF syscon\n");return -ENODEV;}}priv->regmap_grf = grf;
3通過別名(alias)獲取 D-PHY 的索引號(例如 dphy0, dphy1)
priv->phy_index = of_alias_get_id(dev->of_node, "dphy");
if (priv->phy_index < 0)priv->phy_index = 0;
4?獲取時鐘資源
5?設置寄存器指針
priv->grf_regs = drv_data->grf_regs;
priv->txrx_regs = drv_data->txrx_regs;
priv->csiphy_regs = drv_data->csiphy_regs;
priv->drv_data = drv_data;
6?根據控制類型選擇操作函數和寄存器地址
CSI Host 模式:SoC 作為攝像頭控制器,連接并讀取攝像頭數據;
TX/RX 模式:SoC 作為通用的 MIPI D-PHY 收發器,可能用于其他用途(比如顯示、調試等);
if (drv_data->ctl_type == MIPI_DPHY_CTL_CSI_HOST) {res = platform_get_resource(pdev, IORESOURCE_MEM, 0);priv->csihost_base_addr = devm_ioremap_resource(dev, res);priv->stream_on = csi_mipidphy_stream_on;priv->stream_off = csi_mipidphy_stream_off;
} else {priv->stream_on = mipidphy_txrx_stream_on;priv->txrx_base_addr = NULL;res = platform_get_resource(pdev, IORESOURCE_MEM, 0);priv->txrx_base_addr = devm_ioremap_resource(dev, res);if (IS_ERR(priv->txrx_base_addr))priv->stream_on = mipidphy_rx_stream_on;priv->stream_off = NULL;
}
7?初始化 V4L2 子設備
sd = &priv->sd;
mutex_init(&priv->mutex);
v4l2_subdev_init(sd, &mipidphy_subdev_ops);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(sd->name, sizeof(sd->name), "rockchip-mipi-dphy-rx");
sd->dev = dev;
8?初始化媒體實體和電源管理
ret = rockchip_mipidphy_media_init(priv);
if (ret < 0)goto destroy_mutex;pm_runtime_enable(&pdev->dev);
drv_data->individual_init(priv);
return 0;