PWM 驱动简析
设备树 PWM 控制器节点
I.MX6ULL 有 8 路 PWM 输出,因此对应 8 个 PWM 控制器,所有在设备树下就有 8 个PWM 控制器节点。这 8 路 PWM 都属于 I.MX6ULL 的 AIPS-1 域,但是在设备树 imx6ull.dtsi 中分为了两部分, PWM1~PWM4 在一起, PWM5~PWM8 在一起,这 8 路 PWM 并没有全部放到一起,这一点一定要注意,不要以为 imx6ull.dtsi 没有写完整。这 8 路 PWM 的设备树节点内容都是一样的,除了 reg 属性不同(毕竟不同的控制器,其地址范围不同)。本章实验我们使用GPIO1_IO04 这个引脚来完成 PWM 实验,而 GPIO1_IO04 就是 PWM3 的输出引脚,所以这里我们就以 PWM3 为例进行讲解, imx6ull.dtsi 文件中的 pwm3 节点信息如下:
1 pwm3: pwm@02088000 {
2 compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
3 reg = <0x02088000 0x4000>;
4 interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
5 clocks = <&clks IMX6UL_CLK_PWM3>,
6 <&clks IMX6UL_CLK_PWM3>;
7 clock-names = "ipg", "per";
8 #pwm-cells = <2>;
9 };
第 2 行, compatible 属性值有两个“fsl,imx6ul-pwm”和“fsl,imx27-pwm”,所以在整个 Linux源码里面搜索这两个字符窜即可找到 I.MX6ULL 的 PWM 驱动文件,这个文件就是drivers/pwm/pwm-imx.c。
关 于 I.MX6ULL 的 PWM 节 点 更 为 详 细 的 信 息 请 参 考 对 应 的 绑 定 文 档 :Documentation/devicetree/bindings/pwm/ imx-pwm.txt,这里就不去分析了。
PWM 子系统
Linux 内核提供了个 PWM 子系统框架,编写 PWM 驱动的时候一定要符合这个框架。 PWM子系统的核心是 pwm_chip 结构体,定义在文件 include/linux/pwm.h 中,定义如下:
1 struct pwm_chip {
2 struct device *dev;
3 struct list_head list;
4 const struct pwm_ops *ops;
5 int base;
6 unsigned int npwm;
7 struct pwm_device *pwms;
8 struct pwm_device * (*of_xlate)(struct pwm_chip *pc,
9 const struct of_phandle_args *args);
10 unsigned int of_pwm_n_cells;
11 bool can_sleep;
12 };
第 4 行, pwm_ops 结构体就是 PWM 外设的各种操作函数集合,编写 PWM 外设驱动的时候需要开发人员实现。 pwm_ops 结构体也定义在 pwm.h 头文件中,定义如下:
1 struct pwm_ops {
2 int (*request)(struct pwm_chip *chip, //请求 PWM
3 struct pwm_device *pwm);
4 void (*free)(struct pwm_chip *chip, //释放 PWM
5 struct pwm_device *pwm);
6 int (*config)(struct pwm_chip *chip, //配置 PWM 周期和占空比
7