Blame view

drivers/usb/phy/phy-twl6030-usb.c 11.8 KB
c33fad0c3   Hema HK   usb: otg: Adding ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /*
   * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
   *
   * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * Author: Hema HK <hemahk@ti.com>
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/platform_device.h>
  #include <linux/io.h>
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
28
  #include <linux/usb/musb-omap.h>
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
29
  #include <linux/usb/phy_companion.h>
6284be23d   Kishon Vijay Abraham I   phy: omap-usb2: m...
30
  #include <linux/phy/omap_usb.h>
c33fad0c3   Hema HK   usb: otg: Adding ...
31
32
33
  #include <linux/i2c/twl.h>
  #include <linux/regulator/consumer.h>
  #include <linux/err.h>
c33fad0c3   Hema HK   usb: otg: Adding ...
34
  #include <linux/slab.h>
603ab524e   Hema HK   usb: otg: TWL6030...
35
  #include <linux/delay.h>
80d7d8a76   Sachin Kamat   usb: phy: twl6030...
36
  #include <linux/of.h>
c33fad0c3   Hema HK   usb: otg: Adding ...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  
  /* usb register definitions */
  #define USB_VENDOR_ID_LSB		0x00
  #define USB_VENDOR_ID_MSB		0x01
  #define USB_PRODUCT_ID_LSB		0x02
  #define USB_PRODUCT_ID_MSB		0x03
  #define USB_VBUS_CTRL_SET		0x04
  #define USB_VBUS_CTRL_CLR		0x05
  #define USB_ID_CTRL_SET			0x06
  #define USB_ID_CTRL_CLR			0x07
  #define USB_VBUS_INT_SRC		0x08
  #define USB_VBUS_INT_LATCH_SET		0x09
  #define USB_VBUS_INT_LATCH_CLR		0x0A
  #define USB_VBUS_INT_EN_LO_SET		0x0B
  #define USB_VBUS_INT_EN_LO_CLR		0x0C
  #define USB_VBUS_INT_EN_HI_SET		0x0D
  #define USB_VBUS_INT_EN_HI_CLR		0x0E
  #define USB_ID_INT_SRC			0x0F
  #define USB_ID_INT_LATCH_SET		0x10
  #define USB_ID_INT_LATCH_CLR		0x11
  
  #define USB_ID_INT_EN_LO_SET		0x12
  #define USB_ID_INT_EN_LO_CLR		0x13
  #define USB_ID_INT_EN_HI_SET		0x14
  #define USB_ID_INT_EN_HI_CLR		0x15
  #define USB_OTG_ADP_CTRL		0x16
  #define USB_OTG_ADP_HIGH		0x17
  #define USB_OTG_ADP_LOW			0x18
  #define USB_OTG_ADP_RISE		0x19
  #define USB_OTG_REVISION		0x1A
  
  /* to be moved to LDO */
  #define TWL6030_MISC2			0xE5
  #define TWL6030_CFG_LDO_PD2		0xF5
  #define TWL6030_BACKUP_REG		0xFA
  
  #define STS_HW_CONDITIONS		0x21
  
  /* In module TWL6030_MODULE_PM_MASTER */
  #define STS_HW_CONDITIONS		0x21
  #define STS_USB_ID			BIT(2)
  
  /* In module TWL6030_MODULE_PM_RECEIVER */
  #define VUSB_CFG_TRANS			0x71
  #define VUSB_CFG_STATE			0x72
  #define VUSB_CFG_VOLTAGE		0x73
  
  /* in module TWL6030_MODULE_MAIN_CHARGE */
  
  #define CHARGERUSB_CTRL1		0x8
  
  #define CONTROLLER_STAT1		0x03
  #define	VBUS_DET			BIT(2)
  
  struct twl6030_usb {
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
92
  	struct phy_companion	comparator;
c33fad0c3   Hema HK   usb: otg: Adding ...
93
94
95
96
97
98
  	struct device		*dev;
  
  	/* for vbus reporting with irqs disabled */
  	spinlock_t		lock;
  
  	struct regulator		*usb3v3;
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
99
100
  	/* used to set vbus, in atomic path */
  	struct work_struct	set_vbus_work;
c33fad0c3   Hema HK   usb: otg: Adding ...
101
102
  	int			irq1;
  	int			irq2;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
103
  	enum omap_musb_vbus_id_status linkstat;
c33fad0c3   Hema HK   usb: otg: Adding ...
104
  	u8			asleep;
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
105
  	bool			vbus_enable;
ff0a1f394   Kishon Vijay Abraham I   usb: twl6030: Add...
106
  	const char		*regulator;
c33fad0c3   Hema HK   usb: otg: Adding ...
107
  };
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
108
  #define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
