From 490e5e3c95d8c88b9de5b15265f77c65d87187ac Mon Sep 17 00:00:00 2001 From: wlf Date: Tue, 11 Mar 2014 14:35:51 +0800 Subject: [PATCH] USB: renamed usb files: ehci-rk.c -> ehci-rockchip.c, ohci-rk.c -> ohci-rockchip.c --- drivers/usb/host/ehci-hcd.c | 16 +- drivers/usb/host/ehci-rkhsic.c | 2 +- drivers/usb/host/ehci-rockchip.c | 369 +++++++++++++++++++++++++++++++ drivers/usb/host/ohci-hcd.c | 2 +- drivers/usb/host/ohci-rockchip.c | 258 +++++++++++++++++++++ 5 files changed, 637 insertions(+), 10 deletions(-) create mode 100755 drivers/usb/host/ehci-rockchip.c create mode 100755 drivers/usb/host/ohci-rockchip.c diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 16068290a74f..aac3985819e8 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1262,13 +1262,13 @@ MODULE_LICENSE ("GPL"); #endif #ifdef CONFIG_USB_EHCI_RK -#include "ehci-rk.c" +#include "ehci-rockchip.c" #define PLATFORM_DRIVER ehci_rk_driver #endif #ifdef CONFIG_USB_EHCI_RKHSIC #include "ehci-rkhsic.c" -#define RK_PLATFORM_DRIVER ehci_rkhsic_driver +#define ROCKCHIP_PLATFORM_DRIVER ehci_rkhsic_driver #endif #ifdef CONFIG_USB_EHCI_HCD_PMC_MSP @@ -1347,15 +1347,15 @@ static int __init ehci_hcd_init(void) goto clean4; #endif -#ifdef RK_PLATFORM_DRIVER - retval = platform_driver_register(&RK_PLATFORM_DRIVER); +#ifdef ROCKCHIP_PLATFORM_DRIVER + retval = platform_driver_register(&ROCKCHIP_PLATFORM_DRIVER); if (retval < 0) goto clean5; #endif return retval; -#ifdef RK_PLATFORM_DRIVER - platform_driver_unregister(&RK_PLATFORM_DRIVER); +#ifdef ROCKCHIP_PLATFORM_DRIVER + platform_driver_unregister(&ROCKCHIP_PLATFORM_DRIVER); clean5: #endif @@ -1387,8 +1387,8 @@ module_init(ehci_hcd_init); static void __exit ehci_hcd_cleanup(void) { -#ifdef RK_PLATFORM_DRIVER - platform_driver_unregister(&RK_PLATFORM_DRIVER); +#ifdef ROCKCHIP_PLATFORM_DRIVER + platform_driver_unregister(&ROCKCHIP_PLATFORM_DRIVER); #endif #ifdef XILINX_OF_PLATFORM_DRIVER platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); diff --git a/drivers/usb/host/ehci-rkhsic.c b/drivers/usb/host/ehci-rkhsic.c index 7bfcade0fca1..480afa7e1ced 100755 --- a/drivers/usb/host/ehci-rkhsic.c +++ b/drivers/usb/host/ehci-rkhsic.c @@ -382,7 +382,7 @@ static struct platform_driver ehci_rkhsic_driver = { .probe = ehci_rkhsic_probe, .remove = ehci_rkhsic_remove, .driver = { - .name = "rk_hsic_host", + .name = "rockchip_hsic_host", .of_match_table = of_match_ptr(rk_hsic_of_match), #ifdef CONFIG_PM .pm = &ehci_rkhsic_dev_pm_ops, diff --git a/drivers/usb/host/ehci-rockchip.c b/drivers/usb/host/ehci-rockchip.c new file mode 100755 index 000000000000..91be75a3d5b5 --- /dev/null +++ b/drivers/usb/host/ehci-rockchip.c @@ -0,0 +1,369 @@ +/* + * EHCI-compliant USB host controller driver for Rockchip SoCs + * + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2009 - 2013 NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +# include +# include +# include +# include +# include +# include +# include "ehci.h" +#ifdef CONFIG_DWC_OTG_274 +# include "../dwc_otg/usbdev_rk.h" +#endif +#ifdef CONFIG_DWC_OTG_310 +# include "../dwc_otg_310/usbdev_rk.h" +#endif + +static int rkehci_status = 1; +static struct ehci_hcd *g_ehci; +#define EHCI_PRINT(x...) printk( KERN_INFO "EHCI: " x ) + +static struct rkehci_pdata_id rkehci_pdata[] = { + { + .name = "rk3188-reserved", + .pdata = NULL, + }, + { + .name = "rk3288-ehci", + .pdata = &rkehci_pdata_rk3288, + }, + { }, +}; + +static void ehci_port_power (struct ehci_hcd *ehci, int is_on) +{ + unsigned port; + + if (!HCS_PPC (ehci->hcs_params)) + return; + + ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down"); + for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) + (void) ehci_hub_control(ehci_to_hcd(ehci), + is_on ? SetPortFeature : ClearPortFeature, + USB_PORT_FEAT_POWER, + port--, NULL, 0); + /* Flush those writes */ + ehci_readl(ehci, &ehci->regs->command); + msleep(20); +} + +static struct hc_driver rk_ehci_hc_driver = { + .description = hcd_name, + .product_desc = "Rockchip On-Chip EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_USB2 | HCD_MEMORY, + + .reset = ehci_init, + .start = ehci_run, + + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + .endpoint_reset = ehci_endpoint_reset, + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, + + /* + * PM support + */ +#ifdef CONFIG_PM + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, +#endif +}; +static ssize_t ehci_power_show( struct device *_dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", rkehci_status); +} +static ssize_t ehci_power_store( struct device *_dev, + struct device_attribute *attr, + const char *buf, size_t count ) +{ + uint32_t val = simple_strtoul(buf, NULL, 16); + struct usb_hcd *hcd = dev_get_drvdata(_dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct rkehci_platform_data *pldata = _dev->platform_data; + + printk("%s: %d setting to: %d\n", __func__, rkehci_status, val); + if(val == rkehci_status) + goto out; + + rkehci_status = val; + switch(val){ + case 0: //power down + ehci_port_power(ehci, 0); + msleep(5); + usb_remove_hcd(hcd); + break; + case 1:// power on + pldata->soft_reset(); + usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED); + ehci_port_power(ehci, 1); + writel_relaxed(0x1d4d ,hcd->regs +0x90); + writel_relaxed(0x4 ,hcd->regs +0xa0); + dsb(); + break; + default: + break; + } +out: + return count; +} +static DEVICE_ATTR(ehci_power, S_IRUGO|S_IWUSR, ehci_power_show, ehci_power_store); +static ssize_t debug_show( struct device *_dev, + struct device_attribute *attr, char *buf) +{ + volatile uint32_t *addr; + + EHCI_PRINT("******** EHCI Capability Registers **********\n"); + addr = &g_ehci->caps->hc_capbase; + EHCI_PRINT("HCIVERSION / CAPLENGTH @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->caps->hcs_params; + EHCI_PRINT("HCSPARAMS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->caps->hcc_params; + EHCI_PRINT("HCCPARAMS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + EHCI_PRINT("********* EHCI Operational Registers *********\n"); + addr = &g_ehci->regs->command; + EHCI_PRINT("USBCMD @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->regs->status; + EHCI_PRINT("USBSTS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->regs->intr_enable; + EHCI_PRINT("USBINTR @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->regs->frame_index; + EHCI_PRINT("FRINDEX @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->regs->segment; + EHCI_PRINT("CTRLDSSEGMENT @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->regs->frame_list; + EHCI_PRINT("PERIODICLISTBASE @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->regs->async_next; + EHCI_PRINT("ASYNCLISTADDR @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = &g_ehci->regs->configured_flag; + EHCI_PRINT("CONFIGFLAG @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + addr = g_ehci->regs->port_status; + EHCI_PRINT("PORTSC @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); + return sprintf(buf, "EHCI Registers Dump\n"); +} +static DEVICE_ATTR(debug_ehci, S_IRUGO, debug_show, NULL); + +static struct of_device_id rk_ehci_of_match[] = { + { + .compatible = "rockchip,rk3288_rk_ehci_host", + .data = &rkehci_pdata[RK3288_USB_CTLR], + }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk_ehci_of_match); + +static int ehci_rk_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + struct resource *res; + struct device *dev = &pdev->dev; + struct rkehci_platform_data *pldata; + int ret; + int retval = 0; + static u64 usb_dmamask = 0xffffffffUL; + struct device_node *node = pdev->dev.of_node; + struct rkehci_pdata_id *p; + const struct of_device_id *match = + of_match_device(of_match_ptr( rk_ehci_of_match ), &pdev->dev); + + dev_dbg(&pdev->dev, "ehci_rk proble\n"); + + if (match){ + p = (struct rkehci_pdata_id *)match->data; + }else{ + dev_err(dev, "ehci_rk match failed\n"); + return -EINVAL; + } + + dev->platform_data = p->pdata; + pldata = dev->platform_data; + pldata->dev = dev; + + if (!node) { + dev_err(dev, "device node not found\n"); + return -EINVAL; + } + + dev->dma_mask = &usb_dmamask; + + retval = device_create_file(dev, &dev_attr_ehci_power); + retval = device_create_file(dev, &dev_attr_debug_ehci); + hcd = usb_create_hcd(&rk_ehci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); + if (!hcd) { + dev_err(&pdev->dev, "Unable to create HCD\n"); + return -ENOMEM; + } + + if(pldata->hw_init) + pldata->hw_init(); + + if(pldata->clock_init){ + pldata->clock_init(pldata); + pldata->clock_enable(pldata, 1); + } + + if(pldata->soft_reset) + pldata->soft_reset(); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Unable to get memory resource\n"); + ret = -ENODEV; + goto put_hcd; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->regs = devm_ioremap_resource(dev, res); + + if (!hcd->regs) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENOMEM; + goto put_hcd; + } + + hcd->irq = platform_get_irq(pdev, 0); + if (hcd->irq < 0) { + dev_err(&pdev->dev, "Unable to get IRQ resource\n"); + ret = hcd->irq; + goto put_hcd; + } + + ehci = hcd_to_ehci(hcd); + ehci->caps = hcd->regs; + ehci->regs = hcd->regs + 0x10; + printk("%s %p %p\n", __func__, ehci->caps, ehci->regs); + + dbg_hcs_params(ehci, "reset"); + dbg_hcc_params(ehci, "reset"); + + ehci->hcs_params = readl(&ehci->caps->hcs_params); + + ret = usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED); + if (ret) { + dev_err(&pdev->dev, "Failed to add USB HCD\n"); + goto put_hcd; + } + + g_ehci = ehci; + ehci_port_power(ehci, 1); + writel_relaxed(0x1d4d ,hcd->regs +0x90); + writel_relaxed(0x4 ,hcd->regs +0xa0); + dsb(); + + printk("%s ok\n", __func__); + + return 0; + +put_hcd: + if(pldata->clock_enable) + pldata->clock_enable(pldata, 0); + usb_put_hcd(hcd); + + return ret; +} +static int ehci_rk_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_put_hcd(hcd); + + return 0; +} +#ifdef CONFIG_PM +static int ehci_rk_pm_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + bool wakeup = device_may_wakeup(dev); + + dev_dbg(dev, "ehci-rockchip PM suspend\n"); + + /* + * EHCI helper function has also the same check before manipulating + * port wakeup flags. We do check here the same condition before + * calling the same helper function to avoid bringing hardware + * from Low power mode when there is no need for adjusting port + * wakeup flags. + */ + if (hcd->self.root_hub->do_remote_wakeup && !wakeup) { + pm_runtime_resume(dev); + ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), + wakeup); + } + + return 0; +} + +static int ehci_rk_pm_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + + dev_dbg(dev, "ehci-rockchip PM resume\n"); + ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); + + return 0; +} +#else +#define ehci_rk_pm_suspend NULL +#define ehci_rk_pm_resume NULL +#endif + +static const struct dev_pm_ops ehci_rk_dev_pm_ops = { + .suspend = ehci_rk_pm_suspend, + .resume = ehci_rk_pm_resume, +}; + +static struct platform_driver ehci_rk_driver = { + .probe = ehci_rk_probe, + .remove = ehci_rk_remove, + .driver = { + .name = "rockchip_ehci_host", + .of_match_table = of_match_ptr(rk_ehci_of_match), +#ifdef CONFIG_PM + .pm = &ehci_rk_dev_pm_ops, +#endif + }, +}; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index e0880a185cea..1412f71a9ec4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1192,7 +1192,7 @@ MODULE_LICENSE ("GPL"); #endif #ifdef CONFIG_USB_OHCI_HCD_RK -#include "ohci-rk.c" +#include "ohci-rockchip.c" #define PLATFORM_DRIVER ohci_hcd_rk_driver #endif diff --git a/drivers/usb/host/ohci-rockchip.c b/drivers/usb/host/ohci-rockchip.c new file mode 100755 index 000000000000..49d4789090fc --- /dev/null +++ b/drivers/usb/host/ohci-rockchip.c @@ -0,0 +1,258 @@ +/* + * ROCKCHIP USB HOST OHCI Controller + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_DWC_OTG_274 +# include "../dwc_otg/usbdev_rk.h" +#endif +#ifdef CONFIG_DWC_OTG_310 +# include "../dwc_otg_310/usbdev_rk.h" +#endif + +static struct rkehci_pdata_id rkohci_pdata[] = { + { + .name = "rk3188-reserved", + .pdata = NULL, + }, + { + .name = "rk3288-ohci", + .pdata = &rkohci_pdata_rk3288, + }, + { }, +}; + +static int ohci_rk_init(struct usb_hcd *hcd) +{ + dev_dbg(hcd->self.controller, "starting OHCI controller\n"); + + return ohci_init(hcd_to_ohci(hcd)); +} + +static int ohci_rk_start(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; + + /* + * RemoteWakeupConnected has to be set explicitly before + * calling ohci_run. The reset value of RWC is 0. + */ + ohci->hc_control = OHCI_CTRL_RWC; + writel(OHCI_CTRL_RWC, &ohci->regs->control); + + ret = ohci_run(ohci); + + if (ret < 0) { + dev_err(hcd->self.controller, "can't start\n"); + ohci_stop(hcd); + } + + return ret; +} + +static const struct hc_driver ohci_rk_hc_driver = { + .description = hcd_name, + .product_desc = "RK OHCI Host Controller", + .hcd_priv_size = sizeof(struct ohci_hcd), + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .reset = ohci_rk_init, + .start = ohci_rk_start, + .stop = ohci_stop, + .shutdown = ohci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, +}; + +static struct of_device_id rk_ohci_of_match[] = { + { + .compatible = "rockchip,rk3288_rk_ohci_host", + .data = &rkohci_pdata[RK3288_USB_CTLR], + }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk_ohci_of_match); + +/* ohci_hcd_rk_probe - initialize RK-based HCDs + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + */ +static int ohci_hcd_rk_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_hcd *hcd = NULL; + void __iomem *regs = NULL; + struct resource *res; + int ret = -ENODEV; + int irq; + struct rkehci_platform_data *pldata; + struct device_node *node = pdev->dev.of_node; + struct rkehci_pdata_id *p; + const struct of_device_id *match = + of_match_device(of_match_ptr( rk_ohci_of_match ), &pdev->dev); + + dev_dbg(&pdev->dev, "ohci_hcd_rk_probe\n"); + + if (usb_disabled()) + return -ENODEV; + + if (match){ + p = (struct rkehci_pdata_id *)match->data; + }else{ + dev_err(dev, "ohci_rk match failed\n"); + return -EINVAL; + } + + dev->platform_data = p->pdata; + pldata = dev->platform_data; + pldata->dev = dev; + + if (!node) { + dev_err(dev, "device node not found\n"); + return -EINVAL; + } + + if(pldata->hw_init) + pldata->hw_init(); + + if(pldata->clock_init){ + pldata->clock_init(pldata); + pldata->clock_enable(pldata, 1); + } + + if(pldata->soft_reset) + pldata->soft_reset(); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "OHCI irq failed\n"); + ret = irq; + goto clk_disable; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "UHH OHCI get resource failed\n"); + ret = -ENOMEM; + goto clk_disable; + } + + regs = devm_ioremap_resource(dev, res); + if (!regs) { + dev_err(dev, "UHH OHCI ioremap failed\n"); + ret = -ENOMEM; + goto clk_disable; + } + + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!dev->dma_mask) + dev->dma_mask = &dev->coherent_dma_mask; + if (!dev->coherent_dma_mask) + dev->coherent_dma_mask = DMA_BIT_MASK(32); + + hcd = usb_create_hcd(&ohci_rk_hc_driver, dev, + dev_name(dev)); + if (!hcd) { + dev_err(dev, "usb_create_hcd failed\n"); + ret = -ENOMEM; + goto clk_disable; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->regs = regs; + + ohci_hcd_init(hcd_to_ohci(hcd)); + + ret = usb_add_hcd(hcd, irq, 0); + if (ret) { + dev_dbg(dev, "failed to add hcd with err %d\n", ret); + goto err_add_hcd; + } + + return 0; + +err_add_hcd: + usb_put_hcd(hcd); + +clk_disable: + if(pldata->clock_enable) + pldata->clock_enable(pldata, 0); + + return ret; +} + +static int ohci_hcd_rk_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_remove_hcd(hcd); + usb_put_hcd(hcd); + return 0; +} + +static void ohci_hcd_rk_shutdown(struct platform_device *pdev) +{ + struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); + + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); +} + +static struct platform_driver ohci_hcd_rk_driver = { + .probe = ohci_hcd_rk_probe, + .remove = ohci_hcd_rk_remove, + .shutdown = ohci_hcd_rk_shutdown, + .driver = { + .name = "ohci-rockchip", + .of_match_table = of_match_ptr(rk_ohci_of_match), + }, +}; +MODULE_ALIAS("platform:rockchip-ohci"); -- 2.34.1