1 // SPDX-License-Identifier: GPL-2.0+
3 * Driver for SMSC USB4604 USB HSIC 4-port 2.0 hub controller driver
4 * Based on usb3503 driver
6 * Copyright (c) 2012-2013 Dongjin Kim (tobetter@gmail.com)
7 * Copyright (c) 2016 Linaro Ltd.
10 #include <linux/i2c.h>
11 #include <linux/delay.h>
12 #include <linux/slab.h>
13 #include <linux/module.h>
14 #include <linux/gpio/consumer.h>
23 enum usb4604_mode mode
;
25 struct gpio_desc
*gpio_reset
;
28 static void usb4604_reset(struct usb4604
*hub
, int state
)
30 gpiod_set_value_cansleep(hub
->gpio_reset
, state
);
32 /* Wait for i2c logic to come up */
37 static int usb4604_connect(struct usb4604
*hub
)
39 struct device
*dev
= hub
->dev
;
40 struct i2c_client
*client
= to_i2c_client(dev
);
42 u8 connect_cmd
[] = { 0xaa, 0x55, 0x00 };
44 usb4604_reset(hub
, 1);
46 err
= i2c_master_send(client
, connect_cmd
, ARRAY_SIZE(connect_cmd
));
48 usb4604_reset(hub
, 0);
52 hub
->mode
= USB4604_MODE_HUB
;
53 dev_dbg(dev
, "switched to HUB mode\n");
58 static int usb4604_switch_mode(struct usb4604
*hub
, enum usb4604_mode mode
)
60 struct device
*dev
= hub
->dev
;
64 case USB4604_MODE_HUB
:
65 err
= usb4604_connect(hub
);
68 case USB4604_MODE_STANDBY
:
69 usb4604_reset(hub
, 0);
70 dev_dbg(dev
, "switched to STANDBY mode\n");
74 dev_err(dev
, "unknown mode is requested\n");
82 static int usb4604_probe(struct usb4604
*hub
)
84 struct device
*dev
= hub
->dev
;
85 struct device_node
*np
= dev
->of_node
;
86 struct gpio_desc
*gpio
;
87 u32 mode
= USB4604_MODE_HUB
;
89 gpio
= devm_gpiod_get_optional(dev
, "reset", GPIOD_OUT_LOW
);
92 hub
->gpio_reset
= gpio
;
94 if (of_property_read_u32(np
, "initial-mode", &hub
->mode
))
97 return usb4604_switch_mode(hub
, hub
->mode
);
100 static int usb4604_i2c_probe(struct i2c_client
*i2c
,
101 const struct i2c_device_id
*id
)
105 hub
= devm_kzalloc(&i2c
->dev
, sizeof(*hub
), GFP_KERNEL
);
109 i2c_set_clientdata(i2c
, hub
);
110 hub
->dev
= &i2c
->dev
;
112 return usb4604_probe(hub
);
115 #ifdef CONFIG_PM_SLEEP
116 static int usb4604_i2c_suspend(struct device
*dev
)
118 struct i2c_client
*client
= to_i2c_client(dev
);
119 struct usb4604
*hub
= i2c_get_clientdata(client
);
121 usb4604_switch_mode(hub
, USB4604_MODE_STANDBY
);
126 static int usb4604_i2c_resume(struct device
*dev
)
128 struct i2c_client
*client
= to_i2c_client(dev
);
129 struct usb4604
*hub
= i2c_get_clientdata(client
);
131 usb4604_switch_mode(hub
, hub
->mode
);
137 static SIMPLE_DEV_PM_OPS(usb4604_i2c_pm_ops
, usb4604_i2c_suspend
,
140 static const struct i2c_device_id usb4604_id
[] = {
144 MODULE_DEVICE_TABLE(i2c
, usb4604_id
);
147 static const struct of_device_id usb4604_of_match
[] = {
148 { .compatible
= "smsc,usb4604" },
151 MODULE_DEVICE_TABLE(of
, usb4604_of_match
);
154 static struct i2c_driver usb4604_i2c_driver
= {
157 .pm
= &usb4604_i2c_pm_ops
,
158 .of_match_table
= of_match_ptr(usb4604_of_match
),
160 .probe
= usb4604_i2c_probe
,
161 .id_table
= usb4604_id
,
163 module_i2c_driver(usb4604_i2c_driver
);
165 MODULE_DESCRIPTION("USB4604 USB HUB driver");
166 MODULE_LICENSE("GPL v2");