瑞芯微 MIPI D-PHY 接收器(RX)驱动学习笔记
驱动文件位置 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;