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>
288055555fSTony Lindgren #include <linux/usb/musb.h>
2994ae9843SFelipe Balbi #include <linux/usb/phy_companion.h>
306284be23SKishon Vijay Abraham I #include <linux/phy/omap_usb.h>
31a2054256SWolfram Sang #include <linux/mfd/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>
3680d7d8a7SSachin Kamat #include <linux/of.h>
3794ae9843SFelipe Balbi 
3894ae9843SFelipe Balbi /* usb register definitions */
3994ae9843SFelipe Balbi #define USB_VENDOR_ID_LSB		0x00
4094ae9843SFelipe Balbi #define USB_VENDOR_ID_MSB		0x01
4194ae9843SFelipe Balbi #define USB_PRODUCT_ID_LSB		0x02
4294ae9843SFelipe Balbi #define USB_PRODUCT_ID_MSB		0x03
4394ae9843SFelipe Balbi #define USB_VBUS_CTRL_SET		0x04
4494ae9843SFelipe Balbi #define USB_VBUS_CTRL_CLR		0x05
4594ae9843SFelipe Balbi #define USB_ID_CTRL_SET			0x06
4694ae9843SFelipe Balbi #define USB_ID_CTRL_CLR			0x07
4794ae9843SFelipe Balbi #define USB_VBUS_INT_SRC		0x08
4894ae9843SFelipe Balbi #define USB_VBUS_INT_LATCH_SET		0x09
4994ae9843SFelipe Balbi #define USB_VBUS_INT_LATCH_CLR		0x0A
5094ae9843SFelipe Balbi #define USB_VBUS_INT_EN_LO_SET		0x0B
5194ae9843SFelipe Balbi #define USB_VBUS_INT_EN_LO_CLR		0x0C
5294ae9843SFelipe Balbi #define USB_VBUS_INT_EN_HI_SET		0x0D
5394ae9843SFelipe Balbi #define USB_VBUS_INT_EN_HI_CLR		0x0E
5494ae9843SFelipe Balbi #define USB_ID_INT_SRC			0x0F
5594ae9843SFelipe Balbi #define USB_ID_INT_LATCH_SET		0x10
5694ae9843SFelipe Balbi #define USB_ID_INT_LATCH_CLR		0x11
5794ae9843SFelipe Balbi 
5894ae9843SFelipe Balbi #define USB_ID_INT_EN_LO_SET		0x12
5994ae9843SFelipe Balbi #define USB_ID_INT_EN_LO_CLR		0x13
6094ae9843SFelipe Balbi #define USB_ID_INT_EN_HI_SET		0x14
6194ae9843SFelipe Balbi #define USB_ID_INT_EN_HI_CLR		0x15
6294ae9843SFelipe Balbi #define USB_OTG_ADP_CTRL		0x16
6394ae9843SFelipe Balbi #define USB_OTG_ADP_HIGH		0x17
6494ae9843SFelipe Balbi #define USB_OTG_ADP_LOW			0x18
6594ae9843SFelipe Balbi #define USB_OTG_ADP_RISE		0x19
6694ae9843SFelipe Balbi #define USB_OTG_REVISION		0x1A
6794ae9843SFelipe Balbi 
6894ae9843SFelipe Balbi /* to be moved to LDO */
6994ae9843SFelipe Balbi #define TWL6030_MISC2			0xE5
7094ae9843SFelipe Balbi #define TWL6030_CFG_LDO_PD2		0xF5
7194ae9843SFelipe Balbi #define TWL6030_BACKUP_REG		0xFA
7294ae9843SFelipe Balbi 
7394ae9843SFelipe Balbi #define STS_HW_CONDITIONS		0x21
7494ae9843SFelipe Balbi 
7594ae9843SFelipe Balbi /* In module TWL6030_MODULE_PM_MASTER */
7694ae9843SFelipe Balbi #define STS_HW_CONDITIONS		0x21
7794ae9843SFelipe Balbi #define STS_USB_ID			BIT(2)
7894ae9843SFelipe Balbi 
7994ae9843SFelipe Balbi /* In module TWL6030_MODULE_PM_RECEIVER */
8094ae9843SFelipe Balbi #define VUSB_CFG_TRANS			0x71
8194ae9843SFelipe Balbi #define VUSB_CFG_STATE			0x72
8294ae9843SFelipe Balbi #define VUSB_CFG_VOLTAGE		0x73
8394ae9843SFelipe Balbi 
8494ae9843SFelipe Balbi /* in module TWL6030_MODULE_MAIN_CHARGE */
8594ae9843SFelipe Balbi 
8694ae9843SFelipe Balbi #define CHARGERUSB_CTRL1		0x8
8794ae9843SFelipe Balbi 
8894ae9843SFelipe Balbi #define CONTROLLER_STAT1		0x03
8994ae9843SFelipe Balbi #define	VBUS_DET			BIT(2)
9094ae9843SFelipe Balbi 
9194ae9843SFelipe Balbi struct twl6030_usb {
9294ae9843SFelipe Balbi 	struct phy_companion	comparator;
9394ae9843SFelipe Balbi 	struct device		*dev;
9494ae9843SFelipe Balbi 
9594ae9843SFelipe Balbi 	/* for vbus reporting with irqs disabled */
9694ae9843SFelipe Balbi 	spinlock_t		lock;
9794ae9843SFelipe Balbi 
9894ae9843SFelipe Balbi 	struct regulator		*usb3v3;
9994ae9843SFelipe Balbi 
100b6a619a8STony Lindgren 	/* used to check initial cable status after probe */
101b6a619a8STony Lindgren 	struct delayed_work	get_status_work;
102b6a619a8STony Lindgren 
10394ae9843SFelipe Balbi 	/* used to set vbus, in atomic path */
10494ae9843SFelipe Balbi 	struct work_struct	set_vbus_work;
10594ae9843SFelipe Balbi 
10694ae9843SFelipe Balbi 	int			irq1;
10794ae9843SFelipe Balbi 	int			irq2;
1088055555fSTony Lindgren 	enum musb_vbus_id_status linkstat;
10994ae9843SFelipe Balbi 	u8			asleep;
11094ae9843SFelipe Balbi 	bool			vbus_enable;
11194ae9843SFelipe Balbi };
11294ae9843SFelipe Balbi 
11394ae9843SFelipe Balbi #define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
11494ae9843SFelipe Balbi 
11594ae9843SFelipe Balbi /*-------------------------------------------------------------------------*/
11694ae9843SFelipe Balbi 
11794ae9843SFelipe Balbi static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
11894ae9843SFelipe Balbi 						u8 data, u8 address)
11994ae9843SFelipe Balbi {
12094ae9843SFelipe Balbi 	int ret = 0;
12194ae9843SFelipe Balbi 
12294ae9843SFelipe Balbi 	ret = twl_i2c_write_u8(module, data, address);
12394ae9843SFelipe Balbi 	if (ret < 0)
12494ae9843SFelipe Balbi 		dev_err(twl->dev,
12594ae9843SFelipe Balbi 			"Write[0x%x] Error %d\n", address, ret);
12694ae9843SFelipe Balbi 	return ret;
12794ae9843SFelipe Balbi }
12894ae9843SFelipe Balbi 
12994ae9843SFelipe Balbi static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
13094ae9843SFelipe Balbi {
1310b551490SDan Carpenter 	u8 data;
1320b551490SDan Carpenter 	int ret;
13394ae9843SFelipe Balbi 
13494ae9843SFelipe Balbi 	ret = twl_i2c_read_u8(module, &data, address);
13594ae9843SFelipe Balbi 	if (ret >= 0)
13694ae9843SFelipe Balbi 		ret = data;
13794ae9843SFelipe Balbi 	else
13894ae9843SFelipe Balbi 		dev_err(twl->dev,
13994ae9843SFelipe Balbi 			"readb[0x%x,0x%x] Error %d\n",
14094ae9843SFelipe Balbi 					module, address, ret);
14194ae9843SFelipe Balbi 	return ret;
14294ae9843SFelipe Balbi }
14394ae9843SFelipe Balbi 
14494ae9843SFelipe Balbi static int twl6030_start_srp(struct phy_companion *comparator)
14594ae9843SFelipe Balbi {
14694ae9843SFelipe Balbi 	struct twl6030_usb *twl = comparator_to_twl(comparator);
14794ae9843SFelipe Balbi 
14894ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
14994ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
15094ae9843SFelipe Balbi 
15194ae9843SFelipe Balbi 	mdelay(100);
15294ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);
15394ae9843SFelipe Balbi 
15494ae9843SFelipe Balbi 	return 0;
15594ae9843SFelipe Balbi }
15694ae9843SFelipe Balbi 
15794ae9843SFelipe Balbi static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
15894ae9843SFelipe Balbi {
15994ae9843SFelipe Balbi 	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
16094ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_BACKUP_REG);
16194ae9843SFelipe Balbi 
16294ae9843SFelipe Balbi 	/* Program CFG_LDO_PD2 register and set VUSB bit */
16394ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_CFG_LDO_PD2);
16494ae9843SFelipe Balbi 
16594ae9843SFelipe Balbi 	/* Program MISC2 register and set bit VUSB_IN_VBAT */
16694ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2);
16794ae9843SFelipe Balbi 
1681ad528dbSNicolae Rosia 	twl->usb3v3 = regulator_get(twl->dev, "usb");
16994ae9843SFelipe Balbi 	if (IS_ERR(twl->usb3v3))
17094ae9843SFelipe Balbi 		return -ENODEV;
17194ae9843SFelipe Balbi 
17294ae9843SFelipe Balbi 	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
17394ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
17494ae9843SFelipe Balbi 
17594ae9843SFelipe Balbi 	/*
17694ae9843SFelipe Balbi 	 * Program the USB_ID_CTRL_SET register to enable GND drive
17794ae9843SFelipe Balbi 	 * and the ID comparators
17894ae9843SFelipe Balbi 	 */
17994ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
18094ae9843SFelipe Balbi 
18194ae9843SFelipe Balbi 	return 0;
18294ae9843SFelipe Balbi }
18394ae9843SFelipe Balbi 
18494ae9843SFelipe Balbi static ssize_t twl6030_usb_vbus_show(struct device *dev,
18594ae9843SFelipe Balbi 			struct device_attribute *attr, char *buf)
18694ae9843SFelipe Balbi {
18794ae9843SFelipe Balbi 	struct twl6030_usb *twl = dev_get_drvdata(dev);
18894ae9843SFelipe Balbi 	unsigned long flags;
18994ae9843SFelipe Balbi 	int ret = -EINVAL;
19094ae9843SFelipe Balbi 
19194ae9843SFelipe Balbi 	spin_lock_irqsave(&twl->lock, flags);
19294ae9843SFelipe Balbi 
19394ae9843SFelipe Balbi 	switch (twl->linkstat) {
1948055555fSTony Lindgren 	case MUSB_VBUS_VALID:
19594ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
19694ae9843SFelipe Balbi 	       break;
1978055555fSTony Lindgren 	case MUSB_ID_GROUND:
19894ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "id\n");
19994ae9843SFelipe Balbi 	       break;
2008055555fSTony Lindgren 	case MUSB_VBUS_OFF:
20194ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "none\n");
20294ae9843SFelipe Balbi 	       break;
20394ae9843SFelipe Balbi 	default:
20494ae9843SFelipe Balbi 	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
20594ae9843SFelipe Balbi 	}
20694ae9843SFelipe Balbi 	spin_unlock_irqrestore(&twl->lock, flags);
20794ae9843SFelipe Balbi 
20894ae9843SFelipe Balbi 	return ret;
20994ae9843SFelipe Balbi }
21094ae9843SFelipe Balbi static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
21194ae9843SFelipe Balbi 
21294ae9843SFelipe Balbi static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
21394ae9843SFelipe Balbi {
21494ae9843SFelipe Balbi 	struct twl6030_usb *twl = _twl;
2158055555fSTony Lindgren 	enum musb_vbus_id_status status = MUSB_UNKNOWN;
21694ae9843SFelipe Balbi 	u8 vbus_state, hw_state;
217bb54542cSFabio Baltieri 	int ret;
21894ae9843SFelipe Balbi 
21994ae9843SFelipe Balbi 	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
22094ae9843SFelipe Balbi 
22194ae9843SFelipe Balbi 	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
22294ae9843SFelipe Balbi 						CONTROLLER_STAT1);
22394ae9843SFelipe Balbi 	if (!(hw_state & STS_USB_ID)) {
22494ae9843SFelipe Balbi 		if (vbus_state & VBUS_DET) {
225bb54542cSFabio Baltieri 			ret = regulator_enable(twl->usb3v3);
226bb54542cSFabio Baltieri 			if (ret)
227bb54542cSFabio Baltieri 				dev_err(twl->dev, "Failed to enable usb3v3\n");
228bb54542cSFabio Baltieri 
22994ae9843SFelipe Balbi 			twl->asleep = 1;
2308055555fSTony Lindgren 			status = MUSB_VBUS_VALID;
23194ae9843SFelipe Balbi 			twl->linkstat = status;
23212b7db2bSTony Lindgren 			ret = musb_mailbox(status);
23312b7db2bSTony Lindgren 			if (ret)
23412b7db2bSTony Lindgren 				twl->linkstat = MUSB_UNKNOWN;
23594ae9843SFelipe Balbi 		} else {
2368055555fSTony Lindgren 			if (twl->linkstat != MUSB_UNKNOWN) {
2378055555fSTony Lindgren 				status = MUSB_VBUS_OFF;
23894ae9843SFelipe Balbi 				twl->linkstat = status;
23912b7db2bSTony Lindgren 				ret = musb_mailbox(status);
24012b7db2bSTony Lindgren 				if (ret)
24112b7db2bSTony Lindgren 					twl->linkstat = MUSB_UNKNOWN;
24294ae9843SFelipe Balbi 				if (twl->asleep) {
24394ae9843SFelipe Balbi 					regulator_disable(twl->usb3v3);
24494ae9843SFelipe Balbi 					twl->asleep = 0;
24594ae9843SFelipe Balbi 				}
24694ae9843SFelipe Balbi 			}
24794ae9843SFelipe Balbi 		}
24894ae9843SFelipe Balbi 	}
24994ae9843SFelipe Balbi 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
25094ae9843SFelipe Balbi 
25194ae9843SFelipe Balbi 	return IRQ_HANDLED;
25294ae9843SFelipe Balbi }
25394ae9843SFelipe Balbi 
25494ae9843SFelipe Balbi static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
25594ae9843SFelipe Balbi {
25694ae9843SFelipe Balbi 	struct twl6030_usb *twl = _twl;
2578055555fSTony Lindgren 	enum musb_vbus_id_status status = MUSB_UNKNOWN;
25894ae9843SFelipe Balbi 	u8 hw_state;
259bb54542cSFabio Baltieri 	int ret;
26094ae9843SFelipe Balbi 
26194ae9843SFelipe Balbi 	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
26294ae9843SFelipe Balbi 
26394ae9843SFelipe Balbi 	if (hw_state & STS_USB_ID) {
264bb54542cSFabio Baltieri 		ret = regulator_enable(twl->usb3v3);
265bb54542cSFabio Baltieri 		if (ret)
266bb54542cSFabio Baltieri 			dev_err(twl->dev, "Failed to enable usb3v3\n");
26794ae9843SFelipe Balbi 
26894ae9843SFelipe Balbi 		twl->asleep = 1;
26994ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
27094ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
2718055555fSTony Lindgren 		status = MUSB_ID_GROUND;
27294ae9843SFelipe Balbi 		twl->linkstat = status;
27312b7db2bSTony Lindgren 		ret = musb_mailbox(status);
27412b7db2bSTony Lindgren 		if (ret)
27512b7db2bSTony Lindgren 			twl->linkstat = MUSB_UNKNOWN;
27694ae9843SFelipe Balbi 	} else  {
27794ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
27894ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
27994ae9843SFelipe Balbi 	}
28094ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
28194ae9843SFelipe Balbi 
28294ae9843SFelipe Balbi 	return IRQ_HANDLED;
28394ae9843SFelipe Balbi }
28494ae9843SFelipe Balbi 
285b6a619a8STony Lindgren static void twl6030_status_work(struct work_struct *work)
286b6a619a8STony Lindgren {
287b6a619a8STony Lindgren 	struct twl6030_usb *twl = container_of(work, struct twl6030_usb,
288b6a619a8STony Lindgren 					       get_status_work.work);
289b6a619a8STony Lindgren 
290b6a619a8STony Lindgren 	twl6030_usb_irq(twl->irq2, twl);
291b6a619a8STony Lindgren 	twl6030_usbotg_irq(twl->irq1, twl);
292b6a619a8STony Lindgren }
293b6a619a8STony Lindgren 
29494ae9843SFelipe Balbi static int twl6030_enable_irq(struct twl6030_usb *twl)
29594ae9843SFelipe Balbi {
29694ae9843SFelipe Balbi 	twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
29794ae9843SFelipe Balbi 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
29894ae9843SFelipe Balbi 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
29994ae9843SFelipe Balbi 
30094ae9843SFelipe Balbi 	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
30194ae9843SFelipe Balbi 				REG_INT_MSK_LINE_C);
30294ae9843SFelipe Balbi 	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
30394ae9843SFelipe Balbi 				REG_INT_MSK_STS_C);
30494ae9843SFelipe Balbi 
30594ae9843SFelipe Balbi 	return 0;
30694ae9843SFelipe Balbi }
30794ae9843SFelipe Balbi 
30894ae9843SFelipe Balbi static void otg_set_vbus_work(struct work_struct *data)
30994ae9843SFelipe Balbi {
31094ae9843SFelipe Balbi 	struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
31194ae9843SFelipe Balbi 								set_vbus_work);
31294ae9843SFelipe Balbi 
31394ae9843SFelipe Balbi 	/*
31494ae9843SFelipe Balbi 	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
31594ae9843SFelipe Balbi 	 * register. This enables boost mode.
31694ae9843SFelipe Balbi 	 */
31794ae9843SFelipe Balbi 
31894ae9843SFelipe Balbi 	if (twl->vbus_enable)
31994ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x40,
32094ae9843SFelipe Balbi 							CHARGERUSB_CTRL1);
32194ae9843SFelipe Balbi 	else
32294ae9843SFelipe Balbi 		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x00,
32394ae9843SFelipe Balbi 							CHARGERUSB_CTRL1);
32494ae9843SFelipe Balbi }
32594ae9843SFelipe Balbi 
32694ae9843SFelipe Balbi static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
32794ae9843SFelipe Balbi {
32894ae9843SFelipe Balbi 	struct twl6030_usb *twl = comparator_to_twl(comparator);
32994ae9843SFelipe Balbi 
33094ae9843SFelipe Balbi 	twl->vbus_enable = enabled;
33194ae9843SFelipe Balbi 	schedule_work(&twl->set_vbus_work);
33294ae9843SFelipe Balbi 
33394ae9843SFelipe Balbi 	return 0;
33494ae9843SFelipe Balbi }
33594ae9843SFelipe Balbi 
33694ae9843SFelipe Balbi static int twl6030_usb_probe(struct platform_device *pdev)
33794ae9843SFelipe Balbi {
33894ae9843SFelipe Balbi 	u32 ret;
33994ae9843SFelipe Balbi 	struct twl6030_usb	*twl;
34094ae9843SFelipe Balbi 	int			status, err;
34194ae9843SFelipe Balbi 	struct device_node	*np = pdev->dev.of_node;
34294ae9843SFelipe Balbi 	struct device		*dev = &pdev->dev;
3431ad528dbSNicolae Rosia 
3441ad528dbSNicolae Rosia 	if (!np) {
3451ad528dbSNicolae Rosia 		dev_err(dev, "no DT info\n");
3461ad528dbSNicolae Rosia 		return -EINVAL;
3471ad528dbSNicolae Rosia 	}
34894ae9843SFelipe Balbi 
3492ee8ff30SSachin Kamat 	twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL);
35094ae9843SFelipe Balbi 	if (!twl)
35194ae9843SFelipe Balbi 		return -ENOMEM;
35294ae9843SFelipe Balbi 
35394ae9843SFelipe Balbi 	twl->dev		= &pdev->dev;
35494ae9843SFelipe Balbi 	twl->irq1		= platform_get_irq(pdev, 0);
35594ae9843SFelipe Balbi 	twl->irq2		= platform_get_irq(pdev, 1);
3568055555fSTony Lindgren 	twl->linkstat		= MUSB_UNKNOWN;
35794ae9843SFelipe Balbi 
35894ae9843SFelipe Balbi 	twl->comparator.set_vbus	= twl6030_set_vbus;
35994ae9843SFelipe Balbi 	twl->comparator.start_srp	= twl6030_start_srp;
36094ae9843SFelipe Balbi 
36194ae9843SFelipe Balbi 	ret = omap_usb2_set_comparator(&twl->comparator);
36294ae9843SFelipe Balbi 	if (ret == -ENODEV) {
36394ae9843SFelipe Balbi 		dev_info(&pdev->dev, "phy not ready, deferring probe");
36494ae9843SFelipe Balbi 		return -EPROBE_DEFER;
36594ae9843SFelipe Balbi 	}
36694ae9843SFelipe Balbi 
36794ae9843SFelipe Balbi 	/* init spinlock for workqueue */
36894ae9843SFelipe Balbi 	spin_lock_init(&twl->lock);
36994ae9843SFelipe Balbi 
37094ae9843SFelipe Balbi 	err = twl6030_usb_ldo_init(twl);
37194ae9843SFelipe Balbi 	if (err) {
37294ae9843SFelipe Balbi 		dev_err(&pdev->dev, "ldo init failed\n");
37394ae9843SFelipe Balbi 		return err;
37494ae9843SFelipe Balbi 	}
37594ae9843SFelipe Balbi 
37694ae9843SFelipe Balbi 	platform_set_drvdata(pdev, twl);
37794ae9843SFelipe Balbi 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
37894ae9843SFelipe Balbi 		dev_warn(&pdev->dev, "could not create sysfs file\n");
37994ae9843SFelipe Balbi 
38094ae9843SFelipe Balbi 	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
381b6a619a8STony Lindgren 	INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work);
38294ae9843SFelipe Balbi 
38394ae9843SFelipe Balbi 	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
38494ae9843SFelipe Balbi 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
38594ae9843SFelipe Balbi 			"twl6030_usb", twl);
38694ae9843SFelipe Balbi 	if (status < 0) {
38794ae9843SFelipe Balbi 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
38894ae9843SFelipe Balbi 			twl->irq1, status);
38994ae9843SFelipe Balbi 		device_remove_file(twl->dev, &dev_attr_vbus);
39094ae9843SFelipe Balbi 		return status;
39194ae9843SFelipe Balbi 	}
39294ae9843SFelipe Balbi 
39394ae9843SFelipe Balbi 	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
39494ae9843SFelipe Balbi 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
39594ae9843SFelipe Balbi 			"twl6030_usb", twl);
39694ae9843SFelipe Balbi 	if (status < 0) {
39794ae9843SFelipe Balbi 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
39894ae9843SFelipe Balbi 			twl->irq2, status);
39994ae9843SFelipe Balbi 		free_irq(twl->irq1, twl);
40094ae9843SFelipe Balbi 		device_remove_file(twl->dev, &dev_attr_vbus);
40194ae9843SFelipe Balbi 		return status;
40294ae9843SFelipe Balbi 	}
40394ae9843SFelipe Balbi 
40494ae9843SFelipe Balbi 	twl->asleep = 0;
40594ae9843SFelipe Balbi 	twl6030_enable_irq(twl);
406b6a619a8STony Lindgren 	schedule_delayed_work(&twl->get_status_work, HZ);
40794ae9843SFelipe Balbi 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
40894ae9843SFelipe Balbi 
40994ae9843SFelipe Balbi 	return 0;
41094ae9843SFelipe Balbi }
41194ae9843SFelipe Balbi 
41264dc9e2eSGreg Kroah-Hartman static int twl6030_usb_remove(struct platform_device *pdev)
41394ae9843SFelipe Balbi {
41494ae9843SFelipe Balbi 	struct twl6030_usb *twl = platform_get_drvdata(pdev);
41594ae9843SFelipe Balbi 
416b6a619a8STony Lindgren 	cancel_delayed_work(&twl->get_status_work);
41794ae9843SFelipe Balbi 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
41894ae9843SFelipe Balbi 		REG_INT_MSK_LINE_C);
41994ae9843SFelipe Balbi 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
42094ae9843SFelipe Balbi 			REG_INT_MSK_STS_C);
42194ae9843SFelipe Balbi 	free_irq(twl->irq1, twl);
42294ae9843SFelipe Balbi 	free_irq(twl->irq2, twl);
42394ae9843SFelipe Balbi 	regulator_put(twl->usb3v3);
42494ae9843SFelipe Balbi 	device_remove_file(twl->dev, &dev_attr_vbus);
42594ae9843SFelipe Balbi 	cancel_work_sync(&twl->set_vbus_work);
42694ae9843SFelipe Balbi 
42794ae9843SFelipe Balbi 	return 0;
42894ae9843SFelipe Balbi }
42994ae9843SFelipe Balbi 
43094ae9843SFelipe Balbi static const struct of_device_id twl6030_usb_id_table[] = {
43194ae9843SFelipe Balbi 	{ .compatible = "ti,twl6030-usb" },
43294ae9843SFelipe Balbi 	{}
43394ae9843SFelipe Balbi };
43494ae9843SFelipe Balbi MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
43594ae9843SFelipe Balbi 
43694ae9843SFelipe Balbi static struct platform_driver twl6030_usb_driver = {
43794ae9843SFelipe Balbi 	.probe		= twl6030_usb_probe,
43864dc9e2eSGreg Kroah-Hartman 	.remove		= twl6030_usb_remove,
43994ae9843SFelipe Balbi 	.driver		= {
44094ae9843SFelipe Balbi 		.name	= "twl6030_usb",
44194ae9843SFelipe Balbi 		.of_match_table = of_match_ptr(twl6030_usb_id_table),
44294ae9843SFelipe Balbi 	},
44394ae9843SFelipe Balbi };
44494ae9843SFelipe Balbi 
44594ae9843SFelipe Balbi static int __init twl6030_usb_init(void)
44694ae9843SFelipe Balbi {
44794ae9843SFelipe Balbi 	return platform_driver_register(&twl6030_usb_driver);
44894ae9843SFelipe Balbi }
44994ae9843SFelipe Balbi subsys_initcall(twl6030_usb_init);
45094ae9843SFelipe Balbi 
45194ae9843SFelipe Balbi static void __exit twl6030_usb_exit(void)
45294ae9843SFelipe Balbi {
45394ae9843SFelipe Balbi 	platform_driver_unregister(&twl6030_usb_driver);
45494ae9843SFelipe Balbi }
45594ae9843SFelipe Balbi module_exit(twl6030_usb_exit);
45694ae9843SFelipe Balbi 
45794ae9843SFelipe Balbi MODULE_ALIAS("platform:twl6030_usb");
45894ae9843SFelipe Balbi MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
45994ae9843SFelipe Balbi MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
46094ae9843SFelipe Balbi MODULE_LICENSE("GPL");
461