代码:git clone https://github.com/chasinglulu/linux.git -b X4412-Kernel
问题描述
开发板移植linux-4.16.0内核和ubuntu-18.04文件系统,几乎所有的基本功能都能正常使用,但是在重启后,所有的USB设备不能被枚举,也就是驱动不能正常probe
问题分析
从硬件原理图上可以看到开发板使用了一个usb3503器件,这是一个usb hub。
在编译内核时,已经把usb3503的驱动编译进内核映像中,查看源代码,发现驱动会解析设备树中关于usb3503的配置节点,然而实际上,这个设备的I2C、INTN、connect引脚都是直接连到VDD或GND,只有RESET
引脚连接到GPC0_0
引脚上,也就是这个设备只能使用默认功能,其他可控制的功能不可能被使用,然后分析内核驱动代码,发现每次重启没有重新重设这个设备。
解决办法
设备树添加usb3503设备的节点
usb-hub {
compatible = "smsc,usb3503";
reset-gpios = <&gpc0 0 GPIO_ACTIVE_LOW>;
initial-mode = <2>;
};
修改驱动文件,有些功能不可能使用,所以修改部分代码,patch如下:
--- a/drivers/usb/misc/usb3503.c 2018-07-04 22:00:22.000000000 +0800
+++ b/drivers/usb/misc/usb3503.c 2018-07-05 19:49:00.760564394 +0800
@@ -43,97 +43,28 @@
struct usb3503 {
enum usb3503_mode mode;
- struct regmap *regmap;
struct device *dev;
- struct clk *clk;
- u8 port_off_mask;
- int gpio_intn;
int gpio_reset;
- int gpio_connect;
- bool secondary_ref_clk;
};
static int usb3503_reset(struct usb3503 *hub, int state)
{
- if (!state && gpio_is_valid(hub->gpio_connect))
- gpio_set_value_cansleep(hub->gpio_connect, 0);
-
if (gpio_is_valid(hub->gpio_reset))
gpio_set_value_cansleep(hub->gpio_reset, state);
/* Wait T_HUBINIT == 4ms for hub logic to stabilize */
- if (state)
+ if (!state)
usleep_range(4000, 10000);
return 0;
}
-static int usb3503_connect(struct usb3503 *hub)
-{
- struct device *dev = hub->dev;
- int err;
-
- usb3503_reset(hub, 1);
-
- if (hub->regmap) {
- /* SP_ILOCK: set connect_n, config_n for config */
- err = regmap_write(hub->regmap, USB3503_SP_ILOCK,
- (USB3503_SPILOCK_CONNECT
- | USB3503_SPILOCK_CONFIG));
- if (err < 0) {
- dev_err(dev, "SP_ILOCK failed (%d)\n", err);
- return err;
- }
-
- /* PDS : Set the ports which are disabled in self-powered mode. */
- if (hub->port_off_mask) {
- err = regmap_update_bits(hub->regmap, USB3503_PDS,
- hub->port_off_mask,
- hub->port_off_mask);
- if (err < 0) {
- dev_err(dev, "PDS failed (%d)\n", err);
-