Path: blob/master/arch/powerpc/platforms/cell/setup.c
10818 views
/*1* linux/arch/powerpc/platforms/cell/cell_setup.c2*3* Copyright (C) 1995 Linus Torvalds4* Adapted from 'alpha' version by Gary Thomas5* Modified by Cort Dougan ([email protected])6* Modified by PPC64 Team, IBM Corp7* Modified by Cell Team, IBM Deutschland Entwicklung GmbH8*9* This program is free software; you can redistribute it and/or10* modify it under the terms of the GNU General Public License11* as published by the Free Software Foundation; either version12* 2 of the License, or (at your option) any later version.13*/14#undef DEBUG1516#include <linux/sched.h>17#include <linux/kernel.h>18#include <linux/mm.h>19#include <linux/stddef.h>20#include <linux/unistd.h>21#include <linux/user.h>22#include <linux/reboot.h>23#include <linux/init.h>24#include <linux/delay.h>25#include <linux/irq.h>26#include <linux/seq_file.h>27#include <linux/root_dev.h>28#include <linux/console.h>29#include <linux/mutex.h>30#include <linux/memory_hotplug.h>31#include <linux/of_platform.h>3233#include <asm/mmu.h>34#include <asm/processor.h>35#include <asm/io.h>36#include <asm/pgtable.h>37#include <asm/prom.h>38#include <asm/rtas.h>39#include <asm/pci-bridge.h>40#include <asm/iommu.h>41#include <asm/dma.h>42#include <asm/machdep.h>43#include <asm/time.h>44#include <asm/nvram.h>45#include <asm/cputable.h>46#include <asm/ppc-pci.h>47#include <asm/irq.h>48#include <asm/spu.h>49#include <asm/spu_priv1.h>50#include <asm/udbg.h>51#include <asm/mpic.h>52#include <asm/cell-regs.h>53#include <asm/io-workarounds.h>5455#include "interrupt.h"56#include "pervasive.h"57#include "ras.h"5859#ifdef DEBUG60#define DBG(fmt...) udbg_printf(fmt)61#else62#define DBG(fmt...)63#endif6465static void cell_show_cpuinfo(struct seq_file *m)66{67struct device_node *root;68const char *model = "";6970root = of_find_node_by_path("/");71if (root)72model = of_get_property(root, "model", NULL);73seq_printf(m, "machine\t\t: CHRP %s\n", model);74of_node_put(root);75}7677static void cell_progress(char *s, unsigned short hex)78{79printk("*** %04x : %s\n", hex, s ? s : "");80}8182static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)83{84struct pci_controller *hose;85const char *s;86int i;8788if (!machine_is(cell))89return;9091/* We're searching for a direct child of the PHB */92if (dev->bus->self != NULL || dev->devfn != 0)93return;9495hose = pci_bus_to_host(dev->bus);96if (hose == NULL)97return;9899/* Only on PCIE */100if (!of_device_is_compatible(hose->dn, "pciex"))101return;102103/* And only on axon */104s = of_get_property(hose->dn, "model", NULL);105if (!s || strcmp(s, "Axon") != 0)106return;107108for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {109dev->resource[i].start = dev->resource[i].end = 0;110dev->resource[i].flags = 0;111}112113printk(KERN_DEBUG "PCI: Hiding resources on Axon PCIE RC %s\n",114pci_name(dev));115}116DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);117118static int __devinit cell_setup_phb(struct pci_controller *phb)119{120const char *model;121struct device_node *np;122123int rc = rtas_setup_phb(phb);124if (rc)125return rc;126127np = phb->dn;128model = of_get_property(np, "model", NULL);129if (model == NULL || strcmp(np->name, "pci"))130return 0;131132/* Setup workarounds for spider */133if (strcmp(model, "Spider"))134return 0;135136iowa_register_bus(phb, &spiderpci_ops, &spiderpci_iowa_init,137(void *)SPIDER_PCI_REG_BASE);138return 0;139}140141static const struct of_device_id cell_bus_ids[] __initdata = {142{ .type = "soc", },143{ .compatible = "soc", },144{ .type = "spider", },145{ .type = "axon", },146{ .type = "plb5", },147{ .type = "plb4", },148{ .type = "opb", },149{ .type = "ebc", },150{},151};152153static int __init cell_publish_devices(void)154{155struct device_node *root = of_find_node_by_path("/");156struct device_node *np;157int node;158159/* Publish OF platform devices for southbridge IOs */160of_platform_bus_probe(NULL, cell_bus_ids, NULL);161162/* On spider based blades, we need to manually create the OF163* platform devices for the PCI host bridges164*/165for_each_child_of_node(root, np) {166if (np->type == NULL || (strcmp(np->type, "pci") != 0 &&167strcmp(np->type, "pciex") != 0))168continue;169of_platform_device_create(np, NULL, NULL);170}171172/* There is no device for the MIC memory controller, thus we create173* a platform device for it to attach the EDAC driver to.174*/175for_each_online_node(node) {176if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL)177continue;178platform_device_register_simple("cbe-mic", node, NULL, 0);179}180181return 0;182}183machine_subsys_initcall(cell, cell_publish_devices);184185static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)186{187struct irq_chip *chip = irq_desc_get_chip(desc);188struct mpic *mpic = irq_desc_get_handler_data(desc);189unsigned int virq;190191virq = mpic_get_one_irq(mpic);192if (virq != NO_IRQ)193generic_handle_irq(virq);194195chip->irq_eoi(&desc->irq_data);196}197198static void __init mpic_init_IRQ(void)199{200struct device_node *dn;201struct mpic *mpic;202unsigned int virq;203204for (dn = NULL;205(dn = of_find_node_by_name(dn, "interrupt-controller"));) {206if (!of_device_is_compatible(dn, "CBEA,platform-open-pic"))207continue;208209/* The MPIC driver will get everything it needs from the210* device-tree, just pass 0 to all arguments211*/212mpic = mpic_alloc(dn, 0, 0, 0, 0, " MPIC ");213if (mpic == NULL)214continue;215mpic_init(mpic);216217virq = irq_of_parse_and_map(dn, 0);218if (virq == NO_IRQ)219continue;220221printk(KERN_INFO "%s : hooking up to IRQ %d\n",222dn->full_name, virq);223irq_set_handler_data(virq, mpic);224irq_set_chained_handler(virq, cell_mpic_cascade);225}226}227228229static void __init cell_init_irq(void)230{231iic_init_IRQ();232spider_init_IRQ();233mpic_init_IRQ();234}235236static void __init cell_set_dabrx(void)237{238mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);239}240241static void __init cell_setup_arch(void)242{243#ifdef CONFIG_SPU_BASE244spu_priv1_ops = &spu_priv1_mmio_ops;245spu_management_ops = &spu_management_of_ops;246#endif247248cbe_regs_init();249250cell_set_dabrx();251252#ifdef CONFIG_CBE_RAS253cbe_ras_init();254#endif255256#ifdef CONFIG_SMP257smp_init_cell();258#endif259/* init to some ~sane value until calibrate_delay() runs */260loops_per_jiffy = 50000000;261262/* Find and initialize PCI host bridges */263init_pci_config_tokens();264265cbe_pervasive_init();266#ifdef CONFIG_DUMMY_CONSOLE267conswitchp = &dummy_con;268#endif269270mmio_nvram_init();271}272273static int __init cell_probe(void)274{275unsigned long root = of_get_flat_dt_root();276277if (!of_flat_dt_is_compatible(root, "IBM,CBEA") &&278!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))279return 0;280281hpte_init_native();282283return 1;284}285286define_machine(cell) {287.name = "Cell",288.probe = cell_probe,289.setup_arch = cell_setup_arch,290.show_cpuinfo = cell_show_cpuinfo,291.restart = rtas_restart,292.power_off = rtas_power_off,293.halt = rtas_halt,294.get_boot_time = rtas_get_boot_time,295.get_rtc_time = rtas_get_rtc_time,296.set_rtc_time = rtas_set_rtc_time,297.calibrate_decr = generic_calibrate_decr,298.progress = cell_progress,299.init_IRQ = cell_init_irq,300.pci_setup_phb = cell_setup_phb,301};302303304