c33fad0c3   Hema HK   usb: otg: Adding ...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  
  /*-------------------------------------------------------------------------*/
  
  static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
  						u8 data, u8 address)
  {
  	int ret = 0;
  
  	ret = twl_i2c_write_u8(module, data, address);
  	if (ret < 0)
  		dev_err(twl->dev,
  			"Write[0x%x] Error %d
  ", address, ret);
  	return ret;
  }
  
  static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
  {
0b5514903   Dan Carpenter   usb: phy: twl6030...
127
128
  	u8 data;
  	int ret;
c33fad0c3   Hema HK   usb: otg: Adding ...
129
130
131
132
133
134
135
136
137
138
139
  
  	ret = twl_i2c_read_u8(module, &data, address);
  	if (ret >= 0)
  		ret = data;
  	else
  		dev_err(twl->dev,
  			"readb[0x%x,0x%x] Error %d
  ",
  					module, address, ret);
  	return ret;
  }
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
140
  static int twl6030_start_srp(struct phy_companion *comparator)
c33fad0c3   Hema HK   usb: otg: Adding ...
141
  {
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
142
  	struct twl6030_usb *twl = comparator_to_twl(comparator);
603ab524e   Hema HK   usb: otg: TWL6030...
143
144
145
146
147
148
149
150
151
  
  	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
  	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
  
  	mdelay(100);
  	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);
  
  	return 0;
  }
