root/drivers/phy/ti/phy-tusb1210.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tusb1210_power_on
  2. tusb1210_power_off
  3. tusb1210_set_mode
  4. tusb1210_probe
  5. tusb1210_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /**
   3  * tusb1210.c - TUSB1210 USB ULPI PHY driver
   4  *
   5  * Copyright (C) 2015 Intel Corporation
   6  *
   7  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
   8  */
   9 #include <linux/module.h>
  10 #include <linux/ulpi/driver.h>
  11 #include <linux/ulpi/regs.h>
  12 #include <linux/gpio/consumer.h>
  13 #include <linux/phy/ulpi_phy.h>
  14 
  15 #define TUSB1210_VENDOR_SPECIFIC2               0x80
  16 #define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT   0
  17 #define TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT  4
  18 #define TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT      6
  19 
  20 struct tusb1210 {
  21         struct ulpi *ulpi;
  22         struct phy *phy;
  23         struct gpio_desc *gpio_reset;
  24         struct gpio_desc *gpio_cs;
  25         u8 vendor_specific2;
  26 };
  27 
  28 static int tusb1210_power_on(struct phy *phy)
  29 {
  30         struct tusb1210 *tusb = phy_get_drvdata(phy);
  31 
  32         gpiod_set_value_cansleep(tusb->gpio_reset, 1);
  33         gpiod_set_value_cansleep(tusb->gpio_cs, 1);
  34 
  35         /* Restore the optional eye diagram optimization value */
  36         if (tusb->vendor_specific2)
  37                 ulpi_write(tusb->ulpi, TUSB1210_VENDOR_SPECIFIC2,
  38                            tusb->vendor_specific2);
  39 
  40         return 0;
  41 }
  42 
  43 static int tusb1210_power_off(struct phy *phy)
  44 {
  45         struct tusb1210 *tusb = phy_get_drvdata(phy);
  46 
  47         gpiod_set_value_cansleep(tusb->gpio_reset, 0);
  48         gpiod_set_value_cansleep(tusb->gpio_cs, 0);
  49 
  50         return 0;
  51 }
  52 
  53 static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode)
  54 {
  55         struct tusb1210 *tusb = phy_get_drvdata(phy);
  56         int ret;
  57 
  58         ret = ulpi_read(tusb->ulpi, ULPI_OTG_CTRL);
  59         if (ret < 0)
  60                 return ret;
  61 
  62         switch (mode) {
  63         case PHY_MODE_USB_HOST:
  64                 ret |= (ULPI_OTG_CTRL_DRVVBUS_EXT
  65                         | ULPI_OTG_CTRL_ID_PULLUP
  66                         | ULPI_OTG_CTRL_DP_PULLDOWN
  67                         | ULPI_OTG_CTRL_DM_PULLDOWN);
  68                 ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
  69                 ret |= ULPI_OTG_CTRL_DRVVBUS;
  70                 break;
  71         case PHY_MODE_USB_DEVICE:
  72                 ret &= ~(ULPI_OTG_CTRL_DRVVBUS
  73                          | ULPI_OTG_CTRL_DP_PULLDOWN
  74                          | ULPI_OTG_CTRL_DM_PULLDOWN);
  75                 ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
  76                 ret &= ~ULPI_OTG_CTRL_DRVVBUS_EXT;
  77                 break;
  78         default:
  79                 /* nothing */
  80                 return 0;
  81         }
  82 
  83         return ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
  84 }
  85 
  86 static const struct phy_ops phy_ops = {
  87         .power_on = tusb1210_power_on,
  88         .power_off = tusb1210_power_off,
  89         .set_mode = tusb1210_set_mode,
  90         .owner = THIS_MODULE,
  91 };
  92 
  93 static int tusb1210_probe(struct ulpi *ulpi)
  94 {
  95         struct tusb1210 *tusb;
  96         u8 val, reg;
  97 
  98         tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
  99         if (!tusb)
 100                 return -ENOMEM;
 101 
 102         tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
 103                                                    GPIOD_OUT_LOW);
 104         if (IS_ERR(tusb->gpio_reset))
 105                 return PTR_ERR(tusb->gpio_reset);
 106 
 107         gpiod_set_value_cansleep(tusb->gpio_reset, 1);
 108 
 109         tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
 110                                                 GPIOD_OUT_LOW);
 111         if (IS_ERR(tusb->gpio_cs))
 112                 return PTR_ERR(tusb->gpio_cs);
 113 
 114         gpiod_set_value_cansleep(tusb->gpio_cs, 1);
 115 
 116         /*
 117          * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye
 118          * diagram optimization and DP/DM swap.
 119          */
 120 
 121         /* High speed output drive strength configuration */
 122         device_property_read_u8(&ulpi->dev, "ihstx", &val);
 123         reg = val << TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT;
 124 
 125         /* High speed output impedance configuration */
 126         device_property_read_u8(&ulpi->dev, "zhsdrv", &val);
 127         reg |= val << TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT;
 128 
 129         /* DP/DM swap control */
 130         device_property_read_u8(&ulpi->dev, "datapolarity", &val);
 131         reg |= val << TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT;
 132 
 133         if (reg) {
 134                 ulpi_write(ulpi, TUSB1210_VENDOR_SPECIFIC2, reg);
 135                 tusb->vendor_specific2 = reg;
 136         }
 137 
 138         tusb->phy = ulpi_phy_create(ulpi, &phy_ops);
 139         if (IS_ERR(tusb->phy))
 140                 return PTR_ERR(tusb->phy);
 141 
 142         tusb->ulpi = ulpi;
 143 
 144         phy_set_drvdata(tusb->phy, tusb);
 145         ulpi_set_drvdata(ulpi, tusb);
 146         return 0;
 147 }
 148 
 149 static void tusb1210_remove(struct ulpi *ulpi)
 150 {
 151         struct tusb1210 *tusb = ulpi_get_drvdata(ulpi);
 152 
 153         ulpi_phy_destroy(ulpi, tusb->phy);
 154 }
 155 
 156 #define TI_VENDOR_ID 0x0451
 157 
 158 static const struct ulpi_device_id tusb1210_ulpi_id[] = {
 159         { TI_VENDOR_ID, 0x1507, },  /* TUSB1210 */
 160         { TI_VENDOR_ID, 0x1508, },  /* TUSB1211 */
 161         { },
 162 };
 163 MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
 164 
 165 static struct ulpi_driver tusb1210_driver = {
 166         .id_table = tusb1210_ulpi_id,
 167         .probe = tusb1210_probe,
 168         .remove = tusb1210_remove,
 169         .driver = {
 170                 .name = "tusb1210",
 171                 .owner = THIS_MODULE,
 172         },
 173 };
 174 
 175 module_ulpi_driver(tusb1210_driver);
 176 
 177 MODULE_AUTHOR("Intel Corporation");
 178 MODULE_LICENSE("GPL v2");
 179 MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver");

/* [<][>][^][v][top][bottom][index][help] */