mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 0ff306f2b70716698824e8f602e650e0cc2d5ea5 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 int raspberrypi_pwm_get_state(struct pwm_chip *chip,
 | |
| @@ -119,7 +127,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",
 | |
| @@ -146,28 +154,34 @@ 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.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
 | |
|  
 | |
|  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);
 |