X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=blobdiff_plain;f=drivers%2Fusb%2Fdwc_otg_310%2Fusbdev_rk32.c;h=5f383907261598e301d6655f53938fa8f8b6bffc;hp=52b643fc3fdd8eee09a86a2977fa037864e3b4cc;hb=9a47b6de548a83d198e2a92b53fe735c62832515;hpb=d4cb6899acfe231372e72c2e8b0c4e8f5f9efe15 diff --git a/drivers/usb/dwc_otg_310/usbdev_rk32.c b/drivers/usb/dwc_otg_310/usbdev_rk32.c old mode 100755 new mode 100644 index 52b643fc3fdd..5f3839072615 --- a/drivers/usb/dwc_otg_310/usbdev_rk32.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk32.c @@ -1,17 +1,25 @@ - +#ifdef CONFIG_ARM #include "usbdev_rk.h" #include "usbdev_grf_regs.h" #include "dwc_otg_regs.h" static struct dwc_otg_control_usb *control_usb; +int is_rk3288_usb(void) +{ + if (!control_usb) + return false; + + return control_usb->chip_id == RK3288_USB_CTLR ? true : false; +} + #ifdef CONFIG_USB20_OTG static void usb20otg_hw_init(void) { #ifndef CONFIG_USB20_HOST - //enable soft control - control_usb->grf_uoc2_base->CON2 = (0x01<<2)|((0x01<<2)<<16); - // enter suspend - control_usb->grf_uoc2_base->CON3 = 0x2A|(0x3F<<16); + /* enable soft control */ + control_usb->grf_uoc2_base->CON2 = (0x01 << 2) | ((0x01 << 2) << 16); + /* enter suspend */ + control_usb->grf_uoc2_base->CON3 = 0x2A | (0x3F << 16); #endif /* usb phy config init * usb phy enter usb mode */ @@ -19,56 +27,57 @@ static void usb20otg_hw_init(void) /* other haredware init,include: * DRV_VBUS GPIO init */ - if(gpio_get_value(control_usb->otg_gpios->gpio)){ - gpio_set_value(control_usb->otg_gpios->gpio, 0); + if (gpio_is_valid(control_usb->otg_gpios->gpio)) { + if (gpio_get_value(control_usb->otg_gpios->gpio)) + gpio_set_value(control_usb->otg_gpios->gpio, 0); } } -static void usb20otg_phy_suspend(void* pdata, int suspend) +static void usb20otg_phy_suspend(void *pdata, int suspend) { - struct dwc_otg_platform_data *usbpdata=pdata; - - if(suspend){ - //enable soft control - control_usb->grf_uoc0_base->CON2 = (0x01<<2)|((0x01<<2)<<16); - //enter suspend - control_usb->grf_uoc0_base->CON3 = 0x2A|(0x3F<<16); - mdelay(1); - /* set siddq,the analog blocks are powered down - * note: - * 1. Before asserting SIDDQ, ensure that VDATSRCENB0, - * VDATDETENB0, DCDENB0, BYPASSSEL0, ADPPRBENB0, - * and TESTBURNIN are set to 1'b0. - * 2. Before asserting SIDDQ, ensure that phy enter suspend.*/ - control_usb->grf_uoc0_base->CON0 = (0x01<<13)|((0x01<<13)<<16); + struct dwc_otg_platform_data *usbpdata = pdata; + + if (suspend) { + /* enable soft control */ + control_usb->grf_uoc0_base->CON2 = + (0x01 << 2) | ((0x01 << 2) << 16); + /* enter suspend */ + control_usb->grf_uoc0_base->CON3 = 0x2A | (0x3F << 16); usbpdata->phy_status = 1; - }else{ - /* unset siddq,the analog blocks are powered up */ - control_usb->grf_uoc0_base->CON0 = (0x01<<13)<<16; - mdelay(1); - //exit suspend - control_usb->grf_uoc0_base->CON2 = ((0x01<<2)<<16); + } else { + /* exit suspend */ + control_usb->grf_uoc0_base->CON2 = ((0x01 << 2) << 16); usbpdata->phy_status = 0; } } -static void usb20otg_soft_reset(void) +static void usb20otg_soft_reset(void *pdata, enum rkusb_rst_flag rst_type) { - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTG_H, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGPHY, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGC, true); - udelay(5); + struct dwc_otg_platform_data *usbpdata = pdata; + struct reset_control *rst_otg_h, *rst_otg_p, *rst_otg_c; + + rst_otg_h = devm_reset_control_get(usbpdata->dev, "otg_ahb"); + rst_otg_p = devm_reset_control_get(usbpdata->dev, "otg_phy"); + rst_otg_c = devm_reset_control_get(usbpdata->dev, "otg_controller"); + if (IS_ERR(rst_otg_h) || IS_ERR(rst_otg_p) || IS_ERR(rst_otg_c)) { + dev_err(usbpdata->dev, "Fail to get reset control from dts\n"); + return; + } - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTG_H, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGPHY, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGC, false); + reset_control_assert(rst_otg_h); + reset_control_assert(rst_otg_p); + reset_control_assert(rst_otg_c); + udelay(5); + reset_control_deassert(rst_otg_h); + reset_control_deassert(rst_otg_p); + reset_control_deassert(rst_otg_c); mdelay(2); } -static void usb20otg_clock_init(void* pdata) +static void usb20otg_clock_init(void *pdata) { - struct dwc_otg_platform_data *usbpdata=pdata; - struct clk* ahbclk,*phyclk; + struct dwc_otg_platform_data *usbpdata = pdata; + struct clk *ahbclk, *phyclk; ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb0"); if (IS_ERR(ahbclk)) { @@ -86,14 +95,14 @@ static void usb20otg_clock_init(void* pdata) usbpdata->ahbclk = ahbclk; } -static void usb20otg_clock_enable(void* pdata, int enable) +static void usb20otg_clock_enable(void *pdata, int enable) { - struct dwc_otg_platform_data *usbpdata=pdata; + struct dwc_otg_platform_data *usbpdata = pdata; - if(enable){ + if (enable) { clk_prepare_enable(usbpdata->ahbclk); clk_prepare_enable(usbpdata->phyclk); - }else{ + } else { clk_disable_unprepare(usbpdata->ahbclk); clk_disable_unprepare(usbpdata->phyclk); } @@ -103,59 +112,89 @@ static int usb20otg_get_status(int id) { int ret = -1; - switch(id){ - case USB_STATUS_BVABLID: - // bvalid in grf - ret = control_usb->grf_soc_status2_rk3288->otg_bvalid; - break; - case USB_STATUS_DPDM: - // dpdm in grf - ret = control_usb->grf_soc_status2_rk3288->otg_linestate; - break; - case USB_STATUS_ID: - // id in grf - ret = control_usb->grf_soc_status2_rk3288->otg_iddig; - break; - case USB_CHIP_ID: - ret = control_usb->chip_id; - break; - case USB_REMOTE_WAKEUP: - ret = control_usb->remote_wakeup; - break; - case USB_IRQ_WAKEUP: - ret = control_usb->usb_irq_wakeup; - break; - default: - break; + switch (id) { + case USB_STATUS_BVABLID: + /* bvalid in grf */ + ret = control_usb->grf_soc_status2_rk3288->otg_bvalid; + break; + case USB_STATUS_DPDM: + /* dpdm in grf */ + ret = control_usb->grf_soc_status2_rk3288->otg_linestate; + break; + case USB_STATUS_ID: + /* id in grf */ + ret = control_usb->grf_soc_status2_rk3288->otg_iddig; + break; + case USB_CHIP_ID: + ret = control_usb->chip_id; + break; + case USB_REMOTE_WAKEUP: + ret = control_usb->remote_wakeup; + break; + case USB_IRQ_WAKEUP: + ret = control_usb->usb_irq_wakeup; + break; + default: + break; } return ret; } #ifdef CONFIG_RK_USB_UART -static void dwc_otg_uart_mode(void* pdata, int enter_usb_uart_mode) +/** + * dwc_otg_uart_enabled - check if a usb-uart bypass func is enabled in DT + * + * Returns true if the status property of node "usb_uart" is set to "okay" + * or "ok", if this property is absent it will use the default status "ok" + * 0 otherwise + */ +static bool dwc_otg_uart_enabled(void) { - if(1 == enter_usb_uart_mode){ - /* bypass dm, enter uart mode*/ + struct device_node *np; + + np = of_find_node_by_name(NULL, "usb_uart"); + if (np && of_device_is_available(np)) + return true; + + return false; +} + +static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode) +{ + if ((1 == enter_usb_uart_mode) && dwc_otg_uart_enabled()) { + /* bypass dm, enter uart mode */ control_usb->grf_uoc0_base->CON3 = (0x00c0 | (0x00c0 << 16)); - - }else if(0 == enter_usb_uart_mode){ + + } else if (0 == enter_usb_uart_mode) { /* enter usb mode */ control_usb->grf_uoc0_base->CON3 = (0x00c0 << 16); } } +#else +static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode) +{ +} #endif static void usb20otg_power_enable(int enable) { - if(0 == enable){//disable otg_drv power - gpio_set_value(control_usb->otg_gpios->gpio, 0); - }else if(1 == enable){//enable otg_drv power - gpio_set_value(control_usb->otg_gpios->gpio, 1); + if (0 == enable) { + /* disable otg_drv power */ + if (gpio_is_valid(control_usb->otg_gpios->gpio)) + gpio_set_value(control_usb->otg_gpios->gpio, 0); + + rk_battery_charger_detect_cb(USB_OTG_POWER_OFF); + } else if (1 == enable) { + /* enable otg_drv power */ + if (gpio_is_valid(control_usb->otg_gpios->gpio)) + gpio_set_value(control_usb->otg_gpios->gpio, 1); + + if (!usb20otg_get_status(USB_STATUS_BVABLID)) + rk_battery_charger_detect_cb(USB_OTG_POWER_ON); } } - struct dwc_otg_platform_data usb20otg_pdata_rk3288 = { .phyclk = NULL, .ahbclk = NULL, @@ -168,10 +207,8 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3288 = { .clock_enable = usb20otg_clock_enable, .get_status = usb20otg_get_status, .power_enable = usb20otg_power_enable, -#ifdef CONFIG_RK_USB_UART .dwc_otg_uart_mode = dwc_otg_uart_mode, -#endif - .bc_detect_cb=usb20otg_battery_charger_detect_cb, + .bc_detect_cb = rk_battery_charger_detect_cb, }; #endif @@ -182,57 +219,63 @@ static void usb20host_hw_init(void) { /* usb phy config init * set common_on = 0, in suspend mode, host1 PLL blocks remain powered. - * for RK3288, hsic and other modules use host1 (DWC_OTG) 480M phy clk. + * for RK3288, ehci1 and other modules use host1 (DWC_OTG) 480M phy clk. */ - control_usb->grf_uoc2_base->CON0 = (1<<16)|0; + control_usb->grf_uoc2_base->CON0 = (1 << 16) | 0; /* other haredware init,include: * DRV_VBUS GPIO init */ - if(!gpio_get_value(control_usb->host_gpios->gpio)){ - gpio_set_value(control_usb->host_gpios->gpio, 1); + if (gpio_is_valid(control_usb->host_gpios->gpio)) { + if (!gpio_get_value(control_usb->host_gpios->gpio)) + gpio_set_value(control_usb->host_gpios->gpio, 1); } } -static void usb20host_phy_suspend(void* pdata, int suspend) +static void usb20host_phy_suspend(void *pdata, int suspend) { - struct dwc_otg_platform_data *usbpdata=pdata; - - if(suspend){ - // enable soft control - control_usb->grf_uoc2_base->CON2 = (0x01<<2)|((0x01<<2)<<16); - // enter suspend - control_usb->grf_uoc2_base->CON3 = 0x2A|(0x3F<<16); - mdelay(1); - // set siddq - control_usb->grf_uoc2_base->CON0 = (0x01<<13)|((0x01<<13)<<16); + struct dwc_otg_platform_data *usbpdata = pdata; + + if (suspend) { + /* enable soft control */ + control_usb->grf_uoc2_base->CON2 = + (0x01 << 2) | ((0x01 << 2) << 16); + /* enter suspend */ + control_usb->grf_uoc2_base->CON3 = 0x2A | (0x3F << 16); usbpdata->phy_status = 1; - }else{ - // unset siddq - control_usb->grf_uoc2_base->CON0 = (0x01<<13)<<16; - mdelay(1); - // exit suspend - control_usb->grf_uoc2_base->CON2 = ((0x01<<2)<<16); + } else { + /* exit suspend */ + control_usb->grf_uoc2_base->CON2 = ((0x01 << 2) << 16); usbpdata->phy_status = 0; } } -static void usb20host_soft_reset(void) +static void usb20host_soft_reset(void *pdata, enum rkusb_rst_flag rst_type) { - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1_H, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1PHY, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1C, true); - udelay(5); + struct dwc_otg_platform_data *usbpdata = pdata; + struct reset_control *rst_host1_h, *rst_host1_p, *rst_host1_c; + + rst_host1_h = devm_reset_control_get(usbpdata->dev, "host1_ahb"); + rst_host1_p = devm_reset_control_get(usbpdata->dev, "host1_phy"); + rst_host1_c = devm_reset_control_get(usbpdata->dev, "host1_controller"); + if (IS_ERR(rst_host1_h) || IS_ERR(rst_host1_p) || IS_ERR(rst_host1_c)) { + dev_err(usbpdata->dev, "Fail to get reset control from dts\n"); + return; + } - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1_H, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1PHY, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1C, false); + reset_control_assert(rst_host1_h); + reset_control_assert(rst_host1_p); + reset_control_assert(rst_host1_c); + udelay(5); + reset_control_deassert(rst_host1_h); + reset_control_deassert(rst_host1_p); + reset_control_deassert(rst_host1_c); mdelay(2); } -static void usb20host_clock_init(void* pdata) +static void usb20host_clock_init(void *pdata) { - struct dwc_otg_platform_data *usbpdata=pdata; - struct clk* ahbclk, *phyclk, *phyclk_480m; + struct dwc_otg_platform_data *usbpdata = pdata; + struct clk *ahbclk, *phyclk, *phyclk_480m; ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb1"); if (IS_ERR(ahbclk)) { @@ -257,14 +300,14 @@ static void usb20host_clock_init(void* pdata) usbpdata->phyclk_480m = phyclk_480m; } -static void usb20host_clock_enable(void* pdata, int enable) +static void usb20host_clock_enable(void *pdata, int enable) { - struct dwc_otg_platform_data *usbpdata=pdata; + struct dwc_otg_platform_data *usbpdata = pdata; - if(enable){ + if (enable) { clk_prepare_enable(usbpdata->ahbclk); clk_prepare_enable(usbpdata->phyclk); - }else{ + } else { clk_disable_unprepare(usbpdata->ahbclk); clk_disable_unprepare(usbpdata->phyclk); } @@ -274,30 +317,30 @@ static int usb20host_get_status(int id) { int ret = -1; - switch(id){ - case USB_STATUS_BVABLID: - // bvalid in grf - ret = control_usb->grf_soc_status2_rk3288->host1_bvalid; - break; - case USB_STATUS_DPDM: - // dpdm in grf - ret = control_usb->grf_soc_status2_rk3288->host1_linestate; - break; - case USB_STATUS_ID: - // id in grf - ret = control_usb->grf_soc_status2_rk3288->host1_iddig; - break; - case USB_CHIP_ID: - ret = control_usb->chip_id; - break; - case USB_REMOTE_WAKEUP: - ret = control_usb->remote_wakeup; - break; - case USB_IRQ_WAKEUP: - ret = control_usb->usb_irq_wakeup; - break; - default: - break; + switch (id) { + case USB_STATUS_BVABLID: + /* bvalid in grf */ + ret = control_usb->grf_soc_status2_rk3288->host1_bvalid; + break; + case USB_STATUS_DPDM: + /* dpdm in grf */ + ret = control_usb->grf_soc_status2_rk3288->host1_linestate; + break; + case USB_STATUS_ID: + /* id in grf */ + ret = control_usb->grf_soc_status2_rk3288->host1_iddig; + break; + case USB_CHIP_ID: + ret = control_usb->chip_id; + break; + case USB_REMOTE_WAKEUP: + ret = control_usb->remote_wakeup; + break; + case USB_IRQ_WAKEUP: + ret = control_usb->usb_irq_wakeup; + break; + default: + break; } return ret; @@ -305,14 +348,17 @@ static int usb20host_get_status(int id) static void usb20host_power_enable(int enable) { - if(0 == enable){//disable host_drv power - //do not disable power in default - }else if(1 == enable){//enable host_drv power - gpio_set_value(control_usb->host_gpios->gpio, 1); + if (0 == enable) { + /* disable host_drv power */ + if (gpio_is_valid(control_usb->host_gpios->gpio)) + gpio_set_value(control_usb->host_gpios->gpio, 0); + } else if (1 == enable) { + /* enable host_drv power */ + if (gpio_is_valid(control_usb->host_gpios->gpio)) + gpio_set_value(control_usb->host_gpios->gpio, 1); } } - struct dwc_otg_platform_data usb20host_pdata_rk3288 = { .phyclk = NULL, .ahbclk = NULL, @@ -329,18 +375,19 @@ struct dwc_otg_platform_data usb20host_pdata_rk3288 = { #endif -#ifdef CONFIG_USB_EHCI_RKHSIC -static void rk_hsic_hw_init(void) +#ifdef CONFIG_USB_EHCI1_RK +static void rk_ehci1_hw_init(void) { - // usb phy config init - // hsic phy config init, set hsicphy_txsrtune - control_usb->grf_uoc3_base->CON0 = ((0xf<<6)<<16)|(0xf<<6); + /* usb phy config init + * ehci1 phy config init, set ehci1phy_txsrtune */ + control_usb->grf_uoc3_base->CON0 = ((0xf << 6) << 16) | (0xf << 6); /* other haredware init - * set common_on = 0, in suspend mode, otg/host PLL blocks remain powered + * set common_on = 0, in suspend mode, + * otg/host PLL blocks remain powered * for RK3288, use host1 (DWC_OTG) 480M phy clk */ - control_usb->grf_uoc2_base->CON0 = (1<<16)|0; + control_usb->grf_uoc2_base->CON0 = (1 << 16) | 0; /* change INCR to INCR16 or INCR8(beats less than 16) * or INCR4(beats less than 8) or SINGLE(beats less than 4) @@ -348,85 +395,91 @@ static void rk_hsic_hw_init(void) control_usb->grf_uoc4_base->CON0 = 0x00ff00bc; } -static void rk_hsic_clock_init(void* pdata) +static void rk_ehci1_clock_init(void *pdata) { - /* By default, hsicphy_480m's parent is otg phy 480MHz clk + /* By default, ehci1phy_480m's parent is otg phy 480MHz clk * rk3188 must use host phy 480MHz clk, because if otg bypass * to uart mode, otg phy 480MHz clk will be closed automatically */ - struct rkehci_platform_data *usbpdata=pdata; - struct clk *ahbclk, *phyclk480m_hsic, *phyclk12m_hsic; + struct rkehci_platform_data *usbpdata = pdata; + struct clk *ahbclk, *phyclk480m_ehci1, *phyclk12m_ehci1; - phyclk480m_hsic = devm_clk_get(usbpdata->dev, "hsicphy_480m"); - if (IS_ERR(phyclk480m_hsic)) { - dev_err(usbpdata->dev, "Failed to get hsicphy_480m\n"); + phyclk480m_ehci1 = devm_clk_get(usbpdata->dev, "ehci1phy_480m"); + if (IS_ERR(phyclk480m_ehci1)) { + dev_err(usbpdata->dev, "Failed to get ehci1phy_480m\n"); return; } - phyclk12m_hsic = devm_clk_get(usbpdata->dev, "hsicphy_12m"); - if (IS_ERR(phyclk12m_hsic)) { - dev_err(usbpdata->dev, "Failed to get hsicphy_12m\n"); + phyclk12m_ehci1 = devm_clk_get(usbpdata->dev, "ehci1phy_12m"); + if (IS_ERR(phyclk12m_ehci1)) { + dev_err(usbpdata->dev, "Failed to get ehci1phy_12m\n"); return; } - ahbclk = devm_clk_get(usbpdata->dev, "hclk_hsic"); + ahbclk = devm_clk_get(usbpdata->dev, "hclk_ehci1"); if (IS_ERR(ahbclk)) { - dev_err(usbpdata->dev, "Failed to get hclk_hsic\n"); + dev_err(usbpdata->dev, "Failed to get hclk_ehci1\n"); return; } - usbpdata->hclk_hsic = ahbclk; - usbpdata->hsic_phy_480m = phyclk480m_hsic; - usbpdata->hsic_phy_12m = phyclk12m_hsic; + usbpdata->hclk_ehci = ahbclk; + usbpdata->ehci_phy_480m = phyclk480m_ehci1; + usbpdata->ehci_phy_12m = phyclk12m_ehci1; } -static void rk_hsic_clock_enable(void* pdata, int enable) +static void rk_ehci1_clock_enable(void *pdata, int enable) { - struct rkehci_platform_data *usbpdata=pdata; + struct rkehci_platform_data *usbpdata = pdata; - if(enable == usbpdata->clk_status) + if (enable == usbpdata->clk_status) return; - if(enable){ - clk_prepare_enable(usbpdata->hclk_hsic); - clk_prepare_enable(usbpdata->hsic_phy_480m); - clk_prepare_enable(usbpdata->hsic_phy_12m); + if (enable) { + clk_prepare_enable(usbpdata->hclk_ehci); + clk_prepare_enable(usbpdata->ehci_phy_480m); + clk_prepare_enable(usbpdata->ehci_phy_12m); usbpdata->clk_status = 1; - }else{ - clk_disable_unprepare(usbpdata->hclk_hsic); - clk_disable_unprepare(usbpdata->hsic_phy_480m); - clk_disable_unprepare(usbpdata->hsic_phy_12m); + } else { + clk_disable_unprepare(usbpdata->hclk_ehci); + clk_disable_unprepare(usbpdata->ehci_phy_480m); + clk_disable_unprepare(usbpdata->ehci_phy_12m); usbpdata->clk_status = 0; } } -static void rk_hsic_soft_reset(void) +static void rk_ehci1_soft_reset(void *pdata, enum rkusb_rst_flag rst_type) { - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC_AUX, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSICPHY, true); - udelay(5); + struct rkehci_platform_data *usbpdata = pdata; + struct reset_control *rst_ehci1_h, *rst_ehci1_a, *rst_ehci1_p; - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC_AUX, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSICPHY, false); + rst_ehci1_h = devm_reset_control_get(usbpdata->dev, "ehci1_ahb"); + rst_ehci1_a = devm_reset_control_get(usbpdata->dev, "ehci1_aux"); + rst_ehci1_p = devm_reset_control_get(usbpdata->dev, "ehci1_phy"); + + reset_control_assert(rst_ehci1_h); + reset_control_assert(rst_ehci1_a); + reset_control_assert(rst_ehci1_p); + udelay(5); + reset_control_deassert(rst_ehci1_h); + reset_control_deassert(rst_ehci1_a); + reset_control_deassert(rst_ehci1_p); mdelay(2); - /* HSIC per-port reset */ - control_usb->grf_uoc3_base->CON0 = ((1<<10)<<16)|(1<<10); + /* EHCI1 per-port reset */ + control_usb->grf_uoc3_base->CON0 = ((1 << 10) << 16) | (1 << 10); udelay(2); - control_usb->grf_uoc3_base->CON0 = ((1<<10)<<16)|(0<<10); + control_usb->grf_uoc3_base->CON0 = ((1 << 10) << 16) | (0 << 10); udelay(2); } -struct rkehci_platform_data rkhsic_pdata_rk3288 = { - .hclk_hsic = NULL, - .hsic_phy_12m = NULL, - .hsic_phy_480m = NULL, +struct rkehci_platform_data rkehci1_pdata_rk3288 = { + .hclk_ehci = NULL, + .ehci_phy_12m = NULL, + .ehci_phy_480m = NULL, .clk_status = -1, - .hw_init = rk_hsic_hw_init, - .clock_init = rk_hsic_clock_init, - .clock_enable = rk_hsic_clock_enable, - .soft_reset = rk_hsic_soft_reset, + .hw_init = rk_ehci1_hw_init, + .clock_init = rk_ehci1_clock_init, + .clock_enable = rk_ehci1_clock_enable, + .soft_reset = rk_ehci1_soft_reset, }; #endif @@ -436,38 +489,34 @@ static void rk_ehci_hw_init(void) /* usb phy config init */ /* DRV_VBUS GPIO init */ - if(!gpio_get_value(control_usb->host_gpios->gpio)){ - gpio_set_value(control_usb->host_gpios->gpio, 1); + if (gpio_is_valid(control_usb->host_gpios->gpio)) { + if (!gpio_get_value(control_usb->host_gpios->gpio)) + gpio_set_value(control_usb->host_gpios->gpio, 1); } } -static void rk_ehci_phy_suspend(void* pdata, int suspend) +static void rk_ehci_phy_suspend(void *pdata, int suspend) { - struct rkehci_platform_data *usbpdata=pdata; - - if(suspend){ - // enable soft control - control_usb->grf_uoc1_base->CON2 = (0x01<<2)|((0x01<<2)<<16); - // enter suspend - control_usb->grf_uoc1_base->CON3 = 0x2A|(0x3F<<16); - mdelay(1); - // set siddq - control_usb->grf_uoc1_base->CON0 = (0x01<<13) | ((0x01<<13) << 16); + struct rkehci_platform_data *usbpdata = pdata; + + if (suspend) { + /* enable soft control */ + control_usb->grf_uoc1_base->CON2 = + (0x01 << 2) | ((0x01 << 2) << 16); + /* enter suspend */ + control_usb->grf_uoc1_base->CON3 = 0x2A | (0x3F << 16); usbpdata->phy_status = 1; - }else{ - // unset siddq - control_usb->grf_uoc1_base->CON0 = ((0x01<<13) << 16); - mdelay(1); - // exit suspend - control_usb->grf_uoc1_base->CON2 = ((0x01<<2)<<16); + } else { + /* exit suspend */ + control_usb->grf_uoc1_base->CON2 = ((0x01 << 2) << 16); usbpdata->phy_status = 0; } } -static void rk_ehci_clock_init(void* pdata) +static void rk_ehci_clock_init(void *pdata) { - struct rkehci_platform_data *usbpdata=pdata; - struct clk* ahbclk,*phyclk; + struct rkehci_platform_data *usbpdata = pdata; + struct clk *ahbclk, *phyclk; ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb2"); if (IS_ERR(ahbclk)) { @@ -485,35 +534,48 @@ static void rk_ehci_clock_init(void* pdata) usbpdata->ahbclk = ahbclk; } -static void rk_ehci_clock_enable(void* pdata, int enable) +static void rk_ehci_clock_enable(void *pdata, int enable) { - struct rkehci_platform_data *usbpdata=pdata; + struct rkehci_platform_data *usbpdata = pdata; - if(enable == usbpdata->clk_status) + if (enable == usbpdata->clk_status) return; - if(enable){ + if (enable) { clk_prepare_enable(usbpdata->ahbclk); clk_prepare_enable(usbpdata->phyclk); usbpdata->clk_status = 1; - }else{ + } else { clk_disable_unprepare(usbpdata->ahbclk); clk_disable_unprepare(usbpdata->phyclk); usbpdata->clk_status = 0; } } -static void rk_ehci_soft_reset(void) +static void rk_ehci_soft_reset(void *pdata, enum rkusb_rst_flag rst_type) { - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0_H, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0PHY, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0C, true); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USB_HOST0, true); - udelay(5); + struct rkehci_platform_data *usbpdata = pdata; + struct reset_control *rst_host0_h, *rst_host0_p, + *rst_host0_c , *rst_host0; + + rst_host0_h = devm_reset_control_get(usbpdata->dev, "ehci_ahb"); + rst_host0_p = devm_reset_control_get(usbpdata->dev, "ehci_phy"); + rst_host0_c = devm_reset_control_get(usbpdata->dev, "ehci_controller"); + rst_host0 = devm_reset_control_get(usbpdata->dev, "ehci"); + if (IS_ERR(rst_host0_h) || IS_ERR(rst_host0_p) || + IS_ERR(rst_host0_c) || IS_ERR(rst_host0)) { + dev_err(usbpdata->dev, "Fail to get reset control from dts\n"); + return; + } - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0_H, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0PHY, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0C, false); - rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USB_HOST0, false); + reset_control_assert(rst_host0_h); + reset_control_assert(rst_host0_p); + reset_control_assert(rst_host0_c); + reset_control_assert(rst_host0); + udelay(5); + reset_control_deassert(rst_host0_h); + reset_control_deassert(rst_host0_p); + reset_control_deassert(rst_host0_c); + reset_control_deassert(rst_host0); mdelay(2); } @@ -521,22 +583,22 @@ static int rk_ehci_get_status(int id) { int ret = -1; - switch(id){ - case USB_STATUS_DPDM: - // dpdm in grf - ret = control_usb->grf_soc_status2_rk3288->host0_linestate; - break; - case USB_CHIP_ID: - ret = control_usb->chip_id; - break; - case USB_REMOTE_WAKEUP: - ret = control_usb->remote_wakeup; - break; - case USB_IRQ_WAKEUP: - ret = control_usb->usb_irq_wakeup; - break; - default: - break; + switch (id) { + case USB_STATUS_DPDM: + /* dpdm in grf */ + ret = control_usb->grf_soc_status2_rk3288->host0_linestate; + break; + case USB_CHIP_ID: + ret = control_usb->chip_id; + break; + case USB_REMOTE_WAKEUP: + ret = control_usb->remote_wakeup; + break; + case USB_IRQ_WAKEUP: + ret = control_usb->usb_irq_wakeup; + break; + default: + break; } return ret; @@ -562,23 +624,24 @@ static void rk_ohci_hw_init(void) /* usb phy config init */ /* DRV_VBUS GPIO init */ - if(!gpio_get_value(control_usb->host_gpios->gpio)){ - gpio_set_value(control_usb->host_gpios->gpio, 1); + if (gpio_is_valid(control_usb->host_gpios->gpio)) { + if (!gpio_get_value(control_usb->host_gpios->gpio)) + gpio_set_value(control_usb->host_gpios->gpio, 1); } } -static void rk_ohci_clock_init(void* pdata) +static void rk_ohci_clock_init(void *pdata) { - struct rkehci_platform_data *usbpdata=pdata; - struct clk* ahbclk,*phyclk; + struct rkehci_platform_data *usbpdata = pdata; + struct clk *ahbclk, *phyclk; - ahbclk =devm_clk_get(usbpdata->dev, "hclk_usb3"); + ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb3"); if (IS_ERR(ahbclk)) { dev_err(usbpdata->dev, "Failed to get hclk_usb3\n"); return; } - phyclk = devm_clk_get(usbpdata->dev, "clk_usbphy3");; + phyclk = devm_clk_get(usbpdata->dev, "clk_usbphy3"); if (IS_ERR(phyclk)) { dev_err(usbpdata->dev, "Failed to get clk_usbphy3\n"); return; @@ -588,24 +651,24 @@ static void rk_ohci_clock_init(void* pdata) usbpdata->ahbclk = ahbclk; } -static void rk_ohci_clock_enable(void* pdata, int enable) +static void rk_ohci_clock_enable(void *pdata, int enable) { - struct rkehci_platform_data *usbpdata=pdata; + struct rkehci_platform_data *usbpdata = pdata; - if(enable == usbpdata->clk_status) + if (enable == usbpdata->clk_status) return; - if(enable){ + if (enable) { clk_prepare_enable(usbpdata->ahbclk); clk_prepare_enable(usbpdata->phyclk); usbpdata->clk_status = 1; - }else{ + } else { clk_disable_unprepare(usbpdata->ahbclk); clk_disable_unprepare(usbpdata->phyclk); usbpdata->clk_status = 0; } } -static void rk_ohci_soft_reset(void) +static void rk_ohci_soft_reset(void *pdata, enum rkusb_rst_flag rst_type) { } @@ -621,37 +684,37 @@ struct rkehci_platform_data rkohci_pdata_rk3288 = { #endif /********************************************************************* - rk3288 usb detections + rk3288 usb detections *********************************************************************/ #define WAKE_LOCK_TIMEOUT (HZ * 10) -inline static void do_wakeup(struct work_struct *work) +static inline void do_wakeup(struct work_struct *work) { - rk_send_wakeup_key(); // wake up the system + /* wake up the system */ + rk_send_wakeup_key(); } static void usb_battery_charger_detect_work(struct work_struct *work) { - rk_usb_charger_status = usb_battery_charger_detect(0); + rk_battery_charger_detect_cb(usb_battery_charger_detect(1)); } + /********** handler for bvalid irq **********/ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) { /* clear irq */ control_usb->grf_uoc0_base->CON4 = (0x0008 | (0x0008 << 16)); -#ifdef CONFIG_RK_USB_UART /* usb otg dp/dm switch to usb phy */ dwc_otg_uart_mode(NULL, PHY_USB_MODE); -#endif - if(control_usb->usb_irq_wakeup){ - wake_lock_timeout(&control_usb->usb_wakelock, WAKE_LOCK_TIMEOUT); - schedule_delayed_work(&control_usb->usb_det_wakeup_work, HZ/10); + if (control_usb->usb_irq_wakeup) { + wake_lock_timeout(&control_usb->usb_wakelock, + WAKE_LOCK_TIMEOUT); + schedule_delayed_work(&control_usb->usb_det_wakeup_work, + HZ / 10); } - - rk_usb_charger_status = USB_BC_TYPE_SDP; - schedule_delayed_work(&control_usb->usb_charger_det_work, HZ/10); + schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10); return IRQ_HANDLED; } @@ -659,145 +722,146 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) /***** handler for otg id rise and fall edge *****/ static irqreturn_t id_irq_handler(int irq, void *dev_id) { - unsigned int uoc_con; - - /* clear irq */ - uoc_con = control_usb->grf_uoc0_base->CON4; - - if(uoc_con & (1<<5))//id rise - { - control_usb->grf_uoc0_base->CON4 = ((1<<5)|(1<<21)); //clear id rise irq pandding - } - - if(uoc_con & (1<<7))//id fall - { -#ifdef CONFIG_RK_USB_UART - /* usb otg dp/dm switch to usb phy */ - dwc_otg_uart_mode(NULL, PHY_USB_MODE); -#endif - control_usb->grf_uoc0_base->CON4 = ((1<<7)|(1<<23));//clear id fall irq pandding - } + unsigned int uoc_con; + + /* clear irq */ + uoc_con = control_usb->grf_uoc0_base->CON4; + + /* id rise */ + if (uoc_con & (1 << 5)) { + /* clear id rise irq pandding */ + control_usb->grf_uoc0_base->CON4 = ((1 << 5) | (1 << 21)); + } + + /* id fall */ + if (uoc_con & (1 << 7)) { + /* usb otg dp/dm switch to usb phy */ + dwc_otg_uart_mode(NULL, PHY_USB_MODE); + /* clear id fall irq pandding */ + control_usb->grf_uoc0_base->CON4 = ((1 << 7) | (1 << 23)); + } - if(control_usb->usb_irq_wakeup){ - wake_lock_timeout(&control_usb->usb_wakelock, WAKE_LOCK_TIMEOUT); - schedule_delayed_work(&control_usb->usb_det_wakeup_work, HZ/10); + if (control_usb->usb_irq_wakeup) { + wake_lock_timeout(&control_usb->usb_wakelock, + WAKE_LOCK_TIMEOUT); + schedule_delayed_work(&control_usb->usb_det_wakeup_work, + HZ / 10); } - return IRQ_HANDLED; + return IRQ_HANDLED; } -/***** handler for otg line status change *****/ +#ifdef USB_LINESTATE_IRQ +/***** handler for usb line status change *****/ static irqreturn_t line_irq_handler(int irq, void *dev_id) { - /* clear irq */ - - if(control_usb->grf_uoc0_base->CON0 & 1<<15){ - control_usb->grf_uoc0_base->CON0 = (1<<15 | 1<<31); - } - - if(control_usb->grf_uoc1_base->CON0 & 1<<15){ - control_usb->grf_uoc1_base->CON0 = (1<<15 | 1<<31); - } - - if(control_usb->grf_uoc2_base->CON0 & 1<<15){ - control_usb->grf_uoc2_base->CON0 = (1<<15 | 1<<31); - } - - if(control_usb->usb_irq_wakeup){ - wake_lock_timeout(&control_usb->usb_wakelock, WAKE_LOCK_TIMEOUT); - schedule_delayed_work(&control_usb->usb_det_wakeup_work, HZ/10); + /* clear irq */ + + if (control_usb->grf_uoc0_base->CON0 & 1 << 15) + control_usb->grf_uoc0_base->CON0 = (1 << 15 | 1 << 31); + + if (control_usb->grf_uoc1_base->CON0 & 1 << 15) + control_usb->grf_uoc1_base->CON0 = (1 << 15 | 1 << 31); + + if (control_usb->grf_uoc2_base->CON0 & 1 << 15) + control_usb->grf_uoc2_base->CON0 = (1 << 15 | 1 << 31); + + if (control_usb->usb_irq_wakeup) { + wake_lock_timeout(&control_usb->usb_wakelock, + WAKE_LOCK_TIMEOUT); + schedule_delayed_work(&control_usb->usb_det_wakeup_work, + HZ / 10); } - return IRQ_HANDLED; + return IRQ_HANDLED; } +#endif /************* register usb detection irqs **************/ static int otg_irq_detect_init(struct platform_device *pdev) { int ret = 0; int irq = 0; - - if(control_usb->usb_irq_wakeup){ - wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect"); + if (control_usb->usb_irq_wakeup) { + wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND, + "usb_detect"); INIT_DELAYED_WORK(&control_usb->usb_det_wakeup_work, do_wakeup); } - /*register otg_bvalid irq*/ + /*register otg_bvalid irq */ irq = platform_get_irq_byname(pdev, "otg_bvalid"); - if (irq > 0) { - ret = request_irq(irq, bvalid_irq_handler, 0, "otg_bvalid", NULL); - if(ret < 0){ + if ((irq > 0) && control_usb->usb_irq_wakeup) { + ret = request_irq(irq, bvalid_irq_handler, + 0, "otg_bvalid", NULL); + if (ret < 0) { dev_err(&pdev->dev, "request_irq %d failed!\n", irq); - return ret; - }else{ - control_usb->grf_uoc0_base->CON4 = 0x000c000c;// enable bvalid irq - if(control_usb->usb_irq_wakeup){ - enable_irq_wake(irq); - } + } else { + /* enable bvalid irq */ + control_usb->grf_uoc0_base->CON4 = 0x000c000c; } } -#if 0 - /*register otg_id irq*/ - irq = platform_get_irq_byname(pdev, "otg_id"); - if(irq > 0){ - ret = request_irq(irq, id_irq_handler, 0, "otg_id", NULL); - if(ret < 0){ + + /*register otg_id irq */ + irq = platform_get_irq_byname(pdev, "otg_id"); + if ((irq > 0) && control_usb->usb_irq_wakeup) { + ret = request_irq(irq, id_irq_handler, 0, "otg_id", NULL); + if (ret < 0) { dev_err(&pdev->dev, "request_irq %d failed!\n", irq); - return ret; - }else{ - control_usb->grf_uoc0_base->CON4 = 0x00f000f0; - if(control_usb->usb_irq_wakeup){ - enable_irq_wake(irq); - } + } else { + /* enable otg_id irq */ + control_usb->grf_uoc0_base->CON4 = 0x00f000f0; } - } - - /*register otg_linestate irq*/ - irq = platform_get_irq_byname(pdev, "otg_linestate"); - if(irq > 0){ - ret = request_irq(irq, line_irq_handler, 0, "otg_linestate", NULL); - if(ret < 0){ + } +#if 0 + /*register otg_linestate irq */ + irq = platform_get_irq_byname(pdev, "otg_linestate"); + if (irq > 0) { + ret = + request_irq(irq, line_irq_handler, 0, "otg_linestate", + NULL); + if (ret < 0) { dev_err(&pdev->dev, "request_irq %d failed!\n", irq); return ret; - }else{ - control_usb->grf_uoc0_base->CON0 = 0xc000c000; - if(control_usb->usb_irq_wakeup){ - enable_irq_wake(irq); - } + } else { + control_usb->grf_uoc0_base->CON0 = 0xc000c000; + if (control_usb->usb_irq_wakeup) + enable_irq_wake(irq); } - } - - /*register host0_linestate irq*/ - irq = platform_get_irq_byname(pdev, "host0_linestate"); - if(irq > 0){ - ret = request_irq(irq, line_irq_handler, 0, "host0_linestate", NULL); - if(ret < 0){ + } + + /*register host0_linestate irq */ + irq = platform_get_irq_byname(pdev, "host0_linestate"); + if (irq > 0) { + ret = + request_irq(irq, line_irq_handler, 0, "host0_linestate", + NULL); + if (ret < 0) { dev_err(&pdev->dev, "request_irq %d failed!\n", irq); return ret; - }else{ - control_usb->grf_uoc1_base->CON0 = 0xc000c000; - if(control_usb->usb_irq_wakeup){ - enable_irq_wake(irq); - } + } else { + control_usb->grf_uoc1_base->CON0 = 0xc000c000; + if (control_usb->usb_irq_wakeup) + enable_irq_wake(irq); } - } - - /*register host1_linestate irq*/ - irq = platform_get_irq_byname(pdev, "host1_linestate"); - if(irq > 0){ - ret = request_irq(irq, line_irq_handler, 0, "host1_linestate", NULL); - if(ret < 0){ + } + + /*register host1_linestate irq */ + irq = platform_get_irq_byname(pdev, "host1_linestate"); + if (irq > 0) { + ret = + request_irq(irq, line_irq_handler, 0, "host1_linestate", + NULL); + if (ret < 0) { dev_err(&pdev->dev, "request_irq %d failed!\n", irq); return ret; - }else{ - control_usb->grf_uoc2_base->CON0 = 0xc000c000; - if(control_usb->usb_irq_wakeup){ - enable_irq_wake(irq); - } + } else { + control_usb->grf_uoc2_base->CON0 = 0xc000c000; + if (control_usb->usb_irq_wakeup) + enable_irq_wake(irq); } - } -#endif + } +#endif return ret; } @@ -818,216 +882,213 @@ static int usb_grf_ioremap(struct platform_device *pdev) void *grf_uoc4_base; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_SOC_STATUS1"); + "GRF_SOC_STATUS1"); grf_soc_status1 = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_soc_status1)){ + if (IS_ERR(grf_soc_status1)) { ret = PTR_ERR(grf_soc_status1); return ret; } - control_usb->grf_soc_status1_rk3288 = (pGRF_SOC_STATUS1_RK3288)grf_soc_status1; + control_usb->grf_soc_status1_rk3288 = + (pGRF_SOC_STATUS1_RK3288) grf_soc_status1; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_SOC_STATUS2"); + "GRF_SOC_STATUS2"); grf_soc_status2 = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_soc_status2)){ + if (IS_ERR(grf_soc_status2)) { ret = PTR_ERR(grf_soc_status2); return ret; } - control_usb->grf_soc_status2_rk3288 = (pGRF_SOC_STATUS2_RK3288)grf_soc_status2; + control_usb->grf_soc_status2_rk3288 = + (pGRF_SOC_STATUS2_RK3288) grf_soc_status2; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_SOC_STATUS19"); + "GRF_SOC_STATUS19"); grf_soc_status19 = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_soc_status19)){ + if (IS_ERR(grf_soc_status19)) { ret = PTR_ERR(grf_soc_status19); return ret; } - control_usb->grf_soc_status19_rk3288 = (pGRF_SOC_STATUS19_RK3288)grf_soc_status19; + control_usb->grf_soc_status19_rk3288 = + (pGRF_SOC_STATUS19_RK3288) grf_soc_status19; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_SOC_STATUS21"); + "GRF_SOC_STATUS21"); grf_soc_status21 = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_soc_status21)){ + if (IS_ERR(grf_soc_status21)) { ret = PTR_ERR(grf_soc_status21); return ret; } - control_usb->grf_soc_status21_rk3288 = (pGRF_SOC_STATUS21_RK3288)grf_soc_status21; + control_usb->grf_soc_status21_rk3288 = + (pGRF_SOC_STATUS21_RK3288) grf_soc_status21; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_UOC0_BASE"); + "GRF_UOC0_BASE"); grf_uoc0_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_uoc0_base)){ + if (IS_ERR(grf_uoc0_base)) { ret = PTR_ERR(grf_uoc0_base); return ret; } - control_usb->grf_uoc0_base = (pGRF_UOC0_REG)grf_uoc0_base; + control_usb->grf_uoc0_base = (pGRF_UOC0_REG) grf_uoc0_base; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_UOC1_BASE"); + "GRF_UOC1_BASE"); grf_uoc1_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_uoc1_base)){ + if (IS_ERR(grf_uoc1_base)) { ret = PTR_ERR(grf_uoc1_base); return ret; } - control_usb->grf_uoc1_base = (pGRF_UOC1_REG)grf_uoc1_base; + control_usb->grf_uoc1_base = (pGRF_UOC1_REG) grf_uoc1_base; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_UOC2_BASE"); + "GRF_UOC2_BASE"); grf_uoc2_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_uoc2_base)){ + if (IS_ERR(grf_uoc2_base)) { ret = PTR_ERR(grf_uoc2_base); return ret; } - control_usb->grf_uoc2_base = (pGRF_UOC2_REG)grf_uoc2_base; + control_usb->grf_uoc2_base = (pGRF_UOC2_REG) grf_uoc2_base; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_UOC3_BASE"); + "GRF_UOC3_BASE"); grf_uoc3_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_uoc3_base)){ + if (IS_ERR(grf_uoc3_base)) { ret = PTR_ERR(grf_uoc3_base); return ret; } - control_usb->grf_uoc3_base = (pGRF_UOC3_REG)grf_uoc3_base; + control_usb->grf_uoc3_base = (pGRF_UOC3_REG) grf_uoc3_base; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "GRF_UOC4_BASE"); + "GRF_UOC4_BASE"); grf_uoc4_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(grf_uoc4_base)){ + if (IS_ERR(grf_uoc4_base)) { ret = PTR_ERR(grf_uoc4_base); return ret; } - control_usb->grf_uoc4_base = (pGRF_UOC4_REG)grf_uoc4_base; + control_usb->grf_uoc4_base = (pGRF_UOC4_REG) grf_uoc4_base; return ret; } -#ifdef CONFIG_OF - -static const struct of_device_id dwc_otg_control_usb_id_table[] = { - { - .compatible = "rockchip,rk3288-dwc-control-usb", - }, - { }, -}; - -#endif - -static int dwc_otg_control_usb_probe(struct platform_device *pdev) +static int rk_usb_control_probe(struct platform_device *pdev) { int gpio, err; struct device_node *np = pdev->dev.of_node; - struct clk* hclk_usb_peri, *phyclk_480m, *phyclk480m_parent; int ret = 0; - control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),GFP_KERNEL); + control_usb = + devm_kzalloc(&pdev->dev, sizeof(*control_usb), GFP_KERNEL); if (!control_usb) { dev_err(&pdev->dev, "unable to alloc memory for control usb\n"); - ret = -ENOMEM; - goto err1; + ret = -ENOMEM; + goto out; } control_usb->chip_id = RK3288_USB_CTLR; control_usb->remote_wakeup = of_property_read_bool(np, - "rockchip,remote_wakeup"); + "rockchip,remote_wakeup"); control_usb->usb_irq_wakeup = of_property_read_bool(np, - "rockchip,usb_irq_wakeup"); + "rockchip,usb_irq_wakeup"); - INIT_DELAYED_WORK(&control_usb->usb_charger_det_work, usb_battery_charger_detect_work); + INIT_DELAYED_WORK(&control_usb->usb_charger_det_work, + usb_battery_charger_detect_work); - hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri"); - if (IS_ERR(hclk_usb_peri)) { - dev_err(&pdev->dev, "Failed to get hclk_usb_peri\n"); - ret = -EINVAL; - goto err1; + control_usb->host_gpios = + devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL); + if (!control_usb->host_gpios) { + dev_err(&pdev->dev, "unable to alloc memory for host_gpios\n"); + ret = -ENOMEM; + goto out; } - control_usb->hclk_usb_peri = hclk_usb_peri; - clk_prepare_enable(hclk_usb_peri); + gpio = of_get_named_gpio(np, "host_drv_gpio", 0); + control_usb->host_gpios->gpio = gpio; - phyclk480m_parent = devm_clk_get(&pdev->dev, "usbphy2_480m"); - if (IS_ERR(phyclk480m_parent)) { - dev_err(&pdev->dev, "Failed to get usbphy2_480m\n"); - goto err2; + if (!gpio_is_valid(gpio)) { + dev_warn(&pdev->dev, "host_drv_gpio is not specified or invalid\n"); + } else { + err = devm_gpio_request(&pdev->dev, gpio, "host_drv_gpio"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for host_drv\n", + gpio); + ret = err; + goto out; + } + gpio_direction_output(control_usb->host_gpios->gpio, 1); } - phyclk_480m = devm_clk_get(&pdev->dev, "usbphy_480m"); - if (IS_ERR(phyclk_480m)) { - dev_err(&pdev->dev, "Failed to get usbphy_480m\n"); - goto err2; + control_usb->otg_gpios = + devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL); + if (!control_usb->otg_gpios) { + dev_err(&pdev->dev, "unable to alloc memory for otg_gpios\n"); + ret = -ENOMEM; + goto out; } - clk_set_parent(phyclk_480m, phyclk480m_parent); + gpio = of_get_named_gpio(np, "otg_drv_gpio", 0); + control_usb->otg_gpios->gpio = gpio; - ret = usb_grf_ioremap(pdev); - if(ret){ - dev_err(&pdev->dev, "Failed to ioremap usb grf\n"); - goto err2; + if (!gpio_is_valid(gpio)) { + dev_warn(&pdev->dev, "otg_drv_gpio is not specified or invalid\n"); + } else { + err = devm_gpio_request(&pdev->dev, gpio, "otg_drv_gpio"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for otg_drv\n", gpio); + ret = err; + goto out; + } + gpio_direction_output(control_usb->otg_gpios->gpio, 0); } - control_usb->host_gpios = devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL); - if(!control_usb->host_gpios){ - dev_err(&pdev->dev, "unable to alloc memory for host_gpios\n"); - ret = -ENOMEM; - goto err2; - } +out: + return ret; +} - gpio = of_get_named_gpio(np, "gpios", 0); - if(!gpio_is_valid(gpio)){ - dev_err(&pdev->dev, "invalid host gpio%d\n", gpio); - ret = -EINVAL; - goto err2; - } - control_usb->host_gpios->gpio = gpio; - err = devm_gpio_request(&pdev->dev, gpio, "host_drv_gpio"); - if (err) { - dev_err(&pdev->dev, - "failed to request GPIO%d for host_drv\n", - gpio); - ret = err; - goto err2; - } - gpio_direction_output(control_usb->host_gpios->gpio, 1); +#ifdef CONFIG_OF +static const struct of_device_id dwc_otg_control_usb_id_table[] = { + { + .compatible = "rockchip,rk3288-dwc-control-usb", + }, + {}, +}; +#endif - control_usb->otg_gpios = devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL); - if(!control_usb->otg_gpios){ - dev_err(&pdev->dev, "unable to alloc memory for otg_gpios\n"); - ret = -ENOMEM; - goto err2; - } +static int dwc_otg_control_usb_probe(struct platform_device *pdev) +{ + int ret = 0; - gpio = of_get_named_gpio(np, "gpios", 1); - if(!gpio_is_valid(gpio)){ - dev_err(&pdev->dev, "invalid otg gpio%d\n", gpio); - ret = -EINVAL; - goto err2; - } - control_usb->otg_gpios->gpio = gpio; - err = devm_gpio_request(&pdev->dev, gpio, "otg_drv_gpio"); - if (err) { - dev_err(&pdev->dev, - "failed to request GPIO%d for otg_drv\n", - gpio); - ret = err; - goto err2; + ret = rk_usb_control_probe(pdev); + if (ret) + return ret; + + control_usb->hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri"); + if (IS_ERR(control_usb->hclk_usb_peri)) { + dev_info(&pdev->dev, "no hclk_usb_peri specified\n"); + control_usb->hclk_usb_peri = NULL; } - gpio_direction_output(control_usb->otg_gpios->gpio, 0); -#ifdef CONFIG_USB20_OTG - if(usb20otg_get_status(USB_STATUS_BVABLID)){ - rk_usb_charger_status = USB_BC_TYPE_SDP; - schedule_delayed_work(&control_usb->usb_charger_det_work, HZ/10); + clk_prepare_enable(control_usb->hclk_usb_peri); + + ret = usb_grf_ioremap(pdev); + if (ret) { + dev_err(&pdev->dev, "Failed to ioremap usb grf\n"); + goto err; } +#ifdef CONFIG_USB20_OTG + if (usb20otg_get_status(USB_STATUS_BVABLID)) + schedule_delayed_work(&control_usb->usb_charger_det_work, + HZ / 10); #endif ret = otg_irq_detect_init(pdev); if (ret < 0) - goto err2; + goto err; return 0; -err2: - clk_disable_unprepare(hclk_usb_peri); -err1: +err: + clk_disable_unprepare(control_usb->hclk_usb_peri); return ret; } @@ -1038,18 +1099,26 @@ static int dwc_otg_control_usb_remove(struct platform_device *pdev) } static struct platform_driver dwc_otg_control_usb_driver = { - .probe = dwc_otg_control_usb_probe, - .remove = dwc_otg_control_usb_remove, - .driver = { - .name = "rk3288-dwc-control-usb", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(dwc_otg_control_usb_id_table), - }, + .probe = dwc_otg_control_usb_probe, + .remove = dwc_otg_control_usb_remove, + .driver = { + .name = "rk3288-dwc-control-usb", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(dwc_otg_control_usb_id_table), + }, }; static int __init dwc_otg_control_usb_init(void) { - return platform_driver_register(&dwc_otg_control_usb_driver); + int retval = 0; + + retval = platform_driver_register(&dwc_otg_control_usb_driver); + + if (retval < 0) { + printk(KERN_ERR "%s retval=%d\n", __func__, retval); + return retval; + } + return retval; } subsys_initcall(dwc_otg_control_usb_init); @@ -1064,3 +1133,4 @@ MODULE_ALIAS("platform: dwc_control_usb"); MODULE_AUTHOR("RockChip Inc."); MODULE_DESCRIPTION("RockChip Control Module USB Driver"); MODULE_LICENSE("GPL v2"); +#endif