diff --git a/drivers/pwm/pwm-raspberrypi-poe.c b/drivers/pwm/pwm-raspberrypi-poe.c index 2939b71a7ba7..4cf3d6fd5011 100644 --- a/drivers/pwm/pwm-raspberrypi-poe.c +++ b/drivers/pwm/pwm-raspberrypi-poe.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -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_from_chip(struct pwm_chip *chip) 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(struct rpi_firmware *firmware, }; 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(struct rpi_firmware *firmware, }; 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; + 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); + } - *val = le32_to_cpu(msg.val); - - return 0; + return ret; } static int raspberrypi_pwm_get_state(struct pwm_chip *chip, @@ -119,7 +127,7 @@ static int raspberrypi_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 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", @@ -146,28 +154,34 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev) 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.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)); @@ -179,6 +193,7 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev) 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);