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 21 struct 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 29 static int tusb1210_ulpi_write(struct tusb1210 *tusb, u8 reg, u8 val) 30 { 31 int ret; 32 33 ret = ulpi_write(tusb->ulpi, reg, val); 34 if (ret) 35 dev_err(&tusb->ulpi->dev, "error %d writing val 0x%02x to reg 0x%02x\n", 36 ret, val, reg); 37 38 return ret; 39 } 40 41 static int tusb1210_ulpi_read(struct tusb1210 *tusb, u8 reg, u8 *val) 42 { 43 int ret; 44 45 ret = ulpi_read(tusb->ulpi, reg); 46 if (ret >= 0) { 47 *val = ret; 48 ret = 0; 49 } else { 50 dev_err(&tusb->ulpi->dev, "error %d reading reg 0x%02x\n", ret, reg); 51 } 52 53 return ret; 54 } 55 56 static int tusb1210_power_on(struct phy *phy) 57 { 58 struct tusb1210 *tusb = phy_get_drvdata(phy); 59 60 gpiod_set_value_cansleep(tusb->gpio_reset, 1); 61 gpiod_set_value_cansleep(tusb->gpio_cs, 1); 62 63 /* Restore the optional eye diagram optimization value */ 64 return tusb1210_ulpi_write(tusb, TUSB1210_VENDOR_SPECIFIC2, 65 tusb->vendor_specific2); 66 } 67 68 static int tusb1210_power_off(struct phy *phy) 69 { 70 struct tusb1210 *tusb = phy_get_drvdata(phy); 71 72 gpiod_set_value_cansleep(tusb->gpio_reset, 0); 73 gpiod_set_value_cansleep(tusb->gpio_cs, 0); 74 75 return 0; 76 } 77 78 static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode) 79 { 80 struct tusb1210 *tusb = phy_get_drvdata(phy); 81 int ret; 82 u8 reg; 83 84 ret = tusb1210_ulpi_read(tusb, ULPI_OTG_CTRL, ®); 85 if (ret < 0) 86 return ret; 87 88 switch (mode) { 89 case PHY_MODE_USB_HOST: 90 reg |= (ULPI_OTG_CTRL_DRVVBUS_EXT 91 | ULPI_OTG_CTRL_ID_PULLUP 92 | ULPI_OTG_CTRL_DP_PULLDOWN 93 | ULPI_OTG_CTRL_DM_PULLDOWN); 94 tusb1210_ulpi_write(tusb, ULPI_OTG_CTRL, reg); 95 reg |= ULPI_OTG_CTRL_DRVVBUS; 96 break; 97 case PHY_MODE_USB_DEVICE: 98 reg &= ~(ULPI_OTG_CTRL_DRVVBUS 99 | ULPI_OTG_CTRL_DP_PULLDOWN 100 | ULPI_OTG_CTRL_DM_PULLDOWN); 101 tusb1210_ulpi_write(tusb, ULPI_OTG_CTRL, reg); 102 reg &= ~ULPI_OTG_CTRL_DRVVBUS_EXT; 103 break; 104 default: 105 /* nothing */ 106 return 0; 107 } 108 109 return tusb1210_ulpi_write(tusb, ULPI_OTG_CTRL, reg); 110 } 111 112 static const struct phy_ops phy_ops = { 113 .power_on = tusb1210_power_on, 114 .power_off = tusb1210_power_off, 115 .set_mode = tusb1210_set_mode, 116 .owner = THIS_MODULE, 117 }; 118 119 static int tusb1210_probe(struct ulpi *ulpi) 120 { 121 struct tusb1210 *tusb; 122 u8 val, reg; 123 int ret; 124 125 tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL); 126 if (!tusb) 127 return -ENOMEM; 128 129 tusb->ulpi = ulpi; 130 131 tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset", 132 GPIOD_OUT_LOW); 133 if (IS_ERR(tusb->gpio_reset)) 134 return PTR_ERR(tusb->gpio_reset); 135 136 gpiod_set_value_cansleep(tusb->gpio_reset, 1); 137 138 tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs", 139 GPIOD_OUT_LOW); 140 if (IS_ERR(tusb->gpio_cs)) 141 return PTR_ERR(tusb->gpio_cs); 142 143 gpiod_set_value_cansleep(tusb->gpio_cs, 1); 144 145 /* 146 * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye 147 * diagram optimization and DP/DM swap. 148 */ 149 150 ret = tusb1210_ulpi_read(tusb, TUSB1210_VENDOR_SPECIFIC2, ®); 151 if (ret) 152 return ret; 153 154 /* High speed output drive strength configuration */ 155 if (!device_property_read_u8(&ulpi->dev, "ihstx", &val)) 156 u8p_replace_bits(®, val, (u8)TUSB1210_VENDOR_SPECIFIC2_IHSTX_MASK); 157 158 /* High speed output impedance configuration */ 159 if (!device_property_read_u8(&ulpi->dev, "zhsdrv", &val)) 160 u8p_replace_bits(®, val, (u8)TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_MASK); 161 162 /* DP/DM swap control */ 163 if (!device_property_read_u8(&ulpi->dev, "datapolarity", &val)) 164 u8p_replace_bits(®, val, (u8)TUSB1210_VENDOR_SPECIFIC2_DP_MASK); 165 166 ret = tusb1210_ulpi_write(tusb, TUSB1210_VENDOR_SPECIFIC2, reg); 167 if (ret) 168 return ret; 169 170 tusb->vendor_specific2 = reg; 171 172 tusb->phy = ulpi_phy_create(ulpi, &phy_ops); 173 if (IS_ERR(tusb->phy)) 174 return PTR_ERR(tusb->phy); 175 176 phy_set_drvdata(tusb->phy, tusb); 177 ulpi_set_drvdata(ulpi, tusb); 178 return 0; 179 } 180 181 static void tusb1210_remove(struct ulpi *ulpi) 182 { 183 struct tusb1210 *tusb = ulpi_get_drvdata(ulpi); 184 185 ulpi_phy_destroy(ulpi, tusb->phy); 186 } 187 188 #define TI_VENDOR_ID 0x0451 189 190 static const struct ulpi_device_id tusb1210_ulpi_id[] = { 191 { TI_VENDOR_ID, 0x1507, }, /* TUSB1210 */ 192 { TI_VENDOR_ID, 0x1508, }, /* TUSB1211 */ 193 { }, 194 }; 195 MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id); 196 197 static struct ulpi_driver tusb1210_driver = { 198 .id_table = tusb1210_ulpi_id, 199 .probe = tusb1210_probe, 200 .remove = tusb1210_remove, 201 .driver = { 202 .name = "tusb1210", 203 .owner = THIS_MODULE, 204 }, 205 }; 206 207 module_ulpi_driver(tusb1210_driver); 208 209 MODULE_AUTHOR("Intel Corporation"); 210 MODULE_LICENSE("GPL v2"); 211 MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver"); 212