diff options
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r-- | drivers/usb/chipidea/Kconfig | 6 | ||||
-rw-r--r-- | drivers/usb/chipidea/Makefile | 6 | ||||
-rw-r--r-- | drivers/usb/chipidea/bits.h | 16 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci.h | 51 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.c (renamed from drivers/usb/chipidea/ci13xxx_imx.c) | 117 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.h (renamed from drivers/usb/chipidea/ci13xxx_imx.h) | 0 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_msm.c (renamed from drivers/usb/chipidea/ci13xxx_msm.c) | 49 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_pci.c (renamed from drivers/usb/chipidea/ci13xxx_pci.c) | 61 | ||||
-rw-r--r-- | drivers/usb/chipidea/core.c | 109 | ||||
-rw-r--r-- | drivers/usb/chipidea/debug.c | 61 | ||||
-rw-r--r-- | drivers/usb/chipidea/debug.h | 8 | ||||
-rw-r--r-- | drivers/usb/chipidea/host.c | 10 | ||||
-rw-r--r-- | drivers/usb/chipidea/host.h | 4 | ||||
-rw-r--r-- | drivers/usb/chipidea/udc.c | 785 | ||||
-rw-r--r-- | drivers/usb/chipidea/udc.h | 26 | ||||
-rw-r--r-- | drivers/usb/chipidea/usbmisc_imx.c | 15 |
16 files changed, 737 insertions, 587 deletions
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index b2df442eb3e..eb2aa2e5a84 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -12,15 +12,15 @@ if USB_CHIPIDEA config USB_CHIPIDEA_UDC bool "ChipIdea device controller" - depends on USB_GADGET=y || USB_GADGET=USB_CHIPIDEA + depends on USB_GADGET=y || USB_CHIPIDEA=m help Say Y here to enable device controller functionality of the ChipIdea driver. config USB_CHIPIDEA_HOST bool "ChipIdea host controller" - depends on USB=y || USB=USB_CHIPIDEA - depends on USB_EHCI_HCD=y + depends on USB=y + depends on USB_EHCI_HCD=y || USB_CHIPIDEA=m select USB_EHCI_ROOT_HUB_TT help Say Y here to enable host controller functionality of the diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 4ab83e98219..3bbbcba0381 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -9,13 +9,13 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o # Glue/Bridge layers go here -obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o +obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_msm.o # PCI doesn't provide stubs, need to check ifneq ($(CONFIG_PCI),) - obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o + obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_pci.o endif ifneq ($(CONFIG_OF_DEVICE),) - obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx.o + obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_imx.o usbmisc_imx.o endif diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h index 050de8562a0..aefa0261220 100644 --- a/drivers/usb/chipidea/bits.h +++ b/drivers/usb/chipidea/bits.h @@ -48,10 +48,24 @@ #define PORTSC_SUSP BIT(7) #define PORTSC_HSP BIT(9) #define PORTSC_PTC (0x0FUL << 16) +/* PTS and PTW for non lpm version only */ +#define PORTSC_PTS(d) \ + ((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0)) +#define PORTSC_PTW BIT(28) +#define PORTSC_STS BIT(29) /* DEVLC */ #define DEVLC_PSPD (0x03UL << 25) -#define DEVLC_PSPD_HS (0x02UL << 25) +#define DEVLC_PSPD_HS (0x02UL << 25) +#define DEVLC_PTW BIT(27) +#define DEVLC_STS BIT(28) +#define DEVLC_PTS(d) (((d) & 0x7) << 29) + +/* Encoding for DEVLC_PTS and PORTSC_PTS */ +#define PTS_UTMI 0 +#define PTS_ULPI 2 +#define PTS_SERIAL 3 +#define PTS_HSIC 4 /* OTGSC */ #define OTGSC_IDPU BIT(5) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index b0a6bce064c..33cb29f36e0 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -22,14 +22,14 @@ * DEFINE *****************************************************************************/ #define TD_PAGE_COUNT 5 -#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */ +#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */ #define ENDPT_MAX 32 /****************************************************************************** * STRUCTURES *****************************************************************************/ /** - * struct ci13xxx_ep - endpoint representation + * struct ci_hw_ep - endpoint representation * @ep: endpoint structure for gadget drivers * @dir: endpoint direction (TX/RX) * @num: endpoint number @@ -41,7 +41,7 @@ * @lock: pointer to controller's spinlock * @td_pool: pointer to controller's TD pool */ -struct ci13xxx_ep { +struct ci_hw_ep { struct usb_ep ep; u8 dir; u8 num; @@ -49,15 +49,16 @@ struct ci13xxx_ep { char name[16]; struct { struct list_head queue; - struct ci13xxx_qh *ptr; + struct ci_hw_qh *ptr; dma_addr_t dma; } qh; int wedge; /* global resources */ - struct ci13xxx *ci; + struct ci_hdrc *ci; spinlock_t *lock; struct dma_pool *td_pool; + struct td_node *pending_td; }; enum ci_role { @@ -74,9 +75,9 @@ enum ci_role { * name: role name string (host/gadget) */ struct ci_role_driver { - int (*start)(struct ci13xxx *); - void (*stop)(struct ci13xxx *); - irqreturn_t (*irq)(struct ci13xxx *); + int (*start)(struct ci_hdrc *); + void (*stop)(struct ci_hdrc *); + irqreturn_t (*irq)(struct ci_hdrc *); const char *name; }; @@ -101,7 +102,7 @@ struct hw_bank { }; /** - * struct ci13xxx - chipidea device representation + * struct ci_hdrc - chipidea device representation * @dev: pointer to parent device * @lock: access synchronization * @hw_bank: hardware register mapping @@ -116,7 +117,7 @@ struct hw_bank { * @gadget: device side representation for peripheral controller * @driver: gadget driver * @hw_ep_max: total number of endpoints supported by hardware - * @ci13xxx_ep: array of endpoints + * @ci_hw_ep: array of endpoints * @ep0_dir: ep0 direction * @ep0out: pointer to ep0 OUT endpoint * @ep0in: pointer to ep0 IN endpoint @@ -132,7 +133,7 @@ struct hw_bank { * @hcd: pointer to usb_hcd for ehci host driver * @debugfs: root dentry for this controller in debugfs */ -struct ci13xxx { +struct ci_hdrc { struct device *dev; spinlock_t lock; struct hw_bank hw_bank; @@ -149,9 +150,9 @@ struct ci13xxx { struct usb_gadget gadget; struct usb_gadget_driver *driver; unsigned hw_ep_max; - struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; + struct ci_hw_ep ci_hw_ep[ENDPT_MAX]; u32 ep0_dir; - struct ci13xxx_ep *ep0out, *ep0in; + struct ci_hw_ep *ep0out, *ep0in; struct usb_request *status; bool setaddr; @@ -160,7 +161,7 @@ struct ci13xxx { u8 suspended; u8 test_mode; - struct ci13xxx_platform_data *platdata; + struct ci_hdrc_platform_data *platdata; int vbus_active; /* FIXME: some day, we'll not use global phy */ bool global_phy; @@ -169,13 +170,13 @@ struct ci13xxx { struct dentry *debugfs; }; -static inline struct ci_role_driver *ci_role(struct ci13xxx *ci) +static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) { BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]); return ci->roles[ci->role]; } -static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role) +static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) { int ret; @@ -191,7 +192,7 @@ static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role) return ret; } -static inline void ci_role_stop(struct ci13xxx *ci) +static inline void ci_role_stop(struct ci_hdrc *ci) { enum ci_role role = ci->role; @@ -210,7 +211,7 @@ static inline void ci_role_stop(struct ci13xxx *ci) #define REG_BITS (32) /* register indices */ -enum ci13xxx_regs { +enum ci_hw_regs { CAP_CAPLENGTH, CAP_HCCPARAMS, CAP_DCCPARAMS, @@ -242,7 +243,7 @@ enum ci13xxx_regs { * * This function returns register contents */ -static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) +static inline u32 hw_read(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask) { return ioread32(ci->hw_bank.regmap[reg]) & mask; } @@ -253,7 +254,7 @@ static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) * @mask: bitfield mask * @data: new value */ -static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg, +static inline void hw_write(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask, u32 data) { if (~mask) @@ -270,7 +271,7 @@ static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg, * * This function returns register contents */ -static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg, +static inline u32 hw_test_and_clear(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask) { u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; @@ -287,7 +288,7 @@ static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg, * * This function returns register contents */ -static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg, +static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask, u32 data) { u32 val = hw_read(ci, reg, ~0); @@ -296,10 +297,10 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg, return (val & mask) >> __ffs(mask); } -int hw_device_reset(struct ci13xxx *ci, u32 mode); +int hw_device_reset(struct ci_hdrc *ci, u32 mode); -int hw_port_test_set(struct ci13xxx *ci, u8 mode); +int hw_port_test_set(struct ci_hdrc *ci, u8 mode); -u8 hw_port_test_get(struct ci13xxx *ci); +u8 hw_port_test_get(struct ci_hdrc *ci); #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 73f9d5f15ad..14362c00db3 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -20,16 +20,14 @@ #include <linux/usb/chipidea.h> #include <linux/clk.h> #include <linux/regulator/consumer.h> -#include <linux/pinctrl/consumer.h> #include "ci.h" -#include "ci13xxx_imx.h" +#include "ci_hdrc_imx.h" #define pdev_to_phy(pdev) \ ((struct usb_phy *)platform_get_drvdata(pdev)) -struct ci13xxx_imx_data { - struct device_node *phy_np; +struct ci_hdrc_imx_data { struct usb_phy *phy; struct platform_device *ci_pdev; struct clk *clk; @@ -88,22 +86,17 @@ EXPORT_SYMBOL_GPL(usbmisc_get_init_data); /* End of common functions shared by usbmisc drivers*/ -static struct ci13xxx_platform_data ci13xxx_imx_platdata = { - .name = "ci13xxx_imx", - .flags = CI13XXX_REQUIRE_TRANSCEIVER | - CI13XXX_PULLUP_ON_VBUS | - CI13XXX_DISABLE_STREAMING, - .capoffset = DEF_CAPOFFSET, -}; - -static int ci13xxx_imx_probe(struct platform_device *pdev) +static int ci_hdrc_imx_probe(struct platform_device *pdev) { - struct ci13xxx_imx_data *data; - struct platform_device *plat_ci, *phy_pdev; - struct device_node *phy_np; + struct ci_hdrc_imx_data *data; + struct ci_hdrc_platform_data pdata = { + .name = "ci_hdrc_imx", + .capoffset = DEF_CAPOFFSET, + .flags = CI_HDRC_REQUIRE_TRANSCEIVER | + CI_HDRC_PULLUP_ON_VBUS | + CI_HDRC_DISABLE_STREAMING, + }; struct resource *res; - struct regulator *reg_vbus; - struct pinctrl *pinctrl; int ret; if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL) @@ -112,7 +105,7 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) { - dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n"); + dev_err(&pdev->dev, "Failed to allocate ci_hdrc-imx data!\n"); return -ENOMEM; } @@ -122,11 +115,6 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) return -ENOENT; } - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, "pinctrl get/select failed, err=%ld\n", - PTR_ERR(pinctrl)); - data->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(data->clk)) { dev_err(&pdev->dev, @@ -141,37 +129,33 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) return ret; } - phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0); - if (phy_np) { - data->phy_np = phy_np; - phy_pdev = of_find_device_by_node(phy_np); - if (phy_pdev) { - struct usb_phy *phy; - phy = pdev_to_phy(phy_pdev); - if (phy && - try_module_get(phy_pdev->dev.driver->owner)) { - usb_phy_init(phy); - data->phy = phy; - } + data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); + if (!IS_ERR(data->phy)) { + ret = usb_phy_init(data->phy); + if (ret) { + dev_err(&pdev->dev, "unable to init phy: %d\n", ret); + goto err_clk; } + } else if (PTR_ERR(data->phy) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err_clk; } /* we only support host now, so enable vbus here */ - reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); - if (!IS_ERR(reg_vbus)) { - ret = regulator_enable(reg_vbus); + data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); + if (!IS_ERR(data->reg_vbus)) { + ret = regulator_enable(data->reg_vbus); if (ret) { dev_err(&pdev->dev, "Failed to enable vbus regulator, err=%d\n", ret); - goto put_np; + goto err_clk; } - data->reg_vbus = reg_vbus; } else { - reg_vbus = NULL; + data->reg_vbus = NULL; } - ci13xxx_imx_platdata.phy = data->phy; + pdata.phy = data->phy; if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; @@ -187,11 +171,11 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) } } - plat_ci = ci13xxx_add_device(&pdev->dev, + data->ci_pdev = ci_hdrc_add_device(&pdev->dev, pdev->resource, pdev->num_resources, - &ci13xxx_imx_platdata); - if (IS_ERR(plat_ci)) { - ret = PTR_ERR(plat_ci); + &pdata); + if (IS_ERR(data->ci_pdev)) { + ret = PTR_ERR(data->ci_pdev); dev_err(&pdev->dev, "Can't register ci_hdrc platform device, err=%d\n", ret); @@ -203,11 +187,10 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret); - goto put_np; + goto disable_device; } } - data->ci_pdev = plat_ci; platform_set_drvdata(pdev, data); pm_runtime_no_callbacks(&pdev->dev); @@ -215,22 +198,22 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) return 0; +disable_device: + ci_hdrc_remove_device(data->ci_pdev); err: - if (reg_vbus) - regulator_disable(reg_vbus); -put_np: - if (phy_np) - of_node_put(phy_np); + if (data->reg_vbus) + regulator_disable(data->reg_vbus); +err_clk: clk_disable_unprepare(data->clk); return ret; } -static int ci13xxx_imx_remove(struct platform_device *pdev) +static int ci_hdrc_imx_remove(struct platform_device *pdev) { - struct ci13xxx_imx_data *data = platform_get_drvdata(pdev); + struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); - ci13xxx_remove_device(data->ci_pdev); + ci_hdrc_remove_device(data->ci_pdev); if (data->reg_vbus) regulator_disable(data->reg_vbus); @@ -240,35 +223,31 @@ static int ci13xxx_imx_remove(struct platform_device *pdev) module_put(data->phy->dev->driver->owner); } - of_node_put(data->phy_np); - clk_disable_unprepare(data->clk); - platform_set_drvdata(pdev, NULL); - return 0; } -static const struct of_device_id ci13xxx_imx_dt_ids[] = { +static const struct of_device_id ci_hdrc_imx_dt_ids[] = { { .compatible = "fsl,imx27-usb", }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids); +MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); -static struct platform_driver ci13xxx_imx_driver = { - .probe = ci13xxx_imx_probe, - .remove = ci13xxx_imx_remove, +static struct platform_driver ci_hdrc_imx_driver = { + .probe = ci_hdrc_imx_probe, + .remove = ci_hdrc_imx_remove, .driver = { .name = "imx_usb", .owner = THIS_MODULE, - .of_match_table = ci13xxx_imx_dt_ids, + .of_match_table = ci_hdrc_imx_dt_ids, }, }; -module_platform_driver(ci13xxx_imx_driver); +module_platform_driver(ci_hdrc_imx_driver); MODULE_ALIAS("platform:imx-usb"); MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("CI13xxx i.MX USB binding"); +MODULE_DESCRIPTION("CI HDRC i.MX USB binding"); MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); diff --git a/drivers/usb/chipidea/ci13xxx_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h index 550bfa45762..550bfa45762 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.h +++ b/drivers/usb/chipidea/ci_hdrc_imx.h diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index 7d16681fd3d..fb657ef50a9 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -17,19 +17,19 @@ #define MSM_USB_BASE (ci->hw_bank.abs) -static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event) +static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) { struct device *dev = ci->gadget.dev.parent; int val; switch (event) { - case CI13XXX_CONTROLLER_RESET_EVENT: - dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n"); + case CI_HDRC_CONTROLLER_RESET_EVENT: + dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); writel(0, USB_AHBBURST); writel(0, USB_AHBMODE); break; - case CI13XXX_CONTROLLER_STOPPED_EVENT: - dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n"); + case CI_HDRC_CONTROLLER_STOPPED_EVENT: + dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n"); /* * Put the transceiver in non-driving mode. Otherwise host * may not detect soft-disconnection. @@ -40,32 +40,32 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event) usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); break; default: - dev_dbg(dev, "unknown ci13xxx event\n"); + dev_dbg(dev, "unknown ci_hdrc event\n"); break; } } -static struct ci13xxx_platform_data ci13xxx_msm_platdata = { - .name = "ci13xxx_msm", - .flags = CI13XXX_REGS_SHARED | - CI13XXX_REQUIRE_TRANSCEIVER | - CI13XXX_PULLUP_ON_VBUS | - CI13XXX_DISABLE_STREAMING, +static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = { + .name = "ci_hdrc_msm", + .flags = CI_HDRC_REGS_SHARED | + CI_HDRC_REQUIRE_TRANSCEIVER | + CI_HDRC_PULLUP_ON_VBUS | + CI_HDRC_DISABLE_STREAMING, - .notify_event = ci13xxx_msm_notify_event, + .notify_event = ci_hdrc_msm_notify_event, }; -static int ci13xxx_msm_probe(struct platform_device *pdev) +static int ci_hdrc_msm_probe(struct platform_device *pdev) { struct platform_device *plat_ci; - dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); + dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n"); - plat_ci = ci13xxx_add_device(&pdev->dev, + plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource, pdev->num_resources, - &ci13xxx_msm_platdata); + &ci_hdrc_msm_platdata); if (IS_ERR(plat_ci)) { - dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); + dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); return PTR_ERR(plat_ci); } @@ -77,23 +77,24 @@ static int ci13xxx_msm_probe(struct platform_device *pdev) return 0; } -static int ci13xxx_msm_remove(struct platform_device *pdev) +static int ci_hdrc_msm_remove(struct platform_device *pdev) { struct platform_device *plat_ci = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); - ci13xxx_remove_device(plat_ci); + ci_hdrc_remove_device(plat_ci); return 0; } -static struct platform_driver ci13xxx_msm_driver = { - .probe = ci13xxx_msm_probe, - .remove = ci13xxx_msm_remove, +static struct platform_driver ci_hdrc_msm_driver = { + .probe = ci_hdrc_msm_probe, + .remove = ci_hdrc_msm_remove, .driver = { .name = "msm_hsusb", }, }; -module_platform_driver(ci13xxx_msm_driver); +module_platform_driver(ci_hdrc_msm_driver); MODULE_ALIAS("platform:msm_hsusb"); +MODULE_ALIAS("platform:ci13xxx_msm"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci_hdrc_pci.c index 4e1fc61b9d9..042320a6c6c 100644 --- a/drivers/usb/chipidea/ci13xxx_pci.c +++ b/drivers/usb/chipidea/ci_hdrc_pci.c @@ -1,5 +1,5 @@ /* - * ci13xxx_pci.c - MIPS USB IP core family device controller + * ci_hdrc_pci.c - MIPS USB IP core family device controller * * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. * @@ -18,29 +18,29 @@ #include <linux/usb/chipidea.h> /* driver name */ -#define UDC_DRIVER_NAME "ci13xxx_pci" +#define UDC_DRIVER_NAME "ci_hdrc_pci" /****************************************************************************** * PCI block *****************************************************************************/ -static struct ci13xxx_platform_data pci_platdata = { +static struct ci_hdrc_platform_data pci_platdata = { .name = UDC_DRIVER_NAME, .capoffset = DEF_CAPOFFSET, }; -static struct ci13xxx_platform_data langwell_pci_platdata = { +static struct ci_hdrc_platform_data langwell_pci_platdata = { .name = UDC_DRIVER_NAME, .capoffset = 0, }; -static struct ci13xxx_platform_data penwell_pci_platdata = { +static struct ci_hdrc_platform_data penwell_pci_platdata = { .name = UDC_DRIVER_NAME, .capoffset = 0, .power_budget = 200, }; /** - * ci13xxx_pci_probe: PCI probe + * ci_hdrc_pci_probe: PCI probe * @pdev: USB device controller being probed * @id: PCI hotplug ID connecting controller to UDC framework * @@ -48,10 +48,10 @@ static struct ci13xxx_platform_data penwell_pci_platdata = { * Allocates basic PCI resources for this USB device controller, and then * invokes the udc_probe() method to start the UDC associated with it */ -static int ci13xxx_pci_probe(struct pci_dev *pdev, +static int ci_hdrc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct ci13xxx_platform_data *platdata = (void *)id->driver_data; + struct ci_hdrc_platform_data *platdata = (void *)id->driver_data; struct platform_device *plat_ci; struct resource res[3]; int retval = 0, nres = 2; @@ -61,17 +61,15 @@ static int ci13xxx_pci_probe(struct pci_dev *pdev, return -ENODEV; } - retval = pci_enable_device(pdev); + retval = pcim_enable_device(pdev); if (retval) - goto done; + return retval; if (!pdev->irq) { dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); - retval = -ENODEV; - goto disable_device; + return -ENODEV; } - pci_set_power_state(pdev, PCI_D0); pci_set_master(pdev); pci_try_set_mwi(pdev); @@ -82,38 +80,30 @@ static int ci13xxx_pci_probe(struct pci_dev *pdev, res[1].start = pdev->irq; res[1].flags = IORESOURCE_IRQ; - plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata); + plat_ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata); if (IS_ERR(plat_ci)) { - dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); - retval = PTR_ERR(plat_ci); - goto disable_device; + dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); + return PTR_ERR(plat_ci); } pci_set_drvdata(pdev, plat_ci); return 0; - - disable_device: - pci_disable_device(pdev); - done: - return retval; } /** - * ci13xxx_pci_remove: PCI remove + * ci_hdrc_pci_remove: PCI remove * @pdev: USB Device Controller being removed * - * Reverses the effect of ci13xxx_pci_probe(), + * Reverses the effect of ci_hdrc_pci_probe(), * first invoking the udc_remove() and then releases * all PCI resources allocated for this USB device controller */ -static void ci13xxx_pci_remove(struct pci_dev *pdev) +static void ci_hdrc_pci_remove(struct pci_dev *pdev) { struct platform_device *plat_ci = pci_get_drvdata(pdev); - ci13xxx_remove_device(plat_ci); - pci_set_drvdata(pdev, NULL); - pci_disable_device(pdev); + ci_hdrc_remove_device(plat_ci); } /** @@ -122,7 +112,7 @@ static void ci13xxx_pci_remove(struct pci_dev *pdev) * * Check "pci.h" for details */ -static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { +static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = { { PCI_DEVICE(0x153F, 0x1004), .driver_data = (kernel_ulong_t)&pci_platdata, @@ -141,18 +131,19 @@ static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { }, { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } }; -MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); +MODULE_DEVICE_TABLE(pci, ci_hdrc_pci_id_table); -static struct pci_driver ci13xxx_pci_driver = { +static struct pci_driver ci_hdrc_pci_driver = { .name = UDC_DRIVER_NAME, - .id_table = ci13xxx_pci_id_table, - .probe = ci13xxx_pci_probe, - .remove = ci13xxx_pci_remove, + .id_table = ci_hdrc_pci_id_table, + .probe = ci_hdrc_pci_probe, + .remove = ci_hdrc_pci_remove, }; -module_pci_driver(ci13xxx_pci_driver); +module_pci_driver(ci_hdrc_pci_driver); MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); MODULE_LICENSE("GPL"); MODULE_VERSION("June 2008"); +MODULE_ALIAS("platform:ci13xxx_pci"); diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 475c9c11468..a5df24c578f 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -43,8 +43,7 @@ * * TODO List * - OTG - * - Isochronous & Interrupt Traffic - * - Handle requests which spawns into several TDs + * - Interrupt Traffic * - GET_STATUS(device) - always reports 0 * - Gadget API (majority of optional features) * - Suspend & Remote Wakeup @@ -64,6 +63,8 @@ #include <linux/usb/gadget.h> #include <linux/usb/otg.h> #include <linux/usb/chipidea.h> +#include <linux/usb/of.h> +#include <linux/phy.h> #include "ci.h" #include "udc.h" @@ -116,7 +117,7 @@ static uintptr_t ci_regs_lpm[] = { [OP_ENDPTCTRL] = 0x0ECUL, }; -static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm) +static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm) { int i; @@ -148,7 +149,7 @@ static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm) * * This function returns an error code */ -int hw_port_test_set(struct ci13xxx *ci, u8 mode) +int hw_port_test_set(struct ci_hdrc *ci, u8 mode) { const u8 TEST_MODE_MAX = 7; @@ -164,12 +165,12 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode) * * This function returns port test mode value */ -u8 hw_port_test_get(struct ci13xxx *ci) +u8 hw_port_test_get(struct ci_hdrc *ci) { return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC); } -static int hw_device_init(struct ci13xxx *ci, void __iomem *base) +static int hw_device_init(struct ci_hdrc *ci, void __iomem *base) { u32 reg; @@ -208,13 +209,52 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base) return 0; } +static void hw_phymode_configure(struct ci_hdrc *ci) +{ + u32 portsc, lpm, sts; + + switch (ci->platdata->phy_mode) { + case USBPHY_INTERFACE_MODE_UTMI: + portsc = PORTSC_PTS(PTS_UTMI); + lpm = DEVLC_PTS(PTS_UTMI); + break; + case USBPHY_INTERFACE_MODE_UTMIW: + portsc = PORTSC_PTS(PTS_UTMI) | PORTSC_PTW; + lpm = DEVLC_PTS(PTS_UTMI) | DEVLC_PTW; + break; + case USBPHY_INTERFACE_MODE_ULPI: + portsc = PORTSC_PTS(PTS_ULPI); + lpm = DEVLC_PTS(PTS_ULPI); + break; + case USBPHY_INTERFACE_MODE_SERIAL: + portsc = PORTSC_PTS(PTS_SERIAL); + lpm = DEVLC_PTS(PTS_SERIAL); + sts = 1; + break; + case USBPHY_INTERFACE_MODE_HSIC: + portsc = PORTSC_PTS(PTS_HSIC); + lpm = DEVLC_PTS(PTS_HSIC); + break; + default: + return; + } + + if (ci->hw_bank.lpm) { + hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm); + hw_write(ci, OP_DEVLC, DEVLC_STS, sts); + } else { + hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc); + hw_write(ci, OP_PORTSC, PORTSC_STS, sts); + } +} + /** * hw_device_reset: resets chip (execute without interruption) * @ci: the controller * * This function returns an error code */ -int hw_device_reset(struct ci13xxx *ci, u32 mode) +int hw_device_reset(struct ci_hdrc *ci, u32 mode) { /* should flush & stop before reset */ hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); @@ -224,12 +264,13 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) while (hw_read(ci, OP_USBCMD, USBCMD_RST)) udelay(10); /* not RTOS friendly */ + hw_phymode_configure(ci); if (ci->platdata->notify_event) ci->platdata->notify_event(ci, - CI13XXX_CONTROLLER_RESET_EVENT); + CI_HDRC_CONTROLLER_RESET_EVENT); - if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) + if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); /* USBMODE should be configured step by step */ @@ -251,7 +292,7 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) * ci_otg_role - pick role based on ID pin state * @ci: the controller */ -static enum ci_role ci_otg_role(struct ci13xxx *ci) +static enum ci_role ci_otg_role(struct ci_hdrc *ci) { u32 sts = hw_read(ci, OP_OTGSC, ~0); enum ci_role role = sts & OTGSC_ID @@ -267,7 +308,7 @@ static enum ci_role ci_otg_role(struct ci13xxx *ci) */ static void ci_role_work(struct work_struct *work) { - struct ci13xxx *ci = container_of(work, struct ci13xxx, work); + struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work); enum ci_role role = ci_otg_role(ci); if (role != ci->role) { @@ -283,7 +324,7 @@ static void ci_role_work(struct work_struct *work) static irqreturn_t ci_irq(int irq, void *data) { - struct ci13xxx *ci = data; + struct ci_hdrc *ci = data; irqreturn_t ret = IRQ_NONE; u32 otgsc = 0; @@ -305,9 +346,9 @@ static irqreturn_t ci_irq(int irq, void *data) static DEFINE_IDA(ci_ida); -struct platform_device *ci13xxx_add_device(struct device *dev, +struct platform_device *ci_hdrc_add_device(struct device *dev, struct resource *res, int nres, - struct ci13xxx_platform_data *platdata) + struct ci_hdrc_platform_data *platdata) { struct platform_device *pdev; int id, ret; @@ -347,29 +388,33 @@ put_id: ida_simple_remove(&ci_ida, id); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(ci13xxx_add_device); +EXPORT_SYMBOL_GPL(ci_hdrc_add_device); -void ci13xxx_remove_device(struct platform_device *pdev) +void ci_hdrc_remove_device(struct platform_device *pdev) { int id = pdev->id; platform_device_unregister(pdev); ida_simple_remove(&ci_ida, id); } -EXPORT_SYMBOL_GPL(ci13xxx_remove_device); +EXPORT_SYMBOL_GPL(ci_hdrc_remove_device); static int ci_hdrc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ci13xxx *ci; + struct ci_hdrc *ci; struct resource *res; void __iomem *base; int ret; + enum usb_dr_mode dr_mode; if (!dev->platform_data) { dev_err(dev, "platform data missing\n"); return -ENODEV; } + if (!dev->of_node && dev->parent) + dev->of_node = dev->parent->of_node; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) @@ -409,14 +454,28 @@ static int ci_hdrc_probe(struct platform_device *pdev) return -ENODEV; } + if (!ci->platdata->phy_mode) + ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); + + if (!ci->platdata->dr_mode) + ci->platdata->dr_mode = of_usb_get_dr_mode(dev->of_node); + + if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN) + ci->platdata->dr_mode = USB_DR_MODE_OTG; + + dr_mode = ci->platdata->dr_mode; /* initialize role(s) before the interrupt is requested */ - ret = ci_hdrc_host_init(ci); - if (ret) - dev_info(dev, "doesn't support host\n"); + if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { + ret = ci_hdrc_host_init(ci); + if (ret) + dev_info(dev, "doesn't support host\n"); + } - ret = ci_hdrc_gadget_init(ci); - if (ret) - dev_info(dev, "doesn't support gadget\n"); + if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { + ret = ci_hdrc_gadget_init(ci); + if (ret) + dev_info(dev, "doesn't support gadget\n"); + } if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { dev_err(dev, "no supported roles\n"); @@ -467,7 +526,7 @@ rm_wq: static int ci_hdrc_remove(struct platform_device *pdev) { - struct ci13xxx *ci = platform_get_drvdata(pdev); + struct ci_hdrc *ci = platform_get_drvdata(pdev); dbg_remove_files(ci); flush_workqueue(ci->wq); diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 36a7063a6cb..96d899aee47 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -18,7 +18,7 @@ */ static int ci_device_show(struct seq_file *s, void *data) { - struct ci13xxx *ci = s->private; + struct ci_hdrc *ci = s->private; struct usb_gadget *gadget = &ci->gadget; seq_printf(s, "speed = %d\n", gadget->speed); @@ -58,7 +58,7 @@ static const struct file_operations ci_device_fops = { */ static int ci_port_test_show(struct seq_file *s, void *data) { - struct ci13xxx *ci = s->private; + struct ci_hdrc *ci = s->private; unsigned long flags; unsigned mode; @@ -78,7 +78,7 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct ci13xxx *ci = s->private; + struct ci_hdrc *ci = s->private; unsigned long flags; unsigned mode; char buf[32]; @@ -115,7 +115,7 @@ static const struct file_operations ci_port_test_fops = { */ static int ci_qheads_show(struct seq_file *s, void *data) { - struct ci13xxx *ci = s->private; + struct ci_hdrc *ci = s->private; unsigned long flags; unsigned i, j; @@ -126,15 +126,15 @@ static int ci_qheads_show(struct seq_file *s, void *data) spin_lock_irqsave(&ci->lock, flags); for (i = 0; i < ci->hw_ep_max/2; i++) { - struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i]; - struct ci13xxx_ep *mEpTx = - &ci->ci13xxx_ep[i + ci->hw_ep_max/2]; + struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i]; + struct ci_hw_ep *hweptx = + &ci->ci_hw_ep[i + ci->hw_ep_max/2]; seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n", - i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); - for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) + i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma); + for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++) seq_printf(s, " %04X: %08X %08X\n", j, - *((u32 *)mEpRx->qh.ptr + j), - *((u32 *)mEpTx->qh.ptr + j)); + *((u32 *)hweprx->qh.ptr + j), + *((u32 *)hweptx->qh.ptr + j)); } spin_unlock_irqrestore(&ci->lock, flags); @@ -158,11 +158,12 @@ static const struct file_operations ci_qheads_fops = { */ static int ci_requests_show(struct seq_file *s, void *data) { - struct ci13xxx *ci = s->private; + struct ci_hdrc *ci = s->private; unsigned long flags; struct list_head *ptr = NULL; - struct ci13xxx_req *req = NULL; - unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32); + struct ci_hw_req *req = NULL; + struct td_node *node, *tmpnode; + unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32); if (ci->role != CI_ROLE_GADGET) { seq_printf(s, "not in gadget mode\n"); @@ -171,16 +172,20 @@ static int ci_requests_show(struct seq_file *s, void *data) spin_lock_irqsave(&ci->lock, flags); for (i = 0; i < ci->hw_ep_max; i++) - list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) { - req = list_entry(ptr, struct ci13xxx_req, queue); - - seq_printf(s, "EP=%02i: TD=%08X %s\n", - i % (ci->hw_ep_max / 2), (u32)req->dma, - ((i < ci->hw_ep_max/2) ? "RX" : "TX")); - - for (j = 0; j < qsize; j++) - seq_printf(s, " %04X: %08X\n", j, - *((u32 *)req->ptr + j)); + list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) { + req = list_entry(ptr, struct ci_hw_req, queue); + + list_for_each_entry_safe(node, tmpnode, &req->tds, td) { + seq_printf(s, "EP=%02i: TD=%08X %s\n", + i % (ci->hw_ep_max / 2), + (u32)node->dma, + ((i < ci->hw_ep_max/2) ? + "RX" : "TX")); + + for (j = 0; j < qsize; j++) + seq_printf(s, " %04X: %08X\n", j, + *((u32 *)node->ptr + j)); + } } spin_unlock_irqrestore(&ci->lock, flags); @@ -201,7 +206,7 @@ static const struct file_operations ci_requests_fops = { static int ci_role_show(struct seq_file *s, void *data) { - struct ci13xxx *ci = s->private; + struct ci_hdrc *ci = s->private; seq_printf(s, "%s\n", ci_role(ci)->name); @@ -212,7 +217,7 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct ci13xxx *ci = s->private; + struct ci_hdrc *ci = s->private; enum ci_role role; char buf[8]; int ret; @@ -254,7 +259,7 @@ static const struct file_operations ci_role_fops = { * * This function returns an error code */ -int dbg_create_files(struct ci13xxx *ci) +int dbg_create_files(struct ci_hdrc *ci) { struct dentry *dent; @@ -295,7 +300,7 @@ err: * dbg_remove_files: destroys the attribute interface * @ci: device */ -void dbg_remove_files(struct ci13xxx *ci) +void dbg_remove_files(struct ci_hdrc *ci) { debugfs_remove_recursive(ci->debugfs); } diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h index 7ca6ca0a24a..e16478c4a94 100644 --- a/drivers/usb/chipidea/debug.h +++ b/drivers/usb/chipidea/debug.h @@ -14,15 +14,15 @@ #define __DRIVERS_USB_CHIPIDEA_DEBUG_H #ifdef CONFIG_USB_CHIPIDEA_DEBUG -int dbg_create_files(struct ci13xxx *ci); -void dbg_remove_files(struct ci13xxx *ci); +int dbg_create_files(struct ci_hdrc *ci); +void dbg_remove_files(struct ci_hdrc *ci); #else -static inline int dbg_create_files(struct ci13xxx *ci) +static inline int dbg_create_files(struct ci_hdrc *ci) { return 0; } -static inline void dbg_remove_files(struct ci13xxx *ci) +static inline void dbg_remove_files(struct ci_hdrc *ci) { } #endif diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 8e9d31277c4..40d0fda4f66 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -33,12 +33,12 @@ static struct hc_driver __read_mostly ci_ehci_hc_driver; -static irqreturn_t host_irq(struct ci13xxx *ci) +static irqreturn_t host_irq(struct ci_hdrc *ci) { return usb_hcd_irq(ci->irq, ci->hcd); } -static int host_start(struct ci13xxx *ci) +static int host_start(struct ci_hdrc *ci) { struct usb_hcd *hcd; struct ehci_hcd *ehci; @@ -70,13 +70,13 @@ static int host_start(struct ci13xxx *ci) else ci->hcd = hcd; - if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) + if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); return ret; } -static void host_stop(struct ci13xxx *ci) +static void host_stop(struct ci_hdrc *ci) { struct usb_hcd *hcd = ci->hcd; @@ -84,7 +84,7 @@ static void host_stop(struct ci13xxx *ci) usb_put_hcd(hcd); } -int ci_hdrc_host_init(struct ci13xxx *ci) +int ci_hdrc_host_init(struct ci_hdrc *ci) { struct ci_role_driver *rdrv; diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h index 761fb1fd6d9..058875c1533 100644 --- a/drivers/usb/chipidea/host.h +++ b/drivers/usb/chipidea/host.h @@ -3,11 +3,11 @@ #ifdef CONFIG_USB_CHIPIDEA_HOST -int ci_hdrc_host_init(struct ci13xxx *ci); +int ci_hdrc_host_init(struct ci_hdrc *ci); #else -static inline int ci_hdrc_host_init(struct ci13xxx *ci) +static inline int ci_hdrc_host_init(struct ci_hdrc *ci) { return -ENXIO; } diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b501346484a..e475fcda1d6 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -61,7 +61,7 @@ static inline int hw_ep_bit(int num, int dir) return num + (dir ? 16 : 0); } -static inline int ep_to_bit(struct ci13xxx *ci, int n) +static inline int ep_to_bit(struct ci_hdrc *ci, int n) { int fill = 16 - ci->hw_ep_max / 2; @@ -77,7 +77,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n) * * This function returns an error code */ -static int hw_device_state(struct ci13xxx *ci, u32 dma) +static int hw_device_state(struct ci_hdrc *ci, u32 dma) { if (dma) { hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); @@ -97,7 +97,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma) * * This function returns an error code */ -static int hw_ep_flush(struct ci13xxx *ci, int num, int dir) +static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) { int n = hw_ep_bit(num, dir); @@ -118,7 +118,7 @@ static int hw_ep_flush(struct ci13xxx *ci, int num, int dir) * * This function returns an error code */ -static int hw_ep_disable(struct ci13xxx *ci, int num, int dir) +static int hw_ep_disable(struct ci_hdrc *ci, int num, int dir) { hw_ep_flush(ci, num, dir); hw_write(ci, OP_ENDPTCTRL + num, @@ -134,7 +134,7 @@ static int hw_ep_disable(struct ci13xxx *ci, int num, int dir) * * This function returns an error code */ -static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type) +static int hw_ep_enable(struct ci_hdrc *ci, int num, int dir, int type) { u32 mask, data; @@ -168,7 +168,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type) * * This function returns 1 if endpoint halted */ -static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir) +static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir) { u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; @@ -182,7 +182,7 @@ static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir) * * This function returns setup status */ -static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n) +static int hw_test_and_clear_setup_status(struct ci_hdrc *ci, int n) { n = ep_to_bit(ci, n); return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); @@ -196,7 +196,7 @@ static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n) * * This function returns an error code */ -static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl) +static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl) { int n = hw_ep_bit(num, dir); @@ -223,13 +223,13 @@ static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl) * * This function returns an error code */ -static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value) +static int hw_ep_set_halt(struct ci_hdrc *ci, int num, int dir, int value) { if (value != 0 && value != 1) return -EINVAL; do { - enum ci13xxx_regs reg = OP_ENDPTCTRL + num; + enum ci_hw_regs reg = OP_ENDPTCTRL + num; u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; @@ -246,7 +246,7 @@ static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value) * * This function returns true if high speed port */ -static int hw_port_is_high_speed(struct ci13xxx *ci) +static int hw_port_is_high_speed(struct ci_hdrc *ci) { return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : hw_read(ci, OP_PORTSC, PORTSC_HSP); @@ -257,7 +257,7 @@ static int hw_port_is_high_speed(struct ci13xxx *ci) * * This function returns register data */ -static u32 hw_read_intr_enable(struct ci13xxx *ci) +static u32 hw_read_intr_enable(struct ci_hdrc *ci) { return hw_read(ci, OP_USBINTR, ~0); } @@ -267,7 +267,7 @@ static u32 hw_read_intr_enable(struct ci13xxx *ci) * * This function returns register data */ -static u32 hw_read_intr_status(struct ci13xxx *ci) +static u32 hw_read_intr_status(struct ci_hdrc *ci) { return hw_read(ci, OP_USBSTS, ~0); } @@ -279,7 +279,7 @@ static u32 hw_read_intr_status(struct ci13xxx *ci) * * This function returns complete status */ -static int hw_test_and_clear_complete(struct ci13xxx *ci, int n) +static int hw_test_and_clear_complete(struct ci_hdrc *ci, int n) { n = ep_to_bit(ci, n); return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n)); @@ -291,7 +291,7 @@ static int hw_test_and_clear_complete(struct ci13xxx *ci, int n) * * This function returns active interrutps */ -static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) +static u32 hw_test_and_clear_intr_active(struct ci_hdrc *ci) { u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); @@ -305,7 +305,7 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) * * This function returns guard value */ -static int hw_test_and_clear_setup_guard(struct ci13xxx *ci) +static int hw_test_and_clear_setup_guard(struct ci_hdrc *ci) { return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0); } @@ -316,7 +316,7 @@ static int hw_test_and_clear_setup_guard(struct ci13xxx *ci) * * This function returns guard value */ -static int hw_test_and_set_setup_guard(struct ci13xxx *ci) +static int hw_test_and_set_setup_guard(struct ci_hdrc *ci) { return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); } @@ -328,7 +328,7 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *ci) * This function explicitly sets the address, without the "USBADRA" (advance) * feature, which is not supported by older versions of the controller. */ -static void hw_usb_set_address(struct ci13xxx *ci, u8 value) +static void hw_usb_set_address(struct ci_hdrc *ci, u8 value) { hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, value << __ffs(DEVICEADDR_USBADR)); @@ -340,7 +340,7 @@ static void hw_usb_set_address(struct ci13xxx *ci, u8 value) * * This function returns an error code */ -static int hw_usb_reset(struct ci13xxx *ci) +static int hw_usb_reset(struct ci_hdrc *ci) { hw_usb_set_address(ci, 0); @@ -368,11 +368,60 @@ static int hw_usb_reset(struct ci13xxx *ci) /****************************************************************************** * UTIL block *****************************************************************************/ + +static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq, + unsigned length) +{ + int i; + u32 temp; + struct td_node *lastnode, *node = kzalloc(sizeof(struct td_node), + GFP_ATOMIC); + + if (node == NULL) + return -ENOMEM; + + node->ptr = dma_pool_alloc(hwep->td_pool, GFP_ATOMIC, + &node->dma); + if (node->ptr == NULL) { + kfree(node); + return -ENOMEM; + } + + memset(node->ptr, 0, sizeof(struct ci_hw_td)); + node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES)); + node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES); + node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE); + + temp = (u32) (hwreq->req.dma + hwreq->req.actual); + if (length) { + node->ptr->page[0] = cpu_to_le32(temp); + for (i = 1; i < TD_PAGE_COUNT; i++) { + u32 page = temp + i * CI_HDRC_PAGE_SIZE; + page &= ~TD_RESERVED_MASK; + node->ptr->page[i] = cpu_to_le32(page); + } + } + + hwreq->req.actual += length; + + if (!list_empty(&hwreq->tds)) { + /* get the last entry */ + lastnode = list_entry(hwreq->tds.prev, + struct td_node, td); + lastnode->ptr->next = cpu_to_le32(node->dma); + } + + INIT_LIST_HEAD(&node->td); + list_add_tail(&node->td, &hwreq->tds); + + return 0; +} + /** * _usb_addr: calculates endpoint address from direction & number * @ep: endpoint */ -static inline u8 _usb_addr(struct ci13xxx_ep *ep) +static inline u8 _usb_addr(struct ci_hw_ep *ep) { return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; } @@ -380,75 +429,73 @@ static inline u8 _usb_addr(struct ci13xxx_ep *ep) /** * _hardware_queue: configures a request at hardware level * @gadget: gadget - * @mEp: endpoint + * @hwep: endpoint * * This function returns an error code */ -static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) +static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) { - struct ci13xxx *ci = mEp->ci; - unsigned i; + struct ci_hdrc *ci = hwep->ci; int ret = 0; - unsigned length = mReq->req.length; + unsigned rest = hwreq->req.length; + int pages = TD_PAGE_COUNT; + struct td_node *firstnode, *lastnode; /* don't queue twice */ - if (mReq->req.status == -EALREADY) + if (hwreq->req.status == -EALREADY) return -EALREADY; - mReq->req.status = -EALREADY; - - if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) { - mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC, - &mReq->zdma); - if (mReq->zptr == NULL) - return -ENOMEM; + hwreq->req.status = -EALREADY; - memset(mReq->zptr, 0, sizeof(*mReq->zptr)); - mReq->zptr->next = cpu_to_le32(TD_TERMINATE); - mReq->zptr->token = cpu_to_le32(TD_STATUS_ACTIVE); - if (!mReq->req.no_interrupt) - mReq->zptr->token |= cpu_to_le32(TD_IOC); - } - ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir); + ret = usb_gadget_map_request(&ci->gadget, &hwreq->req, hwep->dir); if (ret) return ret; /* - * TD configuration - * TODO - handle requests which spawns into several TDs + * The first buffer could be not page aligned. + * In that case we have to span into one extra td. */ - memset(mReq->ptr, 0, sizeof(*mReq->ptr)); - mReq->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES)); - mReq->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES); - mReq->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE); - if (mReq->zptr) { - mReq->ptr->next = cpu_to_le32(mReq->zdma); - } else { - mReq->ptr->next = cpu_to_le32(TD_TERMINATE); - if (!mReq->req.no_interrupt) - mReq->ptr->token |= cpu_to_le32(TD_IOC); - } - mReq->ptr->page[0] = cpu_to_le32(mReq->req.dma); - for (i = 1; i < TD_PAGE_COUNT; i++) { - u32 page = mReq->req.dma + i * CI13XXX_PAGE_SIZE; - page &= ~TD_RESERVED_MASK; - mReq->ptr->page[i] = cpu_to_le32(page); + if (hwreq->req.dma % PAGE_SIZE) + pages--; + + if (rest == 0) + add_td_to_list(hwep, hwreq, 0); + + while (rest > 0) { + unsigned count = min(hwreq->req.length - hwreq->req.actual, + (unsigned)(pages * CI_HDRC_PAGE_SIZE)); + add_td_to_list(hwep, hwreq, count); + rest -= count; } + if (hwreq->req.zero && hwreq->req.length + && (hwreq->req.length % hwep->ep.maxpacket == 0)) + add_td_to_list(hwep, hwreq, 0); + + firstnode = list_first_entry(&hwreq->tds, struct td_node, td); + + lastnode = list_entry(hwreq->tds.prev, + struct td_node, td); + + lastnode->ptr->next = cpu_to_le32(TD_TERMINATE); + if (!hwreq->req.no_interrupt) + lastnode->ptr->token |= cpu_to_le32(TD_IOC); wmb(); - if (!list_empty(&mEp->qh.queue)) { - struct ci13xxx_req *mReqPrev; - int n = hw_ep_bit(mEp->num, mEp->dir); + hwreq->req.actual = 0; + if (!list_empty(&hwep->qh.queue)) { + struct ci_hw_req *hwreqprev; + int n = hw_ep_bit(hwep->num, hwep->dir); int tmp_stat; - u32 next = mReq->dma & TD_ADDR_MASK; - - mReqPrev = list_entry(mEp->qh.queue.prev, - struct ci13xxx_req, queue); - if (mReqPrev->zptr) - mReqPrev->zptr->next = cpu_to_le32(next); - else - mReqPrev->ptr->next = cpu_to_le32(next); + struct td_node *prevlastnode; + u32 next = firstnode->dma & TD_ADDR_MASK; + + hwreqprev = list_entry(hwep->qh.queue.prev, + struct ci_hw_req, queue); + prevlastnode = list_entry(hwreqprev->tds.prev, + struct td_node, td); + + prevlastnode->ptr->next = cpu_to_le32(next); wmb(); if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) goto done; @@ -462,99 +509,152 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) } /* QH configuration */ - mEp->qh.ptr->td.next = cpu_to_le32(mReq->dma); /* TERMINATE = 0 */ - mEp->qh.ptr->td.token &= + hwep->qh.ptr->td.next = cpu_to_le32(firstnode->dma); + hwep->qh.ptr->td.token &= cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE)); + if (hwep->type == USB_ENDPOINT_XFER_ISOC) { + u32 mul = hwreq->req.length / hwep->ep.maxpacket; + + if (hwreq->req.length % hwep->ep.maxpacket) + mul++; + hwep->qh.ptr->cap |= mul << __ffs(QH_MULT); + } + wmb(); /* synchronize before ep prime */ - ret = hw_ep_prime(ci, mEp->num, mEp->dir, - mEp->type == USB_ENDPOINT_XFER_CONTROL); + ret = hw_ep_prime(ci, hwep->num, hwep->dir, + hwep->type == USB_ENDPOINT_XFER_CONTROL); done: return ret; } +/* + * free_pending_td: remove a pending request for the endpoint + * @hwep: endpoint + */ +static void free_pending_td(struct ci_hw_ep *hwep) +{ + struct td_node *pending = hwep->pending_td; + + dma_pool_free(hwep->td_pool, pending->ptr, pending->dma); + hwep->pending_td = NULL; + kfree(pending); +} + /** * _hardware_dequeue: handles a request at hardware level * @gadget: gadget - * @mEp: endpoint + * @hwep: endpoint * * This function returns an error code */ -static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) +static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) { - u32 tmptoken = le32_to_cpu(mReq->ptr->token); + u32 tmptoken; + struct td_node *node, *tmpnode; + unsigned remaining_length; + unsigned actual = hwreq->req.length; - if (mReq->req.status != -EALREADY) + if (hwreq->req.status != -EALREADY) return -EINVAL; - if ((TD_STATUS_ACTIVE & tmptoken) != 0) - return -EBUSY; + hwreq->req.status = 0; - if (mReq->zptr) { - if ((cpu_to_le32(TD_STATUS_ACTIVE) & mReq->zptr->token) != 0) + list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { + tmptoken = le32_to_cpu(node->ptr->token); + if ((TD_STATUS_ACTIVE & tmptoken) != 0) { + hwreq->req.status = -EALREADY; return -EBUSY; - dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma); - mReq->zptr = NULL; - } + } - mReq->req.status = 0; + remaining_length = (tmptoken & TD_TOTAL_BYTES); + remaining_length >>= __ffs(TD_TOTAL_BYTES); + actual -= remaining_length; + + hwreq->req.status = tmptoken & TD_STATUS; + if ((TD_STATUS_HALTED & hwreq->req.status)) { + hwreq->req.status = -EPIPE; + break; + } else if ((TD_STATUS_DT_ERR & hwreq->req.status)) { + hwreq->req.status = -EPROTO; + break; + } else if ((TD_STATUS_TR_ERR & hwreq->req.status)) { + hwreq->req.status = -EILSEQ; + break; + } - usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir); + if (remaining_length) { + if (hwep->dir) { + hwreq->req.status = -EPROTO; + break; + } + } + /* + * As the hardware could still address the freed td + * which will run the udc unusable, the cleanup of the + * td has to be delayed by one. + */ + if (hwep->pending_td) + free_pending_td(hwep); - mReq->req.status = tmptoken & TD_STATUS; - if ((TD_STATUS_HALTED & mReq->req.status) != 0) - mReq->req.status = -1; - else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0) - mReq->req.status = -1; - else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0) - mReq->req.status = -1; + hwep->pending_td = node; + list_del_init(&node->td); + } - mReq->req.actual = tmptoken & TD_TOTAL_BYTES; - mReq->req.actual >>= __ffs(TD_TOTAL_BYTES); - mReq->req.actual = mReq->req.length - mReq->req.actual; - mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual; + usb_gadget_unmap_request(&hwep->ci->gadget, &hwreq->req, hwep->dir); - return mReq->req.actual; + hwreq->req.actual += actual; + + if (hwreq->req.status) + return hwreq->req.status; + + return hwreq->req.actual; } /** * _ep_nuke: dequeues all endpoint requests - * @mEp: endpoint + * @hwep: endpoint * * This function returns an error code * Caller must hold lock */ -static int _ep_nuke(struct ci13xxx_ep *mEp) -__releases(mEp->lock) -__acquires(mEp->lock) +static int _ep_nuke(struct ci_hw_ep *hwep) +__releases(hwep->lock) +__acquires(hwep->lock) { - if (mEp == NULL) + struct td_node *node, *tmpnode; + if (hwep == NULL) return -EINVAL; - hw_ep_flush(mEp->ci, mEp->num, mEp->dir); + hw_ep_flush(hwep->ci, hwep->num, hwep->dir); - while (!list_empty(&mEp->qh.queue)) { + while (!list_empty(&hwep->qh.queue)) { /* pop oldest request */ - struct ci13xxx_req *mReq = \ - list_entry(mEp->qh.queue.next, - struct ci13xxx_req, queue); - - if (mReq->zptr) { - dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma); - mReq->zptr = NULL; + struct ci_hw_req *hwreq = list_entry(hwep->qh.queue.next, + struct ci_hw_req, queue); + + list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { + dma_pool_free(hwep->td_pool, node->ptr, node->dma); + list_del_init(&node->td); + node->ptr = NULL; + kfree(node); } - list_del_init(&mReq->queue); - mReq->req.status = -ESHUTDOWN; + list_del_init(&hwreq->queue); + hwreq->req.status = -ESHUTDOWN; - if (mReq->req.complete != NULL) { - spin_unlock(mEp->lock); - mReq->req.complete(&mEp->ep, &mReq->req); - spin_lock(mEp->lock); + if (hwreq->req.complete != NULL) { + spin_unlock(hwep->lock); + hwreq->req.complete(&hwep->ep, &hwreq->req); + spin_lock(hwep->lock); } } + + if (hwep->pending_td) + free_pending_td(hwep); + return 0; } @@ -567,7 +667,7 @@ __acquires(mEp->lock) static int _gadget_stop_activity(struct usb_gadget *gadget) { struct usb_ep *ep; - struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); + struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); unsigned long flags; spin_lock_irqsave(&ci->lock, flags); @@ -608,7 +708,7 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) * * This function resets USB engine after a bus reset occurred */ -static void isr_reset_handler(struct ci13xxx *ci) +static void isr_reset_handler(struct ci_hdrc *ci) __releases(ci->lock) __acquires(ci->lock) { @@ -658,47 +758,48 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) static int _ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t __maybe_unused gfp_flags) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); - struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); - struct ci13xxx *ci = mEp->ci; + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); + struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); + struct ci_hdrc *ci = hwep->ci; int retval = 0; - if (ep == NULL || req == NULL || mEp->ep.desc == NULL) + if (ep == NULL || req == NULL || hwep->ep.desc == NULL) return -EINVAL; - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { + if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { if (req->length) - mEp = (ci->ep0_dir == RX) ? + hwep = (ci->ep0_dir == RX) ? ci->ep0out : ci->ep0in; - if (!list_empty(&mEp->qh.queue)) { - _ep_nuke(mEp); + if (!list_empty(&hwep->qh.queue)) { + _ep_nuke(hwep); retval = -EOVERFLOW; - dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n", - _usb_addr(mEp)); + dev_warn(hwep->ci->dev, "endpoint ctrl %X nuked\n", + _usb_addr(hwep)); } } - /* first nuke then test link, e.g. previous status has not sent */ - if (!list_empty(&mReq->queue)) { - dev_err(mEp->ci->dev, "request already in queue\n"); - return -EBUSY; + if (usb_endpoint_xfer_isoc(hwep->ep.desc) && + hwreq->req.length > (1 + hwep->ep.mult) * hwep->ep.maxpacket) { + dev_err(hwep->ci->dev, "request length too big for isochronous\n"); + return -EMSGSIZE; } - if (req->length > (TD_PAGE_COUNT - 1) * CI13XXX_PAGE_SIZE) { - dev_err(mEp->ci->dev, "request bigger than one td\n"); - return -EMSGSIZE; + /* first nuke then test link, e.g. previous status has not sent */ + if (!list_empty(&hwreq->queue)) { + dev_err(hwep->ci->dev, "request already in queue\n"); + return -EBUSY; } /* push request */ - mReq->req.status = -EINPROGRESS; - mReq->req.actual = 0; + hwreq->req.status = -EINPROGRESS; + hwreq->req.actual = 0; - retval = _hardware_enqueue(mEp, mReq); + retval = _hardware_enqueue(hwep, hwreq); if (retval == -EALREADY) retval = 0; if (!retval) - list_add_tail(&mReq->queue, &mEp->qh.queue); + list_add_tail(&hwreq->queue, &hwep->qh.queue); return retval; } @@ -710,22 +811,22 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req, * * This function returns an error code */ -static int isr_get_status_response(struct ci13xxx *ci, +static int isr_get_status_response(struct ci_hdrc *ci, struct usb_ctrlrequest *setup) -__releases(mEp->lock) -__acquires(mEp->lock) +__releases(hwep->lock) +__acquires(hwep->lock) { - struct ci13xxx_ep *mEp = ci->ep0in; + struct ci_hw_ep *hwep = ci->ep0in; struct usb_request *req = NULL; gfp_t gfp_flags = GFP_ATOMIC; int dir, num, retval; - if (mEp == NULL || setup == NULL) + if (hwep == NULL || setup == NULL) return -EINVAL; - spin_unlock(mEp->lock); - req = usb_ep_alloc_request(&mEp->ep, gfp_flags); - spin_lock(mEp->lock); + spin_unlock(hwep->lock); + req = usb_ep_alloc_request(&hwep->ep, gfp_flags); + spin_lock(hwep->lock); if (req == NULL) return -ENOMEM; @@ -750,7 +851,7 @@ __acquires(mEp->lock) } /* else do nothing; reserved for future use */ - retval = _ep_queue(&mEp->ep, req, gfp_flags); + retval = _ep_queue(&hwep->ep, req, gfp_flags); if (retval) goto err_free_buf; @@ -759,9 +860,9 @@ __acquires(mEp->lock) err_free_buf: kfree(req->buf); err_free_req: - spin_unlock(mEp->lock); - usb_ep_free_request(&mEp->ep, req); - spin_lock(mEp->lock); + spin_unlock(hwep->lock); + usb_ep_free_request(&hwep->ep, req); + spin_lock(hwep->lock); return retval; } @@ -776,7 +877,7 @@ __acquires(mEp->lock) static void isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) { - struct ci13xxx *ci = req->context; + struct ci_hdrc *ci = req->context; unsigned long flags; if (ci->setaddr) { @@ -796,48 +897,48 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) * * This function returns an error code */ -static int isr_setup_status_phase(struct ci13xxx *ci) +static int isr_setup_status_phase(struct ci_hdrc *ci) { int retval; - struct ci13xxx_ep *mEp; + struct ci_hw_ep *hwep; - mEp = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; + hwep = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; ci->status->context = ci; ci->status->complete = isr_setup_status_complete; - retval = _ep_queue(&mEp->ep, ci->status, GFP_ATOMIC); + retval = _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC); return retval; } /** * isr_tr_complete_low: transaction complete low level handler - * @mEp: endpoint + * @hwep: endpoint * * This function returns an error code * Caller must hold lock */ -static int isr_tr_complete_low(struct ci13xxx_ep *mEp) -__releases(mEp->lock) -__acquires(mEp->lock) +static int isr_tr_complete_low(struct ci_hw_ep *hwep) +__releases(hwep->lock) +__acquires(hwep->lock) { - struct ci13xxx_req *mReq, *mReqTemp; - struct ci13xxx_ep *mEpTemp = mEp; + struct ci_hw_req *hwreq, *hwreqtemp; + struct ci_hw_ep *hweptemp = hwep; int retval = 0; - list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, + list_for_each_entry_safe(hwreq, hwreqtemp, &hwep->qh.queue, queue) { - retval = _hardware_dequeue(mEp, mReq); + retval = _hardware_dequeue(hwep, hwreq); if (retval < 0) break; - list_del_init(&mReq->queue); - if (mReq->req.complete != NULL) { - spin_unlock(mEp->lock); - if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) && - mReq->req.length) - mEpTemp = mEp->ci->ep0in; - mReq->req.complete(&mEpTemp->ep, &mReq->req); - spin_lock(mEp->lock); + list_del_init(&hwreq->queue); + if (hwreq->req.complete != NULL) { + spin_unlock(hwep->lock); + if ((hwep->type == USB_ENDPOINT_XFER_CONTROL) && + hwreq->req.length) + hweptemp = hwep->ci->ep0in; + hwreq->req.complete(&hweptemp->ep, &hwreq->req); + spin_lock(hwep->lock); } } @@ -853,7 +954,7 @@ __acquires(mEp->lock) * * This function handles traffic events */ -static void isr_tr_complete_handler(struct ci13xxx *ci) +static void isr_tr_complete_handler(struct ci_hdrc *ci) __releases(ci->lock) __acquires(ci->lock) { @@ -861,21 +962,21 @@ __acquires(ci->lock) u8 tmode = 0; for (i = 0; i < ci->hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; + struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; int type, num, dir, err = -EINVAL; struct usb_ctrlrequest req; - if (mEp->ep.desc == NULL) + if (hwep->ep.desc == NULL) continue; /* not configured */ if (hw_test_and_clear_complete(ci, i)) { - err = isr_tr_complete_low(mEp); - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { + err = isr_tr_complete_low(hwep); + if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { if (err > 0) /* needs status phase */ err = isr_setup_status_phase(ci); if (err < 0) { spin_unlock(&ci->lock); - if (usb_ep_set_halt(&mEp->ep)) + if (usb_ep_set_halt(&hwep->ep)) dev_err(ci->dev, "error: ep_set_halt\n"); spin_lock(&ci->lock); @@ -883,7 +984,7 @@ __acquires(ci->lock) } } - if (mEp->type != USB_ENDPOINT_XFER_CONTROL || + if (hwep->type != USB_ENDPOINT_XFER_CONTROL || !hw_test_and_clear_setup_status(ci, i)) continue; @@ -902,7 +1003,7 @@ __acquires(ci->lock) /* read_setup_packet */ do { hw_test_and_set_setup_guard(ci); - memcpy(&req, &mEp->qh.ptr->setup, sizeof(req)); + memcpy(&req, &hwep->qh.ptr->setup, sizeof(req)); } while (!hw_test_and_clear_setup_guard(ci)); type = req.bRequestType; @@ -921,10 +1022,10 @@ __acquires(ci->lock) num &= USB_ENDPOINT_NUMBER_MASK; if (dir) /* TX */ num += ci->hw_ep_max/2; - if (!ci->ci13xxx_ep[num].wedge) { + if (!ci->ci_hw_ep[num].wedge) { spin_unlock(&ci->lock); err = usb_ep_clear_halt( - &ci->ci13xxx_ep[num].ep); + &ci->ci_hw_ep[num].ep); spin_lock(&ci->lock); if (err) break; @@ -974,7 +1075,7 @@ __acquires(ci->lock) num += ci->hw_ep_max/2; spin_unlock(&ci->lock); - err = usb_ep_set_halt(&ci->ci13xxx_ep[num].ep); + err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); spin_lock(&ci->lock); if (!err) isr_setup_status_phase(ci); @@ -1021,7 +1122,7 @@ delegate: if (err < 0) { spin_unlock(&ci->lock); - if (usb_ep_set_halt(&mEp->ep)) + if (usb_ep_set_halt(&hwep->ep)) dev_err(ci->dev, "error: ep_set_halt\n"); spin_lock(&ci->lock); } @@ -1039,7 +1140,7 @@ delegate: static int ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); int retval = 0; unsigned long flags; u32 cap = 0; @@ -1047,39 +1148,41 @@ static int ep_enable(struct usb_ep *ep, if (ep == NULL || desc == NULL) return -EINVAL; - spin_lock_irqsave(mEp->lock, flags); + spin_lock_irqsave(hwep->lock, flags); /* only internal SW should enable ctrl endpts */ - mEp->ep.desc = desc; + hwep->ep.desc = desc; - if (!list_empty(&mEp->qh.queue)) - dev_warn(mEp->ci->dev, "enabling a non-empty endpoint!\n"); + if (!list_empty(&hwep->qh.queue)) + dev_warn(hwep->ci->dev, "enabling a non-empty endpoint!\n"); - mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX; - mEp->num = usb_endpoint_num(desc); - mEp->type = usb_endpoint_type(desc); + hwep->dir = usb_endpoint_dir_in(desc) ? TX : RX; + hwep->num = usb_endpoint_num(desc); + hwep->type = usb_endpoint_type(desc); - mEp->ep.maxpacket = usb_endpoint_maxp(desc); + hwep->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff; + hwep->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc)); - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) + if (hwep->type == USB_ENDPOINT_XFER_CONTROL) cap |= QH_IOS; - if (mEp->num) + if (hwep->num) cap |= QH_ZLT; - cap |= (mEp->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; + cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; - mEp->qh.ptr->cap = cpu_to_le32(cap); + hwep->qh.ptr->cap = cpu_to_le32(cap); - mEp->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ + hwep->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ /* * Enable endpoints in the HW other than ep0 as ep0 * is always enabled */ - if (mEp->num) - retval |= hw_ep_enable(mEp->ci, mEp->num, mEp->dir, mEp->type); + if (hwep->num) + retval |= hw_ep_enable(hwep->ci, hwep->num, hwep->dir, + hwep->type); - spin_unlock_irqrestore(mEp->lock, flags); + spin_unlock_irqrestore(hwep->lock, flags); return retval; } @@ -1090,32 +1193,32 @@ static int ep_enable(struct usb_ep *ep, */ static int ep_disable(struct usb_ep *ep) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); int direction, retval = 0; unsigned long flags; if (ep == NULL) return -EINVAL; - else if (mEp->ep.desc == NULL) + else if (hwep->ep.desc == NULL) return -EBUSY; - spin_lock_irqsave(mEp->lock, flags); + spin_lock_irqsave(hwep->lock, flags); /* only internal SW should disable ctrl endpts */ - direction = mEp->dir; + direction = hwep->dir; do { - retval |= _ep_nuke(mEp); - retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir); + retval |= _ep_nuke(hwep); + retval |= hw_ep_disable(hwep->ci, hwep->num, hwep->dir); - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->dir = (mEp->dir == TX) ? RX : TX; + if (hwep->type == USB_ENDPOINT_XFER_CONTROL) + hwep->dir = (hwep->dir == TX) ? RX : TX; - } while (mEp->dir != direction); + } while (hwep->dir != direction); - mEp->ep.desc = NULL; + hwep->ep.desc = NULL; - spin_unlock_irqrestore(mEp->lock, flags); + spin_unlock_irqrestore(hwep->lock, flags); return retval; } @@ -1126,25 +1229,18 @@ static int ep_disable(struct usb_ep *ep) */ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); - struct ci13xxx_req *mReq = NULL; + struct ci_hw_req *hwreq = NULL; if (ep == NULL) return NULL; - mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); - if (mReq != NULL) { - INIT_LIST_HEAD(&mReq->queue); - - mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags, - &mReq->dma); - if (mReq->ptr == NULL) { - kfree(mReq); - mReq = NULL; - } + hwreq = kzalloc(sizeof(struct ci_hw_req), gfp_flags); + if (hwreq != NULL) { + INIT_LIST_HEAD(&hwreq->queue); + INIT_LIST_HEAD(&hwreq->tds); } - return (mReq == NULL) ? NULL : &mReq->req; + return (hwreq == NULL) ? NULL : &hwreq->req; } /** @@ -1154,24 +1250,30 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) */ static void ep_free_request(struct usb_ep *ep, struct usb_request *req) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); - struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); + struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); + struct td_node *node, *tmpnode; unsigned long flags; if (ep == NULL || req == NULL) { return; - } else if (!list_empty(&mReq->queue)) { - dev_err(mEp->ci->dev, "freeing queued request\n"); + } else if (!list_empty(&hwreq->queue)) { + dev_err(hwep->ci->dev, "freeing queued request\n"); return; } - spin_lock_irqsave(mEp->lock, flags); + spin_lock_irqsave(hwep->lock, flags); - if (mReq->ptr) - dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma); - kfree(mReq); + list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { + dma_pool_free(hwep->td_pool, node->ptr, node->dma); + list_del_init(&node->td); + node->ptr = NULL; + kfree(node); + } + + kfree(hwreq); - spin_unlock_irqrestore(mEp->lock, flags); + spin_unlock_irqrestore(hwep->lock, flags); } /** @@ -1182,16 +1284,16 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req) static int ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t __maybe_unused gfp_flags) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); int retval = 0; unsigned long flags; - if (ep == NULL || req == NULL || mEp->ep.desc == NULL) + if (ep == NULL || req == NULL || hwep->ep.desc == NULL) return -EINVAL; - spin_lock_irqsave(mEp->lock, flags); + spin_lock_irqsave(hwep->lock, flags); retval = _ep_queue(ep, req, gfp_flags); - spin_unlock_irqrestore(mEp->lock, flags); + spin_unlock_irqrestore(hwep->lock, flags); return retval; } @@ -1202,33 +1304,33 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, */ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); - struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); + struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); unsigned long flags; - if (ep == NULL || req == NULL || mReq->req.status != -EALREADY || - mEp->ep.desc == NULL || list_empty(&mReq->queue) || - list_empty(&mEp->qh.queue)) + if (ep == NULL || req == NULL || hwreq->req.status != -EALREADY || + hwep->ep.desc == NULL || list_empty(&hwreq->queue) || + list_empty(&hwep->qh.queue)) return -EINVAL; - spin_lock_irqsave(mEp->lock, flags); + spin_lock_irqsave(hwep->lock, flags); - hw_ep_flush(mEp->ci, mEp->num, mEp->dir); + hw_ep_flush(hwep->ci, hwep->num, hwep->dir); /* pop request */ - list_del_init(&mReq->queue); + list_del_init(&hwreq->queue); - usb_gadget_unmap_request(&mEp->ci->gadget, req, mEp->dir); + usb_gadget_unmap_request(&hwep->ci->gadget, req, hwep->dir); req->status = -ECONNRESET; - if (mReq->req.complete != NULL) { - spin_unlock(mEp->lock); - mReq->req.complete(&mEp->ep, &mReq->req); - spin_lock(mEp->lock); + if (hwreq->req.complete != NULL) { + spin_unlock(hwep->lock); + hwreq->req.complete(&hwep->ep, &hwreq->req); + spin_lock(hwep->lock); } - spin_unlock_irqrestore(mEp->lock, flags); + spin_unlock_irqrestore(hwep->lock, flags); return 0; } @@ -1239,37 +1341,40 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) */ static int ep_set_halt(struct usb_ep *ep, int value) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); int direction, retval = 0; unsigned long flags; - if (ep == NULL || mEp->ep.desc == NULL) + if (ep == NULL || hwep->ep.desc == NULL) return -EINVAL; - spin_lock_irqsave(mEp->lock, flags); + if (usb_endpoint_xfer_isoc(hwep->ep.desc)) + return -EOPNOTSUPP; + + spin_lock_irqsave(hwep->lock, flags); #ifndef STALL_IN /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ - if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX && - !list_empty(&mEp->qh.queue)) { - spin_unlock_irqrestore(mEp->lock, flags); + if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX && + !list_empty(&hwep->qh.queue)) { + spin_unlock_irqrestore(hwep->lock, flags); return -EAGAIN; } #endif - direction = mEp->dir; + direction = hwep->dir; do { - retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value); + retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value); if (!value) - mEp->wedge = 0; + hwep->wedge = 0; - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->dir = (mEp->dir == TX) ? RX : TX; + if (hwep->type == USB_ENDPOINT_XFER_CONTROL) + hwep->dir = (hwep->dir == TX) ? RX : TX; - } while (mEp->dir != direction); + } while (hwep->dir != direction); - spin_unlock_irqrestore(mEp->lock, flags); + spin_unlock_irqrestore(hwep->lock, flags); return retval; } @@ -1280,15 +1385,15 @@ static int ep_set_halt(struct usb_ep *ep, int value) */ static int ep_set_wedge(struct usb_ep *ep) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); unsigned long flags; - if (ep == NULL || mEp->ep.desc == NULL) + if (ep == NULL || hwep->ep.desc == NULL) return -EINVAL; - spin_lock_irqsave(mEp->lock, flags); - mEp->wedge = 1; - spin_unlock_irqrestore(mEp->lock, flags); + spin_lock_irqsave(hwep->lock, flags); + hwep->wedge = 1; + spin_unlock_irqrestore(hwep->lock, flags); return usb_ep_set_halt(ep); } @@ -1300,19 +1405,19 @@ static int ep_set_wedge(struct usb_ep *ep) */ static void ep_fifo_flush(struct usb_ep *ep) { - struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); + struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); unsigned long flags; if (ep == NULL) { - dev_err(mEp->ci->dev, "%02X: -EINVAL\n", _usb_addr(mEp)); + dev_err(hwep->ci->dev, "%02X: -EINVAL\n", _usb_addr(hwep)); return; } - spin_lock_irqsave(mEp->lock, flags); + spin_lock_irqsave(hwep->lock, flags); - hw_ep_flush(mEp->ci, mEp->num, mEp->dir); + hw_ep_flush(hwep->ci, hwep->num, hwep->dir); - spin_unlock_irqrestore(mEp->lock, flags); + spin_unlock_irqrestore(hwep->lock, flags); } /** @@ -1334,13 +1439,13 @@ static const struct usb_ep_ops usb_ep_ops = { /****************************************************************************** * GADGET block *****************************************************************************/ -static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) +static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) { - struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); unsigned long flags; int gadget_ready = 0; - if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS)) + if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS)) return -EOPNOTSUPP; spin_lock_irqsave(&ci->lock, flags); @@ -1358,7 +1463,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) hw_device_state(ci, 0); if (ci->platdata->notify_event) ci->platdata->notify_event(ci, - CI13XXX_CONTROLLER_STOPPED_EVENT); + CI_HDRC_CONTROLLER_STOPPED_EVENT); _gadget_stop_activity(&ci->gadget); pm_runtime_put_sync(&_gadget->dev); } @@ -1367,9 +1472,9 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) return 0; } -static int ci13xxx_wakeup(struct usb_gadget *_gadget) +static int ci_udc_wakeup(struct usb_gadget *_gadget) { - struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); unsigned long flags; int ret = 0; @@ -1388,21 +1493,21 @@ out: return ret; } -static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) +static int ci_udc_vbus_draw(struct usb_gadget *_gadget, unsigned ma) { - struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); if (ci->transceiver) - return usb_phy_set_power(ci->transceiver, mA); + return usb_phy_set_power(ci->transceiver, ma); return -ENOTSUPP; } /* Change Data+ pullup status * this func is used by usb_gadget_connect/disconnet */ -static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) +static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) { - struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); if (is_on) hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); @@ -1412,9 +1517,9 @@ static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) return 0; } -static int ci13xxx_start(struct usb_gadget *gadget, +static int ci_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); -static int ci13xxx_stop(struct usb_gadget *gadget, +static int ci_udc_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver); /** * Device operations part of the API to the USB controller hardware, @@ -1422,46 +1527,46 @@ static int ci13xxx_stop(struct usb_gadget *gadget, * Check "usb_gadget.h" for details */ static const struct usb_gadget_ops usb_gadget_ops = { - .vbus_session = ci13xxx_vbus_session, - .wakeup = ci13xxx_wakeup, - .pullup = ci13xxx_pullup, - .vbus_draw = ci13xxx_vbus_draw, - .udc_start = ci13xxx_start, - .udc_stop = ci13xxx_stop, + .vbus_session = ci_udc_vbus_session, + .wakeup = ci_udc_wakeup, + .pullup = ci_udc_pullup, + .vbus_draw = ci_udc_vbus_draw, + .udc_start = ci_udc_start, + .udc_stop = ci_udc_stop, }; -static int init_eps(struct ci13xxx *ci) +static int init_eps(struct ci_hdrc *ci) { int retval = 0, i, j; for (i = 0; i < ci->hw_ep_max/2; i++) for (j = RX; j <= TX; j++) { int k = i + j * ci->hw_ep_max/2; - struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[k]; + struct ci_hw_ep *hwep = &ci->ci_hw_ep[k]; - scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i, + scnprintf(hwep->name, sizeof(hwep->name), "ep%i%s", i, (j == TX) ? "in" : "out"); - mEp->ci = ci; - mEp->lock = &ci->lock; - mEp->td_pool = ci->td_pool; + hwep->ci = ci; + hwep->lock = &ci->lock; + hwep->td_pool = ci->td_pool; - mEp->ep.name = mEp->name; - mEp->ep.ops = &usb_ep_ops; + hwep->ep.name = hwep->name; + hwep->ep.ops = &usb_ep_ops; /* * for ep0: maxP defined in desc, for other * eps, maxP is set by epautoconfig() called * by gadget layer */ - mEp->ep.maxpacket = (unsigned short)~0; + hwep->ep.maxpacket = (unsigned short)~0; - INIT_LIST_HEAD(&mEp->qh.queue); - mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, - &mEp->qh.dma); - if (mEp->qh.ptr == NULL) + INIT_LIST_HEAD(&hwep->qh.queue); + hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, + &hwep->qh.dma); + if (hwep->qh.ptr == NULL) retval = -ENOMEM; else - memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr)); + memset(hwep->qh.ptr, 0, sizeof(*hwep->qh.ptr)); /* * set up shorthands for ep0 out and in endpoints, @@ -1469,42 +1574,42 @@ static int init_eps(struct ci13xxx *ci) */ if (i == 0) { if (j == RX) - ci->ep0out = mEp; + ci->ep0out = hwep; else - ci->ep0in = mEp; + ci->ep0in = hwep; - mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; + hwep->ep.maxpacket = CTRL_PAYLOAD_MAX; continue; } - list_add_tail(&mEp->ep.ep_list, &ci->gadget.ep_list); + list_add_tail(&hwep->ep.ep_list, &ci->gadget.ep_list); } return retval; } -static void destroy_eps(struct ci13xxx *ci) +static void destroy_eps(struct ci_hdrc *ci) { int i; for (i = 0; i < ci->hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; + struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; - dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); + dma_pool_free(ci->qh_pool, hwep->qh.ptr, hwep->qh.dma); } } /** - * ci13xxx_start: register a gadget driver + * ci_udc_start: register a gadget driver * @gadget: our gadget * @driver: the driver being registered * * Interrupts are enabled here. */ -static int ci13xxx_start(struct usb_gadget *gadget, +static int ci_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { - struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); + struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); unsigned long flags; int retval = -ENOMEM; @@ -1525,9 +1630,9 @@ static int ci13xxx_start(struct usb_gadget *gadget, ci->driver = driver; pm_runtime_get_sync(&ci->gadget.dev); - if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { + if (ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) { if (ci->vbus_active) { - if (ci->platdata->flags & CI13XXX_REGS_SHARED) + if (ci->platdata->flags & CI_HDRC_REGS_SHARED) hw_device_reset(ci, USBMODE_CM_DC); } else { pm_runtime_put_sync(&ci->gadget.dev); @@ -1545,22 +1650,22 @@ static int ci13xxx_start(struct usb_gadget *gadget, } /** - * ci13xxx_stop: unregister a gadget driver + * ci_udc_stop: unregister a gadget driver */ -static int ci13xxx_stop(struct usb_gadget *gadget, +static int ci_udc_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { - struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); + struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); unsigned long flags; spin_lock_irqsave(&ci->lock, flags); - if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) || + if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) || ci->vbus_active) { hw_device_state(ci, 0); if (ci->platdata->notify_event) ci->platdata->notify_event(ci, - CI13XXX_CONTROLLER_STOPPED_EVENT); + CI_HDRC_CONTROLLER_STOPPED_EVENT); ci->driver = NULL; spin_unlock_irqrestore(&ci->lock, flags); _gadget_stop_activity(&ci->gadget); @@ -1582,7 +1687,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget, * This function returns IRQ_HANDLED if the IRQ has been handled * It locks access to registers */ -static irqreturn_t udc_irq(struct ci13xxx *ci) +static irqreturn_t udc_irq(struct ci_hdrc *ci) { irqreturn_t retval; u32 intr; @@ -1592,7 +1697,7 @@ static irqreturn_t udc_irq(struct ci13xxx *ci) spin_lock(&ci->lock); - if (ci->platdata->flags & CI13XXX_REGS_SHARED) { + if (ci->platdata->flags & CI_HDRC_REGS_SHARED) { if (hw_read(ci, OP_USBMODE, USBMODE_CM) != USBMODE_CM_DC) { spin_unlock(&ci->lock); @@ -1642,7 +1747,7 @@ static irqreturn_t udc_irq(struct ci13xxx *ci) * udc_start: initialize gadget role * @ci: chipidea controller */ -static int udc_start(struct ci13xxx *ci) +static int udc_start(struct ci_hdrc *ci) { struct device *dev = ci->dev; int retval = 0; @@ -1658,15 +1763,15 @@ static int udc_start(struct ci13xxx *ci) INIT_LIST_HEAD(&ci->gadget.ep_list); /* alloc resources */ - ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, - sizeof(struct ci13xxx_qh), - 64, CI13XXX_PAGE_SIZE); + ci->qh_pool = dma_pool_create("ci_hw_qh", dev, + sizeof(struct ci_hw_qh), + 64, CI_HDRC_PAGE_SIZE); if (ci->qh_pool == NULL) return -ENOMEM; - ci->td_pool = dma_pool_create("ci13xxx_td", dev, - sizeof(struct ci13xxx_td), - 64, CI13XXX_PAGE_SIZE); + ci->td_pool = dma_pool_create("ci_hw_td", dev, + sizeof(struct ci_hw_td), + 64, CI_HDRC_PAGE_SIZE); if (ci->td_pool == NULL) { retval = -ENOMEM; goto free_qh_pool; @@ -1684,14 +1789,14 @@ static int udc_start(struct ci13xxx *ci) ci->transceiver = NULL; } - if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { + if (ci->platdata->flags & CI_HDRC_REQUIRE_TRANSCEIVER) { if (ci->transceiver == NULL) { retval = -ENODEV; goto destroy_eps; } } - if (!(ci->platdata->flags & CI13XXX_REGS_SHARED)) { + if (!(ci->platdata->flags & CI_HDRC_REGS_SHARED)) { retval = hw_device_reset(ci, USBMODE_CM_DC); if (retval) goto put_transceiver; @@ -1738,7 +1843,7 @@ free_qh_pool: * * No interrupts active, the IRQ has been released */ -static void udc_stop(struct ci13xxx *ci) +static void udc_stop(struct ci_hdrc *ci) { if (ci == NULL) return; @@ -1765,7 +1870,7 @@ static void udc_stop(struct ci13xxx *ci) * * This function enables the gadget role, if the device is "device capable". */ -int ci_hdrc_gadget_init(struct ci13xxx *ci) +int ci_hdrc_gadget_init(struct ci_hdrc *ci) { struct ci_role_driver *rdrv; diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h index d12e8b59b11..455ac216922 100644 --- a/drivers/usb/chipidea/udc.h +++ b/drivers/usb/chipidea/udc.h @@ -20,7 +20,7 @@ #define TX 1 /* similar to USB_DIR_IN but can be used as an index */ /* DMA layout of transfer descriptors */ -struct ci13xxx_td { +struct ci_hw_td { /* 0 */ u32 next; #define TD_TERMINATE BIT(0) @@ -43,24 +43,31 @@ struct ci13xxx_td { } __attribute__ ((packed, aligned(4))); /* DMA layout of queue heads */ -struct ci13xxx_qh { +struct ci_hw_qh { /* 0 */ u32 cap; #define QH_IOS BIT(15) #define QH_MAX_PKT (0x07FFUL << 16) #define QH_ZLT BIT(29) #define QH_MULT (0x0003UL << 30) +#define QH_ISO_MULT(x) ((x >> 11) & 0x03) /* 1 */ u32 curr; /* 2 - 8 */ - struct ci13xxx_td td; + struct ci_hw_td td; /* 9 */ u32 RESERVED; struct usb_ctrlrequest setup; } __attribute__ ((packed, aligned(4))); +struct td_node { + struct list_head td; + dma_addr_t dma; + struct ci_hw_td *ptr; +}; + /** - * struct ci13xxx_req - usb request representation + * struct ci_hw_req - usb request representation * @req: request structure for gadget drivers * @queue: link to QH list * @ptr: transfer descriptor for this request @@ -68,22 +75,19 @@ struct ci13xxx_qh { * @zptr: transfer descriptor for the zero packet * @zdma: dma address of the zero packet's transfer descriptor */ -struct ci13xxx_req { +struct ci_hw_req { struct usb_request req; struct list_head queue; - struct ci13xxx_td *ptr; - dma_addr_t dma; - struct ci13xxx_td *zptr; - dma_addr_t zdma; + struct list_head tds; }; #ifdef CONFIG_USB_CHIPIDEA_UDC -int ci_hdrc_gadget_init(struct ci13xxx *ci); +int ci_hdrc_gadget_init(struct ci_hdrc *ci); #else -static inline int ci_hdrc_gadget_init(struct ci13xxx *ci) +static inline int ci_hdrc_gadget_init(struct ci_hdrc *ci) { return -ENXIO; } diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 714a6bd810e..ac5a4615520 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -16,7 +16,7 @@ #include <linux/io.h> #include <linux/delay.h> -#include "ci13xxx_imx.h" +#include "ci_hdrc_imx.h" #define USB_DEV_MAX 4 @@ -175,6 +175,7 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); static int usbmisc_imx_probe(struct platform_device *pdev) { @@ -243,17 +244,7 @@ static struct platform_driver usbmisc_imx_driver = { }, }; -int usbmisc_imx_drv_init(void) -{ - return platform_driver_register(&usbmisc_imx_driver); -} -subsys_initcall(usbmisc_imx_drv_init); - -void usbmisc_imx_drv_exit(void) -{ - platform_driver_unregister(&usbmisc_imx_driver); -} -module_exit(usbmisc_imx_drv_exit); +module_platform_driver(usbmisc_imx_driver); MODULE_ALIAS("platform:usbmisc-imx"); MODULE_LICENSE("GPL v2"); |