Root/target/linux/mpc83xx/patches-2.6.32/001-rb600.patch

1--- /dev/null
2+++ b/arch/powerpc/boot/dts/rb600.dts
3@@ -0,0 +1,242 @@
4+/*
5+ * RouterBOARD 600 series Device Tree Source
6+ *
7+ * Copyright 2009 Michael Guntsche <mike@it-loops.com>
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+/dts-v1/;
16+
17+/ {
18+ model = "RB600";
19+ compatible = "MPC83xx";
20+ #address-cells = <1>;
21+ #size-cells = <1>;
22+
23+ aliases {
24+ ethernet0 = &enet0;
25+ ethernet1 = &enet1;
26+ };
27+
28+ chosen {
29+ linux,stdout-path = "/soc8343@e0000000/serial@4500";
30+ };
31+
32+ cpus {
33+ #address-cells = <1>;
34+ #size-cells = <0>;
35+
36+ PowerPC,8343E@0 {
37+ device_type = "cpu";
38+ reg = <0x0>;
39+ d-cache-line-size = <0x20>;
40+ i-cache-line-size = <0x20>;
41+ d-cache-size = <0x8000>;
42+ i-cache-size = <0x8000>;
43+ timebase-frequency = <0x0000000>; // filled by the bootwrapper from the firmware blob
44+ clock-frequency = <0x00000000>; // filled by the bootwrapper from the firmware blob
45+ };
46+ };
47+
48+ memory {
49+ device_type = "memory";
50+ reg = <0x0 0x0000000>; // filled by the bootwrapper from the firmware blob
51+ };
52+
53+ cf@f9200000 {
54+ lb-timings = <0x5dc 0x3e8 0x1194 0x5dc 0x2af8>;
55+ interrupt-at-level = <0x0>;
56+ interrupt-parent = <&ipic>;
57+ interrupts = <0x16 0x8>;
58+ lbc_extra_divider = <0x1>;
59+ reg = <0xf9200000 0x200000>;
60+ device_type = "rb,cf";
61+ };
62+
63+ cf@f9000000 {
64+ lb-timings = <0x5dc 0x3e8 0x1194 0x5dc 0x2af8>;
65+ interrupt-at-level = <0x0>;
66+ interrupt-parent = <&ipic>;
67+ interrupts = <0x14 0x8>;
68+ lbc_extra_divider = <0x1>;
69+ reg = <0xf9000000 0x200000>;
70+ device_type = "rb,cf";
71+ };
72+
73+ flash {
74+ reg = <0xff800000 0x20000>;
75+ };
76+
77+ nnand {
78+ reg = <0xf0000000 0x1000>;
79+ };
80+
81+ nand {
82+ ale = <&gpio 0x6>;
83+ cle = <&gpio 0x5>;
84+ nce = <&gpio 0x4>;
85+ rdy = <&gpio 0x3>;
86+ reg = <0xf8000000 0x1000>;
87+ device_type = "rb,nand";
88+ };
89+
90+ fancon {
91+ interrupt-parent = <&ipic>;
92+ interrupts = <0x17 0x8>;
93+ sense = <&gpio 0x7>;
94+ fan_on = <&gpio 0x9>;
95+ };
96+
97+ pci0: pci@e0008500 {
98+ device_type = "pci";
99+ compatible = "fsl,mpc8349-pci";
100+ reg = <0xe0008500 0x100 0xe0008300 0x8>;
101+ #address-cells = <3>;
102+ #size-cells = <2>;
103+ #interrupt-cells = <1>;
104+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 0x1000000 0x0 0x0 0xd0000000 0x0 0x4000000>;
105+ bus-range = <0x0 0x0>;
106+ interrupt-map = <
107+ 0x5800 0x0 0x0 0x1 &ipic 0x15 0x8
108+ 0x6000 0x0 0x0 0x1 &ipic 0x30 0x8
109+ 0x6000 0x0 0x0 0x2 &ipic 0x11 0x8
110+ 0x6800 0x0 0x0 0x1 &ipic 0x11 0x8
111+ 0x6800 0x0 0x0 0x2 &ipic 0x12 0x8
112+ 0x7000 0x0 0x0 0x1 &ipic 0x12 0x8
113+ 0x7000 0x0 0x0 0x2 &ipic 0x13 0x8
114+ 0x7800 0x0 0x0 0x1 &ipic 0x13 0x8
115+ 0x7800 0x0 0x0 0x2 &ipic 0x30 0x8
116+ 0x8000 0x0 0x0 0x1 &ipic 0x30 0x8
117+ 0x8000 0x0 0x0 0x2 &ipic 0x12 0x8
118+ 0x8000 0x0 0x0 0x3 &ipic 0x11 0x8
119+ 0x8000 0x0 0x0 0x4 &ipic 0x13 0x8
120+ 0xa000 0x0 0x0 0x1 &ipic 0x30 0x8
121+ 0xa000 0x0 0x0 0x2 &ipic 0x11 0x8
122+ 0xa000 0x0 0x0 0x3 &ipic 0x12 0x8
123+ 0xa000 0x0 0x0 0x4 &ipic 0x13 0x8
124+ 0xa800 0x0 0x0 0x1 &ipic 0x11 0x8
125+ 0xa800 0x0 0x0 0x2 &ipic 0x12 0x8
126+ 0xa800 0x0 0x0 0x3 &ipic 0x13 0x8
127+ 0xa800 0x0 0x0 0x4 &ipic 0x30 0x8>;
128+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
129+ interrupt-parent = <&ipic>;
130+ };
131+
132+ soc8343@e0000000 {
133+ #address-cells = <1>;
134+ #size-cells = <1>;
135+ device_type = "soc";
136+ compatible = "simple-bus";
137+ ranges = <0x0 0xe0000000 0x100000>;
138+ reg = <0xe0000000 0x200>;
139+ bus-frequency = <0x1>;
140+
141+ led {
142+ user_led = <0x400 0x8>;
143+ };
144+
145+ beeper {
146+ reg = <0x500 0x100>;
147+ };
148+
149+ gpio: gpio@0 {
150+ reg = <0xc08 0x4>;
151+ device-id = <0x0>;
152+ compatible = "gpio";
153+ device_type = "gpio";
154+ };
155+
156+ enet0: ethernet@25000 {
157+ #address-cells = <1>;
158+ #size-cells = <1>;
159+ cell-index = <0>;
160+ phy-handle = <&phy0>;
161+ tbi-handle = <&tbi0>;
162+ interrupt-parent = <&ipic>;
163+ interrupts = <0x23 0x8 0x24 0x8 0x25 0x8>;
164+ local-mac-address = [00 00 00 00 00 00];
165+ reg = <0x25000 0x1000>;
166+ ranges = <0x0 0x25000 0x1000>;
167+ compatible = "gianfar";
168+ model = "TSEC";
169+ device_type = "network";
170+
171+ mdio@520 {
172+ #address-cells = <1>;
173+ #size-cells = <0>;
174+ compatible = "fsl,gianfar-tbi";
175+ reg = <0x520 0x20>;
176+
177+ tbi0: tbi-phy@11 {
178+ reg = <0x11>;
179+ device_type = "tbi-phy";
180+ };
181+ };
182+ };
183+
184+ enet1: ethernet@24000 {
185+ #address-cells = <1>;
186+ #size-cells = <1>;
187+ cell-index = <1>;
188+ phy-handle = <&phy1>;
189+ tbi-handle = <&tbi1>;
190+ interrupt-parent = <&ipic>;
191+ interrupts = <0x20 0x8 0x21 0x8 0x22 0x8>;
192+ local-mac-address = [00 00 00 00 00 00];
193+ reg = <0x24000 0x1000>;
194+ ranges = <0x0 0x24000 0x1000>;
195+ compatible = "gianfar";
196+ model = "TSEC";
197+ device_type = "network";
198+
199+ mdio@520 {
200+ #size-cells = <0x0>;
201+ #address-cells = <0x1>;
202+ reg = <0x520 0x20>;
203+ compatible = "fsl,gianfar-mdio";
204+
205+ phy0: ethernet-phy@0 {
206+ device_type = "ethernet-phy";
207+ reg = <0x0>;
208+ };
209+
210+ phy1: ethernet-phy@1 {
211+ device_type = "ethernet-phy";
212+ reg = <0x1>;
213+ };
214+
215+ tbi1: tbi-phy@11 {
216+ reg = <0x11>;
217+ device_type = "tbi-phy";
218+ };
219+ };
220+ };
221+
222+ ipic: pic@700 {
223+ interrupt-controller;
224+ #address-cells = <0>;
225+ #interrupt-cells = <2>;
226+ reg = <0x700 0x100>;
227+ device_type = "ipic";
228+ };
229+
230+ serial@4500 {
231+ interrupt-parent = <&ipic>;
232+ interrupts = <0x9 0x8>;
233+ clock-frequency = <0xfe4f840>;
234+ reg = <0x4500 0x100>;
235+ compatible = "ns16550";
236+ device_type = "serial";
237+ };
238+
239+ wdt@200 {
240+ reg = <0x200 0x100>;
241+ compatible = "mpc83xx_wdt";
242+ device_type = "watchdog";
243+ };
244+ };
245+};
246--- a/arch/powerpc/boot/Makefile
247+++ b/arch/powerpc/boot/Makefile
248@@ -73,7 +73,7 @@ src-plat := of.c cuboot-52xx.c cuboot-82
249         cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c \
250         cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
251         fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \
252- cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
253+ cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c rb600.c \
254         cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
255         virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
256         cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c
257@@ -231,6 +231,7 @@ image-$(CONFIG_MPC834x_ITX) += cuImage.
258 image-$(CONFIG_MPC834x_MDS) += cuImage.mpc834x_mds
259 image-$(CONFIG_MPC836x_MDS) += cuImage.mpc836x_mds
260 image-$(CONFIG_ASP834x) += dtbImage.asp834x-redboot
261+image-$(CONFIG_RB_PPC) += dtbImage.rb600
262 
263 # Board ports in arch/powerpc/platform/85xx/Kconfig
264 image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads
265--- /dev/null
266+++ b/arch/powerpc/boot/rb600.c
267@@ -0,0 +1,80 @@
268+/*
269+ * The RouterBOARD platform -- for booting RB600(A) RouterBOARDs.
270+ *
271+ * Author: Michael Guntsche <mike@it-loops.com>
272+ *
273+ * Copyright (c) 2009 Michael Guntsche
274+ *
275+ * This program is free software; you can redistribute it and/or modify it
276+ * under the terms of the GNU General Public License version 2 as published
277+ * by the Free Software Foundation.
278+ */
279+
280+#include "ops.h"
281+#include "types.h"
282+#include "io.h"
283+#include "stdio.h"
284+#include <libfdt.h>
285+
286+BSS_STACK(4*1024);
287+
288+u64 memsize64;
289+const void *fw_dtb;
290+
291+static void rb600_fixups(void)
292+{
293+ const u32 *reg, *timebase, *clock;
294+ int node, size;
295+ void *chosen;
296+ const char* bootargs;
297+
298+ dt_fixup_memory(0, memsize64);
299+
300+ /* Set the MAC addresses. */
301+ node = fdt_path_offset(fw_dtb, "/soc8343@e0000000/ethernet@24000");
302+ reg = fdt_getprop(fw_dtb, node, "mac-address", &size);
303+ dt_fixup_mac_address_by_alias("ethernet1", (const u8 *)reg);
304+
305+ node = fdt_path_offset(fw_dtb, "/soc8343@e0000000/ethernet@25000");
306+ reg = fdt_getprop(fw_dtb, node, "mac-address", &size);
307+ dt_fixup_mac_address_by_alias("ethernet0", (const u8 *)reg);
308+
309+ /* Find the CPU timebase and clock frequencies. */
310+ node = fdt_node_offset_by_prop_value(fw_dtb, -1, "device_type", "cpu", sizeof("cpu"));
311+ timebase = fdt_getprop(fw_dtb, node, "timebase-frequency", &size);
312+ clock = fdt_getprop(fw_dtb, node, "clock-frequency", &size);
313+ dt_fixup_cpu_clocks(*clock, *timebase, 0);
314+
315+ /* Fixup chosen
316+ * The bootloader reads the kernelparm segment and adds the content to
317+ * bootargs. This is needed to specify root and other boot flags.
318+ */
319+ chosen = finddevice("/chosen");
320+ node = fdt_path_offset(fw_dtb, "/chosen");
321+ bootargs = fdt_getprop(fw_dtb, node, "bootargs", &size);
322+ setprop_str(chosen, "bootargs", bootargs);
323+}
324+
325+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
326+ unsigned long r6, unsigned long r7)
327+{
328+ const u32 *reg;
329+ int node, size;
330+
331+ fw_dtb = (const void *)r3;
332+
333+ /* Find the memory range. */
334+ node = fdt_node_offset_by_prop_value(fw_dtb, -1, "device_type", "memory", sizeof("memory"));
335+ reg = fdt_getprop(fw_dtb, node, "reg", &size);
336+ memsize64 = reg[1];
337+
338+ /* Now we have the memory size; initialize the heap. */
339+ simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64);
340+
341+ /* Prepare the device tree and find the console. */
342+ fdt_init(_dtb_start);
343+ serial_console_init();
344+
345+ /* Remaining fixups... */
346+ platform_ops.fixups = rb600_fixups;
347+}
348--- a/arch/powerpc/boot/wrapper
349+++ b/arch/powerpc/boot/wrapper
350@@ -202,7 +202,7 @@ ps3)
351     isection=.kernel:initrd
352     link_address=''
353     ;;
354-ep88xc|ep405|ep8248e)
355+ep88xc|ep405|ep8248e|rb600)
356     platformo="$object/fixed-head.o $object/$platform.o"
357     binary=y
358     ;;
359--- a/arch/powerpc/kernel/Makefile
360+++ b/arch/powerpc/kernel/Makefile
361@@ -104,9 +104,11 @@ obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450
362 
363 obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
364 
365+ifneq ($(CONFIG_RB_IOMAP),y)
366 ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
367 obj-y += iomap.o
368 endif
369+endif
370 
371 obj-$(CONFIG_PPC64) += $(obj64-y)
372 obj-$(CONFIG_PPC32) += $(obj32-y)
373--- a/arch/powerpc/platforms/83xx/Kconfig
374+++ b/arch/powerpc/platforms/83xx/Kconfig
375@@ -30,6 +30,15 @@ config MPC832x_RDB
376     help
377       This option enables support for the MPC8323 RDB board.
378 
379+config RB_PPC
380+ bool "MikroTik RouterBOARD 600 series"
381+ select DEFAULT_UIMAGE
382+ select QUICC_ENGINE
383+ select PPC_MPC834x
384+ select RB_IOMAP
385+ help
386+ This option enables support for MikroTik RouterBOARD 600 series boards.
387+
388 config MPC834x_MDS
389     bool "Freescale MPC834x MDS"
390     select DEFAULT_UIMAGE
391--- a/arch/powerpc/platforms/83xx/Makefile
392+++ b/arch/powerpc/platforms/83xx/Makefile
393@@ -6,6 +6,7 @@ obj-$(CONFIG_SUSPEND) += suspend.o susp
394 obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
395 obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
396 obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
397+obj-$(CONFIG_RB_PPC) += rbppc.o
398 obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
399 obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o
400 obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o
401--- /dev/null
402+++ b/arch/powerpc/platforms/83xx/rbppc.c
403@@ -0,0 +1,316 @@
404+/*
405+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
406+ * Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
407+ * Copyright (C) Mikrotik 2007
408+ *
409+ * This program is free software; you can redistribute it and/or modify it
410+ * under the terms of the GNU General Public License as published by the
411+ * Free Software Foundation; either version 2 of the License, or (at your
412+ * option) any later version.
413+ */
414+
415+#include <linux/delay.h>
416+#include <linux/root_dev.h>
417+#include <linux/initrd.h>
418+#include <linux/interrupt.h>
419+#include <linux/of_platform.h>
420+#include <linux/of_device.h>
421+#include <linux/of_platform.h>
422+#include <asm/time.h>
423+#include <asm/ipic.h>
424+#include <asm/udbg.h>
425+#include <asm/qe.h>
426+#include <asm/qe_ic.h>
427+#include <sysdev/fsl_soc.h>
428+#include <sysdev/fsl_pci.h>
429+#include "mpc83xx.h"
430+
431+#define SYSCTL 0x100
432+#define SICRL 0x014
433+
434+#define GTCFR2 0x04
435+#define GTMDR4 0x22
436+#define GTRFR4 0x26
437+#define GTCNR4 0x2e
438+#define GTVER4 0x36
439+#define GTPSR4 0x3e
440+
441+#define GTCFR_BCM 0x40
442+#define GTCFR_STP4 0x20
443+#define GTCFR_RST4 0x10
444+#define GTCFR_STP3 0x02
445+#define GTCFR_RST3 0x01
446+
447+#define GTMDR_ORI 0x10
448+#define GTMDR_FRR 0x08
449+#define GTMDR_ICLK16 0x04
450+
451+extern int par_io_data_set(u8 port, u8 pin, u8 val);
452+extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
453+ int assignment, int has_irq);
454+
455+static unsigned timer_freq;
456+static void *gtm;
457+
458+static int beeper_irq;
459+static unsigned beeper_gpio_pin[2];
460+
461+irqreturn_t rbppc_timer_irq(int irq, void *ptr)
462+{
463+ static int toggle = 0;
464+
465+ par_io_data_set(beeper_gpio_pin[0], beeper_gpio_pin[1], toggle);
466+ toggle = !toggle;
467+
468+ /* ack interrupt */
469+ out_be16(gtm + GTVER4, 3);
470+
471+ return IRQ_HANDLED;
472+}
473+
474+void rbppc_beep(unsigned freq)
475+{
476+ unsigned gtmdr;
477+
478+ if (freq > 5000) freq = 5000;
479+
480+ if (!gtm)
481+ return;
482+ if (!freq) {
483+ out_8(gtm + GTCFR2, GTCFR_STP4 | GTCFR_STP3);
484+ return;
485+ }
486+
487+ out_8(gtm + GTCFR2, GTCFR_RST4 | GTCFR_STP3);
488+ out_be16(gtm + GTPSR4, 255);
489+ gtmdr = GTMDR_FRR | GTMDR_ICLK16;
490+ if (beeper_irq != NO_IRQ) gtmdr |= GTMDR_ORI;
491+ out_be16(gtm + GTMDR4, gtmdr);
492+ out_be16(gtm + GTVER4, 3);
493+
494+ out_be16(gtm + GTRFR4, timer_freq / 16 / 256 / freq / 2);
495+ out_be16(gtm + GTCNR4, 0);
496+}
497+EXPORT_SYMBOL(rbppc_beep);
498+
499+static void __init rbppc_setup_arch(void)
500+{
501+ struct device_node *np;
502+
503+ np = of_find_node_by_type(NULL, "cpu");
504+ if (np) {
505+ const unsigned *fp = of_get_property(np, "clock-frequency", NULL);
506+ loops_per_jiffy = fp ? *fp / HZ : 0;
507+
508+ of_node_put(np);
509+ }
510+
511+ np = of_find_node_by_name(NULL, "serial");
512+ if (np) {
513+ timer_freq =
514+ *(unsigned *) of_get_property(np, "clock-frequency", NULL);
515+ of_node_put(np);
516+ }
517+
518+#ifdef CONFIG_PCI
519+ np = of_find_node_by_type(NULL, "pci");
520+ if (np) {
521+ mpc83xx_add_bridge(np);
522+ }
523+#endif
524+
525+#ifdef CONFIG_QUICC_ENGINE
526+ np = of_find_node_by_name(np, "par_io");
527+ if (np) {
528+ qe_reset();
529+ par_io_init(np);
530+ of_node_put(np);
531+
532+ np = NULL;
533+ while (1) {
534+ np = of_find_node_by_name(np, "ucc");
535+ if (!np) break;
536+
537+ par_io_of_config(np);
538+ }
539+ }
540+#endif
541+
542+}
543+
544+void __init rbppc_init_IRQ(void)
545+{
546+ struct device_node *np;
547+
548+ np = of_find_node_by_type(NULL, "ipic");
549+ if (np) {
550+ ipic_init(np, 0);
551+ ipic_set_default_priority();
552+ of_node_put(np);
553+ }
554+
555+#ifdef CONFIG_QUICC_ENGINE
556+ np = of_find_node_by_type(NULL, "qeic");
557+ if (np) {
558+ qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
559+ of_node_put(np);
560+ }
561+#endif
562+}
563+
564+static int __init rbppc_probe(void)
565+{
566+ char *model;
567+
568+ model = of_get_flat_dt_prop(of_get_flat_dt_root(), "model", NULL);
569+
570+ if (!model)
571+ return 0;
572+
573+ if (strcmp(model, "RB600") == 0)
574+ return 1;
575+
576+ return 0;
577+}
578+
579+static void __init rbppc_beeper_init(struct device_node *beeper)
580+{
581+ struct resource res;
582+ struct device_node *gpio;
583+ const unsigned *pin;
584+ const unsigned *gpio_id;
585+
586+ if (of_address_to_resource(beeper, 0, &res)) {
587+ printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: No region specified\n", beeper->full_name);
588+ return;
589+ }
590+
591+ pin = of_get_property(beeper, "gpio", NULL);
592+ if (pin) {
593+ gpio = of_find_node_by_phandle(pin[0]);
594+
595+ if (!gpio) {
596+ printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: GPIO handle %x not found\n", beeper->full_name, pin[0]);
597+ return;
598+ }
599+
600+ gpio_id = of_get_property(gpio, "device-id", NULL);
601+ if (!gpio_id) {
602+ printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: No device-id specified in GPIO\n", beeper->full_name);
603+ return;
604+ }
605+
606+ beeper_gpio_pin[0] = *gpio_id;
607+ beeper_gpio_pin[1] = pin[1];
608+
609+ par_io_config_pin(*gpio_id, pin[1], 1, 0, 0, 0);
610+ } else {
611+ void *sysctl;
612+
613+ sysctl = ioremap_nocache(get_immrbase() + SYSCTL, 0x100);
614+ out_be32(sysctl + SICRL,
615+ in_be32(sysctl + SICRL) | (1 << (31 - 19)));
616+ iounmap(sysctl);
617+ }
618+
619+ gtm = ioremap_nocache(res.start, res.end - res.start + 1);
620+
621+ beeper_irq = irq_of_parse_and_map(beeper, 0);
622+ if (beeper_irq != NO_IRQ) {
623+ int e = request_irq(beeper_irq, rbppc_timer_irq, 0, "beeper", NULL);
624+ if (e) {
625+ printk(KERN_ERR "rbppc_beeper_init(%s): Request of beeper irq failed!\n", beeper->full_name);
626+ }
627+ }
628+}
629+
630+#define SBIT(x) (0x80000000 >> (x))
631+#define DBIT(x, y) ((y) << (32 - (((x % 16) + 1) * 2)))
632+
633+#define SICRL_RB600(x) ((x) + (0x114 >> 2))
634+#define GPIO_DIR_RB600(x) ((x) + (0xc00 >> 2))
635+#define GPIO_DATA_RB600(x) ((x) + (0xc08 >> 2))
636+
637+static void rbppc_restart(char *cmd)
638+{
639+ __be32 __iomem *reg;
640+
641+ reg = ioremap(get_immrbase(), 0x1000);
642+ local_irq_disable();
643+ out_be32(SICRL_RB600(reg), in_be32(SICRL_RB600(reg)) & ~0x00800000);
644+ out_be32(GPIO_DIR_RB600(reg), in_be32(GPIO_DIR_RB600(reg)) | SBIT(2));
645+ out_be32(GPIO_DATA_RB600(reg), in_be32(GPIO_DATA_RB600(reg)) & ~SBIT(2));
646+
647+ while (1);
648+}
649+
650+static void rbppc_halt(void)
651+{
652+ while (1);
653+}
654+
655+static struct of_device_id rbppc_ids[] = {
656+ { .type = "soc", },
657+ { .compatible = "soc", },
658+ { .compatible = "simple-bus", },
659+ { .compatible = "gianfar", },
660+ { },
661+};
662+
663+static int __init rbppc_declare_of_platform_devices(void)
664+{
665+ struct device_node *np;
666+ unsigned idx;
667+
668+ of_platform_bus_probe(NULL, rbppc_ids, NULL);
669+
670+ np = of_find_node_by_type(NULL, "mdio");
671+ if (np) {
672+ unsigned len;
673+ unsigned *res;
674+ const unsigned *eres;
675+ struct device_node *ep;
676+
677+ ep = of_find_compatible_node(NULL, "network", "ucc_geth");
678+ if (ep) {
679+ eres = of_get_property(ep, "reg", &len);
680+ res = (unsigned *) of_get_property(np, "reg", &len);
681+ if (res && eres) {
682+ res[0] = eres[0] + 0x120;
683+ }
684+ }
685+ }
686+
687+ np = of_find_node_by_name(NULL, "nand");
688+ if (np) {
689+ of_platform_device_create(np, "nand", NULL);
690+ }
691+
692+ idx = 0;
693+ for_each_node_by_type(np, "rb,cf") {
694+ char dev_name[12];
695+ snprintf(dev_name, sizeof(dev_name), "cf.%u", idx);
696+ of_platform_device_create(np, dev_name, NULL);
697+ ++idx;
698+ }
699+
700+ np = of_find_node_by_name(NULL, "beeper");
701+ if (np) {
702+ rbppc_beeper_init(np);
703+ }
704+
705+ return 0;
706+}
707+machine_device_initcall(rb600, rbppc_declare_of_platform_devices);
708+
709+define_machine(rb600) {
710+ .name = "MikroTik RouterBOARD 600 series",
711+ .probe = rbppc_probe,
712+ .setup_arch = rbppc_setup_arch,
713+ .init_IRQ = rbppc_init_IRQ,
714+ .get_irq = ipic_get_irq,
715+ .restart = rbppc_restart,
716+ .halt = rbppc_halt,
717+ .time_init = mpc83xx_time_init,
718+ .calibrate_decr = generic_calibrate_decr,
719+};
720--- a/arch/powerpc/platforms/Kconfig
721+++ b/arch/powerpc/platforms/Kconfig
722@@ -142,6 +142,10 @@ config GENERIC_IOMAP
723     bool
724     default n
725 
726+config RB_IOMAP
727+ bool
728+ default y if RB_PPC
729+
730 source "drivers/cpufreq/Kconfig"
731 
732 menu "CPU Frequency drivers"
733--- a/arch/powerpc/sysdev/Makefile
734+++ b/arch/powerpc/sysdev/Makefile
735@@ -56,3 +56,5 @@ obj-$(CONFIG_PPC_MPC52xx) += mpc5xxx_clo
736 ifeq ($(CONFIG_SUSPEND),y)
737 obj-$(CONFIG_6xx) += 6xx-suspend.o
738 endif
739+
740+obj-$(CONFIG_RB_IOMAP) += rb_iomap.o
741--- /dev/null
742+++ b/arch/powerpc/sysdev/rb_iomap.c
743@@ -0,0 +1,223 @@
744+#include <linux/init.h>
745+#include <linux/pci.h>
746+#include <linux/mm.h>
747+#include <asm/io.h>
748+
749+#define LOCALBUS_START 0x40000000
750+#define LOCALBUS_MASK 0x007fffff
751+#define LOCALBUS_REGMASK 0x001fffff
752+
753+static void __iomem *localbus_base;
754+
755+static inline int is_localbus(void __iomem *addr)
756+{
757+ return ((unsigned) addr & ~LOCALBUS_MASK) == LOCALBUS_START;
758+}
759+
760+static inline unsigned localbus_regoff(unsigned reg) {
761+ return (reg << 16) | (((reg ^ 8) & 8) << 17);
762+}
763+
764+static inline void __iomem *localbus_addr(void __iomem *addr)
765+{
766+ return localbus_base
767+ + ((unsigned) addr & LOCALBUS_MASK & ~LOCALBUS_REGMASK)
768+ + localbus_regoff((unsigned) addr & LOCALBUS_REGMASK);
769+}
770+
771+unsigned int ioread8(void __iomem *addr)
772+{
773+ if (is_localbus(addr))
774+ return in_be16(localbus_addr(addr)) >> 8;
775+ return readb(addr);
776+}
777+EXPORT_SYMBOL(ioread8);
778+
779+unsigned int ioread16(void __iomem *addr)
780+{
781+ if (is_localbus(addr))
782+ return le16_to_cpu(in_be16(localbus_addr(addr)));
783+ return readw(addr);
784+}
785+EXPORT_SYMBOL(ioread16);
786+
787+unsigned int ioread16be(void __iomem *addr)
788+{
789+ return in_be16(addr);
790+}
791+EXPORT_SYMBOL(ioread16be);
792+
793+unsigned int ioread32(void __iomem *addr)
794+{
795+ return readl(addr);
796+}
797+EXPORT_SYMBOL(ioread32);
798+
799+unsigned int ioread32be(void __iomem *addr)
800+{
801+ return in_be32(addr);
802+}
803+EXPORT_SYMBOL(ioread32be);
804+
805+void iowrite8(u8 val, void __iomem *addr)
806+{
807+ if (is_localbus(addr))
808+ out_be16(localbus_addr(addr), ((u16) val) << 8);
809+ else
810+ writeb(val, addr);
811+}
812+EXPORT_SYMBOL(iowrite8);
813+
814+void iowrite16(u16 val, void __iomem *addr)
815+{
816+ if (is_localbus(addr))
817+ out_be16(localbus_addr(addr), cpu_to_le16(val));
818+ else
819+ writew(val, addr);
820+}
821+EXPORT_SYMBOL(iowrite16);
822+
823+void iowrite16be(u16 val, void __iomem *addr)
824+{
825+ out_be16(addr, val);
826+}
827+EXPORT_SYMBOL(iowrite16be);
828+
829+void iowrite32(u32 val, void __iomem *addr)
830+{
831+ writel(val, addr);
832+}
833+EXPORT_SYMBOL(iowrite32);
834+
835+void iowrite32be(u32 val, void __iomem *addr)
836+{
837+ out_be32(addr, val);
838+}
839+EXPORT_SYMBOL(iowrite32be);
840+
841+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
842+{
843+ if (is_localbus(addr)) {
844+ unsigned i;
845+ void *laddr = localbus_addr(addr);
846+ u8 *buf = dst;
847+
848+ for (i = 0; i < count; ++i) {
849+ *buf++ = in_be16(laddr) >> 8;
850+ }
851+ } else {
852+ _insb((u8 __iomem *) addr, dst, count);
853+ }
854+}
855+EXPORT_SYMBOL(ioread8_rep);
856+
857+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
858+{
859+ if (is_localbus(addr)) {
860+ unsigned i;
861+ void *laddr = localbus_addr(addr);
862+ u16 *buf = dst;
863+
864+ for (i = 0; i < count; ++i) {
865+ *buf++ = in_be16(laddr);
866+ }
867+ } else {
868+ _insw_ns((u16 __iomem *) addr, dst, count);
869+ }
870+}
871+EXPORT_SYMBOL(ioread16_rep);
872+
873+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
874+{
875+ _insl_ns((u32 __iomem *) addr, dst, count);
876+}
877+EXPORT_SYMBOL(ioread32_rep);
878+
879+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
880+{
881+ if (is_localbus(addr)) {
882+ unsigned i;
883+ void *laddr = localbus_addr(addr);
884+ const u8 *buf = src;
885+
886+ for (i = 0; i < count; ++i) {
887+ out_be16(laddr, ((u16) *buf++) << 8);
888+ }
889+ } else {
890+ _outsb((u8 __iomem *) addr, src, count);
891+ }
892+}
893+EXPORT_SYMBOL(iowrite8_rep);
894+
895+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
896+{
897+ if (is_localbus(addr)) {
898+ unsigned i;
899+ void *laddr = localbus_addr(addr);
900+ const u16 *buf = src;
901+
902+ for (i = 0; i < count; ++i) {
903+ out_be16(laddr, *buf++);
904+ }
905+ } else {
906+ _outsw_ns((u16 __iomem *) addr, src, count);
907+ }
908+}
909+EXPORT_SYMBOL(iowrite16_rep);
910+
911+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
912+{
913+ _outsl_ns((u32 __iomem *) addr, src, count);
914+}
915+EXPORT_SYMBOL(iowrite32_rep);
916+
917+void __iomem *ioport_map(unsigned long port, unsigned int len)
918+{
919+ return (void __iomem *) (port + _IO_BASE);
920+}
921+EXPORT_SYMBOL(ioport_unmap);
922+
923+void ioport_unmap(void __iomem *addr)
924+{
925+ /* Nothing to do */
926+}
927+EXPORT_SYMBOL(ioport_map);
928+
929+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
930+{
931+ unsigned long start = pci_resource_start(dev, bar);
932+ unsigned long len = pci_resource_len(dev, bar);
933+ unsigned long flags = pci_resource_flags(dev, bar);
934+
935+ if (!len)
936+ return NULL;
937+ if (max && len > max)
938+ len = max;
939+ if (flags & IORESOURCE_IO)
940+ return ioport_map(start, len);
941+ if (flags & IORESOURCE_MEM)
942+ return ioremap(start, len);
943+ /* What? */
944+ return NULL;
945+}
946+EXPORT_SYMBOL(pci_iomap);
947+
948+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
949+{
950+ /* Nothing to do */
951+}
952+EXPORT_SYMBOL(pci_iounmap);
953+
954+void __iomem *localbus_map(unsigned long addr, unsigned int len)
955+{
956+ if (!localbus_base)
957+ localbus_base = ioremap(addr & ~LOCALBUS_MASK,
958+ LOCALBUS_MASK + 1);
959+ return (void *) (LOCALBUS_START + (addr & LOCALBUS_MASK));
960+}
961+EXPORT_SYMBOL(localbus_map);
962+
963+void localbus_unmap(void __iomem *addr)
964+{
965+}
966+EXPORT_SYMBOL(localbus_unmap);
967--- a/drivers/ata/Kconfig
968+++ b/drivers/ata/Kconfig
969@@ -781,5 +781,12 @@ config PATA_BF54X
970 
971       If unsure, say N.
972 
973+config PATA_RB_PPC
974+ tristate "MikroTik RB600 PATA support"
975+ depends on RB_PPC
976+ help
977+ This option enables support for PATA devices on MikroTik RouterBOARD
978+ 600 series boards.
979+
980 endif # ATA_SFF
981 endif # ATA
982--- a/drivers/ata/Makefile
983+++ b/drivers/ata/Makefile
984@@ -77,6 +77,7 @@ obj-$(CONFIG_PATA_PLATFORM) += pata_plat
985 obj-$(CONFIG_PATA_AT91) += pata_at91.o
986 obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
987 obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
988+obj-$(CONFIG_PATA_RB_PPC) += pata_rbppc_cf.o
989 # Should be last but two libata driver
990 obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
991 # Should be last but one libata driver
992--- /dev/null
993+++ b/drivers/ata/pata_rbppc_cf.c
994@@ -0,0 +1,701 @@
995+/*
996+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
997+ * Copyright (C) Mikrotik 2007
998+ *
999+ * This program is free software; you can redistribute it and/or modify it
1000+ * under the terms of the GNU General Public License as published by the
1001+ * Free Software Foundation; either version 2 of the License, or (at your
1002+ * option) any later version.
1003+ */
1004+
1005+#include <linux/kernel.h>
1006+#include <linux/module.h>
1007+#include <linux/init.h>
1008+#include <scsi/scsi_host.h>
1009+#include <linux/libata.h>
1010+#include <linux/of_platform.h>
1011+#include <linux/ata_platform.h>
1012+
1013+#define DEBUG_UPM 0
1014+
1015+#define DRV_NAME "pata_rbppc_cf"
1016+#define DRV_VERSION "0.0.2"
1017+
1018+#define DEV2SEL_OFFSET 0x00100000
1019+
1020+#define IMMR_LBCFG_OFFSET 0x00005000
1021+#define IMMR_LBCFG_SIZE 0x00001000
1022+
1023+#define LOCAL_BUS_MCMR 0x00000078
1024+#define MxMR_OP_MASK 0x30000000
1025+#define MxMR_OP_NORMAL 0x00000000
1026+#define MxMR_OP_WRITE 0x10000000
1027+#define MxMR_OP_READ 0x20000000
1028+#define MxMR_OP_RUN 0x30000000
1029+#define MxMR_LUPWAIT_LOW 0x08000000
1030+#define MxMR_LUPWAIT_HIGH 0x00000000
1031+#define MxMR_LUPWAIT_ENABLE 0x00040000
1032+#define MxMR_RLF_MASK 0x0003c000
1033+#define MxMR_RLF_SHIFT 14
1034+#define MxMR_WLF_MASK 0x00003c00
1035+#define MxMR_WLF_SHIFT 10
1036+#define MxMR_MAD_MASK 0x0000003f
1037+#define LOCAL_BUS_MDR 0x00000088
1038+#define LOCAL_BUS_LCRR 0x000000D4
1039+#define LCRR_CLKDIV_MASK 0x0000000f
1040+
1041+#define LOOP_SIZE 4
1042+
1043+#define UPM_READ_SINGLE_OFFSET 0x00
1044+#define UPM_WRITE_SINGLE_OFFSET 0x18
1045+#define UPM_DATA_SIZE 0x40
1046+
1047+#define LBT_CPUIN_MIN 0
1048+#define LBT_CPUOUT_MIN 1
1049+#define LBT_CPUOUT_MAX 2
1050+#define LBT_EXTDEL_MIN 3
1051+#define LBT_EXTDEL_MAX 4
1052+#define LBT_SIZE 5
1053+
1054+/* UPM machine configuration bits */
1055+#define N_BASE 0x00f00000
1056+#define N_CS 0xf0000000
1057+#define N_CS_H1 0xc0000000
1058+#define N_CS_H2 0x30000000
1059+#define N_WE 0x0f000000
1060+#define N_WE_H1 0x0c000000
1061+#define N_WE_H2 0x03000000
1062+#define N_OE 0x00030000
1063+#define N_OE_H1 0x00020000
1064+#define N_OE_H2 0x00010000
1065+#define WAEN 0x00001000
1066+#define REDO_2 0x00000100
1067+#define REDO_3 0x00000200
1068+#define REDO_4 0x00000300
1069+#define LOOP 0x00000080
1070+#define NA 0x00000008
1071+#define UTA 0x00000004
1072+#define LAST 0x00000001
1073+
1074+#define REDO_VAL(mult) (REDO_2 * ((mult) - 1))
1075+#define REDO_MAX_MULT 4
1076+
1077+#define READ_BASE (N_BASE | N_WE)
1078+#define WRITE_BASE (N_BASE | N_OE)
1079+#define EMPTY (N_BASE | N_CS | N_OE | N_WE | LAST)
1080+
1081+#define EOF_UPM_SETTINGS 0
1082+#define ANOTHER_TIMING 1
1083+
1084+#define OA_CPUIN_MIN 0x01
1085+#define OA_CPUOUT_MAX 0x02
1086+#define OD_CPUOUT_MIN 0x04
1087+#define OA_CPUOUT_DELTA 0x06
1088+#define OA_EXTDEL_MAX 0x08
1089+#define OD_EXTDEL_MIN 0x10
1090+#define OA_EXTDEL_DELTA 0x18
1091+#define O_MIN_CYCLE_TIME 0x20
1092+#define O_MINUS_PREV 0x40
1093+#define O_HALF_CYCLE 0x80
1094+
1095+extern void __iomem *localbus_map(unsigned long addr, unsigned int len);
1096+extern void localbus_unmap(void __iomem *addr);
1097+
1098+struct rbppc_cf_info {
1099+ unsigned lbcfg_addr;
1100+ unsigned clk_time_ps;
1101+ int cur_mode;
1102+ u32 lb_timings[LBT_SIZE];
1103+};
1104+static struct rbppc_cf_info *rbinfo = NULL;
1105+
1106+struct upm_setting {
1107+ unsigned value;
1108+ unsigned ns[7];
1109+ unsigned clk_minus;
1110+ unsigned group_size;
1111+ unsigned options;
1112+};
1113+
1114+static const struct upm_setting cfUpmReadSingle[] = {
1115+ { READ_BASE | N_OE,
1116+ /* t1 - ADDR setup time */
1117+ { 70, 50, 30, 30, 25, 15, 10 }, 0, 0, (OA_CPUOUT_DELTA |
1118+ OA_EXTDEL_MAX) },
1119+ { READ_BASE | N_OE_H1,
1120+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
1121+ { READ_BASE,
1122+ /* t2 - OE0 time */
1123+ { 290, 290, 290, 80, 70, 65, 55 }, 0, 2, (OA_CPUOUT_MAX |
1124+ OA_CPUIN_MIN) },
1125+ { READ_BASE | WAEN,
1126+ { 1, 1, 1, 1, 1, 0, 0 }, 0, 0, 0 },
1127+ { READ_BASE | UTA,
1128+ { 1, 1, 1, 1, 1, 1, 1 }, 0, 0, 0 },
1129+ { READ_BASE | N_OE,
1130+ /* t9 - ADDR hold time */
1131+ { 20, 15, 10, 10, 10, 10, 10 }, 0, 0, (OA_CPUOUT_DELTA |
1132+ OD_EXTDEL_MIN) },
1133+ { READ_BASE | N_OE | N_CS_H2,
1134+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
1135+ { READ_BASE | N_OE | N_CS,
1136+ /* t6Z -IORD data tristate */
1137+ { 30, 30, 30, 30, 30, 20, 20 }, 1, 1, O_MINUS_PREV },
1138+ { ANOTHER_TIMING,
1139+ /* t2i -IORD recovery time */
1140+ { 0, 0, 0, 70, 25, 25, 20 }, 2, 0, 0 },
1141+ { ANOTHER_TIMING,
1142+ /* CS 0 -> 1 MAX */
1143+ { 0, 0, 0, 0, 0, 0, 0 }, 1, 0, (OA_CPUOUT_DELTA |
1144+ OA_EXTDEL_MAX) },
1145+ { READ_BASE | N_OE | N_CS | LAST,
1146+ { 1, 1, 1, 1, 1, 1, 1 }, 0, 0, 0 },
1147+ { EOF_UPM_SETTINGS,
1148+ /* min total cycle time - includes turnaround and ALE cycle */
1149+ { 600, 383, 240, 180, 120, 100, 80 }, 2, 0, O_MIN_CYCLE_TIME },
1150+};
1151+
1152+static const struct upm_setting cfUpmWriteSingle[] = {
1153+ { WRITE_BASE | N_WE,
1154+ /* t1 - ADDR setup time */
1155+ { 70, 50, 30, 30, 25, 15, 10 }, 0, 0, (OA_CPUOUT_DELTA |
1156+ OA_EXTDEL_MAX) },
1157+ { WRITE_BASE | N_WE_H1,
1158+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
1159+ { WRITE_BASE,
1160+ /* t2 - WE0 time */
1161+ { 290, 290, 290, 80, 70, 65, 55 }, 0, 1, OA_CPUOUT_DELTA },
1162+ { WRITE_BASE | WAEN,
1163+ { 1, 1, 1, 1, 1, 0, 0 }, 0, 0, 0 },
1164+ { WRITE_BASE | N_WE,
1165+ /* t9 - ADDR hold time */
1166+ { 20, 15, 10, 10, 10, 10, 10 }, 0, 0, (OA_CPUOUT_DELTA |
1167+ OD_EXTDEL_MIN) },
1168+ { WRITE_BASE | N_WE | N_CS_H2,
1169+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
1170+ { WRITE_BASE | N_WE | N_CS,
1171+ /* t4 - DATA hold time */
1172+ { 30, 20, 15, 10, 10, 10, 10 }, 0, 1, O_MINUS_PREV },
1173+ { ANOTHER_TIMING,
1174+ /* t2i -IOWR recovery time */
1175+ { 0, 0, 0, 70, 25, 25, 20 }, 1, 0, 0 },
1176+ { ANOTHER_TIMING,
1177+ /* CS 0 -> 1 MAX */
1178+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, (OA_CPUOUT_DELTA |
1179+ OA_EXTDEL_MAX) },
1180+ { WRITE_BASE | N_WE | N_CS | UTA | LAST,
1181+ { 1, 1, 1, 1, 1, 1, 1 }, 0, 0, 0 },
1182+ /* min total cycle time - includes ALE cycle */
1183+ { EOF_UPM_SETTINGS,
1184+ { 600, 383, 240, 180, 120, 100, 80 }, 1, 0, O_MIN_CYCLE_TIME },
1185+};
1186+
1187+static u8 rbppc_cf_check_status(struct ata_port *ap) {
1188+ u8 val = ioread8(ap->ioaddr.status_addr);
1189+ if (val == 0xF9)
1190+ val = 0x7F;
1191+ return val;
1192+}
1193+
1194+static u8 rbppc_cf_check_altstatus(struct ata_port *ap) {
1195+ u8 val = ioread8(ap->ioaddr.altstatus_addr);
1196+ if (val == 0xF9)
1197+ val = 0x7F;
1198+ return val;
1199+}
1200+
1201+static void rbppc_cf_dummy_noret(struct ata_port *ap) { }
1202+static int rbppc_cf_dummy_ret0(struct ata_port *ap) { return 0; }
1203+
1204+static int ps2clk(int ps, unsigned clk_time_ps) {
1205+ int psMaxOver;
1206+ if (ps <= 0) return 0;
1207+
1208+ /* round down if <= 2% over clk border, but no more than 1/4 clk cycle */
1209+ psMaxOver = ps * 2 / 100;
1210+ if (4 * psMaxOver > clk_time_ps) {
1211+ psMaxOver = clk_time_ps / 4;
1212+ }
1213+ return (ps + clk_time_ps - 1 - psMaxOver) / clk_time_ps;
1214+}
1215+
1216+static int upm_gen_ps_table(const struct upm_setting *upm,
1217+ int mode, struct rbppc_cf_info *info,
1218+ int *psFinal) {
1219+ int uidx;
1220+ int lastUpmValIdx = 0;
1221+ int group_start_idx = -1;
1222+ int group_left_num = -1;
1223+ int clk_time_ps = info->clk_time_ps;
1224+
1225+ for (uidx = 0; upm[uidx].value != EOF_UPM_SETTINGS; ++uidx) {
1226+ const struct upm_setting *us = upm + uidx;
1227+ unsigned opt = us->options;
1228+ int ps = us->ns[mode] * 1000 - us->clk_minus * clk_time_ps;
1229+
1230+ if (opt & OA_CPUIN_MIN) ps += info->lb_timings[LBT_CPUIN_MIN];
1231+ if (opt & OD_CPUOUT_MIN) ps -= info->lb_timings[LBT_CPUOUT_MIN];
1232+ if (opt & OA_CPUOUT_MAX) ps += info->lb_timings[LBT_CPUOUT_MAX];
1233+ if (opt & OD_EXTDEL_MIN) ps -= info->lb_timings[LBT_EXTDEL_MIN];
1234+ if (opt & OA_EXTDEL_MAX) ps += info->lb_timings[LBT_EXTDEL_MAX];
1235+
1236+ if (us->value == ANOTHER_TIMING) {
1237+ /* use longest timing from alternatives */
1238+ if (psFinal[lastUpmValIdx] < ps) {
1239+ psFinal[lastUpmValIdx] = ps;
1240+ }
1241+ ps = 0;
1242+ }
1243+ else {
1244+ if (us->group_size) {
1245+ group_start_idx = uidx;
1246+ group_left_num = us->group_size;
1247+ }
1248+ else if (group_left_num > 0) {
1249+ /* group time is divided on all group members */
1250+ int clk = ps2clk(ps, clk_time_ps);
1251+ psFinal[group_start_idx] -= clk * clk_time_ps;
1252+ --group_left_num;
1253+ }
1254+ if ((opt & O_MINUS_PREV) && lastUpmValIdx > 0) {
1255+ int clk = ps2clk(psFinal[lastUpmValIdx],
1256+ clk_time_ps);
1257+ ps -= clk * clk_time_ps;
1258+ }
1259+ lastUpmValIdx = uidx;
1260+ }
1261+ psFinal[uidx] = ps;
1262+ }
1263+ return uidx;
1264+}
1265+
1266+static int free_half(int ps, int clk, int clk_time_ps) {
1267+ if (clk < 2) return 0;
1268+ return (clk * clk_time_ps - ps) * 2 >= clk_time_ps;
1269+}
1270+
1271+static void upm_gen_clk_table(const struct upm_setting *upm,
1272+ int mode, int clk_time_ps,
1273+ int max_uidx, const int *psFinal, int *clkFinal) {
1274+ int clk_cycle_time;
1275+ int clk_total;
1276+ int uidx;
1277+
1278+ /* convert picoseconds to clocks */
1279+ clk_total = 0;
1280+ for (uidx = 0; uidx < max_uidx; ++uidx) {
1281+ int clk = ps2clk(psFinal[uidx], clk_time_ps);
1282+ clkFinal[uidx] = clk;
1283+ clk_total += clk;
1284+ }
1285+
1286+ /* check possibility of half cycle usage */
1287+ for (uidx = 1; uidx < max_uidx - 1; ++uidx) {
1288+ if ((upm[uidx].options & O_HALF_CYCLE) &&
1289+ free_half(psFinal[uidx - 1], clkFinal[uidx - 1],
1290+ clk_time_ps) &&
1291+ free_half(psFinal[uidx + 1], clkFinal[uidx + 1],
1292+ clk_time_ps)) {
1293+ ++clkFinal[uidx];
1294+ --clkFinal[uidx - 1];
1295+ --clkFinal[uidx + 1];
1296+ }
1297+ }
1298+
1299+ if ((upm[max_uidx].options & O_MIN_CYCLE_TIME) == 0) return;
1300+
1301+ /* check cycle time, adjust timings if needed */
1302+ clk_cycle_time = (ps2clk(upm[max_uidx].ns[mode] * 1000, clk_time_ps) -
1303+ upm[max_uidx].clk_minus);
1304+ uidx = 0;
1305+ while (clk_total < clk_cycle_time) {
1306+ /* extend all timings in round-robin to match cycle time */
1307+ if (clkFinal[uidx]) {
1308+#if DEBUG_UPM
1309+ printk(KERN_INFO "extending %u by 1 clk\n", uidx);
1310+#endif
1311+ ++clkFinal[uidx];
1312+ ++clk_total;
1313+ }
1314+ ++uidx;
1315+ if (uidx == max_uidx) uidx = 0;
1316+ }
1317+}
1318+
1319+static void add_data_val(unsigned val, int *clkLeft, int maxClk,
1320+ unsigned *data, int *dataIdx) {
1321+ if (*clkLeft == 0) return;
1322+
1323+ if (maxClk == 0 && *clkLeft >= LOOP_SIZE * 2) {
1324+ int times;
1325+ int times1;
1326+ int times2;
1327+
1328+ times = *clkLeft / LOOP_SIZE;
1329+ if (times > REDO_MAX_MULT * 2) times = REDO_MAX_MULT * 2;
1330+ times1 = times / 2;
1331+ times2 = times - times1;
1332+
1333+ val |= LOOP;
1334+ data[*dataIdx] = val | REDO_VAL(times1);
1335+ ++(*dataIdx);
1336+ data[*dataIdx] = val | REDO_VAL(times2);
1337+ ++(*dataIdx);
1338+
1339+ *clkLeft -= times * LOOP_SIZE;
1340+ return;
1341+ }
1342+
1343+ if (maxClk < 1 || maxClk > REDO_MAX_MULT) maxClk = REDO_MAX_MULT;
1344+ if (*clkLeft < maxClk) maxClk = *clkLeft;
1345+
1346+ *clkLeft -= maxClk;
1347+ val |= REDO_VAL(maxClk);
1348+
1349+ data[*dataIdx] = val;
1350+ ++(*dataIdx);
1351+}
1352+
1353+static int upm_gen_final_data(const struct upm_setting *upm,
1354+ int max_uidx, int *clkFinal, unsigned *data) {
1355+ int dataIdx;
1356+ int uidx;
1357+
1358+ dataIdx = 0;
1359+ for (uidx = 0; uidx < max_uidx; ++uidx) {
1360+ int clk = clkFinal[uidx];
1361+ while (clk > 0) {
1362+ add_data_val(upm[uidx].value, &clk, 0,
1363+ data, &dataIdx);
1364+ }
1365+ }
1366+ return dataIdx;
1367+}
1368+
1369+static int conv_upm_table(const struct upm_setting *upm,
1370+ int mode, struct rbppc_cf_info *info,
1371+ unsigned *data) {
1372+#if DEBUG_UPM
1373+ int uidx;
1374+#endif
1375+ int psFinal[32];
1376+ int clkFinal[32];
1377+ int max_uidx;
1378+ int data_len;
1379+
1380+ max_uidx = upm_gen_ps_table(upm, mode, info, psFinal);
1381+
1382+ upm_gen_clk_table(upm, mode, info->clk_time_ps, max_uidx,
1383+ psFinal, clkFinal);
1384+
1385+#if DEBUG_UPM
1386+ /* dump out debug info */
1387+ for (uidx = 0; uidx < max_uidx; ++uidx) {
1388+ if (clkFinal[uidx]) {
1389+ printk(KERN_INFO "idx %d val %08x clk %d ps %d\n",
1390+ uidx, upm[uidx].value,
1391+ clkFinal[uidx], psFinal[uidx]);
1392+ }
1393+ }
1394+#endif
1395+
1396+ data_len = upm_gen_final_data(upm, max_uidx, clkFinal, data);
1397+
1398+#if DEBUG_UPM
1399+ for (uidx = 0; uidx < data_len; ++uidx) {
1400+ printk(KERN_INFO "cf UPM x result: idx %d val %08x\n",
1401+ uidx, data[uidx]);
1402+ }
1403+#endif
1404+ return 0;
1405+}
1406+
1407+static int gen_upm_data(int mode, struct rbppc_cf_info *info, unsigned *data) {
1408+ int i;
1409+
1410+ for (i = 0; i < UPM_DATA_SIZE; ++i) {
1411+ data[i] = EMPTY;
1412+ }
1413+
1414+ if (conv_upm_table(cfUpmReadSingle, mode, info, data + UPM_READ_SINGLE_OFFSET)) {
1415+ return -1;
1416+ }
1417+ if (conv_upm_table(cfUpmWriteSingle, mode, info, data + UPM_WRITE_SINGLE_OFFSET)) {
1418+ return -1;
1419+ }
1420+ return 0;
1421+}
1422+
1423+static void rbppc_cf_program_upm(void *upmMemAddr, volatile void *lbcfg_mxmr, volatile void *lbcfg_mdr, const unsigned *upmData, unsigned offset, unsigned len) {
1424+ unsigned i;
1425+ unsigned mxmr;
1426+
1427+ mxmr = in_be32(lbcfg_mxmr);
1428+ mxmr &= ~(MxMR_OP_MASK | MxMR_MAD_MASK);
1429+ mxmr |= (MxMR_OP_WRITE | offset);
1430+ out_be32(lbcfg_mxmr, mxmr);
1431+ in_be32(lbcfg_mxmr); /* flush MxMR write */
1432+
1433+ for (i = 0; i < len; ++i) {
1434+ int to;
1435+ unsigned data = upmData[i + offset];
1436+ out_be32(lbcfg_mdr, data);
1437+ in_be32(lbcfg_mdr); /* flush MDR write */
1438+
1439+ iowrite8(1, upmMemAddr); /* dummy write to any CF addr */
1440+
1441+ /* wait for dummy write to complete */
1442+ for (to = 10000; to >= 0; --to) {
1443+ mxmr = in_be32(lbcfg_mxmr);
1444+ if (((mxmr ^ (i + 1)) & MxMR_MAD_MASK) == 0) {
1445+ break;
1446+ }
1447+ if (to == 0) {
1448+ printk(KERN_ERR "rbppc_cf_program_upm: UPMx program error at 0x%x: Timeout\n", i);
1449+ }
1450+ }
1451+ }
1452+ mxmr &= ~(MxMR_OP_MASK | MxMR_RLF_MASK | MxMR_WLF_MASK);
1453+ mxmr |= (MxMR_OP_NORMAL | (LOOP_SIZE << MxMR_RLF_SHIFT) | (LOOP_SIZE << MxMR_WLF_SHIFT));
1454+ out_be32(lbcfg_mxmr, mxmr);
1455+}
1456+
1457+static int rbppc_cf_update_piomode(struct ata_port *ap, int mode) {
1458+ struct rbppc_cf_info *info = (struct rbppc_cf_info *)ap->host->private_data;
1459+ void *lbcfgBase;
1460+ unsigned upmData[UPM_DATA_SIZE];
1461+
1462+ if (gen_upm_data(mode, info, upmData)) {
1463+ return -1;
1464+ }
1465+
1466+ lbcfgBase = ioremap_nocache(info->lbcfg_addr, IMMR_LBCFG_SIZE);
1467+
1468+ rbppc_cf_program_upm(ap->ioaddr.cmd_addr, ((char *)lbcfgBase) + LOCAL_BUS_MCMR, ((char *)lbcfgBase) + LOCAL_BUS_MDR, upmData, 0, UPM_DATA_SIZE);
1469+ iounmap(lbcfgBase);
1470+ return 0;
1471+}
1472+
1473+static void rbppc_cf_set_piomode(struct ata_port *ap, struct ata_device *adev)
1474+{
1475+ struct rbppc_cf_info *info = (struct rbppc_cf_info *)ap->host->private_data;
1476+ int mode = adev->pio_mode - XFER_PIO_0;
1477+
1478+ DPRINTK("rbppc_cf_set_piomode: PIO %d\n", mode);
1479+ if (mode < 0) mode = 0;
1480+ if (mode > 6) mode = 6;
1481+
1482+ if (info->cur_mode < 0 || info->cur_mode > mode) {
1483+ if (rbppc_cf_update_piomode(ap, mode) == 0) {
1484+ printk(KERN_INFO "rbppc_cf_set_piomode: PIO mode changed to %d\n", mode);
1485+ info->cur_mode = mode;
1486+ }
1487+ }
1488+}
1489+
1490+static struct scsi_host_template rbppc_cf_sht = {
1491+ ATA_BASE_SHT(DRV_NAME),
1492+};
1493+
1494+static struct ata_port_operations rbppc_cf_port_ops = {
1495+ .inherits = &ata_bmdma_port_ops,
1496+
1497+ .sff_check_status = rbppc_cf_check_status,
1498+ .sff_check_altstatus = rbppc_cf_check_altstatus,
1499+
1500+ .set_piomode = rbppc_cf_set_piomode,
1501+
1502+ .port_start = rbppc_cf_dummy_ret0,
1503+
1504+ .sff_irq_clear = rbppc_cf_dummy_noret,
1505+};
1506+
1507+static int rbppc_cf_init_info(struct of_device *pdev, struct rbppc_cf_info *info) {
1508+ struct device_node *np;
1509+ struct resource res;
1510+ const u32 *u32ptr;
1511+ void *lbcfgBase;
1512+ void *lbcfg_lcrr;
1513+ unsigned lbc_clk_khz;
1514+ unsigned lbc_extra_divider = 1;
1515+ unsigned ccb_freq_hz;
1516+ unsigned lb_div;
1517+
1518+ u32ptr = of_get_property(pdev->node, "lbc_extra_divider", NULL);
1519+ if (u32ptr && *u32ptr) {
1520+ lbc_extra_divider = *u32ptr;
1521+#if DEBUG_UPM
1522+ printk(KERN_INFO "rbppc_cf_init_info: LBC extra divider %u\n",
1523+ lbc_extra_divider);
1524+#endif
1525+ }
1526+
1527+ np = of_find_node_by_type(NULL, "serial");
1528+ if (!np) {
1529+ printk(KERN_ERR "rbppc_cf_init_info: No serial node found\n");
1530+ return -1;
1531+ }
1532+ u32ptr = of_get_property(np, "clock-frequency", NULL);
1533+ if (u32ptr == 0 || *u32ptr == 0) {
1534+ printk(KERN_ERR "rbppc_cf_init_info: Serial does not have clock-frequency\n");
1535+ of_node_put(np);
1536+ return -1;
1537+ }
1538+ ccb_freq_hz = *u32ptr;
1539+ of_node_put(np);
1540+
1541+ np = of_find_node_by_type(NULL, "soc");
1542+ if (!np) {
1543+ printk(KERN_ERR "rbppc_cf_init_info: No soc node found\n");
1544+ return -1;
1545+ }
1546+ if (of_address_to_resource(np, 0, &res)) {
1547+ printk(KERN_ERR "rbppc_cf_init_info: soc does not have resource\n");
1548+ of_node_put(np);
1549+ return -1;
1550+ }
1551+ info->lbcfg_addr = res.start + IMMR_LBCFG_OFFSET;
1552+ of_node_put(np);
1553+
1554+ lbcfgBase = ioremap_nocache(info->lbcfg_addr, IMMR_LBCFG_SIZE);
1555+ lbcfg_lcrr = ((char*)lbcfgBase) + LOCAL_BUS_LCRR;
1556+ lb_div = (in_be32(lbcfg_lcrr) & LCRR_CLKDIV_MASK) * lbc_extra_divider;
1557+ iounmap(lbcfgBase);
1558+
1559+ lbc_clk_khz = ccb_freq_hz / (1000 * lb_div);
1560+ info->clk_time_ps = 1000000000 / lbc_clk_khz;
1561+ printk(KERN_INFO "rbppc_cf_init_info: Using Local-Bus clock %u kHz %u ps\n",
1562+ lbc_clk_khz, info->clk_time_ps);
1563+
1564+ u32ptr = of_get_property(pdev->node, "lb-timings", NULL);
1565+ if (u32ptr) {
1566+ memcpy(info->lb_timings, u32ptr, LBT_SIZE * sizeof(*u32ptr));
1567+#if DEBUG_UPM
1568+ printk(KERN_INFO "rbppc_cf_init_info: Got LB timings <%u %u %u %u %u>\n",
1569+ u32ptr[0], u32ptr[1], u32ptr[2], u32ptr[3], u32ptr[4]);
1570+#endif
1571+ }
1572+ info->cur_mode = -1;
1573+ return 0;
1574+}
1575+
1576+static int rbppc_cf_probe(struct of_device *pdev,
1577+ const struct of_device_id *match)
1578+{
1579+ struct ata_host *host;
1580+ struct ata_port *ap;
1581+ struct rbppc_cf_info *info = NULL;
1582+ struct resource res;
1583+ void *baddr;
1584+ const u32 *u32ptr;
1585+ int irq_level = 0;
1586+ int err = -ENOMEM;
1587+
1588+ printk(KERN_INFO "rbppc_cf_probe: MikroTik RouterBOARD 600 series Compact Flash PATA driver, version " DRV_VERSION "\n");
1589+
1590+ if (rbinfo == NULL) {
1591+ info = kmalloc(sizeof(*info), GFP_KERNEL);
1592+ if (info == NULL) {
1593+ printk(KERN_ERR "rbppc_cf_probe: Out of memory\n");
1594+ goto err_info;
1595+ }
1596+ memset(info, 0, sizeof(*info));
1597+
1598+ if (rbppc_cf_init_info(pdev, info)) {
1599+ goto err_info;
1600+ }
1601+ rbinfo = info;
1602+ }
1603+
1604+ u32ptr = of_get_property(pdev->node, "interrupt-at-level", NULL);
1605+ if (u32ptr) {
1606+ irq_level = *u32ptr;
1607+ printk(KERN_INFO "rbppc_cf_probe: IRQ level %u\n", irq_level);
1608+ }
1609+
1610+ if (of_address_to_resource(pdev->node, 0, &res)) {
1611+ printk(KERN_ERR "rbppc_cf_probe: No reg property found\n");
1612+ goto err_info;
1613+ }
1614+
1615+ host = ata_host_alloc(&pdev->dev, 1);
1616+ if (!host)
1617+ goto err_info;
1618+
1619+ baddr = localbus_map(res.start, res.end - res.start + 1);
1620+ host->iomap = baddr;
1621+ host->private_data = rbinfo;
1622+
1623+ ap = host->ports[0];
1624+ ap->ops = &rbppc_cf_port_ops;
1625+ ap->pio_mask = 0x7F; /* PIO modes 0-6 */
1626+ ap->flags = ATA_FLAG_NO_LEGACY;
1627+ ap->mwdma_mask = 0;
1628+
1629+ ap->ioaddr.cmd_addr = baddr;
1630+ ata_sff_std_ports(&ap->ioaddr);
1631+ ap->ioaddr.ctl_addr = ap->ioaddr.cmd_addr + 14;
1632+ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
1633+ ap->ioaddr.bmdma_addr = 0;
1634+
1635+ err = ata_host_activate(
1636+ host,
1637+ irq_of_parse_and_map(pdev->node, 0), ata_sff_interrupt,
1638+ irq_level ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW,
1639+ &rbppc_cf_sht);
1640+ if (!err) return 0;
1641+
1642+ localbus_unmap(baddr);
1643+err_info:
1644+ if (info) {
1645+ kfree(info);
1646+ rbinfo = NULL;
1647+ }
1648+ return err;
1649+}
1650+
1651+static int rbppc_cf_remove(struct of_device *pdev)
1652+{
1653+ struct device *dev = &pdev->dev;
1654+ struct ata_host *host = dev_get_drvdata(dev);
1655+
1656+ if (host == NULL) return -1;
1657+
1658+ ata_host_detach(host);
1659+ return 0;
1660+}
1661+
1662+static struct of_device_id rbppc_cf_ids[] = {
1663+ { .name = "cf", },
1664+ { },
1665+};
1666+
1667+static struct of_platform_driver rbppc_cf_driver = {
1668+ .name = "cf",
1669+ .probe = rbppc_cf_probe,
1670+ .remove = rbppc_cf_remove,
1671+ .match_table = rbppc_cf_ids,
1672+ .driver = {
1673+ .name = "rbppc-cf",
1674+ .owner = THIS_MODULE,
1675+ },
1676+};
1677+
1678+static int __init rbppc_init(void)
1679+{
1680+ return of_register_platform_driver(&rbppc_cf_driver);
1681+}
1682+
1683+static void __exit rbppc_exit(void)
1684+{
1685+ of_unregister_platform_driver(&rbppc_cf_driver);
1686+}
1687+
1688+MODULE_AUTHOR("Mikrotikls SIA");
1689+MODULE_AUTHOR("Noah Fontes");
1690+MODULE_DESCRIPTION("MikroTik RouterBOARD 600 series Compact Flash PATA driver");
1691+MODULE_LICENSE("GPL");
1692+MODULE_VERSION(DRV_VERSION);
1693+
1694+module_init(rbppc_init);
1695+module_exit(rbppc_exit);
1696--- a/drivers/mtd/nand/Kconfig
1697+++ b/drivers/mtd/nand/Kconfig
1698@@ -403,6 +403,13 @@ config MTD_NAND_PLATFORM
1699       devices. You will need to provide platform-specific functions
1700       via platform_data.
1701 
1702+config MTD_NAND_RB_PPC
1703+ tristate "MikroTik RB600 NAND support"
1704+ depends on MTD_NAND && MTD_PARTITIONS && RB_PPC
1705+ help
1706+ This option enables support for the NAND device on MikroTik
1707+ RouterBOARD 600 series boards.
1708+
1709 config MTD_ALAUDA
1710     tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
1711     depends on MTD_NAND && USB
1712--- a/drivers/mtd/nand/Makefile
1713+++ b/drivers/mtd/nand/Makefile
1714@@ -31,6 +31,7 @@ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) +=
1715 obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
1716 obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o
1717 obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
1718+obj-$(CONFIG_MTD_NAND_RB_PPC) += rbppc_nand.o
1719 obj-$(CONFIG_MTD_ALAUDA) += alauda.o
1720 obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
1721 obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
1722--- /dev/null
1723+++ b/drivers/mtd/nand/rbppc_nand.c
1724@@ -0,0 +1,252 @@
1725+/*
1726+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
1727+ * Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
1728+ * Copyright (C) Mikrotik 2007
1729+ *
1730+ * This program is free software; you can redistribute it and/or modify it
1731+ * under the terms of the GNU General Public License as published by the
1732+ * Free Software Foundation; either version 2 of the License, or (at your
1733+ * option) any later version.
1734+ */
1735+
1736+#include <linux/init.h>
1737+#include <linux/mtd/nand.h>
1738+#include <linux/mtd/mtd.h>
1739+#include <linux/mtd/partitions.h>
1740+#include <linux/of_platform.h>
1741+#include <asm/of_platform.h>
1742+#include <asm/of_device.h>
1743+#include <linux/delay.h>
1744+#include <asm/io.h>
1745+
1746+#define DRV_NAME "rbppc_nand"
1747+#define DRV_VERSION "0.0.2"
1748+
1749+static struct mtd_info rmtd;
1750+static struct nand_chip rnand;
1751+
1752+struct rbppc_nand_info {
1753+ void *gpi;
1754+ void *gpo;
1755+ void *localbus;
1756+
1757+ unsigned gpio_rdy;
1758+ unsigned gpio_nce;
1759+ unsigned gpio_cle;
1760+ unsigned gpio_ale;
1761+ unsigned gpio_ctrls;
1762+};
1763+
1764+/* We must use the OOB layout from yaffs 1 if we want this to be recognized
1765+ * properly. Borrowed from the OpenWRT patches for the RB532.
1766+ *
1767+ * See <https://dev.openwrt.org/browser/trunk/target/linux/rb532/
1768+ * patches-2.6.28/025-rb532_nand_fixup.patch> for more details.
1769+ */
1770+static struct nand_ecclayout rbppc_nand_oob_16 = {
1771+ .eccbytes = 6,
1772+ .eccpos = { 8, 9, 10, 13, 14, 15 },
1773+ .oobavail = 9,
1774+ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
1775+};
1776+
1777+static struct mtd_partition rbppc_nand_partition_info[] = {
1778+ {
1779+ name: "RouterBOARD NAND Boot",
1780+ offset: 0,
1781+ size: 4 * 1024 * 1024,
1782+ },
1783+ {
1784+ name: "RouterBOARD NAND Main",
1785+ offset: MTDPART_OFS_NXTBLK,
1786+ size: MTDPART_SIZ_FULL,
1787+ },
1788+};
1789+
1790+static int rbppc_nand_dev_ready(struct mtd_info *mtd) {
1791+ struct nand_chip *chip = mtd->priv;
1792+ struct rbppc_nand_info *priv = chip->priv;
1793+
1794+ return in_be32(priv->gpi) & priv->gpio_rdy;
1795+}
1796+
1797+static void rbppc_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) {
1798+ struct nand_chip *chip = mtd->priv;
1799+ struct rbppc_nand_info *priv = chip->priv;
1800+
1801+ if (ctrl & NAND_CTRL_CHANGE) {
1802+ unsigned val = in_be32(priv->gpo);
1803+ if (!(val & priv->gpio_nce)) {
1804+ /* make sure Local Bus has done NAND operations */
1805+ readb(priv->localbus);
1806+ }
1807+
1808+ if (ctrl & NAND_CLE) {
1809+ val |= priv->gpio_cle;
1810+ } else {
1811+ val &= ~priv->gpio_cle;
1812+ }
1813+ if (ctrl & NAND_ALE) {
1814+ val |= priv->gpio_ale;
1815+ } else {
1816+ val &= ~priv->gpio_ale;
1817+ }
1818+ if (!(ctrl & NAND_NCE)) {
1819+ val |= priv->gpio_nce;
1820+ } else {
1821+ val &= ~priv->gpio_nce;
1822+ }
1823+ out_be32(priv->gpo, val);
1824+
1825+ /* make sure GPIO output has changed */
1826+ val ^= in_be32(priv->gpo);
1827+ if (val & priv->gpio_ctrls) {
1828+ printk(KERN_ERR "rbppc_nand_hwcontrol: NAND GPO change failed 0x%08x\n", val);
1829+ }
1830+ }
1831+
1832+ if (cmd != NAND_CMD_NONE) writeb(cmd, chip->IO_ADDR_W);
1833+}
1834+
1835+static void rbppc_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
1836+{
1837+ struct nand_chip *chip = mtd->priv;
1838+ memcpy(buf, chip->IO_ADDR_R, len);
1839+}
1840+
1841+static unsigned init_ok = 0;
1842+
1843+static int rbppc_nand_probe(struct of_device *pdev,
1844+ const struct of_device_id *match)
1845+{
1846+ struct device_node *gpio;
1847+ struct device_node *nnand;
1848+ struct resource res;
1849+ struct rbppc_nand_info *info;
1850+ void *baddr;
1851+ const unsigned *rdy, *nce, *cle, *ale;
1852+
1853+ printk(KERN_INFO "rbppc_nand_probe: MikroTik RouterBOARD 600 series NAND driver, version " DRV_VERSION "\n");
1854+
1855+ info = kmalloc(sizeof(*info), GFP_KERNEL);
1856+
1857+ rdy = of_get_property(pdev->node, "rdy", NULL);
1858+ nce = of_get_property(pdev->node, "nce", NULL);
1859+ cle = of_get_property(pdev->node, "cle", NULL);
1860+ ale = of_get_property(pdev->node, "ale", NULL);
1861+
1862+ if (!rdy || !nce || !cle || !ale) {
1863+ printk(KERN_ERR "rbppc_nand_probe: GPIO properties are missing\n");
1864+ goto err;
1865+ }
1866+ if (rdy[0] != nce[0] || rdy[0] != cle[0] || rdy[0] != ale[0]) {
1867+ printk(KERN_ERR "rbppc_nand_probe: Different GPIOs are not supported\n");
1868+ goto err;
1869+ }
1870+
1871+ gpio = of_find_node_by_phandle(rdy[0]);
1872+ if (!gpio) {
1873+ printk(KERN_ERR "rbppc_nand_probe: No GPIO<%x> node found\n", *rdy);
1874+ goto err;
1875+ }
1876+ if (of_address_to_resource(gpio, 0, &res)) {
1877+ printk(KERN_ERR "rbppc_nand_probe: No reg property in GPIO found\n");
1878+ goto err;
1879+ }
1880+ info->gpo = ioremap_nocache(res.start, res.end - res.start + 1);
1881+
1882+ if (!of_address_to_resource(gpio, 1, &res)) {
1883+ info->gpi = ioremap_nocache(res.start, res.end - res.start + 1);
1884+ } else {
1885+ info->gpi = info->gpo;
1886+ }
1887+ of_node_put(gpio);
1888+
1889+ info->gpio_rdy = 1 << (31 - rdy[1]);
1890+ info->gpio_nce = 1 << (31 - nce[1]);
1891+ info->gpio_cle = 1 << (31 - cle[1]);
1892+ info->gpio_ale = 1 << (31 - ale[1]);
1893+ info->gpio_ctrls = info->gpio_nce | info->gpio_cle | info->gpio_ale;
1894+
1895+ nnand = of_find_node_by_name(NULL, "nnand");
1896+ if (!nnand) {
1897+ printk("rbppc_nand_probe: No nNAND found\n");
1898+ goto err;
1899+ }
1900+ if (of_address_to_resource(nnand, 0, &res)) {
1901+ printk("rbppc_nand_probe: No reg property in nNAND found\n");
1902+ goto err;
1903+ }
1904+ of_node_put(nnand);
1905+ info->localbus = ioremap_nocache(res.start, res.end - res.start + 1);
1906+
1907+ if (of_address_to_resource(pdev->node, 0, &res)) {
1908+ printk("rbppc_nand_probe: No reg property found\n");
1909+ goto err;
1910+ }
1911+ baddr = ioremap_nocache(res.start, res.end - res.start + 1);
1912+
1913+ memset(&rnand, 0, sizeof(rnand));
1914+ rnand.cmd_ctrl = rbppc_nand_cmd_ctrl;
1915+ rnand.dev_ready = rbppc_nand_dev_ready;
1916+ rnand.read_buf = rbppc_nand_read_buf;
1917+ rnand.IO_ADDR_W = baddr;
1918+ rnand.IO_ADDR_R = baddr;
1919+ rnand.priv = info;
1920+
1921+ memset(&rmtd, 0, sizeof(rmtd));
1922+ rnand.ecc.mode = NAND_ECC_SOFT;
1923+ rnand.ecc.layout = &rbppc_nand_oob_16;
1924+ rnand.chip_delay = 25;
1925+ rnand.options |= NAND_NO_AUTOINCR;
1926+ rmtd.priv = &rnand;
1927+ rmtd.owner = THIS_MODULE;
1928+
1929+ if (nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1)) {
1930+ printk(KERN_ERR "rbppc_nand_probe: RouterBOARD NAND device not found\n");
1931+ return -ENXIO;
1932+ }
1933+
1934+ add_mtd_partitions(&rmtd, rbppc_nand_partition_info, 2);
1935+ init_ok = 1;
1936+ return 0;
1937+
1938+err:
1939+ kfree(info);
1940+ return -1;
1941+}
1942+
1943+static struct of_device_id rbppc_nand_ids[] = {
1944+ { .name = "nand", },
1945+ { },
1946+};
1947+
1948+static struct of_platform_driver rbppc_nand_driver = {
1949+ .name = "nand",
1950+ .probe = rbppc_nand_probe,
1951+ .match_table = rbppc_nand_ids,
1952+ .driver = {
1953+ .name = "rbppc-nand",
1954+ .owner = THIS_MODULE,
1955+ },
1956+};
1957+
1958+static int __init rbppc_nand_init(void)
1959+{
1960+ return of_register_platform_driver(&rbppc_nand_driver);
1961+}
1962+
1963+static void __exit rbppc_nand_exit(void)
1964+{
1965+ of_unregister_platform_driver(&rbppc_nand_driver);
1966+}
1967+
1968+MODULE_AUTHOR("Mikrotikls SIA");
1969+MODULE_AUTHOR("Noah Fontes");
1970+MODULE_AUTHOR("Michael Guntsche");
1971+MODULE_DESCRIPTION("MikroTik RouterBOARD 600 series NAND driver");
1972+MODULE_LICENSE("GPL");
1973+MODULE_VERSION(DRV_VERSION);
1974+
1975+module_init(rbppc_nand_init);
1976+module_exit(rbppc_nand_exit);
1977

Archive Download this file



interactive