[go: nahoru, domu]

1b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory/*
2b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * Palmas USB transceiver driver
3b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory *
4b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
5b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * This program is free software; you can redistribute it and/or modify
6b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * it under the terms of the GNU General Public License as published by
7b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * the Free Software Foundation; either version 2 of the License, or
8b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * (at your option) any later version.
9b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory *
10b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * Author: Graeme Gregory <gg@slimlogic.co.uk>
11b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * Author: Kishon Vijay Abraham I <kishon@ti.com>
12b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory *
13b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * Based on twl6030_usb.c
14b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory *
15b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * Author: Hema HK <hemahk@ti.com>
16b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory *
17b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * This program is distributed in the hope that it will be useful,
18b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * but WITHOUT ANY WARRANTY; without even the implied warranty of
19b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory * GNU General Public License for more details.
21b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory */
22b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
23b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory#include <linux/module.h>
24b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory#include <linux/interrupt.h>
25b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory#include <linux/platform_device.h>
26f63d32d4080407176082ef2cc439a3c81b15af16Kishon Vijay Abraham I#include <linux/slab.h>
27b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory#include <linux/err.h>
28b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory#include <linux/mfd/palmas.h>
29b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory#include <linux/of.h>
30b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory#include <linux/of_platform.h>
31b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
32b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic const char *palmas_extcon_cable[] = {
33b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	[0] = "USB",
34b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	[1] = "USB-HOST",
35b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	NULL,
36b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory};
37b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
38b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic const int mutually_exclusive[] = {0x3, 0x0};
39b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
40b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic void palmas_usb_wakeup(struct palmas *palmas, int enable)
41b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory{
42b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	if (enable)
43b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		palmas_write(palmas, PALMAS_USB_OTG_BASE, PALMAS_USB_WAKEUP,
44b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			PALMAS_USB_WAKEUP_ID_WK_UP_COMP);
45b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	else
46b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		palmas_write(palmas, PALMAS_USB_OTG_BASE, PALMAS_USB_WAKEUP, 0);
47b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory}
48b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
49b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
50b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory{
51b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	struct palmas_usb *palmas_usb = _palmas_usb;
52b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	unsigned int vbus_line_state;
53b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
54b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_read(palmas_usb->palmas, PALMAS_INTERRUPT_BASE,
55b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		PALMAS_INT3_LINE_STATE, &vbus_line_state);
56b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
57b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	if (vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS) {
58b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
59b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
603f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi			extcon_set_cable_state(palmas_usb->edev, "USB", true);
61002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan			dev_info(palmas_usb->dev, "USB cable is attached\n");
62b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		} else {
63b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			dev_dbg(palmas_usb->dev,
64b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory				"Spurious connect event detected\n");
65b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		}
66b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	} else if (!(vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS)) {
67b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
68b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
693f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi			extcon_set_cable_state(palmas_usb->edev, "USB", false);
70002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan			dev_info(palmas_usb->dev, "USB cable is detached\n");
71b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		} else {
72b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			dev_dbg(palmas_usb->dev,
73b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory				"Spurious disconnect event detected\n");
74b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		}
75b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	}
76b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
77b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	return IRQ_HANDLED;
78b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory}
79b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
80b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
81b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory{
82b7d2d5be3c910fddd19cafa0861016712c665168George Cherian	unsigned int set, id_src;
83b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	struct palmas_usb *palmas_usb = _palmas_usb;
84b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
85b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_read(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
86b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		PALMAS_USB_ID_INT_LATCH_SET, &set);
87b7d2d5be3c910fddd19cafa0861016712c665168George Cherian	palmas_read(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
88b7d2d5be3c910fddd19cafa0861016712c665168George Cherian		PALMAS_USB_ID_INT_SRC, &id_src);
89b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
90b7d2d5be3c910fddd19cafa0861016712c665168George Cherian	if ((set & PALMAS_USB_ID_INT_SRC_ID_GND) &&
91b7d2d5be3c910fddd19cafa0861016712c665168George Cherian				(id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) {
92b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
93b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			PALMAS_USB_ID_INT_LATCH_CLR,
94b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
95b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		palmas_usb->linkstat = PALMAS_USB_STATE_ID;
963f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi		extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true);
97002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan		dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
98b7d2d5be3c910fddd19cafa0861016712c665168George Cherian	} else if ((set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) &&
99b7d2d5be3c910fddd19cafa0861016712c665168George Cherian				(id_src & PALMAS_USB_ID_INT_SRC_ID_FLOAT)) {
100b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
101b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			PALMAS_USB_ID_INT_LATCH_CLR,
102b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory			PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
103b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
1043f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi		extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false);
105002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan		dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
106002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan	} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) &&
107002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan				(!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) {
108002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan		palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
1093f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi		extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false);
110002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan		dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
111b7d2d5be3c910fddd19cafa0861016712c665168George Cherian	} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_DISCONNECT) &&
112b7d2d5be3c910fddd19cafa0861016712c665168George Cherian				(id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) {
113b7d2d5be3c910fddd19cafa0861016712c665168George Cherian		palmas_usb->linkstat = PALMAS_USB_STATE_ID;
1143f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi		extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true);
115b7d2d5be3c910fddd19cafa0861016712c665168George Cherian		dev_info(palmas_usb->dev, " USB-HOST cable is attached\n");
116b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	}
117b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
118b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	return IRQ_HANDLED;
119b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory}
120b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
121b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic void palmas_enable_irq(struct palmas_usb *palmas_usb)
122b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory{
123b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
124b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		PALMAS_USB_VBUS_CTRL_SET,
125b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP);
126b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
127b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
128b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
129b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
130b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
131b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		PALMAS_USB_ID_INT_EN_HI_SET,
132002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan		PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
133002945f014ab51c470fdbd30b199fa85f715280dLaxman Dewangan		PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
134b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
1357281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	if (palmas_usb->enable_vbus_detection)
1367281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
137b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
138b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	/* cold plug for host mode needs this delay */
1397281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	if (palmas_usb->enable_id_detection) {
1407281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		msleep(30);
1417281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb);
1427281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	}
143b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory}
144b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
145b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic int palmas_usb_probe(struct platform_device *pdev)
146b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory{
147b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
1487c0f6558f893eb5eddb52ee0fa84c2d43b2c199aJingoo Han	struct palmas_usb_platform_data	*pdata = dev_get_platdata(&pdev->dev);
149b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	struct device_node *node = pdev->dev.of_node;
150b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	struct palmas_usb *palmas_usb;
151b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	int status;
152b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
153b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL);
154b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	if (!palmas_usb)
155b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		return -ENOMEM;
156b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
1577281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	if (node && !pdata) {
1587281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_usb->wakeup = of_property_read_bool(node, "ti,wakeup");
1597281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_usb->enable_id_detection = of_property_read_bool(node,
1607281e05aabee7484624d448da208932690ed62b3Laxman Dewangan						"ti,enable-id-detection");
1617281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_usb->enable_vbus_detection = of_property_read_bool(node,
1627281e05aabee7484624d448da208932690ed62b3Laxman Dewangan						"ti,enable-vbus-detection");
1637281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	} else {
1647281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_usb->wakeup = true;
1657281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_usb->enable_id_detection = true;
1667281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		palmas_usb->enable_vbus_detection = true;
1677281e05aabee7484624d448da208932690ed62b3Laxman Dewangan
1687281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		if (pdata)
1697281e05aabee7484624d448da208932690ed62b3Laxman Dewangan			palmas_usb->wakeup = pdata->wakeup;
1707281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	}
1717281e05aabee7484624d448da208932690ed62b3Laxman Dewangan
172b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas->usb = palmas_usb;
173b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_usb->palmas = palmas;
174b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
175b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_usb->dev	 = &pdev->dev;
176b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
177b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
178b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory						PALMAS_ID_OTG_IRQ);
179b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
180b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory						PALMAS_ID_IRQ);
181b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
182b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory						PALMAS_VBUS_OTG_IRQ);
183b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
184b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory						PALMAS_VBUS_IRQ);
185b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
1867281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	palmas_usb_wakeup(palmas, palmas_usb->wakeup);
187b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
188b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	platform_set_drvdata(pdev, palmas_usb);
189b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
1903f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi	palmas_usb->edev = devm_extcon_dev_allocate(&pdev->dev,
1913f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi						    palmas_extcon_cable);
1923f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi	if (IS_ERR(palmas_usb->edev)) {
1933f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi		dev_err(&pdev->dev, "failed to allocate extcon device\n");
1943f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi		return -ENOMEM;
1953f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi	}
1963f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi	palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL);
1973f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi	palmas_usb->edev->mutually_exclusive = mutually_exclusive;
198b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
1993f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi	status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
200b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	if (status) {
201b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		dev_err(&pdev->dev, "failed to register extcon device\n");
2023f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi		kfree(palmas_usb->edev->name);
203b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		return status;
204b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	}
205b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
2067281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	if (palmas_usb->enable_id_detection) {
2077281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		status = devm_request_threaded_irq(palmas_usb->dev,
2087281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				palmas_usb->id_irq,
2097281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				NULL, palmas_id_irq_handler,
2107281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
2117281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				IRQF_ONESHOT | IRQF_EARLY_RESUME,
2127281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				"palmas_usb_id", palmas_usb);
2137281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		if (status < 0) {
2147281e05aabee7484624d448da208932690ed62b3Laxman Dewangan			dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
215b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory					palmas_usb->id_irq, status);
2163f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi			kfree(palmas_usb->edev->name);
217b4dad55abd47a23ca2c445d771c64204f7b12b49Sangjung Woo			return status;
2187281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		}
219b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	}
220b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
2217281e05aabee7484624d448da208932690ed62b3Laxman Dewangan	if (palmas_usb->enable_vbus_detection) {
2227281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		status = devm_request_threaded_irq(palmas_usb->dev,
2237281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				palmas_usb->vbus_irq, NULL,
2247281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				palmas_vbus_irq_handler,
2257281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
2267281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				IRQF_ONESHOT | IRQF_EARLY_RESUME,
2277281e05aabee7484624d448da208932690ed62b3Laxman Dewangan				"palmas_usb_vbus", palmas_usb);
2287281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		if (status < 0) {
2297281e05aabee7484624d448da208932690ed62b3Laxman Dewangan			dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
230b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory					palmas_usb->vbus_irq, status);
2313f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi			kfree(palmas_usb->edev->name);
232b4dad55abd47a23ca2c445d771c64204f7b12b49Sangjung Woo			return status;
2337281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		}
234b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	}
235b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
236b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	palmas_enable_irq(palmas_usb);
237024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	device_set_wakeup_capable(&pdev->dev, true);
238b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	return 0;
239b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory}
240b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
241b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic int palmas_usb_remove(struct platform_device *pdev)
242b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory{
243b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	struct palmas_usb *palmas_usb = platform_get_drvdata(pdev);
244b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
2453f79a3fb5f41e8f2229e5bf8aa725eaa79686f14Chanwoo Choi	kfree(palmas_usb->edev->name);
246b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
247b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	return 0;
248b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory}
249b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
250024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan#ifdef CONFIG_PM_SLEEP
251024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewanganstatic int palmas_usb_suspend(struct device *dev)
252024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan{
253024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
254024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan
255024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	if (device_may_wakeup(dev)) {
2567281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		if (palmas_usb->enable_vbus_detection)
2577281e05aabee7484624d448da208932690ed62b3Laxman Dewangan			enable_irq_wake(palmas_usb->vbus_irq);
2587281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		if (palmas_usb->enable_id_detection)
2597281e05aabee7484624d448da208932690ed62b3Laxman Dewangan			enable_irq_wake(palmas_usb->id_irq);
260024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	}
261024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	return 0;
262024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan}
263024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan
264024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewanganstatic int palmas_usb_resume(struct device *dev)
265024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan{
266024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
267024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan
268024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	if (device_may_wakeup(dev)) {
2697281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		if (palmas_usb->enable_vbus_detection)
2707281e05aabee7484624d448da208932690ed62b3Laxman Dewangan			disable_irq_wake(palmas_usb->vbus_irq);
2717281e05aabee7484624d448da208932690ed62b3Laxman Dewangan		if (palmas_usb->enable_id_detection)
2727281e05aabee7484624d448da208932690ed62b3Laxman Dewangan			disable_irq_wake(palmas_usb->id_irq);
273024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	}
274024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan	return 0;
275024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan};
276024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan#endif
277024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan
2788d4288fb99076063a1a17ad92eb8b2ccef9eafd9Jingoo Hanstatic SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_usb_suspend, palmas_usb_resume);
279024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan
2803bc2ac7deffecc52932ee24357f6c33e5e9ce420Krzysztof Kozlowskistatic const struct of_device_id of_palmas_match_tbl[] = {
281b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	{ .compatible = "ti,palmas-usb", },
2825fbc77d6ebd0ab801273085bbf98fdaa66054ad8Kishon Vijay Abraham I	{ .compatible = "ti,palmas-usb-vid", },
283b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	{ .compatible = "ti,twl6035-usb", },
2845fbc77d6ebd0ab801273085bbf98fdaa66054ad8Kishon Vijay Abraham I	{ .compatible = "ti,twl6035-usb-vid", },
285b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	{ /* end */ }
286b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory};
287b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
288b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorystatic struct platform_driver palmas_usb_driver = {
289b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	.probe = palmas_usb_probe,
290b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	.remove = palmas_usb_remove,
291b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	.driver = {
292b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		.name = "palmas-usb",
293b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		.of_match_table = of_palmas_match_tbl,
294b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory		.owner = THIS_MODULE,
295024783ef422791d7ca58b106495f7c31802df6f3Laxman Dewangan		.pm = &palmas_pm_ops,
296b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory	},
297b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory};
298b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
299b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregorymodule_platform_driver(palmas_usb_driver);
300b1f254e35d85535b17af2786d06fe88f15f304f7Graeme Gregory
301b1f254e35d85535b17af2786d06fe88f15f304f7Graeme GregoryMODULE_ALIAS("platform:palmas-usb");
302b1f254e35d85535b17af2786d06fe88f15f304f7Graeme GregoryMODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
303b1f254e35d85535b17af2786d06fe88f15f304f7Graeme GregoryMODULE_DESCRIPTION("Palmas USB transceiver driver");
304b1f254e35d85535b17af2786d06fe88f15f304f7Graeme GregoryMODULE_LICENSE("GPL");
305b1f254e35d85535b17af2786d06fe88f15f304f7Graeme GregoryMODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
306