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