aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ar7
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
committerWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
commita07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch)
tree84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/ar7
downloadohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz
ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/ar7')
-rw-r--r--arch/mips/ar7/Makefile11
-rw-r--r--arch/mips/ar7/Platform5
-rw-r--r--arch/mips/ar7/clock.c494
-rw-r--r--arch/mips/ar7/gpio.c331
-rw-r--r--arch/mips/ar7/irq.c165
-rw-r--r--arch/mips/ar7/memory.c56
-rw-r--r--arch/mips/ar7/platform.c722
-rw-r--r--arch/mips/ar7/prom.c256
-rw-r--r--arch/mips/ar7/setup.c93
-rw-r--r--arch/mips/ar7/time.c31
10 files changed, 2164 insertions, 0 deletions
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
new file mode 100644
index 000000000..cd51c6c6e
--- /dev/null
+++ b/arch/mips/ar7/Makefile
@@ -0,0 +1,11 @@
1# SPDX-License-Identifier: GPL-2.0
2
3obj-y := \
4 prom.o \
5 setup.o \
6 memory.o \
7 irq.o \
8 time.o \
9 platform.o \
10 gpio.o \
11 clock.o
diff --git a/arch/mips/ar7/Platform b/arch/mips/ar7/Platform
new file mode 100644
index 000000000..a9257cc01
--- /dev/null
+++ b/arch/mips/ar7/Platform
@@ -0,0 +1,5 @@
1#
2# Texas Instruments AR7
3#
4cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
5load-$(CONFIG_AR7) += 0xffffffff94100000
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
new file mode 100644
index 000000000..95def949c
--- /dev/null
+++ b/arch/mips/ar7/clock.c
@@ -0,0 +1,494 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
5 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
6 */
7
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <linux/types.h>
11#include <linux/export.h>
12#include <linux/delay.h>
13#include <linux/gcd.h>
14#include <linux/io.h>
15#include <linux/err.h>
16#include <linux/clk.h>
17
18#include <asm/addrspace.h>
19#include <asm/mach-ar7/ar7.h>
20
21#define BOOT_PLL_SOURCE_MASK 0x3
22#define CPU_PLL_SOURCE_SHIFT 16
23#define BUS_PLL_SOURCE_SHIFT 14
24#define USB_PLL_SOURCE_SHIFT 18
25#define DSP_PLL_SOURCE_SHIFT 22
26#define BOOT_PLL_SOURCE_AFE 0
27#define BOOT_PLL_SOURCE_BUS 0
28#define BOOT_PLL_SOURCE_REF 1
29#define BOOT_PLL_SOURCE_XTAL 2
30#define BOOT_PLL_SOURCE_CPU 3
31#define BOOT_PLL_BYPASS 0x00000020
32#define BOOT_PLL_ASYNC_MODE 0x02000000
33#define BOOT_PLL_2TO1_MODE 0x00008000
34
35#define TNETD7200_CLOCK_ID_CPU 0
36#define TNETD7200_CLOCK_ID_DSP 1
37#define TNETD7200_CLOCK_ID_USB 2
38
39#define TNETD7200_DEF_CPU_CLK 211000000
40#define TNETD7200_DEF_DSP_CLK 125000000
41#define TNETD7200_DEF_USB_CLK 48000000
42
43struct tnetd7300_clock {
44 u32 ctrl;
45#define PREDIV_MASK 0x001f0000
46#define PREDIV_SHIFT 16
47#define POSTDIV_MASK 0x0000001f
48 u32 unused1[3];
49 u32 pll;
50#define MUL_MASK 0x0000f000
51#define MUL_SHIFT 12
52#define PLL_MODE_MASK 0x00000001
53#define PLL_NDIV 0x00000800
54#define PLL_DIV 0x00000002
55#define PLL_STATUS 0x00000001
56 u32 unused2[3];
57};
58
59struct tnetd7300_clocks {
60 struct tnetd7300_clock bus;
61 struct tnetd7300_clock cpu;
62 struct tnetd7300_clock usb;
63 struct tnetd7300_clock dsp;
64};
65
66struct tnetd7200_clock {
67 u32 ctrl;
68 u32 unused1[3];
69#define DIVISOR_ENABLE_MASK 0x00008000
70 u32 mul;
71 u32 prediv;
72 u32 postdiv;
73 u32 postdiv2;
74 u32 unused2[6];
75 u32 cmd;
76 u32 status;
77 u32 cmden;
78 u32 padding[15];
79};
80
81struct tnetd7200_clocks {
82 struct tnetd7200_clock cpu;
83 struct tnetd7200_clock dsp;
84 struct tnetd7200_clock usb;
85};
86
87static struct clk bus_clk = {
88 .rate = 125000000,
89};
90
91static struct clk cpu_clk = {
92 .rate = 150000000,
93};
94
95static struct clk dsp_clk;
96static struct clk vbus_clk;
97
98static void approximate(int base, int target, int *prediv,
99 int *postdiv, int *mul)
100{
101 int i, j, k, freq, res = target;
102 for (i = 1; i <= 16; i++)
103 for (j = 1; j <= 32; j++)
104 for (k = 1; k <= 32; k++) {
105 freq = abs(base / j * i / k - target);
106 if (freq < res) {
107 res = freq;
108 *mul = i;
109 *prediv = j;
110 *postdiv = k;
111 }
112 }
113}
114
115static void calculate(int base, int target, int *prediv, int *postdiv,
116 int *mul)
117{
118 int tmp_gcd, tmp_base, tmp_freq;
119
120 for (*prediv = 1; *prediv <= 32; (*prediv)++) {
121 tmp_base = base / *prediv;
122 tmp_gcd = gcd(target, tmp_base);
123 *mul = target / tmp_gcd;
124 *postdiv = tmp_base / tmp_gcd;
125 if ((*mul < 1) || (*mul >= 16))
126 continue;
127 if ((*postdiv > 0) & (*postdiv <= 32))
128 break;
129 }
130
131 if (base / *prediv * *mul / *postdiv != target) {
132 approximate(base, target, prediv, postdiv, mul);
133 tmp_freq = base / *prediv * *mul / *postdiv;
134 printk(KERN_WARNING
135 "Adjusted requested frequency %d to %d\n",
136 target, tmp_freq);
137 }
138
139 printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
140 *prediv, *postdiv, *mul);
141}
142
143static int tnetd7300_dsp_clock(void)
144{
145 u32 didr1, didr2;
146 u8 rev = ar7_chip_rev();
147 didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
148 didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
149 if (didr2 & (1 << 23))
150 return 0;
151 if ((rev >= 0x23) && (rev != 0x57))
152 return 250000000;
153 if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
154 > 4208000)
155 return 250000000;
156 return 0;
157}
158
159static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
160 u32 *bootcr, u32 bus_clock)
161{
162 int product;
163 int base_clock = AR7_REF_CLOCK;
164 u32 ctrl = readl(&clock->ctrl);
165 u32 pll = readl(&clock->pll);
166 int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
167 int postdiv = (ctrl & POSTDIV_MASK) + 1;
168 int divisor = prediv * postdiv;
169 int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
170
171 switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
172 case BOOT_PLL_SOURCE_BUS:
173 base_clock = bus_clock;
174 break;
175 case BOOT_PLL_SOURCE_REF:
176 base_clock = AR7_REF_CLOCK;
177 break;
178 case BOOT_PLL_SOURCE_XTAL:
179 base_clock = AR7_XTAL_CLOCK;
180 break;
181 case BOOT_PLL_SOURCE_CPU:
182 base_clock = cpu_clk.rate;
183 break;
184 }
185
186 if (*bootcr & BOOT_PLL_BYPASS)
187 return base_clock / divisor;
188
189 if ((pll & PLL_MODE_MASK) == 0)
190 return (base_clock >> (mul / 16 + 1)) / divisor;
191
192 if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
193 product = (mul & 1) ?
194 (base_clock * mul) >> 1 :
195 (base_clock * (mul - 1)) >> 2;
196 return product / divisor;
197 }
198
199 if (mul == 16)
200 return base_clock / divisor;
201
202 return base_clock * mul / divisor;
203}
204
205static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
206 u32 *bootcr, u32 frequency)
207{
208 int prediv, postdiv, mul;
209 int base_clock = bus_clk.rate;
210
211 switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
212 case BOOT_PLL_SOURCE_BUS:
213 base_clock = bus_clk.rate;
214 break;
215 case BOOT_PLL_SOURCE_REF:
216 base_clock = AR7_REF_CLOCK;
217 break;
218 case BOOT_PLL_SOURCE_XTAL:
219 base_clock = AR7_XTAL_CLOCK;
220 break;
221 case BOOT_PLL_SOURCE_CPU:
222 base_clock = cpu_clk.rate;
223 break;
224 }
225
226 calculate(base_clock, frequency, &prediv, &postdiv, &mul);
227
228 writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
229 mdelay(1);
230 writel(4, &clock->pll);
231 while (readl(&clock->pll) & PLL_STATUS)
232 ;
233 writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
234 mdelay(75);
235}
236
237static void __init tnetd7300_init_clocks(void)
238{
239 u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
240 struct tnetd7300_clocks *clocks =
241 ioremap(UR8_REGS_CLOCKS,
242 sizeof(struct tnetd7300_clocks));
243
244 bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
245 &clocks->bus, bootcr, AR7_AFE_CLOCK);
246
247 if (*bootcr & BOOT_PLL_ASYNC_MODE)
248 cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
249 &clocks->cpu, bootcr, AR7_AFE_CLOCK);
250 else
251 cpu_clk.rate = bus_clk.rate;
252
253 if (dsp_clk.rate == 250000000)
254 tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
255 bootcr, dsp_clk.rate);
256
257 iounmap(clocks);
258 iounmap(bootcr);
259}
260
261static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
262 int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
263{
264 printk(KERN_INFO
265 "Clocks: base = %d, frequency = %u, prediv = %d, "
266 "postdiv = %d, postdiv2 = %d, mul = %d\n",
267 base, frequency, prediv, postdiv, postdiv2, mul);
268
269 writel(0, &clock->ctrl);
270 writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
271 writel((mul - 1) & 0xF, &clock->mul);
272
273 while (readl(&clock->status) & 0x1)
274 ; /* nop */
275
276 writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
277
278 writel(readl(&clock->cmden) | 1, &clock->cmden);
279 writel(readl(&clock->cmd) | 1, &clock->cmd);
280
281 while (readl(&clock->status) & 0x1)
282 ; /* nop */
283
284 writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
285
286 writel(readl(&clock->cmden) | 1, &clock->cmden);
287 writel(readl(&clock->cmd) | 1, &clock->cmd);
288
289 while (readl(&clock->status) & 0x1)
290 ; /* nop */
291
292 writel(readl(&clock->ctrl) | 1, &clock->ctrl);
293}
294
295static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
296{
297 if (*bootcr & BOOT_PLL_ASYNC_MODE)
298 /* Async */
299 switch (clock_id) {
300 case TNETD7200_CLOCK_ID_DSP:
301 return AR7_REF_CLOCK;
302 default:
303 return AR7_AFE_CLOCK;
304 }
305 else
306 /* Sync */
307 if (*bootcr & BOOT_PLL_2TO1_MODE)
308 /* 2:1 */
309 switch (clock_id) {
310 case TNETD7200_CLOCK_ID_DSP:
311 return AR7_REF_CLOCK;
312 default:
313 return AR7_AFE_CLOCK;
314 }
315 else
316 /* 1:1 */
317 return AR7_REF_CLOCK;
318}
319
320
321static void __init tnetd7200_init_clocks(void)
322{
323 u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
324 struct tnetd7200_clocks *clocks =
325 ioremap(AR7_REGS_CLOCKS,
326 sizeof(struct tnetd7200_clocks));
327 int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
328 int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
329 int usb_base, usb_mul, usb_prediv, usb_postdiv;
330
331 cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
332 dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
333
334 if (*bootcr & BOOT_PLL_ASYNC_MODE) {
335 printk(KERN_INFO "Clocks: Async mode\n");
336
337 printk(KERN_INFO "Clocks: Setting DSP clock\n");
338 calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
339 &dsp_prediv, &dsp_postdiv, &dsp_mul);
340 bus_clk.rate =
341 ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
342 tnetd7200_set_clock(dsp_base, &clocks->dsp,
343 dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
344 bus_clk.rate);
345
346 printk(KERN_INFO "Clocks: Setting CPU clock\n");
347 calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
348 &cpu_postdiv, &cpu_mul);
349 cpu_clk.rate =
350 ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
351 tnetd7200_set_clock(cpu_base, &clocks->cpu,
352 cpu_prediv, cpu_postdiv, -1, cpu_mul,
353 cpu_clk.rate);
354
355 } else
356 if (*bootcr & BOOT_PLL_2TO1_MODE) {
357 printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
358
359 printk(KERN_INFO "Clocks: Setting CPU clock\n");
360 calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
361 &cpu_postdiv, &cpu_mul);
362 cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
363 / cpu_postdiv;
364 tnetd7200_set_clock(cpu_base, &clocks->cpu,
365 cpu_prediv, cpu_postdiv, -1, cpu_mul,
366 cpu_clk.rate);
367
368 printk(KERN_INFO "Clocks: Setting DSP clock\n");
369 calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
370 &dsp_postdiv, &dsp_mul);
371 bus_clk.rate = cpu_clk.rate / 2;
372 tnetd7200_set_clock(dsp_base, &clocks->dsp,
373 dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
374 dsp_mul * 2, bus_clk.rate);
375 } else {
376 printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
377
378 printk(KERN_INFO "Clocks: Setting DSP clock\n");
379 calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
380 &dsp_postdiv, &dsp_mul);
381 bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
382 / dsp_postdiv;
383 tnetd7200_set_clock(dsp_base, &clocks->dsp,
384 dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
385 dsp_mul * 2, bus_clk.rate);
386
387 cpu_clk.rate = bus_clk.rate;
388 }
389
390 printk(KERN_INFO "Clocks: Setting USB clock\n");
391 usb_base = bus_clk.rate;
392 calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
393 &usb_postdiv, &usb_mul);
394 tnetd7200_set_clock(usb_base, &clocks->usb,
395 usb_prediv, usb_postdiv, -1, usb_mul,
396 TNETD7200_DEF_USB_CLK);
397
398 dsp_clk.rate = cpu_clk.rate;
399
400 iounmap(clocks);
401 iounmap(bootcr);
402}
403
404/*
405 * Linux clock API
406 */
407int clk_enable(struct clk *clk)
408{
409 return 0;
410}
411EXPORT_SYMBOL(clk_enable);
412
413void clk_disable(struct clk *clk)
414{
415}
416EXPORT_SYMBOL(clk_disable);
417
418unsigned long clk_get_rate(struct clk *clk)
419{
420 if (!clk)
421 return 0;
422
423 return clk->rate;
424}
425EXPORT_SYMBOL(clk_get_rate);
426
427struct clk *clk_get(struct device *dev, const char *id)
428{
429 if (!strcmp(id, "bus"))
430 return &bus_clk;
431 /* cpmac and vbus share the same rate */
432 if (!strcmp(id, "cpmac"))
433 return &vbus_clk;
434 if (!strcmp(id, "cpu"))
435 return &cpu_clk;
436 if (!strcmp(id, "dsp"))
437 return &dsp_clk;
438 if (!strcmp(id, "vbus"))
439 return &vbus_clk;
440 return ERR_PTR(-ENOENT);
441}
442EXPORT_SYMBOL(clk_get);
443
444void clk_put(struct clk *clk)
445{
446}
447EXPORT_SYMBOL(clk_put);
448
449void __init ar7_init_clocks(void)
450{
451 switch (ar7_chip_id()) {
452 case AR7_CHIP_7100:
453 case AR7_CHIP_7200:
454 tnetd7200_init_clocks();
455 break;
456 case AR7_CHIP_7300:
457 dsp_clk.rate = tnetd7300_dsp_clock();
458 tnetd7300_init_clocks();
459 break;
460 default:
461 break;
462 }
463 /* adjust vbus clock rate */
464 vbus_clk.rate = bus_clk.rate / 2;
465}
466
467/* dummy functions, should not be called */
468long clk_round_rate(struct clk *clk, unsigned long rate)
469{
470 WARN_ON(clk);
471 return 0;
472}
473EXPORT_SYMBOL(clk_round_rate);
474
475int clk_set_rate(struct clk *clk, unsigned long rate)
476{
477 WARN_ON(clk);
478 return 0;
479}
480EXPORT_SYMBOL(clk_set_rate);
481
482int clk_set_parent(struct clk *clk, struct clk *parent)
483{
484 WARN_ON(clk);
485 return 0;
486}
487EXPORT_SYMBOL(clk_set_parent);
488
489struct clk *clk_get_parent(struct clk *clk)
490{
491 WARN_ON(clk);
492 return NULL;
493}
494EXPORT_SYMBOL(clk_get_parent);
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
new file mode 100644
index 000000000..8b006addd
--- /dev/null
+++ b/arch/mips/ar7/gpio.c
@@ -0,0 +1,331 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
5 * Copyright (C) 2009-2010 Florian Fainelli <florian@openwrt.org>
6 */
7
8#include <linux/init.h>
9#include <linux/export.h>
10#include <linux/gpio.h>
11
12#include <asm/mach-ar7/ar7.h>
13
14#define AR7_GPIO_MAX 32
15#define TITAN_GPIO_MAX 51
16
17struct ar7_gpio_chip {
18 void __iomem *regs;
19 struct gpio_chip chip;
20};
21
22static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
23{
24 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
25 void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
26
27 return !!(readl(gpio_in) & (1 << gpio));
28}
29
30static int titan_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
31{
32 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
33 void __iomem *gpio_in0 = gpch->regs + TITAN_GPIO_INPUT_0;
34 void __iomem *gpio_in1 = gpch->regs + TITAN_GPIO_INPUT_1;
35
36 return readl(gpio >> 5 ? gpio_in1 : gpio_in0) & (1 << (gpio & 0x1f));
37}
38
39static void ar7_gpio_set_value(struct gpio_chip *chip,
40 unsigned gpio, int value)
41{
42 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
43 void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT;
44 unsigned tmp;
45
46 tmp = readl(gpio_out) & ~(1 << gpio);
47 if (value)
48 tmp |= 1 << gpio;
49 writel(tmp, gpio_out);
50}
51
52static void titan_gpio_set_value(struct gpio_chip *chip,
53 unsigned gpio, int value)
54{
55 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
56 void __iomem *gpio_out0 = gpch->regs + TITAN_GPIO_OUTPUT_0;
57 void __iomem *gpio_out1 = gpch->regs + TITAN_GPIO_OUTPUT_1;
58 unsigned tmp;
59
60 tmp = readl(gpio >> 5 ? gpio_out1 : gpio_out0) & ~(1 << (gpio & 0x1f));
61 if (value)
62 tmp |= 1 << (gpio & 0x1f);
63 writel(tmp, gpio >> 5 ? gpio_out1 : gpio_out0);
64}
65
66static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
67{
68 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
69 void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
70
71 writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
72
73 return 0;
74}
75
76static int titan_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
77{
78 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
79 void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
80 void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
81
82 if (gpio >= TITAN_GPIO_MAX)
83 return -EINVAL;
84
85 writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) | (1 << (gpio & 0x1f)),
86 gpio >> 5 ? gpio_dir1 : gpio_dir0);
87 return 0;
88}
89
90static int ar7_gpio_direction_output(struct gpio_chip *chip,
91 unsigned gpio, int value)
92{
93 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
94 void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
95
96 ar7_gpio_set_value(chip, gpio, value);
97 writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
98
99 return 0;
100}
101
102static int titan_gpio_direction_output(struct gpio_chip *chip,
103 unsigned gpio, int value)
104{
105 struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
106 void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
107 void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
108
109 if (gpio >= TITAN_GPIO_MAX)
110 return -EINVAL;
111
112 titan_gpio_set_value(chip, gpio, value);
113 writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) & ~(1 <<
114 (gpio & 0x1f)), gpio >> 5 ? gpio_dir1 : gpio_dir0);
115
116 return 0;
117}
118
119static struct ar7_gpio_chip ar7_gpio_chip = {
120 .chip = {
121 .label = "ar7-gpio",
122 .direction_input = ar7_gpio_direction_input,
123 .direction_output = ar7_gpio_direction_output,
124 .set = ar7_gpio_set_value,
125 .get = ar7_gpio_get_value,
126 .base = 0,
127 .ngpio = AR7_GPIO_MAX,
128 }
129};
130
131static struct ar7_gpio_chip titan_gpio_chip = {
132 .chip = {
133 .label = "titan-gpio",
134 .direction_input = titan_gpio_direction_input,
135 .direction_output = titan_gpio_direction_output,
136 .set = titan_gpio_set_value,
137 .get = titan_gpio_get_value,
138 .base = 0,
139 .ngpio = TITAN_GPIO_MAX,
140 }
141};
142
143static inline int ar7_gpio_enable_ar7(unsigned gpio)
144{
145 void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
146
147 writel(readl(gpio_en) | (1 << gpio), gpio_en);
148
149 return 0;
150}
151
152static inline int ar7_gpio_enable_titan(unsigned gpio)
153{
154 void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
155 void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
156
157 writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) | (1 << (gpio & 0x1f)),
158 gpio >> 5 ? gpio_en1 : gpio_en0);
159
160 return 0;
161}
162
163int ar7_gpio_enable(unsigned gpio)
164{
165 return ar7_is_titan() ? ar7_gpio_enable_titan(gpio) :
166 ar7_gpio_enable_ar7(gpio);
167}
168EXPORT_SYMBOL(ar7_gpio_enable);
169
170static inline int ar7_gpio_disable_ar7(unsigned gpio)
171{
172 void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
173
174 writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
175
176 return 0;
177}
178
179static inline int ar7_gpio_disable_titan(unsigned gpio)
180{
181 void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
182 void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
183
184 writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) & ~(1 << (gpio & 0x1f)),
185 gpio >> 5 ? gpio_en1 : gpio_en0);
186
187 return 0;
188}
189
190int ar7_gpio_disable(unsigned gpio)
191{
192 return ar7_is_titan() ? ar7_gpio_disable_titan(gpio) :
193 ar7_gpio_disable_ar7(gpio);
194}
195EXPORT_SYMBOL(ar7_gpio_disable);
196
197struct titan_gpio_cfg {
198 u32 reg;
199 u32 shift;
200 u32 func;
201};
202
203static const struct titan_gpio_cfg titan_gpio_table[] = {
204 /* reg, start bit, mux value */
205 {4, 24, 1},
206 {4, 26, 1},
207 {4, 28, 1},
208 {4, 30, 1},
209 {5, 6, 1},
210 {5, 8, 1},
211 {5, 10, 1},
212 {5, 12, 1},
213 {7, 14, 3},
214 {7, 16, 3},
215 {7, 18, 3},
216 {7, 20, 3},
217 {7, 22, 3},
218 {7, 26, 3},
219 {7, 28, 3},
220 {7, 30, 3},
221 {8, 0, 3},
222 {8, 2, 3},
223 {8, 4, 3},
224 {8, 10, 3},
225 {8, 14, 3},
226 {8, 16, 3},
227 {8, 18, 3},
228 {8, 20, 3},
229 {9, 8, 3},
230 {9, 10, 3},
231 {9, 12, 3},
232 {9, 14, 3},
233 {9, 18, 3},
234 {9, 20, 3},
235 {9, 24, 3},
236 {9, 26, 3},
237 {9, 28, 3},
238 {9, 30, 3},
239 {10, 0, 3},
240 {10, 2, 3},
241 {10, 8, 3},
242 {10, 10, 3},
243 {10, 12, 3},
244 {10, 14, 3},
245 {13, 12, 3},
246 {13, 14, 3},
247 {13, 16, 3},
248 {13, 18, 3},
249 {13, 24, 3},
250 {13, 26, 3},
251 {13, 28, 3},
252 {13, 30, 3},
253 {14, 2, 3},
254 {14, 6, 3},
255 {14, 8, 3},
256 {14, 12, 3}
257};
258
259static int titan_gpio_pinsel(unsigned gpio)
260{
261 struct titan_gpio_cfg gpio_cfg;
262 u32 mux_status, pin_sel_reg, tmp;
263 void __iomem *pin_sel = (void __iomem *)KSEG1ADDR(AR7_REGS_PINSEL);
264
265 if (gpio >= ARRAY_SIZE(titan_gpio_table))
266 return -EINVAL;
267
268 gpio_cfg = titan_gpio_table[gpio];
269 pin_sel_reg = gpio_cfg.reg - 1;
270
271 mux_status = (readl(pin_sel + pin_sel_reg) >> gpio_cfg.shift) & 0x3;
272
273 /* Check the mux status */
274 if (!((mux_status == 0) || (mux_status == gpio_cfg.func)))
275 return 0;
276
277 /* Set the pin sel value */
278 tmp = readl(pin_sel + pin_sel_reg);
279 tmp |= ((gpio_cfg.func & 0x3) << gpio_cfg.shift);
280 writel(tmp, pin_sel + pin_sel_reg);
281
282 return 0;
283}
284
285/* Perform minimal Titan GPIO configuration */
286static void titan_gpio_init(void)
287{
288 unsigned i;
289
290 for (i = 44; i < 48; i++) {
291 titan_gpio_pinsel(i);
292 ar7_gpio_enable_titan(i);
293 titan_gpio_direction_input(&titan_gpio_chip.chip, i);
294 }
295}
296
297int __init ar7_gpio_init(void)
298{
299 int ret;
300 struct ar7_gpio_chip *gpch;
301 unsigned size;
302
303 if (!ar7_is_titan()) {
304 gpch = &ar7_gpio_chip;
305 size = 0x10;
306 } else {
307 gpch = &titan_gpio_chip;
308 size = 0x1f;
309 }
310
311 gpch->regs = ioremap(AR7_REGS_GPIO, size);
312 if (!gpch->regs) {
313 printk(KERN_ERR "%s: failed to ioremap regs\n",
314 gpch->chip.label);
315 return -ENOMEM;
316 }
317
318 ret = gpiochip_add_data(&gpch->chip, gpch);
319 if (ret) {
320 printk(KERN_ERR "%s: failed to add gpiochip\n",
321 gpch->chip.label);
322 return ret;
323 }
324 printk(KERN_INFO "%s: registered %d GPIOs\n",
325 gpch->chip.label, gpch->chip.ngpio);
326
327 if (ar7_is_titan())
328 titan_gpio_init();
329
330 return ret;
331}
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
new file mode 100644
index 000000000..f0a7942d3
--- /dev/null
+++ b/arch/mips/ar7/irq.c
@@ -0,0 +1,165 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
5 */
6
7#include <linux/interrupt.h>
8#include <linux/io.h>
9#include <linux/irq.h>
10
11#include <asm/irq_cpu.h>
12#include <asm/mipsregs.h>
13#include <asm/mach-ar7/ar7.h>
14
15#define EXCEPT_OFFSET 0x80
16#define PACE_OFFSET 0xA0
17#define CHNLS_OFFSET 0x200
18
19#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10)
20#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8)
21#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */
22#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */
23#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */
24#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */
25#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */
26#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */
27#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */
28#define PIR_OFFSET (0x40)
29#define MSR_OFFSET (0x44)
30#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */
31#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */
32
33#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
34
35#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
36
37static int ar7_irq_base;
38
39static void ar7_unmask_irq(struct irq_data *d)
40{
41 writel(1 << ((d->irq - ar7_irq_base) % 32),
42 REG(ESR_OFFSET(d->irq - ar7_irq_base)));
43}
44
45static void ar7_mask_irq(struct irq_data *d)
46{
47 writel(1 << ((d->irq - ar7_irq_base) % 32),
48 REG(ECR_OFFSET(d->irq - ar7_irq_base)));
49}
50
51static void ar7_ack_irq(struct irq_data *d)
52{
53 writel(1 << ((d->irq - ar7_irq_base) % 32),
54 REG(CR_OFFSET(d->irq - ar7_irq_base)));
55}
56
57static void ar7_unmask_sec_irq(struct irq_data *d)
58{
59 writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
60}
61
62static void ar7_mask_sec_irq(struct irq_data *d)
63{
64 writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
65}
66
67static void ar7_ack_sec_irq(struct irq_data *d)
68{
69 writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
70}
71
72static struct irq_chip ar7_irq_type = {
73 .name = "AR7",
74 .irq_unmask = ar7_unmask_irq,
75 .irq_mask = ar7_mask_irq,
76 .irq_ack = ar7_ack_irq
77};
78
79static struct irq_chip ar7_sec_irq_type = {
80 .name = "AR7",
81 .irq_unmask = ar7_unmask_sec_irq,
82 .irq_mask = ar7_mask_sec_irq,
83 .irq_ack = ar7_ack_sec_irq,
84};
85
86static void __init ar7_irq_init(int base)
87{
88 int i;
89 /*
90 * Disable interrupts and clear pending
91 */
92 writel(0xffffffff, REG(ECR_OFFSET(0)));
93 writel(0xff, REG(ECR_OFFSET(32)));
94 writel(0xffffffff, REG(SEC_ECR_OFFSET));
95 writel(0xffffffff, REG(CR_OFFSET(0)));
96 writel(0xff, REG(CR_OFFSET(32)));
97 writel(0xffffffff, REG(SEC_CR_OFFSET));
98
99 ar7_irq_base = base;
100
101 for (i = 0; i < 40; i++) {
102 writel(i, REG(CHNL_OFFSET(i)));
103 /* Primary IRQ's */
104 irq_set_chip_and_handler(base + i, &ar7_irq_type,
105 handle_level_irq);
106 /* Secondary IRQ's */
107 if (i < 32)
108 irq_set_chip_and_handler(base + i + 40,
109 &ar7_sec_irq_type,
110 handle_level_irq);
111 }
112
113 if (request_irq(2, no_action, IRQF_NO_THREAD, "AR7 cascade interrupt",
114 NULL))
115 pr_err("Failed to request irq 2 (AR7 cascade interrupt)\n");
116 if (request_irq(ar7_irq_base, no_action, IRQF_NO_THREAD,
117 "AR7 cascade interrupt", NULL)) {
118 pr_err("Failed to request irq %d (AR7 cascade interrupt)\n",
119 ar7_irq_base);
120 }
121 set_c0_status(IE_IRQ0);
122}
123
124void __init arch_init_irq(void)
125{
126 mips_cpu_irq_init();
127 ar7_irq_init(8);
128}
129
130static void ar7_cascade(void)
131{
132 u32 status;
133 int i, irq;
134
135 /* Primary IRQ's */
136 irq = readl(REG(PIR_OFFSET)) & 0x3f;
137 if (irq) {
138 do_IRQ(ar7_irq_base + irq);
139 return;
140 }
141
142 /* Secondary IRQ's are cascaded through primary '0' */
143 writel(1, REG(CR_OFFSET(irq)));
144 status = readl(REG(SEC_SR_OFFSET));
145 for (i = 0; i < 32; i++) {
146 if (status & 1) {
147 do_IRQ(ar7_irq_base + i + 40);
148 return;
149 }
150 status >>= 1;
151 }
152
153 spurious_interrupt();
154}
155
156asmlinkage void plat_irq_dispatch(void)
157{
158 unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
159 if (pending & STATUSF_IP7) /* cpu timer */
160 do_IRQ(7);
161 else if (pending & STATUSF_IP2) /* int0 hardware line */
162 ar7_cascade();
163 else
164 spurious_interrupt();
165}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
new file mode 100644
index 000000000..787716c5e
--- /dev/null
+++ b/arch/mips/ar7/memory.c
@@ -0,0 +1,56 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
5 */
6#include <linux/memblock.h>
7#include <linux/init.h>
8#include <linux/mm.h>
9#include <linux/pfn.h>
10#include <linux/proc_fs.h>
11#include <linux/string.h>
12#include <linux/swap.h>
13
14#include <asm/bootinfo.h>
15#include <asm/page.h>
16#include <asm/sections.h>
17
18#include <asm/mach-ar7/ar7.h>
19
20static int __init memsize(void)
21{
22 u32 size = (64 << 20);
23 u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
24 u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
25 u32 *tmpaddr = addr;
26
27 while (tmpaddr > kernel_end) {
28 *tmpaddr = (u32)tmpaddr;
29 size >>= 1;
30 tmpaddr -= size >> 2;
31 }
32
33 do {
34 tmpaddr += size >> 2;
35 if (*tmpaddr != (u32)tmpaddr)
36 break;
37 size <<= 1;
38 } while (size < (64 << 20));
39
40 writel((u32)tmpaddr, &addr);
41
42 return size;
43}
44
45void __init prom_meminit(void)
46{
47 unsigned long pages;
48
49 pages = memsize() >> PAGE_SHIFT;
50 memblock_add(PHYS_OFFSET, pages << PAGE_SHIFT);
51}
52
53void __init prom_free_prom_memory(void)
54{
55 /* Nothing to free */
56}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
new file mode 100644
index 000000000..215149a85
--- /dev/null
+++ b/arch/mips/ar7/platform.c
@@ -0,0 +1,722 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
5 */
6
7#include <linux/init.h>
8#include <linux/types.h>
9#include <linux/delay.h>
10#include <linux/dma-mapping.h>
11#include <linux/platform_device.h>
12#include <linux/mtd/physmap.h>
13#include <linux/serial.h>
14#include <linux/serial_8250.h>
15#include <linux/ioport.h>
16#include <linux/io.h>
17#include <linux/vlynq.h>
18#include <linux/leds.h>
19#include <linux/string.h>
20#include <linux/etherdevice.h>
21#include <linux/phy.h>
22#include <linux/phy_fixed.h>
23#include <linux/gpio.h>
24#include <linux/clk.h>
25
26#include <asm/addrspace.h>
27#include <asm/mach-ar7/ar7.h>
28#include <asm/mach-ar7/prom.h>
29
30/*****************************************************************************
31 * VLYNQ Bus
32 ****************************************************************************/
33struct plat_vlynq_data {
34 struct plat_vlynq_ops ops;
35 int gpio_bit;
36 int reset_bit;
37};
38
39static int vlynq_on(struct vlynq_device *dev)
40{
41 int ret;
42 struct plat_vlynq_data *pdata = dev->dev.platform_data;
43
44 ret = gpio_request(pdata->gpio_bit, "vlynq");
45 if (ret)
46 goto out;
47
48 ar7_device_reset(pdata->reset_bit);
49
50 ret = ar7_gpio_disable(pdata->gpio_bit);
51 if (ret)
52 goto out_enabled;
53
54 ret = ar7_gpio_enable(pdata->gpio_bit);
55 if (ret)
56 goto out_enabled;
57
58 ret = gpio_direction_output(pdata->gpio_bit, 0);
59 if (ret)
60 goto out_gpio_enabled;
61
62 msleep(50);
63
64 gpio_set_value(pdata->gpio_bit, 1);
65
66 msleep(50);
67
68 return 0;
69
70out_gpio_enabled:
71 ar7_gpio_disable(pdata->gpio_bit);
72out_enabled:
73 ar7_device_disable(pdata->reset_bit);
74 gpio_free(pdata->gpio_bit);
75out:
76 return ret;
77}
78
79static void vlynq_off(struct vlynq_device *dev)
80{
81 struct plat_vlynq_data *pdata = dev->dev.platform_data;
82
83 ar7_gpio_disable(pdata->gpio_bit);
84 gpio_free(pdata->gpio_bit);
85 ar7_device_disable(pdata->reset_bit);
86}
87
88static struct resource vlynq_low_res[] = {
89 {
90 .name = "regs",
91 .flags = IORESOURCE_MEM,
92 .start = AR7_REGS_VLYNQ0,
93 .end = AR7_REGS_VLYNQ0 + 0xff,
94 },
95 {
96 .name = "irq",
97 .flags = IORESOURCE_IRQ,
98 .start = 29,
99 .end = 29,
100 },
101 {
102 .name = "mem",
103 .flags = IORESOURCE_MEM,
104 .start = 0x04000000,
105 .end = 0x04ffffff,
106 },
107 {
108 .name = "devirq",
109 .flags = IORESOURCE_IRQ,
110 .start = 80,
111 .end = 111,
112 },
113};
114
115static struct resource vlynq_high_res[] = {
116 {
117 .name = "regs",
118 .flags = IORESOURCE_MEM,
119 .start = AR7_REGS_VLYNQ1,
120 .end = AR7_REGS_VLYNQ1 + 0xff,
121 },
122 {
123 .name = "irq",
124 .flags = IORESOURCE_IRQ,
125 .start = 33,
126 .end = 33,
127 },
128 {
129 .name = "mem",
130 .flags = IORESOURCE_MEM,
131 .start = 0x0c000000,
132 .end = 0x0cffffff,
133 },
134 {
135 .name = "devirq",
136 .flags = IORESOURCE_IRQ,
137 .start = 112,
138 .end = 143,
139 },
140};
141
142static struct plat_vlynq_data vlynq_low_data = {
143 .ops = {
144 .on = vlynq_on,
145 .off = vlynq_off,
146 },
147 .reset_bit = 20,
148 .gpio_bit = 18,
149};
150
151static struct plat_vlynq_data vlynq_high_data = {
152 .ops = {
153 .on = vlynq_on,
154 .off = vlynq_off,
155 },
156 .reset_bit = 16,
157 .gpio_bit = 19,
158};
159
160static struct platform_device vlynq_low = {
161 .id = 0,
162 .name = "vlynq",
163 .dev = {
164 .platform_data = &vlynq_low_data,
165 },
166 .resource = vlynq_low_res,
167 .num_resources = ARRAY_SIZE(vlynq_low_res),
168};
169
170static struct platform_device vlynq_high = {
171 .id = 1,
172 .name = "vlynq",
173 .dev = {
174 .platform_data = &vlynq_high_data,
175 },
176 .resource = vlynq_high_res,
177 .num_resources = ARRAY_SIZE(vlynq_high_res),
178};
179
180/*****************************************************************************
181 * Flash
182 ****************************************************************************/
183static struct resource physmap_flash_resource = {
184 .name = "mem",
185 .flags = IORESOURCE_MEM,
186 .start = 0x10000000,
187 .end = 0x107fffff,
188};
189
190static const char *ar7_probe_types[] = { "ar7part", NULL };
191
192static struct physmap_flash_data physmap_flash_data = {
193 .width = 2,
194 .part_probe_types = ar7_probe_types,
195};
196
197static struct platform_device physmap_flash = {
198 .name = "physmap-flash",
199 .dev = {
200 .platform_data = &physmap_flash_data,
201 },
202 .resource = &physmap_flash_resource,
203 .num_resources = 1,
204};
205
206/*****************************************************************************
207 * Ethernet
208 ****************************************************************************/
209static struct resource cpmac_low_res[] = {
210 {
211 .name = "regs",
212 .flags = IORESOURCE_MEM,
213 .start = AR7_REGS_MAC0,
214 .end = AR7_REGS_MAC0 + 0x7ff,
215 },
216 {
217 .name = "irq",
218 .flags = IORESOURCE_IRQ,
219 .start = 27,
220 .end = 27,
221 },
222};
223
224static struct resource cpmac_high_res[] = {
225 {
226 .name = "regs",
227 .flags = IORESOURCE_MEM,
228 .start = AR7_REGS_MAC1,
229 .end = AR7_REGS_MAC1 + 0x7ff,
230 },
231 {
232 .name = "irq",
233 .flags = IORESOURCE_IRQ,
234 .start = 41,
235 .end = 41,
236 },
237};
238
239static struct fixed_phy_status fixed_phy_status __initdata = {
240 .link = 1,
241 .speed = 100,
242 .duplex = 1,
243};
244
245static struct plat_cpmac_data cpmac_low_data = {
246 .reset_bit = 17,
247 .power_bit = 20,
248 .phy_mask = 0x80000000,
249};
250
251static struct plat_cpmac_data cpmac_high_data = {
252 .reset_bit = 21,
253 .power_bit = 22,
254 .phy_mask = 0x7fffffff,
255};
256
257static u64 cpmac_dma_mask = DMA_BIT_MASK(32);
258
259static struct platform_device cpmac_low = {
260 .id = 0,
261 .name = "cpmac",
262 .dev = {
263 .dma_mask = &cpmac_dma_mask,
264 .coherent_dma_mask = DMA_BIT_MASK(32),
265 .platform_data = &cpmac_low_data,
266 },
267 .resource = cpmac_low_res,
268 .num_resources = ARRAY_SIZE(cpmac_low_res),
269};
270
271static struct platform_device cpmac_high = {
272 .id = 1,
273 .name = "cpmac",
274 .dev = {
275 .dma_mask = &cpmac_dma_mask,
276 .coherent_dma_mask = DMA_BIT_MASK(32),
277 .platform_data = &cpmac_high_data,
278 },
279 .resource = cpmac_high_res,
280 .num_resources = ARRAY_SIZE(cpmac_high_res),
281};
282
283static void __init cpmac_get_mac(int instance, unsigned char *dev_addr)
284{
285 char name[5], *mac;
286
287 sprintf(name, "mac%c", 'a' + instance);
288 mac = prom_getenv(name);
289 if (!mac && instance) {
290 sprintf(name, "mac%c", 'a');
291 mac = prom_getenv(name);
292 }
293
294 if (mac) {
295 if (!mac_pton(mac, dev_addr)) {
296 pr_warn("cannot parse mac address, using random address\n");
297 eth_random_addr(dev_addr);
298 }
299 } else
300 eth_random_addr(dev_addr);
301}
302
303/*****************************************************************************
304 * USB
305 ****************************************************************************/
306static struct resource usb_res[] = {
307 {
308 .name = "regs",
309 .flags = IORESOURCE_MEM,
310 .start = AR7_REGS_USB,
311 .end = AR7_REGS_USB + 0xff,
312 },
313 {
314 .name = "irq",
315 .flags = IORESOURCE_IRQ,
316 .start = 32,
317 .end = 32,
318 },
319 {
320 .name = "mem",
321 .flags = IORESOURCE_MEM,
322 .start = 0x03400000,
323 .end = 0x03401fff,
324 },
325};
326
327static struct platform_device ar7_udc = {
328 .name = "ar7_udc",
329 .resource = usb_res,
330 .num_resources = ARRAY_SIZE(usb_res),
331};
332
333/*****************************************************************************
334 * LEDs
335 ****************************************************************************/
336static const struct gpio_led default_leds[] = {
337 {
338 .name = "status",
339 .gpio = 8,
340 .active_low = 1,
341 },
342};
343
344static const struct gpio_led titan_leds[] = {
345 { .name = "status", .gpio = 8, .active_low = 1, },
346 { .name = "wifi", .gpio = 13, .active_low = 1, },
347};
348
349static const struct gpio_led dsl502t_leds[] = {
350 {
351 .name = "status",
352 .gpio = 9,
353 .active_low = 1,
354 },
355 {
356 .name = "ethernet",
357 .gpio = 7,
358 .active_low = 1,
359 },
360 {
361 .name = "usb",
362 .gpio = 12,
363 .active_low = 1,
364 },
365};
366
367static const struct gpio_led dg834g_leds[] = {
368 {
369 .name = "ppp",
370 .gpio = 6,
371 .active_low = 1,
372 },
373 {
374 .name = "status",
375 .gpio = 7,
376 .active_low = 1,
377 },
378 {
379 .name = "adsl",
380 .gpio = 8,
381 .active_low = 1,
382 },
383 {
384 .name = "wifi",
385 .gpio = 12,
386 .active_low = 1,
387 },
388 {
389 .name = "power",
390 .gpio = 14,
391 .active_low = 1,
392 .default_trigger = "default-on",
393 },
394};
395
396static const struct gpio_led fb_sl_leds[] = {
397 {
398 .name = "1",
399 .gpio = 7,
400 },
401 {
402 .name = "2",
403 .gpio = 13,
404 .active_low = 1,
405 },
406 {
407 .name = "3",
408 .gpio = 10,
409 .active_low = 1,
410 },
411 {
412 .name = "4",
413 .gpio = 12,
414 .active_low = 1,
415 },
416 {
417 .name = "5",
418 .gpio = 9,
419 .active_low = 1,
420 },
421};
422
423static const struct gpio_led fb_fon_leds[] = {
424 {
425 .name = "1",
426 .gpio = 8,
427 },
428 {
429 .name = "2",
430 .gpio = 3,
431 .active_low = 1,
432 },
433 {
434 .name = "3",
435 .gpio = 5,
436 },
437 {
438 .name = "4",
439 .gpio = 4,
440 .active_low = 1,
441 },
442 {
443 .name = "5",
444 .gpio = 11,
445 .active_low = 1,
446 },
447};
448
449static const struct gpio_led gt701_leds[] = {
450 {
451 .name = "inet:green",
452 .gpio = 13,
453 .active_low = 1,
454 },
455 {
456 .name = "usb",
457 .gpio = 12,
458 .active_low = 1,
459 },
460 {
461 .name = "inet:red",
462 .gpio = 9,
463 .active_low = 1,
464 },
465 {
466 .name = "power:red",
467 .gpio = 7,
468 .active_low = 1,
469 },
470 {
471 .name = "power:green",
472 .gpio = 8,
473 .active_low = 1,
474 .default_trigger = "default-on",
475 },
476 {
477 .name = "ethernet",
478 .gpio = 10,
479 .active_low = 1,
480 },
481};
482
483static struct gpio_led_platform_data ar7_led_data;
484
485static struct platform_device ar7_gpio_leds = {
486 .name = "leds-gpio",
487 .dev = {
488 .platform_data = &ar7_led_data,
489 }
490};
491
492static void __init detect_leds(void)
493{
494 char *prid, *usb_prod;
495
496 /* Default LEDs */
497 ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
498 ar7_led_data.leds = default_leds;
499
500 /* FIXME: the whole thing is unreliable */
501 prid = prom_getenv("ProductID");
502 usb_prod = prom_getenv("usb_prod");
503
504 /* If we can't get the product id from PROM, use the default LEDs */
505 if (!prid)
506 return;
507
508 if (strstr(prid, "Fritz_Box_FON")) {
509 ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
510 ar7_led_data.leds = fb_fon_leds;
511 } else if (strstr(prid, "Fritz_Box_")) {
512 ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
513 ar7_led_data.leds = fb_sl_leds;
514 } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
515 && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
516 ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
517 ar7_led_data.leds = dsl502t_leds;
518 } else if (strstr(prid, "DG834")) {
519 ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
520 ar7_led_data.leds = dg834g_leds;
521 } else if (strstr(prid, "CYWM") || strstr(prid, "CYWL")) {
522 ar7_led_data.num_leds = ARRAY_SIZE(titan_leds);
523 ar7_led_data.leds = titan_leds;
524 } else if (strstr(prid, "GT701")) {
525 ar7_led_data.num_leds = ARRAY_SIZE(gt701_leds);
526 ar7_led_data.leds = gt701_leds;
527 }
528}
529
530/*****************************************************************************
531 * Watchdog
532 ****************************************************************************/
533static struct resource ar7_wdt_res = {
534 .name = "regs",
535 .flags = IORESOURCE_MEM,
536 .start = -1, /* Filled at runtime */
537 .end = -1, /* Filled at runtime */
538};
539
540static struct platform_device ar7_wdt = {
541 .name = "ar7_wdt",
542 .resource = &ar7_wdt_res,
543 .num_resources = 1,
544};
545
546/*****************************************************************************
547 * Init
548 ****************************************************************************/
549static int __init ar7_register_uarts(void)
550{
551#ifdef CONFIG_SERIAL_8250
552 static struct uart_port uart_port __initdata;
553 struct clk *bus_clk;
554 int res;
555
556 memset(&uart_port, 0, sizeof(struct uart_port));
557
558 bus_clk = clk_get(NULL, "bus");
559 if (IS_ERR(bus_clk))
560 panic("unable to get bus clk");
561
562 uart_port.type = PORT_AR7;
563 uart_port.uartclk = clk_get_rate(bus_clk) / 2;
564 uart_port.iotype = UPIO_MEM32;
565 uart_port.flags = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF;
566 uart_port.regshift = 2;
567
568 uart_port.line = 0;
569 uart_port.irq = AR7_IRQ_UART0;
570 uart_port.mapbase = AR7_REGS_UART0;
571 uart_port.membase = ioremap(uart_port.mapbase, 256);
572
573 res = early_serial_setup(&uart_port);
574 if (res)
575 return res;
576
577 /* Only TNETD73xx have a second serial port */
578 if (ar7_has_second_uart()) {
579 uart_port.line = 1;
580 uart_port.irq = AR7_IRQ_UART1;
581 uart_port.mapbase = UR8_REGS_UART1;
582 uart_port.membase = ioremap(uart_port.mapbase, 256);
583
584 res = early_serial_setup(&uart_port);
585 if (res)
586 return res;
587 }
588#endif
589
590 return 0;
591}
592
593static void __init titan_fixup_devices(void)
594{
595 /* Set vlynq0 data */
596 vlynq_low_data.reset_bit = 15;
597 vlynq_low_data.gpio_bit = 14;
598
599 /* Set vlynq1 data */
600 vlynq_high_data.reset_bit = 16;
601 vlynq_high_data.gpio_bit = 7;
602
603 /* Set vlynq0 resources */
604 vlynq_low_res[0].start = TITAN_REGS_VLYNQ0;
605 vlynq_low_res[0].end = TITAN_REGS_VLYNQ0 + 0xff;
606 vlynq_low_res[1].start = 33;
607 vlynq_low_res[1].end = 33;
608 vlynq_low_res[2].start = 0x0c000000;
609 vlynq_low_res[2].end = 0x0fffffff;
610 vlynq_low_res[3].start = 80;
611 vlynq_low_res[3].end = 111;
612
613 /* Set vlynq1 resources */
614 vlynq_high_res[0].start = TITAN_REGS_VLYNQ1;
615 vlynq_high_res[0].end = TITAN_REGS_VLYNQ1 + 0xff;
616 vlynq_high_res[1].start = 34;
617 vlynq_high_res[1].end = 34;
618 vlynq_high_res[2].start = 0x40000000;
619 vlynq_high_res[2].end = 0x43ffffff;
620 vlynq_high_res[3].start = 112;
621 vlynq_high_res[3].end = 143;
622
623 /* Set cpmac0 data */
624 cpmac_low_data.phy_mask = 0x40000000;
625
626 /* Set cpmac1 data */
627 cpmac_high_data.phy_mask = 0x80000000;
628
629 /* Set cpmac0 resources */
630 cpmac_low_res[0].start = TITAN_REGS_MAC0;
631 cpmac_low_res[0].end = TITAN_REGS_MAC0 + 0x7ff;
632
633 /* Set cpmac1 resources */
634 cpmac_high_res[0].start = TITAN_REGS_MAC1;
635 cpmac_high_res[0].end = TITAN_REGS_MAC1 + 0x7ff;
636}
637
638static int __init ar7_register_devices(void)
639{
640 void __iomem *bootcr;
641 u32 val;
642 int res;
643
644 res = ar7_gpio_init();
645 if (res)
646 pr_warn("unable to register gpios: %d\n", res);
647
648 res = ar7_register_uarts();
649 if (res)
650 pr_err("unable to setup uart(s): %d\n", res);
651
652 res = platform_device_register(&physmap_flash);
653 if (res)
654 pr_warn("unable to register physmap-flash: %d\n", res);
655
656 if (ar7_is_titan())
657 titan_fixup_devices();
658
659 ar7_device_disable(vlynq_low_data.reset_bit);
660 res = platform_device_register(&vlynq_low);
661 if (res)
662 pr_warn("unable to register vlynq-low: %d\n", res);
663
664 if (ar7_has_high_vlynq()) {
665 ar7_device_disable(vlynq_high_data.reset_bit);
666 res = platform_device_register(&vlynq_high);
667 if (res)
668 pr_warn("unable to register vlynq-high: %d\n", res);
669 }
670
671 if (ar7_has_high_cpmac()) {
672 res = fixed_phy_add(PHY_POLL, cpmac_high.id,
673 &fixed_phy_status);
674 if (!res) {
675 cpmac_get_mac(1, cpmac_high_data.dev_addr);
676
677 res = platform_device_register(&cpmac_high);
678 if (res)
679 pr_warn("unable to register cpmac-high: %d\n",
680 res);
681 } else
682 pr_warn("unable to add cpmac-high phy: %d\n", res);
683 } else
684 cpmac_low_data.phy_mask = 0xffffffff;
685
686 res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
687 if (!res) {
688 cpmac_get_mac(0, cpmac_low_data.dev_addr);
689 res = platform_device_register(&cpmac_low);
690 if (res)
691 pr_warn("unable to register cpmac-low: %d\n", res);
692 } else
693 pr_warn("unable to add cpmac-low phy: %d\n", res);
694
695 detect_leds();
696 res = platform_device_register(&ar7_gpio_leds);
697 if (res)
698 pr_warn("unable to register leds: %d\n", res);
699
700 res = platform_device_register(&ar7_udc);
701 if (res)
702 pr_warn("unable to register usb slave: %d\n", res);
703
704 /* Register watchdog only if enabled in hardware */
705 bootcr = ioremap(AR7_REGS_DCL, 4);
706 val = readl(bootcr);
707 iounmap(bootcr);
708 if (val & AR7_WDT_HW_ENA) {
709 if (ar7_has_high_vlynq())
710 ar7_wdt_res.start = UR8_REGS_WDT;
711 else
712 ar7_wdt_res.start = AR7_REGS_WDT;
713
714 ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
715 res = platform_device_register(&ar7_wdt);
716 if (res)
717 pr_warn("unable to register watchdog: %d\n", res);
718 }
719
720 return 0;
721}
722device_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
new file mode 100644
index 000000000..5810d3993
--- /dev/null
+++ b/arch/mips/ar7/prom.c
@@ -0,0 +1,256 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Carsten Langgaard, carstenl@mips.com
4 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
5 *
6 * Putting things on the screen/serial line using YAMONs facilities.
7 */
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/serial_reg.h>
11#include <linux/spinlock.h>
12#include <linux/export.h>
13#include <linux/string.h>
14#include <linux/io.h>
15#include <asm/bootinfo.h>
16#include <asm/setup.h>
17
18#include <asm/mach-ar7/ar7.h>
19#include <asm/mach-ar7/prom.h>
20
21#define MAX_ENTRY 80
22
23struct env_var {
24 char *name;
25 char *value;
26};
27
28static struct env_var adam2_env[MAX_ENTRY];
29
30char *prom_getenv(const char *name)
31{
32 int i;
33
34 for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++)
35 if (!strcmp(name, adam2_env[i].name))
36 return adam2_env[i].value;
37
38 return NULL;
39}
40EXPORT_SYMBOL(prom_getenv);
41
42static void __init ar7_init_cmdline(int argc, char *argv[])
43{
44 int i;
45
46 for (i = 1; i < argc; i++) {
47 strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE);
48 if (i < (argc - 1))
49 strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
50 }
51}
52
53struct psbl_rec {
54 u32 psbl_size;
55 u32 env_base;
56 u32 env_size;
57 u32 ffs_base;
58 u32 ffs_size;
59};
60
61static const char psp_env_version[] __initconst = "TIENV0.8";
62
63struct psp_env_chunk {
64 u8 num;
65 u8 ctrl;
66 u16 csum;
67 u8 len;
68 char data[11];
69} __packed;
70
71struct psp_var_map_entry {
72 u8 num;
73 char *value;
74};
75
76static const struct psp_var_map_entry psp_var_map[] = {
77 { 1, "cpufrequency" },
78 { 2, "memsize" },
79 { 3, "flashsize" },
80 { 4, "modetty0" },
81 { 5, "modetty1" },
82 { 8, "maca" },
83 { 9, "macb" },
84 { 28, "sysfrequency" },
85 { 38, "mipsfrequency" },
86};
87
88/*
89
90Well-known variable (num is looked up in table above for matching variable name)
91Example: cpufrequency=211968000
92+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
93| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
94+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
95
96Name=Value pair in a single chunk
97Example: NAME=VALUE
98+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
99| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
100+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
101
102Name=Value pair in 2 chunks (len is the number of chunks)
103Example: bootloaderVersion=1.3.7.15
104+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
105| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
106+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
107| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
108+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
109
110Data is padded with 0xFF
111
112*/
113
114#define PSP_ENV_SIZE 4096
115
116static char psp_env_data[PSP_ENV_SIZE] = { 0, };
117
118static char * __init lookup_psp_var_map(u8 num)
119{
120 int i;
121
122 for (i = 0; i < ARRAY_SIZE(psp_var_map); i++)
123 if (psp_var_map[i].num == num)
124 return psp_var_map[i].value;
125
126 return NULL;
127}
128
129static void __init add_adam2_var(char *name, char *value)
130{
131 int i;
132
133 for (i = 0; i < MAX_ENTRY; i++) {
134 if (!adam2_env[i].name) {
135 adam2_env[i].name = name;
136 adam2_env[i].value = value;
137 return;
138 } else if (!strcmp(adam2_env[i].name, name)) {
139 adam2_env[i].value = value;
140 return;
141 }
142 }
143}
144
145static int __init parse_psp_env(void *psp_env_base)
146{
147 int i, n;
148 char *name, *value;
149 struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
150
151 memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
152
153 i = 1;
154 n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
155 while (i < n) {
156 if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
157 break;
158 value = chunks[i].data;
159 if (chunks[i].num) {
160 name = lookup_psp_var_map(chunks[i].num);
161 } else {
162 name = value;
163 value += strlen(name) + 1;
164 }
165 if (name)
166 add_adam2_var(name, value);
167 i += chunks[i].len;
168 }
169 return 0;
170}
171
172static void __init ar7_init_env(struct env_var *env)
173{
174 int i;
175 struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
176 void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
177
178 if (strcmp(psp_env, psp_env_version) == 0) {
179 parse_psp_env(psp_env);
180 } else {
181 for (i = 0; i < MAX_ENTRY; i++, env++)
182 if (env->name)
183 add_adam2_var(env->name, env->value);
184 }
185}
186
187static void __init console_config(void)
188{
189#ifdef CONFIG_SERIAL_8250_CONSOLE
190 char console_string[40];
191 int baud = 0;
192 char parity = '\0', bits = '\0', flow = '\0';
193 char *s, *p;
194
195 if (strstr(arcs_cmdline, "console="))
196 return;
197
198 s = prom_getenv("modetty0");
199 if (s) {
200 baud = simple_strtoul(s, &p, 10);
201 s = p;
202 if (*s == ',')
203 s++;
204 if (*s)
205 parity = *s++;
206 if (*s == ',')
207 s++;
208 if (*s)
209 bits = *s++;
210 if (*s == ',')
211 s++;
212 if (*s == 'h')
213 flow = 'r';
214 }
215
216 if (baud == 0)
217 baud = 38400;
218 if (parity != 'n' && parity != 'o' && parity != 'e')
219 parity = 'n';
220 if (bits != '7' && bits != '8')
221 bits = '8';
222
223 if (flow == 'r')
224 sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
225 parity, bits, flow);
226 else
227 sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
228 bits);
229 strlcat(arcs_cmdline, console_string, COMMAND_LINE_SIZE);
230#endif
231}
232
233void __init prom_init(void)
234{
235 ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
236 ar7_init_env((struct env_var *)fw_arg2);
237 console_config();
238}
239
240#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
241static inline unsigned int serial_in(int offset)
242{
243 return readl((void *)PORT(offset));
244}
245
246static inline void serial_out(int offset, int value)
247{
248 writel(value, (void *)PORT(offset));
249}
250
251void prom_putchar(char c)
252{
253 while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
254 ;
255 serial_out(UART_TX, c);
256}
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
new file mode 100644
index 000000000..352d5dbc7
--- /dev/null
+++ b/arch/mips/ar7/setup.c
@@ -0,0 +1,93 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Carsten Langgaard, carstenl@mips.com
4 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
5 */
6#include <linux/init.h>
7#include <linux/ioport.h>
8#include <linux/pm.h>
9#include <linux/time.h>
10
11#include <asm/reboot.h>
12#include <asm/mach-ar7/ar7.h>
13#include <asm/mach-ar7/prom.h>
14
15static void ar7_machine_restart(char *command)
16{
17 u32 *softres_reg = ioremap(AR7_REGS_RESET + AR7_RESET_SOFTWARE, 1);
18
19 writel(1, softres_reg);
20}
21
22static void ar7_machine_halt(void)
23{
24 while (1)
25 ;
26}
27
28static void ar7_machine_power_off(void)
29{
30 u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1);
31 u32 power_state = readl(power_reg) | (3 << 30);
32
33 writel(power_state, power_reg);
34 ar7_machine_halt();
35}
36
37const char *get_system_type(void)
38{
39 u16 chip_id = ar7_chip_id();
40 u16 titan_variant_id = titan_chip_id();
41
42 switch (chip_id) {
43 case AR7_CHIP_7100:
44 return "TI AR7 (TNETD7100)";
45 case AR7_CHIP_7200:
46 return "TI AR7 (TNETD7200)";
47 case AR7_CHIP_7300:
48 return "TI AR7 (TNETD7300)";
49 case AR7_CHIP_TITAN:
50 switch (titan_variant_id) {
51 case TITAN_CHIP_1050:
52 return "TI AR7 (TNETV1050)";
53 case TITAN_CHIP_1055:
54 return "TI AR7 (TNETV1055)";
55 case TITAN_CHIP_1056:
56 return "TI AR7 (TNETV1056)";
57 case TITAN_CHIP_1060:
58 return "TI AR7 (TNETV1060)";
59 }
60 fallthrough;
61 default:
62 return "TI AR7 (unknown)";
63 }
64}
65
66static int __init ar7_init_console(void)
67{
68 return 0;
69}
70console_initcall(ar7_init_console);
71
72/*
73 * Initializes basic routines and structures pointers, memory size (as
74 * given by the bios and saves the command line.
75 */
76void __init plat_mem_setup(void)
77{
78 unsigned long io_base;
79
80 _machine_restart = ar7_machine_restart;
81 _machine_halt = ar7_machine_halt;
82 pm_power_off = ar7_machine_power_off;
83
84 io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
85 if (!io_base)
86 panic("Can't remap IO base!");
87 set_io_port_base(io_base);
88
89 prom_meminit();
90
91 printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
92 get_system_type(), ar7_chip_id(), ar7_chip_rev());
93}
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
new file mode 100644
index 000000000..72aa77d70
--- /dev/null
+++ b/arch/mips/ar7/time.c
@@ -0,0 +1,31 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Carsten Langgaard, carstenl@mips.com
4 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
5 *
6 * Setting up the clock on the MIPS boards.
7 */
8
9#include <linux/init.h>
10#include <linux/time.h>
11#include <linux/err.h>
12#include <linux/clk.h>
13
14#include <asm/time.h>
15#include <asm/mach-ar7/ar7.h>
16
17void __init plat_time_init(void)
18{
19 struct clk *cpu_clk;
20
21 /* Initialize ar7 clocks so the CPU clock frequency is correct */
22 ar7_init_clocks();
23
24 cpu_clk = clk_get(NULL, "cpu");
25 if (IS_ERR(cpu_clk)) {
26 printk(KERN_ERR "unable to get cpu clock\n");
27 return;
28 }
29
30 mips_hpt_frequency = clk_get_rate(cpu_clk) / 2;
31}