aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/aspeed-pwm-tacho.c
diff options
context:
space:
mode:
authorJaghathiswari Rankappagounder Natarajan <jaghu@google.com>2017-04-04 20:52:41 -0400
committerGuenter Roeck <linux@roeck-us.net>2017-04-10 16:12:18 -0400
commit2d7a548a3eff382da5cd743670693b7657327714 (patch)
tree271f02605416567bd58c140cbb469e798e0dc647 /drivers/hwmon/aspeed-pwm-tacho.c
parentd702b353b9d3fccbeabba96ed530ffc87f303465 (diff)
drivers: hwmon: Support for ASPEED PWM/Fan tach
The ASPEED AST2400/2500 PWM controller supports 8 PWM output ports. The ASPEED AST2400/2500 Fan tach controller supports 16 tachometer inputs. The device driver matches on the device tree node. The configuration values are read from the device tree and written to the respective registers. The driver provides a sysfs entries through which the user can configure the duty-cycle value (ranging from 0 to 100 percent) and read the fan tach rpm value. Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com> 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.c835
1 files changed, 835 insertions, 0 deletions
diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c
new file mode 100644
index 000000000000..48403a2115be
--- /dev/null
+++ b/drivers/hwmon/aspeed-pwm-tacho.c
@@ -0,0 +1,835 @@
1/*
2 * Copyright (c) 2016 Google, Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 or later as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/gpio/consumer.h>
11#include <linux/delay.h>
12#include <linux/hwmon.h>
13#include <linux/hwmon-sysfs.h>
14#include <linux/io.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/of_platform.h>
18#include <linux/of_device.h>
19#include <linux/platform_device.h>
20#include <linux/sysfs.h>
21#include <linux/regmap.h>
22
23/* ASPEED PWM & FAN Tach Register Definition */
24#define ASPEED_PTCR_CTRL 0x00
25#define ASPEED_PTCR_CLK_CTRL 0x04
26#define ASPEED_PTCR_DUTY0_CTRL 0x08
27#define ASPEED_PTCR_DUTY1_CTRL 0x0c
28#define ASPEED_PTCR_TYPEM_CTRL 0x10
29#define ASPEED_PTCR_TYPEM_CTRL1 0x14
30#define ASPEED_PTCR_TYPEN_CTRL 0x18
31#define ASPEED_PTCR_TYPEN_CTRL1 0x1c
32#define ASPEED_PTCR_TACH_SOURCE 0x20
33#define ASPEED_PTCR_TRIGGER 0x28
34#define ASPEED_PTCR_RESULT 0x2c
35#define ASPEED_PTCR_INTR_CTRL 0x30
36#define ASPEED_PTCR_INTR_STS 0x34
37#define ASPEED_PTCR_TYPEM_LIMIT 0x38
38#define ASPEED_PTCR_TYPEN_LIMIT 0x3C
39#define ASPEED_PTCR_CTRL_EXT 0x40
40#define ASPEED_PTCR_CLK_CTRL_EXT 0x44
41#define ASPEED_PTCR_DUTY2_CTRL 0x48
42#define ASPEED_PTCR_DUTY3_CTRL 0x4c
43#define ASPEED_PTCR_TYPEO_CTRL 0x50
44#define ASPEED_PTCR_TYPEO_CTRL1 0x54
45#define ASPEED_PTCR_TACH_SOURCE_EXT 0x60
46#define ASPEED_PTCR_TYPEO_LIMIT 0x78
47
48/* ASPEED_PTCR_CTRL : 0x00 - General Control Register */
49#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1 15
50#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2 6
51#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK (BIT(7) | BIT(15))
52
53#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1 14
54#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2 5
55#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK (BIT(6) | BIT(14))
56
57#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1 13
58#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2 4
59#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK (BIT(5) | BIT(13))
60
61#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1 12
62#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2 3
63#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK (BIT(4) | BIT(12))
64
65#define ASPEED_PTCR_CTRL_FAN_NUM_EN(x) BIT(16 + (x))
66
67#define ASPEED_PTCR_CTRL_PWMD_EN BIT(11)
68#define ASPEED_PTCR_CTRL_PWMC_EN BIT(10)
69#define ASPEED_PTCR_CTRL_PWMB_EN BIT(9)
70#define ASPEED_PTCR_CTRL_PWMA_EN BIT(8)
71
72#define ASPEED_PTCR_CTRL_CLK_SRC BIT(1)
73#define ASPEED_PTCR_CTRL_CLK_EN BIT(0)
74
75/* ASPEED_PTCR_CLK_CTRL : 0x04 - Clock Control Register */
76/* TYPE N */
77#define ASPEED_PTCR_CLK_CTRL_TYPEN_MASK GENMASK(31, 16)
78#define ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT 24
79#define ASPEED_PTCR_CLK_CTRL_TYPEN_H 20
80#define ASPEED_PTCR_CLK_CTRL_TYPEN_L 16
81/* TYPE M */
82#define ASPEED_PTCR_CLK_CTRL_TYPEM_MASK GENMASK(15, 0)
83#define ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT 8
84#define ASPEED_PTCR_CLK_CTRL_TYPEM_H 4
85#define ASPEED_PTCR_CLK_CTRL_TYPEM_L 0
86
87/*
88 * ASPEED_PTCR_DUTY_CTRL/1/2/3 : 0x08/0x0C/0x48/0x4C - PWM-FAN duty control
89 * 0/1/2/3 register
90 */
91#define DUTY_CTRL_PWM2_FALL_POINT 24
92#define DUTY_CTRL_PWM2_RISE_POINT 16
93#define DUTY_CTRL_PWM2_RISE_FALL_MASK GENMASK(31, 16)
94#define DUTY_CTRL_PWM1_FALL_POINT 8
95#define DUTY_CTRL_PWM1_RISE_POINT 0
96#define DUTY_CTRL_PWM1_RISE_FALL_MASK GENMASK(15, 0)
97
98/* ASPEED_PTCR_TYPEM_CTRL : 0x10/0x18/0x50 - Type M/N/O Ctrl 0 Register */
99#define TYPE_CTRL_FAN_MASK (GENMASK(5, 1) | GENMASK(31, 16))
100#define TYPE_CTRL_FAN1_MASK GENMASK(31, 0)
101#define TYPE_CTRL_FAN_PERIOD 16
102#define TYPE_CTRL_FAN_MODE 4
103#define TYPE_CTRL_FAN_DIVISION 1
104#define TYPE_CTRL_FAN_TYPE_EN 1
105
106/* ASPEED_PTCR_TACH_SOURCE : 0x20/0x60 - Tach Source Register */
107/* bit [0,1] at 0x20, bit [2] at 0x60 */
108#define TACH_PWM_SOURCE_BIT01(x) ((x) * 2)
109#define TACH_PWM_SOURCE_BIT2(x) ((x) * 2)
110#define TACH_PWM_SOURCE_MASK_BIT01(x) (0x3 << ((x) * 2))
111#define TACH_PWM_SOURCE_MASK_BIT2(x) BIT((x) * 2)
112
113/* ASPEED_PTCR_RESULT : 0x2c - Result Register */
114#define RESULT_STATUS_MASK BIT(31)
115#define RESULT_VALUE_MASK 0xfffff
116
117/* ASPEED_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */
118#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1 15
119#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2 6
120#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK (BIT(7) | BIT(15))
121
122#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1 14
123#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2 5
124#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK (BIT(6) | BIT(14))
125
126#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1 13
127#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2 4
128#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK (BIT(5) | BIT(13))
129
130#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1 12
131#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2 3
132#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK (BIT(4) | BIT(12))
133
134#define ASPEED_PTCR_CTRL_PWMH_EN BIT(11)
135#define ASPEED_PTCR_CTRL_PWMG_EN BIT(10)
136#define ASPEED_PTCR_CTRL_PWMF_EN BIT(9)
137#define ASPEED_PTCR_CTRL_PWME_EN BIT(8)
138
139/* ASPEED_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */
140/* TYPE O */
141#define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0)
142#define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8
143#define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4
144#define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0
145
146#define PWM_MAX 255
147
148#define M_PWM_DIV_H 0x00
149#define M_PWM_DIV_L 0x05
150#define M_PWM_PERIOD 0x5F
151#define M_TACH_CLK_DIV 0x00
152#define M_TACH_MODE 0x00
153#define M_TACH_UNIT 0x1000
154#define INIT_FAN_CTRL 0xFF
155
156struct aspeed_pwm_tacho_data {
157 struct regmap *regmap;
158 unsigned long clk_freq;
159 bool pwm_present[8];
160 bool fan_tach_present[16];
161 u8 type_pwm_clock_unit[3];
162 u8 type_pwm_clock_division_h[3];
163 u8 type_pwm_clock_division_l[3];
164 u8 type_fan_tach_clock_division[3];
165 u16 type_fan_tach_unit[3];
166 u8 pwm_port_type[8];
167 u8 pwm_port_fan_ctrl[8];
168 u8 fan_tach_ch_source[16];
169 const struct attribute_group *groups[3];
170};
171
172enum type { TYPEM, TYPEN, TYPEO };
173
174struct type_params {
175 u32 l_value;
176 u32 h_value;
177 u32 unit_value;
178 u32 clk_ctrl_mask;
179 u32 clk_ctrl_reg;
180 u32 ctrl_reg;
181 u32 ctrl_reg1;
182};
183
184static const struct type_params type_params[] = {
185 [TYPEM] = {
186 .l_value = ASPEED_PTCR_CLK_CTRL_TYPEM_L,
187 .h_value = ASPEED_PTCR_CLK_CTRL_TYPEM_H,
188 .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT,
189 .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEM_MASK,
190 .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL,
191 .ctrl_reg = ASPEED_PTCR_TYPEM_CTRL,
192 .ctrl_reg1 = ASPEED_PTCR_TYPEM_CTRL1,
193 },
194 [TYPEN] = {
195 .l_value = ASPEED_PTCR_CLK_CTRL_TYPEN_L,
196 .h_value = ASPEED_PTCR_CLK_CTRL_TYPEN_H,
197 .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT,
198 .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEN_MASK,
199 .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL,
200 .ctrl_reg = ASPEED_PTCR_TYPEN_CTRL,
201 .ctrl_reg1 = ASPEED_PTCR_TYPEN_CTRL1,
202 },
203 [TYPEO] = {
204 .l_value = ASPEED_PTCR_CLK_CTRL_TYPEO_L,
205 .h_value = ASPEED_PTCR_CLK_CTRL_TYPEO_H,
206 .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT,
207 .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEO_MASK,
208 .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL_EXT,
209 .ctrl_reg = ASPEED_PTCR_TYPEO_CTRL,
210 .ctrl_reg1 = ASPEED_PTCR_TYPEO_CTRL1,
211 }
212};
213
214enum pwm_port { PWMA, PWMB, PWMC, PWMD, PWME, PWMF, PWMG, PWMH };
215
216struct pwm_port_params {
217 u32 pwm_en;
218 u32 ctrl_reg;
219 u32 type_part1;
220 u32 type_part2;
221 u32 type_mask;
222 u32 duty_ctrl_rise_point;
223 u32 duty_ctrl_fall_point;
224 u32 duty_ctrl_reg;
225 u32 duty_ctrl_rise_fall_mask;
226};
227
228static const struct pwm_port_params pwm_port_params[] = {
229 [PWMA] = {
230 .pwm_en = ASPEED_PTCR_CTRL_PWMA_EN,
231 .ctrl_reg = ASPEED_PTCR_CTRL,
232 .type_part1 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1,
233 .type_part2 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2,
234 .type_mask = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK,
235 .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
236 .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
237 .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL,
238 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
239 },
240 [PWMB] = {
241 .pwm_en = ASPEED_PTCR_CTRL_PWMB_EN,
242 .ctrl_reg = ASPEED_PTCR_CTRL,
243 .type_part1 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1,
244 .type_part2 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2,
245 .type_mask = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK,
246 .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
247 .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
248 .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL,
249 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
250 },
251 [PWMC] = {
252 .pwm_en = ASPEED_PTCR_CTRL_PWMC_EN,
253 .ctrl_reg = ASPEED_PTCR_CTRL,
254 .type_part1 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1,
255 .type_part2 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2,
256 .type_mask = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK,
257 .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
258 .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
259 .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL,
260 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
261 },
262 [PWMD] = {
263 .pwm_en = ASPEED_PTCR_CTRL_PWMD_EN,
264 .ctrl_reg = ASPEED_PTCR_CTRL,
265 .type_part1 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1,
266 .type_part2 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2,
267 .type_mask = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK,
268 .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
269 .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
270 .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL,
271 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
272 },
273 [PWME] = {
274 .pwm_en = ASPEED_PTCR_CTRL_PWME_EN,
275 .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
276 .type_part1 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1,
277 .type_part2 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2,
278 .type_mask = ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK,
279 .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
280 .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
281 .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL,
282 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
283 },
284 [PWMF] = {
285 .pwm_en = ASPEED_PTCR_CTRL_PWMF_EN,
286 .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
287 .type_part1 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1,
288 .type_part2 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2,
289 .type_mask = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK,
290 .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
291 .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
292 .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL,
293 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
294 },
295 [PWMG] = {
296 .pwm_en = ASPEED_PTCR_CTRL_PWMG_EN,
297 .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
298 .type_part1 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1,
299 .type_part2 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2,
300 .type_mask = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK,
301 .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
302 .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
303 .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL,
304 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
305 },
306 [PWMH] = {
307 .pwm_en = ASPEED_PTCR_CTRL_PWMH_EN,
308 .ctrl_reg = ASPEED_PTCR_CTRL_EXT,
309 .type_part1 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1,
310 .type_part2 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2,
311 .type_mask = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK,
312 .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
313 .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
314 .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL,
315 .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
316 }
317};
318
319static int regmap_aspeed_pwm_tacho_reg_write(void *context, unsigned int reg,
320 unsigned int val)
321{
322 void __iomem *regs = (void __iomem *)context;
323
324 writel(val, regs + reg);
325 return 0;
326}
327
328static int regmap_aspeed_pwm_tacho_reg_read(void *context, unsigned int reg,
329 unsigned int *val)
330{
331 void __iomem *regs = (void __iomem *)context;
332
333 *val = readl(regs + reg);
334 return 0;
335}
336
337static const struct regmap_config aspeed_pwm_tacho_regmap_config = {
338 .reg_bits = 32,
339 .val_bits = 32,
340 .reg_stride = 4,
341 .max_register = ASPEED_PTCR_TYPEO_LIMIT,
342 .reg_write = regmap_aspeed_pwm_tacho_reg_write,
343 .reg_read = regmap_aspeed_pwm_tacho_reg_read,
344 .fast_io = true,
345};
346
347static void aspeed_set_clock_enable(struct regmap *regmap, bool val)
348{
349 regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
350 ASPEED_PTCR_CTRL_CLK_EN,
351 val ? ASPEED_PTCR_CTRL_CLK_EN : 0);
352}
353
354static void aspeed_set_clock_source(struct regmap *regmap, int val)
355{
356 regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
357 ASPEED_PTCR_CTRL_CLK_SRC,
358 val ? ASPEED_PTCR_CTRL_CLK_SRC : 0);
359}
360
361static void aspeed_set_pwm_clock_values(struct regmap *regmap, u8 type,
362 u8 div_high, u8 div_low, u8 unit)
363{
364 u32 reg_value = ((div_high << type_params[type].h_value) |
365 (div_low << type_params[type].l_value) |
366 (unit << type_params[type].unit_value));
367
368 regmap_update_bits(regmap, type_params[type].clk_ctrl_reg,
369 type_params[type].clk_ctrl_mask, reg_value);
370}
371
372static void aspeed_set_pwm_port_enable(struct regmap *regmap, u8 pwm_port,
373 bool enable)
374{
375 regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg,
376 pwm_port_params[pwm_port].pwm_en,
377 enable ? pwm_port_params[pwm_port].pwm_en : 0);
378}
379
380static void aspeed_set_pwm_port_type(struct regmap *regmap,
381 u8 pwm_port, u8 type)
382{
383 u32 reg_value = (type & 0x1) << pwm_port_params[pwm_port].type_part1;
384
385 reg_value |= (type & 0x2) << pwm_port_params[pwm_port].type_part2;
386
387 regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg,
388 pwm_port_params[pwm_port].type_mask, reg_value);
389}
390
391static void aspeed_set_pwm_port_duty_rising_falling(struct regmap *regmap,
392 u8 pwm_port, u8 rising,
393 u8 falling)
394{
395 u32 reg_value = (rising <<
396 pwm_port_params[pwm_port].duty_ctrl_rise_point);
397 reg_value |= (falling <<
398 pwm_port_params[pwm_port].duty_ctrl_fall_point);
399
400 regmap_update_bits(regmap, pwm_port_params[pwm_port].duty_ctrl_reg,
401 pwm_port_params[pwm_port].duty_ctrl_rise_fall_mask,
402 reg_value);
403}
404
405static void aspeed_set_tacho_type_enable(struct regmap *regmap, u8 type,
406 bool enable)
407{
408 regmap_update_bits(regmap, type_params[type].ctrl_reg,
409 TYPE_CTRL_FAN_TYPE_EN,
410 enable ? TYPE_CTRL_FAN_TYPE_EN : 0);
411}
412
413static void aspeed_set_tacho_type_values(struct regmap *regmap, u8 type,
414 u8 mode, u16 unit, u8 division)
415{
416 u32 reg_value = ((mode << TYPE_CTRL_FAN_MODE) |
417 (unit << TYPE_CTRL_FAN_PERIOD) |
418 (division << TYPE_CTRL_FAN_DIVISION));
419
420 regmap_update_bits(regmap, type_params[type].ctrl_reg,
421 TYPE_CTRL_FAN_MASK, reg_value);
422 regmap_update_bits(regmap, type_params[type].ctrl_reg1,
423 TYPE_CTRL_FAN1_MASK, unit << 16);
424}
425
426static void aspeed_set_fan_tach_ch_enable(struct regmap *regmap, u8 fan_tach_ch,
427 bool enable)
428{
429 regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
430 ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch),
431 enable ?
432 ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch) : 0);
433}
434
435static void aspeed_set_fan_tach_ch_source(struct regmap *regmap, u8 fan_tach_ch,
436 u8 fan_tach_ch_source)
437{
438 u32 reg_value1 = ((fan_tach_ch_source & 0x3) <<
439 TACH_PWM_SOURCE_BIT01(fan_tach_ch));
440 u32 reg_value2 = (((fan_tach_ch_source & 0x4) >> 2) <<
441 TACH_PWM_SOURCE_BIT2(fan_tach_ch));
442
443 regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE,
444 TACH_PWM_SOURCE_MASK_BIT01(fan_tach_ch),
445 reg_value1);
446
447 regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE_EXT,
448 TACH_PWM_SOURCE_MASK_BIT2(fan_tach_ch),
449 reg_value2);
450}
451
452static void aspeed_set_pwm_port_fan_ctrl(struct aspeed_pwm_tacho_data *priv,
453 u8 index, u8 fan_ctrl)
454{
455 u16 period, dc_time_on;
456
457 period = priv->type_pwm_clock_unit[priv->pwm_port_type[index]];
458 period += 1;
459 dc_time_on = (fan_ctrl * period) / PWM_MAX;
460
461 if (dc_time_on == 0) {
462 aspeed_set_pwm_port_enable(priv->regmap, index, false);
463 } else {
464 if (dc_time_on == period)
465 dc_time_on = 0;
466
467 aspeed_set_pwm_port_duty_rising_falling(priv->regmap, index, 0,
468 dc_time_on);
469 aspeed_set_pwm_port_enable(priv->regmap, index, true);
470 }
471}
472
473static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data
474 *priv, u8 type)
475{
476 u32 clk;
477 u16 tacho_unit;
478 u8 clk_unit, div_h, div_l, tacho_div;
479
480 clk = priv->clk_freq;
481 clk_unit = priv->type_pwm_clock_unit[type];
482 div_h = priv->type_pwm_clock_division_h[type];
483 div_h = 0x1 << div_h;
484 div_l = priv->type_pwm_clock_division_l[type];
485 if (div_l == 0)
486 div_l = 1;
487 else
488 div_l = div_l * 2;
489
490 tacho_unit = priv->type_fan_tach_unit[type];
491 tacho_div = priv->type_fan_tach_clock_division[type];
492
493 tacho_div = 0x4 << (tacho_div * 2);
494 return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit);
495}
496
497static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
498 u8 fan_tach_ch)
499{
500 u32 raw_data, tach_div, clk_source, sec, val;
501 u8 fan_tach_ch_source, type;
502
503 regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
504 regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
505
506 fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch];
507 type = priv->pwm_port_type[fan_tach_ch_source];
508
509 sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type));
510 msleep(sec);
511
512 regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
513 raw_data = val & RESULT_VALUE_MASK;
514 tach_div = priv->type_fan_tach_clock_division[type];
515 tach_div = 0x4 << (tach_div * 2);
516 clk_source = priv->clk_freq;
517
518 if (raw_data == 0)
519 return 0;
520
521 return (clk_source * 60) / (2 * raw_data * tach_div);
522}
523
524static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
525 const char *buf, size_t count)
526{
527 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
528 int index = sensor_attr->index;
529 int ret;
530 struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
531 long fan_ctrl;
532
533 ret = kstrtol(buf, 10, &fan_ctrl);
534 if (ret != 0)
535 return ret;
536
537 if (fan_ctrl < 0 || fan_ctrl > PWM_MAX)
538 return -EINVAL;
539
540 if (priv->pwm_port_fan_ctrl[index] == fan_ctrl)
541 return count;
542
543 priv->pwm_port_fan_ctrl[index] = fan_ctrl;
544 aspeed_set_pwm_port_fan_ctrl(priv, index, fan_ctrl);
545
546 return count;
547}
548
549static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
550 char *buf)
551{
552 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
553 int index = sensor_attr->index;
554 struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
555
556 return sprintf(buf, "%u\n", priv->pwm_port_fan_ctrl[index]);
557}
558
559static ssize_t show_rpm(struct device *dev, struct device_attribute *attr,
560 char *buf)
561{
562 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
563 int index = sensor_attr->index;
564 u32 rpm;
565 struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
566
567 rpm = aspeed_get_fan_tach_ch_rpm(priv, index);
568
569 return sprintf(buf, "%u\n", rpm);
570}
571
572static umode_t pwm_is_visible(struct kobject *kobj,
573 struct attribute *a, int index)
574{
575 struct device *dev = container_of(kobj, struct device, kobj);
576 struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
577
578 if (!priv->pwm_present[index])
579 return 0;
580 return a->mode;
581}
582
583static umode_t fan_dev_is_visible(struct kobject *kobj,
584 struct attribute *a, int index)
585{
586 struct device *dev = container_of(kobj, struct device, kobj);
587 struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
588
589 if (!priv->fan_tach_present[index])
590 return 0;
591 return a->mode;
592}
593
594static SENSOR_DEVICE_ATTR(pwm0, 0644,
595 show_pwm, set_pwm, 0);
596static SENSOR_DEVICE_ATTR(pwm1, 0644,
597 show_pwm, set_pwm, 1);
598static SENSOR_DEVICE_ATTR(pwm2, 0644,
599 show_pwm, set_pwm, 2);
600static SENSOR_DEVICE_ATTR(pwm3, 0644,
601 show_pwm, set_pwm, 3);
602static SENSOR_DEVICE_ATTR(pwm4, 0644,
603 show_pwm, set_pwm, 4);
604static SENSOR_DEVICE_ATTR(pwm5, 0644,
605 show_pwm, set_pwm, 5);
606static SENSOR_DEVICE_ATTR(pwm6, 0644,
607 show_pwm, set_pwm, 6);
608static SENSOR_DEVICE_ATTR(pwm7, 0644,
609 show_pwm, set_pwm, 7);
610static struct attribute *pwm_dev_attrs[] = {
611 &sensor_dev_attr_pwm0.dev_attr.attr,
612 &sensor_dev_attr_pwm1.dev_attr.attr,
613 &sensor_dev_attr_pwm2.dev_attr.attr,
614 &sensor_dev_attr_pwm3.dev_attr.attr,
615 &sensor_dev_attr_pwm4.dev_attr.attr,
616 &sensor_dev_attr_pwm5.dev_attr.attr,
617 &sensor_dev_attr_pwm6.dev_attr.attr,
618 &sensor_dev_attr_pwm7.dev_attr.attr,
619 NULL,
620};
621
622static const struct attribute_group pwm_dev_group = {
623 .attrs = pwm_dev_attrs,
624 .is_visible = pwm_is_visible,
625};
626
627static SENSOR_DEVICE_ATTR(fan0_input, 0444,
628 show_rpm, NULL, 0);
629static SENSOR_DEVICE_ATTR(fan1_input, 0444,
630 show_rpm, NULL, 1);
631static SENSOR_DEVICE_ATTR(fan2_input, 0444,
632 show_rpm, NULL, 2);
633static SENSOR_DEVICE_ATTR(fan3_input, 0444,
634 show_rpm, NULL, 3);
635static SENSOR_DEVICE_ATTR(fan4_input, 0444,
636 show_rpm, NULL, 4);
637static SENSOR_DEVICE_ATTR(fan5_input, 0444,
638 show_rpm, NULL, 5);
639static SENSOR_DEVICE_ATTR(fan6_input, 0444,
640 show_rpm, NULL, 6);
641static SENSOR_DEVICE_ATTR(fan7_input, 0444,
642 show_rpm, NULL, 7);
643static SENSOR_DEVICE_ATTR(fan8_input, 0444,
644 show_rpm, NULL, 8);
645static SENSOR_DEVICE_ATTR(fan9_input, 0444,
646 show_rpm, NULL, 9);
647static SENSOR_DEVICE_ATTR(fan10_input, 0444,
648 show_rpm, NULL, 10);
649static SENSOR_DEVICE_ATTR(fan11_input, 0444,
650 show_rpm, NULL, 11);
651static SENSOR_DEVICE_ATTR(fan12_input, 0444,
652 show_rpm, NULL, 12);
653static SENSOR_DEVICE_ATTR(fan13_input, 0444,
654 show_rpm, NULL, 13);
655static SENSOR_DEVICE_ATTR(fan14_input, 0444,
656 show_rpm, NULL, 14);
657static SENSOR_DEVICE_ATTR(fan15_input, 0444,
658 show_rpm, NULL, 15);
659static struct attribute *fan_dev_attrs[] = {
660 &sensor_dev_attr_fan0_input.dev_attr.attr,
661 &sensor_dev_attr_fan1_input.dev_attr.attr,
662 &sensor_dev_attr_fan2_input.dev_attr.attr,
663 &sensor_dev_attr_fan3_input.dev_attr.attr,
664 &sensor_dev_attr_fan4_input.dev_attr.attr,
665 &sensor_dev_attr_fan5_input.dev_attr.attr,
666 &sensor_dev_attr_fan6_input.dev_attr.attr,
667 &sensor_dev_attr_fan7_input.dev_attr.attr,
668 &sensor_dev_attr_fan8_input.dev_attr.attr,
669 &sensor_dev_attr_fan9_input.dev_attr.attr,
670 &sensor_dev_attr_fan10_input.dev_attr.attr,
671 &sensor_dev_attr_fan11_input.dev_attr.attr,
672 &sensor_dev_attr_fan12_input.dev_attr.attr,
673 &sensor_dev_attr_fan13_input.dev_attr.attr,
674 &sensor_dev_attr_fan14_input.dev_attr.attr,
675 &sensor_dev_attr_fan15_input.dev_attr.attr,
676 NULL
677};
678
679static const struct attribute_group fan_dev_group = {
680 .attrs = fan_dev_attrs,
681 .is_visible = fan_dev_is_visible,
682};
683
684/*
685 * The clock type is type M :
686 * The PWM frequency = 24MHz / (type M clock division L bit *
687 * type M clock division H bit * (type M PWM period bit + 1))
688 */
689static void aspeed_create_type(struct aspeed_pwm_tacho_data *priv)
690{
691 priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H;
692 priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L;
693 priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD;
694 aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H,
695 M_PWM_DIV_L, M_PWM_PERIOD);
696 aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true);
697 priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV;
698 priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT;
699 aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE,
700 M_TACH_UNIT, M_TACH_CLK_DIV);
701}
702
703static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv,
704 u8 pwm_port)
705{
706 aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true);
707 priv->pwm_present[pwm_port] = true;
708
709 priv->pwm_port_type[pwm_port] = TYPEM;
710 aspeed_set_pwm_port_type(priv->regmap, pwm_port, TYPEM);
711
712 priv->pwm_port_fan_ctrl[pwm_port] = INIT_FAN_CTRL;
713 aspeed_set_pwm_port_fan_ctrl(priv, pwm_port, INIT_FAN_CTRL);
714}
715
716static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv,
717 u8 *fan_tach_ch,
718 int count,
719 u8 pwm_source)
720{
721 u8 val, index;
722
723 for (val = 0; val < count; val++) {
724 index = fan_tach_ch[val];
725 aspeed_set_fan_tach_ch_enable(priv->regmap, index, true);
726 priv->fan_tach_present[index] = true;
727 priv->fan_tach_ch_source[index] = pwm_source;
728 aspeed_set_fan_tach_ch_source(priv->regmap, index, pwm_source);
729 }
730}
731
732static int aspeed_create_fan(struct device *dev,
733 struct device_node *child,
734 struct aspeed_pwm_tacho_data *priv)
735{
736 u8 *fan_tach_ch;
737 u32 pwm_port;
738 int ret, count;
739
740 ret = of_property_read_u32(child, "reg", &pwm_port);
741 if (ret)
742 return ret;
743 aspeed_create_pwm_port(priv, (u8)pwm_port);
744
745 count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch");
746 if (count < 1)
747 return -EINVAL;
748 fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count,
749 GFP_KERNEL);
750 if (!fan_tach_ch)
751 return -ENOMEM;
752 ret = of_property_read_u8_array(child, "aspeed,fan-tach-ch",
753 fan_tach_ch, count);
754 if (ret)
755 return ret;
756 aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, pwm_port);
757
758 return 0;
759}
760
761static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
762{
763 struct device *dev = &pdev->dev;
764 struct device_node *np, *child;
765 struct aspeed_pwm_tacho_data *priv;
766 void __iomem *regs;
767 struct resource *res;
768 struct device *hwmon;
769 struct clk *clk;
770 int ret;
771
772 np = dev->of_node;
773
774 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
775 if (!res)
776 return -ENOENT;
777 regs = devm_ioremap_resource(dev, res);
778 if (IS_ERR(regs))
779 return PTR_ERR(regs);
780 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
781 if (!priv)
782 return -ENOMEM;
783 priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
784 &aspeed_pwm_tacho_regmap_config);
785 if (IS_ERR(priv->regmap))
786 return PTR_ERR(priv->regmap);
787 regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE, 0);
788 regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 0);
789
790 clk = devm_clk_get(dev, NULL);
791 if (IS_ERR(clk))
792 return -ENODEV;
793 priv->clk_freq = clk_get_rate(clk);
794 aspeed_set_clock_enable(priv->regmap, true);
795 aspeed_set_clock_source(priv->regmap, 0);
796
797 aspeed_create_type(priv);
798
799 for_each_child_of_node(np, child) {
800 ret = aspeed_create_fan(dev, child, priv);
801 of_node_put(child);
802 if (ret)
803 return ret;
804 }
805 of_node_put(np);
806
807 priv->groups[0] = &pwm_dev_group;
808 priv->groups[1] = &fan_dev_group;
809 priv->groups[2] = NULL;
810 hwmon = devm_hwmon_device_register_with_groups(dev,
811 "aspeed_pwm_tacho",
812 priv, priv->groups);
813 return PTR_ERR_OR_ZERO(hwmon);
814}
815
816static const struct of_device_id of_pwm_tacho_match_table[] = {
817 { .compatible = "aspeed,ast2400-pwm-tacho", },
818 { .compatible = "aspeed,ast2500-pwm-tacho", },
819 {},
820};
821MODULE_DEVICE_TABLE(of, of_pwm_tacho_match_table);
822
823static struct platform_driver aspeed_pwm_tacho_driver = {
824 .probe = aspeed_pwm_tacho_probe,
825 .driver = {
826 .name = "aspeed_pwm_tacho",
827 .of_match_table = of_pwm_tacho_match_table,
828 },
829};
830
831module_platform_driver(aspeed_pwm_tacho_driver);
832
833MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>");
834MODULE_DESCRIPTION("ASPEED PWM and Fan Tacho device driver");
835MODULE_LICENSE("GPL");