Two parts to this post. Part 1, the DTS: / { model = "StorCenter"; compatible = "storcenter"; #address-cells = <1>; #size-cells = <1>; cpus { #address-cells = <1>; #size-cells = <0>; PowerPC,603e { /* Really 8241 */ device_type = "cpu"; reg = <0>; /* XXX correct? */ clock-frequency = ; /* Hz */ timebase-frequency = ; /* Hz */ bus-frequency = <0>; /* Following required by dtc but not used */ i-cache-line-size = <0>; d-cache-line-size = <0>; i-cache-size = <4000>; d-cache-size = <4000>; }; }; memory { device_type = "memory"; reg = <00000000 04000000>; /* 64MB @ 0x0 */ }; flash at ff800000 { device_type = "rom"; compatible = "direct-mapped"; probe-type = "CFI"; reg = ; bank-width = <1>; /* XXX add protium partitions*/ partitions = < 00000000 0000E000 0000E000 00002000 00010000 00040000 00050000 00200000 00250000 004B0000 00700000 00020000 00720000 00010000 00730000 00010000 00740000 000B0000 >; /* XXX fix names */ partition-names = "uboot2env", "dtb", "uboot2", "emkernel", "emfs", "uboot1", "empty", "uboot1-env", "SysConf"; }; soc10x { #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <2>; device_type = "soc"; compatible = "mpc10x"; store-gathering = <0>; /* 0 == off, !0 == on */ reg = <80000000 00100000>; ranges = <80000000 80000000 70000000 /* pci mem space */ fdf00000 fdf00000 00100000 /* EUMB */ fe000000 fe000000 00c00000 /* pci i/o space */ fec00000 fec00000 00300000 /* pci cfg regs */ fef00000 fef00000 00100000>; /* pci iack */ i2c at fdf03000 { device_type = "i2c"; compatible = "fsl-i2c"; reg = ; interrupts = <5 2>; interrupt-parent = <&mpic>; /* dfsrr; */ rtc@68 { compatible = "dallas,ds1337"; reg = <68>; }; }; serial at fdf04500 { device_type = "serial"; compatible = "ns16550"; reg = ; clock-frequency = ; /* Hz */ current-speed = ; interrupts = <9 2>; interrupt-parent = <&mpic>; }; serial at fdf04600 { device_type = "serial"; compatible = "ns16550"; reg = ; clock-frequency = ; /* Hz */ current-speed = ; interrupts = ; interrupt-parent = <&mpic>; }; mpic: pic at fdf40000 { #interrupt-cells = <2>; #address-cells = <0>; device_type = "open-pic"; compatible = "chrp,open-pic"; interrupt-controller; reg = ; built-in; }; pci at fe800000 { #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; device_type = "pci"; compatible = "mpc10x-pci"; reg = ; ranges = <01000000 0 0 fe000000 0 00c00000 02000000 0 80000000 80000000 0 70000000>; bus-range = <0 ff>; clock-frequency = ; /* Hz */ interrupt-parent = <&mpic>; interrupt-map-mask = ; interrupt-map = < /* XXX need ide */ /* XXX need usb ohci */ /* XXX need usb ohci */ /* XXX need usb ehci */ /* IDSEL 0x15 - ETH */ /* 7800 0 0 1 &mpic 0 1 7800 0 0 2 &mpic 0 1 7800 0 0 3 &mpic 0 1 7800 0 0 4 &mpic 0 1 */ 5800 0 0 1 &mpic 0 1 5800 0 0 2 &mpic 1 1 5800 0 0 3 &mpic 2 1 5800 0 0 4 &mpic 3 1 /* IDSEL 12 - IRQ1 IDE0 */ 6000 0 0 1 &mpic 1 1 6000 0 0 2 &mpic 2 1 6000 0 0 3 &mpic 3 1 6000 0 0 4 &mpic 0 1 /* IDSEL 14 - IRQ3 USB2.0 */ 7000 0 0 1 &mpic 3 1 7000 0 0 2 &mpic 3 1 7000 0 0 3 &mpic 3 1 7000 0 0 4 &mpic 3 1 >; }; }; }; part 2: storcenter.c /* * Board setup routines for the QNAP Turbostation platform (TS-101/TS-201) * * Copyright (C) 2007 Oyvind Repvik (nail@nslu2-linux.org) * * Based on linkstation.c by G. Liakhovetski * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of * any kind, whether express or implied. */ #include #include #include #include #include #include #include #include #include "mpc10x.h" static int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; int *bus_range; printk("Adding PCI host bridge %s\n", dev->full_name); bus_range = (int *) of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); hose = pcibios_alloc_controller(dev); if (hose == NULL) return -ENOMEM; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; /* setup_indirect_pci(hose, MPC10X_MAPB_CNFG_ADDR, MPC10X_MAPB_CNFG_DATA); j */ setup_indirect_pci(hose, MPC10X_MAPB_CNFG_ADDR, MPC10X_MAPB_CNFG_DATA, 0 ); /* Interpret the "ranges" property */ /* This also maps the I/O region and sets isa_io/mem_base */ pci_process_bridge_OF_ranges(hose, dev, 1); return 0; } static void __init storcenter_setup_arch(void) { struct device_node *np; /* Lookup PCI host bridges */ for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) add_bridge(np); printk(KERN_INFO "IOMEGA StorCenter\n"); } /* * Interrupt setup and service. Interrrupts on the turbostation come * from the four PCI slots plus onboard 8241 devices: I2C, DUART. */ static void __init storcenter_init_IRQ(void) { struct mpic *mpic; struct device_node *dnp; void *prop; int size; phys_addr_t paddr; dnp = of_find_node_by_type(NULL, "open-pic"); if (dnp == NULL) return; prop = (struct device_node *)of_get_property(dnp, "reg", &size); paddr = (phys_addr_t)of_translate_address(dnp, prop); mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC "); BUG_ON(mpic == NULL); /* PCI IRQs */ /* * 2.6.12 patch: * openpic_set_sources(0, 5, OpenPIC_Addr + 0x10200); * openpic_set_sources(5, 2, OpenPIC_Addr + 0x11120); * first_irq, num_irqs, __iomem first_ISR * o_ss: i, src: 0, fdf50200 * o_ss: i, src: 1, fdf50220 * o_ss: i, src: 2, fdf50240 * o_ss: i, src: 3, fdf50260 * o_ss: i, src: 4, fdf50280 * o_ss: i, src: 5, fdf51120 * o_ss: i, src: 6, fdf51140 */ mpic_assign_isu(mpic, 0, paddr + 0x10200); mpic_assign_isu(mpic, 1, paddr + 0x10220); mpic_assign_isu(mpic, 2, paddr + 0x10240); mpic_assign_isu(mpic, 3, paddr + 0x10260); mpic_assign_isu(mpic, 4, paddr + 0x10280); mpic_assign_isu(mpic, 5, paddr + 0x11120); mpic_assign_isu(mpic, 6, paddr + 0x11140); mpic_init(mpic); } static void storcenter_restart(char *cmd) { /* Insert restart-stuff */ } static void storcenter_power_off(void) { /* Insert powerdown-stuff */ } static void storcenter_halt(void) { storcenter_power_off(); } static void storcenter_show_cpuinfo(struct seq_file *m) { seq_printf(m, "vendor\t\t: IOMEGA\n"); seq_printf(m, "machine\t\t: StorCenter\n"); } static int __init storcenter_probe(void) { unsigned long root; root = of_get_flat_dt_root(); if (!of_flat_dt_is_compatible(root, "storcenter")) return 0; return 1; } define_machine(storcenter){ .name = "IOMEGA StorCenter", .probe = storcenter_probe, .setup_arch = storcenter_setup_arch, .init_IRQ = storcenter_init_IRQ, .show_cpuinfo = storcenter_show_cpuinfo, .get_irq = mpic_get_irq, .restart = storcenter_restart, .power_off = storcenter_power_off, .halt = storcenter_halt, .calibrate_decr = generic_calibrate_decr, };