blob: 92dbd48f3b244a384a41b6a9d9bc97f74582584a [file] [log] [blame]
Jack Pham4e9dff72017-04-04 18:05:53 -07001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/slab.h>
16#include <linux/interrupt.h>
17#include <linux/err.h>
18#include <linux/platform_device.h>
19#include <linux/extcon.h>
20#include <linux/delay.h>
21#include <linux/sysfs.h>
22#include <linux/io.h>
23#include <linux/bitops.h>
24#include <linux/tty.h>
25#include <linux/tty_flip.h>
26#include <linux/serial_core.h>
27#include <linux/serial.h>
Channagoud Kadabi75f54e82016-12-06 16:35:10 -080028#include <linux/workqueue.h>
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -070029#include <linux/power_supply.h>
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070030
31#define EUD_ENABLE_CMD 1
32#define EUD_DISABLE_CMD 0
33
34#define EUD_REG_COM_TX_ID 0x0000
35#define EUD_REG_COM_TX_LEN 0x0004
36#define EUD_REG_COM_TX_DAT 0x0008
37#define EUD_REG_COM_RX_ID 0x000C
38#define EUD_REG_COM_RX_LEN 0x0010
39#define EUD_REG_COM_RX_DAT 0x0014
40#define EUD_REG_INT1_EN_MASK 0x0024
41#define EUD_REG_INT_STATUS_1 0x0044
42#define EUD_REG_CTL_OUT_1 0x0074
43#define EUD_REG_VBUS_INT_CLR 0x0080
44#define EUD_REG_CHGR_INT_CLR 0x0084
45#define EUD_REG_CSR_EUD_EN 0x1014
46#define EUD_REG_SW_ATTACH_DET 0x1018
47
48#define EUD_INT_RX BIT(0)
49#define EUD_INT_TX BIT(1)
50#define EUD_INT_VBUS BIT(2)
51#define EUD_INT_CHGR BIT(3)
52#define EUD_INT_SAFE_MODE BIT(4)
53#define EUD_INT_ALL (EUD_INT_RX | EUD_INT_TX | \
54 EUD_INT_VBUS | EUD_INT_CHGR | \
55 EUD_INT_SAFE_MODE)
56
57#define EUD_NR 1
58#define EUD_CONSOLE NULL
59#define UART_ID 0x90
60#define MAX_FIFO_SIZE 14
61
62struct eud_chip {
63 struct device *dev;
64 int eud_irq;
Channagoud Kadabi75f54e82016-12-06 16:35:10 -080065 unsigned int extcon_id;
66 unsigned int int_status;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070067 bool usb_attach;
68 bool chgr_enable;
69 void __iomem *eud_reg_base;
70 struct extcon_dev *extcon;
71 struct uart_port port;
Channagoud Kadabi75f54e82016-12-06 16:35:10 -080072 struct work_struct eud_work;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070073};
74
75static const unsigned int eud_extcon_cable[] = {
76 EXTCON_USB,
77 EXTCON_CHG_USB_SDP,
78 EXTCON_NONE,
79};
80
81/*
82 * On the kernel command line specify eud.enable=1 to enable EUD.
83 * EUD is disabled by default.
84 */
85static int enable;
86static struct platform_device *eud_private;
87
88static void enable_eud(struct platform_device *pdev)
89{
90 struct eud_chip *priv = platform_get_drvdata(pdev);
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -070091 struct power_supply *usb_psy = NULL;
92 union power_supply_propval pval = {0};
93 union power_supply_propval tval = {0};
94 int ret;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070095
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -070096 usb_psy = power_supply_get_by_name("usb");
97 if (!usb_psy) {
98 dev_warn(&pdev->dev, "Could not get usb power_supply\n");
99 return;
100 }
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800101
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -0700102 ret = power_supply_get_property(usb_psy,
103 POWER_SUPPLY_PROP_PRESENT, &pval);
104 if (ret) {
105 dev_err(&pdev->dev, "Unable to read USB PRESENT: %x\n", ret);
106 return;
107 }
108
109 ret = power_supply_get_property(usb_psy,
110 POWER_SUPPLY_PROP_REAL_TYPE, &tval);
111 if (ret) {
112 dev_err(&pdev->dev, "Unable to read USB TYPE: %x\n", ret);
113 return;
114 }
115
116 if (pval.intval && (tval.intval == POWER_SUPPLY_TYPE_USB ||
117 tval.intval == POWER_SUPPLY_TYPE_USB_CDP)) {
118 /* write into CSR to enable EUD */
119 writel_relaxed(BIT(0), priv->eud_reg_base + EUD_REG_CSR_EUD_EN);
120 /* Enable vbus, chgr & safe mode warning interrupts */
121 writel_relaxed(EUD_INT_VBUS | EUD_INT_CHGR | EUD_INT_SAFE_MODE,
122 priv->eud_reg_base + EUD_REG_INT1_EN_MASK);
123
124 /* Ensure Register Writes Complete */
125 wmb();
126
127 /*
128 * Set the default cable state to usb connect and charger
129 * enable
130 */
131 extcon_set_state_sync(priv->extcon, EXTCON_USB, true);
132 extcon_set_state_sync(priv->extcon, EXTCON_CHG_USB_SDP, true);
133 } else {
134 dev_warn(&pdev->dev, "Connect USB cable before enabling EUD\n");
135 return;
136 }
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800137
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700138 dev_dbg(&pdev->dev, "%s: EUD Enabled!\n", __func__);
139}
140
141static void disable_eud(struct platform_device *pdev)
142{
143 struct eud_chip *priv = platform_get_drvdata(pdev);
144
145 /* write into CSR to disable EUD */
146 writel_relaxed(0, priv->eud_reg_base + EUD_REG_CSR_EUD_EN);
147 dev_dbg(&pdev->dev, "%s: EUD Disabled!\n", __func__);
148}
149
150static int param_eud_set(const char *val, const struct kernel_param *kp)
151{
152 int enable = 0;
153
154 if (sscanf(val, "%du", &enable) != 1)
155 return -EINVAL;
156
157 if (enable != EUD_ENABLE_CMD && enable != EUD_DISABLE_CMD)
158 return -EINVAL;
159
160 if (enable == EUD_ENABLE_CMD) {
161 pr_debug("%s: Enbling EUD\n", __func__);
162 enable_eud(eud_private);
163 } else if (enable == EUD_DISABLE_CMD) {
164 pr_debug("%s: Disabling EUD\n", __func__);
165 disable_eud(eud_private);
166 }
167
168 *((uint *)kp->arg) = enable;
169 return 0;
170}
171
172static const struct kernel_param_ops eud_param_ops = {
173 .set = param_eud_set,
174 .get = param_get_int,
175};
176
177module_param_cb(enable, &eud_param_ops, &enable, 0644);
178
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800179static void eud_event_notifier(struct work_struct *eud_work)
180{
181 struct eud_chip *chip = container_of(eud_work, struct eud_chip,
182 eud_work);
183
184 if (chip->int_status == EUD_INT_VBUS)
Jack Pham4e9dff72017-04-04 18:05:53 -0700185 extcon_set_state_sync(chip->extcon, chip->extcon_id,
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800186 chip->usb_attach);
187 else if (chip->int_status == EUD_INT_CHGR)
Jack Pham4e9dff72017-04-04 18:05:53 -0700188 extcon_set_state_sync(chip->extcon, chip->extcon_id,
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800189 chip->chgr_enable);
190}
191
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700192static void usb_attach_detach(struct eud_chip *chip)
193{
194 u32 reg;
195
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800196 chip->extcon_id = EXTCON_USB;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700197 /* read ctl_out_1[4] to find USB attach or detach event */
198 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_CTL_OUT_1);
199 if (reg & BIT(4))
200 chip->usb_attach = true;
201 else
202 chip->usb_attach = false;
203
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800204 schedule_work(&chip->eud_work);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700205
206 /* set and clear vbus_int_clr[0] to clear interrupt */
207 writel_relaxed(BIT(0), chip->eud_reg_base + EUD_REG_VBUS_INT_CLR);
208 /* Ensure Register Writes Complete */
209 wmb();
210 writel_relaxed(0, chip->eud_reg_base + EUD_REG_VBUS_INT_CLR);
211}
212
213static void chgr_enable_disable(struct eud_chip *chip)
214{
215 u32 reg;
216
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800217 chip->extcon_id = EXTCON_CHG_USB_SDP;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700218 /* read ctl_out_1[6] to find charger enable or disable event */
219 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_CTL_OUT_1);
220 if (reg & BIT(6))
221 chip->chgr_enable = true;
222 else
223 chip->chgr_enable = false;
224
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800225 schedule_work(&chip->eud_work);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700226
227 /* set and clear chgr_int_clr[0] to clear interrupt */
228 writel_relaxed(BIT(0), chip->eud_reg_base + EUD_REG_CHGR_INT_CLR);
229 /* Ensure Register Writes Complete */
230 wmb();
231 writel_relaxed(0, chip->eud_reg_base + EUD_REG_CHGR_INT_CLR);
232}
233
234static void pet_eud(struct eud_chip *chip)
235{
236 u32 reg;
237
238 /* read sw_attach_det[0] to find attach/detach event */
239 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_SW_ATTACH_DET);
240 if (reg & BIT(0)) {
241 /* Detach & Attach pet for EUD */
242 writel_relaxed(0, chip->eud_reg_base + EUD_REG_SW_ATTACH_DET);
243 /* Ensure Register Writes Complete */
244 wmb();
245 /* Delay to make sure detach pet is done before attach pet */
246 udelay(100);
247 writel_relaxed(BIT(0), chip->eud_reg_base +
248 EUD_REG_SW_ATTACH_DET);
249 /* Ensure Register Writes Complete */
250 wmb();
251 } else {
252 /* Attach pet for EUD */
253 writel_relaxed(BIT(0), chip->eud_reg_base +
254 EUD_REG_SW_ATTACH_DET);
255 /* Ensure Register Writes Complete */
256 wmb();
257 }
258}
259
260static unsigned int eud_tx_empty(struct uart_port *port)
261{
262 u32 reg;
263
264 /* read status register and cross check for Tx interrupt */
265 reg = readl_relaxed(port->membase + EUD_REG_INT_STATUS_1);
266 if (reg & EUD_INT_TX)
267 return TIOCSER_TEMT;
268 else
269 return 0;
270}
271
272static void eud_stop_tx(struct uart_port *port)
273{
274 /* Disable Tx interrupt */
275 writel_relaxed(~EUD_INT_TX, port->membase + EUD_REG_INT_STATUS_1);
276 /* Ensure Register Writes Complete */
277 wmb();
278}
279
280static void eud_start_tx(struct uart_port *port)
281{
282 /* Enable Tx interrupt */
283 writel_relaxed(EUD_INT_TX, port->membase + EUD_REG_INT_STATUS_1);
284 /* Ensure Register Writes Complete */
285 wmb();
286}
287
288static void eud_stop_rx(struct uart_port *port)
289{
290 /* Disable Rx interrupt */
291 writel_relaxed(~EUD_INT_RX, port->membase + EUD_REG_INT_STATUS_1);
292 /* Ensure Register Writes Complete */
293 wmb();
294}
295
296static int eud_startup(struct uart_port *port)
297{
298 /* Enable Rx interrupt */
299 writel_relaxed(EUD_INT_RX, port->membase + EUD_REG_INT_STATUS_1);
300 /* Ensure Register Writes Complete */
301 wmb();
302 return 0;
303}
304
305static void eud_shutdown(struct uart_port *port)
306{
307 /* Disable both Tx & Rx interrupts */
308 writel_relaxed(~EUD_INT_TX | ~EUD_INT_RX,
309 port->membase + EUD_REG_INT_STATUS_1);
310 /* Ensure Register Writes Complete */
311 wmb();
312}
313
314static const char *eud_type(struct uart_port *port)
315{
316 return (port->type == PORT_EUD_UART) ? "EUD UART" : NULL;
317}
318
319static int eud_request_port(struct uart_port *port)
320{
321 /* Nothing to request */
322 return 0;
323}
324
325static void eud_release_port(struct uart_port *port)
326{
327 /* Nothing to release */
328}
329
330static void eud_config_port(struct uart_port *port, int flags)
331{
332 /* set port type, clear Tx and Rx interrupts */
333 port->type = PORT_EUD_UART;
334 writel_relaxed(~EUD_INT_TX | ~EUD_INT_RX,
335 port->membase + EUD_REG_INT_STATUS_1);
336 /* Ensure Register Writes Complete */
337 wmb();
338}
339
340static int eud_verify_port(struct uart_port *port,
341 struct serial_struct *ser)
342{
343 if (ser->type != PORT_UNKNOWN && ser->type != PORT_EUD_UART)
344 return -EINVAL;
345 return 0;
346}
347
348/* serial functions supported */
349static const struct uart_ops eud_uart_ops = {
350 .tx_empty = eud_tx_empty,
351 .stop_tx = eud_stop_tx,
352 .start_tx = eud_start_tx,
353 .stop_rx = eud_stop_rx,
354 .startup = eud_startup,
355 .shutdown = eud_shutdown,
356 .type = eud_type,
357 .release_port = eud_release_port,
358 .request_port = eud_request_port,
359 .config_port = eud_config_port,
360 .verify_port = eud_verify_port,
361};
362
363static struct uart_driver eud_uart_driver = {
364 .owner = THIS_MODULE,
365 .driver_name = "msm-eud",
366 .dev_name = "ttyEUD",
367 .nr = EUD_NR,
368 .cons = EUD_CONSOLE,
369};
370
371static void eud_uart_rx(struct eud_chip *chip)
372{
373 struct uart_port *port = &chip->port;
374 u32 reg;
375 unsigned int len;
376 unsigned char ch, flag;
377 int i;
378
379 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_RX_ID);
380 if (reg != UART_ID) {
381 dev_err(chip->dev, "Rx isn't for us!\n");
382 return;
383 }
384 /* Read Rx Len & Data registers */
385 spin_lock(&port->lock);
386 len = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_RX_LEN);
387 for (i = 0; i < len; i++) {
388 ch = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_RX_DAT);
389 flag = TTY_NORMAL;
390 port->icount.rx++;
391
392 if (uart_handle_sysrq_char(port, ch))
393 continue;
394 uart_insert_char(port, 0, 0, ch, flag);
395 }
396
397 spin_unlock(&port->lock);
398 tty_flip_buffer_push(&port->state->port);
399}
400
401static void eud_uart_tx(struct eud_chip *chip)
402{
403 struct uart_port *port = &chip->port;
404 struct circ_buf *xmit = &port->state->xmit;
405 unsigned int len;
406 u32 reg;
407
408 writel_relaxed(UART_ID, chip->eud_reg_base + EUD_REG_COM_TX_ID);
409 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_TX_ID);
410 if (reg != UART_ID) {
411 dev_err(chip->dev, "Tx isn't for us!\n");
412 return;
413 }
414 /* Write to Tx Len & Data registers */
415 spin_lock(&port->lock);
416 len = uart_circ_chars_pending(xmit);
417 if (len > 0) {
418 if (len > port->fifosize)
419 len = port->fifosize;
420 while (len--) {
421 writel_relaxed(xmit->buf[xmit->tail],
422 port->membase + EUD_REG_COM_TX_DAT);
423 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
424 port->icount.tx++;
425 }
426 }
427 spin_unlock(&port->lock);
428}
429
430static irqreturn_t handle_eud_irq(int irq, void *data)
431{
432 struct eud_chip *chip = data;
433 u32 reg;
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800434 u32 int_mask_en1 = readl_relaxed(chip->eud_reg_base +
435 EUD_REG_INT1_EN_MASK);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700436
437 /* read status register and find out which interrupt triggered */
438 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_INT_STATUS_1);
439 if (reg & EUD_INT_RX) {
440 dev_dbg(chip->dev, "EUD RX Interrupt!\n");
441 eud_uart_rx(chip);
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800442 } else if ((reg & EUD_INT_TX) & int_mask_en1) {
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700443 dev_dbg(chip->dev, "EUD TX Interrupt!\n");
444 eud_uart_tx(chip);
445 } else if (reg & EUD_INT_VBUS) {
446 dev_dbg(chip->dev, "EUD VBUS Interrupt!\n");
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800447 chip->int_status = EUD_INT_VBUS;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700448 usb_attach_detach(chip);
449 } else if (reg & EUD_INT_CHGR) {
450 dev_dbg(chip->dev, "EUD CHGR Interrupt!\n");
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800451 chip->int_status = EUD_INT_CHGR;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700452 chgr_enable_disable(chip);
453 } else if (reg & EUD_INT_SAFE_MODE) {
454 dev_dbg(chip->dev, "EUD SAFE MODE Interrupt!\n");
455 pet_eud(chip);
456 } else {
457 dev_dbg(chip->dev, "Unknown/spurious EUD Interrupt!\n");
458 return IRQ_NONE;
459 }
460
461 return IRQ_HANDLED;
462}
463
464static int msm_eud_probe(struct platform_device *pdev)
465{
466 struct eud_chip *chip;
467 struct uart_port *port;
468 struct resource *res;
469 int ret;
470
471 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
472 if (!chip) {
473 ret = -ENOMEM;
474 return ret;
475 }
476
477 platform_set_drvdata(pdev, chip);
478
479 chip->extcon = devm_extcon_dev_allocate(&pdev->dev, eud_extcon_cable);
480 if (IS_ERR(chip->extcon)) {
481 dev_err(chip->dev, "failed to allocate extcon device\n");
482 return PTR_ERR(chip->extcon);
483 }
484
485 ret = devm_extcon_dev_register(&pdev->dev, chip->extcon);
486 if (ret) {
487 dev_err(chip->dev, "failed to register extcon device\n");
488 return ret;
489 }
490
491 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eud_base");
492 if (!res) {
493 dev_err(chip->dev, "%s: failed to get resource eud_base\n",
494 __func__);
495 ret = -ENOMEM;
496 return ret;
497 }
498
499 chip->eud_reg_base = devm_ioremap_resource(&pdev->dev, res);
500 if (IS_ERR(chip->eud_reg_base))
501 return PTR_ERR(chip->eud_reg_base);
502
503 chip->eud_irq = platform_get_irq_byname(pdev, "eud_irq");
504
505 ret = devm_request_irq(&pdev->dev, chip->eud_irq, handle_eud_irq,
506 IRQF_TRIGGER_HIGH, "eud_irq", chip);
507 if (ret) {
508 dev_err(chip->dev, "request failed for eud irq\n");
509 return ret;
510 }
511
512 device_init_wakeup(&pdev->dev, true);
513 enable_irq_wake(chip->eud_irq);
514
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800515 INIT_WORK(&chip->eud_work, eud_event_notifier);
516
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700517 port = &chip->port;
518 port->line = pdev->id;
519 port->type = PORT_EUD_UART;
520 port->dev = chip->dev;
521 port->fifosize = MAX_FIFO_SIZE;
522 port->iotype = SERIAL_IO_MEM;
523 port->flags = UPF_BOOT_AUTOCONF;
524 port->membase = chip->eud_reg_base;
525 port->irq = chip->eud_irq;
526 port->ops = &eud_uart_ops;
527
528 ret = uart_add_one_port(&eud_uart_driver, port);
529 if (!ret) {
530 dev_err(chip->dev, "failed to add uart port!\n");
531 return ret;
532 }
533
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700534 eud_private = pdev;
535
536 /* Enable EUD */
537 if (enable)
538 enable_eud(pdev);
539
540 return 0;
541}
542
543static int msm_eud_remove(struct platform_device *pdev)
544{
545 struct eud_chip *chip = platform_get_drvdata(pdev);
546 struct uart_port *port = &chip->port;
547
548 uart_remove_one_port(&eud_uart_driver, port);
549 device_init_wakeup(chip->dev, false);
550
551 return 0;
552}
553
554static const struct of_device_id msm_eud_dt_match[] = {
555 {.compatible = "qcom,msm-eud"},
556 {},
557};
558MODULE_DEVICE_TABLE(of, msm_eud_dt_match);
559
560static struct platform_driver msm_eud_driver = {
561 .probe = msm_eud_probe,
562 .remove = msm_eud_remove,
563 .driver = {
564 .name = "msm-eud",
565 .owner = THIS_MODULE,
566 .of_match_table = msm_eud_dt_match,
567 },
568};
569
570static int __init msm_eud_init(void)
571{
572 int ret;
573
574 ret = uart_register_driver(&eud_uart_driver);
575 if (ret) {
576 pr_err("%s: Failed to register EUD UART driver\n",
577 __func__);
578 return ret;
579 }
580
581 ret = platform_driver_register(&msm_eud_driver);
582 if (ret) {
583 pr_err("%s: Failed to register EUD driver\n",
584 __func__);
585 uart_unregister_driver(&eud_uart_driver);
586 return ret;
587 }
588
589 return 0;
590}
591module_init(msm_eud_init);
592
593static void __exit msm_eud_exit(void)
594{
595 platform_driver_unregister(&msm_eud_driver);
596 uart_unregister_driver(&eud_uart_driver);
597}
598module_exit(msm_eud_exit);
599
600MODULE_DESCRIPTION("QTI EUD driver");
601MODULE_LICENSE("GPL v2");