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"); 180