Path: blob/master/arch/powerpc/platforms/85xx/mpc85xx_cds.c
10820 views
/*1* MPC85xx setup and early boot code plus other random bits.2*3* Maintained by Kumar Gala (see MAINTAINERS for contact information)4*5* Copyright 2005 Freescale Semiconductor Inc.6*7* This program is free software; you can redistribute it and/or modify it8* under the terms of the GNU General Public License as published by the9* Free Software Foundation; either version 2 of the License, or (at your10* option) any later version.11*/1213#include <linux/stddef.h>14#include <linux/kernel.h>15#include <linux/init.h>16#include <linux/errno.h>17#include <linux/reboot.h>18#include <linux/pci.h>19#include <linux/kdev_t.h>20#include <linux/major.h>21#include <linux/console.h>22#include <linux/delay.h>23#include <linux/seq_file.h>24#include <linux/initrd.h>25#include <linux/module.h>26#include <linux/interrupt.h>27#include <linux/fsl_devices.h>28#include <linux/of_platform.h>2930#include <asm/system.h>31#include <asm/pgtable.h>32#include <asm/page.h>33#include <asm/atomic.h>34#include <asm/time.h>35#include <asm/io.h>36#include <asm/machdep.h>37#include <asm/ipic.h>38#include <asm/pci-bridge.h>39#include <asm/irq.h>40#include <mm/mmu_decl.h>41#include <asm/prom.h>42#include <asm/udbg.h>43#include <asm/mpic.h>44#include <asm/i8259.h>4546#include <sysdev/fsl_soc.h>47#include <sysdev/fsl_pci.h>4849/* CADMUS info */50/* xxx - galak, move into device tree */51#define CADMUS_BASE (0xf8004000)52#define CADMUS_SIZE (256)53#define CM_VER (0)54#define CM_CSR (1)55#define CM_RST (2)565758static int cds_pci_slot = 2;59static volatile u8 *cadmus;6061#ifdef CONFIG_PCI6263#define ARCADIA_HOST_BRIDGE_IDSEL 1764#define ARCADIA_2ND_BRIDGE_IDSEL 36566static int mpc85xx_exclude_device(struct pci_controller *hose,67u_char bus, u_char devfn)68{69/* We explicitly do not go past the Tundra 320 Bridge */70if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))71return PCIBIOS_DEVICE_NOT_FOUND;72if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))73return PCIBIOS_DEVICE_NOT_FOUND;74else75return PCIBIOS_SUCCESSFUL;76}7778static void mpc85xx_cds_restart(char *cmd)79{80struct pci_dev *dev;81u_char tmp;8283if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686,84NULL))) {8586/* Use the VIA Super Southbridge to force a PCI reset */87pci_read_config_byte(dev, 0x47, &tmp);88pci_write_config_byte(dev, 0x47, tmp | 1);8990/* Flush the outbound PCI write queues */91pci_read_config_byte(dev, 0x47, &tmp);9293/*94* At this point, the harware reset should have triggered.95* However, if it doesn't work for some mysterious reason,96* just fall through to the default reset below.97*/9899pci_dev_put(dev);100}101102/*103* If we can't find the VIA chip (maybe the P2P bridge is disabled)104* or the VIA chip reset didn't work, just use the default reset.105*/106fsl_rstcr_restart(NULL);107}108109static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev)110{111u_char c;112if (dev->vendor == PCI_VENDOR_ID_VIA) {113switch (dev->device) {114case PCI_DEVICE_ID_VIA_82C586_1:115/*116* U-Boot does not set the enable bits117* for the IDE device. Force them on here.118*/119pci_read_config_byte(dev, 0x40, &c);120c |= 0x03; /* IDE: Chip Enable Bits */121pci_write_config_byte(dev, 0x40, c);122123/*124* Since only primary interface works, force the125* IDE function to standard primary IDE interrupt126* w/ 8259 offset127*/128dev->irq = 14;129pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);130break;131/*132* Force legacy USB interrupt routing133*/134case PCI_DEVICE_ID_VIA_82C586_2:135/* There are two USB controllers.136* Identify them by functon number137*/138if (PCI_FUNC(dev->devfn) == 3)139dev->irq = 11;140else141dev->irq = 10;142pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);143default:144break;145}146}147}148149static void __devinit skip_fake_bridge(struct pci_dev *dev)150{151/* Make it an error to skip the fake bridge152* in pci_setup_device() in probe.c */153dev->hdr_type = 0x7f;154}155DECLARE_PCI_FIXUP_EARLY(0x1957, 0x3fff, skip_fake_bridge);156DECLARE_PCI_FIXUP_EARLY(0x3fff, 0x1957, skip_fake_bridge);157DECLARE_PCI_FIXUP_EARLY(0xff3f, 0x5719, skip_fake_bridge);158159#ifdef CONFIG_PPC_I8259160static void mpc85xx_8259_cascade_handler(unsigned int irq,161struct irq_desc *desc)162{163unsigned int cascade_irq = i8259_irq();164165if (cascade_irq != NO_IRQ)166/* handle an interrupt from the 8259 */167generic_handle_irq(cascade_irq);168169/* check for any interrupts from the shared IRQ line */170handle_fasteoi_irq(irq, desc);171}172173static irqreturn_t mpc85xx_8259_cascade_action(int irq, void *dev_id)174{175return IRQ_HANDLED;176}177178static struct irqaction mpc85xxcds_8259_irqaction = {179.handler = mpc85xx_8259_cascade_action,180.flags = IRQF_SHARED,181.name = "8259 cascade",182};183#endif /* PPC_I8259 */184#endif /* CONFIG_PCI */185186static void __init mpc85xx_cds_pic_init(void)187{188struct mpic *mpic;189struct resource r;190struct device_node *np = NULL;191192np = of_find_node_by_type(np, "open-pic");193194if (np == NULL) {195printk(KERN_ERR "Could not find open-pic node\n");196return;197}198199if (of_address_to_resource(np, 0, &r)) {200printk(KERN_ERR "Failed to map mpic register space\n");201of_node_put(np);202return;203}204205mpic = mpic_alloc(np, r.start,206MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,2070, 256, " OpenPIC ");208BUG_ON(mpic == NULL);209210/* Return the mpic node */211of_node_put(np);212213mpic_init(mpic);214}215216#if defined(CONFIG_PPC_I8259) && defined(CONFIG_PCI)217static int mpc85xx_cds_8259_attach(void)218{219int ret;220struct device_node *np = NULL;221struct device_node *cascade_node = NULL;222int cascade_irq;223224/* Initialize the i8259 controller */225for_each_node_by_type(np, "interrupt-controller")226if (of_device_is_compatible(np, "chrp,iic")) {227cascade_node = np;228break;229}230231if (cascade_node == NULL) {232printk(KERN_DEBUG "Could not find i8259 PIC\n");233return -ENODEV;234}235236cascade_irq = irq_of_parse_and_map(cascade_node, 0);237if (cascade_irq == NO_IRQ) {238printk(KERN_ERR "Failed to map cascade interrupt\n");239return -ENXIO;240}241242i8259_init(cascade_node, 0);243of_node_put(cascade_node);244245/*246* Hook the interrupt to make sure desc->action is never NULL.247* This is required to ensure that the interrupt does not get248* disabled when the last user of the shared IRQ line frees their249* interrupt.250*/251if ((ret = setup_irq(cascade_irq, &mpc85xxcds_8259_irqaction))) {252printk(KERN_ERR "Failed to setup cascade interrupt\n");253return ret;254}255256/* Success. Connect our low-level cascade handler. */257irq_set_handler(cascade_irq, mpc85xx_8259_cascade_handler);258259return 0;260}261machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach);262263#endif /* CONFIG_PPC_I8259 */264265/*266* Setup the architecture267*/268static void __init mpc85xx_cds_setup_arch(void)269{270#ifdef CONFIG_PCI271struct device_node *np;272#endif273274if (ppc_md.progress)275ppc_md.progress("mpc85xx_cds_setup_arch()", 0);276277cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE);278cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;279280if (ppc_md.progress) {281char buf[40];282snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n",283cadmus[CM_VER], cds_pci_slot);284ppc_md.progress(buf, 0);285}286287#ifdef CONFIG_PCI288for_each_node_by_type(np, "pci") {289if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||290of_device_is_compatible(np, "fsl,mpc8548-pcie")) {291struct resource rsrc;292of_address_to_resource(np, 0, &rsrc);293if ((rsrc.start & 0xfffff) == 0x8000)294fsl_add_bridge(np, 1);295else296fsl_add_bridge(np, 0);297}298}299300ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;301ppc_md.pci_exclude_device = mpc85xx_exclude_device;302#endif303}304305static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)306{307uint pvid, svid, phid1;308309pvid = mfspr(SPRN_PVR);310svid = mfspr(SPRN_SVR);311312seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");313seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]);314seq_printf(m, "PVR\t\t: 0x%x\n", pvid);315seq_printf(m, "SVR\t\t: 0x%x\n", svid);316317/* Display cpu Pll setting */318phid1 = mfspr(SPRN_HID1);319seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));320}321322323/*324* Called very early, device-tree isn't unflattened325*/326static int __init mpc85xx_cds_probe(void)327{328unsigned long root = of_get_flat_dt_root();329330return of_flat_dt_is_compatible(root, "MPC85xxCDS");331}332333static struct of_device_id __initdata of_bus_ids[] = {334{ .type = "soc", },335{ .compatible = "soc", },336{ .compatible = "simple-bus", },337{ .compatible = "gianfar", },338{},339};340341static int __init declare_of_platform_devices(void)342{343return of_platform_bus_probe(NULL, of_bus_ids, NULL);344}345machine_device_initcall(mpc85xx_cds, declare_of_platform_devices);346347define_machine(mpc85xx_cds) {348.name = "MPC85xx CDS",349.probe = mpc85xx_cds_probe,350.setup_arch = mpc85xx_cds_setup_arch,351.init_IRQ = mpc85xx_cds_pic_init,352.show_cpuinfo = mpc85xx_cds_show_cpuinfo,353.get_irq = mpic_get_irq,354#ifdef CONFIG_PCI355.restart = mpc85xx_cds_restart,356.pcibios_fixup_bus = fsl_pcibios_fixup_bus,357#else358.restart = fsl_rstcr_restart,359#endif360.calibrate_decr = generic_calibrate_decr,361.progress = udbg_progress,362};363364365