1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2023 Nuvoton Technology corporation.
6 #include <linux/bitfield.h>
7 #include <linux/bits.h>
9 #include <linux/hwmon.h>
10 #include <linux/hwmon-sysfs.h>
11 #include <linux/i2c.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/regmap.h>
15 #include <linux/slab.h>
17 #define NCT7363_REG_FUNC_CFG_BASE(x) (0x20 + (x))
18 #define NCT7363_REG_LSRS(x) (0x34 + ((x) / 8))
19 #define NCT7363_REG_PWMEN_BASE(x) (0x38 + (x))
20 #define NCT7363_REG_FANINEN_BASE(x) (0x41 + (x))
21 #define NCT7363_REG_FANINX_HVAL(x) (0x48 + ((x) * 2))
22 #define NCT7363_REG_FANINX_LVAL(x) (0x49 + ((x) * 2))
23 #define NCT7363_REG_FANINX_HL(x) (0x6C + ((x) * 2))
24 #define NCT7363_REG_FANINX_LL(x) (0x6D + ((x) * 2))
25 #define NCT7363_REG_FSCPXDUTY(x) (0x90 + ((x) * 2))
26 #define NCT7363_REG_FSCPXDIV(x) (0x91 + ((x) * 2))
28 #define PWM_SEL(x) (BIT(0) << ((x) * 2))
29 #define FANIN_SEL(_x) ({typeof(_x) (x) = (_x); \
30 BIT(1) << (((x) < 8) ? \
33 #define ALARM_SEL(x, y) ((x) & (BIT((y) % 8)))
34 #define VALUE_TO_REG(x, y) (((x) >> ((y) * 8)) & 0xFF)
36 #define NCT7363_FANINX_LVAL_MASK GENMASK(4, 0)
37 #define NCT7363_FANIN_MASK GENMASK(12, 0)
39 #define NCT7363_PWM_COUNT 16
41 static inline unsigned int fan_from_reg(u16 val
)
43 if (val
== NCT7363_FANIN_MASK
|| val
== 0)
46 return (1350000UL / val
);
49 static const struct of_device_id nct7363_of_match
[] = {
50 { .compatible
= "nuvoton,nct7363", },
51 { .compatible
= "nuvoton,nct7362", },
54 MODULE_DEVICE_TABLE(of
, nct7363_of_match
);
57 struct regmap
*regmap
;
63 static int nct7363_read_fan(struct device
*dev
, u32 attr
, int channel
,
66 struct nct7363_data
*data
= dev_get_drvdata(dev
);
75 * High-byte register should be read first to latch
76 * synchronous low-byte value
78 ret
= regmap_bulk_read(data
->regmap
,
79 NCT7363_REG_FANINX_HVAL(channel
),
84 cnt
= (regval
[0] << 5) | (regval
[1] & NCT7363_FANINX_LVAL_MASK
);
85 *val
= fan_from_reg(cnt
);
88 ret
= regmap_bulk_read(data
->regmap
,
89 NCT7363_REG_FANINX_HL(channel
),
94 cnt
= (regval
[0] << 5) | (regval
[1] & NCT7363_FANINX_LVAL_MASK
);
95 *val
= fan_from_reg(cnt
);
98 ret
= regmap_read(data
->regmap
,
99 NCT7363_REG_LSRS(channel
), ®
);
103 *val
= (long)ALARM_SEL(reg
, channel
) > 0 ? 1 : 0;
110 static int nct7363_write_fan(struct device
*dev
, u32 attr
, int channel
,
113 struct nct7363_data
*data
= dev_get_drvdata(dev
);
122 val
= clamp_val(DIV_ROUND_CLOSEST(1350000, val
),
123 1, NCT7363_FANIN_MASK
);
124 regval
[0] = val
>> 5;
125 regval
[1] = val
& NCT7363_FANINX_LVAL_MASK
;
127 ret
= regmap_bulk_write(data
->regmap
,
128 NCT7363_REG_FANINX_HL(channel
),
136 static umode_t
nct7363_fan_is_visible(const void *_data
, u32 attr
, int channel
)
138 const struct nct7363_data
*data
= _data
;
141 case hwmon_fan_input
:
142 case hwmon_fan_alarm
:
143 if (data
->fanin_mask
& BIT(channel
))
147 if (data
->fanin_mask
& BIT(channel
))
157 static int nct7363_read_pwm(struct device
*dev
, u32 attr
, int channel
,
160 struct nct7363_data
*data
= dev_get_drvdata(dev
);
165 case hwmon_pwm_input
:
166 ret
= regmap_read(data
->regmap
,
167 NCT7363_REG_FSCPXDUTY(channel
), ®val
);
178 static int nct7363_write_pwm(struct device
*dev
, u32 attr
, int channel
,
181 struct nct7363_data
*data
= dev_get_drvdata(dev
);
185 case hwmon_pwm_input
:
186 if (val
< 0 || val
> 255)
189 ret
= regmap_write(data
->regmap
,
190 NCT7363_REG_FSCPXDUTY(channel
), val
);
199 static umode_t
nct7363_pwm_is_visible(const void *_data
, u32 attr
, int channel
)
201 const struct nct7363_data
*data
= _data
;
204 case hwmon_pwm_input
:
205 if (data
->pwm_mask
& BIT(channel
))
215 static int nct7363_read(struct device
*dev
, enum hwmon_sensor_types type
,
216 u32 attr
, int channel
, long *val
)
220 return nct7363_read_fan(dev
, attr
, channel
, val
);
222 return nct7363_read_pwm(dev
, attr
, channel
, val
);
228 static int nct7363_write(struct device
*dev
, enum hwmon_sensor_types type
,
229 u32 attr
, int channel
, long val
)
233 return nct7363_write_fan(dev
, attr
, channel
, val
);
235 return nct7363_write_pwm(dev
, attr
, channel
, val
);
241 static umode_t
nct7363_is_visible(const void *data
,
242 enum hwmon_sensor_types type
,
243 u32 attr
, int channel
)
247 return nct7363_fan_is_visible(data
, attr
, channel
);
249 return nct7363_pwm_is_visible(data
, attr
, channel
);
255 static const struct hwmon_channel_info
*nct7363_info
[] = {
256 HWMON_CHANNEL_INFO(fan
,
257 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
258 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
259 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
260 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
261 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
262 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
263 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
264 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
265 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
266 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
267 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
268 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
269 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
270 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
271 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
,
272 HWMON_F_INPUT
| HWMON_F_MIN
| HWMON_F_ALARM
),
273 HWMON_CHANNEL_INFO(pwm
,
293 static const struct hwmon_ops nct7363_hwmon_ops
= {
294 .is_visible
= nct7363_is_visible
,
295 .read
= nct7363_read
,
296 .write
= nct7363_write
,
299 static const struct hwmon_chip_info nct7363_chip_info
= {
300 .ops
= &nct7363_hwmon_ops
,
301 .info
= nct7363_info
,
304 static int nct7363_init_chip(struct nct7363_data
*data
)
309 /* Pin Function Configuration */
310 for (i
= 0; i
< NCT7363_PWM_COUNT
; i
++) {
311 if (data
->pwm_mask
& BIT(i
))
312 func_config
|= PWM_SEL(i
);
313 if (data
->fanin_mask
& BIT(i
))
314 func_config
|= FANIN_SEL(i
);
317 for (i
= 0; i
< 4; i
++) {
318 ret
= regmap_write(data
->regmap
, NCT7363_REG_FUNC_CFG_BASE(i
),
319 VALUE_TO_REG(func_config
, i
));
324 /* PWM and FANIN Monitoring Enable */
325 for (i
= 0; i
< 2; i
++) {
326 ret
= regmap_write(data
->regmap
, NCT7363_REG_PWMEN_BASE(i
),
327 VALUE_TO_REG(data
->pwm_mask
, i
));
331 ret
= regmap_write(data
->regmap
, NCT7363_REG_FANINEN_BASE(i
),
332 VALUE_TO_REG(data
->fanin_mask
, i
));
340 static int nct7363_present_pwm_fanin(struct device
*dev
,
341 struct device_node
*child
,
342 struct nct7363_data
*data
)
344 u8 fanin_ch
[NCT7363_PWM_COUNT
];
345 struct of_phandle_args args
;
349 ret
= of_parse_phandle_with_args(child
, "pwms", "#pwm-cells",
354 if (args
.args
[0] >= NCT7363_PWM_COUNT
)
356 data
->pwm_mask
|= BIT(args
.args
[0]);
358 fanin_cnt
= of_property_count_u8_elems(child
, "tach-ch");
359 if (fanin_cnt
< 1 || fanin_cnt
> NCT7363_PWM_COUNT
)
362 ret
= of_property_read_u8_array(child
, "tach-ch", fanin_ch
, fanin_cnt
);
366 for (ch
= 0; ch
< fanin_cnt
; ch
++) {
367 index
= fanin_ch
[ch
];
368 if (index
>= NCT7363_PWM_COUNT
)
370 data
->fanin_mask
|= BIT(index
);
376 static bool nct7363_regmap_is_volatile(struct device
*dev
, unsigned int reg
)
379 case NCT7363_REG_LSRS(0) ... NCT7363_REG_LSRS(15):
380 case NCT7363_REG_FANINX_HVAL(0) ... NCT7363_REG_FANINX_LVAL(15):
381 case NCT7363_REG_FANINX_HL(0) ... NCT7363_REG_FANINX_LL(15):
382 case NCT7363_REG_FSCPXDUTY(0) ... NCT7363_REG_FSCPXDIV(15):
389 static const struct regmap_config nct7363_regmap_config
= {
392 .use_single_read
= true,
393 .use_single_write
= true,
394 .cache_type
= REGCACHE_RBTREE
,
395 .volatile_reg
= nct7363_regmap_is_volatile
,
398 static int nct7363_probe(struct i2c_client
*client
)
400 struct device
*dev
= &client
->dev
;
401 struct device_node
*child
;
402 struct nct7363_data
*data
;
403 struct device
*hwmon_dev
;
406 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
410 data
->regmap
= devm_regmap_init_i2c(client
, &nct7363_regmap_config
);
411 if (IS_ERR(data
->regmap
))
412 return PTR_ERR(data
->regmap
);
414 for_each_child_of_node(dev
->of_node
, child
) {
415 ret
= nct7363_present_pwm_fanin(dev
, child
, data
);
422 /* Initialize the chip */
423 ret
= nct7363_init_chip(data
);
428 devm_hwmon_device_register_with_info(dev
, client
->name
, data
,
429 &nct7363_chip_info
, NULL
);
430 return PTR_ERR_OR_ZERO(hwmon_dev
);
433 static struct i2c_driver nct7363_driver
= {
434 .class = I2C_CLASS_HWMON
,
437 .of_match_table
= nct7363_of_match
,
439 .probe
= nct7363_probe
,
442 module_i2c_driver(nct7363_driver
);
444 MODULE_AUTHOR("CW Ho <cwho@nuvoton.com>");
445 MODULE_AUTHOR("Ban Feng <kcfeng0@nuvoton.com>");
446 MODULE_DESCRIPTION("NCT7363 Hardware Monitoring Driver");
447 MODULE_LICENSE("GPL");