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/Makefile4
-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/ebu.c53
-rw-r--r--arch/mips/lantiq/xway/gpio.c195
-rw-r--r--arch/mips/lantiq/xway/pmu.c70
-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/reset.c91
9 files changed, 777 insertions, 0 deletions
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
new file mode 100644
index 000000000000..9c85ff9184c6
--- /dev/null
+++ b/arch/mips/lantiq/xway/Makefile
@@ -0,0 +1,4 @@
1obj-y := pmu.o ebu.o reset.o gpio.o
2
3obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
4obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c
new file mode 100644
index 000000000000..22d823acd536
--- /dev/null
+++ b/arch/mips/lantiq/xway/clk-ase.c
@@ -0,0 +1,48 @@
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/module.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
new file mode 100644
index 000000000000..ddd39593c581
--- /dev/null
+++ b/arch/mips/lantiq/xway/clk-xway.c
@@ -0,0 +1,223 @@
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/module.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/ebu.c b/arch/mips/lantiq/xway/ebu.c
new file mode 100644
index 000000000000..66eb52fa50a1
--- /dev/null
+++ b/arch/mips/lantiq/xway/ebu.c
@@ -0,0 +1,53 @@
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/version.h>
14#include <linux/ioport.h>
15
16#include <lantiq_soc.h>
17
18/* all access to the ebu must be locked */
19DEFINE_SPINLOCK(ebu_lock);
20EXPORT_SYMBOL_GPL(ebu_lock);
21
22static struct resource ltq_ebu_resource = {
23 .name = "ebu",
24 .start = LTQ_EBU_BASE_ADDR,
25 .end = LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
26 .flags = IORESOURCE_MEM,
27};
28
29/* remapped base addr of the clock unit and external bus unit */
30void __iomem *ltq_ebu_membase;
31
32static int __init lantiq_ebu_init(void)
33{
34 /* insert and request the memory region */
35 if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
36 panic("Failed to insert ebu memory\n");
37
38 if (request_mem_region(ltq_ebu_resource.start,
39 resource_size(&ltq_ebu_resource), "ebu") < 0)
40 panic("Failed to request ebu memory\n");
41
42 /* remap ebu register range */
43 ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
44 resource_size(&ltq_ebu_resource));
45 if (!ltq_ebu_membase)
46 panic("Failed to remap ebu memory\n");
47
48 /* make sure to unprotect the memory region where flash is located */
49 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
50 return 0;
51}
52
53postcore_initcall(lantiq_ebu_init);
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
new file mode 100644
index 000000000000..a321451a5455
--- /dev/null
+++ b/arch/mips/lantiq/xway/gpio.c
@@ -0,0 +1,195 @@
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/slab.h>
10#include <linux/module.h>
11#include <linux/platform_device.h>
12#include <linux/gpio.h>
13#include <linux/ioport.h>
14#include <linux/io.h>
15
16#include <lantiq_soc.h>
17
18#define LTQ_GPIO_OUT 0x00
19#define LTQ_GPIO_IN 0x04
20#define LTQ_GPIO_DIR 0x08
21#define LTQ_GPIO_ALTSEL0 0x0C
22#define LTQ_GPIO_ALTSEL1 0x10
23#define LTQ_GPIO_OD 0x14
24
25#define PINS_PER_PORT 16
26#define MAX_PORTS 3
27
28#define ltq_gpio_getbit(m, r, p) (!!(ltq_r32(m + r) & (1 << p)))
29#define ltq_gpio_setbit(m, r, p) ltq_w32_mask(0, (1 << p), m + r)
30#define ltq_gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r)
31
32struct ltq_gpio {
33 void __iomem *membase;
34 struct gpio_chip chip;
35};
36
37static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
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,
52 unsigned int alt1, unsigned int dir, const char *name)
53{
54 int id = 0;
55
56 if (pin >= (MAX_PORTS * PINS_PER_PORT))
57 return -EINVAL;
58 if (gpio_request(pin, name)) {
59 pr_err("failed to setup lantiq gpio: %s\n", name);
60 return -EBUSY;
61 }
62 if (dir)
63 gpio_direction_output(pin, 1);
64 else
65 gpio_direction_input(pin);
66 while (pin >= PINS_PER_PORT) {
67 pin -= PINS_PER_PORT;
68 id++;
69 }
70 if (alt0)
71 ltq_gpio_setbit(ltq_gpio_port[id].membase,
72 LTQ_GPIO_ALTSEL0, pin);
73 else
74 ltq_gpio_clearbit(ltq_gpio_port[id].membase,
75 LTQ_GPIO_ALTSEL0, pin);
76 if (alt1)
77 ltq_gpio_setbit(ltq_gpio_port[id].membase,
78 LTQ_GPIO_ALTSEL1, pin);
79 else
80 ltq_gpio_clearbit(ltq_gpio_port[id].membase,
81 LTQ_GPIO_ALTSEL1, pin);
82 return 0;
83}
84EXPORT_SYMBOL(ltq_gpio_request);
85
86static void ltq_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
87{
88 struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
89
90 if (value)
91 ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
92 else
93 ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
94}
95
96static int ltq_gpio_get(struct gpio_chip *chip, unsigned int offset)
97{
98 struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
99
100 return ltq_gpio_getbit(ltq_gpio->membase, LTQ_GPIO_IN, offset);
101}
102
103static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
104{
105 struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
106
107 ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
108 ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
109
110 return 0;
111}
112
113static int ltq_gpio_direction_output(struct gpio_chip *chip,
114 unsigned int offset, int value)
115{
116 struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
117
118 ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
119 ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
120 ltq_gpio_set(chip, offset, value);
121
122 return 0;
123}
124
125static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset)
126{
127 struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
128
129 ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset);
130 ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
131 return 0;
132}
133
134static int ltq_gpio_probe(struct platform_device *pdev)
135{
136 struct resource *res;
137
138 if (pdev->id >= MAX_PORTS) {
139 dev_err(&pdev->dev, "invalid gpio port %d\n",
140 pdev->id);
141 return -EINVAL;
142 }
143 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
144 if (!res) {
145 dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
146 pdev->id);
147 return -ENOENT;
148 }
149 res = devm_request_mem_region(&pdev->dev, res->start,
150 resource_size(res), dev_name(&pdev->dev));
151 if (!res) {
152 dev_err(&pdev->dev,
153 "failed to request memory for gpio port %d\n",
154 pdev->id);
155 return -EBUSY;
156 }
157 ltq_gpio_port[pdev->id].membase = devm_ioremap_nocache(&pdev->dev,
158 res->start, resource_size(res));
159 if (!ltq_gpio_port[pdev->id].membase) {
160 dev_err(&pdev->dev, "failed to remap memory for gpio port %d\n",
161 pdev->id);
162 return -ENOMEM;
163 }
164 ltq_gpio_port[pdev->id].chip.label = "ltq_gpio";
165 ltq_gpio_port[pdev->id].chip.direction_input = ltq_gpio_direction_input;
166 ltq_gpio_port[pdev->id].chip.direction_output =
167 ltq_gpio_direction_output;
168 ltq_gpio_port[pdev->id].chip.get = ltq_gpio_get;
169 ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set;
170 ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req;
171 ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id;
172 ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
173 platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
174 return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
175}
176
177static struct platform_driver
178ltq_gpio_driver = {
179 .probe = ltq_gpio_probe,
180 .driver = {
181 .name = "ltq_gpio",
182 .owner = THIS_MODULE,
183 },
184};
185
186int __init ltq_gpio_init(void)
187{
188 int ret = platform_driver_register(&ltq_gpio_driver);
189
190 if (ret)
191 pr_info("ltq_gpio : Error registering platfom driver!");
192 return ret;
193}
194
195postcore_initcall(ltq_gpio_init);
diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
new file mode 100644
index 000000000000..9d69f01e352b
--- /dev/null
+++ b/arch/mips/lantiq/xway/pmu.c
@@ -0,0 +1,70 @@
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/version.h>
12#include <linux/ioport.h>
13
14#include <lantiq_soc.h>
15
16/* PMU - the power management unit allows us to turn part of the core
17 * on and off
18 */
19
20/* the enable / disable registers */
21#define LTQ_PMU_PWDCR 0x1C
22#define LTQ_PMU_PWDSR 0x20
23
24#define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y))
25#define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x))
26
27static struct resource ltq_pmu_resource = {
28 .name = "pmu",
29 .start = LTQ_PMU_BASE_ADDR,
30 .end = LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
31 .flags = IORESOURCE_MEM,
32};
33
34static void __iomem *ltq_pmu_membase;
35
36void ltq_pmu_enable(unsigned int module)
37{
38 int err = 1000000;
39
40 ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
41 do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
42
43 if (!err)
44 panic("activating PMU module failed!\n");
45}
46EXPORT_SYMBOL(ltq_pmu_enable);
47
48void ltq_pmu_disable(unsigned int module)
49{
50 ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
51}
52EXPORT_SYMBOL(ltq_pmu_disable);
53
54int __init ltq_pmu_init(void)
55{
56 if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
57 panic("Failed to insert pmu memory\n");
58
59 if (request_mem_region(ltq_pmu_resource.start,
60 resource_size(&ltq_pmu_resource), "pmu") < 0)
61 panic("Failed to request pmu memory\n");
62
63 ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
64 resource_size(&ltq_pmu_resource));
65 if (!ltq_pmu_membase)
66 panic("Failed to remap pmu memory\n");
67 return 0;
68}
69
70core_initcall(ltq_pmu_init);
diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
new file mode 100644
index 000000000000..abe49f4db57f
--- /dev/null
+++ b/arch/mips/lantiq/xway/prom-ase.c
@@ -0,0 +1,39 @@
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/module.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
new file mode 100644
index 000000000000..1686692ac24d
--- /dev/null
+++ b/arch/mips/lantiq/xway/prom-xway.c
@@ -0,0 +1,54 @@
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/module.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/reset.c b/arch/mips/lantiq/xway/reset.c
new file mode 100644
index 000000000000..a1be36d0e490
--- /dev/null
+++ b/arch/mips/lantiq/xway/reset.c
@@ -0,0 +1,91 @@
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/io.h>
11#include <linux/ioport.h>
12#include <linux/pm.h>
13#include <linux/module.h>
14#include <asm/reboot.h>
15
16#include <lantiq_soc.h>
17
18#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))
20
21/* register definitions */
22#define LTQ_RCU_RST 0x0010
23#define LTQ_RCU_RST_ALL 0x40000000
24
25#define LTQ_RCU_RST_STAT 0x0014
26#define LTQ_RCU_STAT_SHIFT 26
27
28static struct resource ltq_rcu_resource = {
29 .name = "rcu",
30 .start = LTQ_RCU_BASE_ADDR,
31 .end = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
32 .flags = IORESOURCE_MEM,
33};
34
35/* remapped base addr of the reset control unit */
36static void __iomem *ltq_rcu_membase;
37
38/* This function is used by the watchdog driver */
39int ltq_reset_cause(void)
40{
41 u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT);
42 return val >> LTQ_RCU_STAT_SHIFT;
43}
44EXPORT_SYMBOL_GPL(ltq_reset_cause);
45
46static void ltq_machine_restart(char *command)
47{
48 pr_notice("System restart\n");
49 local_irq_disable();
50 ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST);
51 unreachable();
52}
53
54static void ltq_machine_halt(void)
55{
56 pr_notice("System halted.\n");
57 local_irq_disable();
58 unreachable();
59}
60
61static void ltq_machine_power_off(void)
62{
63 pr_notice("Please turn off the power now.\n");
64 local_irq_disable();
65 unreachable();
66}
67
68static int __init mips_reboot_setup(void)
69{
70 /* insert and request the memory region */
71 if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
72 panic("Failed to insert rcu memory\n");
73
74 if (request_mem_region(ltq_rcu_resource.start,
75 resource_size(&ltq_rcu_resource), "rcu") < 0)
76 panic("Failed to request rcu memory\n");
77
78 /* remap rcu register range */
79 ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
80 resource_size(&ltq_rcu_resource));
81 if (!ltq_rcu_membase)
82 panic("Failed to remap rcu memory\n");
83
84 _machine_restart = ltq_machine_restart;
85 _machine_halt = ltq_machine_halt;
86 pm_power_off = ltq_machine_power_off;
87
88 return 0;
89}
90
91arch_initcall(mips_reboot_setup);