c33fad0c3   Hema HK   usb: otg: Adding ...
152
153
  static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
  {
c33fad0c3   Hema HK   usb: otg: Adding ...
154
155
156
157
158
159
160
161
  	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
  	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
  
  	/* Program CFG_LDO_PD2 register and set VUSB bit */
  	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
  
  	/* Program MISC2 register and set bit VUSB_IN_VBAT */
  	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
ff0a1f394   Kishon Vijay Abraham I   usb: twl6030: Add...
162
  	twl->usb3v3 = regulator_get(twl->dev, twl->regulator);
c33fad0c3   Hema HK   usb: otg: Adding ...
163
164
  	if (IS_ERR(twl->usb3v3))
  		return -ENODEV;
c33fad0c3   Hema HK   usb: otg: Adding ...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
  	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
  
  	/*
  	 * Program the USB_ID_CTRL_SET register to enable GND drive
  	 * and the ID comparators
  	 */
  	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
  
  	return 0;
  }
  
  static ssize_t twl6030_usb_vbus_show(struct device *dev,
  			struct device_attribute *attr, char *buf)
  {
  	struct twl6030_usb *twl = dev_get_drvdata(dev);
  	unsigned long flags;
  	int ret = -EINVAL;
  
  	spin_lock_irqsave(&twl->lock, flags);
  
  	switch (twl->linkstat) {
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
187
  	case OMAP_MUSB_VBUS_VALID:
c33fad0c3   Hema HK   usb: otg: Adding ...
188
189
190
  	       ret = snprintf(buf, PAGE_SIZE, "vbus
  ");
  	       break;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
191
  	case OMAP_MUSB_ID_GROUND:
c33fad0c3   Hema HK   usb: otg: Adding ...
192
193
194
  	       ret = snprintf(buf, PAGE_SIZE, "id
  ");
  	       break;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
195
  	case OMAP_MUSB_VBUS_OFF:
c33fad0c3   Hema HK   usb: otg: Adding ...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  	       ret = snprintf(buf, PAGE_SIZE, "none
  ");
  	       break;
  	default:
  	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN
  ");
  	}
  	spin_unlock_irqrestore(&twl->lock, flags);
  
  	return ret;
  }
  static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
  
  static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
  {
  	struct twl6030_usb *twl = _twl;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
212
  	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
c33fad0c3   Hema HK   usb: otg: Adding ...
213
  	u8 vbus_state, hw_state;
bb54542cf   Fabio Baltieri   usb: phy: twl6030...
214
  	int ret;
c33fad0c3   Hema HK   usb: otg: Adding ...
215
216
217
218
219
220
221
  
  	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
  
  	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
  						CONTROLLER_STAT1);
  	if (!(hw_state & STS_USB_ID)) {
  		if (vbus_state & VBUS_DET) {
bb54542cf   Fabio Baltieri   usb: phy: twl6030...
222
223
224
225
  			ret = regulator_enable(twl->usb3v3);
  			if (ret)
  				dev_err(twl->dev, "Failed to enable usb3v3
  ");
6dc2503b8   Hema HK   usb: otg: enable ...
226
  			twl->asleep = 1;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
227
  			status = OMAP_MUSB_VBUS_VALID;
6dc2503b8   Hema HK   usb: otg: enable ...
228
  			twl->linkstat = status;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
229
  			omap_musb_mailbox(status);
c33fad0c3   Hema HK   usb: otg: Adding ...
230
  		} else {
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
231
232
233
234
235
236
237
238
  			if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
  				status = OMAP_MUSB_VBUS_OFF;
  				twl->linkstat = status;
  				omap_musb_mailbox(status);
  				if (twl->asleep) {
  					regulator_disable(twl->usb3v3);
  					twl->asleep = 0;
  				}
6dc2503b8   Hema HK   usb: otg: enable ...
239
  			}
c33fad0c3   Hema HK   usb: otg: Adding ...
240
241
242
243
244
245
246
247
248
249
  		}
  	}
  	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
  
  	return IRQ_HANDLED;
  }
  
  static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
  {
  	struct twl6030_usb *twl = _twl;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
250
  	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
c33fad0c3   Hema HK   usb: otg: Adding ...
251
  	u8 hw_state;
bb54542cf   Fabio Baltieri   usb: phy: twl6030...
252
  	int ret;
c33fad0c3   Hema HK   usb: otg: Adding ...
253
254
255
256
  
  	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
  
  	if (hw_state & STS_USB_ID) {
bb54542cf   Fabio Baltieri   usb: phy: twl6030...
257
258
259
260
  		ret = regulator_enable(twl->usb3v3);
  		if (ret)
  			dev_err(twl->dev, "Failed to enable usb3v3
  ");
c33fad0c3   Hema HK   usb: otg: Adding ...
261

6dc2503b8   Hema HK   usb: otg: enable ...
262
  		twl->asleep = 1;
dc8738d95   Moiz Sonasath   usb: otg: twl6030...
263
264
  		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
  		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
265
  		status = OMAP_MUSB_ID_GROUND;
31e9992ab   Hema HK   usb: otg: Remove ...
266
  		twl->linkstat = status;
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
267
  		omap_musb_mailbox(status);
c33fad0c3   Hema HK   usb: otg: Adding ...
268
  	} else  {
dc8738d95   Moiz Sonasath   usb: otg: twl6030...
269
270
  		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
  		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
c33fad0c3   Hema HK   usb: otg: Adding ...
271
  	}
dc8738d95   Moiz Sonasath   usb: otg: twl6030...
272
  	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
c33fad0c3   Hema HK   usb: otg: Adding ...
273
274
275
  
  	return IRQ_HANDLED;
  }
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
276
  static int twl6030_enable_irq(struct twl6030_usb *twl)
c33fad0c3   Hema HK   usb: otg: Adding ...
277
  {
dc8738d95   Moiz Sonasath   usb: otg: twl6030...
278
  	twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
c33fad0c3   Hema HK   usb: otg: Adding ...
279
280
281
282
283
284
285
286
287
288
289
290
  	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
  	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
  
  	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
  				REG_INT_MSK_LINE_C);
  	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
  				REG_INT_MSK_STS_C);
  	twl6030_usb_irq(twl->irq2, twl);
  	twl6030_usbotg_irq(twl->irq1, twl);
  
  	return 0;
  }
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
291
  static void otg_set_vbus_work(struct work_struct *data)
c33fad0c3   Hema HK   usb: otg: Adding ...
292
  {
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
293
294
  	struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
  								set_vbus_work);
c33fad0c3   Hema HK   usb: otg: Adding ...
295
296
297
298
299
  
  	/*
  	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
  	 * register. This enables boost mode.
  	 */
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
300
301
  
  	if (twl->vbus_enable)
c33fad0c3   Hema HK   usb: otg: Adding ...
302
  		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
303
304
  							CHARGERUSB_CTRL1);
  	else
