Commit a95cfa6b authored by Andreas Herrmann's avatar Andreas Herrmann Committed by Greg Kroah-Hartman

USB: host: Remove hard-coded octeon platform information for ehci/ohci

Instead rely on device tree information for ehci and ohci.

This was suggested with
http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=1401358203-60225-4-git-send-email-alex.smith%40imgtec.com

  "The device tree will *always* have correct ehci/ohci clock
  configuration, so use it.  This allows us to remove a big chunk of
  platform configuration code from octeon-platform.c."

More or less I rebased that patch on Alan's work to remove ehci-octeon
and ohci-octeon drivers.

Cc: David Daney <david.daney@cavium.com>
Cc: Alex Smith <alex.smith@imgtec.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarAndreas Herrmann <andreas.herrmann@caviumnetworks.com>
Acked-by: default avatarRalf Baechle <ralf@linux-mips.org>
Tested-by: default avatarAaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 314b41b1
...@@ -77,7 +77,7 @@ static DEFINE_MUTEX(octeon2_usb_clocks_mutex); ...@@ -77,7 +77,7 @@ static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
static int octeon2_usb_clock_start_cnt; 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; u64 div;
union cvmx_uctlx_if_ena if_ena; union cvmx_uctlx_if_ena if_ena;
...@@ -86,6 +86,8 @@ static void octeon2_usb_clocks_start(void) ...@@ -86,6 +86,8 @@ static void octeon2_usb_clocks_start(void)
union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
int i; int i;
unsigned long io_clk_64_to_ns; unsigned long io_clk_64_to_ns;
u32 clock_rate = 12000000;
bool is_crystal_clock = false;
mutex_lock(&octeon2_usb_clocks_mutex); mutex_lock(&octeon2_usb_clocks_mutex);
...@@ -96,6 +98,28 @@ static void octeon2_usb_clocks_start(void) ...@@ -96,6 +98,28 @@ static void octeon2_usb_clocks_start(void)
io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); 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 * Step 1: Wait for voltages stable. That surely happened
* before starting the kernel. * before starting the kernel.
...@@ -126,9 +150,22 @@ static void octeon2_usb_clocks_start(void) ...@@ -126,9 +150,22 @@ static void octeon2_usb_clocks_start(void)
cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
/* 3b */ /* 3b */
/* 12MHz crystal. */ clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1;
clk_rst_ctl.s.p_refclk_sel = 0; switch (clock_rate) {
clk_rst_ctl.s.p_refclk_div = 0; 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); cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
/* 3c */ /* 3c */
...@@ -259,7 +296,7 @@ static void octeon2_usb_clocks_stop(void) ...@@ -259,7 +296,7 @@ static void octeon2_usb_clocks_stop(void)
static int octeon_ehci_power_on(struct platform_device *pdev) static int octeon_ehci_power_on(struct platform_device *pdev)
{ {
octeon2_usb_clocks_start(); octeon2_usb_clocks_start(&pdev->dev);
return 0; return 0;
} }
...@@ -277,11 +314,11 @@ static struct usb_ehci_pdata octeon_ehci_pdata = { ...@@ -277,11 +314,11 @@ static struct usb_ehci_pdata octeon_ehci_pdata = {
.power_off = octeon_ehci_power_off, .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; 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)); ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
/* Use 64-bit addressing. */ /* Use 64-bit addressing. */
...@@ -299,59 +336,28 @@ static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64); ...@@ -299,59 +336,28 @@ static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64);
static int __init octeon_ehci_device_init(void) static int __init octeon_ehci_device_init(void)
{ {
struct platform_device *pd; struct platform_device *pd;
struct device_node *ehci_node;
int ret = 0; int ret = 0;
struct resource usb_resources[] = { ehci_node = of_find_node_by_name(NULL, "ehci");
{ if (!ehci_node)
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_IRQ,
}
};
/* Only Octeon2 has ehci/ohci */
if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
return 0; return 0;
if (octeon_is_simulation() || usb_disabled()) pd = of_find_device_by_node(ehci_node);
return 0; /* No USB in the simulator. */ if (!pd)
return 0;
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->dev.dma_mask = &octeon_ehci_dma_mask; pd->dev.dma_mask = &octeon_ehci_dma_mask;
pd->dev.platform_data = &octeon_ehci_pdata; 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; return ret;
} }
device_initcall(octeon_ehci_device_init); device_initcall(octeon_ehci_device_init);
static int octeon_ohci_power_on(struct platform_device *pdev) static int octeon_ohci_power_on(struct platform_device *pdev)
{ {
octeon2_usb_clocks_start(); octeon2_usb_clocks_start(&pdev->dev);
return 0; return 0;
} }
...@@ -369,11 +375,11 @@ static struct usb_ohci_pdata octeon_ohci_pdata = { ...@@ -369,11 +375,11 @@ static struct usb_ohci_pdata octeon_ohci_pdata = {
.power_off = octeon_ohci_power_off, .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; 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.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
ohci_ctl.s.l2c_addr_msb = 0; ohci_ctl.s.l2c_addr_msb = 0;
...@@ -387,57 +393,27 @@ static void __init octeon_ohci_hw_start(void) ...@@ -387,57 +393,27 @@ static void __init octeon_ohci_hw_start(void)
static int __init octeon_ohci_device_init(void) static int __init octeon_ohci_device_init(void)
{ {
struct platform_device *pd; struct platform_device *pd;
struct device_node *ohci_node;
int ret = 0; int ret = 0;
struct resource usb_resources[] = { ohci_node = of_find_node_by_name(NULL, "ohci");
{ if (!ohci_node)
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_IRQ,
}
};
/* Only Octeon2 has ehci/ohci */
if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
return 0; return 0;
if (octeon_is_simulation() || usb_disabled()) pd = of_find_device_by_node(ohci_node);
return 0; /* No USB in the simulator. */ if (!pd)
return 0;
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->dev.platform_data = &octeon_ohci_pdata; pd->dev.platform_data = &octeon_ohci_pdata;
octeon_ohci_hw_start(); octeon_ohci_hw_start(&pd->dev);
ret = platform_device_add(pd);
if (ret)
goto fail;
return ret;
fail:
platform_device_put(pd);
out:
return ret; return ret;
} }
device_initcall(octeon_ohci_device_init); device_initcall(octeon_ohci_device_init);
#endif /* CONFIG_USB */ #endif /* CONFIG_USB */
static struct of_device_id __initdata octeon_ids[] = { static struct of_device_id __initdata octeon_ids[] = {
{ .compatible = "simple-bus", }, { .compatible = "simple-bus", },
{ .compatible = "cavium,octeon-6335-uctl", }, { .compatible = "cavium,octeon-6335-uctl", },
......
...@@ -353,6 +353,7 @@ static const struct of_device_id vt8500_ehci_ids[] = { ...@@ -353,6 +353,7 @@ static const struct of_device_id vt8500_ehci_ids[] = {
{ .compatible = "via,vt8500-ehci", }, { .compatible = "via,vt8500-ehci", },
{ .compatible = "wm,prizm-ehci", }, { .compatible = "wm,prizm-ehci", },
{ .compatible = "generic-ehci", }, { .compatible = "generic-ehci", },
{ .compatible = "cavium,octeon-6335-ehci", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
......
...@@ -328,6 +328,7 @@ static int ohci_platform_resume(struct device *dev) ...@@ -328,6 +328,7 @@ static int ohci_platform_resume(struct device *dev)
static const struct of_device_id ohci_platform_ids[] = { static const struct of_device_id ohci_platform_ids[] = {
{ .compatible = "generic-ohci", }, { .compatible = "generic-ohci", },
{ .compatible = "cavium,octeon-6335-ohci", },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, ohci_platform_ids); MODULE_DEVICE_TABLE(of, ohci_platform_ids);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment