194ae9843SFelipe Balbi /*
294ae9843SFelipe Balbi  * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
394ae9843SFelipe Balbi  *
494ae9843SFelipe Balbi  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
594ae9843SFelipe Balbi  * This program is free software; you can redistribute it and/or modify
694ae9843SFelipe Balbi  * it under the terms of the GNU General Public License as published by
794ae9843SFelipe Balbi  * the Free Software Foundation; either version 2 of the License, or
894ae9843SFelipe Balbi  * (at your option) any later version.
994ae9843SFelipe Balbi  *
1094ae9843SFelipe Balbi  * Author: Hema HK <hemahk@ti.com>
1194ae9843SFelipe Balbi  *
1294ae9843SFelipe Balbi  * This program is distributed in the hope that it will be useful,
1394ae9843SFelipe Balbi  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1494ae9843SFelipe Balbi  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1594ae9843SFelipe Balbi  * GNU General Public License for more details.
1694ae9843SFelipe Balbi  *
1794ae9843SFelipe Balbi  * You should have received a copy of the GNU General Public License
1894ae9843SFelipe Balbi  * along with this program; if not, write to the Free Software
1994ae9843SFelipe Balbi  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2094ae9843SFelipe Balbi  *
2194ae9843SFelipe Balbi  */
2294ae9843SFelipe Balbi 
2394ae9843SFelipe Balbi #include <linux/module.h>
2494ae9843SFelipe Balbi #include <linux/init.h>
2594ae9843SFelipe Balbi #include <linux/interrupt.h>
2694ae9843SFelipe Balbi #include <linux/platform_device.h>
2794ae9843SFelipe Balbi #include <linux/io.h>
2894ae9843SFelipe Balbi #include <linux/usb/musb-omap.h>
2994ae9843SFelipe Balbi #include <linux/usb/phy_companion.h>
3094ae9843SFelipe Balbi #include <linux/usb/omap_usb.h>
3194ae9843SFelipe Balbi #include <linux/i2c/twl.h>
3294ae9843SFelipe Balbi #include <linux/regulator/consumer.h>
3394ae9843SFelipe Balbi #include <linux/err.h>
3494ae9843SFelipe Balbi #include <linux/slab.h>
3594ae9843SFelipe Balbi #include <linux/delay.h>
3694ae9843SFelipe Balbi 
3794ae9843SFelipe Balbi /* usb register definitions */
3894ae9843SFelipe Balbi #define USB_VENDOR_ID_LSB		0x00
3994ae9843SFelipe Balbi #define USB_VENDOR_ID_MSB		0x01
4094ae9843SFelipe Balbi #define USB_PRODUCT_ID_LSB		0x02
4194ae9843SFelipe Balbi #define USB_PRODUCT_ID_MSB		0x03
4294ae9843SFelipe Balbi #define USB_VBUS_CTRL_SET		0x04
4394ae9843SFelipe Balbi #define USB_VBUS_CTRL_CLR		0x05
4494ae9843SFelipe Balbi #define USB_ID_CTRL_SET			0x06
4594ae9843SFelipe Balbi #define USB_ID_CTRL_CLR			0x07
4694ae9843SFelipe Balbi #define USB_VBUS_INT_SRC		0x08
4794ae9843SFelipe Balbi #define USB_VBUS_INT_LATCH_SET		0x09
4894ae9843SFelipe Balbi #define USB_VBUS_INT_LATCH_CLR		0x0A
4994ae9843SFelipe Balbi #define USB_VBUS_INT_EN_LO_SET		0x0B
5094ae9843SFelipe Balbi #define USB_VBUS_INT_EN_LO_CLR		0x0C
5194ae9843SFelipe Balbi #define USB_VBUS_INT_EN_HI_SET		0x0D
5294ae9843SFelipe Balbi #define USB_VBUS_INT_EN_HI_CLR		0x0E
5394ae9843SFelipe Balbi #define USB_ID_INT_SRC			0x0F
5494ae9843SFelipe Balbi #define USB_ID_INT_LATCH_SET		0x10
5594ae9843SFelipe Balbi #define USB_ID_INT_LATCH_CLR		0x11
5694ae9843SFelipe Balbi 
5794ae9843SFelipe Balbi #define USB_ID_INT_EN_LO_SET		0x12
5894ae9843SFelipe Balbi #define USB_ID_INT_EN_LO_CLR		0x13
5994ae9843SFelipe Balbi #define USB_ID_INT_EN_HI_SET		0x14
6094ae9843SFelipe Balbi #define USB_ID_INT_EN_HI_CLR		0x15
6194ae9843SFelipe Balbi #define USB_OTG_ADP_CTRL		0x16
6294ae9843SFelipe Balbi #define USB_OTG_ADP_HIGH		0x17
6394ae9843SFelipe Balbi #define USB_OTG_ADP_LOW			0x18
6494ae9843SFelipe Balbi #define USB_OTG_ADP_RISE		0x19
6594ae9843SFelipe Balbi #define USB_OTG_REVISION		0x1A
6694ae9843SFelipe Balbi 
6794ae9843SFelipe Balbi /* to be moved to LDO */
6894ae9843SFelipe Balbi #define TWL6030_MISC2			0xE5
6994ae9843SFelipe Balbi #define TWL6030_CFG_LDO_PD2		0xF5
7094ae9843SFelipe Balbi #define TWL6030_BACKUP_REG		0xFA
7194ae9843SFelipe Balbi 
7294ae9843SFelipe Balbi #define STS_HW_CONDITIONS		0x21
7394ae9843SFelipe Balbi 
7494ae9843SFelipe Balbi /* In module TWL6030_MODULE_PM_MASTER */
7594ae9843SFelipe Balbi #define STS_HW_CONDITIONS		0x21
7694ae9843SFelipe Balbi #define STS_USB_ID			BIT(2)
7794ae9843SFelipe Balbi 
7894ae9843SFelipe Balbi /* In module TWL6030_MODULE_PM_RECEIVER */
7994ae9843SFelipe Balbi #define VUSB_CFG_TRANS			0x71
8094ae9843SFelipe Balbi #define VUSB_CFG_STATE			0x72
8194ae9843SFelipe Balbi #define VUSB_CFG_VOLTAGE		0x73
8294ae9843SFelipe Balbi 
8394ae9843SFelipe Balbi /* in module TWL6030_MODULE_MAIN_CHARGE */
8494ae9843SFelipe Balbi 
8594ae9843SFelipe Balbi #define CHARGERUSB_CTRL1		0x8
8694ae9843SFelipe Balbi 
8794ae9843SFelipe Balbi #define CONTROLLER_STAT1		0x03
8894ae9843SFelipe Balbi #define	VBUS_DET			BIT(2)
8994ae9843SFelipe Balbi 
9094ae9843SFelipe Balbi struct twl6030_usb {
9194ae9843SFelipe Balbi 	struct phy_companion	comparator;
9294ae9843SFelipe Balbi 	struct device		*dev;
9394ae9843SFelipe Balbi 
9494ae9843SFelipe Balbi 	/* for vbus reporting with irqs disabled */
9594ae9843SFelipe Balbi 	spinlock_t		lock;
9694ae9843SFelipe Balbi 
9794ae9843SFelipe Balbi 	struct regulator		*usb3v3;
9894ae9843SFelipe Balbi 
9994ae9843SFelipe Balbi 	/* used to set vbus, in atomic path */
10094ae9843SFelipe Balbi 	struct work_struct	set_vbus_work;
10194ae9843SFelipe Balbi 
10294ae9843SFelipe Balbi 	int			irq1;
10394ae9843SFelipe Balbi 	int			irq2;
10494ae9843SFelipe Balbi 	enum omap_musb_vbus_id_status linkstat;
10594ae9843SFelipe Balbi 	u8			asleep;
10694ae9843SFelipe Balbi 	bool			irq_enabled;
10794ae9843SFelipe Balbi 	bool			vbus_enable;
10894ae9843SFelipe Balbi 	const char		*regulator;
10994ae9843SFelipe Balbi };
11094ae9843SFelipe Balbi 
11194ae9843SFelipe Balbi #define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
11294ae9843SFelipe Balbi 
11394ae9843SFelipe Balbi /*-------------------------------------------------------------------------*/
11494ae9843SFelipe Balbi 
11594ae9843SFelipe Balbi static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
11694ae9843SFelipe Balbi 						u8 data, u8 address)
11794ae9843SFelipe Balbi {
11894ae9843SFelipe Balbi 	int ret = 0;
11994ae9843SFelipe Balbi 
12094ae9843SFelipe Balbi 	ret = twl_i2c_write_u8(module, data, address);
12194ae9843SFelipe Balbi 	if (ret < 0)
12294ae9843SFelipe Balbi 		dev_err(twl->dev,
12394ae9843SFelipe Balbi 			"Write[0x%x] Error %d\n", address, ret);
12494ae9843SFelipe Balbi 	return ret;
12594ae9843SFelipe Balbi }
12694ae9843SFelipe Balbi 
12794ae9843SFelipe Balbi static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
12894ae9843SFelipe Balbi {
12994ae9843SFelipe Balbi 	u8 data, ret = 0;
13094ae9843SFelipe Balbi 
13194ae9843SFelipe Balbi 	ret = twl_i2c_read_u8(module, &data, address);
13294ae9843SFelipe Balbi 	if (ret >= 0)
13394ae9843SFelipe Balbi 		ret = data;
13494ae9843SFelipe Balbi 	else
13594ae9843SFelipe Balbi 		dev_err(twl->dev,
13694ae9843SFelipe Balbi 			"readb[0x%x,0x%x] Error %d\n",
13794ae9843SFelipe Balbi 					module, address, ret);
13894ae9843SFelipe Balbi 	return ret;
13994ae9843SFelipe Balbi }
14094ae9843SFelipe Balbi 
14194ae9843SFelipe Balbi static int twl6030_start_srp(struct phy_companion *comparator)
14294ae9843SFelipe Balbi {
14394ae9843SFelipe Balbi 	struct twl6030_usb *twl = comparator_to_twl(comparator);
14494ae9843SFelipe Balbi 
14594ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
14694ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
14794ae9843SFelipe Balbi 
14894ae9843SFelipe Balbi 	mdelay(100);
14994ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);
15094ae9843SFelipe Balbi 
15194ae9843SFelipe Balbi 	return 0;
15294ae9843SFelipe Balbi }
15394ae9843SFelipe Balbi 
15494ae9843SFelipe Balbi static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
15594ae9843SFelipe Balbi {
15694ae9843SFelipe Balbi 	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
15794ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
15894ae9843SFelipe Balbi 
15994ae9843SFelipe Balbi 	/* Program CFG_LDO_PD2 register and set VUSB bit */
16094ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
16194ae9843SFelipe Balbi 
16294ae9843SFelipe Balbi 	/* Program MISC2 register and set bit VUSB_IN_VBAT */
16394ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
16494ae9843SFelipe Balbi 
16594ae9843SFelipe Balbi 	twl->usb3v3 = regulator_get(twl->dev, twl->regulator);
16694ae9843SFelipe Balbi 	if (IS_ERR(twl->usb3v3))
16794ae9843SFelipe Balbi 		return -ENODEV;
16894ae9843SFelipe Balbi 
16994ae9843SFelipe Balbi 	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
17094ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
17194ae9843SFelipe Balbi 
17294ae9843SFelipe Balbi 	/*
17394ae9843SFelipe Balbi 	 * Program the USB_ID_CTRL_SET register to enable GND drive
17494ae9843SFelipe Balbi 	 * and the ID comparators
17594ae9843SFelipe Balbi 	 */
17694ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
17794ae9843SFelipe Balbi 
17894ae9843SFelipe Balbi 	return 0;
17994ae9843SFelipe Balbi }
18094ae9843SFelipe Balbi 
18194ae9843SFelipe Balbi static ssize_t twl6030_usb_vbus_show(struct device *dev,
18294ae9843SFelipe Balbi 			struct device_attribute *attr, char *buf)
18394ae9843SFelipe Balbi {
18494ae9843SFelipe Balbi 	struct twl6030_usb *twl = dev_get_drvdata(dev);
18594ae9843SFelipe Balbi 	unsigned long flags;
18694ae9843SFelipe Balbi 	int ret = -EINVAL;
18794ae9843SFelipe Balbi 
18894ae9843SFelipe Balbi 	spin_lock_irqsave(&twl->lock, flags);
18994ae9843SFelipe Balbi 
19094ae9843SFelipe Balbi 	switch (twl->linkstat) {
19194ae9843SFelipe Balbi 	case OMAP_MUSB_VBUS_VALID:
19294ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
19394ae9843SFelipe Balbi 	       break;
19494ae9843SFelipe Balbi 	case OMAP_MUSB_ID_GROUND:
19594ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "id\n");
19694ae9843SFelipe Balbi 	       break;
19794ae9843SFelipe Balbi 	case OMAP_MUSB_VBUS_OFF:
19894ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "none\n");
19994ae9843SFelipe Balbi 	       break;
20094ae9843SFelipe Balbi 	default:
20194ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
20294ae9843SFelipe Balbi 	}
20394ae9843SFelipe Balbi 	spin_unlock_irqrestore(&twl->lock, flags);
20494ae9843SFelipe Balbi 
20594ae9843SFelipe Balbi 	return ret;
20694ae9843SFelipe Balbi }
20794ae9843SFelipe Balbi static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
20894ae9843SFelipe Balbi 
20994ae9843SFelipe Balbi static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
21094ae9843SFelipe Balbi {
21194ae9843SFelipe Balbi 	struct twl6030_usb *twl = _twl;
21294ae9843SFelipe Balbi 	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
21394ae9843SFelipe Balbi 	u8 vbus_state, hw_state;
214bb54542cSFabio Baltieri 	int ret;
21594ae9843SFelipe Balbi 
21694ae9843SFelipe Balbi 	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
21794ae9843SFelipe Balbi 
21894ae9843SFelipe Balbi 	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
21994ae9843SFelipe Balbi 						CONTROLLER_STAT1);
22094ae9843SFelipe Balbi 	if (!(hw_state & STS_USB_ID)) {
22194ae9843SFelipe Balbi 		if (vbus_state & VBUS_DET) {
222bb54542cSFabio Baltieri 			ret = regulator_enable(twl->usb3v3);
223bb54542cSFabio Baltieri 			if (ret)
224bb54542cSFabio Baltieri 				dev_err(twl->dev, "Failed to enable usb3v3\n");
225bb54542cSFabio Baltieri 
22694ae9843SFelipe Balbi 			twl->asleep = 1;
22794ae9843SFelipe Balbi 			status = OMAP_MUSB_VBUS_VALID;
22894ae9843SFelipe Balbi 			twl->linkstat = status;
22994ae9843SFelipe Balbi 			omap_musb_mailbox(status);
23094ae9843SFelipe Balbi 		} else {
23194ae9843SFelipe Balbi 			if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
23294ae9843SFelipe Balbi 				status = OMAP_MUSB_VBUS_OFF;
23394ae9843SFelipe Balbi 				twl->linkstat = status;
23494ae9843SFelipe Balbi 				omap_musb_mailbox(status);
23594ae9843SFelipe Balbi 				if (twl->asleep) {
23694ae9843SFelipe Balbi 					regulator_disable(twl->usb3v3);
23794ae9843SFelipe Balbi 					twl->asleep = 0;
23894ae9843SFelipe Balbi 				}
23994ae9843SFelipe Balbi 			}
24094ae9843SFelipe Balbi 		}
24194ae9843SFelipe Balbi 	}
24294ae9843SFelipe Balbi 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
24394ae9843SFelipe Balbi 
24494ae9843SFelipe Balbi 	return IRQ_HANDLED;
24594ae9843SFelipe Balbi }
24694ae9843SFelipe Balbi 
24794ae9843SFelipe Balbi static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
24894ae9843SFelipe Balbi {
24994ae9843SFelipe Balbi 	struct twl6030_usb *twl = _twl;
25094ae9843SFelipe Balbi 	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
25194ae9843SFelipe Balbi 	u8 hw_state;
252bb54542cSFabio Baltieri 	int ret;
25394ae9843SFelipe Balbi 
25494ae9843SFelipe Balbi 	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
25594ae9843SFelipe Balbi 
25694ae9843SFelipe Balbi 	if (hw_state & STS_USB_ID) {
257bb54542cSFabio Baltieri 		ret = regulator_enable(twl->usb3v3);
258bb54542cSFabio Baltieri 		if (ret)
259bb54542cSFabio Baltieri 			dev_err(twl->dev, "Failed to enable usb3v3\n");
26094ae9843SFelipe Balbi 
26194ae9843SFelipe Balbi 		twl->asleep = 1;
26294ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
26394ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
26494ae9843SFelipe Balbi 		status = OMAP_MUSB_ID_GROUND;
26594ae9843SFelipe Balbi 		twl->linkstat = status;
26694ae9843SFelipe Balbi 		omap_musb_mailbox(status);
26794ae9843SFelipe Balbi 	} else  {
26894ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
26994ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
27094ae9843SFelipe Balbi 	}
27194ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
27294ae9843SFelipe Balbi 
27394ae9843SFelipe Balbi 	return IRQ_HANDLED;
27494ae9843SFelipe Balbi }
27594ae9843SFelipe Balbi 
27694ae9843SFelipe Balbi static int twl6030_enable_irq(struct twl6030_usb *twl)
27794ae9843SFelipe Balbi {
27894ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
27994ae9843SFelipe Balbi 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
28094ae9843SFelipe Balbi 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
28194ae9843SFelipe Balbi 
28294ae9843SFelipe Balbi 	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
28394ae9843SFelipe Balbi 				REG_INT_MSK_LINE_C);
28494ae9843SFelipe Balbi 	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
28594ae9843SFelipe Balbi 				REG_INT_MSK_STS_C);
28694ae9843SFelipe Balbi 	twl6030_usb_irq(twl->irq2, twl);
28794ae9843SFelipe Balbi 	twl6030_usbotg_irq(twl->irq1, twl);
28894ae9843SFelipe Balbi 
28994ae9843SFelipe Balbi 	return 0;
29094ae9843SFelipe Balbi }
29194ae9843SFelipe Balbi 
29294ae9843SFelipe Balbi static void otg_set_vbus_work(struct work_struct *data)
29394ae9843SFelipe Balbi {
29494ae9843SFelipe Balbi 	struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
29594ae9843SFelipe Balbi 								set_vbus_work);
29694ae9843SFelipe Balbi 
29794ae9843SFelipe Balbi 	/*
29894ae9843SFelipe Balbi 	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
29994ae9843SFelipe Balbi 	 * register. This enables boost mode.
30094ae9843SFelipe Balbi 	 */
30194ae9843SFelipe Balbi 
30294ae9843SFelipe Balbi 	if (twl->vbus_enable)
30394ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
30494ae9843SFelipe Balbi 							CHARGERUSB_CTRL1);
30594ae9843SFelipe Balbi 	else
30694ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
30794ae9843SFelipe Balbi 							CHARGERUSB_CTRL1);
30894ae9843SFelipe Balbi }
30994ae9843SFelipe Balbi 
31094ae9843SFelipe Balbi static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
31194ae9843SFelipe Balbi {
31294ae9843SFelipe Balbi 	struct twl6030_usb *twl = comparator_to_twl(comparator);
31394ae9843SFelipe Balbi 
31494ae9843SFelipe Balbi 	twl->vbus_enable = enabled;
31594ae9843SFelipe Balbi 	schedule_work(&twl->set_vbus_work);
31694ae9843SFelipe Balbi 
31794ae9843SFelipe Balbi 	return 0;
31894ae9843SFelipe Balbi }
31994ae9843SFelipe Balbi 
32094ae9843SFelipe Balbi static int twl6030_usb_probe(struct platform_device *pdev)
32194ae9843SFelipe Balbi {
32294ae9843SFelipe Balbi 	u32 ret;
32394ae9843SFelipe Balbi 	struct twl6030_usb	*twl;
32494ae9843SFelipe Balbi 	int			status, err;
32594ae9843SFelipe Balbi 	struct device_node	*np = pdev->dev.of_node;
32694ae9843SFelipe Balbi 	struct device		*dev = &pdev->dev;
32794ae9843SFelipe Balbi 	struct twl4030_usb_data	*pdata = dev->platform_data;
32894ae9843SFelipe Balbi 
32994ae9843SFelipe Balbi 	twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
33094ae9843SFelipe Balbi 	if (!twl)
33194ae9843SFelipe Balbi 		return -ENOMEM;
33294ae9843SFelipe Balbi 
33394ae9843SFelipe Balbi 	twl->dev		= &pdev->dev;
33494ae9843SFelipe Balbi 	twl->irq1		= platform_get_irq(pdev, 0);
33594ae9843SFelipe Balbi 	twl->irq2		= platform_get_irq(pdev, 1);
33694ae9843SFelipe Balbi 	twl->linkstat		= OMAP_MUSB_UNKNOWN;
33794ae9843SFelipe Balbi 
33894ae9843SFelipe Balbi 	twl->comparator.set_vbus	= twl6030_set_vbus;
33994ae9843SFelipe Balbi 	twl->comparator.start_srp	= twl6030_start_srp;
34094ae9843SFelipe Balbi 
34194ae9843SFelipe Balbi 	ret = omap_usb2_set_comparator(&twl->comparator);
34294ae9843SFelipe Balbi 	if (ret == -ENODEV) {
34394ae9843SFelipe Balbi 		dev_info(&pdev->dev, "phy not ready, deferring probe");
34494ae9843SFelipe Balbi 		return -EPROBE_DEFER;
34594ae9843SFelipe Balbi 	}
34694ae9843SFelipe Balbi 
34794ae9843SFelipe Balbi 	if (np) {
34894ae9843SFelipe Balbi 		twl->regulator = "usb";
34994ae9843SFelipe Balbi 	} else if (pdata) {
35089ce43fbSGraeme Gregory 		if (pdata->features & TWL6032_SUBCLASS)
35194ae9843SFelipe Balbi 			twl->regulator = "ldousb";
35294ae9843SFelipe Balbi 		else
35394ae9843SFelipe Balbi 			twl->regulator = "vusb";
35494ae9843SFelipe Balbi 	} else {
35594ae9843SFelipe Balbi 		dev_err(&pdev->dev, "twl6030 initialized without pdata\n");
35694ae9843SFelipe Balbi 		return -EINVAL;
35794ae9843SFelipe Balbi 	}
35894ae9843SFelipe Balbi 
35994ae9843SFelipe Balbi 	/* init spinlock for workqueue */
36094ae9843SFelipe Balbi 	spin_lock_init(&twl->lock);
36194ae9843SFelipe Balbi 
36294ae9843SFelipe Balbi 	err = twl6030_usb_ldo_init(twl);
36394ae9843SFelipe Balbi 	if (err) {
36494ae9843SFelipe Balbi 		dev_err(&pdev->dev, "ldo init failed\n");
36594ae9843SFelipe Balbi 		return err;
36694ae9843SFelipe Balbi 	}
36794ae9843SFelipe Balbi 
36894ae9843SFelipe Balbi 	platform_set_drvdata(pdev, twl);
36994ae9843SFelipe Balbi 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
37094ae9843SFelipe Balbi 		dev_warn(&pdev->dev, "could not create sysfs file\n");
37194ae9843SFelipe Balbi 
37294ae9843SFelipe Balbi 	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
37394ae9843SFelipe Balbi 
37494ae9843SFelipe Balbi 	twl->irq_enabled = true;
37594ae9843SFelipe Balbi 	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
37694ae9843SFelipe Balbi 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
37794ae9843SFelipe Balbi 			"twl6030_usb", twl);
37894ae9843SFelipe Balbi 	if (status < 0) {
37994ae9843SFelipe Balbi 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
38094ae9843SFelipe Balbi 			twl->irq1, status);
38194ae9843SFelipe Balbi 		device_remove_file(twl->dev, &dev_attr_vbus);
38294ae9843SFelipe Balbi 		return status;
38394ae9843SFelipe Balbi 	}
38494ae9843SFelipe Balbi 
38594ae9843SFelipe Balbi 	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
38694ae9843SFelipe Balbi 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
38794ae9843SFelipe Balbi 			"twl6030_usb", twl);
38894ae9843SFelipe Balbi 	if (status < 0) {
38994ae9843SFelipe Balbi 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
39094ae9843SFelipe Balbi 			twl->irq2, status);
39194ae9843SFelipe Balbi 		free_irq(twl->irq1, twl);
39294ae9843SFelipe Balbi 		device_remove_file(twl->dev, &dev_attr_vbus);
39394ae9843SFelipe Balbi 		return status;
39494ae9843SFelipe Balbi 	}
39594ae9843SFelipe Balbi 
39694ae9843SFelipe Balbi 	twl->asleep = 0;
39794ae9843SFelipe Balbi 	twl6030_enable_irq(twl);
39894ae9843SFelipe Balbi 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
39994ae9843SFelipe Balbi 
40094ae9843SFelipe Balbi 	return 0;
40194ae9843SFelipe Balbi }
40294ae9843SFelipe Balbi 
40364dc9e2eSGreg Kroah-Hartman static int twl6030_usb_remove(struct platform_device *pdev)
40494ae9843SFelipe Balbi {
40594ae9843SFelipe Balbi 	struct twl6030_usb *twl = platform_get_drvdata(pdev);
40694ae9843SFelipe Balbi 
40794ae9843SFelipe Balbi 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
40894ae9843SFelipe Balbi 		REG_INT_MSK_LINE_C);
40994ae9843SFelipe Balbi 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
41094ae9843SFelipe Balbi 			REG_INT_MSK_STS_C);
41194ae9843SFelipe Balbi 	free_irq(twl->irq1, twl);
41294ae9843SFelipe Balbi 	free_irq(twl->irq2, twl);
41394ae9843SFelipe Balbi 	regulator_put(twl->usb3v3);
41494ae9843SFelipe Balbi 	device_remove_file(twl->dev, &dev_attr_vbus);
41594ae9843SFelipe Balbi 	cancel_work_sync(&twl->set_vbus_work);
41694ae9843SFelipe Balbi 
41794ae9843SFelipe Balbi 	return 0;
41894ae9843SFelipe Balbi }
41994ae9843SFelipe Balbi 
42094ae9843SFelipe Balbi #ifdef CONFIG_OF
42194ae9843SFelipe Balbi static const struct of_device_id twl6030_usb_id_table[] = {
42294ae9843SFelipe Balbi 	{ .compatible = "ti,twl6030-usb" },
42394ae9843SFelipe Balbi 	{}
42494ae9843SFelipe Balbi };
42594ae9843SFelipe Balbi MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
42694ae9843SFelipe Balbi #endif
42794ae9843SFelipe Balbi 
42894ae9843SFelipe Balbi static struct platform_driver twl6030_usb_driver = {
42994ae9843SFelipe Balbi 	.probe		= twl6030_usb_probe,
43064dc9e2eSGreg Kroah-Hartman 	.remove		= twl6030_usb_remove,
43194ae9843SFelipe Balbi 	.driver		= {
43294ae9843SFelipe Balbi 		.name	= "twl6030_usb",
43394ae9843SFelipe Balbi 		.owner	= THIS_MODULE,
43494ae9843SFelipe Balbi 		.of_match_table = of_match_ptr(twl6030_usb_id_table),
43594ae9843SFelipe Balbi 	},
43694ae9843SFelipe Balbi };
43794ae9843SFelipe Balbi 
43894ae9843SFelipe Balbi static int __init twl6030_usb_init(void)
43994ae9843SFelipe Balbi {
44094ae9843SFelipe Balbi 	return platform_driver_register(&twl6030_usb_driver);
44194ae9843SFelipe Balbi }
44294ae9843SFelipe Balbi subsys_initcall(twl6030_usb_init);
44394ae9843SFelipe Balbi 
44494ae9843SFelipe Balbi static void __exit twl6030_usb_exit(void)
44594ae9843SFelipe Balbi {
44694ae9843SFelipe Balbi 	platform_driver_unregister(&twl6030_usb_driver);
44794ae9843SFelipe Balbi }
44894ae9843SFelipe Balbi module_exit(twl6030_usb_exit);
44994ae9843SFelipe Balbi 
45094ae9843SFelipe Balbi MODULE_ALIAS("platform:twl6030_usb");
45194ae9843SFelipe Balbi MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
45294ae9843SFelipe Balbi MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
45394ae9843SFelipe Balbi MODULE_LICENSE("GPL");
454