diff options
Diffstat (limited to 'arch/powerpc/platforms/celleb')
-rw-r--r-- | arch/powerpc/platforms/celleb/Kconfig | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/io-workarounds.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/iommu.c | 26 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/pci.c | 14 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/scc_epci.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/scc_uhc.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/setup.c | 147 |
7 files changed, 156 insertions, 45 deletions
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig index 04748d410fc9..372891edcdd2 100644 --- a/arch/powerpc/platforms/celleb/Kconfig +++ b/arch/powerpc/platforms/celleb/Kconfig @@ -2,6 +2,8 @@ config PPC_CELLEB bool "Toshiba's Cell Reference Set 'Celleb' Architecture" depends on PPC_MULTIPLATFORM && PPC64 select PPC_CELL + select PPC_CELL_NATIVE + select PPC_RTAS select PPC_INDIRECT_IO select PPC_OF_PLATFORM_PCI select HAS_TXX9_SERIAL diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c index 2b912140bcbb..423339be1bac 100644 --- a/arch/powerpc/platforms/celleb/io-workarounds.c +++ b/arch/powerpc/platforms/celleb/io-workarounds.c @@ -22,6 +22,7 @@ #undef DEBUG +#include <linux/of.h> #include <linux/of_device.h> #include <linux/irq.h> @@ -222,7 +223,7 @@ void __init celleb_pci_add_one(struct pci_controller *phb, void (*dummy_read)(struct pci_controller *)) { struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count]; - struct device_node *np = phb->arch_data; + struct device_node *np = phb->dn; if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) { printk(KERN_ERR "Too many pci bridges, workarounds" @@ -256,13 +257,13 @@ int __init celleb_pci_workaround_init(void) celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!celleb_dummy_page_va) { - printk(KERN_ERR "Celleb: dummy read disabled." + printk(KERN_ERR "Celleb: dummy read disabled. " "Alloc celleb_dummy_page_va failed\n"); return 1; } list_for_each_entry(phb, &hose_list, list_node) { - node = phb->arch_data; + node = phb->dn; match = of_match_node(celleb_pci_workaround_match, node); if (match) { diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c index 755d869d8553..93b0efddd658 100644 --- a/arch/powerpc/platforms/celleb/iommu.c +++ b/arch/powerpc/platforms/celleb/iommu.c @@ -22,8 +22,9 @@ #include <linux/init.h> #include <linux/dma-mapping.h> #include <linux/pci.h> +#include <linux/of_platform.h> -#include <asm/of_platform.h> +#include <asm/machdep.h> #include "beat_wrapper.h" @@ -51,6 +52,8 @@ static int __init find_dma_window(u64 *io_space_id, u64 *ioid, return 0; } +static unsigned long celleb_dma_direct_offset; + static void __init celleb_init_direct_mapping(void) { u64 lpar_addr, io_addr; @@ -68,7 +71,18 @@ static void __init celleb_init_direct_mapping(void) ioid, DMA_FLAGS); } - dma_direct_offset = dma_base; + celleb_dma_direct_offset = dma_base; +} + +static void celleb_dma_dev_setup(struct device *dev) +{ + dev->archdata.dma_ops = get_pci_dma_ops(); + dev->archdata.dma_data = (void *)celleb_dma_direct_offset; +} + +static void celleb_pci_dma_dev_setup(struct pci_dev *pdev) +{ + celleb_dma_dev_setup(&pdev->dev); } static int celleb_of_bus_notify(struct notifier_block *nb, @@ -80,7 +94,7 @@ static int celleb_of_bus_notify(struct notifier_block *nb, if (action != BUS_NOTIFY_ADD_DEVICE) return 0; - dev->archdata.dma_ops = get_pci_dma_ops(); + celleb_dma_dev_setup(dev); return 0; } @@ -91,14 +105,12 @@ static struct notifier_block celleb_of_bus_notifier = { static int __init celleb_init_iommu(void) { - if (!machine_is(celleb)) - return -ENODEV; - celleb_init_direct_mapping(); set_pci_dma_ops(&dma_direct_ops); + ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup; bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier); return 0; } -arch_initcall(celleb_init_iommu); +machine_arch_initcall(celleb_beat, celleb_init_iommu); diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c index 6bc32fda7a6b..51b390d34e4d 100644 --- a/arch/powerpc/platforms/celleb/pci.c +++ b/arch/powerpc/platforms/celleb/pci.c @@ -31,6 +31,7 @@ #include <linux/init.h> #include <linux/bootmem.h> #include <linux/pci_regs.h> +#include <linux/of.h> #include <linux/of_device.h> #include <asm/io.h> @@ -138,8 +139,6 @@ static void celleb_config_read_fake(unsigned char *config, int where, *val = celleb_fake_config_readl(p); break; } - - return; } static void celleb_config_write_fake(unsigned char *config, int where, @@ -158,7 +157,6 @@ static void celleb_config_write_fake(unsigned char *config, int where, celleb_fake_config_writel(val, p); break; } - return; } static int celleb_fake_pci_read_config(struct pci_bus *bus, @@ -351,6 +349,10 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node, wi1 = of_get_property(node, "vendor-id", NULL); wi2 = of_get_property(node, "class-code", NULL); wi3 = of_get_property(node, "revision-id", NULL); + if (!wi0 || !wi1 || !wi2 || !wi3) { + printk(KERN_ERR "PCI: Missing device tree properties.\n"); + goto error; + } celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff); celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff); @@ -372,6 +374,10 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node, celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr); li = of_get_property(node, "interrupts", &rlen); + if (!li) { + printk(KERN_ERR "PCI: interrupts not found.\n"); + goto error; + } val = li[0]; celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1); celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val); @@ -475,7 +481,7 @@ static struct of_device_id celleb_phb_match[] __initdata = { int __init celleb_setup_phb(struct pci_controller *phb) { - struct device_node *dev = phb->arch_data; + struct device_node *dev = phb->dn; const struct of_device_id *match; int (*setup_func)(struct device_node *, struct pci_controller *); diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c index 9d076426676c..a3c7cfbcb323 100644 --- a/arch/powerpc/platforms/celleb/scc_epci.c +++ b/arch/powerpc/platforms/celleb/scc_epci.c @@ -95,7 +95,7 @@ void __init epci_workaround_init(struct pci_controller *hose) private->dummy_page_da = dma_map_single(hose->parent, celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE); if (private->dummy_page_da == DMA_ERROR_CODE) { - printk(KERN_ERR "EPCI: dummy read disabled." + printk(KERN_ERR "EPCI: dummy read disabled. " "Map dummy page failed.\n"); return; } diff --git a/arch/powerpc/platforms/celleb/scc_uhc.c b/arch/powerpc/platforms/celleb/scc_uhc.c index b59c38a06e3e..cb4307994087 100644 --- a/arch/powerpc/platforms/celleb/scc_uhc.c +++ b/arch/powerpc/platforms/celleb/scc_uhc.c @@ -47,7 +47,8 @@ static void enable_scc_uhc(struct pci_dev *dev) u32 val = 0; int i; - if (!machine_is(celleb)) + if (!machine_is(celleb_beat) && + !machine_is(celleb_native)) return; uhc_base = ioremap(pci_resource_start(dev, 0), diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index ddfb35ae741f..f27ae1e3fb58 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c @@ -40,6 +40,7 @@ #include <linux/seq_file.h> #include <linux/root_dev.h> #include <linux/console.h> +#include <linux/of_platform.h> #include <asm/mmu.h> #include <asm/processor.h> @@ -52,12 +53,16 @@ #include <asm/time.h> #include <asm/spu_priv1.h> #include <asm/firmware.h> -#include <asm/of_platform.h> +#include <asm/rtas.h> +#include <asm/cell-regs.h> #include "interrupt.h" #include "beat_wrapper.h" #include "beat.h" #include "pci.h" +#include "../cell/interrupt.h" +#include "../cell/pervasive.h" +#include "../cell/ras.h" static char celleb_machine_type[128] = "Celleb"; @@ -88,61 +93,122 @@ static void celleb_progress(char *s, unsigned short hex) printk("*** %04x : %s\n", hex, s ? s : ""); } -static void __init celleb_setup_arch(void) +static void __init celleb_setup_arch_common(void) +{ + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000; + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif +} + +static struct of_device_id celleb_bus_ids[] __initdata = { + { .type = "scc", }, + { .type = "ioif", }, /* old style */ + {}, +}; + +static int __init celleb_publish_devices(void) +{ + /* Publish OF platform devices for southbridge IOs */ + of_platform_bus_probe(NULL, celleb_bus_ids, NULL); + + celleb_pci_workaround_init(); + + return 0; +} +machine_device_initcall(celleb_beat, celleb_publish_devices); +machine_device_initcall(celleb_native, celleb_publish_devices); + + +/* + * functions for Celleb-Beat + */ +static void __init celleb_setup_arch_beat(void) { #ifdef CONFIG_SPU_BASE - spu_priv1_ops = &spu_priv1_beat_ops; - spu_management_ops = &spu_management_of_ops; + spu_priv1_ops = &spu_priv1_beat_ops; + spu_management_ops = &spu_management_of_ops; #endif #ifdef CONFIG_SMP smp_init_celleb(); #endif - /* init to some ~sane value until calibrate_delay() runs */ - loops_per_jiffy = 50000000; - -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif + celleb_setup_arch_common(); } -static int __init celleb_probe(void) +static int __init celleb_probe_beat(void) { unsigned long root = of_get_flat_dt_root(); if (!of_flat_dt_is_compatible(root, "Beat")) return 0; - powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE; + powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS + | FW_FEATURE_BEAT | FW_FEATURE_LPAR; hpte_init_beat_v3(); + return 1; } -static struct of_device_id celleb_bus_ids[] __initdata = { - { .type = "scc", }, - { .type = "ioif", }, /* old style */ - {}, -}; -static int __init celleb_publish_devices(void) +/* + * functions for Celleb-native + */ +static void __init celleb_init_IRQ_native(void) { - if (!machine_is(celleb)) - return 0; + iic_init_IRQ(); + spider_init_IRQ(); +} - /* Publish OF platform devices for southbridge IOs */ - of_platform_bus_probe(NULL, celleb_bus_ids, NULL); +static void __init celleb_setup_arch_native(void) +{ +#ifdef CONFIG_SPU_BASE + spu_priv1_ops = &spu_priv1_mmio_ops; + spu_management_ops = &spu_management_of_ops; +#endif - celleb_pci_workaround_init(); + cbe_regs_init(); - return 0; +#ifdef CONFIG_CBE_RAS + cbe_ras_init(); +#endif + +#ifdef CONFIG_SMP + smp_init_cell(); +#endif + + cbe_pervasive_init(); + + /* XXX: nvram initialization should be added */ + + celleb_setup_arch_common(); } -device_initcall(celleb_publish_devices); -define_machine(celleb) { - .name = "Cell Reference Set", - .probe = celleb_probe, - .setup_arch = celleb_setup_arch, +static int __init celleb_probe_native(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "Beat") || + !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb")) + return 0; + + powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS; + hpte_init_native(); + + return 1; +} + + +/* + * machine definitions + */ +define_machine(celleb_beat) { + .name = "Cell Reference Set (Beat)", + .probe = celleb_probe_beat, + .setup_arch = celleb_setup_arch_beat, .show_cpuinfo = celleb_show_cpuinfo, .restart = beat_restart, .power_off = beat_power_off, @@ -167,3 +233,26 @@ define_machine(celleb) { .machine_crash_shutdown = default_machine_crash_shutdown, #endif }; + +define_machine(celleb_native) { + .name = "Cell Reference Set (native)", + .probe = celleb_probe_native, + .setup_arch = celleb_setup_arch_native, + .show_cpuinfo = celleb_show_cpuinfo, + .restart = rtas_restart, + .power_off = rtas_power_off, + .halt = rtas_halt, + .get_boot_time = rtas_get_boot_time, + .get_rtc_time = rtas_get_rtc_time, + .set_rtc_time = rtas_set_rtc_time, + .calibrate_decr = generic_calibrate_decr, + .progress = celleb_progress, + .pci_probe_mode = celleb_pci_probe_mode, + .pci_setup_phb = celleb_setup_phb, + .init_IRQ = celleb_init_IRQ_native, +#ifdef CONFIG_KEXEC + .machine_kexec = default_machine_kexec, + .machine_kexec_prepare = default_machine_kexec_prepare, + .machine_crash_shutdown = default_machine_crash_shutdown, +#endif +}; |