1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
6 #include <linux/module.h>
7 #include <linux/power_supply.h>
8 #include <linux/regmap.h>
10 #define IP5XXX_SYS_CTL0 0x01
11 #define IP5XXX_SYS_CTL0_WLED_DET_EN BIT(4)
12 #define IP5XXX_SYS_CTL0_WLED_EN BIT(3)
13 #define IP5XXX_SYS_CTL0_BOOST_EN BIT(2)
14 #define IP5XXX_SYS_CTL0_CHARGER_EN BIT(1)
15 #define IP5XXX_SYS_CTL1 0x02
16 #define IP5XXX_SYS_CTL1_LIGHT_SHDN_EN BIT(1)
17 #define IP5XXX_SYS_CTL1_LOAD_PWRUP_EN BIT(0)
18 #define IP5XXX_SYS_CTL2 0x0c
19 #define IP5XXX_SYS_CTL2_LIGHT_SHDN_TH GENMASK(7, 3)
20 #define IP5XXX_SYS_CTL3 0x03
21 #define IP5XXX_SYS_CTL3_LONG_PRESS_TIME_SEL GENMASK(7, 6)
22 #define IP5XXX_SYS_CTL3_BTN_SHDN_EN BIT(5)
23 #define IP5XXX_SYS_CTL4 0x04
24 #define IP5XXX_SYS_CTL4_SHDN_TIME_SEL GENMASK(7, 6)
25 #define IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN BIT(5)
26 #define IP5XXX_SYS_CTL5 0x07
27 #define IP5XXX_SYS_CTL5_NTC_DIS BIT(6)
28 #define IP5XXX_SYS_CTL5_WLED_MODE_SEL BIT(1)
29 #define IP5XXX_SYS_CTL5_BTN_SHDN_SEL BIT(0)
30 #define IP5XXX_CHG_CTL1 0x22
31 #define IP5XXX_CHG_CTL1_BOOST_UVP_SEL GENMASK(3, 2)
32 #define IP5XXX_CHG_CTL2 0x24
33 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL GENMASK(6, 5)
34 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V (0x0 << 5)
35 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V (0x1 << 5)
36 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V (0x2 << 5)
37 #define IP5XXX_CHG_CTL2_CONST_VOLT_SEL GENMASK(2, 1)
38 #define IP5XXX_CHG_CTL4 0x26
39 #define IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN BIT(6)
40 #define IP5XXX_CHG_CTL4A 0x25
41 #define IP5XXX_CHG_CTL4A_CONST_CUR_SEL GENMASK(4, 0)
42 #define IP5XXX_MFP_CTL0 0x51
43 #define IP5XXX_MFP_CTL1 0x52
44 #define IP5XXX_GPIO_CTL2 0x53
45 #define IP5XXX_GPIO_CTL2A 0x54
46 #define IP5XXX_GPIO_CTL3 0x55
47 #define IP5XXX_READ0 0x71
48 #define IP5XXX_READ0_CHG_STAT GENMASK(7, 5)
49 #define IP5XXX_READ0_CHG_STAT_IDLE (0x0 << 5)
50 #define IP5XXX_READ0_CHG_STAT_TRICKLE (0x1 << 5)
51 #define IP5XXX_READ0_CHG_STAT_CONST_VOLT (0x2 << 5)
52 #define IP5XXX_READ0_CHG_STAT_CONST_CUR (0x3 << 5)
53 #define IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP (0x4 << 5)
54 #define IP5XXX_READ0_CHG_STAT_FULL (0x5 << 5)
55 #define IP5XXX_READ0_CHG_STAT_TIMEOUT (0x6 << 5)
56 #define IP5XXX_READ0_CHG_OP BIT(4)
57 #define IP5XXX_READ0_CHG_END BIT(3)
58 #define IP5XXX_READ0_CONST_VOLT_TIMEOUT BIT(2)
59 #define IP5XXX_READ0_CHG_TIMEOUT BIT(1)
60 #define IP5XXX_READ0_TRICKLE_TIMEOUT BIT(0)
61 #define IP5XXX_READ0_TIMEOUT GENMASK(2, 0)
62 #define IP5XXX_READ1 0x72
63 #define IP5XXX_READ1_WLED_PRESENT BIT(7)
64 #define IP5XXX_READ1_LIGHT_LOAD BIT(6)
65 #define IP5XXX_READ1_VIN_OVERVOLT BIT(5)
66 #define IP5XXX_READ2 0x77
67 #define IP5XXX_READ2_BTN_PRESS BIT(3)
68 #define IP5XXX_READ2_BTN_LONG_PRESS BIT(1)
69 #define IP5XXX_READ2_BTN_SHORT_PRESS BIT(0)
70 #define IP5XXX_BATVADC_DAT0 0xa2
71 #define IP5XXX_BATVADC_DAT1 0xa3
72 #define IP5XXX_BATIADC_DAT0 0xa4
73 #define IP5XXX_BATIADC_DAT1 0xa5
74 #define IP5XXX_BATOCV_DAT0 0xa8
75 #define IP5XXX_BATOCV_DAT1 0xa9
78 struct regmap
*regmap
;
83 * The IP5xxx charger only responds on I2C when it is "awake". The charger is
84 * generally only awake when VIN is powered or when its boost converter is
85 * enabled. Going into shutdown resets all register values. To handle this:
86 * 1) When any bus error occurs, assume the charger has gone into shutdown.
87 * 2) Attempt the initialization sequence on each subsequent register access
90 static int ip5xxx_read(struct ip5xxx
*ip5xxx
, unsigned int reg
,
95 ret
= regmap_read(ip5xxx
->regmap
, reg
, val
);
97 ip5xxx
->initialized
= false;
102 static int ip5xxx_update_bits(struct ip5xxx
*ip5xxx
, unsigned int reg
,
103 unsigned int mask
, unsigned int val
)
107 ret
= regmap_update_bits(ip5xxx
->regmap
, reg
, mask
, val
);
109 ip5xxx
->initialized
= false;
114 static int ip5xxx_initialize(struct power_supply
*psy
)
116 struct ip5xxx
*ip5xxx
= power_supply_get_drvdata(psy
);
119 if (ip5xxx
->initialized
)
123 * Disable shutdown under light load.
124 * Enable power on when under load.
126 ret
= ip5xxx_update_bits(ip5xxx
, IP5XXX_SYS_CTL1
,
127 IP5XXX_SYS_CTL1_LIGHT_SHDN_EN
|
128 IP5XXX_SYS_CTL1_LOAD_PWRUP_EN
,
129 IP5XXX_SYS_CTL1_LOAD_PWRUP_EN
);
134 * Enable shutdown after a long button press (as configured below).
136 ret
= ip5xxx_update_bits(ip5xxx
, IP5XXX_SYS_CTL3
,
137 IP5XXX_SYS_CTL3_BTN_SHDN_EN
,
138 IP5XXX_SYS_CTL3_BTN_SHDN_EN
);
143 * Power on automatically when VIN is removed.
145 ret
= ip5xxx_update_bits(ip5xxx
, IP5XXX_SYS_CTL4
,
146 IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN
,
147 IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN
);
153 * Configure the button for two presses => LED, long press => shutdown.
155 ret
= ip5xxx_update_bits(ip5xxx
, IP5XXX_SYS_CTL5
,
156 IP5XXX_SYS_CTL5_NTC_DIS
|
157 IP5XXX_SYS_CTL5_WLED_MODE_SEL
|
158 IP5XXX_SYS_CTL5_BTN_SHDN_SEL
,
159 IP5XXX_SYS_CTL5_WLED_MODE_SEL
|
160 IP5XXX_SYS_CTL5_BTN_SHDN_SEL
);
164 ip5xxx
->initialized
= true;
165 dev_dbg(psy
->dev
.parent
, "Initialized after power on\n");
170 static const enum power_supply_property ip5xxx_battery_properties
[] = {
171 POWER_SUPPLY_PROP_STATUS
,
172 POWER_SUPPLY_PROP_CHARGE_TYPE
,
173 POWER_SUPPLY_PROP_HEALTH
,
174 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
,
175 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
176 POWER_SUPPLY_PROP_VOLTAGE_OCV
,
177 POWER_SUPPLY_PROP_CURRENT_NOW
,
178 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
,
179 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
,
180 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
,
181 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
,
184 static int ip5xxx_battery_get_status(struct ip5xxx
*ip5xxx
, int *val
)
189 ret
= ip5xxx_read(ip5xxx
, IP5XXX_READ0
, &rval
);
193 switch (rval
& IP5XXX_READ0_CHG_STAT
) {
194 case IP5XXX_READ0_CHG_STAT_IDLE
:
195 *val
= POWER_SUPPLY_STATUS_DISCHARGING
;
197 case IP5XXX_READ0_CHG_STAT_TRICKLE
:
198 case IP5XXX_READ0_CHG_STAT_CONST_CUR
:
199 case IP5XXX_READ0_CHG_STAT_CONST_VOLT
:
200 *val
= POWER_SUPPLY_STATUS_CHARGING
;
202 case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP
:
203 case IP5XXX_READ0_CHG_STAT_FULL
:
204 *val
= POWER_SUPPLY_STATUS_FULL
;
206 case IP5XXX_READ0_CHG_STAT_TIMEOUT
:
207 *val
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
216 static int ip5xxx_battery_get_charge_type(struct ip5xxx
*ip5xxx
, int *val
)
221 ret
= ip5xxx_read(ip5xxx
, IP5XXX_READ0
, &rval
);
225 switch (rval
& IP5XXX_READ0_CHG_STAT
) {
226 case IP5XXX_READ0_CHG_STAT_IDLE
:
227 case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP
:
228 case IP5XXX_READ0_CHG_STAT_FULL
:
229 case IP5XXX_READ0_CHG_STAT_TIMEOUT
:
230 *val
= POWER_SUPPLY_CHARGE_TYPE_NONE
;
232 case IP5XXX_READ0_CHG_STAT_TRICKLE
:
233 *val
= POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
235 case IP5XXX_READ0_CHG_STAT_CONST_CUR
:
236 case IP5XXX_READ0_CHG_STAT_CONST_VOLT
:
237 *val
= POWER_SUPPLY_CHARGE_TYPE_STANDARD
;
246 static int ip5xxx_battery_get_health(struct ip5xxx
*ip5xxx
, int *val
)
251 ret
= ip5xxx_read(ip5xxx
, IP5XXX_READ0
, &rval
);
255 if (rval
& IP5XXX_READ0_TIMEOUT
)
256 *val
= POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE
;
258 *val
= POWER_SUPPLY_HEALTH_GOOD
;
263 static int ip5xxx_battery_get_voltage_max(struct ip5xxx
*ip5xxx
, int *val
)
268 ret
= ip5xxx_read(ip5xxx
, IP5XXX_CHG_CTL2
, &rval
);
273 * It is not clear what this will return if
274 * IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN is not set...
276 switch (rval
& IP5XXX_CHG_CTL2_BAT_TYPE_SEL
) {
277 case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V
:
280 case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V
:
283 case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V
:
293 static int ip5xxx_battery_read_adc(struct ip5xxx
*ip5xxx
,
294 u8 lo_reg
, u8 hi_reg
, int *val
)
299 ret
= ip5xxx_read(ip5xxx
, lo_reg
, &lo
);
303 ret
= ip5xxx_read(ip5xxx
, hi_reg
, &hi
);
307 *val
= sign_extend32(hi
<< 8 | lo
, 13);
312 static int ip5xxx_battery_get_property(struct power_supply
*psy
,
313 enum power_supply_property psp
,
314 union power_supply_propval
*val
)
316 struct ip5xxx
*ip5xxx
= power_supply_get_drvdata(psy
);
320 ret
= ip5xxx_initialize(psy
);
325 case POWER_SUPPLY_PROP_STATUS
:
326 return ip5xxx_battery_get_status(ip5xxx
, &val
->intval
);
328 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
329 return ip5xxx_battery_get_charge_type(ip5xxx
, &val
->intval
);
331 case POWER_SUPPLY_PROP_HEALTH
:
332 return ip5xxx_battery_get_health(ip5xxx
, &val
->intval
);
334 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
:
335 return ip5xxx_battery_get_voltage_max(ip5xxx
, &val
->intval
);
337 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
338 ret
= ip5xxx_battery_read_adc(ip5xxx
, IP5XXX_BATVADC_DAT0
,
339 IP5XXX_BATVADC_DAT1
, &raw
);
341 val
->intval
= 2600000 + DIV_ROUND_CLOSEST(raw
* 26855, 100);
344 case POWER_SUPPLY_PROP_VOLTAGE_OCV
:
345 ret
= ip5xxx_battery_read_adc(ip5xxx
, IP5XXX_BATOCV_DAT0
,
346 IP5XXX_BATOCV_DAT1
, &raw
);
348 val
->intval
= 2600000 + DIV_ROUND_CLOSEST(raw
* 26855, 100);
351 case POWER_SUPPLY_PROP_CURRENT_NOW
:
352 ret
= ip5xxx_battery_read_adc(ip5xxx
, IP5XXX_BATIADC_DAT0
,
353 IP5XXX_BATIADC_DAT1
, &raw
);
355 val
->intval
= DIV_ROUND_CLOSEST(raw
* 149197, 200);
358 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
:
359 ret
= ip5xxx_read(ip5xxx
, IP5XXX_CHG_CTL4A
, &rval
);
363 rval
&= IP5XXX_CHG_CTL4A_CONST_CUR_SEL
;
364 val
->intval
= 100000 * rval
;
367 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
368 val
->intval
= 100000 * 0x1f;
371 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
:
372 ret
= ip5xxx_battery_get_voltage_max(ip5xxx
, &vmax
);
376 ret
= ip5xxx_read(ip5xxx
, IP5XXX_CHG_CTL2
, &rval
);
380 rval
&= IP5XXX_CHG_CTL2_CONST_VOLT_SEL
;
381 val
->intval
= vmax
+ 14000 * (rval
>> 1);
384 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
:
385 ret
= ip5xxx_battery_get_voltage_max(ip5xxx
, &vmax
);
389 val
->intval
= vmax
+ 14000 * 3;
397 static int ip5xxx_battery_set_voltage_max(struct ip5xxx
*ip5xxx
, int val
)
404 rval
= IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V
;
407 rval
= IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V
;
410 rval
= IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V
;
416 ret
= ip5xxx_update_bits(ip5xxx
, IP5XXX_CHG_CTL2
,
417 IP5XXX_CHG_CTL2_BAT_TYPE_SEL
, rval
);
421 ret
= ip5xxx_update_bits(ip5xxx
, IP5XXX_CHG_CTL4
,
422 IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN
,
423 IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN
);
430 static int ip5xxx_battery_set_property(struct power_supply
*psy
,
431 enum power_supply_property psp
,
432 const union power_supply_propval
*val
)
434 struct ip5xxx
*ip5xxx
= power_supply_get_drvdata(psy
);
438 ret
= ip5xxx_initialize(psy
);
443 case POWER_SUPPLY_PROP_STATUS
:
444 switch (val
->intval
) {
445 case POWER_SUPPLY_STATUS_CHARGING
:
446 rval
= IP5XXX_SYS_CTL0_CHARGER_EN
;
448 case POWER_SUPPLY_STATUS_DISCHARGING
:
449 case POWER_SUPPLY_STATUS_NOT_CHARGING
:
455 return ip5xxx_update_bits(ip5xxx
, IP5XXX_SYS_CTL0
,
456 IP5XXX_SYS_CTL0_CHARGER_EN
, rval
);
458 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
:
459 return ip5xxx_battery_set_voltage_max(ip5xxx
, val
->intval
);
461 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
:
462 rval
= val
->intval
/ 100000;
463 return ip5xxx_update_bits(ip5xxx
, IP5XXX_CHG_CTL4A
,
464 IP5XXX_CHG_CTL4A_CONST_CUR_SEL
, rval
);
466 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
:
467 ret
= ip5xxx_battery_get_voltage_max(ip5xxx
, &vmax
);
471 rval
= ((val
->intval
- vmax
) / 14000) << 1;
472 return ip5xxx_update_bits(ip5xxx
, IP5XXX_CHG_CTL2
,
473 IP5XXX_CHG_CTL2_CONST_VOLT_SEL
, rval
);
480 static int ip5xxx_battery_property_is_writeable(struct power_supply
*psy
,
481 enum power_supply_property psp
)
483 return psp
== POWER_SUPPLY_PROP_STATUS
||
484 psp
== POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
||
485 psp
== POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
||
486 psp
== POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
;
489 static const struct power_supply_desc ip5xxx_battery_desc
= {
490 .name
= "ip5xxx-battery",
491 .type
= POWER_SUPPLY_TYPE_BATTERY
,
492 .properties
= ip5xxx_battery_properties
,
493 .num_properties
= ARRAY_SIZE(ip5xxx_battery_properties
),
494 .get_property
= ip5xxx_battery_get_property
,
495 .set_property
= ip5xxx_battery_set_property
,
496 .property_is_writeable
= ip5xxx_battery_property_is_writeable
,
499 static const enum power_supply_property ip5xxx_boost_properties
[] = {
500 POWER_SUPPLY_PROP_ONLINE
,
501 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
504 static int ip5xxx_boost_get_property(struct power_supply
*psy
,
505 enum power_supply_property psp
,
506 union power_supply_propval
*val
)
508 struct ip5xxx
*ip5xxx
= power_supply_get_drvdata(psy
);
512 ret
= ip5xxx_initialize(psy
);
517 case POWER_SUPPLY_PROP_ONLINE
:
518 ret
= ip5xxx_read(ip5xxx
, IP5XXX_SYS_CTL0
, &rval
);
522 val
->intval
= !!(rval
& IP5XXX_SYS_CTL0_BOOST_EN
);
525 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
526 ret
= ip5xxx_read(ip5xxx
, IP5XXX_CHG_CTL1
, &rval
);
530 rval
&= IP5XXX_CHG_CTL1_BOOST_UVP_SEL
;
531 val
->intval
= 4530000 + 100000 * (rval
>> 2);
539 static int ip5xxx_boost_set_property(struct power_supply
*psy
,
540 enum power_supply_property psp
,
541 const union power_supply_propval
*val
)
543 struct ip5xxx
*ip5xxx
= power_supply_get_drvdata(psy
);
547 ret
= ip5xxx_initialize(psy
);
552 case POWER_SUPPLY_PROP_ONLINE
:
553 rval
= val
->intval
? IP5XXX_SYS_CTL0_BOOST_EN
: 0;
554 return ip5xxx_update_bits(ip5xxx
, IP5XXX_SYS_CTL0
,
555 IP5XXX_SYS_CTL0_BOOST_EN
, rval
);
557 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
558 rval
= ((val
->intval
- 4530000) / 100000) << 2;
559 return ip5xxx_update_bits(ip5xxx
, IP5XXX_CHG_CTL1
,
560 IP5XXX_CHG_CTL1_BOOST_UVP_SEL
, rval
);
567 static int ip5xxx_boost_property_is_writeable(struct power_supply
*psy
,
568 enum power_supply_property psp
)
573 static const struct power_supply_desc ip5xxx_boost_desc
= {
574 .name
= "ip5xxx-boost",
575 .type
= POWER_SUPPLY_TYPE_USB
,
576 .properties
= ip5xxx_boost_properties
,
577 .num_properties
= ARRAY_SIZE(ip5xxx_boost_properties
),
578 .get_property
= ip5xxx_boost_get_property
,
579 .set_property
= ip5xxx_boost_set_property
,
580 .property_is_writeable
= ip5xxx_boost_property_is_writeable
,
583 static const struct regmap_config ip5xxx_regmap_config
= {
586 .max_register
= IP5XXX_BATOCV_DAT1
,
589 static int ip5xxx_power_probe(struct i2c_client
*client
)
591 struct power_supply_config psy_cfg
= {};
592 struct device
*dev
= &client
->dev
;
593 struct power_supply
*psy
;
594 struct ip5xxx
*ip5xxx
;
596 ip5xxx
= devm_kzalloc(dev
, sizeof(*ip5xxx
), GFP_KERNEL
);
600 ip5xxx
->regmap
= devm_regmap_init_i2c(client
, &ip5xxx_regmap_config
);
601 if (IS_ERR(ip5xxx
->regmap
))
602 return PTR_ERR(ip5xxx
->regmap
);
604 psy_cfg
.of_node
= dev
->of_node
;
605 psy_cfg
.drv_data
= ip5xxx
;
607 psy
= devm_power_supply_register(dev
, &ip5xxx_battery_desc
, &psy_cfg
);
611 psy
= devm_power_supply_register(dev
, &ip5xxx_boost_desc
, &psy_cfg
);
618 static const struct of_device_id ip5xxx_power_of_match
[] = {
619 { .compatible
= "injoinic,ip5108" },
620 { .compatible
= "injoinic,ip5109" },
621 { .compatible
= "injoinic,ip5207" },
622 { .compatible
= "injoinic,ip5209" },
625 MODULE_DEVICE_TABLE(of
, ip5xxx_power_of_match
);
627 static struct i2c_driver ip5xxx_power_driver
= {
628 .probe
= ip5xxx_power_probe
,
630 .name
= "ip5xxx-power",
631 .of_match_table
= ip5xxx_power_of_match
,
634 module_i2c_driver(ip5xxx_power_driver
);
636 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
637 MODULE_DESCRIPTION("Injoinic IP5xxx power bank IC driver");
638 MODULE_LICENSE("GPL");