Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  1/*
  2 * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
  3 *
  4 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License as published by
  7 * the Free Software Foundation; either version 2 of the License, or
  8 * (at your option) any later version.
  9 *
 10 * Author: Hema HK <hemahk@ti.com>
 11 *
 12 * This program is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15 * GNU General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20 *
 21 */
 22
 23#include <linux/module.h>
 24#include <linux/init.h>
 25#include <linux/interrupt.h>
 26#include <linux/platform_device.h>
 27#include <linux/io.h>
 28#include <linux/usb/otg.h>
 29#include <linux/i2c/twl.h>
 30#include <linux/regulator/consumer.h>
 31#include <linux/err.h>
 32#include <linux/notifier.h>
 33#include <linux/slab.h>
 34#include <linux/delay.h>
 35
 36/* usb register definitions */
 37#define USB_VENDOR_ID_LSB		0x00
 38#define USB_VENDOR_ID_MSB		0x01
 39#define USB_PRODUCT_ID_LSB		0x02
 40#define USB_PRODUCT_ID_MSB		0x03
 41#define USB_VBUS_CTRL_SET		0x04
 42#define USB_VBUS_CTRL_CLR		0x05
 43#define USB_ID_CTRL_SET			0x06
 44#define USB_ID_CTRL_CLR			0x07
 45#define USB_VBUS_INT_SRC		0x08
 46#define USB_VBUS_INT_LATCH_SET		0x09
 47#define USB_VBUS_INT_LATCH_CLR		0x0A
 48#define USB_VBUS_INT_EN_LO_SET		0x0B
 49#define USB_VBUS_INT_EN_LO_CLR		0x0C
 50#define USB_VBUS_INT_EN_HI_SET		0x0D
 51#define USB_VBUS_INT_EN_HI_CLR		0x0E
 52#define USB_ID_INT_SRC			0x0F
 53#define USB_ID_INT_LATCH_SET		0x10
 54#define USB_ID_INT_LATCH_CLR		0x11
 55
 56#define USB_ID_INT_EN_LO_SET		0x12
 57#define USB_ID_INT_EN_LO_CLR		0x13
 58#define USB_ID_INT_EN_HI_SET		0x14
 59#define USB_ID_INT_EN_HI_CLR		0x15
 60#define USB_OTG_ADP_CTRL		0x16
 61#define USB_OTG_ADP_HIGH		0x17
 62#define USB_OTG_ADP_LOW			0x18
 63#define USB_OTG_ADP_RISE		0x19
 64#define USB_OTG_REVISION		0x1A
 65
 66/* to be moved to LDO */
 67#define TWL6030_MISC2			0xE5
 68#define TWL6030_CFG_LDO_PD2		0xF5
 69#define TWL6030_BACKUP_REG		0xFA
 70
 71#define STS_HW_CONDITIONS		0x21
 72
 73/* In module TWL6030_MODULE_PM_MASTER */
 74#define STS_HW_CONDITIONS		0x21
 75#define STS_USB_ID			BIT(2)
 76
 77/* In module TWL6030_MODULE_PM_RECEIVER */
 78#define VUSB_CFG_TRANS			0x71
 79#define VUSB_CFG_STATE			0x72
 80#define VUSB_CFG_VOLTAGE		0x73
 81
 82/* in module TWL6030_MODULE_MAIN_CHARGE */
 83
 84#define CHARGERUSB_CTRL1		0x8
 85
 86#define CONTROLLER_STAT1		0x03
 87#define	VBUS_DET			BIT(2)
 88
 89struct twl6030_usb {
 90	struct otg_transceiver	otg;
 91	struct device		*dev;
 92
 93	/* for vbus reporting with irqs disabled */
 94	spinlock_t		lock;
 95
 96	struct regulator		*usb3v3;
 97
 98	/* used to set vbus, in atomic path */
 99	struct work_struct	set_vbus_work;
100
101	int			irq1;
102	int			irq2;
103	u8			linkstat;
104	u8			asleep;
105	bool			irq_enabled;
106	bool			vbus_enable;
107	unsigned long		features;
108};
109
110#define xceiv_to_twl(x)		container_of((x), struct twl6030_usb, otg)
111
112/*-------------------------------------------------------------------------*/
113
114static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
115						u8 data, u8 address)
116{
117	int ret = 0;
118
119	ret = twl_i2c_write_u8(module, data, address);
120	if (ret < 0)
121		dev_err(twl->dev,
122			"Write[0x%x] Error %d\n", address, ret);
123	return ret;
124}
125
126static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
127{
128	u8 data, ret = 0;
129
130	ret = twl_i2c_read_u8(module, &data, address);
131	if (ret >= 0)
132		ret = data;
133	else
134		dev_err(twl->dev,
135			"readb[0x%x,0x%x] Error %d\n",
136					module, address, ret);
137	return ret;
138}
139
140/*-------------------------------------------------------------------------*/
141static int twl6030_set_phy_clk(struct otg_transceiver *x, int on)
142{
143	struct twl6030_usb *twl;
144	struct device *dev;
145	struct twl4030_usb_data *pdata;
146
147	twl = xceiv_to_twl(x);
148	dev  = twl->dev;
149	pdata = dev->platform_data;
150
151	pdata->phy_set_clock(twl->dev, on);
152
153	return 0;
154}
155
156static int twl6030_phy_init(struct otg_transceiver *x)
157{
158	struct twl6030_usb *twl;
159	struct device *dev;
160	struct twl4030_usb_data *pdata;
161
162	twl = xceiv_to_twl(x);
163	dev  = twl->dev;
164	pdata = dev->platform_data;
165
166	if (twl->linkstat == USB_EVENT_ID)
167		pdata->phy_power(twl->dev, 1, 1);
168	else
169		pdata->phy_power(twl->dev, 0, 1);
170
171	return 0;
172}
173
174static void twl6030_phy_shutdown(struct otg_transceiver *x)
175{
176	struct twl6030_usb *twl;
177	struct device *dev;
178	struct twl4030_usb_data *pdata;
179
180	twl = xceiv_to_twl(x);
181	dev  = twl->dev;
182	pdata = dev->platform_data;
183	pdata->phy_power(twl->dev, 0, 0);
184}
185
186static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend)
187{
188	struct twl6030_usb *twl = xceiv_to_twl(x);
189	struct device *dev = twl->dev;
190	struct twl4030_usb_data *pdata = dev->platform_data;
191
192	pdata->phy_suspend(dev, suspend);
193
194	return 0;
195}
196
197static int twl6030_start_srp(struct otg_transceiver *x)
198{
199	struct twl6030_usb *twl = xceiv_to_twl(x);
200
201	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
202	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
203
204	mdelay(100);
205	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);
206
207	return 0;
208}
209
210static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
211{
212	char *regulator_name;
213
214	if (twl->features & TWL6025_SUBCLASS)
215		regulator_name = "ldousb";
216	else
217		regulator_name = "vusb";
218
219	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
220	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
221
222	/* Program CFG_LDO_PD2 register and set VUSB bit */
223	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
224
225	/* Program MISC2 register and set bit VUSB_IN_VBAT */
226	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
227
228	twl->usb3v3 = regulator_get(twl->dev, regulator_name);
229	if (IS_ERR(twl->usb3v3))
230		return -ENODEV;
231
232	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
233	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
234
235	/*
236	 * Program the USB_ID_CTRL_SET register to enable GND drive
237	 * and the ID comparators
238	 */
239	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
240
241	return 0;
242}
243
244static ssize_t twl6030_usb_vbus_show(struct device *dev,
245			struct device_attribute *attr, char *buf)
246{
247	struct twl6030_usb *twl = dev_get_drvdata(dev);
248	unsigned long flags;
249	int ret = -EINVAL;
250
251	spin_lock_irqsave(&twl->lock, flags);
252
253	switch (twl->linkstat) {
254	case USB_EVENT_VBUS:
255	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
256	       break;
257	case USB_EVENT_ID:
258	       ret = snprintf(buf, PAGE_SIZE, "id\n");
259	       break;
260	case USB_EVENT_NONE:
261	       ret = snprintf(buf, PAGE_SIZE, "none\n");
262	       break;
263	default:
264	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
265	}
266	spin_unlock_irqrestore(&twl->lock, flags);
267
268	return ret;
269}
270static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
271
272static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
273{
274	struct twl6030_usb *twl = _twl;
275	int status;
276	u8 vbus_state, hw_state;
277
278	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
279
280	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
281						CONTROLLER_STAT1);
282	if (!(hw_state & STS_USB_ID)) {
283		if (vbus_state & VBUS_DET) {
284			regulator_enable(twl->usb3v3);
285			twl->asleep = 1;
286			status = USB_EVENT_VBUS;
287			twl->otg.default_a = false;
288			twl->otg.state = OTG_STATE_B_IDLE;
289			twl->linkstat = status;
290			twl->otg.last_event = status;
291			atomic_notifier_call_chain(&twl->otg.notifier,
292						status, twl->otg.gadget);
293		} else {
294			status = USB_EVENT_NONE;
295			twl->linkstat = status;
296			twl->otg.last_event = status;
297			atomic_notifier_call_chain(&twl->otg.notifier,
298						status, twl->otg.gadget);
299			if (twl->asleep) {
300				regulator_disable(twl->usb3v3);
301				twl->asleep = 0;
302			}
303		}
304	}
305	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
306
307	return IRQ_HANDLED;
308}
309
310static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
311{
312	struct twl6030_usb *twl = _twl;
313	int status = USB_EVENT_NONE;
314	u8 hw_state;
315
316	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
317
318	if (hw_state & STS_USB_ID) {
319
320		regulator_enable(twl->usb3v3);
321		twl->asleep = 1;
322		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
323		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
324								0x10);
325		status = USB_EVENT_ID;
326		twl->otg.default_a = true;
327		twl->otg.state = OTG_STATE_A_IDLE;
328		twl->linkstat = status;
329		twl->otg.last_event = status;
330		atomic_notifier_call_chain(&twl->otg.notifier, status,
331							twl->otg.gadget);
332	} else  {
333		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
334								0x10);
335		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
336								0x1);
337	}
338	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);
339
340	return IRQ_HANDLED;
341}
342
343static int twl6030_set_peripheral(struct otg_transceiver *x,
344		struct usb_gadget *gadget)
345{
346	struct twl6030_usb *twl;
347
348	if (!x)
349		return -ENODEV;
350
351	twl = xceiv_to_twl(x);
352	twl->otg.gadget = gadget;
353	if (!gadget)
354		twl->otg.state = OTG_STATE_UNDEFINED;
355
356	return 0;
357}
358
359static int twl6030_enable_irq(struct otg_transceiver *x)
360{
361	struct twl6030_usb *twl = xceiv_to_twl(x);
362
363	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
364	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
365	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
366
367	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
368				REG_INT_MSK_LINE_C);
369	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
370				REG_INT_MSK_STS_C);
371	twl6030_usb_irq(twl->irq2, twl);
372	twl6030_usbotg_irq(twl->irq1, twl);
373
374	return 0;
375}
376
377static void otg_set_vbus_work(struct work_struct *data)
378{
379	struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
380								set_vbus_work);
381
382	/*
383	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
384	 * register. This enables boost mode.
385	 */
386
387	if (twl->vbus_enable)
388		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
389							CHARGERUSB_CTRL1);
390	else
391		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
392							CHARGERUSB_CTRL1);
393}
394
395static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
396{
397	struct twl6030_usb *twl = xceiv_to_twl(x);
398
399	twl->vbus_enable = enabled;
400	schedule_work(&twl->set_vbus_work);
401
402	return 0;
403}
404
405static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host)
406{
407	struct twl6030_usb *twl;
408
409	if (!x)
410		return -ENODEV;
411
412	twl = xceiv_to_twl(x);
413	twl->otg.host = host;
414	if (!host)
415		twl->otg.state = OTG_STATE_UNDEFINED;
416	return 0;
417}
418
419static int __devinit twl6030_usb_probe(struct platform_device *pdev)
420{
421	struct twl6030_usb	*twl;
422	int			status, err;
423	struct twl4030_usb_data *pdata;
424	struct device *dev = &pdev->dev;
425	pdata = dev->platform_data;
426
427	twl = kzalloc(sizeof *twl, GFP_KERNEL);
428	if (!twl)
429		return -ENOMEM;
430
431	twl->dev		= &pdev->dev;
432	twl->irq1		= platform_get_irq(pdev, 0);
433	twl->irq2		= platform_get_irq(pdev, 1);
434	twl->features		= pdata->features;
435	twl->otg.dev		= twl->dev;
436	twl->otg.label		= "twl6030";
437	twl->otg.set_host	= twl6030_set_host;
438	twl->otg.set_peripheral	= twl6030_set_peripheral;
439	twl->otg.set_vbus	= twl6030_set_vbus;
440	twl->otg.init		= twl6030_phy_init;
441	twl->otg.shutdown	= twl6030_phy_shutdown;
442	twl->otg.set_suspend	= twl6030_phy_suspend;
443	twl->otg.start_srp	= twl6030_start_srp;
444
445	/* init spinlock for workqueue */
446	spin_lock_init(&twl->lock);
447
448	err = twl6030_usb_ldo_init(twl);
449	if (err) {
450		dev_err(&pdev->dev, "ldo init failed\n");
451		kfree(twl);
452		return err;
453	}
454	otg_set_transceiver(&twl->otg);
455
456	platform_set_drvdata(pdev, twl);
457	if (device_create_file(&pdev->dev, &dev_attr_vbus))
458		dev_warn(&pdev->dev, "could not create sysfs file\n");
459
460	ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
461
462	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
463
464	twl->irq_enabled = true;
465	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
466			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
467			"twl6030_usb", twl);
468	if (status < 0) {
469		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
470			twl->irq1, status);
471		device_remove_file(twl->dev, &dev_attr_vbus);
472		kfree(twl);
473		return status;
474	}
475
476	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
477			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
478			"twl6030_usb", twl);
479	if (status < 0) {
480		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
481			twl->irq2, status);
482		free_irq(twl->irq1, twl);
483		device_remove_file(twl->dev, &dev_attr_vbus);
484		kfree(twl);
485		return status;
486	}
487
488	twl->asleep = 0;
489	pdata->phy_init(dev);
490	twl6030_phy_suspend(&twl->otg, 0);
491	twl6030_enable_irq(&twl->otg);
492	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
493
494	return 0;
495}
496
497static int __exit twl6030_usb_remove(struct platform_device *pdev)
498{
499	struct twl6030_usb *twl = platform_get_drvdata(pdev);
500
501	struct twl4030_usb_data *pdata;
502	struct device *dev = &pdev->dev;
503	pdata = dev->platform_data;
504
505	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
506		REG_INT_MSK_LINE_C);
507	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
508			REG_INT_MSK_STS_C);
509	free_irq(twl->irq1, twl);
510	free_irq(twl->irq2, twl);
511	regulator_put(twl->usb3v3);
512	pdata->phy_exit(twl->dev);
513	device_remove_file(twl->dev, &dev_attr_vbus);
514	cancel_work_sync(&twl->set_vbus_work);
515	kfree(twl);
516
517	return 0;
518}
519
520static struct platform_driver twl6030_usb_driver = {
521	.probe		= twl6030_usb_probe,
522	.remove		= __exit_p(twl6030_usb_remove),
523	.driver		= {
524		.name	= "twl6030_usb",
525		.owner	= THIS_MODULE,
526	},
527};
528
529static int __init twl6030_usb_init(void)
530{
531	return platform_driver_register(&twl6030_usb_driver);
532}
533subsys_initcall(twl6030_usb_init);
534
535static void __exit twl6030_usb_exit(void)
536{
537	platform_driver_unregister(&twl6030_usb_driver);
538}
539module_exit(twl6030_usb_exit);
540
541MODULE_ALIAS("platform:twl6030_usb");
542MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
543MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
544MODULE_LICENSE("GPL");