linux/drivers/phy/ti/phy-tusb1210.c
<<
>>
Prefs
   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
  20struct 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
  28static 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
  43static 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
  53static 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
  86static 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
  93static 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
 149static 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
 158static const struct ulpi_device_id tusb1210_ulpi_id[] = {
 159        { TI_VENDOR_ID, 0x1507, },  /* TUSB1210 */
 160        { TI_VENDOR_ID, 0x1508, },  /* TUSB1211 */
 161        { },
 162};
 163MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
 164
 165static 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
 175module_ulpi_driver(tusb1210_driver);
 176
 177MODULE_AUTHOR("Intel Corporation");
 178MODULE_LICENSE("GPL v2");
 179MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver");
 180