File Index
Files and directories
Sign in
FILE

ftsteutates.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hwmon/ftsteutates.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Support for the FTS Systemmonitoring Chip "Teutates"
  4 *
  5 * Copyright (C) 2016 Fujitsu Technology Solutions GmbH,
  6 *		  Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>
  7 */
  8#include <linux/err.h>
  9#include <linux/hwmon.h>
 10#include <linux/i2c.h>
 11#include <linux/init.h>
 12#include <linux/jiffies.h>
 13#include <linux/math.h>
 14#include <linux/module.h>
 15#include <linux/slab.h>
 16#include <linux/watchdog.h>
 17
 18#define FTS_DEVICE_ID_REG		0x0000
 19#define FTS_DEVICE_REVISION_REG		0x0001
 20#define FTS_DEVICE_STATUS_REG		0x0004
 21#define FTS_SATELLITE_STATUS_REG	0x0005
 22#define FTS_EVENT_STATUS_REG		0x0006
 23#define FTS_GLOBAL_CONTROL_REG		0x0007
 24
 25#define FTS_DEVICE_DETECT_REG_1		0x0C
 26#define FTS_DEVICE_DETECT_REG_2		0x0D
 27#define FTS_DEVICE_DETECT_REG_3		0x0E
 28
 29#define FTS_SENSOR_EVENT_REG		0x0010
 30
 31#define FTS_FAN_EVENT_REG		0x0014
 32#define FTS_FAN_PRESENT_REG		0x0015
 33
 34#define FTS_POWER_ON_TIME_COUNTER_A	0x007A
 35#define FTS_POWER_ON_TIME_COUNTER_B	0x007B
 36#define FTS_POWER_ON_TIME_COUNTER_C	0x007C
 37
 38#define FTS_PAGE_SELECT_REG		0x007F
 39
 40#define FTS_WATCHDOG_TIME_PRESET	0x000B
 41#define FTS_WATCHDOG_CONTROL		0x5081
 42
 43#define FTS_NO_FAN_SENSORS		0x08
 44#define FTS_NO_TEMP_SENSORS		0x10
 45#define FTS_NO_VOLT_SENSORS		0x04
 46
 47#define FTS_FAN_SOURCE_INVALID		0xff
 48
 49static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 50
 51static const struct i2c_device_id fts_id[] = {
 52	{ "ftsteutates" },
 53	{ }
 54};
 55MODULE_DEVICE_TABLE(i2c, fts_id);
 56
 57enum WATCHDOG_RESOLUTION {
 58	seconds = 1,
 59	minutes = 60
 60};
 61
 62struct fts_data {
 63	struct i2c_client *client;
 64	unsigned long last_updated; /* in jiffies */
 65	struct watchdog_device wdd;
 66	enum WATCHDOG_RESOLUTION resolution;
 67	bool valid; /* false until following fields are valid */
 68
 69	u8 volt[FTS_NO_VOLT_SENSORS];
 70
 71	u8 temp_input[FTS_NO_TEMP_SENSORS];
 72	u8 temp_alarm;
 73
 74	u8 fan_present;
 75	u8 fan_input[FTS_NO_FAN_SENSORS]; /* in rps */
 76	u8 fan_source[FTS_NO_FAN_SENSORS];
 77	u8 fan_alarm;
 78};
 79
 80#define FTS_REG_FAN_INPUT(idx) ((idx) + 0x20)
 81#define FTS_REG_FAN_SOURCE(idx) ((idx) + 0x30)
 82#define FTS_REG_FAN_CONTROL(idx) (((idx) << 16) + 0x4881)
 83
 84#define FTS_REG_TEMP_INPUT(idx) ((idx) + 0x40)
 85#define FTS_REG_TEMP_CONTROL(idx) (((idx) << 16) + 0x0681)
 86
 87#define FTS_REG_VOLT(idx) ((idx) + 0x18)
 88
 89/*****************************************************************************/
 90/* I2C Helper functions							     */
 91/*****************************************************************************/
 92static int fts_read_byte(struct i2c_client *client, unsigned short reg)
 93{
 94	int ret;
 95	unsigned char page = reg >> 8;
 96
 97	dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page);
 98	ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page);
 99	if (ret < 0)
