xref: /linux/drivers/hwmon/ftsteutates.c (revision 02892f90a9851f508e557b3c75e93fc178310d5f)
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 
49 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
50 
51 static const struct i2c_device_id fts_id[] = {
52 	{ "ftsteutates" },
53 	{ }
54 };
55 MODULE_DEVICE_TABLE(i2c, fts_id);
56 
57 enum WATCHDOG_RESOLUTION {
58 	seconds = 1,
59 	minutes = 60
60 };
61 
62 struct 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 /*****************************************************************************/
92 static 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 
108 static 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 /*****************************************************************************/
129 static 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 /*****************************************************************************/
197 static 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 
228 static 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 
251 static 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 
259 static 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 
267 static const struct watchdog_info fts_wd_info = {
268 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
269 	.identity = "FTS Teutates Hardware Watchdog",
270 };
271 
272 static 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 
279 static 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 
317 static 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 
353 static 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 
433 static 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 
488 static const struct hwmon_ops fts_ops = {
489 	.is_visible = fts_is_visible,
490 	.read = fts_read,
491 	.write = fts_write,
492 };
493 
494 static 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 
543 static 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 /*****************************************************************************/
551 static 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 
587 static 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 /*****************************************************************************/
644 static 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 
655 module_i2c_driver(fts_driver);
656 
657 MODULE_AUTHOR("Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>");
658 MODULE_DESCRIPTION("FTS Teutates driver");
659 MODULE_LICENSE("GPL");
660