67cc12541cfd60ccb316de128f0b9e4912cdb799
[openwrt.git] / target / linux / mpc83xx / patches-2.6.35 / 017-platforms_83xx_rbppc.patch
1 --- /dev/null
2 +++ b/arch/powerpc/platforms/83xx/rbppc.c
3 @@ -0,0 +1,316 @@
4 +/*
5 + * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
6 + * Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
7 + * Copyright (C) Mikrotik 2007
8 + *
9 + * This program is free software; you can redistribute it and/or modify it
10 + * under the terms of the GNU General Public License as published by the
11 + * Free Software Foundation; either version 2 of the License, or (at your
12 + * option) any later version.
13 + */
14 +
15 +#include <linux/delay.h>
16 +#include <linux/root_dev.h>
17 +#include <linux/initrd.h>
18 +#include <linux/interrupt.h>
19 +#include <linux/of_platform.h>
20 +#include <linux/of_device.h>
21 +#include <linux/of_platform.h>
22 +#include <asm/time.h>
23 +#include <asm/ipic.h>
24 +#include <asm/udbg.h>
25 +#include <asm/qe.h>
26 +#include <asm/qe_ic.h>
27 +#include <sysdev/fsl_soc.h>
28 +#include <sysdev/fsl_pci.h>
29 +#include "mpc83xx.h"
30 +
31 +#define SYSCTL         0x100
32 +#define SICRL          0x014
33 +
34 +#define GTCFR2         0x04
35 +#define GTMDR4         0x22
36 +#define GTRFR4         0x26
37 +#define GTCNR4         0x2e
38 +#define GTVER4         0x36
39 +#define GTPSR4         0x3e
40 +
41 +#define GTCFR_BCM      0x40
42 +#define GTCFR_STP4     0x20
43 +#define GTCFR_RST4     0x10
44 +#define GTCFR_STP3     0x02
45 +#define GTCFR_RST3     0x01
46 +
47 +#define GTMDR_ORI      0x10
48 +#define GTMDR_FRR      0x08
49 +#define GTMDR_ICLK16   0x04
50 +
51 +extern int par_io_data_set(u8 port, u8 pin, u8 val);
52 +extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
53 +                            int assignment, int has_irq);
54 +
55 +static unsigned timer_freq;
56 +static void *gtm;
57 +
58 +static int beeper_irq;
59 +static unsigned beeper_gpio_pin[2];
60 +
61 +irqreturn_t rbppc_timer_irq(int irq, void *ptr)
62 +{
63 +       static int toggle = 0;
64 +
65 +       par_io_data_set(beeper_gpio_pin[0], beeper_gpio_pin[1], toggle);
66 +       toggle = !toggle;
67 +
68 +       /* ack interrupt */
69 +       out_be16(gtm + GTVER4, 3);
70 +
71 +       return IRQ_HANDLED;
72 +}
73 +
74 +void rbppc_beep(unsigned freq)
75 +{
76 +       unsigned gtmdr;
77 +
78 +       if (freq > 5000) freq = 5000;
79 +
80 +       if (!gtm)
81 +               return;
82 +       if (!freq) {
83 +               out_8(gtm + GTCFR2, GTCFR_STP4 | GTCFR_STP3);
84 +               return;
85 +       }
86 +
87 +       out_8(gtm + GTCFR2, GTCFR_RST4 | GTCFR_STP3);
88 +       out_be16(gtm + GTPSR4, 255);
89 +       gtmdr = GTMDR_FRR | GTMDR_ICLK16;
90 +       if (beeper_irq != NO_IRQ) gtmdr |= GTMDR_ORI;
91 +       out_be16(gtm + GTMDR4, gtmdr);
92 +       out_be16(gtm + GTVER4, 3);
93 +
94 +       out_be16(gtm + GTRFR4, timer_freq / 16 / 256 / freq / 2);
95 +       out_be16(gtm + GTCNR4, 0);
96 +}
97 +EXPORT_SYMBOL(rbppc_beep);
98 +
99 +static void __init rbppc_setup_arch(void)
100 +{
101 +       struct device_node *np;
102 +
103 +       np = of_find_node_by_type(NULL, "cpu");
104 +       if (np) {
105 +               const unsigned *fp = of_get_property(np, "clock-frequency", NULL);
106 +               loops_per_jiffy = fp ? *fp / HZ : 0;
107 +
108 +               of_node_put(np);
109 +       }
110 +
111 +       np = of_find_node_by_name(NULL, "serial");
112 +       if (np) {
113 +               timer_freq =
114 +                   *(unsigned *) of_get_property(np, "clock-frequency", NULL);
115 +               of_node_put(np);
116 +       }
117 +
118 +#ifdef CONFIG_PCI
119 +       np = of_find_node_by_type(NULL, "pci");
120 +       if (np) {
121 +               mpc83xx_add_bridge(np);
122 +       }
123 +#endif
124 +
125 +#ifdef CONFIG_QUICC_ENGINE
126 +       np = of_find_node_by_name(np, "par_io");
127 +       if (np) {
128 +               qe_reset();
129 +               par_io_init(np);
130 +               of_node_put(np);
131 +
132 +               np = NULL;
133 +               while (1) {
134 +                       np = of_find_node_by_name(np, "ucc");
135 +                       if (!np) break;
136 +
137 +                       par_io_of_config(np);
138 +               }
139 +       }
140 +#endif
141 +
142 +}
143 +
144 +void __init rbppc_init_IRQ(void)
145 +{
146 +       struct device_node *np;
147 +
148 +       np = of_find_node_by_type(NULL, "ipic");
149 +       if (np) {
150 +               ipic_init(np, 0);
151 +               ipic_set_default_priority();
152 +               of_node_put(np);
153 +       }
154 +
155 +#ifdef CONFIG_QUICC_ENGINE
156 +       np = of_find_node_by_type(NULL, "qeic");
157 +       if (np) {
158 +               qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
159 +               of_node_put(np);
160 +       }
161 +#endif
162 +}
163 +
164 +static int __init rbppc_probe(void)
165 +{
166 +       char *model;
167 +
168 +       model = of_get_flat_dt_prop(of_get_flat_dt_root(), "model", NULL);
169 +
170 +       if (!model)
171 +               return 0;
172 +
173 +       if (strcmp(model, "RB600") == 0)
174 +               return 1;
175 +
176 +       return 0;
177 +}
178 +
179 +static void __init rbppc_beeper_init(struct device_node *beeper)
180 +{
181 +       struct resource res;
182 +       struct device_node *gpio;
183 +       const unsigned *pin;
184 +       const unsigned *gpio_id;
185 +
186 +       if (of_address_to_resource(beeper, 0, &res)) {
187 +               printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: No region specified\n", beeper->full_name);
188 +               return;
189 +       }
190 +
191 +       pin = of_get_property(beeper, "gpio", NULL);
192 +       if (pin) {
193 +               gpio = of_find_node_by_phandle(pin[0]);
194 +
195 +               if (!gpio) {
196 +                       printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: GPIO handle %x not found\n", beeper->full_name, pin[0]);
197 +                       return;
198 +               }
199 +
200 +               gpio_id = of_get_property(gpio, "device-id", NULL);
201 +               if (!gpio_id) {
202 +                       printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: No device-id specified in GPIO\n", beeper->full_name);
203 +                       return;
204 +               }
205 +
206 +               beeper_gpio_pin[0] = *gpio_id;
207 +               beeper_gpio_pin[1] = pin[1];
208 +
209 +               par_io_config_pin(*gpio_id, pin[1], 1, 0, 0, 0);
210 +       } else {
211 +               void *sysctl;
212 +
213 +               sysctl = ioremap_nocache(get_immrbase() + SYSCTL, 0x100);
214 +               out_be32(sysctl + SICRL,
215 +                        in_be32(sysctl + SICRL) | (1 << (31 - 19)));
216 +               iounmap(sysctl);
217 +       }
218 +
219 +       gtm = ioremap_nocache(res.start, res.end - res.start + 1);
220 +
221 +       beeper_irq = irq_of_parse_and_map(beeper, 0);
222 +       if (beeper_irq != NO_IRQ) {
223 +               int e = request_irq(beeper_irq, rbppc_timer_irq, 0, "beeper", NULL);
224 +               if (e) {
225 +                       printk(KERN_ERR "rbppc_beeper_init(%s): Request of beeper irq failed!\n", beeper->full_name);
226 +               }
227 +       }
228 +}
229 +
230 +#define SBIT(x) (0x80000000 >> (x))
231 +#define DBIT(x, y) ((y) << (32 - (((x % 16) + 1) * 2)))
232 +
233 +#define SICRL_RB600(x) ((x) + (0x114 >> 2))
234 +#define GPIO_DIR_RB600(x) ((x) + (0xc00 >> 2))
235 +#define GPIO_DATA_RB600(x) ((x) + (0xc08 >> 2))
236 +
237 +static void rbppc_restart(char *cmd)
238 +{
239 +       __be32 __iomem *reg;
240 +
241 +       reg = ioremap(get_immrbase(), 0x1000);
242 +       local_irq_disable();
243 +       out_be32(SICRL_RB600(reg), in_be32(SICRL_RB600(reg)) & ~0x00800000);
244 +       out_be32(GPIO_DIR_RB600(reg), in_be32(GPIO_DIR_RB600(reg)) | SBIT(2));
245 +       out_be32(GPIO_DATA_RB600(reg), in_be32(GPIO_DATA_RB600(reg)) & ~SBIT(2));
246 +
247 +       while (1);
248 +}
249 +
250 +static void rbppc_halt(void)
251 +{
252 +       while (1);
253 +}
254 +
255 +static struct of_device_id rbppc_ids[] = {
256 +       { .type = "soc", },
257 +       { .compatible = "soc", },
258 +       { .compatible = "simple-bus", },
259 +       { .compatible = "gianfar", },
260 +       { },
261 +};
262 +
263 +static int __init rbppc_declare_of_platform_devices(void)
264 +{
265 +       struct device_node *np;
266 +       unsigned idx;
267 +
268 +       of_platform_bus_probe(NULL, rbppc_ids, NULL);
269 +
270 +       np = of_find_node_by_type(NULL, "mdio");
271 +       if (np) {
272 +               unsigned len;
273 +               unsigned *res;
274 +               const unsigned *eres;
275 +               struct device_node *ep;
276 +
277 +               ep = of_find_compatible_node(NULL, "network", "ucc_geth");
278 +               if (ep) {
279 +                       eres = of_get_property(ep, "reg", &len);
280 +                       res = (unsigned *) of_get_property(np, "reg", &len);
281 +                       if (res && eres) {
282 +                               res[0] = eres[0] + 0x120;
283 +                       }
284 +               }
285 +       }
286 +
287 +       np = of_find_node_by_name(NULL, "nand");
288 +       if (np) {
289 +               of_platform_device_create(np, "nand", NULL);
290 +       }
291 +
292 +       idx = 0;
293 +       for_each_node_by_type(np, "rb,cf") {
294 +               char dev_name[12];
295 +               snprintf(dev_name, sizeof(dev_name), "cf.%u", idx);
296 +               of_platform_device_create(np, dev_name, NULL);
297 +               ++idx;
298 +       }
299 +
300 +       np = of_find_node_by_name(NULL, "beeper");
301 +       if (np) {
302 +               rbppc_beeper_init(np);
303 +       }
304 +
305 +       return 0;
306 +}
307 +device_initcall(rbppc_declare_of_platform_devices);
308 +
309 +define_machine(rb600) {
310 +       .name                           = "MikroTik RouterBOARD 600 series",
311 +       .probe                          = rbppc_probe,
312 +       .setup_arch                     = rbppc_setup_arch,
313 +       .init_IRQ                       = rbppc_init_IRQ,
314 +       .get_irq                        = ipic_get_irq,
315 +       .restart                        = rbppc_restart,
316 +       .halt                           = rbppc_halt,
317 +       .time_init                      = mpc83xx_time_init,
318 +       .calibrate_decr                 = generic_calibrate_decr,
319 +};