aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/usb3503.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc/usb3503.c')
-rw-r--r--drivers/usb/misc/usb3503.c93
1 files changed, 76 insertions, 17 deletions
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index da45ed971332..a31641e18d19 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -78,22 +78,21 @@ static int usb3503_reset(struct usb3503 *hub, int state)
78 return 0; 78 return 0;
79} 79}
80 80
81static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) 81static int usb3503_connect(struct usb3503 *hub)
82{ 82{
83 struct device *dev = hub->dev; 83 struct device *dev = hub->dev;
84 int err = 0; 84 int err;
85 85
86 switch (mode) { 86 usb3503_reset(hub, 1);
87 case USB3503_MODE_HUB:
88 usb3503_reset(hub, 1);
89 87
88 if (hub->regmap) {
90 /* SP_ILOCK: set connect_n, config_n for config */ 89 /* SP_ILOCK: set connect_n, config_n for config */
91 err = regmap_write(hub->regmap, USB3503_SP_ILOCK, 90 err = regmap_write(hub->regmap, USB3503_SP_ILOCK,
92 (USB3503_SPILOCK_CONNECT 91 (USB3503_SPILOCK_CONNECT
93 | USB3503_SPILOCK_CONFIG)); 92 | USB3503_SPILOCK_CONFIG));
94 if (err < 0) { 93 if (err < 0) {
95 dev_err(dev, "SP_ILOCK failed (%d)\n", err); 94 dev_err(dev, "SP_ILOCK failed (%d)\n", err);
96 goto err_hubmode; 95 return err;
97 } 96 }
98 97
99 /* PDS : Disable For Self Powered Operation */ 98 /* PDS : Disable For Self Powered Operation */
@@ -103,7 +102,7 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
103 hub->port_off_mask); 102 hub->port_off_mask);
104 if (err < 0) { 103 if (err < 0) {
105 dev_err(dev, "PDS failed (%d)\n", err); 104 dev_err(dev, "PDS failed (%d)\n", err);
106 goto err_hubmode; 105 return err;
107 } 106 }
108 } 107 }
109 108
@@ -113,7 +112,7 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
113 USB3503_SELF_BUS_PWR); 112 USB3503_SELF_BUS_PWR);
114 if (err < 0) { 113 if (err < 0) {
115 dev_err(dev, "CFG1 failed (%d)\n", err); 114 dev_err(dev, "CFG1 failed (%d)\n", err);
116 goto err_hubmode; 115 return err;
117 } 116 }
118 117
119 /* SP_LOCK: clear connect_n, config_n for hub connect */ 118 /* SP_LOCK: clear connect_n, config_n for hub connect */
@@ -122,14 +121,27 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
122 | USB3503_SPILOCK_CONFIG), 0); 121 | USB3503_SPILOCK_CONFIG), 0);
123 if (err < 0) { 122 if (err < 0) {
124 dev_err(dev, "SP_ILOCK failed (%d)\n", err); 123 dev_err(dev, "SP_ILOCK failed (%d)\n", err);
125 goto err_hubmode; 124 return err;
126 } 125 }
126 }
127 127
128 if (gpio_is_valid(hub->gpio_connect)) 128 if (gpio_is_valid(hub->gpio_connect))
129 gpio_set_value_cansleep(hub->gpio_connect, 1); 129 gpio_set_value_cansleep(hub->gpio_connect, 1);
130 130
131 hub->mode = mode; 131 hub->mode = USB3503_MODE_HUB;
132 dev_info(dev, "switched to HUB mode\n"); 132 dev_info(dev, "switched to HUB mode\n");
133
134 return 0;
135}
136
137static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
138{
139 struct device *dev = hub->dev;
140 int err = 0;
141
142 switch (mode) {
143 case USB3503_MODE_HUB:
144 err = usb3503_connect(hub);
133 break; 145 break;
134 146
135 case USB3503_MODE_STANDBY: 147 case USB3503_MODE_STANDBY:
@@ -145,7 +157,6 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
145 break; 157 break;
146 } 158 }
147 159
148err_hubmode:
149 return err; 160 return err;
150} 161}
151 162
@@ -198,6 +209,9 @@ static int usb3503_probe(struct usb3503 *hub)
198 hub->mode = mode; 209 hub->mode = mode;
199 } 210 }
200 211
212 if (hub->port_off_mask && !hub->regmap)
213 dev_err(dev, "Ports disabled with no control interface\n");
214
201 if (gpio_is_valid(hub->gpio_intn)) { 215 if (gpio_is_valid(hub->gpio_intn)) {
202 err = devm_gpio_request_one(dev, hub->gpio_intn, 216 err = devm_gpio_request_one(dev, hub->gpio_intn,
203 GPIOF_OUT_INIT_HIGH, "usb3503 intn"); 217 GPIOF_OUT_INIT_HIGH, "usb3503 intn");
@@ -263,6 +277,20 @@ static int usb3503_i2c_probe(struct i2c_client *i2c,
263 return usb3503_probe(hub); 277 return usb3503_probe(hub);
264} 278}
265 279
280static int usb3503_platform_probe(struct platform_device *pdev)
281{
282 struct usb3503 *hub;
283
284 hub = devm_kzalloc(&pdev->dev, sizeof(struct usb3503), GFP_KERNEL);
285 if (!hub) {
286 dev_err(&pdev->dev, "private data alloc fail\n");
287 return -ENOMEM;
288 }
289 hub->dev = &pdev->dev;
290
291 return usb3503_probe(hub);
292}
293
266static const struct i2c_device_id usb3503_id[] = { 294static const struct i2c_device_id usb3503_id[] = {
267 { USB3503_I2C_NAME, 0 }, 295 { USB3503_I2C_NAME, 0 },
268 { } 296 { }
@@ -278,7 +306,7 @@ static const struct of_device_id usb3503_of_match[] = {
278MODULE_DEVICE_TABLE(of, usb3503_of_match); 306MODULE_DEVICE_TABLE(of, usb3503_of_match);
279#endif 307#endif
280 308
281static struct i2c_driver usb3503_driver = { 309static struct i2c_driver usb3503_i2c_driver = {
282 .driver = { 310 .driver = {
283 .name = USB3503_I2C_NAME, 311 .name = USB3503_I2C_NAME,
284 .of_match_table = of_match_ptr(usb3503_of_match), 312 .of_match_table = of_match_ptr(usb3503_of_match),
@@ -287,7 +315,38 @@ static struct i2c_driver usb3503_driver = {
287 .id_table = usb3503_id, 315 .id_table = usb3503_id,
288}; 316};
289 317
290module_i2c_driver(usb3503_driver); 318static struct platform_driver usb3503_platform_driver = {
319 .driver = {
320 .name = USB3503_I2C_NAME,
321 .of_match_table = of_match_ptr(usb3503_of_match),
322 .owner = THIS_MODULE,
323 },
324 .probe = usb3503_platform_probe,
325};
326
327static int __init usb3503_init(void)
328{
329 int err;
330
331 err = i2c_register_driver(THIS_MODULE, &usb3503_i2c_driver);
332 if (err != 0)
333 pr_err("usb3503: Failed to register I2C driver: %d\n", err);
334
335 err = platform_driver_register(&usb3503_platform_driver);
336 if (err != 0)
337 pr_err("usb3503: Failed to register platform driver: %d\n",
338 err);
339
340 return 0;
341}
342module_init(usb3503_init);
343
344static void __exit usb3503_exit(void)
345{
346 platform_driver_unregister(&usb3503_platform_driver);
347 i2c_del_driver(&usb3503_i2c_driver);
348}
349module_exit(usb3503_exit);
291 350
292MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>"); 351MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>");
293MODULE_DESCRIPTION("USB3503 USB HUB driver"); 352MODULE_DESCRIPTION("USB3503 USB HUB driver");