Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
0004  *
0005  * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com
0006  *
0007  * Author: Hema HK <hemahk@ti.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/io.h>
0015 #include <linux/usb/musb.h>
0016 #include <linux/usb/phy_companion.h>
0017 #include <linux/phy/omap_usb.h>
0018 #include <linux/mfd/twl.h>
0019 #include <linux/regulator/consumer.h>
0020 #include <linux/err.h>
0021 #include <linux/slab.h>
0022 #include <linux/delay.h>
0023 #include <linux/of.h>
0024 
0025 /* usb register definitions */
0026 #define USB_VENDOR_ID_LSB       0x00
0027 #define USB_VENDOR_ID_MSB       0x01
0028 #define USB_PRODUCT_ID_LSB      0x02
0029 #define USB_PRODUCT_ID_MSB      0x03
0030 #define USB_VBUS_CTRL_SET       0x04
0031 #define USB_VBUS_CTRL_CLR       0x05
0032 #define USB_ID_CTRL_SET         0x06
0033 #define USB_ID_CTRL_CLR         0x07
0034 #define USB_VBUS_INT_SRC        0x08
0035 #define USB_VBUS_INT_LATCH_SET      0x09
0036 #define USB_VBUS_INT_LATCH_CLR      0x0A
0037 #define USB_VBUS_INT_EN_LO_SET      0x0B
0038 #define USB_VBUS_INT_EN_LO_CLR      0x0C
0039 #define USB_VBUS_INT_EN_HI_SET      0x0D
0040 #define USB_VBUS_INT_EN_HI_CLR      0x0E
0041 #define USB_ID_INT_SRC          0x0F
0042 #define USB_ID_INT_LATCH_SET        0x10
0043 #define USB_ID_INT_LATCH_CLR        0x11
0044 
0045 #define USB_ID_INT_EN_LO_SET        0x12
0046 #define USB_ID_INT_EN_LO_CLR        0x13
0047 #define USB_ID_INT_EN_HI_SET        0x14
0048 #define USB_ID_INT_EN_HI_CLR        0x15
0049 #define USB_OTG_ADP_CTRL        0x16
0050 #define USB_OTG_ADP_HIGH        0x17
0051 #define USB_OTG_ADP_LOW         0x18
0052 #define USB_OTG_ADP_RISE        0x19
0053 #define USB_OTG_REVISION        0x1A
0054 
0055 /* to be moved to LDO */
0056 #define TWL6030_MISC2           0xE5
0057 #define TWL6030_CFG_LDO_PD2     0xF5
0058 #define TWL6030_BACKUP_REG      0xFA
0059 
0060 #define STS_HW_CONDITIONS       0x21
0061 
0062 /* In module TWL6030_MODULE_PM_MASTER */
0063 #define STS_HW_CONDITIONS       0x21
0064 #define STS_USB_ID          BIT(2)
0065 
0066 /* In module TWL6030_MODULE_PM_RECEIVER */
0067 #define VUSB_CFG_TRANS          0x71
0068 #define VUSB_CFG_STATE          0x72
0069 #define VUSB_CFG_VOLTAGE        0x73
0070 
0071 /* in module TWL6030_MODULE_MAIN_CHARGE */
0072 
0073 #define CHARGERUSB_CTRL1        0x8
0074 
0075 #define CONTROLLER_STAT1        0x03
0076 #define VBUS_DET            BIT(2)
0077 
0078 struct twl6030_usb {
0079     struct phy_companion    comparator;
0080     struct device       *dev;
0081 
0082     /* for vbus reporting with irqs disabled */
0083     spinlock_t      lock;
0084 
0085     struct regulator        *usb3v3;
0086 
0087     /* used to check initial cable status after probe */
0088     struct delayed_work get_status_work;
0089 
0090     /* used to set vbus, in atomic path */
0091     struct work_struct  set_vbus_work;
0092 
0093     int         irq1;
0094     int         irq2;
0095     enum musb_vbus_id_status linkstat;
0096     u8          asleep;
0097     bool            vbus_enable;
0098 };
0099 
0100 #define comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
0101 
0102 /*-------------------------------------------------------------------------*/
0103 
0104 static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
0105                         u8 data, u8 address)
0106 {
0107     int ret = 0;
0108 
0109     ret = twl_i2c_write_u8(module, data, address);
0110     if (ret < 0)
0111         dev_err(twl->dev,
0112             "Write[0x%x] Error %d\n", address, ret);
0113     return ret;
0114 }
0115 
0116 static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
0117 {
0118     u8 data;
0119     int ret;
0120 
0121     ret = twl_i2c_read_u8(module, &data, address);
0122     if (ret >= 0)
0123         ret = data;
0124     else
0125         dev_err(twl->dev,
0126             "readb[0x%x,0x%x] Error %d\n",
0127                     module, address, ret);
0128     return ret;
0129 }
0130 
0131 static int twl6030_start_srp(struct phy_companion *comparator)
0132 {
0133     struct twl6030_usb *twl = comparator_to_twl(comparator);
0134 
0135     twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
0136     twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
0137 
0138     mdelay(100);
0139     twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);
0140 
0141     return 0;
0142 }
0143 
0144 static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
0145 {
0146     /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
0147     twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_BACKUP_REG);
0148 
0149     /* Program CFG_LDO_PD2 register and set VUSB bit */
0150     twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_CFG_LDO_PD2);
0151 
0152     /* Program MISC2 register and set bit VUSB_IN_VBAT */
0153     twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2);
0154 
0155     twl->usb3v3 = regulator_get(twl->dev, "usb");
0156     if (IS_ERR(twl->usb3v3))
0157         return -ENODEV;
0158 
0159     /* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
0160     twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
0161 
0162     /*
0163      * Program the USB_ID_CTRL_SET register to enable GND drive
0164      * and the ID comparators
0165      */
0166     twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
0167 
0168     return 0;
0169 }
0170 
0171 static ssize_t vbus_show(struct device *dev,
0172             struct device_attribute *attr, char *buf)
0173 {
0174     struct twl6030_usb *twl = dev_get_drvdata(dev);
0175     unsigned long flags;
0176     int ret = -EINVAL;
0177 
0178     spin_lock_irqsave(&twl->lock, flags);
0179 
0180     switch (twl->linkstat) {
0181     case MUSB_VBUS_VALID:
0182            ret = snprintf(buf, PAGE_SIZE, "vbus\n");
0183            break;
0184     case MUSB_ID_GROUND:
0185            ret = snprintf(buf, PAGE_SIZE, "id\n");
0186            break;
0187     case MUSB_VBUS_OFF:
0188            ret = snprintf(buf, PAGE_SIZE, "none\n");
0189            break;
0190     default:
0191            ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
0192     }
0193     spin_unlock_irqrestore(&twl->lock, flags);
0194 
0195     return ret;
0196 }
0197 static DEVICE_ATTR_RO(vbus);
0198 
0199 static struct attribute *twl6030_attrs[] = {
0200     &dev_attr_vbus.attr,
0201     NULL,
0202 };
0203 ATTRIBUTE_GROUPS(twl6030);
0204 
0205 static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
0206 {
0207     struct twl6030_usb *twl = _twl;
0208     enum musb_vbus_id_status status = MUSB_UNKNOWN;
0209     u8 vbus_state, hw_state;
0210     int ret;
0211 
0212     hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
0213 
0214     vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
0215                         CONTROLLER_STAT1);
0216     if (!(hw_state & STS_USB_ID)) {
0217         if (vbus_state & VBUS_DET) {
0218             ret = regulator_enable(twl->usb3v3);
0219             if (ret)
0220                 dev_err(twl->dev, "Failed to enable usb3v3\n");
0221 
0222             twl->asleep = 1;
0223             status = MUSB_VBUS_VALID;
0224             twl->linkstat = status;
0225             ret = musb_mailbox(status);
0226             if (ret)
0227                 twl->linkstat = MUSB_UNKNOWN;
0228         } else {
0229             if (twl->linkstat != MUSB_UNKNOWN) {
0230                 status = MUSB_VBUS_OFF;
0231                 twl->linkstat = status;
0232                 ret = musb_mailbox(status);
0233                 if (ret)
0234                     twl->linkstat = MUSB_UNKNOWN;
0235                 if (twl->asleep) {
0236                     regulator_disable(twl->usb3v3);
0237                     twl->asleep = 0;
0238                 }
0239             }
0240         }
0241     }
0242     sysfs_notify(&twl->dev->kobj, NULL, "vbus");
0243 
0244     return IRQ_HANDLED;
0245 }
0246 
0247 static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
0248 {
0249     struct twl6030_usb *twl = _twl;
0250     enum musb_vbus_id_status status = MUSB_UNKNOWN;
0251     u8 hw_state;
0252     int ret;
0253 
0254     hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
0255 
0256     if (hw_state & STS_USB_ID) {
0257         ret = regulator_enable(twl->usb3v3);
0258         if (ret)
0259             dev_err(twl->dev, "Failed to enable usb3v3\n");
0260 
0261         twl->asleep = 1;
0262         twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
0263         twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
0264         status = MUSB_ID_GROUND;
0265         twl->linkstat = status;
0266         ret = musb_mailbox(status);
0267         if (ret)
0268             twl->linkstat = MUSB_UNKNOWN;
0269     } else  {
0270         twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
0271         twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
0272     }
0273     twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
0274 
0275     return IRQ_HANDLED;
0276 }
0277 
0278 static void twl6030_status_work(struct work_struct *work)
0279 {
0280     struct twl6030_usb *twl = container_of(work, struct twl6030_usb,
0281                            get_status_work.work);
0282 
0283     twl6030_usb_irq(twl->irq2, twl);
0284     twl6030_usbotg_irq(twl->irq1, twl);
0285 }
0286 
0287 static int twl6030_enable_irq(struct twl6030_usb *twl)
0288 {
0289     twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
0290     twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
0291     twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
0292 
0293     twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
0294                 REG_INT_MSK_LINE_C);
0295     twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
0296                 REG_INT_MSK_STS_C);
0297 
0298     return 0;
0299 }
0300 
0301 static void otg_set_vbus_work(struct work_struct *data)
0302 {
0303     struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
0304                                 set_vbus_work);
0305 
0306     /*
0307      * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
0308      * register. This enables boost mode.
0309      */
0310 
0311     if (twl->vbus_enable)
0312         twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x40,
0313                             CHARGERUSB_CTRL1);
0314     else
0315         twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x00,
0316                             CHARGERUSB_CTRL1);
0317 }
0318 
0319 static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
0320 {
0321     struct twl6030_usb *twl = comparator_to_twl(comparator);
0322 
0323     twl->vbus_enable = enabled;
0324     schedule_work(&twl->set_vbus_work);
0325 
0326     return 0;
0327 }
0328 
0329 static int twl6030_usb_probe(struct platform_device *pdev)
0330 {
0331     u32 ret;
0332     struct twl6030_usb  *twl;
0333     int         status, err;
0334     struct device_node  *np = pdev->dev.of_node;
0335     struct device       *dev = &pdev->dev;
0336 
0337     if (!np) {
0338         dev_err(dev, "no DT info\n");
0339         return -EINVAL;
0340     }
0341 
0342     twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL);
0343     if (!twl)
0344         return -ENOMEM;
0345 
0346     twl->dev        = &pdev->dev;
0347     twl->irq1       = platform_get_irq(pdev, 0);
0348     twl->irq2       = platform_get_irq(pdev, 1);
0349     twl->linkstat       = MUSB_UNKNOWN;
0350 
0351     if (twl->irq1 < 0)
0352         return twl->irq1;
0353     if (twl->irq2 < 0)
0354         return twl->irq2;
0355 
0356     twl->comparator.set_vbus    = twl6030_set_vbus;
0357     twl->comparator.start_srp   = twl6030_start_srp;
0358 
0359     ret = omap_usb2_set_comparator(&twl->comparator);
0360     if (ret == -ENODEV) {
0361         dev_info(&pdev->dev, "phy not ready, deferring probe");
0362         return -EPROBE_DEFER;
0363     }
0364 
0365     /* init spinlock for workqueue */
0366     spin_lock_init(&twl->lock);
0367 
0368     err = twl6030_usb_ldo_init(twl);
0369     if (err) {
0370         dev_err(&pdev->dev, "ldo init failed\n");
0371         return err;
0372     }
0373 
0374     platform_set_drvdata(pdev, twl);
0375 
0376     INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
0377     INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work);
0378 
0379     status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
0380             IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0381             "twl6030_usb", twl);
0382     if (status < 0) {
0383         dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
0384             twl->irq1, status);
0385         goto err_put_regulator;
0386     }
0387 
0388     status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
0389             IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0390             "twl6030_usb", twl);
0391     if (status < 0) {
0392         dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
0393             twl->irq2, status);
0394         goto err_free_irq1;
0395     }
0396 
0397     twl->asleep = 0;
0398     twl6030_enable_irq(twl);
0399     schedule_delayed_work(&twl->get_status_work, HZ);
0400     dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
0401 
0402     return 0;
0403 
0404 err_free_irq1:
0405     free_irq(twl->irq1, twl);
0406 err_put_regulator:
0407     regulator_put(twl->usb3v3);
0408 
0409     return status;
0410 }
0411 
0412 static int twl6030_usb_remove(struct platform_device *pdev)
0413 {
0414     struct twl6030_usb *twl = platform_get_drvdata(pdev);
0415 
0416     cancel_delayed_work_sync(&twl->get_status_work);
0417     twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
0418         REG_INT_MSK_LINE_C);
0419     twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
0420             REG_INT_MSK_STS_C);
0421     free_irq(twl->irq1, twl);
0422     free_irq(twl->irq2, twl);
0423     regulator_put(twl->usb3v3);
0424     cancel_work_sync(&twl->set_vbus_work);
0425 
0426     return 0;
0427 }
0428 
0429 static const struct of_device_id twl6030_usb_id_table[] = {
0430     { .compatible = "ti,twl6030-usb" },
0431     {}
0432 };
0433 MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
0434 
0435 static struct platform_driver twl6030_usb_driver = {
0436     .probe      = twl6030_usb_probe,
0437     .remove     = twl6030_usb_remove,
0438     .driver     = {
0439         .name   = "twl6030_usb",
0440         .of_match_table = of_match_ptr(twl6030_usb_id_table),
0441         .dev_groups = twl6030_groups,
0442     },
0443 };
0444 
0445 static int __init twl6030_usb_init(void)
0446 {
0447     return platform_driver_register(&twl6030_usb_driver);
0448 }
0449 subsys_initcall(twl6030_usb_init);
0450 
0451 static void __exit twl6030_usb_exit(void)
0452 {
0453     platform_driver_unregister(&twl6030_usb_driver);
0454 }
0455 module_exit(twl6030_usb_exit);
0456 
0457 MODULE_ALIAS("platform:twl6030_usb");
0458 MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
0459 MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
0460 MODULE_LICENSE("GPL");