Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Board setup routines for the storcenter
0003  *
0004  * Copyright 2007 (C) Oyvind Repvik (nail@nslu2-linux.org)
0005  * Copyright 2007 Andy Wilcox, Jon Loeliger
0006  *
0007  * Based on linkstation.c by G. Liakhovetski
0008  *
0009  * This file is licensed under the terms of the GNU General Public License
0010  * version 2.  This program is licensed "as is" without any warranty of
0011  * any kind, whether express or implied.
0012  */
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/pci.h>
0016 #include <linux/initrd.h>
0017 #include <linux/of_platform.h>
0018 
0019 #include <asm/time.h>
0020 #include <asm/mpic.h>
0021 #include <asm/pci-bridge.h>
0022 
0023 #include "mpc10x.h"
0024 
0025 
0026 static const struct of_device_id storcenter_of_bus[] __initconst = {
0027     { .name = "soc", },
0028     {},
0029 };
0030 
0031 static int __init storcenter_device_probe(void)
0032 {
0033     of_platform_bus_probe(NULL, storcenter_of_bus, NULL);
0034     return 0;
0035 }
0036 machine_device_initcall(storcenter, storcenter_device_probe);
0037 
0038 
0039 static int __init storcenter_add_bridge(struct device_node *dev)
0040 {
0041 #ifdef CONFIG_PCI
0042     int len;
0043     struct pci_controller *hose;
0044     const int *bus_range;
0045 
0046     printk("Adding PCI host bridge %pOF\n", dev);
0047 
0048     hose = pcibios_alloc_controller(dev);
0049     if (hose == NULL)
0050         return -ENOMEM;
0051 
0052     bus_range = of_get_property(dev, "bus-range", &len);
0053     hose->first_busno = bus_range ? bus_range[0] : 0;
0054     hose->last_busno = bus_range ? bus_range[1] : 0xff;
0055 
0056     setup_indirect_pci(hose, MPC10X_MAPB_CNFG_ADDR, MPC10X_MAPB_CNFG_DATA, 0);
0057 
0058     /* Interpret the "ranges" property */
0059     /* This also maps the I/O region and sets isa_io/mem_base */
0060     pci_process_bridge_OF_ranges(hose, dev, 1);
0061 #endif
0062 
0063     return 0;
0064 }
0065 
0066 static void __init storcenter_setup_arch(void)
0067 {
0068     printk(KERN_INFO "IOMEGA StorCenter\n");
0069 }
0070 
0071 static void __init storcenter_setup_pci(void)
0072 {
0073     struct device_node *np;
0074 
0075     /* Lookup PCI host bridges */
0076     for_each_compatible_node(np, "pci", "mpc10x-pci")
0077         storcenter_add_bridge(np);
0078 }
0079 
0080 /*
0081  * Interrupt setup and service.  Interrupts on the turbostation come
0082  * from the four PCI slots plus onboard 8241 devices: I2C, DUART.
0083  */
0084 static void __init storcenter_init_IRQ(void)
0085 {
0086     struct mpic *mpic;
0087 
0088     mpic = mpic_alloc(NULL, 0, 0, 16, 0, " OpenPIC  ");
0089     BUG_ON(mpic == NULL);
0090 
0091     /*
0092      * 16 Serial Interrupts followed by 16 Internal Interrupts.
0093      * I2C is the second internal, so it is at 17, 0x11020.
0094      */
0095     mpic_assign_isu(mpic, 0, mpic->paddr + 0x10200);
0096     mpic_assign_isu(mpic, 1, mpic->paddr + 0x11000);
0097 
0098     mpic_init(mpic);
0099 }
0100 
0101 static void __noreturn storcenter_restart(char *cmd)
0102 {
0103     local_irq_disable();
0104 
0105     /* Set exception prefix high - to the firmware */
0106     mtmsr(mfmsr() | MSR_IP);
0107     isync();
0108 
0109     /* Wait for reset to happen */
0110     for (;;) ;
0111 }
0112 
0113 static int __init storcenter_probe(void)
0114 {
0115     return of_machine_is_compatible("iomega,storcenter");
0116 }
0117 
0118 define_machine(storcenter){
0119     .name           = "IOMEGA StorCenter",
0120     .probe          = storcenter_probe,
0121     .setup_arch         = storcenter_setup_arch,
0122     .discover_phbs      = storcenter_setup_pci,
0123     .init_IRQ       = storcenter_init_IRQ,
0124     .get_irq        = mpic_get_irq,
0125     .restart        = storcenter_restart,
0126     .calibrate_decr     = generic_calibrate_decr,
0127 };