blob: f7f3317184bed4a000eb6d6e1aac424e70387d11 [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 Prabhala5a497782017-09-22 13:47:47 -070030#include <linux/clk.h>
31#include <linux/of.h>
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070032
33#define EUD_ENABLE_CMD 1
34#define EUD_DISABLE_CMD 0
35
36#define EUD_REG_COM_TX_ID 0x0000
37#define EUD_REG_COM_TX_LEN 0x0004
38#define EUD_REG_COM_TX_DAT 0x0008
39#define EUD_REG_COM_RX_ID 0x000C
40#define EUD_REG_COM_RX_LEN 0x0010
41#define EUD_REG_COM_RX_DAT 0x0014
42#define EUD_REG_INT1_EN_MASK 0x0024
43#define EUD_REG_INT_STATUS_1 0x0044
44#define EUD_REG_CTL_OUT_1 0x0074
45#define EUD_REG_VBUS_INT_CLR 0x0080
46#define EUD_REG_CHGR_INT_CLR 0x0084
47#define EUD_REG_CSR_EUD_EN 0x1014
48#define EUD_REG_SW_ATTACH_DET 0x1018
49
50#define EUD_INT_RX BIT(0)
51#define EUD_INT_TX BIT(1)
52#define EUD_INT_VBUS BIT(2)
53#define EUD_INT_CHGR BIT(3)
54#define EUD_INT_SAFE_MODE BIT(4)
55#define EUD_INT_ALL (EUD_INT_RX | EUD_INT_TX | \
56 EUD_INT_VBUS | EUD_INT_CHGR | \
57 EUD_INT_SAFE_MODE)
58
59#define EUD_NR 1
60#define EUD_CONSOLE NULL
61#define UART_ID 0x90
62#define MAX_FIFO_SIZE 14
63
64struct eud_chip {
65 struct device *dev;
66 int eud_irq;
Channagoud Kadabi75f54e82016-12-06 16:35:10 -080067 unsigned int extcon_id;
68 unsigned int int_status;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070069 bool usb_attach;
70 bool chgr_enable;
71 void __iomem *eud_reg_base;
72 struct extcon_dev *extcon;
73 struct uart_port port;
Channagoud Kadabi75f54e82016-12-06 16:35:10 -080074 struct work_struct eud_work;
Harry Yange2dd0e52017-08-03 14:50:32 -070075 struct power_supply *batt_psy;
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -070076 struct clk *cfg_ahb_clk;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070077};
78
79static const unsigned int eud_extcon_cable[] = {
80 EXTCON_USB,
81 EXTCON_CHG_USB_SDP,
82 EXTCON_NONE,
83};
84
85/*
86 * On the kernel command line specify eud.enable=1 to enable EUD.
87 * EUD is disabled by default.
88 */
89static int enable;
90static struct platform_device *eud_private;
91
92static void enable_eud(struct platform_device *pdev)
93{
94 struct eud_chip *priv = platform_get_drvdata(pdev);
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -070095 struct power_supply *usb_psy = NULL;
96 union power_supply_propval pval = {0};
97 union power_supply_propval tval = {0};
98 int ret;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -070099
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -0700100 usb_psy = power_supply_get_by_name("usb");
101 if (!usb_psy) {
102 dev_warn(&pdev->dev, "Could not get usb power_supply\n");
103 return;
104 }
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800105
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -0700106 ret = power_supply_get_property(usb_psy,
107 POWER_SUPPLY_PROP_PRESENT, &pval);
108 if (ret) {
109 dev_err(&pdev->dev, "Unable to read USB PRESENT: %x\n", ret);
110 return;
111 }
112
113 ret = power_supply_get_property(usb_psy,
114 POWER_SUPPLY_PROP_REAL_TYPE, &tval);
115 if (ret) {
116 dev_err(&pdev->dev, "Unable to read USB TYPE: %x\n", ret);
117 return;
118 }
119
120 if (pval.intval && (tval.intval == POWER_SUPPLY_TYPE_USB ||
121 tval.intval == POWER_SUPPLY_TYPE_USB_CDP)) {
122 /* write into CSR to enable EUD */
123 writel_relaxed(BIT(0), priv->eud_reg_base + EUD_REG_CSR_EUD_EN);
124 /* Enable vbus, chgr & safe mode warning interrupts */
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -0700125 writel_relaxed(EUD_INT_VBUS | EUD_INT_CHGR,
Channagoud Kadabi0c1fec12017-05-24 16:47:18 -0700126 priv->eud_reg_base + EUD_REG_INT1_EN_MASK);
127
128 /* Ensure Register Writes Complete */
129 wmb();
130
131 /*
132 * Set the default cable state to usb connect and charger
133 * enable
134 */
135 extcon_set_state_sync(priv->extcon, EXTCON_USB, true);
136 extcon_set_state_sync(priv->extcon, EXTCON_CHG_USB_SDP, true);
137 } else {
138 dev_warn(&pdev->dev, "Connect USB cable before enabling EUD\n");
139 return;
140 }
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800141
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700142 dev_dbg(&pdev->dev, "%s: EUD Enabled!\n", __func__);
143}
144
145static void disable_eud(struct platform_device *pdev)
146{
147 struct eud_chip *priv = platform_get_drvdata(pdev);
148
149 /* write into CSR to disable EUD */
150 writel_relaxed(0, priv->eud_reg_base + EUD_REG_CSR_EUD_EN);
151 dev_dbg(&pdev->dev, "%s: EUD Disabled!\n", __func__);
152}
153
154static int param_eud_set(const char *val, const struct kernel_param *kp)
155{
156 int enable = 0;
157
158 if (sscanf(val, "%du", &enable) != 1)
159 return -EINVAL;
160
161 if (enable != EUD_ENABLE_CMD && enable != EUD_DISABLE_CMD)
162 return -EINVAL;
163
164 if (enable == EUD_ENABLE_CMD) {
165 pr_debug("%s: Enbling EUD\n", __func__);
166 enable_eud(eud_private);
167 } else if (enable == EUD_DISABLE_CMD) {
168 pr_debug("%s: Disabling EUD\n", __func__);
169 disable_eud(eud_private);
170 }
171
172 *((uint *)kp->arg) = enable;
173 return 0;
174}
175
176static const struct kernel_param_ops eud_param_ops = {
177 .set = param_eud_set,
178 .get = param_get_int,
179};
180
181module_param_cb(enable, &eud_param_ops, &enable, 0644);
182
Harry Yange2dd0e52017-08-03 14:50:32 -0700183static bool is_batt_available(struct eud_chip *chip)
184{
185 if (!chip->batt_psy)
186 chip->batt_psy = power_supply_get_by_name("battery");
187
188 if (!chip->batt_psy)
189 return false;
190
191 return true;
192}
193
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800194static void eud_event_notifier(struct work_struct *eud_work)
195{
196 struct eud_chip *chip = container_of(eud_work, struct eud_chip,
197 eud_work);
Harry Yange2dd0e52017-08-03 14:50:32 -0700198 union power_supply_propval pval;
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800199
200 if (chip->int_status == EUD_INT_VBUS)
Jack Pham4e9dff72017-04-04 18:05:53 -0700201 extcon_set_state_sync(chip->extcon, chip->extcon_id,
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800202 chip->usb_attach);
Harry Yange2dd0e52017-08-03 14:50:32 -0700203 else if (chip->int_status == EUD_INT_CHGR) {
204 if (is_batt_available(chip)) {
205 pval.intval = !chip->chgr_enable;
206 power_supply_set_property(chip->batt_psy,
207 POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
208 }
209 }
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800210}
211
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700212static void usb_attach_detach(struct eud_chip *chip)
213{
214 u32 reg;
215
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800216 chip->extcon_id = EXTCON_USB;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700217 /* read ctl_out_1[4] to find USB attach or detach event */
218 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_CTL_OUT_1);
219 if (reg & BIT(4))
220 chip->usb_attach = true;
221 else
222 chip->usb_attach = false;
223
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800224 schedule_work(&chip->eud_work);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700225
226 /* set and clear vbus_int_clr[0] to clear interrupt */
227 writel_relaxed(BIT(0), chip->eud_reg_base + EUD_REG_VBUS_INT_CLR);
228 /* Ensure Register Writes Complete */
229 wmb();
230 writel_relaxed(0, chip->eud_reg_base + EUD_REG_VBUS_INT_CLR);
231}
232
233static void chgr_enable_disable(struct eud_chip *chip)
234{
235 u32 reg;
236
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800237 chip->extcon_id = EXTCON_CHG_USB_SDP;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700238 /* read ctl_out_1[6] to find charger enable or disable event */
239 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_CTL_OUT_1);
240 if (reg & BIT(6))
241 chip->chgr_enable = true;
242 else
243 chip->chgr_enable = false;
244
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800245 schedule_work(&chip->eud_work);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700246
247 /* set and clear chgr_int_clr[0] to clear interrupt */
248 writel_relaxed(BIT(0), chip->eud_reg_base + EUD_REG_CHGR_INT_CLR);
249 /* Ensure Register Writes Complete */
250 wmb();
251 writel_relaxed(0, chip->eud_reg_base + EUD_REG_CHGR_INT_CLR);
252}
253
254static void pet_eud(struct eud_chip *chip)
255{
256 u32 reg;
257
258 /* read sw_attach_det[0] to find attach/detach event */
259 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_SW_ATTACH_DET);
260 if (reg & BIT(0)) {
261 /* Detach & Attach pet for EUD */
262 writel_relaxed(0, chip->eud_reg_base + EUD_REG_SW_ATTACH_DET);
263 /* Ensure Register Writes Complete */
264 wmb();
265 /* Delay to make sure detach pet is done before attach pet */
266 udelay(100);
267 writel_relaxed(BIT(0), chip->eud_reg_base +
268 EUD_REG_SW_ATTACH_DET);
269 /* Ensure Register Writes Complete */
270 wmb();
271 } else {
272 /* Attach pet for EUD */
273 writel_relaxed(BIT(0), chip->eud_reg_base +
274 EUD_REG_SW_ATTACH_DET);
275 /* Ensure Register Writes Complete */
276 wmb();
277 }
278}
279
280static unsigned int eud_tx_empty(struct uart_port *port)
281{
282 u32 reg;
283
284 /* read status register and cross check for Tx interrupt */
285 reg = readl_relaxed(port->membase + EUD_REG_INT_STATUS_1);
286 if (reg & EUD_INT_TX)
287 return TIOCSER_TEMT;
288 else
289 return 0;
290}
291
292static void eud_stop_tx(struct uart_port *port)
293{
294 /* Disable Tx interrupt */
295 writel_relaxed(~EUD_INT_TX, port->membase + EUD_REG_INT_STATUS_1);
296 /* Ensure Register Writes Complete */
297 wmb();
298}
299
300static void eud_start_tx(struct uart_port *port)
301{
302 /* Enable Tx interrupt */
303 writel_relaxed(EUD_INT_TX, port->membase + EUD_REG_INT_STATUS_1);
304 /* Ensure Register Writes Complete */
305 wmb();
306}
307
308static void eud_stop_rx(struct uart_port *port)
309{
310 /* Disable Rx interrupt */
311 writel_relaxed(~EUD_INT_RX, port->membase + EUD_REG_INT_STATUS_1);
312 /* Ensure Register Writes Complete */
313 wmb();
314}
315
316static int eud_startup(struct uart_port *port)
317{
318 /* Enable Rx interrupt */
319 writel_relaxed(EUD_INT_RX, port->membase + EUD_REG_INT_STATUS_1);
320 /* Ensure Register Writes Complete */
321 wmb();
322 return 0;
323}
324
325static void eud_shutdown(struct uart_port *port)
326{
327 /* Disable both Tx & Rx interrupts */
328 writel_relaxed(~EUD_INT_TX | ~EUD_INT_RX,
329 port->membase + EUD_REG_INT_STATUS_1);
330 /* Ensure Register Writes Complete */
331 wmb();
332}
333
334static const char *eud_type(struct uart_port *port)
335{
336 return (port->type == PORT_EUD_UART) ? "EUD UART" : NULL;
337}
338
339static int eud_request_port(struct uart_port *port)
340{
341 /* Nothing to request */
342 return 0;
343}
344
345static void eud_release_port(struct uart_port *port)
346{
347 /* Nothing to release */
348}
349
350static void eud_config_port(struct uart_port *port, int flags)
351{
352 /* set port type, clear Tx and Rx interrupts */
353 port->type = PORT_EUD_UART;
354 writel_relaxed(~EUD_INT_TX | ~EUD_INT_RX,
355 port->membase + EUD_REG_INT_STATUS_1);
356 /* Ensure Register Writes Complete */
357 wmb();
358}
359
360static int eud_verify_port(struct uart_port *port,
361 struct serial_struct *ser)
362{
363 if (ser->type != PORT_UNKNOWN && ser->type != PORT_EUD_UART)
364 return -EINVAL;
365 return 0;
366}
367
368/* serial functions supported */
369static const struct uart_ops eud_uart_ops = {
370 .tx_empty = eud_tx_empty,
371 .stop_tx = eud_stop_tx,
372 .start_tx = eud_start_tx,
373 .stop_rx = eud_stop_rx,
374 .startup = eud_startup,
375 .shutdown = eud_shutdown,
376 .type = eud_type,
377 .release_port = eud_release_port,
378 .request_port = eud_request_port,
379 .config_port = eud_config_port,
380 .verify_port = eud_verify_port,
381};
382
383static struct uart_driver eud_uart_driver = {
384 .owner = THIS_MODULE,
385 .driver_name = "msm-eud",
386 .dev_name = "ttyEUD",
387 .nr = EUD_NR,
388 .cons = EUD_CONSOLE,
389};
390
391static void eud_uart_rx(struct eud_chip *chip)
392{
393 struct uart_port *port = &chip->port;
394 u32 reg;
395 unsigned int len;
396 unsigned char ch, flag;
397 int i;
398
399 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_RX_ID);
400 if (reg != UART_ID) {
401 dev_err(chip->dev, "Rx isn't for us!\n");
402 return;
403 }
404 /* Read Rx Len & Data registers */
405 spin_lock(&port->lock);
406 len = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_RX_LEN);
407 for (i = 0; i < len; i++) {
408 ch = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_RX_DAT);
409 flag = TTY_NORMAL;
410 port->icount.rx++;
411
412 if (uart_handle_sysrq_char(port, ch))
413 continue;
414 uart_insert_char(port, 0, 0, ch, flag);
415 }
416
417 spin_unlock(&port->lock);
418 tty_flip_buffer_push(&port->state->port);
419}
420
421static void eud_uart_tx(struct eud_chip *chip)
422{
423 struct uart_port *port = &chip->port;
424 struct circ_buf *xmit = &port->state->xmit;
425 unsigned int len;
426 u32 reg;
427
428 writel_relaxed(UART_ID, chip->eud_reg_base + EUD_REG_COM_TX_ID);
429 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_COM_TX_ID);
430 if (reg != UART_ID) {
431 dev_err(chip->dev, "Tx isn't for us!\n");
432 return;
433 }
434 /* Write to Tx Len & Data registers */
435 spin_lock(&port->lock);
436 len = uart_circ_chars_pending(xmit);
437 if (len > 0) {
438 if (len > port->fifosize)
439 len = port->fifosize;
440 while (len--) {
441 writel_relaxed(xmit->buf[xmit->tail],
442 port->membase + EUD_REG_COM_TX_DAT);
443 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
444 port->icount.tx++;
445 }
446 }
447 spin_unlock(&port->lock);
448}
449
450static irqreturn_t handle_eud_irq(int irq, void *data)
451{
452 struct eud_chip *chip = data;
453 u32 reg;
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -0700454 u32 int_mask_en1;
455
456 clk_prepare_enable(chip->cfg_ahb_clk);
457
458 int_mask_en1 = readl_relaxed(chip->eud_reg_base +
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800459 EUD_REG_INT1_EN_MASK);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700460
461 /* read status register and find out which interrupt triggered */
462 reg = readl_relaxed(chip->eud_reg_base + EUD_REG_INT_STATUS_1);
463 if (reg & EUD_INT_RX) {
464 dev_dbg(chip->dev, "EUD RX Interrupt!\n");
465 eud_uart_rx(chip);
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800466 } else if ((reg & EUD_INT_TX) & int_mask_en1) {
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700467 dev_dbg(chip->dev, "EUD TX Interrupt!\n");
468 eud_uart_tx(chip);
469 } else if (reg & EUD_INT_VBUS) {
470 dev_dbg(chip->dev, "EUD VBUS Interrupt!\n");
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800471 chip->int_status = EUD_INT_VBUS;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700472 usb_attach_detach(chip);
473 } else if (reg & EUD_INT_CHGR) {
474 dev_dbg(chip->dev, "EUD CHGR Interrupt!\n");
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800475 chip->int_status = EUD_INT_CHGR;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700476 chgr_enable_disable(chip);
477 } else if (reg & EUD_INT_SAFE_MODE) {
478 dev_dbg(chip->dev, "EUD SAFE MODE Interrupt!\n");
479 pet_eud(chip);
480 } else {
481 dev_dbg(chip->dev, "Unknown/spurious EUD Interrupt!\n");
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -0700482 clk_disable_unprepare(chip->cfg_ahb_clk);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700483 return IRQ_NONE;
484 }
485
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -0700486 clk_disable_unprepare(chip->cfg_ahb_clk);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700487 return IRQ_HANDLED;
488}
489
490static int msm_eud_probe(struct platform_device *pdev)
491{
492 struct eud_chip *chip;
493 struct uart_port *port;
494 struct resource *res;
495 int ret;
496
497 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
498 if (!chip) {
499 ret = -ENOMEM;
500 return ret;
501 }
502
503 platform_set_drvdata(pdev, chip);
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -0700504 chip->dev = &pdev->dev;
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700505
506 chip->extcon = devm_extcon_dev_allocate(&pdev->dev, eud_extcon_cable);
507 if (IS_ERR(chip->extcon)) {
508 dev_err(chip->dev, "failed to allocate extcon device\n");
509 return PTR_ERR(chip->extcon);
510 }
511
512 ret = devm_extcon_dev_register(&pdev->dev, chip->extcon);
513 if (ret) {
514 dev_err(chip->dev, "failed to register extcon device\n");
515 return ret;
516 }
517
518 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eud_base");
519 if (!res) {
520 dev_err(chip->dev, "%s: failed to get resource eud_base\n",
521 __func__);
522 ret = -ENOMEM;
523 return ret;
524 }
525
526 chip->eud_reg_base = devm_ioremap_resource(&pdev->dev, res);
527 if (IS_ERR(chip->eud_reg_base))
528 return PTR_ERR(chip->eud_reg_base);
529
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -0700530 if (of_property_match_string(pdev->dev.of_node,
531 "clock-names", "cfg_ahb_clk") >= 0) {
532 chip->cfg_ahb_clk = devm_clk_get(&pdev->dev, "cfg_ahb_clk");
533 if (IS_ERR(chip->cfg_ahb_clk)) {
534 ret = PTR_ERR(chip->cfg_ahb_clk);
535 if (ret != -EPROBE_DEFER)
536 dev_err(chip->dev,
537 "clk get failed for cfg_ahb_clk ret %d\n",
538 ret);
539 return ret;
540 }
541 }
542
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700543 chip->eud_irq = platform_get_irq_byname(pdev, "eud_irq");
544
Satya Durga Srinivasu Prabhala5a497782017-09-22 13:47:47 -0700545 ret = devm_request_threaded_irq(&pdev->dev, chip->eud_irq,
546 NULL, handle_eud_irq,
547 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
548 "eud_irq", chip);
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700549 if (ret) {
550 dev_err(chip->dev, "request failed for eud irq\n");
551 return ret;
552 }
553
554 device_init_wakeup(&pdev->dev, true);
555 enable_irq_wake(chip->eud_irq);
556
Channagoud Kadabi75f54e82016-12-06 16:35:10 -0800557 INIT_WORK(&chip->eud_work, eud_event_notifier);
558
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700559 port = &chip->port;
560 port->line = pdev->id;
561 port->type = PORT_EUD_UART;
562 port->dev = chip->dev;
563 port->fifosize = MAX_FIFO_SIZE;
564 port->iotype = SERIAL_IO_MEM;
565 port->flags = UPF_BOOT_AUTOCONF;
566 port->membase = chip->eud_reg_base;
567 port->irq = chip->eud_irq;
568 port->ops = &eud_uart_ops;
569
570 ret = uart_add_one_port(&eud_uart_driver, port);
571 if (!ret) {
572 dev_err(chip->dev, "failed to add uart port!\n");
573 return ret;
574 }
575
Satya Durga Srinivasu Prabhala60909002016-09-12 11:36:09 -0700576 eud_private = pdev;
577
578 /* Enable EUD */
579 if (enable)
580 enable_eud(pdev);
581
582 return 0;
583}
584
585static int msm_eud_remove(struct platform_device *pdev)
586{
587 struct eud_chip *chip = platform_get_drvdata(pdev);
588 struct uart_port *port = &chip->port;
589
590 uart_remove_one_port(&eud_uart_driver, port);
591 device_init_wakeup(chip->dev, false);
592
593 return 0;
594}
595
596static const struct of_device_id msm_eud_dt_match[] = {
597 {.compatible = "qcom,msm-eud"},
598 {},
599};
600MODULE_DEVICE_TABLE(of, msm_eud_dt_match);
601
602static struct platform_driver msm_eud_driver = {
603 .probe = msm_eud_probe,
604 .remove = msm_eud_remove,
605 .driver = {
606 .name = "msm-eud",
607 .owner = THIS_MODULE,
608 .of_match_table = msm_eud_dt_match,
609 },
610};
611
612static int __init msm_eud_init(void)
613{
614 int ret;
615
616 ret = uart_register_driver(&eud_uart_driver);
617 if (ret) {
618 pr_err("%s: Failed to register EUD UART driver\n",
619 __func__);
620 return ret;
621 }
622
623 ret = platform_driver_register(&msm_eud_driver);
624 if (ret) {
625 pr_err("%s: Failed to register EUD driver\n",
626 __func__);
627 uart_unregister_driver(&eud_uart_driver);
628 return ret;
629 }
630
631 return 0;
632}
633module_init(msm_eud_init);
634
635static void __exit msm_eud_exit(void)
636{
637 platform_driver_unregister(&msm_eud_driver);
638 uart_unregister_driver(&eud_uart_driver);
639}
640module_exit(msm_eud_exit);
641
642MODULE_DESCRIPTION("QTI EUD driver");
643MODULE_LICENSE("GPL v2");