[PATCH 1/3] usb: chipidea: add CSR SiRFSoC ci13xxx usb driver
Felipe Balbi
balbi at ti.com
Tue Jun 11 21:19:33 EDT 2013
On Sun, Jun 09, 2013 at 11:25:36AM +0800, Barry Song wrote:
> From: Rong Wang <Rong.Wang at csr.com>
>
> 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 <marex at denx.de>
> Cc: Richard Zhao <richard.zhao at freescale.com>
> Signed-off-by: Rong Wang <Rong.Wang at csr.com>
> Signed-off-by: Barry Song <Baohua.Song at csr.com>
> ---
> 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<Rong.Wang at csr.com>
> + *
> + * 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130612/0fae6d4c/attachment.sig>
More information about the linux-arm-kernel
mailing list