firewall: update to git head
[openwrt.git] / target / linux / lantiq / patches-3.7 / 0101-MIPS-lantiq-adds-support-for-SVIP-SoC-Family.patch
1 From 4d77ad216ad86b3b25c196a189fa28f3e53c3ffd Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Fri, 30 Nov 2012 21:32:00 +0100
4 Subject: [PATCH 101/123] MIPS: lantiq: adds support for SVIP SoC Family
5
6 ---
7  arch/mips/kernel/cevt-r4k.c     |    4 +-
8  arch/mips/lantiq/Kconfig        |    4 ++
9  arch/mips/lantiq/Makefile       |    1 +
10  arch/mips/lantiq/Platform       |    1 +
11  arch/mips/lantiq/clk.c          |    7 +++
12  arch/mips/lantiq/clk.h          |    4 ++
13  arch/mips/lantiq/svip/Makefile  |    1 +
14  arch/mips/lantiq/svip/clk.c     |   70 ++++++++++++++++++++++++++
15  arch/mips/lantiq/svip/prom.c    |   43 ++++++++++++++++
16  arch/mips/lantiq/svip/reset.c   |  105 +++++++++++++++++++++++++++++++++++++++
17  arch/mips/lantiq/svip/sysctrl.c |   81 ++++++++++++++++++++++++++++++
18  11 files changed, 320 insertions(+), 1 deletion(-)
19  create mode 100644 arch/mips/lantiq/svip/Makefile
20  create mode 100644 arch/mips/lantiq/svip/clk.c
21  create mode 100644 arch/mips/lantiq/svip/prom.c
22  create mode 100644 arch/mips/lantiq/svip/reset.c
23  create mode 100644 arch/mips/lantiq/svip/sysctrl.c
24
25 --- a/arch/mips/kernel/cevt-r4k.c
26 +++ b/arch/mips/kernel/cevt-r4k.c
27 @@ -176,8 +176,10 @@ int __cpuinit r4k_clockevent_init(void)
28         if (!cpu_has_counter || !mips_hpt_frequency)
29                 return -ENXIO;
30  
31 -       if (!c0_compare_int_usable())
32 +       if (!c0_compare_int_usable()) {
33 +               printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
34                 return -ENXIO;
35 +       }
36  
37         /*
38          * With vectored interrupts things are getting platform specific.
39 --- a/arch/mips/lantiq/Kconfig
40 +++ b/arch/mips/lantiq/Kconfig
41 @@ -22,6 +22,10 @@ config SOC_FALCON
42         bool "FALCON"
43         select PINCTRL_FALCON
44  
45 +config SOC_SVIP
46 +       bool "SVIP"
47 +       select MIPS_CPU_SCACHE
48 +
49  endchoice
50  
51  choice
52 --- a/arch/mips/lantiq/Makefile
53 +++ b/arch/mips/lantiq/Makefile
54 @@ -12,3 +12,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_prin
55  
56  obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
57  obj-$(CONFIG_SOC_FALCON) += falcon/
58 +obj-$(CONFIG_SOC_SVIP) += svip/
59 --- a/arch/mips/lantiq/Platform
60 +++ b/arch/mips/lantiq/Platform
61 @@ -7,3 +7,4 @@ cflags-$(CONFIG_LANTIQ)         += -I$(srctree)
62  load-$(CONFIG_LANTIQ)          = 0xffffffff80002000
63  cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
64  cflags-$(CONFIG_SOC_FALCON)    += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
65 +cflags-$(CONFIG_SOC_SVIP)      += -I$(srctree)/arch/mips/include/asm/mach-lantiq/svip
66 --- a/arch/mips/lantiq/clk.c
67 +++ b/arch/mips/lantiq/clk.c
68 @@ -163,8 +163,15 @@ void __init plat_time_init(void)
69         ltq_soc_init();
70  
71         clk = clk_get_cpu();
72 +#ifdef CONFIG_SOC_SVIP
73 +       mips_hpt_frequency = ltq_svip_cpu_hz() / get_counter_resolution();
74 +       write_c0_count(0);
75 +       write_c0_compare(mips_hpt_frequency / HZ);
76 +       enable_irq(MIPS_CPU_TIMER_IRQ);
77 +#else
78         mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
79         write_c0_compare(read_c0_count());
80 +#endif
81         pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
82         clk_put(clk);
83  }
84 --- a/arch/mips/lantiq/clk.h
85 +++ b/arch/mips/lantiq/clk.h
86 @@ -75,4 +75,8 @@ extern unsigned long ltq_ar9_fpi_hz(void
87  extern unsigned long ltq_vr9_cpu_hz(void);
88  extern unsigned long ltq_vr9_fpi_hz(void);
89  
90 +extern unsigned long ltq_svip_cpu_hz(void);
91 +extern unsigned long ltq_svip_fpi_hz(void);
92 +extern unsigned long ltq_svip_io_hz(void);
93 +
94  #endif
95 --- /dev/null
96 +++ b/arch/mips/lantiq/svip/Makefile
97 @@ -0,0 +1 @@
98 +obj-y := prom.o reset.o sysctrl.o clk.o
99 --- /dev/null
100 +++ b/arch/mips/lantiq/svip/clk.c
101 @@ -0,0 +1,70 @@
102 +/*
103 + *  This program is free software; you can redistribute it and/or modify it
104 + *  under the terms of the GNU General Public License version 2 as published
105 + *  by the Free Software Foundation.
106 + *
107 + *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
108 + */
109 +
110 +#include <linux/io.h>
111 +#include <linux/export.h>
112 +#include <linux/init.h>
113 +#include <linux/clk.h>
114 +
115 +#include <asm/time.h>
116 +#include <asm/irq.h>
117 +#include <asm/div64.h>
118 +
119 +#include <lantiq_soc.h>
120 +
121 +#include "../clk.h"
122 +
123 +#define STATUS_CONFIG_CLK_MODE         (0x1 << 1)
124 +#define STATUS_CONFIG_CLK_MODE_GET(val)        ((((val) & STATUS_CONFIG_CLK_MODE) >> 4) & 0x1)
125 +#define STATUS_CONFIG                  0x0010
126 +
127 +#define SYS0_PLL1CR_PLLDIV             (0x3)
128 +#define SYS0_PLL1CR_PLLDIV_GET(val)    ((((val) & SYS0_PLL1CR_PLLDIV) >> 0) & 0x3)
129 +#define SYS0_PLL1CR                    0x0008
130 +
131 +#define SYS1_FPICR_FPIDIV              (0x1)
132 +#define SYS1_FPICR_FPIDIV_GET(val)     ((((val) & SYS1_FPICR_FPIDIV) >> 0) & 0x1)
133 +#define SYS1_FPICR                     0x0014
134 +
135 +unsigned long ltq_svip_io_hz(void)
136 +{
137 +       return 200000000; /* 200 MHz */
138 +}
139 +
140 +unsigned long ltq_svip_cpu_hz(void)
141 +{
142 +       /* Magic BootROM speed location... */
143 +       if ((*(u32 *)0x9fc07ff0) == 1)
144 +               return *(u32 *)0x9fc07ff4;
145 +
146 +       if (STATUS_CONFIG_CLK_MODE_GET(ltq_status_r32(STATUS_CONFIG)) == 1) {
147 +       /* xT16 */
148 +               return 393216000;
149 +       } else {
150 +               switch (SYS0_PLL1CR_PLLDIV_GET(ltq_sys0_r32(SYS0_PLL1CR))) {
151 +               case 3:
152 +                       return 475000000;
153 +               case 2:
154 +                       return 450000000;
155 +               case 1:
156 +                       return 425000000;
157 +               default:
158 +                       break;
159 +               }
160 +       }
161 +       return 400000000;
162 +}
163 +
164 +unsigned long ltq_svip_fpi_hz(void)
165 +{
166 +       u32 fbs0_div[2] = {4, 8};
167 +       u32 div;
168 +
169 +       div = SYS1_FPICR_FPIDIV_GET(ltq_sys1_r32(SYS1_FPICR));
170 +       return ltq_svip_cpu_hz() / fbs0_div[div];
171 +}
172 --- /dev/null
173 +++ b/arch/mips/lantiq/svip/prom.c
174 @@ -0,0 +1,43 @@
175 +/*
176 + * This program is free software; you can redistribute it and/or modify it
177 + * under the terms of the GNU General Public License version 2 as published
178 + * by the Free Software Foundation.
179 + *
180 + * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
181 + * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
182 + */
183 +
184 +#include <linux/kernel.h>
185 +#include <asm/io.h>
186 +
187 +#include <lantiq_soc.h>
188 +
189 +#include "../prom.h"
190 +
191 +#define SOC_SVIP       "SVIP"
192 +
193 +#define COMP_SVIP      "lantiq,svip"
194 +
195 +#define PART_SHIFT     12
196 +#define PART_MASK      0x0FFFF000
197 +#define REV_SHIFT      28
198 +#define REV_MASK       0xF0000000
199 +
200 +void __init ltq_soc_detect(struct ltq_soc_info *i)
201 +{
202 +       i->partnum = (ltq_r32(LTQ_STATUS_CHIPID) & PART_MASK) >> PART_SHIFT;
203 +       i->rev = (ltq_r32(LTQ_STATUS_CHIPID) & REV_MASK) >> REV_SHIFT;
204 +       sprintf(i->rev_type, "1.%d", i->rev);
205 +
206 +       switch (i->partnum) {
207 +       case SOC_ID_SVIP:
208 +               i->name = SOC_SVIP;
209 +               i->type = SOC_TYPE_SVIP;
210 +               i->compatible = COMP_SVIP;
211 +               break;
212 +
213 +       default:
214 +               printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
215 +               break;
216 +       }
217 +}
218 --- /dev/null
219 +++ b/arch/mips/lantiq/svip/reset.c
220 @@ -0,0 +1,105 @@
221 +/*
222 + *  This program is free software; you can redistribute it and/or modify it
223 + *  under the terms of the GNU General Public License version 2 as published
224 + *  by the Free Software Foundation.
225 + *
226 + *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
227 + */
228 +
229 +#include <linux/init.h>
230 +#include <linux/io.h>
231 +#include <linux/ioport.h>
232 +#include <linux/pm.h>
233 +#include <linux/module.h>
234 +#include <asm/reboot.h>
235 +
236 +#include <lantiq_soc.h>
237 +
238 +#define CPLD_CMDREG3  ((volatile unsigned char*)(KSEG1 + 0x120000f3))
239 +
240 +#define LTQ_EBU_ADDRSEL2       0x0028
241 +#define LTQ_EBU_BUSCON2         0x0068
242 +#define LTQ_BOOT_CPU_OFFSET    0x20
243 +
244 +#define LTQ_L2_SPRAM_BASE      (KSEG1 + 0x1F1E8000)
245 +#define LTQ_BOOT_RVEC(cpu)     (volatile u32*)(LTQ_L2_SPRAM_BASE + \
246 +                               (cpu * LTQ_BOOT_CPU_OFFSET))
247 +
248 +#define SYS0_BCR               0x0004
249 +#define BMODE_SHIFT            16
250 +#define BMODE_MASK             0x1f
251 +
252 +#define SYS1_CLKCLR            0x0008
253 +#define SYS1_RREQR             0x0044
254 +#define SYS1_RRLSR             0x0048
255 +#define SYS1_RBTR              0x004c
256 +#define SYS1_CPU0RSR           0x0060
257 +#define SYS1_CPU0RSR_MASK      0x0007
258 +
259 +/* This function is used by the watchdog driver */
260 +int ltq_reset_cause(void)
261 +{
262 +       return ltq_sys1_r32(SYS1_CPU0RSR) & SYS1_CPU0RSR_MASK;
263 +}
264 +EXPORT_SYMBOL_GPL(ltq_reset_cause);
265 +
266 +/* allow platform code to find out what source we booted from */
267 +unsigned char ltq_boot_select(void)
268 +{
269 +       return (ltq_sys0_r32(SYS0_BCR) >> BMODE_SHIFT) & BMODE_MASK;
270 +}
271 +
272 +static void ltq_machine_restart(char *command)
273 +{
274 +       local_irq_disable();
275 +       if (/*mips_machtype == LANTIQ_MACH_EASY33016 ||
276 +           mips_machtype == LANTIQ_MACH_EASY336)*/
277 +           1) {
278 +               /* We just use the CPLD function to reset the entire system as a
279 +                  workaround for the switch reset problem */
280 +               local_irq_disable();
281 +               ltq_ebu_w32(0x120000f1, LTQ_EBU_ADDRSEL2);
282 +               ltq_ebu_w32(0x404027ff, LTQ_EBU_BUSCON2);
283 +
284 +               if (/*mips_machtype == LANTIQ_MACH_EASY336*/
285 +                       0)
286 +                       /* set bit 0 to reset SVIP */
287 +                       *CPLD_CMDREG3 = (1<<0);
288 +               else
289 +                       /* set bit 7 to reset SVIP, set bit 3 to reset xT */
290 +                       *CPLD_CMDREG3 = (1<<7) | (1<<3);
291 +       } else {
292 +               *LTQ_BOOT_RVEC(0) = 0;
293 +               /* reset all except PER, SUBSYS and CPU0 */
294 +               ltq_sys1_w32(0x00043F3E, SYS1_RREQR);
295 +               /* release WDT0 reset */
296 +               ltq_sys1_w32(0x00000100, SYS1_RRLSR);
297 +               /* restore reset value for clock enables */
298 +               ltq_sys1_w32(~0x0c000040, SYS1_CLKCLR);
299 +               /* reset SUBSYS (incl. DDR2) and CPU0 */
300 +               ltq_sys1_w32(0x00030001, SYS1_RBTR);
301 +       }
302 +
303 +       unreachable();
304 +}
305 +
306 +static void ltq_machine_halt(void)
307 +{
308 +       local_irq_disable();
309 +       unreachable();
310 +}
311 +
312 +static void ltq_machine_power_off(void)
313 +{
314 +       local_irq_disable();
315 +}
316 +
317 +static int __init mips_reboot_setup(void)
318 +{
319 +       _machine_restart = ltq_machine_restart;
320 +       _machine_halt = ltq_machine_halt;
321 +       pm_power_off = ltq_machine_power_off;
322 +       return 0;
323 +}
324 +
325 +arch_initcall(mips_reboot_setup);
326 --- /dev/null
327 +++ b/arch/mips/lantiq/svip/sysctrl.c
328 @@ -0,0 +1,81 @@
329 +/*
330 + *  This program is free software; you can redistribute it and/or modify it
331 + *  under the terms of the GNU General Public License version 2 as published
332 + *  by the Free Software Foundation.
333 + *
334 + *  Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
335 + */
336 +
337 +#include <linux/ioport.h>
338 +#include <linux/export.h>
339 +#include <linux/clkdev.h>
340 +#include <linux/of.h>
341 +#include <linux/of_platform.h>
342 +#include <linux/of_address.h>
343 +
344 +#include <lantiq_soc.h>
345 +
346 +#include "../clk.h"
347 +#include "../prom.h"
348 +
349 +void __iomem *ltq_sys0_membase;
350 +void __iomem *ltq_sys1_membase;
351 +void __iomem *ltq_sys2_membase;
352 +void __iomem *ltq_status_membase;
353 +void __iomem *ltq_ebu_membase;
354 +
355 +/* bring up all register ranges that we need for basic system control */
356 +void __init ltq_soc_init(void)
357 +{
358 +       struct resource res_sys0, res_sys1, res_sys2, res_status, res_ebu;
359 +       struct device_node *np_sys0 =
360 +                       of_find_compatible_node(NULL, NULL, "lantiq,sys0-svip");
361 +       struct device_node *np_sys1 =
362 +                       of_find_compatible_node(NULL, NULL, "lantiq,sys1-svip");
363 +       struct device_node *np_sys2 =
364 +                       of_find_compatible_node(NULL, NULL, "lantiq,sys2-svip");
365 +       struct device_node *np_status =
366 +                       of_find_compatible_node(NULL, NULL, "lantiq,status-svip");
367 +       struct device_node *np_ebu =
368 +                       of_find_compatible_node(NULL, NULL, "lantiq,ebu-svip");
369 +
370 +       /* check if all the core register ranges are available */
371 +       if (!np_sys0 || !np_sys1 || !np_sys2 || !np_status || !np_ebu)
372 +               panic("Failed to load core nodes from devicetree");
373 +
374 +       if (of_address_to_resource(np_sys0, 0, &res_sys0) ||
375 +                       of_address_to_resource(np_sys1, 0, &res_sys1) ||
376 +                       of_address_to_resource(np_sys2, 0, &res_sys2) ||
377 +                       of_address_to_resource(np_status, 0, &res_status) ||
378 +                       of_address_to_resource(np_ebu, 0, &res_ebu))
379 +               panic("Failed to get core resources");
380 +
381 +       if ((request_mem_region(res_sys0.start, resource_size(&res_sys0),
382 +                               res_sys0.name) < 0) ||
383 +               (request_mem_region(res_sys1.start, resource_size(&res_sys1),
384 +                               res_sys1.name) < 0) ||
385 +               (request_mem_region(res_sys2.start, resource_size(&res_sys2),
386 +                               res_sys2.name) < 0) ||
387 +               (request_mem_region(res_status.start, resource_size(&res_status),
388 +                               res_status.name) < 0) ||
389 +               (request_mem_region(res_ebu.start, resource_size(&res_ebu),
390 +                               res_ebu.name) < 0))
391 +               pr_err("Failed to request core reources");
392 +
393 +       ltq_sys0_membase = ioremap_nocache(res_sys0.start,
394 +                                               resource_size(&res_sys0));
395 +       ltq_sys1_membase = ioremap_nocache(res_sys1.start,
396 +                                               resource_size(&res_sys1));
397 +       ltq_sys2_membase = ioremap_nocache(res_sys2.start,
398 +                                               resource_size(&res_sys2));
399 +       ltq_status_membase = ioremap_nocache(res_status.start,
400 +                                               resource_size(&res_status));
401 +       ltq_ebu_membase = ioremap_nocache(res_ebu.start,
402 +                                               resource_size(&res_ebu));
403 +       if (!ltq_sys0_membase || !ltq_sys1_membase || !ltq_sys2_membase ||
404 +                       !ltq_status_membase || !ltq_ebu_membase)
405 +               panic("Failed to remap core resources");
406 +
407 +       clkdev_add_static(ltq_svip_cpu_hz(), ltq_svip_fpi_hz(),
408 +                               ltq_svip_io_hz());
409 +}