diff options
author | Lukasz Majewski <l.majewski@samsung.com> | 2015-02-26 08:59:36 -0500 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2015-03-09 12:59:36 -0400 |
commit | 2e5219c77183be47eb9ae4b1a4195e008d196c73 (patch) | |
tree | e4401ed00f312bb3a6ee8ce188c89b1b46b5bfd5 /drivers/hwmon | |
parent | cb85ca332f4d72ca68464c55f63af0387f6bbdb1 (diff) |
hwmon: (pwm-fan) Read PWM FAN configuration from device tree
This patch provides code for reading PWM FAN configuration data via
device tree. The pwm-fan can work with full speed when configuration
is not provided. However, errors are propagated when wrong DT bindings
are found.
Additionally the struct pwm_fan_ctx has been extended.
Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/pwm-fan.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index bd42d3996a86..e6ed3532deac 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c | |||
@@ -30,7 +30,10 @@ | |||
30 | struct pwm_fan_ctx { | 30 | struct pwm_fan_ctx { |
31 | struct mutex lock; | 31 | struct mutex lock; |
32 | struct pwm_device *pwm; | 32 | struct pwm_device *pwm; |
33 | unsigned char pwm_value; | 33 | unsigned int pwm_value; |
34 | unsigned int pwm_fan_state; | ||
35 | unsigned int pwm_fan_max_state; | ||
36 | unsigned int *pwm_fan_cooling_levels; | ||
34 | }; | 37 | }; |
35 | 38 | ||
36 | static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm) | 39 | static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm) |
@@ -100,6 +103,46 @@ static struct attribute *pwm_fan_attrs[] = { | |||
100 | 103 | ||
101 | ATTRIBUTE_GROUPS(pwm_fan); | 104 | ATTRIBUTE_GROUPS(pwm_fan); |
102 | 105 | ||
106 | int pwm_fan_of_get_cooling_data(struct device *dev, struct pwm_fan_ctx *ctx) | ||
107 | { | ||
108 | struct device_node *np = dev->of_node; | ||
109 | int num, i, ret; | ||
110 | |||
111 | if (!of_find_property(np, "cooling-levels", NULL)) | ||
112 | return 0; | ||
113 | |||
114 | ret = of_property_count_u32_elems(np, "cooling-levels"); | ||
115 | if (ret <= 0) { | ||
116 | dev_err(dev, "Wrong data!\n"); | ||
117 | return ret ? : -EINVAL; | ||
118 | } | ||
119 | |||
120 | num = ret; | ||
121 | ctx->pwm_fan_cooling_levels = devm_kzalloc(dev, num * sizeof(u32), | ||
122 | GFP_KERNEL); | ||
123 | if (!ctx->pwm_fan_cooling_levels) | ||
124 | return -ENOMEM; | ||
125 | |||
126 | ret = of_property_read_u32_array(np, "cooling-levels", | ||
127 | ctx->pwm_fan_cooling_levels, num); | ||
128 | if (ret) { | ||
129 | dev_err(dev, "Property 'cooling-levels' cannot be read!\n"); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | for (i = 0; i < num; i++) { | ||
134 | if (ctx->pwm_fan_cooling_levels[i] > MAX_PWM) { | ||
135 | dev_err(dev, "PWM fan state[%d]:%d > %d\n", i, | ||
136 | ctx->pwm_fan_cooling_levels[i], MAX_PWM); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | ctx->pwm_fan_max_state = num - 1; | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
103 | static int pwm_fan_probe(struct platform_device *pdev) | 146 | static int pwm_fan_probe(struct platform_device *pdev) |
104 | { | 147 | { |
105 | struct device *hwmon; | 148 | struct device *hwmon; |
@@ -145,6 +188,11 @@ static int pwm_fan_probe(struct platform_device *pdev) | |||
145 | pwm_disable(ctx->pwm); | 188 | pwm_disable(ctx->pwm); |
146 | return PTR_ERR(hwmon); | 189 | return PTR_ERR(hwmon); |
147 | } | 190 | } |
191 | |||
192 | ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx); | ||
193 | if (ret) | ||
194 | return ret; | ||
195 | |||
148 | return 0; | 196 | return 0; |
149 | } | 197 | } |
150 | 198 | ||