1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for SFR NeufBox 6 Hardware Monitoring
5 * Copyright 2020 Álvaro Fernández Rojas <noltari@gmail.com>
6 * Copyright 2010 Miguel Gaio <miguel.gaio@efixo.com>
8 #include <linux/delay.h>
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/i2c.h>
13 #include <linux/hwmon.h>
14 #include <linux/err.h>
15 #include <linux/mutex.h>
16 #include <linux/pwm.h>
17 #include <linux/sysfs.h>
19 #define NB6_LEDS_PWM_REG 0x10
20 #define NB6_TEMP_REG 0x22
21 #define NB6_VOLTAGE_REG 0x24
22 #define NB6_DMESG_CTL_REG 0x26
23 #define NB6_DMESG_VAL_REG 0x27
24 #define NB6_LEDS_MODE_REG 0x31
25 #define NB6_RELEASE_REG 0x90
26 #define NB6_STATS_BOOT_REG 0xa0
27 #define NB6_STATS_PANIC_REG 0xa1
28 #define NB6_STATS_OOPS_REG 0xa2
29 #define NB6_WDT_REG 0xee
31 #define NB6_DELAY 1000
32 #define NB6_DMESG_SIZE 512
33 #define NB6_I2C_RETRIES 5
34 #define NB6_LEDS_MODE_LEN 32
35 #define NB6_LEDS_PWM_COUNT 9
36 #define NB6_PWM(x) (NB6_LEDS_PWM_REG + x)
37 #define NB6_WDT_LEN 10
39 #define ADC_quantum(Vref) ((1000 * (Vref)) / 1024)
40 #define ADC_mV(Vref,x) ((ADC_quantum(Vref) * (x)) / 1000)
41 #define ADC_Temperature(t) (1000 * (100 * ADC_mV(1800, t)) / 349)
44 #define ADC_Voltage(v) ((ADC_mV(2400, v) * ((10 * (MR1 + MR2)) / MR2)) / 10)
48 struct i2c_client
*i2c
;
52 u8 leds_pwm
[NB6_LEDS_PWM_COUNT
];
67 LEDS_MODE_BOOT_RESCUE
,
71 LEDS_MODE_WDT_TEMPERATURE
,
72 LEDS_MODE_WDT_VOLTAGE
,
78 static char const *leds_modes_str
[] = {
79 [LEDS_MODE_DISABLE
] = "disable",
80 [LEDS_MODE_BOOT
] = "boot",
81 [LEDS_MODE_BOOT_MAIN
] = "boot-main",
82 [LEDS_MODE_BOOT_TFTP
] = "boot-tftp",
83 [LEDS_MODE_BOOT_RESCUE
] = "boot-rescue",
84 [LEDS_MODE_LOGIN
] = "login",
85 [LEDS_MODE_BURNING
] = "burning",
86 [LEDS_MODE_DOWNLOAD
] = "downloading",
87 [LEDS_MODE_WDT_TEMPERATURE
] = "wdt-temperature",
88 [LEDS_MODE_WDT_VOLTAGE
] = "wdt-voltage",
89 [LEDS_MODE_PANIC
] = "panic",
90 [LEDS_MODE_CONTROL
] = "control",
95 static u8
nb6_readb(struct nb6_data
*data
, u8 addr
, u8 val
)
100 for (i
= 0; i
< NB6_I2C_RETRIES
; i
++) {
101 status
= i2c_smbus_read_byte_data(data
->i2c
, addr
);
107 dev_err(data
->dev
, "read error (%d): addr=0x%02x", status
, addr
);
112 static u16
nb6_readw(struct nb6_data
*data
, u8 addr
, u16 val
)
116 tmp
= nb6_readb(data
, addr
, (val
>> 8) & 0xff);
117 val
= (val
& 0xff) | (tmp
<< 8);
119 tmp
= nb6_readb(data
, addr
+ 1, val
& 0xff);
120 val
= (val
& 0xff00) | tmp
;
125 static s32
nb6_writeb(struct nb6_data
*data
, u8 addr
, u8 val
)
130 for (i
= 0; i
< NB6_I2C_RETRIES
; i
++) {
131 status
= i2c_smbus_write_byte_data(data
->i2c
, addr
, val
);
137 dev_err(data
->dev
, "write error (%d): addr=0x%02x val=0x%02x", status
, addr
, val
);
142 static inline void leds_mode_update(struct nb6_data
*data
, u8 val
)
144 if ((data
->leds_mode
!= val
) &&
145 !nb6_writeb(data
, NB6_LEDS_MODE_REG
, val
))
146 data
->leds_mode
= val
;
149 static inline void leds_pwm_update(struct nb6_data
*data
, u8 id
, u8 val
)
151 if ((data
->leds_pwm
[id
] != val
) &&
152 !nb6_writeb(data
, NB6_PWM(id
), val
))
153 data
->leds_pwm
[id
] = val
;
156 /* Hardware Monitoring */
158 static ssize_t
dmesg_show(struct device
*dev
, struct device_attribute
*attr
,
161 struct nb6_data
*data
= dev_get_drvdata(dev
);
164 mutex_lock(&data
->lock
);
166 if (nb6_writeb(data
, NB6_DMESG_CTL_REG
, 0)) {
167 mutex_unlock(&data
->lock
);
171 for (i
= 0; i
< NB6_DMESG_SIZE
; i
++)
172 buf
[i
] = nb6_readb(data
, NB6_DMESG_VAL_REG
, ~0);
174 mutex_unlock(&data
->lock
);
181 static DEVICE_ATTR_RO(dmesg
);
183 static ssize_t
leds_mode_show(struct device
*dev
,
184 struct device_attribute
*attr
, char *buf
)
186 struct nb6_data
*data
= dev_get_drvdata(dev
);
190 mutex_lock(&data
->lock
);
191 data
->leds_mode
= nb6_readb(data
, NB6_LEDS_MODE_REG
, data
->leds_mode
);
192 mutex_unlock(&data
->lock
);
194 for (i
= 0; i
< ARRAY_SIZE(leds_modes_str
); i
++) {
195 off
+= sprintf(buf
+ off
,
196 (i
== data
->leds_mode
) ? "[%s] " : "%s ",
200 off
+= sprintf(buf
+ off
, "\n");
205 static ssize_t
leds_mode_store(struct device
*dev
,
206 struct device_attribute
*attr
,
207 const char *buf
, size_t count
)
209 struct nb6_data
*data
= dev_get_drvdata(dev
);
210 char _s
[NB6_LEDS_MODE_LEN
];
214 snprintf(_s
, sizeof(_s
), "%s", buf
);
216 for (i
= 0; i
< ARRAY_SIZE(leds_modes_str
); i
++) {
217 if (!strcmp(s
, leds_modes_str
[i
])) {
218 leds_mode_update(data
, i
);
226 static DEVICE_ATTR_RW(leds_mode
);
228 static ssize_t
release_show(struct device
*dev
, struct device_attribute
*attr
,
231 struct nb6_data
*data
= dev_get_drvdata(dev
);
233 mutex_lock(&data
->lock
);
234 data
->release
= nb6_readb(data
, NB6_RELEASE_REG
, data
->release
);
235 mutex_unlock(&data
->lock
);
237 return sprintf(buf
, "%u\n", data
->release
);
240 static DEVICE_ATTR_RO(release
);
242 static ssize_t
stats_show(struct device
*dev
, struct device_attribute
*attr
,
245 struct nb6_data
*data
= dev_get_drvdata(dev
);
247 mutex_lock(&data
->lock
);
248 data
->stats_boot
= nb6_readb(data
, NB6_STATS_BOOT_REG
,
250 data
->stats_panic
= nb6_readb(data
, NB6_STATS_PANIC_REG
,
252 data
->stats_oops
= nb6_readb(data
, NB6_STATS_OOPS_REG
,
254 mutex_unlock(&data
->lock
);
256 return sprintf(buf
, "boot: %u\npanic: %u\noops: %u\n",
257 data
->stats_boot
, data
->stats_panic
, data
->stats_oops
);
260 static DEVICE_ATTR_RO(stats
);
262 static ssize_t
temperature_show(struct device
*dev
,
263 struct device_attribute
*da
, char *buf
)
265 struct nb6_data
*data
= dev_get_drvdata(dev
);
267 mutex_lock(&data
->lock
);
268 data
->temperature
= nb6_readw(data
, NB6_TEMP_REG
, data
->temperature
);
269 mutex_unlock(&data
->lock
);
271 return sprintf(buf
, "%u\n", ADC_Temperature(data
->temperature
));
274 static DEVICE_ATTR_RO(temperature
);
276 static ssize_t
voltage_show(struct device
*dev
, struct device_attribute
*attr
,
279 struct nb6_data
*data
= dev_get_drvdata(dev
);
281 mutex_lock(&data
->lock
);
282 data
->voltage
= nb6_readw(data
, NB6_VOLTAGE_REG
, data
->voltage
);
283 mutex_unlock(&data
->lock
);
285 return sprintf(buf
, "%u\n", ADC_Voltage(data
->voltage
));
288 static DEVICE_ATTR_RO(voltage
);
290 static ssize_t
watchdog_show(struct device
*dev
,
291 struct device_attribute
*attr
, char *buf
)
293 struct nb6_data
*data
= dev_get_drvdata(dev
);
295 mutex_lock(&data
->lock
);
296 data
->watchdog
= nb6_readb(data
, NB6_WDT_REG
, data
->watchdog
);
297 mutex_unlock(&data
->lock
);
299 return sprintf(buf
, "%u\n", data
->watchdog
);
302 static ssize_t
watchdog_store(struct device
*dev
,
303 struct device_attribute
*attr
, const char *buf
,
306 struct nb6_data
*data
= dev_get_drvdata(dev
);
310 ret
= kstrtoul(buf
, 0, &val
);
314 mutex_lock(&data
->lock
);
315 if (!nb6_writeb(data
, NB6_WDT_REG
, val
))
316 data
->watchdog
= val
;
317 mutex_unlock(&data
->lock
);
322 static DEVICE_ATTR_RW(watchdog
);
324 static struct attribute
*nb6_attrs
[] = {
325 &dev_attr_dmesg
.attr
,
326 &dev_attr_leds_mode
.attr
,
327 &dev_attr_release
.attr
,
328 &dev_attr_stats
.attr
,
329 &dev_attr_temperature
.attr
,
330 &dev_attr_voltage
.attr
,
331 &dev_attr_watchdog
.attr
,
335 ATTRIBUTE_GROUPS(nb6
);
339 static inline struct nb6_data
*to_nb6_pwm(struct pwm_chip
*chip
)
341 return container_of(chip
, struct nb6_data
, pwm
);
344 static int nb6_pwm_request(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
346 struct nb6_data
*data
= to_nb6_pwm(chip
);
348 mutex_lock(&data
->lock
);
349 if (!nb6_writeb(data
, NB6_PWM(pwm
->hwpwm
), 0))
350 data
->leds_pwm
[pwm
->hwpwm
] = 0;
352 data
->leds_pwm
[pwm
->hwpwm
] = ~0;
353 mutex_unlock(&data
->lock
);
358 static void nb6_pwm_free(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
360 struct nb6_data
*data
= to_nb6_pwm(chip
);
363 mutex_lock(&data
->lock
);
364 for (i
= 0; i
< NB6_LEDS_PWM_COUNT
; i
++) {
365 if (data
->leds_pwm
[i
]) {
366 leds_mode_update(data
, LEDS_MODE_DISABLE
);
370 mutex_unlock(&data
->lock
);
373 static int nb6_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
374 int duty_ns
, int period_ns
)
376 struct nb6_data
*data
= to_nb6_pwm(chip
);
378 mutex_lock(&data
->lock
);
379 leds_mode_update(data
, LEDS_MODE_CONTROL
);
380 leds_pwm_update(data
, pwm
->hwpwm
, duty_ns
);
381 mutex_unlock(&data
->lock
);
386 static int nb6_pwm_enable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
388 struct nb6_data
*data
= to_nb6_pwm(chip
);
390 mutex_lock(&data
->lock
);
391 leds_mode_update(data
, LEDS_MODE_CONTROL
);
392 mutex_unlock(&data
->lock
);
397 static void nb6_pwm_disable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
399 struct nb6_data
*data
= to_nb6_pwm(chip
);
401 mutex_lock(&data
->lock
);
402 leds_pwm_update(data
, pwm
->hwpwm
, 0);
403 mutex_unlock(&data
->lock
);
406 static const struct pwm_ops nb6_pwm_ops
= {
407 .request
= nb6_pwm_request
,
408 .free
= nb6_pwm_free
,
409 .config
= nb6_pwm_config
,
410 .enable
= nb6_pwm_enable
,
411 .disable
= nb6_pwm_disable
,
412 .owner
= THIS_MODULE
,
417 static int nb6_hwmon_probe(struct i2c_client
*client
,
418 const struct i2c_device_id
*id
)
420 struct device
*dev
= &client
->dev
;
421 struct nb6_data
*data
;
422 struct device
*hwmon_dev
;
425 data
= devm_kzalloc(dev
, sizeof(struct nb6_data
), GFP_KERNEL
);
431 data
->leds_mode
= LEDS_MODE_NUM
;
432 i2c_set_clientdata(client
, data
);
433 mutex_init(&data
->lock
);
435 hwmon_dev
= devm_hwmon_device_register_with_groups(dev
, client
->name
,
438 if (IS_ERR(hwmon_dev
))
439 return PTR_ERR(hwmon_dev
);
442 data
->pwm
.ops
= &nb6_pwm_ops
;
444 data
->pwm
.npwm
= NB6_LEDS_PWM_COUNT
;
446 ret
= pwmchip_add(&data
->pwm
);
453 static const struct of_device_id nb6_hwmon_of_match
[] = {
454 { .compatible
= "sfr,nb6_hwmon" },
457 MODULE_DEVICE_TABLE(of
, nb6_hwmon_of_match
);
459 static struct i2c_driver nb6_hwmon_driver
= {
460 .class = I2C_CLASS_HWMON
,
463 .of_match_table
= of_match_ptr(nb6_hwmon_of_match
),
465 .probe
= nb6_hwmon_probe
,
467 module_i2c_driver(nb6_hwmon_driver
);