100		return ret;
101
102	reg &= 0xFF;
103	ret = i2c_smbus_read_byte_data(client, reg);
104	dev_dbg(&client->dev, "read - reg: 0x%.02x: val: 0x%.02x\n", reg, ret);
105	return ret;
106}
107
108static int fts_write_byte(struct i2c_client *client, unsigned short reg,
109			  unsigned char value)
110{
111	int ret;
112	unsigned char page = reg >> 8;
113
114	dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page);
115	ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page);
116	if (ret < 0)
117		return ret;
118
119	reg &= 0xFF;
120	dev_dbg(&client->dev,
121		"write - reg: 0x%.02x: val: 0x%.02x\n", reg, value);
122	ret = i2c_smbus_write_byte_data(client, reg, value);
123	return ret;
124}
125
126/*****************************************************************************/
127/* Data Updater Helper function						     */
128/*****************************************************************************/
129static int fts_update_device(struct fts_data *data)
130{
131	int i, err;
132
133	if (!time_after(jiffies, data->last_updated + 2 * HZ) && data->valid)
134		return 0;
135
136	err = fts_read_byte(data->client, FTS_DEVICE_STATUS_REG);
137	if (err < 0)
138		return err;
139
140	data->valid = !!(err & 0x02); /* Data not ready yet */
141	if (unlikely(!data->valid))
142		return -EAGAIN;
143
144	err = fts_read_byte(data->client, FTS_FAN_PRESENT_REG);
145	if (err < 0)
146		return err;
147	data->fan_present = err;
148
149	err = fts_read_byte(data->client, FTS_FAN_EVENT_REG);
150	if (err < 0)
151		return err;
152	data->fan_alarm = err;
153
154	for (i = 0; i < FTS_NO_FAN_SENSORS; i++) {
155		if (data->fan_present & BIT(i)) {
156			err = fts_read_byte(data->client, FTS_REG_FAN_INPUT(i));
157			if (err < 0)
158				return err;
159			data->fan_input[i] = err;
160
161			err = fts_read_byte(data->client,
162					    FTS_REG_FAN_SOURCE(i));
163			if (err < 0)
164				return err;
165			data->fan_source[i] = err;
166		} else {
167			data->fan_input[i] = 0;
168			data->fan_source[i] = FTS_FAN_SOURCE_INVALID;
169		}
170	}
171
172	err = fts_read_byte(data->client, FTS_SENSOR_EVENT_REG);
173	if (err < 0)
174		return err;
175	data->temp_alarm = err;
176
177	for (i = 0; i < FTS_NO_TEMP_SENSORS; i++) {
178		err = fts_read_byte(data->client, FTS_REG_TEMP_INPUT(i));
179		if (err < 0)
180			return err;
181		data->temp_input[i] = err;
182	}
183
184	for (i = 0; i < FTS_NO_VOLT_SENSORS; i++) {
185		err = fts_read_byte(data->client, FTS_REG_VOLT(i));
186		if (err < 0)
187			return err;
188		data->volt[i] = err;
189	}
190	data->last_updated = jiffies;
191	return 0;
192}
193
194/*****************************************************************************/
195/* Watchdog functions							     */
196/*****************************************************************************/
197static int fts_wd_set_resolution(struct fts_data *data,
198				 enum WATCHDOG_RESOLUTION resolution)
199{
200	int ret;
201
202	if (data->resolution == resolution)
203		return 0;
204
205	ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL);
206	if (ret < 0)
207		return ret;
208
209	if ((resolution == seconds && ret & BIT(1)) ||
210	    (resolution == minutes && (ret & BIT(1)) == 0)) {
211		data->resolution = resolution;
212		return 0;
213	}
214
215	if (resolution == seconds)
216		ret |= BIT(1);
217	else
218		ret &= ~BIT(1);
219
220	ret = fts_write_byte(data->client, FTS_WATCHDOG_CONTROL, ret);
221	if (ret < 0)
222		return ret;
223
224	data->resolution = resolution;
225	return ret;
226}
227
228static int fts_wd_set_timeout(struct watchdog_device *wdd, unsigned int timeout)
229{
230	struct fts_data *data;
231	enum WATCHDOG_RESOLUTION resolution = seconds;
232	int ret;
233
234	data = watchdog_get_drvdata(wdd);
235	/* switch watchdog resolution to minutes if timeout does not fit
236	 * into a byte
237	 */
238	if (timeout > 0xFF) {
239		timeout = DIV_ROUND_UP(timeout, 60) * 60;
240		resolution = minutes;
241	}
242
243	ret = fts_wd_set_resolution(data, resolution);
244	if (ret < 0)
245		return ret;
246
247	wdd->timeout = timeout;
248	return 0;
249}
250
251static int fts_wd_start(struct watchdog_device *wdd)
252{
253	struct fts_data *data = watchdog_get_drvdata(wdd);
254
255	return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET,
256			      wdd->timeout / (u8)data->resolution);
257}
258
259static int fts_wd_stop(struct watchdog_device *wdd)
260{
261	struct fts_data *data;
262
263	data = watchdog_get_drvdata(wdd);
264	return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET, 0);
265}
266
267static const struct watchdog_info fts_wd_info = {
268	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
269	.identity = "FTS Teutates Hardware Watchdog",
270};
271
272static const struct watchdog_ops fts_wd_ops = {
273	.owner = THIS_MODULE,
274	.start = fts_wd_start,
275	.stop = fts_wd_stop,
276	.set_timeout = fts_wd_set_timeout,
277};
278
279static int fts_watchdog_init(struct fts_data *data)
280{
281	int timeout, ret;
282
283	watchdog_set_drvdata(&data->wdd, data);
284
285	timeout = fts_read_byte(data->client, FTS_WATCHDOG_TIME_PRESET);
286	if (timeout < 0)
287		return timeout;
288
289	/* watchdog not running, set timeout to a default of 60 sec. */
290	if (timeout == 0) {
291		ret = fts_wd_set_resolution(data, seconds);
292		if (ret < 0)
293			return ret;
294		data->wdd.timeout = 60;
295	} else {
296		ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL);
297		if (ret < 0)
298			return ret;
299
300		data->resolution = ret & BIT(1) ? seconds : minutes;
301		data->wdd.timeout = timeout * (u8)data->resolution;
302		set_bit(WDOG_HW_RUNNING, &data->wdd.status);
303	}
304
305	/* Register our watchdog part */
306	data->wdd.info = &fts_wd_info;
307	data->wdd.ops = &fts_wd_ops;
308	data->wdd.parent = &data->client->dev;
309	data->wdd.min_timeout = 1;
310
311	/* max timeout 255 minutes. */
312	data->wdd.max_hw_heartbeat_ms = 0xFF * 60 * MSEC_PER_SEC;
313
314	return devm_watchdog_register_device(&data->client->dev, &data->wdd);
315}
316
317static umode_t fts_is_visible(const void *devdata, enum hwmon_sensor_types type, u32 attr,
318			      int channel)
319{
320	switch (type) {
321	case hwmon_temp:
322		switch (attr) {
323		case hwmon_temp_input:
324		case hwmon_temp_fault:
325			return 0444;
326		case hwmon_temp_alarm:
327			return 0644;
328		default:
329			break;
330		}
331		break;
332	case hwmon_fan:
333		switch (attr) {
334		case hwmon_fan_input:
335		case hwmon_fan_fault:
336			return 0444;
337		case hwmon_fan_alarm:
338			return 0644;
339		default:
340			break;
341		}
342		break;
343	case hwmon_pwm:
344	case hwmon_in:
345		return 0444;
346	default:
347		break;
348	}
349
350	return 0;
351}
352
353static int fts_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
354		    long *val)
355{
356	struct fts_data *data = dev_get_drvdata(dev);
357	int ret = fts_update_device(data);
358
359	if (ret < 0)
360		return ret;
361
362	switch (type) {
363	case hwmon_temp:
364		switch (attr) {
365		case hwmon_temp_input:
366			*val = (data->temp_input[channel] - 64) * 1000;
367
368			return 0;
369		case hwmon_temp_alarm:
370			*val = !!(data->temp_alarm & BIT(channel));
371
372			return 0;
373		case hwmon_temp_fault:
374			/* 00h Temperature = Sensor Error */;
375			*val = (data->temp_input[channel] == 0);
376
377			return 0;
378		default:
379			break;
380		}
381		break;
382	case hwmon_fan:
383		switch (attr) {
384		case hwmon_fan_input:
385			*val = data->fan_input[channel] * 60;
386
387			return 0;
388		case hwmon_fan_alarm:
389			*val = !!(data->fan_alarm & BIT(channel));
390
391			return 0;
392		case hwmon_fan_fault:
393			*val = !(data->fan_present & BIT(channel));
394
395			return 0;
396		default:
397			break;
398		}
399		break;
400	case hwmon_pwm:
401		switch (attr) {
402		case hwmon_pwm_auto_channels_temp: {
403			u8 fan_source = data->fan_source[channel];
404
405			if (fan_source == FTS_FAN_SOURCE_INVALID || fan_source >= BITS_PER_LONG)
406				*val = 0;
407			else
408				*val = BIT(fan_source);
409
410			return 0;
411		}
412		default:
413			break;
414		}
415		break;
416	case hwmon_in:
417		switch (attr) {
418		case hwmon_in_input:
419			*val = DIV_ROUND_CLOSEST(data->volt[channel] * 3300, 255);
420
421			return 0;
422		default:
423			break;
424		}
425		break;
426	default:
427		break;
428	}
429
430	return -EOPNOTSUPP;
431}
432
433static int fts_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
434		     long val)
435{
436	struct fts_data *data = dev_get_drvdata(dev);
437	int ret = fts_update_device(data);
438
439	if (ret < 0)
440		return ret;
441
442	switch (type) {
443	case hwmon_temp:
444		switch (attr) {
445		case hwmon_temp_alarm:
446			if (val)
447				return -EINVAL;
448
449			ret = fts_read_byte(data->client, FTS_REG_TEMP_CONTROL(channel));
450			if (ret < 0)
451				return ret;
452			ret = fts_write_byte(data->client, FTS_REG_TEMP_CONTROL(channel),
453					     ret | 0x1);
454			if (ret < 0)
455				return ret;
456			data->valid = false;
457			return 0;
458		default:
459			break;
460		}
461		break;
462	case hwmon_fan:
463		switch (attr) {
464		case hwmon_fan_alarm:
465			if (val)
466				return -EINVAL;
467
468			ret = fts_read_byte(data->client, FTS_REG_FAN_CONTROL(channel));
469			if (ret < 0)
470				return ret;
471			ret = fts_write_byte(data->client, FTS_REG_FAN_CONTROL(channel),
472					     ret | 0x1);
473			if (ret < 0)
474				return ret;
475			data->valid = false;
476			return 0;
477		default:
478			break;
479		}
480		break;
481	default:
482		break;
483	}
484
485	return -EOPNOTSUPP;
486}
487
488static const struct hwmon_ops fts_ops = {
489	.is_visible = fts_is_visible,
490	.read = fts_read,
491	.write = fts_write,
492};
493
494static const struct hwmon_channel_info * const fts_info[] = {
495	HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
496	HWMON_CHANNEL_INFO(temp,
497			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
498			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
499			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
500			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
501			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
502			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
503			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
504			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
505			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
506			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
507			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
508			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
509			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
510			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
511			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT,
512			   HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_FAULT
513			   ),
514	HWMON_CHANNEL_INFO(fan,
515			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT,
516			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT,
517			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT,
518			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT,
519			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT,
520			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT,
521			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT,
522			   HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT
523			   ),
524	HWMON_CHANNEL_INFO(pwm,
525			   HWMON_PWM_AUTO_CHANNELS_TEMP,
526			   HWMON_PWM_AUTO_CHANNELS_TEMP,
527			   HWMON_PWM_AUTO_CHANNELS_TEMP,
528			   HWMON_PWM_AUTO_CHANNELS_TEMP,
529			   HWMON_PWM_AUTO_CHANNELS_TEMP,
530			   HWMON_PWM_AUTO_CHANNELS_TEMP,
531			   HWMON_PWM_AUTO_CHANNELS_TEMP,
532			   HWMON_PWM_AUTO_CHANNELS_TEMP
533			   ),
534	HWMON_CHANNEL_INFO(in,
535			   HWMON_I_INPUT,
536			   HWMON_I_INPUT,
537			   HWMON_I_INPUT,
538			   HWMON_I_INPUT
539			   ),
540	NULL
541};
542
543static const struct hwmon_chip_info fts_chip_info = {
544	.ops = &fts_ops,
545	.info = fts_info,
546};
547
548/*****************************************************************************/
549/* Module initialization / remove functions				     */
550/*****************************************************************************/
551static int fts_detect(struct i2c_client *client,
552		      struct i2c_board_info *info)
553{
554	int val;
555
556	/* detection works with revision greater or equal to 0x2b */
557	val = i2c_smbus_read_byte_data(client, FTS_DEVICE_REVISION_REG);
558	if (val < 0x2b)
559		return -ENODEV;
560
561	/* Device Detect Regs must have 0x17 0x34 and 0x54 */
562	val = i2c_smbus_read_byte_data(client, FTS_DEVICE_DETECT_REG_1);
563	if (val != 0x17)
564		return -ENODEV;
565
566	val = i2c_smbus_read_byte_data(client, FTS_DEVICE_DETECT_REG_2);
567	if (val != 0x34)
568		return -ENODEV;
569
570	val = i2c_smbus_read_byte_data(client, FTS_DEVICE_DETECT_REG_3);
571	if (val != 0x54)
572		return -ENODEV;
573
574	/*
575	 * 0x10 == Baseboard Management Controller, 0x01 == Teutates
576	 * Device ID Reg needs to be 0x11
577	 */
578	val = i2c_smbus_read_byte_data(client, FTS_DEVICE_ID_REG);
579	if (val != 0x11)
580		return -ENODEV;
581
582	strscpy(info->type, fts_id[0].name, I2C_NAME_SIZE);
583	info->flags = 0;
584	return 0;
585}
586
587static int fts_probe(struct i2c_client *client)
588{
589	u8 revision;
590	struct fts_data *data;
591	int err;
592	s8 deviceid;
593	struct device *hwmon_dev;
594
595	if (client->addr != 0x73)
596		return -ENODEV;
597
598	/* Baseboard Management Controller check */
599	deviceid = i2c_smbus_read_byte_data(client, FTS_DEVICE_ID_REG);
600	if (deviceid > 0 && (deviceid & 0xF0) == 0x10) {
601		switch (deviceid & 0x0F) {
602		case 0x01:
603			break;
604		default:
605			dev_dbg(&client->dev,
606				"No Baseboard Management Controller\n");
607			return -ENODEV;
608		}
609	} else {
610		dev_dbg(&client->dev, "No fujitsu board\n");
611		return -ENODEV;
612	}
613
614	data = devm_kzalloc(&client->dev, sizeof(struct fts_data),
615			    GFP_KERNEL);
616	if (!data)
617		return -ENOMEM;
618
619	data->client = client;
620	dev_set_drvdata(&client->dev, data);
621
622	err = i2c_smbus_read_byte_data(client, FTS_DEVICE_REVISION_REG);
623	if (err < 0)
624		return err;
625	revision = err;
626
627	hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, "ftsteutates", data,
628							 &fts_chip_info, NULL);
629	if (IS_ERR(hwmon_dev))
630		return PTR_ERR(hwmon_dev);
631
632	err = fts_watchdog_init(data);
633	if (err)
634		return err;
635
636	dev_info(&client->dev, "Detected FTS Teutates chip, revision: %d.%d\n",
637		 (revision & 0xF0) >> 4, revision & 0x0F);
638	return 0;
639}
640
641/*****************************************************************************/
642/* Module Details							     */
643/*****************************************************************************/
644static struct i2c_driver fts_driver = {
645	.class = I2C_CLASS_HWMON,
646	.driver = {
647		.name = "ftsteutates",
648	},
649	.id_table = fts_id,
650	.probe = fts_probe,
651	.detect = fts_detect,
652	.address_list = normal_i2c,
653};
654
655module_i2c_driver(fts_driver);
656
657MODULE_AUTHOR("Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>");
658MODULE_DESCRIPTION("FTS Teutates driver");
659MODULE_LICENSE("GPL");
~/ Read-only file preview.