aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/lantiq
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2012-12-13 13:40:13 -0500
committerRalf Baechle <ralf@linux-mips.org>2012-12-13 13:40:13 -0500
commit241738bd51cb0efe58e6c570223153e970afe3ae (patch)
tree05263e1ec3fbd58cc4ba5ee69163612fbb769a4a /arch/mips/lantiq
parentbdf20507da11a9a5b32ef04fa09f352828189aef (diff)
parentce8f0d0607bcad3ec0e8599be80353204427093e (diff)
Merge branch 'mips-next' of http://dev.phrozen.org/githttp/mips-next into mips-for-linux-next
Diffstat (limited to 'arch/mips/lantiq')
-rw-r--r--arch/mips/lantiq/Kconfig4
-rw-r--r--arch/mips/lantiq/prom.c5
-rw-r--r--arch/mips/lantiq/xway/Makefile2
-rw-r--r--arch/mips/lantiq/xway/dma.c9
-rw-r--r--arch/mips/lantiq/xway/reset.c58
-rw-r--r--arch/mips/lantiq/xway/sysctrl.c4
-rw-r--r--arch/mips/lantiq/xway/xrx200_phy_fw.c97
7 files changed, 167 insertions, 12 deletions
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index d84f361f1e45..c0021912131e 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -36,4 +36,8 @@ config PCI_LANTIQ
36 bool "PCI Support" 36 bool "PCI Support"
37 depends on SOC_XWAY && PCI 37 depends on SOC_XWAY && PCI
38 38
39config XRX200_PHY_FW
40 bool "XRX200 PHY firmware loader"
41 depends on SOC_XWAY
42
39endif 43endif
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 6cfd6117fbfd..9f9e875967aa 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -87,9 +87,6 @@ void __init device_tree_init(void)
87 reserve_bootmem(base, size, BOOTMEM_DEFAULT); 87 reserve_bootmem(base, size, BOOTMEM_DEFAULT);
88 88
89 unflatten_device_tree(); 89 unflatten_device_tree();
90
91 /* free the space reserved for the dt blob */
92 free_bootmem(base, size);
93} 90}
94 91
95void __init prom_init(void) 92void __init prom_init(void)
@@ -119,7 +116,7 @@ int __init plat_of_setup(void)
119 sizeof(of_ids[0].compatible)); 116 sizeof(of_ids[0].compatible));
120 strncpy(of_ids[1].compatible, "simple-bus", 117 strncpy(of_ids[1].compatible, "simple-bus",
121 sizeof(of_ids[1].compatible)); 118 sizeof(of_ids[1].compatible));
122 return of_platform_bus_probe(NULL, of_ids, NULL); 119 return of_platform_populate(NULL, of_ids, NULL, NULL);
123} 120}
124 121
125arch_initcall(plat_of_setup); 122arch_initcall(plat_of_setup);
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 70a58c747bd0..7a13660d630d 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1 +1,3 @@
1obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o 1obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
2
3obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 0f7228d350d5..6453962ac898 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -25,6 +25,7 @@
25#include <lantiq_soc.h> 25#include <lantiq_soc.h>
26#include <xway_dma.h> 26#include <xway_dma.h>
27 27
28#define LTQ_DMA_ID 0x08
28#define LTQ_DMA_CTRL 0x10 29#define LTQ_DMA_CTRL 0x10
29#define LTQ_DMA_CPOLL 0x14 30#define LTQ_DMA_CPOLL 0x14
30#define LTQ_DMA_CS 0x18 31#define LTQ_DMA_CS 0x18
@@ -214,6 +215,7 @@ ltq_dma_init(struct platform_device *pdev)
214{ 215{
215 struct clk *clk; 216 struct clk *clk;
216 struct resource *res; 217 struct resource *res;
218 unsigned id;
217 int i; 219 int i;
218 220
219 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 221 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -243,7 +245,12 @@ ltq_dma_init(struct platform_device *pdev)
243 ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL); 245 ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
244 ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); 246 ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
245 } 247 }
246 dev_info(&pdev->dev, "init done\n"); 248
249 id = ltq_dma_r32(LTQ_DMA_ID);
250 dev_info(&pdev->dev,
251 "Init done - hw rev: %X, ports: %d, channels: %d\n",
252 id & 0x1f, (id >> 16) & 0xf, id >> 20);
253
247 return 0; 254 return 0;
248} 255}
249 256
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 22c55f73aa9d..544dbb7fb421 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -28,17 +28,24 @@
28#define RCU_RST_REQ 0x0010 28#define RCU_RST_REQ 0x0010
29/* reset status register */ 29/* reset status register */
30#define RCU_RST_STAT 0x0014 30#define RCU_RST_STAT 0x0014
31/* vr9 gphy registers */
32#define RCU_GFS_ADD0_XRX200 0x0020
33#define RCU_GFS_ADD1_XRX200 0x0068
31 34
32/* reboot bit */ 35/* reboot bit */
36#define RCU_RD_GPHY0_XRX200 BIT(31)
33#define RCU_RD_SRST BIT(30) 37#define RCU_RD_SRST BIT(30)
38#define RCU_RD_GPHY1_XRX200 BIT(29)
39
34/* reset cause */ 40/* reset cause */
35#define RCU_STAT_SHIFT 26 41#define RCU_STAT_SHIFT 26
36/* boot selection */ 42/* boot selection */
37#define RCU_BOOT_SEL_SHIFT 26 43#define RCU_BOOT_SEL(x) ((x >> 18) & 0x7)
38#define RCU_BOOT_SEL_MASK 0x7 44#define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
39 45
40/* remapped base addr of the reset control unit */ 46/* remapped base addr of the reset control unit */
41static void __iomem *ltq_rcu_membase; 47static void __iomem *ltq_rcu_membase;
48static struct device_node *ltq_rcu_np;
42 49
43/* This function is used by the watchdog driver */ 50/* This function is used by the watchdog driver */
44int ltq_reset_cause(void) 51int ltq_reset_cause(void)
@@ -52,7 +59,41 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause);
52unsigned char ltq_boot_select(void) 59unsigned char ltq_boot_select(void)
53{ 60{
54 u32 val = ltq_rcu_r32(RCU_RST_STAT); 61 u32 val = ltq_rcu_r32(RCU_RST_STAT);
55 return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK; 62
63 if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200"))
64 return RCU_BOOT_SEL_XRX200(val);
65
66 return RCU_BOOT_SEL(val);
67}
68
69/* reset / boot a gphy */
70static struct ltq_xrx200_gphy_reset {
71 u32 rd;
72 u32 addr;
73} xrx200_gphy[] = {
74 {RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
75 {RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
76};
77
78/* reset and boot a gphy. these phys only exist on xrx200 SoC */
79int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
80{
81 if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
82 dev_err(dev, "this SoC has no GPHY\n");
83 return -EINVAL;
84 }
85 if (id > 1) {
86 dev_err(dev, "%u is an invalid gphy id\n", id);
87 return -EINVAL;
88 }
89 dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
90
91 ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
92 RCU_RST_REQ);
93 ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
94 ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
95 RCU_RST_REQ);
96 return 0;
56} 97}
57 98
58/* reset a io domain for u micro seconds */ 99/* reset a io domain for u micro seconds */
@@ -85,14 +126,17 @@ static void ltq_machine_power_off(void)
85static int __init mips_reboot_setup(void) 126static int __init mips_reboot_setup(void)
86{ 127{
87 struct resource res; 128 struct resource res;
88 struct device_node *np = 129
89 of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway"); 130 ltq_rcu_np = of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
131 if (!ltq_rcu_np)
132 ltq_rcu_np = of_find_compatible_node(NULL, NULL,
133 "lantiq,rcu-xrx200");
90 134
91 /* check if all the reset register range is available */ 135 /* check if all the reset register range is available */
92 if (!np) 136 if (!ltq_rcu_np)
93 panic("Failed to load reset resources from devicetree"); 137 panic("Failed to load reset resources from devicetree");
94 138
95 if (of_address_to_resource(np, 0, &res)) 139 if (of_address_to_resource(ltq_rcu_np, 0, &res))
96 panic("Failed to get rcu memory range"); 140 panic("Failed to get rcu memory range");
97 141
98 if (request_mem_region(res.start, resource_size(&res), res.name) < 0) 142 if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 2917b56b6b25..3925e6609acc 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -370,6 +370,10 @@ void __init ltq_soc_init(void)
370 clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI); 370 clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
371 clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL); 371 clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
372 clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS); 372 clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
373 clkdev_add_pmu("1e108000.eth", NULL, 0,
374 PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
375 PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
376 PMU_PPE_QSB | PMU_PPE_TOP);
373 } else if (of_machine_is_compatible("lantiq,ar9")) { 377 } else if (of_machine_is_compatible("lantiq,ar9")) {
374 clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), 378 clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
375 ltq_ar9_fpi_hz()); 379 ltq_ar9_fpi_hz());
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c
new file mode 100644
index 000000000000..fe808bf5366d
--- /dev/null
+++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c
@@ -0,0 +1,97 @@
1/*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License version 2 as published
4 * by the Free Software Foundation.
5 *
6 * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/delay.h>
10#include <linux/dma-mapping.h>
11#include <linux/module.h>
12#include <linux/firmware.h>
13#include <linux/of_platform.h>
14
15#include <lantiq_soc.h>
16
17#define XRX200_GPHY_FW_ALIGN (16 * 1024)
18
19static dma_addr_t xway_gphy_load(struct platform_device *pdev)
20{
21 const struct firmware *fw;
22 dma_addr_t dev_addr = 0;
23 const char *fw_name;
24 void *fw_addr;
25 size_t size;
26
27 if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
28 dev_err(&pdev->dev, "failed to load firmware filename\n");
29 return 0;
30 }
31
32 dev_info(&pdev->dev, "requesting %s\n", fw_name);
33 if (request_firmware(&fw, fw_name, &pdev->dev)) {
34 dev_err(&pdev->dev, "failed to load firmware: %s\n", fw_name);
35 return 0;
36 }
37
38 /*
39 * GPHY cores need the firmware code in a persistent and contiguous
40 * memory area with a 16 kB boundary aligned start address
41 */
42 size = fw->size + XRX200_GPHY_FW_ALIGN;
43
44 fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL);
45 if (fw_addr) {
46 fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
47 dev_addr = ALIGN(dev_addr, XRX200_GPHY_FW_ALIGN);
48 memcpy(fw_addr, fw->data, fw->size);
49 } else {
50 dev_err(&pdev->dev, "failed to alloc firmware memory\n");
51 }
52
53 release_firmware(fw);
54 return dev_addr;
55}
56
57static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
58{
59 dma_addr_t fw_addr;
60 struct property *pp;
61 unsigned char *phyids;
62 int i, ret = 0;
63
64 fw_addr = xway_gphy_load(pdev);
65 if (!fw_addr)
66 return -EINVAL;
67 pp = of_find_property(pdev->dev.of_node, "phys", NULL);
68 if (!pp)
69 return -ENOENT;
70 phyids = pp->value;
71 for (i = 0; i < pp->length && !ret; i++)
72 ret = xrx200_gphy_boot(&pdev->dev, phyids[i], fw_addr);
73 if (!ret)
74 mdelay(100);
75 return ret;
76}
77
78static const struct of_device_id xway_phy_match[] = {
79 { .compatible = "lantiq,phy-xrx200" },
80 {},
81};
82MODULE_DEVICE_TABLE(of, xway_phy_match);
83
84static struct platform_driver xway_phy_driver = {
85 .probe = xway_phy_fw_probe,
86 .driver = {
87 .name = "phy-xrx200",
88 .owner = THIS_MODULE,
89 .of_match_table = xway_phy_match,
90 },
91};
92
93module_platform_driver(xway_phy_driver);
94
95MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
96MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
97MODULE_LICENSE("GPL");