diff options
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.patch | 171 |
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); |