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 - https://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 struct attribute *twl6030_attrs[] = { 200 &dev_attr_vbus.attr, 201 NULL, 202 }; 203 ATTRIBUTE_GROUPS(twl6030); 204 205 static irqreturn_t twl6030_usb_irq(int irq, void *_twl) 206 { 207 struct twl6030_usb *twl = _twl; 208 enum musb_vbus_id_status status = MUSB_UNKNOWN; 209 u8 vbus_state, hw_state; 210 int ret; 211 212 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 213 214 vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE, 215 CONTROLLER_STAT1); 216 if (!(hw_state & STS_USB_ID)) { 217 if (vbus_state & VBUS_DET) { 218 ret = regulator_enable(twl->usb3v3); 219 if (ret) 220 dev_err(twl->dev, "Failed to enable usb3v3\n"); 221 222 twl->asleep = 1; 223 status = MUSB_VBUS_VALID; 224 twl->linkstat = status; 225 ret = musb_mailbox(status); 226 if (ret) 227 twl->linkstat = MUSB_UNKNOWN; 228 } else { 229 if (twl->linkstat != MUSB_UNKNOWN) { 230 status = MUSB_VBUS_OFF; 231 twl->linkstat = status; 232 ret = musb_mailbox(status); 233 if (ret) 234 twl->linkstat = MUSB_UNKNOWN; 235 if (twl->asleep) { 236 regulator_disable(twl->usb3v3); 237 twl->asleep = 0; 238 } 239 } 240 } 241 } 242 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 243 244 return IRQ_HANDLED; 245 } 246 247 static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) 248 { 249 struct twl6030_usb *twl = _twl; 250 enum musb_vbus_id_status status = MUSB_UNKNOWN; 251 u8 hw_state; 252 int ret; 253 254 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 255 256 if (hw_state & STS_USB_ID) { 257 ret = regulator_enable(twl->usb3v3); 258 if (ret) 259 dev_err(twl->dev, "Failed to enable usb3v3\n"); 260 261 twl->asleep = 1; 262 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); 263 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); 264 status = MUSB_ID_GROUND; 265 twl->linkstat = status; 266 ret = musb_mailbox(status); 267 if (ret) 268 twl->linkstat = MUSB_UNKNOWN; 269 } else { 270 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); 271 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 272 } 273 twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR); 274 275 return IRQ_HANDLED; 276 } 277 278 static void twl6030_status_work(struct work_struct *work) 279 { 280 struct twl6030_usb *twl = container_of(work, struct twl6030_usb, 281 get_status_work.work); 282 283 twl6030_usb_irq(twl->irq2, twl); 284 twl6030_usbotg_irq(twl->irq1, twl); 285 } 286 287 static int twl6030_enable_irq(struct twl6030_usb *twl) 288 { 289 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 290 twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); 291 twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); 292 293 twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, 294 REG_INT_MSK_LINE_C); 295 twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, 296 REG_INT_MSK_STS_C); 297 298 return 0; 299 } 300 301 static void otg_set_vbus_work(struct work_struct *data) 302 { 303 struct twl6030_usb *twl = container_of(data, struct twl6030_usb, 304 set_vbus_work); 305 306 /* 307 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1 308 * register. This enables boost mode. 309 */ 310 311 if (twl->vbus_enable) 312 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x40, 313 CHARGERUSB_CTRL1); 314 else 315 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x00, 316 CHARGERUSB_CTRL1); 317 } 318 319 static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled) 320 { 321 struct twl6030_usb *twl = comparator_to_twl(comparator); 322 323 twl->vbus_enable = enabled; 324 schedule_work(&twl->set_vbus_work); 325 326 return 0; 327 } 328 329 static int twl6030_usb_probe(struct platform_device *pdev) 330 { 331 u32 ret; 332 struct twl6030_usb *twl; 333 int status, err; 334 struct device_node *np = pdev->dev.of_node; 335 struct device *dev = &pdev->dev; 336 337 if (!np) { 338 dev_err(dev, "no DT info\n"); 339 return -EINVAL; 340 } 341 342 twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL); 343 if (!twl) 344 return -ENOMEM; 345 346 twl->dev = &pdev->dev; 347 twl->irq1 = platform_get_irq(pdev, 0); 348 twl->irq2 = platform_get_irq(pdev, 1); 349 twl->linkstat = MUSB_UNKNOWN; 350 351 twl->comparator.set_vbus = twl6030_set_vbus; 352 twl->comparator.start_srp = twl6030_start_srp; 353 354 ret = omap_usb2_set_comparator(&twl->comparator); 355 if (ret == -ENODEV) { 356 dev_info(&pdev->dev, "phy not ready, deferring probe"); 357 return -EPROBE_DEFER; 358 } 359 360 /* init spinlock for workqueue */ 361 spin_lock_init(&twl->lock); 362 363 err = twl6030_usb_ldo_init(twl); 364 if (err) { 365 dev_err(&pdev->dev, "ldo init failed\n"); 366 return err; 367 } 368 369 platform_set_drvdata(pdev, twl); 370 371 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); 372 INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work); 373 374 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, 375 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, 376 "twl6030_usb", twl); 377 if (status < 0) { 378 dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", 379 twl->irq1, status); 380 goto err_put_regulator; 381 } 382 383 status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, 384 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, 385 "twl6030_usb", twl); 386 if (status < 0) { 387 dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", 388 twl->irq2, status); 389 goto err_free_irq1; 390 } 391 392 twl->asleep = 0; 393 twl6030_enable_irq(twl); 394 schedule_delayed_work(&twl->get_status_work, HZ); 395 dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); 396 397 return 0; 398 399 err_free_irq1: 400 free_irq(twl->irq1, twl); 401 err_put_regulator: 402 regulator_put(twl->usb3v3); 403 404 return status; 405 } 406 407 static int twl6030_usb_remove(struct platform_device *pdev) 408 { 409 struct twl6030_usb *twl = platform_get_drvdata(pdev); 410 411 cancel_delayed_work_sync(&twl->get_status_work); 412 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, 413 REG_INT_MSK_LINE_C); 414 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, 415 REG_INT_MSK_STS_C); 416 free_irq(twl->irq1, twl); 417 free_irq(twl->irq2, twl); 418 regulator_put(twl->usb3v3); 419 cancel_work_sync(&twl->set_vbus_work); 420 421 return 0; 422 } 423 424 static const struct of_device_id twl6030_usb_id_table[] = { 425 { .compatible = "ti,twl6030-usb" }, 426 {} 427 }; 428 MODULE_DEVICE_TABLE(of, twl6030_usb_id_table); 429 430 static struct platform_driver twl6030_usb_driver = { 431 .probe = twl6030_usb_probe, 432 .remove = twl6030_usb_remove, 433 .driver = { 434 .name = "twl6030_usb", 435 .of_match_table = of_match_ptr(twl6030_usb_id_table), 436 .dev_groups = twl6030_groups, 437 }, 438 }; 439 440 static int __init twl6030_usb_init(void) 441 { 442 return platform_driver_register(&twl6030_usb_driver); 443 } 444 subsys_initcall(twl6030_usb_init); 445 446 static void __exit twl6030_usb_exit(void) 447 { 448 platform_driver_unregister(&twl6030_usb_driver); 449 } 450 module_exit(twl6030_usb_exit); 451 452 MODULE_ALIAS("platform:twl6030_usb"); 453 MODULE_AUTHOR("Hema HK <hemahk@ti.com>"); 454 MODULE_DESCRIPTION("TWL6030 USB transceiver driver"); 455 MODULE_LICENSE("GPL"); 456