diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2010-05-12 23:12:41 +0000 |
---|---|---|
committer | Lars-Peter Clausen <lars@metafoo.de> | 2010-05-12 23:12:41 +0000 |
commit | b2d6bdcdda588c94900827362a6ad325ff804721 (patch) | |
tree | 402c05359e50ec9e57f35311ae676c231145df39 /target/linux/xburst/patches-2.6.34/055-ohci.patch | |
parent | d17202487530955337093ebd8110279d5c21f2f9 (diff) | |
download | upstream-b2d6bdcdda588c94900827362a6ad325ff804721.tar.gz upstream-b2d6bdcdda588c94900827362a6ad325ff804721.tar.bz2 upstream-b2d6bdcdda588c94900827362a6ad325ff804721.zip |
[xburst] Add 2.6.34 patches
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@21438 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/xburst/patches-2.6.34/055-ohci.patch')
-rw-r--r-- | target/linux/xburst/patches-2.6.34/055-ohci.patch | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/target/linux/xburst/patches-2.6.34/055-ohci.patch b/target/linux/xburst/patches-2.6.34/055-ohci.patch new file mode 100644 index 0000000000..09c0bbb8d0 --- /dev/null +++ b/target/linux/xburst/patches-2.6.34/055-ohci.patch @@ -0,0 +1,313 @@ +From 633d5f445a0149ae32e814f794eae04ae2571c42 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen <lars@metafoo.de> +Date: Sat, 24 Apr 2010 17:18:49 +0200 +Subject: [PATCH] Add jz4740 ohci driver + +--- + drivers/usb/Kconfig | 1 + + drivers/usb/host/ohci-hcd.c | 5 + + drivers/usb/host/ohci-jz4740.c | 264 ++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 270 insertions(+), 0 deletions(-) + create mode 100644 drivers/usb/host/ohci-jz4740.c + +diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig +index 6a58cb1..46b8dc6 100644 +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -46,6 +46,7 @@ config USB_ARCH_HAS_OHCI + default y if PPC_MPC52xx + # MIPS: + default y if SOC_AU1X00 ++ default y if SOC_JZ4740 + # SH: + default y if CPU_SUBTYPE_SH7720 + default y if CPU_SUBTYPE_SH7721 +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index afe59be..d4ec333 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -1090,6 +1090,11 @@ MODULE_LICENSE ("GPL"); + #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver + #endif + ++#ifdef CONFIG_SOC_JZ4740 ++#include "ohci-jz4740.c" ++#define PLATFORM_DRIVER ohci_hcd_jz4740_driver ++#endif ++ + #if !defined(PCI_DRIVER) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(OF_PLATFORM_DRIVER) && \ +diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c +new file mode 100644 +index 0000000..ac190b4 +--- /dev/null ++++ b/drivers/usb/host/ohci-jz4740.c +@@ -0,0 +1,264 @@ ++ ++#include <linux/platform_device.h> ++#include <linux/clk.h> ++#include <linux/regulator/consumer.h> ++ ++struct jz4740_ohci_hcd { ++ struct ohci_hcd ohci_hcd; ++ ++ struct regulator *vbus; ++ bool vbus_enabled; ++ struct clk *clk; ++}; ++ ++static inline struct jz4740_ohci_hcd *hcd_to_jz4740_hcd(struct usb_hcd *hcd) ++{ ++ return (struct jz4740_ohci_hcd *)(hcd->hcd_priv); ++} ++ ++static inline struct usb_hcd *jz4740_hcd_to_hcd(struct jz4740_ohci_hcd *jz4740_ohci) ++{ ++ return container_of ((void *) jz4740_ohci, struct usb_hcd, hcd_priv); ++} ++ ++ ++static int ohci_jz4740_start(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ int ret; ++ ++ ret = ohci_init(ohci); ++ if (ret < 0) ++ return ret; ++ ++ ohci->num_ports = 1; ++ ++ ret = ohci_run(ohci); ++ if (ret < 0) { ++ dev_err(hcd->self.controller, "Can not start %s", ++ hcd->self.bus_name); ++ ohci_stop(hcd); ++ return ret; ++ } ++ return 0; ++} ++ ++static int ohci_jz4740_set_vbus_power(struct jz4740_ohci_hcd *jz4740_ohci, ++ bool enabled) ++{ ++ int ret = 0; ++ ++ if (enabled && !jz4740_ohci->vbus_enabled) { ++ ret = regulator_enable(jz4740_ohci->vbus); ++ if (ret) ++ dev_err(jz4740_hcd_to_hcd(jz4740_ohci)->self.controller, ++ "Could not power vbus\n"); ++ } else if(!enabled && jz4740_ohci->vbus_enabled) { ++ ret = regulator_disable(jz4740_ohci->vbus); ++ } ++ ++ if (ret == 0) ++ jz4740_ohci->vbus_enabled = enabled; ++ ++ return ret; ++} ++ ++static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ++ u16 wIndex, char *buf, u16 wLength) ++{ ++ struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); ++ int ret; ++ ++ if (jz4740_ohci->vbus) { ++ switch (typeReq) { ++ case SetHubFeature: ++ if (wValue == USB_PORT_FEAT_POWER) ++ ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true); ++ break; ++ case ClearHubFeature: ++ if (wValue == USB_PORT_FEAT_POWER) ++ ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false); ++ break; ++ } ++ } ++ ++ if (ret) ++ return ret; ++ ++ return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); ++} ++ ++ ++static const struct hc_driver ohci_jz4740_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "JZ4740 OHCI", ++ .hcd_priv_size = sizeof(struct jz4740_ohci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ohci_irq, ++ .flags = HCD_USB11 | HCD_MEMORY, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .start = ohci_jz4740_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_jz4740_hub_control, ++#ifdef CONFIG_PM ++ .bus_suspend = ohci_bus_suspend, ++ .bus_resume = ohci_bus_resume, ++#endif ++ .start_port_reset = ohci_start_port_reset, ++}; ++ ++ ++static __devinit int jz4740_ohci_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct usb_hcd *hcd; ++ struct jz4740_ohci_hcd *jz4740_ohci; ++ struct resource *res; ++ int irq; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ if (!res) { ++ dev_err(&pdev->dev, "Failed to get platform resource\n"); ++ return -ENOENT; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "Failed to get platform irq\n"); ++ return irq; ++ } ++ ++ hcd = usb_create_hcd(&ohci_jz4740_hc_driver, &pdev->dev, "jz4740"); ++ if (!hcd) { ++ dev_err(&pdev->dev, "Failed to create hcd.\n"); ++ return -ENOMEM; ++ } ++ ++ jz4740_ohci = hcd_to_jz4740_hcd(hcd); ++ ++ res = request_mem_region(res->start, resource_size(res), hcd_name); ++ ++ if (!res) { ++ dev_err(&pdev->dev, "Failed to request mem region.\n"); ++ ret = -EBUSY; ++ goto err_free; ++ } ++ ++ hcd->rsrc_start = res->start; ++ hcd->rsrc_len = resource_size(res); ++ hcd->regs = ioremap(res->start, resource_size(res)); ++ ++ if (!hcd->regs) { ++ dev_err(&pdev->dev, "Failed to ioremap registers.\n"); ++ ret = -EBUSY; ++ goto err_release_mem; ++ } ++ ++ jz4740_ohci->clk = clk_get(&pdev->dev, "uhc"); ++ if (IS_ERR(jz4740_ohci->clk)) { ++ ret = PTR_ERR(jz4740_ohci->clk); ++ dev_err(&pdev->dev, "Failed to get clock: %d\n", ret); ++ goto err_iounmap; ++ } ++ ++ jz4740_ohci->vbus = regulator_get(&pdev->dev, "vbus"); ++ if (IS_ERR(jz4740_ohci->vbus)) ++ jz4740_ohci->vbus = NULL; ++ ++ ++ clk_set_rate(jz4740_ohci->clk, 48000000); ++ clk_enable(jz4740_ohci->clk); ++ if (jz4740_ohci->vbus) ++ ohci_jz4740_set_vbus_power(jz4740_ohci, true); ++ ++ platform_set_drvdata(pdev, hcd); ++ ++ ohci_hcd_init(hcd_to_ohci(hcd)); ++ ++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret); ++ goto err_disable; ++ } ++ ++ return 0; ++ ++err_disable: ++ platform_set_drvdata(pdev, NULL); ++ if (jz4740_ohci->vbus) { ++ regulator_disable(jz4740_ohci->vbus); ++ regulator_put(jz4740_ohci->vbus); ++ } ++ clk_disable(jz4740_ohci->clk); ++ ++ clk_put(jz4740_ohci->clk); ++err_iounmap: ++ iounmap(hcd->regs); ++err_release_mem: ++ release_mem_region(res->start, resource_size(res)); ++err_free: ++ usb_put_hcd(hcd); ++ ++ return ret; ++} ++ ++static __devexit int jz4740_ohci_remove(struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(pdev); ++ struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); ++ ++ usb_remove_hcd(hcd); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (jz4740_ohci->vbus) { ++ regulator_disable(jz4740_ohci->vbus); ++ regulator_put(jz4740_ohci->vbus); ++ } ++ ++ clk_disable(jz4740_ohci->clk); ++ clk_put(jz4740_ohci->clk); ++ ++ iounmap(hcd->regs); ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ ++ usb_put_hcd(hcd); ++ ++ return 0; ++} ++ ++static struct platform_driver ohci_hcd_jz4740_driver = { ++ .probe = jz4740_ohci_probe, ++ .remove = __devexit_p(jz4740_ohci_remove), ++ .driver = { ++ .name = "jz4740-ohci", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_ALIAS("platfrom:jz4740-ohci"); +-- +1.5.6.5 + |