pwm设备驱动

前文有说到软件侧背光的控制过程,
通常的背光,硬件层都是通过pwm来调节的.
本文理下pwm驱动,

pwm也和设备驱动模型一样的思路,分控制器host设备和具体的device驱动,其中驱动又分设备驱动层和驱动核心层.同时又区别与设备模型(没有device, bus,driver中的bus)
pwm设备相当于资源的提供者(supplier),背光相当于pwm的消费者(customer)
本文重点放在pwm设备端(包括设备,以及这个平台设备本身对应的驱动)

pwm本质上是一种通信协议,类似于i2c,spi,usb,
平台设备驱动(分核心层和host device driver层)的意义,一方面是提供通用的接口供外设设备(customer)使用,比如pwm_enable,pwm_disable,另一方面,为host device的驱动(一个soc,可能又多路pwm)开发提供通用的方法和api,内部实现具体逻辑,屏蔽技术细节.
对外部使用pwm协议的设备来说,需要获取设备,需要设置pwm设备的频率,极性,开关等.即:pwm_get,pwm_enable/disable,pwm_config,pwm_set_polarity.

pwm设备再dts中的定义,以pwm0为例

pwm0: pwm@ff680000 {
	compatible = "rockchip,rk3288-pwm";
	reg = <0x0 0xff680000 0x0 0x10>;
	#pwm-cells = <3>;
	pinctrl-names = "active";
	pinctrl-0 = <&pwm0_pin>;
	clocks = <&cru PCLK_PWM>;
	clock-names = "pwm";
	status = "disabled";
};

pwm设备驱动:kernel/driver/pwm/pwm-rockchip.c
static struct platform_driver rockchip_pwm_driver = {
.driver = {
.name = “rockchip-pwm”,
.of_match_table = rockchip_pwm_dt_ids,
},
.probe = rockchip_pwm_probe,
.remove = rockchip_pwm_remove,
};
由此也可以看出,pwm也platform_device,遵循设备驱动模型,

对于pwm 控制器驱动核心层:linux/driver/pwm/core.c
Linux用pwm_chip抽象之,用pwm_ops抽象pwm host的控制方法
.
struct pwm_ops {
int (*request)(struct pwm_chip *chip, struct pwm_device *pwm);
void (*free)(struct pwm_chip *chip, struct pwm_device *pwm);
int (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns);
int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm,
enum pwm_polarity polarity);
int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_capture *result, unsigned long timeout);
int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm);
void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm);
int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state);
void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state);
#ifdef CONFIG_DEBUG_FS
void (*dbg_show)(struct pwm_chip *chip, struct seq_file *s);
#endif
struct module *owner;
};

在probe pwm platform_device(pwm_chip)的时候,赋值设备的chip.ops变量,

对于pwm device设备(以backlight为例)(只关心背光子系统的pwm部分,其本身的背光控制部分,单独分析)
pwm在device端的设备中的定义,
backlight: backlight {
pwms = <&pwm0 0 25000 0>;
};
static int pwm_backlight_probe(struct platform_device *pdev)
{

pb->pwm = devm_pwm_get(&pdev->dev, NULL);
if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER && !node) {
dev_err(&pdev->dev, “unable to request PWM, trying legacy API\n”);
pb->legacy = true;
pb->pwm = pwm_request(data->pwm_id, “pwm-backlight”);
}
pwm_adjust_config(pb->pwm);
bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
&pwm_backlight_ops, &props);

}
由上面代码可知,pwm device 驱动,先是解析了dts中的pwms,根据pwm_id,申请pwm host 资源,然后把这个pwm作为bl的一个背光设备的变量,随背光设备注册到背光子系统中.注册的时候,带入了背光的回调函数.然后在背光的回调函数里面,通过pwm_config,再去设备pwm的占空比等,从而控制背光亮暗.
在背光的开关函数中,通过pwm_enable,pwm_disable控制pwm的开关.
static int pwm_backlight_update_status(struct backlight_device *bl)
{

if (brightness > 0) {
duty_cycle = compute_duty_cycle(pb, brightness);
pwm_config(pb->pwm, duty_cycle, pb->period);
pwm_backlight_power_on(pb, brightness);
} else

}
static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness)
{

pwm_enable(pb->pwm);

}
static void pwm_backlight_power_off(struct pwm_bl_data *pb)
{

pwm_config(pb->pwm, 0, pb->period);
pwm_disable(pb->pwm);

}

总之,pwm device端之驱动,利用pwm host端提供的pwm_op回调函数:pwm_get,pwm_request,pwm_config,pwm_enable,pwm_disable,等与pwm产品联系,利用pwm的资源.

Linux 驱动交流:QQ:1617890720

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九月天-深圳专业软硬件开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值