1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver. 4 * 5 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com 6 * 7 * Author: Hema HK <hemahk@ti.com> 8 */ 9 10 #include <linux/module.h> 11 #include <linux/init.h> 12 #include <linux/interrupt.h> 13 #include <linux/platform_device.h> 14 #include <linux/io.h> 15 #include <linux/usb/musb.h> 16 #include <linux/usb/phy_companion.h> 17 #include <linux/phy/omap_usb.h> 18 #include <linux/mfd/twl.h> 19 #include <linux/regulator/consumer.h> 20 #include <linux/err.h> 21 #include <linux/slab.h> 22 #include <linux/delay.h> 23 #include <linux/of.h> 24 25 /* usb register definitions */ 26 #define USB_VENDOR_ID_LSB 0x00 27 #define USB_VENDOR_ID_MSB 0x01 28 #define USB_PRODUCT_ID_LSB 0x02 29 #define USB_PRODUCT_ID_MSB 0x03 30 #define USB_VBUS_CTRL_SET 0x04 31 #define USB_VBUS_CTRL_CLR 0x05 32 #define USB_ID_CTRL_SET 0x06 33 #define USB_ID_CTRL_CLR 0x07 34 #define USB_VBUS_INT_SRC 0x08 35 #define USB_VBUS_INT_LATCH_SET 0x09 36 #define USB_VBUS_INT_LATCH_CLR 0x0A 37 #define USB_VBUS_INT_EN_LO_SET 0x0B 38 #define USB_VBUS_INT_EN_LO_CLR 0x0C 39 #define USB_VBUS_INT_EN_HI_SET 0x0D 40 #define USB_VBUS_INT_EN_HI_CLR 0x0E 41 #define USB_ID_INT_SRC 0x0F 42 #define USB_ID_INT_LATCH_SET 0x10 43 #define USB_ID_INT_LATCH_CLR 0x11 44 45 #define USB_ID_INT_EN_LO_SET 0x12 46 #define USB_ID_INT_EN_LO_CLR 0x13 47 #define USB_ID_INT_EN_HI_SET 0x14 48 #define USB_ID_INT_EN_HI_CLR 0x15 49 #define USB_OTG_ADP_CTRL 0x16 50 #define USB_OTG_ADP_HIGH 0x17 51 #define USB_OTG_ADP_LOW 0x18 52 #define USB_OTG_ADP_RISE 0x19 53 #define USB_OTG_REVISION 0x1A 54 55 /* to be moved to LDO */ 56 #define TWL6030_MISC2 0xE5 57 #define TWL6030_CFG_LDO_PD2 0xF5 58 #define TWL6030_BACKUP_REG 0xFA 59 60 #define STS_HW_CONDITIONS 0x21 61 62 /* In module TWL6030_MODULE_PM_MASTER */ 63 #define STS_HW_CONDITIONS 0x21 64 #define STS_USB_ID BIT(2) 65 66 /* In module TWL6030_MODULE_PM_RECEIVER */ 67 #define VUSB_CFG_TRANS 0x71 68 #define VUSB_CFG_STATE 0x72 69 #define VUSB_CFG_VOLTAGE 0x73 70 71 /* in module TWL6030_MODULE_MAIN_CHARGE */ 72 73 #define CHARGERUSB_CTRL1 0x8 74 75 #define CONTROLLER_STAT1 0x03 76 #define VBUS_DET BIT(2) 77 78 struct twl6030_usb { 79 struct phy_companion comparator; 80 struct device *dev; 81 82 /* for vbus reporting with irqs disabled */ 83 spinlock_t lock; 84 85 struct regulator *usb3v3; 86 87 /* used to check initial cable status after probe */ 88 struct delayed_work get_status_work; 89 90 /* used to set vbus, in atomic path */ 91 struct work_struct set_vbus_work; 92 93 int irq1; 94 int irq2; 95 enum musb_vbus_id_status linkstat; 96 u8 asleep; 97 bool vbus_enable; 98 }; 99 100 #define comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator) 101 102 /*-------------------------------------------------------------------------*/ 103 104 static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module, 105 u8 data, u8 address) 106 { 107 int ret = 0; 108 109 ret = twl_i2c_write_u8(module, data, address); 110 if (ret < 0) 111 dev_err(twl->dev, 112 "Write[0x%x] Error %d\n", address, ret); 113 return ret; 114 } 115 116 static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) 117 { 118 u8 data; 119 int ret; 120 121 ret = twl_i2c_read_u8(module, &data, address); 122 if (ret >= 0) 123 ret = data; 124 else 125 dev_err(twl->dev, 126 "readb[0x%x,0x%x] Error %d\n", 127 module, address, ret); 128 return ret; 129 } 130 131 static int twl6030_start_srp(struct phy_companion *comparator) 132 { 133 struct twl6030_usb *twl = comparator_to_twl(comparator); 134 135 twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); 136 twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); 137 138 mdelay(100); 139 twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR); 140 141 return 0; 142 } 143 144 static int twl6030_usb_ldo_init(struct twl6030_usb *twl) 145 { 146 /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ 147 twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_BACKUP_REG); 148 149 /* Program CFG_LDO_PD2 register and set VUSB bit */ 150 twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_CFG_LDO_PD2); 151 152 /* Program MISC2 register and set bit VUSB_IN_VBAT */ 153 twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2); 154 155 twl->usb3v3 = regulator_get(twl->dev, "usb"); 156 if (IS_ERR(twl->usb3v3)) 157 return -ENODEV; 158 159 /* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */ 160 twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET); 161 162 /* 163 * Program the USB_ID_CTRL_SET register to enable GND drive 164 * and the ID comparators 165 */ 166 twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET); 167 168 return 0; 169 } 170 171 static ssize_t vbus_show(struct device *dev, 172 struct device_attribute *attr, char *buf) 173 { 174 struct twl6030_usb *twl = dev_get_drvdata(dev); 175 unsigned long flags; 176 int ret = -EINVAL; 177 178 spin_lock_irqsave(&twl->lock, flags); 179 180 switch (twl->linkstat) { 181 case MUSB_VBUS_VALID: 182 ret = snprintf(buf, PAGE_SIZE, "vbus\n"); 183 break; 184 case MUSB_ID_GROUND: 185 ret = snprintf(buf, PAGE_SIZE, "id\n"); 186 break; 187 case MUSB_VBUS_OFF: 188 ret = snprintf(buf, PAGE_SIZE, "none\n"); 189 break; 190 default: 191 ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n"); 192 } 193 spin_unlock_irqrestore(&twl->lock, flags); 194 195 return ret; 196 } 197 static DEVICE_ATTR_RO(vbus); 198 199 static irqreturn_t twl6030_usb_irq(int irq, void *_twl) 200 { 201 struct twl6030_usb *twl = _twl; 202 enum musb_vbus_id_status status = MUSB_UNKNOWN; 203 u8 vbus_state, hw_state; 204 int ret; 205 206 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 207 208 vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE, 209 CONTROLLER_STAT1); 210 if (!(hw_state & STS_USB_ID)) { 211 if (vbus_state & VBUS_DET) { 212 ret = regulator_enable(twl->usb3v3); 213 if (ret) 214 dev_err(twl->dev, "Failed to enable usb3v3\n"); 215 216 twl->asleep = 1; 217 status = MUSB_VBUS_VALID; 218 twl->linkstat = status; 219 ret = musb_mailbox(status); 220 if (ret) 221 twl->linkstat = MUSB_UNKNOWN; 222 } else { 223 if (twl->linkstat != MUSB_UNKNOWN) { 224 status = MUSB_VBUS_OFF; 225 twl->linkstat = status; 226 ret = musb_mailbox(status); 227 if (ret) 228 twl->linkstat = MUSB_UNKNOWN; 229 if (twl->asleep) { 230 regulator_disable(twl->usb3v3); 231 twl->asleep = 0; 232 } 233 } 234 } 235 } 236 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 237 238 return IRQ_HANDLED; 239 } 240 241 static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) 242 { 243 struct twl6030_usb *twl = _twl; 244 enum musb_vbus_id_status status = MUSB_UNKNOWN; 245 u8 hw_state; 246 int ret; 247 248 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 249 250 if (hw_state & STS_USB_ID) { 251 ret = regulator_enable(twl->usb3v3); 252 if (ret) 253 dev_err(twl->dev, "Failed to enable usb3v3\n"); 254 255 twl->asleep = 1; 256 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); 257 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); 258 status = MUSB_ID_GROUND; 259 twl->linkstat = status; 260 ret = musb_mailbox(status); 261 if (ret) 262 twl->linkstat = MUSB_UNKNOWN; 263 } else { 264 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); 265 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 266 } 267 twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR); 268 269 return IRQ_HANDLED; 270 } 271 272 static void twl6030_status_work(struct work_struct *work) 273 { 274 struct twl6030_usb *twl = container_of(work, struct twl6030_usb, 275 get_status_work.work); 276 277 twl6030_usb_irq(twl->irq2, twl); 278 twl6030_usbotg_irq(twl->irq1, twl); 279 } 280 281 static int twl6030_enable_irq(struct twl6030_usb *twl) 282 { 283 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 284 twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); 285 twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); 286 287 twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, 288 REG_INT_MSK_LINE_C); 289 twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, 290 REG_INT_MSK_STS_C); 291 292 return 0; 293 } 294 295 static void otg_set_vbus_work(struct work_struct *data) 296 { 297 struct twl6030_usb *twl = container_of(data, struct twl6030_usb, 298 set_vbus_work); 299 300 /* 301 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1 302 * register. This enables boost mode. 303 */ 304 305 if (twl->vbus_enable) 306 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x40, 307 CHARGERUSB_CTRL1); 308 else 309 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x00, 310 CHARGERUSB_CTRL1); 311 } 312 313 static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled) 314 { 315 struct twl6030_usb *twl = comparator_to_twl(comparator); 316 317 twl->vbus_enable = enabled; 318 schedule_work(&twl->set_vbus_work); 319 320 return 0; 321 } 322 323 static int twl6030_usb_probe(struct platform_device *pdev) 324 { 325 u32 ret; 326 struct twl6030_usb *twl; 327 int status, err; 328 struct device_node *np = pdev->dev.of_node; 329 struct device *dev = &pdev->dev; 330 331 if (!np) { 332 dev_err(dev, "no DT info\n"); 333 return -EINVAL; 334 } 335 336 twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL); 337 if (!twl) 338 return -ENOMEM; 339 340 twl->dev = &pdev->dev; 341 twl->irq1 = platform_get_irq(pdev, 0); 342 twl->irq2 = platform_get_irq(pdev, 1); 343 twl->linkstat = MUSB_UNKNOWN; 344 345 twl->comparator.set_vbus = twl6030_set_vbus; 346 twl->comparator.start_srp = twl6030_start_srp; 347 348 ret = omap_usb2_set_comparator(&twl->comparator); 349 if (ret == -ENODEV) { 350 dev_info(&pdev->dev, "phy not ready, deferring probe"); 351 return -EPROBE_DEFER; 352 } 353 354 /* init spinlock for workqueue */ 355 spin_lock_init(&twl->lock); 356 357 err = twl6030_usb_ldo_init(twl); 358 if (err) { 359 dev_err(&pdev->dev, "ldo init failed\n"); 360 return err; 361 } 362 363 platform_set_drvdata(pdev, twl); 364 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 365 dev_warn(&pdev->dev, "could not create sysfs file\n"); 366 367 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); 368 INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work); 369 370 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, 371 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, 372 "twl6030_usb", twl); 373 if (status < 0) { 374 dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", 375 twl->irq1, status); 376 device_remove_file(twl->dev, &dev_attr_vbus); 377 return status; 378 } 379 380 status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, 381 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, 382 "twl6030_usb", twl); 383 if (status < 0) { 384 dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", 385 twl->irq2, status); 386 free_irq(twl->irq1, twl); 387 device_remove_file(twl->dev, &dev_attr_vbus); 388 return status; 389 } 390 391 twl->asleep = 0; 392 twl6030_enable_irq(twl); 393 schedule_delayed_work(&twl->get_status_work, HZ); 394 dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); 395 396 return 0; 397 } 398 399 static int twl6030_usb_remove(struct platform_device *pdev) 400 { 401 struct twl6030_usb *twl = platform_get_drvdata(pdev); 402 403 cancel_delayed_work(&twl->get_status_work); 404 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, 405 REG_INT_MSK_LINE_C); 406 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, 407 REG_INT_MSK_STS_C); 408 free_irq(twl->irq1, twl); 409 free_irq(twl->irq2, twl); 410 regulator_put(twl->usb3v3); 411 device_remove_file(twl->dev, &dev_attr_vbus); 412 cancel_work_sync(&twl->set_vbus_work); 413 414 return 0; 415 } 416 417 static const struct of_device_id twl6030_usb_id_table[] = { 418 { .compatible = "ti,twl6030-usb" }, 419 {} 420 }; 421 MODULE_DEVICE_TABLE(of, twl6030_usb_id_table); 422 423 static struct platform_driver twl6030_usb_driver = { 424 .probe = twl6030_usb_probe, 425 .remove = twl6030_usb_remove, 426 .driver = { 427 .name = "twl6030_usb", 428 .of_match_table = of_match_ptr(twl6030_usb_id_table), 429 }, 430 }; 431 432 static int __init twl6030_usb_init(void) 433 { 434 return platform_driver_register(&twl6030_usb_driver); 435 } 436 subsys_initcall(twl6030_usb_init); 437 438 static void __exit twl6030_usb_exit(void) 439 { 440 platform_driver_unregister(&twl6030_usb_driver); 441 } 442 module_exit(twl6030_usb_exit); 443 444 MODULE_ALIAS("platform:twl6030_usb"); 445 MODULE_AUTHOR("Hema HK <hemahk@ti.com>"); 446 MODULE_DESCRIPTION("TWL6030 USB transceiver driver"); 447 MODULE_LICENSE("GPL"); 448