blob: 2ffe4cafcfb2bea8b772437ad6d392178e736606 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/platform_device.h>
14#include <linux/err.h>
15#include <linux/pm_runtime.h>
16#include <linux/regulator/consumer.h>
17#include <linux/i2c.h>
18#include <linux/gpio.h>
Manu Gautam863b74132012-11-21 14:30:04 +053019#include <linux/of_gpio.h>
20#include <linux/of_device.h>
21#include <linux/clk.h>
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +053022#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/smsc3503.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070025#include <linux/module.h>
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +053026#include <mach/msm_xo.h>
27
28#define SMSC3503_I2C_ADDR 0x08
29#define SMSC_GSBI_I2C_BUS_ID 10
30static const unsigned short normal_i2c[] = {
31SMSC3503_I2C_ADDR, I2C_CLIENT_END };
32
33struct hsic_hub {
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +053034 struct device *dev;
Manu Gautam863b74132012-11-21 14:30:04 +053035 struct smsc_hub_platform_data *pdata;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +053036 struct i2c_client *client;
37 struct msm_xo_voter *xo_handle;
Manu Gautam863b74132012-11-21 14:30:04 +053038 struct clk *ref_clk;
39 struct regulator *hsic_hub_reg;
40 struct regulator *int_pad_reg, *hub_vbus_reg;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +053041};
42static struct hsic_hub *smsc_hub;
Manu Gautam863b74132012-11-21 14:30:04 +053043static struct platform_driver smsc_hub_driver;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +053044
45/* APIs for setting/clearing bits and for reading/writing values */
46static inline int hsic_hub_get_u8(struct i2c_client *client, u8 reg)
47{
48 int ret;
49
50 ret = i2c_smbus_read_byte_data(client, reg);
51 if (ret < 0)
52 pr_err("%s:i2c_read8 failed\n", __func__);
53 return ret;
54}
55
56static inline int hsic_hub_get_u16(struct i2c_client *client, u8 reg)
57{
58 int ret;
59
60 ret = i2c_smbus_read_word_data(client, reg);
61 if (ret < 0)
62 pr_err("%s:i2c_read16 failed\n", __func__);
63 return ret;
64}
65
66static inline int hsic_hub_write_word_data(struct i2c_client *client, u8 reg,
67 u16 value)
68{
69 int ret;
70
71 ret = i2c_smbus_write_word_data(client, reg, value);
72 if (ret)
73 pr_err("%s:i2c_write16 failed\n", __func__);
74 return ret;
75}
76
77static inline int hsic_hub_write_byte_data(struct i2c_client *client, u8 reg,
78 u8 value)
79{
80 int ret;
81
82 ret = i2c_smbus_write_byte_data(client, reg, value);
83 if (ret)
84 pr_err("%s:i2c_write_byte_data failed\n", __func__);
85 return ret;
86}
87
88static inline int hsic_hub_set_bits(struct i2c_client *client, u8 reg,
89 u8 value)
90{
91 int ret;
92
93 ret = i2c_smbus_read_byte_data(client, reg);
94 if (ret < 0) {
95 pr_err("%s:i2c_read_byte_data failed\n", __func__);
96 return ret;
97 }
98 return i2c_smbus_write_byte_data(client, reg, (ret | value));
99}
100
101static inline int hsic_hub_clear_bits(struct i2c_client *client, u8 reg,
102 u8 value)
103{
104 int ret;
105
106 ret = i2c_smbus_read_byte_data(client, reg);
107 if (ret < 0) {
108 pr_err("%s:i2c_read_byte_data failed\n", __func__);
109 return ret;
110 }
111 return i2c_smbus_write_byte_data(client, reg, (ret & ~value));
112}
113
114static int i2c_hsic_hub_probe(struct i2c_client *client,
115 const struct i2c_device_id *id)
116{
117 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
118 I2C_FUNC_SMBUS_WORD_DATA))
119 return -EIO;
120
Vijayavardhan Vennapusa361da682012-04-12 19:50:02 +0530121 /* CONFIG_N bit in SP_ILOCK register has to be set before changing
122 * other registers to change default configuration of hsic hub.
123 */
124 hsic_hub_set_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
125
126 /* Can change default configuartion like VID,PID, strings etc
127 * by writing new values to hsic hub registers.
128 */
129 hsic_hub_write_word_data(client, SMSC3503_VENDORID, 0x05C6);
130
131 /* CONFIG_N bit in SP_ILOCK register has to be cleared for new
132 * values in registers to be effective after writing to
133 * other registers.
134 */
135 hsic_hub_clear_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
136
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530137 return 0;
138}
139
140static int i2c_hsic_hub_remove(struct i2c_client *client)
141{
142 return 0;
143}
144
145static const struct i2c_device_id hsic_hub_id[] = {
146 {"i2c_hsic_hub", 0},
147 {}
148};
149MODULE_DEVICE_TABLE(i2c, hsichub_id);
150
151static struct i2c_driver hsic_hub_driver = {
152 .driver = {
153 .name = "i2c_hsic_hub",
154 },
155 .probe = i2c_hsic_hub_probe,
156 .remove = i2c_hsic_hub_remove,
157 .id_table = hsic_hub_id,
158};
159
Manu Gautam863b74132012-11-21 14:30:04 +0530160static int msm_hsic_hub_init_clock(struct hsic_hub *hub, int init)
161{
162 int ret;
163
164 if (!init) {
165 if (!IS_ERR(hub->ref_clk))
166 clk_disable_unprepare(hub->ref_clk);
167 else
168 msm_xo_put(smsc_hub->xo_handle);
169
170 return 0;
171 }
172
173 hub->ref_clk = devm_clk_get(hub->dev, "ref_clk");
174 if (IS_ERR(hub->ref_clk)) {
175 dev_dbg(hub->dev, "failed to get ref_clk\n");
176
177 /* In the absence of dedicated ref_clk, xo clocks the HUB */
178 smsc_hub->xo_handle = msm_xo_get(MSM_XO_TCXO_D1, "hsic_hub");
179 if (IS_ERR(smsc_hub->xo_handle)) {
180 dev_err(hub->dev, "not able to get the handle\n"
181 "for TCXO D1 buffer\n");
182 return PTR_ERR(smsc_hub->xo_handle);
183 }
184
185 ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_ON);
186 if (ret) {
187 dev_err(hub->dev, "failed to vote for TCXO\n"
188 "D1 buffer\n");
189 msm_xo_put(smsc_hub->xo_handle);
190 return ret;
191 }
192 } else {
193 ret = clk_prepare_enable(hub->ref_clk);
194 if (ret)
195 dev_err(hub->dev, "clk_enable failed for ref_clk\n");
196 }
197
198 return ret;
199}
200#define HSIC_HUB_INT_VOL_MIN 1800000 /* uV */
201#define HSIC_HUB_INT_VOL_MAX 2950000 /* uV */
202static int msm_hsic_hub_init_gpio(struct hsic_hub *hub, int init)
203{
204 int ret;
205 struct smsc_hub_platform_data *pdata = hub->pdata;
206
207 if (!init) {
208 if (!IS_ERR(smsc_hub->int_pad_reg)) {
209 regulator_disable(smsc_hub->int_pad_reg);
210 regulator_set_voltage(smsc_hub->int_pad_reg, 0,
211 HSIC_HUB_INT_VOL_MAX);
212 }
213 return 0;
214 }
215
216 ret = devm_gpio_request(hub->dev, pdata->hub_reset, "HSIC_HUB_RESET");
217 if (ret < 0) {
218 dev_err(hub->dev, "gpio request failed for GPIO%d\n",
219 pdata->hub_reset);
220 return ret;
221 }
222
223 if (pdata->refclk_gpio) {
224 ret = devm_gpio_request(hub->dev, pdata->refclk_gpio,
225 "HSIC_HUB_CLK");
226 if (ret < 0)
227 dev_err(hub->dev, "gpio request failed (CLK GPIO)\n");
228 }
229
230 if (pdata->int_gpio) {
231 ret = devm_gpio_request(hub->dev, pdata->int_gpio,
232 "HSIC_HUB_INT");
233 if (ret < 0) {
234 dev_err(hub->dev, "gpio request failed (INT GPIO)\n");
235 return ret;
236 }
237
238 /* Enable LDO if required for external pull-up */
239 smsc_hub->int_pad_reg = devm_regulator_get(hub->dev, "hub_int");
240 if (IS_ERR(smsc_hub->int_pad_reg)) {
241 dev_dbg(hub->dev, "unable to get ext hub_int reg\n");
242 } else {
243 ret = regulator_set_voltage(smsc_hub->int_pad_reg,
244 HSIC_HUB_INT_VOL_MIN,
245 HSIC_HUB_INT_VOL_MAX);
246 if (ret) {
247 dev_err(hub->dev, "unable to set the voltage\n"
248 " for hsic hub int reg\n");
249 return ret;
250 }
251 ret = regulator_enable(smsc_hub->int_pad_reg);
252 if (ret) {
253 dev_err(hub->dev, "unable to enable int reg\n");
254 regulator_set_voltage(smsc_hub->int_pad_reg, 0,
255 HSIC_HUB_INT_VOL_MAX);
256 return ret;
257 }
258 }
259 }
260
261 return 0;
262}
263
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530264#define HSIC_HUB_VDD_VOL_MIN 1650000 /* uV */
265#define HSIC_HUB_VDD_VOL_MAX 1950000 /* uV */
266#define HSIC_HUB_VDD_LOAD 36000 /* uA */
Manu Gautam863b74132012-11-21 14:30:04 +0530267static int msm_hsic_hub_init_vdd(struct hsic_hub *hub, int init)
268{
269 int ret;
270
271 if (!init) {
272 if (!IS_ERR(smsc_hub->hsic_hub_reg)) {
273 regulator_disable(smsc_hub->hsic_hub_reg);
274 regulator_set_optimum_mode(smsc_hub->hsic_hub_reg, 0);
275 regulator_set_voltage(smsc_hub->hsic_hub_reg, 0,
276 HSIC_HUB_VDD_VOL_MAX);
277 }
278 return 0;
279 }
280
281 smsc_hub->hsic_hub_reg = devm_regulator_get(hub->dev, "EXT_HUB_VDDIO");
282 if (IS_ERR(smsc_hub->hsic_hub_reg)) {
283 dev_dbg(hub->dev, "unable to get ext hub vddcx\n");
284 } else {
285 ret = regulator_set_voltage(smsc_hub->hsic_hub_reg,
286 HSIC_HUB_VDD_VOL_MIN,
287 HSIC_HUB_VDD_VOL_MAX);
288 if (ret) {
289 dev_err(hub->dev, "unable to set the voltage\n"
290 "for hsic hub reg\n");
291 return ret;
292 }
293
294 ret = regulator_set_optimum_mode(smsc_hub->hsic_hub_reg,
295 HSIC_HUB_VDD_LOAD);
296 if (ret < 0) {
297 dev_err(hub->dev, "Unable to set mode of VDDCX\n");
298 goto reg_optimum_mode_fail;
299 }
300
301 ret = regulator_enable(smsc_hub->hsic_hub_reg);
302 if (ret) {
303 dev_err(hub->dev, "unable to enable ext hub vddcx\n");
304 goto reg_enable_fail;
305 }
306 }
307
308 return 0;
309
310reg_enable_fail:
311 regulator_set_optimum_mode(smsc_hub->hsic_hub_reg, 0);
312reg_optimum_mode_fail:
313 regulator_set_voltage(smsc_hub->hsic_hub_reg, 0,
314 HSIC_HUB_VDD_VOL_MAX);
315
316 return ret;
317}
318struct smsc_hub_platform_data *msm_hub_dt_to_pdata(
319 struct platform_device *pdev)
320{
321 struct device_node *node = pdev->dev.of_node;
322 struct smsc_hub_platform_data *pdata;
323
324 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
325 if (!pdata) {
326 dev_err(&pdev->dev, "unable to allocate platform data\n");
327 return ERR_PTR(-ENOMEM);
328 }
329
330 pdata->hub_reset = of_get_named_gpio(node, "smsc,reset-gpio", 0);
331 if (pdata->hub_reset < 0)
332 return ERR_PTR(pdata->hub_reset);
333
334 pdata->refclk_gpio = of_get_named_gpio(node, "smsc,refclk-gpio", 0);
335 if (pdata->refclk_gpio < 0)
336 pdata->refclk_gpio = 0;
337
338 pdata->int_gpio = of_get_named_gpio(node, "smsc,int-gpio", 0);
339 if (pdata->int_gpio < 0)
340 pdata->int_gpio = 0;
341
342 return pdata;
343}
344
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530345static int __devinit smsc_hub_probe(struct platform_device *pdev)
346{
347 int ret = 0;
348 const struct smsc_hub_platform_data *pdata;
Manu Gautam863b74132012-11-21 14:30:04 +0530349 struct device_node *node = pdev->dev.of_node;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530350 struct i2c_adapter *i2c_adap;
351 struct i2c_board_info i2c_info;
352
Manu Gautam863b74132012-11-21 14:30:04 +0530353 if (pdev->dev.of_node) {
354 dev_dbg(&pdev->dev, "device tree enabled\n");
355 pdev->dev.platform_data = msm_hub_dt_to_pdata(pdev);
356 if (IS_ERR(pdev->dev.platform_data))
357 return PTR_ERR(pdev->dev.platform_data);
358
359 dev_set_name(&pdev->dev, smsc_hub_driver.driver.name);
360 }
361
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530362 if (!pdev->dev.platform_data) {
363 dev_err(&pdev->dev, "No platform data\n");
364 return -ENODEV;
365 }
366
367 pdata = pdev->dev.platform_data;
368 if (!pdata->hub_reset)
369 return -EINVAL;
370
Manu Gautam863b74132012-11-21 14:30:04 +0530371 smsc_hub = devm_kzalloc(&pdev->dev, sizeof(*smsc_hub), GFP_KERNEL);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530372 if (!smsc_hub)
373 return -ENOMEM;
374
Manu Gautam863b74132012-11-21 14:30:04 +0530375 smsc_hub->dev = &pdev->dev;
376 smsc_hub->pdata = pdev->dev.platform_data;
377
378 smsc_hub->hub_vbus_reg = devm_regulator_get(&pdev->dev, "hub_vbus");
379 ret = PTR_ERR(smsc_hub->hub_vbus_reg);
380 if (ret == -EPROBE_DEFER) {
381 dev_dbg(&pdev->dev, "failed to get hub_vbus\n");
382 return ret;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530383 }
384
Manu Gautam863b74132012-11-21 14:30:04 +0530385 ret = msm_hsic_hub_init_vdd(smsc_hub, 1);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530386 if (ret) {
Manu Gautam863b74132012-11-21 14:30:04 +0530387 dev_err(&pdev->dev, "failed to init hub VDD\n");
388 return ret;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530389 }
Manu Gautam863b74132012-11-21 14:30:04 +0530390 ret = msm_hsic_hub_init_clock(smsc_hub, 1);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530391 if (ret) {
Manu Gautam863b74132012-11-21 14:30:04 +0530392 dev_err(&pdev->dev, "failed to init hub clock\n");
393 goto uninit_vdd;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530394 }
Manu Gautam863b74132012-11-21 14:30:04 +0530395 ret = msm_hsic_hub_init_gpio(smsc_hub, 1);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530396 if (ret) {
Manu Gautam863b74132012-11-21 14:30:04 +0530397 dev_err(&pdev->dev, "failed to init hub gpios\n");
398 goto uninit_clock;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530399 }
400
401 gpio_direction_output(pdata->hub_reset, 0);
402 /* Hub reset should be asserted for minimum 2microsec
403 * before deasserting.
404 */
405 udelay(5);
406 gpio_direction_output(pdata->hub_reset, 1);
407
Manu Gautam863b74132012-11-21 14:30:04 +0530408 ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
409 if (ret) {
410 dev_err(&pdev->dev, "failed to add child node, ret=%d\n", ret);
411 goto uninit_gpio;
412 }
413
414 if (!IS_ERR(smsc_hub->hub_vbus_reg)) {
415 ret = regulator_enable(smsc_hub->hub_vbus_reg);
416 if (ret) {
417 dev_err(&pdev->dev, "unable to enable hub_vbus\n");
418 goto uninit_gpio;
419 }
420 }
421
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530422 ret = i2c_add_driver(&hsic_hub_driver);
423 if (ret < 0) {
424 dev_err(&pdev->dev, "failed to add I2C hsic_hub_driver\n");
425 goto i2c_add_fail;
426 }
427 usleep_range(10000, 12000);
428 i2c_adap = i2c_get_adapter(SMSC_GSBI_I2C_BUS_ID);
429
430 if (!i2c_adap) {
431 dev_err(&pdev->dev, "failed to get i2c adapter\n");
432 i2c_del_driver(&hsic_hub_driver);
433 goto i2c_add_fail;
434 }
435
436 memset(&i2c_info, 0, sizeof(struct i2c_board_info));
437 strlcpy(i2c_info.type, "i2c_hsic_hub", I2C_NAME_SIZE);
438
439 smsc_hub->client = i2c_new_probed_device(i2c_adap, &i2c_info,
440 normal_i2c, NULL);
441 i2c_put_adapter(i2c_adap);
442 if (!smsc_hub->client)
443 dev_err(&pdev->dev, "failed to connect to smsc_hub"
444 "through I2C\n");
445
446i2c_add_fail:
447 pm_runtime_set_active(&pdev->dev);
448 pm_runtime_enable(&pdev->dev);
449
450 return 0;
451
Manu Gautam863b74132012-11-21 14:30:04 +0530452uninit_gpio:
453 msm_hsic_hub_init_gpio(smsc_hub, 0);
454uninit_clock:
455 msm_hsic_hub_init_clock(smsc_hub, 0);
456uninit_vdd:
457 msm_hsic_hub_init_vdd(smsc_hub, 0);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530458
459 return ret;
460}
461
462static int smsc_hub_remove(struct platform_device *pdev)
463{
464 const struct smsc_hub_platform_data *pdata;
465
466 pdata = pdev->dev.platform_data;
467 if (smsc_hub->client) {
468 i2c_unregister_device(smsc_hub->client);
469 smsc_hub->client = NULL;
470 i2c_del_driver(&hsic_hub_driver);
471 }
472 pm_runtime_disable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530473
Manu Gautam863b74132012-11-21 14:30:04 +0530474 regulator_disable(smsc_hub->hub_vbus_reg);
475 msm_hsic_hub_init_gpio(smsc_hub, 0);
476 msm_hsic_hub_init_clock(smsc_hub, 0);
477 msm_hsic_hub_init_vdd(smsc_hub, 0);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530478
479 return 0;
480}
481
482#ifdef CONFIG_PM_RUNTIME
483static int msm_smsc_runtime_idle(struct device *dev)
484{
485 dev_dbg(dev, "SMSC HUB runtime idle\n");
486
487 return 0;
488}
489
490static int smsc_hub_lpm_enter(struct device *dev)
491{
Manu Gautam863b74132012-11-21 14:30:04 +0530492 int ret = 0;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530493
Manu Gautam863b74132012-11-21 14:30:04 +0530494 if (!IS_ERR(smsc_hub->ref_clk)) {
495 clk_disable_unprepare(smsc_hub->ref_clk);
496 } else {
497 ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_OFF);
498 if (ret) {
499 pr_err("%s: failed to devote for TCXO\n"
500 "D1 buffer%d\n", __func__, ret);
501 }
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530502 }
503 return ret;
504}
505
506static int smsc_hub_lpm_exit(struct device *dev)
507{
Manu Gautam863b74132012-11-21 14:30:04 +0530508 int ret = 0;
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530509
Manu Gautam863b74132012-11-21 14:30:04 +0530510 if (!IS_ERR(smsc_hub->ref_clk)) {
511 clk_prepare_enable(smsc_hub->ref_clk);
512 } else {
513 ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_ON);
514 if (ret) {
515 pr_err("%s: failed to vote for TCXO\n"
516 "D1 buffer%d\n", __func__, ret);
517 }
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530518 }
519 return ret;
520}
521#endif
522
523#ifdef CONFIG_PM
524static const struct dev_pm_ops smsc_hub_dev_pm_ops = {
525 SET_SYSTEM_SLEEP_PM_OPS(smsc_hub_lpm_enter, smsc_hub_lpm_exit)
526 SET_RUNTIME_PM_OPS(smsc_hub_lpm_enter, smsc_hub_lpm_exit,
527 msm_smsc_runtime_idle)
528};
529#endif
530
Manu Gautam863b74132012-11-21 14:30:04 +0530531static const struct of_device_id hsic_hub_dt_match[] = {
532 { .compatible = "qcom,hsic-smsc-hub",
533 },
534 {}
535};
536MODULE_DEVICE_TABLE(of, hsic_hub_dt_match);
537
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530538static struct platform_driver smsc_hub_driver = {
539 .driver = {
540 .name = "msm_smsc_hub",
541 .owner = THIS_MODULE,
542#ifdef CONFIG_PM
543 .pm = &smsc_hub_dev_pm_ops,
544#endif
Manu Gautam863b74132012-11-21 14:30:04 +0530545 .of_match_table = hsic_hub_dt_match,
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530546 },
Manu Gautam863b74132012-11-21 14:30:04 +0530547 .probe = smsc_hub_probe,
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530548 .remove = smsc_hub_remove,
549};
550
551static int __init smsc_hub_init(void)
552{
Manu Gautam863b74132012-11-21 14:30:04 +0530553 return platform_driver_register(&smsc_hub_driver);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530554}
555
556static void __exit smsc_hub_exit(void)
557{
558 platform_driver_unregister(&smsc_hub_driver);
559}
560subsys_initcall(smsc_hub_init);
561module_exit(smsc_hub_exit);
562
563MODULE_LICENSE("GPL v2");
564MODULE_DESCRIPTION("SMSC HSIC HUB driver");