aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0658-pwm-raspberrypi-poe-Add-option-of-being-created-by-M.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0658-pwm-raspberrypi-poe-Add-option-of-being-created-by-M.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.15/950-0658-pwm-raspberrypi-poe-Add-option-of-being-created-by-M.patch171
1 files changed, 171 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0658-pwm-raspberrypi-poe-Add-option-of-being-created-by-M.patch b/target/linux/bcm27xx/patches-5.15/950-0658-pwm-raspberrypi-poe-Add-option-of-being-created-by-M.patch
new file mode 100644
index 0000000000..2eb971f891
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.15/950-0658-pwm-raspberrypi-poe-Add-option-of-being-created-by-M.patch
@@ -0,0 +1,171 @@
+From fd864dfdcaa04271c09767bba5d77247b0899a6e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 19 Jan 2022 17:26:22 +0000
+Subject: [PATCH] pwm: raspberrypi-poe: Add option of being created by
+ MFD or FW
+
+The firmware can only use I2C0 if the kernel isn't, therefore
+with libcamera and DRM using it the PoE HAT fan control needs
+to move to the kernel.
+
+Add the option for the driver to be created by the PoE HAT core
+MFD driver, and use the I2C regmap that provides to control fan
+functions.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/pwm/pwm-raspberrypi-poe.c | 81 ++++++++++++++++++-------------
+ 1 file changed, 48 insertions(+), 33 deletions(-)
+
+--- a/drivers/pwm/pwm-raspberrypi-poe.c
++++ b/drivers/pwm/pwm-raspberrypi-poe.c
+@@ -16,6 +16,7 @@
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/pwm.h>
++#include <linux/regmap.h>
+
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+ #include <dt-bindings/pwm/raspberrypi,firmware-poe-pwm.h>
+@@ -27,6 +28,10 @@
+
+ struct raspberrypi_pwm {
+ struct rpi_firmware *firmware;
++
++ struct regmap *regmap;
++ u32 offset;
++
+ struct pwm_chip chip;
+ unsigned int duty_cycle;
+ };
+@@ -43,7 +48,7 @@ struct raspberrypi_pwm *raspberrypi_pwm_
+ return container_of(chip, struct raspberrypi_pwm, chip);
+ }
+
+-static int raspberrypi_pwm_set_property(struct rpi_firmware *firmware,
++static int raspberrypi_pwm_set_property(struct raspberrypi_pwm *pwm,
+ u32 reg, u32 val)
+ {
+ struct raspberrypi_pwm_prop msg = {
+@@ -52,17 +57,19 @@ static int raspberrypi_pwm_set_property(
+ };
+ int ret;
+
+- ret = rpi_firmware_property(firmware, RPI_FIRMWARE_SET_POE_HAT_VAL,
+- &msg, sizeof(msg));
+- if (ret)
+- return ret;
+- if (msg.ret)
+- return -EIO;
++ if (pwm->firmware) {
++ ret = rpi_firmware_property(pwm->firmware, RPI_FIRMWARE_SET_POE_HAT_VAL,
++ &msg, sizeof(msg));
++ if (!ret && msg.ret)
++ ret = -EIO;
++ } else {
++ ret = regmap_write(pwm->regmap, pwm->offset + reg, val);
++ }
+
+- return 0;
++ return ret;
+ }
+
+-static int raspberrypi_pwm_get_property(struct rpi_firmware *firmware,
++static int raspberrypi_pwm_get_property(struct raspberrypi_pwm *pwm,
+ u32 reg, u32 *val)
+ {
+ struct raspberrypi_pwm_prop msg = {
+@@ -70,16 +77,17 @@ static int raspberrypi_pwm_get_property(
+ };
+ int ret;
+
+- ret = rpi_firmware_property(firmware, RPI_FIRMWARE_GET_POE_HAT_VAL,
+- &msg, sizeof(msg));
+- if (ret)
+- return ret;
+- if (msg.ret)
+- return -EIO;
+-
+- *val = le32_to_cpu(msg.val);
++ if (pwm->firmware) {
++ ret = rpi_firmware_property(pwm->firmware, RPI_FIRMWARE_GET_POE_HAT_VAL,
++ &msg, sizeof(msg));
++ if (!ret && msg.ret)
++ ret = -EIO;
++ *val = le32_to_cpu(msg.val);
++ } else {
++ ret = regmap_read(pwm->regmap, pwm->offset + reg, val);
++ }
+
+- return 0;
++ return ret;
+ }
+
+ static void raspberrypi_pwm_get_state(struct pwm_chip *chip,
+@@ -117,7 +125,7 @@ static int raspberrypi_pwm_apply(struct
+ if (duty_cycle == rpipwm->duty_cycle)
+ return 0;
+
+- ret = raspberrypi_pwm_set_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
++ ret = raspberrypi_pwm_set_property(rpipwm, RPI_PWM_CUR_DUTY_REG,
+ duty_cycle);
+ if (ret) {
+ dev_err(chip->dev, "Failed to set duty cycle: %pe\n",
+@@ -144,29 +152,35 @@ static int raspberrypi_pwm_probe(struct
+ struct raspberrypi_pwm *rpipwm;
+ int ret;
+
+- firmware_node = of_get_parent(dev->of_node);
+- if (!firmware_node) {
+- dev_err(dev, "Missing firmware node\n");
+- return -ENOENT;
+- }
+-
+- firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node);
+- of_node_put(firmware_node);
+- if (!firmware)
+- return dev_err_probe(dev, -EPROBE_DEFER,
+- "Failed to get firmware handle\n");
+-
+ rpipwm = devm_kzalloc(&pdev->dev, sizeof(*rpipwm), GFP_KERNEL);
+ if (!rpipwm)
+ return -ENOMEM;
+
+- rpipwm->firmware = firmware;
++ if (pdev->dev.parent)
++ rpipwm->regmap = dev_get_regmap(pdev->dev.parent, NULL);
++
++ if (rpipwm->regmap) {
++ ret = device_property_read_u32(&pdev->dev, "reg", &rpipwm->offset);
++ if (ret)
++ return -EINVAL;
++ } else {
++ firmware_node = of_get_parent(dev->of_node);
++
++ firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node);
++ of_node_put(firmware_node);
++ if (!firmware)
++ return dev_err_probe(dev, -EPROBE_DEFER,
++ "Failed to get firmware handle\n");
++
++ rpipwm->firmware = firmware;
++ }
++
+ rpipwm->chip.dev = dev;
+ rpipwm->chip.ops = &raspberrypi_pwm_ops;
+ rpipwm->chip.base = -1;
+ rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM;
+
+- ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
++ ret = raspberrypi_pwm_get_property(rpipwm, RPI_PWM_CUR_DUTY_REG,
+ &rpipwm->duty_cycle);
+ if (ret) {
+ dev_err(dev, "Failed to get duty cycle: %pe\n", ERR_PTR(ret));
+@@ -178,6 +192,7 @@ static int raspberrypi_pwm_probe(struct
+
+ static const struct of_device_id raspberrypi_pwm_of_match[] = {
+ { .compatible = "raspberrypi,firmware-poe-pwm", },
++ { .compatible = "raspberrypi,poe-pwm", },
+ { }
+ };
+ MODULE_DEVICE_TABLE(of, raspberrypi_pwm_of_match);