c33fad0c3   Hema HK   usb: otg: Adding ...
305
  		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
306
307
  							CHARGERUSB_CTRL1);
  }
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
308
  static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
309
  {
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
310
  	struct twl6030_usb *twl = comparator_to_twl(comparator);
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
311
312
313
  
  	twl->vbus_enable = enabled;
  	schedule_work(&twl->set_vbus_work);
c33fad0c3   Hema HK   usb: otg: Adding ...
314
315
  	return 0;
  }
41ac7b3ab   Bill Pemberton   usb: remove use o...
316
  static int twl6030_usb_probe(struct platform_device *pdev)
c33fad0c3   Hema HK   usb: otg: Adding ...
317
  {
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
318
  	u32 ret;
c33fad0c3   Hema HK   usb: otg: Adding ...
319
320
  	struct twl6030_usb	*twl;
  	int			status, err;
ff0a1f394   Kishon Vijay Abraham I   usb: twl6030: Add...
321
322
  	struct device_node	*np = pdev->dev.of_node;
  	struct device		*dev = &pdev->dev;
19f9e188d   Jingoo Han   usb: phy: use dev...
323
  	struct twl4030_usb_data	*pdata = dev_get_platdata(dev);
c33fad0c3   Hema HK   usb: otg: Adding ...
324

2ee8ff308   Sachin Kamat   usb: phy-twl6030:...
325
  	twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL);
c33fad0c3   Hema HK   usb: otg: Adding ...
326
327
328
329
330
331
  	if (!twl)
  		return -ENOMEM;
  
  	twl->dev		= &pdev->dev;
  	twl->irq1		= platform_get_irq(pdev, 0);
  	twl->irq2		= platform_get_irq(pdev, 1);
c9721438c   Kishon Vijay Abraham I   usb: musb: twl: u...
332
  	twl->linkstat		= OMAP_MUSB_UNKNOWN;
46b8f6b0e   Heikki Krogerus   usb: otg: twl6030...
333

0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
334
335
  	twl->comparator.set_vbus	= twl6030_set_vbus;
  	twl->comparator.start_srp	= twl6030_start_srp;
46b8f6b0e   Heikki Krogerus   usb: otg: twl6030...
336

0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
337
338
339
340
341
  	ret = omap_usb2_set_comparator(&twl->comparator);
  	if (ret == -ENODEV) {
  		dev_info(&pdev->dev, "phy not ready, deferring probe");
  		return -EPROBE_DEFER;
  	}
c33fad0c3   Hema HK   usb: otg: Adding ...
342

