On Sun, Jun 09, 2013 at 11:25:36AM +0800, Barry Song wrote: > From: Rong Wang <[email protected]> > > CSR SiRF SoCs licensed chipidea ci13xxx USB IP, this patch > makes the chipidea drivers support CSR SiRF SoCS. > > It also changes the Kconfig, only compile MSM and IMX if related > drivers are enabled. Otherwise, we always need to enable all > clients of chipidea drivers. > > Cc: Marek Vasut <[email protected]> > Cc: Richard Zhao <[email protected]> > Signed-off-by: Rong Wang <[email protected]> > Signed-off-by: Barry Song <[email protected]> > --- > drivers/usb/Kconfig | 1 + > drivers/usb/chipidea/Kconfig | 25 ++++ > drivers/usb/chipidea/Makefile | 5 +- > drivers/usb/chipidea/ci13xxx_sirf.c | 223 > +++++++++++++++++++++++++++++++++++ > 4 files changed, 252 insertions(+), 2 deletions(-) > create mode 100644 drivers/usb/chipidea/ci13xxx_sirf.c > > diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig > index 92e1dc9..9cbe1e0 100644 > --- a/drivers/usb/Kconfig > +++ b/drivers/usb/Kconfig > @@ -49,6 +49,7 @@ config USB_ARCH_HAS_EHCI > default y if ARCH_MMP > default y if MACH_LOONGSON1 > default y if PLAT_ORION > + default y if ARCH_SIRF > default PCI > > # some non-PCI HCDs implement xHCI > diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig > index b2df442..847b9f7 100644 > --- a/drivers/usb/chipidea/Kconfig > +++ b/drivers/usb/chipidea/Kconfig > @@ -31,4 +31,29 @@ config USB_CHIPIDEA_DEBUG > help > Say Y here to enable debugging output of the ChipIdea driver. > > +if USB_CHIPIDEA_UDC && USB_CHIPIDEA_HOST > + > +config USB_CHIPIDEA_SIRF > + depends on ARCH_SIRF > + bool "SiRF USB controller ChipIdea driver binding" > + default y > + help > + Say Y here to enable sirf usb ChipIdea driver binding. > + > +config USB_CHIPIDEA_MSM > + depends on ARCH_MSM > + bool "MSM USB controller ChipIdea driver binding" > + default y > + help > + Say Y here to enable msm usb ChipIdea driver binding. > + > +config USB_CHIPIDEA_IMX > + depends on ARCH_MXC || ARCH_MXS > + bool "i.MX USB controller ChipIdea driver binding" > + default y > + help > + Say Y here to enable imx usb ChipIdea driver binding. > + > +endif > + > endif > diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile > index 4ab83e9..7004fde 100644 > --- a/drivers/usb/chipidea/Makefile > +++ b/drivers/usb/chipidea/Makefile > @@ -9,7 +9,7 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o > > # Glue/Bridge layers go here > > -obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o > +obj-$(CONFIG_USB_CHIPIDEA_MSM) += ci13xxx_msm.o > > # PCI doesn't provide stubs, need to check > ifneq ($(CONFIG_PCI),) > @@ -17,5 +17,6 @@ ifneq ($(CONFIG_PCI),) > endif > > ifneq ($(CONFIG_OF_DEVICE),) > - obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx.o > + obj-$(CONFIG_USB_CHIPIDEA_IMX) += ci13xxx_imx.o usbmisc_imx.o > + obj-$(CONFIG_USB_CHIPIDEA_SIRF) += ci13xxx_sirf.o > endif > diff --git a/drivers/usb/chipidea/ci13xxx_sirf.c > b/drivers/usb/chipidea/ci13xxx_sirf.c > new file mode 100644 > index 0000000..1d84a2f > --- /dev/null > +++ b/drivers/usb/chipidea/ci13xxx_sirf.c > @@ -0,0 +1,223 @@ > +/* > + * USB Controller Driver for CSR SiRF SoC > + * > + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group > company. > + * Rong Wang<[email protected]> > + * > + * Licensed under GPLv2 or later. > + */ > +#include <linux/module.h> > +#include <linux/io.h> > +#include <linux/bitops.h> > +#include <linux/platform_device.h> > +#include <linux/pm_runtime.h> > +#include <linux/of.h> > +#include <linux/of_gpio.h> > +#include <linux/of_address.h> > +#include <linux/of_platform.h> > +#include <linux/clk.h> > +#include <linux/dma-mapping.h> > +#include <linux/delay.h> > +#include <linux/reset.h> > + > +#include <linux/usb/chipidea.h> > +#include "ci.h" > + > +#define RSC_USB_UART_SHARE 0x0 > +#define USB1_MODE_SEL BIT(2) > +#define pdev_to_phy(pdev) ((struct usb_phy *)platform_get_drvdata(pdev))
sorry, no go. This is not the right way to handle USB PHYs.
> +static int sirfsoc_vbus_gpio;
this should be removed too, add it as a member of ci13xx_sirf_data.
> +struct ci13xxx_sirf_data {
> + struct platform_device *ci_pdev;
most likely you don't need the platform_device, you need the struct
device only.
> + struct clk *clk;
> +};
> +
> +static inline int ci13xxx_sirf_drive_vbus(int value)
NACK, you should pass your ci13xx_sirf_data as argument here.
> +{
> + return gpio_direction_output(sirfsoc_vbus_gpio, value ? 0 : 1);
> +}
> +
> +static void ci13xxx_sirf_notify_event(struct ci13xxx *ci, unsigned event)
> +{
> + switch (event) {
> + case CI13XXX_CONTROLLER_RESET_EVENT:
> + ci13xxx_sirf_drive_vbus(1);
> + break;
> + case CI13XXX_CONTROLLER_STOPPED_EVENT:
> + ci13xxx_sirf_drive_vbus(0);
> + break;
> + default:
> + dev_info(ci->dev, "Unknown Event\n");
> + break;
> + }
> +}
> +
> +static struct ci13xxx_platform_data ci13xxx_sirf_platdata = {
> + .name = "ci13xxx_sirf",
> + .flags = CI13XXX_DISABLE_STREAMING,
> + .capoffset = DEF_CAPOFFSET,
> + .notify_event = ci13xxx_sirf_notify_event,
> +};
> +
> +static struct of_device_id rsc_ids[] = {
> + { .compatible = "sirf,prima2-rsc", },
> + { /* sentinel */ }
> +};
> +
> +static int ci13xxx_sirf_probe(struct platform_device *pdev)
> +{
> + struct platform_device *plat_ci, *phy_pdev;
> + struct device_node *rsc_np, *phy_np;
> + struct ci13xxx_sirf_data *data;
> + struct usb_phy *phy;
> + void __iomem *rsc_vbase;
> + int ret;
> +
> + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> + if (!data) {
> + dev_err(&pdev->dev, "Failed to allocate ci13xxx_sirf_data!\n");
> + return -ENOMEM;
> + }
> +
> + /* 1. set usb controller clock */
> + data->clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(data->clk)) {
> + dev_err(&pdev->dev,
> + "Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
> + return PTR_ERR(data->clk);
> + }
> + ret = clk_prepare_enable(data->clk);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "Failed to prepare or enable clock, err=%d\n", ret);
> + return ret;
> + }
> +
> + /* 2. software reset */
> + ret = device_reset(&pdev->dev);
> + if (ret)
> + dev_info(&pdev->dev,
> + "Failed to reset device, err=%d\n", ret);
> +
> + /* 3. vbus configuration */
> + sirfsoc_vbus_gpio = of_get_named_gpio(pdev->dev.of_node,
> + "vbus-gpios", 0);
> + if (sirfsoc_vbus_gpio < 0) {
> + dev_err(&pdev->dev, "Can't get vbus gpio from DT\n");
> + ret = -ENODEV;
> + goto err;
> + }
> + ret = gpio_request(sirfsoc_vbus_gpio, "ci13xxx_sirf");
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to get gpio control\n");
> + goto err;
> + }
> +
> + /* 4. rsc control */
> + rsc_np = of_find_matching_node(NULL, rsc_ids);
> + if (!rsc_np) {
> + dev_err(&pdev->dev, "Failed to get rsc device node\n");
> + ret = -ENODEV;
> + goto err;
> + }
> + rsc_vbase = of_iomap(rsc_np, 0);
> + if (!rsc_vbase) {
> + dev_err(&pdev->dev, "Failed to iomap rsc memory\n");
> + ret = -ENOMEM;
> + goto err;
> + }
> + writel(readl(rsc_vbase + RSC_USB_UART_SHARE) | USB1_MODE_SEL,
> + rsc_vbase + RSC_USB_UART_SHARE);
> +
> + /* 5. set device dma mask */
> + if (!pdev->dev.dma_mask) {
> + pdev->dev.dma_mask = devm_kzalloc(&pdev->dev,
> + sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
> + if (!pdev->dev.dma_mask) {
> + dev_err(&pdev->dev, "Failed to alloc dma_mask!\n");
> + ret = -ENOMEM;
> + goto err;
> + }
> + *pdev->dev.dma_mask = DMA_BIT_MASK(32);
> + dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask);
> + }
> +
> + /* 6. get phy for controller */
> + phy_np = of_parse_phandle(pdev->dev.of_node, "sirf,ci13xxx-usbphy", 0);
> + if (!phy_np) {
> + dev_err(&pdev->dev, "Failed to get phy device node\n");
> + ret = -ENODEV;
> + goto err;
> + }
> + phy_pdev = of_find_device_by_node(phy_np);
> + if (!phy_pdev) {
> + dev_err(&pdev->dev, "Failed to get phy platform device\n");
> + ret = -ENODEV;
> + goto err;
> + }
> + phy = pdev_to_phy(phy_pdev);
> + if (!phy || !try_module_get(phy_pdev->dev.driver->owner)) {
> + dev_err(&pdev->dev, "Failed to get phy control\n");
> + ret = -ENODEV;
> + goto err;
> + }
> + usb_phy_init(phy);
> + ci13xxx_sirf_platdata.phy = phy;
> +
> + /* 7. register to ci13xxx core */
> + plat_ci = ci13xxx_add_device(&pdev->dev,
> + pdev->resource, pdev->num_resources,
> + &ci13xxx_sirf_platdata);
> + if (IS_ERR(plat_ci)) {
> + dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
> + return PTR_ERR(plat_ci);
> + }
> +
> + platform_set_drvdata(pdev, plat_ci);
> +
> + pm_runtime_no_callbacks(&pdev->dev);
> + pm_runtime_enable(&pdev->dev);
> +
> + dev_info(&pdev->dev, "Ready\n");
remove this dev_info()
--
balbi
signature.asc
Description: Digital signature
