From 48adcf148c83faa41999fb0b3524299c4e160fd9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 20 May 2008 01:03:16 +0300 Subject: [CPUFREQ] cpufreq: remove CVS keywords This patch removes CVS keywords that weren't updated for a long time from comments. Signed-off-by: Adrian Bunk Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/powernow-k7.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.h b/arch/x86/kernel/cpu/cpufreq/powernow-k7.h index f8a63b3664e..35fb4eaf6e1 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.h @@ -1,5 +1,4 @@ /* - * $Id: powernow-k7.h,v 1.2 2003/02/10 18:26:01 davej Exp $ * (C) 2003 Dave Jones. * * Licensed under the terms of the GNU GPL License version 2. -- cgit v1.2.3-70-g09d2 From 334ef7a7ab8f80b689a2be95d5e62d2167900865 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Mon, 12 May 2008 21:21:13 +0200 Subject: x86: use performance variant for_each_cpu_mask_nr Change references from for_each_cpu_mask to for_each_cpu_mask_nr where appropriate Reviewed-by: Paul Jackson Reviewed-by: Christoph Lameter Signed-off-by: Mike Travis Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner commit 2d474871e2fb092eb46a0930aba5442e10eb96cc Author: Mike Travis Date: Mon May 12 21:21:13 2008 +0200 --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 6 +++--- arch/x86/kernel/cpu/cpufreq/p4-clockmod.c | 6 +++--- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 8 ++++---- arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | 10 +++++----- arch/x86/kernel/cpu/cpufreq/speedstep-ich.c | 4 ++-- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 4 ++-- arch/x86/kernel/io_apic_64.c | 8 ++++---- arch/x86/kernel/smpboot.c | 8 ++++---- arch/x86/xen/smp.c | 4 ++-- include/asm-x86/ipi.h | 2 +- 11 files changed, 31 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index b0c8208df9f..dd097b83583 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -202,7 +202,7 @@ static void drv_write(struct drv_cmd *cmd) cpumask_t saved_mask = current->cpus_allowed; unsigned int i; - for_each_cpu_mask(i, cmd->mask) { + for_each_cpu_mask_nr(i, cmd->mask) { set_cpus_allowed_ptr(current, &cpumask_of_cpu(i)); do_drv_write(cmd); } @@ -451,7 +451,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, freqs.old = perf->states[perf->state].core_frequency * 1000; freqs.new = data->freq_table[next_state].frequency; - for_each_cpu_mask(i, cmd.mask) { + for_each_cpu_mask_nr(i, cmd.mask) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } @@ -466,7 +466,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, } } - for_each_cpu_mask(i, cmd.mask) { + for_each_cpu_mask_nr(i, cmd.mask) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 199e4e05e5d..f1685fb91fb 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c @@ -122,7 +122,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, return 0; /* notifiers */ - for_each_cpu_mask(i, policy->cpus) { + for_each_cpu_mask_nr(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } @@ -130,11 +130,11 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software * Developer's Manual, Volume 3 */ - for_each_cpu_mask(i, policy->cpus) + for_each_cpu_mask_nr(i, policy->cpus) cpufreq_p4_setdc(i, p4clockmod_table[newstate].index); /* notifiers */ - for_each_cpu_mask(i, policy->cpus) { + for_each_cpu_mask_nr(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 46d4034d9f3..06d6eea5e07 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -966,7 +966,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i freqs.old = find_khz_freq_from_fid(data->currfid); freqs.new = find_khz_freq_from_fid(fid); - for_each_cpu_mask(i, *(data->available_cores)) { + for_each_cpu_mask_nr(i, *(data->available_cores)) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } @@ -974,7 +974,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i res = transition_fid_vid(data, fid, vid); freqs.new = find_khz_freq_from_fid(data->currfid); - for_each_cpu_mask(i, *(data->available_cores)) { + for_each_cpu_mask_nr(i, *(data->available_cores)) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } @@ -997,7 +997,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); - for_each_cpu_mask(i, *(data->available_cores)) { + for_each_cpu_mask_nr(i, *(data->available_cores)) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } @@ -1005,7 +1005,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i res = transition_pstate(data, pstate); freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); - for_each_cpu_mask(i, *(data->available_cores)) { + for_each_cpu_mask_nr(i, *(data->available_cores)) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 908dd347c67..8b0dd6f2a1a 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c @@ -476,7 +476,7 @@ static int centrino_target (struct cpufreq_policy *policy, saved_mask = current->cpus_allowed; first_cpu = 1; cpus_clear(covered_cpus); - for_each_cpu_mask(j, online_policy_cpus) { + for_each_cpu_mask_nr(j, online_policy_cpus) { /* * Support for SMP systems. * Make sure we are running on CPU that wants to change freq @@ -517,7 +517,7 @@ static int centrino_target (struct cpufreq_policy *policy, dprintk("target=%dkHz old=%d new=%d msr=%04x\n", target_freq, freqs.old, freqs.new, msr); - for_each_cpu_mask(k, online_policy_cpus) { + for_each_cpu_mask_nr(k, online_policy_cpus) { freqs.cpu = k; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); @@ -540,7 +540,7 @@ static int centrino_target (struct cpufreq_policy *policy, preempt_enable(); } - for_each_cpu_mask(k, online_policy_cpus) { + for_each_cpu_mask_nr(k, online_policy_cpus) { freqs.cpu = k; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } @@ -554,7 +554,7 @@ static int centrino_target (struct cpufreq_policy *policy, */ if (!cpus_empty(covered_cpus)) { - for_each_cpu_mask(j, covered_cpus) { + for_each_cpu_mask_nr(j, covered_cpus) { set_cpus_allowed_ptr(current, &cpumask_of_cpu(j)); wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); @@ -564,7 +564,7 @@ static int centrino_target (struct cpufreq_policy *policy, tmp = freqs.new; freqs.new = freqs.old; freqs.old = tmp; - for_each_cpu_mask(j, online_policy_cpus) { + for_each_cpu_mask_nr(j, online_policy_cpus) { freqs.cpu = j; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index 1b50244b1fd..191f7263c61 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c @@ -279,7 +279,7 @@ static int speedstep_target (struct cpufreq_policy *policy, cpus_allowed = current->cpus_allowed; - for_each_cpu_mask(i, policy->cpus) { + for_each_cpu_mask_nr(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } @@ -292,7 +292,7 @@ static int speedstep_target (struct cpufreq_policy *policy, /* allow to be run on all CPUs */ set_cpus_allowed_ptr(current, &cpus_allowed); - for_each_cpu_mask(i, policy->cpus) { + for_each_cpu_mask_nr(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 26d615dcb14..bfade3301c3 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -488,7 +488,7 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) int sibling; this_leaf = CPUID4_INFO_IDX(cpu, index); - for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) { + for_each_cpu_mask_nr(sibling, this_leaf->shared_cpu_map) { sibling_leaf = CPUID4_INFO_IDX(sibling, index); cpu_clear(cpu, sibling_leaf->shared_cpu_map); } diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 7c9a813e119..88736cadbaa 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c @@ -527,7 +527,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) if (err) goto out_free; - for_each_cpu_mask(i, b->cpus) { + for_each_cpu_mask_nr(i, b->cpus) { if (i == cpu) continue; @@ -617,7 +617,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) #endif /* remove all sibling symlinks before unregistering */ - for_each_cpu_mask(i, b->cpus) { + for_each_cpu_mask_nr(i, b->cpus) { if (i == cpu) continue; diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index ef1a8dfcc52..e2838cbd2ff 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -718,7 +718,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask) return 0; } - for_each_cpu_mask(cpu, mask) { + for_each_cpu_mask_nr(cpu, mask) { cpumask_t domain, new_mask; int new_cpu; int vector, offset; @@ -739,7 +739,7 @@ next: continue; if (vector == IA32_SYSCALL_VECTOR) goto next; - for_each_cpu_mask(new_cpu, new_mask) + for_each_cpu_mask_nr(new_cpu, new_mask) if (per_cpu(vector_irq, new_cpu)[vector] != -1) goto next; /* Found one! */ @@ -749,7 +749,7 @@ next: cfg->move_in_progress = 1; cfg->old_domain = cfg->domain; } - for_each_cpu_mask(new_cpu, new_mask) + for_each_cpu_mask_nr(new_cpu, new_mask) per_cpu(vector_irq, new_cpu)[vector] = irq; cfg->vector = vector; cfg->domain = domain; @@ -781,7 +781,7 @@ static void __clear_irq_vector(int irq) vector = cfg->vector; cpus_and(mask, cfg->domain, cpu_online_map); - for_each_cpu_mask(cpu, mask) + for_each_cpu_mask_nr(cpu, mask) per_cpu(vector_irq, cpu)[vector] = -1; cfg->vector = 0; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 38988491c62..fff8ebaa554 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -487,7 +487,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) cpu_set(cpu, cpu_sibling_setup_map); if (smp_num_siblings > 1) { - for_each_cpu_mask(i, cpu_sibling_setup_map) { + for_each_cpu_mask_nr(i, cpu_sibling_setup_map) { if (c->phys_proc_id == cpu_data(i).phys_proc_id && c->cpu_core_id == cpu_data(i).cpu_core_id) { cpu_set(i, per_cpu(cpu_sibling_map, cpu)); @@ -510,7 +510,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) return; } - for_each_cpu_mask(i, cpu_sibling_setup_map) { + for_each_cpu_mask_nr(i, cpu_sibling_setup_map) { if (per_cpu(cpu_llc_id, cpu) != BAD_APICID && per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) { cpu_set(i, c->llc_shared_map); @@ -1298,7 +1298,7 @@ static void remove_siblinginfo(int cpu) int sibling; struct cpuinfo_x86 *c = &cpu_data(cpu); - for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { + for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) { cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); /*/ * last thread sibling in this cpu core going down @@ -1307,7 +1307,7 @@ static void remove_siblinginfo(int cpu) cpu_data(sibling).booted_cores--; } - for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) + for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu)) cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); cpus_clear(per_cpu(cpu_sibling_map, cpu)); cpus_clear(per_cpu(cpu_core_map, cpu)); diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 94e69000f98..7a70638797e 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -345,7 +345,7 @@ static void xen_send_IPI_mask(cpumask_t mask, enum ipi_vector vector) cpus_and(mask, mask, cpu_online_map); - for_each_cpu_mask(cpu, mask) + for_each_cpu_mask_nr(cpu, mask) xen_send_IPI_one(cpu, vector); } @@ -413,7 +413,7 @@ int xen_smp_call_function_mask(cpumask_t mask, void (*func)(void *), /* Make sure other vcpus get a chance to run if they need to. */ yield = false; - for_each_cpu_mask(cpu, mask) + for_each_cpu_mask_nr(cpu, mask) if (xen_vcpu_stolen(cpu)) yield = true; diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h index ecc80f341f3..5f7310aa3ef 100644 --- a/include/asm-x86/ipi.h +++ b/include/asm-x86/ipi.h @@ -121,7 +121,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) * - mbligh */ local_irq_save(flags); - for_each_cpu_mask(query_cpu, mask) { + for_each_cpu_mask_nr(query_cpu, mask) { __send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu), vector, APIC_DEST_PHYSICAL); } -- cgit v1.2.3-70-g09d2 From 444933c6c6e82362ba8e0da26f41a53c433d11ef Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:28 +0900 Subject: [IA64] pvops: preparation: remove extern in irq_ia64.c remove extern declaration of handle_IPI() in irq_ia64.c. Instead, declare it in asm-ia64/smp.h. Later handle_IPI() will be referenced from another file. Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/irq_ia64.c | 1 - include/asm-ia64/smp.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 5538471e8d6..c48171bc796 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -600,7 +600,6 @@ static irqreturn_t dummy_handler (int irq, void *dev_id) { BUG(); } -extern irqreturn_t handle_IPI (int irq, void *dev_id); static struct irqaction ipi_irqaction = { .handler = handle_IPI, diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h index ec5f355fb7e..2984e262fc6 100644 --- a/include/asm-ia64/smp.h +++ b/include/asm-ia64/smp.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -123,6 +124,7 @@ extern void __init smp_build_cpu_map(void); extern void __init init_smp_config (void); extern void smp_do_timer (struct pt_regs *regs); +extern irqreturn_t handle_IPI(int irq, void *dev_id); extern void smp_send_reschedule (int cpu); extern void lock_ipi_calllock(void); extern void unlock_ipi_calllock(void); -- cgit v1.2.3-70-g09d2 From 8311d21c35092aa4c4a12e0140e1ef3443489d77 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:29 +0900 Subject: [IA64] pvops: preparation: move the constants, LOAD_OFFSET, to a header file. Move the LOAD_OFFSET definition from vmlinux.lds.S into system.h. On paravirtualized environments, it is necessary to detect the execution environment. One of the solutions is the multi entry point. The multi entry point allows a boot loader to start the kernel execution from the entry point which is different from the ELF entry point. The non standard entry point will defined as the specialized elf note which contains the LMA of the entry point symbol. The constant, LOAD_OFFSET, is necessary to calculate the symbol's LMA. Move the definition into the public header file to make it available to the multi entry point support. Cc: "He, Qing" Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/vmlinux.lds.S | 1 - include/asm-ia64/system.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 5929ab10a28..5a77206c249 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -4,7 +4,6 @@ #include #include -#define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE) #include #define IVT_TEXT \ diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 26e250bfb91..0db8c9812ce 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h @@ -26,6 +26,7 @@ */ #define KERNEL_START (GATE_ADDR+__IA64_UL_CONST(0x100000000)) #define PERCPU_ADDR (-PERCPU_PAGE_SIZE) +#define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE) #ifndef __ASSEMBLY__ -- cgit v1.2.3-70-g09d2 From 90aeb169c03a96e22674741f08054023c33d595b Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:32 +0900 Subject: [IA64] pvops: introduce pv_info which describes some random info. introduce pv_info which describes some randome info about underlying execution environment. Cc: Jes Sorensen Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/Makefile | 2 ++ arch/ia64/kernel/paravirt.c | 41 ++++++++++++++++++++++++++++++ include/asm-ia64/paravirt.h | 62 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 arch/ia64/kernel/paravirt.c create mode 100644 include/asm-ia64/paravirt.h (limited to 'arch') diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 13fd10e8699..10a4ddb5b27 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -36,6 +36,8 @@ obj-$(CONFIG_PCI_MSI) += msi_ia64.o mca_recovery-y += mca_drv.o mca_drv_asm.o obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o +obj-$(CONFIG_PARAVIRT) += paravirt.o + obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) obj-y += esi_stub.o # must be in kernel proper diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c new file mode 100644 index 00000000000..d295ea5e59c --- /dev/null +++ b/arch/ia64/kernel/paravirt.c @@ -0,0 +1,41 @@ +/****************************************************************************** + * arch/ia64/kernel/paravirt.c + * + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * Yaozu (Eddie) Dong + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include + +#include +#include +#include +#include + +#include +#include + +/*************************************************************************** + * general info + */ +struct pv_info pv_info = { + .kernel_rpl = 0, + .paravirt_enabled = 0, + .name = "bare hardware" +}; diff --git a/include/asm-ia64/paravirt.h b/include/asm-ia64/paravirt.h new file mode 100644 index 00000000000..26b43342308 --- /dev/null +++ b/include/asm-ia64/paravirt.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * include/asm-ia64/paravirt.h + * + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#ifndef __ASM_PARAVIRT_H +#define __ASM_PARAVIRT_H + +#ifdef CONFIG_PARAVIRT_GUEST + +#ifndef __ASSEMBLY__ + +#include +#include + +/****************************************************************************** + * general info + */ +struct pv_info { + unsigned int kernel_rpl; + int paravirt_enabled; + const char *name; +}; + +extern struct pv_info pv_info; + +static inline int paravirt_enabled(void) +{ + return pv_info.paravirt_enabled; +} + +static inline unsigned int get_kernel_rpl(void) +{ + return pv_info.kernel_rpl; +} + +#endif /* !__ASSEMBLY__ */ + +#else +/* fallback for native case */ + +#endif /* CONFIG_PARAVIRT_GUEST */ + +#endif /* __ASM_PARAVIRT_H */ -- cgit v1.2.3-70-g09d2 From 3e0879deb700f322f6c81ab34f056fc72d15ec02 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:33 +0900 Subject: [IA64] pvops: add an early setup hook for pv_ops. This patch adds a setup hook in the very early boot sequence before start_kernel() to initialize paravirtualization stuff. The hook will be set by each pv loader code or by using multi entry point. Signed-off-by: Qing He Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/head.S | 41 +++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/paravirt.h | 3 +++ 2 files changed, 44 insertions(+) (limited to 'arch') diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index ddeab4e36fd..db540e58c78 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -26,11 +26,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #ifdef CONFIG_HOTPLUG_CPU #define SAL_PSR_BITS_TO_SET \ @@ -367,6 +370,44 @@ start_ap: ;; (isBP) st8 [r2]=r28 // save the address of the boot param area passed by the bootloader +#ifdef CONFIG_PARAVIRT + + movl r14=hypervisor_setup_hooks + movl r15=hypervisor_type + mov r16=num_hypervisor_hooks + ;; + ld8 r2=[r15] + ;; + cmp.ltu p7,p0=r2,r16 // array size check + shladd r8=r2,3,r14 + ;; +(p7) ld8 r9=[r8] + ;; +(p7) mov b1=r9 +(p7) cmp.ne.unc p7,p0=r9,r0 // no actual branch to NULL + ;; +(p7) br.call.sptk.many rp=b1 + + __INITDATA + +default_setup_hook = 0 // Currently nothing needs to be done. + + .weak xen_setup_hook + + .global hypervisor_type +hypervisor_type: + data8 PARAVIRT_HYPERVISOR_TYPE_DEFAULT + + // must have the same order with PARAVIRT_HYPERVISOR_TYPE_xxx + +hypervisor_setup_hooks: + data8 default_setup_hook + data8 xen_setup_hook +num_hypervisor_hooks = (. - hypervisor_setup_hooks) / 8 + .previous + +#endif + #ifdef CONFIG_SMP (isAP) br.call.sptk.many rp=start_secondary .ret0: diff --git a/include/asm-ia64/paravirt.h b/include/asm-ia64/paravirt.h index 26b43342308..1032b216aea 100644 --- a/include/asm-ia64/paravirt.h +++ b/include/asm-ia64/paravirt.h @@ -26,6 +26,9 @@ #ifdef CONFIG_PARAVIRT_GUEST +#define PARAVIRT_HYPERVISOR_TYPE_DEFAULT 0 +#define PARAVIRT_HYPERVISOR_TYPE_XEN 1 + #ifndef __ASSEMBLY__ #include -- cgit v1.2.3-70-g09d2 From 1ff730b52f0c3e4e3846c3ff345c5526b2633ba9 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:34 +0900 Subject: [IA64] pvops: introduce pv_cpu_ops to paravirtualize privileged instructions. introduce pv_cpu_ops to paravirtualize privleged instructions which are defined by ia64 intrinsics. make them indirect C function calls by introducing function tables, pv_cpu_ops. Signed-off-by: Yaozu (Eddie) Dong Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/paravirt.c | 247 +++++++++++++++++++++++++++++++++++++ include/asm-ia64/Kbuild | 2 +- include/asm-ia64/gcc_intrin.h | 24 ++-- include/asm-ia64/intel_intrin.h | 41 +++--- include/asm-ia64/intrinsics.h | 62 ++++++++-- include/asm-ia64/paravirt_privop.h | 91 ++++++++++++++ 6 files changed, 425 insertions(+), 42 deletions(-) create mode 100644 include/asm-ia64/paravirt_privop.h (limited to 'arch') diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index d295ea5e59c..e5482bb6841 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -39,3 +40,249 @@ struct pv_info pv_info = { .paravirt_enabled = 0, .name = "bare hardware" }; + +/*************************************************************************** + * pv_cpu_ops + * intrinsics hooks. + */ + +/* ia64_native_xxx are macros so that we have to make them real functions */ + +#define DEFINE_VOID_FUNC1(name) \ + static void \ + ia64_native_ ## name ## _func(unsigned long arg) \ + { \ + ia64_native_ ## name(arg); \ + } \ + +#define DEFINE_VOID_FUNC2(name) \ + static void \ + ia64_native_ ## name ## _func(unsigned long arg0, \ + unsigned long arg1) \ + { \ + ia64_native_ ## name(arg0, arg1); \ + } \ + +#define DEFINE_FUNC0(name) \ + static unsigned long \ + ia64_native_ ## name ## _func(void) \ + { \ + return ia64_native_ ## name(); \ + } + +#define DEFINE_FUNC1(name, type) \ + static unsigned long \ + ia64_native_ ## name ## _func(type arg) \ + { \ + return ia64_native_ ## name(arg); \ + } \ + +DEFINE_VOID_FUNC1(fc); +DEFINE_VOID_FUNC1(intrin_local_irq_restore); + +DEFINE_VOID_FUNC2(ptcga); +DEFINE_VOID_FUNC2(set_rr); + +DEFINE_FUNC0(get_psr_i); + +DEFINE_FUNC1(thash, unsigned long); +DEFINE_FUNC1(get_cpuid, int); +DEFINE_FUNC1(get_pmd, int); +DEFINE_FUNC1(get_rr, unsigned long); + +static void +ia64_native_ssm_i_func(void) +{ + ia64_native_ssm(IA64_PSR_I); +} + +static void +ia64_native_rsm_i_func(void) +{ + ia64_native_rsm(IA64_PSR_I); +} + +static void +ia64_native_set_rr0_to_rr4_func(unsigned long val0, unsigned long val1, + unsigned long val2, unsigned long val3, + unsigned long val4) +{ + ia64_native_set_rr0_to_rr4(val0, val1, val2, val3, val4); +} + +#define CASE_GET_REG(id) \ + case _IA64_REG_ ## id: \ + res = ia64_native_getreg(_IA64_REG_ ## id); \ + break; +#define CASE_GET_AR(id) CASE_GET_REG(AR_ ## id) +#define CASE_GET_CR(id) CASE_GET_REG(CR_ ## id) + +unsigned long +ia64_native_getreg_func(int regnum) +{ + unsigned long res = -1; + switch (regnum) { + CASE_GET_REG(GP); + CASE_GET_REG(IP); + CASE_GET_REG(PSR); + CASE_GET_REG(TP); + CASE_GET_REG(SP); + + CASE_GET_AR(KR0); + CASE_GET_AR(KR1); + CASE_GET_AR(KR2); + CASE_GET_AR(KR3); + CASE_GET_AR(KR4); + CASE_GET_AR(KR5); + CASE_GET_AR(KR6); + CASE_GET_AR(KR7); + CASE_GET_AR(RSC); + CASE_GET_AR(BSP); + CASE_GET_AR(BSPSTORE); + CASE_GET_AR(RNAT); + CASE_GET_AR(FCR); + CASE_GET_AR(EFLAG); + CASE_GET_AR(CSD); + CASE_GET_AR(SSD); + CASE_GET_AR(CFLAG); + CASE_GET_AR(FSR); + CASE_GET_AR(FIR); + CASE_GET_AR(FDR); + CASE_GET_AR(CCV); + CASE_GET_AR(UNAT); + CASE_GET_AR(FPSR); + CASE_GET_AR(ITC); + CASE_GET_AR(PFS); + CASE_GET_AR(LC); + CASE_GET_AR(EC); + + CASE_GET_CR(DCR); + CASE_GET_CR(ITM); + CASE_GET_CR(IVA); + CASE_GET_CR(PTA); + CASE_GET_CR(IPSR); + CASE_GET_CR(ISR); + CASE_GET_CR(IIP); + CASE_GET_CR(IFA); + CASE_GET_CR(ITIR); + CASE_GET_CR(IIPA); + CASE_GET_CR(IFS); + CASE_GET_CR(IIM); + CASE_GET_CR(IHA); + CASE_GET_CR(LID); + CASE_GET_CR(IVR); + CASE_GET_CR(TPR); + CASE_GET_CR(EOI); + CASE_GET_CR(IRR0); + CASE_GET_CR(IRR1); + CASE_GET_CR(IRR2); + CASE_GET_CR(IRR3); + CASE_GET_CR(ITV); + CASE_GET_CR(PMV); + CASE_GET_CR(CMCV); + CASE_GET_CR(LRR0); + CASE_GET_CR(LRR1); + + default: + printk(KERN_CRIT "wrong_getreg %d\n", regnum); + break; + } + return res; +} + +#define CASE_SET_REG(id) \ + case _IA64_REG_ ## id: \ + ia64_native_setreg(_IA64_REG_ ## id, val); \ + break; +#define CASE_SET_AR(id) CASE_SET_REG(AR_ ## id) +#define CASE_SET_CR(id) CASE_SET_REG(CR_ ## id) + +void +ia64_native_setreg_func(int regnum, unsigned long val) +{ + switch (regnum) { + case _IA64_REG_PSR_L: + ia64_native_setreg(_IA64_REG_PSR_L, val); + ia64_dv_serialize_data(); + break; + CASE_SET_REG(SP); + CASE_SET_REG(GP); + + CASE_SET_AR(KR0); + CASE_SET_AR(KR1); + CASE_SET_AR(KR2); + CASE_SET_AR(KR3); + CASE_SET_AR(KR4); + CASE_SET_AR(KR5); + CASE_SET_AR(KR6); + CASE_SET_AR(KR7); + CASE_SET_AR(RSC); + CASE_SET_AR(BSP); + CASE_SET_AR(BSPSTORE); + CASE_SET_AR(RNAT); + CASE_SET_AR(FCR); + CASE_SET_AR(EFLAG); + CASE_SET_AR(CSD); + CASE_SET_AR(SSD); + CASE_SET_AR(CFLAG); + CASE_SET_AR(FSR); + CASE_SET_AR(FIR); + CASE_SET_AR(FDR); + CASE_SET_AR(CCV); + CASE_SET_AR(UNAT); + CASE_SET_AR(FPSR); + CASE_SET_AR(ITC); + CASE_SET_AR(PFS); + CASE_SET_AR(LC); + CASE_SET_AR(EC); + + CASE_SET_CR(DCR); + CASE_SET_CR(ITM); + CASE_SET_CR(IVA); + CASE_SET_CR(PTA); + CASE_SET_CR(IPSR); + CASE_SET_CR(ISR); + CASE_SET_CR(IIP); + CASE_SET_CR(IFA); + CASE_SET_CR(ITIR); + CASE_SET_CR(IIPA); + CASE_SET_CR(IFS); + CASE_SET_CR(IIM); + CASE_SET_CR(IHA); + CASE_SET_CR(LID); + CASE_SET_CR(IVR); + CASE_SET_CR(TPR); + CASE_SET_CR(EOI); + CASE_SET_CR(IRR0); + CASE_SET_CR(IRR1); + CASE_SET_CR(IRR2); + CASE_SET_CR(IRR3); + CASE_SET_CR(ITV); + CASE_SET_CR(PMV); + CASE_SET_CR(CMCV); + CASE_SET_CR(LRR0); + CASE_SET_CR(LRR1); + default: + printk(KERN_CRIT "wrong setreg %d\n", regnum); + break; + } +} + +struct pv_cpu_ops pv_cpu_ops = { + .fc = ia64_native_fc_func, + .thash = ia64_native_thash_func, + .get_cpuid = ia64_native_get_cpuid_func, + .get_pmd = ia64_native_get_pmd_func, + .ptcga = ia64_native_ptcga_func, + .get_rr = ia64_native_get_rr_func, + .set_rr = ia64_native_set_rr_func, + .set_rr0_to_rr4 = ia64_native_set_rr0_to_rr4_func, + .ssm_i = ia64_native_ssm_i_func, + .getreg = ia64_native_getreg_func, + .setreg = ia64_native_setreg_func, + .rsm_i = ia64_native_rsm_i_func, + .get_psr_i = ia64_native_get_psr_i_func, + .intrin_local_irq_restore + = ia64_native_intrin_local_irq_restore_func, +}; +EXPORT_SYMBOL(pv_cpu_ops); diff --git a/include/asm-ia64/Kbuild b/include/asm-ia64/Kbuild index eb24a3f47ca..ccbe8ae47a6 100644 --- a/include/asm-ia64/Kbuild +++ b/include/asm-ia64/Kbuild @@ -5,12 +5,12 @@ header-y += fpu.h header-y += fpswa.h header-y += ia64regs.h header-y += intel_intrin.h -header-y += intrinsics.h header-y += perfmon_default_smpl.h header-y += ptrace_offsets.h header-y += rse.h header-y += ucontext.h unifdef-y += gcc_intrin.h +unifdef-y += intrinsics.h unifdef-y += perfmon.h unifdef-y += ustack.h diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h index 2fe292c275f..0f5b5592175 100644 --- a/include/asm-ia64/gcc_intrin.h +++ b/include/asm-ia64/gcc_intrin.h @@ -32,7 +32,7 @@ extern void ia64_bad_param_for_getreg (void); register unsigned long ia64_r13 asm ("r13") __used; #endif -#define ia64_setreg(regnum, val) \ +#define ia64_native_setreg(regnum, val) \ ({ \ switch (regnum) { \ case _IA64_REG_PSR_L: \ @@ -61,7 +61,7 @@ register unsigned long ia64_r13 asm ("r13") __used; } \ }) -#define ia64_getreg(regnum) \ +#define ia64_native_getreg(regnum) \ ({ \ __u64 ia64_intri_res; \ \ @@ -385,7 +385,7 @@ register unsigned long ia64_r13 asm ("r13") __used; #define ia64_invala() asm volatile ("invala" ::: "memory") -#define ia64_thash(addr) \ +#define ia64_native_thash(addr) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \ @@ -438,10 +438,10 @@ register unsigned long ia64_r13 asm ("r13") __used; #define ia64_set_pmd(index, val) \ asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory") -#define ia64_set_rr(index, val) \ +#define ia64_native_set_rr(index, val) \ asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory"); -#define ia64_get_cpuid(index) \ +#define ia64_native_get_cpuid(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index)); \ @@ -477,33 +477,33 @@ register unsigned long ia64_r13 asm ("r13") __used; }) -#define ia64_get_pmd(index) \ +#define ia64_native_get_pmd(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index)); \ ia64_intri_res; \ }) -#define ia64_get_rr(index) \ +#define ia64_native_get_rr(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index)); \ ia64_intri_res; \ }) -#define ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory") +#define ia64_native_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory") #define ia64_sync_i() asm volatile (";; sync.i" ::: "memory") -#define ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory") -#define ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory") +#define ia64_native_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory") +#define ia64_native_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory") #define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory") #define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory") #define ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr)) -#define ia64_ptcga(addr, size) \ +#define ia64_native_ptcga(addr, size) \ do { \ asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory"); \ ia64_dv_serialize_data(); \ @@ -608,7 +608,7 @@ do { \ } \ }) -#define ia64_intrin_local_irq_restore(x) \ +#define ia64_native_intrin_local_irq_restore(x) \ do { \ asm volatile (";; cmp.ne p6,p7=%0,r0;;" \ "(p6) ssm psr.i;" \ diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h index a520d103d80..53cec577558 100644 --- a/include/asm-ia64/intel_intrin.h +++ b/include/asm-ia64/intel_intrin.h @@ -16,8 +16,8 @@ * intrinsic */ -#define ia64_getreg __getReg -#define ia64_setreg __setReg +#define ia64_native_getreg __getReg +#define ia64_native_setreg __setReg #define ia64_hint __hint #define ia64_hint_pause __hint_pause @@ -39,10 +39,10 @@ #define ia64_invala_fr __invala_fr #define ia64_nop __nop #define ia64_sum __sum -#define ia64_ssm __ssm +#define ia64_native_ssm __ssm #define ia64_rum __rum -#define ia64_rsm __rsm -#define ia64_fc __fc +#define ia64_native_rsm __rsm +#define ia64_native_fc __fc #define ia64_ldfs __ldfs #define ia64_ldfd __ldfd @@ -88,16 +88,17 @@ __setIndReg(_IA64_REG_INDR_PMC, index, val) #define ia64_set_pmd(index, val) \ __setIndReg(_IA64_REG_INDR_PMD, index, val) -#define ia64_set_rr(index, val) \ +#define ia64_native_set_rr(index, val) \ __setIndReg(_IA64_REG_INDR_RR, index, val) -#define ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index) -#define __ia64_get_dbr(index) __getIndReg(_IA64_REG_INDR_DBR, index) -#define ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index) -#define ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index) -#define ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index) -#define ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index) -#define ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index) +#define ia64_native_get_cpuid(index) \ + __getIndReg(_IA64_REG_INDR_CPUID, index) +#define __ia64_get_dbr(index) __getIndReg(_IA64_REG_INDR_DBR, index) +#define ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index) +#define ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index) +#define ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index) +#define ia64_native_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index) +#define ia64_native_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index) #define ia64_srlz_d __dsrlz #define ia64_srlz_i __isrlz @@ -119,16 +120,16 @@ #define ia64_ld8_acq __ld8_acq #define ia64_sync_i __synci -#define ia64_thash __thash -#define ia64_ttag __ttag +#define ia64_native_thash __thash +#define ia64_native_ttag __ttag #define ia64_itcd __itcd #define ia64_itci __itci #define ia64_itrd __itrd #define ia64_itri __itri #define ia64_ptce __ptce #define ia64_ptcl __ptcl -#define ia64_ptcg __ptcg -#define ia64_ptcga __ptcga +#define ia64_native_ptcg __ptcg +#define ia64_native_ptcga __ptcga #define ia64_ptri __ptri #define ia64_ptrd __ptrd #define ia64_dep_mi _m64_dep_mi @@ -145,13 +146,13 @@ #define ia64_lfetch_fault __lfetch_fault #define ia64_lfetch_fault_excl __lfetch_fault_excl -#define ia64_intrin_local_irq_restore(x) \ +#define ia64_native_intrin_local_irq_restore(x) \ do { \ if ((x) != 0) { \ - ia64_ssm(IA64_PSR_I); \ + ia64_native_ssm(IA64_PSR_I); \ ia64_srlz_d(); \ } else { \ - ia64_rsm(IA64_PSR_I); \ + ia64_native_rsm(IA64_PSR_I); \ } \ } while (0) diff --git a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h index a3b96892f83..47d686dba1e 100644 --- a/include/asm-ia64/intrinsics.h +++ b/include/asm-ia64/intrinsics.h @@ -18,15 +18,15 @@ # include #endif -#define ia64_get_psr_i() (ia64_getreg(_IA64_REG_PSR) & IA64_PSR_I) - -#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \ -do { \ - ia64_set_rr(0x0000000000000000UL, (val0)); \ - ia64_set_rr(0x2000000000000000UL, (val1)); \ - ia64_set_rr(0x4000000000000000UL, (val2)); \ - ia64_set_rr(0x6000000000000000UL, (val3)); \ - ia64_set_rr(0x8000000000000000UL, (val4)); \ +#define ia64_native_get_psr_i() (ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I) + +#define ia64_native_set_rr0_to_rr4(val0, val1, val2, val3, val4) \ +do { \ + ia64_native_set_rr(0x0000000000000000UL, (val0)); \ + ia64_native_set_rr(0x2000000000000000UL, (val1)); \ + ia64_native_set_rr(0x4000000000000000UL, (val2)); \ + ia64_native_set_rr(0x6000000000000000UL, (val3)); \ + ia64_native_set_rr(0x8000000000000000UL, (val4)); \ } while (0) /* @@ -194,4 +194,48 @@ extern long ia64_cmpxchg_called_with_bad_pointer (void); #endif /* !CONFIG_IA64_DEBUG_CMPXCHG */ #endif + +#ifdef __KERNEL__ +#include +#endif + +#ifndef __ASSEMBLY__ +#if defined(CONFIG_PARAVIRT) && defined(__KERNEL__) +#define IA64_INTRINSIC_API(name) pv_cpu_ops.name +#define IA64_INTRINSIC_MACRO(name) paravirt_ ## name +#else +#define IA64_INTRINSIC_API(name) ia64_native_ ## name +#define IA64_INTRINSIC_MACRO(name) ia64_native_ ## name +#endif + +/************************************************/ +/* Instructions paravirtualized for correctness */ +/************************************************/ +/* fc, thash, get_cpuid, get_pmd, get_eflags, set_eflags */ +/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" + * is not currently used (though it may be in a long-format VHPT system!) + */ +#define ia64_fc IA64_INTRINSIC_API(fc) +#define ia64_thash IA64_INTRINSIC_API(thash) +#define ia64_get_cpuid IA64_INTRINSIC_API(get_cpuid) +#define ia64_get_pmd IA64_INTRINSIC_API(get_pmd) + + +/************************************************/ +/* Instructions paravirtualized for performance */ +/************************************************/ +#define ia64_ssm IA64_INTRINSIC_MACRO(ssm) +#define ia64_rsm IA64_INTRINSIC_MACRO(rsm) +#define ia64_getreg IA64_INTRINSIC_API(getreg) +#define ia64_setreg IA64_INTRINSIC_API(setreg) +#define ia64_set_rr IA64_INTRINSIC_API(set_rr) +#define ia64_get_rr IA64_INTRINSIC_API(get_rr) +#define ia64_ptcga IA64_INTRINSIC_API(ptcga) +#define ia64_get_psr_i IA64_INTRINSIC_API(get_psr_i) +#define ia64_intrin_local_irq_restore \ + IA64_INTRINSIC_API(intrin_local_irq_restore) +#define ia64_set_rr0_to_rr4 IA64_INTRINSIC_API(set_rr0_to_rr4) + +#endif /* !__ASSEMBLY__ */ + #endif /* _ASM_IA64_INTRINSICS_H */ diff --git a/include/asm-ia64/paravirt_privop.h b/include/asm-ia64/paravirt_privop.h new file mode 100644 index 00000000000..7b133ae86df --- /dev/null +++ b/include/asm-ia64/paravirt_privop.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * include/asm-ia64/paravirt_privops.h + * + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ASM_IA64_PARAVIRT_PRIVOP_H +#define _ASM_IA64_PARAVIRT_PRIVOP_H + +#ifdef CONFIG_PARAVIRT + +#ifndef __ASSEMBLY__ + +#include +#include /* for IA64_PSR_I */ + +/****************************************************************************** + * replacement of intrinsics operations. + */ + +struct pv_cpu_ops { + void (*fc)(unsigned long addr); + unsigned long (*thash)(unsigned long addr); + unsigned long (*get_cpuid)(int index); + unsigned long (*get_pmd)(int index); + unsigned long (*getreg)(int reg); + void (*setreg)(int reg, unsigned long val); + void (*ptcga)(unsigned long addr, unsigned long size); + unsigned long (*get_rr)(unsigned long index); + void (*set_rr)(unsigned long index, unsigned long val); + void (*set_rr0_to_rr4)(unsigned long val0, unsigned long val1, + unsigned long val2, unsigned long val3, + unsigned long val4); + void (*ssm_i)(void); + void (*rsm_i)(void); + unsigned long (*get_psr_i)(void); + void (*intrin_local_irq_restore)(unsigned long flags); +}; + +extern struct pv_cpu_ops pv_cpu_ops; + +extern void ia64_native_setreg_func(int regnum, unsigned long val); +extern unsigned long ia64_native_getreg_func(int regnum); + +/************************************************/ +/* Instructions paravirtualized for performance */ +/************************************************/ + +/* mask for ia64_native_ssm/rsm() must be constant.("i" constraing). + * static inline function doesn't satisfy it. */ +#define paravirt_ssm(mask) \ + do { \ + if ((mask) == IA64_PSR_I) \ + pv_cpu_ops.ssm_i(); \ + else \ + ia64_native_ssm(mask); \ + } while (0) + +#define paravirt_rsm(mask) \ + do { \ + if ((mask) == IA64_PSR_I) \ + pv_cpu_ops.rsm_i(); \ + else \ + ia64_native_rsm(mask); \ + } while (0) + +#endif /* __ASSEMBLY__ */ + +#else + +/* fallback for native case */ + +#endif /* CONFIG_PARAVIRT */ + +#endif /* _ASM_IA64_PARAVIRT_PRIVOP_H */ -- cgit v1.2.3-70-g09d2 From 1e39d80a5957eab9dfdd7490d5c5cee272c34aa7 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:35 +0900 Subject: [IA64] pvops: preparation for paravirtulization of hand written assembly code. Preparation for paravirtualization of hand written assembly code. They are paravirtualized by single source code and compiled multi times. To tell those files for target (including native), add one defines. Cc: "Dong, Eddie" Cc: Keith Owens Cc: tgingold@free.fr Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 10a4ddb5b27..8b2524293eb 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -72,3 +72,12 @@ $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE # We must build gate.so before we can assemble it. # Note: kbuild does not track this dependency due to usage of .incbin $(obj)/gate-data.o: $(obj)/gate.so + +# +# native ivt.S and entry.S +# +ASM_PARAVIRT_OBJS = ivt.o entry.o +define paravirtualized_native +AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE +endef +$(foreach obj,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_native,$(obj)))) -- cgit v1.2.3-70-g09d2 From 02e32e36f42f8ea7ee6060d02f2d69ad5bad6d50 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:37 +0900 Subject: [IA64] pvops: paravirtualize minstate.h. paravirtualize minstate.h which are hand written assembly code. They include sensitive or performance critical privileged instructions. So that they are appropriate for paravirtualization. Cc: Keith Owens Cc: Akio Takebe Signed-off-by: Yaozu (Eddie) Dong Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/minstate.h | 13 +++++++------ arch/ia64/kernel/paravirt_inst.h | 29 +++++++++++++++++++++++++++++ include/asm-ia64/native/inst.h | 2 ++ 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 arch/ia64/kernel/paravirt_inst.h (limited to 'arch') diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h index 74b6d670aae..292e214a3b8 100644 --- a/arch/ia64/kernel/minstate.h +++ b/arch/ia64/kernel/minstate.h @@ -2,6 +2,7 @@ #include #include "entry.h" +#include "paravirt_inst.h" #ifdef CONFIG_VIRT_CPU_ACCOUNTING /* read ar.itc in advance, and use it before leaving bank 0 */ @@ -43,16 +44,16 @@ * Note that psr.ic is NOT turned on by this macro. This is so that * we can pass interruption state as arguments to a handler. */ -#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA,WORKAROUND) \ +#define IA64_NATIVE_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND) \ mov r16=IA64_KR(CURRENT); /* M */ \ mov r27=ar.rsc; /* M */ \ mov r20=r1; /* A */ \ mov r25=ar.unat; /* M */ \ - mov r29=cr.ipsr; /* M */ \ + MOV_FROM_IPSR(p0,r29); /* M */ \ mov r26=ar.pfs; /* I */ \ - mov r28=cr.iip; /* M */ \ + MOV_FROM_IIP(r28); /* M */ \ mov r21=ar.fpsr; /* M */ \ - COVER; /* B;; (or nothing) */ \ + __COVER; /* B;; (or nothing) */ \ ;; \ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \ ;; \ @@ -244,6 +245,6 @@ 1: \ .pred.rel "mutex", pKStk, pUStk -#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs, , RSE_WORKAROUND) -#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND) +#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(COVER, mov r30=cr.ifs, , RSE_WORKAROUND) +#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(COVER, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND) #define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, , ) diff --git a/arch/ia64/kernel/paravirt_inst.h b/arch/ia64/kernel/paravirt_inst.h new file mode 100644 index 00000000000..5cad6fb2ed1 --- /dev/null +++ b/arch/ia64/kernel/paravirt_inst.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirt_inst.h + * + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef __IA64_ASM_PARAVIRTUALIZED_XEN +#include +#include +#else +#include +#endif + diff --git a/include/asm-ia64/native/inst.h b/include/asm-ia64/native/inst.h index 2a50b70b969..f1072ace0cf 100644 --- a/include/asm-ia64/native/inst.h +++ b/include/asm-ia64/native/inst.h @@ -20,6 +20,8 @@ * */ +#define DO_SAVE_MIN IA64_NATIVE_DO_SAVE_MIN + #ifdef CONFIG_PARAVIRT_GUEST_ASM_CLOBBER_CHECK # define PARAVIRT_POISON 0xdeadbeefbaadf00d # define CLOBBER(clob) \ -- cgit v1.2.3-70-g09d2 From 498c5170472ff0c03a29d22dbd33225a0be038f4 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:38 +0900 Subject: [IA64] pvops: paravirtualize ivt.S paravirtualize ivt.S which implements fault handler in hand written assembly code. They includes sensitive or performance critical privileged instructions. So they need paravirtualization. Cc: Keith Owens Cc: tgingold@free.fr Cc: Akio Takebe Signed-off-by: Yaozu (Eddie) Dong Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/ivt.S | 249 ++++++++++++++++++++++++------------------------- 1 file changed, 122 insertions(+), 127 deletions(-) (limited to 'arch') diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 80b44ea052d..23749ed3cf0 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -12,6 +12,14 @@ * * 00/08/23 Asit Mallick TLB handling for SMP * 00/12/20 David Mosberger-Tang DTLB/ITLB handler now uses virtual PT. + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer + * Xen paravirtualization + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * pv_ops. + * Yaozu (Eddie) Dong */ /* * This file defines the interruption vector table used by the CPU. @@ -102,13 +110,13 @@ ENTRY(vhpt_miss) * - the faulting virtual address uses unimplemented address bits * - the faulting virtual address has no valid page table mapping */ - mov r16=cr.ifa // get address that caused the TLB miss + MOV_FROM_IFA(r16) // get address that caused the TLB miss #ifdef CONFIG_HUGETLB_PAGE movl r18=PAGE_SHIFT - mov r25=cr.itir + MOV_FROM_ITIR(r25) #endif ;; - rsm psr.dt // use physical addressing for data + RSM_PSR_DT // use physical addressing for data mov r31=pr // save the predicate registers mov r19=IA64_KR(PT_BASE) // get page table base address shl r21=r16,3 // shift bit 60 into sign bit @@ -168,21 +176,21 @@ ENTRY(vhpt_miss) dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr) ;; (p7) ld8 r18=[r21] // read *pte - mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss + MOV_FROM_ISR(r19) // cr.isr bit 32 tells us if this is an insn miss ;; (p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared? - mov r22=cr.iha // get the VHPT address that caused the TLB miss + MOV_FROM_IHA(r22) // get the VHPT address that caused the TLB miss ;; // avoid RAW on p7 (p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss? dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address ;; -(p10) itc.i r18 // insert the instruction TLB entry -(p11) itc.d r18 // insert the data TLB entry + ITC_I_AND_D(p10, p11, r18, r24) // insert the instruction TLB entry and + // insert the data TLB entry (p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault) - mov cr.ifa=r22 + MOV_TO_IFA(r22, r24) #ifdef CONFIG_HUGETLB_PAGE -(p8) mov cr.itir=r25 // change to default page-size for VHPT + MOV_TO_ITIR(p8, r25, r24) // change to default page-size for VHPT #endif /* @@ -192,7 +200,7 @@ ENTRY(vhpt_miss) */ adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23 ;; -(p7) itc.d r24 + ITC_D(p7, r24, r25) ;; #ifdef CONFIG_SMP /* @@ -234,7 +242,7 @@ ENTRY(vhpt_miss) #endif mov pr=r31,-1 // restore predicate registers - rfi + RFI END(vhpt_miss) .org ia64_ivt+0x400 @@ -248,11 +256,11 @@ ENTRY(itlb_miss) * mode, walk the page table, and then re-execute the PTE read and * go on normally after that. */ - mov r16=cr.ifa // get virtual address + MOV_FROM_IFA(r16) // get virtual address mov r29=b0 // save b0 mov r31=pr // save predicates .itlb_fault: - mov r17=cr.iha // get virtual address of PTE + MOV_FROM_IHA(r17) // get virtual address of PTE movl r30=1f // load nested fault continuation point ;; 1: ld8 r18=[r17] // read *pte @@ -261,7 +269,7 @@ ENTRY(itlb_miss) tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared? (p6) br.cond.spnt page_fault ;; - itc.i r18 + ITC_I(p0, r18, r19) ;; #ifdef CONFIG_SMP /* @@ -278,7 +286,7 @@ ENTRY(itlb_miss) (p7) ptc.l r16,r20 #endif mov pr=r31,-1 - rfi + RFI END(itlb_miss) .org ia64_ivt+0x0800 @@ -292,11 +300,11 @@ ENTRY(dtlb_miss) * mode, walk the page table, and then re-execute the PTE read and * go on normally after that. */ - mov r16=cr.ifa // get virtual address + MOV_FROM_IFA(r16) // get virtual address mov r29=b0 // save b0 mov r31=pr // save predicates dtlb_fault: - mov r17=cr.iha // get virtual address of PTE + MOV_FROM_IHA(r17) // get virtual address of PTE movl r30=1f // load nested fault continuation point ;; 1: ld8 r18=[r17] // read *pte @@ -305,7 +313,7 @@ dtlb_fault: tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared? (p6) br.cond.spnt page_fault ;; - itc.d r18 + ITC_D(p0, r18, r19) ;; #ifdef CONFIG_SMP /* @@ -322,7 +330,7 @@ dtlb_fault: (p7) ptc.l r16,r20 #endif mov pr=r31,-1 - rfi + RFI END(dtlb_miss) .org ia64_ivt+0x0c00 @@ -330,9 +338,9 @@ END(dtlb_miss) // 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19) ENTRY(alt_itlb_miss) DBG_FAULT(3) - mov r16=cr.ifa // get address that caused the TLB miss + MOV_FROM_IFA(r16) // get address that caused the TLB miss movl r17=PAGE_KERNEL - mov r21=cr.ipsr + MOV_FROM_IPSR(p0, r21) movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) mov r31=pr ;; @@ -341,9 +349,9 @@ ENTRY(alt_itlb_miss) ;; cmp.gt p8,p0=6,r22 // user mode ;; -(p8) thash r17=r16 + THASH(p8, r17, r16, r23) ;; -(p8) mov cr.iha=r17 + MOV_TO_IHA(p8, r17, r23) (p8) mov r29=b0 // save b0 (p8) br.cond.dptk .itlb_fault #endif @@ -358,9 +366,9 @@ ENTRY(alt_itlb_miss) or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6 (p8) br.cond.spnt page_fault ;; - itc.i r19 // insert the TLB entry + ITC_I(p0, r19, r18) // insert the TLB entry mov pr=r31,-1 - rfi + RFI END(alt_itlb_miss) .org ia64_ivt+0x1000 @@ -368,11 +376,11 @@ END(alt_itlb_miss) // 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46) ENTRY(alt_dtlb_miss) DBG_FAULT(4) - mov r16=cr.ifa // get address that caused the TLB miss + MOV_FROM_IFA(r16) // get address that caused the TLB miss movl r17=PAGE_KERNEL - mov r20=cr.isr + MOV_FROM_ISR(r20) movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) - mov r21=cr.ipsr + MOV_FROM_IPSR(p0, r21) mov r31=pr mov r24=PERCPU_ADDR ;; @@ -381,9 +389,9 @@ ENTRY(alt_dtlb_miss) ;; cmp.gt p8,p0=6,r22 // access to region 0-5 ;; -(p8) thash r17=r16 + THASH(p8, r17, r16, r25) ;; -(p8) mov cr.iha=r17 + MOV_TO_IHA(p8, r17, r25) (p8) mov r29=b0 // save b0 (p8) br.cond.dptk dtlb_fault #endif @@ -402,7 +410,7 @@ ENTRY(alt_dtlb_miss) tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on? ;; (p10) sub r19=r19,r26 -(p10) mov cr.itir=r25 + MOV_TO_ITIR(p10, r25, r24) cmp.ne p8,p0=r0,r23 (p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field (p12) dep r17=-1,r17,4,1 // set ma=UC for region 6 addr @@ -411,11 +419,11 @@ ENTRY(alt_dtlb_miss) dep r21=-1,r21,IA64_PSR_ED_BIT,1 ;; or r19=r19,r17 // insert PTE control bits into r19 -(p6) mov cr.ipsr=r21 + MOV_TO_IPSR(p6, r21, r24) ;; -(p7) itc.d r19 // insert the TLB entry + ITC_D(p7, r19, r18) // insert the TLB entry mov pr=r31,-1 - rfi + RFI END(alt_dtlb_miss) .org ia64_ivt+0x1400 @@ -444,10 +452,10 @@ ENTRY(nested_dtlb_miss) * * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared) */ - rsm psr.dt // switch to using physical data addressing + RSM_PSR_DT // switch to using physical data addressing mov r19=IA64_KR(PT_BASE) // get the page table base address shl r21=r16,3 // shift bit 60 into sign bit - mov r18=cr.itir + MOV_FROM_ITIR(r18) ;; shr.u r17=r16,61 // get the region number into r17 extr.u r18=r18,2,6 // get the faulting page size @@ -510,21 +518,15 @@ END(ikey_miss) //----------------------------------------------------------------------------------- // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) ENTRY(page_fault) - ssm psr.dt - ;; - srlz.i + SSM_PSR_DT_AND_SRLZ_I ;; SAVE_MIN_WITH_COVER alloc r15=ar.pfs,0,0,3,0 - mov out0=cr.ifa - mov out1=cr.isr + MOV_FROM_IFA(out0) + MOV_FROM_ISR(out1) + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3) adds r3=8,r2 // set up second base pointer - ;; - ssm psr.ic | PSR_DEFAULT_BITS - ;; - srlz.i // guarantee that interruption collectin is on - ;; -(p15) ssm psr.i // restore psr.i + SSM_PSR_I(p15, p15, r14) // restore psr.i movl r14=ia64_leave_kernel ;; SAVE_REST @@ -556,10 +558,10 @@ ENTRY(dirty_bit) * page table TLB entry isn't present, we take a nested TLB miss hit where we look * up the physical address of the L3 PTE and then continue at label 1 below. */ - mov r16=cr.ifa // get the address that caused the fault + MOV_FROM_IFA(r16) // get the address that caused the fault movl r30=1f // load continuation point in case of nested fault ;; - thash r17=r16 // compute virtual address of L3 PTE + THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE mov r29=b0 // save b0 in case of nested fault mov r31=pr // save pr #ifdef CONFIG_SMP @@ -576,7 +578,7 @@ ENTRY(dirty_bit) ;; (p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present ;; -(p6) itc.d r25 // install updated PTE + ITC_D(p6, r25, r18) // install updated PTE ;; /* * Tell the assemblers dependency-violation checker that the above "itc" instructions @@ -602,7 +604,7 @@ ENTRY(dirty_bit) itc.d r18 // install updated PTE #endif mov pr=r31,-1 // restore pr - rfi + RFI END(dirty_bit) .org ia64_ivt+0x2400 @@ -611,22 +613,22 @@ END(dirty_bit) ENTRY(iaccess_bit) DBG_FAULT(9) // Like Entry 8, except for instruction access - mov r16=cr.ifa // get the address that caused the fault + MOV_FROM_IFA(r16) // get the address that caused the fault movl r30=1f // load continuation point in case of nested fault mov r31=pr // save predicates #ifdef CONFIG_ITANIUM /* * Erratum 10 (IFA may contain incorrect address) has "NoFix" status. */ - mov r17=cr.ipsr + MOV_FROM_IPSR(p0, r17) ;; - mov r18=cr.iip + MOV_FROM_IIP(r18) tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? ;; (p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa #endif /* CONFIG_ITANIUM */ ;; - thash r17=r16 // compute virtual address of L3 PTE + THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE mov r29=b0 // save b0 in case of nested fault) #ifdef CONFIG_SMP mov r28=ar.ccv // save ar.ccv @@ -642,7 +644,7 @@ ENTRY(iaccess_bit) ;; (p6) cmp.eq p6,p7=r26,r18 // Only if page present ;; -(p6) itc.i r25 // install updated PTE + ITC_I(p6, r25, r26) // install updated PTE ;; /* * Tell the assemblers dependency-violation checker that the above "itc" instructions @@ -668,7 +670,7 @@ ENTRY(iaccess_bit) itc.i r18 // install updated PTE #endif /* !CONFIG_SMP */ mov pr=r31,-1 - rfi + RFI END(iaccess_bit) .org ia64_ivt+0x2800 @@ -677,10 +679,10 @@ END(iaccess_bit) ENTRY(daccess_bit) DBG_FAULT(10) // Like Entry 8, except for data access - mov r16=cr.ifa // get the address that caused the fault + MOV_FROM_IFA(r16) // get the address that caused the fault movl r30=1f // load continuation point in case of nested fault ;; - thash r17=r16 // compute virtual address of L3 PTE + THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE mov r31=pr mov r29=b0 // save b0 in case of nested fault) #ifdef CONFIG_SMP @@ -697,7 +699,7 @@ ENTRY(daccess_bit) ;; (p6) cmp.eq p6,p7=r26,r18 // Only if page is present ;; -(p6) itc.d r25 // install updated PTE + ITC_D(p6, r25, r26) // install updated PTE /* * Tell the assemblers dependency-violation checker that the above "itc" instructions * cannot possibly affect the following loads: @@ -721,7 +723,7 @@ ENTRY(daccess_bit) #endif mov b0=r29 // restore b0 mov pr=r31,-1 - rfi + RFI END(daccess_bit) .org ia64_ivt+0x2c00 @@ -745,10 +747,10 @@ ENTRY(break_fault) */ DBG_FAULT(11) mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc) - mov r29=cr.ipsr // M2 (12 cyc) + MOV_FROM_IPSR(p0, r29) // M2 (12 cyc) mov r31=pr // I0 (2 cyc) - mov r17=cr.iim // M2 (2 cyc) + MOV_FROM_IIM(r17) // M2 (2 cyc) mov.m r27=ar.rsc // M2 (12 cyc) mov r18=__IA64_BREAK_SYSCALL // A @@ -767,7 +769,7 @@ ENTRY(break_fault) nop.m 0 movl r30=sys_call_table // X - mov r28=cr.iip // M2 (2 cyc) + MOV_FROM_IIP(r28) // M2 (2 cyc) cmp.eq p0,p7=r18,r17 // I0 is this a system call? (p7) br.cond.spnt non_syscall // B no -> // @@ -864,18 +866,17 @@ ENTRY(break_fault) #endif mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 nop 0 - bsw.1 // B (6 cyc) regs are saved, switch to bank 1 + BSW_1(r2, r14) // B (6 cyc) regs are saved, switch to bank 1 ;; - ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r16) // M2 now it's safe to re-enable intr.-collection + // M0 ensure interruption collection is on movl r3=ia64_ret_from_syscall // X ;; - - srlz.i // M0 ensure interruption collection is on mov rp=r3 // I0 set the real return addr (p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT -(p15) ssm psr.i // M2 restore psr.i + SSM_PSR_I(p15, p15, r16) // M2 restore psr.i (p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic // NOT REACHED @@ -899,16 +900,15 @@ ENTRY(interrupt) mov r31=pr // prepare to save predicates ;; SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 - ssm psr.ic | PSR_DEFAULT_BITS - ;; + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r14) + // ensure everybody knows psr.ic is back on adds r3=8,r2 // set up second base pointer for SAVE_REST - srlz.i // ensure everybody knows psr.ic is back on ;; SAVE_REST ;; MCA_RECOVER_RANGE(interrupt) alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group - mov out0=cr.ivr // pass cr.ivr as first arg + MOV_FROM_IVR(out0, r8) // pass cr.ivr as first arg add out1=16,sp // pass pointer to pt_regs as second arg ;; srlz.d // make sure we see the effect of cr.ivr @@ -978,6 +978,7 @@ END(interrupt) * - ar.fpsr: set to kernel settings * - b6: preserved (same as on entry) */ +#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE GLOBAL_ENTRY(ia64_syscall_setup) #if PT(B6) != 0 # error This code assumes that b6 is the first field in pt_regs. @@ -1069,6 +1070,7 @@ GLOBAL_ENTRY(ia64_syscall_setup) (p10) mov r8=-EINVAL br.ret.sptk.many b7 END(ia64_syscall_setup) +#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ .org ia64_ivt+0x3c00 ///////////////////////////////////////////////////////////////////////////////////////// @@ -1082,7 +1084,7 @@ END(ia64_syscall_setup) DBG_FAULT(16) FAULT(16) -#ifdef CONFIG_VIRT_CPU_ACCOUNTING +#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(__IA64_ASM_PARAVIRTUALIZED_NATIVE) /* * There is no particular reason for this code to be here, other than * that there happens to be space here that would go unused otherwise. @@ -1092,7 +1094,7 @@ END(ia64_syscall_setup) * account_sys_enter is called from SAVE_MIN* macros if accounting is * enabled and if the macro is entered from user mode. */ -ENTRY(account_sys_enter) +GLOBAL_ENTRY(account_sys_enter) // mov.m r20=ar.itc is called in advance, and r13 is current add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13 add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13 @@ -1134,15 +1136,13 @@ ENTRY(non_syscall) // suitable spot... alloc r14=ar.pfs,0,0,2,0 - mov out0=cr.iim + MOV_FROM_IIM(out0) add out1=16,sp adds r3=8,r2 // set up second base pointer for SAVE_REST - ssm psr.ic | PSR_DEFAULT_BITS - ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24) + // guarantee that interruption collection is on + SSM_PSR_I(p15, p15, r15) // restore psr.i movl r15=ia64_leave_kernel ;; SAVE_REST @@ -1168,14 +1168,12 @@ ENTRY(dispatch_unaligned_handler) SAVE_MIN_WITH_COVER ;; alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) - mov out0=cr.ifa + MOV_FROM_IFA(out0) adds out1=16,sp - ssm psr.ic | PSR_DEFAULT_BITS - ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) + // guarantee that interruption collection is on + SSM_PSR_I(p15, p15, r3) // restore psr.i adds r3=8,r2 // set up second base pointer ;; SAVE_REST @@ -1207,17 +1205,16 @@ ENTRY(dispatch_to_fault_handler) */ SAVE_MIN_WITH_COVER_R19 alloc r14=ar.pfs,0,0,5,0 - mov out0=r15 - mov out1=cr.isr - mov out2=cr.ifa - mov out3=cr.iim - mov out4=cr.itir + MOV_FROM_ISR(out1) + MOV_FROM_IFA(out2) + MOV_FROM_IIM(out3) + MOV_FROM_ITIR(out4) ;; - ssm psr.ic | PSR_DEFAULT_BITS - ;; - srlz.i // guarantee that interruption collection is on + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, out0) + // guarantee that interruption collection is on + mov out0=r15 ;; -(p15) ssm psr.i // restore psr.i + SSM_PSR_I(p15, p15, r3) // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; SAVE_REST @@ -1236,8 +1233,8 @@ END(dispatch_to_fault_handler) // 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49) ENTRY(page_not_present) DBG_FAULT(20) - mov r16=cr.ifa - rsm psr.dt + MOV_FROM_IFA(r16) + RSM_PSR_DT /* * The Linux page fault handler doesn't expect non-present pages to be in * the TLB. Flush the existing entry now, so we meet that expectation. @@ -1256,8 +1253,8 @@ END(page_not_present) // 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52) ENTRY(key_permission) DBG_FAULT(21) - mov r16=cr.ifa - rsm psr.dt + MOV_FROM_IFA(r16) + RSM_PSR_DT mov r31=pr ;; srlz.d @@ -1269,8 +1266,8 @@ END(key_permission) // 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26) ENTRY(iaccess_rights) DBG_FAULT(22) - mov r16=cr.ifa - rsm psr.dt + MOV_FROM_IFA(r16) + RSM_PSR_DT mov r31=pr ;; srlz.d @@ -1282,8 +1279,8 @@ END(iaccess_rights) // 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53) ENTRY(daccess_rights) DBG_FAULT(23) - mov r16=cr.ifa - rsm psr.dt + MOV_FROM_IFA(r16) + RSM_PSR_DT mov r31=pr ;; srlz.d @@ -1295,7 +1292,7 @@ END(daccess_rights) // 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39) ENTRY(general_exception) DBG_FAULT(24) - mov r16=cr.isr + MOV_FROM_ISR(r16) mov r31=pr ;; cmp4.eq p6,p0=0,r16 @@ -1324,8 +1321,8 @@ END(disabled_fp_reg) ENTRY(nat_consumption) DBG_FAULT(26) - mov r16=cr.ipsr - mov r17=cr.isr + MOV_FROM_IPSR(p0, r16) + MOV_FROM_ISR(r17) mov r31=pr // save PR ;; and r18=0xf,r17 // r18 = cr.ipsr.code{3:0} @@ -1335,10 +1332,10 @@ ENTRY(nat_consumption) dep r16=-1,r16,IA64_PSR_ED_BIT,1 (p6) br.cond.spnt 1f // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH) ;; - mov cr.ipsr=r16 // set cr.ipsr.na + MOV_TO_IPSR(p0, r16, r18) mov pr=r31,-1 ;; - rfi + RFI 1: mov pr=r31,-1 ;; @@ -1360,26 +1357,26 @@ ENTRY(speculation_vector) * * cr.imm contains zero_ext(imm21) */ - mov r18=cr.iim + MOV_FROM_IIM(r18) ;; - mov r17=cr.iip + MOV_FROM_IIP(r17) shl r18=r18,43 // put sign bit in position (43=64-21) ;; - mov r16=cr.ipsr + MOV_FROM_IPSR(p0, r16) shr r18=r18,39 // sign extend (39=43-4) ;; add r17=r17,r18 // now add the offset ;; - mov cr.iip=r17 + MOV_FROM_IIP(r17) dep r16=0,r16,41,2 // clear EI ;; - mov cr.ipsr=r16 + MOV_FROM_IPSR(p0, r16) ;; - rfi // and go back + RFI END(speculation_vector) .org ia64_ivt+0x5800 @@ -1517,11 +1514,11 @@ ENTRY(ia32_intercept) DBG_FAULT(46) #ifdef CONFIG_IA32_SUPPORT mov r31=pr - mov r16=cr.isr + MOV_FROM_ISR(r16) ;; extr.u r17=r16,16,8 // get ISR.code mov r18=ar.eflag - mov r19=cr.iim // old eflag value + MOV_FROM_IIM(r19) // old eflag value ;; cmp.ne p6,p0=2,r17 (p6) br.cond.spnt 1f // not a system flag fault @@ -1533,7 +1530,7 @@ ENTRY(ia32_intercept) (p6) br.cond.spnt 1f // eflags.ac bit didn't change ;; mov pr=r31,-1 // restore predicate registers - rfi + RFI 1: #endif // CONFIG_IA32_SUPPORT @@ -1686,11 +1683,10 @@ ENTRY(dispatch_illegal_op_fault) .prologue .body SAVE_MIN_WITH_COVER - ssm psr.ic | PSR_DEFAULT_BITS + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) + // guarantee that interruption collection is on ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i + SSM_PSR_I(p15, p15, r3) // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; alloc r14=ar.pfs,0,0,1,0 // must be first in insn group @@ -1729,12 +1725,11 @@ END(dispatch_illegal_op_fault) ENTRY(dispatch_to_ia32_handler) SAVE_MIN ;; - mov r14=cr.isr - ssm psr.ic | PSR_DEFAULT_BITS - ;; - srlz.i // guarantee that interruption collection is on + MOV_FROM_ISR(r14) + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) + // guarantee that interruption collection is on ;; -(p15) ssm psr.i + SSM_PSR_I(p15, p15, r3) adds r3=8,r2 // Base pointer for SAVE_REST ;; SAVE_REST -- cgit v1.2.3-70-g09d2 From 4df8d22bbbb16ccfa4e10cc068135183c9e5e006 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 27 May 2008 15:08:01 -0700 Subject: [IA64] pvops: paravirtualize entry.S paravirtualize ia64_swtich_to, ia64_leave_syscall and ia64_leave_kernel. They include sensitive or performance critical privileged instructions so that they need paravirtualization. To paravirtualize them by single source and multi compile they are converted into indirect jump. And define each pv instances. Cc: Keith Owens Cc: "Dong, Eddie" Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/Makefile | 2 +- arch/ia64/kernel/entry.S | 115 +++++++++++++++++++++++-------------- arch/ia64/kernel/paravirt.c | 19 ++++++ arch/ia64/kernel/paravirtentry.S | 60 +++++++++++++++++++ include/asm-ia64/native/inst.h | 8 +++ include/asm-ia64/paravirt_privop.h | 23 ++++++++ 6 files changed, 183 insertions(+), 44 deletions(-) create mode 100644 arch/ia64/kernel/paravirtentry.S (limited to 'arch') diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 8b2524293eb..cea91f17d44 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -36,7 +36,7 @@ obj-$(CONFIG_PCI_MSI) += msi_ia64.o mca_recovery-y += mca_drv.o mca_drv_asm.o obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o -obj-$(CONFIG_PARAVIRT) += paravirt.o +obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index ca2bb95726d..56ab156c48a 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -22,6 +22,11 @@ * Patrick O'Rourke * 11/07/2000 */ +/* + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * pv_ops. + */ /* * Global (preserved) predicate usage on syscall entry/exit path: * @@ -45,6 +50,7 @@ #include "minstate.h" +#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE /* * execve() is special because in case of success, we need to * setup a null register window frame. @@ -173,6 +179,7 @@ GLOBAL_ENTRY(sys_clone) mov rp=loc0 br.ret.sptk.many rp END(sys_clone) +#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ /* * prev_task <- ia64_switch_to(struct task_struct *next) @@ -180,7 +187,7 @@ END(sys_clone) * called. The code starting at .map relies on this. The rest of the code * doesn't care about the interrupt masking status. */ -GLOBAL_ENTRY(ia64_switch_to) +GLOBAL_ENTRY(__paravirt_switch_to) .prologue alloc r16=ar.pfs,1,0,0,0 DO_SAVE_SWITCH_STACK @@ -204,7 +211,7 @@ GLOBAL_ENTRY(ia64_switch_to) ;; .done: ld8 sp=[r21] // load kernel stack pointer of new task - mov IA64_KR(CURRENT)=in0 // update "current" application register + MOV_TO_KR(CURRENT, in0, r8, r9) // update "current" application register mov r8=r13 // return pointer to previously running task mov r13=in0 // set "current" pointer ;; @@ -216,26 +223,25 @@ GLOBAL_ENTRY(ia64_switch_to) br.ret.sptk.many rp // boogie on out in new context .map: - rsm psr.ic // interrupts (psr.i) are already disabled here + RSM_PSR_IC(r25) // interrupts (psr.i) are already disabled here movl r25=PAGE_KERNEL ;; srlz.d or r23=r25,r20 // construct PA | page properties mov r25=IA64_GRANULE_SHIFT<<2 ;; - mov cr.itir=r25 - mov cr.ifa=in0 // VA of next task... + MOV_TO_ITIR(p0, r25, r8) + MOV_TO_IFA(in0, r8) // VA of next task... ;; mov r25=IA64_TR_CURRENT_STACK - mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped... + MOV_TO_KR(CURRENT_STACK, r26, r8, r9) // remember last page we mapped... ;; itr.d dtr[r25]=r23 // wire in new mapping... - ssm psr.ic // reenable the psr.ic bit - ;; - srlz.d + SSM_PSR_IC_AND_SRLZ_D(r8, r9) // reenable the psr.ic bit br.cond.sptk .done -END(ia64_switch_to) +END(__paravirt_switch_to) +#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE /* * Note that interrupts are enabled during save_switch_stack and load_switch_stack. This * means that we may get an interrupt with "sp" pointing to the new kernel stack while @@ -375,7 +381,7 @@ END(save_switch_stack) * - b7 holds address to return to * - must not touch r8-r11 */ -ENTRY(load_switch_stack) +GLOBAL_ENTRY(load_switch_stack) .prologue .altrp b7 @@ -571,7 +577,7 @@ GLOBAL_ENTRY(ia64_trace_syscall) .ret3: (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk (pUStk) rsm psr.i // disable interrupts - br.cond.sptk .work_pending_syscall_end + br.cond.sptk ia64_work_pending_syscall_end strace_error: ld8 r3=[r2] // load pt_regs.r8 @@ -636,8 +642,17 @@ GLOBAL_ENTRY(ia64_ret_from_syscall) adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 mov r10=r0 // clear error indication in r10 (p7) br.cond.spnt handle_syscall_error // handle potential syscall failure +#ifdef CONFIG_PARAVIRT + ;; + br.cond.sptk.few ia64_leave_syscall + ;; +#endif /* CONFIG_PARAVIRT */ END(ia64_ret_from_syscall) +#ifndef CONFIG_PARAVIRT // fall through +#endif +#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ + /* * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't * need to switch to bank 0 and doesn't restore the scratch registers. @@ -682,7 +697,7 @@ END(ia64_ret_from_syscall) * ar.csd: cleared * ar.ssd: cleared */ -ENTRY(ia64_leave_syscall) +GLOBAL_ENTRY(__paravirt_leave_syscall) PT_REGS_UNWIND_INFO(0) /* * work.need_resched etc. mustn't get changed by this CPU before it returns to @@ -692,11 +707,11 @@ ENTRY(ia64_leave_syscall) * extra work. We always check for extra work when returning to user-level. * With CONFIG_PREEMPT, we also check for extra work when the preempt_count * is 0. After extra work processing has been completed, execution - * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check + * resumes at ia64_work_processed_syscall with p6 set to 1 if the extra-work-check * needs to be redone. */ #ifdef CONFIG_PREEMPT - rsm psr.i // disable interrupts + RSM_PSR_I(p0, r2, r18) // disable interrupts cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 ;; @@ -706,11 +721,12 @@ ENTRY(ia64_leave_syscall) ;; cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0) #else /* !CONFIG_PREEMPT */ -(pUStk) rsm psr.i + RSM_PSR_I(pUStk, r2, r18) cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk #endif -.work_processed_syscall: +.global __paravirt_work_processed_syscall; +__paravirt_work_processed_syscall: #ifdef CONFIG_VIRT_CPU_ACCOUNTING adds r2=PT(LOADRS)+16,r12 (pUStk) mov.m r22=ar.itc // fetch time at leave @@ -744,7 +760,7 @@ ENTRY(ia64_leave_syscall) (pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE! ;; invala // M0|1 invalidate ALAT - rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection + RSM_PSR_I_IC(r28, r29, r30) // M2 turn off interrupts and interruption collection cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs ld8 r29=[r2],16 // M0|1 load cr.ipsr @@ -765,7 +781,7 @@ ENTRY(ia64_leave_syscall) ;; #endif ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs -(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + MOV_FROM_PSR(pKStk, r22, r21) // M2 read PSR now that interrupts are disabled nop 0 ;; ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0 @@ -798,7 +814,7 @@ ENTRY(ia64_leave_syscall) srlz.d // M0 ensure interruption collection is off (for cover) shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition - cover // B add current frame into dirty partition & set cr.ifs + COVER // B add current frame into dirty partition & set cr.ifs ;; #ifdef CONFIG_VIRT_CPU_ACCOUNTING mov r19=ar.bsp // M2 get new backing store pointer @@ -823,8 +839,9 @@ ENTRY(ia64_leave_syscall) mov.m ar.ssd=r0 // M2 clear ar.ssd mov f11=f0 // F clear f11 br.cond.sptk.many rbs_switch // B -END(ia64_leave_syscall) +END(__paravirt_leave_syscall) +#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE #ifdef CONFIG_IA32_SUPPORT GLOBAL_ENTRY(ia64_ret_from_ia32_execve) PT_REGS_UNWIND_INFO(0) @@ -835,10 +852,20 @@ GLOBAL_ENTRY(ia64_ret_from_ia32_execve) st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit .mem.offset 8,0 st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit +#ifdef CONFIG_PARAVIRT + ;; + // don't fall through, ia64_leave_kernel may be #define'd + br.cond.sptk.few ia64_leave_kernel + ;; +#endif /* CONFIG_PARAVIRT */ END(ia64_ret_from_ia32_execve) +#ifndef CONFIG_PARAVIRT // fall through +#endif #endif /* CONFIG_IA32_SUPPORT */ -GLOBAL_ENTRY(ia64_leave_kernel) +#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ + +GLOBAL_ENTRY(__paravirt_leave_kernel) PT_REGS_UNWIND_INFO(0) /* * work.need_resched etc. mustn't get changed by this CPU before it returns to @@ -852,7 +879,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) * needs to be redone. */ #ifdef CONFIG_PREEMPT - rsm psr.i // disable interrupts + RSM_PSR_I(p0, r17, r31) // disable interrupts cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 ;; @@ -862,7 +889,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) ;; cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0) #else -(pUStk) rsm psr.i + RSM_PSR_I(pUStk, r17, r31) cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk #endif @@ -910,7 +937,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) mov ar.csd=r30 mov ar.ssd=r31 ;; - rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection + RSM_PSR_I_IC(r23, r22, r25) // initiate turning off of interrupt and interruption collection invala // invalidate ALAT ;; ld8.fill r22=[r2],24 @@ -942,7 +969,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) mov ar.ccv=r15 ;; ldf.fill f11=[r2] - bsw.0 // switch back to bank 0 (no stop bit required beforehand...) + BSW_0(r2, r3, r15) // switch back to bank 0 (no stop bit required beforehand...) ;; (pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency) adds r16=PT(CR_IPSR)+16,r12 @@ -950,12 +977,12 @@ GLOBAL_ENTRY(ia64_leave_kernel) #ifdef CONFIG_VIRT_CPU_ACCOUNTING .pred.rel.mutex pUStk,pKStk -(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled (pUStk) mov.m r22=ar.itc // M fetch time at leave nop.i 0 ;; #else -(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled nop.i 0 nop.i 0 ;; @@ -1027,7 +1054,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) * NOTE: alloc, loadrs, and cover can't be predicated. */ (pNonSys) br.cond.dpnt dont_preserve_current_frame - cover // add current frame into dirty partition and set cr.ifs + COVER // add current frame into dirty partition and set cr.ifs ;; mov r19=ar.bsp // get new backing store pointer rbs_switch: @@ -1130,16 +1157,16 @@ skip_rbs_switch: (pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp (pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise ;; - mov cr.ipsr=r29 // M2 + MOV_TO_IPSR(p0, r29, r25) // M2 mov ar.pfs=r26 // I0 (pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise -(p9) mov cr.ifs=r30 // M2 + MOV_TO_IFS(p9, r30, r25)// M2 mov b0=r21 // I0 (pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise mov ar.fpsr=r20 // M2 - mov cr.iip=r28 // M2 + MOV_TO_IIP(r28, r25) // M2 nop 0 ;; (pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode @@ -1148,7 +1175,7 @@ skip_rbs_switch: mov ar.rsc=r27 // M2 mov pr=r31,-1 // I0 - rfi // B + RFI // B /* * On entry: @@ -1174,35 +1201,36 @@ skip_rbs_switch: ;; (pKStk) st4 [r20]=r21 #endif - ssm psr.i // enable interrupts + SSM_PSR_I(p0, p6, r2) // enable interrupts br.call.spnt.many rp=schedule .ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 (re-check) - rsm psr.i // disable interrupts + RSM_PSR_I(p0, r2, r20) // disable interrupts ;; #ifdef CONFIG_PREEMPT (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 ;; (pKStk) st4 [r20]=r0 // preempt_count() <- 0 #endif -(pLvSys)br.cond.sptk.few .work_pending_syscall_end +(pLvSys)br.cond.sptk.few __paravirt_pending_syscall_end br.cond.sptk.many .work_processed_kernel .notify: (pUStk) br.call.spnt.many rp=notify_resume_user .ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 (don't re-check) -(pLvSys)br.cond.sptk.few .work_pending_syscall_end +(pLvSys)br.cond.sptk.few __paravirt_pending_syscall_end br.cond.sptk.many .work_processed_kernel -.work_pending_syscall_end: +.global __paravirt_pending_syscall_end; +__paravirt_pending_syscall_end: adds r2=PT(R8)+16,r12 adds r3=PT(R10)+16,r12 ;; ld8 r8=[r2] ld8 r10=[r3] - br.cond.sptk.many .work_processed_syscall - -END(ia64_leave_kernel) + br.cond.sptk.many __paravirt_work_processed_syscall_target +END(__paravirt_leave_kernel) +#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE ENTRY(handle_syscall_error) /* * Some system calls (e.g., ptrace, mmap) can return arbitrary values which could @@ -1244,7 +1272,7 @@ END(ia64_invoke_schedule_tail) * We declare 8 input registers so the system call args get preserved, * in case we need to restart a system call. */ -ENTRY(notify_resume_user) +GLOBAL_ENTRY(notify_resume_user) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart! mov r9=ar.unat @@ -1306,7 +1334,7 @@ ENTRY(sys_rt_sigreturn) adds sp=16,sp ;; ld8 r9=[sp] // load new ar.unat - mov.sptk b7=r8,ia64_leave_kernel + mov.sptk b7=r8,ia64_native_leave_kernel ;; mov ar.unat=r9 br.many b7 @@ -1665,3 +1693,4 @@ sys_call_table: data8 sys_timerfd_gettime .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls +#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index e5482bb6841..7126ea8f7ec 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -286,3 +286,22 @@ struct pv_cpu_ops pv_cpu_ops = { = ia64_native_intrin_local_irq_restore_func, }; EXPORT_SYMBOL(pv_cpu_ops); + +/****************************************************************************** + * replacement of hand written assembly codes. + */ + +void +paravirt_cpu_asm_init(const struct pv_cpu_asm_switch *cpu_asm_switch) +{ + extern unsigned long paravirt_switch_to_targ; + extern unsigned long paravirt_leave_syscall_targ; + extern unsigned long paravirt_work_processed_syscall_targ; + extern unsigned long paravirt_leave_kernel_targ; + + paravirt_switch_to_targ = cpu_asm_switch->switch_to; + paravirt_leave_syscall_targ = cpu_asm_switch->leave_syscall; + paravirt_work_processed_syscall_targ = + cpu_asm_switch->work_processed_syscall; + paravirt_leave_kernel_targ = cpu_asm_switch->leave_kernel; +} diff --git a/arch/ia64/kernel/paravirtentry.S b/arch/ia64/kernel/paravirtentry.S new file mode 100644 index 00000000000..2f42fcb9776 --- /dev/null +++ b/arch/ia64/kernel/paravirtentry.S @@ -0,0 +1,60 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirtentry.S + * + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include "entry.h" + +#define DATA8(sym, init_value) \ + .pushsection .data.read_mostly ; \ + .align 8 ; \ + .global sym ; \ + sym: ; \ + data8 init_value ; \ + .popsection + +#define BRANCH(targ, reg, breg) \ + movl reg=targ ; \ + ;; \ + ld8 reg=[reg] ; \ + ;; \ + mov breg=reg ; \ + br.cond.sptk.many breg + +#define BRANCH_PROC(sym, reg, breg) \ + DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \ + GLOBAL_ENTRY(paravirt_ ## sym) ; \ + BRANCH(paravirt_ ## sym ## _targ, reg, breg) ; \ + END(paravirt_ ## sym) + +#define BRANCH_PROC_UNWINFO(sym, reg, breg) \ + DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \ + GLOBAL_ENTRY(paravirt_ ## sym) ; \ + PT_REGS_UNWIND_INFO(0) ; \ + BRANCH(paravirt_ ## sym ## _targ, reg, breg) ; \ + END(paravirt_ ## sym) + + +BRANCH_PROC(switch_to, r22, b7) +BRANCH_PROC_UNWINFO(leave_syscall, r22, b7) +BRANCH_PROC(work_processed_syscall, r2, b7) +BRANCH_PROC_UNWINFO(leave_kernel, r22, b7) diff --git a/include/asm-ia64/native/inst.h b/include/asm-ia64/native/inst.h index f1072ace0cf..c953a2ca4fc 100644 --- a/include/asm-ia64/native/inst.h +++ b/include/asm-ia64/native/inst.h @@ -22,6 +22,14 @@ #define DO_SAVE_MIN IA64_NATIVE_DO_SAVE_MIN +#define __paravirt_switch_to ia64_native_switch_to +#define __paravirt_leave_syscall ia64_native_leave_syscall +#define __paravirt_work_processed_syscall ia64_native_work_processed_syscall +#define __paravirt_leave_kernel ia64_native_leave_kernel +#define __paravirt_pending_syscall_end ia64_work_pending_syscall_end +#define __paravirt_work_processed_syscall_target \ + ia64_work_processed_syscall + #ifdef CONFIG_PARAVIRT_GUEST_ASM_CLOBBER_CHECK # define PARAVIRT_POISON 0xdeadbeefbaadf00d # define CLOBBER(clob) \ diff --git a/include/asm-ia64/paravirt_privop.h b/include/asm-ia64/paravirt_privop.h index 7b133ae86df..52482e6940a 100644 --- a/include/asm-ia64/paravirt_privop.h +++ b/include/asm-ia64/paravirt_privop.h @@ -80,12 +80,35 @@ extern unsigned long ia64_native_getreg_func(int regnum); ia64_native_rsm(mask); \ } while (0) +/****************************************************************************** + * replacement of hand written assembly codes. + */ +struct pv_cpu_asm_switch { + unsigned long switch_to; + unsigned long leave_syscall; + unsigned long work_processed_syscall; + unsigned long leave_kernel; +}; +void paravirt_cpu_asm_init(const struct pv_cpu_asm_switch *cpu_asm_switch); + #endif /* __ASSEMBLY__ */ +#define IA64_PARAVIRT_ASM_FUNC(name) paravirt_ ## name + #else /* fallback for native case */ +#define IA64_PARAVIRT_ASM_FUNC(name) ia64_native_ ## name #endif /* CONFIG_PARAVIRT */ +/* these routines utilize privilege-sensitive or performance-sensitive + * privileged instructions so the code must be replaced with + * paravirtualized versions */ +#define ia64_switch_to IA64_PARAVIRT_ASM_FUNC(switch_to) +#define ia64_leave_syscall IA64_PARAVIRT_ASM_FUNC(leave_syscall) +#define ia64_work_processed_syscall \ + IA64_PARAVIRT_ASM_FUNC(work_processed_syscall) +#define ia64_leave_kernel IA64_PARAVIRT_ASM_FUNC(leave_kernel) + #endif /* _ASM_IA64_PARAVIRT_PRIVOP_H */ -- cgit v1.2.3-70-g09d2 From 213060a4d6991a95d0b9344406d195be3464accf Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:40 +0900 Subject: [IA64] pvops: paravirtualize NR_IRQS Make NR_IRQ overridable by each pv instances. Pv instance may need each own number of irqs so that NR_IRQS should be the maximum number of nr_irqs each pv instances need. Cc: Jes Sorensen Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/Makefile | 6 ++++++ arch/ia64/kernel/Makefile | 33 +++++++++++++++++++++++++++++++++ arch/ia64/kernel/nr-irqs.c | 24 ++++++++++++++++++++++++ include/asm-ia64/irq.h | 9 +-------- include/asm-ia64/native/irq.h | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 arch/ia64/kernel/nr-irqs.c create mode 100644 include/asm-ia64/native/irq.h (limited to 'arch') diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 88f1a55c6c9..3b9c8cadfd3 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -99,3 +99,9 @@ define archhelp echo ' boot - Build vmlinux and bootloader for Ski simulator' echo '* unwcheck - Check vmlinux for invalid unwind info' endef + +archprepare: make_nr_irqs_h FORCE +PHONY += make_nr_irqs_h FORCE + +make_nr_irqs_h: FORCE + $(Q)$(MAKE) $(build)=arch/ia64/kernel include/asm-ia64/nr-irqs.h diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index cea91f17d44..87fea11aecb 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -73,6 +73,39 @@ $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE # Note: kbuild does not track this dependency due to usage of .incbin $(obj)/gate-data.o: $(obj)/gate.so +# Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config +define sed-y + "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}" +endef +quiet_cmd_nr_irqs = GEN $@ +define cmd_nr_irqs + (set -e; \ + echo "#ifndef __ASM_NR_IRQS_H__"; \ + echo "#define __ASM_NR_IRQS_H__"; \ + echo "/*"; \ + echo " * DO NOT MODIFY."; \ + echo " *"; \ + echo " * This file was generated by Kbuild"; \ + echo " *"; \ + echo " */"; \ + echo ""; \ + sed -ne $(sed-y) $<; \ + echo ""; \ + echo "#endif" ) > $@ +endef + +# We use internal kbuild rules to avoid the "is up to date" message from make +arch/$(SRCARCH)/kernel/nr-irqs.s: $(srctree)/arch/$(SRCARCH)/kernel/nr-irqs.c \ + $(wildcard $(srctree)/include/asm-ia64/*/irq.h) + $(Q)mkdir -p $(dir $@) + $(call if_changed_dep,cc_s_c) + +include/asm-ia64/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s + $(Q)mkdir -p $(dir $@) + $(call cmd,nr_irqs) + +clean-files += $(objtree)/include/asm-ia64/nr-irqs.h + # # native ivt.S and entry.S # diff --git a/arch/ia64/kernel/nr-irqs.c b/arch/ia64/kernel/nr-irqs.c new file mode 100644 index 00000000000..1ae049181e8 --- /dev/null +++ b/arch/ia64/kernel/nr-irqs.c @@ -0,0 +1,24 @@ +/* + * calculate + * NR_IRQS = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, FOO_NR_IRQS...) + * depending on config. + * This must be calculated before processing asm-offset.c. + */ + +#define ASM_OFFSETS_C 1 + +#include +#include +#include + +void foo(void) +{ + union paravirt_nr_irqs_max { + char ia64_native_nr_irqs[IA64_NATIVE_NR_IRQS]; +#ifdef CONFIG_XEN + char xen_nr_irqs[XEN_NR_IRQS]; +#endif + }; + + DEFINE(NR_IRQS, sizeof (union paravirt_nr_irqs_max)); +} diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h index a66d26827cb..3627116fb0e 100644 --- a/include/asm-ia64/irq.h +++ b/include/asm-ia64/irq.h @@ -13,14 +13,7 @@ #include #include - -#define NR_VECTORS 256 - -#if (NR_VECTORS + 32 * NR_CPUS) < 1024 -#define NR_IRQS (NR_VECTORS + 32 * NR_CPUS) -#else -#define NR_IRQS 1024 -#endif +#include static __inline__ int irq_canonicalize (int irq) diff --git a/include/asm-ia64/native/irq.h b/include/asm-ia64/native/irq.h new file mode 100644 index 00000000000..efe9ff74a3c --- /dev/null +++ b/include/asm-ia64/native/irq.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * include/asm-ia64/native/irq.h + * + * Copyright (c) 2008 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * moved from linux/include/asm-ia64/irq.h. + */ + +#ifndef _ASM_IA64_NATIVE_IRQ_H +#define _ASM_IA64_NATIVE_IRQ_H + +#define NR_VECTORS 256 + +#if (NR_VECTORS + 32 * NR_CPUS) < 1024 +#define IA64_NATIVE_NR_IRQS (NR_VECTORS + 32 * NR_CPUS) +#else +#define IA64_NATIVE_NR_IRQS 1024 +#endif + +#endif /* _ASM_IA64_NATIVE_IRQ_H */ -- cgit v1.2.3-70-g09d2 From e51835d58a5abdf82211f36f500f666ca7ef9aee Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:41 +0900 Subject: [IA64] pvops: define initialization hooks, pv_init_ops, for paravirtualized environment. define pv_init_ops hooks which represents various initialization hooks for paravirtualized environment. and add hooks. Signed-off-by: Alex Williamson Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/paravirt.c | 7 +++++ arch/ia64/kernel/setup.c | 10 +++++++ arch/ia64/kernel/smpboot.c | 2 ++ include/asm-ia64/paravirt.h | 70 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+) (limited to 'arch') diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index 7126ea8f7ec..5daf659ff29 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -41,6 +41,13 @@ struct pv_info pv_info = { .name = "bare hardware" }; +/*************************************************************************** + * pv_init_ops + * initialization hooks. + */ + +struct pv_init_ops pv_init_ops; + /*************************************************************************** * pv_cpu_ops * intrinsics hooks. diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index f48a809c686..750749551e8 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -341,6 +342,8 @@ reserve_memory (void) rsvd_region[n].end = (unsigned long) ia64_imva(_end); n++; + n += paravirt_reserve_memory(&rsvd_region[n]); + #ifdef CONFIG_BLK_DEV_INITRD if (ia64_boot_param->initrd_start) { rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start); @@ -519,6 +522,8 @@ setup_arch (char **cmdline_p) { unw_init(); + paravirt_arch_setup_early(); + ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist); *cmdline_p = __va(ia64_boot_param->command_line); @@ -584,6 +589,9 @@ setup_arch (char **cmdline_p) acpi_boot_init(); #endif + paravirt_banner(); + paravirt_arch_setup_console(cmdline_p); + #ifdef CONFIG_VT if (!conswitchp) { # if defined(CONFIG_DUMMY_CONSOLE) @@ -603,6 +611,8 @@ setup_arch (char **cmdline_p) #endif /* enable IA-64 Machine Check Abort Handling unless disabled */ + if (paravirt_arch_setup_nomca()) + nomca = 1; if (!nomca) ia64_mca_init(); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index d7ad42b77d4..933f3881152 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -642,6 +643,7 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(smp_processor_id(), cpu_online_map); cpu_set(smp_processor_id(), cpu_callin_map); per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; + paravirt_post_smp_prepare_boot_cpu(); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/include/asm-ia64/paravirt.h b/include/asm-ia64/paravirt.h index 1032b216aea..84d74c32eb9 100644 --- a/include/asm-ia64/paravirt.h +++ b/include/asm-ia64/paravirt.h @@ -55,11 +55,81 @@ static inline unsigned int get_kernel_rpl(void) return pv_info.kernel_rpl; } +/****************************************************************************** + * initialization hooks. + */ +struct rsvd_region; + +struct pv_init_ops { + void (*banner)(void); + + int (*reserve_memory)(struct rsvd_region *region); + + void (*arch_setup_early)(void); + void (*arch_setup_console)(char **cmdline_p); + int (*arch_setup_nomca)(void); + + void (*post_smp_prepare_boot_cpu)(void); +}; + +extern struct pv_init_ops pv_init_ops; + +static inline void paravirt_banner(void) +{ + if (pv_init_ops.banner) + pv_init_ops.banner(); +} + +static inline int paravirt_reserve_memory(struct rsvd_region *region) +{ + if (pv_init_ops.reserve_memory) + return pv_init_ops.reserve_memory(region); + return 0; +} + +static inline void paravirt_arch_setup_early(void) +{ + if (pv_init_ops.arch_setup_early) + pv_init_ops.arch_setup_early(); +} + +static inline void paravirt_arch_setup_console(char **cmdline_p) +{ + if (pv_init_ops.arch_setup_console) + pv_init_ops.arch_setup_console(cmdline_p); +} + +static inline int paravirt_arch_setup_nomca(void) +{ + if (pv_init_ops.arch_setup_nomca) + return pv_init_ops.arch_setup_nomca(); + return 0; +} + +static inline void paravirt_post_smp_prepare_boot_cpu(void) +{ + if (pv_init_ops.post_smp_prepare_boot_cpu) + pv_init_ops.post_smp_prepare_boot_cpu(); +} + #endif /* !__ASSEMBLY__ */ #else /* fallback for native case */ +#ifndef __ASSEMBLY__ + +#define paravirt_banner() do { } while (0) +#define paravirt_reserve_memory(region) 0 + +#define paravirt_arch_setup_early() do { } while (0) +#define paravirt_arch_setup_console(cmdline_p) do { } while (0) +#define paravirt_arch_setup_nomca() 0 +#define paravirt_post_smp_prepare_boot_cpu() do { } while (0) + +#endif /* __ASSEMBLY__ */ + + #endif /* CONFIG_PARAVIRT_GUEST */ #endif /* __ASM_PARAVIRT_H */ -- cgit v1.2.3-70-g09d2 From 33b39e84209b0308b572dce017df7ee9b63f086c Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:42 +0900 Subject: [IA64] pvops: add hooks, pv_iosapic_ops, to paravirtualize iosapic. add hooks to paravirtualize iosapic which is a real hardware resource. On virtualized environment it may be replaced something virtualized friendly. Define pv_iosapic_ops and add the hooks. Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 45 +++++++++++++++++++++++++++++---------------- arch/ia64/kernel/paravirt.c | 25 +++++++++++++++++++++++++ include/asm-ia64/iosapic.h | 18 ++++++++++++++++-- include/asm-ia64/paravirt.h | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 082c31dcfd9..587196dd84f 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -587,6 +587,15 @@ static inline int irq_is_shared (int irq) return (iosapic_intr_info[irq].count > 1); } +struct irq_chip* +ia64_native_iosapic_get_irq_chip(unsigned long trigger) +{ + if (trigger == IOSAPIC_EDGE) + return &irq_type_iosapic_edge; + else + return &irq_type_iosapic_level; +} + static int register_intr (unsigned int gsi, int irq, unsigned char delivery, unsigned long polarity, unsigned long trigger) @@ -637,13 +646,10 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery, iosapic_intr_info[irq].dmode = delivery; iosapic_intr_info[irq].trigger = trigger; - if (trigger == IOSAPIC_EDGE) - irq_type = &irq_type_iosapic_edge; - else - irq_type = &irq_type_iosapic_level; + irq_type = iosapic_get_irq_chip(trigger); idesc = irq_desc + irq; - if (idesc->chip != irq_type) { + if (irq_type != NULL && idesc->chip != irq_type) { if (idesc->chip != &no_irq_type) printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", @@ -975,6 +981,22 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, set_rte(gsi, irq, dest, 1); } +void __init +ia64_native_iosapic_pcat_compat_init(void) +{ + if (pcat_compat) { + /* + * Disable the compatibility mode interrupts (8259 style), + * needs IN/OUT support enabled. + */ + printk(KERN_INFO + "%s: Disabling PC-AT compatible 8259 interrupts\n", + __func__); + outb(0xff, 0xA1); + outb(0xff, 0x21); + } +} + void __init iosapic_system_init (int system_pcat_compat) { @@ -989,17 +1011,8 @@ iosapic_system_init (int system_pcat_compat) } pcat_compat = system_pcat_compat; - if (pcat_compat) { - /* - * Disable the compatibility mode interrupts (8259 style), - * needs IN/OUT support enabled. - */ - printk(KERN_INFO - "%s: Disabling PC-AT compatible 8259 interrupts\n", - __func__); - outb(0xff, 0xA1); - outb(0xff, 0x21); - } + if (pcat_compat) + iosapic_pcat_compat_init(); } static inline int diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index 5daf659ff29..65c211b2f98 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -312,3 +312,28 @@ paravirt_cpu_asm_init(const struct pv_cpu_asm_switch *cpu_asm_switch) cpu_asm_switch->work_processed_syscall; paravirt_leave_kernel_targ = cpu_asm_switch->leave_kernel; } + +/*************************************************************************** + * pv_iosapic_ops + * iosapic read/write hooks. + */ + +static unsigned int +ia64_native_iosapic_read(char __iomem *iosapic, unsigned int reg) +{ + return __ia64_native_iosapic_read(iosapic, reg); +} + +static void +ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +{ + __ia64_native_iosapic_write(iosapic, reg, val); +} + +struct pv_iosapic_ops pv_iosapic_ops = { + .pcat_compat_init = ia64_native_iosapic_pcat_compat_init, + .get_irq_chip = ia64_native_iosapic_get_irq_chip, + + .__read = ia64_native_iosapic_read, + .__write = ia64_native_iosapic_write, +}; diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h index a3a4288daae..b9c102e15f2 100644 --- a/include/asm-ia64/iosapic.h +++ b/include/asm-ia64/iosapic.h @@ -55,13 +55,27 @@ #define NR_IOSAPICS 256 -static inline unsigned int __iosapic_read(char __iomem *iosapic, unsigned int reg) +#ifdef CONFIG_PARAVIRT_GUEST +#include +#else +#define iosapic_pcat_compat_init ia64_native_iosapic_pcat_compat_init +#define __iosapic_read __ia64_native_iosapic_read +#define __iosapic_write __ia64_native_iosapic_write +#define iosapic_get_irq_chip ia64_native_iosapic_get_irq_chip +#endif + +extern void __init ia64_native_iosapic_pcat_compat_init(void); +extern struct irq_chip *ia64_native_iosapic_get_irq_chip(unsigned long trigger); + +static inline unsigned int +__ia64_native_iosapic_read(char __iomem *iosapic, unsigned int reg) { writel(reg, iosapic + IOSAPIC_REG_SELECT); return readl(iosapic + IOSAPIC_WINDOW); } -static inline void __iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +static inline void +__ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) { writel(reg, iosapic + IOSAPIC_REG_SELECT); writel(val, iosapic + IOSAPIC_WINDOW); diff --git a/include/asm-ia64/paravirt.h b/include/asm-ia64/paravirt.h index 84d74c32eb9..3a40f624e86 100644 --- a/include/asm-ia64/paravirt.h +++ b/include/asm-ia64/paravirt.h @@ -112,6 +112,46 @@ static inline void paravirt_post_smp_prepare_boot_cpu(void) pv_init_ops.post_smp_prepare_boot_cpu(); } +/****************************************************************************** + * replacement of iosapic operations. + */ + +struct pv_iosapic_ops { + void (*pcat_compat_init)(void); + + struct irq_chip *(*get_irq_chip)(unsigned long trigger); + + unsigned int (*__read)(char __iomem *iosapic, unsigned int reg); + void (*__write)(char __iomem *iosapic, unsigned int reg, u32 val); +}; + +extern struct pv_iosapic_ops pv_iosapic_ops; + +static inline void +iosapic_pcat_compat_init(void) +{ + if (pv_iosapic_ops.pcat_compat_init) + pv_iosapic_ops.pcat_compat_init(); +} + +static inline struct irq_chip* +iosapic_get_irq_chip(unsigned long trigger) +{ + return pv_iosapic_ops.get_irq_chip(trigger); +} + +static inline unsigned int +__iosapic_read(char __iomem *iosapic, unsigned int reg) +{ + return pv_iosapic_ops.__read(iosapic, reg); +} + +static inline void +__iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +{ + return pv_iosapic_ops.__write(iosapic, reg, val); +} + #endif /* !__ASSEMBLY__ */ #else -- cgit v1.2.3-70-g09d2 From 85cbc503787d577c215f9540c57294e1ec799144 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:43 +0900 Subject: [IA64] pvops: add hooks, pv_irq_ops, to paravirtualized irq related operations. introduce pv_irq_ops which adds hooks to paravirtualize irq related operations. On virtualized environment, interruption may be replaced by something virtualization friendly. So the irq related operation also may need paravirtualization. This patch adds necessary hooks to paravirtualize irq related operations. Signed-off-by: Yaozu (Eddie) Dong Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/irq_ia64.c | 18 ++++++++++++----- arch/ia64/kernel/paravirt.c | 15 ++++++++++++++ include/asm-ia64/hw_irq.h | 23 ++++++++++++++++++---- include/asm-ia64/paravirt.h | 48 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index c48171bc796..28d3d483db9 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -196,7 +196,7 @@ static void clear_irq_vector(int irq) } int -assign_irq_vector (int irq) +ia64_native_assign_irq_vector (int irq) { unsigned long flags; int vector, cpu; @@ -222,7 +222,7 @@ assign_irq_vector (int irq) } void -free_irq_vector (int vector) +ia64_native_free_irq_vector (int vector) { if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR) @@ -622,7 +622,7 @@ static struct irqaction tlb_irqaction = { #endif void -register_percpu_irq (ia64_vector vec, struct irqaction *action) +ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action) { irq_desc_t *desc; unsigned int irq; @@ -637,13 +637,21 @@ register_percpu_irq (ia64_vector vec, struct irqaction *action) } void __init -init_IRQ (void) +ia64_native_register_ipi(void) { - register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction); +#endif +} + +void __init +init_IRQ (void) +{ + ia64_register_ipi(); + register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); +#ifdef CONFIG_SMP #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG) if (vector_domain_type != VECTOR_DOMAIN_NONE) { BUG_ON(IA64_FIRST_DEVICE_VECTOR != IA64_IRQ_MOVE_VECTOR); diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index 65c211b2f98..ba5383be03c 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -337,3 +337,18 @@ struct pv_iosapic_ops pv_iosapic_ops = { .__read = ia64_native_iosapic_read, .__write = ia64_native_iosapic_write, }; + +/*************************************************************************** + * pv_irq_ops + * irq operations + */ + +struct pv_irq_ops pv_irq_ops = { + .register_ipi = ia64_native_register_ipi, + + .assign_irq_vector = ia64_native_assign_irq_vector, + .free_irq_vector = ia64_native_free_irq_vector, + .register_percpu_irq = ia64_native_register_percpu_irq, + + .resend_irq = ia64_native_resend_irq, +}; diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index 76366dc9c1a..5c99cbcb8a0 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h @@ -15,7 +15,11 @@ #include #include +#ifndef CONFIG_PARAVIRT typedef u8 ia64_vector; +#else +typedef u16 ia64_vector; +#endif /* * 0 special @@ -104,13 +108,24 @@ DECLARE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq); extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */ +#ifdef CONFIG_PARAVIRT_GUEST +#include +#else +#define ia64_register_ipi ia64_native_register_ipi +#define assign_irq_vector ia64_native_assign_irq_vector +#define free_irq_vector ia64_native_free_irq_vector +#define register_percpu_irq ia64_native_register_percpu_irq +#define ia64_resend_irq ia64_native_resend_irq +#endif + +extern void ia64_native_register_ipi(void); extern int bind_irq_vector(int irq, int vector, cpumask_t domain); -extern int assign_irq_vector (int irq); /* allocate a free vector */ -extern void free_irq_vector (int vector); +extern int ia64_native_assign_irq_vector (int irq); /* allocate a free vector */ +extern void ia64_native_free_irq_vector (int vector); extern int reserve_irq_vector (int vector); extern void __setup_vector_irq(int cpu); extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); -extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); +extern void ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action); extern int check_irq_used (int irq); extern void destroy_and_reserve_irq (unsigned int irq); @@ -122,7 +137,7 @@ static inline int irq_prepare_move(int irq, int cpu) { return 0; } static inline void irq_complete_move(unsigned int irq) {} #endif -static inline void ia64_resend_irq(unsigned int vector) +static inline void ia64_native_resend_irq(unsigned int vector) { platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); } diff --git a/include/asm-ia64/paravirt.h b/include/asm-ia64/paravirt.h index 3a40f624e86..ee15646b6d6 100644 --- a/include/asm-ia64/paravirt.h +++ b/include/asm-ia64/paravirt.h @@ -152,6 +152,54 @@ __iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) return pv_iosapic_ops.__write(iosapic, reg, val); } +/****************************************************************************** + * replacement of irq operations. + */ + +struct pv_irq_ops { + void (*register_ipi)(void); + + int (*assign_irq_vector)(int irq); + void (*free_irq_vector)(int vector); + + void (*register_percpu_irq)(ia64_vector vec, + struct irqaction *action); + + void (*resend_irq)(unsigned int vector); +}; + +extern struct pv_irq_ops pv_irq_ops; + +static inline void +ia64_register_ipi(void) +{ + pv_irq_ops.register_ipi(); +} + +static inline int +assign_irq_vector(int irq) +{ + return pv_irq_ops.assign_irq_vector(irq); +} + +static inline void +free_irq_vector(int vector) +{ + return pv_irq_ops.free_irq_vector(vector); +} + +static inline void +register_percpu_irq(ia64_vector vec, struct irqaction *action) +{ + pv_irq_ops.register_percpu_irq(vec, action); +} + +static inline void +ia64_resend_irq(unsigned int vector) +{ + pv_irq_ops.resend_irq(vector); +} + #endif /* !__ASSEMBLY__ */ #else -- cgit v1.2.3-70-g09d2 From 00d21d82b8a9e290286e09d8eedc20bfc33b0eee Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 19 May 2008 22:13:44 +0900 Subject: [IA64] pvops: add to hooks, pv_time_ops, for steal time accounting. Introduce pv_time_ops which adds hook to steal time accounting. On virtualized environment, cpus are shared by many guests and steal time is the time which is used for other guests. On virtualized environtment, streal time should be accounted. Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/paravirt.c | 15 +++++++++++++++ arch/ia64/kernel/time.c | 23 +++++++++++++++++++++++ include/asm-ia64/paravirt.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) (limited to 'arch') diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index ba5383be03c..afaf5b9a2cf 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -352,3 +352,18 @@ struct pv_irq_ops pv_irq_ops = { .resend_irq = ia64_native_resend_irq, }; + +/*************************************************************************** + * pv_time_ops + * time operations + */ + +static int +ia64_native_do_steal_accounting(unsigned long *new_itm) +{ + return 0; +} + +struct pv_time_ops pv_time_ops = { + .do_steal_accounting = ia64_native_do_steal_accounting, +}; diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 8c73643f2d6..046ca89efc0 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,15 @@ EXPORT_SYMBOL(last_cli_ip); #endif +#ifdef CONFIG_PARAVIRT +static void +paravirt_clocksource_resume(void) +{ + if (pv_time_ops.clocksource_resume) + pv_time_ops.clocksource_resume(); +} +#endif + static struct clocksource clocksource_itc = { .name = "itc", .rating = 350, @@ -56,6 +66,9 @@ static struct clocksource clocksource_itc = { .mult = 0, /*to be calculated*/ .shift = 16, .flags = CLOCK_SOURCE_IS_CONTINUOUS, +#ifdef CONFIG_PARAVIRT + .resume = paravirt_clocksource_resume, +#endif }; static struct clocksource *itc_clocksource; @@ -156,6 +169,9 @@ timer_interrupt (int irq, void *dev_id) profile_tick(CPU_PROFILING); + if (paravirt_do_steal_accounting(&new_itm)) + goto skip_process_time_accounting; + while (1) { update_process_times(user_mode(get_irq_regs())); @@ -185,6 +201,8 @@ timer_interrupt (int irq, void *dev_id) local_irq_disable(); } +skip_process_time_accounting: + do { /* * If we're too close to the next clock tick for @@ -334,6 +352,11 @@ ia64_init_itm (void) */ clocksource_itc.rating = 50; + paravirt_init_missing_ticks_accounting(smp_processor_id()); + + /* avoid softlock up message when cpu is unplug and plugged again. */ + touch_softlockup_watchdog(); + /* Setup the CPU local timer tick */ ia64_cpu_local_tick(); diff --git a/include/asm-ia64/paravirt.h b/include/asm-ia64/paravirt.h index ee15646b6d6..1b4df129f57 100644 --- a/include/asm-ia64/paravirt.h +++ b/include/asm-ia64/paravirt.h @@ -200,6 +200,35 @@ ia64_resend_irq(unsigned int vector) pv_irq_ops.resend_irq(vector); } +/****************************************************************************** + * replacement of time operations. + */ + +extern struct itc_jitter_data_t itc_jitter_data; +extern volatile int time_keeper_id; + +struct pv_time_ops { + void (*init_missing_ticks_accounting)(int cpu); + int (*do_steal_accounting)(unsigned long *new_itm); + + void (*clocksource_resume)(void); +}; + +extern struct pv_time_ops pv_time_ops; + +static inline void +paravirt_init_missing_ticks_accounting(int cpu) +{ + if (pv_time_ops.init_missing_ticks_accounting) + pv_time_ops.init_missing_ticks_accounting(cpu); +} + +static inline int +paravirt_do_steal_accounting(unsigned long *new_itm) +{ + return pv_time_ops.do_steal_accounting(new_itm); +} + #endif /* !__ASSEMBLY__ */ #else @@ -215,6 +244,9 @@ ia64_resend_irq(unsigned int vector) #define paravirt_arch_setup_nomca() 0 #define paravirt_post_smp_prepare_boot_cpu() do { } while (0) +#define paravirt_init_missing_ticks_accounting(cpu) do { } while (0) +#define paravirt_do_steal_accounting(new_itm) 0 + #endif /* __ASSEMBLY__ */ -- cgit v1.2.3-70-g09d2 From 4d58bbcc89e267d52b4df572acbf209a60a8a497 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Wed, 28 May 2008 09:41:58 -0700 Subject: [IA64] pv_ops: move some functions in ivt.S to avoid lack of space. move interrupt, page_fault, non_syscall, dispatch_unaligned_handler and dispatch_to_fault_handler to avoid lack of instructin space. The change set 4dcc29e1574d88f4465ba865ed82800032f76418 bloated SAVE_MIN_WITH_COVER, SAVE_MIN_WITH_COVER_R19 so that it bloated the functions which uses those macros. In the native case, only dispatch_illegal_op_fault had to be moved. When paravirtualized case the all functions which use the macros need to be moved to avoid the lack of space. Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/kernel/ivt.S | 261 +++++++++++++++++++++++++------------------------ 1 file changed, 133 insertions(+), 128 deletions(-) (limited to 'arch') diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 23749ed3cf0..c39627df3cd 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -515,27 +515,6 @@ ENTRY(ikey_miss) FAULT(6) END(ikey_miss) - //----------------------------------------------------------------------------------- - // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) -ENTRY(page_fault) - SSM_PSR_DT_AND_SRLZ_I - ;; - SAVE_MIN_WITH_COVER - alloc r15=ar.pfs,0,0,3,0 - MOV_FROM_IFA(out0) - MOV_FROM_ISR(out1) - SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3) - adds r3=8,r2 // set up second base pointer - SSM_PSR_I(p15, p15, r14) // restore psr.i - movl r14=ia64_leave_kernel - ;; - SAVE_REST - mov rp=r14 - ;; - adds out2=16,r12 // out2 = pointer to pt_regs - br.call.sptk.many b6=ia64_do_page_fault // ignore return address -END(page_fault) - .org ia64_ivt+0x1c00 ///////////////////////////////////////////////////////////////////////////////////////// // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51) @@ -896,26 +875,8 @@ END(break_fault) ///////////////////////////////////////////////////////////////////////////////////////// // 0x3000 Entry 12 (size 64 bundles) External Interrupt (4) ENTRY(interrupt) - DBG_FAULT(12) - mov r31=pr // prepare to save predicates - ;; - SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 - SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r14) - // ensure everybody knows psr.ic is back on - adds r3=8,r2 // set up second base pointer for SAVE_REST - ;; - SAVE_REST - ;; - MCA_RECOVER_RANGE(interrupt) - alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group - MOV_FROM_IVR(out0, r8) // pass cr.ivr as first arg - add out1=16,sp // pass pointer to pt_regs as second arg - ;; - srlz.d // make sure we see the effect of cr.ivr - movl r14=ia64_leave_kernel - ;; - mov rp=r14 - br.call.sptk.many b6=ia64_handle_irq + /* interrupt handler has become too big to fit this area. */ + br.sptk.many __interrupt END(interrupt) .org ia64_ivt+0x3400 @@ -1125,105 +1086,18 @@ END(account_sys_enter) DBG_FAULT(17) FAULT(17) -ENTRY(non_syscall) - mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER - ;; - SAVE_MIN_WITH_COVER - - // There is no particular reason for this code to be here, other than that - // there happens to be space here that would go unused otherwise. If this - // fault ever gets "unreserved", simply moved the following code to a more - // suitable spot... - - alloc r14=ar.pfs,0,0,2,0 - MOV_FROM_IIM(out0) - add out1=16,sp - adds r3=8,r2 // set up second base pointer for SAVE_REST - - SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24) - // guarantee that interruption collection is on - SSM_PSR_I(p15, p15, r15) // restore psr.i - movl r15=ia64_leave_kernel - ;; - SAVE_REST - mov rp=r15 - ;; - br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr -END(non_syscall) - .org ia64_ivt+0x4800 ///////////////////////////////////////////////////////////////////////////////////////// // 0x4800 Entry 18 (size 64 bundles) Reserved DBG_FAULT(18) FAULT(18) - /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... - */ - -ENTRY(dispatch_unaligned_handler) - SAVE_MIN_WITH_COVER - ;; - alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) - MOV_FROM_IFA(out0) - adds out1=16,sp - - SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) - // guarantee that interruption collection is on - SSM_PSR_I(p15, p15, r3) // restore psr.i - adds r3=8,r2 // set up second base pointer - ;; - SAVE_REST - movl r14=ia64_leave_kernel - ;; - mov rp=r14 - br.sptk.many ia64_prepare_handle_unaligned -END(dispatch_unaligned_handler) - .org ia64_ivt+0x4c00 ///////////////////////////////////////////////////////////////////////////////////////// // 0x4c00 Entry 19 (size 64 bundles) Reserved DBG_FAULT(19) FAULT(19) - /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... - */ - -ENTRY(dispatch_to_fault_handler) - /* - * Input: - * psr.ic: off - * r19: fault vector number (e.g., 24 for General Exception) - * r31: contains saved predicates (pr) - */ - SAVE_MIN_WITH_COVER_R19 - alloc r14=ar.pfs,0,0,5,0 - MOV_FROM_ISR(out1) - MOV_FROM_IFA(out2) - MOV_FROM_IIM(out3) - MOV_FROM_ITIR(out4) - ;; - SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, out0) - // guarantee that interruption collection is on - mov out0=r15 - ;; - SSM_PSR_I(p15, p15, r3) // restore psr.i - adds r3=8,r2 // set up second base pointer for SAVE_REST - ;; - SAVE_REST - movl r14=ia64_leave_kernel - ;; - mov rp=r14 - br.call.sptk.many b6=ia64_fault -END(dispatch_to_fault_handler) - // // --- End of long entries, Beginning of short entries // @@ -1670,6 +1544,137 @@ END(ia32_interrupt) DBG_FAULT(67) FAULT(67) + //----------------------------------------------------------------------------------- + // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) +ENTRY(page_fault) + SSM_PSR_DT_AND_SRLZ_I + ;; + SAVE_MIN_WITH_COVER + alloc r15=ar.pfs,0,0,3,0 + MOV_FROM_IFA(out0) + MOV_FROM_ISR(out1) + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3) + adds r3=8,r2 // set up second base pointer + SSM_PSR_I(p15, p15, r14) // restore psr.i + movl r14=ia64_leave_kernel + ;; + SAVE_REST + mov rp=r14 + ;; + adds out2=16,r12 // out2 = pointer to pt_regs + br.call.sptk.many b6=ia64_do_page_fault // ignore return address +END(page_fault) + +ENTRY(non_syscall) + mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER + ;; + SAVE_MIN_WITH_COVER + + // There is no particular reason for this code to be here, other than that + // there happens to be space here that would go unused otherwise. If this + // fault ever gets "unreserved", simply moved the following code to a more + // suitable spot... + + alloc r14=ar.pfs,0,0,2,0 + MOV_FROM_IIM(out0) + add out1=16,sp + adds r3=8,r2 // set up second base pointer for SAVE_REST + + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24) + // guarantee that interruption collection is on + SSM_PSR_I(p15, p15, r15) // restore psr.i + movl r15=ia64_leave_kernel + ;; + SAVE_REST + mov rp=r15 + ;; + br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr +END(non_syscall) + +ENTRY(__interrupt) + DBG_FAULT(12) + mov r31=pr // prepare to save predicates + ;; + SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r14) + // ensure everybody knows psr.ic is back on + adds r3=8,r2 // set up second base pointer for SAVE_REST + ;; + SAVE_REST + ;; + MCA_RECOVER_RANGE(interrupt) + alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group + MOV_FROM_IVR(out0, r8) // pass cr.ivr as first arg + add out1=16,sp // pass pointer to pt_regs as second arg + ;; + srlz.d // make sure we see the effect of cr.ivr + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.call.sptk.many b6=ia64_handle_irq +END(__interrupt) + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + */ + +ENTRY(dispatch_unaligned_handler) + SAVE_MIN_WITH_COVER + ;; + alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) + MOV_FROM_IFA(out0) + adds out1=16,sp + + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) + // guarantee that interruption collection is on + SSM_PSR_I(p15, p15, r3) // restore psr.i + adds r3=8,r2 // set up second base pointer + ;; + SAVE_REST + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.sptk.many ia64_prepare_handle_unaligned +END(dispatch_unaligned_handler) + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + */ + +ENTRY(dispatch_to_fault_handler) + /* + * Input: + * psr.ic: off + * r19: fault vector number (e.g., 24 for General Exception) + * r31: contains saved predicates (pr) + */ + SAVE_MIN_WITH_COVER_R19 + alloc r14=ar.pfs,0,0,5,0 + MOV_FROM_ISR(out1) + MOV_FROM_IFA(out2) + MOV_FROM_IIM(out3) + MOV_FROM_ITIR(out4) + ;; + SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, out0) + // guarantee that interruption collection is on + mov out0=r15 + ;; + SSM_PSR_I(p15, p15, r3) // restore psr.i + adds r3=8,r2 // set up second base pointer for SAVE_REST + ;; + SAVE_REST + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.call.sptk.many b6=ia64_fault +END(dispatch_to_fault_handler) + /* * Squatting in this space ... * -- cgit v1.2.3-70-g09d2 From 3c3796cc32b6e53653a5eb868dc959b8c2779db9 Mon Sep 17 00:00:00 2001 From: HÃ¥vard Skinnemoen Date: Fri, 6 Jun 2008 18:04:53 +0200 Subject: [MTD] [NAND] rename at91_nand -> atmel_nand: internal symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is basically s/at91_nand/atmel_nand/g with some manual inspection. Signed-off-by: HÃ¥vard Skinnemoen Signed-off-by: David Woodhouse --- arch/arm/mach-at91/at91cap9_devices.c | 8 +- arch/arm/mach-at91/at91rm9200_devices.c | 8 +- arch/arm/mach-at91/at91sam9260_devices.c | 8 +- arch/arm/mach-at91/at91sam9261_devices.c | 12 +-- arch/arm/mach-at91/at91sam9263_devices.c | 8 +- arch/arm/mach-at91/at91sam9rl_devices.c | 12 +-- arch/arm/mach-at91/board-cam60.c | 2 +- arch/arm/mach-at91/board-cap9adk.c | 2 +- arch/arm/mach-at91/board-dk.c | 2 +- arch/arm/mach-at91/board-kb9202.c | 2 +- arch/arm/mach-at91/board-sam9-l9260.c | 2 +- arch/arm/mach-at91/board-sam9260ek.c | 2 +- arch/arm/mach-at91/board-sam9261ek.c | 2 +- arch/arm/mach-at91/board-sam9263ek.c | 2 +- arch/arm/mach-at91/board-sam9rlek.c | 2 +- arch/arm/mach-at91/board-yl-9200.c | 2 +- drivers/mtd/nand/atmel_nand.c | 152 +++++++++++++++---------------- drivers/mtd/nand/atmel_nand_ecc.h | 34 +++---- include/asm-arm/arch-at91/board.h | 4 +- 19 files changed, 133 insertions(+), 133 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index be526746e01..fe5148e9f0c 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -278,7 +278,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -296,7 +296,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91cap9_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -305,7 +305,7 @@ static struct platform_device at91cap9_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -346,7 +346,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91cap9_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index de19bee83f7..8ced9bc8209 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -369,7 +369,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -382,7 +382,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91rm9200_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -391,7 +391,7 @@ static struct platform_device at91rm9200_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned int csa; @@ -429,7 +429,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91rm9200_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 393a32aefce..3aa62b1151b 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -283,7 +283,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -301,7 +301,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91sam9260_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -310,7 +310,7 @@ static struct platform_device at91sam9260_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -351,7 +351,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91sam9260_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 728bb8f3944..6b9e423ec47 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -199,7 +199,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -211,8 +211,8 @@ static struct resource nand_resources[] = { } }; -static struct platform_device at91_nand_device = { - .name = "at91_nand", +static struct platform_device atmel_nand_device = { + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -221,7 +221,7 @@ static struct platform_device at91_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -262,11 +262,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data) at91_set_A_periph(AT91_PIN_PC1, 0); /* NANDWE */ nand_data = *data; - platform_device_register(&at91_nand_device); + platform_device_register(&atmel_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 719667e25c9..f1dfbfe094a 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -353,7 +353,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -371,7 +371,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91sam9263_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -380,7 +380,7 @@ static struct platform_device at91sam9263_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -421,7 +421,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91sam9263_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 054689804e7..b21f3339326 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -100,7 +100,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -117,8 +117,8 @@ static struct resource nand_resources[] = { } }; -static struct platform_device at91_nand_device = { - .name = "at91_nand", +static struct platform_device atmel_nand_device = { + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -127,7 +127,7 @@ static struct platform_device at91_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa; @@ -164,11 +164,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data) at91_set_A_periph(AT91_PIN_PB5, 0); /* NANDWE */ nand_data = *data; - platform_device_register(&at91_nand_device); + platform_device_register(&atmel_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c index b22a1a00405..af2c33aff1a 100644 --- a/arch/arm/mach-at91/board-cam60.c +++ b/arch/arm/mach-at91/board-cam60.c @@ -142,7 +142,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return cam60_nand_partition; } -static struct at91_nand_data __initdata cam60_nand_data = { +static struct atmel_nand_data __initdata cam60_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not there diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c index e5512d1ff21..7144e1a89a2 100644 --- a/arch/arm/mach-at91/board-cap9adk.c +++ b/arch/arm/mach-at91/board-cap9adk.c @@ -175,7 +175,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return cap9adk_nand_partitions; } -static struct at91_nand_data __initdata cap9adk_nand_data = { +static struct atmel_nand_data __initdata cap9adk_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c index c1a813c7169..ffecacb71f8 100644 --- a/arch/arm/mach-at91/board-dk.c +++ b/arch/arm/mach-at91/board-dk.c @@ -150,7 +150,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return dk_nand_partition; } -static struct at91_nand_data __initdata dk_nand_data = { +static struct atmel_nand_data __initdata dk_nand_data = { .ale = 22, .cle = 21, .det_pin = AT91_PIN_PB1, diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index 4b39b9cda75..153450f168f 100644 --- a/arch/arm/mach-at91/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c @@ -102,7 +102,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return kb9202_nand_partition; } -static struct at91_nand_data __initdata kb9202_nand_data = { +static struct atmel_nand_data __initdata kb9202_nand_data = { .ale = 22, .cle = 21, // .det_pin = ... not there diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index 8f76af5e219..57a6221943e 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -141,7 +141,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index 4d1d9c77708..6a680795c3c 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -178,7 +178,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 08382c0df22..43dfbd0d543 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -183,7 +183,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 22, .cle = 21, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index b4cd5d0ed59..6605a098011 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -187,7 +187,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index ffc0597aee8..35e69e51f37 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -88,7 +88,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c index b5717108991..e642b3a8bd1 100755 --- a/arch/arm/mach-at91/board-yl-9200.c +++ b/arch/arm/mach-at91/board-yl-9200.c @@ -251,7 +251,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return yl_9200_nand_partition; } -static struct at91_nand_data __initdata yl_9200_nand_data = { +static struct atmel_nand_data __initdata yl_9200_nand_data = { .ale= 6, .cle= 7, /*.det_pin = AT91_PIN_PCxx,*/ /*we don't have a det pin because NandFlash is fixed to board*/ diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 51b703155db..675a82ca77f 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -48,9 +48,9 @@ /* Register access macros */ #define ecc_readl(add, reg) \ - __raw_readl(add + AT91_ECC_##reg) + __raw_readl(add + ATMEL_ECC_##reg) #define ecc_writel(add, reg, value) \ - __raw_writel((value), add + AT91_ECC_##reg) + __raw_writel((value), add + ATMEL_ECC_##reg) #include "atmel_nand_ecc.h" /* Hardware ECC registers */ @@ -59,7 +59,7 @@ * the bytes have to be consecutives to avoid * several NAND_CMD_RNDOUT during read */ -static struct nand_ecclayout at91_oobinfo_large = { +static struct nand_ecclayout atmel_oobinfo_large = { .eccbytes = 4, .eccpos = {60, 61, 62, 63}, .oobfree = { @@ -72,7 +72,7 @@ static struct nand_ecclayout at91_oobinfo_large = { * the bytes have to be consecutives to avoid * several NAND_CMD_RNDOUT during read */ -static struct nand_ecclayout at91_oobinfo_small = { +static struct nand_ecclayout atmel_oobinfo_small = { .eccbytes = 4, .eccpos = {0, 1, 2, 3}, .oobfree = { @@ -80,11 +80,11 @@ static struct nand_ecclayout at91_oobinfo_small = { }, }; -struct at91_nand_host { +struct atmel_nand_host { struct nand_chip nand_chip; struct mtd_info mtd; void __iomem *io_base; - struct at91_nand_data *board; + struct atmel_nand_data *board; struct device *dev; void __iomem *ecc; }; @@ -92,7 +92,7 @@ struct at91_nand_host { /* * Enable NAND. */ -static void at91_nand_enable(struct at91_nand_host *host) +static void atmel_nand_enable(struct atmel_nand_host *host) { if (host->board->enable_pin) gpio_set_value(host->board->enable_pin, 0); @@ -101,7 +101,7 @@ static void at91_nand_enable(struct at91_nand_host *host) /* * Disable NAND. */ -static void at91_nand_disable(struct at91_nand_host *host) +static void atmel_nand_disable(struct atmel_nand_host *host) { if (host->board->enable_pin) gpio_set_value(host->board->enable_pin, 1); @@ -110,16 +110,16 @@ static void at91_nand_disable(struct at91_nand_host *host) /* * Hardware specific access to control-lines */ -static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nand_chip = mtd->priv; - struct at91_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_chip->priv; if (ctrl & NAND_CTRL_CHANGE) { if (ctrl & NAND_NCE) - at91_nand_enable(host); + atmel_nand_enable(host); else - at91_nand_disable(host); + atmel_nand_disable(host); } if (cmd == NAND_CMD_NONE) return; @@ -133,10 +133,10 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) /* * Read the Device Ready pin. */ -static int at91_nand_device_ready(struct mtd_info *mtd) +static int atmel_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd->priv; - struct at91_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_chip->priv; return gpio_get_value(host->board->rdy_pin); } @@ -144,7 +144,7 @@ static int at91_nand_device_ready(struct mtd_info *mtd) /* * write oob for small pages */ -static int at91_nand_write_oob_512(struct mtd_info *mtd, +static int atmel_nand_write_oob_512(struct mtd_info *mtd, struct nand_chip *chip, int page) { int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; @@ -172,7 +172,7 @@ static int at91_nand_write_oob_512(struct mtd_info *mtd, /* * read oob for small pages */ -static int at91_nand_read_oob_512(struct mtd_info *mtd, +static int atmel_nand_read_oob_512(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) { if (sndcmd) { @@ -192,11 +192,11 @@ static int at91_nand_read_oob_512(struct mtd_info *mtd, * dat: raw data (unused) * ecc_code: buffer for ECC */ -static int at91_nand_calculate(struct mtd_info *mtd, +static int atmel_nand_calculate(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) { struct nand_chip *nand_chip = mtd->priv; - struct at91_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_chip->priv; uint32_t *eccpos = nand_chip->ecc.layout->eccpos; unsigned int ecc_value; @@ -207,7 +207,7 @@ static int at91_nand_calculate(struct mtd_info *mtd, ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF; /* get the last 2 ECC bytes */ - ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY; + ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY; ecc_code[eccpos[2]] = ecc_value & 0xFF; ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF; @@ -222,7 +222,7 @@ static int at91_nand_calculate(struct mtd_info *mtd, * chip: nand chip info structure * buf: buffer to store read data */ -static int at91_nand_read_page(struct mtd_info *mtd, +static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf) { int eccsize = chip->ecc.size; @@ -281,11 +281,11 @@ static int at91_nand_read_page(struct mtd_info *mtd, * * Detect and correct a 1 bit error for a page */ -static int at91_nand_correct(struct mtd_info *mtd, u_char *dat, +static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *isnull) { struct nand_chip *nand_chip = mtd->priv; - struct at91_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_chip->priv; unsigned int ecc_status; unsigned int ecc_word, ecc_bit; @@ -293,43 +293,43 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat, ecc_status = ecc_readl(host->ecc, SR); /* if there's no error */ - if (likely(!(ecc_status & AT91_ECC_RECERR))) + if (likely(!(ecc_status & ATMEL_ECC_RECERR))) return 0; /* get error bit offset (4 bits) */ - ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR; + ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR; /* get word address (12 bits) */ - ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR; + ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR; ecc_word >>= 4; /* if there are multiple errors */ - if (ecc_status & AT91_ECC_MULERR) { + if (ecc_status & ATMEL_ECC_MULERR) { /* check if it is a freshly erased block * (filled with 0xff) */ - if ((ecc_bit == AT91_ECC_BITADDR) - && (ecc_word == (AT91_ECC_WORDADDR >> 4))) { + if ((ecc_bit == ATMEL_ECC_BITADDR) + && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) { /* the block has just been erased, return OK */ return 0; } /* it doesn't seems to be a freshly * erased block. * We can't correct so many errors */ - dev_dbg(host->dev, "at91_nand : multiple errors detected." + dev_dbg(host->dev, "atmel_nand : multiple errors detected." " Unable to correct.\n"); return -EIO; } /* if there's a single bit error : we can correct it */ - if (ecc_status & AT91_ECC_ECCERR) { + if (ecc_status & ATMEL_ECC_ECCERR) { /* there's nothing much to do here. * the bit error is on the ECC itself. */ - dev_dbg(host->dev, "at91_nand : one bit error on ECC code." + dev_dbg(host->dev, "atmel_nand : one bit error on ECC code." " Nothing to correct\n"); return 0; } - dev_dbg(host->dev, "at91_nand : one bit error on data." + dev_dbg(host->dev, "atmel_nand : one bit error on data." " (word offset in the page :" " 0x%x bit offset : 0x%x)\n", ecc_word, ecc_bit); @@ -341,14 +341,14 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat, /* 8 bits words */ dat[ecc_word] ^= (1 << ecc_bit); } - dev_dbg(host->dev, "at91_nand : error corrected\n"); + dev_dbg(host->dev, "atmel_nand : error corrected\n"); return 1; } /* * Enable HW ECC : unsused */ -static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; } +static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { ; } #ifdef CONFIG_MTD_PARTITIONS static const char *part_probes[] = { "cmdlinepart", NULL }; @@ -357,9 +357,9 @@ static const char *part_probes[] = { "cmdlinepart", NULL }; /* * Probe for the NAND device. */ -static int __init at91_nand_probe(struct platform_device *pdev) +static int __init atmel_nand_probe(struct platform_device *pdev) { - struct at91_nand_host *host; + struct atmel_nand_host *host; struct mtd_info *mtd; struct nand_chip *nand_chip; struct resource *regs; @@ -372,21 +372,21 @@ static int __init at91_nand_probe(struct platform_device *pdev) #endif /* Allocate memory for the device structure (and zero it) */ - host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL); + host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL); if (!host) { - printk(KERN_ERR "at91_nand: failed to allocate device structure.\n"); + printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n"); return -ENOMEM; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { - printk(KERN_ERR "at91_nand: can't get I/O resource mem\n"); + printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n"); return -ENXIO; } host->io_base = ioremap(mem->start, mem->end - mem->start + 1); if (host->io_base == NULL) { - printk(KERN_ERR "at91_nand: ioremap failed\n"); + printk(KERN_ERR "atmel_nand: ioremap failed\n"); kfree(host); return -EIO; } @@ -403,14 +403,14 @@ static int __init at91_nand_probe(struct platform_device *pdev) /* Set address of NAND IO lines */ nand_chip->IO_ADDR_R = host->io_base; nand_chip->IO_ADDR_W = host->io_base; - nand_chip->cmd_ctrl = at91_nand_cmd_ctrl; + nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; if (host->board->rdy_pin) - nand_chip->dev_ready = at91_nand_device_ready; + nand_chip->dev_ready = atmel_nand_device_ready; regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!regs && hard_ecc) { - printk(KERN_ERR "at91_nand: can't get I/O resource " + printk(KERN_ERR "atmel_nand: can't get I/O resource " "regs\nFalling back on software ECC\n"); } @@ -420,15 +420,15 @@ static int __init at91_nand_probe(struct platform_device *pdev) if (hard_ecc && regs) { host->ecc = ioremap(regs->start, regs->end - regs->start + 1); if (host->ecc == NULL) { - printk(KERN_ERR "at91_nand: ioremap failed\n"); + printk(KERN_ERR "atmel_nand: ioremap failed\n"); res = -EIO; goto err_ecc_ioremap; } nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME; - nand_chip->ecc.calculate = at91_nand_calculate; - nand_chip->ecc.correct = at91_nand_correct; - nand_chip->ecc.hwctl = at91_nand_hwctl; - nand_chip->ecc.read_page = at91_nand_read_page; + nand_chip->ecc.calculate = atmel_nand_calculate; + nand_chip->ecc.correct = atmel_nand_correct; + nand_chip->ecc.hwctl = atmel_nand_hwctl; + nand_chip->ecc.read_page = atmel_nand_read_page; nand_chip->ecc.bytes = 4; nand_chip->ecc.prepad = 0; nand_chip->ecc.postpad = 0; @@ -440,7 +440,7 @@ static int __init at91_nand_probe(struct platform_device *pdev) nand_chip->options |= NAND_BUSWIDTH_16; platform_set_drvdata(pdev, host); - at91_nand_enable(host); + atmel_nand_enable(host); if (host->board->det_pin) { if (gpio_get_value(host->board->det_pin)) { @@ -463,22 +463,22 @@ static int __init at91_nand_probe(struct platform_device *pdev) /* set ECC page size and oob layout */ switch (mtd->writesize) { case 512: - nand_chip->ecc.layout = &at91_oobinfo_small; - nand_chip->ecc.read_oob = at91_nand_read_oob_512; - nand_chip->ecc.write_oob = at91_nand_write_oob_512; - ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528); + nand_chip->ecc.layout = &atmel_oobinfo_small; + nand_chip->ecc.read_oob = atmel_nand_read_oob_512; + nand_chip->ecc.write_oob = atmel_nand_write_oob_512; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528); break; case 1024: - nand_chip->ecc.layout = &at91_oobinfo_large; - ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056); + nand_chip->ecc.layout = &atmel_oobinfo_large; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056); break; case 2048: - nand_chip->ecc.layout = &at91_oobinfo_large; - ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112); + nand_chip->ecc.layout = &atmel_oobinfo_large; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112); break; case 4096: - nand_chip->ecc.layout = &at91_oobinfo_large; - ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224); + nand_chip->ecc.layout = &atmel_oobinfo_large; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224); break; default: /* page size not handled by HW ECC */ @@ -503,7 +503,7 @@ static int __init at91_nand_probe(struct platform_device *pdev) #ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_CMDLINE_PARTS - mtd->name = "at91_nand"; + mtd->name = "atmel_nand"; num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0); #endif @@ -512,7 +512,7 @@ static int __init at91_nand_probe(struct platform_device *pdev) &num_partitions); if ((!partitions) || (num_partitions == 0)) { - printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n"); + printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); res = ENXIO; goto release; } @@ -534,7 +534,7 @@ out: iounmap(host->ecc); err_ecc_ioremap: - at91_nand_disable(host); + atmel_nand_disable(host); platform_set_drvdata(pdev, NULL); iounmap(host->io_base); kfree(host); @@ -544,14 +544,14 @@ err_ecc_ioremap: /* * Remove a NAND device. */ -static int __devexit at91_nand_remove(struct platform_device *pdev) +static int __devexit atmel_nand_remove(struct platform_device *pdev) { - struct at91_nand_host *host = platform_get_drvdata(pdev); + struct atmel_nand_host *host = platform_get_drvdata(pdev); struct mtd_info *mtd = &host->mtd; nand_release(mtd); - at91_nand_disable(host); + atmel_nand_disable(host); iounmap(host->io_base); iounmap(host->ecc); @@ -560,31 +560,31 @@ static int __devexit at91_nand_remove(struct platform_device *pdev) return 0; } -static struct platform_driver at91_nand_driver = { - .probe = at91_nand_probe, - .remove = at91_nand_remove, +static struct platform_driver atmel_nand_driver = { + .probe = atmel_nand_probe, + .remove = atmel_nand_remove, .driver = { - .name = "at91_nand", + .name = "atmel_nand", .owner = THIS_MODULE, }, }; -static int __init at91_nand_init(void) +static int __init atmel_nand_init(void) { - return platform_driver_register(&at91_nand_driver); + return platform_driver_register(&atmel_nand_driver); } -static void __exit at91_nand_exit(void) +static void __exit atmel_nand_exit(void) { - platform_driver_unregister(&at91_nand_driver); + platform_driver_unregister(&atmel_nand_driver); } -module_init(at91_nand_init); -module_exit(at91_nand_exit); +module_init(atmel_nand_init); +module_exit(atmel_nand_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Rick Bronson"); MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32"); -MODULE_ALIAS("platform:at91_nand"); +MODULE_ALIAS("platform:atmel_nand"); diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h index 170db869aac..1ee7f993db1 100644 --- a/drivers/mtd/nand/atmel_nand_ecc.h +++ b/drivers/mtd/nand/atmel_nand_ecc.h @@ -11,26 +11,26 @@ #ifndef ATMEL_NAND_ECC_H #define ATMEL_NAND_ECC_H -#define AT91_ECC_CR 0x00 /* Control register */ -#define AT91_ECC_RST (1 << 0) /* Reset parity */ +#define ATMEL_ECC_CR 0x00 /* Control register */ +#define ATMEL_ECC_RST (1 << 0) /* Reset parity */ -#define AT91_ECC_MR 0x04 /* Mode register */ -#define AT91_ECC_PAGESIZE (3 << 0) /* Page Size */ -#define AT91_ECC_PAGESIZE_528 (0) -#define AT91_ECC_PAGESIZE_1056 (1) -#define AT91_ECC_PAGESIZE_2112 (2) -#define AT91_ECC_PAGESIZE_4224 (3) +#define ATMEL_ECC_MR 0x04 /* Mode register */ +#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */ +#define ATMEL_ECC_PAGESIZE_528 (0) +#define ATMEL_ECC_PAGESIZE_1056 (1) +#define ATMEL_ECC_PAGESIZE_2112 (2) +#define ATMEL_ECC_PAGESIZE_4224 (3) -#define AT91_ECC_SR 0x08 /* Status register */ -#define AT91_ECC_RECERR (1 << 0) /* Recoverable Error */ -#define AT91_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */ -#define AT91_ECC_MULERR (1 << 2) /* Multiple Errors */ +#define ATMEL_ECC_SR 0x08 /* Status register */ +#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */ +#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */ +#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */ -#define AT91_ECC_PR 0x0c /* Parity register */ -#define AT91_ECC_BITADDR (0xf << 0) /* Bit Error Address */ -#define AT91_ECC_WORDADDR (0xfff << 4) /* Word Error Address */ +#define ATMEL_ECC_PR 0x0c /* Parity register */ +#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */ +#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */ -#define AT91_ECC_NPR 0x10 /* NParity register */ -#define AT91_ECC_NPARITY (0xffff << 0) /* NParity */ +#define ATMEL_ECC_NPR 0x10 /* NParity register */ +#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */ #endif diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h index dc189f01c5b..6296922a684 100644 --- a/include/asm-arm/arch-at91/board.h +++ b/include/asm-arm/arch-at91/board.h @@ -85,7 +85,7 @@ struct at91_usbh_data { extern void __init at91_add_device_usbh(struct at91_usbh_data *data); /* NAND / SmartMedia */ -struct at91_nand_data { +struct atmel_nand_data { u8 enable_pin; /* chip enable */ u8 det_pin; /* card detect */ u8 rdy_pin; /* ready/busy */ @@ -94,7 +94,7 @@ struct at91_nand_data { u8 bus_width_16; /* buswidth is 16 bit */ struct mtd_partition* (*partition_info)(int, int*); }; -extern void __init at91_add_device_nand(struct at91_nand_data *data); +extern void __init at91_add_device_nand(struct atmel_nand_data *data); /* I2C*/ extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices); -- cgit v1.2.3-70-g09d2 From e1677ce4e41a7c1bbc35a0dee27d5c7e7d223a4b Mon Sep 17 00:00:00 2001 From: HÃ¥vard Skinnemoen Date: Fri, 6 Jun 2008 18:04:55 +0200 Subject: avr32: move hsmc_init() to core_initcall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The board init code, typically running from postcore_initcall, may need to set up SMC timings. We have to make sure the SMC driver is ready before this happens. Signed-off-by: HÃ¥vard Skinnemoen Signed-off-by: David Woodhouse --- arch/avr32/mach-at32ap/hsmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c index fa427ed4278..b2d9bc61a35 100644 --- a/arch/avr32/mach-at32ap/hsmc.c +++ b/arch/avr32/mach-at32ap/hsmc.c @@ -278,4 +278,4 @@ static int __init hsmc_init(void) { return platform_driver_register(&hsmc_driver); } -arch_initcall(hsmc_init); +core_initcall(hsmc_init); -- cgit v1.2.3-70-g09d2 From 62090a08aba579e6c69319fac4d4a1f806f26400 Mon Sep 17 00:00:00 2001 From: HÃ¥vard Skinnemoen Date: Fri, 6 Jun 2008 18:04:56 +0200 Subject: [MTD] [NAND] avr32: atmel_nand platform code for AT32AP700x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function initializes and adds a platform_device for a NAND flash interface on SMC chip select 3. Signed-off-by: HÃ¥vard Skinnemoen Signed-off-by: David Woodhouse --- arch/avr32/mach-at32ap/at32ap700x.c | 52 +++++++++++++++++++++++++++++++++++ include/asm-avr32/arch-at32ap/board.h | 13 +++++++++ 2 files changed, 65 insertions(+) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 0f24b4f85c1..b65d3e0667a 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1729,6 +1729,58 @@ fail: } #endif +/* -------------------------------------------------------------------- + * NAND Flash / SmartMedia + * -------------------------------------------------------------------- */ +static struct resource smc_cs3_resource[] __initdata = { + { + .start = 0x0c000000, + .end = 0x0fffffff, + .flags = IORESOURCE_MEM, + }, { + .start = 0xfff03c00, + .end = 0xfff03fff, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device *__init +at32_add_device_nand(unsigned int id, struct atmel_nand_data *data) +{ + struct platform_device *pdev; + + if (id != 0 || !data) + return NULL; + + pdev = platform_device_alloc("atmel_nand", id); + if (!pdev) + goto fail; + + if (platform_device_add_resources(pdev, smc_cs3_resource, + ARRAY_SIZE(smc_cs3_resource))) + goto fail; + + if (platform_device_add_data(pdev, data, + sizeof(struct atmel_nand_data))) + goto fail; + + set_ebi_sfr_bits(HMATRIX_BIT(CS3A)); + if (data->enable_pin) + at32_select_gpio(data->enable_pin, + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + if (data->rdy_pin) + at32_select_gpio(data->rdy_pin, 0); + if (data->det_pin) + at32_select_gpio(data->det_pin, 0); + + platform_device_add(pdev); + return pdev; + +fail: + platform_device_put(pdev); + return NULL; +} + /* -------------------------------------------------------------------- * AC97C * -------------------------------------------------------------------- */ diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h index a4e2d28bfb5..cc5906cd741 100644 --- a/include/asm-avr32/arch-at32ap/board.h +++ b/include/asm-avr32/arch-at32ap/board.h @@ -85,4 +85,17 @@ struct platform_device * at32_add_device_cf(unsigned int id, unsigned int extint, struct cf_platform_data *data); +/* NAND / SmartMedia */ +struct atmel_nand_data { + int enable_pin; /* chip enable */ + int det_pin; /* card detect */ + int rdy_pin; /* ready/busy */ + u8 ale; /* address line number connected to ALE */ + u8 cle; /* address line number connected to CLE */ + u8 bus_width_16; /* buswidth is 16 bit */ + struct mtd_partition *(*partition_info)(int size, int *num_partitions); +}; +struct platform_device * +at32_add_device_nand(unsigned int id, struct atmel_nand_data *data); + #endif /* __ASM_ARCH_BOARD_H */ -- cgit v1.2.3-70-g09d2 From e150d6e725c014d72106a8610be40b7b08beb77a Mon Sep 17 00:00:00 2001 From: HÃ¥vard Skinnemoen Date: Fri, 6 Jun 2008 18:04:58 +0200 Subject: avr32: Add support for ATSTK1006 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ATSTK1006 is basically an upgraded version of ATSTK1002 with 128 MiB SDRAM and 256 MiB NAND flash on board. Otherwise, the board is very similar to the ATSTK1002, so it uses the same board support file. Signed-off-by: HÃ¥vard Skinnemoen Signed-off-by: David Woodhouse --- arch/avr32/boards/atstk1000/Kconfig | 4 ++ arch/avr32/boards/atstk1000/Makefile | 1 + arch/avr32/boards/atstk1000/atstk1002.c | 78 ++++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig index af90b00100f..8dc48214f0b 100644 --- a/arch/avr32/boards/atstk1000/Kconfig +++ b/arch/avr32/boards/atstk1000/Kconfig @@ -18,6 +18,10 @@ config BOARD_ATSTK1004 bool "ATSTK1004" select CPU_AT32AP7002 +config BOARD_ATSTK1006 + bool "ATSTK1006" + select CPU_AT32AP7000 + endchoice diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile index beead86462e..edecee03742 100644 --- a/arch/avr32/boards/atstk1000/Makefile +++ b/arch/avr32/boards/atstk1000/Makefile @@ -2,3 +2,4 @@ obj-y += setup.o flash.o obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o +obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 000eb4220a1..5bfaf4d87b3 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -1,7 +1,7 @@ /* - * ATSTK1002 daughterboard-specific init code + * ATSTK1002/ATSTK1006 daughterboard-specific init code * - * Copyright (C) 2005-2006 Atmel Corporation + * Copyright (C) 2005-2007 Atmel Corporation * * 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 @@ -29,6 +29,74 @@ #include "atstk1000.h" +/* + * The ATSTK1006 daughterboard is very similar to the ATSTK1002. Both + * have the AT32AP7000 chip on board; the difference is that the + * STK1006 has 128 MB SDRAM (the STK1002 uses the 8 MB SDRAM chip on + * the STK1000 motherboard) and 256 MB NAND flash (the STK1002 has + * none.) + * + * The RAM difference is handled by the boot loader, so the only + * difference we end up handling here is the NAND flash. + */ +#ifdef CONFIG_BOARD_ATSTK1006 +#include +#include + +static struct smc_timing nand_timing __initdata = { + .ncs_read_setup = 0, + .nrd_setup = 10, + .ncs_write_setup = 0, + .nwe_setup = 10, + + .ncs_read_pulse = 30, + .nrd_pulse = 15, + .ncs_write_pulse = 30, + .nwe_pulse = 15, + + .read_cycle = 30, + .write_cycle = 30, + + .ncs_read_recover = 0, + .nrd_recover = 15, + .ncs_write_recover = 0, + /* WE# high -> RE# low min 60 ns */ + .nwe_recover = 50, +}; + +static struct smc_config nand_config __initdata = { + .bus_width = 1, + .nrd_controlled = 1, + .nwe_controlled = 1, + .nwait_mode = 0, + .byte_write = 0, + .tdf_cycles = 2, + .tdf_mode = 0, +}; + +static struct mtd_partition nand_partitions[] = { + { + .name = "main", + .offset = 0x00000000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_part_info(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(nand_partitions); + return nand_partitions; +} + +struct atmel_nand_data atstk1006_nand_data __initdata = { + .cle = 21, + .ale = 22, + .rdy_pin = GPIO_PIN_PB(30), + .enable_pin = GPIO_PIN_PB(29), + .partition_info = nand_part_info, +}; +#endif + struct eth_addr { u8 addr[6]; }; @@ -212,6 +280,12 @@ static int __init atstk1002_init(void) at32_add_system_devices(); +#ifdef CONFIG_BOARD_ATSTK1006 + smc_set_timing(&nand_config, &nand_timing); + smc_set_configuration(3, &nand_config); + at32_add_device_nand(0, &atstk1006_nand_data); +#endif + #ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM at32_add_device_usart(1); #else -- cgit v1.2.3-70-g09d2 From da3854fc9f80c0240ba7cadd2aebf036683ff21b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 24 Jun 2008 22:15:58 +0100 Subject: DM9000: Fixup blackfin after removing 2 resource usage The dm9000 driver accepts either 2 or 3 resources to describe the platform devices. The 2 resources case abuses the ioresource mechanism by passing ioremap()ed memory through the platform device resources. This patch removes converts boards that were using it to the 3 resources scheme. CC: Bryan Wu Signed-off-by: Ben Dooks Signed-off-by: Laurent Pinchart Signed-off-by: Jeff Garzik --- arch/blackfin/mach-bf527/boards/ezkit.c | 7 ++++++- arch/blackfin/mach-bf533/boards/H8606.c | 7 ++++++- arch/blackfin/mach-bf537/boards/generic_board.c | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 5958eecefcf..689b69c98ee 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -323,10 +323,15 @@ static struct platform_device smc91x_device = { static struct resource dm9000_resources[] = { [0] = { .start = 0x203FB800, - .end = 0x203FB800 + 8, + .end = 0x203FB800 + 1, .flags = IORESOURCE_MEM, }, [1] = { + .start = 0x203FB800 + 4, + .end = 0x203FB800 + 5, + .flags = IORESOURCE_MEM, + }, + [2] = { .start = IRQ_PF9, .end = IRQ_PF9, .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c index 7cc4864f6aa..4103a97c1a7 100644 --- a/arch/blackfin/mach-bf533/boards/H8606.c +++ b/arch/blackfin/mach-bf533/boards/H8606.c @@ -65,10 +65,15 @@ static struct platform_device rtc_device = { static struct resource dm9000_resources[] = { [0] = { .start = 0x20300000, - .end = 0x20300000 + 8, + .end = 0x20300000 + 1, .flags = IORESOURCE_MEM, }, [1] = { + .start = 0x20300000 + 4, + .end = 0x20300000 + 5, + .flags = IORESOURCE_MEM, + }, + [2] = { .start = IRQ_PF10, .end = IRQ_PF10, .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index 7d250828dad..01b63e2ec18 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -166,10 +166,15 @@ static struct platform_device smc91x_device = { static struct resource dm9000_resources[] = { [0] = { .start = 0x203FB800, - .end = 0x203FB800 + 8, + .end = 0x203FB800 + 1, .flags = IORESOURCE_MEM, }, [1] = { + .start = 0x203FB800 + 4, + .end = 0x203FB800 + 5, + .flags = IORESOURCE_MEM, + }, + [2] = { .start = IRQ_PF9, .end = IRQ_PF9, .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), -- cgit v1.2.3-70-g09d2 From fc68911ee379bff429c2f8dfc0a4d3277eb193ec Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 25 Jun 2008 11:41:42 +0800 Subject: Blackfin arch: use the generic platform nand driver to support nand flash on bf53x board which do not have on-chip nand flash controller Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf537/boards/stamp.c | 86 +++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 671f9d67f23..7e4b9d95674 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -29,9 +29,12 @@ */ #include +#include #include #include +#include #include +#include #include #include #include @@ -355,6 +358,84 @@ static struct platform_device net2272_bfin_device = { }; #endif +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) +#ifdef CONFIG_MTD_PARTITIONS +const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; + +static struct mtd_partition bfin_plat_nand_partitions[] = { + { + .name = "linux kernel", + .size = 0x400000, + .offset = 0, + }, { + .name = "file system", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + }, +}; +#endif + +#define BFIN_NAND_PLAT_CLE 2 +#define BFIN_NAND_PLAT_ALE 1 +static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, this->IO_ADDR_W + (1 << BFIN_NAND_PLAT_CLE)); + else + writeb(cmd, this->IO_ADDR_W + (1 << BFIN_NAND_PLAT_ALE)); +} + +#define BFIN_NAND_PLAT_READY GPIO_PF3 +static int bfin_plat_nand_dev_ready(struct mtd_info *mtd) +{ + return gpio_get_value(BFIN_NAND_PLAT_READY); +} + +static struct platform_nand_data bfin_plat_nand_data = { + .chip = { + .chip_delay = 30, +#ifdef CONFIG_MTD_PARTITIONS + .part_probe_types = part_probes, + .partitions = bfin_plat_nand_partitions, + .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions), +#endif + }, + .ctrl = { + .cmd_ctrl = bfin_plat_nand_cmd_ctrl, + .dev_ready = bfin_plat_nand_dev_ready, + }, +}; + +#define MAX(x, y) (x > y ? x : y) +static struct resource bfin_plat_nand_resources = { + .start = 0x20212000, + .end = 0x20212000 + (1 << MAX(BFIN_NAND_PLAT_CLE, BFIN_NAND_PLAT_ALE)), + .flags = IORESOURCE_IO, +}; + +static struct platform_device bfin_async_nand_device = { + .name = "gen_nand", + .id = -1, + .num_resources = 1, + .resource = &bfin_plat_nand_resources, + .dev = { + .platform_data = &bfin_plat_nand_data, + }, +}; + +static void bfin_plat_nand_init(void) +{ + gpio_request(BFIN_NAND_PLAT_READY, "bfin_nand_plat"); +} +#else +static void bfin_plat_nand_init(void) {} +#endif + #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) static struct mtd_partition stamp_partitions[] = { { @@ -922,6 +1003,10 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_gpios_device, +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + &bfin_async_nand_device, +#endif + #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) &stamp_flash_device, #endif @@ -936,6 +1021,7 @@ static int __init stamp_init(void) ARRAY_SIZE(bfin_i2c_board_info)); #endif + bfin_plat_nand_init(); platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); -- cgit v1.2.3-70-g09d2 From 3aa30df3d0d78f568cff9d6a98ae01ae55494f10 Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Fri, 6 Jun 2008 14:12:26 +0200 Subject: cris: compile fixes for 2.6.26-rc5 Add dummy ops for serial debug port. Add setting of c_ispeed/c_ospeed as suggested by Alan Cox. Signed-off-by: Hinko Kocevar Acked-by: Alan Cox Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/kernel/debugport.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c index 04d5eee2c90..162730eb887 100644 --- a/arch/cris/arch-v10/kernel/debugport.c +++ b/arch/cris/arch-v10/kernel/debugport.c @@ -426,12 +426,18 @@ static int dummy_write(struct tty_struct * tty, return count; } -static int -dummy_write_room(struct tty_struct *tty) +static int dummy_write_room(struct tty_struct *tty) { return 8192; } +static const struct tty_operations dummy_ops = { + .open = dummy_open, + .close = dummy_close, + .write = dummy_write, + .write_room = dummy_write_room, +}; + void __init init_dummy_console(void) { @@ -444,14 +450,14 @@ init_dummy_console(void) dummy_driver.type = TTY_DRIVER_TYPE_SERIAL; dummy_driver.subtype = SERIAL_TYPE_NORMAL; dummy_driver.init_termios = tty_std_termios; + /* Normally B9600 default... */ dummy_driver.init_termios.c_cflag = - B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ + B115200 | CS8 | CREAD | HUPCL | CLOCAL; dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + dummy_driver.init_termios.c_ispeed = 115200; + dummy_driver.init_termios.c_ospeed = 115200; - dummy_driver.open = dummy_open; - dummy_driver.close = dummy_close; - dummy_driver.write = dummy_write; - dummy_driver.write_room = dummy_write_room; + dummy_driver.ops = &dummy_ops; if (tty_register_driver(&dummy_driver)) panic("Couldn't register dummy serial driver\n"); } -- cgit v1.2.3-70-g09d2 From 9be48a94b8ae8c944dc918ad65f2f27e9df3ed00 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jun 2008 22:50:56 +0200 Subject: It looks at least odd to apply spin_unlock to a mutex. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @def@ declarer DEFINE_MUTEX; identifier m; @@ DEFINE_MUTEX(m); @@ identifier def.m; @@ ( - spin_lock(&m) + mutex_lock(&m) | - spin_unlock(&m) + mutex_unlock(&m) ) // Signed-off-by: Julia Lawall Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/drivers/pcf8563.c | 2 +- arch/cris/arch-v32/drivers/pcf8563.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index 52103d16dc6..8769dc91407 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c @@ -233,7 +233,7 @@ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, if (copy_to_user((struct rtc_time *) arg, &tm, sizeof tm)) { - spin_unlock(&rtc_lock); + mutex_unlock(&rtc_lock); return -EFAULT; } diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c index 53db3870ba0..f263ab57122 100644 --- a/arch/cris/arch-v32/drivers/pcf8563.c +++ b/arch/cris/arch-v32/drivers/pcf8563.c @@ -229,7 +229,7 @@ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, if (copy_to_user((struct rtc_time *) arg, &tm, sizeof tm)) { - spin_unlock(&rtc_lock); + mutex_unlock(&rtc_lock); return -EFAULT; } -- cgit v1.2.3-70-g09d2 From bdb144b67a7660ce5d044ae9a2fd1a8030f12523 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Sun, 29 Jun 2008 23:15:19 +0200 Subject: [CRIS] Build fixes for compressed and rescue images for v10 and v32: - Use the normal cross gcc instead of using an elf specific cris toolchain. This removes the dependency of this second toolchain. - Use the normal cross objcopy instead of overriding it to use elf-toolchain. This allows compiling using "CROSS_COMPILE=$CRIS_GCC/cris-axis-linux-gnu-" instead of just "CROSS_COMPILE=$CRIS_GCC/cris-axis-linux-gnu/bin/" - Remove redundant rules for compiling, the implicit rules are sufficient. - Convert the arch/cris/arch-v10/boot/compressed/head.S to format accepted by the cris-axis-linux-gnu-gcc (registers must be prefixed with '$', remove explicit underscore on exported symbols) - Remove a number of unused (and duplicated) prototypes from arch/cris/arch-v10/boot/compressed/misc.c. - Correct memcpy and memset return values (actually return them!) Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/boot/Makefile | 1 - arch/cris/arch-v10/boot/compressed/Makefile | 12 +-- arch/cris/arch-v10/boot/compressed/decompress.ld | 3 +- arch/cris/arch-v10/boot/compressed/head.S | 98 ++++++++++++------------ arch/cris/arch-v10/boot/compressed/misc.c | 23 +++--- arch/cris/arch-v10/boot/rescue/Makefile | 7 +- arch/cris/arch-v32/boot/Makefile | 1 - arch/cris/arch-v32/boot/compressed/Makefile | 4 - arch/cris/arch-v32/boot/rescue/Makefile | 1 - 9 files changed, 65 insertions(+), 85 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v10/boot/Makefile b/arch/cris/arch-v10/boot/Makefile index 20c83a53caf..21720301443 100644 --- a/arch/cris/arch-v10/boot/Makefile +++ b/arch/cris/arch-v10/boot/Makefile @@ -2,7 +2,6 @@ # arch/cris/arch-v10/boot/Makefile # -OBJCOPY = objcopy-cris OBJCOPYFLAGS = -O binary --remove-section=.bss subdir- := compressed rescue diff --git a/arch/cris/arch-v10/boot/compressed/Makefile b/arch/cris/arch-v10/boot/compressed/Makefile index 4a031cb27eb..9ec5f87d515 100644 --- a/arch/cris/arch-v10/boot/compressed/Makefile +++ b/arch/cris/arch-v10/boot/compressed/Makefile @@ -2,12 +2,10 @@ # arch/cris/arch-v10/boot/compressed/Makefile # -CC = gcc-cris -melf $(LINUXINCLUDE) -ccflags-y += -O2 -LD = ld-cris +asflags-y += $(LINUXINCLUDE) +ccflags-y += -O2 $(LINUXINCLUDE) ldflags-y += -T $(obj)/decompress.ld OBJECTS = $(obj)/head.o $(obj)/misc.o -OBJCOPY = objcopy-cris OBJCOPYFLAGS = -O binary --remove-section=.bss quiet_cmd_image = BUILD $@ @@ -21,12 +19,6 @@ $(obj)/decompress.o: $(OBJECTS) FORCE $(obj)/decompress.bin: $(obj)/decompress.o FORCE $(call if_changed,objcopy) -$(obj)/head.o: $(obj)/head.S .config - @$(CC) -D__ASSEMBLY__ -traditional -c $< -o $@ - -$(obj)/misc.o: $(obj)/misc.c .config - @$(CC) -D__KERNEL__ -c $< -o $@ - $(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE $(call if_changed,image) diff --git a/arch/cris/arch-v10/boot/compressed/decompress.ld b/arch/cris/arch-v10/boot/compressed/decompress.ld index 0b0a14fe617..e80f4594d54 100644 --- a/arch/cris/arch-v10/boot/compressed/decompress.ld +++ b/arch/cris/arch-v10/boot/compressed/decompress.ld @@ -1,4 +1,5 @@ -OUTPUT_FORMAT(elf32-us-cris) +/* OUTPUT_FORMAT(elf32-us-cris) */ +OUTPUT_FORMAT(elf32-cris) MEMORY { diff --git a/arch/cris/arch-v10/boot/compressed/head.S b/arch/cris/arch-v10/boot/compressed/head.S index 610bdb23755..981fbae8495 100644 --- a/arch/cris/arch-v10/boot/compressed/head.S +++ b/arch/cris/arch-v10/boot/compressed/head.S @@ -15,77 +15,77 @@ #define COMMAND_LINE_MAGIC 0x87109563 ;; Exported symbols - - .globl _input_data - + .globl input_data + + .text nop di ;; We need to initialze DRAM registers before we start using the DRAM - - cmp.d RAM_INIT_MAGIC, r8 ; Already initialized? + + cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized? beq dram_init_finished nop - + #include "../../lib/dram_init.S" - -dram_init_finished: - + +dram_init_finished: + ;; Initiate the PA and PB ports - move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA, r0 - move.b r0, [R_PORT_PA_DATA] + move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r0 + move.b $r0, [R_PORT_PA_DATA] - move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR, r0 - move.b r0, [R_PORT_PA_DIR] + move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR, $r0 + move.b $r0, [R_PORT_PA_DIR] - move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA, r0 - move.b r0, [R_PORT_PB_DATA] + move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r0 + move.b $r0, [R_PORT_PB_DATA] - move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR, r0 - move.b r0, [R_PORT_PB_DIR] + move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR, $r0 + move.b $r0, [R_PORT_PB_DIR] ;; Setup the stack to a suitably high address. ;; We assume 8 MB is the minimum DRAM in an eLinux ;; product and put the sp at the top for now. - move.d 0x40800000, sp + move.d 0x40800000, $sp ;; Figure out where the compressed piggyback image is ;; in the flash (since we wont try to copy it to DRAM ;; before unpacking). It is at _edata, but in flash. ;; Use (_edata - basse) as offset to the current PC. - -basse: move.d pc, r5 - and.d 0x7fffffff, r5 ; strip any non-cache bit - subq 2, r5 ; compensate for the move.d pc instr - move.d r5, r0 ; save for later - flash address of 'basse' - add.d _edata, r5 - sub.d basse, r5 ; r5 = flash address of '_edata' - + +basse: move.d $pc, $r5 + and.d 0x7fffffff, $r5 ; strip any non-cache bit + subq 2, $r5 ; compensate for the move.d $pc instr + move.d $r5, $r0 ; save for later - flash address of 'basse' + add.d _edata, $r5 + sub.d basse, $r5 ; $r5 = flash address of '_edata' + ;; Copy text+data to DRAM - - move.d basse, r1 ; destination - move.d _edata, r2 ; end destination -1: move.w [r0+], r3 - move.w r3, [r1+] - cmp.d r2, r1 + + move.d basse, $r1 ; destination + move.d _edata, $r2 ; end destination +1: move.w [$r0+], $r3 + move.w $r3, [$r1+] + cmp.d $r2, $r1 bcs 1b nop - move.d r5, [_input_data] ; for the decompressor + move.d $r5, [input_data] ; for the decompressor ;; Clear the decompressors BSS (between _edata and _end) - - moveq 0, r0 - move.d _edata, r1 - move.d _end, r2 -1: move.w r0, [r1+] - cmp.d r2, r1 + + moveq 0, $r0 + move.d _edata, $r1 + move.d _end, $r2 +1: move.w $r0, [$r1+] + cmp.d $r2, $r1 bcs 1b nop @@ -94,16 +94,16 @@ basse: move.d pc, r5 move.d $r10, [$r12] move.d _cmd_line_addr, $r12 move.d $r11, [$r12] - - ;; Do the decompression and save compressed size in _inptr - jsr _decompress_kernel - - ;; Put start address of root partition in r9 so the kernel can use it + ;; Do the decompression and save compressed size in inptr + + jsr decompress_kernel + + ;; Put start address of root partition in $r9 so the kernel can use it ;; when mounting from flash - move.d [_input_data], r9 ; flash address of compressed kernel - add.d [_inptr], r9 ; size of compressed kernel + move.d [input_data], $r9 ; flash address of compressed kernel + add.d [inptr], $r9 ; size of compressed kernel ;; Restore command line magic and address. move.d _cmd_line_magic, $r10 @@ -112,12 +112,12 @@ basse: move.d pc, r5 move.d [$r11], $r11 ;; Enter the decompressed kernel - move.d RAM_INIT_MAGIC, r8 ; Tell kernel that DRAM is initialized + move.d RAM_INIT_MAGIC, $r8 ; Tell kernel that DRAM is initialized jump 0x40004000 ; kernel is linked to this address - + .data -_input_data: +input_data: .dword 0 ; used by the decompressor _cmd_line_magic: .dword 0 diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c index 9a43ab19391..59961f20fab 100644 --- a/arch/cris/arch-v10/boot/compressed/misc.c +++ b/arch/cris/arch-v10/boot/compressed/misc.c @@ -30,8 +30,7 @@ #define STATIC static void* memset(void* s, int c, size_t n); -void* memcpy(void* __dest, __const void* __src, - size_t __n); +void* memcpy(void* __dest, __const void* __src, size_t __n); #define memzero(s, n) memset ((s), 0, (n)) @@ -81,11 +80,8 @@ static unsigned outcnt = 0; /* bytes in output buffer */ # define Tracecv(c,x) #endif -static int fill_inbuf(void); static void flush_window(void); static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); extern char *input_data; /* lives in head.S */ @@ -95,7 +91,6 @@ static unsigned long output_ptr = 0; static void *malloc(int size); static void free(void *where); -static void error(char *m); static void gzip_mark(void **); static void gzip_release(void **); @@ -103,8 +98,8 @@ static void puts(const char *); /* the "heap" is put directly after the BSS ends, at end */ -extern int end; -static long free_mem_ptr = (long)&end; +extern int _end; +static long free_mem_ptr = (long)&_end; #include "../../../../../lib/inflate.c" @@ -170,6 +165,8 @@ memset(void* s, int c, size_t n) char *ss = (char*)s; for (i=0;i Date: Sat, 28 Jun 2008 18:25:41 -0400 Subject: x86, 64-bit: patch paravirt inline replacements when loading modules small speedup. Paravirt replacements were added to the i386 module loader by commit 139ec7c416248b9ea227d21839235344edfee1e0. This adds the same code to the x86_64 module loader. Signed-off-by: Anders Kaseorg Acked-by: "H. Peter Anvin" Signed-off-by: Ingo Molnar --- arch/x86/kernel/module_64.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/module_64.c b/arch/x86/kernel/module_64.c index a888e67f587..0e867676b5a 100644 --- a/arch/x86/kernel/module_64.c +++ b/arch/x86/kernel/module_64.c @@ -150,7 +150,8 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL; + const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, + *para = NULL; char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { @@ -160,6 +161,8 @@ int module_finalize(const Elf_Ehdr *hdr, alt = s; if (!strcmp(".smp_locks", secstrings + s->sh_name)) locks= s; + if (!strcmp(".parainstructions", secstrings + s->sh_name)) + para = s; } if (alt) { @@ -175,6 +178,11 @@ int module_finalize(const Elf_Ehdr *hdr, tseg, tseg + text->sh_size); } + if (para) { + void *pseg = (void *)para->sh_addr; + apply_paravirt(pseg, pseg + para->sh_size); + } + return module_bug_finalize(hdr, sechdrs, me); } -- cgit v1.2.3-70-g09d2 From 323ec001c6bb98eeabb5abbdbb8c8055d9496554 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 29 Jun 2008 14:19:31 +0400 Subject: x86: use generic per-device dma coherent allocator Signed-off-by: Dmitry Baryshkov Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 + arch/x86/kernel/pci-dma.c | 122 +----------------------------------------- include/asm-x86/dma-mapping.h | 22 +------- 3 files changed, 4 insertions(+), 141 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e0edaaa6920..9d4714e0020 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -25,6 +25,7 @@ config X86 select HAVE_KRETPROBES select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_ARCH_KGDB if !X86_VOYAGER + select HAVE_GENERIC_DMA_COHERENT if X86_32 config ARCH_DEFCONFIG string diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index dc00a1331ac..b75c81a8d3e 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -197,124 +197,6 @@ static __init int iommu_setup(char *p) } early_param("iommu", iommu_setup); -#ifdef CONFIG_X86_32 -int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, - dma_addr_t device_addr, size_t size, int flags) -{ - void __iomem *mem_base = NULL; - int pages = size >> PAGE_SHIFT; - int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); - - if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0) - goto out; - if (!size) - goto out; - if (dev->dma_mem) - goto out; - - /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ - - mem_base = ioremap(bus_addr, size); - if (!mem_base) - goto out; - - dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); - if (!dev->dma_mem) - goto out; - dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!dev->dma_mem->bitmap) - goto free1_out; - - dev->dma_mem->virt_base = mem_base; - dev->dma_mem->device_base = device_addr; - dev->dma_mem->size = pages; - dev->dma_mem->flags = flags; - - if (flags & DMA_MEMORY_MAP) - return DMA_MEMORY_MAP; - - return DMA_MEMORY_IO; - - free1_out: - kfree(dev->dma_mem); - out: - if (mem_base) - iounmap(mem_base); - return 0; -} -EXPORT_SYMBOL(dma_declare_coherent_memory); - -void dma_release_declared_memory(struct device *dev) -{ - struct dma_coherent_mem *mem = dev->dma_mem; - - if (!mem) - return; - dev->dma_mem = NULL; - iounmap(mem->virt_base); - kfree(mem->bitmap); - kfree(mem); -} -EXPORT_SYMBOL(dma_release_declared_memory); - -void *dma_mark_declared_memory_occupied(struct device *dev, - dma_addr_t device_addr, size_t size) -{ - struct dma_coherent_mem *mem = dev->dma_mem; - int pos, err; - int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1); - - pages >>= PAGE_SHIFT; - - if (!mem) - return ERR_PTR(-EINVAL); - - pos = (device_addr - mem->device_base) >> PAGE_SHIFT; - err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages)); - if (err != 0) - return ERR_PTR(err); - return mem->virt_base + (pos << PAGE_SHIFT); -} -EXPORT_SYMBOL(dma_mark_declared_memory_occupied); - -static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size, - dma_addr_t *dma_handle, void **ret) -{ - struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; - int order = get_order(size); - - if (mem) { - int page = bitmap_find_free_region(mem->bitmap, mem->size, - order); - if (page >= 0) { - *dma_handle = mem->device_base + (page << PAGE_SHIFT); - *ret = mem->virt_base + (page << PAGE_SHIFT); - memset(*ret, 0, size); - } - if (mem->flags & DMA_MEMORY_EXCLUSIVE) - *ret = NULL; - } - return (mem != NULL); -} - -static int dma_release_coherent(struct device *dev, int order, void *vaddr) -{ - struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; - - if (mem && vaddr >= mem->virt_base && vaddr < - (mem->virt_base + (mem->size << PAGE_SHIFT))) { - int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; - - bitmap_release_region(mem->bitmap, page, order); - return 1; - } - return 0; -} -#else -#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0) -#define dma_release_coherent(dev, order, vaddr) (0) -#endif /* CONFIG_X86_32 */ - int dma_supported(struct device *dev, u64 mask) { #ifdef CONFIG_PCI @@ -383,7 +265,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); - if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory)) + if (dma_alloc_from_coherent(dev, size, dma_handle, &memory)) return memory; if (!dev) { @@ -486,7 +368,7 @@ void dma_free_coherent(struct device *dev, size_t size, { int order = get_order(size); WARN_ON(irqs_disabled()); /* for portability */ - if (dma_release_coherent(dev, order, vaddr)) + if (dma_release_from_coherent(dev, order, vaddr)) return; if (dma_ops->unmap_single) dma_ops->unmap_single(dev, bus, size, 0); diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h index a1a4dc7fe6e..c68f360ef56 100644 --- a/include/asm-x86/dma-mapping.h +++ b/include/asm-x86/dma-mapping.h @@ -213,25 +213,5 @@ static inline int dma_get_cache_alignment(void) #define dma_is_consistent(d, h) (1) -#ifdef CONFIG_X86_32 -# define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY -struct dma_coherent_mem { - void *virt_base; - u32 device_base; - int size; - int flags; - unsigned long *bitmap; -}; - -extern int -dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, - dma_addr_t device_addr, size_t size, int flags); - -extern void -dma_release_declared_memory(struct device *dev); - -extern void * -dma_mark_declared_memory_occupied(struct device *dev, - dma_addr_t device_addr, size_t size); -#endif /* CONFIG_X86_32 */ +#include #endif -- cgit v1.2.3-70-g09d2 From 7dd071058f70d517f2d24e80cbb9d9885d565f0a Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 30 Jun 2008 20:38:06 +0200 Subject: [CRIS] Correct image makefiles to allow using a separate OBJ-directory. Make compile succeed when building with O= (srctree != objtree). Signed-off-by: Hinko Kocevar Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/boot/compressed/Makefile | 2 +- arch/cris/arch-v10/boot/rescue/Makefile | 2 +- arch/cris/arch-v32/boot/compressed/Makefile | 2 +- arch/cris/arch-v32/boot/rescue/Makefile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v10/boot/compressed/Makefile b/arch/cris/arch-v10/boot/compressed/Makefile index 9ec5f87d515..08d943ce4be 100644 --- a/arch/cris/arch-v10/boot/compressed/Makefile +++ b/arch/cris/arch-v10/boot/compressed/Makefile @@ -4,7 +4,7 @@ asflags-y += $(LINUXINCLUDE) ccflags-y += -O2 $(LINUXINCLUDE) -ldflags-y += -T $(obj)/decompress.ld +ldflags-y += -T $(srctree)/$(obj)/decompress.ld OBJECTS = $(obj)/head.o $(obj)/misc.o OBJCOPYFLAGS = -O binary --remove-section=.bss diff --git a/arch/cris/arch-v10/boot/rescue/Makefile b/arch/cris/arch-v10/boot/rescue/Makefile index bea8b9c2a7c..07688da9270 100644 --- a/arch/cris/arch-v10/boot/rescue/Makefile +++ b/arch/cris/arch-v10/boot/rescue/Makefile @@ -4,7 +4,7 @@ ccflags-y += -O2 $(LINUXINCLUDE) asflags-y += $(LINUXINCLUDE) -ldflags-y += -T $(obj)/rescue.ld +ldflags-y += -T $(srctree)/$(obj)/rescue.ld OBJCOPYFLAGS = -O binary --remove-section=.bss obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o OBJECT := $(obj)/head.o diff --git a/arch/cris/arch-v32/boot/compressed/Makefile b/arch/cris/arch-v32/boot/compressed/Makefile index 9138938eec3..d6335f26083 100644 --- a/arch/cris/arch-v32/boot/compressed/Makefile +++ b/arch/cris/arch-v32/boot/compressed/Makefile @@ -4,7 +4,7 @@ asflags-y += -I $(srctree)/include/asm/mach/ -I $(srctree)/include/asm/arch ccflags-y += -O2 -I $(srctree)/include/asm/mach/ -I $(srctree)/include/asm/arch -ldflags-y += -T $(obj)/decompress.ld +ldflags-y += -T $(srctree)/$(obj)/decompress.ld OBJECTS = $(obj)/head.o $(obj)/misc.o OBJCOPYFLAGS = -O binary --remove-section=.bss diff --git a/arch/cris/arch-v32/boot/rescue/Makefile b/arch/cris/arch-v32/boot/rescue/Makefile index b548bde185d..44ae0ad61f9 100644 --- a/arch/cris/arch-v32/boot/rescue/Makefile +++ b/arch/cris/arch-v32/boot/rescue/Makefile @@ -7,7 +7,7 @@ ccflags-y += -O2 -I $(srctree)/include/asm/arch/mach/ \ -I $(srctree)/include/asm/arch asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch LD = gcc-cris -mlinux -march=v32 -nostdlib -ldflags-y += -T $(obj)/rescue.ld +ldflags-y += -T $(srctree)/$(obj)/rescue.ld LDPOSTFLAGS = -lgcc OBJCOPYFLAGS = -O binary --remove-section=.bss obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o -- cgit v1.2.3-70-g09d2 From bd451d5ed206cda4ed0e03fac4e5dece2fd7767f Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 30 Jun 2008 23:22:51 +0200 Subject: [CRISv10] Correct whitespace damage. The previous patch was whitespace damaged, correct to indent using tabs. Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/kernel/debugport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c index 162730eb887..3dc6e91ba39 100644 --- a/arch/cris/arch-v10/kernel/debugport.c +++ b/arch/cris/arch-v10/kernel/debugport.c @@ -432,10 +432,10 @@ static int dummy_write_room(struct tty_struct *tty) } static const struct tty_operations dummy_ops = { - .open = dummy_open, - .close = dummy_close, - .write = dummy_write, - .write_room = dummy_write_room, + .open = dummy_open, + .close = dummy_close, + .write = dummy_write, + .write_room = dummy_write_room, }; void __init -- cgit v1.2.3-70-g09d2 From f3c4b53d5ec6bd2ae0f284c1e6371bff545f0f80 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 30 Jun 2008 21:20:23 +0200 Subject: [CRISv10] Clean up compressed/misc.c Many minor fixes in whitespace and formatting. Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/boot/compressed/misc.c | 127 ++++++++++++++++-------------- 1 file changed, 70 insertions(+), 57 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c index 59961f20fab..18e13bce140 100644 --- a/arch/cris/arch-v10/boot/compressed/misc.c +++ b/arch/cris/arch-v10/boot/compressed/misc.c @@ -29,11 +29,10 @@ #define OF(args) args #define STATIC static -void* memset(void* s, int c, size_t n); -void* memcpy(void* __dest, __const void* __src, size_t __n); - -#define memzero(s, n) memset ((s), 0, (n)) +void *memset(void *s, int c, size_t n); +void *memcpy(void *__dest, __const void *__src, size_t __n); +#define memzero(s, n) memset((s), 0, (n)) typedef unsigned char uch; typedef unsigned short ush; @@ -61,23 +60,38 @@ static unsigned outcnt = 0; /* bytes in output buffer */ #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ #define RESERVED 0xC0 /* bit 6,7: reserved */ -#define get_byte() inbuf[inptr++] - +#define get_byte() (inbuf[inptr++]) + /* Diagnostic functions */ #ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Assert(cond, msg) do { \ + if (!(cond)) \ + error(msg); \ + } while (0) # define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +# define Tracev(x) do { \ + if (verbose) \ + fprintf x; \ + } while (0) +# define Tracevv(x) do { \ + if (verbose > 1) \ + fprintf x; \ + } while (0) +# define Tracec(c, x) do { \ + if (verbose && (c)) \ + fprintf x; \ + } while (0) +# define Tracecv(c, x) do { \ + if (verbose > 1 && (c)) \ + fprintf x; \ + } while (0) #else -# define Assert(cond,msg) +# define Assert(cond, msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) +# define Tracec(c, x) +# define Tracecv(c, x) #endif static void flush_window(void); @@ -88,26 +102,27 @@ extern char *input_data; /* lives in head.S */ static long bytes_out = 0; static uch *output_data; static unsigned long output_ptr = 0; - + static void *malloc(int size); static void free(void *where); static void gzip_mark(void **); static void gzip_release(void **); - + static void puts(const char *); /* the "heap" is put directly after the BSS ends, at end */ - + extern int _end; static long free_mem_ptr = (long)&_end; - + #include "../../../../../lib/inflate.c" static void *malloc(int size) { void *p; - if (size <0) error("Malloc error"); + if (size < 0) + error("Malloc error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -137,48 +152,47 @@ static void puts(const char *s) { #ifndef CONFIG_ETRAX_DEBUG_PORT_NULL - while(*s) { + while (*s) { #ifdef CONFIG_ETRAX_DEBUG_PORT0 - while(!(*R_SERIAL0_STATUS & (1 << 5))) ; + while (!(*R_SERIAL0_STATUS & (1 << 5))) ; *R_SERIAL0_TR_DATA = *s++; #endif #ifdef CONFIG_ETRAX_DEBUG_PORT1 - while(!(*R_SERIAL1_STATUS & (1 << 5))) ; + while (!(*R_SERIAL1_STATUS & (1 << 5))) ; *R_SERIAL1_TR_DATA = *s++; #endif #ifdef CONFIG_ETRAX_DEBUG_PORT2 - while(!(*R_SERIAL2_STATUS & (1 << 5))) ; + while (!(*R_SERIAL2_STATUS & (1 << 5))) ; *R_SERIAL2_TR_DATA = *s++; #endif #ifdef CONFIG_ETRAX_DEBUG_PORT3 - while(!(*R_SERIAL3_STATUS & (1 << 5))) ; + while (!(*R_SERIAL3_STATUS & (1 << 5))) ; *R_SERIAL3_TR_DATA = *s++; #endif } #endif } -void* -memset(void* s, int c, size_t n) +void *memset(void *s, int c, size_t n) { int i; - char *ss = (char*)s; + char *ss = (char *)s; - for (i=0;i> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - output_ptr += (ulg)outcnt; - outcnt = 0; + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, *out, ch; + + in = window; + out = &output_data[output_ptr]; + for (n = 0; n < outcnt; n++) { + ch = *out = *in; + out++; + in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + output_ptr += (ulg)outcnt; + outcnt = 0; } -static void -error(char *x) +static void error(char *x) { puts("\n\n"); puts(x); puts("\n\n -- System halted\n"); - while(1); /* Halt */ + while (1); /* Halt */ } void setup_normal_output_buffer(void) @@ -223,7 +237,7 @@ void setup_normal_output_buffer(void) void decompress_kernel(void) { char revision; - + /* input_data is set in head.S */ inbuf = input_data; @@ -255,10 +269,9 @@ void decompress_kernel(void) makecrc(); __asm__ volatile ("move $vr,%0" : "=rm" (revision)); - if (revision < 10) - { + if (revision < 10) { puts("You need an ETRAX 100LX to run linux 2.6\n"); - while(1); + while (1); } puts("Uncompressing Linux...\n"); -- cgit v1.2.3-70-g09d2 From 75f10b465af9efd59906e9079ed9cbda7e0f7a43 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 22 May 2008 16:20:18 +0100 Subject: [ARM] 5047/2: Support resetting by asserting GPIO pin This adds support for resetting via assertion of GPIO pin. This e.g. is used on Sharp Zaurus SL-6000. Signed-off-by: Dmitry Baryshkov Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/Makefile | 2 +- arch/arm/mach-pxa/reset.c | 95 +++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-pxa/hardware.h | 5 ++ include/asm-arm/arch-pxa/system.h | 17 +------ 4 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 arch/arm/mach-pxa/reset.c (limited to 'arch') diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 0e6d05bb81a..c9e66fbe622 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -4,7 +4,7 @@ # Common support (must be linked before board specific support) obj-y += clock.o devices.o generic.o irq.o dma.o \ - time.o gpio.o + time.o gpio.o reset.o obj-$(CONFIG_PM) += pm.o sleep.o standby.o obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c new file mode 100644 index 00000000000..551f313c94d --- /dev/null +++ b/arch/arm/mach-pxa/reset.c @@ -0,0 +1,95 @@ +/* + * 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 + +static void do_hw_reset(void); + +static int reset_gpio = -1; + +int init_gpio_reset(int gpio) +{ + int rc; + + rc = gpio_request(gpio, "reset generator"); + if (rc) { + printk(KERN_ERR "Can't request reset_gpio\n"); + goto out; + } + + rc = gpio_direction_input(gpio); + if (rc) { + printk(KERN_ERR "Can't configure reset_gpio for input\n"); + gpio_free(gpio); + goto out; + } + +out: + if (!rc) + reset_gpio = gpio; + + return rc; +} + +/* + * Trigger GPIO reset. + * This covers various types of logic connecting gpio pin + * to RESET pins (nRESET or GPIO_RESET): + */ +static void do_gpio_reset(void) +{ + BUG_ON(reset_gpio == -1); + + /* drive it low */ + gpio_direction_output(reset_gpio, 0); + mdelay(2); + /* rising edge or drive high */ + gpio_set_value(reset_gpio, 1); + mdelay(2); + /* falling edge */ + gpio_set_value(reset_gpio, 0); + + /* give it some time */ + mdelay(10); + + WARN_ON(1); + /* fallback */ + do_hw_reset(); +} + +static void do_hw_reset(void) +{ + /* Initialize the watchdog and let it fire */ + OWER = OWER_WME; + OSSR = OSSR_M3; + OSMR3 = OSCR + 368640; /* ... in 100 ms */ +} + +void arch_reset(char mode) +{ + if (cpu_is_pxa2xx()) + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + switch (mode) { + case 's': + /* Jump into ROM at address 0 */ + cpu_reset(0); + break; + case 'h': + do_hw_reset(); + break; + case 'g': + do_gpio_reset(); + break; + } +} + diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index e25558faa5a..5547ec797ad 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h @@ -205,6 +205,11 @@ static inline void __deprecated pxa_set_cken(int clock, int enable) */ extern unsigned int get_memclk_frequency_10khz(void); +/* + * register GPIO as reset generator + */ +extern int init_gpio_reset(int gpio); + #endif #if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) diff --git a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h index 9aa6c2e939e..14894ae3fa6 100644 --- a/include/asm-arm/arch-pxa/system.h +++ b/include/asm-arm/arch-pxa/system.h @@ -20,19 +20,4 @@ static inline void arch_idle(void) } -static inline void arch_reset(char mode) -{ - if (cpu_is_pxa2xx()) - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; - - if (mode == 's') { - /* Jump into ROM at address 0 */ - cpu_reset(0); - } else { - /* Initialize the watchdog and let it fire */ - OWER = OWER_WME; - OSSR = OSSR_M3; - OSMR3 = OSCR + 368640; /* ... in 100 ms */ - } -} - +void arch_reset(char mode); -- cgit v1.2.3-70-g09d2 From 4d1fe075e5a84aaae00614cb23096336fda6374f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 29 May 2008 21:18:07 +0100 Subject: [ARM] 5069/1: pxa: include pxa2xx-regs.h in reset.c for RSCR The RCSR definition was moved into pxa2xx-regs.h. Signed-off-by: Philipp Zabel Acked-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/reset.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c index 551f313c94d..9d39dea57ce 100644 --- a/arch/arm/mach-pxa/reset.c +++ b/arch/arm/mach-pxa/reset.c @@ -11,6 +11,7 @@ #include #include +#include static void do_hw_reset(void); -- cgit v1.2.3-70-g09d2 From 86159a98adbb33682a4658c9b1eae95d9c9e25ed Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 22 May 2008 16:21:48 +0100 Subject: [ARM] 5048/2: Clean up tosa and spitz resetting Use new reset_gpio to reset tosa and spitz PDAs. Signed-off-by: Dmitry Baryshkov Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/spitz.c | 7 ++----- arch/arm/mach-pxa/tosa.c | 9 ++++----- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index dace3820f1e..d58c3e906a9 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -530,11 +530,7 @@ static struct platform_device *devices[] __initdata = { static void spitz_poweroff(void) { - pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT); - GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET); - - mdelay(1000); - arm_machine_restart('h'); + arm_machine_restart('g'); } static void spitz_restart(char mode) @@ -548,6 +544,7 @@ static void spitz_restart(char mode) static void __init common_init(void) { + init_gpio_reset(SPITZ_GPIO_ON_RESET); pm_power_off = spitz_poweroff; arm_pm_restart = spitz_restart; diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index c2cbd66db81..9ae2271f93c 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -467,11 +468,7 @@ static struct platform_device *devices[] __initdata = { static void tosa_poweroff(void) { - pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_OUT); - GPSR(TOSA_GPIO_ON_RESET) = GPIO_bit(TOSA_GPIO_ON_RESET); - - mdelay(1000); - arm_machine_restart('h'); + arm_machine_restart('g'); } static void tosa_restart(char mode) @@ -489,6 +486,8 @@ static void __init tosa_init(void) gpio_set_wake(MFP_PIN_GPIO1, 1); /* We can't pass to gpio-keys since it will drop the Reset altfunc */ + init_gpio_reset(TOSA_GPIO_ON_RESET); + pm_power_off = tosa_poweroff; arm_pm_restart = tosa_restart; -- cgit v1.2.3-70-g09d2 From c867155cde9905dfbcb16fcadb1840b06f8869d4 Mon Sep 17 00:00:00 2001 From: eric miao Date: Mon, 26 May 2008 03:28:50 +0100 Subject: [ARM] 5064/1: pxa: explicitly specify tosa keyboard GPIOs' low power states to DRIVE_LOW Signed-off-by: Eric Miao Acked-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 36 ++++++++++++++++++------------------ drivers/input/keyboard/tosakbd.c | 2 -- 2 files changed, 18 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 9ae2271f93c..8bf947dcb2e 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -130,24 +130,24 @@ static unsigned long tosa_pin_config[] = { GPIO47_STUART_TXD, /* Keybd */ - GPIO58_GPIO, - GPIO59_GPIO, - GPIO60_GPIO, - GPIO61_GPIO, - GPIO62_GPIO, - GPIO63_GPIO, - GPIO64_GPIO, - GPIO65_GPIO, - GPIO66_GPIO, - GPIO67_GPIO, - GPIO68_GPIO, - GPIO69_GPIO, - GPIO70_GPIO, - GPIO71_GPIO, - GPIO72_GPIO, - GPIO73_GPIO, - GPIO74_GPIO, - GPIO75_GPIO, + GPIO58_GPIO | MFP_LPM_DRIVE_LOW, + GPIO59_GPIO | MFP_LPM_DRIVE_LOW, + GPIO60_GPIO | MFP_LPM_DRIVE_LOW, + GPIO61_GPIO | MFP_LPM_DRIVE_LOW, + GPIO62_GPIO | MFP_LPM_DRIVE_LOW, + GPIO63_GPIO | MFP_LPM_DRIVE_LOW, + GPIO64_GPIO | MFP_LPM_DRIVE_LOW, + GPIO65_GPIO | MFP_LPM_DRIVE_LOW, + GPIO66_GPIO | MFP_LPM_DRIVE_LOW, + GPIO67_GPIO | MFP_LPM_DRIVE_LOW, + GPIO68_GPIO | MFP_LPM_DRIVE_LOW, + GPIO69_GPIO | MFP_LPM_DRIVE_LOW, + GPIO70_GPIO | MFP_LPM_DRIVE_LOW, + GPIO71_GPIO | MFP_LPM_DRIVE_LOW, + GPIO72_GPIO | MFP_LPM_DRIVE_LOW, + GPIO73_GPIO | MFP_LPM_DRIVE_LOW, + GPIO74_GPIO | MFP_LPM_DRIVE_LOW, + GPIO75_GPIO | MFP_LPM_DRIVE_LOW, /* SPI */ GPIO81_SSP2_CLK_OUT, diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c index 94e444b4ee1..b12b7ee4b6a 100644 --- a/drivers/input/keyboard/tosakbd.c +++ b/drivers/input/keyboard/tosakbd.c @@ -215,8 +215,6 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) unsigned long flags; spin_lock_irqsave(&tosakbd->lock, flags); - PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT); - PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT); tosakbd->suspended = 1; spin_unlock_irqrestore(&tosakbd->lock, flags); -- cgit v1.2.3-70-g09d2 From c4d5f8d43a5423a6bbba4eec1fab9c46e8d53c5d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 9 Jun 2008 13:23:50 +0100 Subject: [ARM] 5081/1: tosa: fix SD GPIOs This changes SD-related GPIO names to be more informative, and allocates two more SD-related GPIOs. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 8bf947dcb2e..ba95cd66b98 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -87,7 +87,7 @@ static unsigned long tosa_pin_config[] = { GPIO6_MMC_CLK, GPIO8_MMC_CS0, GPIO9_GPIO, /* Detect */ - // GPIO10 nSD_INT + GPIO10_GPIO, /* nSD_INT */ /* CF */ GPIO13_GPIO, /* CD_IRQ */ @@ -250,6 +250,15 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250); + err = gpio_request(TOSA_GPIO_nSD_DETECT, "MMC/SD card detect"); + if (err) { + printk(KERN_ERR "tosa_mci_init: can't request nSD_DETECT gpio\n"); + goto err_gpio_detect; + } + err = gpio_direction_input(TOSA_GPIO_nSD_DETECT); + if (err) + goto err_gpio_detect_dir; + err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "MMC/SD card detect", data); @@ -258,7 +267,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void goto err_irq; } - err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp"); + err = gpio_request(TOSA_GPIO_SD_WP, "SD Write Protect"); if (err) { printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n"); goto err_gpio_wp; @@ -267,7 +276,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void if (err) goto err_gpio_wp_dir; - err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr"); + err = gpio_request(TOSA_GPIO_PWR_ON, "SD Power"); if (err) { printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n"); goto err_gpio_pwr; @@ -276,8 +285,20 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void if (err) goto err_gpio_pwr_dir; + err = gpio_request(TOSA_GPIO_nSD_INT, "SD Int"); + if (err) { + printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n"); + goto err_gpio_int; + } + err = gpio_direction_input(TOSA_GPIO_nSD_INT); + if (err) + goto err_gpio_int_dir; + return 0; +err_gpio_int_dir: + gpio_free(TOSA_GPIO_nSD_INT); +err_gpio_int: err_gpio_pwr_dir: gpio_free(TOSA_GPIO_PWR_ON); err_gpio_pwr: @@ -286,6 +307,9 @@ err_gpio_wp_dir: err_gpio_wp: free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data); err_irq: +err_gpio_detect_dir: + gpio_free(TOSA_GPIO_nSD_DETECT); +err_gpio_detect: return err; } @@ -307,9 +331,11 @@ static int tosa_mci_get_ro(struct device *dev) static void tosa_mci_exit(struct device *dev, void *data) { + gpio_free(TOSA_GPIO_nSD_INT); gpio_free(TOSA_GPIO_PWR_ON); gpio_free(TOSA_GPIO_SD_WP); free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data); + gpio_free(TOSA_GPIO_nSD_DETECT); } static struct pxamci_platform_data tosa_mci_platform_data = { -- cgit v1.2.3-70-g09d2 From debba222b20c7e98d7875d9c70552b3094038ab2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 11 Jun 2008 13:27:24 +0100 Subject: [ARM] 5089/1: tosa: cleanup includes Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index ba95cd66b98..9892464d7ab 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -24,15 +24,9 @@ #include #include #include -#include #include -#include #include -#include -#include -#include -#include #include #include #include @@ -41,8 +35,6 @@ #include #include -#include -#include #include #include -- cgit v1.2.3-70-g09d2 From b032fccca80cbbedaa80e5a72a202a43f08aa97e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 12 Jun 2008 11:42:07 +0100 Subject: [ARM] 5083/2: Tosa: fix IrDA transciver powerup. On tosa the tranciver LED isn't powered down if the GPIO47 (STUART_TX) isn't configured as low-level. Power it down if IrDA is off to save a bit of power. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 58 ++++++++++++++++++++++++++++++++--------- include/asm-arm/arch-pxa/tosa.h | 1 + 2 files changed, 47 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 9892464d7ab..7a89f764acf 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -117,10 +117,6 @@ static unsigned long tosa_pin_config[] = { GPIO44_BTUART_CTS, GPIO45_BTUART_RTS, - /* IrDA */ - GPIO46_STUART_RXD, - GPIO47_STUART_TXD, - /* Keybd */ GPIO58_GPIO | MFP_LPM_DRIVE_LOW, GPIO59_GPIO | MFP_LPM_DRIVE_LOW, @@ -147,6 +143,17 @@ static unsigned long tosa_pin_config[] = { GPIO83_SSP2_TXD, }; +static unsigned long tosa_pin_irda_off[] = { + GPIO46_STUART_RXD, + GPIO47_GPIO | MFP_LPM_DRIVE_LOW, +}; + +static unsigned long tosa_pin_irda_on[] = { + GPIO46_STUART_RXD, + GPIO47_STUART_TXD, +}; + + /* * SCOOP Device */ @@ -341,29 +348,55 @@ static struct pxamci_platform_data tosa_mci_platform_data = { /* * Irda */ +static void tosa_irda_transceiver_mode(struct device *dev, int mode) +{ + if (mode & IR_OFF) { + gpio_set_value(TOSA_GPIO_IR_POWERDWN, 0); + pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_off)); + gpio_direction_output(TOSA_GPIO_IRDA_TX, 0); + } else { + pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_on)); + gpio_set_value(TOSA_GPIO_IR_POWERDWN, 1); + } +} + static int tosa_irda_startup(struct device *dev) { int ret; + ret = gpio_request(TOSA_GPIO_IRDA_TX, "IrDA TX"); + if (ret) + goto err_tx; + ret = gpio_direction_output(TOSA_GPIO_IRDA_TX, 0); + if (ret) + goto err_tx_dir; + ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown"); if (ret) - return ret; + goto err_pwr; ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0); if (ret) - gpio_free(TOSA_GPIO_IR_POWERDWN); + goto err_pwr_dir; - return ret; - } + tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF); -static void tosa_irda_shutdown(struct device *dev) -{ + return 0; + +err_pwr_dir: gpio_free(TOSA_GPIO_IR_POWERDWN); +err_pwr: +err_tx_dir: + gpio_free(TOSA_GPIO_IRDA_TX); +err_tx: + return ret; } -static void tosa_irda_transceiver_mode(struct device *dev, int mode) +static void tosa_irda_shutdown(struct device *dev) { - gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF)); + tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF); + gpio_free(TOSA_GPIO_IR_POWERDWN); + gpio_free(TOSA_GPIO_IRDA_TX); } static struct pxaficp_platform_data tosa_ficp_platform_data = { @@ -501,6 +534,7 @@ static void tosa_restart(char mode) static void __init tosa_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_off)); gpio_set_wake(MFP_PIN_GPIO1, 1); /* We can't pass to gpio-keys since it will drop the Reset altfunc */ diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h index c5b6fde6907..18822621615 100644 --- a/include/asm-arm/arch-pxa/tosa.h +++ b/include/asm-arm/arch-pxa/tosa.h @@ -99,6 +99,7 @@ #define TOSA_GPIO_TP_INT (32) /* Touch Panel pen down interrupt */ #define TOSA_GPIO_JC_CF_IRQ (36) /* CF slot1 Ready */ #define TOSA_GPIO_BAT_LOCKED (38) /* Battery locked */ +#define TOSA_GPIO_IRDA_TX (47) #define TOSA_GPIO_TG_SPI_SCLK (81) #define TOSA_GPIO_TG_SPI_CS (82) #define TOSA_GPIO_TG_SPI_MOSI (83) -- cgit v1.2.3-70-g09d2 From bf0116e54e185fd63025f2b975f0f1616ffe41f1 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 14 Jun 2008 11:42:02 +0100 Subject: [ARM] 5097/1: Tosa: support TC6393XB device Add definitions for Toshiba TC6393XB companion chip and register the tc6393xb device. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 127 ++++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-pxa/irqs.h | 1 + include/asm-arm/arch-pxa/tosa.h | 44 +++++++++----- 3 files changed, 158 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 7a89f764acf..2fe0998ac3f 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -18,7 +18,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -509,9 +512,127 @@ static struct platform_device tosaled_device = { }, }; +/* + * Toshiba Mobile IO Controller + */ +static struct resource tc6393xb_resources[] = { + [0] = { + .start = TOSA_LCDC_PHYS, + .end = TOSA_LCDC_PHYS + 0x3ffffff, + .flags = IORESOURCE_MEM, + }, + + [1] = { + .start = TOSA_IRQ_GPIO_TC6393XB_INT, + .end = TOSA_IRQ_GPIO_TC6393XB_INT, + .flags = IORESOURCE_IRQ, + }, +}; + + +static int tosa_tc6393xb_enable(struct platform_device *dev) +{ + int rc; + + rc = gpio_request(TOSA_GPIO_TC6393XB_REST_IN, "tc6393xb #pclr"); + if (rc) + goto err_req_pclr; + rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend"); + if (rc) + goto err_req_suspend; + rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v"); + if (rc) + goto err_req_l3v; + rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0); + if (rc) + goto err_dir_l3v; + rc = gpio_direction_output(TOSA_GPIO_TC6393XB_SUSPEND, 0); + if (rc) + goto err_dir_suspend; + rc = gpio_direction_output(TOSA_GPIO_TC6393XB_REST_IN, 0); + if (rc) + goto err_dir_pclr; + + mdelay(1); + + gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1); + + mdelay(10); + + gpio_set_value(TOSA_GPIO_TC6393XB_REST_IN, 1); + gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1); + + return 0; +err_dir_pclr: +err_dir_suspend: +err_dir_l3v: + gpio_free(TOSA_GPIO_TC6393XB_L3V_ON); +err_req_l3v: + gpio_free(TOSA_GPIO_TC6393XB_SUSPEND); +err_req_suspend: + gpio_free(TOSA_GPIO_TC6393XB_REST_IN); +err_req_pclr: + return rc; +} + +static int tosa_tc6393xb_disable(struct platform_device *dev) +{ + gpio_free(TOSA_GPIO_TC6393XB_L3V_ON); + gpio_free(TOSA_GPIO_TC6393XB_SUSPEND); + gpio_free(TOSA_GPIO_TC6393XB_REST_IN); + + return 0; +} + +static int tosa_tc6393xb_resume(struct platform_device *dev) +{ + gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1); + mdelay(10); + gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1); + mdelay(10); + + return 0; +} + +static int tosa_tc6393xb_suspend(struct platform_device *dev) +{ + gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 0); + gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 0); + return 0; +} + +static struct tc6393xb_platform_data tosa_tc6393xb_setup = { + .scr_pll2cr = 0x0cc1, + .scr_gper = 0x3300, + .scr_gpo_dsr = + TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON), + .scr_gpo_doecr = + TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON), + + .irq_base = IRQ_BOARD_START, + .gpio_base = TOSA_TC6393XB_GPIO_BASE, + + .enable = tosa_tc6393xb_enable, + .disable = tosa_tc6393xb_disable, + .suspend = tosa_tc6393xb_suspend, + .resume = tosa_tc6393xb_resume, +}; + + +static struct platform_device tc6393xb_device = { + .name = "tc6393xb", + .id = -1, + .dev = { + .platform_data = &tosa_tc6393xb_setup, + }, + .num_resources = ARRAY_SIZE(tc6393xb_resources), + .resource = tc6393xb_resources, +}; + static struct platform_device *devices[] __initdata = { &tosascoop_device, &tosascoop_jc_device, + &tc6393xb_device, &tosakbd_device, &tosa_gpio_keys_device, &tosaled_device, @@ -533,6 +654,8 @@ static void tosa_restart(char mode) static void __init tosa_init(void) { + int dummy; + pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config)); pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_off)); gpio_set_wake(MFP_PIN_GPIO1, 1); @@ -548,6 +671,10 @@ static void __init tosa_init(void) /* enable batt_fault */ PMCR = 0x01; + dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12); + dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12); + dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16); + pxa_set_mci_info(&tosa_mci_platform_data); pxa_set_udc_info(&udc_info); pxa_set_ficp_info(&tosa_ficp_platform_data); diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index b6c8fe37768..fa05e76f64e 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h @@ -180,6 +180,7 @@ #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) #elif defined(CONFIG_ARCH_LUBBOCK) || \ defined(CONFIG_MACH_LOGICPD_PXA270) || \ + defined(CONFIG_MACH_TOSA) || \ defined(CONFIG_MACH_MAINSTONE) || \ defined(CONFIG_MACH_PCM027) || \ defined(CONFIG_MACH_MAGICIAN) diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h index 18822621615..a16c103b725 100644 --- a/include/asm-arm/arch-pxa/tosa.h +++ b/include/asm-arm/arch-pxa/tosa.h @@ -25,7 +25,7 @@ */ #define TOSA_SCOOP_GPIO_BASE NR_BUILTIN_GPIO #define TOSA_SCOOP_PXA_VCORE1 SCOOP_GPCR_PA11 -#define TOSA_SCOOP_TC6393_REST_IN SCOOP_GPCR_PA12 +#define TOSA_GPIO_TC6393XB_REST_IN (TOSA_SCOOP_GPIO_BASE + 1) #define TOSA_GPIO_IR_POWERDWN (TOSA_SCOOP_GPIO_BASE + 2) #define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3) #define TOSA_GPIO_PWR_ON (TOSA_SCOOP_GPIO_BASE + 4) @@ -35,11 +35,9 @@ #define TOSA_SCOOP_AC_IN_OL SCOOP_GPCR_PA19 /* GPIO Direction 1 : output mode / 0:input mode */ -#define TOSA_SCOOP_IO_DIR ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \ +#define TOSA_SCOOP_IO_DIR (TOSA_SCOOP_PXA_VCORE1 | \ TOSA_SCOOP_AUD_PWR_ON |\ - TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN ) -/* GPIO out put level when init 1: Hi */ -#define TOSA_SCOOP_IO_OUT ( TOSA_SCOOP_TC6393_REST_IN ) + TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN) /* * SCOOP2 jacket GPIOs @@ -49,16 +47,34 @@ #define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1) #define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2) #define TOSA_GPIO_USB_PULLUP (TOSA_SCOOP_JC_GPIO_BASE + 3) -#define TOSA_SCOOP_JC_TC6393_SUSPEND SCOOP_GPCR_PA15 -#define TOSA_SCOOP_JC_TC3693_L3V_ON SCOOP_GPCR_PA16 +#define TOSA_GPIO_TC6393XB_SUSPEND (TOSA_SCOOP_JC_GPIO_BASE + 4) +#define TOSA_GPIO_TC6393XB_L3V_ON (TOSA_SCOOP_JC_GPIO_BASE + 5) #define TOSA_SCOOP_JC_WLAN_DETECT SCOOP_GPCR_PA17 #define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7) #define TOSA_SCOOP_JC_CARD_LIMIT_SEL SCOOP_GPCR_PA19 /* GPIO Direction 1 : output mode / 0:input mode */ -#define TOSA_SCOOP_JC_IO_DIR ( \ - TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \ - TOSA_SCOOP_JC_CARD_LIMIT_SEL ) +#define TOSA_SCOOP_JC_IO_DIR (TOSA_SCOOP_JC_CARD_LIMIT_SEL) + +/* + * TC6393XB GPIOs + */ +#define TOSA_TC6393XB_GPIO_BASE (NR_BUILTIN_GPIO + 2 * 12) +#define TOSA_TC6393XB_GPIO(i) (TOSA_TC6393XB_GPIO_BASE + (i)) +#define TOSA_TC6393XB_GPIO_BIT(gpio) (1 << (gpio - TOSA_TC6393XB_GPIO_BASE)) + +#define TOSA_GPIO_TG_ON (TOSA_TC6393XB_GPIO_BASE + 0) +#define TOSA_GPIO_L_MUTE (TOSA_TC6393XB_GPIO_BASE + 1) +#define TOSA_GPIO_BL_C20MA (TOSA_TC6393XB_GPIO_BASE + 3) +#define TOSA_GPIO_CARD_VCC_ON (TOSA_TC6393XB_GPIO_BASE + 4) +#define TOSA_GPIO_CHARGE_OFF (TOSA_TC6393XB_GPIO_BASE + 6) +#define TOSA_GPIO_CHARGE_OFF_JC (TOSA_TC6393XB_GPIO_BASE + 7) +#define TOSA_GPIO_BAT0_V_ON (TOSA_TC6393XB_GPIO_BASE + 9) +#define TOSA_GPIO_BAT1_V_ON (TOSA_TC6393XB_GPIO_BASE + 10) +#define TOSA_GPIO_BU_CHRG_ON (TOSA_TC6393XB_GPIO_BASE + 11) +#define TOSA_GPIO_BAT_SW_ON (TOSA_TC6393XB_GPIO_BASE + 12) +#define TOSA_GPIO_BAT0_TH_ON (TOSA_TC6393XB_GPIO_BASE + 14) +#define TOSA_GPIO_BAT1_TH_ON (TOSA_TC6393XB_GPIO_BASE + 15) /* * Timing Generator @@ -84,13 +100,13 @@ #define TOSA_GPIO_JACKET_DETECT (7) #define TOSA_GPIO_nSD_DETECT (9) #define TOSA_GPIO_nSD_INT (10) -#define TOSA_GPIO_TC6393_CLK (11) +#define TOSA_GPIO_TC6393XB_CLK (11) #define TOSA_GPIO_BAT1_CRG (12) #define TOSA_GPIO_CF_CD (13) #define TOSA_GPIO_BAT0_CRG (14) -#define TOSA_GPIO_TC6393_INT (15) +#define TOSA_GPIO_TC6393XB_INT (15) #define TOSA_GPIO_BAT0_LOW (17) -#define TOSA_GPIO_TC6393_RDY (18) +#define TOSA_GPIO_TC6393XB_RDY (18) #define TOSA_GPIO_ON_RESET (19) #define TOSA_GPIO_EAR_IN (20) #define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */ @@ -138,7 +154,7 @@ #define TOSA_IRQ_GPIO_BAT1_CRG IRQ_GPIO(TOSA_GPIO_BAT1_CRG) #define TOSA_IRQ_GPIO_CF_CD IRQ_GPIO(TOSA_GPIO_CF_CD) #define TOSA_IRQ_GPIO_BAT0_CRG IRQ_GPIO(TOSA_GPIO_BAT0_CRG) -#define TOSA_IRQ_GPIO_TC6393_INT IRQ_GPIO(TOSA_GPIO_TC6393_INT) +#define TOSA_IRQ_GPIO_TC6393XB_INT IRQ_GPIO(TOSA_GPIO_TC6393XB_INT) #define TOSA_IRQ_GPIO_BAT0_LOW IRQ_GPIO(TOSA_GPIO_BAT0_LOW) #define TOSA_IRQ_GPIO_EAR_IN IRQ_GPIO(TOSA_GPIO_EAR_IN) #define TOSA_IRQ_GPIO_CF_IRQ IRQ_GPIO(TOSA_GPIO_CF_IRQ) -- cgit v1.2.3-70-g09d2 From 53b14ea336ca45f34821ad78a1b45c2315283621 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 14 Jun 2008 11:43:36 +0100 Subject: [ARM] 5099/1: Tosa: support AC-in detection. Add support for ac-in via pda_power device. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 2fe0998ac3f..f3b12d2897a 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -409,6 +410,70 @@ static struct pxaficp_platform_data tosa_ficp_platform_data = { .shutdown = tosa_irda_shutdown, }; +/* + * Tosa AC IN + */ +static int tosa_power_init(struct device *dev) +{ + int ret = gpio_request(TOSA_GPIO_AC_IN, "ac in"); + if (ret) + goto err_gpio_req; + + ret = gpio_direction_input(TOSA_GPIO_AC_IN); + if (ret) + goto err_gpio_in; + + return 0; + +err_gpio_in: + gpio_free(TOSA_GPIO_AC_IN); +err_gpio_req: + return ret; +} + +static void tosa_power_exit(struct device *dev) +{ + gpio_free(TOSA_GPIO_AC_IN); +} + +static int tosa_power_ac_online(void) +{ + return gpio_get_value(TOSA_GPIO_AC_IN) == 0; +} + +static char *tosa_ac_supplied_to[] = { + "main-battery", + "backup-battery", + "jacket-battery", +}; + +static struct pda_power_pdata tosa_power_data = { + .init = tosa_power_init, + .is_ac_online = tosa_power_ac_online, + .exit = tosa_power_exit, + .supplied_to = tosa_ac_supplied_to, + .num_supplicants = ARRAY_SIZE(tosa_ac_supplied_to), +}; + +static struct resource tosa_power_resource[] = { + { + .name = "ac", + .start = gpio_to_irq(TOSA_GPIO_AC_IN), + .end = gpio_to_irq(TOSA_GPIO_AC_IN), + .flags = IORESOURCE_IRQ | + IORESOURCE_IRQ_HIGHEDGE | + IORESOURCE_IRQ_LOWEDGE, + }, +}; + +static struct platform_device tosa_power_device = { + .name = "pda-power", + .id = -1, + .dev.platform_data = &tosa_power_data, + .resource = tosa_power_resource, + .num_resources = ARRAY_SIZE(tosa_power_resource), +}; + /* * Tosa Keyboard */ @@ -633,6 +698,7 @@ static struct platform_device *devices[] __initdata = { &tosascoop_device, &tosascoop_jc_device, &tc6393xb_device, + &tosa_power_device, &tosakbd_device, &tosa_gpio_keys_device, &tosaled_device, -- cgit v1.2.3-70-g09d2 From 5289fecda021828af85fccc8cc2613a85d0fcf52 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 27 Jun 2008 10:38:44 +0100 Subject: [ARM] 5129/1: tosa: tmio-nand data Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index f3b12d2897a..fa903e7ae62 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -666,6 +669,39 @@ static int tosa_tc6393xb_suspend(struct platform_device *dev) return 0; } +static struct mtd_partition tosa_nand_partition[] = { + { + .name = "smf", + .offset = 0, + .size = 7 * 1024 * 1024, + }, + { + .name = "root", + .offset = MTDPART_OFS_APPEND, + .size = 28 * 1024 * 1024, + }, + { + .name = "home", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr tosa_tc6393xb_nand_bbt = { + .options = 0, + .offs = 4, + .len = 2, + .pattern = scan_ff_pattern +}; + +static struct tmio_nand_data tosa_tc6393xb_nand_config = { + .num_partitions = ARRAY_SIZE(tosa_nand_partition), + .partition = tosa_nand_partition, + .badblock_pattern = &tosa_tc6393xb_nand_bbt, +}; + static struct tc6393xb_platform_data tosa_tc6393xb_setup = { .scr_pll2cr = 0x0cc1, .scr_gper = 0x3300, @@ -681,6 +717,8 @@ static struct tc6393xb_platform_data tosa_tc6393xb_setup = { .disable = tosa_tc6393xb_disable, .suspend = tosa_tc6393xb_suspend, .resume = tosa_tc6393xb_resume, + + .nand_data = &tosa_tc6393xb_nand_config, }; -- cgit v1.2.3-70-g09d2 From 16b32fd0a35b30cbd67395cfcbd360354db44f39 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 5 Jul 2008 09:02:48 +0100 Subject: [ARM] 5150/1: Tosa: support built-in bluetooth power-up The driver is pretty much generic and will be later shared with a few other devices, like hx4700 ipaq. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/Kconfig | 8 ++ arch/arm/mach-pxa/Makefile | 2 + arch/arm/mach-pxa/tosa-bt.c | 150 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-pxa/tosa.c | 17 ++++- include/asm-arm/arch-pxa/tosa.h | 7 +- include/asm-arm/arch-pxa/tosa_bt.h | 22 ++++++ 6 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-pxa/tosa-bt.c create mode 100644 include/asm-arm/arch-pxa/tosa_bt.h (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 5da7a682049..6c162f8fdce 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -273,4 +273,12 @@ config PXA_SSP tristate help Enable support for PXA2xx SSP ports + +config TOSA_BT + tristate "Control the state of built-in bluetooth chip on Sharp SL-6000" + depends on MACH_TOSA + select RFKILL + help + This is a simple driver that is able to control + the state of built in bluetooth chip on tosa. endif diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index c9e66fbe622..18e0b249f7c 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -58,3 +58,5 @@ obj-$(CONFIG_LEDS) += $(led-y) ifeq ($(CONFIG_PCI),y) obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o endif + +obj-$(CONFIG_TOSA_BT) += tosa-bt.o diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c new file mode 100644 index 00000000000..7d8505466e5 --- /dev/null +++ b/arch/arm/mach-pxa/tosa-bt.c @@ -0,0 +1,150 @@ +/* + * Bluetooth built-in chip control + * + * Copyright (c) 2008 Dmitry Baryshkov + * + * 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 + +static void tosa_bt_on(struct tosa_bt_data *data) +{ + gpio_set_value(data->gpio_reset, 0); + gpio_set_value(data->gpio_pwr, 1); + gpio_set_value(data->gpio_reset, 1); + mdelay(20); + gpio_set_value(data->gpio_reset, 0); +} + +static void tosa_bt_off(struct tosa_bt_data *data) +{ + gpio_set_value(data->gpio_reset, 1); + mdelay(10); + gpio_set_value(data->gpio_pwr, 0); + gpio_set_value(data->gpio_reset, 0); +} + +static int tosa_bt_toggle_radio(void *data, enum rfkill_state state) +{ + pr_info("BT_RADIO going: %s\n", + state == RFKILL_STATE_ON ? "on" : "off"); + + if (state == RFKILL_STATE_ON) { + pr_info("TOSA_BT: going ON\n"); + tosa_bt_on(data); + } else { + pr_info("TOSA_BT: going OFF\n"); + tosa_bt_off(data); + } + return 0; +} + +static int tosa_bt_probe(struct platform_device *dev) +{ + int rc; + struct rfkill *rfk; + + struct tosa_bt_data *data = dev->dev.platform_data; + + rc = gpio_request(data->gpio_reset, "Bluetooth reset"); + if (rc) + goto err_reset; + rc = gpio_direction_output(data->gpio_reset, 0); + if (rc) + goto err_reset_dir; + rc = gpio_request(data->gpio_pwr, "Bluetooth power"); + if (rc) + goto err_pwr; + rc = gpio_direction_output(data->gpio_pwr, 0); + if (rc) + goto err_pwr_dir; + + rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH); + if (!rfk) { + rc = -ENOMEM; + goto err_rfk_alloc; + } + + rfk->name = "tosa-bt"; + rfk->toggle_radio = tosa_bt_toggle_radio; + rfk->data = data; +#ifdef CONFIG_RFKILL_LEDS + rfk->led_trigger.name = "tosa-bt"; +#endif + + rc = rfkill_register(rfk); + if (rc) + goto err_rfkill; + + platform_set_drvdata(dev, rfk); + + return 0; + +err_rfkill: + if (rfk) + rfkill_free(rfk); + rfk = NULL; +err_rfk_alloc: + tosa_bt_off(data); +err_pwr_dir: + gpio_free(data->gpio_pwr); +err_pwr: +err_reset_dir: + gpio_free(data->gpio_reset); +err_reset: + return rc; +} + +static int __devexit tosa_bt_remove(struct platform_device *dev) +{ + struct tosa_bt_data *data = dev->dev.platform_data; + struct rfkill *rfk = platform_get_drvdata(dev); + + platform_set_drvdata(dev, NULL); + + if (rfk) + rfkill_unregister(rfk); + rfk = NULL; + + tosa_bt_off(data); + + gpio_free(data->gpio_pwr); + gpio_free(data->gpio_reset); + + return 0; +} + +static struct platform_driver tosa_bt_driver = { + .probe = tosa_bt_probe, + .remove = __devexit_p(tosa_bt_remove), + + .driver = { + .name = "tosa-bt", + .owner = THIS_MODULE, + }, +}; + + +static int __init tosa_bt_init(void) +{ + return platform_driver_register(&tosa_bt_driver); +} + +static void __exit tosa_bt_exit(void) +{ + platform_driver_unregister(&tosa_bt_driver); +} + +module_init(tosa_bt_init); +module_exit(tosa_bt_exit); diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index fa903e7ae62..5a9d329f504 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include #include @@ -562,7 +564,7 @@ static struct gpio_led tosa_gpio_leds[] = { }, { .name = "tosa:blue:bluetooth", - .default_trigger = "none", + .default_trigger = "tosa-bt", .gpio = TOSA_GPIO_BT_LED, }, }; @@ -732,6 +734,18 @@ static struct platform_device tc6393xb_device = { .resource = tc6393xb_resources, }; +static struct tosa_bt_data tosa_bt_data = { + .gpio_pwr = TOSA_GPIO_BT_PWR_EN, + .gpio_reset = TOSA_GPIO_BT_RESET, +}; + +static struct platform_device tosa_bt_device = { + .name = "tosa-bt", + .id = -1, + .dev.platform_data = &tosa_bt_data, +}; + + static struct platform_device *devices[] __initdata = { &tosascoop_device, &tosascoop_jc_device, @@ -740,6 +754,7 @@ static struct platform_device *devices[] __initdata = { &tosakbd_device, &tosa_gpio_keys_device, &tosaled_device, + &tosa_bt_device, }; static void tosa_poweroff(void) diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h index a16c103b725..a72803f0461 100644 --- a/include/asm-arm/arch-pxa/tosa.h +++ b/include/asm-arm/arch-pxa/tosa.h @@ -30,14 +30,13 @@ #define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3) #define TOSA_GPIO_PWR_ON (TOSA_SCOOP_GPIO_BASE + 4) #define TOSA_SCOOP_AUD_PWR_ON SCOOP_GPCR_PA16 -#define TOSA_SCOOP_BT_RESET SCOOP_GPCR_PA17 -#define TOSA_SCOOP_BT_PWR_EN SCOOP_GPCR_PA18 +#define TOSA_GPIO_BT_RESET (TOSA_SCOOP_GPIO_BASE + 6) +#define TOSA_GPIO_BT_PWR_EN (TOSA_SCOOP_GPIO_BASE + 7) #define TOSA_SCOOP_AC_IN_OL SCOOP_GPCR_PA19 /* GPIO Direction 1 : output mode / 0:input mode */ #define TOSA_SCOOP_IO_DIR (TOSA_SCOOP_PXA_VCORE1 | \ - TOSA_SCOOP_AUD_PWR_ON |\ - TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN) + TOSA_SCOOP_AUD_PWR_ON) /* * SCOOP2 jacket GPIOs diff --git a/include/asm-arm/arch-pxa/tosa_bt.h b/include/asm-arm/arch-pxa/tosa_bt.h new file mode 100644 index 00000000000..efc3c3d3b75 --- /dev/null +++ b/include/asm-arm/arch-pxa/tosa_bt.h @@ -0,0 +1,22 @@ +/* + * Tosa bluetooth built-in chip control. + * + * Later it may be shared with some other platforms. + * + * Copyright (c) 2008 Dmitry Baryshkov + * + * 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. + * + */ +#ifndef TOSA_BT_H +#define TOSA_BT_H + +struct tosa_bt_data { + int gpio_pwr; + int gpio_reset; +}; + +#endif + -- cgit v1.2.3-70-g09d2 From 0121702dbaf961b4c996f2579d4286a0a1ed877c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 7 Jul 2008 10:09:29 +0100 Subject: [ARM] 5151/1: Tosa: remove double inclusion of linux/delay.h The patch applies to the linux-next tree. Signed-off-by: Alexander Beregalov Acked-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 5a9d329f504..2d49de572ba 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-70-g09d2 From 3bfb1d20b547a5071d01344581eac5846ea84491 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 8 Jul 2008 11:59:42 -0700 Subject: dmaengine: Driver for the Synopsys DesignWare DMA controller This adds a driver for the Synopsys DesignWare DMA controller (aka DMACA on AVR32 systems.) This DMA controller can be found integrated on the AT32AP7000 chip and is primarily meant for peripheral DMA transfer, but can also be used for memory-to-memory transfers. This patch is based on a driver from David Brownell which was based on an older version of the DMA Engine framework. It also implements the proposed extensions to the DMA Engine API for slave DMA operations. The dmatest client shows no problems, but there may still be room for improvement performance-wise. DMA slave transfer performance is definitely "good enough"; reading 100 MiB from an SD card running at ~20 MHz yields ~7.2 MiB/s average transfer rate. Full documentation for this controller can be found in the Synopsys DW AHB DMAC Databook: http://www.synopsys.com/designware/docs/iip/DW_ahb_dmac/latest/doc/dw_ahb_dmac_db.pdf The controller has lots of implementation options, so it's usually a good idea to check the data sheet of the chip it's intergrated on as well. The AT32AP7000 data sheet can be found here: http://www.atmel.com/dyn/products/datasheets.asp?family_id=682 Changes since v4: * Use client_count instead of dma_chan_is_in_use() * Add missing include * Unmap buffers unless client told us not to Changes since v3: * Update to latest DMA engine and DMA slave APIs * Embed the hw descriptor into the sw descriptor * Clean up and update MODULE_DESCRIPTION, copyright date, etc. Changes since v2: * Dequeue all pending transfers in terminate_all() * Rename dw_dmac.h -> dw_dmac_regs.h * Define and use controller-specific dma_slave data * Fix up a few outdated comments * Define hardware registers as structs (doesn't generate better code, unfortunately, but it looks nicer.) * Get number of channels from platform_data instead of hardcoding it based on CONFIG_WHATEVER_CPU. * Give slave clients exclusive access to the channel Acked-by: Maciej Sosnowski , Signed-off-by: Haavard Skinnemoen Signed-off-by: Dan Williams --- arch/avr32/mach-at32ap/at32ap700x.c | 27 +- drivers/dma/Kconfig | 9 + drivers/dma/Makefile | 1 + drivers/dma/dw_dmac.c | 1122 ++++++++++++++++++++++++++++ drivers/dma/dw_dmac_regs.h | 225 ++++++ include/asm-avr32/arch-at32ap/at32ap700x.h | 16 + include/linux/dw_dmac.h | 62 ++ 7 files changed, 1449 insertions(+), 13 deletions(-) create mode 100644 drivers/dma/dw_dmac.c create mode 100644 drivers/dma/dw_dmac_regs.h create mode 100644 include/linux/dw_dmac.h (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 0f24b4f85c1..892e27e0d58 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -7,6 +7,7 @@ */ #include #include +#include #include #include #include @@ -599,6 +600,17 @@ static void __init genclk_init_parent(struct clk *clk) clk->parent = parent; } +static struct dw_dma_platform_data dw_dmac0_data = { + .nr_channels = 3, +}; + +static struct resource dw_dmac0_resource[] = { + PBMEM(0xff200000), + IRQ(2), +}; +DEFINE_DEV_DATA(dw_dmac, 0); +DEV_CLK(hclk, dw_dmac0, hsb, 10); + /* -------------------------------------------------------------------- * System peripherals * -------------------------------------------------------------------- */ @@ -705,17 +717,6 @@ static struct clk pico_clk = { .users = 1, }; -static struct resource dmaca0_resource[] = { - { - .start = 0xff200000, - .end = 0xff20ffff, - .flags = IORESOURCE_MEM, - }, - IRQ(2), -}; -DEFINE_DEV(dmaca, 0); -DEV_CLK(hclk, dmaca0, hsb, 10); - /* -------------------------------------------------------------------- * HMATRIX * -------------------------------------------------------------------- */ @@ -828,7 +829,7 @@ void __init at32_add_system_devices(void) platform_device_register(&at32_eic0_device); platform_device_register(&smc0_device); platform_device_register(&pdc_device); - platform_device_register(&dmaca0_device); + platform_device_register(&dw_dmac0_device); platform_device_register(&at32_tcb0_device); platform_device_register(&at32_tcb1_device); @@ -1891,7 +1892,7 @@ struct clk *at32_clock_list[] = { &smc0_mck, &pdc_hclk, &pdc_pclk, - &dmaca0_hclk, + &dw_dmac0_hclk, &pico_clk, &pio0_mck, &pio1_mck, diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 4b6bd3d099c..cd303901eb5 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -38,6 +38,15 @@ config INTEL_IOP_ADMA help Enable support for the Intel(R) IOP Series RAID engines. +config DW_DMAC + tristate "Synopsys DesignWare AHB DMA support" + depends on AVR32 + select DMA_ENGINE + default y if CPU_AT32AP7000 + help + Support the Synopsys DesignWare AHB DMA controller. This + can be integrated in chips such as the Atmel AT32ap7000. + config FSL_DMA bool "Freescale MPC85xx/MPC83xx DMA support" depends on PPC diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 181e3646fbf..14f59527d4f 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -6,3 +6,4 @@ ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_FSL_DMA) += fsldma.o obj-$(CONFIG_MV_XOR) += mv_xor.o +obj-$(CONFIG_DW_DMAC) += dw_dmac.o diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c new file mode 100644 index 00000000000..94df9177124 --- /dev/null +++ b/drivers/dma/dw_dmac.c @@ -0,0 +1,1122 @@ +/* + * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on + * AVR32 systems.) + * + * Copyright (C) 2007-2008 Atmel Corporation + * + * 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 "dw_dmac_regs.h" + +/* + * This supports the Synopsys "DesignWare AHB Central DMA Controller", + * (DW_ahb_dmac) which is used with various AMBA 2.0 systems (not all + * of which use ARM any more). See the "Databook" from Synopsys for + * information beyond what licensees probably provide. + * + * The driver has currently been tested only with the Atmel AT32AP7000, + * which does not support descriptor writeback. + */ + +/* NOTE: DMS+SMS is system-specific. We should get this information + * from the platform code somehow. + */ +#define DWC_DEFAULT_CTLLO (DWC_CTLL_DST_MSIZE(0) \ + | DWC_CTLL_SRC_MSIZE(0) \ + | DWC_CTLL_DMS(0) \ + | DWC_CTLL_SMS(1) \ + | DWC_CTLL_LLP_D_EN \ + | DWC_CTLL_LLP_S_EN) + +/* + * This is configuration-dependent and usually a funny size like 4095. + * Let's round it down to the nearest power of two. + * + * Note that this is a transfer count, i.e. if we transfer 32-bit + * words, we can do 8192 bytes per descriptor. + * + * This parameter is also system-specific. + */ +#define DWC_MAX_COUNT 2048U + +/* + * Number of descriptors to allocate for each channel. This should be + * made configurable somehow; preferably, the clients (at least the + * ones using slave transfers) should be able to give us a hint. + */ +#define NR_DESCS_PER_CHANNEL 64 + +/*----------------------------------------------------------------------*/ + +/* + * Because we're not relying on writeback from the controller (it may not + * even be configured into the core!) we don't need to use dma_pool. These + * descriptors -- and associated data -- are cacheable. We do need to make + * sure their dcache entries are written back before handing them off to + * the controller, though. + */ + +static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc) +{ + return list_entry(dwc->active_list.next, struct dw_desc, desc_node); +} + +static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc) +{ + return list_entry(dwc->queue.next, struct dw_desc, desc_node); +} + +static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc) +{ + struct dw_desc *desc, *_desc; + struct dw_desc *ret = NULL; + unsigned int i = 0; + + spin_lock_bh(&dwc->lock); + list_for_each_entry_safe(desc, _desc, &dwc->free_list, desc_node) { + if (async_tx_test_ack(&desc->txd)) { + list_del(&desc->desc_node); + ret = desc; + break; + } + dev_dbg(&dwc->chan.dev, "desc %p not ACKed\n", desc); + i++; + } + spin_unlock_bh(&dwc->lock); + + dev_vdbg(&dwc->chan.dev, "scanned %u descriptors on freelist\n", i); + + return ret; +} + +static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc) +{ + struct dw_desc *child; + + list_for_each_entry(child, &desc->txd.tx_list, desc_node) + dma_sync_single_for_cpu(dwc->chan.dev.parent, + child->txd.phys, sizeof(child->lli), + DMA_TO_DEVICE); + dma_sync_single_for_cpu(dwc->chan.dev.parent, + desc->txd.phys, sizeof(desc->lli), + DMA_TO_DEVICE); +} + +/* + * Move a descriptor, including any children, to the free list. + * `desc' must not be on any lists. + */ +static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) +{ + if (desc) { + struct dw_desc *child; + + dwc_sync_desc_for_cpu(dwc, desc); + + spin_lock_bh(&dwc->lock); + list_for_each_entry(child, &desc->txd.tx_list, desc_node) + dev_vdbg(&dwc->chan.dev, + "moving child desc %p to freelist\n", + child); + list_splice_init(&desc->txd.tx_list, &dwc->free_list); + dev_vdbg(&dwc->chan.dev, "moving desc %p to freelist\n", desc); + list_add(&desc->desc_node, &dwc->free_list); + spin_unlock_bh(&dwc->lock); + } +} + +/* Called with dwc->lock held and bh disabled */ +static dma_cookie_t +dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc) +{ + dma_cookie_t cookie = dwc->chan.cookie; + + if (++cookie < 0) + cookie = 1; + + dwc->chan.cookie = cookie; + desc->txd.cookie = cookie; + + return cookie; +} + +/*----------------------------------------------------------------------*/ + +/* Called with dwc->lock held and bh disabled */ +static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) +{ + struct dw_dma *dw = to_dw_dma(dwc->chan.device); + + /* ASSERT: channel is idle */ + if (dma_readl(dw, CH_EN) & dwc->mask) { + dev_err(&dwc->chan.dev, + "BUG: Attempted to start non-idle channel\n"); + dev_err(&dwc->chan.dev, + " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n", + channel_readl(dwc, SAR), + channel_readl(dwc, DAR), + channel_readl(dwc, LLP), + channel_readl(dwc, CTL_HI), + channel_readl(dwc, CTL_LO)); + + /* The tasklet will hopefully advance the queue... */ + return; + } + + channel_writel(dwc, LLP, first->txd.phys); + channel_writel(dwc, CTL_LO, + DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); + channel_writel(dwc, CTL_HI, 0); + channel_set_bit(dw, CH_EN, dwc->mask); +} + +/*----------------------------------------------------------------------*/ + +static void +dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc) +{ + dma_async_tx_callback callback; + void *param; + struct dma_async_tx_descriptor *txd = &desc->txd; + + dev_vdbg(&dwc->chan.dev, "descriptor %u complete\n", txd->cookie); + + dwc->completed = txd->cookie; + callback = txd->callback; + param = txd->callback_param; + + dwc_sync_desc_for_cpu(dwc, desc); + list_splice_init(&txd->tx_list, &dwc->free_list); + list_move(&desc->desc_node, &dwc->free_list); + + /* + * We use dma_unmap_page() regardless of how the buffers were + * mapped before they were submitted... + */ + if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) + dma_unmap_page(dwc->chan.dev.parent, desc->lli.dar, desc->len, + DMA_FROM_DEVICE); + if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) + dma_unmap_page(dwc->chan.dev.parent, desc->lli.sar, desc->len, + DMA_TO_DEVICE); + + /* + * The API requires that no submissions are done from a + * callback, so we don't need to drop the lock here + */ + if (callback) + callback(param); +} + +static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) +{ + struct dw_desc *desc, *_desc; + LIST_HEAD(list); + + if (dma_readl(dw, CH_EN) & dwc->mask) { + dev_err(&dwc->chan.dev, + "BUG: XFER bit set, but channel not idle!\n"); + + /* Try to continue after resetting the channel... */ + channel_clear_bit(dw, CH_EN, dwc->mask); + while (dma_readl(dw, CH_EN) & dwc->mask) + cpu_relax(); + } + + /* + * Submit queued descriptors ASAP, i.e. before we go through + * the completed ones. + */ + if (!list_empty(&dwc->queue)) + dwc_dostart(dwc, dwc_first_queued(dwc)); + list_splice_init(&dwc->active_list, &list); + list_splice_init(&dwc->queue, &dwc->active_list); + + list_for_each_entry_safe(desc, _desc, &list, desc_node) + dwc_descriptor_complete(dwc, desc); +} + +static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) +{ + dma_addr_t llp; + struct dw_desc *desc, *_desc; + struct dw_desc *child; + u32 status_xfer; + + /* + * Clear block interrupt flag before scanning so that we don't + * miss any, and read LLP before RAW_XFER to ensure it is + * valid if we decide to scan the list. + */ + dma_writel(dw, CLEAR.BLOCK, dwc->mask); + llp = channel_readl(dwc, LLP); + status_xfer = dma_readl(dw, RAW.XFER); + + if (status_xfer & dwc->mask) { + /* Everything we've submitted is done */ + dma_writel(dw, CLEAR.XFER, dwc->mask); + dwc_complete_all(dw, dwc); + return; + } + + dev_vdbg(&dwc->chan.dev, "scan_descriptors: llp=0x%x\n", llp); + + list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) { + if (desc->lli.llp == llp) + /* This one is currently in progress */ + return; + + list_for_each_entry(child, &desc->txd.tx_list, desc_node) + if (child->lli.llp == llp) + /* Currently in progress */ + return; + + /* + * No descriptors so far seem to be in progress, i.e. + * this one must be done. + */ + dwc_descriptor_complete(dwc, desc); + } + + dev_err(&dwc->chan.dev, + "BUG: All descriptors done, but channel not idle!\n"); + + /* Try to continue after resetting the channel... */ + channel_clear_bit(dw, CH_EN, dwc->mask); + while (dma_readl(dw, CH_EN) & dwc->mask) + cpu_relax(); + + if (!list_empty(&dwc->queue)) { + dwc_dostart(dwc, dwc_first_queued(dwc)); + list_splice_init(&dwc->queue, &dwc->active_list); + } +} + +static void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli) +{ + dev_printk(KERN_CRIT, &dwc->chan.dev, + " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", + lli->sar, lli->dar, lli->llp, + lli->ctlhi, lli->ctllo); +} + +static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) +{ + struct dw_desc *bad_desc; + struct dw_desc *child; + + dwc_scan_descriptors(dw, dwc); + + /* + * The descriptor currently at the head of the active list is + * borked. Since we don't have any way to report errors, we'll + * just have to scream loudly and try to carry on. + */ + bad_desc = dwc_first_active(dwc); + list_del_init(&bad_desc->desc_node); + list_splice_init(&dwc->queue, dwc->active_list.prev); + + /* Clear the error flag and try to restart the controller */ + dma_writel(dw, CLEAR.ERROR, dwc->mask); + if (!list_empty(&dwc->active_list)) + dwc_dostart(dwc, dwc_first_active(dwc)); + + /* + * KERN_CRITICAL may seem harsh, but since this only happens + * when someone submits a bad physical address in a + * descriptor, we should consider ourselves lucky that the + * controller flagged an error instead of scribbling over + * random memory locations. + */ + dev_printk(KERN_CRIT, &dwc->chan.dev, + "Bad descriptor submitted for DMA!\n"); + dev_printk(KERN_CRIT, &dwc->chan.dev, + " cookie: %d\n", bad_desc->txd.cookie); + dwc_dump_lli(dwc, &bad_desc->lli); + list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node) + dwc_dump_lli(dwc, &child->lli); + + /* Pretend the descriptor completed successfully */ + dwc_descriptor_complete(dwc, bad_desc); +} + +static void dw_dma_tasklet(unsigned long data) +{ + struct dw_dma *dw = (struct dw_dma *)data; + struct dw_dma_chan *dwc; + u32 status_block; + u32 status_xfer; + u32 status_err; + int i; + + status_block = dma_readl(dw, RAW.BLOCK); + status_xfer = dma_readl(dw, RAW.BLOCK); + status_err = dma_readl(dw, RAW.ERROR); + + dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n", + status_block, status_err); + + for (i = 0; i < dw->dma.chancnt; i++) { + dwc = &dw->chan[i]; + spin_lock(&dwc->lock); + if (status_err & (1 << i)) + dwc_handle_error(dw, dwc); + else if ((status_block | status_xfer) & (1 << i)) + dwc_scan_descriptors(dw, dwc); + spin_unlock(&dwc->lock); + } + + /* + * Re-enable interrupts. Block Complete interrupts are only + * enabled if the INT_EN bit in the descriptor is set. This + * will trigger a scan before the whole list is done. + */ + channel_set_bit(dw, MASK.XFER, dw->all_chan_mask); + channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask); + channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask); +} + +static irqreturn_t dw_dma_interrupt(int irq, void *dev_id) +{ + struct dw_dma *dw = dev_id; + u32 status; + + dev_vdbg(dw->dma.dev, "interrupt: status=0x%x\n", + dma_readl(dw, STATUS_INT)); + + /* + * Just disable the interrupts. We'll turn them back on in the + * softirq handler. + */ + channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); + channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); + channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); + + status = dma_readl(dw, STATUS_INT); + if (status) { + dev_err(dw->dma.dev, + "BUG: Unexpected interrupts pending: 0x%x\n", + status); + + /* Try to recover */ + channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1); + channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1); + channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1); + channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1); + channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1); + } + + tasklet_schedule(&dw->tasklet); + + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------*/ + +static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct dw_desc *desc = txd_to_dw_desc(tx); + struct dw_dma_chan *dwc = to_dw_dma_chan(tx->chan); + dma_cookie_t cookie; + + spin_lock_bh(&dwc->lock); + cookie = dwc_assign_cookie(dwc, desc); + + /* + * REVISIT: We should attempt to chain as many descriptors as + * possible, perhaps even appending to those already submitted + * for DMA. But this is hard to do in a race-free manner. + */ + if (list_empty(&dwc->active_list)) { + dev_vdbg(&tx->chan->dev, "tx_submit: started %u\n", + desc->txd.cookie); + dwc_dostart(dwc, desc); + list_add_tail(&desc->desc_node, &dwc->active_list); + } else { + dev_vdbg(&tx->chan->dev, "tx_submit: queued %u\n", + desc->txd.cookie); + + list_add_tail(&desc->desc_node, &dwc->queue); + } + + spin_unlock_bh(&dwc->lock); + + return cookie; +} + +static struct dma_async_tx_descriptor * +dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, + size_t len, unsigned long flags) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_desc *desc; + struct dw_desc *first; + struct dw_desc *prev; + size_t xfer_count; + size_t offset; + unsigned int src_width; + unsigned int dst_width; + u32 ctllo; + + dev_vdbg(&chan->dev, "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n", + dest, src, len, flags); + + if (unlikely(!len)) { + dev_dbg(&chan->dev, "prep_dma_memcpy: length is zero!\n"); + return NULL; + } + + /* + * We can be a lot more clever here, but this should take care + * of the most common optimization. + */ + if (!((src | dest | len) & 3)) + src_width = dst_width = 2; + else if (!((src | dest | len) & 1)) + src_width = dst_width = 1; + else + src_width = dst_width = 0; + + ctllo = DWC_DEFAULT_CTLLO + | DWC_CTLL_DST_WIDTH(dst_width) + | DWC_CTLL_SRC_WIDTH(src_width) + | DWC_CTLL_DST_INC + | DWC_CTLL_SRC_INC + | DWC_CTLL_FC_M2M; + prev = first = NULL; + + for (offset = 0; offset < len; offset += xfer_count << src_width) { + xfer_count = min_t(size_t, (len - offset) >> src_width, + DWC_MAX_COUNT); + + desc = dwc_desc_get(dwc); + if (!desc) + goto err_desc_get; + + desc->lli.sar = src + offset; + desc->lli.dar = dest + offset; + desc->lli.ctllo = ctllo; + desc->lli.ctlhi = xfer_count; + + if (!first) { + first = desc; + } else { + prev->lli.llp = desc->txd.phys; + dma_sync_single_for_device(chan->dev.parent, + prev->txd.phys, sizeof(prev->lli), + DMA_TO_DEVICE); + list_add_tail(&desc->desc_node, + &first->txd.tx_list); + } + prev = desc; + } + + + if (flags & DMA_PREP_INTERRUPT) + /* Trigger interrupt after last block */ + prev->lli.ctllo |= DWC_CTLL_INT_EN; + + prev->lli.llp = 0; + dma_sync_single_for_device(chan->dev.parent, + prev->txd.phys, sizeof(prev->lli), + DMA_TO_DEVICE); + + first->txd.flags = flags; + first->len = len; + + return &first->txd; + +err_desc_get: + dwc_desc_put(dwc, first); + return NULL; +} + +static struct dma_async_tx_descriptor * +dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_data_direction direction, + unsigned long flags) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma_slave *dws = dwc->dws; + struct dw_desc *prev; + struct dw_desc *first; + u32 ctllo; + dma_addr_t reg; + unsigned int reg_width; + unsigned int mem_width; + unsigned int i; + struct scatterlist *sg; + size_t total_len = 0; + + dev_vdbg(&chan->dev, "prep_dma_slave\n"); + + if (unlikely(!dws || !sg_len)) + return NULL; + + reg_width = dws->slave.reg_width; + prev = first = NULL; + + sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction); + + switch (direction) { + case DMA_TO_DEVICE: + ctllo = (DWC_DEFAULT_CTLLO + | DWC_CTLL_DST_WIDTH(reg_width) + | DWC_CTLL_DST_FIX + | DWC_CTLL_SRC_INC + | DWC_CTLL_FC_M2P); + reg = dws->slave.tx_reg; + for_each_sg(sgl, sg, sg_len, i) { + struct dw_desc *desc; + u32 len; + u32 mem; + + desc = dwc_desc_get(dwc); + if (!desc) { + dev_err(&chan->dev, + "not enough descriptors available\n"); + goto err_desc_get; + } + + mem = sg_phys(sg); + len = sg_dma_len(sg); + mem_width = 2; + if (unlikely(mem & 3 || len & 3)) + mem_width = 0; + + desc->lli.sar = mem; + desc->lli.dar = reg; + desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width); + desc->lli.ctlhi = len >> mem_width; + + if (!first) { + first = desc; + } else { + prev->lli.llp = desc->txd.phys; + dma_sync_single_for_device(chan->dev.parent, + prev->txd.phys, + sizeof(prev->lli), + DMA_TO_DEVICE); + list_add_tail(&desc->desc_node, + &first->txd.tx_list); + } + prev = desc; + total_len += len; + } + break; + case DMA_FROM_DEVICE: + ctllo = (DWC_DEFAULT_CTLLO + | DWC_CTLL_SRC_WIDTH(reg_width) + | DWC_CTLL_DST_INC + | DWC_CTLL_SRC_FIX + | DWC_CTLL_FC_P2M); + + reg = dws->slave.rx_reg; + for_each_sg(sgl, sg, sg_len, i) { + struct dw_desc *desc; + u32 len; + u32 mem; + + desc = dwc_desc_get(dwc); + if (!desc) { + dev_err(&chan->dev, + "not enough descriptors available\n"); + goto err_desc_get; + } + + mem = sg_phys(sg); + len = sg_dma_len(sg); + mem_width = 2; + if (unlikely(mem & 3 || len & 3)) + mem_width = 0; + + desc->lli.sar = reg; + desc->lli.dar = mem; + desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width); + desc->lli.ctlhi = len >> reg_width; + + if (!first) { + first = desc; + } else { + prev->lli.llp = desc->txd.phys; + dma_sync_single_for_device(chan->dev.parent, + prev->txd.phys, + sizeof(prev->lli), + DMA_TO_DEVICE); + list_add_tail(&desc->desc_node, + &first->txd.tx_list); + } + prev = desc; + total_len += len; + } + break; + default: + return NULL; + } + + if (flags & DMA_PREP_INTERRUPT) + /* Trigger interrupt after last block */ + prev->lli.ctllo |= DWC_CTLL_INT_EN; + + prev->lli.llp = 0; + dma_sync_single_for_device(chan->dev.parent, + prev->txd.phys, sizeof(prev->lli), + DMA_TO_DEVICE); + + first->len = total_len; + + return &first->txd; + +err_desc_get: + dwc_desc_put(dwc, first); + return NULL; +} + +static void dwc_terminate_all(struct dma_chan *chan) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma *dw = to_dw_dma(chan->device); + struct dw_desc *desc, *_desc; + LIST_HEAD(list); + + /* + * This is only called when something went wrong elsewhere, so + * we don't really care about the data. Just disable the + * channel. We still have to poll the channel enable bit due + * to AHB/HSB limitations. + */ + spin_lock_bh(&dwc->lock); + + channel_clear_bit(dw, CH_EN, dwc->mask); + + while (dma_readl(dw, CH_EN) & dwc->mask) + cpu_relax(); + + /* active_list entries will end up before queued entries */ + list_splice_init(&dwc->queue, &list); + list_splice_init(&dwc->active_list, &list); + + spin_unlock_bh(&dwc->lock); + + /* Flush all pending and queued descriptors */ + list_for_each_entry_safe(desc, _desc, &list, desc_node) + dwc_descriptor_complete(dwc, desc); +} + +static enum dma_status +dwc_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, + dma_cookie_t *done, dma_cookie_t *used) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + dma_cookie_t last_used; + dma_cookie_t last_complete; + int ret; + + last_complete = dwc->completed; + last_used = chan->cookie; + + ret = dma_async_is_complete(cookie, last_complete, last_used); + if (ret != DMA_SUCCESS) { + dwc_scan_descriptors(to_dw_dma(chan->device), dwc); + + last_complete = dwc->completed; + last_used = chan->cookie; + + ret = dma_async_is_complete(cookie, last_complete, last_used); + } + + if (done) + *done = last_complete; + if (used) + *used = last_used; + + return ret; +} + +static void dwc_issue_pending(struct dma_chan *chan) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + + spin_lock_bh(&dwc->lock); + if (!list_empty(&dwc->queue)) + dwc_scan_descriptors(to_dw_dma(chan->device), dwc); + spin_unlock_bh(&dwc->lock); +} + +static int dwc_alloc_chan_resources(struct dma_chan *chan, + struct dma_client *client) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma *dw = to_dw_dma(chan->device); + struct dw_desc *desc; + struct dma_slave *slave; + struct dw_dma_slave *dws; + int i; + u32 cfghi; + u32 cfglo; + + dev_vdbg(&chan->dev, "alloc_chan_resources\n"); + + /* Channels doing slave DMA can only handle one client. */ + if (dwc->dws || client->slave) { + if (chan->client_count) + return -EBUSY; + } + + /* ASSERT: channel is idle */ + if (dma_readl(dw, CH_EN) & dwc->mask) { + dev_dbg(&chan->dev, "DMA channel not idle?\n"); + return -EIO; + } + + dwc->completed = chan->cookie = 1; + + cfghi = DWC_CFGH_FIFO_MODE; + cfglo = 0; + + slave = client->slave; + if (slave) { + /* + * We need controller-specific data to set up slave + * transfers. + */ + BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev); + + dws = container_of(slave, struct dw_dma_slave, slave); + + dwc->dws = dws; + cfghi = dws->cfg_hi; + cfglo = dws->cfg_lo; + } else { + dwc->dws = NULL; + } + + channel_writel(dwc, CFG_LO, cfglo); + channel_writel(dwc, CFG_HI, cfghi); + + /* + * NOTE: some controllers may have additional features that we + * need to initialize here, like "scatter-gather" (which + * doesn't mean what you think it means), and status writeback. + */ + + spin_lock_bh(&dwc->lock); + i = dwc->descs_allocated; + while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) { + spin_unlock_bh(&dwc->lock); + + desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL); + if (!desc) { + dev_info(&chan->dev, + "only allocated %d descriptors\n", i); + spin_lock_bh(&dwc->lock); + break; + } + + dma_async_tx_descriptor_init(&desc->txd, chan); + desc->txd.tx_submit = dwc_tx_submit; + desc->txd.flags = DMA_CTRL_ACK; + INIT_LIST_HEAD(&desc->txd.tx_list); + desc->txd.phys = dma_map_single(chan->dev.parent, &desc->lli, + sizeof(desc->lli), DMA_TO_DEVICE); + dwc_desc_put(dwc, desc); + + spin_lock_bh(&dwc->lock); + i = ++dwc->descs_allocated; + } + + /* Enable interrupts */ + channel_set_bit(dw, MASK.XFER, dwc->mask); + channel_set_bit(dw, MASK.BLOCK, dwc->mask); + channel_set_bit(dw, MASK.ERROR, dwc->mask); + + spin_unlock_bh(&dwc->lock); + + dev_dbg(&chan->dev, + "alloc_chan_resources allocated %d descriptors\n", i); + + return i; +} + +static void dwc_free_chan_resources(struct dma_chan *chan) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma *dw = to_dw_dma(chan->device); + struct dw_desc *desc, *_desc; + LIST_HEAD(list); + + dev_dbg(&chan->dev, "free_chan_resources (descs allocated=%u)\n", + dwc->descs_allocated); + + /* ASSERT: channel is idle */ + BUG_ON(!list_empty(&dwc->active_list)); + BUG_ON(!list_empty(&dwc->queue)); + BUG_ON(dma_readl(to_dw_dma(chan->device), CH_EN) & dwc->mask); + + spin_lock_bh(&dwc->lock); + list_splice_init(&dwc->free_list, &list); + dwc->descs_allocated = 0; + dwc->dws = NULL; + + /* Disable interrupts */ + channel_clear_bit(dw, MASK.XFER, dwc->mask); + channel_clear_bit(dw, MASK.BLOCK, dwc->mask); + channel_clear_bit(dw, MASK.ERROR, dwc->mask); + + spin_unlock_bh(&dwc->lock); + + list_for_each_entry_safe(desc, _desc, &list, desc_node) { + dev_vdbg(&chan->dev, " freeing descriptor %p\n", desc); + dma_unmap_single(chan->dev.parent, desc->txd.phys, + sizeof(desc->lli), DMA_TO_DEVICE); + kfree(desc); + } + + dev_vdbg(&chan->dev, "free_chan_resources done\n"); +} + +/*----------------------------------------------------------------------*/ + +static void dw_dma_off(struct dw_dma *dw) +{ + dma_writel(dw, CFG, 0); + + channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); + channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); + channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask); + channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask); + channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); + + while (dma_readl(dw, CFG) & DW_CFG_DMA_EN) + cpu_relax(); +} + +static int __init dw_probe(struct platform_device *pdev) +{ + struct dw_dma_platform_data *pdata; + struct resource *io; + struct dw_dma *dw; + size_t size; + int irq; + int err; + int i; + + pdata = pdev->dev.platform_data; + if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) + return -EINVAL; + + io = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!io) + return -EINVAL; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + size = sizeof(struct dw_dma); + size += pdata->nr_channels * sizeof(struct dw_dma_chan); + dw = kzalloc(size, GFP_KERNEL); + if (!dw) + return -ENOMEM; + + if (!request_mem_region(io->start, DW_REGLEN, pdev->dev.driver->name)) { + err = -EBUSY; + goto err_kfree; + } + + memset(dw, 0, sizeof *dw); + + dw->regs = ioremap(io->start, DW_REGLEN); + if (!dw->regs) { + err = -ENOMEM; + goto err_release_r; + } + + dw->clk = clk_get(&pdev->dev, "hclk"); + if (IS_ERR(dw->clk)) { + err = PTR_ERR(dw->clk); + goto err_clk; + } + clk_enable(dw->clk); + + /* force dma off, just in case */ + dw_dma_off(dw); + + err = request_irq(irq, dw_dma_interrupt, 0, "dw_dmac", dw); + if (err) + goto err_irq; + + platform_set_drvdata(pdev, dw); + + tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); + + dw->all_chan_mask = (1 << pdata->nr_channels) - 1; + + INIT_LIST_HEAD(&dw->dma.channels); + for (i = 0; i < pdata->nr_channels; i++, dw->dma.chancnt++) { + struct dw_dma_chan *dwc = &dw->chan[i]; + + dwc->chan.device = &dw->dma; + dwc->chan.cookie = dwc->completed = 1; + dwc->chan.chan_id = i; + list_add_tail(&dwc->chan.device_node, &dw->dma.channels); + + dwc->ch_regs = &__dw_regs(dw)->CHAN[i]; + spin_lock_init(&dwc->lock); + dwc->mask = 1 << i; + + INIT_LIST_HEAD(&dwc->active_list); + INIT_LIST_HEAD(&dwc->queue); + INIT_LIST_HEAD(&dwc->free_list); + + channel_clear_bit(dw, CH_EN, dwc->mask); + } + + /* Clear/disable all interrupts on all channels. */ + dma_writel(dw, CLEAR.XFER, dw->all_chan_mask); + dma_writel(dw, CLEAR.BLOCK, dw->all_chan_mask); + dma_writel(dw, CLEAR.SRC_TRAN, dw->all_chan_mask); + dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask); + dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask); + + channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); + channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); + channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask); + channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask); + channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); + + dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); + dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); + dw->dma.dev = &pdev->dev; + dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; + dw->dma.device_free_chan_resources = dwc_free_chan_resources; + + dw->dma.device_prep_dma_memcpy = dwc_prep_dma_memcpy; + + dw->dma.device_prep_slave_sg = dwc_prep_slave_sg; + dw->dma.device_terminate_all = dwc_terminate_all; + + dw->dma.device_is_tx_complete = dwc_is_tx_complete; + dw->dma.device_issue_pending = dwc_issue_pending; + + dma_writel(dw, CFG, DW_CFG_DMA_EN); + + printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n", + pdev->dev.bus_id, dw->dma.chancnt); + + dma_async_device_register(&dw->dma); + + return 0; + +err_irq: + clk_disable(dw->clk); + clk_put(dw->clk); +err_clk: + iounmap(dw->regs); + dw->regs = NULL; +err_release_r: + release_resource(io); +err_kfree: + kfree(dw); + return err; +} + +static int __exit dw_remove(struct platform_device *pdev) +{ + struct dw_dma *dw = platform_get_drvdata(pdev); + struct dw_dma_chan *dwc, *_dwc; + struct resource *io; + + dw_dma_off(dw); + dma_async_device_unregister(&dw->dma); + + free_irq(platform_get_irq(pdev, 0), dw); + tasklet_kill(&dw->tasklet); + + list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels, + chan.device_node) { + list_del(&dwc->chan.device_node); + channel_clear_bit(dw, CH_EN, dwc->mask); + } + + clk_disable(dw->clk); + clk_put(dw->clk); + + iounmap(dw->regs); + dw->regs = NULL; + + io = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(io->start, DW_REGLEN); + + kfree(dw); + + return 0; +} + +static void dw_shutdown(struct platform_device *pdev) +{ + struct dw_dma *dw = platform_get_drvdata(pdev); + + dw_dma_off(platform_get_drvdata(pdev)); + clk_disable(dw->clk); +} + +static int dw_suspend_late(struct platform_device *pdev, pm_message_t mesg) +{ + struct dw_dma *dw = platform_get_drvdata(pdev); + + dw_dma_off(platform_get_drvdata(pdev)); + clk_disable(dw->clk); + return 0; +} + +static int dw_resume_early(struct platform_device *pdev) +{ + struct dw_dma *dw = platform_get_drvdata(pdev); + + clk_enable(dw->clk); + dma_writel(dw, CFG, DW_CFG_DMA_EN); + return 0; + +} + +static struct platform_driver dw_driver = { + .remove = __exit_p(dw_remove), + .shutdown = dw_shutdown, + .suspend_late = dw_suspend_late, + .resume_early = dw_resume_early, + .driver = { + .name = "dw_dmac", + }, +}; + +static int __init dw_init(void) +{ + return platform_driver_probe(&dw_driver, dw_probe); +} +module_init(dw_init); + +static void __exit dw_exit(void) +{ + platform_driver_unregister(&dw_driver); +} +module_exit(dw_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver"); +MODULE_AUTHOR("Haavard Skinnemoen "); diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h new file mode 100644 index 00000000000..00fdd187bb0 --- /dev/null +++ b/drivers/dma/dw_dmac_regs.h @@ -0,0 +1,225 @@ +/* + * Driver for the Synopsys DesignWare AHB DMA Controller + * + * Copyright (C) 2005-2007 Atmel Corporation + * + * 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 + +#define DW_DMA_MAX_NR_CHANNELS 8 + +/* + * Redefine this macro to handle differences between 32- and 64-bit + * addressing, big vs. little endian, etc. + */ +#define DW_REG(name) u32 name; u32 __pad_##name + +/* Hardware register definitions. */ +struct dw_dma_chan_regs { + DW_REG(SAR); /* Source Address Register */ + DW_REG(DAR); /* Destination Address Register */ + DW_REG(LLP); /* Linked List Pointer */ + u32 CTL_LO; /* Control Register Low */ + u32 CTL_HI; /* Control Register High */ + DW_REG(SSTAT); + DW_REG(DSTAT); + DW_REG(SSTATAR); + DW_REG(DSTATAR); + u32 CFG_LO; /* Configuration Register Low */ + u32 CFG_HI; /* Configuration Register High */ + DW_REG(SGR); + DW_REG(DSR); +}; + +struct dw_dma_irq_regs { + DW_REG(XFER); + DW_REG(BLOCK); + DW_REG(SRC_TRAN); + DW_REG(DST_TRAN); + DW_REG(ERROR); +}; + +struct dw_dma_regs { + /* per-channel registers */ + struct dw_dma_chan_regs CHAN[DW_DMA_MAX_NR_CHANNELS]; + + /* irq handling */ + struct dw_dma_irq_regs RAW; /* r */ + struct dw_dma_irq_regs STATUS; /* r (raw & mask) */ + struct dw_dma_irq_regs MASK; /* rw (set = irq enabled) */ + struct dw_dma_irq_regs CLEAR; /* w (ack, affects "raw") */ + + DW_REG(STATUS_INT); /* r */ + + /* software handshaking */ + DW_REG(REQ_SRC); + DW_REG(REQ_DST); + DW_REG(SGL_REQ_SRC); + DW_REG(SGL_REQ_DST); + DW_REG(LAST_SRC); + DW_REG(LAST_DST); + + /* miscellaneous */ + DW_REG(CFG); + DW_REG(CH_EN); + DW_REG(ID); + DW_REG(TEST); + + /* optional encoded params, 0x3c8..0x3 */ +}; + +/* Bitfields in CTL_LO */ +#define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ +#define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ +#define DWC_CTLL_SRC_WIDTH(n) ((n)<<4) +#define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */ +#define DWC_CTLL_DST_DEC (1<<7) +#define DWC_CTLL_DST_FIX (2<<7) +#define DWC_CTLL_SRC_INC (0<<7) /* SAR update/not */ +#define DWC_CTLL_SRC_DEC (1<<9) +#define DWC_CTLL_SRC_FIX (2<<9) +#define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ +#define DWC_CTLL_SRC_MSIZE(n) ((n)<<14) +#define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */ +#define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */ +#define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */ +#define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */ +#define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */ +#define DWC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */ +/* plus 4 transfer types for peripheral-as-flow-controller */ +#define DWC_CTLL_DMS(n) ((n)<<23) /* dst master select */ +#define DWC_CTLL_SMS(n) ((n)<<25) /* src master select */ +#define DWC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */ +#define DWC_CTLL_LLP_S_EN (1 << 28) /* src block chain */ + +/* Bitfields in CTL_HI */ +#define DWC_CTLH_DONE 0x00001000 +#define DWC_CTLH_BLOCK_TS_MASK 0x00000fff + +/* Bitfields in CFG_LO. Platform-configurable bits are in */ +#define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ +#define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ +#define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ +#define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */ +#define DWC_CFGL_MAX_BURST(x) ((x) << 20) +#define DWC_CFGL_RELOAD_SAR (1 << 30) +#define DWC_CFGL_RELOAD_DAR (1 << 31) + +/* Bitfields in CFG_HI. Platform-configurable bits are in */ +#define DWC_CFGH_DS_UPD_EN (1 << 5) +#define DWC_CFGH_SS_UPD_EN (1 << 6) + +/* Bitfields in SGR */ +#define DWC_SGR_SGI(x) ((x) << 0) +#define DWC_SGR_SGC(x) ((x) << 20) + +/* Bitfields in DSR */ +#define DWC_DSR_DSI(x) ((x) << 0) +#define DWC_DSR_DSC(x) ((x) << 20) + +/* Bitfields in CFG */ +#define DW_CFG_DMA_EN (1 << 0) + +#define DW_REGLEN 0x400 + +struct dw_dma_chan { + struct dma_chan chan; + void __iomem *ch_regs; + u8 mask; + + spinlock_t lock; + + /* these other elements are all protected by lock */ + dma_cookie_t completed; + struct list_head active_list; + struct list_head queue; + struct list_head free_list; + + struct dw_dma_slave *dws; + + unsigned int descs_allocated; +}; + +static inline struct dw_dma_chan_regs __iomem * +__dwc_regs(struct dw_dma_chan *dwc) +{ + return dwc->ch_regs; +} + +#define channel_readl(dwc, name) \ + __raw_readl(&(__dwc_regs(dwc)->name)) +#define channel_writel(dwc, name, val) \ + __raw_writel((val), &(__dwc_regs(dwc)->name)) + +static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) +{ + return container_of(chan, struct dw_dma_chan, chan); +} + + +struct dw_dma { + struct dma_device dma; + void __iomem *regs; + struct tasklet_struct tasklet; + struct clk *clk; + + u8 all_chan_mask; + + struct dw_dma_chan chan[0]; +}; + +static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw) +{ + return dw->regs; +} + +#define dma_readl(dw, name) \ + __raw_readl(&(__dw_regs(dw)->name)) +#define dma_writel(dw, name, val) \ + __raw_writel((val), &(__dw_regs(dw)->name)) + +#define channel_set_bit(dw, reg, mask) \ + dma_writel(dw, reg, ((mask) << 8) | (mask)) +#define channel_clear_bit(dw, reg, mask) \ + dma_writel(dw, reg, ((mask) << 8) | 0) + +static inline struct dw_dma *to_dw_dma(struct dma_device *ddev) +{ + return container_of(ddev, struct dw_dma, dma); +} + +/* LLI == Linked List Item; a.k.a. DMA block descriptor */ +struct dw_lli { + /* values that are not changed by hardware */ + dma_addr_t sar; + dma_addr_t dar; + dma_addr_t llp; /* chain to next lli */ + u32 ctllo; + /* values that may get written back: */ + u32 ctlhi; + /* sstat and dstat can snapshot peripheral register state. + * silicon config may discard either or both... + */ + u32 sstat; + u32 dstat; +}; + +struct dw_desc { + /* FIRST values the hardware uses */ + struct dw_lli lli; + + /* THEN values for driver housekeeping */ + struct list_head desc_node; + struct dma_async_tx_descriptor txd; + size_t len; +}; + +static inline struct dw_desc * +txd_to_dw_desc(struct dma_async_tx_descriptor *txd) +{ + return container_of(txd, struct dw_desc, txd); +} diff --git a/include/asm-avr32/arch-at32ap/at32ap700x.h b/include/asm-avr32/arch-at32ap/at32ap700x.h index 31e48b0e732..d18a3053be0 100644 --- a/include/asm-avr32/arch-at32ap/at32ap700x.h +++ b/include/asm-avr32/arch-at32ap/at32ap700x.h @@ -30,4 +30,20 @@ #define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N)) #define GPIO_PIN_PE(N) (GPIO_PIOE_BASE + (N)) + +/* + * DMAC peripheral hardware handshaking interfaces, used with dw_dmac + */ +#define DMAC_MCI_RX 0 +#define DMAC_MCI_TX 1 +#define DMAC_DAC_TX 2 +#define DMAC_AC97_A_RX 3 +#define DMAC_AC97_A_TX 4 +#define DMAC_AC97_B_RX 5 +#define DMAC_AC97_B_TX 6 +#define DMAC_DMAREQ_0 7 +#define DMAC_DMAREQ_1 8 +#define DMAC_DMAREQ_2 9 +#define DMAC_DMAREQ_3 10 + #endif /* __ASM_ARCH_AT32AP700X_H__ */ diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h new file mode 100644 index 00000000000..04d217b442b --- /dev/null +++ b/include/linux/dw_dmac.h @@ -0,0 +1,62 @@ +/* + * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on + * AVR32 systems.) + * + * Copyright (C) 2007 Atmel Corporation + * + * 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. + */ +#ifndef DW_DMAC_H +#define DW_DMAC_H + +#include + +/** + * struct dw_dma_platform_data - Controller configuration parameters + * @nr_channels: Number of channels supported by hardware (max 8) + */ +struct dw_dma_platform_data { + unsigned int nr_channels; +}; + +/** + * struct dw_dma_slave - Controller-specific information about a slave + * @slave: Generic information about the slave + * @ctl_lo: Platform-specific initializer for the CTL_LO register + * @cfg_hi: Platform-specific initializer for the CFG_HI register + * @cfg_lo: Platform-specific initializer for the CFG_LO register + */ +struct dw_dma_slave { + struct dma_slave slave; + u32 cfg_hi; + u32 cfg_lo; +}; + +/* Platform-configurable bits in CFG_HI */ +#define DWC_CFGH_FCMODE (1 << 0) +#define DWC_CFGH_FIFO_MODE (1 << 1) +#define DWC_CFGH_PROTCTL(x) ((x) << 2) +#define DWC_CFGH_SRC_PER(x) ((x) << 7) +#define DWC_CFGH_DST_PER(x) ((x) << 11) + +/* Platform-configurable bits in CFG_LO */ +#define DWC_CFGL_PRIO(x) ((x) << 5) /* priority */ +#define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */ +#define DWC_CFGL_LOCK_CH_BLOCK (1 << 12) +#define DWC_CFGL_LOCK_CH_XACT (2 << 12) +#define DWC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */ +#define DWC_CFGL_LOCK_BUS_BLOCK (1 << 14) +#define DWC_CFGL_LOCK_BUS_XACT (2 << 14) +#define DWC_CFGL_LOCK_CH (1 << 15) /* channel lockout */ +#define DWC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */ +#define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ +#define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ + +static inline struct dw_dma_slave *to_dw_dma_slave(struct dma_slave *slave) +{ + return container_of(slave, struct dw_dma_slave, slave); +} + +#endif /* DW_DMAC_H */ -- cgit v1.2.3-70-g09d2 From 299a140dacaa514be5e567b5851c187c42ec38c4 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 8 Jul 2008 14:47:16 +0200 Subject: x86, AMD IOMMU: ignore detection of GART IOMMU One of the last IOMMU updates covered a bug in the AMD IOMMU code. The early detection code does not succeed if the GART is already detected. This patch fixes this. Cc: Robert Richter Cc: Bhavna Sarathy Signed-off-by: Joerg Roedel Cc: iommu@lists.linux-foundation.org Cc: Joerg Roedel Cc: Robert Richter Cc: Bhavna Sarathy Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 2a13e430437..bb0280077a3 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -828,7 +828,7 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table) void __init amd_iommu_detect(void) { - if (swiotlb || no_iommu || iommu_detected) + if (swiotlb || no_iommu || (iommu_detected && !gart_iommu_aperture)) return; if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) { -- cgit v1.2.3-70-g09d2 From ab6bc3e343fbe3be4a0f67225e849d0db6b4b7ac Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 5 Jul 2008 15:53:36 +0400 Subject: x86: idle process - add checking for NULL early param Signed-off-by: Cyrill Gorcunov Cc: akpm@linux-foundation.org Cc: andi@firstfloor.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index ba370dc8685..58325a6604a 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -164,6 +164,9 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) static int __init idle_setup(char *str) { + if (!str) + return -EINVAL; + if (!strcmp(str, "poll")) { printk("using polling idle threads.\n"); pm_idle = poll_idle; -- cgit v1.2.3-70-g09d2 From d6cd7effcc5e0047faf15ab0a54c980f1a616a07 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 5 Jul 2008 15:53:37 +0400 Subject: x86: io delay - add checking for NULL early param Signed-off-by: Cyrill Gorcunov Cc: akpm@linux-foundation.org Cc: andi@firstfloor.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_delay.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index 5921e5f0a64..1c3a66a67f8 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -103,6 +103,9 @@ void __init io_delay_init(void) static int __init io_delay_param(char *s) { + if (!s) + return -EINVAL; + if (!strcmp(s, "0x80")) io_delay_type = CONFIG_IO_DELAY_TYPE_0X80; else if (!strcmp(s, "0xed")) -- cgit v1.2.3-70-g09d2 From 4d8cc874d7ed43eda72765e9c0e141e170fee4f3 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 5 Jul 2008 15:53:38 +0400 Subject: x86: smpboot maxcpus - add checking for NULL early param Signed-off-by: Cyrill Gorcunov Cc: akpm@linux-foundation.org Cc: andi@firstfloor.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/smpboot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fd933b5465b..e47bfac70c3 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1452,7 +1452,8 @@ static int __init parse_maxcpus(char *arg) { extern unsigned int maxcpus; - maxcpus = simple_strtoul(arg, NULL, 0); + if (arg) + maxcpus = simple_strtoul(arg, NULL, 0); return 0; } early_param("maxcpus", parse_maxcpus); -- cgit v1.2.3-70-g09d2 From e172274ccc55d20536fbdceb6131f38e288541e0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Jun 2008 09:17:31 +0100 Subject: [ARM] 5088/3: pxa2xx: add pxa2xx_set_spi_info to register pxa2xx-spi platform devices Add a function to dynamically allocate and register pxa2xx-spi platform devices, to be used by PXA2xx and PXA3xx based systems. Switch pcm027 and lubbock to use it. Signed-off-by: Guennadi Liakhovetski Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/Kconfig | 1 + arch/arm/mach-pxa/devices.c | 18 ++++++++++++++++++ arch/arm/mach-pxa/lubbock.c | 10 +--------- arch/arm/mach-pxa/pcm027.c | 31 +++++++++++++++++++++++++++++++ include/asm-arm/arch-pxa/pxa2xx_spi.h | 2 ++ 5 files changed, 53 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 914bb33dab9..ef7271e3781 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -139,6 +139,7 @@ config MACH_PCM027 bool "Phytec phyCORE-PXA270 CPU module (PCM-027)" select PXA27x select IWMMXT + select PXA_SSP endmenu diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index a6f2390ce66..abc161dd083 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -831,3 +832,20 @@ void __init pxa3xx_set_mci3_info(struct pxamci_platform_data *info) } #endif /* CONFIG_PXA3xx */ + +/* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1. + * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */ +void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info) +{ + struct platform_device *pd; + + pd = platform_device_alloc("pxa2xx-spi", id); + if (pd == NULL) { + printk(KERN_ERR "pxa2xx-spi: failed to allocate device id %d\n", + id); + return; + } + + pd->dev.platform_data = info; + platform_device_add(pd); +} diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index a3fae413920..e041cceab16 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -226,14 +226,6 @@ static struct pxa2xx_spi_master pxa_ssp_master_info = { .num_chipselect = 0, }; -static struct platform_device pxa_ssp = { - .name = "pxa2xx-spi", - .id = 1, - .dev = { - .platform_data = &pxa_ssp_master_info, - }, -}; - static int lubbock_ads7846_pendown_state(void) { /* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */ @@ -367,7 +359,6 @@ static struct platform_device *devices[] __initdata = { &smc91x_device, &lubbock_flash_device[0], &lubbock_flash_device[1], - &pxa_ssp, }; static struct pxafb_mode_info sharp_lm8v31_mode = { @@ -501,6 +492,7 @@ static void __init lubbock_init(void) lubbock_flash_data[flashboot].name = "boot-rom"; (void) platform_add_devices(devices, ARRAY_SIZE(devices)); + pxa2xx_set_spi_info(1, &pxa_ssp_master_info); spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); } diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c index 3b945eb0aee..377f3be8ce5 100644 --- a/arch/arm/mach-pxa/pcm027.c +++ b/arch/arm/mach-pxa/pcm027.c @@ -24,7 +24,9 @@ #include #include #include +#include #include + #include #include #include @@ -108,6 +110,32 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; +/* + * SPI host and devices + */ +static struct pxa2xx_spi_master pxa_ssp_master_info = { + .num_chipselect = 1, +}; + +static struct max7301_platform_data max7301_info = { + .base = -1, +}; + +/* bus_num must match id in pxa2xx_set_spi_info() call */ +static struct spi_board_info spi_board_info[] __initdata = { + { + .modalias = "max7301", + .platform_data = &max7301_info, + .max_speed_hz = 13000000, + .bus_num = 1, + .chip_select = 0, + .mode = SPI_MODE_0, + }, +}; + +/* + * NOR flash + */ static struct physmap_flash_data pcm027_flash_data = { .width = 4, }; @@ -190,6 +218,9 @@ static void __init pcm027_init(void) #ifdef CONFIG_MACH_PCM990_BASEBOARD pcm990_baseboard_init(); #endif + + pxa2xx_set_spi_info(1, &pxa_ssp_master_info); + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); } static void __init pcm027_map_io(void) diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h index 3459fb26ce9..2206cb61a9f 100644 --- a/include/asm-arm/arch-pxa/pxa2xx_spi.h +++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h @@ -41,4 +41,6 @@ struct pxa2xx_spi_chip { void (*cs_control)(u32 command); }; +extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info); + #endif /*PXA2XX_SPI_H_*/ -- cgit v1.2.3-70-g09d2 From c7b4f5ba07a16d2c84ac6cc312488cc6cc0db518 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 1 Jul 2008 15:45:10 +0100 Subject: [ARM] 5142/1: pxa: move move zaurus declarations to proper place Signed-off-by: Dmitry Baryshkov Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/Kconfig | 102 +++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 51 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index ef7271e3781..01d23e5717a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -58,6 +58,57 @@ config PXA_SHARPSL SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa) handheld computer. +config MACH_POODLE + bool "Enable Sharp SL-5600 (Poodle) Support" + depends on PXA_SHARPSL + select PXA25x + select SHARP_LOCOMO + select PXA_SSP + +config MACH_CORGI + bool "Enable Sharp SL-C700 (Corgi) Support" + depends on PXA_SHARPSL + select PXA25x + select PXA_SHARP_C7xx + +config MACH_SHEPHERD + bool "Enable Sharp SL-C750 (Shepherd) Support" + depends on PXA_SHARPSL + select PXA25x + select PXA_SHARP_C7xx + +config MACH_HUSKY + bool "Enable Sharp SL-C760 (Husky) Support" + depends on PXA_SHARPSL + select PXA25x + select PXA_SHARP_C7xx + +config MACH_AKITA + bool "Enable Sharp SL-1000 (Akita) Support" + depends on PXA_SHARPSL + select PXA27x + select PXA_SHARP_Cxx00 + select MACH_SPITZ + select I2C + select I2C_PXA + +config MACH_SPITZ + bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" + depends on PXA_SHARPSL + select PXA27x + select PXA_SHARP_Cxx00 + +config MACH_BORZOI + bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support" + depends on PXA_SHARPSL + select PXA27x + select PXA_SHARP_Cxx00 + +config MACH_TOSA + bool "Enable Sharp SL-6000x (Tosa) Support" + depends on PXA_SHARPSL + select PXA25x + config ARCH_PXA_ESERIES bool "PXA based Toshiba e-series PDAs" select PXA25x @@ -199,57 +250,6 @@ endif endmenu -config MACH_POODLE - bool "Enable Sharp SL-5600 (Poodle) Support" - depends on PXA_SHARPSL - select PXA25x - select SHARP_LOCOMO - select PXA_SSP - -config MACH_CORGI - bool "Enable Sharp SL-C700 (Corgi) Support" - depends on PXA_SHARPSL - select PXA25x - select PXA_SHARP_C7xx - -config MACH_SHEPHERD - bool "Enable Sharp SL-C750 (Shepherd) Support" - depends on PXA_SHARPSL - select PXA25x - select PXA_SHARP_C7xx - -config MACH_HUSKY - bool "Enable Sharp SL-C760 (Husky) Support" - depends on PXA_SHARPSL - select PXA25x - select PXA_SHARP_C7xx - -config MACH_AKITA - bool "Enable Sharp SL-1000 (Akita) Support" - depends on PXA_SHARPSL - select PXA27x - select PXA_SHARP_Cxx00 - select MACH_SPITZ - select I2C - select I2C_PXA - -config MACH_SPITZ - bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" - depends on PXA_SHARPSL - select PXA27x - select PXA_SHARP_Cxx00 - -config MACH_BORZOI - bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support" - depends on PXA_SHARPSL - select PXA27x - select PXA_SHARP_Cxx00 - -config MACH_TOSA - bool "Enable Sharp SL-6000x (Tosa) Support" - depends on PXA_SHARPSL - select PXA25x - config PXA25x bool help -- cgit v1.2.3-70-g09d2 From c0b8556f2f8146bd38324b14b1ce00f249ba8ed9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 2 Jul 2008 13:50:09 +0100 Subject: [ARM] 5143/1: pxa: further cleanup PXA Kconfig by removing one unnecessary menu level Signed-off-by: Dmitry Baryshkov Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/Kconfig | 48 ++++++++++------------------------------------- 1 file changed, 10 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 01d23e5717a..faa2c3f6c1a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -20,14 +20,17 @@ endmenu endif -menu "Select target boards" - config ARCH_GUMSTIX bool "Gumstix XScale boards" help Say Y here if you intend to run this kernel on a Gumstix Full Function Minature Computer. +config MACH_GUMSTIX_F + bool "Basix, Connex, ws-200ax, ws-400ax systems" + depends on ARCH_GUMSTIX + select PXA25x + config ARCH_LUBBOCK bool "Intel DBPXA250 Development Platform" select PXA25x @@ -157,6 +160,10 @@ config MACH_TRIZEPS4 bool "Keith und Koep Trizeps4 DIMM-Module" select PXA27x +config MACH_TRIZEPS4_CONXS + bool "ConXS Eval Board" + depends on MACH_TRIZEPS4 + config MACH_EM_X270 bool "CompuLab EM-x270 platform" select PXA27x @@ -192,17 +199,10 @@ config MACH_PCM027 select IWMMXT select PXA_SSP -endmenu - -choice - prompt "Used baseboard" - depends on MACH_PCM027 - config MACH_PCM990_BASEBOARD bool "PHYTEC PCM-990 development board" select HAVE_PWM - -endchoice + depends on MACH_PCM027 choice prompt "display on pcm990" @@ -219,34 +219,6 @@ config PCM990_DISPLAY_NONE endchoice -if ARCH_GUMSTIX - -choice - prompt "Select target Gumstix board" - -config MACH_GUMSTIX_F - bool "Basix, Connex, ws-200ax, ws-400ax systems" - select PXA25x - -endchoice - -endif - - -if MACH_TRIZEPS4 - -choice - prompt "Select base board for Trizeps 4 module" - -config MACH_TRIZEPS4_CONXS - bool "ConXS Eval Board" - -config MACH_TRIZEPS4_ANY - bool "another Board" - -endchoice - -endif endmenu -- cgit v1.2.3-70-g09d2 From 6a566fbbcc902df6c9c4dc151bf399018083fb10 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 16 Jun 2008 08:16:46 +0100 Subject: [ARM] 5095/2: pcm990: switch from pxa_gpio_mode to pxa2xx_mfp_config pxa_gpio_mode() is deprecated, use the new pxa2xx_mfp_config() function to configure GPIOs in pcm990 platform code. Convert "array, ARRAY_SIZE(array)" to "ARRAY_AND_SIZE(array)" while at it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Russell King --- arch/arm/mach-pxa/pcm990-baseboard.c | 74 ++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 33 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index 5d87c7c866e..30023b00e47 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -33,14 +33,30 @@ #include #include #include -#include #include #include #include #include #include +#include #include "devices.h" +#include "generic.h" + +static unsigned long pcm990_pin_config[] __initdata = { + /* MMC */ + GPIO32_MMC_CLK, + GPIO112_MMC_CMD, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + /* USB */ + GPIO88_USBH1_PWR, + GPIO89_USBH1_PEN, + /* PWM0 */ + GPIO16_PWM0_OUT, +}; /* * pcm990_lcd_power - control power supply to the LCD @@ -277,16 +293,6 @@ static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int, { int err; - /* - * enable GPIO for PXA27x MMC controller - */ - pxa_gpio_mode(GPIO32_MMCCLK_MD); - pxa_gpio_mode(GPIO112_MMCCMD_MD); - pxa_gpio_mode(GPIO92_MMCDAT0_MD); - pxa_gpio_mode(GPIO109_MMCDAT1_MD); - pxa_gpio_mode(GPIO110_MMCDAT2_MD); - pxa_gpio_mode(GPIO111_MMCDAT3_MD); - err = request_irq(PCM027_MMCDET_IRQ, mci_detect_int, IRQF_DISABLED, "MMC card detect", data); if (err) @@ -333,8 +339,6 @@ static struct pxamci_platform_data pcm990_mci_platform_data = { */ static int pcm990_ohci_init(struct device *dev) { - pxa_gpio_mode(PCM990_USB_OVERCURRENT); - pxa_gpio_mode(PCM990_USB_PWR_EN); /* * disable USB port 2 and 3 * power sense is active low @@ -361,23 +365,27 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = { * PXA27x Camera specific stuff */ #if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) +static unsigned long pcm990_camera_pin_config[] = { + /* CIF */ + GPIO98_CIF_DD_0, + GPIO105_CIF_DD_1, + GPIO104_CIF_DD_2, + GPIO103_CIF_DD_3, + GPIO95_CIF_DD_4, + GPIO94_CIF_DD_5, + GPIO93_CIF_DD_6, + GPIO108_CIF_DD_7, + GPIO107_CIF_DD_8, + GPIO106_CIF_DD_9, + GPIO42_CIF_MCLK, + GPIO45_CIF_PCLK, + GPIO43_CIF_FV, + GPIO44_CIF_LV, +}; + static int pcm990_pxacamera_init(struct device *dev) { - pxa_gpio_mode(GPIO98_CIF_DD_0_MD); - pxa_gpio_mode(GPIO105_CIF_DD_1_MD); - pxa_gpio_mode(GPIO104_CIF_DD_2_MD); - pxa_gpio_mode(GPIO103_CIF_DD_3_MD); - pxa_gpio_mode(GPIO95_CIF_DD_4_MD); - pxa_gpio_mode(GPIO94_CIF_DD_5_MD); - pxa_gpio_mode(GPIO93_CIF_DD_6_MD); - pxa_gpio_mode(GPIO108_CIF_DD_7_MD); - pxa_gpio_mode(GPIO107_CIF_DD_8_MD); - pxa_gpio_mode(GPIO106_CIF_DD_9_MD); - pxa_gpio_mode(GPIO42_CIF_MCLK_MD); - pxa_gpio_mode(GPIO45_CIF_PCLK_MD); - pxa_gpio_mode(GPIO43_CIF_FV_MD); - pxa_gpio_mode(GPIO44_CIF_LV_MD); - + pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_camera_pin_config)); return 0; } @@ -449,8 +457,10 @@ static struct map_desc pcm990_io_desc[] __initdata = { */ void __init pcm990_baseboard_init(void) { + pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config)); + /* register CPLD access */ - iotable_init(pcm990_io_desc, ARRAY_SIZE(pcm990_io_desc)); + iotable_init(ARRAY_AND_SIZE(pcm990_io_desc)); /* register CPLD's IRQ controller */ pcm990_init_irq(); @@ -458,7 +468,6 @@ void __init pcm990_baseboard_init(void) #ifndef CONFIG_PCM990_DISPLAY_NONE set_pxa_fb_info(&pcm990_fbinfo); #endif - pxa_gpio_mode(GPIO16_PWM0_MD); platform_device_register(&pcm990_backlight_device); /* MMC */ @@ -473,9 +482,8 @@ void __init pcm990_baseboard_init(void) #if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) pxa_set_camera_info(&pcm990_pxacamera_platform_data); - i2c_register_board_info(0, pcm990_i2c_devices, - ARRAY_SIZE(pcm990_i2c_devices)); + i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices)); #endif - printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n"); + printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n"); } -- cgit v1.2.3-70-g09d2 From ff279202781c473545862918a8ef1f4ef7712e47 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 22 May 2008 10:14:21 +0100 Subject: [ARM] 5042/1: magician: request GPIOs for pda_power Signed-off-by: Philipp Zabel Signed-off-by: Russell King --- arch/arm/mach-pxa/magician.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 01b2fa79021..595e8c4902f 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -511,6 +511,37 @@ static struct platform_device pasic3 = { * External power */ +static int power_supply_init(struct device *dev) +{ + int ret; + + ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC"); + if (ret) + goto err_cs_ac; + ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_USB, "CABLE_STATE_USB"); + if (ret) + goto err_cs_usb; + ret = gpio_request(EGPIO_MAGICIAN_CHARGE_EN, "CHARGE_EN"); + if (ret) + goto err_chg_en; + ret = gpio_request(GPIO30_MAGICIAN_nCHARGE_EN, "nCHARGE_EN"); + if (!ret) + ret = gpio_direction_output(GPIO30_MAGICIAN_nCHARGE_EN, 0); + if (ret) + goto err_nchg_en; + + return 0; + +err_nchg_en: + gpio_free(EGPIO_MAGICIAN_CHARGE_EN); +err_chg_en: + gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB); +err_cs_usb: + gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC); +err_cs_ac: + return ret; +} + static int magician_is_ac_online(void) { return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC); @@ -527,14 +558,24 @@ static void magician_set_charge(int flags) gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags); } +static void power_supply_exit(struct device *dev) +{ + gpio_free(GPIO30_MAGICIAN_nCHARGE_EN); + gpio_free(EGPIO_MAGICIAN_CHARGE_EN); + gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB); + gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC); +} + static char *magician_supplicants[] = { "ds2760-battery.0", "backup-battery" }; static struct pda_power_pdata power_supply_info = { + .init = power_supply_init, .is_ac_online = magician_is_ac_online, .is_usb_online = magician_is_usb_online, .set_charge = magician_set_charge, + .exit = power_supply_exit, .supplied_to = magician_supplicants, .num_supplicants = ARRAY_SIZE(magician_supplicants), }; -- cgit v1.2.3-70-g09d2 From e181191acdfde5b1f9690c74a2459dd0a3331c62 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 22 Jun 2008 13:00:55 +0100 Subject: [ARM] 5119/1: magician: include linux/gpio.h instead of asm/gpio.h Signed-off-by: Philipp Zabel Signed-off-by: Russell King --- arch/arm/mach-pxa/magician.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 595e8c4902f..6de2c13bd65 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3-70-g09d2 From 7a97010eb4f47c9d2d66bfb838a8638a8d02d9ef Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 26 Jun 2008 21:03:54 +0100 Subject: [ARM] 5125/1: magician: move gpio pin configuration into __initdata section The pin configuration array is only used during board init. Signed-off-by: Philipp Zabel Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/magician.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 6de2c13bd65..2dc14c361c1 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -44,7 +44,7 @@ #include "devices.h" #include "generic.h" -static unsigned long magician_pin_config[] = { +static unsigned long magician_pin_config[] __initdata = { /* SDRAM and Static Memory I/O Signals */ GPIO20_nSDCS_2, -- cgit v1.2.3-70-g09d2 From e277479aba3d35745c822540e9c3d941aabb4e98 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 26 Jun 2008 21:04:31 +0100 Subject: [ARM] 5126/1: magician: remove superfluous mtd includes These were only needed for hardcoded flash partition tables, which were never submitted. It is better to have the bootloader pass the partition table to the kernel instead. Signed-off-by: Philipp Zabel Signed-off-by: Russell King --- arch/arm/mach-pxa/magician.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 2dc14c361c1..9f249dc726e 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include #include #include -- cgit v1.2.3-70-g09d2 From d0f7f1dff01698d228dc108895fbb9b13af37dab Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 30 Jun 2008 18:11:35 +0100 Subject: [ARM] 5137/1: magician: MACH_MAGICIAN doesn't need to depend on ARCH_PXA It is only defined inside an "if ARCH_PXA ... endif" block, so the depends on is not needed. Signed-off-by: Philipp Zabel ? Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index faa2c3f6c1a..61a131fd44a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -189,7 +189,6 @@ config MACH_ARMCORE config MACH_MAGICIAN bool "Enable HTC Magician Support" - depends on ARCH_PXA select PXA27x select IWMMXT -- cgit v1.2.3-70-g09d2 From 14d1012db8462bbb7139ac4622f92e541d3019d1 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 30 Jun 2008 18:11:55 +0100 Subject: [ARM] 5138/1: magician: set pwm-backlight .id = -1 There will always be only one pwm-backlight on this device. Signed-off-by: Philipp Zabel Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/magician.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 9f249dc726e..bad5821be41 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -397,6 +397,7 @@ static struct platform_pwm_backlight_data backlight_data = { static struct platform_device backlight = { .name = "pwm-backlight", + .id = -1, .dev = { .parent = &pxa27x_device_pwm0.dev, .platform_data = &backlight_data, -- cgit v1.2.3-70-g09d2 From 3c85bce6f820258b49bb74c53d2f47c058199f1b Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 16 Jun 2008 08:16:46 +0100 Subject: [ARM] 5101/2: EM-X270 updates Convert EM-X270 pin configuration to use MFP tables and gpio library Make device initialization dependent on respective driver CONFIG_ value (like in zylonite) Add keypad and gpio_key devices Signed-off-by: Mike Rapoport Signed-off-by: Russell King --- arch/arm/mach-pxa/em-x270.c | 373 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 293 insertions(+), 80 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index e23865affc0..e5cc6ca63c7 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -1,7 +1,7 @@ /* - * Support for CompuLab EM-x270 platform + * Support for CompuLab EM-X270 platform * - * Copyright (C) 2007 CompuLab, Ltd. + * Copyright (C) 2007, 2008 CompuLab, Ltd. * Author: Mike Rapoport * * This program is free software; you can redistribute it and/or modify @@ -14,31 +14,159 @@ #include #include - #include #include +#include +#include +#include #include - #include +#include #include -#include #include #include #include #include #include -#include +#include #include "generic.h" /* GPIO IRQ usage */ -#define EM_X270_MMC_PD (105) -#define EM_X270_ETHIRQ IRQ_GPIO(41) -#define EM_X270_MMC_IRQ IRQ_GPIO(13) +#define GPIO41_ETHIRQ (41) +#define GPIO13_MMC_CD (13) +#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) +#define EM_X270_MMC_CD IRQ_GPIO(GPIO13_MMC_CD) + +/* NAND control GPIOs */ +#define GPIO11_NAND_CS (11) +#define GPIO56_NAND_RB (56) + +static unsigned long em_x270_pin_config[] = { + /* AC'97 */ + GPIO28_AC97_BITCLK, + GPIO29_AC97_SDATA_IN_0, + GPIO30_AC97_SDATA_OUT, + GPIO31_AC97_SYNC, + GPIO98_AC97_SYSCLK, + GPIO113_AC97_nRESET, + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_BTUART_RTS, + + /* STUART */ + GPIO46_STUART_RXD, + GPIO47_STUART_TXD, + + /* MCI controller */ + GPIO32_MMC_CLK, + GPIO112_MMC_CMD, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + + /* LCD */ + GPIO58_LCD_LDD_0, + GPIO59_LCD_LDD_1, + GPIO60_LCD_LDD_2, + GPIO61_LCD_LDD_3, + GPIO62_LCD_LDD_4, + GPIO63_LCD_LDD_5, + GPIO64_LCD_LDD_6, + GPIO65_LCD_LDD_7, + GPIO66_LCD_LDD_8, + GPIO67_LCD_LDD_9, + GPIO68_LCD_LDD_10, + GPIO69_LCD_LDD_11, + GPIO70_LCD_LDD_12, + GPIO71_LCD_LDD_13, + GPIO72_LCD_LDD_14, + GPIO73_LCD_LDD_15, + GPIO74_LCD_FCLK, + GPIO75_LCD_LCLK, + GPIO76_LCD_PCLK, + GPIO77_LCD_BIAS, + + /* QCI */ + GPIO84_CIF_FV, + GPIO25_CIF_LV, + GPIO53_CIF_MCLK, + GPIO54_CIF_PCLK, + GPIO81_CIF_DD_0, + GPIO55_CIF_DD_1, + GPIO51_CIF_DD_2, + GPIO50_CIF_DD_3, + GPIO52_CIF_DD_4, + GPIO48_CIF_DD_5, + GPIO17_CIF_DD_6, + GPIO12_CIF_DD_7, + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + + /* Keypad */ + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO34_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO39_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH, + GPIO91_KP_MKIN_6 | WAKEUP_ON_LEVEL_HIGH, + GPIO36_KP_MKIN_7 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + GPIO107_KP_MKOUT_4, + GPIO108_KP_MKOUT_5, + GPIO96_KP_MKOUT_6, + GPIO22_KP_MKOUT_7, + + /* SSP1 */ + GPIO26_SSP1_RXD, + GPIO23_SSP1_SCLK, + GPIO24_SSP1_SFRM, + GPIO57_SSP1_TXD, + + /* SSP2 */ + GPIO19_SSP2_SCLK, + GPIO14_SSP2_SFRM, + GPIO89_SSP2_TXD, + GPIO88_SSP2_RXD, + + /* SDRAM and local bus */ + GPIO15_nCS_1, + GPIO78_nCS_2, + GPIO79_nCS_3, + GPIO80_nCS_4, + GPIO49_nPWE, + GPIO18_RDY, + + /* GPIO */ + GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, + + /* power controls */ + GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */ + GPIO115_GPIO | MFP_LPM_DRIVE_LOW, /* WLAN_PWEN */ + + /* NAND controls */ + GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */ + GPIO56_GPIO, /* NAND Ready/Busy */ + + /* interrupts */ + GPIO13_GPIO, /* MMC card detect */ + GPIO41_GPIO, /* DM9000 interrupt */ +}; -static struct resource em_x270_dm9k_resource[] = { +#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) +static struct resource em_x270_dm9000_resource[] = { [0] = { .start = PXA_CS2_PHYS, .end = PXA_CS2_PHYS + 3, @@ -52,36 +180,34 @@ static struct resource em_x270_dm9k_resource[] = { [2] = { .start = EM_X270_ETHIRQ, .end = EM_X270_ETHIRQ, - .flags = IORESOURCE_IRQ, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; -/* for the moment we limit ourselves to 32bit IO until some - * better IO routines can be written and tested - */ -static struct dm9000_plat_data em_x270_dm9k_platdata = { +static struct dm9000_plat_data em_x270_dm9000_platdata = { .flags = DM9000_PLATF_32BITONLY, }; -/* Ethernet device */ -static struct platform_device em_x270_dm9k = { +static struct platform_device em_x270_dm9000 = { .name = "dm9000", .id = 0, - .num_resources = ARRAY_SIZE(em_x270_dm9k_resource), - .resource = em_x270_dm9k_resource, + .num_resources = ARRAY_SIZE(em_x270_dm9000_resource), + .resource = em_x270_dm9000_resource, .dev = { - .platform_data = &em_x270_dm9k_platdata, + .platform_data = &em_x270_dm9000_platdata, } }; -/* WM9712 touchscreen controller. Hopefully the driver will make it to - * the mainstream sometime */ -static struct platform_device em_x270_ts = { - .name = "wm97xx-ts", - .id = -1, -}; +static void __init em_x270_init_dm9000(void) +{ + platform_device_register(&em_x270_dm9000); +} +#else +static inline void em_x270_init_dm9000(void) {} +#endif -/* RTC */ +/* V3020 RTC */ +#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE) static struct resource em_x270_v3020_resource[] = { [0] = { .start = PXA_CS4_PHYS, @@ -104,20 +230,26 @@ static struct platform_device em_x270_rtc = { } }; -/* NAND flash */ -#define GPIO_NAND_CS (11) -#define GPIO_NAND_RB (56) +static void __init em_x270_init_rtc(void) +{ + platform_device_register(&em_x270_rtc); +} +#else +static inline void em_x270_init_rtc(void) {} +#endif +/* NAND flash */ +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) static inline void nand_cs_on(void) { - GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); + gpio_set_value(GPIO11_NAND_CS, 0); } static void nand_cs_off(void) { dsb(); - GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); + gpio_set_value(GPIO11_NAND_CS, 1); } /* hardware specific access to control-lines */ @@ -157,7 +289,7 @@ static int em_x270_nand_device_ready(struct mtd_info *mtd) { dsb(); - return GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB); + return gpio_get_value(GPIO56_NAND_RB); } static struct mtd_partition em_x270_partition_info[] = { @@ -210,16 +342,35 @@ static struct platform_device em_x270_nand = { } }; -/* platform devices */ -static struct platform_device *platform_devices[] __initdata = { - &em_x270_dm9k, - &em_x270_ts, - &em_x270_rtc, - &em_x270_nand, -}; +static void __init em_x270_init_nand(void) +{ + int err; + err = gpio_request(GPIO11_NAND_CS, "NAND CS"); + if (err) { + pr_warning("EM-X270: failed to request NAND CS gpio\n"); + return; + } + + gpio_direction_output(GPIO11_NAND_CS, 1); + + err = gpio_request(GPIO56_NAND_RB, "NAND R/B"); + if (err) { + pr_warning("EM-X270: failed to request NAND R/B gpio\n"); + gpio_free(GPIO11_NAND_CS); + return; + } + + gpio_direction_input(GPIO56_NAND_RB); + + platform_device_register(&em_x270_nand); +} +#else +static inline void em_x270_init_nand(void) {} +#endif /* PXA27x OHCI controller setup */ +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) static int em_x270_ohci_init(struct device *dev) { /* Set the Power Control Polarity Low */ @@ -237,27 +388,23 @@ static struct pxaohci_platform_data em_x270_ohci_platform_data = { .init = em_x270_ohci_init, }; +static void __init em_x270_init_ohci(void) +{ + pxa_set_ohci_info(&em_x270_ohci_platform_data); +} +#else +static inline void em_x270_init_ohci(void) {} +#endif +/* MCI controller setup */ +#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE) static int em_x270_mci_init(struct device *dev, irq_handler_t em_x270_detect_int, void *data) { - int err; - - /* setup GPIO for PXA27x MMC controller */ - pxa_gpio_mode(GPIO32_MMCCLK_MD); - pxa_gpio_mode(GPIO112_MMCCMD_MD); - pxa_gpio_mode(GPIO92_MMCDAT0_MD); - pxa_gpio_mode(GPIO109_MMCDAT1_MD); - pxa_gpio_mode(GPIO110_MMCDAT2_MD); - pxa_gpio_mode(GPIO111_MMCDAT3_MD); - - /* EM-X270 uses GPIO13 as SD power enable */ - pxa_gpio_mode(EM_X270_MMC_PD | GPIO_OUT); - - err = request_irq(EM_X270_MMC_IRQ, em_x270_detect_int, - IRQF_DISABLED | IRQF_TRIGGER_FALLING, - "MMC card detect", data); + int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int, + IRQF_DISABLED | IRQF_TRIGGER_FALLING, + "MMC card detect", data); if (err) { printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n", __func__, err); @@ -279,7 +426,8 @@ static void em_x270_mci_setpower(struct device *dev, unsigned int vdd) static void em_x270_mci_exit(struct device *dev, void *data) { - free_irq(EM_X270_MMC_IRQ, data); + int irq = gpio_to_irq(GPIO13_MMC_CD); + free_irq(irq, data); } static struct pxamci_platform_data em_x270_mci_platform_data = { @@ -289,7 +437,16 @@ static struct pxamci_platform_data em_x270_mci_platform_data = { .exit = em_x270_mci_exit, }; +static void __init em_x270_init_mmc(void) +{ + pxa_set_mci_info(&em_x270_mci_platform_data); +} +#else +static inline void em_x270_init_mmc(void) {} +#endif + /* LCD 480x640 */ +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) static struct pxafb_mode_info em_x270_lcd_mode = { .pixclock = 50000, .bpp = 16, @@ -307,40 +464,96 @@ static struct pxafb_mode_info em_x270_lcd_mode = { static struct pxafb_mach_info em_x270_lcd = { .modes = &em_x270_lcd_mode, .num_modes = 1, - .cmap_inverse = 0, - .cmap_static = 0, - .lccr0 = LCCR0_PAS, - .lccr3 = LCCR3_PixClkDiv(0x01) | LCCR3_Acb(0xff), + .lcd_conn = LCD_COLOR_TFT_16BPP, }; - -static void __init em_x270_init(void) +static void __init em_x270_init_lcd(void) { - /* setup LCD */ set_pxa_fb_info(&em_x270_lcd); +} +#else +static inline void em_x270_init_lcd(void) {} +#endif - /* register EM-X270 platform devices */ - platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); +#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE) +static void __init em_x270_init_ac97(void) +{ pxa_set_ac97_info(NULL); +} +#else +static inline void em_x270_init_ac97(void) {} +#endif + +#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) +static unsigned int em_x270_matrix_keys[] = { + KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B), + KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT), + KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D), +}; - /* set MCI and OHCI platform parameters */ - pxa_set_mci_info(&em_x270_mci_platform_data); - pxa_set_ohci_info(&em_x270_ohci_platform_data); +struct pxa27x_keypad_platform_data em_x270_keypad_info = { + /* code map for the matrix keys */ + .matrix_key_rows = 3, + .matrix_key_cols = 3, + .matrix_key_map = em_x270_matrix_keys, + .matrix_key_map_size = ARRAY_SIZE(em_x270_matrix_keys), +}; + +static void __init em_x270_init_keypad(void) +{ + pxa_set_keypad_info(&em_x270_keypad_info); +} +#else +static inline void em_x270_init_keypad(void) {} +#endif - /* setup STUART GPIOs */ - pxa_gpio_mode(GPIO46_STRXD_MD); - pxa_gpio_mode(GPIO47_STTXD_MD); +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button gpio_keys_button[] = { + [0] = { + .desc = "sleep/wakeup", + .code = KEY_SUSPEND, + .type = EV_PWR, + .gpio = 1, + .wakeup = 1, + }, +}; - /* setup BTUART GPIOs */ - pxa_gpio_mode(GPIO42_BTRXD_MD); - pxa_gpio_mode(GPIO43_BTTXD_MD); - pxa_gpio_mode(GPIO44_BTCTS_MD); - pxa_gpio_mode(GPIO45_BTRTS_MD); +static struct gpio_keys_platform_data em_x270_gpio_keys_data = { + .buttons = gpio_keys_button, + .nbuttons = 1, +}; - /* Setup interrupt for dm9000 */ - set_irq_type(EM_X270_ETHIRQ, IRQT_RISING); +static struct platform_device em_x270_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &em_x270_gpio_keys_data, + }, +}; + +static void __init em_x270_init_gpio_keys(void) +{ + platform_device_register(&em_x270_gpio_keys); +} +#else +static inline void em_x270_init_gpio_keys(void) {} +#endif + +static void __init em_x270_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config)); + + em_x270_init_dm9000(); + em_x270_init_rtc(); + em_x270_init_nand(); + em_x270_init_lcd(); + em_x270_init_mmc(); + em_x270_init_ohci(); + em_x270_init_keypad(); + em_x270_init_gpio_keys(); + em_x270_init_ac97(); } -MACHINE_START(EM_X270, "Compulab EM-x270") +MACHINE_START(EM_X270, "Compulab EM-X270") .boot_params = 0xa0000100, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, -- cgit v1.2.3-70-g09d2 From 2f01a973729712c373ccc8acde4d218c38f3029a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 17 Jun 2008 12:29:58 +0100 Subject: [ARM] 5103/2: CM-X270: update core platform support Convert CM-X270 pin configuration to use MFP tables. Make device initialization dependent on respective driver CONFIG_ value (like in zylonite). Cleanup includes Signed-off-by: Mike Rapoport Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/cm-x270-pci.c | 27 +-- arch/arm/mach-pxa/cm-x270-pci.h | 14 +- arch/arm/mach-pxa/cm-x270.c | 405 ++++++++++++++++++++++++++++------------ 3 files changed, 307 insertions(+), 139 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c index 319c9ff3ab9..bcf0cde6ccc 100644 --- a/arch/arm/mach-pxa/cm-x270-pci.c +++ b/arch/arm/mach-pxa/cm-x270-pci.c @@ -5,7 +5,7 @@ * * Bits taken from various places. * - * Copyright (C) 2007 Compulab, Ltd. + * Copyright (C) 2007, 2008 Compulab, Ltd. * Mike Rapoport * * This program is free software; you can redistribute it and/or modify @@ -19,16 +19,16 @@ #include #include #include +#include #include -#include #include -#include #include #include -unsigned long it8152_base_address = CMX270_IT8152_VIRT; +unsigned long it8152_base_address; +static int cmx270_it8152_irq_gpio; /* * Only first 64MB of memory can be accessed via PCI. @@ -42,7 +42,7 @@ void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size, unsigned int sz = SZ_64M >> PAGE_SHIFT; if (machine_is_armcore()) { - pr_info("Adjusting zones for CM-x270\n"); + pr_info("Adjusting zones for CM-X270\n"); /* * Only adjust if > 64M on current system @@ -60,19 +60,20 @@ void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size, static void cmx270_it8152_irq_demux(unsigned int irq, struct irq_desc *desc) { /* clear our parent irq */ - GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ); + GEDR(cmx270_it8152_irq_gpio) = GPIO_bit(cmx270_it8152_irq_gpio); it8152_irq_demux(irq, desc); } -void __cmx270_pci_init_irq(void) +void __cmx270_pci_init_irq(int irq_gpio) { it8152_init_irq(); - pxa_gpio_mode(IRQ_TO_GPIO(GPIO_IT8152_IRQ)); - set_irq_type(IRQ_GPIO(GPIO_IT8152_IRQ), IRQT_RISING); - set_irq_chained_handler(IRQ_GPIO(GPIO_IT8152_IRQ), - cmx270_it8152_irq_demux); + cmx270_it8152_irq_gpio = irq_gpio; + + set_irq_type(gpio_to_irq(irq_gpio), IRQT_RISING); + + set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx270_it8152_irq_demux); } #ifdef CONFIG_PM @@ -115,8 +116,8 @@ static int __init cmx270_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) /* Here comes the ugly part. The routing is baseboard specific, - but defining a platform for each possible base of CM-x270 is - unrealistic. Here we keep mapping for ATXBase and SB-x270. + but defining a platform for each possible base of CM-X270 is + unrealistic. Here we keep mapping for ATXBase and SB-X270. */ /* ATXBASE PCI slot */ if (slot == 7) diff --git a/arch/arm/mach-pxa/cm-x270-pci.h b/arch/arm/mach-pxa/cm-x270-pci.h index ffe37b66f9a..48f532f4cb5 100644 --- a/arch/arm/mach-pxa/cm-x270-pci.h +++ b/arch/arm/mach-pxa/cm-x270-pci.h @@ -1,13 +1,13 @@ -extern void __cmx270_pci_init_irq(void); +extern void __cmx270_pci_init_irq(int irq_gpio); extern void __cmx270_pci_suspend(void); extern void __cmx270_pci_resume(void); #ifdef CONFIG_PCI -#define cmx270_pci_init_irq __cmx270_pci_init_irq -#define cmx270_pci_suspend __cmx270_pci_suspend -#define cmx270_pci_resume __cmx270_pci_resume +#define cmx270_pci_init_irq(x) __cmx270_pci_init_irq(x) +#define cmx270_pci_suspend(x) __cmx270_pci_suspend(x) +#define cmx270_pci_resume(x) __cmx270_pci_resume(x) #else -#define cmx270_pci_init_irq() do {} while (0) -#define cmx270_pci_suspend() do {} while (0) -#define cmx270_pci_resume() do {} while (0) +#define cmx270_pci_init_irq(x) do {} while (0) +#define cmx270_pci_suspend(x) do {} while (0) +#define cmx270_pci_resume(x) do {} while (0) #endif diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c index b3c3fd72d04..402e807eae5 100644 --- a/arch/arm/mach-pxa/cm-x270.c +++ b/arch/arm/mach-pxa/cm-x270.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/mach-pxa/cm-x270.c * - * Copyright (C) 2007 CompuLab, Ltd. + * Copyright (C) 2007, 2008 CompuLab, Ltd. * Mike Rapoport * * This program is free software; you can redistribute it and/or modify @@ -9,44 +9,156 @@ * published by the Free Software Foundation. */ -#include -#include -#include #include -#include #include -#include -#include +#include +#include #include #include -#include - #include