From 6bfeccdc110a4f92e44d51d67b274977392cbf46 Mon Sep 17 00:00:00 2001 From: Zang Roy-r61911 Date: Thu, 15 Mar 2007 10:37:56 +1100 Subject: [POWERPC] kernel: Remove loops_per_jiffy code for 7448HPC2 platforms Remove loops_per_jiffy early initialization code for 7448HPC2 platforms. Since udelay no longer uses loops_per_jiffy it is not necessary to initialize it early. Signed-off-by: Roy Zang Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index c3f64ddb0be..366702e8c03 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -72,22 +72,10 @@ int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) static void __init mpc7448_hpc2_setup_arch(void) { - struct device_node *cpu; struct device_node *np; if (ppc_md.progress) ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0); - cpu = of_find_node_by_type(NULL, "cpu"); - if (cpu != 0) { - const unsigned int *fp; - - fp = of_get_property(cpu, "clock-frequency", NULL); - if (fp != 0) - loops_per_jiffy = *fp / HZ; - else - loops_per_jiffy = 50000000 / HZ; - of_node_put(cpu); - } tsi108_csr_vir_base = get_vir_csrbase(); /* setup PCI host bridge */ -- cgit v1.2.3 From 8fce6dd29fa9d1ac880bf0cb4528e9bd5878cf68 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 21 Mar 2007 21:40:42 +1100 Subject: [POWERPC] powermac: Fix G5-cpufreq for cpu on/offline The original code here is wrong, it applies "previous" knowledge. The way the cpufreq core is designed is that the policy for the secondary CPU that comes online says that it must in fact not use this policy but use the same as the other CPUs that are listed, which in fact is CPU#0. Signed-off-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/cpufreq_64.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 567d5523b69..00f50298c34 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -357,13 +357,13 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu) static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) { - if (policy->cpu != 0) - return -ENODEV; - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; - policy->cpus = cpu_possible_map; + /* secondary CPUs are tied to the primary one by the + * cpufreq core if in the secondary policy we tell it that + * it actually must be one policy together with all others. */ + policy->cpus = cpu_online_map; cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); return cpufreq_frequency_table_cpuinfo(policy, -- cgit v1.2.3 From 650f7b3b2f0ead0673e90452cf3dedde97c537ba Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Wed, 11 Apr 2007 06:11:23 +1000 Subject: [POWERPC] pseries: Handle null iommu dma-window property correctly Some versions of pSeries firmware fail to set up a dma-window property for PCI slots that are unoccupied. As a result, the loop searching for this propery, in pci_dma_dev_setup_pSeriesLP(), can run to the end, resulting in a NULL pointer dereference later in the routine. This patch prevents the crash, and prints a warning message. This is theoretically a rare error, as it occurs on what is hopefully just beta levels of firmware. But just in case this firmware escapes into the wild, this patch will avoid the crash. Signed-off-by: Linas Vepstas --- arch/powerpc/platforms/pseries/iommu.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 66665c82415..eec684a8e44 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -504,6 +504,12 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) break; } + if (!pdn || !PCI_DN(pdn)) { + printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: " + "no DMA window found for pci dev=%s dn=%s\n", + pci_name(dev), dn? dn->full_name : ""); + return; + } DBG(" parent is %s\n", pdn->full_name); /* Check for parent == NULL so we don't try to setup the empty EADS -- cgit v1.2.3 From 3baee955953957be5496cd28e9c544d9db214262 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Wed, 11 Apr 2007 07:56:49 +1000 Subject: [POWERPC] Add 'mdio' to bus scan id list for platforms with QE UEC Add 'mdio' to bus scan id list for platforms with QE UEC as a consequence of converting UEC mdio driver to an of_platform driver in the ucc_geth phylib conversion patch. Signed-off-by: Kim Phillips Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/83xx/mpc832x_mds.c | 1 + arch/powerpc/platforms/83xx/mpc832x_rdb.c | 1 + arch/powerpc/platforms/83xx/mpc836x_mds.c | 1 + arch/powerpc/platforms/85xx/mpc85xx_mds.c | 1 + 4 files changed, 4 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index fff09f5d6ed..94843ed52a9 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -111,6 +111,7 @@ static struct of_device_id mpc832x_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, + { .type = "mdio", }, {}, }; diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 6b71e9ffb11..b0b22bb29de 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -73,6 +73,7 @@ static struct of_device_id mpc832x_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, + { .type = "mdio", }, {}, }; diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index 526ed090a44..bceeff8bbfd 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c @@ -118,6 +118,7 @@ static struct of_device_id mpc836x_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, + { .type = "mdio", }, {}, }; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 54db4168995..e3dddbfe66f 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -147,6 +147,7 @@ static struct of_device_id mpc85xx_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, + { .type = "mdio", }, {}, }; -- cgit v1.2.3 From 69d48b409cac747cc0707b05b769e38488a6ad35 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 30 Apr 2007 15:37:06 +1000 Subject: [POWERPC] Fix STRICT_MM_TYPECHECKS Since we don't have it active by default, the STRICT_MM_TYPECHECKS option has bitrotted again. This patch fixes a couple of simple build fixes if the option is selected. First, pud_t mustn't be defined in page.h on 32-bit systems, because it conflicts with the version in the generic pud-folding code. Second, pci_32.c is missing a __pgprot() wrapper call. Third, a couple of PS3 files use constants of type pgprot_t when they need the raw values, we add pgprot_val() calls to fix this. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/ps3/htab.c | 3 ++- arch/powerpc/platforms/ps3/spu.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index ea60c451cf8..a1409e450c7 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c @@ -273,7 +273,8 @@ void __init ps3_map_htab(void) result = lv1_map_htab(0, &htab_addr); - htab = (hpte_t *)__ioremap(htab_addr, htab_size, PAGE_READONLY_X); + htab = (hpte_t *)__ioremap(htab_addr, htab_size, + pgprot_val(PAGE_READONLY_X)); DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, htab_addr, (unsigned long)htab); diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index a397e4e17c1..af8efe3c459 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c @@ -184,7 +184,7 @@ static int __init setup_areas(struct spu *spu) spu_pdata(spu)->shadow = __ioremap( spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow), - PAGE_READONLY | _PAGE_NO_CACHE | _PAGE_GUARDED); + pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED); if (!spu_pdata(spu)->shadow) { pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); goto fail_ioremap; -- cgit v1.2.3 From be9c94dd7776467813419f49fabe8017bc2d4c81 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Apr 2007 21:37:15 +1000 Subject: [POWERPC] Fix suspend states again In commit 0fba3a1f39f8b0a50b56c8b068fa52131cbc84c2 (a very long time ago, May 2006), I fixed a bug that caused powermacs to crash when you tried entering standby/mem suspend states. As I'm now getting more familiar with the suspend code I notice a few more things: 1. we previously misunderstood what pm_ops is for, it isn't supposed to be for doing platform dependent suspend/resume stuff that needs to be done for suspend to disk (as we currently try to use it!), it is instead for entering platform dependent suspend states ("standby", "mem"). 2. due to the first point, we never properly save FPU and altivec states when suspending to disk. It probably hasn't hurt yet because the process that writes the "disk" to /sys/power/state uses neither and its context is used. This patch addresses these points as follows: 1. remove all pm_ops from powermac, powermac suspend to ram isn't currently usable via /sys/power/state but is done via the PMU instead. 2. move the code responsible for storing FPU/altivec state into save_processor_state and the set_context() call to restore_processor_state. 3. add a call to kernel_enable_spe() It may look like there is some code removal missing but that is actually because the new suspend.h file overrides the ppc/suspend.h one which was previously used. Signed-off-by: Johannes Berg Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/setup.c | 65 --------------------------------- 1 file changed, 65 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index b820cabac69..5ae57e17d2b 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -439,76 +439,11 @@ static void __init find_boot_device(void) #endif } -/* TODO: Merge the suspend-to-ram with the common code !!! - * currently, this is a stub implementation for suspend-to-disk - * only - */ - -#ifdef CONFIG_SOFTWARE_SUSPEND - -static int pmac_pm_prepare(suspend_state_t state) -{ - printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); - - return 0; -} - -static int pmac_pm_enter(suspend_state_t state) -{ - printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); - - /* Giveup the lazy FPU & vec so we don't have to back them - * up from the low level code - */ - enable_kernel_fp(); - -#ifdef CONFIG_ALTIVEC - if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) - enable_kernel_altivec(); -#endif /* CONFIG_ALTIVEC */ - - return 0; -} - -static int pmac_pm_finish(suspend_state_t state) -{ - printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); - - /* Restore userland MMU context */ - set_context(current->active_mm->context.id, current->active_mm->pgd); - - return 0; -} - -static int pmac_pm_valid(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_DISK: - return 1; - /* can't do any other states via generic mechanism yet */ - default: - return 0; - } -} - -static struct pm_ops pmac_pm_ops = { - .pm_disk_mode = PM_DISK_SHUTDOWN, - .prepare = pmac_pm_prepare, - .enter = pmac_pm_enter, - .finish = pmac_pm_finish, - .valid = pmac_pm_valid, -}; - -#endif /* CONFIG_SOFTWARE_SUSPEND */ - static int initializing = 1; static int pmac_late_init(void) { initializing = 0; -#ifdef CONFIG_SOFTWARE_SUSPEND - pm_set_ops(&pmac_pm_ops); -#endif /* CONFIG_SOFTWARE_SUSPEND */ return 0; } -- cgit v1.2.3 From f0a1d024cc2699f4897d611da1d91777cccc530b Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 1 May 2007 07:00:50 +1000 Subject: [POWERPC] PS3: Add DABR support Add PS3 support for the PowerPC processor's Data Address Breakpoint Register (DABR). Signed-off-by: Arnd Bergmann Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/ps3/setup.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index ac5df9688dc..c9894933084 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -137,6 +137,12 @@ early_param("ps3fb", early_parse_ps3fb); #define prealloc_ps3fb_videomemory() do { } while (0) #endif +static int ps3_set_dabr(u64 dabr) +{ + enum {DABR_USER = 1, DABR_KERNEL = 2,}; + + return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0; +} static void __init ps3_setup_arch(void) { @@ -234,6 +240,7 @@ define_machine(ps3) { .get_boot_time = ps3_get_boot_time, .set_rtc_time = ps3_set_rtc_time, .get_rtc_time = ps3_get_rtc_time, + .set_dabr = ps3_set_dabr, .calibrate_decr = ps3_calibrate_decr, .progress = ps3_progress, .restart = ps3_restart, -- cgit v1.2.3 From 12828856630e616742e092c8ccbda6ebc56a9375 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 1 May 2007 07:00:56 +1000 Subject: [POWERPC] PS3: Remove duplicate variable assignement A minor change to remove a duplicate variable assignement in ps3_mm_shutdown(); Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/ps3/mm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index 2014d2b4444..f8a3e206c58 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -826,5 +826,4 @@ void __init ps3_mm_init(void) void ps3_mm_shutdown(void) { ps3_mm_region_destroy(&map.r1); - map.total = map.rm.size; } -- cgit v1.2.3 From dc4f60c25ae71e8278dcf909486e4aa34de7eecb Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 1 May 2007 07:01:01 +1000 Subject: [POWERPC] PS3: Interrupt routine fixups. Fixups for the ps3 interrupt routines to support all HV device in a generic way. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/ps3/interrupt.c | 234 +++++++++++++++++++++++---------- arch/powerpc/platforms/ps3/smp.c | 6 +- arch/powerpc/platforms/ps3/spu.c | 16 +-- 3 files changed, 178 insertions(+), 78 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 631c3009561..9da82c266ba 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -89,7 +89,18 @@ struct ps3_private { static DEFINE_PER_CPU(struct ps3_private, ps3_private); -int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, +/** + * ps3_virq_setup - virq related setup. + * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be + * serviced on. + * @outlet: The HV outlet from the various create outlet routines. + * @virq: The assigned Linux virq. + * + * Calls irq_create_mapping() to get a virq and sets the chip data to + * ps3_private data. + */ + +int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet, unsigned int *virq) { int result; @@ -111,17 +122,6 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, goto fail_create; } - /* Binds outlet to cpu + virq. */ - - result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); - - if (result) { - pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", - __func__, __LINE__, ps3_result(result)); - result = -EPERM; - goto fail_connect; - } - pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__, outlet, cpu, *virq); @@ -136,94 +136,118 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, return result; fail_set: - lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq); -fail_connect: irq_dispose_mapping(*virq); fail_create: return result; } -EXPORT_SYMBOL_GPL(ps3_alloc_irq); -int ps3_free_irq(unsigned int virq) +/** + * ps3_virq_destroy - virq related teardown. + * @virq: The assigned Linux virq. + * + * Clears chip data and calls irq_dispose_mapping() for the virq. + */ + +int ps3_virq_destroy(unsigned int virq) { - int result; const struct ps3_private *pd = get_irq_chip_data(virq); pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, pd->node, pd->cpu, virq); - result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); - - if (result) - pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", - __func__, __LINE__, ps3_result(result)); - set_irq_chip_data(virq, NULL); irq_dispose_mapping(virq); - return result; + + pr_debug("%s:%d <-\n", __func__, __LINE__); + return 0; } -EXPORT_SYMBOL_GPL(ps3_free_irq); /** - * ps3_alloc_io_irq - Assign a virq to a system bus device. + * ps3_irq_plug_setup - Generic outlet and virq related setup. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. - * @interrupt_id: The device interrupt id read from the system repository. + * @outlet: The HV outlet from the various create outlet routines. * @virq: The assigned Linux virq. * - * An io irq represents a non-virtualized device interrupt. interrupt_id - * coresponds to the interrupt number of the interrupt controller. + * Sets up virq and connects the irq plug. */ -int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id, +int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, unsigned int *virq) { int result; - unsigned long outlet; + struct ps3_private *pd; - result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); + result = ps3_virq_setup(cpu, outlet, virq); if (result) { - pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; + pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__); + goto fail_setup; } - result = ps3_alloc_irq(cpu, outlet, virq); - BUG_ON(result); + pd = get_irq_chip_data(*virq); + + /* Binds outlet to cpu + virq. */ + + result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); + if (result) { + pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", + __func__, __LINE__, ps3_result(result)); + result = -EPERM; + goto fail_connect; + } + + return result; + +fail_connect: + ps3_virq_destroy(*virq); +fail_setup: return result; } -EXPORT_SYMBOL_GPL(ps3_alloc_io_irq); +EXPORT_SYMBOL_GPL(ps3_irq_plug_setup); + +/** + * ps3_irq_plug_destroy - Generic outlet and virq related teardown. + * @virq: The assigned Linux virq. + * + * Disconnects the irq plug and tears down virq. + * Do not call for system bus event interrupts setup with + * ps3_sb_event_receive_port_setup(). + */ -int ps3_free_io_irq(unsigned int virq) +int ps3_irq_plug_destroy(unsigned int virq) { int result; + const struct ps3_private *pd = get_irq_chip_data(virq); - result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); + pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, + pd->node, pd->cpu, virq); + + result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); if (result) - pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", - __func__, __LINE__, ps3_result(result)); + pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", + __func__, __LINE__, ps3_result(result)); - ps3_free_irq(virq); + ps3_virq_destroy(virq); return result; } -EXPORT_SYMBOL_GPL(ps3_free_io_irq); +EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy); /** - * ps3_alloc_event_irq - Allocate a virq for use with a system event. + * ps3_event_receive_port_setup - Setup an event receive port. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @virq: The assigned Linux virq. * * The virq can be used with lv1_connect_interrupt_event_receive_port() to - * arrange to receive events, or with ps3_send_event_locally() to signal - * events. + * arrange to receive interrupts from system-bus devices, or with + * ps3_send_event_locally() to signal events. */ -int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) +int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq) { int result; unsigned long outlet; @@ -237,17 +261,27 @@ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) return result; } - result = ps3_alloc_irq(cpu, outlet, virq); + result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } +EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup); + +/** + * ps3_event_receive_port_destroy - Destroy an event receive port. + * @virq: The assigned Linux virq. + * + * Since ps3_event_receive_port_destroy destroys the receive port outlet, + * SB devices need to call disconnect_interrupt_event_receive_port() before + * this. + */ -int ps3_free_event_irq(unsigned int virq) +int ps3_event_receive_port_destroy(unsigned int virq) { int result; - pr_debug(" -> %s:%d\n", __func__, __LINE__); + pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq); result = lv1_destruct_event_receive_port(virq_to_hw(virq)); @@ -255,11 +289,17 @@ int ps3_free_event_irq(unsigned int virq) pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", __func__, __LINE__, ps3_result(result)); - ps3_free_irq(virq); + /* lv1_destruct_event_receive_port() destroys the IRQ plug, + * so don't call ps3_irq_plug_destroy() here. + */ + + result = ps3_virq_destroy(virq); + BUG_ON(result); pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } +EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy); int ps3_send_event_locally(unsigned int virq) { @@ -267,7 +307,7 @@ int ps3_send_event_locally(unsigned int virq) } /** - * ps3_connect_event_irq - Assign a virq to a system bus device. + * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @did: The HV device identifier read from the system repository. @@ -278,13 +318,15 @@ int ps3_send_event_locally(unsigned int virq) * coresponds to the software interrupt number. */ -int ps3_connect_event_irq(enum ps3_cpu_binding cpu, +int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, const struct ps3_device_id *did, unsigned int interrupt_id, unsigned int *virq) { + /* this should go in system-bus.c */ + int result; - result = ps3_alloc_event_irq(cpu, virq); + result = ps3_event_receive_port_setup(cpu, virq); if (result) return result; @@ -296,7 +338,7 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" " failed: %s\n", __func__, __LINE__, ps3_result(result)); - ps3_free_event_irq(*virq); + ps3_event_receive_port_destroy(*virq); *virq = NO_IRQ; return result; } @@ -306,10 +348,13 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, return 0; } +EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); -int ps3_disconnect_event_irq(const struct ps3_device_id *did, +int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, unsigned int interrupt_id, unsigned int virq) { + /* this should go in system-bus.c */ + int result; pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, @@ -323,14 +368,65 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did, " failed: %s\n", __func__, __LINE__, ps3_result(result)); - ps3_free_event_irq(virq); + result = ps3_event_receive_port_destroy(virq); + BUG_ON(result); pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } +EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy); /** - * ps3_alloc_vuart_irq - Configure the system virtual uart virq. + * ps3_io_irq_setup - Setup a system bus io irq. + * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be + * serviced on. + * @interrupt_id: The device interrupt id read from the system repository. + * @virq: The assigned Linux virq. + * + * An io irq represents a non-virtualized device interrupt. interrupt_id + * coresponds to the interrupt number of the interrupt controller. + */ + +int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id, + unsigned int *virq) +{ + int result; + unsigned long outlet; + + result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); + + if (result) { + pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", + __func__, __LINE__, ps3_result(result)); + return result; + } + + result = ps3_irq_plug_setup(cpu, outlet, virq); + BUG_ON(result); + + return result; +} +EXPORT_SYMBOL_GPL(ps3_io_irq_setup); + +int ps3_io_irq_destroy(unsigned int virq) +{ + int result; + + result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); + + if (result) + pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", + __func__, __LINE__, ps3_result(result)); + + result = ps3_irq_plug_destroy(virq); + BUG_ON(result); + + return result; +} +EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); + +/** + * ps3_vuart_irq_setup - Setup the system virtual uart virq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap. @@ -340,7 +436,7 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did, * freeing the interrupt will return a wrong state error. */ -int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, +int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, unsigned int *virq) { int result; @@ -359,13 +455,13 @@ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, return result; } - result = ps3_alloc_irq(cpu, outlet, virq); + result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } -int ps3_free_vuart_irq(unsigned int virq) +int ps3_vuart_irq_destroy(unsigned int virq) { int result; @@ -377,13 +473,14 @@ int ps3_free_vuart_irq(unsigned int virq) return result; } - ps3_free_irq(virq); + result = ps3_irq_plug_destroy(virq); + BUG_ON(result); return result; } /** - * ps3_alloc_spe_irq - Configure an spe virq. + * ps3_spe_irq_setup - Setup an spe virq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @spe_id: The spe_id returned from lv1_construct_logical_spe(). @@ -392,7 +489,7 @@ int ps3_free_vuart_irq(unsigned int virq) * */ -int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, +int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, unsigned int class, unsigned int *virq) { int result; @@ -408,15 +505,16 @@ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, return result; } - result = ps3_alloc_irq(cpu, outlet, virq); + result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } -int ps3_free_spe_irq(unsigned int virq) +int ps3_spe_irq_destroy(unsigned int virq) { - ps3_free_irq(virq); + int result = ps3_irq_plug_destroy(virq); + BUG_ON(result); return 0; } diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index 6fb887961a6..8729348c060 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c @@ -110,7 +110,7 @@ static void __init ps3_smp_setup_cpu(int cpu) BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); for (i = 0; i < MSG_COUNT; i++) { - result = ps3_alloc_event_irq(cpu, &virqs[i]); + result = ps3_event_receive_port_setup(cpu, &virqs[i]); if (result) continue; @@ -134,11 +134,13 @@ void ps3_smp_cleanup_cpu(int cpu) int i; DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); + for (i = 0; i < MSG_COUNT; i++) { - ps3_free_event_irq(virqs[i]); free_irq(virqs[i], (void*)(long)i); + ps3_event_receive_port_destroy(virqs[i]); virqs[i] = NO_IRQ; } + DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); } diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index af8efe3c459..651437cb2c1 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c @@ -230,19 +230,19 @@ static int __init setup_interrupts(struct spu *spu) { int result; - result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, + result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 0, &spu->irqs[0]); if (result) goto fail_alloc_0; - result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, + result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 1, &spu->irqs[1]); if (result) goto fail_alloc_1; - result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, + result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 2, &spu->irqs[2]); if (result) @@ -251,9 +251,9 @@ static int __init setup_interrupts(struct spu *spu) return result; fail_alloc_2: - ps3_free_spe_irq(spu->irqs[1]); + ps3_spe_irq_destroy(spu->irqs[1]); fail_alloc_1: - ps3_free_spe_irq(spu->irqs[0]); + ps3_spe_irq_destroy(spu->irqs[0]); fail_alloc_0: spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; return result; @@ -301,9 +301,9 @@ static int ps3_destroy_spu(struct spu *spu) result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); BUG_ON(result); - ps3_free_spe_irq(spu->irqs[2]); - ps3_free_spe_irq(spu->irqs[1]); - ps3_free_spe_irq(spu->irqs[0]); + ps3_spe_irq_destroy(spu->irqs[2]); + ps3_spe_irq_destroy(spu->irqs[1]); + ps3_spe_irq_destroy(spu->irqs[0]); spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; -- cgit v1.2.3 From 90f7afefaeda946977824617c225b53f0813e357 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 1 May 2007 14:43:39 +1000 Subject: [POWERPC] pasemi: Only call of_platform_bus_probe() on relevant platforms Only publish of_platform devices if running on a machine that has them. Signed-off-by: Olof Johansson Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pasemi/setup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index f88f0ec4c8c..38bd9037773 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -211,7 +211,10 @@ static struct of_device_id pasemi_bus_ids[] = { static int __init pasemi_publish_devices(void) { - /* Publish OF platform devices for southbridge IOs */ + if (!machine_is(pasemi)) + return 0; + + /* Publish OF platform devices for SDC and other non-PCI devices */ of_platform_bus_probe(NULL, pasemi_bus_ids, NULL); return 0; -- cgit v1.2.3 From d9333afd6a714760c13f76ba275a32ec7bd979c1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 May 2007 06:33:51 +1000 Subject: [POWERPC] powermac: Support G5 CPU hotplug This allows "hotplugging" of CPUs on G5 machines. CPUs that are disabled are put into an idle loop with the decrementer frequency set to minimum. To wake them up again we kick them just like when bringing them up. To stop those CPUs from messing with any global state we stop them from entering the timer interrupt. Signed-off-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/setup.c | 52 +++++++++++++++++++++++++++++++-- arch/powerpc/platforms/powermac/smp.c | 12 ++++++-- 2 files changed, 60 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 5ae57e17d2b..e365bff74d8 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -444,6 +444,9 @@ static int initializing = 1; static int pmac_late_init(void) { initializing = 0; + /* this is udbg (which is __init) and we can later use it during + * cpu hotplug (in smp_core99_kick_cpu) */ + ppc_md.progress = NULL; return 0; } @@ -661,7 +664,52 @@ static int pmac_pci_probe_mode(struct pci_bus *bus) return PCI_PROBE_NORMAL; return PCI_PROBE_DEVTREE; } -#endif + +#ifdef CONFIG_HOTPLUG_CPU +/* access per cpu vars from generic smp.c */ +DECLARE_PER_CPU(int, cpu_state); + +static void pmac_cpu_die(void) +{ + /* + * turn off as much as possible, we'll be + * kicked out as this will only be invoked + * on core99 platforms for now ... + */ + + printk(KERN_INFO "CPU#%d offline\n", smp_processor_id()); + __get_cpu_var(cpu_state) = CPU_DEAD; + smp_wmb(); + + /* + * during the path that leads here preemption is disabled, + * reenable it now so that when coming up preempt count is + * zero correctly + */ + preempt_enable(); + + /* + * hard-disable interrupts for the non-NAP case, the NAP code + * needs to re-enable interrupts (but soft-disables them) + */ + hard_irq_disable(); + + while (1) { + /* let's not take timer interrupts too often ... */ + set_dec(0x7fffffff); + + /* should always be true at this point */ + if (cpu_has_feature(CPU_FTR_CAN_NAP)) + power4_cpu_offline_powersave(); + else { + HMT_low(); + HMT_very_low(); + } + } +} +#endif /* CONFIG_HOTPLUG_CPU */ + +#endif /* CONFIG_PPC64 */ define_machine(powermac) { .name = "PowerMac", @@ -698,6 +746,6 @@ define_machine(powermac) { .phys_mem_access_prot = pci_phys_mem_access_prot, #endif #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) - .cpu_die = generic_mach_cpu_die, + .cpu_die = pmac_cpu_die, #endif }; diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 6f32c4eca6e..33035411318 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -900,7 +900,7 @@ void smp_core99_cpu_die(unsigned int cpu) cpu_dead[cpu] = 0; } -#endif +#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */ /* Core99 Macs (dual G4s and G5s) */ struct smp_ops_t core99_smp_ops = { @@ -910,8 +910,16 @@ struct smp_ops_t core99_smp_ops = { .setup_cpu = smp_core99_setup_cpu, .give_timebase = smp_core99_give_timebase, .take_timebase = smp_core99_take_timebase, -#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) +#if defined(CONFIG_HOTPLUG_CPU) +# if defined(CONFIG_PPC32) .cpu_disable = smp_core99_cpu_disable, .cpu_die = smp_core99_cpu_die, +# endif +# if defined(CONFIG_PPC64) + .cpu_disable = generic_cpu_disable, + .cpu_die = generic_cpu_die, + /* intentionally do *NOT* assign cpu_enable, + * the generic code will use kick_cpu then! */ +# endif #endif }; -- cgit v1.2.3 From 55b61fec22caa3e7872caea6c4100fc75cb8f49b Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 May 2007 17:26:52 +1000 Subject: [POWERPC] Rename device_is_compatible to of_device_is_compatible for consistency with other Open Firmware interfaces (and Sparc). This is just a straight replacement. This leaves the compatibility define in place. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/85xx/mpc8544_ds.c | 2 +- arch/powerpc/platforms/85xx/mpc85xx_cds.c | 2 +- arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 2 +- arch/powerpc/platforms/cell/interrupt.c | 6 +++--- arch/powerpc/platforms/cell/setup.c | 2 +- arch/powerpc/platforms/cell/spider-pic.c | 4 ++-- arch/powerpc/platforms/chrp/pci.c | 2 +- arch/powerpc/platforms/chrp/setup.c | 2 +- arch/powerpc/platforms/maple/pci.c | 12 ++++++------ arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/pasemi/setup.c | 2 +- arch/powerpc/platforms/powermac/feature.c | 26 +++++++++++++------------- arch/powerpc/platforms/powermac/low_i2c.c | 2 +- arch/powerpc/platforms/powermac/nvram.c | 4 ++-- arch/powerpc/platforms/powermac/pci.c | 30 +++++++++++++++--------------- arch/powerpc/platforms/powermac/pic.c | 2 +- arch/powerpc/platforms/powermac/setup.c | 4 ++-- arch/powerpc/platforms/powermac/smp.c | 6 +++--- arch/powerpc/platforms/pseries/lpar.c | 4 ++-- arch/powerpc/platforms/pseries/setup.c | 2 +- arch/powerpc/platforms/pseries/xics.c | 4 ++-- 21 files changed, 61 insertions(+), 61 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c index 2867f85e632..bec84ffe708 100644 --- a/arch/powerpc/platforms/85xx/mpc8544_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c @@ -84,7 +84,7 @@ void __init mpc8544_ds_pic_init(void) #ifdef CONFIG_PPC_I8259 /* Initialize the i8259 controller */ for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "chrp,iic")) { + if (of_device_is_compatible(np, "chrp,iic")) { cascade_node = np; break; } diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 7e71636f909..1490eb3ce0d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -197,7 +197,7 @@ static void __init mpc85xx_cds_pic_init(void) #ifdef CONFIG_PPC_I8259 /* Initialize the i8259 controller */ for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "chrp,iic")) { + if (of_device_is_compatible(np, "chrp,iic")) { cascade_node = np; break; } diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 3d3d98f5bd4..90877565caa 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -102,7 +102,7 @@ mpc86xx_hpcn_init_irq(void) #ifdef CONFIG_PCI /* Initialize i8259 controller */ for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "chrp,iic")) { + if (of_device_is_compatible(np, "chrp,iic")) { cascade_node = np; break; } diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 4fc4e92775d..47264e72202 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -227,7 +227,7 @@ void iic_request_IPIs(void) static int iic_host_match(struct irq_host *h, struct device_node *node) { - return device_is_compatible(node, + return of_device_is_compatible(node, "IBM,CBEA-Internal-Interrupt-Controller"); } @@ -256,7 +256,7 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct, unsigned int node, ext, unit, class; const u32 *val; - if (!device_is_compatible(ct, + if (!of_device_is_compatible(ct, "IBM,CBEA-Internal-Interrupt-Controller")) return -ENODEV; if (intsize != 1) @@ -324,7 +324,7 @@ static int __init setup_iic(void) for (dn = NULL; (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) { - if (!device_is_compatible(dn, + if (!of_device_is_compatible(dn, "IBM,CBEA-Internal-Interrupt-Controller")) continue; np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL); diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 54b96183cb6..db6654272e1 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -112,7 +112,7 @@ static void __init mpic_init_IRQ(void) for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { - if (!device_is_compatible(dn, "CBEA,platform-open-pic")) + if (!of_device_is_compatible(dn, "CBEA,platform-open-pic")) continue; /* The MPIC driver will get everything it needs from the diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index fb1f15797bb..05f4b3d3d75 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -358,12 +358,12 @@ void __init spider_init_IRQ(void) */ for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { - if (device_is_compatible(dn, "CBEA,platform-spider-pic")) { + if (of_device_is_compatible(dn, "CBEA,platform-spider-pic")) { if (of_address_to_resource(dn, 0, &r)) { printk(KERN_WARNING "spider-pic: Failed\n"); continue; } - } else if (device_is_compatible(dn, "sti,platform-spider-pic") + } else if (of_device_is_compatible(dn, "sti,platform-spider-pic") && (chip < 2)) { static long hard_coded_pics[] = { 0x24000008000ul, 0x34000008000ul}; diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 1469d6478f6..d32fedc991d 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -267,7 +267,7 @@ chrp_find_bridges(void) model = of_get_property(dev, "model", NULL); if (model == NULL) model = ""; - if (device_is_compatible(dev, "IBM,python")) { + if (of_device_is_compatible(dev, "IBM,python")) { setup_python(hose, dev); } else if (is_mot || strncmp(model, "Motorola, Grackle", 17) == 0) { diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 1870038a8e0..373de4c063d 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -448,7 +448,7 @@ static void __init chrp_find_8259(void) /* Look for cascade */ for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "chrp,iic")) { + if (of_device_is_compatible(np, "chrp,iic")) { pic = np; break; } diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index b1d3b99c3f9..7aaa5bbc936 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -467,15 +467,15 @@ static int __init add_bridge(struct device_node *dev) hose->last_busno = bus_range ? bus_range[1] : 0xff; disp_name = NULL; - if (device_is_compatible(dev, "u3-agp")) { + if (of_device_is_compatible(dev, "u3-agp")) { setup_u3_agp(hose); disp_name = "U3-AGP"; primary = 0; - } else if (device_is_compatible(dev, "u3-ht")) { + } else if (of_device_is_compatible(dev, "u3-ht")) { setup_u3_ht(hose); disp_name = "U3-HT"; primary = 1; - } else if (device_is_compatible(dev, "u4-pcie")) { + } else if (of_device_is_compatible(dev, "u4-pcie")) { setup_u4_pcie(hose); disp_name = "U4-PCIE"; primary = 0; @@ -556,12 +556,12 @@ void __init maple_pci_init(void) continue; if (strcmp(np->type, "pci") && strcmp(np->type, "ht")) continue; - if ((device_is_compatible(np, "u4-pcie") || - device_is_compatible(np, "u3-agp")) && + if ((of_device_is_compatible(np, "u4-pcie") || + of_device_is_compatible(np, "u3-agp")) && add_bridge(np) == 0) of_node_get(np); - if (device_is_compatible(np, "u3-ht")) { + if (of_device_is_compatible(np, "u3-ht")) { of_node_get(np); ht = np; } diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 2a30c5b2532..354c0586162 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -231,7 +231,7 @@ static void __init maple_init_IRQ(void) */ for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "open-pic")) { + if (of_device_is_compatible(np, "open-pic")) { mpic_node = np; break; } diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 38bd9037773..38f107b3c52 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -114,7 +114,7 @@ static __init void pas_init_IRQ(void) mpic_node = NULL; for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "open-pic")) { + if (of_device_is_compatible(np, "open-pic")) { mpic_node = np; break; } diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 52cfdd86c92..f29705f8047 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1418,7 +1418,7 @@ static long g5_eth_phy_reset(struct device_node *node, long param, long value) phy = of_get_next_child(node, NULL); if (!phy) return -ENODEV; - need_reset = device_is_compatible(phy, "B5221"); + need_reset = of_device_is_compatible(phy, "B5221"); of_node_put(phy); if (!need_reset) return 0; @@ -2624,7 +2624,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) { if (!compat) break; - if (device_is_compatible(node, compat)) + if (of_device_is_compatible(node, compat)) break; } if (!node) @@ -2728,7 +2728,7 @@ initial_serial_shutdown(struct device_node *np) conn = of_get_property(np, "AAPL,connector", &len); if (conn && (strcmp(conn, "infrared") == 0)) port_type = PMAC_SCC_IRDA; - else if (device_is_compatible(np, "cobalt")) + else if (of_device_is_compatible(np, "cobalt")) modem = 1; else if (slots && slots->count > 0) { if (strcmp(slots->name, "IrDA") == 0) @@ -2787,7 +2787,7 @@ set_initial_features(void) */ np = of_find_node_by_name(NULL, "ethernet"); while(np) { - if (device_is_compatible(np, "K2-GMAC")) + if (of_device_is_compatible(np, "K2-GMAC")) g5_gmac_enable(np, 0, 1); np = of_find_node_by_name(np, "ethernet"); } @@ -2799,7 +2799,7 @@ set_initial_features(void) */ np = of_find_node_by_name(NULL, "firewire"); while(np) { - if (device_is_compatible(np, "pci106b,5811")) { + if (of_device_is_compatible(np, "pci106b,5811")) { macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; g5_fw_enable(np, 0, 1); } @@ -2817,8 +2817,8 @@ set_initial_features(void) np = of_find_node_by_name(NULL, "ethernet"); while(np) { if (np->parent - && device_is_compatible(np->parent, "uni-north") - && device_is_compatible(np, "gmac")) + && of_device_is_compatible(np->parent, "uni-north") + && of_device_is_compatible(np, "gmac")) core99_gmac_enable(np, 0, 1); np = of_find_node_by_name(np, "ethernet"); } @@ -2831,10 +2831,10 @@ set_initial_features(void) np = of_find_node_by_name(NULL, "firewire"); while(np) { if (np->parent - && device_is_compatible(np->parent, "uni-north") - && (device_is_compatible(np, "pci106b,18") || - device_is_compatible(np, "pci106b,30") || - device_is_compatible(np, "pci11c1,5811"))) { + && of_device_is_compatible(np->parent, "uni-north") + && (of_device_is_compatible(np, "pci106b,18") || + of_device_is_compatible(np, "pci106b,30") || + of_device_is_compatible(np, "pci11c1,5811"))) { macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; core99_firewire_enable(np, 0, 1); } @@ -2845,8 +2845,8 @@ set_initial_features(void) np = of_find_node_by_name(NULL, "ata-6"); while(np) { if (np->parent - && device_is_compatible(np->parent, "uni-north") - && device_is_compatible(np, "kauai-ata")) { + && of_device_is_compatible(np->parent, "uni-north") + && of_device_is_compatible(np, "kauai-ata")) { core99_ata100_enable(np, 1); } np = of_find_node_by_name(np, "ata-6"); diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 5430e146b3e..3f507ab9c5e 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -1207,7 +1207,7 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev, if (strcmp(np->name, p->name)) continue; if (p->compatible && - !device_is_compatible(np, p->compatible)) + !of_device_is_compatible(np, p->compatible)) continue; if (p->quirks & pmac_i2c_quirk_skip) break; diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 692945c1491..c6f0f9e738e 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -553,7 +553,7 @@ static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr) * identify the chip using flash id commands and base ourselves on * a list of known chips IDs */ - if (device_is_compatible(dp, "amd-0137")) { + if (of_device_is_compatible(dp, "amd-0137")) { core99_erase_bank = amd_erase_bank; core99_write_bank = amd_write_bank; } else { @@ -588,7 +588,7 @@ int __init pmac_nvram_init(void) } } - is_core_99 = device_is_compatible(dp, "nvram,flash"); + is_core_99 = of_device_is_compatible(dp, "nvram,flash"); if (is_core_99) { err = core99_nvram_setup(dp, r1.start); goto bail; diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 22c4ae4c693..c4af9e21ac9 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -934,15 +934,15 @@ static int __init add_bridge(struct device_node *dev) /* 64 bits only bridges */ #ifdef CONFIG_PPC64 - if (device_is_compatible(dev, "u3-agp")) { + if (of_device_is_compatible(dev, "u3-agp")) { setup_u3_agp(hose); disp_name = "U3-AGP"; primary = 0; - } else if (device_is_compatible(dev, "u3-ht")) { + } else if (of_device_is_compatible(dev, "u3-ht")) { setup_u3_ht(hose); disp_name = "U3-HT"; primary = 1; - } else if (device_is_compatible(dev, "u4-pcie")) { + } else if (of_device_is_compatible(dev, "u4-pcie")) { setup_u4_pcie(hose); disp_name = "U4-PCIE"; primary = 0; @@ -953,7 +953,7 @@ static int __init add_bridge(struct device_node *dev) /* 32 bits only bridges */ #ifdef CONFIG_PPC32 - if (device_is_compatible(dev, "uni-north")) { + if (of_device_is_compatible(dev, "uni-north")) { primary = setup_uninorth(hose, &rsrc); disp_name = "UniNorth"; } else if (strcmp(dev->name, "pci") == 0) { @@ -1129,21 +1129,21 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) return 0; uninorth_child = node->parent && - device_is_compatible(node->parent, "uni-north"); + of_device_is_compatible(node->parent, "uni-north"); /* Firewire & GMAC were disabled after PCI probe, the driver is * claiming them, we must re-enable them now. */ if (uninorth_child && !strcmp(node->name, "firewire") && - (device_is_compatible(node, "pci106b,18") || - device_is_compatible(node, "pci106b,30") || - device_is_compatible(node, "pci11c1,5811"))) { + (of_device_is_compatible(node, "pci106b,18") || + of_device_is_compatible(node, "pci106b,30") || + of_device_is_compatible(node, "pci11c1,5811"))) { pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1); pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1); updatecfg = 1; } if (uninorth_child && !strcmp(node->name, "ethernet") && - device_is_compatible(node, "gmac")) { + of_device_is_compatible(node, "gmac")) { pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1); updatecfg = 1; } @@ -1203,18 +1203,18 @@ void __init pmac_pcibios_after_init(void) #endif /* CONFIG_BLK_DEV_IDE */ for_each_node_by_name(nd, "firewire") { - if (nd->parent && (device_is_compatible(nd, "pci106b,18") || - device_is_compatible(nd, "pci106b,30") || - device_is_compatible(nd, "pci11c1,5811")) - && device_is_compatible(nd->parent, "uni-north")) { + if (nd->parent && (of_device_is_compatible(nd, "pci106b,18") || + of_device_is_compatible(nd, "pci106b,30") || + of_device_is_compatible(nd, "pci11c1,5811")) + && of_device_is_compatible(nd->parent, "uni-north")) { pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); } } of_node_put(nd); for_each_node_by_name(nd, "ethernet") { - if (nd->parent && device_is_compatible(nd, "gmac") - && device_is_compatible(nd->parent, "uni-north")) + if (nd->parent && of_device_is_compatible(nd, "gmac") + && of_device_is_compatible(nd->parent, "uni-north")) pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); } of_node_put(nd); diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index ae5097ac037..87cd6805171 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -364,7 +364,7 @@ static void __init pmac_pic_probe_oldstyle(void) slave = of_find_node_by_name(master, "mac-io"); /* Check ordering of master & slave */ - if (device_is_compatible(master, "gatwick")) { + if (of_device_is_compatible(master, "gatwick")) { struct device_node *tmp; BUG_ON(slave == NULL); tmp = master; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index e365bff74d8..a410bc76a8a 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -659,8 +659,8 @@ static int pmac_pci_probe_mode(struct pci_bus *bus) /* We need to use normal PCI probing for the AGP bus, * since the device for the AGP bridge isn't in the tree. */ - if (bus->self == NULL && (device_is_compatible(node, "u3-agp") || - device_is_compatible(node, "u4-pcie"))) + if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") || + of_device_is_compatible(node, "u4-pcie"))) return PCI_PROBE_NORMAL; return PCI_PROBE_DEVTREE; } diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 33035411318..84f1860493b 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -562,7 +562,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) /* Look for the clock chip */ while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) { p = of_get_parent(cc); - ok = p && device_is_compatible(p, "uni-n-i2c"); + ok = p && of_device_is_compatible(p, "uni-n-i2c"); of_node_put(p); if (!ok) continue; @@ -575,11 +575,11 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) continue; switch (*reg) { case 0xd2: - if (device_is_compatible(cc,"pulsar-legacy-slewing")) { + if (of_device_is_compatible(cc,"pulsar-legacy-slewing")) { pmac_tb_freeze = smp_core99_pulsar_tb_freeze; pmac_tb_pulsar_addr = 0xd2; name = "Pulsar"; - } else if (device_is_compatible(cc, "cy28508")) { + } else if (of_device_is_compatible(cc, "cy28508")) { pmac_tb_freeze = smp_core99_cypress_tb_freeze; name = "Cypress"; } diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 3a70e8ad7bc..362dfbc260a 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -231,13 +231,13 @@ void __init find_udbg_vterm(void) goto out; vtermno = termno[0]; - if (device_is_compatible(stdout_node, "hvterm1")) { + if (of_device_is_compatible(stdout_node, "hvterm1")) { udbg_putc = udbg_putcLP; udbg_getc = udbg_getcLP; udbg_getc_poll = udbg_getc_pollLP; if (add_console) add_preferred_console("hvc", termno[0] & 0xff, NULL); - } else if (device_is_compatible(stdout_node, "hvterm-protocol")) { + } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) { vtermno = termno[0]; udbg_putc = udbg_hvsi_putc; udbg_getc = udbg_hvsi_getc; diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 33eec2822c6..470db6efaeb 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -168,7 +168,7 @@ static void __init pseries_mpic_init_IRQ(void) /* Look for cascade */ for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "chrp,iic")) { + if (of_device_is_compatible(np, "chrp,iic")) { cascade = np; break; } diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 896cbf340c4..b854e7f1001 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -477,7 +477,7 @@ static int xics_host_match(struct irq_host *h, struct device_node *node) * like vdevices, events, etc... The trick we use here is to match * everything here except the legacy 8259 which is compatible "chrp,iic" */ - return !device_is_compatible(node, "chrp,iic"); + return !of_device_is_compatible(node, "chrp,iic"); } static int xics_host_map_direct(struct irq_host *h, unsigned int virq, @@ -618,7 +618,7 @@ static void __init xics_setup_8259_cascade(void) unsigned long intack = 0; for_each_node_by_type(np, "interrupt-controller") - if (device_is_compatible(np, "chrp,iic")) { + if (of_device_is_compatible(np, "chrp,iic")) { found = np; break; } -- cgit v1.2.3 From 2abb7019e2877e7f9b1d2432f5a5c36caca5ed1c Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 4 May 2007 14:39:21 +1000 Subject: [POWERPC] pasemi: Update ppc_proc_freq from cpufreq driver Update the global cpu speed variable according to current cpufreq speed, /proc/cpuinfo reports the actual speed. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pasemi/cpufreq.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c index 2a57d602368..3ae083851b0 100644 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/arch/powerpc/platforms/pasemi/cpufreq.c @@ -31,6 +31,7 @@ #include #include #include +#include #define SDCASR_REG 0x0100 #define SDCASR_REG_STRIDE 0x1000 @@ -204,6 +205,8 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cur = pas_freqs[cur_astate].frequency; policy->cpus = cpu_online_map; + ppc_proc_freq = policy->cur * 1000ul; + cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu); /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max @@ -270,6 +273,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy, cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); mutex_unlock(&pas_switch_mutex); + ppc_proc_freq = freqs.new * 1000ul; return 0; } -- cgit v1.2.3 From 5cae84c9710cbb780bcbc96ac842a9e539f059ad Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Mon, 7 May 2007 01:38:49 +1000 Subject: [POWERPC] lite5200(b) support for i2c Add fsl-i2c to mpc5200 i2c node in device tree, and enable FSL_SOC. Tested to work with built-in eeprom on lite5200b. Signed-off-by: Domen Puncer Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/52xx/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index bc4aa4a80a1..3ffaa066c2c 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -1,5 +1,6 @@ config PPC_MPC52xx bool + select FSL_SOC default n config PPC_MPC5200 -- cgit v1.2.3 From 2e1ee1f76684c5d4dd8e5a08cbf22d57f88769ed Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Mon, 7 May 2007 01:38:52 +1000 Subject: [POWERPC] mpc52xx suspend to deep-sleep Implement deep-sleep on MPC52xx. SDRAM is put into self-refresh with help of SRAM code (alternatives would be code in FLASH, I-cache). Interrupt code must also not be in SDRAM, so put it in I-cache. MPC52xx core is static, so contents will remain intact even with clocks turned off. Signed-off-by: Domen Puncer Acked-by: Grant Likely Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/52xx/Makefile | 2 + arch/powerpc/platforms/52xx/efika.c | 15 +++ arch/powerpc/platforms/52xx/lite5200.c | 28 ++++ arch/powerpc/platforms/52xx/mpc52xx_pm.c | 191 ++++++++++++++++++++++++++++ arch/powerpc/platforms/52xx/mpc52xx_sleep.S | 154 ++++++++++++++++++++++ 5 files changed, 390 insertions(+) create mode 100644 arch/powerpc/platforms/52xx/mpc52xx_pm.c create mode 100644 arch/powerpc/platforms/52xx/mpc52xx_sleep.S (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index 07cdbcacf15..b91e39c84d4 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile @@ -8,3 +8,5 @@ endif obj-$(CONFIG_PPC_EFIKA) += efika.o obj-$(CONFIG_PPC_LITE5200) += lite5200.o + +obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index a6bba97314e..f591a9fc19b 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -184,6 +184,16 @@ static void efika_show_cpuinfo(struct seq_file *m) of_node_put(root); } +#ifdef CONFIG_PM +static void efika_suspend_prepare(void __iomem *mbar) +{ + u8 pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */ + u8 level = 1; /* wakeup on high level */ + /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */ + mpc52xx_set_wakeup_gpio(pin, level); +} +#endif + static void __init efika_setup_arch(void) { rtas_initialize(); @@ -199,6 +209,11 @@ static void __init efika_setup_arch(void) efika_pcisetup(); +#ifdef CONFIG_PM + mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare; + mpc52xx_pm_init(); +#endif + if (ppc_md.progress) ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0); } diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 8e2646ac417..1cfc00dfb99 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -85,6 +85,28 @@ error: iounmap(gpio); } +#ifdef CONFIG_PM +static u32 descr_a; +static void lite5200_suspend_prepare(void __iomem *mbar) +{ + u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ + u8 level = 0; /* wakeup on low level */ + mpc52xx_set_wakeup_gpio(pin, level); + + /* + * power down usb port + * this needs to be called before of-ohci suspend code + */ + descr_a = in_be32(mbar + 0x1048); + out_be32(mbar + 0x1048, (descr_a & ~0x200) | 0x100); +} + +static void lite5200_resume_finish(void __iomem *mbar) +{ + out_be32(mbar + 0x1048, descr_a); +} +#endif + static void __init lite5200_setup_arch(void) { struct device_node *np; @@ -107,6 +129,12 @@ static void __init lite5200_setup_arch(void) mpc52xx_setup_cpu(); /* Generic */ lite5200_setup_cpu(); /* Platorm specific */ +#ifdef CONFIG_PM + mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; + mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; + mpc52xx_pm_init(); +#endif + #ifdef CONFIG_PCI np = of_find_node_by_type(NULL, "pci"); if (np) { diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c new file mode 100644 index 00000000000..fd40044d16c --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include + +#include "mpc52xx_pic.h" + + +/* these are defined in mpc52xx_sleep.S, and only used here */ +extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs, + struct mpc52xx_cdm *, struct mpc52xx_intr *); +extern void mpc52xx_ds_sram(void); +extern const long mpc52xx_ds_sram_size; +extern void mpc52xx_ds_cached(void); +extern const long mpc52xx_ds_cached_size; + +static void __iomem *mbar; +static void __iomem *sdram; +static struct mpc52xx_cdm __iomem *cdm; +static struct mpc52xx_intr __iomem *intr; +static struct mpc52xx_gpio_wkup __iomem *gpiow; +static void *sram; +static int sram_size; + +struct mpc52xx_suspend mpc52xx_suspend; + +static int mpc52xx_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + return 1; + default: + return 0; + } +} + +int mpc52xx_set_wakeup_gpio(u8 pin, u8 level) +{ + u16 tmp; + + /* enable gpio */ + out_8(&gpiow->wkup_gpioe, in_8(&gpiow->wkup_gpioe) | (1 << pin)); + /* set as input */ + out_8(&gpiow->wkup_ddr, in_8(&gpiow->wkup_ddr) & ~(1 << pin)); + /* enable deep sleep interrupt */ + out_8(&gpiow->wkup_inten, in_8(&gpiow->wkup_inten) | (1 << pin)); + /* low/high level creates wakeup interrupt */ + tmp = in_be16(&gpiow->wkup_itype); + tmp &= ~(0x3 << (pin * 2)); + tmp |= (!level + 1) << (pin * 2); + out_be16(&gpiow->wkup_itype, tmp); + /* master enable */ + out_8(&gpiow->wkup_maste, 1); + + return 0; +} + +int mpc52xx_pm_prepare(suspend_state_t state) +{ + if (state != PM_SUSPEND_STANDBY) + return -EINVAL; + + /* map the whole register space */ + mbar = mpc52xx_find_and_map("mpc5200"); + if (!mbar) { + printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__); + return -ENOSYS; + } + /* these offsets are from mpc5200 users manual */ + sdram = mbar + 0x100; + cdm = mbar + 0x200; + intr = mbar + 0x500; + gpiow = mbar + 0xc00; + sram = mbar + 0x8000; /* Those will be handled by the */ + sram_size = 0x4000; /* bestcomm driver soon */ + + /* call board suspend code, if applicable */ + if (mpc52xx_suspend.board_suspend_prepare) + mpc52xx_suspend.board_suspend_prepare(mbar); + else { + printk(KERN_ALERT "%s: %i don't know how to wake up the board\n", + __func__, __LINE__); + goto out_unmap; + } + + return 0; + + out_unmap: + iounmap(mbar); + return -ENOSYS; +} + + +char saved_sram[0x4000]; + +int mpc52xx_pm_enter(suspend_state_t state) +{ + u32 clk_enables; + u32 msr, hid0; + u32 intr_main_mask; + void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500; + unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size; + char saved_0x500[mpc52xx_ds_cached_size]; + + /* disable all interrupts in PIC */ + intr_main_mask = in_be32(&intr->main_mask); + out_be32(&intr->main_mask, intr_main_mask | 0x1ffff); + + /* don't let DEC expire any time soon */ + mtspr(SPRN_DEC, 0x7fffffff); + + /* save SRAM */ + memcpy(saved_sram, sram, sram_size); + + /* copy low level suspend code to sram */ + memcpy(sram, mpc52xx_ds_sram, mpc52xx_ds_sram_size); + + out_8(&cdm->ccs_sleep_enable, 1); + out_8(&cdm->osc_sleep_enable, 1); + out_8(&cdm->ccs_qreq_test, 1); + + /* disable all but SDRAM and bestcomm (SRAM) clocks */ + clk_enables = in_be32(&cdm->clk_enables); + out_be32(&cdm->clk_enables, clk_enables & 0x00088000); + + /* disable power management */ + msr = mfmsr(); + mtmsr(msr & ~MSR_POW); + + /* enable sleep mode, disable others */ + hid0 = mfspr(SPRN_HID0); + mtspr(SPRN_HID0, (hid0 & ~(HID0_DOZE | HID0_NAP | HID0_DPM)) | HID0_SLEEP); + + /* save original, copy our irq handler, flush from dcache and invalidate icache */ + memcpy(saved_0x500, irq_0x500, mpc52xx_ds_cached_size); + memcpy(irq_0x500, mpc52xx_ds_cached, mpc52xx_ds_cached_size); + flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop); + + /* call low-level sleep code */ + mpc52xx_deep_sleep(sram, sdram, cdm, intr); + + /* restore original irq handler */ + memcpy(irq_0x500, saved_0x500, mpc52xx_ds_cached_size); + flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop); + + /* restore old power mode */ + mtmsr(msr & ~MSR_POW); + mtspr(SPRN_HID0, hid0); + mtmsr(msr); + + out_be32(&cdm->clk_enables, clk_enables); + out_8(&cdm->ccs_sleep_enable, 0); + out_8(&cdm->osc_sleep_enable, 0); + + /* restore SRAM */ + memcpy(sram, saved_sram, sram_size); + + /* restart jiffies */ + wakeup_decrementer(); + + /* reenable interrupts in PIC */ + out_be32(&intr->main_mask, intr_main_mask); + + return 0; +} + +int mpc52xx_pm_finish(suspend_state_t state) +{ + /* call board resume code */ + if (mpc52xx_suspend.board_resume_finish) + mpc52xx_suspend.board_resume_finish(mbar); + + iounmap(mbar); + + return 0; +} + +static struct pm_ops mpc52xx_pm_ops = { + .valid = mpc52xx_pm_valid, + .prepare = mpc52xx_pm_prepare, + .enter = mpc52xx_pm_enter, + .finish = mpc52xx_pm_finish, +}; + +int __init mpc52xx_pm_init(void) +{ + pm_set_ops(&mpc52xx_pm_ops); + return 0; +} diff --git a/arch/powerpc/platforms/52xx/mpc52xx_sleep.S b/arch/powerpc/platforms/52xx/mpc52xx_sleep.S new file mode 100644 index 00000000000..4dc170b0ae1 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_sleep.S @@ -0,0 +1,154 @@ +#include +#include +#include + + +.text + +_GLOBAL(mpc52xx_deep_sleep) +mpc52xx_deep_sleep: /* args r3-r6: SRAM, SDRAM regs, CDM regs, INTR regs */ + + /* enable interrupts */ + mfmsr r7 + ori r7, r7, 0x8000 /* EE */ + mtmsr r7 + sync; isync; + + li r10, 0 /* flag that irq handler sets */ + + /* enable tmr7 (or any other) interrupt */ + lwz r8, 0x14(r6) /* intr->main_mask */ + ori r8, r8, 0x1 + xori r8, r8, 0x1 + stw r8, 0x14(r6) + sync + + /* emulate tmr7 interrupt */ + li r8, 0x1 + stw r8, 0x40(r6) /* intr->main_emulate */ + sync + + /* wait for it to happen */ +1: + cmpi cr0, r10, 1 + bne cr0, 1b + + /* lock icache */ + mfspr r10, SPRN_HID0 + ori r10, r10, 0x2000 + sync; isync; + mtspr SPRN_HID0, r10 + sync; isync; + + + mflr r9 /* save LR */ + + /* jump to sram */ + mtlr r3 + blrl + + mtlr r9 /* restore LR */ + + /* unlock icache */ + mfspr r10, SPRN_HID0 + ori r10, r10, 0x2000 + xori r10, r10, 0x2000 + sync; isync; + mtspr SPRN_HID0, r10 + sync; isync; + + + /* return to C code */ + blr + + +_GLOBAL(mpc52xx_ds_sram) +mpc52xx_ds_sram: + /* put SDRAM into self-refresh */ + lwz r8, 0x4(r4) /* sdram->ctrl */ + + oris r8, r8, 0x8000 /* mode_en */ + stw r8, 0x4(r4) + sync + + ori r8, r8, 0x0002 /* soft_pre */ + stw r8, 0x4(r4) + sync + xori r8, r8, 0x0002 + + xoris r8, r8, 0x8000 /* !mode_en */ + stw r8, 0x4(r4) + sync + + oris r8, r8, 0x5000 + xoris r8, r8, 0x4000 /* ref_en !cke */ + stw r8, 0x4(r4) + sync + + /* disable SDRAM clock */ + lwz r8, 0x14(r5) /* cdm->clkenable */ + ori r8, r8, 0x0008 + xori r8, r8, 0x0008 + stw r8, 0x14(r5) + sync + + + /* put mpc5200 to sleep */ + mfmsr r10 + oris r10, r10, 0x0004 /* POW = 1 */ + sync; isync; + mtmsr r10 + sync; isync; + + + /* enable clock */ + lwz r8, 0x14(r5) + ori r8, r8, 0x0008 + stw r8, 0x14(r5) + sync + + /* get ram out of self-refresh */ + lwz r8, 0x4(r4) + oris r8, r8, 0x5000 /* cke ref_en */ + stw r8, 0x4(r4) + sync + + blr +_GLOBAL(mpc52xx_ds_sram_size) +mpc52xx_ds_sram_size: + .long $-mpc52xx_ds_sram + + +/* ### interrupt handler for wakeup from deep-sleep ### */ +_GLOBAL(mpc52xx_ds_cached) +mpc52xx_ds_cached: + mtspr SPRN_SPRG0, r7 + mtspr SPRN_SPRG1, r8 + + /* disable emulated interrupt */ + mfspr r7, 311 /* MBAR */ + addi r7, r7, 0x540 /* intr->main_emul */ + li r8, 0 + stw r8, 0(r7) + sync + dcbf 0, r7 + + /* acknowledge wakeup, so CCS releases power pown */ + mfspr r7, 311 /* MBAR */ + addi r7, r7, 0x524 /* intr->enc_status */ + lwz r8, 0(r7) + ori r8, r8, 0x0400 + stw r8, 0(r7) + sync + dcbf 0, r7 + + /* flag - we handled the interrupt */ + li r10, 1 + + mfspr r8, SPRN_SPRG1 + mfspr r7, SPRN_SPRG0 + + rfi +_GLOBAL(mpc52xx_ds_cached_size) +mpc52xx_ds_cached_size: + .long $-mpc52xx_ds_cached -- cgit v1.2.3 From fb39a96e23d4d1115f8e7e0b9916d0e9c23d8f65 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Tue, 8 May 2007 03:11:11 +1000 Subject: [POWERPC] Export pcibios_remove_pci_devices The pseries PCI hotplug code cannot build as a module, unless the pcibios_remove_pci_devices function is exported. Signed-off-by: Linas Vepstas ---- arch/powerpc/platforms/pseries/pci_dlpar.c | 1 + 1 file changed, 1 insertion(+) Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/pci_dlpar.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index fdc1a369f76..ffaf6c5c517 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -79,6 +79,7 @@ pcibios_remove_pci_devices(struct pci_bus *bus) pci_remove_bus_device(dev); } } +EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices); /* Must be called before pci_bus_add_devices */ void -- cgit v1.2.3 From 08390db07a012b972189629a30eb695cdcb0ec14 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 May 2007 07:25:22 +1000 Subject: [POWERPC] Add tsi108_pci.h for common PCI functions Add a header file for the common PCI routines used for the TSI bridge Signed-off-by: Josh Boyer Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 366702e8c03..06c86a1b4fb 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -41,6 +41,7 @@ #include #include #include "mpc7448_hpc2.h" +#include #include #include @@ -57,10 +58,7 @@ isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; #endif -extern int tsi108_setup_pci(struct device_node *dev); extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); -extern void tsi108_pci_int_init(struct device_node *node); -extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc); int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) { @@ -210,7 +208,6 @@ static int __init mpc7448_hpc2_probe(void) static int mpc7448_machine_check_exception(struct pt_regs *regs) { - extern void tsi108_clear_pci_cfg_error(void); const struct exception_table_entry *entry; /* Are we prepared to handle this fault */ -- cgit v1.2.3 From 05ad6a9159401804c9bcec8922a9c4a1cb2bfb59 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 May 2007 07:27:15 +1000 Subject: [POWERPC] Generalize tsi108 PCI setup Generalize tsi108_setup_pci to take the config space physical address and primary bus designator as a parameter. Signed-off-by: Josh Boyer Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 06c86a1b4fb..4542e0c837c 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -52,6 +52,8 @@ #define DBG(fmt...) do { } while(0) #endif +#define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000 + #ifndef CONFIG_PCI isa_io_base = MPC7448_HPC2_ISA_IO_BASE; isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; @@ -79,7 +81,7 @@ static void __init mpc7448_hpc2_setup_arch(void) /* setup PCI host bridge */ #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - tsi108_setup_pci(np); + tsi108_setup_pci(np, MPC7448HPC2_PCI_CFG_PHYS, 0); ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device; if (ppc_md.progress) -- cgit v1.2.3 From cb9e4d10c448a388babd9dfbfa2b8bb1c5bbf84f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 May 2007 07:28:38 +1000 Subject: [POWERPC] Add support for 750CL Holly board Add PowerPC 750 Holly/Hickory platform support Signed-off-by: Stephen Winiecki Signed-off-by: Josh Boyer Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/embedded6xx/Kconfig | 14 +- arch/powerpc/platforms/embedded6xx/Makefile | 1 + arch/powerpc/platforms/embedded6xx/holly.c | 317 ++++++++++++++++++++++++++++ 3 files changed, 329 insertions(+), 3 deletions(-) create mode 100644 arch/powerpc/platforms/embedded6xx/holly.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 9557908ef54..8f3c2a73e16 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig @@ -20,16 +20,24 @@ config MPC7448HPC2 select TSI108_BRIDGE select DEFAULT_UIMAGE select PPC_UDBG_16550 - select MPIC - select MPIC_WEIRD help Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) platform + +config PPC_HOLLY + bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" + select TSI108_BRIDGE + select PPC_UDBG_16550 + help + Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval + Board with TSI108/9 bridge (Hickory/Holly) endchoice config TSI108_BRIDGE bool - depends on MPC7448HPC2 + depends on MPC7448HPC2 || PPC_HOLLY + select MPIC + select MPIC_WEIRD default y config MPC10X_BRIDGE diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile index d3d11a3cd65..b39fe4f470d 100644 --- a/arch/powerpc/platforms/embedded6xx/Makefile +++ b/arch/powerpc/platforms/embedded6xx/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o +obj-$(CONFIG_PPC_HOLLY) += holly.o diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c new file mode 100644 index 00000000000..3a0b4a01401 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/holly.c @@ -0,0 +1,317 @@ +/* + * Board setup routines for the IBM 750GX/CL platform w/ TSI10x bridge + * + * Copyright 2007 IBM Corporation + * + * Stephen Winiecki + * Josh Boyer + * + * Based on code from mpc7448_hpc2.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#define HOLLY_PCI_CFG_PHYS 0x7c000000 + +int holly_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +static void holly_remap_bridge(void) +{ + u32 lut_val, lut_addr; + int i; + + printk(KERN_INFO "Remapping PCI bridge\n"); + + /* Re-init the PCI bridge and LUT registers to have mappings that don't + * rely on PIBS + */ + lut_addr = 0x900; + for (i = 0; i < 31; i++) { + tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000201); + lut_addr += 4; + tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0); + lut_addr += 4; + } + + /* Reserve the last LUT entry for PCI I/O space */ + tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000241); + lut_addr += 4; + tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0); + + /* Map PCI I/O space */ + tsi108_write_reg(TSI108_PCI_PFAB_IO_UPPER, 0x0); + tsi108_write_reg(TSI108_PCI_PFAB_IO, 0x1); + + /* Map PCI CFG space */ + tsi108_write_reg(TSI108_PCI_PFAB_BAR0_UPPER, 0x0); + tsi108_write_reg(TSI108_PCI_PFAB_BAR0, 0x7c000000 | 0x01); + + /* We don't need MEM32 and PRM remapping so disable them */ + tsi108_write_reg(TSI108_PCI_PFAB_MEM32, 0x0); + tsi108_write_reg(TSI108_PCI_PFAB_PFM3, 0x0); + tsi108_write_reg(TSI108_PCI_PFAB_PFM4, 0x0); + + /* Set P2O_BAR0 */ + tsi108_write_reg(TSI108_PCI_P2O_BAR0_UPPER, 0x0); + tsi108_write_reg(TSI108_PCI_P2O_BAR0, 0xc0000000); + + /* Init the PCI LUTs to do no remapping */ + lut_addr = 0x500; + lut_val = 0x00000002; + + for (i = 0; i < 32; i++) { + tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, lut_val); + lut_addr += 4; + tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, 0x40000000); + lut_addr += 4; + lut_val += 0x02000000; + } + tsi108_write_reg(TSI108_PCI_P2O_PAGE_SIZES, 0x00007900); + + /* Set 64-bit PCI bus address for system memory */ + tsi108_write_reg(TSI108_PCI_P2O_BAR2_UPPER, 0x0); + tsi108_write_reg(TSI108_PCI_P2O_BAR2, 0x0); +} + +static void __init holly_setup_arch(void) +{ + struct device_node *cpu; + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("holly_setup_arch():set_bridge", 0); + + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu) { + const unsigned int *fp; + + fp = of_get_property(cpu, "clock-frequency", NULL); + if (fp) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(cpu); + } + tsi108_csr_vir_base = get_vir_csrbase(); + + /* setup PCI host bridge */ + holly_remap_bridge(); + + np = of_find_node_by_type(NULL, "pci"); + if (np) + tsi108_setup_pci(np, HOLLY_PCI_CFG_PHYS, 1); + + ppc_md.pci_exclude_device = holly_exclude_device; + if (ppc_md.progress) + ppc_md.progress("tsi108: resources set", 0x100); + + printk(KERN_INFO "PPC750GX/CL Platform\n"); +} + +/* + * Interrupt setup and service. Interrrupts on the holly come + * from the four external INT pins, PCI interrupts are routed via + * PCI interrupt control registers, it generates internal IRQ23 + * + * Interrupt routing on the Holly Board: + * TSI108:PB_INT[0] -> CPU0:INT# + * TSI108:PB_INT[1] -> CPU0:MCP# + * TSI108:PB_INT[2] -> N/C + * TSI108:PB_INT[3] -> N/C + */ +static void __init holly_init_IRQ(void) +{ + struct mpic *mpic; + phys_addr_t mpic_paddr = 0; + struct device_node *tsi_pic; +#ifdef CONFIG_PCI + unsigned int cascade_pci_irq; + struct device_node *tsi_pci; + struct device_node *cascade_node = NULL; +#endif + + tsi_pic = of_find_node_by_type(NULL, "open-pic"); + if (tsi_pic) { + unsigned int size; + const void *prop = of_get_property(tsi_pic, "reg", &size); + mpic_paddr = of_translate_address(tsi_pic, prop); + } + + if (mpic_paddr == 0) { + printk(KERN_ERR "%s: No tsi108 PIC found !\n", __func__); + return; + } + + pr_debug("%s: tsi108 pic phys_addr = 0x%x\n", __func__, (u32) mpic_paddr); + + mpic = mpic_alloc(tsi_pic, mpic_paddr, + MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | + MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, + 24, + NR_IRQS-4, /* num_sources used */ + "Tsi108_PIC"); + + BUG_ON(mpic == NULL); + + mpic_assign_isu(mpic, 0, mpic_paddr + 0x100); + + mpic_init(mpic); + +#ifdef CONFIG_PCI + tsi_pci = of_find_node_by_type(NULL, "pci"); + if (tsi_pci == NULL) { + printk(KERN_ERR "%s: No tsi108 pci node found !\n", __func__); + return; + } + + cascade_node = of_find_node_by_type(NULL, "pic-router"); + if (cascade_node == NULL) { + printk(KERN_ERR "%s: No tsi108 pci cascade node found !\n", __func__); + return; + } + + cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0); + pr_debug("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__, (u32) cascade_pci_irq); + tsi108_pci_int_init(cascade_node); + set_irq_data(cascade_pci_irq, mpic); + set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade); +#endif + /* Configure MPIC outputs to CPU0 */ + tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0); + of_node_put(tsi_pic); +} + +void holly_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: IBM\n"); + seq_printf(m, "machine\t\t: PPC750 GX/CL\n"); +} + +void holly_restart(char *cmd) +{ + __be32 __iomem *ocn_bar1 = NULL; + unsigned long bar; + struct device_node *bridge = NULL; + const void *prop; + int size; + phys_addr_t addr = 0xc0000000; + + local_irq_disable(); + + bridge = of_find_node_by_type(NULL, "tsi-bridge"); + if (bridge) { + prop = of_get_property(bridge, "reg", &size); + addr = of_translate_address(bridge, prop); + } + addr += (TSI108_PB_OFFSET + 0x414); + + ocn_bar1 = ioremap(addr, 0x4); + + /* Turn on the BOOT bit so the addresses are correctly + * routed to the HLP interface */ + bar = ioread32be(ocn_bar1); + bar |= 2; + iowrite32be(bar, ocn_bar1); + iosync(); + + /* Set SRR0 to the reset vector and turn on MSR_IP */ + mtspr(SPRN_SRR0, 0xfff00100); + mtspr(SPRN_SRR1, MSR_IP); + + /* Do an rfi to jump back to firmware. Somewhat evil, + * but it works + */ + __asm__ __volatile__("rfi" : : : "memory"); + + /* Spin until reset happens. Shouldn't really get here */ + for (;;) ; +} + +void holly_power_off(void) +{ + local_irq_disable(); + /* No way to shut power off with software */ + for (;;) ; +} + +void holly_halt(void) +{ + holly_power_off(); +} + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init holly_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (!of_flat_dt_is_compatible(root, "ibm,holly")) + return 0; + return 1; +} + +static int ppc750_machine_check_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *entry; + + /* Are we prepared to handle this fault */ + if ((entry = search_exception_tables(regs->nip)) != NULL) { + tsi108_clear_pci_cfg_error(); + regs->msr |= MSR_RI; + regs->nip = entry->fixup; + return 1; + } + return 0; +} + +define_machine(holly){ + .name = "PPC750 GX/CL TSI", + .probe = holly_probe, + .setup_arch = holly_setup_arch, + .init_IRQ = holly_init_IRQ, + .show_cpuinfo = holly_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = holly_restart, + .calibrate_decr = generic_calibrate_decr, + .machine_check_exception = ppc750_machine_check_exception, + .progress = udbg_progress, +}; -- cgit v1.2.3 From 00c2ae35bd50664bcd841becc6efceef8aa5d074 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 8 May 2007 08:04:05 +1000 Subject: [POWERPC] Add powerpc PCI-E reset API implementation Adds the pSeries platform implementation for a new PCI API which can be used to issue various types of PCI-E reset, including PCI-E warm reset and PCI-E hot reset. This is needed for an ipr PCI-E adapter which does not properly implement BIST. Running BIST on this adapter results in PCI-E errors. The only reliable reset mechanism that exists on this hardware is PCI Fundamental reset (warm reset). Acked-by: Linas Vepstas Signed-off-by: Brian King Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 48fbd442e9d..63e23062e98 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -579,6 +579,36 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state) rc, state, pdn->node->full_name); } +/** + * pcibios_set_pcie_slot_reset - Set PCI-E reset state + * @dev: pci device struct + * @state: reset state to enter + * + * Return value: + * 0 if success + **/ +int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) +{ + struct device_node *dn = pci_device_to_OF_node(dev); + struct pci_dn *pdn = PCI_DN(dn); + + switch (state) { + case pcie_deassert_reset: + rtas_pci_slot_reset(pdn, 0); + break; + case pcie_hot_reset: + rtas_pci_slot_reset(pdn, 1); + break; + case pcie_warm_reset: + rtas_pci_slot_reset(pdn, 3); + break; + default: + return -EINVAL; + }; + + return 0; +} + /** * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second * @pdn: pci device node to be reset. -- cgit v1.2.3 From 85f2bf9f60f55b6727ed310ebbaa2df7142326e5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 8 May 2007 12:58:35 +1000 Subject: [POWERPC] RTAS MSI implementation Implement MSI support via RTAS (RTAS = run-time firmware on pSeries machines). For now we assumes that if the required RTAS tokens for MSI are present, then we want to use the RTAS MSI routines. When RTAS is managing MSIs for us, it will/may enable MSI on devices that support it by default. This is contrary to the Linux model where a device is in LSI mode until the driver requests MSIs. To remedy this we add a pci_irq_fixup call, which disables MSI if they've been assigned by firmware and the device also supports LSI. Devices that don't support LSI at all will be left as is, drivers are still expected to call pci_enable_msi() before using the device. At the moment there is no pci_irq_fixup on pSeries, so we can just set it unconditionally. If other platforms use the RTAS MSI backend they'll need to check that still holds. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/msi.c | 270 ++++++++++++++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 arch/powerpc/platforms/pseries/msi.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 90235d59875..ae1fc92dc1c 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_PCI) += pci.o pci_dlpar.o +obj-$(CONFIG_PCI_MSI) += msi.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c new file mode 100644 index 00000000000..6063ea2f67a --- /dev/null +++ b/arch/powerpc/platforms/pseries/msi.c @@ -0,0 +1,270 @@ +/* + * Copyright 2006 Jake Moilanen , IBM Corp. + * Copyright 2006-2007 Michael Ellerman, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 of the + * License. + * + */ + +#include +#include +#include + +#include +#include +#include + +static int query_token, change_token; + +#define RTAS_QUERY_FN 0 +#define RTAS_CHANGE_FN 1 +#define RTAS_RESET_FN 2 +#define RTAS_CHANGE_MSI_FN 3 +#define RTAS_CHANGE_MSIX_FN 4 + +static struct pci_dn *get_pdn(struct pci_dev *pdev) +{ + struct device_node *dn; + struct pci_dn *pdn; + + dn = pci_device_to_OF_node(pdev); + if (!dn) { + dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n"); + return NULL; + } + + pdn = PCI_DN(dn); + if (!pdn) { + dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n"); + return NULL; + } + + return pdn; +} + +/* RTAS Helpers */ + +static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) +{ + u32 addr, seq_num, rtas_ret[3]; + unsigned long buid; + int rc; + + addr = rtas_config_addr(pdn->busno, pdn->devfn, 0); + buid = pdn->phb->buid; + + seq_num = 1; + do { + if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN) + rc = rtas_call(change_token, 6, 4, rtas_ret, addr, + BUID_HI(buid), BUID_LO(buid), + func, num_irqs, seq_num); + else + rc = rtas_call(change_token, 6, 3, rtas_ret, addr, + BUID_HI(buid), BUID_LO(buid), + func, num_irqs, seq_num); + + seq_num = rtas_ret[1]; + } while (rtas_busy_delay(rc)); + + if (rc == 0) /* Success */ + rc = rtas_ret[0]; + + pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d) = (%d)\n", + func, num_irqs, rc); + + return rc; +} + +static void rtas_disable_msi(struct pci_dev *pdev) +{ + struct pci_dn *pdn; + + pdn = get_pdn(pdev); + if (!pdn) + return; + + if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0) + pr_debug("rtas_msi: Setting MSIs to 0 failed!\n"); +} + +static int rtas_query_irq_number(struct pci_dn *pdn, int offset) +{ + u32 addr, rtas_ret[2]; + unsigned long buid; + int rc; + + addr = rtas_config_addr(pdn->busno, pdn->devfn, 0); + buid = pdn->phb->buid; + + do { + rc = rtas_call(query_token, 4, 3, rtas_ret, addr, + BUID_HI(buid), BUID_LO(buid), offset); + } while (rtas_busy_delay(rc)); + + if (rc) { + pr_debug("rtas_msi: error (%d) querying source number\n", rc); + return rc; + } + + return rtas_ret[0]; +} + +static void rtas_teardown_msi_irqs(struct pci_dev *pdev) +{ + struct msi_desc *entry; + + list_for_each_entry(entry, &pdev->msi_list, list) { + if (entry->irq == NO_IRQ) + continue; + + set_irq_msi(entry->irq, NULL); + irq_dispose_mapping(entry->irq); + } + + rtas_disable_msi(pdev); +} + +static int check_req_msi(struct pci_dev *pdev, int nvec) +{ + struct device_node *dn; + struct pci_dn *pdn; + const u32 *req_msi; + + pdn = get_pdn(pdev); + if (!pdn) + return -ENODEV; + + dn = pdn->node; + + req_msi = of_get_property(dn, "ibm,req#msi", NULL); + if (!req_msi) { + pr_debug("rtas_msi: No ibm,req#msi on %s\n", dn->full_name); + return -ENOENT; + } + + if (*req_msi < nvec) { + pr_debug("rtas_msi: ibm,req#msi requests < %d MSIs\n", nvec); + return -ENOSPC; + } + + return 0; +} + +static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type) +{ + if (type == PCI_CAP_ID_MSIX) + pr_debug("rtas_msi: MSI-X untested, trying anyway.\n"); + + return check_req_msi(pdev, nvec); +} + +static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +{ + struct pci_dn *pdn; + int hwirq, virq, i, rc; + struct msi_desc *entry; + + pdn = get_pdn(pdev); + if (!pdn) + return -ENODEV; + + /* + * Try the new more explicit firmware interface, if that fails fall + * back to the old interface. The old interface is known to never + * return MSI-Xs. + */ + if (type == PCI_CAP_ID_MSI) { + rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); + + if (rc != nvec) { + pr_debug("rtas_msi: trying the old firmware call.\n"); + rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); + } + } else + rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); + + if (rc != nvec) { + pr_debug("rtas_msi: rtas_change_msi() failed\n"); + + /* + * In case of an error it's not clear whether the device is + * left with MSI enabled or not, so we explicitly disable. + */ + goto out_free; + } + + i = 0; + list_for_each_entry(entry, &pdev->msi_list, list) { + hwirq = rtas_query_irq_number(pdn, i); + if (hwirq < 0) { + rc = hwirq; + pr_debug("rtas_msi: error (%d) getting hwirq\n", rc); + goto out_free; + } + + virq = irq_create_mapping(NULL, hwirq); + + if (virq == NO_IRQ) { + pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq); + rc = -ENOSPC; + goto out_free; + } + + dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq); + set_irq_msi(virq, entry); + unmask_msi_irq(virq); + } + + return 0; + + out_free: + rtas_teardown_msi_irqs(pdev); + return rc; +} + +static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev) +{ + /* No LSI -> leave MSIs (if any) configured */ + if (pdev->irq == NO_IRQ) { + dev_dbg(&pdev->dev, "rtas_msi: no LSI, nothing to do.\n"); + return; + } + + /* No MSI -> MSIs can't have been assigned by fw, leave LSI */ + if (check_req_msi(pdev, 1)) { + dev_dbg(&pdev->dev, "rtas_msi: no req#msi, nothing to do.\n"); + return; + } + + dev_dbg(&pdev->dev, "rtas_msi: disabling existing MSI.\n"); + rtas_disable_msi(pdev); +} + +static int rtas_msi_init(void) +{ + query_token = rtas_token("ibm,query-interrupt-source-number"); + change_token = rtas_token("ibm,change-msi"); + + if ((query_token == RTAS_UNKNOWN_SERVICE) || + (change_token == RTAS_UNKNOWN_SERVICE)) { + pr_debug("rtas_msi: no RTAS tokens, no MSI support.\n"); + return -1; + } + + pr_debug("rtas_msi: Registering RTAS MSI callbacks.\n"); + + WARN_ON(ppc_md.setup_msi_irqs); + ppc_md.setup_msi_irqs = rtas_setup_msi_irqs; + ppc_md.teardown_msi_irqs = rtas_teardown_msi_irqs; + ppc_md.msi_check_device = rtas_msi_check_device; + + WARN_ON(ppc_md.pci_irq_fixup); + ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup; + + return 0; +} +arch_initcall(rtas_msi_init); -- cgit v1.2.3 From 2cd976477035716af52a6eff6625f32e5813c02b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 May 2007 12:59:30 +1000 Subject: [POWERPC] Add powerpc/platforms/44x, disable platforms/4xx for now This prepares for Ebony/440 support by creating an arch/powerpc/platforms/44x directory. It is populated with a single misc_44x.S file, into which is moved the 44x specific reset code from head_44x.S (on the grounds that we should really stop clogging up the head_* files with random asm helper routines). At the same time, we disable the (empty save Kconfig and Makefile) arch/powerpc/platforms/4xx directory from the arch/powerpc/platforms Makefile. Contrary to the comment in arch/powerpc/platforms/4xx/Makefile, attempting to build such an empty Makefile will fail, thus breaking compile for the 44x platforms we're about to add. It can go back in once we start porting some of the 40x platforms (and thus it becomes non-empty). Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/44x/44x.h | 6 ++++++ arch/powerpc/platforms/44x/Makefile | 1 + arch/powerpc/platforms/44x/misc_44x.S | 26 ++++++++++++++++++++++++++ arch/powerpc/platforms/Makefile | 3 ++- 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/platforms/44x/44x.h create mode 100644 arch/powerpc/platforms/44x/Makefile create mode 100644 arch/powerpc/platforms/44x/misc_44x.S (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h new file mode 100644 index 00000000000..45f24b166f4 --- /dev/null +++ b/arch/powerpc/platforms/44x/44x.h @@ -0,0 +1,6 @@ +#ifndef __POWERPC_PLATFORMS_44X_44X_H +#define __POWERPC_PLATFORMS_44X_44X_H + +extern void ppc44x_reset_system(char *cmd); + +#endif /* __POWERPC_PLATFORMS_44X_44X_H */ diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile new file mode 100644 index 00000000000..575fdde5c90 --- /dev/null +++ b/arch/powerpc/platforms/44x/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_44x) := misc_44x.o diff --git a/arch/powerpc/platforms/44x/misc_44x.S b/arch/powerpc/platforms/44x/misc_44x.S new file mode 100644 index 00000000000..52bde71485b --- /dev/null +++ b/arch/powerpc/platforms/44x/misc_44x.S @@ -0,0 +1,26 @@ +/* + * This file contains miscellaneous low-level functions for PPC 44x. + * Copyright 2007 David Gibson , IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include + + .text + +/* + * void ppc44x_reset_system(char *cmd) + * + * At present, this routine just applies a system reset. + */ +_GLOBAL(ppc44x_reset_system) + mfspr r13,SPRN_DBCR0 + oris r13,r13,DBCR0_RST_SYSTEM@h + mtspr SPRN_DBCR0,r13 + b . /* Just in case the reset doesn't work */ diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 452004283f1..d6e041a46d2 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -6,7 +6,8 @@ obj-$(CONFIG_PPC_PMAC) += powermac/ endif endif obj-$(CONFIG_PPC_CHRP) += chrp/ -obj-$(CONFIG_4xx) += 4xx/ +#obj-$(CONFIG_4xx) += 4xx/ +obj-$(CONFIG_44x) += 44x/ obj-$(CONFIG_PPC_MPC52xx) += 52xx/ obj-$(CONFIG_PPC_8xx) += 8xx/ obj-$(CONFIG_PPC_82xx) += 82xx/ -- cgit v1.2.3 From f6dfc80554b27da11dbb36ebae166b23ec3aa9ca Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 May 2007 14:10:01 +1000 Subject: [POWERPC] Support for the Ebony 440GP reference board in arch/powerpc This adds platform support code for the Ebony (440GP) evaluation board. This includes both code in arch/powerpc/platforms/44x for board initialization, and zImage wrapper code to correctly tweak the flattened device tree based on information from the firmware. The zImage supports both IBM OpenBIOS (aka "treeboot") and old versions of uboot which don't support a flattened device tree. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/44x/Kconfig | 56 ++++++++++++++++++++++++++++ arch/powerpc/platforms/44x/Makefile | 1 + arch/powerpc/platforms/44x/ebony.c | 73 +++++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/Kconfig | 1 + 4 files changed, 131 insertions(+) create mode 100644 arch/powerpc/platforms/44x/Kconfig create mode 100644 arch/powerpc/platforms/44x/ebony.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig new file mode 100644 index 00000000000..8e66949e7c6 --- /dev/null +++ b/arch/powerpc/platforms/44x/Kconfig @@ -0,0 +1,56 @@ +#config BAMBOO +# bool "Bamboo" +# depends on 44x +# default n +# select 440EP +# help +# This option enables support for the IBM PPC440EP evaluation board. + +config EBONY + bool "Ebony" + depends on 44x + default y + select 440GP + help + This option enables support for the IBM PPC440GP evaluation board. + +#config LUAN +# bool "Luan" +# depends on 44x +# default n +# select 440SP +# help +# This option enables support for the IBM PPC440SP evaluation board. + +#config OCOTEA +# bool "Ocotea" +# depends on 44x +# default n +# select 440GX +# help +# This option enables support for the IBM PPC440GX evaluation board. + +# 44x specific CPU modules, selected based on the board above. +config 440EP + bool + select PPC_FPU + select IBM440EP_ERR42 + +config 440GP + bool + select IBM_NEW_EMAC_ZMII + +config 440GX + bool + +config 440SP + bool + +config 440A + bool + depends on 440GX + default y + +# 44x errata/workaround config symbols, selected by the CPU models above +config IBM440EP_ERR42 + bool diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile index 575fdde5c90..41d0a18a0e4 100644 --- a/arch/powerpc/platforms/44x/Makefile +++ b/arch/powerpc/platforms/44x/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_44x) := misc_44x.o +obj-$(CONFIG_EBONY) += ebony.o diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c new file mode 100644 index 00000000000..ad526eafc90 --- /dev/null +++ b/arch/powerpc/platforms/44x/ebony.c @@ -0,0 +1,73 @@ +/* + * Ebony board specific routines + * + * Matt Porter + * Copyright 2002-2005 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003-2005 Zultys Technologies + * + * Rewritten and ported to the merged powerpc tree: + * Copyright 2007 David Gibson , IBM Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "44x.h" + +static struct of_device_id ebony_of_bus[] = { + { .type = "ibm,plb", }, + { .type = "ibm,opb", }, + { .type = "ibm,ebc", }, + {}, +}; + +static int __init ebony_device_probe(void) +{ + if (!machine_is(ebony)) + return 0; + + of_platform_bus_probe(NULL, ebony_of_bus, NULL); + + return 0; +} +device_initcall(ebony_device_probe); + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init ebony_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (!of_flat_dt_is_compatible(root, "ibm,ebony")) + return 0; + + return 1; +} + +static void __init ebony_setup_arch(void) +{ +} + +define_machine(ebony) { + .name = "Ebony", + .probe = ebony_probe, + .setup_arch = ebony_setup_arch, + .progress = udbg_progress, + .init_IRQ = uic_init_tree, + .get_irq = uic_get_irq, + .restart = ppc44x_reset_system, + .calibrate_decr = generic_calibrate_decr, +}; diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 51e33347c14..361acfa2894 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -42,6 +42,7 @@ source "arch/powerpc/platforms/83xx/Kconfig" source "arch/powerpc/platforms/85xx/Kconfig" source "arch/powerpc/platforms/86xx/Kconfig" source "arch/powerpc/platforms/embedded6xx/Kconfig" +source "arch/powerpc/platforms/44x/Kconfig" #source "arch/powerpc/platforms/4xx/Kconfig config PPC_NATIVE -- cgit v1.2.3 From d9b55a03611ff2e2e54fb4e1ad2648d5eb870fa3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 May 2007 12:59:31 +1000 Subject: [POWERPC] Early serial debug support for PPC44x This adds support for early serial debugging via the built in port on IBM/AMCC PowerPC 44x CPUs. It uses a bolted TLB entry in address space 1 for the UART's mapping, allowing robust debugging both before and after the initialization of the MMU. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/44x/44x.h | 2 ++ arch/powerpc/platforms/44x/misc_44x.S | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h index 45f24b166f4..42eabf87fea 100644 --- a/arch/powerpc/platforms/44x/44x.h +++ b/arch/powerpc/platforms/44x/44x.h @@ -1,6 +1,8 @@ #ifndef __POWERPC_PLATFORMS_44X_44X_H #define __POWERPC_PLATFORMS_44X_44X_H +extern u8 as1_readb(volatile u8 __iomem *addr); +extern void as1_writeb(u8 data, volatile u8 __iomem *addr); extern void ppc44x_reset_system(char *cmd); #endif /* __POWERPC_PLATFORMS_44X_44X_H */ diff --git a/arch/powerpc/platforms/44x/misc_44x.S b/arch/powerpc/platforms/44x/misc_44x.S index 52bde71485b..3bce71d5d75 100644 --- a/arch/powerpc/platforms/44x/misc_44x.S +++ b/arch/powerpc/platforms/44x/misc_44x.S @@ -14,6 +14,37 @@ .text +/* + * Do an IO access in AS1 + */ +_GLOBAL(as1_readb) + mfmsr r7 + ori r0,r7,MSR_DS + sync + mtmsr r0 + sync + isync + lbz r3,0(r3) + sync + mtmsr r7 + sync + isync + blr + +_GLOBAL(as1_writeb) + mfmsr r7 + ori r0,r7,MSR_DS + sync + mtmsr r0 + sync + isync + stb r3,0(r4) + sync + mtmsr r7 + sync + isync + blr + /* * void ppc44x_reset_system(char *cmd) * -- cgit v1.2.3