From 121a4d13e679d86bf55bb3941eb33b10fa8c785b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 22 Jun 2017 16:35:14 +0900 Subject: usb: add static to local symbols Sparse reports "... was not declared. Should it be static?" Signed-off-by: Masahiro Yamada diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 13aa70d..f08709d 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -937,7 +937,7 @@ unknown: return -1; } -const struct ehci_ops default_ehci_ops = { +static const struct ehci_ops default_ehci_ops = { .set_usb_mode = ehci_set_usbmode, .get_port_speed = ehci_get_port_speed, .powerup_fixup = ehci_powerup_fixup, diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 110ddc9..efc5d4e 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -373,8 +373,8 @@ int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp) } /* returns 0 if no match, 1 if match */ -int usb_match_device(const struct usb_device_descriptor *desc, - const struct usb_device_id *id) +static int usb_match_device(const struct usb_device_descriptor *desc, + const struct usb_device_id *id) { if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && id->idVendor != le16_to_cpu(desc->idVendor)) @@ -410,9 +410,9 @@ int usb_match_device(const struct usb_device_descriptor *desc, } /* returns 0 if no match, 1 if match */ -int usb_match_one_id_intf(const struct usb_device_descriptor *desc, - const struct usb_interface_descriptor *int_desc, - const struct usb_device_id *id) +static int usb_match_one_id_intf(const struct usb_device_descriptor *desc, + const struct usb_interface_descriptor *int_desc, + const struct usb_device_id *id) { /* The interface class, subclass, protocol and number should never be * checked for a match if the device class is Vendor Specific, @@ -445,9 +445,9 @@ int usb_match_one_id_intf(const struct usb_device_descriptor *desc, } /* returns 0 if no match, 1 if match */ -int usb_match_one_id(struct usb_device_descriptor *desc, - struct usb_interface_descriptor *int_desc, - const struct usb_device_id *id) +static int usb_match_one_id(struct usb_device_descriptor *desc, + struct usb_interface_descriptor *int_desc, + const struct usb_device_id *id) { if (!usb_match_device(desc, id)) return 0; @@ -680,7 +680,7 @@ int usb_detect_change(void) return change; } -int usb_child_post_bind(struct udevice *dev) +static int usb_child_post_bind(struct udevice *dev) { struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); int val; diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 33961cd..a4591f2 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -19,7 +19,7 @@ void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) DWC3_GCTL_PRTCAPDIR(mode)); } -void dwc3_phy_reset(struct dwc3 *dwc3_reg) +static void dwc3_phy_reset(struct dwc3 *dwc3_reg) { /* Assert USB3 PHY reset */ setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3201177..bd8f4c4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -192,7 +192,7 @@ static int xhci_start(struct xhci_hcor *hcor) * @param hcor pointer to host controller operation registers * @return -EBUSY if XHCI Controller is not halted else status of handshake */ -int xhci_reset(struct xhci_hcor *hcor) +static int xhci_reset(struct xhci_hcor *hcor) { u32 cmd; u32 state; @@ -481,7 +481,7 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr) * @param udev pointer to the Device Data Structure * @return Returns 0 on succes else return error code on failure */ -int _xhci_alloc_device(struct usb_device *udev) +static int _xhci_alloc_device(struct usb_device *udev) { struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); union xhci_trb *event; -- cgit v0.10.2 From b7c1c7d2bad9eb052e80b28af6005d7f0ba1db30 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:38:40 +0200 Subject: usb: host: xhci-dwc3: Convert driver to DM Add Driver Model support with use of generic DT compatible string "snps,dwc3" Signed-off-by: Patrice Chotard Reviewed-by: Bin Meng diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index a4591f2..fb106f3 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -9,9 +9,15 @@ */ #include +#include +#include + +#include "xhci.h" #include #include +DECLARE_GLOBAL_DATA_PTR; + void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) { clrsetbits_le32(&dwc3_reg->g_ctl, @@ -97,3 +103,43 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) setbits_le32(&dwc3_reg->g_fladj, GFLADJ_30MHZ_REG_SEL | GFLADJ_30MHZ(val)); } + +static int xhci_dwc3_probe(struct udevice *dev) +{ + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + struct xhci_hcor *hcor; + struct xhci_hccr *hccr; + struct dwc3 *dwc3_reg; + + hccr = (struct xhci_hccr *)devfdt_get_addr(dev); + hcor = (struct xhci_hcor *)((phys_addr_t)hccr + + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); + + dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); + + dwc3_core_init(dwc3_reg); + + return xhci_register(dev, hccr, hcor); +} + +static int xhci_dwc3_remove(struct udevice *dev) +{ + return xhci_deregister(dev); +} + +static const struct udevice_id xhci_dwc3_ids[] = { + { .compatible = "snps,dwc3" }, + { } +}; + +U_BOOT_DRIVER(xhci_dwc3) = { + .name = "xhci-dwc3", + .id = UCLASS_USB, + .of_match = xhci_dwc3_ids, + .probe = xhci_dwc3_probe, + .remove = xhci_dwc3_remove, + .ops = &xhci_usb_ops, + .priv_auto_alloc_size = sizeof(struct xhci_ctrl), + .platdata_auto_alloc_size = sizeof(struct xhci_dwc3_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; -- cgit v0.10.2 From 576e3cc700c598487fed741ee85103373a3f69d6 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:38:41 +0200 Subject: usb: host: xhci-dwc3: Add dual role mode support from DT DWC3 dual role mode is selected using DT "dr_mode" property. If not found, DWC3 controller is configured in HOST mode by default Signed-off-by: Patrice Chotard Reviewed-by: Marek Vasut Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index fb106f3..93ae986 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -15,6 +15,7 @@ #include "xhci.h" #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -110,6 +111,7 @@ static int xhci_dwc3_probe(struct udevice *dev) struct xhci_hcor *hcor; struct xhci_hccr *hccr; struct dwc3 *dwc3_reg; + enum usb_dr_mode dr_mode; hccr = (struct xhci_hccr *)devfdt_get_addr(dev); hcor = (struct xhci_hcor *)((phys_addr_t)hccr + @@ -119,6 +121,13 @@ static int xhci_dwc3_probe(struct udevice *dev) dwc3_core_init(dwc3_reg); + dr_mode = usb_get_dr_mode(dev_of_offset(dev)); + if (dr_mode == USB_DR_MODE_UNKNOWN) + /* by default set dual role mode to HOST */ + dr_mode = USB_DR_MODE_HOST; + + dwc3_set_mode(dwc3_reg, dr_mode); + return xhci_register(dev, hccr, hcor); } -- cgit v0.10.2 From b9688df3cbf4bf92fa96e1cc9ff7be510e06b54b Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:38:42 +0200 Subject: drivers: phy: Set phy->dev to NULL when generic_phy_get_by_index() fails phy->dev need to be set to NULL in case of generic_phy_get_by_index() fails. Then phy->dev can be used to check if the phy is valid Reported-by: Jean-Jacques Hiblot Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index d8b8d58..68e518f 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -45,6 +45,7 @@ int generic_phy_get_by_index(struct udevice *dev, int index, debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy); assert(phy); + phy->dev = NULL; ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index, &args); if (ret) { -- cgit v0.10.2 From b94888b4c051126b02770066ce1e7f4ea9a1ced8 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:38:43 +0200 Subject: drivers: phy: add generic_phy_valid() method This allow to check if a PHY has been correctly initialised and avoid to get access to phy struct. Signed-off-by: Patrice Chotard diff --git a/include/generic-phy.h b/include/generic-phy.h index 762704c..58cd2b2 100644 --- a/include/generic-phy.h +++ b/include/generic-phy.h @@ -220,4 +220,15 @@ int generic_phy_get_by_index(struct udevice *user, int index, int generic_phy_get_by_name(struct udevice *user, const char *phy_name, struct phy *phy); +/** + * generic_phy_valid() - check if PHY port is valid + * + * @phy: the PHY port to check + * @return TRUE if valid, or FALSE + */ +static inline bool generic_phy_valid(struct phy *phy) +{ + return phy->dev != NULL; +} + #endif /*__GENERIC_PHY_H */ -- cgit v0.10.2 From f56db163adf9f922020436e5a3f85ffbdbaed04f Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:38:44 +0200 Subject: usb: host: xhci-dwc3: Add generic PHY support Add support of generic PHY framework support Signed-off-by: Patrice Chotard Reviewed-by: Marek Vasut Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 93ae986..374fe74 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -10,6 +10,8 @@ #include #include +#include +#include #include #include "xhci.h" @@ -19,6 +21,10 @@ DECLARE_GLOBAL_DATA_PTR; +struct xhci_dwc3_platdata { + struct phy usb_phy; +}; + void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) { clrsetbits_le32(&dwc3_reg->g_ctl, @@ -112,11 +118,26 @@ static int xhci_dwc3_probe(struct udevice *dev) struct xhci_hccr *hccr; struct dwc3 *dwc3_reg; enum usb_dr_mode dr_mode; + int ret; hccr = (struct xhci_hccr *)devfdt_get_addr(dev); hcor = (struct xhci_hcor *)((phys_addr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); + ret = generic_phy_get_by_index(dev, 0, &plat->usb_phy); + if (ret) { + if (ret != -ENOENT) { + error("Failed to get USB PHY for %s\n", dev->name); + return ret; + } + } else { + ret = generic_phy_init(&plat->usb_phy); + if (ret) { + error("Can't init USB PHY for %s\n", dev->name); + return ret; + } + } + dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); dwc3_core_init(dwc3_reg); @@ -133,6 +154,17 @@ static int xhci_dwc3_probe(struct udevice *dev) static int xhci_dwc3_remove(struct udevice *dev) { + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + int ret; + + if (generic_phy_valid(&plat->usb_phy)) { + ret = generic_phy_exit(&plat->usb_phy); + if (ret) { + error("Can't deinit USB PHY for %s\n", dev->name); + return ret; + } + } + return xhci_deregister(dev); } -- cgit v0.10.2 From 9bd5cdf6b62b249dc48a00a23b44dc7be547f9f9 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:05 +0200 Subject: reset: add reset_request() This is needed in error path to assert previously deasserted reset by using a saved reset_ctl reference. Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index de3695f..4fd82b9 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -97,6 +97,15 @@ int reset_get_by_name(struct udevice *dev, const char *name, return reset_get_by_index(dev, index, reset_ctl); } +int reset_request(struct reset_ctl *reset_ctl) +{ + struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); + + debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); + + return ops->request(reset_ctl); +} + int reset_free(struct reset_ctl *reset_ctl) { struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); diff --git a/include/reset.h b/include/reset.h index f45fcf8..4f2e35f 100644 --- a/include/reset.h +++ b/include/reset.h @@ -100,6 +100,15 @@ int reset_get_by_name(struct udevice *dev, const char *name, struct reset_ctl *reset_ctl); /** + * reset_request - Request a reset signal. + * + * @reset_ctl: A reset control struct. + * + * @return 0 if OK, or a negative error code. + */ +int reset_request(struct reset_ctl *reset_ctl); + +/** * reset_free - Free a previously requested reset signal. * * @reset_ctl: A reset control struct that was previously successfully -- cgit v0.10.2 From 3b9d1bdd4e5fe0c44e5d4d0a0916dbccc558749d Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:06 +0200 Subject: reset: add reset_release_all() Add reset_release_all() method which Assert/Free an array of resets signal that has been previously successfully requested by reset_get_by_*() Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index 4fd82b9..307a297 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -42,6 +42,7 @@ int reset_get_by_index(struct udevice *dev, int index, debug("%s(dev=%p, index=%d, reset_ctl=%p)\n", __func__, dev, index, reset_ctl); + reset_ctl->dev = NULL; ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0, index, &args); @@ -87,6 +88,7 @@ int reset_get_by_name(struct udevice *dev, const char *name, debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name, reset_ctl); + reset_ctl->dev = NULL; index = dev_read_stringlist_search(dev, "reset-names", name); if (index < 0) { @@ -133,6 +135,29 @@ int reset_deassert(struct reset_ctl *reset_ctl) return ops->rst_deassert(reset_ctl); } +int reset_release_all(struct reset_ctl *reset_ctl, int count) +{ + int i, ret; + + for (i = 0; i < count; i++) { + debug("%s(reset_ctl[%d]=%p)\n", __func__, i, &reset_ctl[i]); + + /* check if reset has been previously requested */ + if (!reset_ctl[i].dev) + continue; + + ret = reset_assert(&reset_ctl[i]); + if (ret) + return ret; + + ret = reset_free(&reset_ctl[i]); + if (ret) + return ret; + } + + return 0; +} + UCLASS_DRIVER(reset) = { .id = UCLASS_RESET, .name = "reset", diff --git a/include/reset.h b/include/reset.h index 4f2e35f..7185ade 100644 --- a/include/reset.h +++ b/include/reset.h @@ -144,6 +144,18 @@ int reset_assert(struct reset_ctl *reset_ctl); */ int reset_deassert(struct reset_ctl *reset_ctl); +/** + * reset_release_all - Assert/Free an array of previously requested resets. + * + * For each reset contained in the reset array, this function will check if + * reset has been previously requested and then will assert and free it. + * + * @reset_ctl: A reset struct array that was previously successfully + * requested by reset_get_by_*(). + * @count Number of reset contained in the array + * @return 0 if OK, or a negative error code. + */ +int reset_release_all(struct reset_ctl *reset_ctl, int count); #else static inline int reset_get_by_index(struct udevice *dev, int index, struct reset_ctl *reset_ctl) @@ -171,6 +183,12 @@ static inline int reset_deassert(struct reset_ctl *reset_ctl) { return 0; } + +static inline int reset_release_all(struct reset_ctl *reset_ctl, int count) +{ + return 0; +} + #endif #endif -- cgit v0.10.2 From 82a8a669b4f7159f1f3c3251c2fcb36965896290 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:07 +0200 Subject: clk: add clk_release_all() Add clk_release_all() method which Disable/Free an array of clocks that has been previously requested by clk_request/get_by_*() Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 83b6328..ffbe872 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -65,6 +65,8 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk); assert(clk); + clk->dev = NULL; + ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0, index, &args); if (ret) { @@ -102,6 +104,7 @@ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk) int index; debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk); + clk->dev = NULL; index = dev_read_stringlist_search(dev, "clock-names", name); if (index < 0) { @@ -187,6 +190,29 @@ int clk_disable(struct clk *clk) return ops->disable(clk); } +int clk_release_all(struct clk *clk, int count) +{ + int i, ret; + + for (i = 0; i < count; i++) { + debug("%s(clk[%d]=%p)\n", __func__, i, &clk[i]); + + /* check if clock has been previously requested */ + if (!clk[i].dev) + continue; + + ret = clk_disable(&clk[i]); + if (ret && ret != -ENOSYS) + return ret; + + ret = clk_free(&clk[i]); + if (ret && ret != -ENOSYS) + return ret; + } + + return 0; +} + UCLASS_DRIVER(clk) = { .id = UCLASS_CLK, .name = "clk", diff --git a/include/clk.h b/include/clk.h index 5a5c2ff..a905a41 100644 --- a/include/clk.h +++ b/include/clk.h @@ -174,6 +174,20 @@ int clk_enable(struct clk *clk); */ int clk_disable(struct clk *clk); +/** + * clk_release_all() - Disable (turn off)/Free an array of previously + * requested clocks. + * + * For each clock contained in the clock array, this function will check if + * clock has been previously requested and then will disable and free it. + * + * @clk: A clock struct array that was previously successfully + * requested by clk_request/get_by_*(). + * @count Number of clock contained in the array + * @return zero on success, or -ve error code. + */ +int clk_release_all(struct clk *clk, int count); + int soc_clk_dump(void); #endif -- cgit v0.10.2 From 642346ae269c3c5c54cf7e15c426c42f4df031da Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:08 +0200 Subject: dm: core: add ofnode_count_phandle_with_args() This function is usefull to get phandle number contained in a property list. For example, this allows to allocate the right amount of memory to keep clock's reference contained into the "clocks" property. To implement it, either of_count_phandle_with_args() or fdtdec_parse_phandle_with_args() are used respectively for live tree and flat tree. By passing index = -1, these 2 functions returns the number of phandle contained into the property list. Add also the dev_count_phandle_with_args() based on ofnode_count_phandle_with_args() Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index 2bb23ee..c31cba7 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -665,6 +665,13 @@ int of_parse_phandle_with_args(const struct device_node *np, index, out_args); } +int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name) +{ + return __of_parse_phandle_with_args(np, list_name, cells_name, 0, + -1, NULL); +} + static void of_alias_add(struct alias_prop *ap, struct device_node *np, int id, const char *stem, int stem_len) { diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index fd068b0..5fc77c5 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -313,6 +313,18 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, return 0; } +int ofnode_count_phandle_with_args(ofnode node, const char *list_name, + const char *cells_name) +{ + if (ofnode_is_np(node)) + return of_count_phandle_with_args(ofnode_to_np(node), + list_name, cells_name); + else + return fdtdec_parse_phandle_with_args(gd->fdt_blob, + ofnode_to_offset(node), list_name, cells_name, + 0, -1, NULL); +} + ofnode ofnode_path(const char *path) { if (of_live_active()) diff --git a/include/dm/of_access.h b/include/dm/of_access.h index c5ea391..c49d287 100644 --- a/include/dm/of_access.h +++ b/include/dm/of_access.h @@ -353,6 +353,24 @@ int of_parse_phandle_with_args(const struct device_node *np, int index, struct of_phandle_args *out_args); /** + * of_count_phandle_with_args() - Count the number of phandle in a list + * + * @np: pointer to a device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @return number of phandle found, -ENOENT if + * @list_name does not exist, -EINVAL if a phandle was not found, + * @cells_name could not be found, the arguments were truncated or there + * were too many arguments. + * + * Returns number of phandle found on success, on error returns appropriate + * errno value. + * + */ +int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name); + +/** * of_alias_scan() - Scan all properties of the 'aliases' node * * The function scans all the properties of the 'aliases' node and populates diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 15ad519..8eecce5 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -433,6 +433,23 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, struct ofnode_phandle_args *out_args); /** + * ofnode_count_phandle_with_args() - Count number of phandle in a list + * + * This function is useful to count phandles into a list. + * Returns number of phandle on success, on error returns appropriate + * errno value. + * + * @node: device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @return number of phandle on success, -ENOENT if @list_name does not + * exist, -EINVAL if a phandle was not found, @cells_name could not + * be found. + */ +int ofnode_count_phandle_with_args(ofnode node, const char *list_name, + const char *cells_name); + +/** * ofnode_path() - find a node by full path * * @path: Full path to node, e.g. "/bus/spi@1" diff --git a/include/dm/read.h b/include/dm/read.h index b86a2f5..d09b04d 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -209,6 +209,24 @@ int dev_read_phandle_with_args(struct udevice *dev, const char *list_name, struct ofnode_phandle_args *out_args); /** + * dev_count_phandle_with_args() - Return phandle number in a list + * + * This function is usefull to get phandle number contained in a property list. + * For example, this allows to allocate the right amount of memory to keep + * clock's reference contained into the "clocks" property. + * + * + * @dev: device whose node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @Returns number of phandle found on success, on error returns appropriate + * errno value. + */ + +int dev_count_phandle_with_args(struct udevice *dev, const char *list_name, + const char *cells_name); + +/** * dev_read_addr_cells() - Get the number of address cells for a device's node * * This walks back up the tree to find the closest #address-cells property @@ -416,6 +434,13 @@ static inline int dev_read_phandle_with_args(struct udevice *dev, out_args); } +static inline int dev_count_phandle_with_args(struct udevice *dev, + const char *list_name, const char *cells_name) +{ + return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name, + cells_name); +} + static inline int dev_read_addr_cells(struct udevice *dev) { /* NOTE: this call should walk up the parent stack */ -- cgit v0.10.2 From 10bb775e925d2a1c516c96904a5e1d2e747c4e1b Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:09 +0200 Subject: usb: host: ehci-generic: replace printf() by error() this allows to get file, line and function location of the current error message. Signed-off-by: patrice chotard Reviewed-by: Simon Glass diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index fb78462..2116ae1 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -34,7 +34,7 @@ static int ehci_usb_probe(struct udevice *dev) if (ret < 0) break; if (clk_enable(&clk)) - printf("failed to enable clock %d\n", i); + error("failed to enable clock %d\n", i); clk_free(&clk); } @@ -46,7 +46,7 @@ static int ehci_usb_probe(struct udevice *dev) if (ret < 0) break; if (reset_deassert(&reset)) - printf("failed to deassert reset %d\n", i); + error("failed to deassert reset %d\n", i); reset_free(&reset); } -- cgit v0.10.2 From a1cee8e808042e2597d162b1687fdb470634271e Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:10 +0200 Subject: usb: host: ehci-generic: add error path and .remove callback Use an array to save enabled clocks reference and deasserted resets in order to respectively disabled and asserted them in case of error during probe() or during driver removal. Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2116ae1..e058445 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -18,43 +19,114 @@ */ struct generic_ehci { struct ehci_ctrl ctrl; + struct clk *clocks; + struct reset_ctl *resets; + int clock_count; + int reset_count; }; static int ehci_usb_probe(struct udevice *dev) { + struct generic_ehci *priv = dev_get_priv(dev); struct ehci_hccr *hccr; struct ehci_hcor *hcor; - int i; - - for (i = 0; ; i++) { - struct clk clk; - int ret; - - ret = clk_get_by_index(dev, i, &clk); - if (ret < 0) - break; - if (clk_enable(&clk)) - error("failed to enable clock %d\n", i); - clk_free(&clk); + int i, err, ret, clock_nb, reset_nb; + + err = 0; + priv->clock_count = 0; + clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks", + "#clock-cells"); + if (clock_nb > 0) { + priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), + GFP_KERNEL); + if (!priv->clocks) + return -ENOMEM; + + for (i = 0; i < clock_nb; i++) { + err = clk_get_by_index(dev, i, &priv->clocks[i]); + + if (err < 0) + break; + err = clk_enable(&priv->clocks[i]); + if (err) { + error("failed to enable clock %d\n", i); + clk_free(&priv->clocks[i]); + goto clk_err; + } + priv->clock_count++; + } + } else { + if (clock_nb != -ENOENT) { + error("failed to get clock phandle(%d)\n", clock_nb); + return clock_nb; + } } - for (i = 0; ; i++) { - struct reset_ctl reset; - int ret; + priv->reset_count = 0; + reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets", + "#reset-cells"); + if (reset_nb > 0) { + priv->resets = devm_kcalloc(dev, reset_nb, + sizeof(struct reset_ctl), + GFP_KERNEL); + if (!priv->resets) + return -ENOMEM; + + for (i = 0; i < reset_nb; i++) { + err = reset_get_by_index(dev, i, &priv->resets[i]); + if (err < 0) + break; - ret = reset_get_by_index(dev, i, &reset); - if (ret < 0) - break; - if (reset_deassert(&reset)) - error("failed to deassert reset %d\n", i); - reset_free(&reset); + if (reset_deassert(&priv->resets[i])) { + error("failed to deassert reset %d\n", i); + reset_free(&priv->resets[i]); + goto reset_err; + } + priv->reset_count++; + } + } else { + if (reset_nb != -ENOENT) { + error("failed to get reset phandle(%d)\n", reset_nb); + goto clk_err; + } } hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); + err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); + if (err) + goto reset_err; + + return 0; + +reset_err: + ret = reset_release_all(priv->resets, priv->reset_count); + if (ret) + error("failed to assert all resets\n"); +clk_err: + ret = clk_release_all(priv->clocks, priv->clock_count); + if (ret) + error("failed to disable all clocks\n"); + + return err; +} + +static int ehci_usb_remove(struct udevice *dev) +{ + struct generic_ehci *priv = dev_get_priv(dev); + int ret; + + ret = ehci_deregister(dev); + if (ret) + return ret; + + ret = reset_release_all(priv->resets, priv->reset_count); + if (ret) + return ret; + + return clk_release_all(priv->clocks, priv->clock_count); } static const struct udevice_id ehci_usb_ids[] = { @@ -67,7 +139,7 @@ U_BOOT_DRIVER(ehci_generic) = { .id = UCLASS_USB, .of_match = ehci_usb_ids, .probe = ehci_usb_probe, - .remove = ehci_deregister, + .remove = ehci_usb_remove, .ops = &ehci_usb_ops, .priv_auto_alloc_size = sizeof(struct generic_ehci), .flags = DM_FLAG_ALLOC_PRIV_DMA, -- cgit v0.10.2 From 0d0ba1a73d6c34b7668f860e90ab57eacd9dd5b4 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:11 +0200 Subject: usb: host: ehci-generic: add generic PHY support Extend ehci-generic driver with generic PHY framework Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index e058445..3f751f1 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ struct generic_ehci { struct ehci_ctrl ctrl; struct clk *clocks; struct reset_ctl *resets; + struct phy phy; int clock_count; int reset_count; }; @@ -91,16 +93,37 @@ static int ehci_usb_probe(struct udevice *dev) } } + err = generic_phy_get_by_index(dev, 0, &priv->phy); + if (err) { + if (err != -ENOENT) { + error("failed to get usb phy\n"); + goto reset_err; + } + } + + err = generic_phy_init(&priv->phy); + if (err) { + error("failed to init usb phy\n"); + goto reset_err; + } + hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); if (err) - goto reset_err; + goto phy_err; return 0; +phy_err: + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_exit(&priv->phy); + if (ret) + error("failed to release phy\n"); + } + reset_err: ret = reset_release_all(priv->resets, priv->reset_count); if (ret) @@ -122,6 +145,12 @@ static int ehci_usb_remove(struct udevice *dev) if (ret) return ret; + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_exit(&priv->phy); + if (ret) + return ret; + } + ret = reset_release_all(priv->resets, priv->reset_count); if (ret) return ret; -- cgit v0.10.2 From 155d9f65d3bf78cc7113475110c129dc0dbbdae1 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:12 +0200 Subject: usb: host: ohci-generic: add CLOCK support use array to save enabled clocks reference in order to disabled them in case of error during probe() or during driver removal. Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index f85738f..f5b27cc 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -5,7 +5,9 @@ */ #include +#include #include +#include #include "ohci.h" #if !defined(CONFIG_USB_OHCI_NEW) @@ -14,18 +16,67 @@ struct generic_ohci { ohci_t ohci; + struct clk *clocks; /* clock list */ + int clock_count; /* number of clock in clock list */ }; static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); + struct generic_ohci *priv = dev_get_priv(dev); + int i, err, ret, clock_nb; - return ohci_register(dev, regs); + err = 0; + priv->clock_count = 0; + clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); + if (clock_nb > 0) { + priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), + GFP_KERNEL); + if (!priv->clocks) + return -ENOMEM; + + for (i = 0; i < clock_nb; i++) { + err = clk_get_by_index(dev, i, &priv->clocks[i]); + if (err < 0) + break; + + err = clk_enable(&priv->clocks[i]); + if (err) { + error("failed to enable clock %d\n", i); + clk_free(&priv->clocks[i]); + goto clk_err; + } + priv->clock_count++; + } + } else if (clock_nb != -ENOENT) { + error("failed to get clock phandle(%d)\n", clock_nb); + return clock_nb; + } + + err = ohci_register(dev, regs); + if (err) + goto clk_err; + + return 0; + +clk_err: + ret = clk_release_all(priv->clocks, priv->clock_count); + if (ret) + error("failed to disable all clocks\n"); + + return err; } static int ohci_usb_remove(struct udevice *dev) { - return ohci_deregister(dev); + struct generic_ohci *priv = dev_get_priv(dev); + int ret; + + ret = ohci_deregister(dev); + if (ret) + return ret; + + return clk_release_all(priv->clocks, priv->clock_count); } static const struct udevice_id ohci_usb_ids[] = { -- cgit v0.10.2 From 8a51b4b3dac35a18acca2538efe2c2979aa56417 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:13 +0200 Subject: usb: host: ohci-generic: add RESET support use array to save deasserted resets reference in order to assert them in case of error during probe() or during driver removal. Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index f5b27cc..95d54c1 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "ohci.h" #if !defined(CONFIG_USB_OHCI_NEW) @@ -17,14 +18,16 @@ struct generic_ohci { ohci_t ohci; struct clk *clocks; /* clock list */ + struct reset_ctl *resets; /* reset list */ int clock_count; /* number of clock in clock list */ + int reset_count; /* number of reset in reset list */ }; static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); struct generic_ohci *priv = dev_get_priv(dev); - int i, err, ret, clock_nb; + int i, err, ret, clock_nb, reset_nb; err = 0; priv->clock_count = 0; @@ -53,12 +56,43 @@ static int ohci_usb_probe(struct udevice *dev) return clock_nb; } + priv->reset_count = 0; + reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells"); + if (reset_nb > 0) { + priv->resets = devm_kcalloc(dev, reset_nb, + sizeof(struct reset_ctl), + GFP_KERNEL); + if (!priv->resets) + return -ENOMEM; + + for (i = 0; i < reset_nb; i++) { + err = reset_get_by_index(dev, i, &priv->resets[i]); + if (err < 0) + break; + + err = reset_deassert(&priv->resets[i]); + if (err) { + error("failed to deassert reset %d\n", i); + reset_free(&priv->resets[i]); + goto reset_err; + } + priv->reset_count++; + } + } else if (reset_nb != -ENOENT) { + error("failed to get reset phandle(%d)\n", reset_nb); + goto clk_err; + } + err = ohci_register(dev, regs); if (err) - goto clk_err; + goto reset_err; return 0; +reset_err: + ret = reset_release_all(priv->resets, priv->reset_count); + if (ret) + error("failed to assert all resets\n"); clk_err: ret = clk_release_all(priv->clocks, priv->clock_count); if (ret) @@ -76,6 +110,10 @@ static int ohci_usb_remove(struct udevice *dev) if (ret) return ret; + ret = reset_release_all(priv->resets, priv->reset_count); + if (ret) + return ret; + return clk_release_all(priv->clocks, priv->clock_count); } -- cgit v0.10.2 From 28df1cfddd9e722d0016d0930b0e523a82737695 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 18 Jul 2017 11:57:14 +0200 Subject: usb: host: ohci-generic: add generic PHY support Extend ohci-generic driver with generic PHY framework Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index 95d54c1..9249039 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "ohci.h" @@ -19,6 +20,7 @@ struct generic_ohci { ohci_t ohci; struct clk *clocks; /* clock list */ struct reset_ctl *resets; /* reset list */ + struct phy phy; int clock_count; /* number of clock in clock list */ int reset_count; /* number of reset in reset list */ }; @@ -83,12 +85,33 @@ static int ohci_usb_probe(struct udevice *dev) goto clk_err; } + err = generic_phy_get_by_index(dev, 0, &priv->phy); + if (err) { + if (err != -ENOENT) { + error("failed to get usb phy\n"); + goto reset_err; + } + } + + err = generic_phy_init(&priv->phy); + if (err) { + error("failed to init usb phy\n"); + goto reset_err; + } + err = ohci_register(dev, regs); if (err) - goto reset_err; + goto phy_err; return 0; +phy_err: + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_exit(&priv->phy); + if (ret) + error("failed to release phy\n"); + } + reset_err: ret = reset_release_all(priv->resets, priv->reset_count); if (ret) @@ -110,6 +133,12 @@ static int ohci_usb_remove(struct udevice *dev) if (ret) return ret; + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_exit(&priv->phy); + if (ret) + return ret; + } + ret = reset_release_all(priv->resets, priv->reset_count); if (ret) return ret; -- cgit v0.10.2 From f2e0315e9d27a6495bde8d80983be4e0208bb63f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:49:53 +0800 Subject: usb: xhci: Remove incorrect comments for struct xhci_container_ctx There is no member called 'dma' in struct xhci_container_ctx. Remove the comments that mentions it. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 2afa386..431afd8 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -482,10 +482,9 @@ struct xhci_protocol_caps { * @type: Type of context. Used to calculated offsets to contained contexts. * @size: Size of the context data * @bytes: The raw context data given to HW - * @dma: dma address of the bytes * * Represents either a Device or Input context. Holds a pointer to the raw - * memory used for the context (bytes) and dma address of it (dma). + * memory used for the context (bytes). */ struct xhci_container_ctx { unsigned type; -- cgit v0.10.2 From 43eb0d448867f9f3c7b02957a2196ac987840a17 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:49:54 +0800 Subject: usb: xhci: Correct command TRB 4th dword initialization In xhci_queue_command(), when the command is not 'reset endpoint', 'stop endpoint' or 'set TR dequeue pointer', endpoint ID should not be encoded in the TRB. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 2675a8f..579e670 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -280,8 +280,15 @@ void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, fields[0] = lower_32_bits(val_64); fields[1] = upper_32_bits(val_64); fields[2] = 0; - fields[3] = TRB_TYPE(cmd) | EP_ID_FOR_TRB(ep_index) | - SLOT_ID_FOR_TRB(slot_id) | ctrl->cmd_ring->cycle_state; + fields[3] = TRB_TYPE(cmd) | SLOT_ID_FOR_TRB(slot_id) | + ctrl->cmd_ring->cycle_state; + + /* + * Only 'reset endpoint', 'stop endpoint' and 'set TR dequeue pointer' + * commands need endpoint id encoded. + */ + if (cmd >= TRB_RESET_EP && cmd <= TRB_SET_DEQ) + fields[3] |= EP_ID_FOR_TRB(ep_index); queue_trb(ctrl, ctrl->cmd_ring, false, fields); -- cgit v0.10.2 From 209b98de01d26ef199c887934cd025fdbd761d16 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:49:55 +0800 Subject: usb: xhci: Initialize scratchpad buffer array and scratchpad buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scratchpad buffer array is used to define the locations of statically allocated memory pages that are available for the private use of the xHC. The xHCI spec explicitly mentions that system software shall allocate the scratchpad buffers before placing the xHC in to Run mode (Run/Stop (R/S) = ‘1’), however U-Boot is missing this part. This causes xHC on Intel platform does not respond the very first 'enable slot' command that is given to xHC and the 'enable slot' command completion event TRB is never generated and xHC seems to hang forever. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 62db51d..12e277a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -96,6 +96,25 @@ static void xhci_ring_free(struct xhci_ring *ring) } /** + * Free the scratchpad buffer array and scratchpad buffers + * + * @ctrl host controller data structure + * @return none + */ +static void xhci_scratchpad_free(struct xhci_ctrl *ctrl) +{ + if (!ctrl->scratchpad) + return; + + ctrl->dcbaa->dev_context_ptrs[0] = 0; + + free((void *)(uintptr_t)ctrl->scratchpad->sp_array[0]); + free(ctrl->scratchpad->sp_array); + free(ctrl->scratchpad); + ctrl->scratchpad = NULL; +} + +/** * frees the "xhci_container_ctx" pointer passed * * @param ptr pointer to "xhci_container_ctx" to be freed @@ -155,6 +174,7 @@ void xhci_cleanup(struct xhci_ctrl *ctrl) { xhci_ring_free(ctrl->event_ring); xhci_ring_free(ctrl->cmd_ring); + xhci_scratchpad_free(ctrl); xhci_free_virt_devices(ctrl); free(ctrl->erst.entries); free(ctrl->dcbaa); @@ -320,6 +340,70 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs) } /** + * Set up the scratchpad buffer array and scratchpad buffers + * + * @ctrl host controller data structure + * @return -ENOMEM if buffer allocation fails, 0 on success + */ +static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) +{ + struct xhci_hccr *hccr = ctrl->hccr; + struct xhci_hcor *hcor = ctrl->hcor; + struct xhci_scratchpad *scratchpad; + int num_sp; + uint32_t page_size; + void *buf; + int i; + + num_sp = HCS_MAX_SCRATCHPAD(xhci_readl(&hccr->cr_hcsparams2)); + if (!num_sp) + return 0; + + scratchpad = malloc(sizeof(*scratchpad)); + if (!scratchpad) + goto fail_sp; + ctrl->scratchpad = scratchpad; + + scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64)); + if (!scratchpad->sp_array) + goto fail_sp2; + ctrl->dcbaa->dev_context_ptrs[0] = + cpu_to_le64((uintptr_t)scratchpad->sp_array); + + page_size = xhci_readl(&hcor->or_pagesize) & 0xffff; + for (i = 0; i < 16; i++) { + if ((0x1 & page_size) != 0) + break; + page_size = page_size >> 1; + } + BUG_ON(i == 16); + + page_size = 1 << (i + 12); + buf = memalign(page_size, num_sp * page_size); + if (!buf) + goto fail_sp3; + memset(buf, '\0', num_sp * page_size); + xhci_flush_cache((uintptr_t)buf, num_sp * page_size); + + for (i = 0; i < num_sp; i++) { + uintptr_t ptr = (uintptr_t)buf + i * page_size; + scratchpad->sp_array[i] = cpu_to_le64(ptr); + } + + return 0; + +fail_sp3: + free(scratchpad->sp_array); + +fail_sp2: + free(scratchpad); + ctrl->scratchpad = NULL; + +fail_sp: + return -ENOMEM; +} + +/** * Allocates the Container context * * @param ctrl Host controller data structure @@ -499,6 +583,9 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, xhci_writeq(&ctrl->ir_set->erst_base, val_64); + /* set up the scratchpad buffer array and scratchpad buffers */ + xhci_scratchpad_alloc(ctrl); + /* initializing the virtual devices to NULL */ for (i = 0; i < MAX_HC_SLOTS; ++i) ctrl->devs[i] = NULL; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 431afd8..32dd611 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -111,9 +111,10 @@ struct xhci_hccr { #define HCS_IST(p) (((p) >> 0) & 0xf) /* bits 4:7, max number of Event Ring segments */ #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) +/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */ /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ -/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ -#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) +/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */ +#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f)) /* HCSPARAMS3 - hcs_params3 - bitmasks */ /* bits 0:7, Max U1 to U0 latency for the roothub ports */ @@ -1037,6 +1038,10 @@ struct xhci_erst { unsigned int erst_size; }; +struct xhci_scratchpad { + u64 *sp_array; +}; + /* * Each segment table entry is 4*32bits long. 1K seems like an ok size: * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, @@ -1224,6 +1229,7 @@ struct xhci_ctrl { struct xhci_intr_reg *ir_set; struct xhci_erst erst; struct xhci_erst_entry entry[ERST_NUM_SEGS]; + struct xhci_scratchpad *scratchpad; struct xhci_virt_device *devs[MAX_HC_SLOTS]; int rootdev; }; -- cgit v0.10.2 From aab0db08c07de0807d609f19c17dfb8eaf589231 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:49:56 +0800 Subject: usb: xhci: Add input slot context in xhci_set_configuration() A valid input slot context for a 'configure endpoint' command requires the 'Context Entries' field to be initialized to the index of the last valid endpoint context that is defined by the target configuration. We set up the 'Context Entries' field, but we forget to include the input slot context in the input control context 'Add Context flags' bitmap. So xHC will simply ignore input slot context and continue using its own which contains old information of the device. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index bd8f4c4..95a0fba 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -332,8 +332,8 @@ static int xhci_set_configuration(struct usb_device *udev) ifdesc = &udev->config.if_desc[0]; ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Zero the input context control */ - ctrl_ctx->add_flags = 0; + /* Initialize the input context control */ + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); ctrl_ctx->drop_flags = 0; /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ -- cgit v0.10.2 From f7a9e5dd03f83cf31a85eadf8666939abe47b739 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:49:57 +0800 Subject: usb: hub: Update handling connect status/change in usb_scan_port() It was observed that on Intel MinnowMax board, when xHCI is enabled in the BayTrail SoC, with a USB 3.0 device connected to the bottom USB 3.0 port (mapped to xHCI root port #7), its PORTSC register is always 0x201203 (CCS = 1, CSC = 0). The root cause of such behavior is unknown yet. Connect status change bit is set on the same port with a USB 2.0 device (mapped to xHCI port #1, which is a different port on the root hub). With current logic in usb_scan_port(), the enumeration process will abort if it does not detect a connect status change on a hub port. However since a device connection status is correctly reported, the enumeration process can still continue. With this change, USB device connected to the bottom blue port on MinnowMax board can be enumerated under either SS or HS mode. Signed-off-by: Bin Meng Reviewed-by: Stefan Roese Tested-by: Stefan Roese Tested-by: Dinh Nguyen diff --git a/common/usb_hub.c b/common/usb_hub.c index d135526..4fe0daa 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -405,8 +405,15 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) portchange = le16_to_cpu(portsts->wPortChange); debug("Port %d Status %X Change %X\n", i + 1, portstatus, portchange); - /* No connection change happened, wait a bit more. */ - if (!(portchange & USB_PORT_STAT_C_CONNECTION)) { + /* + * No connection change happened, wait a bit more. + * + * For some situation, the hub reports no connection change but a + * device is connected to the port (eg: CCS bit is set but CSC is not + * in the PORTSC register of a root hub), ignore such case. + */ + if (!(portchange & USB_PORT_STAT_C_CONNECTION) && + !(portstatus & USB_PORT_STAT_CONNECTION)) { if (get_timer(0) >= hub->connect_timeout) { debug("devnum=%d port=%d: timeout\n", dev->devnum, i + 1); @@ -418,10 +425,6 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) return 0; } - /* Test if the connection came up, and if not exit */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return 0; - /* A new USB device is ready at this point */ debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1); -- cgit v0.10.2 From f34211960214290d8b38dab2fbdfb18f07582f45 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:49:58 +0800 Subject: usb: hub: Send correct wValue to get hub descriptor of a USB 3.0 hub Testing a USB 3.0 hub by connecting it to the xHCI port on Intel MinnowMax, when issuing 'get hub descriptor' to the hub, xHCI reports a transfer event TRB with a completion code 6 which means 'Stall Error'. In fact super speed USB hub descriptor type is 0x2a, not 0x29. Sending correct SETUP packet to the hub makes it not stall anymore. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/common/usb_hub.c b/common/usb_hub.c index 4fe0daa..48831b5 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -65,11 +65,21 @@ __weak void usb_hub_reset_devices(int port) return; } +static inline bool usb_hub_is_superspeed(struct usb_device *hdev) +{ + return hdev->descriptor.bDeviceProtocol == 3; +} + static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) { + unsigned short dtype = USB_DT_HUB; + + if (usb_hub_is_superspeed(dev)) + dtype = USB_DT_SS_HUB; + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, - USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT); + dtype << 8, 0, data, size, USB_CNTL_TIMEOUT); } static int usb_clear_port_feature(struct usb_device *dev, int port, int feature) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 95a0fba..59ee476 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -727,6 +727,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): switch (le16_to_cpu(req->value) >> 8) { case USB_DT_HUB: + case USB_DT_SS_HUB: debug("USB_DT_HUB config\n"); srcptr = &descriptor.hub; srclen = 0x8; diff --git a/include/usb_defs.h b/include/usb_defs.h index 8214ba9..608a0ca 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -93,6 +93,7 @@ #define USB_DT_REPORT (USB_TYPE_CLASS | 0x02) #define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) #define USB_DT_HUB (USB_TYPE_CLASS | 0x09) +#define USB_DT_SS_HUB (USB_TYPE_CLASS | 0x0a) /* Descriptor sizes per descriptor type */ #define USB_DT_DEVICE_SIZE 18 -- cgit v0.10.2 From 53771a490e05e8be750a6ee50002e30df4776e9b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:49:59 +0800 Subject: usb: hub: Revise wLength for 'get port status' request For accuracy, we should use 'sizeof(struct usb_port_status)' as the wLength for 'get port status' request, although it happens to be equal to 'sizeof(struct usb_hub_status)'. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/common/usb_hub.c b/common/usb_hub.c index 48831b5..83c6767 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -107,7 +107,7 @@ int usb_get_port_status(struct usb_device *dev, int port, void *data) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, - data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT); + data, sizeof(struct usb_port_status), USB_CNTL_TIMEOUT); } -- cgit v0.10.2 From 337fc7e665a20bd0c23da233ffb9e8469d999e72 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:00 +0800 Subject: usb: hub: Change USB hub descriptor to match USB 3.0 hubs USB 3.0 hubs have a slightly different hub descriptor than USB 2.0 hubs, with a fixed (rather than variable length) size. Change the host controller drivers that access those last two fields (DeviceRemovable and PortPowerCtrlMask) to use the union. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/common/usb_hub.c b/common/usb_hub.c index 83c6767..a46d26a 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -583,17 +583,19 @@ static int usb_hub_configure(struct usb_device *dev) &descriptor->wHubCharacteristics)), &hub->desc.wHubCharacteristics); /* set the bitmap */ - bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; + bitmap = (unsigned char *)&hub->desc.u.hs.DeviceRemovable[0]; /* devices not removable by default */ memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); - bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0]; + bitmap = (unsigned char *)&hub->desc.u.hs.PortPowerCtrlMask[0]; memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) - hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i]; + hub->desc.u.hs.DeviceRemovable[i] = + descriptor->u.hs.DeviceRemovable[i]; for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) - hub->desc.PortPowerCtrlMask[i] = descriptor->PortPowerCtrlMask[i]; + hub->desc.u.hs.PortPowerCtrlMask[i] = + descriptor->u.hs.PortPowerCtrlMask[i]; dev->maxchild = descriptor->bNbrPorts; debug("%d ports detected\n", dev->maxchild); @@ -637,7 +639,7 @@ static int usb_hub_configure(struct usb_device *dev) for (i = 0; i < dev->maxchild; i++) debug("port %d is%s removable\n", i + 1, - hub->desc.DeviceRemovable[(i + 1) / 8] & \ + hub->desc.u.hs.DeviceRemovable[(i + 1) / 8] & \ (1 << ((i + 1) % 8)) ? " not" : ""); if (sizeof(struct usb_hub_status) > USB_BUFSIZ) { diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c index 9ffda9c..1432858 100644 --- a/drivers/usb/emul/sandbox_hub.c +++ b/drivers/usb/emul/sandbox_hub.c @@ -96,7 +96,12 @@ static struct usb_hub_descriptor hub_desc = { 1 << 7), .bPwrOn2PwrGood = 2, .bHubContrCurrent = 5, - .DeviceRemovable = {0, 0xff}, /* all ports removeable */ + { + { + /* all ports removeable */ + .DeviceRemovable = {0, 0xff} + } + } #if SANDBOX_NUM_PORTS > 8 #error "This code sets up an incorrect mask" #endif diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f08709d..40ac3a6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -52,8 +52,8 @@ static struct descriptor { 0, /* wHubCharacteristics */ 10, /* bPwrOn2PwrGood */ 0, /* bHubCntrCurrent */ - {}, /* Device removable */ - {} /* at most 7 ports! XXX */ + { /* Device removable */ + } /* at most 7 ports! XXX */ }, { 0x12, /* bLength */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 59ee476..d5a1b34 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -50,8 +50,8 @@ static struct descriptor { cpu_to_le16(0x8), /* wHubCharacteristics */ 10, /* bPwrOn2PwrGood */ 0, /* bHubCntrCurrent */ - {}, /* Device removable */ - {} /* at most 7 ports! XXX */ + { /* Device removable */ + } /* at most 7 ports! XXX */ }, { 0x12, /* bLength */ diff --git a/include/usb.h b/include/usb.h index 62f051f..eb82cc2 100644 --- a/include/usb.h +++ b/include/usb.h @@ -546,10 +546,20 @@ struct usb_hub_descriptor { unsigned short wHubCharacteristics; unsigned char bPwrOn2PwrGood; unsigned char bHubContrCurrent; - unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; - unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; - /* DeviceRemovable and PortPwrCtrlMask want to be variable-length - bitmaps that hold max 255 entries. (bit0 is ignored) */ + /* 2.0 and 3.0 hubs differ here */ + union { + struct { + /* add 1 bit for hub status change; round to bytes */ + __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; + __u8 PortPowerCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; + } __attribute__ ((packed)) hs; + + struct { + __u8 bHubHdrDecLat; + __le16 wHubDelay; + __le16 DeviceRemovable; + } __attribute__ ((packed)) ss; + } u; } __attribute__ ((packed)); -- cgit v0.10.2 From 98ba3d6c23963852c49b08e19fdbe1738edffe5b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:01 +0800 Subject: usb: hub: Add 3.0 hub port status mask of 2.0 hub USB 3.0 hub port status has different bit position regarding to port power, port speed, etc. But others are the same as 2.0 hubs. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/include/usb_defs.h b/include/usb_defs.h index 608a0ca..6b4385a 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -262,12 +262,17 @@ /* * Changes to wPortStatus bit field in USB 3.0 - * See USB 3.0 spec Table 10-11 + * See USB 3.0 spec Table 10-10 */ #define USB_SS_PORT_STAT_LINK_STATE 0x01e0 #define USB_SS_PORT_STAT_POWER 0x0200 #define USB_SS_PORT_STAT_SPEED 0x1c00 #define USB_SS_PORT_STAT_SPEED_5GBPS 0x0000 +/* Bits that are the same from USB 2.0 */ +#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \ + USB_PORT_STAT_ENABLE | \ + USB_PORT_STAT_OVERCURRENT | \ + USB_PORT_STAT_RESET) /* wPortChange bits */ #define USB_PORT_STAT_C_CONNECTION 0x0001 -- cgit v0.10.2 From 1bdcd9019d576b2637393e0b1ec65eab67a7c82f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:02 +0800 Subject: usb: xhci: Change MAX_HC_PORTS to 255 HCSPARAMS1:MaxPorts field specifies the maximum port number value, and its valid values are in the range of 1 to 255. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 32dd611..3cf08e4 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -30,7 +30,7 @@ /* Max number of USB devices for any host controller - limit in section 6.1 */ #define MAX_HC_SLOTS 256 /* Section 5.3.3 - MaxPorts */ -#define MAX_HC_PORTS 127 +#define MAX_HC_PORTS 255 /* Up to 16 ms to halt an HC */ #define XHCI_MAX_HALT_USEC (16*1000) @@ -102,8 +102,8 @@ struct xhci_hccr { #define HCS_MAX_INTRS(p) (((p) >> 8) & 0x7ff) /* bits 24:31, Max Ports - max value is 0x7F = 127 ports */ #define HCS_MAX_PORTS_SHIFT 24 -#define HCS_MAX_PORTS_MASK (0x7f << HCS_MAX_PORTS_SHIFT) -#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f) +#define HCS_MAX_PORTS_MASK (0xff << HCS_MAX_PORTS_SHIFT) +#define HCS_MAX_PORTS(p) (((p) >> 24) & 0xff) /* HCSPARAMS2 - hcs_params2 - bitmasks */ /* bits 0:3, frames or uframes that SW needs to queue transactions -- cgit v0.10.2 From 7274671e045ec78a0023949d99c26ae6b98b7a8e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:03 +0800 Subject: usb: xhci: Get rid of CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS xHC reports supported maximum number of ports in the HCSPARAMS1 register, so it's unnecessary to use a hardcoded config option CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d5a1b34..62ab62b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -668,12 +668,14 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, uint32_t reg; volatile uint32_t *status_reg; struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + struct xhci_hccr *hccr = ctrl->hccr; struct xhci_hcor *hcor = ctrl->hcor; + int max_ports = HCS_MAX_PORTS(xhci_readl(&hccr->cr_hcsparams1)); if ((req->requesttype & USB_RT_PORT) && - le16_to_cpu(req->index) > CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", - le16_to_cpu(req->index) - 1); + le16_to_cpu(req->index) > max_ports) { + printf("The request port(%d) exceeds maximum port number\n", + le16_to_cpu(req->index) - 1); return -EINVAL; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 3cf08e4..b9602ba 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -172,9 +172,7 @@ struct xhci_hcor { volatile uint64_t or_dcbaap; volatile uint32_t or_config; volatile uint32_t reserved_2[241]; - struct xhci_hcor_port_regs portregs[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS]; - - uint32_t reserved_4[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS * 254]; + struct xhci_hcor_port_regs portregs[MAX_HC_PORTS]; }; /* USBCMD - USB command - command bitmasks */ -- cgit v0.10.2 From 29313428744112ad8f601c86e29440a386aa6543 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:04 +0800 Subject: configs: Remove CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS in all boards Now that xHCD does not use CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS, remove it in all boards' config files. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h index a91b7df..70e7473 100644 --- a/include/configs/am43xx_evm.h +++ b/include/configs/am43xx_evm.h @@ -82,7 +82,6 @@ #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) #define CONFIG_SYS_USB_FAT_BOOT_PARTITION 1 #define CONFIG_USB_XHCI_OMAP -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_OMAP_USB_PHY #define CONFIG_AM437X_USB2PHY2_HOST diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h index 9216998..9976686 100644 --- a/include/configs/am57xx_evm.h +++ b/include/configs/am57xx_evm.h @@ -92,7 +92,6 @@ /* USB xHCI HOST */ #define CONFIG_USB_XHCI_OMAP -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_OMAP_USB_PHY #define CONFIG_OMAP_USB3PHY1_HOST diff --git a/include/configs/cl-som-am57x.h b/include/configs/cl-som-am57x.h index c1cf413..120ac02 100644 --- a/include/configs/cl-som-am57x.h +++ b/include/configs/cl-som-am57x.h @@ -83,7 +83,6 @@ /* USB xHCI HOST */ #define CONFIG_USB_XHCI_OMAP -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_OMAP_USB_PHY #define CONFIG_OMAP_USB3PHY1_HOST diff --git a/include/configs/cm_t43.h b/include/configs/cm_t43.h index f6e0743..7a61107 100644 --- a/include/configs/cm_t43.h +++ b/include/configs/cm_t43.h @@ -60,7 +60,6 @@ /* USB support */ #define CONFIG_USB_XHCI_OMAP -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_OMAP_USB_PHY #define CONFIG_AM437X_USB2PHY2_HOST diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h index 8566bdc..b509151 100644 --- a/include/configs/dra7xx_evm.h +++ b/include/configs/dra7xx_evm.h @@ -154,7 +154,6 @@ /* USB xHCI HOST */ #define CONFIG_USB_XHCI_OMAP -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_OMAP_USB_PHY #define CONFIG_OMAP_USB2PHY2_HOST diff --git a/include/configs/ds414.h b/include/configs/ds414.h index a209e6f..c1e9346 100644 --- a/include/configs/ds414.h +++ b/include/configs/ds414.h @@ -68,7 +68,6 @@ #if 0 #undef CONFIG_DM_USB #define CONFIG_USB_XHCI_PCI -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif #if !defined(CONFIG_USB_XHCI_HCD) diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index 378219d..7cb3278 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -135,7 +135,6 @@ /* USB */ #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_ASIX diff --git a/include/configs/ls1012afrdm.h b/include/configs/ls1012afrdm.h index f6f88e8..6b1ba57 100644 --- a/include/configs/ls1012afrdm.h +++ b/include/configs/ls1012afrdm.h @@ -39,7 +39,6 @@ #ifdef CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif #define CONFIG_CMD_MEMINFO diff --git a/include/configs/ls1012aqds.h b/include/configs/ls1012aqds.h index 9e6c7a7..bebb0df 100644 --- a/include/configs/ls1012aqds.h +++ b/include/configs/ls1012aqds.h @@ -124,7 +124,6 @@ #ifdef CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif /* MMC */ diff --git a/include/configs/ls1012ardb.h b/include/configs/ls1012ardb.h index 0705bc5..32c8cec 100644 --- a/include/configs/ls1012ardb.h +++ b/include/configs/ls1012ardb.h @@ -27,7 +27,6 @@ #ifdef CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif /* diff --git a/include/configs/ls1021aiot.h b/include/configs/ls1021aiot.h index 1f2eb52..58f893f 100644 --- a/include/configs/ls1021aiot.h +++ b/include/configs/ls1021aiot.h @@ -26,7 +26,6 @@ #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_XHCI_DWC3 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif #if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_XHCI_USB) diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h index 251a66e..83e7e7a 100644 --- a/include/configs/ls1021aqds.h +++ b/include/configs/ls1021aqds.h @@ -413,7 +413,6 @@ unsigned long get_board_ddr_clk(void); #ifdef CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif /* diff --git a/include/configs/ls1021atwr.h b/include/configs/ls1021atwr.h index b9e5cdb..0aa6fdd 100644 --- a/include/configs/ls1021atwr.h +++ b/include/configs/ls1021atwr.h @@ -50,7 +50,6 @@ #ifdef CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif #define CONFIG_SYS_CLK_FREQ 100000000 diff --git a/include/configs/ls1043aqds.h b/include/configs/ls1043aqds.h index 415a705..0897da1 100644 --- a/include/configs/ls1043aqds.h +++ b/include/configs/ls1043aqds.h @@ -377,7 +377,6 @@ unsigned long get_board_ddr_clk(void); #ifdef CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif /* diff --git a/include/configs/ls1043ardb.h b/include/configs/ls1043ardb.h index 59e7760..617a712 100644 --- a/include/configs/ls1043ardb.h +++ b/include/configs/ls1043ardb.h @@ -288,7 +288,6 @@ #ifdef CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif #endif diff --git a/include/configs/ls1046aqds.h b/include/configs/ls1046aqds.h index ea99676..bb3d941 100644 --- a/include/configs/ls1046aqds.h +++ b/include/configs/ls1046aqds.h @@ -144,7 +144,6 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_XHCI_DWC3 #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_CMD_USB #define CONFIG_USB_STORAGE #endif diff --git a/include/configs/ls1046ardb.h b/include/configs/ls1046ardb.h index 20a5e7f..8c72291 100644 --- a/include/configs/ls1046ardb.h +++ b/include/configs/ls1046ardb.h @@ -220,7 +220,6 @@ #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_XHCI_DWC3 #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_CMD_USB #define CONFIG_USB_STORAGE #endif diff --git a/include/configs/ls2080aqds.h b/include/configs/ls2080aqds.h index 929ae32..66936c4 100644 --- a/include/configs/ls2080aqds.h +++ b/include/configs/ls2080aqds.h @@ -446,7 +446,6 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #include diff --git a/include/configs/ls2080ardb.h b/include/configs/ls2080ardb.h index 0be4c4f..744a789 100644 --- a/include/configs/ls2080ardb.h +++ b/include/configs/ls2080ardb.h @@ -346,7 +346,6 @@ unsigned long get_board_sys_clk(void); #define CONFIG_HAS_FSL_XHCI_USB #define CONFIG_USB_XHCI_FSL #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #undef CONFIG_CMDLINE_EDITING #include diff --git a/include/configs/mvebu_armada-37xx.h b/include/configs/mvebu_armada-37xx.h index 778cc9e..feb8112 100644 --- a/include/configs/mvebu_armada-37xx.h +++ b/include/configs/mvebu_armada-37xx.h @@ -97,10 +97,8 @@ #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 /* USB 3.0 */ -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3 - #define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \ - CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) + 3) /* USB ethernet */ #define CONFIG_USB_HOST_ETHER diff --git a/include/configs/mvebu_armada-8k.h b/include/configs/mvebu_armada-8k.h index 53db10f..da66d64 100644 --- a/include/configs/mvebu_armada-8k.h +++ b/include/configs/mvebu_armada-8k.h @@ -101,10 +101,8 @@ #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 /* USB 3.0 */ -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3 - #define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \ - CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) + 3) /* USB ethernet */ #define CONFIG_USB_HOST_ETHER diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h index 7f9f0c5..906c821 100644 --- a/include/configs/rk3328_common.h +++ b/include/configs/rk3328_common.h @@ -63,6 +63,4 @@ #define CONFIG_USB_OHCI_NEW #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 -/* xhci host */ -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #endif diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h index 6c9d760..3317887 100644 --- a/include/configs/rk3399_common.h +++ b/include/configs/rk3399_common.h @@ -80,7 +80,4 @@ #define CONFIG_USB_ETHER_SMSC95XX #define CONFIG_USB_ETHER_RTL8152 -/* rockchip xhci host driver */ -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 - #endif diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h index c6122a0..26290ef 100644 --- a/include/configs/ti_armv7_keystone2.h +++ b/include/configs/ti_armv7_keystone2.h @@ -193,7 +193,6 @@ /* USB Configuration */ #define CONFIG_USB_XHCI_KEYSTONE -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_USB_SS_BASE KS2_USB_SS_BASE #define CONFIG_USB_HOST_XHCI_BASE KS2_USB_HOST_XHCI_BASE #define CONFIG_DEV_USB_PHY_BASE KS2_DEV_USB_PHY_BASE diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index cc65f07..6f53139 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -101,9 +101,6 @@ #define CONFIG_SYS_NAND_USE_FLASH_BBT #define CONFIG_SYS_NAND_BAD_BLOCK_POS 0 -/* USB */ -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 4 - /* SD/MMC */ #define CONFIG_SUPPORT_EMMC_BOOT diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index c30e37c..7c5ec19 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -90,8 +90,6 @@ #define CONFIG_SYS_LOAD_ADDR 0x8000000 #if defined(CONFIG_ZYNQMP_USB) -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 - #define CONFIG_SYS_DFU_DATA_BUF_SIZE 0x1800000 #define DFU_DEFAULT_POLL_TIMEOUT 300 #define CONFIG_USB_CABLE_CHECK diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 93f0bf4..6312863 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4877,7 +4877,6 @@ CONFIG_SYS_USB_OHCI_CPU_INIT CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS CONFIG_SYS_USB_OHCI_REGS_BASE CONFIG_SYS_USB_OHCI_SLOT_NAME -CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS CONFIG_SYS_USER_SWITCHES_BASE CONFIG_SYS_USE_BOOT_NORFLASH CONFIG_SYS_USE_DATAFLASH -- cgit v0.10.2 From 99c225568890df8fd224a4944d98599a5b2b721d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:05 +0800 Subject: usb: ehci: Get rid of CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS EHC reports supported maximum number of ports in the HCSPARAMS register, so it's unnecessary to use a hardcoded config option CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 40ac3a6..3243c1d 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -148,9 +148,12 @@ static void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, static uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port) { - if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { + int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams)); + + if (port < 0 || port >= max_ports) { /* Printing the message would cause a scan failure! */ - debug("The request port(%u) is not configured\n", port); + debug("The request port(%u) exceeds maximum port number\n", + port); return NULL; } @@ -205,6 +208,7 @@ static int ehci_shutdown(struct ehci_ctrl *ctrl) { int i, ret = 0; uint32_t cmd, reg; + int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams)); if (!ctrl || !ctrl->hcor) return -EINVAL; @@ -219,7 +223,7 @@ static int ehci_shutdown(struct ehci_ctrl *ctrl) 100 * 1000); if (!ret) { - for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) { + for (i = 0; i < max_ports; i++) { reg = ehci_readl(&ctrl->hcor->or_portsc[i]); reg |= EHCI_PS_SUSP; ehci_writel(&ctrl->hcor->or_portsc[i], reg); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 2ab830d..7c39bec 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -11,9 +11,8 @@ #include -#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 -#endif +/* Section 2.2.3 - N_PORTS */ +#define MAX_HC_PORTS 15 /* * Register Space. @@ -62,7 +61,7 @@ struct ehci_hcor { uint32_t _reserved_1_[6]; uint32_t or_configflag; #define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ - uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; + uint32_t or_portsc[MAX_HC_PORTS]; #define PORTSC_PSPD(x) (((x) >> 26) & 0x3) #define PORTSC_PSPD_FS 0x0 #define PORTSC_PSPD_LS 0x1 -- cgit v0.10.2 From cbb89ed026e761b58a2568fea7b98135abcefe21 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:06 +0800 Subject: configs: Remove CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS in all boards Now that EHCD does not use CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS, remove it in all boards' config files. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/arch/arm/include/asm/ehci-omap.h b/arch/arm/include/asm/ehci-omap.h index 5a53e40..9dbb2c4 100644 --- a/arch/arm/include/asm/ehci-omap.h +++ b/arch/arm/include/asm/ehci-omap.h @@ -19,11 +19,7 @@ enum usbhs_omap_port_mode { OMAP_EHCI_PORT_MODE_HSIC, }; -#ifdef CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS -#define OMAP_HS_USB_PORTS CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS -#else #define OMAP_HS_USB_PORTS 3 -#endif #define is_ehci_phy_mode(x) ((x) == OMAP_EHCI_PORT_MODE_PHY) #define is_ehci_tll_mode(x) ((x) == OMAP_EHCI_PORT_MODE_TLL) diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h index 0a2bcb2..32c5932 100644 --- a/include/configs/MPC8572DS.h +++ b/include/configs/MPC8572DS.h @@ -560,7 +560,6 @@ #define CONFIG_USB_EHCI_PCI #define CONFIG_EHCI_HCD_INIT_AFTER_RESET #define CONFIG_PCI_EHCI_DEVICE 0 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 #endif #undef CONFIG_WATCHDOG /* watchdog disabled */ diff --git a/include/configs/cm_t54.h b/include/configs/cm_t54.h index 69706d2..8a4c333 100644 --- a/include/configs/cm_t54.h +++ b/include/configs/cm_t54.h @@ -56,7 +56,6 @@ #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) /* USB UHH support options */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET #define CONFIG_OMAP_EHCI_PHY2_RESET_GPIO 76 /* HSIC2 HUB #RESET */ diff --git a/include/configs/corvus.h b/include/configs/corvus.h index ed1a228..0150727 100644 --- a/include/configs/corvus.h +++ b/include/configs/corvus.h @@ -94,9 +94,6 @@ #define CONFIG_NET_RETRY_COUNT 20 #define CONFIG_AT91_WANTS_COMMON_PHY -/* USB */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 - #define CONFIG_MTD_DEVICE #define CONFIG_MTD_PARTITIONS diff --git a/include/configs/duovero.h b/include/configs/duovero.h index 8efcc94..c4496a7 100644 --- a/include/configs/duovero.h +++ b/include/configs/duovero.h @@ -25,8 +25,6 @@ #define CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS /* USB UHH support options */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 - #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 1 #define CONFIG_OMAP_EHCI_PHY2_RESET_GPIO 62 diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index 7cb3278..3b73bbc 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -134,8 +134,6 @@ /* Enable Time Command */ /* USB */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 - #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_ASIX #define CONFIG_USB_ETHER_SMSC95XX diff --git a/include/configs/ma5d4evk.h b/include/configs/ma5d4evk.h index 2744efb..7c28a94 100644 --- a/include/configs/ma5d4evk.h +++ b/include/configs/ma5d4evk.h @@ -96,7 +96,6 @@ * USB */ #ifdef CONFIG_CMD_USB -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 /* USB device */ #define CONFIG_USB_ETHER diff --git a/include/configs/mcx.h b/include/configs/mcx.h index 73fdfbd..3f5fdab 100644 --- a/include/configs/mcx.h +++ b/include/configs/mcx.h @@ -74,7 +74,6 @@ /* EHCI */ #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 57 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_ASIX #define CONFIG_USB_ETHER_MCS7830 diff --git a/include/configs/mvebu_armada-37xx.h b/include/configs/mvebu_armada-37xx.h index feb8112..1307d21 100644 --- a/include/configs/mvebu_armada-37xx.h +++ b/include/configs/mvebu_armada-37xx.h @@ -93,12 +93,7 @@ #define CONFIG_NET_RETRY_COUNT 50 #define CONFIG_PHY_MARVELL -/* USB 2.0 */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 - -/* USB 3.0 */ -#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \ - 3) +#define CONFIG_USB_MAX_CONTROLLER_COUNT (3 + 3) /* USB ethernet */ #define CONFIG_USB_HOST_ETHER diff --git a/include/configs/mvebu_armada-8k.h b/include/configs/mvebu_armada-8k.h index da66d64..86ae19c 100644 --- a/include/configs/mvebu_armada-8k.h +++ b/include/configs/mvebu_armada-8k.h @@ -97,12 +97,7 @@ #define CONFIG_ARP_TIMEOUT 200 #define CONFIG_NET_RETRY_COUNT 50 -/* USB 2.0 */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 - -/* USB 3.0 */ -#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \ - 3) +#define CONFIG_USB_MAX_CONTROLLER_COUNT (3 + 3) /* USB ethernet */ #define CONFIG_USB_HOST_ETHER diff --git a/include/configs/mx35pdk.h b/include/configs/mx35pdk.h index 9ae3d18..8338d6d 100644 --- a/include/configs/mx35pdk.h +++ b/include/configs/mx35pdk.h @@ -195,7 +195,6 @@ #define CONFIG_SYS_NAND_LARGEPAGE /* EHCI driver */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 #define CONFIG_EHCI_IS_TDI #define CONFIG_EHCI_HCD_INIT_AFTER_RESET #define CONFIG_USB_EHCI_MXC diff --git a/include/configs/odroid.h b/include/configs/odroid.h index 9552c96..563854d 100644 --- a/include/configs/odroid.h +++ b/include/configs/odroid.h @@ -184,7 +184,6 @@ /* USB */ #define CONFIG_USB_EHCI_EXYNOS -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_SMSC95XX diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h index 4422d5e..2fc6693 100644 --- a/include/configs/omap3_beagle.h +++ b/include/configs/omap3_beagle.h @@ -58,7 +58,6 @@ #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 147 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_ASIX #define CONFIG_USB_ETHER_MCS7830 diff --git a/include/configs/omap3_overo.h b/include/configs/omap3_overo.h index 834822d..133069a 100644 --- a/include/configs/omap3_overo.h +++ b/include/configs/omap3_overo.h @@ -41,7 +41,6 @@ /* USB EHCI */ #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 183 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 /* commands to include */ diff --git a/include/configs/omap4_panda.h b/include/configs/omap4_panda.h index a973ce6..9951980 100644 --- a/include/configs/omap4_panda.h +++ b/include/configs/omap4_panda.h @@ -17,8 +17,6 @@ */ /* USB UHH support options */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 - #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 1 #define CONFIG_OMAP_EHCI_PHY2_RESET_GPIO 62 diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h index eb5e6df..9b65009 100644 --- a/include/configs/omap5_uevm.h +++ b/include/configs/omap5_uevm.h @@ -51,7 +51,6 @@ #define CONFIG_SYS_I2C_TCA642X_ADDR 0x22 /* USB UHH support options */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET #define CONFIG_OMAP_EHCI_PHY2_RESET_GPIO 80 diff --git a/include/configs/picosam9g45.h b/include/configs/picosam9g45.h index 88f841d..a14739f 100644 --- a/include/configs/picosam9g45.h +++ b/include/configs/picosam9g45.h @@ -97,9 +97,6 @@ #define CONFIG_RESET_PHY_R #define CONFIG_AT91_WANTS_COMMON_PHY -/* USB */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 - #define CONFIG_SYS_LOAD_ADDR 0x22000000 /* load address */ #define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE diff --git a/include/configs/poplar.h b/include/configs/poplar.h index d59f32a..d2ecd0d 100644 --- a/include/configs/poplar.h +++ b/include/configs/poplar.h @@ -30,7 +30,6 @@ #define CONFIG_PL01X_SERIAL /* USB configuration */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 #define CONFIG_SYS_USB_EVENT_POLL #define CONFIG_USB_HOST_ETHER diff --git a/include/configs/sama5d2_ptc.h b/include/configs/sama5d2_ptc.h index b25be97..401f198 100644 --- a/include/configs/sama5d2_ptc.h +++ b/include/configs/sama5d2_ptc.h @@ -65,10 +65,6 @@ /* USB */ #define CONFIG_CMD_USB -#ifdef CONFIG_CMD_USB -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 -#endif - /* USB device */ #define CONFIG_USB_GADGET #define CONFIG_USB_GADGET_DUALSPEED diff --git a/include/configs/snapper9g45.h b/include/configs/snapper9g45.h index 2c5f264..47dd991 100644 --- a/include/configs/snapper9g45.h +++ b/include/configs/snapper9g45.h @@ -60,9 +60,6 @@ #define CONFIG_TFTP_PORT #define CONFIG_TFTP_TSIZE -/* USB */ -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 - /* MMC */ #define CONFIG_GENERIC_ATMEL_MCI diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index fefd58f..681c91c 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -310,7 +310,6 @@ extern int soft_i2c_gpio_scl; #define CONFIG_USB_OHCI_NEW #define CONFIG_USB_OHCI_SUNXI #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 #endif #ifdef CONFIG_USB_MUSB_SUNXI diff --git a/include/configs/tam3517-common.h b/include/configs/tam3517-common.h index a9991fc..fb173eb 100644 --- a/include/configs/tam3517-common.h +++ b/include/configs/tam3517-common.h @@ -67,7 +67,6 @@ 115200} /* EHCI */ #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 25 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 /* commands to include */ #define CONFIG_CMD_NAND /* NAND support */ diff --git a/include/configs/tao3530.h b/include/configs/tao3530.h index 38f5bd0..08134f4 100644 --- a/include/configs/tao3530.h +++ b/include/configs/tao3530.h @@ -228,7 +228,6 @@ /* USB EHCI */ #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 162 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_SMSC95XX diff --git a/include/configs/tegra114-common.h b/include/configs/tegra114-common.h index 107a0f8..75d2065 100644 --- a/include/configs/tegra114-common.h +++ b/include/configs/tegra114-common.h @@ -63,6 +63,5 @@ /* For USB EHCI controller */ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 #endif /* _TEGRA114_COMMON_H_ */ diff --git a/include/configs/tegra124-common.h b/include/configs/tegra124-common.h index 8cf9bac..0d61753 100644 --- a/include/configs/tegra124-common.h +++ b/include/configs/tegra124-common.h @@ -65,7 +65,6 @@ /* For USB EHCI controller */ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 /* GPU needs setup */ #define CONFIG_TEGRA_GPU diff --git a/include/configs/tegra20-common.h b/include/configs/tegra20-common.h index db1cc24..342ffbe 100644 --- a/include/configs/tegra20-common.h +++ b/include/configs/tegra20-common.h @@ -82,7 +82,6 @@ */ #define CONFIG_USB_EHCI_TXFIFO_THRESH 10 #define CONFIG_EHCI_IS_TDI -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 #define CONFIG_SYS_NAND_SELF_INIT #define CONFIG_SYS_NAND_ONFI_DETECTION diff --git a/include/configs/tegra210-common.h b/include/configs/tegra210-common.h index 874fe34d..4c05576 100644 --- a/include/configs/tegra210-common.h +++ b/include/configs/tegra210-common.h @@ -68,7 +68,6 @@ /* For USB EHCI controller */ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 /* GPU needs setup */ #define CONFIG_TEGRA_GPU diff --git a/include/configs/tegra30-common.h b/include/configs/tegra30-common.h index 6083847..c2096fb 100644 --- a/include/configs/tegra30-common.h +++ b/include/configs/tegra30-common.h @@ -64,6 +64,5 @@ /* For USB EHCI controller */ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 #endif /* _TEGRA30_COMMON_H_ */ diff --git a/include/configs/vinco.h b/include/configs/vinco.h index dc35b28..adff1b6 100644 --- a/include/configs/vinco.h +++ b/include/configs/vinco.h @@ -63,12 +63,6 @@ #endif -/* USB */ - -#ifdef CONFIG_CMD_USB -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 -#endif - /* USB device */ #define CONFIG_USB_ETHER #define CONFIG_USB_ETH_RNDIS diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index 1be6974..aa1e505 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -128,7 +128,6 @@ * USB configuration */ #define CONFIG_USB_EHCI_PCI -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 12 #define CONFIG_SYS_USB_EVENT_POLL #define CONFIG_USB_HOST_ETHER diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 6312863..8f921c1 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4868,7 +4868,6 @@ CONFIG_SYS_UNSPEC_STRID CONFIG_SYS_USBCTRL CONFIG_SYS_USBD_BASE CONFIG_SYS_USB_EHCI_CPU_INIT -CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS CONFIG_SYS_USB_EHCI_REGS_BASE CONFIG_SYS_USB_FAT_BOOT_PARTITION CONFIG_SYS_USB_HOST -- cgit v0.10.2 From 78abf14fc2ff577d0385f36fe91769d458fbc4a5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:07 +0800 Subject: usb: cmd: Print actual packet size for super speed devices USB 3.0 defines bMaxPacketSize0 field in the device descriptor as the exponent of 2, so let's print the calculated actual size. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/cmd/usb.c b/cmd/usb.c index 4fa456e..992d414 100644 --- a/cmd/usb.c +++ b/cmd/usb.c @@ -150,6 +150,8 @@ static void usb_display_string(struct usb_device *dev, int index) static void usb_display_desc(struct usb_device *dev) { + uint packet_size = dev->descriptor.bMaxPacketSize0; + if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) { printf("%d: %s, USB Revision %x.%x\n", dev->devnum, usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass), @@ -171,9 +173,10 @@ static void usb_display_desc(struct usb_device *dev) usb_get_class_desc( dev->config.if_desc[0].desc.bInterfaceClass)); } + if (dev->descriptor.bcdUSB >= cpu_to_le16(0x0300)) + packet_size = 1 << packet_size; printf(" - PacketSize: %d Configurations: %d\n", - dev->descriptor.bMaxPacketSize0, - dev->descriptor.bNumConfigurations); + packet_size, dev->descriptor.bNumConfigurations); printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n", dev->descriptor.idVendor, dev->descriptor.idProduct, (dev->descriptor.bcdDevice>>8) & 0xff, -- cgit v0.10.2 From d7cde2811326731c9453b5880646b50a0b994916 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:08 +0800 Subject: usb: xhci: Convert CONFIG_USB_XHCI_PCI to Kconfig Add CONFIG_USB_XHCI_PCI as a Kconfig option. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index bc2c1f1..9edc589 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -31,6 +31,12 @@ config USB_XHCI_MVEBU SoCs, which includes Armada8K, Armada3700 and other Armada family SoCs. +config USB_XHCI_PCI + bool "Support for PCI-based xHCI USB controller" + default y if X86 + help + Enables support for the PCI-based xHCI controller. + config USB_XHCI_ROCKCHIP bool "Support for Rockchip on-chip xHCI USB controller" depends on ARCH_ROCKCHIP diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 8f921c1..2d642de 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -5194,7 +5194,6 @@ CONFIG_USB_XHCI_EXYNOS CONFIG_USB_XHCI_FSL CONFIG_USB_XHCI_KEYSTONE CONFIG_USB_XHCI_OMAP -CONFIG_USB_XHCI_PCI CONFIG_USER_LOWLEVEL_INIT CONFIG_USE_FDT CONFIG_USE_INTERRUPT -- cgit v0.10.2 From 6e4d039aaaf87dcc83c743948c6bbcb49739e6a2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:09 +0800 Subject: x86: minnowmax: Add a environment variable for USB power-on delay Occasionally it was observed that on Intel MinnowMax board, with a USB 2.0 device connected to the bottom port, when doing 'usb start' on the xHCI controller: scanning bus 0 for devices... cannot reset port 3!? But neither of the two USB ports is routed to xHCI root port 3. Adding some debug information shows that xHCI port 3 PORTSC register mysteriously reports both CCS = 1 and CSC = 1. This is not seen every time. After increasing the timeout to wait for power to become stable, the issue is gone. So this indicates current default USB power-on delay (20ms) might be at a critical region where power is stable/unstable. U-Boot provides a mechanism to have a environment variable to override the default one. Add one for MinnowMax. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index ae95485..6ea607d 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -20,7 +20,8 @@ #define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,serial\0" \ "stdout=vidconsole,serial\0" \ - "stderr=vidconsole,serial\0" + "stderr=vidconsole,serial\0" \ + "usb_pgood_delay=40\0" #define CONFIG_SCSI_DEV_LIST \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}, \ -- cgit v0.10.2 From c9621012a6f86500d60648a5e714b1c36e9111b9 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:50:10 +0800 Subject: x86: minnowmax: Enable USB xHCI support BayTrail SoC supports both EHCI and xHCI controllers. However only one host controller (either EHCI or xHCI) can be used. To enable HSIC and SS ports, xHCI must be used. This turns on xHCI support on Intel MinnowMax board. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Stefan Roese diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts index 4c0a8fe..a0ad03c 100644 --- a/arch/x86/dts/minnowmax.dts +++ b/arch/x86/dts/minnowmax.dts @@ -272,6 +272,9 @@ fsp,enable-spi; fsp,enable-sata; fsp,sata-mode = ; +#ifdef CONFIG_USB_XHCI_HCD + fsp,enable-xhci; +#endif fsp,lpe-mode = ; fsp,lpss-sio-mode = ; fsp,enable-dma0; diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig index 81e8253..d058753 100644 --- a/configs/minnowmax_defconfig +++ b/configs/minnowmax_defconfig @@ -69,6 +69,7 @@ CONFIG_ICH_SPI=y CONFIG_TIMER=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y CONFIG_DM_VIDEO=y -- cgit v0.10.2 From 978f6a3b14f212cc7a956846c9e0cb9ca18620b1 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:07 +0800 Subject: usb: xhci-pci: Drop non-DM version of xhci-pci driver As there is no board that currently uses xhci-pci driver without DM USB, drop its support and leave only DM support. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 9edc589..67ad72b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -33,6 +33,7 @@ config USB_XHCI_MVEBU config USB_XHCI_PCI bool "Support for PCI-based xHCI USB controller" + depends on DM_USB default y if X86 help Enables support for the PCI-based xHCI controller. diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 63daaa6..5ad8452 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -14,56 +14,6 @@ #include "xhci.h" -#ifndef CONFIG_DM_USB - -/* - * Create the appropriate control structures to manage a new XHCI host - * controller. - */ -int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr, - struct xhci_hcor **ret_hcor) -{ - struct xhci_hccr *hccr; - struct xhci_hcor *hcor; - pci_dev_t pdev; - uint32_t cmd; - int len; - - pdev = pci_find_class(PCI_CLASS_SERIAL_USB_XHCI, index); - if (pdev < 0) { - printf("XHCI host controller not found\n"); - return -1; - } - - hccr = (struct xhci_hccr *)pci_map_bar(pdev, - PCI_BASE_ADDRESS_0, PCI_REGION_MEM); - len = HC_LENGTH(xhci_readl(&hccr->cr_capbase)); - hcor = (struct xhci_hcor *)((uint32_t)hccr + len); - - debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", - (uint32_t)hccr, (uint32_t)hcor, len); - - *ret_hccr = hccr; - *ret_hcor = hcor; - - /* enable busmaster */ - pci_read_config_dword(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_dword(pdev, PCI_COMMAND, cmd); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding * to the XHCI host - * controller - */ -void xhci_hcd_stop(int index) -{ -} - -#else - struct xhci_pci_priv { struct xhci_ctrl ctrl; /* Needs to come first in this struct! */ }; @@ -137,5 +87,3 @@ static struct pci_device_id xhci_pci_supported[] = { }; U_BOOT_PCI_DEVICE(xhci_pci, xhci_pci_supported); - -#endif /* CONFIG_DM_USB */ -- cgit v0.10.2 From 5e941943d88aebcfc2e9c8a0801061d39e218bb5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:08 +0800 Subject: usb: xhci-pci: Clean up the driver a little bit This cleans up the driver a little bit. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5ad8452..e4a0ef4 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -8,16 +8,10 @@ #include #include -#include #include #include - #include "xhci.h" -struct xhci_pci_priv { - struct xhci_ctrl ctrl; /* Needs to come first in this struct! */ -}; - static void xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, struct xhci_hcor **ret_hcor) { @@ -53,17 +47,6 @@ static int xhci_pci_probe(struct udevice *dev) return xhci_register(dev, hccr, hcor); } -static int xhci_pci_remove(struct udevice *dev) -{ - int ret; - - ret = xhci_deregister(dev); - if (ret) - return ret; - - return 0; -} - static const struct udevice_id xhci_pci_ids[] = { { .compatible = "xhci-pci" }, { } @@ -73,11 +56,11 @@ U_BOOT_DRIVER(xhci_pci) = { .name = "xhci_pci", .id = UCLASS_USB, .probe = xhci_pci_probe, - .remove = xhci_pci_remove, + .remove = xhci_deregister, .of_match = xhci_pci_ids, .ops = &xhci_usb_ops, .platdata_auto_alloc_size = sizeof(struct usb_platdata), - .priv_auto_alloc_size = sizeof(struct xhci_pci_priv), + .priv_auto_alloc_size = sizeof(struct xhci_ctrl), .flags = DM_FLAG_ALLOC_PRIV_DMA, }; -- cgit v0.10.2 From dfa96e06761e223288e59d7a3e1d574f014b5a0d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:09 +0800 Subject: usb: hub: Use 'struct usb_hub_device' as hub device's uclass_priv Use USB hub device's dev->uclass_priv to point to 'usb_hub_device' so that with driver model usb_hub_reset() and usb_hub_allocate() are no longer needed. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/common/usb_hub.c b/common/usb_hub.c index a46d26a..37b358b 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -55,9 +55,6 @@ struct usb_device_scan { struct list_head list; }; -/* TODO(sjg@chromium.org): Remove this when CONFIG_DM_USB is defined */ -static struct usb_hub_device hub_dev[USB_MAX_HUB]; -static int usb_hub_index; static LIST_HEAD(usb_scan_list); __weak void usb_hub_reset_devices(int port) @@ -164,6 +161,10 @@ static void usb_hub_power_on(struct usb_hub_device *hub) max(100, (int)pgood_delay) + 1000); } +#ifndef CONFIG_DM_USB +static struct usb_hub_device hub_dev[USB_MAX_HUB]; +static int usb_hub_index; + void usb_hub_reset(void) { usb_hub_index = 0; @@ -180,6 +181,7 @@ static struct usb_hub_device *usb_hub_allocate(void) printf("ERROR: USB_MAX_HUB (%d) reached\n", USB_MAX_HUB); return NULL; } +#endif #define MAX_TRIES 5 @@ -543,6 +545,20 @@ out: return ret; } +static struct usb_hub_device *usb_get_hub_device(struct usb_device *dev) +{ + struct usb_hub_device *hub; + +#ifndef CONFIG_DM_USB + /* "allocate" Hub device */ + hub = usb_hub_allocate(); +#else + hub = dev_get_uclass_priv(dev->dev); +#endif + + return hub; +} + static int usb_hub_configure(struct usb_device *dev) { int i, length; @@ -554,11 +570,11 @@ static int usb_hub_configure(struct usb_device *dev) __maybe_unused struct usb_hub_status *hubsts; int ret; - /* "allocate" Hub device */ - hub = usb_hub_allocate(); + hub = usb_get_hub_device(dev); if (hub == NULL) return -ENOMEM; hub->pusb_dev = dev; + /* Get the the hub descriptor */ ret = usb_get_hub_descriptor(dev, buffer, 4); if (ret < 0) { @@ -792,6 +808,7 @@ UCLASS_DRIVER(usb_hub) = { .child_pre_probe = usb_child_pre_probe, .per_child_auto_alloc_size = sizeof(struct usb_device), .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), + .per_device_auto_alloc_size = sizeof(struct usb_hub_device), }; static const struct usb_device_id hub_id_table[] = { diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index efc5d4e..d8d74bd 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -177,7 +177,6 @@ int usb_stop(void) #ifdef CONFIG_USB_STORAGE usb_stor_reset(); #endif - usb_hub_reset(); uc_priv->companion_device_count = 0; usb_started = 0; @@ -230,7 +229,6 @@ int usb_init(void) int ret; asynch_allowed = 1; - usb_hub_reset(); ret = uclass_get(UCLASS_USB, &uc); if (ret) -- cgit v0.10.2 From a199a7244899f6385035459cbc62409bd9bbcc23 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:10 +0800 Subject: usb: hub: Remove hub_port_reset() At present hub_port_reset() is defined in DM USB, but it is never called hence remove it (removing another ifdefs). While we are here, change legacy_hub_port_reset() name to usb_hub_port_reset() to better match other function names in the same hub module. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/common/usb_hub.c b/common/usb_hub.c index 37b358b..086b155 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -207,8 +207,18 @@ static inline char *portspeed(int portstatus) return speed_str; } -int legacy_hub_port_reset(struct usb_device *dev, int port, - unsigned short *portstat) +/** + * usb_hub_port_reset() - reset a port given its usb_device pointer + * + * Reset a hub port and see if a device is present on that port, providing + * sufficient time for it to show itself. The port status is returned. + * + * @dev: USB device to reset + * @port: Port number to reset (note ports are numbered from 0 here) + * @portstat: Returns port status + */ +static int usb_hub_port_reset(struct usb_device *dev, int port, + unsigned short *portstat) { int err, tries; ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); @@ -281,15 +291,6 @@ int legacy_hub_port_reset(struct usb_device *dev, int port, return 0; } -#ifdef CONFIG_DM_USB -int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat) -{ - struct usb_device *udev = dev_get_parent_priv(dev); - - return legacy_hub_port_reset(udev, port, portstat); -} -#endif - int usb_hub_port_connect_change(struct usb_device *dev, int port) { ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); @@ -323,7 +324,7 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port) } /* Reset the port */ - ret = legacy_hub_port_reset(dev, port, &portstatus); + ret = usb_hub_port_reset(dev, port, &portstatus); if (ret < 0) { if (ret != -ENXIO) printf("cannot reset port %i!?\n", port + 1); diff --git a/include/usb.h b/include/usb.h index eb82cc2..a266677 100644 --- a/include/usb.h +++ b/include/usb.h @@ -871,24 +871,6 @@ bool usb_device_has_child_on_port(struct usb_device *parent, int port); int usb_hub_probe(struct usb_device *dev, int ifnum); void usb_hub_reset(void); -/** - * legacy_hub_port_reset() - reset a port given its usb_device pointer - * - * Reset a hub port and see if a device is present on that port, providing - * sufficient time for it to show itself. The port status is returned. - * - * With driver model this moves to hub_port_reset() and is passed a struct - * udevice. - * - * @dev: USB device to reset - * @port: Port number to reset (note ports are numbered from 0 here) - * @portstat: Returns port status - */ -int legacy_hub_port_reset(struct usb_device *dev, int port, - unsigned short *portstat); - -int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat); - /* * usb_find_usb2_hub_address_port() - Get hub address and port for TT setting * -- cgit v0.10.2 From 46c1d49330fe21b3f9d2f7577ee4268248e7b666 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:11 +0800 Subject: usb: hub: Add a new API to test if a hub device is root hub Sometimes we need know if a given hub device is root hub or not. Add a new API to test this. This removes the xHCI driver's own version is_root_hub() and change to use the new API. While we are here, remove the unused/commented out get_usb_device() in the xHCI driver too. Signed-off-by: Bin Meng diff --git a/common/usb_hub.c b/common/usb_hub.c index 086b155..a8c2f56 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -67,6 +67,16 @@ static inline bool usb_hub_is_superspeed(struct usb_device *hdev) return hdev->descriptor.bDeviceProtocol == 3; } +#ifdef CONFIG_DM_USB +bool usb_hub_is_root_hub(struct udevice *hub) +{ + if (device_get_uclass_id(hub->parent) != UCLASS_USB_HUB) + return true; + + return false; +} +#endif + static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) { unsigned short dtype = USB_DT_HUB; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 62ab62b..0c88980 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1116,26 +1116,6 @@ int usb_lowlevel_stop(int index) #endif /* CONFIG_DM_USB */ #ifdef CONFIG_DM_USB -/* -static struct usb_device *get_usb_device(struct udevice *dev) -{ - struct usb_device *udev; - - if (device_get_uclass_id(dev) == UCLASS_USB) - udev = dev_get_uclass_priv(dev); - else - udev = dev_get_parent_priv(dev); - - return udev; -} -*/ -static bool is_root_hub(struct udevice *dev) -{ - if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) - return true; - - return false; -} static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buffer, int length, @@ -1150,10 +1130,10 @@ static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev, hub = udev->dev; if (device_get_uclass_id(hub) == UCLASS_USB_HUB) { /* Figure out our port number on the root hub */ - if (is_root_hub(hub)) { + if (usb_hub_is_root_hub(hub)) { root_portnr = udev->portnr; } else { - while (!is_root_hub(hub->parent)) + while (!usb_hub_is_root_hub(hub->parent)) hub = hub->parent; uhop = dev_get_parent_priv(hub); root_portnr = uhop->portnr; diff --git a/include/usb.h b/include/usb.h index a266677..64dfa84 100644 --- a/include/usb.h +++ b/include/usb.h @@ -776,6 +776,14 @@ int usb_setup_device(struct usb_device *dev, bool do_read, struct usb_device *parent); /** + * usb_hub_is_root_hub() - Test whether a hub device is root hub or not + * + * @hub: USB hub device to test + * @return: true if the hub device is root hub, false otherwise. + */ +bool usb_hub_is_root_hub(struct udevice *hub); + +/** * usb_hub_scan() - Scan a hub and find its devices * * @hub: Hub device to scan -- cgit v0.10.2 From 74ffc7cbb1d2d1f218b1bd67d1bd3cc1cba8aa79 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:12 +0800 Subject: usb: hub: Translate USB 3.0 hub port status into old version USB 3.0 hub port status field has different bit positions from 2.0 hubs. Since U-Boot only understands the old version, translate the new one into the old one. Since we are going to add USB 3.0 hub support, this feature is only available with driver model USB. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/common/usb_hub.c b/common/usb_hub.c index a8c2f56..b0ff159 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -112,9 +112,40 @@ static int usb_get_hub_status(struct usb_device *dev, void *data) int usb_get_port_status(struct usb_device *dev, int port, void *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + int ret; + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, sizeof(struct usb_port_status), USB_CNTL_TIMEOUT); + +#ifdef CONFIG_DM_USB + if (ret < 0) + return ret; + + /* + * Translate the USB 3.0 hub port status field into the old version + * that U-Boot understands. Do this only when the hub is not root hub. + * For root hub, the port status field has already been translated + * in the host controller driver (see xhci_submit_root() in xhci.c). + * + * Note: this only supports driver model. + */ + + if (!usb_hub_is_root_hub(dev->dev) && usb_hub_is_superspeed(dev)) { + struct usb_port_status *status = (struct usb_port_status *)data; + u16 tmp = (status->wPortStatus) & USB_SS_PORT_STAT_MASK; + + if (status->wPortStatus & USB_SS_PORT_STAT_POWER) + tmp |= USB_PORT_STAT_POWER; + if ((status->wPortStatus & USB_SS_PORT_STAT_SPEED) == + USB_SS_PORT_STAT_SPEED_5GBPS) + tmp |= USB_PORT_STAT_SUPER_SPEED; + + status->wPortStatus = tmp; + } +#endif + + return ret; } -- cgit v0.10.2 From bbc6f06c0031249bf1983b875e54cb7549bafe60 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:13 +0800 Subject: usb: hub: Support 'set hub depth' request for USB 3.0 hubs USB 3.0 hub uses a hub depth value multiplied by four as an offset into the 'route string' to locate the bits it uses to determine the downstream port number. We shall set the hub depth value of a USB 3.0 hub after it is configured. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/common/usb_hub.c b/common/usb_hub.c index b0ff159..18c366a 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -75,6 +75,16 @@ bool usb_hub_is_root_hub(struct udevice *hub) return false; } + +static int usb_set_hub_depth(struct usb_device *dev, int depth) +{ + if (depth < 0 || depth > 4) + return -EINVAL; + + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_HUB_DEPTH, USB_DIR_OUT | USB_RT_HUB, + depth, 0, NULL, 0, USB_CNTL_TIMEOUT); +} #endif static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) @@ -726,6 +736,48 @@ static int usb_hub_configure(struct usb_device *dev) debug("%sover-current condition exists\n", (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \ "" : "no "); + +#ifdef CONFIG_DM_USB + /* + * A maximum of seven tiers are allowed in a USB topology, and the + * root hub occupies the first tier. The last tier ends with a normal + * USB device. USB 3.0 hubs use a 20-bit field called 'route string' + * to route packets to the designated downstream port. The hub uses a + * hub depth value multiplied by four as an offset into the 'route + * string' to locate the bits it uses to determine the downstream + * port number. + */ + if (usb_hub_is_root_hub(dev->dev)) { + hub->hub_depth = -1; + } else { + struct udevice *hdev; + int depth = 0; + + hdev = dev->dev->parent; + while (!usb_hub_is_root_hub(hdev)) { + depth++; + hdev = hdev->parent; + } + + hub->hub_depth = depth; + + if (usb_hub_is_superspeed(dev)) { + debug("set hub (%p) depth to %d\n", dev, depth); + /* + * This request sets the value that the hub uses to + * determine the index into the 'route string index' + * for this hub. + */ + ret = usb_set_hub_depth(dev, depth); + if (ret < 0) { + debug("%s: failed to set hub depth (%lX)\n", + __func__, dev->status); + return ret; + } + } + } +#endif + usb_hub_power_on(hub); /* diff --git a/include/usb.h b/include/usb.h index 64dfa84..f71da52 100644 --- a/include/usb.h +++ b/include/usb.h @@ -570,6 +570,7 @@ struct usb_hub_device { ulong connect_timeout; /* Device connection timeout in ms */ ulong query_delay; /* Device query delay in ms */ int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */ + int hub_depth; /* USB 3.0 hub depth */ }; #ifdef CONFIG_DM_USB diff --git a/include/usb_defs.h b/include/usb_defs.h index 6b4385a..273337f 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -306,6 +306,9 @@ /* Mask for wIndex in get/set port feature */ #define USB_HUB_PORT_MASK 0xf +/* Hub class request codes */ +#define USB_REQ_SET_HUB_DEPTH 0x0c + /* * CBI style */ -- cgit v0.10.2 From daec4691449fa4728f29260554701602e8f91d5c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:14 +0800 Subject: usb: xhci: Change xhci_setup_addressable_virt_dev() signature For future extension, change xhci_setup_addressable_virt_dev() signature to accept a pointer to 'struct usb_device', instead of its members slot_id & speed, as the struct already contains these two plus some other useful information of the device. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 12e277a..9aa3092 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -713,14 +713,16 @@ void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *in_ctx, * @param udev pointer to the Device Data Structure * @return returns negative value on failure else 0 on success */ -void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, int slot_id, - int speed, int hop_portnr) +void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, + struct usb_device *udev, int hop_portnr) { struct xhci_virt_device *virt_dev; struct xhci_ep_ctx *ep0_ctx; struct xhci_slot_ctx *slot_ctx; u32 port_num = 0; u64 trb_64 = 0; + int slot_id = udev->slot_id; + int speed = udev->speed; virt_dev = ctrl->devs[slot_id]; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 0c88980..336613f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -415,8 +415,7 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr) * so setting up the slot context. */ debug("Setting up addressable devices %p\n", ctrl->dcbaa); - xhci_setup_addressable_virt_dev(ctrl, udev->slot_id, udev->speed, - root_portnr); + xhci_setup_addressable_virt_dev(ctrl, udev, root_portnr); ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index b9602ba..cdce67c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1247,8 +1247,8 @@ void xhci_endpoint_copy(struct xhci_ctrl *ctrl, void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *in_ctx, struct xhci_container_ctx *out_ctx); -void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, int slot_id, - int speed, int hop_portnr); +void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, + struct usb_device *udev, int hop_portnr); void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, u32 ep_index, trb_type cmd); void xhci_acknowledge_event(struct xhci_ctrl *ctrl); -- cgit v0.10.2 From 493b8dd070f2412b49190b71b44baddbb2b24e37 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:15 +0800 Subject: usb: xhci: Program 'route string' in the input slot context xHCI spec says: the values of the 'route string' field shall be initialized by the first 'Address Device' command issued to a device slot, and shall not be modified by any other command. So far U-Boot does not program this field, and it does not prevent SS device directly attached to root port, or HS device behind an HS hub, from working, due to the fact that 'route string' is used by the xHC to target SS packets. But in order to enumerate devices behind an SS hub, this field must be programmed. With this commit and along with previous commits, now SS & HS devices attached to a USB 3.0 hub can be enumerated by U-Boot. As usual, this new feature is only available when DM is on. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 9aa3092..c02059e 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -723,6 +723,11 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, u64 trb_64 = 0; int slot_id = udev->slot_id; int speed = udev->speed; + int route = 0; +#ifdef CONFIG_DM_USB + struct usb_device *dev = udev; + struct usb_hub_device *hub; +#endif virt_dev = ctrl->devs[slot_id]; @@ -733,7 +738,32 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx); /* Only the control endpoint is valid - one endpoint context */ - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | 0); + slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1)); + +#ifdef CONFIG_DM_USB + /* Calculate the route string for this device */ + port_num = dev->portnr; + while (!usb_hub_is_root_hub(dev->dev)) { + hub = dev_get_uclass_priv(dev->dev); + /* + * Each hub in the topology is expected to have no more than + * 15 ports in order for the route string of a device to be + * unique. SuperSpeed hubs are restricted to only having 15 + * ports, but FS/LS/HS hubs are not. The xHCI specification + * says that if the port number the device is greater than 15, + * that portion of the route string shall be set to 15. + */ + if (port_num > 15) + port_num = 15; + route |= port_num << (hub->hub_depth * 4); + dev = dev_get_parent_priv(dev->dev); + port_num = dev->portnr; + dev = dev_get_parent_priv(dev->dev->parent); + } + + debug("route string %x\n", route); +#endif + slot_ctx->dev_info |= route; switch (speed) { case USB_SPEED_SUPER: -- cgit v0.10.2 From 5624dfd5aa91c244519ec60b40b4a42b4d9a43ca Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:16 +0800 Subject: usb: hub: Parse and save TT details from device descriptor A high speed hub has a special responsibility to handle full speed/ low speed devices connected on downstream ports. In this case, the hub must isolate the high speed signaling environment from the full speed/low speed signaling environment with the help of Transaction Translator (TT). TT details are provided by hub descriptors and we parse and save it to hub uclass_priv for later use. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/common/usb_hub.c b/common/usb_hub.c index 18c366a..bbb1155 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -700,6 +700,56 @@ static int usb_hub_configure(struct usb_device *dev) break; } + switch (dev->descriptor.bDeviceProtocol) { + case USB_HUB_PR_FS: + break; + case USB_HUB_PR_HS_SINGLE_TT: + debug("Single TT\n"); + break; + case USB_HUB_PR_HS_MULTI_TT: + ret = usb_set_interface(dev, 0, 1); + if (ret == 0) { + debug("TT per port\n"); + hub->tt.multi = true; + } else { + debug("Using single TT (err %d)\n", ret); + } + break; + case USB_HUB_PR_SS: + /* USB 3.0 hubs don't have a TT */ + break; + default: + debug("Unrecognized hub protocol %d\n", + dev->descriptor.bDeviceProtocol); + break; + } + + /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */ + switch (hubCharacteristics & HUB_CHAR_TTTT) { + case HUB_TTTT_8_BITS: + if (dev->descriptor.bDeviceProtocol != 0) { + hub->tt.think_time = 666; + debug("TT requires at most %d FS bit times (%d ns)\n", + 8, hub->tt.think_time); + } + break; + case HUB_TTTT_16_BITS: + hub->tt.think_time = 666 * 2; + debug("TT requires at most %d FS bit times (%d ns)\n", + 16, hub->tt.think_time); + break; + case HUB_TTTT_24_BITS: + hub->tt.think_time = 666 * 3; + debug("TT requires at most %d FS bit times (%d ns)\n", + 24, hub->tt.think_time); + break; + case HUB_TTTT_32_BITS: + hub->tt.think_time = 666 * 4; + debug("TT requires at most %d FS bit times (%d ns)\n", + 32, hub->tt.think_time); + break; + } + debug("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2); debug("hub controller current requirement: %dmA\n", diff --git a/include/usb.h b/include/usb.h index f71da52..58b4549 100644 --- a/include/usb.h +++ b/include/usb.h @@ -537,6 +537,21 @@ struct usb_hub_status { unsigned short wHubChange; } __attribute__ ((packed)); +/* + * Hub Device descriptor + * USB Hub class device protocols + */ +#define USB_HUB_PR_FS 0 /* Full speed hub */ +#define USB_HUB_PR_HS_NO_TT 0 /* Hi-speed hub without TT */ +#define USB_HUB_PR_HS_SINGLE_TT 1 /* Hi-speed hub with single TT */ +#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */ +#define USB_HUB_PR_SS 3 /* Super speed hub */ + +/* Transaction Translator Think Times, in bits */ +#define HUB_TTTT_8_BITS 0x00 +#define HUB_TTTT_16_BITS 0x20 +#define HUB_TTTT_24_BITS 0x40 +#define HUB_TTTT_32_BITS 0x60 /* Hub descriptor */ struct usb_hub_descriptor { @@ -571,6 +586,7 @@ struct usb_hub_device { ulong query_delay; /* Device query delay in ms */ int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */ int hub_depth; /* USB 3.0 hub depth */ + struct usb_tt tt; /* Transaction Translator */ }; #ifdef CONFIG_DM_USB diff --git a/include/usb_defs.h b/include/usb_defs.h index 273337f..b7f2ead 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -293,6 +293,7 @@ #define HUB_CHAR_LPSM 0x0003 #define HUB_CHAR_COMPOUND 0x0004 #define HUB_CHAR_OCPM 0x0018 +#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */ /* * Hub Status & Hub Change bit masks @@ -310,6 +311,17 @@ #define USB_REQ_SET_HUB_DEPTH 0x0c /* + * As of USB 2.0, full/low speed devices are segregated into trees. + * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). + * The other type grows from high speed hubs when they connect to + * full/low speed devices using "Transaction Translators" (TTs). + */ +struct usb_tt { + bool multi; /* true means one TT per port */ + unsigned think_time; /* think time in ns */ +}; + +/* * CBI style */ -- cgit v0.10.2 From 9ca1b4bab10d8b3a5dbbbd98df46ce75159222b8 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:17 +0800 Subject: dm: usb: Add a new USB controller operation 'update_hub_device' For USB host controllers like xHC, its internal representation of hub needs to be updated after the hub descriptor is fetched. This adds a new op that does this. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index d8d74bd..0b8a501 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -139,6 +139,17 @@ int usb_reset_root_port(struct usb_device *udev) return ops->reset_root_port(bus, udev); } +int usb_update_hub_device(struct usb_device *udev) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->update_hub_device) + return -ENOSYS; + + return ops->update_hub_device(bus, udev); +} + int usb_stop(void) { struct udevice *bus; diff --git a/include/usb.h b/include/usb.h index 58b4549..fad0401 100644 --- a/include/usb.h +++ b/include/usb.h @@ -758,6 +758,14 @@ struct dm_usb_ops { * reset_root_port() - Reset usb root port */ int (*reset_root_port)(struct udevice *bus, struct usb_device *udev); + + /** + * update_hub_device() - Update HCD's internal representation of hub + * + * After a hub descriptor is fetched, notify HCD so that its internal + * representation of this hub can be updated (xHCI) + */ + int (*update_hub_device)(struct udevice *bus, struct usb_device *udev); }; #define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops) @@ -931,6 +939,17 @@ int usb_new_device(struct usb_device *dev); int usb_alloc_device(struct usb_device *dev); /** + * update_hub_device() - Update HCD's internal representation of hub + * + * After a hub descriptor is fetched, notify HCD so that its internal + * representation of this hub can be updated. + * + * @dev: Hub device + * @return 0 if OK, -ve on error + */ +int usb_update_hub_device(struct usb_device *dev); + +/** * usb_emul_setup_device() - Set up a new USB device emulation * * This is normally called when a new emulation device is bound. It tells @@ -943,7 +962,7 @@ int usb_alloc_device(struct usb_device *dev); * @desc_list: List of points or USB descriptors, terminated by NULL. * The first entry must be struct usb_device_descriptor, * and others follow on after that. - * @return 0 if OK, -ve on error + * @return 0 if OK, -ENOSYS if not implemented, other -ve on error */ int usb_emul_setup_device(struct udevice *dev, int maxpacketsize, struct usb_string *strings, void **desc_list); -- cgit v0.10.2 From 81060bb1c02abb242b73f118ce297dbe483a40f7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:18 +0800 Subject: usb: hub: Call usb_update_hub_device() after hub descriptor is fetched After fetching hub descriptor, we need to call USB uclass operation update_hub_device() to notify HCD to do some preparation work. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/common/usb_hub.c b/common/usb_hub.c index bbb1155..70bc6e2 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -789,6 +789,17 @@ static int usb_hub_configure(struct usb_device *dev) #ifdef CONFIG_DM_USB /* + * Update USB host controller's internal representation of this hub + * after the hub descriptor is fetched. + */ + ret = usb_update_hub_device(dev); + if (ret < 0 && ret != -ENOSYS) { + debug("%s: failed to update hub device for HCD (%x)\n", + __func__, ret); + return ret; + } + + /* * A maximum of seven tiers are allowed in a USB topology, and the * root hub occupies the first tier. The last tier ends with a normal * USB device. USB 3.0 hubs use a 20-bit field called 'route string' -- cgit v0.10.2 From d228ca362b0f2aa3679866c7a40702085653233e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:19 +0800 Subject: usb: xhci: Implement update_hub_device() operation There is no way to know whether the attached device is a hub or not in advance before the device's descriptor is fetched. But once we know it's a high speed hub, per the xHCI spec, we need to tell xHC it's a hub device by initializing hub-related fields in the input slot context. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 336613f..9b82ee5 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1170,6 +1170,64 @@ static int xhci_alloc_device(struct udevice *dev, struct usb_device *udev) return _xhci_alloc_device(udev); } +static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev) +{ + struct xhci_ctrl *ctrl = dev_get_priv(dev); + struct usb_hub_device *hub = dev_get_uclass_priv(udev->dev); + struct xhci_virt_device *virt_dev; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_container_ctx *out_ctx; + struct xhci_container_ctx *in_ctx; + struct xhci_slot_ctx *slot_ctx; + int slot_id = udev->slot_id; + unsigned think_time; + + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); + + /* Ignore root hubs */ + if (usb_hub_is_root_hub(udev->dev)) + return 0; + + virt_dev = ctrl->devs[slot_id]; + BUG_ON(!virt_dev); + + out_ctx = virt_dev->out_ctx; + in_ctx = virt_dev->in_ctx; + + ctrl_ctx = xhci_get_input_control_ctx(in_ctx); + /* Initialize the input context control */ + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); + ctrl_ctx->drop_flags = 0; + + xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); + + /* slot context */ + xhci_slot_copy(ctrl, in_ctx, out_ctx); + slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); + + /* Update hub related fields */ + slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); + if (hub->tt.multi && udev->speed == USB_SPEED_HIGH) + slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); + slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(udev->maxchild)); + /* + * Set TT think time - convert from ns to FS bit times. + * Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns + * + * 0 = 8 FS bit times, 1 = 16 FS bit times, + * 2 = 24 FS bit times, 3 = 32 FS bit times. + * + * This field shall be 0 if the device is not a high-spped hub. + */ + think_time = hub->tt.think_time; + if (think_time != 0) + think_time = (think_time / 666) - 1; + if (udev->speed == USB_SPEED_HIGH) + slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time)); + + return xhci_configure_endpoints(udev, false); +} + int xhci_register(struct udevice *dev, struct xhci_hccr *hccr, struct xhci_hcor *hcor) { @@ -1222,6 +1280,7 @@ struct dm_usb_ops xhci_usb_ops = { .bulk = xhci_submit_bulk_msg, .interrupt = xhci_submit_int_msg, .alloc_device = xhci_alloc_device, + .update_hub_device = xhci_update_hub_device, }; #endif -- cgit v0.10.2 From 196ef8323c53b5d43fd9c244daaca1e2172ca47c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:20 +0800 Subject: usb: xhci: Correct TT_SLOT and TT_PORT macros These two macros really need a parameter to make them useful. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index cdce67c..a497d9d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -548,12 +548,12 @@ struct xhci_slot_ctx { * The Slot ID of the hub that isolates the high speed signaling from * this low or full-speed device. '0' if attached to root hub port. */ -#define TT_SLOT (0xff) +#define TT_SLOT(p) (((p) & 0xff) << 0) /* * The number of the downstream facing port of the high-speed hub * '0' if the device is not low or full speed. */ -#define TT_PORT (0xff << 8) +#define TT_PORT(p) (((p) & 0xff) << 8) #define TT_THINK_TIME(p) (((p) & 0x3) << 16) /* dev_state bitmasks */ -- cgit v0.10.2 From 78e30987520870e0fc1d6b1cba5b46ce86dfff59 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:21 +0800 Subject: usb: xhci: Enable TT to support LS/FS devices behind a HS hub So far LS/FS devices directly attached to xHC root port can be successfully enumerated by xHCI driver, but if they are connected behind a hub, the enumeration process fails to address the device. It turns out xHCI driver still misses a part that in the device's input slot context, all Transaction Translator (TT) related fields are not programmed. The xHCI spec defines how to enable TT. Now LS/FS devices like USB keyboard/mouse can be enumerated behind a high speed hub. Signed-off-by: Bin Meng Reviewed-by: Simon Glass diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index c02059e..d5eab3a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -783,6 +783,20 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, BUG(); } +#ifdef CONFIG_DM_USB + /* Set up TT fields to support FS/LS devices */ + if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) { + dev = dev_get_parent_priv(udev->dev); + if (dev->speed == USB_SPEED_HIGH) { + hub = dev_get_uclass_priv(udev->dev); + if (hub->tt.multi) + slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); + slot_ctx->tt_info |= cpu_to_le32(TT_PORT(udev->portnr)); + slot_ctx->tt_info |= cpu_to_le32(TT_SLOT(dev->slot_id)); + } + } +#endif + port_num = hop_portnr; debug("port_num = %d\n", port_num); -- cgit v0.10.2 From bab0146ea91146aafa8cf10a34a45ae85eca5683 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 21 Jun 2016 14:50:48 +0200 Subject: usb: gadget: f_thor: Free the allocated out request buffer Fix the memory leak by freeing the allocated out request buffer Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index a60e948..cd4d9e6 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -891,6 +891,7 @@ static void thor_func_disable(struct usb_function *f) } if (dev->out_ep->driver_data) { + free(dev->out_req->buf); dev->out_req->buf = NULL; usb_ep_free_request(dev->out_ep, dev->out_req); usb_ep_disable(dev->out_ep); -- cgit v0.10.2 From 4de512018ba7d57f1672be21c7459281f7c97514 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 19 Jul 2017 16:39:22 +0200 Subject: dfu: allow dfu read on partition greater than 2GB solve issue on get_medium_size() function the detection of error is a simple test < 0 but for ARM platform, long is 32bits and 2GB = 0x80000000 is seen as error. I solve the issue by changing the prototype fo the function to separate size and result. This patch prepare the next patch with size change to u64. Signed-off-by: Patrick Delaunay diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index ceb33e3..c777016 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -339,9 +339,9 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) if (dfu->i_buf_start == NULL) return -ENOMEM; - dfu->r_left = dfu->get_medium_size(dfu); - if (dfu->r_left < 0) - return dfu->r_left; + ret = dfu->get_medium_size(dfu, &dfu->r_left); + if (ret < 0) + return ret; debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left); diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 926ccbd..d918f95 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -209,23 +209,23 @@ int dfu_flush_medium_mmc(struct dfu_entity *dfu) return ret; } -long dfu_get_medium_size_mmc(struct dfu_entity *dfu) +int dfu_get_medium_size_mmc(struct dfu_entity *dfu, long *size) { int ret; - long len; switch (dfu->layout) { case DFU_RAW_ADDR: - return dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size; + *size = dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size; + return 0; case DFU_FS_FAT: case DFU_FS_EXT4: dfu_file_buf_filled = -1; - ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, &len); + ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, size); if (ret < 0) return ret; - if (len > CONFIG_SYS_DFU_MAX_FILE_SIZE) + if (*size > CONFIG_SYS_DFU_MAX_FILE_SIZE) return -1; - return len; + return 0; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c index 97cd608..ed4ceb7 100644 --- a/drivers/dfu/dfu_nand.c +++ b/drivers/dfu/dfu_nand.c @@ -114,9 +114,11 @@ static int dfu_write_medium_nand(struct dfu_entity *dfu, return ret; } -long dfu_get_medium_size_nand(struct dfu_entity *dfu) +int dfu_get_medium_size_nand(struct dfu_entity *dfu, long *size) { - return dfu->data.nand.size; + *size = dfu->data.nand.size; + + return 0; } static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf, diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c index c1b0021..b95cb9f 100644 --- a/drivers/dfu/dfu_ram.c +++ b/drivers/dfu/dfu_ram.c @@ -41,9 +41,11 @@ static int dfu_write_medium_ram(struct dfu_entity *dfu, u64 offset, return dfu_transfer_medium_ram(DFU_OP_WRITE, dfu, offset, buf, len); } -long dfu_get_medium_size_ram(struct dfu_entity *dfu) +int dfu_get_medium_size_ram(struct dfu_entity *dfu, long *size) { - return dfu->data.ram.size; + *size = dfu->data.ram.size; + + return 0; } static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset, diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index b6d5fe2..2b26f2c 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -12,9 +12,11 @@ #include #include -static long dfu_get_medium_size_sf(struct dfu_entity *dfu) +static int dfu_get_medium_size_sf(struct dfu_entity *dfu, long *size) { - return dfu->data.sf.size; + *size = dfu->data.sf.size; + + return 0; } static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf, diff --git a/include/dfu.h b/include/dfu.h index f39d3f1..5b621b5 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -110,7 +110,7 @@ struct dfu_entity { struct sf_internal_data sf; } data; - long (*get_medium_size)(struct dfu_entity *dfu); + int (*get_medium_size)(struct dfu_entity *dfu, long *size); int (*read_medium)(struct dfu_entity *dfu, u64 offset, void *buf, long *len); -- cgit v0.10.2 From 15970d871c299c8a4218911ee68edb0495a69cd4 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 19 Jul 2017 16:39:23 +0200 Subject: dfu: remove limitation on partition size Change long (32 bits on arm) to u64 (same type than offset) for size and read offset r_left So partition and device used for DFU can be greater than 4GB Signed-off-by: Patrick Delaunay diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index c777016..0f1ab0d 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -343,7 +343,7 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) if (ret < 0) return ret; - debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left); + debug("%s: %s %lld [B]\n", __func__, dfu->name, dfu->r_left); dfu->i_blk_seq_num = 0; dfu->crc = 0; diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index d918f95..bb23e7f 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -17,7 +17,7 @@ #include static unsigned char *dfu_file_buf; -static long dfu_file_buf_len; +static u64 dfu_file_buf_len; static long dfu_file_buf_filled; static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, @@ -107,7 +107,7 @@ static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len) } static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu, - void *buf, long *len) + void *buf, u64 *len) { const char *fsname, *opname; char cmd_buf[DFU_CMD_BUF_SIZE]; @@ -150,7 +150,7 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu, sprintf(cmd_buf + strlen(cmd_buf), " %s", dfu->name); if (op == DFU_OP_WRITE) - sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len); + sprintf(cmd_buf + strlen(cmd_buf), " %llx", *len); debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); @@ -209,7 +209,7 @@ int dfu_flush_medium_mmc(struct dfu_entity *dfu) return ret; } -int dfu_get_medium_size_mmc(struct dfu_entity *dfu, long *size) +int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size) { int ret; @@ -237,7 +237,7 @@ static int mmc_file_unbuffer(struct dfu_entity *dfu, u64 offset, void *buf, long *len) { int ret; - long file_len; + u64 file_len; if (dfu_file_buf_filled == -1) { ret = mmc_file_op(DFU_OP_READ, dfu, dfu_file_buf, &file_len); diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c index ed4ceb7..6dc9ff7 100644 --- a/drivers/dfu/dfu_nand.c +++ b/drivers/dfu/dfu_nand.c @@ -114,7 +114,7 @@ static int dfu_write_medium_nand(struct dfu_entity *dfu, return ret; } -int dfu_get_medium_size_nand(struct dfu_entity *dfu, long *size) +int dfu_get_medium_size_nand(struct dfu_entity *dfu, u64 *size) { *size = dfu->data.nand.size; diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c index b95cb9f..6e3f531 100644 --- a/drivers/dfu/dfu_ram.c +++ b/drivers/dfu/dfu_ram.c @@ -41,7 +41,7 @@ static int dfu_write_medium_ram(struct dfu_entity *dfu, u64 offset, return dfu_transfer_medium_ram(DFU_OP_WRITE, dfu, offset, buf, len); } -int dfu_get_medium_size_ram(struct dfu_entity *dfu, long *size) +int dfu_get_medium_size_ram(struct dfu_entity *dfu, u64 *size) { *size = dfu->data.ram.size; diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index 2b26f2c..2d2586d 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -12,7 +12,7 @@ #include #include -static int dfu_get_medium_size_sf(struct dfu_entity *dfu, long *size) +static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size) { *size = dfu->data.sf.size; diff --git a/include/dfu.h b/include/dfu.h index 5b621b5..7e322d9 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -110,7 +110,7 @@ struct dfu_entity { struct sf_internal_data sf; } data; - int (*get_medium_size)(struct dfu_entity *dfu, long *size); + int (*get_medium_size)(struct dfu_entity *dfu, u64 *size); int (*read_medium)(struct dfu_entity *dfu, u64 offset, void *buf, long *len); @@ -132,7 +132,7 @@ struct dfu_entity { u8 *i_buf; u8 *i_buf_start; u8 *i_buf_end; - long r_left; + u64 r_left; long b_left; u32 bad_skip; /* for nand use */ -- cgit v0.10.2 From 57da060755ac757237bd8781f7b2aef80167301e Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 19 Jul 2017 16:39:24 +0200 Subject: dfu: factorize transaction cleanup rename cleanup function, as now called by read Signed-off-by: Patrick Delaunay diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 0f1ab0d..63a5a44 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -165,7 +165,7 @@ static int dfu_write_buffer_drain(struct dfu_entity *dfu) return ret; } -void dfu_write_transaction_cleanup(struct dfu_entity *dfu) +void dfu_transaction_cleanup(struct dfu_entity *dfu) { /* clear everything */ dfu->crc = 0; @@ -174,6 +174,10 @@ void dfu_write_transaction_cleanup(struct dfu_entity *dfu) dfu->i_buf_start = dfu_buf; dfu->i_buf_end = dfu_buf; dfu->i_buf = dfu->i_buf_start; + dfu->r_left = 0; + dfu->b_left = 0; + dfu->bad_skip = 0; + dfu->inited = 0; } @@ -192,7 +196,7 @@ int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name, dfu->crc); - dfu_write_transaction_cleanup(dfu); + dfu_transaction_cleanup(dfu); return ret; } @@ -223,7 +227,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) if (dfu->i_blk_seq_num != blk_seq_num) { printf("%s: Wrong sequence number! [%d] [%d]\n", __func__, dfu->i_blk_seq_num, blk_seq_num); - dfu_write_transaction_cleanup(dfu); + dfu_transaction_cleanup(dfu); return -1; } @@ -247,7 +251,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) if ((dfu->i_buf + size) > dfu->i_buf_end) { ret = dfu_write_buffer_drain(dfu); if (ret) { - dfu_write_transaction_cleanup(dfu); + dfu_transaction_cleanup(dfu); return ret; } } @@ -256,7 +260,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) if ((dfu->i_buf + size) > dfu->i_buf_end) { error("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf, size, dfu->i_buf_end); - dfu_write_transaction_cleanup(dfu); + dfu_transaction_cleanup(dfu); return -1; } @@ -267,7 +271,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) { ret = dfu_write_buffer_drain(dfu); if (ret) { - dfu_write_transaction_cleanup(dfu); + dfu_transaction_cleanup(dfu); return ret; } } @@ -377,17 +381,7 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu_hash_algo->name, dfu->crc); puts("\nUPLOAD ... done\nCtrl+C to exit ...\n"); - dfu->i_blk_seq_num = 0; - dfu->crc = 0; - dfu->offset = 0; - dfu->i_buf_start = dfu_buf; - dfu->i_buf_end = dfu_buf; - dfu->i_buf = dfu->i_buf_start; - dfu->b_left = 0; - - dfu->bad_skip = 0; - - dfu->inited = 0; + dfu_transaction_cleanup(dfu); } return ret; -- cgit v0.10.2 From 6fa8dddd069db868d64948e70c40f3d75a9fa253 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 19 Jul 2017 16:39:25 +0200 Subject: dfu: add common function to initiate transaction - factorize code between read and write transaction - always use dfu_transaction_cleanup() to initialize the internal variable: easy maintenance - replace direct access by dfu_get_buf() and dfu_get_buf_size() Signed-off-by: Patrick Delaunay diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 63a5a44..f6281f4 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -171,8 +171,8 @@ void dfu_transaction_cleanup(struct dfu_entity *dfu) dfu->crc = 0; dfu->offset = 0; dfu->i_blk_seq_num = 0; - dfu->i_buf_start = dfu_buf; - dfu->i_buf_end = dfu_buf; + dfu->i_buf_start = dfu_get_buf(dfu); + dfu->i_buf_end = dfu->i_buf_start; dfu->i_buf = dfu->i_buf_start; dfu->r_left = 0; dfu->b_left = 0; @@ -181,6 +181,32 @@ void dfu_transaction_cleanup(struct dfu_entity *dfu) dfu->inited = 0; } +int dfu_transaction_initiate(struct dfu_entity *dfu, bool read) +{ + int ret = 0; + + if (dfu->inited) + return 0; + + dfu_transaction_cleanup(dfu); + + if (dfu->i_buf_start == NULL) + return -ENOMEM; + + dfu->i_buf_end = dfu->i_buf_start + dfu_get_buf_size(); + + if (read) { + ret = dfu->get_medium_size(dfu, &dfu->r_left); + if (ret < 0) + return ret; + debug("%s: %s %lld [B]\n", __func__, dfu->name, dfu->r_left); + } + + dfu->inited = 1; + + return 0; +} + int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) { int ret = 0; @@ -209,20 +235,9 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) __func__, dfu->name, buf, size, blk_seq_num, dfu->offset, (unsigned long)(dfu->i_buf - dfu->i_buf_start)); - if (!dfu->inited) { - /* initial state */ - dfu->crc = 0; - dfu->offset = 0; - dfu->bad_skip = 0; - dfu->i_blk_seq_num = 0; - dfu->i_buf_start = dfu_get_buf(dfu); - if (dfu->i_buf_start == NULL) - return -ENOMEM; - dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size; - dfu->i_buf = dfu->i_buf_start; - - dfu->inited = 1; - } + ret = dfu_transaction_initiate(dfu, false); + if (ret < 0) + return ret; if (dfu->i_blk_seq_num != blk_seq_num) { printf("%s: Wrong sequence number! [%d] [%d]\n", @@ -338,28 +353,9 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n", __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf); - if (!dfu->inited) { - dfu->i_buf_start = dfu_get_buf(dfu); - if (dfu->i_buf_start == NULL) - return -ENOMEM; - - ret = dfu->get_medium_size(dfu, &dfu->r_left); - if (ret < 0) - return ret; - - debug("%s: %s %lld [B]\n", __func__, dfu->name, dfu->r_left); - - dfu->i_blk_seq_num = 0; - dfu->crc = 0; - dfu->offset = 0; - dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size; - dfu->i_buf = dfu->i_buf_start; - dfu->b_left = 0; - - dfu->bad_skip = 0; - - dfu->inited = 1; - } + ret = dfu_transaction_initiate(dfu, true); + if (ret < 0) + return ret; if (dfu->i_blk_seq_num != blk_seq_num) { printf("%s: Wrong sequence number! [%d] [%d]\n", -- cgit v0.10.2 From d9fb7bece056522d659d9e17b73b3fd5549817c3 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 24 Jul 2017 17:07:02 +0200 Subject: dm: phy: add missing #ifdef CONFIG_PHY To avoid compilation breakage on platform that doesn't support DM PHY but uses xhci-dwc3 driver, add the missing CONFIG_PHY flag. Introduced by patch : 84e53877 "usb: host: xhci-dwc3: Add generic PHY support" Cc: Ran Wang Cc: Bin Meng Signed-off-by: Patrice Chotard Reported-by: Ran Wang diff --git a/include/generic-phy.h b/include/generic-phy.h index 58cd2b2..eac5adc 100644 --- a/include/generic-phy.h +++ b/include/generic-phy.h @@ -122,6 +122,7 @@ struct phy_ops { int (*power_off)(struct phy *phy); }; +#ifdef CONFIG_PHY /** * generic_phy_init() - initialize the PHY port @@ -220,6 +221,47 @@ int generic_phy_get_by_index(struct udevice *user, int index, int generic_phy_get_by_name(struct udevice *user, const char *phy_name, struct phy *phy); +#else /* CONFIG_PHY */ + +static inline int generic_phy_init(struct phy *phy) +{ + return 0; +} + +static inline int generic_phy_exit(struct phy *phy) +{ + return 0; +} + +static inline int generic_phy_reset(struct phy *phy) +{ + return 0; +} + +static inline int generic_phy_power_on(struct phy *phy) +{ + return 0; +} + +static inline int generic_phy_power_off(struct phy *phy) +{ + return 0; +} + +static inline int generic_phy_get_by_index(struct udevice *user, int index, + struct phy *phy) +{ + return 0; +} + +static inline int generic_phy_get_by_name(struct udevice *user, const char *phy_name, + struct phy *phy) +{ + return 0; +} + +#endif /* CONFIG_PHY */ + /** * generic_phy_valid() - check if PHY port is valid * -- cgit v0.10.2 From 623b7aca1f82bf1dee089c77f9a1020e80abaccc Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 24 Jul 2017 17:07:03 +0200 Subject: dm: usb: host: xhci-dwc3: add missing #ifdef CONFIG_DM_USB Add CONFIG_DM_USB flag to avoid following compilation errors detected by buildman : +drivers/usb/host/built-in.o: In function `xhci_dwc3_remove': +drivers/usb/host/xhci-dwc3.c:168: undefined reference to `xhci_deregister' +drivers/usb/host/built-in.o: In function `xhci_dwc3_probe': +drivers/usb/host/xhci-dwc3.c:145: undefined reference to `usb_get_dr_mode' +drivers/usb/host/xhci-dwc3.c:152: undefined reference to `xhci_register' introduced by patch d5c3f014da3 "usb: host: xhci-dwc3: Convert driver to DM" Signed-off-by: Patrice Chotard Reported-by: Ran Wang diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 374fe74..541a785 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -111,6 +111,7 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) GFLADJ_30MHZ(val)); } +#ifdef CONFIG_DM_USB static int xhci_dwc3_probe(struct udevice *dev) { struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); @@ -184,3 +185,4 @@ U_BOOT_DRIVER(xhci_dwc3) = { .platdata_auto_alloc_size = sizeof(struct xhci_dwc3_platdata), .flags = DM_FLAG_ALLOC_PRIV_DMA, }; +#endif -- cgit v0.10.2 From 4b3928a08f24d21c2d34487b9d89fee35814bd0d Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 24 Jul 2017 17:07:04 +0200 Subject: usb: host: ehci-generic: initialize PHY only when found Call generic_phy_init() only when a PHY was found. This will avoid a crash if no "phys" property is found in DT. Signed-off-by: Patrice Chotard Reported-by: Patrick Delaunay diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 3f751f1..03f8d32 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -99,12 +99,13 @@ static int ehci_usb_probe(struct udevice *dev) error("failed to get usb phy\n"); goto reset_err; } - } + } else { - err = generic_phy_init(&priv->phy); - if (err) { - error("failed to init usb phy\n"); - goto reset_err; + err = generic_phy_init(&priv->phy); + if (err) { + error("failed to init usb phy\n"); + goto reset_err; + } } hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); -- cgit v0.10.2 From 2080d023d90e2972f82dfde624d209cf5a0c569c Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 24 Jul 2017 17:07:05 +0200 Subject: usb: host: ohci-generic: initialize PHY only when found Call generic_phy_init() only when a PHY was found. This will avoid a crash if no "phys" property is found in DT. Signed-off-by: Patrice Chotard Reported-by: Patrick Delaunay diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index 9249039..e22ee97 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -91,12 +91,13 @@ static int ohci_usb_probe(struct udevice *dev) error("failed to get usb phy\n"); goto reset_err; } - } + } else { - err = generic_phy_init(&priv->phy); - if (err) { - error("failed to init usb phy\n"); - goto reset_err; + err = generic_phy_init(&priv->phy); + if (err) { + error("failed to init usb phy\n"); + goto reset_err; + } } err = ohci_register(dev, regs); -- cgit v0.10.2 From 3b63db37ad7e4672684bd686fcc3fc07b84e4fb9 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Mon, 24 Jul 2017 15:18:15 +0200 Subject: phy: add a NO-OP phy driver This driver is used to stub PHY operations in a driver (USB, SATA). This is useful when the 'client' driver (USB, SATA, ...) uses the PHY framework and there is no actual PHY harwdare to drive. Signed-off-by: Jean-Jacques Hiblot diff --git a/Documentation/devicetree/bindings/phy/no-op.txt b/Documentation/devicetree/bindings/phy/no-op.txt new file mode 100644 index 0000000..a338112 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/no-op.txt @@ -0,0 +1,16 @@ +NOP PHY driver + +This driver is used to stub PHY operations in a driver (USB, SATA). +This is useful when the 'client' driver (USB, SATA, ...) uses the PHY framework +and there is no actual PHY harwdare to drive. + +Required properties: +- compatible : must contain "nop-phy" +- #phy-cells : must contain <0> + +Example: + +nop_phy { + compatible = "nop-phy"; + #phy-cells = <0>; +}; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 7841554..98f2a1b 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -41,6 +41,24 @@ config PHY_SANDBOX This select a dummy sandbox PHY driver. It used only to implement the unit tests for the phy framework +config NOP_PHY + bool "NOP PHY driver" + depends on PHY + help + Support for a no-op PHY driver (stubbed PHY driver). + + This is useful when a driver uses the PHY framework but no real PHY + hardware exists. + +config SPL_NOP_PHY + bool "NOP PHY driver in SPL" + depends on SPL_PHY + help + Support for a no-op PHY driver (stubbed PHY driver) in the SPL. + + This is useful when a driver uses the PHY framework but no real PHY + hardware exists. + config PIPE3_PHY bool "Support omap's PIPE3 PHY" depends on PHY && ARCH_OMAP2PLUS diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 6ce96d2..ab56c46 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -6,5 +6,6 @@ # obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o +obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o diff --git a/drivers/phy/nop-phy.c b/drivers/phy/nop-phy.c new file mode 100644 index 0000000..2201cc3 --- /dev/null +++ b/drivers/phy/nop-phy.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Written by Jean-Jacques Hiblot + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static const struct udevice_id nop_phy_ids[] = { + { .compatible = "nop-phy" }, + { } +}; + +static struct phy_ops nop_phy_ops = { +}; + +U_BOOT_DRIVER(nop_phy) = { + .name = "nop_phy", + .id = UCLASS_PHY, + .of_match = nop_phy_ids, + .ops = &nop_phy_ops, +}; -- cgit v0.10.2 From d38a8ea19c1d82296619557069618aaefc1ad977 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 25 Jul 2017 13:24:44 +0200 Subject: usb: host: xhci-dxc3: fix compilation warnings Fix following warnings encountered with platforms dra7xx_evm and dra7xx_hs_evm : arm: + dra7xx_evm + hccr = (struct xhci_hccr *)devfdt_get_addr(dev); + ^ + hcor = (struct xhci_hcor *)((phys_addr_t)hccr + + ^ w+drivers/usb/host/xhci-dwc3.c: In function 'xhci_dwc3_probe': w+drivers/usb/host/xhci-dwc3.c:124:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] w+drivers/usb/host/xhci-dwc3.c:125:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] w+drivers/usb/host/xhci-dwc3.c:125:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] arm: + dra7xx_hs_evm + hccr = (struct xhci_hccr *)devfdt_get_addr(dev); + ^ + hcor = (struct xhci_hcor *)((phys_addr_t)hccr + + ^ w+drivers/usb/host/xhci-dwc3.c: In function 'xhci_dwc3_probe': w+drivers/usb/host/xhci-dwc3.c:124:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] w+drivers/usb/host/xhci-dwc3.c:125:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] w+drivers/usb/host/xhci-dwc3.c:125:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] Introduced by 7e65e84 usb: host: xhci-dwc3: Convert driver to DM Signed-off-by: Patrice Chotard diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 541a785..4191a89 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -121,8 +121,8 @@ static int xhci_dwc3_probe(struct udevice *dev) enum usb_dr_mode dr_mode; int ret; - hccr = (struct xhci_hccr *)devfdt_get_addr(dev); - hcor = (struct xhci_hcor *)((phys_addr_t)hccr + + hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev)); + hcor = (struct xhci_hcor *)((uintptr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); ret = generic_phy_get_by_index(dev, 0, &plat->usb_phy); -- cgit v0.10.2 From b108d8a0de3ddc6fe8aae55bc54e3edc69b4778b Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 25 Jul 2017 13:24:45 +0200 Subject: clk: fix compilation errors for poplar platform Move clk_release_all() prototype and definition inside OF_CONTROL flag to avoid following compilation error for poplar platform: aarch64: + poplar +drivers/usb/host/built-in.o: In function `ehci_usb_remove': +drivers/usb/host/ehci-generic.c:159: undefined reference to `clk_release_all' +drivers/usb/host/built-in.o: In function `ehci_usb_probe': +drivers/usb/host/ehci-generic.c:133: undefined reference to `clk_release_all' +make[1]: *** [u-boot] Error 139 +make: *** [sub-make] Error 2 Introduced by 4e542c4 clk: add clk_release_all() Signed-off-by: Patrice Chotard diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index ffbe872..e68d927 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -114,6 +114,30 @@ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk) return clk_get_by_index(dev, index, clk); } + +int clk_release_all(struct clk *clk, int count) +{ + int i, ret; + + for (i = 0; i < count; i++) { + debug("%s(clk[%d]=%p)\n", __func__, i, &clk[i]); + + /* check if clock has been previously requested */ + if (!clk[i].dev) + continue; + + ret = clk_disable(&clk[i]); + if (ret && ret != -ENOSYS) + return ret; + + ret = clk_free(&clk[i]); + if (ret && ret != -ENOSYS) + return ret; + } + + return 0; +} + #endif /* OF_CONTROL */ int clk_request(struct udevice *dev, struct clk *clk) @@ -190,29 +214,6 @@ int clk_disable(struct clk *clk) return ops->disable(clk); } -int clk_release_all(struct clk *clk, int count) -{ - int i, ret; - - for (i = 0; i < count; i++) { - debug("%s(clk[%d]=%p)\n", __func__, i, &clk[i]); - - /* check if clock has been previously requested */ - if (!clk[i].dev) - continue; - - ret = clk_disable(&clk[i]); - if (ret && ret != -ENOSYS) - return ret; - - ret = clk_free(&clk[i]); - if (ret && ret != -ENOSYS) - return ret; - } - - return 0; -} - UCLASS_DRIVER(clk) = { .id = UCLASS_CLK, .name = "clk", diff --git a/include/clk.h b/include/clk.h index a905a41..c5988f7 100644 --- a/include/clk.h +++ b/include/clk.h @@ -98,6 +98,21 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk); * @return 0 if OK, or a negative error code. */ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk); + +/** + * clk_release_all() - Disable (turn off)/Free an array of previously + * requested clocks. + * + * For each clock contained in the clock array, this function will check if + * clock has been previously requested and then will disable and free it. + * + * @clk: A clock struct array that was previously successfully + * requested by clk_request/get_by_*(). + * @count Number of clock contained in the array + * @return zero on success, or -ve error code. + */ +int clk_release_all(struct clk *clk, int count); + #else static inline int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) @@ -110,6 +125,12 @@ static inline int clk_get_by_name(struct udevice *dev, const char *name, { return -ENOSYS; } + +static inline int clk_release_all(struct clk *clk, int count) +{ + return -ENOSYS; +} + #endif /** @@ -174,20 +195,6 @@ int clk_enable(struct clk *clk); */ int clk_disable(struct clk *clk); -/** - * clk_release_all() - Disable (turn off)/Free an array of previously - * requested clocks. - * - * For each clock contained in the clock array, this function will check if - * clock has been previously requested and then will disable and free it. - * - * @clk: A clock struct array that was previously successfully - * requested by clk_request/get_by_*(). - * @count Number of clock contained in the array - * @return zero on success, or -ve error code. - */ -int clk_release_all(struct clk *clk, int count); - int soc_clk_dump(void); #endif -- cgit v0.10.2