diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 21:24:55 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 21:24:55 +0300 |
commit | e29876723f7cb7728f0d6a674d23f92673e9f112 (patch) | |
tree | ea1da8bf77139f6cc6de029988208a7eddaf2002 /arch/mips/cavium-octeon | |
parent | 8c988ae787af4900bec5410658e8a82844185c85 (diff) | |
parent | 4d4bac4499e9955521af80198063ef9c2f2bd634 (diff) | |
download | linux-e29876723f7cb7728f0d6a674d23f92673e9f112.tar.xz |
Merge tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg KH:
"Here's the big pull request for the USB driver tree for 3.20-rc1.
Nothing major happening here, just lots of gadget driver updates, new
device ids, and a bunch of cleanups.
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (299 commits)
usb: musb: fix device hotplug behind hub
usb: dwc2: Fix a bug in reading the endpoint directions from reg.
staging: emxx_udc: fix the build error
usb: Retry port status check on resume to work around RH bugs
Revert "usb: Reset USB-3 devices on USB-3 link bounce"
uhci-hub: use HUB_CHAR_*
usb: kconfig: replace PPC_OF with PPC
ehci-pci: disable for Intel MID platforms (update)
usb: gadget: Kconfig: use bool instead of boolean
usb: musb: blackfin: remove incorrect __exit_p()
USB: fix use-after-free bug in usb_hcd_unlink_urb()
ehci-pci: disable for Intel MID platforms
usb: host: pci_quirks: joing string literals
USB: add flag for HCDs that can't receive wakeup requests (isp1760-hcd)
USB: usbfs: allow URBs to be reaped after disconnection
cdc-acm: kill unnecessary messages
cdc-acm: add sanity checks
usb: phy: phy-generic: Fix USB PHY gpio reset
usb: dwc2: fix USB core dependencies
usb: renesas_usbhs: fix NULL pointer dereference in dma_release_channel()
...
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r-- | arch/mips/cavium-octeon/octeon-platform.c | 152 |
1 files changed, 63 insertions, 89 deletions
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index b67ddf0f8bcd..12410a2788d8 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -77,7 +77,7 @@ static DEFINE_MUTEX(octeon2_usb_clocks_mutex); static int octeon2_usb_clock_start_cnt; -static void octeon2_usb_clocks_start(void) +static void octeon2_usb_clocks_start(struct device *dev) { u64 div; union cvmx_uctlx_if_ena if_ena; @@ -86,6 +86,8 @@ static void octeon2_usb_clocks_start(void) union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; int i; unsigned long io_clk_64_to_ns; + u32 clock_rate = 12000000; + bool is_crystal_clock = false; mutex_lock(&octeon2_usb_clocks_mutex); @@ -96,6 +98,28 @@ static void octeon2_usb_clocks_start(void) io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); + if (dev->of_node) { + struct device_node *uctl_node; + const char *clock_type; + + uctl_node = of_get_parent(dev->of_node); + if (!uctl_node) { + dev_err(dev, "No UCTL device node\n"); + goto exit; + } + i = of_property_read_u32(uctl_node, + "refclk-frequency", &clock_rate); + if (i) { + dev_err(dev, "No UCTL \"refclk-frequency\"\n"); + goto exit; + } + i = of_property_read_string(uctl_node, + "refclk-type", &clock_type); + + if (!i && strcmp("crystal", clock_type) == 0) + is_crystal_clock = true; + } + /* * Step 1: Wait for voltages stable. That surely happened * before starting the kernel. @@ -126,9 +150,22 @@ static void octeon2_usb_clocks_start(void) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); /* 3b */ - /* 12MHz crystal. */ - clk_rst_ctl.s.p_refclk_sel = 0; - clk_rst_ctl.s.p_refclk_div = 0; + clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1; + switch (clock_rate) { + default: + pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n", + clock_rate); + /* Fall through */ + case 12000000: + clk_rst_ctl.s.p_refclk_div = 0; + break; + case 24000000: + clk_rst_ctl.s.p_refclk_div = 1; + break; + case 48000000: + clk_rst_ctl.s.p_refclk_div = 2; + break; + } cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); /* 3c */ @@ -259,7 +296,7 @@ static void octeon2_usb_clocks_stop(void) static int octeon_ehci_power_on(struct platform_device *pdev) { - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(&pdev->dev); return 0; } @@ -273,15 +310,16 @@ static struct usb_ehci_pdata octeon_ehci_pdata = { #ifdef __BIG_ENDIAN .big_endian_mmio = 1, #endif + .dma_mask_64 = 1, .power_on = octeon_ehci_power_on, .power_off = octeon_ehci_power_off, }; -static void __init octeon_ehci_hw_start(void) +static void __init octeon_ehci_hw_start(struct device *dev) { union cvmx_uctlx_ehci_ctl ehci_ctl; - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(dev); ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0)); /* Use 64-bit addressing. */ @@ -294,64 +332,30 @@ static void __init octeon_ehci_hw_start(void) octeon2_usb_clocks_stop(); } -static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64); - static int __init octeon_ehci_device_init(void) { struct platform_device *pd; + struct device_node *ehci_node; int ret = 0; - struct resource usb_resources[] = { - { - .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, - } - }; - - /* Only Octeon2 has ehci/ohci */ - if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) + ehci_node = of_find_node_by_name(NULL, "ehci"); + if (!ehci_node) return 0; - if (octeon_is_simulation() || usb_disabled()) - return 0; /* No USB in the simulator. */ - - pd = platform_device_alloc("ehci-platform", 0); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - usb_resources[0].start = 0x00016F0000000000ULL; - usb_resources[0].end = usb_resources[0].start + 0x100; - - usb_resources[1].start = OCTEON_IRQ_USB0; - usb_resources[1].end = OCTEON_IRQ_USB0; - - ret = platform_device_add_resources(pd, usb_resources, - ARRAY_SIZE(usb_resources)); - if (ret) - goto fail; + pd = of_find_device_by_node(ehci_node); + if (!pd) + return 0; - pd->dev.dma_mask = &octeon_ehci_dma_mask; pd->dev.platform_data = &octeon_ehci_pdata; - octeon_ehci_hw_start(); + octeon_ehci_hw_start(&pd->dev); - ret = platform_device_add(pd); - if (ret) - goto fail; - - return ret; -fail: - platform_device_put(pd); -out: return ret; } device_initcall(octeon_ehci_device_init); static int octeon_ohci_power_on(struct platform_device *pdev) { - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(&pdev->dev); return 0; } @@ -369,11 +373,11 @@ static struct usb_ohci_pdata octeon_ohci_pdata = { .power_off = octeon_ohci_power_off, }; -static void __init octeon_ohci_hw_start(void) +static void __init octeon_ohci_hw_start(struct device *dev) { union cvmx_uctlx_ohci_ctl ohci_ctl; - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(dev); ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0)); ohci_ctl.s.l2c_addr_msb = 0; @@ -387,57 +391,27 @@ static void __init octeon_ohci_hw_start(void) static int __init octeon_ohci_device_init(void) { struct platform_device *pd; + struct device_node *ohci_node; int ret = 0; - struct resource usb_resources[] = { - { - .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, - } - }; - - /* Only Octeon2 has ehci/ohci */ - if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) + ohci_node = of_find_node_by_name(NULL, "ohci"); + if (!ohci_node) return 0; - if (octeon_is_simulation() || usb_disabled()) - return 0; /* No USB in the simulator. */ - - pd = platform_device_alloc("ohci-platform", 0); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - usb_resources[0].start = 0x00016F0000000400ULL; - usb_resources[0].end = usb_resources[0].start + 0x100; - - usb_resources[1].start = OCTEON_IRQ_USB0; - usb_resources[1].end = OCTEON_IRQ_USB0; - - ret = platform_device_add_resources(pd, usb_resources, - ARRAY_SIZE(usb_resources)); - if (ret) - goto fail; + pd = of_find_device_by_node(ohci_node); + if (!pd) + return 0; pd->dev.platform_data = &octeon_ohci_pdata; - octeon_ohci_hw_start(); - - ret = platform_device_add(pd); - if (ret) - goto fail; + octeon_ohci_hw_start(&pd->dev); return ret; -fail: - platform_device_put(pd); -out: - return ret; } device_initcall(octeon_ohci_device_init); #endif /* CONFIG_USB */ + static struct of_device_id __initdata octeon_ids[] = { { .compatible = "simple-bus", }, { .compatible = "cavium,octeon-6335-uctl", }, |