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