1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * hdc3020.c - Support for the TI HDC3020,HDC3021 and HDC3022
4 * temperature + relative humidity sensors
5 *
6 * Copyright (C) 2023
7 *
8 * Copyright (C) 2024 Liebherr-Electronics and Drives GmbH
9 *
10 * Datasheet: https://www.ti.com/lit/ds/symlink/hdc3020.pdf
11 */
12
13#include <linux/bitfield.h>
14#include <linux/bitops.h>
15#include <linux/cleanup.h>
16#include <linux/crc8.h>
17#include <linux/delay.h>
18#include <linux/i2c.h>
19#include <linux/init.h>
20#include <linux/interrupt.h>
21#include <linux/module.h>
22#include <linux/mutex.h>
23#include <linux/units.h>
24
25#include <asm/unaligned.h>
26
27#include <linux/iio/events.h>
28#include <linux/iio/iio.h>
29
30#define HDC3020_S_AUTO_10HZ_MOD0	0x2737
31#define HDC3020_S_STATUS		0x3041
32#define HDC3020_HEATER_DISABLE		0x3066
33#define HDC3020_HEATER_ENABLE		0x306D
34#define HDC3020_HEATER_CONFIG		0x306E
35#define HDC3020_EXIT_AUTO		0x3093
36#define HDC3020_S_T_RH_THRESH_LOW	0x6100
37#define HDC3020_S_T_RH_THRESH_LOW_CLR	0x610B
38#define HDC3020_S_T_RH_THRESH_HIGH_CLR	0x6116
39#define HDC3020_S_T_RH_THRESH_HIGH	0x611D
40#define HDC3020_R_T_RH_AUTO		0xE000
41#define HDC3020_R_T_LOW_AUTO		0xE002
42#define HDC3020_R_T_HIGH_AUTO		0xE003
43#define HDC3020_R_RH_LOW_AUTO		0xE004
44#define HDC3020_R_RH_HIGH_AUTO		0xE005
45#define HDC3020_R_T_RH_THRESH_LOW	0xE102
46#define HDC3020_R_T_RH_THRESH_LOW_CLR	0xE109
47#define HDC3020_R_T_RH_THRESH_HIGH_CLR	0xE114
48#define HDC3020_R_T_RH_THRESH_HIGH	0xE11F
49#define HDC3020_R_STATUS		0xF32D
50
51#define HDC3020_THRESH_TEMP_MASK	GENMASK(8, 0)
52#define HDC3020_THRESH_TEMP_TRUNC_SHIFT	7
53#define HDC3020_THRESH_HUM_MASK		GENMASK(15, 9)
54#define HDC3020_THRESH_HUM_TRUNC_SHIFT	9
55
56#define HDC3020_STATUS_T_LOW_ALERT	BIT(6)
57#define HDC3020_STATUS_T_HIGH_ALERT	BIT(7)
58#define HDC3020_STATUS_RH_LOW_ALERT	BIT(8)
59#define HDC3020_STATUS_RH_HIGH_ALERT	BIT(9)
60
61#define HDC3020_READ_RETRY_TIMES	10
62#define HDC3020_BUSY_DELAY_MS		10
63
64#define HDC3020_CRC8_POLYNOMIAL		0x31
65
66#define HDC3020_MIN_TEMP		-40
67#define HDC3020_MAX_TEMP		125
68
69struct hdc3020_data {
70	struct i2c_client *client;
71	/*
72	 * Ensure that the sensor configuration (currently only heater is
73	 * supported) will not be changed during the process of reading
74	 * sensor data (this driver will try HDC3020_READ_RETRY_TIMES times
75	 * if the device does not respond).
76	 */
77	struct mutex lock;
78};
79
80static const int hdc3020_heater_vals[] = {0, 1, 0x3FFF};
81
82static const struct iio_event_spec hdc3020_t_rh_event[] = {
83	{
84		.type = IIO_EV_TYPE_THRESH,
85		.dir = IIO_EV_DIR_RISING,
86		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
87		BIT(IIO_EV_INFO_HYSTERESIS),
88	},
89	{
90		.type = IIO_EV_TYPE_THRESH,
91		.dir = IIO_EV_DIR_FALLING,
92		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
93		BIT(IIO_EV_INFO_HYSTERESIS),
94	},
95};
96
97static const struct iio_chan_spec hdc3020_channels[] = {
98	{
99		.type = IIO_TEMP,
100		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
101		BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |
102		BIT(IIO_CHAN_INFO_TROUGH) | BIT(IIO_CHAN_INFO_OFFSET),
103		.event_spec = hdc3020_t_rh_event,
104		.num_event_specs = ARRAY_SIZE(hdc3020_t_rh_event),
105	},
106	{
107		.type = IIO_HUMIDITYRELATIVE,
108		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
109		BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |
110		BIT(IIO_CHAN_INFO_TROUGH),
111		.event_spec = hdc3020_t_rh_event,
112		.num_event_specs = ARRAY_SIZE(hdc3020_t_rh_event),
113	},
114	{
115		/*
116		 * For setting the internal heater, which can be switched on to
117		 * prevent or remove any condensation that may develop when the
118		 * ambient environment approaches its dew point temperature.
119		 */
120		.type = IIO_CURRENT,
121		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
122		.info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW),
123		.output = 1,
124	},
125};
126
127DECLARE_CRC8_TABLE(hdc3020_crc8_table);
128
129static int hdc3020_write_bytes(struct hdc3020_data *data, u8 *buf, u8 len)
130{
131	struct i2c_client *client = data->client;
132	struct i2c_msg msg;
133	int ret, cnt;
134
135	msg.addr = client->addr;
136	msg.flags = 0;
137	msg.buf = buf;
138	msg.len = len;
139
140	/*
141	 * During the measurement process, HDC3020 will not return data.
142	 * So wait for a while and try again
143	 */
144	for (cnt = 0; cnt < HDC3020_READ_RETRY_TIMES; cnt++) {
145		ret = i2c_transfer(client->adapter, &msg, 1);
146		if (ret == 1)
147			return 0;
148
149		mdelay(HDC3020_BUSY_DELAY_MS);
150	}
151	dev_err(&client->dev, "Could not write sensor command\n");
152
153	return -ETIMEDOUT;
154}
155
156static
157int hdc3020_read_bytes(struct hdc3020_data *data, u16 reg, u8 *buf, int len)
158{
159	u8 reg_buf[2];
160	int ret, cnt;
161	struct i2c_client *client = data->client;
162	struct i2c_msg msg[2] = {
163		[0] = {
164			.addr = client->addr,
165			.flags = 0,
166			.buf = reg_buf,
167			.len = 2,
168		},
169		[1] = {
170			.addr = client->addr,
171			.flags = I2C_M_RD,
172			.buf = buf,
173			.len = len,
174		},
175	};
176
177	put_unaligned_be16(reg, reg_buf);
178	/*
179	 * During the measurement process, HDC3020 will not return data.
180	 * So wait for a while and try again
181	 */
182	for (cnt = 0; cnt < HDC3020_READ_RETRY_TIMES; cnt++) {
183		ret = i2c_transfer(client->adapter, msg, 2);
184		if (ret == 2)
185			return 0;
186
187		mdelay(HDC3020_BUSY_DELAY_MS);
188	}
189	dev_err(&client->dev, "Could not read sensor data\n");
190
191	return -ETIMEDOUT;
192}
193
194static int hdc3020_read_be16(struct hdc3020_data *data, u16 reg)
195{
196	u8 crc, buf[3];
197	int ret;
198
199	ret = hdc3020_read_bytes(data, reg, buf, 3);
200	if (ret < 0)
201		return ret;
202
203	crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
204	if (crc != buf[2])
205		return -EINVAL;
206
207	return get_unaligned_be16(buf);
208}
209
210static int hdc3020_exec_cmd(struct hdc3020_data *data, u16 reg)
211{
212	u8 reg_buf[2];
213
214	put_unaligned_be16(reg, reg_buf);
215	return hdc3020_write_bytes(data, reg_buf, 2);
216}
217
218static int hdc3020_read_measurement(struct hdc3020_data *data,
219				    enum iio_chan_type type, int *val)
220{
221	u8 crc, buf[6];
222	int ret;
223
224	ret = hdc3020_read_bytes(data, HDC3020_R_T_RH_AUTO, buf, 6);
225	if (ret < 0)
226		return ret;
227
228	/* CRC check of the temperature measurement */
229	crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
230	if (crc != buf[2])
231		return -EINVAL;
232
233	/* CRC check of the relative humidity measurement */
234	crc = crc8(hdc3020_crc8_table, buf + 3, 2, CRC8_INIT_VALUE);
235	if (crc != buf[5])
236		return -EINVAL;
237
238	if (type == IIO_TEMP)
239		*val = get_unaligned_be16(buf);
240	else if (type == IIO_HUMIDITYRELATIVE)
241		*val = get_unaligned_be16(&buf[3]);
242	else
243		return -EINVAL;
244
245	return 0;
246}
247
248static int hdc3020_read_raw(struct iio_dev *indio_dev,
249			    struct iio_chan_spec const *chan, int *val,
250			    int *val2, long mask)
251{
252	struct hdc3020_data *data = iio_priv(indio_dev);
253	int ret;
254
255	if (chan->type != IIO_TEMP && chan->type != IIO_HUMIDITYRELATIVE)
256		return -EINVAL;
257
258	switch (mask) {
259	case IIO_CHAN_INFO_RAW: {
260		guard(mutex)(&data->lock);
261		ret = hdc3020_read_measurement(data, chan->type, val);
262		if (ret < 0)
263			return ret;
264
265		return IIO_VAL_INT;
266	}
267	case IIO_CHAN_INFO_PEAK: {
268		guard(mutex)(&data->lock);
269		if (chan->type == IIO_TEMP)
270			ret = hdc3020_read_be16(data, HDC3020_R_T_HIGH_AUTO);
271		else
272			ret = hdc3020_read_be16(data, HDC3020_R_RH_HIGH_AUTO);
273
274		if (ret < 0)
275			return ret;
276
277		*val = ret;
278		return IIO_VAL_INT;
279	}
280	case IIO_CHAN_INFO_TROUGH: {
281		guard(mutex)(&data->lock);
282		if (chan->type == IIO_TEMP)
283			ret = hdc3020_read_be16(data, HDC3020_R_T_LOW_AUTO);
284		else
285			ret = hdc3020_read_be16(data, HDC3020_R_RH_LOW_AUTO);
286
287		if (ret < 0)
288			return ret;
289
290		*val = ret;
291		return IIO_VAL_INT;
292	}
293	case IIO_CHAN_INFO_SCALE:
294		*val2 = 65536;
295		if (chan->type == IIO_TEMP)
296			*val = 175;
297		else
298			*val = 100;
299		return IIO_VAL_FRACTIONAL;
300
301	case IIO_CHAN_INFO_OFFSET:
302		if (chan->type != IIO_TEMP)
303			return -EINVAL;
304
305		*val = -16852;
306		return IIO_VAL_INT;
307
308	default:
309		return -EINVAL;
310	}
311}
312
313static int hdc3020_read_available(struct iio_dev *indio_dev,
314				  struct iio_chan_spec const *chan,
315				  const int **vals,
316				  int *type, int *length, long mask)
317{
318	if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_CURRENT)
319		return -EINVAL;
320
321	*vals = hdc3020_heater_vals;
322	*type = IIO_VAL_INT;
323
324	return IIO_AVAIL_RANGE;
325}
326
327static int hdc3020_update_heater(struct hdc3020_data *data, int val)
328{
329	u8 buf[5];
330	int ret;
331
332	if (val < hdc3020_heater_vals[0] || val > hdc3020_heater_vals[2])
333		return -EINVAL;
334
335	if (!val)
336		hdc3020_exec_cmd(data, HDC3020_HEATER_DISABLE);
337
338	put_unaligned_be16(HDC3020_HEATER_CONFIG, buf);
339	put_unaligned_be16(val & GENMASK(13, 0), &buf[2]);
340	buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
341	ret = hdc3020_write_bytes(data, buf, 5);
342	if (ret < 0)
343		return ret;
344
345	return hdc3020_exec_cmd(data, HDC3020_HEATER_ENABLE);
346}
347
348static int hdc3020_write_raw(struct iio_dev *indio_dev,
349			     struct iio_chan_spec const *chan,
350			     int val, int val2, long mask)
351{
352	struct hdc3020_data *data = iio_priv(indio_dev);
353
354	switch (mask) {
355	case IIO_CHAN_INFO_RAW:
356		if (chan->type != IIO_CURRENT)
357			return -EINVAL;
358
359		guard(mutex)(&data->lock);
360		return hdc3020_update_heater(data, val);
361	}
362
363	return -EINVAL;
364}
365
366static int hdc3020_write_thresh(struct iio_dev *indio_dev,
367				const struct iio_chan_spec *chan,
368				enum iio_event_type type,
369				enum iio_event_direction dir,
370				enum iio_event_info info,
371				int val, int val2)
372{
373	struct hdc3020_data *data = iio_priv(indio_dev);
374	u8 buf[5];
375	u64 tmp;
376	u16 reg;
377	int ret;
378
379	/* Supported temperature range is from ���40 to 125 degree celsius */
380	if (val < HDC3020_MIN_TEMP || val > HDC3020_MAX_TEMP)
381		return -EINVAL;
382
383	/* Select threshold register */
384	if (info == IIO_EV_INFO_VALUE) {
385		if (dir == IIO_EV_DIR_RISING)
386			reg = HDC3020_S_T_RH_THRESH_HIGH;
387		else
388			reg = HDC3020_S_T_RH_THRESH_LOW;
389	} else {
390		if (dir == IIO_EV_DIR_RISING)
391			reg = HDC3020_S_T_RH_THRESH_HIGH_CLR;
392		else
393			reg = HDC3020_S_T_RH_THRESH_LOW_CLR;
394	}
395
396	guard(mutex)(&data->lock);
397	ret = hdc3020_read_be16(data, reg);
398	if (ret < 0)
399		return ret;
400
401	switch (chan->type) {
402	case IIO_TEMP:
403		/*
404		 * Calculate temperature threshold, shift it down to get the
405		 * truncated threshold representation in the 9LSBs while keeping
406		 * the current humidity threshold in the 7 MSBs.
407		 */
408		tmp = ((u64)(((val + 45) * MICRO) + val2)) * 65535ULL;
409		tmp = div_u64(tmp, MICRO * 175);
410		val = tmp >> HDC3020_THRESH_TEMP_TRUNC_SHIFT;
411		val = FIELD_PREP(HDC3020_THRESH_TEMP_MASK, val);
412		val |= (FIELD_GET(HDC3020_THRESH_HUM_MASK, ret) <<
413			HDC3020_THRESH_HUM_TRUNC_SHIFT);
414		break;
415	case IIO_HUMIDITYRELATIVE:
416		/*
417		 * Calculate humidity threshold, shift it down and up to get the
418		 * truncated threshold representation in the 7MSBs while keeping
419		 * the current temperature threshold in the 9 LSBs.
420		 */
421		tmp = ((u64)((val * MICRO) + val2)) * 65535ULL;
422		tmp = div_u64(tmp, MICRO * 100);
423		val = tmp >> HDC3020_THRESH_HUM_TRUNC_SHIFT;
424		val = FIELD_PREP(HDC3020_THRESH_HUM_MASK, val);
425		val |= FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
426		break;
427	default:
428		return -EOPNOTSUPP;
429	}
430
431	put_unaligned_be16(reg, buf);
432	put_unaligned_be16(val, buf + 2);
433	buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
434	return hdc3020_write_bytes(data, buf, 5);
435}
436
437static int hdc3020_read_thresh(struct iio_dev *indio_dev,
438			       const struct iio_chan_spec *chan,
439			       enum iio_event_type type,
440			       enum iio_event_direction dir,
441			       enum iio_event_info info,
442			       int *val, int *val2)
443{
444	struct hdc3020_data *data = iio_priv(indio_dev);
445	u16 reg;
446	int ret;
447
448	/* Select threshold register */
449	if (info == IIO_EV_INFO_VALUE) {
450		if (dir == IIO_EV_DIR_RISING)
451			reg = HDC3020_R_T_RH_THRESH_HIGH;
452		else
453			reg = HDC3020_R_T_RH_THRESH_LOW;
454	} else {
455		if (dir == IIO_EV_DIR_RISING)
456			reg = HDC3020_R_T_RH_THRESH_HIGH_CLR;
457		else
458			reg = HDC3020_R_T_RH_THRESH_LOW_CLR;
459	}
460
461	guard(mutex)(&data->lock);
462	ret = hdc3020_read_be16(data, reg);
463	if (ret < 0)
464		return ret;
465
466	switch (chan->type) {
467	case IIO_TEMP:
468		/*
469		 * Get the temperature threshold from 9 LSBs, shift them to get
470		 * the truncated temperature threshold representation and
471		 * calculate the threshold according to the formula in the
472		 * datasheet.
473		 */
474		*val = FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
475		*val = *val << HDC3020_THRESH_TEMP_TRUNC_SHIFT;
476		*val = -2949075 + (175 * (*val));
477		*val2 = 65535;
478		return IIO_VAL_FRACTIONAL;
479	case IIO_HUMIDITYRELATIVE:
480		/*
481		 * Get the humidity threshold from 7 MSBs, shift them to get the
482		 * truncated humidity threshold representation and calculate the
483		 * threshold according to the formula in the datasheet.
484		 */
485		*val = FIELD_GET(HDC3020_THRESH_HUM_MASK, ret);
486		*val = (*val << HDC3020_THRESH_HUM_TRUNC_SHIFT) * 100;
487		*val2 = 65535;
488		return IIO_VAL_FRACTIONAL;
489	default:
490		return -EOPNOTSUPP;
491	}
492}
493
494static irqreturn_t hdc3020_interrupt_handler(int irq, void *private)
495{
496	struct iio_dev *indio_dev = private;
497	struct hdc3020_data *data;
498	s64 time;
499	int ret;
500
501	data = iio_priv(indio_dev);
502	ret = hdc3020_read_be16(data, HDC3020_R_STATUS);
503	if (ret < 0)
504		return IRQ_HANDLED;
505
506	if (!(ret & (HDC3020_STATUS_T_HIGH_ALERT | HDC3020_STATUS_T_LOW_ALERT |
507		HDC3020_STATUS_RH_HIGH_ALERT | HDC3020_STATUS_RH_LOW_ALERT)))
508		return IRQ_NONE;
509
510	time = iio_get_time_ns(indio_dev);
511	if (ret & HDC3020_STATUS_T_HIGH_ALERT)
512		iio_push_event(indio_dev,
513			       IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
514						  IIO_NO_MOD,
515						  IIO_EV_TYPE_THRESH,
516						  IIO_EV_DIR_RISING),
517						  time);
518
519	if (ret & HDC3020_STATUS_T_LOW_ALERT)
520		iio_push_event(indio_dev,
521			       IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
522						  IIO_NO_MOD,
523						  IIO_EV_TYPE_THRESH,
524						  IIO_EV_DIR_FALLING),
525						  time);
526
527	if (ret & HDC3020_STATUS_RH_HIGH_ALERT)
528		iio_push_event(indio_dev,
529			       IIO_MOD_EVENT_CODE(IIO_HUMIDITYRELATIVE, 0,
530						  IIO_NO_MOD,
531						  IIO_EV_TYPE_THRESH,
532						  IIO_EV_DIR_RISING),
533						  time);
534
535	if (ret & HDC3020_STATUS_RH_LOW_ALERT)
536		iio_push_event(indio_dev,
537			       IIO_MOD_EVENT_CODE(IIO_HUMIDITYRELATIVE, 0,
538						  IIO_NO_MOD,
539						  IIO_EV_TYPE_THRESH,
540						  IIO_EV_DIR_FALLING),
541						  time);
542
543	return IRQ_HANDLED;
544}
545
546static const struct iio_info hdc3020_info = {
547	.read_raw = hdc3020_read_raw,
548	.write_raw = hdc3020_write_raw,
549	.read_avail = hdc3020_read_available,
550	.read_event_value = hdc3020_read_thresh,
551	.write_event_value = hdc3020_write_thresh,
552};
553
554static void hdc3020_stop(void *data)
555{
556	hdc3020_exec_cmd((struct hdc3020_data *)data, HDC3020_EXIT_AUTO);
557}
558
559static int hdc3020_probe(struct i2c_client *client)
560{
561	struct iio_dev *indio_dev;
562	struct hdc3020_data *data;
563	int ret;
564
565	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
566		return -EOPNOTSUPP;
567
568	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
569	if (!indio_dev)
570		return -ENOMEM;
571
572	data = iio_priv(indio_dev);
573	data->client = client;
574	mutex_init(&data->lock);
575
576	crc8_populate_msb(hdc3020_crc8_table, HDC3020_CRC8_POLYNOMIAL);
577
578	indio_dev->name = "hdc3020";
579	indio_dev->modes = INDIO_DIRECT_MODE;
580	indio_dev->info = &hdc3020_info;
581	indio_dev->channels = hdc3020_channels;
582	indio_dev->num_channels = ARRAY_SIZE(hdc3020_channels);
583	if (client->irq) {
584		ret = devm_request_threaded_irq(&client->dev, client->irq,
585						NULL, hdc3020_interrupt_handler,
586						IRQF_ONESHOT, "hdc3020",
587						indio_dev);
588		if (ret)
589			return dev_err_probe(&client->dev, ret,
590					     "Failed to request IRQ\n");
591
592		/*
593		 * The alert output is activated by default upon power up,
594		 * hardware reset, and soft reset. Clear the status register.
595		 */
596		ret = hdc3020_exec_cmd(data, HDC3020_S_STATUS);
597		if (ret)
598			return ret;
599	}
600
601	ret = hdc3020_exec_cmd(data, HDC3020_S_AUTO_10HZ_MOD0);
602	if (ret)
603		return dev_err_probe(&client->dev, ret,
604				     "Unable to set up measurement\n");
605
606	ret = devm_add_action_or_reset(&data->client->dev, hdc3020_stop, data);
607	if (ret)
608		return ret;
609
610	ret = devm_iio_device_register(&data->client->dev, indio_dev);
611	if (ret)
612		return dev_err_probe(&client->dev, ret, "Failed to add device");
613
614	return 0;
615}
616
617static const struct i2c_device_id hdc3020_id[] = {
618	{ "hdc3020" },
619	{ "hdc3021" },
620	{ "hdc3022" },
621	{ }
622};
623MODULE_DEVICE_TABLE(i2c, hdc3020_id);
624
625static const struct of_device_id hdc3020_dt_ids[] = {
626	{ .compatible = "ti,hdc3020" },
627	{ .compatible = "ti,hdc3021" },
628	{ .compatible = "ti,hdc3022" },
629	{ }
630};
631MODULE_DEVICE_TABLE(of, hdc3020_dt_ids);
632
633static struct i2c_driver hdc3020_driver = {
634	.driver = {
635		.name = "hdc3020",
636		.of_match_table = hdc3020_dt_ids,
637	},
638	.probe = hdc3020_probe,
639	.id_table = hdc3020_id,
640};
641module_i2c_driver(hdc3020_driver);
642
643MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gmail.com>");
644MODULE_AUTHOR("Li peiyu <579lpy@gmail.com>");
645MODULE_DESCRIPTION("TI HDC3020 humidity and temperature sensor driver");
646MODULE_LICENSE("GPL");
647