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