aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/aspeed-pwm-tacho.c
diff options
context:
space:
mode:
authorMykola Kostenok <c_mykolak@mellanox.com>2017-08-03 04:50:44 -0400
committerGuenter Roeck <linux@roeck-us.net>2017-08-13 11:24:38 -0400
commitf198907d2ff6db9541863764576aaf3bc9f58ec0 (patch)
tree0d9f2f036ef54a83ea93417ac9ccf3e2c918cd29 /drivers/hwmon/aspeed-pwm-tacho.c
parent5e047541c1412f22d1c0950260da337ebc9bdb49 (diff)
hwmon: (aspeed-pwm-tacho) cooling device support.
Add support in aspeed-pwm-tacho driver for cooling device creation. This cooling device could be bound to a thermal zone for the thermal control. Device will appear in /sys/class/thermal folder as cooling_deviceX. Then it could be bound to particular thermal zones. Allow specification of the cooling levels vector - PWM duty cycle values in a range from 0 to 255 which correspond to thermal cooling states. Signed-off-by: Mykola Kostenok <c_mykolak@mellanox.com> Reviewed-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/aspeed-pwm-tacho.c')
-rw-r--r--drivers/hwmon/aspeed-pwm-tacho.c116
1 files changed, 114 insertions, 2 deletions
diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c
index ddfe66bdff86..69b97d45e3cb 100644
--- a/drivers/hwmon/aspeed-pwm-tacho.c
+++ b/drivers/hwmon/aspeed-pwm-tacho.c
@@ -20,6 +20,7 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/sysfs.h> 21#include <linux/sysfs.h>
22#include <linux/regmap.h> 22#include <linux/regmap.h>
23#include <linux/thermal.h>
23 24
24/* ASPEED PWM & FAN Tach Register Definition */ 25/* ASPEED PWM & FAN Tach Register Definition */
25#define ASPEED_PTCR_CTRL 0x00 26#define ASPEED_PTCR_CTRL 0x00
@@ -166,6 +167,18 @@
166/* How long we sleep in us while waiting for an RPM result. */ 167/* How long we sleep in us while waiting for an RPM result. */
167#define ASPEED_RPM_STATUS_SLEEP_USEC 500 168#define ASPEED_RPM_STATUS_SLEEP_USEC 500
168 169
170#define MAX_CDEV_NAME_LEN 16
171
172struct aspeed_cooling_device {
173 char name[16];
174 struct aspeed_pwm_tacho_data *priv;
175 struct thermal_cooling_device *tcdev;
176 int pwm_port;
177 u8 *cooling_levels;
178 u8 max_state;
179 u8 cur_state;
180};
181
169struct aspeed_pwm_tacho_data { 182struct aspeed_pwm_tacho_data {
170 struct regmap *regmap; 183 struct regmap *regmap;
171 unsigned long clk_freq; 184 unsigned long clk_freq;
@@ -180,6 +193,7 @@ struct aspeed_pwm_tacho_data {
180 u8 pwm_port_type[8]; 193 u8 pwm_port_type[8];
181 u8 pwm_port_fan_ctrl[8]; 194 u8 pwm_port_fan_ctrl[8];
182 u8 fan_tach_ch_source[16]; 195 u8 fan_tach_ch_source[16];
196 struct aspeed_cooling_device *cdev[8];
183 const struct attribute_group *groups[3]; 197 const struct attribute_group *groups[3];
184}; 198};
185 199
@@ -765,6 +779,94 @@ static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv,
765 } 779 }
766} 780}
767 781
782static int
783aspeed_pwm_cz_get_max_state(struct thermal_cooling_device *tcdev,
784 unsigned long *state)
785{
786 struct aspeed_cooling_device *cdev = tcdev->devdata;
787
788 *state = cdev->max_state;
789
790 return 0;
791}
792
793static int
794aspeed_pwm_cz_get_cur_state(struct thermal_cooling_device *tcdev,
795 unsigned long *state)
796{
797 struct aspeed_cooling_device *cdev = tcdev->devdata;
798
799 *state = cdev->cur_state;
800
801 return 0;
802}
803
804static int
805aspeed_pwm_cz_set_cur_state(struct thermal_cooling_device *tcdev,
806 unsigned long state)
807{
808 struct aspeed_cooling_device *cdev = tcdev->devdata;
809
810 if (state > cdev->max_state)
811 return -EINVAL;
812
813 cdev->cur_state = state;
814 cdev->priv->pwm_port_fan_ctrl[cdev->pwm_port] =
815 cdev->cooling_levels[cdev->cur_state];
816 aspeed_set_pwm_port_fan_ctrl(cdev->priv, cdev->pwm_port,
817 cdev->cooling_levels[cdev->cur_state]);
818
819 return 0;
820}
821
822static const struct thermal_cooling_device_ops aspeed_pwm_cool_ops = {
823 .get_max_state = aspeed_pwm_cz_get_max_state,
824 .get_cur_state = aspeed_pwm_cz_get_cur_state,
825 .set_cur_state = aspeed_pwm_cz_set_cur_state,
826};
827
828static int aspeed_create_pwm_cooling(struct device *dev,
829 struct device_node *child,
830 struct aspeed_pwm_tacho_data *priv,
831 u32 pwm_port, u8 num_levels)
832{
833 int ret;
834 struct aspeed_cooling_device *cdev;
835
836 cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL);
837
838 if (!cdev)
839 return -ENOMEM;
840
841 cdev->cooling_levels = devm_kzalloc(dev, num_levels, GFP_KERNEL);
842 if (!cdev->cooling_levels)
843 return -ENOMEM;
844
845 cdev->max_state = num_levels - 1;
846 ret = of_property_read_u8_array(child, "cooling-levels",
847 cdev->cooling_levels,
848 num_levels);
849 if (ret) {
850 dev_err(dev, "Property 'cooling-levels' cannot be read.\n");
851 return ret;
852 }
853 snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%s%d", child->name, pwm_port);
854
855 cdev->tcdev = thermal_of_cooling_device_register(child,
856 cdev->name,
857 cdev,
858 &aspeed_pwm_cool_ops);
859 if (IS_ERR(cdev->tcdev))
860 return PTR_ERR(cdev->tcdev);
861
862 cdev->priv = priv;
863 cdev->pwm_port = pwm_port;
864
865 priv->cdev[pwm_port] = cdev;
866
867 return 0;
868}
869
768static int aspeed_create_fan(struct device *dev, 870static int aspeed_create_fan(struct device *dev,
769 struct device_node *child, 871 struct device_node *child,
770 struct aspeed_pwm_tacho_data *priv) 872 struct aspeed_pwm_tacho_data *priv)
@@ -778,6 +880,15 @@ static int aspeed_create_fan(struct device *dev,
778 return ret; 880 return ret;
779 aspeed_create_pwm_port(priv, (u8)pwm_port); 881 aspeed_create_pwm_port(priv, (u8)pwm_port);
780 882
883 ret = of_property_count_u8_elems(child, "cooling-levels");
884
885 if (ret > 0) {
886 ret = aspeed_create_pwm_cooling(dev, child, priv, pwm_port,
887 ret);
888 if (ret)
889 return ret;
890 }
891
781 count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch"); 892 count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch");
782 if (count < 1) 893 if (count < 1)
783 return -EINVAL; 894 return -EINVAL;
@@ -834,9 +945,10 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
834 945
835 for_each_child_of_node(np, child) { 946 for_each_child_of_node(np, child) {
836 ret = aspeed_create_fan(dev, child, priv); 947 ret = aspeed_create_fan(dev, child, priv);
837 of_node_put(child); 948 if (ret) {
838 if (ret) 949 of_node_put(child);
839 return ret; 950 return ret;
951 }
840 } 952 }
841 953
842 priv->groups[0] = &pwm_dev_group; 954 priv->groups[0] = &pwm_dev_group;