1 From 750fcf1df4414e0823100135a3ff7ea760d0fa86 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 19 Jan 2022 17:26:22 +0000
4 Subject: [PATCH] pwm: raspberrypi-poe: Add option of being created by
7 The firmware can only use I2C0 if the kernel isn't, therefore
8 with libcamera and DRM using it the PoE HAT fan control needs
11 Add the option for the driver to be created by the PoE HAT core
12 MFD driver, and use the I2C regmap that provides to control fan
15 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
17 drivers/pwm/pwm-raspberrypi-poe.c | 81 ++++++++++++++++++-------------
18 1 file changed, 48 insertions(+), 33 deletions(-)
20 --- a/drivers/pwm/pwm-raspberrypi-poe.c
21 +++ b/drivers/pwm/pwm-raspberrypi-poe.c
24 #include <linux/platform_device.h>
25 #include <linux/pwm.h>
26 +#include <linux/regmap.h>
28 #include <soc/bcm2835/raspberrypi-firmware.h>
29 #include <dt-bindings/pwm/raspberrypi,firmware-poe-pwm.h>
32 struct raspberrypi_pwm {
33 struct rpi_firmware *firmware;
35 + struct regmap *regmap;
39 unsigned int duty_cycle;
41 @@ -43,7 +48,7 @@ struct raspberrypi_pwm *raspberrypi_pwm_
42 return container_of(chip, struct raspberrypi_pwm, chip);
45 -static int raspberrypi_pwm_set_property(struct rpi_firmware *firmware,
46 +static int raspberrypi_pwm_set_property(struct raspberrypi_pwm *pwm,
49 struct raspberrypi_pwm_prop msg = {
50 @@ -52,17 +57,19 @@ static int raspberrypi_pwm_set_property(
54 - ret = rpi_firmware_property(firmware, RPI_FIRMWARE_SET_POE_HAT_VAL,
60 + if (pwm->firmware) {
61 + ret = rpi_firmware_property(pwm->firmware, RPI_FIRMWARE_SET_POE_HAT_VAL,
63 + if (!ret && msg.ret)
66 + ret = regmap_write(pwm->regmap, pwm->offset + reg, val);
73 -static int raspberrypi_pwm_get_property(struct rpi_firmware *firmware,
74 +static int raspberrypi_pwm_get_property(struct raspberrypi_pwm *pwm,
77 struct raspberrypi_pwm_prop msg = {
78 @@ -70,16 +77,17 @@ static int raspberrypi_pwm_get_property(
82 - ret = rpi_firmware_property(firmware, RPI_FIRMWARE_GET_POE_HAT_VAL,
89 - *val = le32_to_cpu(msg.val);
90 + if (pwm->firmware) {
91 + ret = rpi_firmware_property(pwm->firmware, RPI_FIRMWARE_GET_POE_HAT_VAL,
93 + if (!ret && msg.ret)
95 + *val = le32_to_cpu(msg.val);
97 + ret = regmap_read(pwm->regmap, pwm->offset + reg, val);
104 static int raspberrypi_pwm_get_state(struct pwm_chip *chip,
105 @@ -119,7 +127,7 @@ static int raspberrypi_pwm_apply(struct
106 if (duty_cycle == rpipwm->duty_cycle)
109 - ret = raspberrypi_pwm_set_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
110 + ret = raspberrypi_pwm_set_property(rpipwm, RPI_PWM_CUR_DUTY_REG,
113 dev_err(chip->dev, "Failed to set duty cycle: %pe\n",
114 @@ -146,28 +154,34 @@ static int raspberrypi_pwm_probe(struct
115 struct raspberrypi_pwm *rpipwm;
118 - firmware_node = of_get_parent(dev->of_node);
119 - if (!firmware_node) {
120 - dev_err(dev, "Missing firmware node\n");
124 - firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node);
125 - of_node_put(firmware_node);
127 - return dev_err_probe(dev, -EPROBE_DEFER,
128 - "Failed to get firmware handle\n");
130 rpipwm = devm_kzalloc(&pdev->dev, sizeof(*rpipwm), GFP_KERNEL);
134 - rpipwm->firmware = firmware;
135 + if (pdev->dev.parent)
136 + rpipwm->regmap = dev_get_regmap(pdev->dev.parent, NULL);
138 + if (rpipwm->regmap) {
139 + ret = device_property_read_u32(&pdev->dev, "reg", &rpipwm->offset);
143 + firmware_node = of_get_parent(dev->of_node);
145 + firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node);
146 + of_node_put(firmware_node);
148 + return dev_err_probe(dev, -EPROBE_DEFER,
149 + "Failed to get firmware handle\n");
151 + rpipwm->firmware = firmware;
154 rpipwm->chip.dev = dev;
155 rpipwm->chip.ops = &raspberrypi_pwm_ops;
156 rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM;
158 - ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
159 + ret = raspberrypi_pwm_get_property(rpipwm, RPI_PWM_CUR_DUTY_REG,
160 &rpipwm->duty_cycle);
162 dev_err(dev, "Failed to get duty cycle: %pe\n", ERR_PTR(ret));
163 @@ -179,6 +193,7 @@ static int raspberrypi_pwm_probe(struct
165 static const struct of_device_id raspberrypi_pwm_of_match[] = {
166 { .compatible = "raspberrypi,firmware-poe-pwm", },
167 + { .compatible = "raspberrypi,poe-pwm", },
170 MODULE_DEVICE_TABLE(of, raspberrypi_pwm_of_match);