aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/lantiq/xway
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/lantiq/xway')
-rw-r--r--arch/mips/lantiq/xway/Kconfig23
-rw-r--r--arch/mips/lantiq/xway/Makefile8
-rw-r--r--arch/mips/lantiq/xway/clk-ase.c48
-rw-r--r--arch/mips/lantiq/xway/clk-xway.c223
-rw-r--r--arch/mips/lantiq/xway/clk.c151
-rw-r--r--arch/mips/lantiq/xway/devices.c119
-rw-r--r--arch/mips/lantiq/xway/devices.h20
-rw-r--r--arch/mips/lantiq/xway/dma.c61
-rw-r--r--arch/mips/lantiq/xway/ebu.c52
-rw-r--r--arch/mips/lantiq/xway/gpio.c12
-rw-r--r--arch/mips/lantiq/xway/gpio_ebu.c126
-rw-r--r--arch/mips/lantiq/xway/gpio_stp.c157
-rw-r--r--arch/mips/lantiq/xway/mach-easy50601.c57
-rw-r--r--arch/mips/lantiq/xway/mach-easy50712.c74
-rw-r--r--arch/mips/lantiq/xway/pmu.c69
-rw-r--r--arch/mips/lantiq/xway/prom-ase.c39
-rw-r--r--arch/mips/lantiq/xway/prom-xway.c54
-rw-r--r--arch/mips/lantiq/xway/prom.c115
-rw-r--r--arch/mips/lantiq/xway/reset.c77
-rw-r--r--arch/mips/lantiq/xway/setup-ase.c19
-rw-r--r--arch/mips/lantiq/xway/setup-xway.c20
-rw-r--r--arch/mips/lantiq/xway/sysctrl.c371
22 files changed, 726 insertions, 1169 deletions
diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig
deleted file mode 100644
index 2b857de36620..000000000000
--- a/arch/mips/lantiq/xway/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
1if SOC_XWAY
2
3menu "MIPS Machine"
4
5config LANTIQ_MACH_EASY50712
6 bool "Easy50712 - Danube"
7 default y
8
9endmenu
10
11endif
12
13if SOC_AMAZON_SE
14
15menu "MIPS Machine"
16
17config LANTIQ_MACH_EASY50601
18 bool "Easy50601 - Amazon SE"
19 default y
20
21endmenu
22
23endif
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index c517f2e77563..dc3194f6ee42 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,7 +1 @@
1obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o obj-y := prom.o sysctrl.o clk.o reset.o gpio.o dma.o
2
3obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
4obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
5
6obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
7obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c
deleted file mode 100644
index 652258309c9c..000000000000
--- a/arch/mips/lantiq/xway/clk-ase.c
+++ /dev/null
@@ -1,48 +0,0 @@
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) 2011 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/io.h>
10#include <linux/export.h>
11#include <linux/init.h>
12#include <linux/clk.h>
13
14#include <asm/time.h>
15#include <asm/irq.h>
16#include <asm/div64.h>
17
18#include <lantiq_soc.h>
19
20/* cgu registers */
21#define LTQ_CGU_SYS 0x0010
22
23unsigned int ltq_get_io_region_clock(void)
24{
25 return CLOCK_133M;
26}
27EXPORT_SYMBOL(ltq_get_io_region_clock);
28
29unsigned int ltq_get_fpi_bus_clock(int fpi)
30{
31 return CLOCK_133M;
32}
33EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
34
35unsigned int ltq_get_cpu_hz(void)
36{
37 if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
38 return CLOCK_266M;
39 else
40 return CLOCK_133M;
41}
42EXPORT_SYMBOL(ltq_get_cpu_hz);
43
44unsigned int ltq_get_fpi_hz(void)
45{
46 return CLOCK_133M;
47}
48EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/clk-xway.c b/arch/mips/lantiq/xway/clk-xway.c
deleted file mode 100644
index 696b1a3e0642..000000000000
--- a/arch/mips/lantiq/xway/clk-xway.c
+++ /dev/null
@@ -1,223 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/io.h>
10#include <linux/export.h>
11#include <linux/init.h>
12#include <linux/clk.h>
13
14#include <asm/time.h>
15#include <asm/irq.h>
16#include <asm/div64.h>
17
18#include <lantiq_soc.h>
19
20static unsigned int ltq_ram_clocks[] = {
21 CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
22#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
23
24#define BASIC_FREQUENCY_1 35328000
25#define BASIC_FREQUENCY_2 36000000
26#define BASIS_REQUENCY_USB 12000000
27
28#define GET_BITS(x, msb, lsb) \
29 (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
30
31#define LTQ_CGU_PLL0_CFG 0x0004
32#define LTQ_CGU_PLL1_CFG 0x0008
33#define LTQ_CGU_PLL2_CFG 0x000C
34#define LTQ_CGU_SYS 0x0010
35#define LTQ_CGU_UPDATE 0x0014
36#define LTQ_CGU_IF_CLK 0x0018
37#define LTQ_CGU_OSC_CON 0x001C
38#define LTQ_CGU_SMD 0x0020
39#define LTQ_CGU_CT1SR 0x0028
40#define LTQ_CGU_CT2SR 0x002C
41#define LTQ_CGU_PCMCR 0x0030
42#define LTQ_CGU_PCI_CR 0x0034
43#define LTQ_CGU_PD_PC 0x0038
44#define LTQ_CGU_FMR 0x003C
45
46#define CGU_PLL0_PHASE_DIVIDER_ENABLE \
47 (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
48#define CGU_PLL0_BYPASS \
49 (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
50#define CGU_PLL0_CFG_DSMSEL \
51 (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
52#define CGU_PLL0_CFG_FRAC_EN \
53 (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
54#define CGU_PLL1_SRC \
55 (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
56#define CGU_PLL2_PHASE_DIVIDER_ENABLE \
57 (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
58#define CGU_SYS_FPI_SEL (1 << 6)
59#define CGU_SYS_DDR_SEL 0x3
60#define CGU_PLL0_SRC (1 << 29)
61
62#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
63#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
64#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
65#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
66#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
67
68static unsigned int ltq_get_pll0_fdiv(void);
69
70static inline unsigned int get_input_clock(int pll)
71{
72 switch (pll) {
73 case 0:
74 if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
75 return BASIS_REQUENCY_USB;
76 else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
77 return BASIC_FREQUENCY_1;
78 else
79 return BASIC_FREQUENCY_2;
80 case 1:
81 if (CGU_PLL1_SRC)
82 return BASIS_REQUENCY_USB;
83 else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
84 return BASIC_FREQUENCY_1;
85 else
86 return BASIC_FREQUENCY_2;
87 case 2:
88 switch (CGU_PLL2_SRC) {
89 case 0:
90 return ltq_get_pll0_fdiv();
91 case 1:
92 return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
93 BASIC_FREQUENCY_1 :
94 BASIC_FREQUENCY_2;
95 case 2:
96 return BASIS_REQUENCY_USB;
97 }
98 default:
99 return 0;
100 }
101}
102
103static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
104{
105 u64 res, clock = get_input_clock(pll);
106
107 res = num * clock;
108 do_div(res, den);
109 return res;
110}
111
112static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
113 unsigned int K)
114{
115 unsigned int num = ((N + 1) << 10) + K;
116 unsigned int den = (M + 1) << 10;
117
118 return cal_dsm(pll, num, den);
119}
120
121static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
122 unsigned int K)
123{
124 unsigned int num = ((N + 1) << 11) + K + 512;
125 unsigned int den = (M + 1) << 11;
126
127 return cal_dsm(pll, num, den);
128}
129
130static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
131 unsigned int K)
132{
133 unsigned int num = K >= 512 ?
134 ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
135 unsigned int den = (M + 1) << 12;
136
137 return cal_dsm(pll, num, den);
138}
139
140static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
141 unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
142{
143 if (!dsmsel)
144 return mash_dsm(pll, M, N, K);
145 else if (!phase_div_en)
146 return mash_dsm(pll, M, N, K);
147 else
148 return ssff_dsm_2(pll, M, N, K);
149}
150
151static inline unsigned int ltq_get_pll0_fosc(void)
152{
153 if (CGU_PLL0_BYPASS)
154 return get_input_clock(0);
155 else
156 return !CGU_PLL0_CFG_FRAC_EN
157 ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
158 CGU_PLL0_CFG_DSMSEL,
159 CGU_PLL0_PHASE_DIVIDER_ENABLE)
160 : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
161 CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
162 CGU_PLL0_PHASE_DIVIDER_ENABLE);
163}
164
165static unsigned int ltq_get_pll0_fdiv(void)
166{
167 unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
168
169 return (ltq_get_pll0_fosc() + (div >> 1)) / div;
170}
171
172unsigned int ltq_get_io_region_clock(void)
173{
174 unsigned int ret = ltq_get_pll0_fosc();
175
176 switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
177 default:
178 case 0:
179 return (ret + 1) / 2;
180 case 1:
181 return (ret * 2 + 2) / 5;
182 case 2:
183 return (ret + 1) / 3;
184 case 3:
185 return (ret + 2) / 4;
186 }
187}
188EXPORT_SYMBOL(ltq_get_io_region_clock);
189
190unsigned int ltq_get_fpi_bus_clock(int fpi)
191{
192 unsigned int ret = ltq_get_io_region_clock();
193
194 if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
195 ret >>= 1;
196 return ret;
197}
198EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
199
200unsigned int ltq_get_cpu_hz(void)
201{
202 switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
203 case 0:
204 return CLOCK_333M;
205 case 4:
206 return DDR_HZ;
207 case 8:
208 return DDR_HZ << 1;
209 default:
210 return DDR_HZ >> 1;
211 }
212}
213EXPORT_SYMBOL(ltq_get_cpu_hz);
214
215unsigned int ltq_get_fpi_hz(void)
216{
217 unsigned int ddr_clock = DDR_HZ;
218
219 if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
220 return ddr_clock >> 1;
221 return ddr_clock;
222}
223EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
new file mode 100644
index 000000000000..9aa17f79a742
--- /dev/null
+++ b/arch/mips/lantiq/xway/clk.c
@@ -0,0 +1,151 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/io.h>
10#include <linux/export.h>
11#include <linux/init.h>
12#include <linux/clk.h>
13
14#include <asm/time.h>
15#include <asm/irq.h>
16#include <asm/div64.h>
17
18#include <lantiq_soc.h>
19
20#include "../clk.h"
21
22static unsigned int ram_clocks[] = {
23 CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
24#define DDR_HZ ram_clocks[ltq_cgu_r32(CGU_SYS) & 0x3]
25
26/* legacy xway clock */
27#define CGU_SYS 0x10
28
29/* vr9 clock */
30#define CGU_SYS_VR9 0x0c
31#define CGU_IF_CLK_VR9 0x24
32
33unsigned long ltq_danube_fpi_hz(void)
34{
35 unsigned long ddr_clock = DDR_HZ;
36
37 if (ltq_cgu_r32(CGU_SYS) & 0x40)
38 return ddr_clock >> 1;
39 return ddr_clock;
40}
41
42unsigned long ltq_danube_cpu_hz(void)
43{
44 switch (ltq_cgu_r32(CGU_SYS) & 0xc) {
45 case 0:
46 return CLOCK_333M;
47 case 4:
48 return DDR_HZ;
49 case 8:
50 return DDR_HZ << 1;
51 default:
52 return DDR_HZ >> 1;
53 }
54}
55
56unsigned long ltq_ar9_sys_hz(void)
57{
58 if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2)
59 return CLOCK_393M;
60 return CLOCK_333M;
61}
62
63unsigned long ltq_ar9_fpi_hz(void)
64{
65 unsigned long sys = ltq_ar9_sys_hz();
66
67 if (ltq_cgu_r32(CGU_SYS) & BIT(0))
68 return sys;
69 return sys >> 1;
70}
71
72unsigned long ltq_ar9_cpu_hz(void)
73{
74 if (ltq_cgu_r32(CGU_SYS) & BIT(2))
75 return ltq_ar9_fpi_hz();
76 else
77 return ltq_ar9_sys_hz();
78}
79
80unsigned long ltq_vr9_cpu_hz(void)
81{
82 unsigned int cpu_sel;
83 unsigned long clk;
84
85 cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf;
86
87 switch (cpu_sel) {
88 case 0:
89 clk = CLOCK_600M;
90 break;
91 case 1:
92 clk = CLOCK_500M;
93 break;
94 case 2:
95 clk = CLOCK_393M;
96 break;
97 case 3:
98 clk = CLOCK_333M;
99 break;
100 case 5:
101 case 6:
102 clk = CLOCK_196_608M;
103 break;
104 case 7:
105 clk = CLOCK_167M;
106 break;
107 case 4:
108 case 8:
109 case 9:
110 clk = CLOCK_125M;
111 break;
112 default:
113 clk = 0;
114 break;
115 }
116
117 return clk;
118}
119
120unsigned long ltq_vr9_fpi_hz(void)
121{
122 unsigned int ocp_sel, cpu_clk;
123 unsigned long clk;
124
125 cpu_clk = ltq_vr9_cpu_hz();
126 ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3;
127
128 switch (ocp_sel) {
129 case 0:
130 /* OCP ratio 1 */
131 clk = cpu_clk;
132 break;
133 case 2:
134 /* OCP ratio 2 */
135 clk = cpu_clk / 2;
136 break;
137 case 3:
138 /* OCP ratio 2.5 */
139 clk = (cpu_clk * 2) / 5;
140 break;
141 case 4:
142 /* OCP ratio 3 */
143 clk = cpu_clk / 3;
144 break;
145 default:
146 clk = 0;
147 break;
148 }
149
150 return clk;
151}
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
deleted file mode 100644
index d614aa7ff07f..000000000000
--- a/arch/mips/lantiq/xway/devices.c
+++ /dev/null
@@ -1,119 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/init.h>
10#include <linux/export.h>
11#include <linux/types.h>
12#include <linux/string.h>
13#include <linux/mtd/physmap.h>
14#include <linux/kernel.h>
15#include <linux/reboot.h>
16#include <linux/platform_device.h>
17#include <linux/leds.h>
18#include <linux/etherdevice.h>
19#include <linux/time.h>
20#include <linux/io.h>
21#include <linux/gpio.h>
22
23#include <asm/bootinfo.h>
24#include <asm/irq.h>
25
26#include <lantiq_soc.h>
27#include <lantiq_irq.h>
28#include <lantiq_platform.h>
29
30#include "devices.h"
31
32/* gpio */
33static struct resource ltq_gpio_resource[] = {
34 {
35 .name = "gpio0",
36 .start = LTQ_GPIO0_BASE_ADDR,
37 .end = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
38 .flags = IORESOURCE_MEM,
39 }, {
40 .name = "gpio1",
41 .start = LTQ_GPIO1_BASE_ADDR,
42 .end = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
43 .flags = IORESOURCE_MEM,
44 }, {
45 .name = "gpio2",
46 .start = LTQ_GPIO2_BASE_ADDR,
47 .end = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
48 .flags = IORESOURCE_MEM,
49 }
50};
51
52void __init ltq_register_gpio(void)
53{
54 platform_device_register_simple("ltq_gpio", 0,
55 &ltq_gpio_resource[0], 1);
56 platform_device_register_simple("ltq_gpio", 1,
57 &ltq_gpio_resource[1], 1);
58
59 /* AR9 and VR9 have an extra gpio block */
60 if (ltq_is_ar9() || ltq_is_vr9()) {
61 platform_device_register_simple("ltq_gpio", 2,
62 &ltq_gpio_resource[2], 1);
63 }
64}
65
66/* serial to parallel conversion */
67static struct resource ltq_stp_resource = {
68 .name = "stp",
69 .start = LTQ_STP_BASE_ADDR,
70 .end = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
71 .flags = IORESOURCE_MEM,
72};
73
74void __init ltq_register_gpio_stp(void)
75{
76 platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
77}
78
79/* asc ports - amazon se has its own serial mapping */
80static struct resource ltq_ase_asc_resources[] = {
81 {
82 .name = "asc0",
83 .start = LTQ_ASC1_BASE_ADDR,
84 .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
85 .flags = IORESOURCE_MEM,
86 },
87 IRQ_RES(tx, LTQ_ASC_ASE_TIR),
88 IRQ_RES(rx, LTQ_ASC_ASE_RIR),
89 IRQ_RES(err, LTQ_ASC_ASE_EIR),
90};
91
92void __init ltq_register_ase_asc(void)
93{
94 platform_device_register_simple("ltq_asc", 0,
95 ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
96}
97
98/* ethernet */
99static struct resource ltq_etop_resources = {
100 .name = "etop",
101 .start = LTQ_ETOP_BASE_ADDR,
102 .end = LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
103 .flags = IORESOURCE_MEM,
104};
105
106static struct platform_device ltq_etop = {
107 .name = "ltq_etop",
108 .resource = &ltq_etop_resources,
109 .num_resources = 1,
110};
111
112void __init
113ltq_register_etop(struct ltq_eth_data *eth)
114{
115 if (eth) {
116 ltq_etop.dev.platform_data = eth;
117 platform_device_register(&ltq_etop);
118 }
119}
diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
deleted file mode 100644
index e90493471bc1..000000000000
--- a/arch/mips/lantiq/xway/devices.h
+++ /dev/null
@@ -1,20 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#ifndef _LTQ_DEVICES_XWAY_H__
10#define _LTQ_DEVICES_XWAY_H__
11
12#include "../devices.h"
13#include <linux/phy.h>
14
15extern void ltq_register_gpio(void);
16extern void ltq_register_gpio_stp(void);
17extern void ltq_register_ase_asc(void);
18extern void ltq_register_etop(struct ltq_eth_data *eth);
19
20#endif
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index b210e936c7c3..55d2c4fa4714 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -19,7 +19,8 @@
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/dma-mapping.h> 21#include <linux/dma-mapping.h>
22#include <linux/export.h> 22#include <linux/module.h>
23#include <linux/clk.h>
23 24
24#include <lantiq_soc.h> 25#include <lantiq_soc.h>
25#include <xway_dma.h> 26#include <xway_dma.h>
@@ -55,13 +56,6 @@
55#define ltq_dma_w32_mask(x, y, z) ltq_w32_mask(x, y, \ 56#define ltq_dma_w32_mask(x, y, z) ltq_w32_mask(x, y, \
56 ltq_dma_membase + (z)) 57 ltq_dma_membase + (z))
57 58
58static struct resource ltq_dma_resource = {
59 .name = "dma",
60 .start = LTQ_DMA_BASE_ADDR,
61 .end = LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
62 .flags = IORESOURCE_MEM,
63};
64
65static void __iomem *ltq_dma_membase; 59static void __iomem *ltq_dma_membase;
66 60
67void 61void
@@ -215,27 +209,28 @@ ltq_dma_init_port(int p)
215} 209}
216EXPORT_SYMBOL_GPL(ltq_dma_init_port); 210EXPORT_SYMBOL_GPL(ltq_dma_init_port);
217 211
218int __init 212static int __devinit
219ltq_dma_init(void) 213ltq_dma_init(struct platform_device *pdev)
220{ 214{
215 struct clk *clk;
216 struct resource *res;
221 int i; 217 int i;
222 218
223 /* insert and request the memory region */ 219 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
224 if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0) 220 if (!res)
225 panic("Failed to insert dma memory"); 221 panic("Failed to get dma resource");
226
227 if (request_mem_region(ltq_dma_resource.start,
228 resource_size(&ltq_dma_resource), "dma") < 0)
229 panic("Failed to request dma memory");
230 222
231 /* remap dma register range */ 223 /* remap dma register range */
232 ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start, 224 ltq_dma_membase = devm_request_and_ioremap(&pdev->dev, res);
233 resource_size(&ltq_dma_resource));
234 if (!ltq_dma_membase) 225 if (!ltq_dma_membase)
235 panic("Failed to remap dma memory"); 226 panic("Failed to remap dma resource");
236 227
237 /* power up and reset the dma engine */ 228 /* power up and reset the dma engine */
238 ltq_pmu_enable(PMU_DMA); 229 clk = clk_get(&pdev->dev, NULL);
230 if (IS_ERR(clk))
231 panic("Failed to get dma clock");
232
233 clk_enable(clk);
239 ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL); 234 ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
240 235
241 /* disable all interrupts */ 236 /* disable all interrupts */
@@ -248,7 +243,29 @@ ltq_dma_init(void)
248 ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL); 243 ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
249 ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); 244 ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
250 } 245 }
246 dev_info(&pdev->dev, "init done\n");
251 return 0; 247 return 0;
252} 248}
253 249
254postcore_initcall(ltq_dma_init); 250static const struct of_device_id dma_match[] = {
251 { .compatible = "lantiq,dma-xway" },
252 {},
253};
254MODULE_DEVICE_TABLE(of, dma_match);
255
256static struct platform_driver dma_driver = {
257 .probe = ltq_dma_init,
258 .driver = {
259 .name = "dma-xway",
260 .owner = THIS_MODULE,
261 .of_match_table = dma_match,
262 },
263};
264
265int __init
266dma_init(void)
267{
268 return platform_driver_register(&dma_driver);
269}
270
271postcore_initcall(dma_init);
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
deleted file mode 100644
index 862e3e830680..000000000000
--- a/arch/mips/lantiq/xway/ebu.c
+++ /dev/null
@@ -1,52 +0,0 @@
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 * EBU - the external bus unit attaches PCI, NOR and NAND
7 *
8 * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/ioport.h>
14
15#include <lantiq_soc.h>
16
17/* all access to the ebu must be locked */
18DEFINE_SPINLOCK(ebu_lock);
19EXPORT_SYMBOL_GPL(ebu_lock);
20
21static struct resource ltq_ebu_resource = {
22 .name = "ebu",
23 .start = LTQ_EBU_BASE_ADDR,
24 .end = LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
25 .flags = IORESOURCE_MEM,
26};
27
28/* remapped base addr of the clock unit and external bus unit */
29void __iomem *ltq_ebu_membase;
30
31static int __init lantiq_ebu_init(void)
32{
33 /* insert and request the memory region */
34 if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
35 panic("Failed to insert ebu memory");
36
37 if (request_mem_region(ltq_ebu_resource.start,
38 resource_size(&ltq_ebu_resource), "ebu") < 0)
39 panic("Failed to request ebu memory");
40
41 /* remap ebu register range */
42 ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
43 resource_size(&ltq_ebu_resource));
44 if (!ltq_ebu_membase)
45 panic("Failed to remap ebu memory");
46
47 /* make sure to unprotect the memory region where flash is located */
48 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
49 return 0;
50}
51
52postcore_initcall(lantiq_ebu_init);
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
index c429a5bc080f..2ab39e93d9be 100644
--- a/arch/mips/lantiq/xway/gpio.c
+++ b/arch/mips/lantiq/xway/gpio.c
@@ -36,18 +36,6 @@ struct ltq_gpio {
36 36
37static struct ltq_gpio ltq_gpio_port[MAX_PORTS]; 37static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
38 38
39int gpio_to_irq(unsigned int gpio)
40{
41 return -EINVAL;
42}
43EXPORT_SYMBOL(gpio_to_irq);
44
45int irq_to_gpio(unsigned int gpio)
46{
47 return -EINVAL;
48}
49EXPORT_SYMBOL(irq_to_gpio);
50
51int ltq_gpio_request(unsigned int pin, unsigned int alt0, 39int ltq_gpio_request(unsigned int pin, unsigned int alt0,
52 unsigned int alt1, unsigned int dir, const char *name) 40 unsigned int alt1, unsigned int dir, const char *name)
53{ 41{
diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
deleted file mode 100644
index aae17170472f..000000000000
--- a/arch/mips/lantiq/xway/gpio_ebu.c
+++ /dev/null
@@ -1,126 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/init.h>
10#include <linux/export.h>
11#include <linux/types.h>
12#include <linux/platform_device.h>
13#include <linux/mutex.h>
14#include <linux/gpio.h>
15#include <linux/io.h>
16
17#include <lantiq_soc.h>
18
19/*
20 * By attaching hardware latches to the EBU it is possible to create output
21 * only gpios. This driver configures a special memory address, which when
22 * written to outputs 16 bit to the latches.
23 */
24
25#define LTQ_EBU_BUSCON 0x1e7ff /* 16 bit access, slowest timing */
26#define LTQ_EBU_WP 0x80000000 /* write protect bit */
27
28/* we keep a shadow value of the last value written to the ebu */
29static int ltq_ebu_gpio_shadow = 0x0;
30static void __iomem *ltq_ebu_gpio_membase;
31
32static void ltq_ebu_apply(void)
33{
34 unsigned long flags;
35
36 spin_lock_irqsave(&ebu_lock, flags);
37 ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1);
38 *((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow;
39 ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
40 spin_unlock_irqrestore(&ebu_lock, flags);
41}
42
43static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value)
44{
45 if (value)
46 ltq_ebu_gpio_shadow |= (1 << offset);
47 else
48 ltq_ebu_gpio_shadow &= ~(1 << offset);
49 ltq_ebu_apply();
50}
51
52static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset,
53 int value)
54{
55 ltq_ebu_set(chip, offset, value);
56
57 return 0;
58}
59
60static struct gpio_chip ltq_ebu_chip = {
61 .label = "ltq_ebu",
62 .direction_output = ltq_ebu_direction_output,
63 .set = ltq_ebu_set,
64 .base = 72,
65 .ngpio = 16,
66 .can_sleep = 1,
67 .owner = THIS_MODULE,
68};
69
70static int ltq_ebu_probe(struct platform_device *pdev)
71{
72 int ret = 0;
73 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
74
75 if (!res) {
76 dev_err(&pdev->dev, "failed to get memory resource\n");
77 return -ENOENT;
78 }
79
80 res = devm_request_mem_region(&pdev->dev, res->start,
81 resource_size(res), dev_name(&pdev->dev));
82 if (!res) {
83 dev_err(&pdev->dev, "failed to request memory resource\n");
84 return -EBUSY;
85 }
86
87 ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start,
88 resource_size(res));
89 if (!ltq_ebu_gpio_membase) {
90 dev_err(&pdev->dev, "Failed to ioremap mem region\n");
91 return -ENOMEM;
92 }
93
94 /* grab the default shadow value passed form the platform code */
95 ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data;
96
97 /* tell the ebu controller which memory address we will be using */
98 ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1);
99
100 /* write protect the region */
101 ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
102
103 ret = gpiochip_add(&ltq_ebu_chip);
104 if (!ret)
105 ltq_ebu_apply();
106 return ret;
107}
108
109static struct platform_driver ltq_ebu_driver = {
110 .probe = ltq_ebu_probe,
111 .driver = {
112 .name = "ltq_ebu",
113 .owner = THIS_MODULE,
114 },
115};
116
117static int __init ltq_ebu_init(void)
118{
119 int ret = platform_driver_register(&ltq_ebu_driver);
120
121 if (ret)
122 pr_info("ltq_ebu : Error registering platform driver!");
123 return ret;
124}
125
126postcore_initcall(ltq_ebu_init);
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
deleted file mode 100644
index fd07d87adaa9..000000000000
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ /dev/null
@@ -1,157 +0,0 @@
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) 2007 John Crispin <blogic@openwrt.org>
7 *
8 */
9
10#include <linux/slab.h>
11#include <linux/init.h>
12#include <linux/export.h>
13#include <linux/types.h>
14#include <linux/platform_device.h>
15#include <linux/mutex.h>
16#include <linux/io.h>
17#include <linux/gpio.h>
18
19#include <lantiq_soc.h>
20
21#define LTQ_STP_CON0 0x00
22#define LTQ_STP_CON1 0x04
23#define LTQ_STP_CPU0 0x08
24#define LTQ_STP_CPU1 0x0C
25#define LTQ_STP_AR 0x10
26
27#define LTQ_STP_CON_SWU (1 << 31)
28#define LTQ_STP_2HZ 0
29#define LTQ_STP_4HZ (1 << 23)
30#define LTQ_STP_8HZ (2 << 23)
31#define LTQ_STP_10HZ (3 << 23)
32#define LTQ_STP_SPEED_MASK (0xf << 23)
33#define LTQ_STP_UPD_FPI (1 << 31)
34#define LTQ_STP_UPD_MASK (3 << 30)
35#define LTQ_STP_ADSL_SRC (3 << 24)
36
37#define LTQ_STP_GROUP0 (1 << 0)
38
39#define LTQ_STP_RISING 0
40#define LTQ_STP_FALLING (1 << 26)
41#define LTQ_STP_EDGE_MASK (1 << 26)
42
43#define ltq_stp_r32(reg) __raw_readl(ltq_stp_membase + reg)
44#define ltq_stp_w32(val, reg) __raw_writel(val, ltq_stp_membase + reg)
45#define ltq_stp_w32_mask(clear, set, reg) \
46 ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \
47 ltq_stp_membase + (reg))
48
49static int ltq_stp_shadow = 0xffff;
50static void __iomem *ltq_stp_membase;
51
52static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)
53{
54 if (value)
55 ltq_stp_shadow |= (1 << offset);
56 else
57 ltq_stp_shadow &= ~(1 << offset);
58 ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);
59}
60
61static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,
62 int value)
63{
64 ltq_stp_set(chip, offset, value);
65
66 return 0;
67}
68
69static struct gpio_chip ltq_stp_chip = {
70 .label = "ltq_stp",
71 .direction_output = ltq_stp_direction_output,
72 .set = ltq_stp_set,
73 .base = 48,
74 .ngpio = 24,
75 .can_sleep = 1,
76 .owner = THIS_MODULE,
77};
78
79static int ltq_stp_hw_init(void)
80{
81 /* the 3 pins used to control the external stp */
82 ltq_gpio_request(4, 1, 0, 1, "stp-st");
83 ltq_gpio_request(5, 1, 0, 1, "stp-d");
84 ltq_gpio_request(6, 1, 0, 1, "stp-sh");
85
86 /* sane defaults */
87 ltq_stp_w32(0, LTQ_STP_AR);
88 ltq_stp_w32(0, LTQ_STP_CPU0);
89 ltq_stp_w32(0, LTQ_STP_CPU1);
90 ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0);
91 ltq_stp_w32(0, LTQ_STP_CON1);
92
93 /* rising or falling edge */
94 ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
95
96 /* per default stp 15-0 are set */
97 ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
98
99 /* stp are update periodically by the FPI bus */
100 ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
101
102 /* set stp update speed */
103 ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);
104
105 /* tell the hardware that pin (led) 0 and 1 are controlled
106 * by the dsl arc
107 */
108 ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
109
110 ltq_pmu_enable(PMU_LED);
111 return 0;
112}
113
114static int __devinit ltq_stp_probe(struct platform_device *pdev)
115{
116 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
117 int ret = 0;
118
119 if (!res)
120 return -ENOENT;
121 res = devm_request_mem_region(&pdev->dev, res->start,
122 resource_size(res), dev_name(&pdev->dev));
123 if (!res) {
124 dev_err(&pdev->dev, "failed to request STP memory\n");
125 return -EBUSY;
126 }
127 ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start,
128 resource_size(res));
129 if (!ltq_stp_membase) {
130 dev_err(&pdev->dev, "failed to remap STP memory\n");
131 return -ENOMEM;
132 }
133 ret = gpiochip_add(&ltq_stp_chip);
134 if (!ret)
135 ret = ltq_stp_hw_init();
136
137 return ret;
138}
139
140static struct platform_driver ltq_stp_driver = {
141 .probe = ltq_stp_probe,
142 .driver = {
143 .name = "ltq_stp",
144 .owner = THIS_MODULE,
145 },
146};
147
148int __init ltq_stp_init(void)
149{
150 int ret = platform_driver_register(&ltq_stp_driver);
151
152 if (ret)
153 pr_info("ltq_stp: error registering platform driver");
154 return ret;
155}
156
157postcore_initcall(ltq_stp_init);
diff --git a/arch/mips/lantiq/xway/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c
deleted file mode 100644
index d5aaf637ab19..000000000000
--- a/arch/mips/lantiq/xway/mach-easy50601.c
+++ /dev/null
@@ -1,57 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/init.h>
10#include <linux/platform_device.h>
11#include <linux/mtd/mtd.h>
12#include <linux/mtd/partitions.h>
13#include <linux/mtd/physmap.h>
14#include <linux/input.h>
15
16#include <lantiq.h>
17
18#include "../machtypes.h"
19#include "devices.h"
20
21static struct mtd_partition easy50601_partitions[] = {
22 {
23 .name = "uboot",
24 .offset = 0x0,
25 .size = 0x10000,
26 },
27 {
28 .name = "uboot_env",
29 .offset = 0x10000,
30 .size = 0x10000,
31 },
32 {
33 .name = "linux",
34 .offset = 0x20000,
35 .size = 0xE0000,
36 },
37 {
38 .name = "rootfs",
39 .offset = 0x100000,
40 .size = 0x300000,
41 },
42};
43
44static struct physmap_flash_data easy50601_flash_data = {
45 .nr_parts = ARRAY_SIZE(easy50601_partitions),
46 .parts = easy50601_partitions,
47};
48
49static void __init easy50601_init(void)
50{
51 ltq_register_nor(&easy50601_flash_data);
52}
53
54MIPS_MACHINE(LTQ_MACH_EASY50601,
55 "EASY50601",
56 "EASY50601 Eval Board",
57 easy50601_init);
diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
deleted file mode 100644
index ea5027b3239d..000000000000
--- a/arch/mips/lantiq/xway/mach-easy50712.c
+++ /dev/null
@@ -1,74 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/init.h>
10#include <linux/platform_device.h>
11#include <linux/mtd/mtd.h>
12#include <linux/mtd/partitions.h>
13#include <linux/mtd/physmap.h>
14#include <linux/input.h>
15#include <linux/phy.h>
16
17#include <lantiq_soc.h>
18#include <irq.h>
19
20#include "../machtypes.h"
21#include "devices.h"
22
23static struct mtd_partition easy50712_partitions[] = {
24 {
25 .name = "uboot",
26 .offset = 0x0,
27 .size = 0x10000,
28 },
29 {
30 .name = "uboot_env",
31 .offset = 0x10000,
32 .size = 0x10000,
33 },
34 {
35 .name = "linux",
36 .offset = 0x20000,
37 .size = 0xe0000,
38 },
39 {
40 .name = "rootfs",
41 .offset = 0x100000,
42 .size = 0x300000,
43 },
44};
45
46static struct physmap_flash_data easy50712_flash_data = {
47 .nr_parts = ARRAY_SIZE(easy50712_partitions),
48 .parts = easy50712_partitions,
49};
50
51static struct ltq_pci_data ltq_pci_data = {
52 .clock = PCI_CLOCK_INT,
53 .gpio = PCI_GNT1 | PCI_REQ1,
54 .irq = {
55 [14] = INT_NUM_IM0_IRL0 + 22,
56 },
57};
58
59static struct ltq_eth_data ltq_eth_data = {
60 .mii_mode = PHY_INTERFACE_MODE_MII,
61};
62
63static void __init easy50712_init(void)
64{
65 ltq_register_gpio_stp();
66 ltq_register_nor(&easy50712_flash_data);
67 ltq_register_pci(&ltq_pci_data);
68 ltq_register_etop(&ltq_eth_data);
69}
70
71MIPS_MACHINE(LTQ_MACH_EASY50712,
72 "EASY50712",
73 "EASY50712 Eval Board",
74 easy50712_init);
diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
deleted file mode 100644
index fe85361e032e..000000000000
--- a/arch/mips/lantiq/xway/pmu.c
+++ /dev/null
@@ -1,69 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/ioport.h>
12
13#include <lantiq_soc.h>
14
15/* PMU - the power management unit allows us to turn part of the core
16 * on and off
17 */
18
19/* the enable / disable registers */
20#define LTQ_PMU_PWDCR 0x1C
21#define LTQ_PMU_PWDSR 0x20
22
23#define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y))
24#define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x))
25
26static struct resource ltq_pmu_resource = {
27 .name = "pmu",
28 .start = LTQ_PMU_BASE_ADDR,
29 .end = LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
30 .flags = IORESOURCE_MEM,
31};
32
33static void __iomem *ltq_pmu_membase;
34
35void ltq_pmu_enable(unsigned int module)
36{
37 int err = 1000000;
38
39 ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
40 do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
41
42 if (!err)
43 panic("activating PMU module failed!");
44}
45EXPORT_SYMBOL(ltq_pmu_enable);
46
47void ltq_pmu_disable(unsigned int module)
48{
49 ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
50}
51EXPORT_SYMBOL(ltq_pmu_disable);
52
53int __init ltq_pmu_init(void)
54{
55 if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
56 panic("Failed to insert pmu memory");
57
58 if (request_mem_region(ltq_pmu_resource.start,
59 resource_size(&ltq_pmu_resource), "pmu") < 0)
60 panic("Failed to request pmu memory");
61
62 ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
63 resource_size(&ltq_pmu_resource));
64 if (!ltq_pmu_membase)
65 panic("Failed to remap pmu memory");
66 return 0;
67}
68
69core_initcall(ltq_pmu_init);
diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
deleted file mode 100644
index ae4959ae865c..000000000000
--- a/arch/mips/lantiq/xway/prom-ase.c
+++ /dev/null
@@ -1,39 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/export.h>
10#include <linux/clk.h>
11#include <asm/bootinfo.h>
12#include <asm/time.h>
13
14#include <lantiq_soc.h>
15
16#include "../prom.h"
17
18#define SOC_AMAZON_SE "Amazon_SE"
19
20#define PART_SHIFT 12
21#define PART_MASK 0x0FFFFFFF
22#define REV_SHIFT 28
23#define REV_MASK 0xF0000000
24
25void __init ltq_soc_detect(struct ltq_soc_info *i)
26{
27 i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
28 i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
29 switch (i->partnum) {
30 case SOC_ID_AMAZON_SE:
31 i->name = SOC_AMAZON_SE;
32 i->type = SOC_TYPE_AMAZON_SE;
33 break;
34
35 default:
36 unreachable();
37 break;
38 }
39}
diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c
deleted file mode 100644
index 2228133ca356..000000000000
--- a/arch/mips/lantiq/xway/prom-xway.c
+++ /dev/null
@@ -1,54 +0,0 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/export.h>
10#include <linux/clk.h>
11#include <asm/bootinfo.h>
12#include <asm/time.h>
13
14#include <lantiq_soc.h>
15
16#include "../prom.h"
17
18#define SOC_DANUBE "Danube"
19#define SOC_TWINPASS "Twinpass"
20#define SOC_AR9 "AR9"
21
22#define PART_SHIFT 12
23#define PART_MASK 0x0FFFFFFF
24#define REV_SHIFT 28
25#define REV_MASK 0xF0000000
26
27void __init ltq_soc_detect(struct ltq_soc_info *i)
28{
29 i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
30 i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
31 switch (i->partnum) {
32 case SOC_ID_DANUBE1:
33 case SOC_ID_DANUBE2:
34 i->name = SOC_DANUBE;
35 i->type = SOC_TYPE_DANUBE;
36 break;
37
38 case SOC_ID_TWINPASS:
39 i->name = SOC_TWINPASS;
40 i->type = SOC_TYPE_DANUBE;
41 break;
42
43 case SOC_ID_ARX188:
44 case SOC_ID_ARX168:
45 case SOC_ID_ARX182:
46 i->name = SOC_AR9;
47 i->type = SOC_TYPE_AR9;
48 break;
49
50 default:
51 unreachable();
52 break;
53 }
54}
diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c
new file mode 100644
index 000000000000..248429ab2622
--- /dev/null
+++ b/arch/mips/lantiq/xway/prom.c
@@ -0,0 +1,115 @@
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) 2010 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/export.h>
10#include <linux/clk.h>
11#include <asm/bootinfo.h>
12#include <asm/time.h>
13
14#include <lantiq_soc.h>
15
16#include "../prom.h"
17
18#define SOC_DANUBE "Danube"
19#define SOC_TWINPASS "Twinpass"
20#define SOC_AMAZON_SE "Amazon_SE"
21#define SOC_AR9 "AR9"
22#define SOC_GR9 "GR9"
23#define SOC_VR9 "VR9"
24
25#define COMP_DANUBE "lantiq,danube"
26#define COMP_TWINPASS "lantiq,twinpass"
27#define COMP_AMAZON_SE "lantiq,ase"
28#define COMP_AR9 "lantiq,ar9"
29#define COMP_GR9 "lantiq,gr9"
30#define COMP_VR9 "lantiq,vr9"
31
32#define PART_SHIFT 12
33#define PART_MASK 0x0FFFFFFF
34#define REV_SHIFT 28
35#define REV_MASK 0xF0000000
36
37void __init ltq_soc_detect(struct ltq_soc_info *i)
38{
39 i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
40 i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
41 sprintf(i->rev_type, "1.%d", i->rev);
42 switch (i->partnum) {
43 case SOC_ID_DANUBE1:
44 case SOC_ID_DANUBE2:
45 i->name = SOC_DANUBE;
46 i->type = SOC_TYPE_DANUBE;
47 i->compatible = COMP_DANUBE;
48 break;
49
50 case SOC_ID_TWINPASS:
51 i->name = SOC_TWINPASS;
52 i->type = SOC_TYPE_DANUBE;
53 i->compatible = COMP_TWINPASS;
54 break;
55
56 case SOC_ID_ARX188:
57 case SOC_ID_ARX168_1:
58 case SOC_ID_ARX168_2:
59 case SOC_ID_ARX182:
60 i->name = SOC_AR9;
61 i->type = SOC_TYPE_AR9;
62 i->compatible = COMP_AR9;
63 break;
64
65 case SOC_ID_GRX188:
66 case SOC_ID_GRX168:
67 i->name = SOC_GR9;
68 i->type = SOC_TYPE_AR9;
69 i->compatible = COMP_GR9;
70 break;
71
72 case SOC_ID_AMAZON_SE_1:
73 case SOC_ID_AMAZON_SE_2:
74#ifdef CONFIG_PCI
75 panic("ase is only supported for non pci kernels");
76#endif
77 i->name = SOC_AMAZON_SE;
78 i->type = SOC_TYPE_AMAZON_SE;
79 i->compatible = COMP_AMAZON_SE;
80 break;
81
82 case SOC_ID_VRX282:
83 case SOC_ID_VRX268:
84 case SOC_ID_VRX288:
85 i->name = SOC_VR9;
86 i->type = SOC_TYPE_VR9;
87 i->compatible = COMP_VR9;
88 break;
89
90 case SOC_ID_GRX268:
91 case SOC_ID_GRX288:
92 i->name = SOC_GR9;
93 i->type = SOC_TYPE_VR9;
94 i->compatible = COMP_GR9;
95 break;
96
97 case SOC_ID_VRX268_2:
98 case SOC_ID_VRX288_2:
99 i->name = SOC_VR9;
100 i->type = SOC_TYPE_VR9_2;
101 i->compatible = COMP_VR9;
102 break;
103
104 case SOC_ID_GRX282_2:
105 case SOC_ID_GRX288_2:
106 i->name = SOC_GR9;
107 i->type = SOC_TYPE_VR9_2;
108 i->compatible = COMP_GR9;
109 break;
110
111 default:
112 unreachable();
113 break;
114 }
115}
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 8b66bd87f0c1..22c55f73aa9d 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -11,26 +11,31 @@
11#include <linux/ioport.h> 11#include <linux/ioport.h>
12#include <linux/pm.h> 12#include <linux/pm.h>
13#include <linux/export.h> 13#include <linux/export.h>
14#include <linux/delay.h>
15#include <linux/of_address.h>
16#include <linux/of_platform.h>
17
14#include <asm/reboot.h> 18#include <asm/reboot.h>
15 19
16#include <lantiq_soc.h> 20#include <lantiq_soc.h>
17 21
22#include "../prom.h"
23
18#define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y)) 24#define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y))
19#define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x)) 25#define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x))
20 26
21/* register definitions */ 27/* reset request register */
22#define LTQ_RCU_RST 0x0010 28#define RCU_RST_REQ 0x0010
23#define LTQ_RCU_RST_ALL 0x40000000 29/* reset status register */
24 30#define RCU_RST_STAT 0x0014
25#define LTQ_RCU_RST_STAT 0x0014
26#define LTQ_RCU_STAT_SHIFT 26
27 31
28static struct resource ltq_rcu_resource = { 32/* reboot bit */
29 .name = "rcu", 33#define RCU_RD_SRST BIT(30)
30 .start = LTQ_RCU_BASE_ADDR, 34/* reset cause */
31 .end = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1, 35#define RCU_STAT_SHIFT 26
32 .flags = IORESOURCE_MEM, 36/* boot selection */
33}; 37#define RCU_BOOT_SEL_SHIFT 26
38#define RCU_BOOT_SEL_MASK 0x7
34 39
35/* remapped base addr of the reset control unit */ 40/* remapped base addr of the reset control unit */
36static void __iomem *ltq_rcu_membase; 41static void __iomem *ltq_rcu_membase;
@@ -38,48 +43,64 @@ static void __iomem *ltq_rcu_membase;
38/* This function is used by the watchdog driver */ 43/* This function is used by the watchdog driver */
39int ltq_reset_cause(void) 44int ltq_reset_cause(void)
40{ 45{
41 u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT); 46 u32 val = ltq_rcu_r32(RCU_RST_STAT);
42 return val >> LTQ_RCU_STAT_SHIFT; 47 return val >> RCU_STAT_SHIFT;
43} 48}
44EXPORT_SYMBOL_GPL(ltq_reset_cause); 49EXPORT_SYMBOL_GPL(ltq_reset_cause);
45 50
51/* allow platform code to find out what source we booted from */
52unsigned char ltq_boot_select(void)
53{
54 u32 val = ltq_rcu_r32(RCU_RST_STAT);
55 return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
56}
57
58/* reset a io domain for u micro seconds */
59void ltq_reset_once(unsigned int module, ulong u)
60{
61 ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
62 udelay(u);
63 ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
64}
65
46static void ltq_machine_restart(char *command) 66static void ltq_machine_restart(char *command)
47{ 67{
48 pr_notice("System restart\n");
49 local_irq_disable(); 68 local_irq_disable();
50 ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST); 69 ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ);
51 unreachable(); 70 unreachable();
52} 71}
53 72
54static void ltq_machine_halt(void) 73static void ltq_machine_halt(void)
55{ 74{
56 pr_notice("System halted.\n");
57 local_irq_disable(); 75 local_irq_disable();
58 unreachable(); 76 unreachable();
59} 77}
60 78
61static void ltq_machine_power_off(void) 79static void ltq_machine_power_off(void)
62{ 80{
63 pr_notice("Please turn off the power now.\n");
64 local_irq_disable(); 81 local_irq_disable();
65 unreachable(); 82 unreachable();
66} 83}
67 84
68static int __init mips_reboot_setup(void) 85static int __init mips_reboot_setup(void)
69{ 86{
70 /* insert and request the memory region */ 87 struct resource res;
71 if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0) 88 struct device_node *np =
72 panic("Failed to insert rcu memory"); 89 of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
90
91 /* check if all the reset register range is available */
92 if (!np)
93 panic("Failed to load reset resources from devicetree");
94
95 if (of_address_to_resource(np, 0, &res))
96 panic("Failed to get rcu memory range");
73 97
74 if (request_mem_region(ltq_rcu_resource.start, 98 if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
75 resource_size(&ltq_rcu_resource), "rcu") < 0) 99 pr_err("Failed to request rcu memory");
76 panic("Failed to request rcu memory");
77 100
78 /* remap rcu register range */ 101 ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
79 ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
80 resource_size(&ltq_rcu_resource));
81 if (!ltq_rcu_membase) 102 if (!ltq_rcu_membase)
82 panic("Failed to remap rcu memory"); 103 panic("Failed to remap core memory");
83 104
84 _machine_restart = ltq_machine_restart; 105 _machine_restart = ltq_machine_restart;
85 _machine_halt = ltq_machine_halt; 106 _machine_halt = ltq_machine_halt;
diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c
deleted file mode 100644
index f6f326798a39..000000000000
--- a/arch/mips/lantiq/xway/setup-ase.c
+++ /dev/null
@@ -1,19 +0,0 @@
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) 2011 John Crispin <blogic@openwrt.org>
7 */
8
9#include <lantiq_soc.h>
10
11#include "../prom.h"
12#include "devices.h"
13
14void __init ltq_soc_setup(void)
15{
16 ltq_register_ase_asc();
17 ltq_register_gpio();
18 ltq_register_wdt();
19}
diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c
deleted file mode 100644
index c292f643a858..000000000000
--- a/arch/mips/lantiq/xway/setup-xway.c
+++ /dev/null
@@ -1,20 +0,0 @@
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) 2011 John Crispin <blogic@openwrt.org>
7 */
8
9#include <lantiq_soc.h>
10
11#include "../prom.h"
12#include "devices.h"
13
14void __init ltq_soc_setup(void)
15{
16 ltq_register_asc(0);
17 ltq_register_asc(1);
18 ltq_register_gpio();
19 ltq_register_wdt();
20}
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
new file mode 100644
index 000000000000..83780f7c842b
--- /dev/null
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -0,0 +1,371 @@
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) 2011-2012 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/ioport.h>
10#include <linux/export.h>
11#include <linux/clkdev.h>
12#include <linux/of.h>
13#include <linux/of_platform.h>
14#include <linux/of_address.h>
15
16#include <lantiq_soc.h>
17
18#include "../clk.h"
19#include "../prom.h"
20
21/* clock control register */
22#define CGU_IFCCR 0x0018
23/* system clock register */
24#define CGU_SYS 0x0010
25/* pci control register */
26#define CGU_PCICR 0x0034
27/* ephy configuration register */
28#define CGU_EPHY 0x10
29/* power control register */
30#define PMU_PWDCR 0x1C
31/* power status register */
32#define PMU_PWDSR 0x20
33/* power control register */
34#define PMU_PWDCR1 0x24
35/* power status register */
36#define PMU_PWDSR1 0x28
37/* power control register */
38#define PWDCR(x) ((x) ? (PMU_PWDCR1) : (PMU_PWDCR))
39/* power status register */
40#define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR))
41
42/* clock gates that we can en/disable */
43#define PMU_USB0_P BIT(0)
44#define PMU_PCI BIT(4)
45#define PMU_DMA BIT(5)
46#define PMU_USB0 BIT(6)
47#define PMU_ASC0 BIT(7)
48#define PMU_EPHY BIT(7) /* ase */
49#define PMU_SPI BIT(8)
50#define PMU_DFE BIT(9)
51#define PMU_EBU BIT(10)
52#define PMU_STP BIT(11)
53#define PMU_GPT BIT(12)
54#define PMU_AHBS BIT(13) /* vr9 */
55#define PMU_FPI BIT(14)
56#define PMU_AHBM BIT(15)
57#define PMU_ASC1 BIT(17)
58#define PMU_PPE_QSB BIT(18)
59#define PMU_PPE_SLL01 BIT(19)
60#define PMU_PPE_TC BIT(21)
61#define PMU_PPE_EMA BIT(22)
62#define PMU_PPE_DPLUM BIT(23)
63#define PMU_PPE_DPLUS BIT(24)
64#define PMU_USB1_P BIT(26)
65#define PMU_USB1 BIT(27)
66#define PMU_SWITCH BIT(28)
67#define PMU_PPE_TOP BIT(29)
68#define PMU_GPHY BIT(30)
69#define PMU_PCIE_CLK BIT(31)
70
71#define PMU1_PCIE_PHY BIT(0)
72#define PMU1_PCIE_CTL BIT(1)
73#define PMU1_PCIE_PDI BIT(4)
74#define PMU1_PCIE_MSI BIT(5)
75
76#define pmu_w32(x, y) ltq_w32((x), pmu_membase + (y))
77#define pmu_r32(x) ltq_r32(pmu_membase + (x))
78
79static void __iomem *pmu_membase;
80void __iomem *ltq_cgu_membase;
81void __iomem *ltq_ebu_membase;
82
83/* legacy function kept alive to ease clkdev transition */
84void ltq_pmu_enable(unsigned int module)
85{
86 int err = 1000000;
87
88 pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
89 do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
90
91 if (!err)
92 panic("activating PMU module failed!");
93}
94EXPORT_SYMBOL(ltq_pmu_enable);
95
96/* legacy function kept alive to ease clkdev transition */
97void ltq_pmu_disable(unsigned int module)
98{
99 pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
100}
101EXPORT_SYMBOL(ltq_pmu_disable);
102
103/* enable a hw clock */
104static int cgu_enable(struct clk *clk)
105{
106 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR);
107 return 0;
108}
109
110/* disable a hw clock */
111static void cgu_disable(struct clk *clk)
112{
113 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR);
114}
115
116/* enable a clock gate */
117static int pmu_enable(struct clk *clk)
118{
119 int retry = 1000000;
120
121 pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
122 PWDCR(clk->module));
123 do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
124
125 if (!retry)
126 panic("activating PMU module failed!\n");
127
128 return 0;
129}
130
131/* disable a clock gate */
132static void pmu_disable(struct clk *clk)
133{
134 pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
135 PWDCR(clk->module));
136}
137
138/* the pci enable helper */
139static int pci_enable(struct clk *clk)
140{
141 unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR);
142 /* set bus clock speed */
143 if (of_machine_is_compatible("lantiq,ar9")) {
144 ifccr &= ~0x1f00000;
145 if (clk->rate == CLOCK_33M)
146 ifccr |= 0xe00000;
147 else
148 ifccr |= 0x700000; /* 62.5M */
149 } else {
150 ifccr &= ~0xf00000;
151 if (clk->rate == CLOCK_33M)
152 ifccr |= 0x800000;
153 else
154 ifccr |= 0x400000; /* 62.5M */
155 }
156 ltq_cgu_w32(ifccr, CGU_IFCCR);
157 pmu_enable(clk);
158 return 0;
159}
160
161/* enable the external clock as a source */
162static int pci_ext_enable(struct clk *clk)
163{
164 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16),
165 CGU_IFCCR);
166 ltq_cgu_w32((1 << 30), CGU_PCICR);
167 return 0;
168}
169
170/* disable the external clock as a source */
171static void pci_ext_disable(struct clk *clk)
172{
173 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16),
174 CGU_IFCCR);
175 ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR);
176}
177
178/* enable a clockout source */
179static int clkout_enable(struct clk *clk)
180{
181 int i;
182
183 /* get the correct rate */
184 for (i = 0; i < 4; i++) {
185 if (clk->rates[i] == clk->rate) {
186 int shift = 14 - (2 * clk->module);
187 unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR);
188
189 ifccr &= ~(3 << shift);
190 ifccr |= i << shift;
191 ltq_cgu_w32(ifccr, CGU_IFCCR);
192 return 0;
193 }
194 }
195 return -1;
196}
197
198/* manage the clock gates via PMU */
199static void clkdev_add_pmu(const char *dev, const char *con,
200 unsigned int module, unsigned int bits)
201{
202 struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
203
204 clk->cl.dev_id = dev;
205 clk->cl.con_id = con;
206 clk->cl.clk = clk;
207 clk->enable = pmu_enable;
208 clk->disable = pmu_disable;
209 clk->module = module;
210 clk->bits = bits;
211 clkdev_add(&clk->cl);
212}
213
214/* manage the clock generator */
215static void clkdev_add_cgu(const char *dev, const char *con,
216 unsigned int bits)
217{
218 struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
219
220 clk->cl.dev_id = dev;
221 clk->cl.con_id = con;
222 clk->cl.clk = clk;
223 clk->enable = cgu_enable;
224 clk->disable = cgu_disable;
225 clk->bits = bits;
226 clkdev_add(&clk->cl);
227}
228
229/* pci needs its own enable function as the setup is a bit more complex */
230static unsigned long valid_pci_rates[] = {CLOCK_33M, CLOCK_62_5M, 0};
231
232static void clkdev_add_pci(void)
233{
234 struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
235 struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL);
236
237 /* main pci clock */
238 clk->cl.dev_id = "17000000.pci";
239 clk->cl.con_id = NULL;
240 clk->cl.clk = clk;
241 clk->rate = CLOCK_33M;
242 clk->rates = valid_pci_rates;
243 clk->enable = pci_enable;
244 clk->disable = pmu_disable;
245 clk->module = 0;
246 clk->bits = PMU_PCI;
247 clkdev_add(&clk->cl);
248
249 /* use internal/external bus clock */
250 clk_ext->cl.dev_id = "17000000.pci";
251 clk_ext->cl.con_id = "external";
252 clk_ext->cl.clk = clk_ext;
253 clk_ext->enable = pci_ext_enable;
254 clk_ext->disable = pci_ext_disable;
255 clkdev_add(&clk_ext->cl);
256}
257
258/* xway socs can generate clocks on gpio pins */
259static unsigned long valid_clkout_rates[4][5] = {
260 {CLOCK_32_768K, CLOCK_1_536M, CLOCK_2_5M, CLOCK_12M, 0},
261 {CLOCK_40M, CLOCK_12M, CLOCK_24M, CLOCK_48M, 0},
262 {CLOCK_25M, CLOCK_40M, CLOCK_30M, CLOCK_60M, 0},
263 {CLOCK_12M, CLOCK_50M, CLOCK_32_768K, CLOCK_25M, 0},
264};
265
266static void clkdev_add_clkout(void)
267{
268 int i;
269
270 for (i = 0; i < 4; i++) {
271 struct clk *clk;
272 char *name;
273
274 name = kzalloc(sizeof("clkout0"), GFP_KERNEL);
275 sprintf(name, "clkout%d", i);
276
277 clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
278 clk->cl.dev_id = "1f103000.cgu";
279 clk->cl.con_id = name;
280 clk->cl.clk = clk;
281 clk->rate = 0;
282 clk->rates = valid_clkout_rates[i];
283 clk->enable = clkout_enable;
284 clk->module = i;
285 clkdev_add(&clk->cl);
286 }
287}
288
289/* bring up all register ranges that we need for basic system control */
290void __init ltq_soc_init(void)
291{
292 struct resource res_pmu, res_cgu, res_ebu;
293 struct device_node *np_pmu =
294 of_find_compatible_node(NULL, NULL, "lantiq,pmu-xway");
295 struct device_node *np_cgu =
296 of_find_compatible_node(NULL, NULL, "lantiq,cgu-xway");
297 struct device_node *np_ebu =
298 of_find_compatible_node(NULL, NULL, "lantiq,ebu-xway");
299
300 /* check if all the core register ranges are available */
301 if (!np_pmu || !np_cgu || !np_ebu)
302 panic("Failed to load core nodess from devicetree");
303
304 if (of_address_to_resource(np_pmu, 0, &res_pmu) ||
305 of_address_to_resource(np_cgu, 0, &res_cgu) ||
306 of_address_to_resource(np_ebu, 0, &res_ebu))
307 panic("Failed to get core resources");
308
309 if ((request_mem_region(res_pmu.start, resource_size(&res_pmu),
310 res_pmu.name) < 0) ||
311 (request_mem_region(res_cgu.start, resource_size(&res_cgu),
312 res_cgu.name) < 0) ||
313 (request_mem_region(res_ebu.start, resource_size(&res_ebu),
314 res_ebu.name) < 0))
315 pr_err("Failed to request core reources");
316
317 pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu));
318 ltq_cgu_membase = ioremap_nocache(res_cgu.start,
319 resource_size(&res_cgu));
320 ltq_ebu_membase = ioremap_nocache(res_ebu.start,
321 resource_size(&res_ebu));
322 if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase)
323 panic("Failed to remap core resources");
324
325 /* make sure to unprotect the memory region where flash is located */
326 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
327
328 /* add our generic xway clocks */
329 clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI);
330 clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0);
331 clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT);
332 clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP);
333 clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA);
334 clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI);
335 clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU);
336 clkdev_add_clkout();
337
338 /* add the soc dependent clocks */
339 if (!of_machine_is_compatible("lantiq,vr9"))
340 clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE);
341
342 if (!of_machine_is_compatible("lantiq,ase")) {
343 clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1);
344 clkdev_add_pci();
345 }
346
347 if (of_machine_is_compatible("lantiq,ase")) {
348 if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
349 clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
350 else
351 clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
352 clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
353 clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
354 } else if (of_machine_is_compatible("lantiq,vr9")) {
355 clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
356 ltq_vr9_fpi_hz());
357 clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
358 clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
359 clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
360 clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
361 clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
362 clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
363 } else if (of_machine_is_compatible("lantiq,ar9")) {
364 clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
365 ltq_ar9_fpi_hz());
366 clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
367 } else {
368 clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
369 ltq_danube_fpi_hz());
370 }
371}