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 
tusb1210_power_on(struct phy * phy)29 static 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 
tusb1210_power_off(struct phy * phy)44 static 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 
tusb1210_set_mode(struct phy * phy,enum phy_mode mode,int submode)54 static 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 
87 static 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 
tusb1210_probe(struct ulpi * ulpi)94 static 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 
tusb1210_remove(struct ulpi * ulpi)150 static 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 
159 static const struct ulpi_device_id tusb1210_ulpi_id[] = {
160 	{ TI_VENDOR_ID, 0x1507, },  /* TUSB1210 */
161 	{ TI_VENDOR_ID, 0x1508, },  /* TUSB1211 */
162 	{ },
163 };
164 MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
165 
166 static 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 
176 module_ulpi_driver(tusb1210_driver);
177 
178 MODULE_AUTHOR("Intel Corporation");
179 MODULE_LICENSE("GPL v2");
180 MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver");
181