diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2012-12-13 13:40:13 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-12-13 13:40:13 -0500 |
commit | 241738bd51cb0efe58e6c570223153e970afe3ae (patch) | |
tree | 05263e1ec3fbd58cc4ba5ee69163612fbb769a4a /arch/mips/lantiq | |
parent | bdf20507da11a9a5b32ef04fa09f352828189aef (diff) | |
parent | ce8f0d0607bcad3ec0e8599be80353204427093e (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/Kconfig | 4 | ||||
-rw-r--r-- | arch/mips/lantiq/prom.c | 5 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/dma.c | 9 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/reset.c | 58 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/sysctrl.c | 4 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/xrx200_phy_fw.c | 97 |
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 | ||
39 | config XRX200_PHY_FW | ||
40 | bool "XRX200 PHY firmware loader" | ||
41 | depends on SOC_XWAY | ||
42 | |||
39 | endif | 43 | endif |
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 | ||
95 | void __init prom_init(void) | 92 | void __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 | ||
125 | arch_initcall(plat_of_setup); | 122 | arch_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 @@ | |||
1 | obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o | 1 | obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o |
2 | |||
3 | obj-$(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 */ |
41 | static void __iomem *ltq_rcu_membase; | 47 | static void __iomem *ltq_rcu_membase; |
48 | static 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 */ |
44 | int ltq_reset_cause(void) | 51 | int ltq_reset_cause(void) |
@@ -52,7 +59,41 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause); | |||
52 | unsigned char ltq_boot_select(void) | 59 | unsigned 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 */ | ||
70 | static 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 */ | ||
79 | int 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) | |||
85 | static int __init mips_reboot_setup(void) | 126 | static 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 | |||
19 | static 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 | |||
57 | static 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 | |||
78 | static const struct of_device_id xway_phy_match[] = { | ||
79 | { .compatible = "lantiq,phy-xrx200" }, | ||
80 | {}, | ||
81 | }; | ||
82 | MODULE_DEVICE_TABLE(of, xway_phy_match); | ||
83 | |||
84 | static 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 | |||
93 | module_platform_driver(xway_phy_driver); | ||
94 | |||
95 | MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||
96 | MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader"); | ||
97 | MODULE_LICENSE("GPL"); | ||