ff0a1f394   Kishon Vijay Abraham I   usb: twl6030: Add...
343
344
345
  	if (np) {
  		twl->regulator = "usb";
  	} else if (pdata) {
89ce43fbb   Graeme Gregory   mfd: twl-core: Ch...
346
  		if (pdata->features & TWL6032_SUBCLASS)
ff0a1f394   Kishon Vijay Abraham I   usb: twl6030: Add...
347
348
349
350
351
352
353
354
  			twl->regulator = "ldousb";
  		else
  			twl->regulator = "vusb";
  	} else {
  		dev_err(&pdev->dev, "twl6030 initialized without pdata
  ");
  		return -EINVAL;
  	}
c33fad0c3   Hema HK   usb: otg: Adding ...
355
356
357
358
359
360
361
  	/* init spinlock for workqueue */
  	spin_lock_init(&twl->lock);
  
  	err = twl6030_usb_ldo_init(twl);
  	if (err) {
  		dev_err(&pdev->dev, "ldo init failed
  ");
c33fad0c3   Hema HK   usb: otg: Adding ...
362
363
  		return err;
  	}
c33fad0c3   Hema HK   usb: otg: Adding ...
364
365
366
367
368
  
  	platform_set_drvdata(pdev, twl);
  	if (device_create_file(&pdev->dev, &dev_attr_vbus))
  		dev_warn(&pdev->dev, "could not create sysfs file
  ");
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
369
  	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
c33fad0c3   Hema HK   usb: otg: Adding ...
370
  	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
8f9d973a0   Ming Lei   USB: twl6030-usb:...
371
  			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
c33fad0c3   Hema HK   usb: otg: Adding ...
372
373
374
375
376
377
  			"twl6030_usb", twl);
  	if (status < 0) {
  		dev_err(&pdev->dev, "can't get IRQ %d, err %d
  ",
  			twl->irq1, status);
  		device_remove_file(twl->dev, &dev_attr_vbus);
c33fad0c3   Hema HK   usb: otg: Adding ...
378
379
380
381
  		return status;
  	}
  
  	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
8f9d973a0   Ming Lei   USB: twl6030-usb:...
382
  			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
c33fad0c3   Hema HK   usb: otg: Adding ...
383
384
385
386
387
388
389
  			"twl6030_usb", twl);
  	if (status < 0) {
  		dev_err(&pdev->dev, "can't get IRQ %d, err %d
  ",
  			twl->irq2, status);
  		free_irq(twl->irq1, twl);
  		device_remove_file(twl->dev, &dev_attr_vbus);
c33fad0c3   Hema HK   usb: otg: Adding ...
390
391
  		return status;
  	}
6dc2503b8   Hema HK   usb: otg: enable ...
392
  	twl->asleep = 0;
0e98de67b   Kishon Vijay Abraham I   usb: otg: make tw...
393
  	twl6030_enable_irq(twl);
c33fad0c3   Hema HK   usb: otg: Adding ...
394
395
396
397
398
  	dev_info(&pdev->dev, "Initialized TWL6030 USB module
  ");
  
  	return 0;
  }
39d35681d   Dmitry Torokhov   USB: remove incor...
399
  static int twl6030_usb_remove(struct platform_device *pdev)
c33fad0c3   Hema HK   usb: otg: Adding ...
400
401
  {
  	struct twl6030_usb *twl = platform_get_drvdata(pdev);
c33fad0c3   Hema HK   usb: otg: Adding ...
402
403
404
405
406
407
408
  	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
  		REG_INT_MSK_LINE_C);
  	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
  			REG_INT_MSK_STS_C);
  	free_irq(twl->irq1, twl);
  	free_irq(twl->irq2, twl);
  	regulator_put(twl->usb3v3);
c33fad0c3   Hema HK   usb: otg: Adding ...
409
  	device_remove_file(twl->dev, &dev_attr_vbus);
5bf54506b   Moiz Sonasath   USB: OTG: Use wor...
410
  	cancel_work_sync(&twl->set_vbus_work);
c33fad0c3   Hema HK   usb: otg: Adding ...
411
412
413
  
  	return 0;
  }
ff0a1f394   Kishon Vijay Abraham I   usb: twl6030: Add...
414
415
416
417
418
419
420
  #ifdef CONFIG_OF
  static const struct of_device_id twl6030_usb_id_table[] = {
  	{ .compatible = "ti,twl6030-usb" },
  	{}
  };
  MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
  #endif
c33fad0c3   Hema HK   usb: otg: Adding ...
421
422
  static struct platform_driver twl6030_usb_driver = {
  	.probe		= twl6030_usb_probe,
39d35681d   Dmitry Torokhov   USB: remove incor...
423
  	.remove		= twl6030_usb_remove,
c33fad0c3   Hema HK   usb: otg: Adding ...
424
425
426
  	.driver		= {
  		.name	= "twl6030_usb",
  		.owner	= THIS_MODULE,
ff0a1f394   Kishon Vijay Abraham I   usb: twl6030: Add...
427
  		.of_match_table = of_match_ptr(twl6030_usb_id_table),
c33fad0c3   Hema HK   usb: otg: Adding ...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  	},
  };
  
  static int __init twl6030_usb_init(void)
  {
  	return platform_driver_register(&twl6030_usb_driver);
  }
  subsys_initcall(twl6030_usb_init);
  
  static void __exit twl6030_usb_exit(void)
  {
  	platform_driver_unregister(&twl6030_usb_driver);
  }
  module_exit(twl6030_usb_exit);
  
  MODULE_ALIAS("platform:twl6030_usb");
  MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
  MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
  MODULE_LICENSE("GPL");