diff options
Diffstat (limited to 'drivers/usb/chipidea/core.c')
-rw-r--r-- | drivers/usb/chipidea/core.c | 113 |
1 files changed, 101 insertions, 12 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index ab6212e888e1..3feebf7f31f0 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -64,6 +64,7 @@ #include <linux/of.h> #include <linux/phy.h> #include <linux/regulator/consumer.h> +#include <linux/usb/ehci_def.h> #include "ci.h" #include "udc.h" @@ -84,6 +85,8 @@ static const u8 ci_regs_nolpm[] = { [OP_USBINTR] = 0x08U, [OP_DEVICEADDR] = 0x14U, [OP_ENDPTLISTADDR] = 0x18U, + [OP_TTCTRL] = 0x1CU, + [OP_BURSTSIZE] = 0x20U, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0x64U, @@ -106,6 +109,8 @@ static const u8 ci_regs_lpm[] = { [OP_USBINTR] = 0x08U, [OP_DEVICEADDR] = 0x14U, [OP_ENDPTLISTADDR] = 0x18U, + [OP_TTCTRL] = 0x1CU, + [OP_BURSTSIZE] = 0x20U, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0xC4U, @@ -118,7 +123,7 @@ static const u8 ci_regs_lpm[] = { [OP_ENDPTCTRL] = 0xECU, }; -static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm) +static void hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm) { int i; @@ -134,7 +139,6 @@ static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm) ? ci_regs_lpm[OP_ENDPTCTRL] : ci_regs_nolpm[OP_ENDPTCTRL]); - return 0; } static enum ci_revision ci_get_revision(struct ci_hdrc *ci) @@ -403,6 +407,55 @@ static int ci_usb_phy_init(struct ci_hdrc *ci) return ret; } + +/** + * ci_platform_configure: do controller configure + * @ci: the controller + * + */ +void ci_platform_configure(struct ci_hdrc *ci) +{ + bool is_device_mode, is_host_mode; + + is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC; + is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC; + + if (is_device_mode && + (ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING)) + hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); + + if (is_host_mode && + (ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING)) + hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); + + if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) { + if (ci->hw_bank.lpm) + hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC); + else + hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC); + } + + if (ci->platdata->flags & CI_HDRC_SET_NON_ZERO_TTHA) + hw_write(ci, OP_TTCTRL, TTCTRL_TTHA_MASK, TTCTRL_TTHA); + + hw_write(ci, OP_USBCMD, 0xff0000, ci->platdata->itc_setting << 16); + + if (ci->platdata->flags & CI_HDRC_OVERRIDE_AHB_BURST) + hw_write_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK, + ci->platdata->ahb_burst_config); + + /* override burst size, take effect only when ahb_burst_config is 0 */ + if (!hw_read_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK)) { + if (ci->platdata->flags & CI_HDRC_OVERRIDE_TX_BURST) + hw_write(ci, OP_BURSTSIZE, TX_BURST_MASK, + ci->platdata->tx_burst_size << __ffs(TX_BURST_MASK)); + + if (ci->platdata->flags & CI_HDRC_OVERRIDE_RX_BURST) + hw_write(ci, OP_BURSTSIZE, RX_BURST_MASK, + ci->platdata->rx_burst_size); + } +} + /** * hw_controller_reset: do controller reset * @ci: the controller @@ -447,16 +500,6 @@ int hw_device_reset(struct ci_hdrc *ci) ci->platdata->notify_event(ci, CI_HDRC_CONTROLLER_RESET_EVENT); - if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) - hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); - - if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) { - if (ci->hw_bank.lpm) - hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC); - else - hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC); - } - /* USBMODE should be configured step by step */ hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_DC); @@ -469,6 +512,8 @@ int hw_device_reset(struct ci_hdrc *ci) return -ENODEV; } + ci_platform_configure(ci); + return 0; } @@ -606,6 +651,50 @@ static int ci_get_platdata(struct device *dev, if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL) platdata->flags |= CI_HDRC_FORCE_FULLSPEED; + platdata->itc_setting = 1; + if (of_find_property(dev->of_node, "itc-setting", NULL)) { + ret = of_property_read_u32(dev->of_node, "itc-setting", + &platdata->itc_setting); + if (ret) { + dev_err(dev, + "failed to get itc-setting\n"); + return ret; + } + } + + if (of_find_property(dev->of_node, "ahb-burst-config", NULL)) { + ret = of_property_read_u32(dev->of_node, "ahb-burst-config", + &platdata->ahb_burst_config); + if (ret) { + dev_err(dev, + "failed to get ahb-burst-config\n"); + return ret; + } + platdata->flags |= CI_HDRC_OVERRIDE_AHB_BURST; + } + + if (of_find_property(dev->of_node, "tx-burst-size-dword", NULL)) { + ret = of_property_read_u32(dev->of_node, "tx-burst-size-dword", + &platdata->tx_burst_size); + if (ret) { + dev_err(dev, + "failed to get tx-burst-size-dword\n"); + return ret; + } + platdata->flags |= CI_HDRC_OVERRIDE_TX_BURST; + } + + if (of_find_property(dev->of_node, "rx-burst-size-dword", NULL)) { + ret = of_property_read_u32(dev->of_node, "rx-burst-size-dword", + &platdata->rx_burst_size); + if (ret) { + dev_err(dev, + "failed to get rx-burst-size-dword\n"); + return ret; + } + platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST; + } + return 0; } |