From 93fa7636dfdc059b25df148f230c0991096afdef Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Tue, 8 Apr 2008 11:01:58 +0200 Subject: x86, ptrace: PEBS support Polish the ds.h interface and add support for PEBS. Ds.c is meant to be the resource allocator for per-thread and per-cpu BTS and PEBS recording. It is used by ptrace/utrace to provide execution tracing of debugged tasks. It will be used by profilers (e.g. perfmon2). It may be used by kernel debuggers to provide a kernel execution trace. Changes in detail: - guard DS and ptrace by CONFIG macros - separate DS and BTS more clearly - simplify field accesses - add functions to manage PEBS buffers - add simple protection/allocation mechanism - added support for Atom Opens: - buffer overflow handling Currently, only circular buffers are supported. This is all we need for debugging. Profilers would want an overflow notification. This is planned to be added when perfmon2 is made to use the ds.h interface. - utrace intermediate layer Signed-off-by: Markus Metzger Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig.cpu | 18 + arch/x86/kernel/cpu/intel.c | 3 +- arch/x86/kernel/ds.c | 953 ++++++++++++++++++++++++++++++------------- arch/x86/kernel/process_32.c | 25 +- arch/x86/kernel/process_64.c | 25 +- arch/x86/kernel/ptrace.c | 444 ++++++++++++-------- arch/x86/kernel/setup_64.c | 3 +- 7 files changed, 1009 insertions(+), 462 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 2ad6301849a..13f3f8bebfd 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -415,3 +415,21 @@ config X86_MINIMUM_CPU_FAMILY config X86_DEBUGCTLMSR def_bool y depends on !(M586MMX || M586TSC || M586 || M486 || M386) + +config X86_DS + bool "Debug Store support" + default y + help + Add support for Debug Store. + This allows the kernel to provide a memory buffer to the hardware + to store various profiling and tracing events. + +config X86_PTRACE_BTS + bool "ptrace interface to Branch Trace Store" + default y + depends on (X86_DS && X86_DEBUGCTLMSR) + help + Add a ptrace interface to allow collecting an execution trace + of the traced task. + This collects control flow changes in a (cyclic) buffer and allows + debuggers to fill in the gaps and show an execution trace of the debuggee. diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index fe9224c51d3..cbffa2a25a1 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -222,10 +222,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_BTS); if (!(l1 & (1<<12))) set_cpu_cap(c, X86_FEATURE_PEBS); + ds_init_intel(c); } if (cpu_has_bts) - ds_init_intel(c); + ptrace_bts_init_intel(c); } static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 11c11b8ec48..5b32b6d062b 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -2,26 +2,48 @@ * Debug Store support * * This provides a low-level interface to the hardware's Debug Store - * feature that is used for last branch recording (LBR) and + * feature that is used for branch trace store (BTS) and * precise-event based sampling (PEBS). * - * Different architectures use a different DS layout/pointer size. - * The below functions therefore work on a void*. + * It manages: + * - per-thread and per-cpu allocation of BTS and PEBS + * - buffer memory allocation (optional) + * - buffer overflow handling + * - buffer access * + * It assumes: + * - get_task_struct on all parameter tasks + * - current is allowed to trace parameter tasks * - * Since there is no user for PEBS, yet, only LBR (or branch - * trace store, BTS) is supported. * - * - * Copyright (C) 2007 Intel Corporation. - * Markus Metzger , Dec 2007 + * Copyright (C) 2007-2008 Intel Corporation. + * Markus Metzger , 2007-2008 */ + +#ifdef CONFIG_X86_DS + #include #include #include #include +#include + + +/* + * The configuration for a particular DS hardware implementation. + */ +struct ds_configuration { + /* the size of the DS structure in bytes */ + unsigned char sizeof_ds; + /* the size of one pointer-typed field in the DS structure in bytes; + this covers the first 8 fields related to buffer management. */ + unsigned char sizeof_field; + /* the size of a BTS/PEBS record in bytes */ + unsigned char sizeof_rec[2]; +}; +static struct ds_configuration ds_cfg; /* @@ -44,378 +66,747 @@ * (interrupt occurs when write pointer passes interrupt pointer) * - value to which counter is reset following counter overflow * - * On later architectures, the last branch recording hardware uses - * 64bit pointers even in 32bit mode. - * - * - * Branch Trace Store (BTS) records store information about control - * flow changes. They at least provide the following information: - * - source linear address - * - destination linear address + * Later architectures use 64bit pointers throughout, whereas earlier + * architectures use 32bit pointers in 32bit mode. * - * Netburst supported a predicated bit that had been dropped in later - * architectures. We do not suppor it. * + * We compute the base address for the first 8 fields based on: + * - the field size stored in the DS configuration + * - the relative field position + * - an offset giving the start of the respective region * - * In order to abstract from the actual DS and BTS layout, we describe - * the access to the relevant fields. - * Thanks to Andi Kleen for proposing this design. + * This offset is further used to index various arrays holding + * information for BTS and PEBS at the respective index. * - * The implementation, however, is not as general as it might seem. In - * order to stay somewhat simple and efficient, we assume an - * underlying unsigned type (mostly a pointer type) and we expect the - * field to be at least as big as that type. + * On later 32bit processors, we only access the lower 32bit of the + * 64bit pointer fields. The upper halves will be zeroed out. */ -/* - * A special from_ip address to indicate that the BTS record is an - * info record that needs to be interpreted or skipped. - */ -#define BTS_ESCAPE_ADDRESS (-1) +enum ds_field { + ds_buffer_base = 0, + ds_index, + ds_absolute_maximum, + ds_interrupt_threshold, +}; -/* - * A field access descriptor - */ -struct access_desc { - unsigned char offset; - unsigned char size; +enum ds_qualifier { + ds_bts = 0, + ds_pebs }; +static inline unsigned long ds_get(const unsigned char *base, + enum ds_qualifier qual, enum ds_field field) +{ + base += (ds_cfg.sizeof_field * (field + (4 * qual))); + return *(unsigned long *)base; +} + +static inline void ds_set(unsigned char *base, enum ds_qualifier qual, + enum ds_field field, unsigned long value) +{ + base += (ds_cfg.sizeof_field * (field + (4 * qual))); + (*(unsigned long *)base) = value; +} + + /* - * The configuration for a particular DS/BTS hardware implementation. + * Locking is done only for allocating BTS or PEBS resources and for + * guarding context and buffer memory allocation. + * + * Most functions require the current task to own the ds context part + * they are going to access. All the locking is done when validating + * access to the context. */ -struct ds_configuration { - /* the DS configuration */ - unsigned char sizeof_ds; - struct access_desc bts_buffer_base; - struct access_desc bts_index; - struct access_desc bts_absolute_maximum; - struct access_desc bts_interrupt_threshold; - /* the BTS configuration */ - unsigned char sizeof_bts; - struct access_desc from_ip; - struct access_desc to_ip; - /* BTS variants used to store additional information like - timestamps */ - struct access_desc info_type; - struct access_desc info_data; - unsigned long debugctl_mask; -}; +static spinlock_t ds_lock = __SPIN_LOCK_UNLOCKED(ds_lock); /* - * The global configuration used by the below accessor functions + * Validate that the current task is allowed to access the BTS/PEBS + * buffer of the parameter task. + * + * Returns 0, if access is granted; -Eerrno, otherwise. */ -static struct ds_configuration ds_cfg; +static inline int ds_validate_access(struct ds_context *context, + enum ds_qualifier qual) +{ + if (!context) + return -EPERM; + + if (context->owner[qual] == current) + return 0; + + return -EPERM; +} + /* - * Accessor functions for some DS and BTS fields using the above - * global ptrace_bts_cfg. + * We either support (system-wide) per-cpu or per-thread allocation. + * We distinguish the two based on the task_struct pointer, where a + * NULL pointer indicates per-cpu allocation for the current cpu. + * + * Allocations are use-counted. As soon as resources are allocated, + * further allocations must be of the same type (per-cpu or + * per-thread). We model this by counting allocations (i.e. the number + * of tracers of a certain type) for one type negatively: + * =0 no tracers + * >0 number of per-thread tracers + * <0 number of per-cpu tracers + * + * The below functions to get and put tracers and to check the + * allocation type require the ds_lock to be held by the caller. + * + * Tracers essentially gives the number of ds contexts for a certain + * type of allocation. */ -static inline unsigned long get_bts_buffer_base(char *base) +static long tracers; + +static inline void get_tracer(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_buffer_base.offset); + tracers += (task ? 1 : -1); } -static inline void set_bts_buffer_base(char *base, unsigned long value) + +static inline void put_tracer(struct task_struct *task) { - (*(unsigned long *)(base + ds_cfg.bts_buffer_base.offset)) = value; + tracers -= (task ? 1 : -1); } -static inline unsigned long get_bts_index(char *base) + +static inline int check_tracer(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_index.offset); + return (task ? (tracers >= 0) : (tracers <= 0)); } -static inline void set_bts_index(char *base, unsigned long value) + + +/* + * The DS context is either attached to a thread or to a cpu: + * - in the former case, the thread_struct contains a pointer to the + * attached context. + * - in the latter case, we use a static array of per-cpu context + * pointers. + * + * Contexts are use-counted. They are allocated on first access and + * deallocated when the last user puts the context. + * + * We distinguish between an allocating and a non-allocating get of a + * context: + * - the allocating get is used for requesting BTS/PEBS resources. It + * requires the caller to hold the global ds_lock. + * - the non-allocating get is used for all other cases. A + * non-existing context indicates an error. It acquires and releases + * the ds_lock itself for obtaining the context. + * + * A context and its DS configuration are allocated and deallocated + * together. A context always has a DS configuration of the + * appropriate size. + */ +static DEFINE_PER_CPU(struct ds_context *, system_context); + +#define this_system_context per_cpu(system_context, smp_processor_id()) + +/* + * Returns the pointer to the parameter task's context or to the + * system-wide context, if task is NULL. + * + * Increases the use count of the returned context, if not NULL. + */ +static inline struct ds_context *ds_get_context(struct task_struct *task) { - (*(unsigned long *)(base + ds_cfg.bts_index.offset)) = value; + struct ds_context *context; + + spin_lock(&ds_lock); + + context = (task ? task->thread.ds_ctx : this_system_context); + if (context) + context->count++; + + spin_unlock(&ds_lock); + + return context; } -static inline unsigned long get_bts_absolute_maximum(char *base) + +/* + * Same as ds_get_context, but allocates the context and it's DS + * structure, if necessary; returns NULL; if out of memory. + * + * pre: requires ds_lock to be held + */ +static inline struct ds_context *ds_alloc_context(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_absolute_maximum.offset); + struct ds_context **p_context = + (task ? &task->thread.ds_ctx : &this_system_context); + struct ds_context *context = *p_context; + + if (!context) { + context = kzalloc(sizeof(*context), GFP_KERNEL); + + if (!context) + return 0; + + context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); + if (!context->ds) { + kfree(context); + return 0; + } + + *p_context = context; + + context->this = p_context; + context->task = task; + + if (task) + set_tsk_thread_flag(task, TIF_DS_AREA_MSR); + + if (!task || (task == current)) + wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0); + + get_tracer(task); + } + + context->count++; + + return context; } -static inline void set_bts_absolute_maximum(char *base, unsigned long value) + +/* + * Decreases the use count of the parameter context, if not NULL. + * Deallocates the context, if the use count reaches zero. + */ +static inline void ds_put_context(struct ds_context *context) { - (*(unsigned long *)(base + ds_cfg.bts_absolute_maximum.offset)) = value; + if (!context) + return; + + spin_lock(&ds_lock); + + if (--context->count) + goto out; + + *(context->this) = 0; + + if (context->task) + clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR); + + if (!context->task || (context->task == current)) + wrmsrl(MSR_IA32_DS_AREA, 0); + + put_tracer(context->task); + + /* free any leftover buffers from tracers that did not + * deallocate them properly. */ + kfree(context->buffer[ds_bts]); + kfree(context->buffer[ds_pebs]); + kfree(context->ds); + kfree(context); + out: + spin_unlock(&ds_lock); } -static inline unsigned long get_bts_interrupt_threshold(char *base) + + +/* + * Handle a buffer overflow + * + * task: the task whose buffers are overflowing; + * NULL for a buffer overflow on the current cpu + * context: the ds context + * qual: the buffer type + */ +static void ds_overflow(struct task_struct *task, struct ds_context *context, + enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.bts_interrupt_threshold.offset); + if (!context) + return; + + if (context->callback[qual]) + (*context->callback[qual])(task); + + /* todo: do some more overflow handling */ } -static inline void set_bts_interrupt_threshold(char *base, unsigned long value) + + +/* + * Allocate a non-pageable buffer of the parameter size. + * Checks the memory and the locked memory rlimit. + * + * Returns the buffer, if successful; + * NULL, if out of memory or rlimit exceeded. + * + * size: the requested buffer size in bytes + * pages (out): if not NULL, contains the number of pages reserved + */ +static inline void *ds_allocate_buffer(size_t size, unsigned int *pages) { - (*(unsigned long *)(base + ds_cfg.bts_interrupt_threshold.offset)) = value; + unsigned long rlim, vm, pgsz; + void *buffer; + + pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; + + rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; + vm = current->mm->total_vm + pgsz; + if (rlim < vm) + return 0; + + rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; + vm = current->mm->locked_vm + pgsz; + if (rlim < vm) + return 0; + + buffer = kzalloc(size, GFP_KERNEL); + if (!buffer) + return 0; + + current->mm->total_vm += pgsz; + current->mm->locked_vm += pgsz; + + if (pages) + *pages = pgsz; + + return buffer; } -static inline unsigned long get_from_ip(char *base) + +static int ds_request(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl, enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.from_ip.offset); + struct ds_context *context; + unsigned long buffer, adj; + const unsigned long alignment = (1 << 3); + int error = 0; + + if (!ds_cfg.sizeof_ds) + return -EOPNOTSUPP; + + /* we require some space to do alignment adjustments below */ + if (size < (alignment + ds_cfg.sizeof_rec[qual])) + return -EINVAL; + + /* buffer overflow notification is not yet implemented */ + if (ovfl) + return -EOPNOTSUPP; + + + spin_lock(&ds_lock); + + if (!check_tracer(task)) + return -EPERM; + + error = -ENOMEM; + context = ds_alloc_context(task); + if (!context) + goto out_unlock; + + error = -EALREADY; + if (context->owner[qual] == current) + goto out_unlock; + error = -EPERM; + if (context->owner[qual] != 0) + goto out_unlock; + context->owner[qual] = current; + + spin_unlock(&ds_lock); + + + error = -ENOMEM; + if (!base) { + base = ds_allocate_buffer(size, &context->pages[qual]); + if (!base) + goto out_release; + + context->buffer[qual] = base; + } + error = 0; + + context->callback[qual] = ovfl; + + /* adjust the buffer address and size to meet alignment + * constraints: + * - buffer is double-word aligned + * - size is multiple of record size + * + * We checked the size at the very beginning; we have enough + * space to do the adjustment. + */ + buffer = (unsigned long)base; + + adj = ALIGN(buffer, alignment) - buffer; + buffer += adj; + size -= adj; + + size /= ds_cfg.sizeof_rec[qual]; + size *= ds_cfg.sizeof_rec[qual]; + + ds_set(context->ds, qual, ds_buffer_base, buffer); + ds_set(context->ds, qual, ds_index, buffer); + ds_set(context->ds, qual, ds_absolute_maximum, buffer + size); + + if (ovfl) { + /* todo: select a suitable interrupt threshold */ + } else + ds_set(context->ds, qual, + ds_interrupt_threshold, buffer + size + 1); + + /* we keep the context until ds_release */ + return error; + + out_release: + context->owner[qual] = 0; + ds_put_context(context); + return error; + + out_unlock: + spin_unlock(&ds_lock); + ds_put_context(context); + return error; } -static inline void set_from_ip(char *base, unsigned long value) + +int ds_request_bts(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl) { - (*(unsigned long *)(base + ds_cfg.from_ip.offset)) = value; + return ds_request(task, base, size, ovfl, ds_bts); } -static inline unsigned long get_to_ip(char *base) + +int ds_request_pebs(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl) { - return *(unsigned long *)(base + ds_cfg.to_ip.offset); + return ds_request(task, base, size, ovfl, ds_pebs); } -static inline void set_to_ip(char *base, unsigned long value) + +static int ds_release(struct task_struct *task, enum ds_qualifier qual) { - (*(unsigned long *)(base + ds_cfg.to_ip.offset)) = value; + struct ds_context *context; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + kfree(context->buffer[qual]); + context->buffer[qual] = 0; + + current->mm->total_vm -= context->pages[qual]; + current->mm->locked_vm -= context->pages[qual]; + context->pages[qual] = 0; + context->owner[qual] = 0; + + /* + * we put the context twice: + * once for the ds_get_context + * once for the corresponding ds_request + */ + ds_put_context(context); + out: + ds_put_context(context); + return error; } -static inline unsigned char get_info_type(char *base) + +int ds_release_bts(struct task_struct *task) { - return *(unsigned char *)(base + ds_cfg.info_type.offset); + return ds_release(task, ds_bts); } -static inline void set_info_type(char *base, unsigned char value) + +int ds_release_pebs(struct task_struct *task) { - (*(unsigned char *)(base + ds_cfg.info_type.offset)) = value; + return ds_release(task, ds_pebs); } -static inline unsigned long get_info_data(char *base) + +static int ds_get_index(struct task_struct *task, size_t *pos, + enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.info_data.offset); + struct ds_context *context; + unsigned long base, index; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + base = ds_get(context->ds, qual, ds_buffer_base); + index = ds_get(context->ds, qual, ds_index); + + error = ((index - base) / ds_cfg.sizeof_rec[qual]); + if (pos) + *pos = error; + out: + ds_put_context(context); + return error; } -static inline void set_info_data(char *base, unsigned long value) + +int ds_get_bts_index(struct task_struct *task, size_t *pos) { - (*(unsigned long *)(base + ds_cfg.info_data.offset)) = value; + return ds_get_index(task, pos, ds_bts); } +int ds_get_pebs_index(struct task_struct *task, size_t *pos) +{ + return ds_get_index(task, pos, ds_pebs); +} -int ds_allocate(void **dsp, size_t bts_size_in_bytes) +static int ds_get_end(struct task_struct *task, size_t *pos, + enum ds_qualifier qual) { - size_t bts_size_in_records; - unsigned long bts; - void *ds; + struct ds_context *context; + unsigned long base, end; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + base = ds_get(context->ds, qual, ds_buffer_base); + end = ds_get(context->ds, qual, ds_absolute_maximum); + + error = ((end - base) / ds_cfg.sizeof_rec[qual]); + if (pos) + *pos = error; + out: + ds_put_context(context); + return error; +} - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; +int ds_get_bts_end(struct task_struct *task, size_t *pos) +{ + return ds_get_end(task, pos, ds_bts); +} - if (bts_size_in_bytes < 0) - return -EINVAL; +int ds_get_pebs_end(struct task_struct *task, size_t *pos) +{ + return ds_get_end(task, pos, ds_pebs); +} - bts_size_in_records = - bts_size_in_bytes / ds_cfg.sizeof_bts; - bts_size_in_bytes = - bts_size_in_records * ds_cfg.sizeof_bts; +static int ds_access(struct task_struct *task, size_t index, + const void **record, enum ds_qualifier qual) +{ + struct ds_context *context; + unsigned long base, idx; + int error; - if (bts_size_in_bytes <= 0) + if (!record) return -EINVAL; - bts = (unsigned long)kzalloc(bts_size_in_bytes, GFP_KERNEL); + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; - if (!bts) - return -ENOMEM; + base = ds_get(context->ds, qual, ds_buffer_base); + idx = base + (index * ds_cfg.sizeof_rec[qual]); - ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); + error = -EINVAL; + if (idx > ds_get(context->ds, qual, ds_absolute_maximum)) + goto out; - if (!ds) { - kfree((void *)bts); - return -ENOMEM; - } - - set_bts_buffer_base(ds, bts); - set_bts_index(ds, bts); - set_bts_absolute_maximum(ds, bts + bts_size_in_bytes); - set_bts_interrupt_threshold(ds, bts + bts_size_in_bytes + 1); - - *dsp = ds; - return 0; + *record = (const void *)idx; + error = ds_cfg.sizeof_rec[qual]; + out: + ds_put_context(context); + return error; } -int ds_free(void **dsp) +int ds_access_bts(struct task_struct *task, size_t index, const void **record) { - if (*dsp) { - kfree((void *)get_bts_buffer_base(*dsp)); - kfree(*dsp); - *dsp = NULL; - } - return 0; + return ds_access(task, index, record, ds_bts); } -int ds_get_bts_size(void *ds) +int ds_access_pebs(struct task_struct *task, size_t index, const void **record) { - int size_in_bytes; - - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; - - if (!ds) - return 0; - - size_in_bytes = - get_bts_absolute_maximum(ds) - - get_bts_buffer_base(ds); - return size_in_bytes; + return ds_access(task, index, record, ds_pebs); } -int ds_get_bts_end(void *ds) +static int ds_write(struct task_struct *task, const void *record, size_t size, + enum ds_qualifier qual, int force) { - int size_in_bytes = ds_get_bts_size(ds); - - if (size_in_bytes <= 0) - return size_in_bytes; + struct ds_context *context; + int error; - return size_in_bytes / ds_cfg.sizeof_bts; -} + if (!record) + return -EINVAL; -int ds_get_bts_index(void *ds) -{ - int index_offset_in_bytes; + error = -EPERM; + context = ds_get_context(task); + if (!context) + goto out; - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; + if (!force) { + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + } - index_offset_in_bytes = - get_bts_index(ds) - - get_bts_buffer_base(ds); + error = 0; + while (size) { + unsigned long base, index, end, write_end, int_th; + unsigned long write_size, adj_write_size; + + /* + * write as much as possible without producing an + * overflow interrupt. + * + * interrupt_threshold must either be + * - bigger than absolute_maximum or + * - point to a record between buffer_base and absolute_maximum + * + * index points to a valid record. + */ + base = ds_get(context->ds, qual, ds_buffer_base); + index = ds_get(context->ds, qual, ds_index); + end = ds_get(context->ds, qual, ds_absolute_maximum); + int_th = ds_get(context->ds, qual, ds_interrupt_threshold); + + write_end = min(end, int_th); + + /* if we are already beyond the interrupt threshold, + * we fill the entire buffer */ + if (write_end <= index) + write_end = end; + + if (write_end <= index) + goto out; + + write_size = min((unsigned long) size, write_end - index); + memcpy((void *)index, record, write_size); + + record = (const char *)record + write_size; + size -= write_size; + error += write_size; + + adj_write_size = write_size / ds_cfg.sizeof_rec[qual]; + adj_write_size *= ds_cfg.sizeof_rec[qual]; + + /* zero out trailing bytes */ + memset((char *)index + write_size, 0, + adj_write_size - write_size); + index += adj_write_size; + + if (index >= end) + index = base; + ds_set(context->ds, qual, ds_index, index); + + if (index >= int_th) + ds_overflow(task, context, qual); + } - return index_offset_in_bytes / ds_cfg.sizeof_bts; + out: + ds_put_context(context); + return error; } -int ds_set_overflow(void *ds, int method) +int ds_write_bts(struct task_struct *task, const void *record, size_t size) { - switch (method) { - case DS_O_SIGNAL: - return -EOPNOTSUPP; - case DS_O_WRAP: - return 0; - default: - return -EINVAL; - } + return ds_write(task, record, size, ds_bts, /* force = */ 0); } -int ds_get_overflow(void *ds) +int ds_write_pebs(struct task_struct *task, const void *record, size_t size) { - return DS_O_WRAP; + return ds_write(task, record, size, ds_pebs, /* force = */ 0); } -int ds_clear(void *ds) +int ds_unchecked_write_bts(struct task_struct *task, + const void *record, size_t size) { - int bts_size = ds_get_bts_size(ds); - unsigned long bts_base; - - if (bts_size <= 0) - return bts_size; - - bts_base = get_bts_buffer_base(ds); - memset((void *)bts_base, 0, bts_size); - - set_bts_index(ds, bts_base); - return 0; + return ds_write(task, record, size, ds_bts, /* force = */ 1); } -int ds_read_bts(void *ds, int index, struct bts_struct *out) +int ds_unchecked_write_pebs(struct task_struct *task, + const void *record, size_t size) { - void *bts; + return ds_write(task, record, size, ds_pebs, /* force = */ 1); +} - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; +static int ds_reset_or_clear(struct task_struct *task, + enum ds_qualifier qual, int clear) +{ + struct ds_context *context; + unsigned long base, end; + int error; - if (index < 0) - return -EINVAL; + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; - if (index >= ds_get_bts_size(ds)) - return -EINVAL; + base = ds_get(context->ds, qual, ds_buffer_base); + end = ds_get(context->ds, qual, ds_absolute_maximum); - bts = (void *)(get_bts_buffer_base(ds) + (index * ds_cfg.sizeof_bts)); + if (clear) + memset((void *)base, 0, end - base); - memset(out, 0, sizeof(*out)); - if (get_from_ip(bts) == BTS_ESCAPE_ADDRESS) { - out->qualifier = get_info_type(bts); - out->variant.jiffies = get_info_data(bts); - } else { - out->qualifier = BTS_BRANCH; - out->variant.lbr.from_ip = get_from_ip(bts); - out->variant.lbr.to_ip = get_to_ip(bts); - } + ds_set(context->ds, qual, ds_index, base); - return sizeof(*out);; + error = 0; + out: + ds_put_context(context); + return error; } -int ds_write_bts(void *ds, const struct bts_struct *in) +int ds_reset_bts(struct task_struct *task) { - unsigned long bts; - - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; - - if (ds_get_bts_size(ds) <= 0) - return -ENXIO; + return ds_reset_or_clear(task, ds_bts, /* clear = */ 0); +} - bts = get_bts_index(ds); +int ds_reset_pebs(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_pebs, /* clear = */ 0); +} - memset((void *)bts, 0, ds_cfg.sizeof_bts); - switch (in->qualifier) { - case BTS_INVALID: - break; +int ds_clear_bts(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_bts, /* clear = */ 1); +} - case BTS_BRANCH: - set_from_ip((void *)bts, in->variant.lbr.from_ip); - set_to_ip((void *)bts, in->variant.lbr.to_ip); - break; +int ds_clear_pebs(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_pebs, /* clear = */ 1); +} - case BTS_TASK_ARRIVES: - case BTS_TASK_DEPARTS: - set_from_ip((void *)bts, BTS_ESCAPE_ADDRESS); - set_info_type((void *)bts, in->qualifier); - set_info_data((void *)bts, in->variant.jiffies); - break; +int ds_get_pebs_reset(struct task_struct *task, u64 *value) +{ + struct ds_context *context; + int error; - default: + if (!value) return -EINVAL; - } - bts = bts + ds_cfg.sizeof_bts; - if (bts >= get_bts_absolute_maximum(ds)) - bts = get_bts_buffer_base(ds); - set_bts_index(ds, bts); + context = ds_get_context(task); + error = ds_validate_access(context, ds_pebs); + if (error < 0) + goto out; - return ds_cfg.sizeof_bts; + *value = *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8)); + + error = 0; + out: + ds_put_context(context); + return error; } -unsigned long ds_debugctl_mask(void) +int ds_set_pebs_reset(struct task_struct *task, u64 value) { - return ds_cfg.debugctl_mask; -} + struct ds_context *context; + int error; -#ifdef __i386__ -static const struct ds_configuration ds_cfg_netburst = { - .sizeof_ds = 9 * 4, - .bts_buffer_base = { 0, 4 }, - .bts_index = { 4, 4 }, - .bts_absolute_maximum = { 8, 4 }, - .bts_interrupt_threshold = { 12, 4 }, - .sizeof_bts = 3 * 4, - .from_ip = { 0, 4 }, - .to_ip = { 4, 4 }, - .info_type = { 4, 1 }, - .info_data = { 8, 4 }, - .debugctl_mask = (1<<2)|(1<<3) -}; + context = ds_get_context(task); + error = ds_validate_access(context, ds_pebs); + if (error < 0) + goto out; -static const struct ds_configuration ds_cfg_pentium_m = { - .sizeof_ds = 9 * 4, - .bts_buffer_base = { 0, 4 }, - .bts_index = { 4, 4 }, - .bts_absolute_maximum = { 8, 4 }, - .bts_interrupt_threshold = { 12, 4 }, - .sizeof_bts = 3 * 4, - .from_ip = { 0, 4 }, - .to_ip = { 4, 4 }, - .info_type = { 4, 1 }, - .info_data = { 8, 4 }, - .debugctl_mask = (1<<6)|(1<<7) + *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8)) = value; + + error = 0; + out: + ds_put_context(context); + return error; +} + +static const struct ds_configuration ds_cfg_var = { + .sizeof_ds = sizeof(long) * 12, + .sizeof_field = sizeof(long), + .sizeof_rec[ds_bts] = sizeof(long) * 3, + .sizeof_rec[ds_pebs] = sizeof(long) * 10 }; -#endif /* _i386_ */ - -static const struct ds_configuration ds_cfg_core2 = { - .sizeof_ds = 9 * 8, - .bts_buffer_base = { 0, 8 }, - .bts_index = { 8, 8 }, - .bts_absolute_maximum = { 16, 8 }, - .bts_interrupt_threshold = { 24, 8 }, - .sizeof_bts = 3 * 8, - .from_ip = { 0, 8 }, - .to_ip = { 8, 8 }, - .info_type = { 8, 1 }, - .info_data = { 16, 8 }, - .debugctl_mask = (1<<6)|(1<<7)|(1<<9) +static const struct ds_configuration ds_cfg_64 = { + .sizeof_ds = 8 * 12, + .sizeof_field = 8, + .sizeof_rec[ds_bts] = 8 * 3, + .sizeof_rec[ds_pebs] = 8 * 10 }; static inline void @@ -429,14 +820,13 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) switch (c->x86) { case 0x6: switch (c->x86_model) { -#ifdef __i386__ case 0xD: case 0xE: /* Pentium M */ - ds_configure(&ds_cfg_pentium_m); + ds_configure(&ds_cfg_var); break; -#endif /* _i386_ */ case 0xF: /* Core2 */ - ds_configure(&ds_cfg_core2); + case 0x1C: /* Atom */ + ds_configure(&ds_cfg_64); break; default: /* sorry, don't know about them */ @@ -445,13 +835,11 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) break; case 0xF: switch (c->x86_model) { -#ifdef __i386__ case 0x0: case 0x1: case 0x2: /* Netburst */ - ds_configure(&ds_cfg_netburst); + ds_configure(&ds_cfg_var); break; -#endif /* _i386_ */ default: /* sorry, don't know about them */ break; @@ -462,3 +850,14 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) break; } } + +void ds_free(struct ds_context *context) +{ + /* This is called when the task owning the parameter context + * is dying. There should not be any user of that context left + * to disturb us, anymore. */ + unsigned long leftovers = context->count; + while (leftovers--) + ds_put_context(context); +} +#endif /* CONFIG_X86_DS */ diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index f8476dfbb60..5cec8a75a4e 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -316,6 +316,14 @@ void exit_thread(void) tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; put_cpu(); } +#ifdef CONFIG_X86_DS + /* Free any DS contexts that have not been properly released. */ + if (unlikely(current->thread.ds_ctx)) { + /* we clear debugctl to make sure DS is not used. */ + update_debugctlmsr(0); + ds_free(current->thread.ds_ctx); + } +#endif /* CONFIG_X86_DS */ } void flush_thread(void) @@ -482,18 +490,27 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, { struct thread_struct *prev, *next; unsigned long debugctl; + unsigned long ds_prev = 0, ds_next = 0; prev = &prev_p->thread; next = &next_p->thread; debugctl = prev->debugctlmsr; - if (next->ds_area_msr != prev->ds_area_msr) { + +#ifdef CONFIG_X86_DS + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { /* we clear debugctl to make sure DS * is not in use when we change it */ debugctl = 0; update_debugctlmsr(0); - wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0); + wrmsr(MSR_IA32_DS_AREA, ds_next, 0); } +#endif /* CONFIG_X86_DS */ if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); @@ -517,13 +534,13 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, hard_enable_TSC(); } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e2319f39988..ad213494a22 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -267,6 +267,14 @@ void exit_thread(void) t->io_bitmap_max = 0; put_cpu(); } +#ifdef CONFIG_X86_DS + /* Free any DS contexts that have not been properly released. */ + if (unlikely(t->ds_ctx)) { + /* we clear debugctl to make sure DS is not used. */ + update_debugctlmsr(0); + ds_free(t->ds_ctx); + } +#endif /* CONFIG_X86_DS */ } void flush_thread(void) @@ -492,18 +500,27 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, { struct thread_struct *prev, *next; unsigned long debugctl; + unsigned long ds_prev = 0, ds_next = 0; prev = &prev_p->thread, next = &next_p->thread; debugctl = prev->debugctlmsr; - if (next->ds_area_msr != prev->ds_area_msr) { + +#ifdef CONFIG_X86_DS + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { /* we clear debugctl to make sure DS * is not in use when we change it */ debugctl = 0; update_debugctlmsr(0); - wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr); + wrmsrl(MSR_IA32_DS_AREA, ds_next); } +#endif /* CONFIG_X86_DS */ if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); @@ -541,13 +558,13 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ } /* diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index fb03ef380f0..b7ff783dc5f 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -554,45 +554,115 @@ static int ptrace_set_debugreg(struct task_struct *child, return 0; } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS +/* + * The configuration for a particular BTS hardware implementation. + */ +struct bts_configuration { + /* the size of a BTS record in bytes; at most BTS_MAX_RECORD_SIZE */ + unsigned char sizeof_bts; + /* the size of a field in the BTS record in bytes */ + unsigned char sizeof_field; + /* a bitmask to enable/disable BTS in DEBUGCTL MSR */ + unsigned long debugctl_mask; +}; +static struct bts_configuration bts_cfg; + +#define BTS_MAX_RECORD_SIZE (8 * 3) + + +/* + * Branch Trace Store (BTS) uses the following format. Different + * architectures vary in the size of those fields. + * - source linear address + * - destination linear address + * - flags + * + * Later architectures use 64bit pointers throughout, whereas earlier + * architectures use 32bit pointers in 32bit mode. + * + * We compute the base address for the first 8 fields based on: + * - the field size stored in the DS configuration + * - the relative field position + * + * In order to store additional information in the BTS buffer, we use + * a special source address to indicate that the record requires + * special interpretation. + * + * Netburst indicated via a bit in the flags field whether the branch + * was predicted; this is ignored. + */ -static int ptrace_bts_get_size(struct task_struct *child) +enum bts_field { + bts_from = 0, + bts_to, + bts_flags, + + bts_escape = (unsigned long)-1, + bts_qual = bts_to, + bts_jiffies = bts_flags +}; + +static inline unsigned long bts_get(const char *base, enum bts_field field) { - if (!child->thread.ds_area_msr) - return -ENXIO; + base += (bts_cfg.sizeof_field * field); + return *(unsigned long *)base; +} - return ds_get_bts_index((void *)child->thread.ds_area_msr); +static inline void bts_set(char *base, enum bts_field field, unsigned long val) +{ + base += (bts_cfg.sizeof_field * field);; + (*(unsigned long *)base) = val; } -static int ptrace_bts_read_record(struct task_struct *child, - long index, +/* + * Translate a BTS record from the raw format into the bts_struct format + * + * out (out): bts_struct interpretation + * raw: raw BTS record + */ +static void ptrace_bts_translate_record(struct bts_struct *out, const void *raw) +{ + memset(out, 0, sizeof(*out)); + if (bts_get(raw, bts_from) == bts_escape) { + out->qualifier = bts_get(raw, bts_qual); + out->variant.jiffies = bts_get(raw, bts_jiffies); + } else { + out->qualifier = BTS_BRANCH; + out->variant.lbr.from_ip = bts_get(raw, bts_from); + out->variant.lbr.to_ip = bts_get(raw, bts_to); + } +} + +static int ptrace_bts_read_record(struct task_struct *child, size_t index, struct bts_struct __user *out) { struct bts_struct ret; - int retval; - int bts_end; - int bts_index; - - if (!child->thread.ds_area_msr) - return -ENXIO; + const void *bts_record; + size_t bts_index, bts_end; + int error; - if (index < 0) - return -EINVAL; + error = ds_get_bts_end(child, &bts_end); + if (error < 0) + return error; - bts_end = ds_get_bts_end((void *)child->thread.ds_area_msr); if (bts_end <= index) return -EINVAL; + error = ds_get_bts_index(child, &bts_index); + if (error < 0) + return error; + /* translate the ptrace bts index into the ds bts index */ - bts_index = ds_get_bts_index((void *)child->thread.ds_area_msr); - bts_index -= (index + 1); - if (bts_index < 0) - bts_index += bts_end; + bts_index += bts_end - (index + 1); + if (bts_end <= bts_index) + bts_index -= bts_end; - retval = ds_read_bts((void *)child->thread.ds_area_msr, - bts_index, &ret); - if (retval < 0) - return retval; + error = ds_access_bts(child, bts_index, &bts_record); + if (error < 0) + return error; + + ptrace_bts_translate_record(&ret, bts_record); if (copy_to_user(out, &ret, sizeof(ret))) return -EFAULT; @@ -600,101 +670,106 @@ static int ptrace_bts_read_record(struct task_struct *child, return sizeof(ret); } -static int ptrace_bts_clear(struct task_struct *child) -{ - if (!child->thread.ds_area_msr) - return -ENXIO; - - return ds_clear((void *)child->thread.ds_area_msr); -} - static int ptrace_bts_drain(struct task_struct *child, long size, struct bts_struct __user *out) { - int end, i; - void *ds = (void *)child->thread.ds_area_msr; - - if (!ds) - return -ENXIO; + struct bts_struct ret; + const unsigned char *raw; + size_t end, i; + int error; - end = ds_get_bts_index(ds); - if (end <= 0) - return end; + error = ds_get_bts_index(child, &end); + if (error < 0) + return error; if (size < (end * sizeof(struct bts_struct))) return -EIO; - for (i = 0; i < end; i++, out++) { - struct bts_struct ret; - int retval; + error = ds_access_bts(child, 0, (const void **)&raw); + if (error < 0) + return error; - retval = ds_read_bts(ds, i, &ret); - if (retval < 0) - return retval; + for (i = 0; i < end; i++, out++, raw += bts_cfg.sizeof_bts) { + ptrace_bts_translate_record(&ret, raw); if (copy_to_user(out, &ret, sizeof(ret))) return -EFAULT; } - ds_clear(ds); + error = ds_clear_bts(child); + if (error < 0) + return error; return end; } +static void ptrace_bts_ovfl(struct task_struct *child) +{ + send_sig(child->thread.bts_ovfl_signal, child, 0); +} + static int ptrace_bts_config(struct task_struct *child, long cfg_size, const struct ptrace_bts_config __user *ucfg) { struct ptrace_bts_config cfg; - int bts_size, ret = 0; - void *ds; + int error = 0; + + error = -EOPNOTSUPP; + if (!bts_cfg.sizeof_bts) + goto errout; + error = -EIO; if (cfg_size < sizeof(cfg)) - return -EIO; + goto errout; + error = -EFAULT; if (copy_from_user(&cfg, ucfg, sizeof(cfg))) - return -EFAULT; + goto errout; - if ((int)cfg.size < 0) - return -EINVAL; + error = -EINVAL; + if ((cfg.flags & PTRACE_BTS_O_SIGNAL) && + !(cfg.flags & PTRACE_BTS_O_ALLOC)) + goto errout; - bts_size = 0; - ds = (void *)child->thread.ds_area_msr; - if (ds) { - bts_size = ds_get_bts_size(ds); - if (bts_size < 0) - return bts_size; - } - cfg.size = PAGE_ALIGN(cfg.size); + if (cfg.flags & PTRACE_BTS_O_ALLOC) { + ds_ovfl_callback_t ovfl = 0; + unsigned int sig = 0; - if (bts_size != cfg.size) { - ret = ptrace_bts_realloc(child, cfg.size, - cfg.flags & PTRACE_BTS_O_CUT_SIZE); - if (ret < 0) + /* we ignore the error in case we were not tracing child */ + (void)ds_release_bts(child); + + if (cfg.flags & PTRACE_BTS_O_SIGNAL) { + if (!cfg.signal) + goto errout; + + sig = cfg.signal; + ovfl = ptrace_bts_ovfl; + } + + error = ds_request_bts(child, /* base = */ 0, cfg.size, ovfl); + if (error < 0) goto errout; - ds = (void *)child->thread.ds_area_msr; + child->thread.bts_ovfl_signal = sig; } - if (cfg.flags & PTRACE_BTS_O_SIGNAL) - ret = ds_set_overflow(ds, DS_O_SIGNAL); - else - ret = ds_set_overflow(ds, DS_O_WRAP); - if (ret < 0) + error = -EINVAL; + if (!child->thread.ds_ctx && cfg.flags) goto errout; if (cfg.flags & PTRACE_BTS_O_TRACE) - child->thread.debugctlmsr |= ds_debugctl_mask(); + child->thread.debugctlmsr |= bts_cfg.debugctl_mask; else - child->thread.debugctlmsr &= ~ds_debugctl_mask(); + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; if (cfg.flags & PTRACE_BTS_O_SCHED) set_tsk_thread_flag(child, TIF_BTS_TRACE_TS); else clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); - ret = sizeof(cfg); + error = sizeof(cfg); out: if (child->thread.debugctlmsr) @@ -702,10 +777,10 @@ out: else clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - return ret; + return error; errout: - child->thread.debugctlmsr &= ~ds_debugctl_mask(); + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); goto out; } @@ -714,29 +789,40 @@ static int ptrace_bts_status(struct task_struct *child, long cfg_size, struct ptrace_bts_config __user *ucfg) { - void *ds = (void *)child->thread.ds_area_msr; struct ptrace_bts_config cfg; + size_t end; + const void *base, *max; + int error; if (cfg_size < sizeof(cfg)) return -EIO; - memset(&cfg, 0, sizeof(cfg)); + error = ds_get_bts_end(child, &end); + if (error < 0) + return error; - if (ds) { - cfg.size = ds_get_bts_size(ds); + error = ds_access_bts(child, /* index = */ 0, &base); + if (error < 0) + return error; - if (ds_get_overflow(ds) == DS_O_SIGNAL) - cfg.flags |= PTRACE_BTS_O_SIGNAL; + error = ds_access_bts(child, /* index = */ end, &max); + if (error < 0) + return error; - if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && - child->thread.debugctlmsr & ds_debugctl_mask()) - cfg.flags |= PTRACE_BTS_O_TRACE; + memset(&cfg, 0, sizeof(cfg)); + cfg.size = (max - base); + cfg.signal = child->thread.bts_ovfl_signal; + cfg.bts_size = sizeof(struct bts_struct); - if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) - cfg.flags |= PTRACE_BTS_O_SCHED; - } + if (cfg.signal) + cfg.flags |= PTRACE_BTS_O_SIGNAL; - cfg.bts_size = sizeof(struct bts_struct); + if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && + child->thread.debugctlmsr & bts_cfg.debugctl_mask) + cfg.flags |= PTRACE_BTS_O_TRACE; + + if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) + cfg.flags |= PTRACE_BTS_O_SCHED; if (copy_to_user(ucfg, &cfg, sizeof(cfg))) return -EFAULT; @@ -744,89 +830,38 @@ static int ptrace_bts_status(struct task_struct *child, return sizeof(cfg); } - static int ptrace_bts_write_record(struct task_struct *child, const struct bts_struct *in) { - int retval; + unsigned char bts_record[BTS_MAX_RECORD_SIZE]; - if (!child->thread.ds_area_msr) - return -ENXIO; + BUG_ON(BTS_MAX_RECORD_SIZE < bts_cfg.sizeof_bts); - retval = ds_write_bts((void *)child->thread.ds_area_msr, in); - if (retval) - return retval; + memset(bts_record, 0, bts_cfg.sizeof_bts); + switch (in->qualifier) { + case BTS_INVALID: + break; - return sizeof(*in); -} + case BTS_BRANCH: + bts_set(bts_record, bts_from, in->variant.lbr.from_ip); + bts_set(bts_record, bts_to, in->variant.lbr.to_ip); + break; -static int ptrace_bts_realloc(struct task_struct *child, - int size, int reduce_size) -{ - unsigned long rlim, vm; - int ret, old_size; + case BTS_TASK_ARRIVES: + case BTS_TASK_DEPARTS: + bts_set(bts_record, bts_from, bts_escape); + bts_set(bts_record, bts_qual, in->qualifier); + bts_set(bts_record, bts_jiffies, in->variant.jiffies); + break; - if (size < 0) + default: return -EINVAL; - - old_size = ds_get_bts_size((void *)child->thread.ds_area_msr); - if (old_size < 0) - return old_size; - - ret = ds_free((void **)&child->thread.ds_area_msr); - if (ret < 0) - goto out; - - size >>= PAGE_SHIFT; - old_size >>= PAGE_SHIFT; - - current->mm->total_vm -= old_size; - current->mm->locked_vm -= old_size; - - if (size == 0) - goto out; - - rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; - vm = current->mm->total_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->total_vm; - if (size <= 0) - goto out; } - rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; - vm = current->mm->locked_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->locked_vm; - if (size <= 0) - goto out; - } - - ret = ds_allocate((void **)&child->thread.ds_area_msr, - size << PAGE_SHIFT); - if (ret < 0) - goto out; - - current->mm->total_vm += size; - current->mm->locked_vm += size; - -out: - if (child->thread.ds_area_msr) - set_tsk_thread_flag(child, TIF_DS_AREA_MSR); - else - clear_tsk_thread_flag(child, TIF_DS_AREA_MSR); - - return ret; + /* The writing task will be the switched-to task on a context + * switch. It needs to write into the switched-from task's BTS + * buffer. */ + return ds_unchecked_write_bts(child, bts_record, bts_cfg.sizeof_bts); } void ptrace_bts_take_timestamp(struct task_struct *tsk, @@ -839,7 +874,66 @@ void ptrace_bts_take_timestamp(struct task_struct *tsk, ptrace_bts_write_record(tsk, &rec); } -#endif /* X86_BTS */ + +static const struct bts_configuration bts_cfg_netburst = { + .sizeof_bts = sizeof(long) * 3, + .sizeof_field = sizeof(long), + .debugctl_mask = (1<<2)|(1<<3)|(1<<5) +}; + +static const struct bts_configuration bts_cfg_pentium_m = { + .sizeof_bts = sizeof(long) * 3, + .sizeof_field = sizeof(long), + .debugctl_mask = (1<<6)|(1<<7) +}; + +static const struct bts_configuration bts_cfg_core2 = { + .sizeof_bts = 8 * 3, + .sizeof_field = 8, + .debugctl_mask = (1<<6)|(1<<7)|(1<<9) +}; + +static inline void bts_configure(const struct bts_configuration *cfg) +{ + bts_cfg = *cfg; +} + +void __cpuinit ptrace_bts_init_intel(struct cpuinfo_x86 *c) +{ + switch (c->x86) { + case 0x6: + switch (c->x86_model) { + case 0xD: + case 0xE: /* Pentium M */ + bts_configure(&bts_cfg_pentium_m); + break; + case 0xF: /* Core2 */ + case 0x1C: /* Atom */ + bts_configure(&bts_cfg_core2); + break; + default: + /* sorry, don't know about them */ + break; + } + break; + case 0xF: + switch (c->x86_model) { + case 0x0: + case 0x1: + case 0x2: /* Netburst */ + bts_configure(&bts_cfg_netburst); + break; + default: + /* sorry, don't know about them */ + break; + } + break; + default: + /* sorry, don't know about them */ + break; + } +} +#endif /* CONFIG_X86_PTRACE_BTS */ /* * Called by kernel/ptrace.c when detaching.. @@ -852,15 +946,15 @@ void ptrace_disable(struct task_struct *child) #ifdef TIF_SYSCALL_EMU clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); #endif - if (child->thread.ds_area_msr) { -#ifdef X86_BTS - ptrace_bts_realloc(child, 0, 0); -#endif - child->thread.debugctlmsr &= ~ds_debugctl_mask(); - if (!child->thread.debugctlmsr) - clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); - } +#ifdef CONFIG_X86_PTRACE_BTS + (void)ds_release_bts(child); + + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; + if (!child->thread.debugctlmsr) + clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); + + clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); +#endif /* CONFIG_X86_PTRACE_BTS */ } #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION @@ -980,7 +1074,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* * These bits need more cooking - not enabled yet: */ -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS case PTRACE_BTS_CONFIG: ret = ptrace_bts_config (child, data, (struct ptrace_bts_config __user *)addr); @@ -992,7 +1086,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_BTS_SIZE: - ret = ptrace_bts_get_size(child); + ret = ds_get_bts_index(child, /* pos = */ 0); break; case PTRACE_BTS_GET: @@ -1001,14 +1095,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_BTS_CLEAR: - ret = ptrace_bts_clear(child); + ret = ds_clear_bts(child); break; case PTRACE_BTS_DRAIN: ret = ptrace_bts_drain (child, data, (struct bts_struct __user *) addr); break; -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ default: ret = ptrace_request(child, request, addr, data); diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index f2fc8feb727..f7aebe13c99 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -920,11 +920,12 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_BTS); if (!(l1 & (1<<12))) set_cpu_cap(c, X86_FEATURE_PEBS); + ds_init_intel(c); } if (cpu_has_bts) - ds_init_intel(c); + ptrace_bts_init_intel(c); n = c->extended_cpuid_level; if (n >= 0x80000008) { -- cgit v1.2.3 From 970e725098a6da5a9c1f8128102c812e31a0444c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 16 Apr 2008 16:40:17 -0700 Subject: x86, ptrace: PEBS support, warning fix arch/x86/kernel/process_32.c:566: warning: unused variable 'ds_next' arch/x86/kernel/process_32.c:566: warning: unused variable 'ds_prev' Cc: Markus Metzger Cc: Andi Kleen Cc: "H. Peter Anvin" Cc: "Siddha, Suresh B" Cc: Roland McGrath Cc: Michael Kerrisk Cc: Cc: stephane eranian Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_32.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 5cec8a75a4e..496ea3110aa 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -484,20 +484,13 @@ int set_tsc_mode(unsigned int val) return 0; } -static noinline void -__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, - struct tss_struct *tss) +#ifdef CONFIG_X86_DS +static int update_debugctl(struct thread_struct *prev, + struct thread_struct *next, unsigned long debugctl) { - struct thread_struct *prev, *next; - unsigned long debugctl; - unsigned long ds_prev = 0, ds_next = 0; + unsigned long ds_prev = 0; + unsigned long ds_next = 0; - prev = &prev_p->thread; - next = &next_p->thread; - - debugctl = prev->debugctlmsr; - -#ifdef CONFIG_X86_DS if (prev->ds_ctx) ds_prev = (unsigned long)prev->ds_ctx->ds; if (next->ds_ctx) @@ -510,8 +503,28 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, update_debugctlmsr(0); wrmsr(MSR_IA32_DS_AREA, ds_next, 0); } + return debugctl; +} +#else +static int update_debugctl(struct thread_struct *prev, + struct thread_struct *next, unsigned long debugctl) +{ + return debugctl; +} #endif /* CONFIG_X86_DS */ +static noinline void +__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, + struct tss_struct *tss) +{ + struct thread_struct *prev, *next; + unsigned long debugctl; + + prev = &prev_p->thread; + next = &next_p->thread; + + debugctl = update_debugctl(prev, next, prev->debugctlmsr); + if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); -- cgit v1.2.3 From 573da4224e8c3800e613d715e909c3179a7e3cb2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 28 Apr 2008 23:15:04 +0400 Subject: x86: DS cleanup - dont treat 0 as NULL Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/ds.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 5b32b6d062b..24a323c9599 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -238,12 +238,12 @@ static inline struct ds_context *ds_alloc_context(struct task_struct *task) context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) - return 0; + return NULL; context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); if (!context->ds) { kfree(context); - return 0; + return NULL; } *p_context = context; @@ -279,7 +279,7 @@ static inline void ds_put_context(struct ds_context *context) if (--context->count) goto out; - *(context->this) = 0; + *(context->this) = NULL; if (context->task) clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR); @@ -341,16 +341,16 @@ static inline void *ds_allocate_buffer(size_t size, unsigned int *pages) rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; vm = current->mm->total_vm + pgsz; if (rlim < vm) - return 0; + return NULL; rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; vm = current->mm->locked_vm + pgsz; if (rlim < vm) - return 0; + return NULL; buffer = kzalloc(size, GFP_KERNEL); if (!buffer) - return 0; + return NULL; current->mm->total_vm += pgsz; current->mm->locked_vm += pgsz; @@ -395,7 +395,7 @@ static int ds_request(struct task_struct *task, void *base, size_t size, if (context->owner[qual] == current) goto out_unlock; error = -EPERM; - if (context->owner[qual] != 0) + if (context->owner[qual] != NULL) goto out_unlock; context->owner[qual] = current; @@ -445,7 +445,7 @@ static int ds_request(struct task_struct *task, void *base, size_t size, return error; out_release: - context->owner[qual] = 0; + context->owner[qual] = NULL; ds_put_context(context); return error; @@ -825,7 +825,7 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) ds_configure(&ds_cfg_var); break; case 0xF: /* Core2 */ - case 0x1C: /* Atom */ + case 0x1C: /* Atom */ ds_configure(&ds_cfg_64); break; default: -- cgit v1.2.3 From 34b2cd5b688b012975fcfc3b3970fc3508fa82c4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 17 May 2008 08:30:07 +0200 Subject: x86: PEBS cleanup Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index ad213494a22..4a93c98a60a 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -500,7 +500,6 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, { struct thread_struct *prev, *next; unsigned long debugctl; - unsigned long ds_prev = 0, ds_next = 0; prev = &prev_p->thread, next = &next_p->thread; @@ -508,17 +507,23 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, debugctl = prev->debugctlmsr; #ifdef CONFIG_X86_DS - if (prev->ds_ctx) - ds_prev = (unsigned long)prev->ds_ctx->ds; - if (next->ds_ctx) - ds_next = (unsigned long)next->ds_ctx->ds; - - if (ds_next != ds_prev) { - /* we clear debugctl to make sure DS - * is not in use when we change it */ - debugctl = 0; - update_debugctlmsr(0); - wrmsrl(MSR_IA32_DS_AREA, ds_next); + { + unsigned long ds_prev = 0, ds_next = 0; + + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { + /* + * We clear debugctl to make sure DS + * is not in use when we change it: + */ + debugctl = 0; + update_debugctlmsr(0); + wrmsrl(MSR_IA32_DS_AREA, ds_next); + } } #endif /* CONFIG_X86_DS */ -- cgit v1.2.3 From 63cc8c75156462d4b42cbdd76c293b7eee7ddbfe Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 12 May 2008 15:44:40 +0200 Subject: percpu: introduce DEFINE_PER_CPU_PAGE_ALIGNED() macro While examining holes in percpu section I found this : c05f5000 D per_cpu__current_task c05f5000 D __per_cpu_start c05f5004 D per_cpu__cpu_number c05f5008 D per_cpu__irq_regs c05f500c d per_cpu__cpu_devices c05f5040 D per_cpu__cyc2ns c05f6000 d per_cpu__cpuid4_info c05f6004 d per_cpu__cache_kobject c05f6008 d per_cpu__index_kobject c05f7000 D per_cpu__gdt_page This is because gdt_page is a percpu variable, defined with a page alignement, and linker is doing its job, two times because of .o nesting in the build process. I introduced a new macro DEFINE_PER_CPU_PAGE_ALIGNED() to avoid wasting this space. All page aligned variables (only one at this time) are put in a separate subsection .data.percpu.page_aligned, at the very begining of percpu zone. Before patch , on a x86_32 machine : .data.percpu 30232 3227471872 .data.percpu 22168 3227471872 Thats 8064 bytes saved for each CPU. Signed-off-by: Eric Dumazet Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/vmlinux_32.lds.S | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index d0463a94624..b2f54fafb8b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -21,7 +21,7 @@ #include "cpu.h" -DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { +DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S index ce5ed083a1e..0f7c29a8c4e 100644 --- a/arch/x86/kernel/vmlinux_32.lds.S +++ b/arch/x86/kernel/vmlinux_32.lds.S @@ -189,6 +189,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { __per_cpu_start = .; + *(.data.percpu.page_aligned) *(.data.percpu) *(.data.percpu.shared_aligned) __per_cpu_end = .; -- cgit v1.2.3 From 3243b4ed817fad04e56e7b7dc78ec28dc8322ff2 Mon Sep 17 00:00:00 2001 From: Krzysztof Oledzki Date: Wed, 4 Jun 2008 03:40:17 +0200 Subject: x86: add another PCI ID for ICH6 force-hpet Tested on Asus P5GDC-V $ lspci -n -n |grep ISA 00:1f.0 ISA bridge [0601]: Intel Corporation 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge [8086:2640] (rev 03) Force enabled HPET at base address 0xfed00000 hpet clockevent registered hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0 hpet0: 3 64-bit timers, 14318180 Hz Signed-off-by: Krzysztof Piotr Oledzki Signed-off-by: Ingo Molnar --- arch/x86/kernel/quirks.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index d89a648fe71..06e1fd6be83 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -158,6 +158,8 @@ static void ich_force_enable_hpet(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, ich_force_enable_hpet); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, -- cgit v1.2.3 From 59ea746337c69f6a5f1bc4d5e8544b3cbf12f801 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 12 Jun 2008 13:56:40 +0200 Subject: MM: virtual address debug Add some (configurable) expensive sanity checking to catch wrong address translations on x86. - create linux/mmdebug.h file to be able include this file in asm headers to not get unsolvable loops in header files - __phys_addr on x86_32 became a function in ioremap.c since PAGE_OFFSET, is_vmalloc_addr and VMALLOC_* non-constasts are undefined if declared in page_32.h - add __phys_addr_const for initializing doublefault_tss.__cr3 Tested on 386, 386pae, x86_64 and x86_64 numa=fake=2. Contains Andi's enable numa virtual address debug patch. Signed-off-by: Jiri Slaby Cc: Andi Kleen Signed-off-by: Ingo Molnar --- arch/x86/kernel/doublefault_32.c | 2 +- arch/x86/mm/ioremap.c | 31 ++++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index a47798b59f0..395acb12b0d 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c @@ -66,6 +66,6 @@ struct tss_struct doublefault_tss __cacheline_aligned = { .ds = __USER_DS, .fs = __KERNEL_PERCPU, - .__cr3 = __pa(swapper_pg_dir) + .__cr3 = __phys_addr_const((unsigned long)swapper_pg_dir) } }; diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 2b2bb3f9b68..a78ffef62a2 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -23,18 +23,26 @@ #ifdef CONFIG_X86_64 -unsigned long __phys_addr(unsigned long x) +static inline int phys_addr_valid(unsigned long addr) { - if (x >= __START_KERNEL_map) - return x - __START_KERNEL_map + phys_base; - return x - PAGE_OFFSET; + return addr < (1UL << boot_cpu_data.x86_phys_bits); } -EXPORT_SYMBOL(__phys_addr); -static inline int phys_addr_valid(unsigned long addr) +unsigned long __phys_addr(unsigned long x) { - return addr < (1UL << boot_cpu_data.x86_phys_bits); + if (x >= __START_KERNEL_map) { + x -= __START_KERNEL_map; + VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE); + x += phys_base; + } else { + VIRTUAL_BUG_ON(x < PAGE_OFFSET); + x -= PAGE_OFFSET; + VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM : + !phys_addr_valid(x)); + } + return x; } +EXPORT_SYMBOL(__phys_addr); #else @@ -43,6 +51,15 @@ static inline int phys_addr_valid(unsigned long addr) return 1; } +unsigned long __phys_addr(unsigned long x) +{ + /* VMALLOC_* aren't constants; not available at the boot time */ + VIRTUAL_BUG_ON(x < PAGE_OFFSET || (system_state != SYSTEM_BOOTING && + is_vmalloc_addr((void *)x))); + return x - PAGE_OFFSET; +} +EXPORT_SYMBOL(__phys_addr); + #endif int page_is_ram(unsigned long pagenr) -- cgit v1.2.3 From a1bf9631be7332ce0641e299ddafad2d8223100f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 12 Jun 2008 13:56:40 +0200 Subject: x86, MM: virtual address debug, v2 I've removed the test from phys_to_nid and made a function from __phys_addr only when the debugging is enabled (on x86_32). Signed-off-by: Jiri Slaby Cc: tglx@linutronix.de Cc: hpa@zytor.com Cc: Mike Travis Cc: Nick Piggin Cc: Cc: linux-mm@kvack.org Cc: Jiri Slaby Cc: Andi Kleen Signed-off-by: Ingo Molnar --- arch/x86/mm/ioremap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index a78ffef62a2..9dd3cb90597 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -51,6 +51,7 @@ static inline int phys_addr_valid(unsigned long addr) return 1; } +#ifdef CONFIG_DEBUG_VIRTUAL unsigned long __phys_addr(unsigned long x) { /* VMALLOC_* aren't constants; not available at the boot time */ @@ -59,6 +60,7 @@ unsigned long __phys_addr(unsigned long x) return x - PAGE_OFFSET; } EXPORT_SYMBOL(__phys_addr); +#endif #endif -- cgit v1.2.3 From f3561810b163aca5388ad550abbbc82ae5323189 Mon Sep 17 00:00:00 2001 From: Joe Buehler Date: Mon, 9 Jun 2008 08:55:20 -0400 Subject: x86: add PCI ID for 6300ESB force hpet 00:1f.0 ISA bridge: Intel Corporation 6300ESB LPC Interface Controller (rev 02) 00:1f.0 Class 0601: 8086:25a1 (rev 02) kernel: pci 0000:00:1f.0: Force enabled HPET at 0xfed00000 kernel: hpet clockevent registered kernel: hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0 kernel: hpet0: 3 64-bit timers, 14318180 Hz Signed-off-by: Ingo Molnar --- arch/x86/kernel/quirks.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 06e1fd6be83..f327abafe3e 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -257,6 +257,8 @@ static void old_ich_force_enable_hpet_user(struct pci_dev *dev) old_ich_force_enable_hpet(dev); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, + old_ich_force_enable_hpet_user); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, old_ich_force_enable_hpet_user); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, -- cgit v1.2.3 From d94d93ca5cc36cd78c532def62772c98fe8ba5d7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:46 -0700 Subject: x64, x2apic/intr-remap: 8259 specific mask/unmask routines 8259 specific mask/unmask routines which be used later while enabling interrupt-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/i8259.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index dc92b49d920..4b8a53d841f 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -282,6 +282,30 @@ static int __init i8259A_init_sysfs(void) device_initcall(i8259A_init_sysfs); +void mask_8259A(void) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ + + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +void unmask_8259A(void) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + + outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ + outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ + + spin_unlock_irqrestore(&i8259A_lock, flags); +} + void init_8259A(int auto_eoi) { unsigned long flags; -- cgit v1.2.3 From 4dc2f96cacd1e74c688f94348a3bfd0a980817d5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:47 -0700 Subject: x64, x2apic/intr-remap: ioapic routines which deal with initial io-apic RTE setup Generic ioapic specific routines which be used later during enabling interrupt-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_64.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 9e645cba11c..84dd63c13d6 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -114,6 +114,9 @@ DEFINE_SPINLOCK(vector_lock); */ int nr_ioapic_registers[MAX_IO_APICS]; +/* I/O APIC RTE contents at the OS boot up */ +struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS]; + /* I/O APIC entries */ struct mp_config_ioapic mp_ioapics[MAX_IO_APICS]; int nr_ioapics; @@ -446,6 +449,69 @@ static void clear_IO_APIC (void) clear_IO_APIC_pin(apic, pin); } +/* + * Saves and masks all the unmasked IO-APIC RTE's + */ +int save_mask_IO_APIC_setup(void) +{ + union IO_APIC_reg_01 reg_01; + unsigned long flags; + int apic, pin; + + /* + * The number of IO-APIC IRQ registers (== #pins): + */ + for (apic = 0; apic < nr_ioapics; apic++) { + spin_lock_irqsave(&ioapic_lock, flags); + reg_01.raw = io_apic_read(apic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + nr_ioapic_registers[apic] = reg_01.bits.entries+1; + } + + for (apic = 0; apic < nr_ioapics; apic++) { + early_ioapic_entries[apic] = + kzalloc(sizeof(struct IO_APIC_route_entry) * + nr_ioapic_registers[apic], GFP_KERNEL); + if (!early_ioapic_entries[apic]) + return -ENOMEM; + } + + for (apic = 0; apic < nr_ioapics; apic++) + for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { + struct IO_APIC_route_entry entry; + + entry = early_ioapic_entries[apic][pin] = + ioapic_read_entry(apic, pin); + if (!entry.mask) { + entry.mask = 1; + ioapic_write_entry(apic, pin, entry); + } + } + return 0; +} + +void restore_IO_APIC_setup(void) +{ + int apic, pin; + + for (apic = 0; apic < nr_ioapics; apic++) + for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) + ioapic_write_entry(apic, pin, + early_ioapic_entries[apic][pin]); +} + +void reinit_intr_remapped_IO_APIC(int intr_remapping) +{ + /* + * for now plain restore of previous settings. + * TBD: In the case of OS enabling interrupt-remapping, + * IO-APIC RTE's need to be setup to point to interrupt-remapping + * table entries. for now, do a plain restore, and wait for + * the setup_IO_APIC_irqs() to do proper initialization. + */ + restore_IO_APIC_setup(); +} + int skip_ioapic_setup; int ioapic_force; -- cgit v1.2.3 From 0c81c746f9bdbfaafe64322d540c8b7b59c27314 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:48 -0700 Subject: x64, x2apic/intr-remap: introduce read_apic_id() to genapic routines Move the read_apic_id() to genapic routines. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 5 +++++ arch/x86/kernel/genapic_64.c | 11 ----------- arch/x86/kernel/genapic_flat_64.c | 14 +++++++++++++- arch/x86/kernel/genx2apic_uv_x.c | 14 +++++++++++++- 4 files changed, 31 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 1e3d32e27c1..9dd4ee4735f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1096,6 +1096,11 @@ void __cpuinit generic_processor_info(int apicid, int version) cpu_set(cpu, cpu_present_map); } +int hard_smp_processor_id(void) +{ + return read_apic_id(); +} + /* * Power management */ diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 1fa8be5bd21..7414871751a 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -79,17 +79,6 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 0; } -unsigned int read_apic_id(void) -{ - unsigned int id; - - WARN_ON(preemptible() && num_online_cpus() > 1); - id = apic_read(APIC_ID); - if (uv_system_type >= UV_X2APIC) - id |= __get_cpu_var(x2apic_extra_bits); - return id; -} - enum uv_system_type get_uv_system_type(void) { return uv_system_type; diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 1a9c68845ee..400ed8df8b4 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -15,9 +15,11 @@ #include #include #include +#include #include #include #include +#include static cpumask_t flat_target_cpus(void) { @@ -95,9 +97,17 @@ static void flat_send_IPI_all(int vector) __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); } +static unsigned int read_xapic_id(void) +{ + unsigned int id; + + id = GET_XAPIC_ID(apic_read(APIC_ID)); + return id; +} + static int flat_apic_id_registered(void) { - return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map); + return physid_isset(read_xapic_id(), phys_cpu_present_map); } static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask) @@ -123,6 +133,7 @@ struct genapic apic_flat = { .send_IPI_mask = flat_send_IPI_mask, .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, + .read_apic_id = read_xapic_id, }; /* @@ -187,4 +198,5 @@ struct genapic apic_physflat = { .send_IPI_mask = physflat_send_IPI_mask, .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, + .read_apic_id = read_xapic_id, }; diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 711f11c30b0..1ef99be1848 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -134,9 +135,19 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } +static unsigned int uv_read_apic_id(void) +{ + unsigned int id; + + WARN_ON(preemptible() && num_online_cpus() > 1); + id = apic_read(APIC_ID) | __get_cpu_var(x2apic_extra_bits); + + return id; +} + static unsigned int phys_pkg_id(int index_msb) { - return GET_APIC_ID(read_apic_id()) >> index_msb; + return uv_read_apic_id() >> index_msb; } #ifdef ZZZ /* Needs x2apic patch */ @@ -159,6 +170,7 @@ struct genapic apic_x2apic_uv_x = { /* ZZZ.send_IPI_self = uv_send_IPI_self, */ .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */ + .read_apic_id = uv_read_apic_id, }; static __cpuinit void set_x2apic_extra_bits(int pnode) -- cgit v1.2.3 From 2d7a66d02e11af9ab8e16c76d22767e622b4e3d7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 11 Jul 2008 14:24:19 -0700 Subject: x64, x2apic/intr-remap: Interrupt-remapping and x2apic support, fix Yinghai Lu wrote: > Setting APIC routing to physical flat > Kernel panic - not syncing: Boot APIC ID in local APIC unexpected (0 vs 4) > Pid: 1, comm: swapper Not tainted 2.6.26-rc9-tip-01763-g74f94b1-dirty #320 > > Call Trace: > [] ? set_cpu_sibling_map+0x38c/0x3bd > [] ? read_xapic_id+0x25/0x3e > [] ? verify_local_APIC+0x139/0x1b9 > [] ? read_xapic_id+0x25/0x3e > [] ? native_smp_prepare_cpus+0x224/0x2e9 > [] ? kernel_init+0x64/0x341 > [] ? child_rip+0xa/0x11 > [] ? kernel_init+0x0/0x341 > [] ? child_rip+0x0/0x11 > > > guess read_apic_id changing cuase some problem... genapic's read_apic_id() returns the actual apic id extracted from the APIC_ID register. And in some cases like UV, read_apic_id() returns completely different values from APIC ID register. Use the native apic register read, rather than genapic read_apic_id() in verify_local_APIC() And also, lapic_suspend() should also use native apic register read. Reported-by: Yinghai Lu Signed-off-by: Suresh Siddha Cc: "akpm@linux-foundation.org" Cc: "arjan@linux.intel.com" Cc: "andi@firstfloor.org" Cc: "ebiederm@xmission.com" Cc: "jbarnes@virtuousgeek.org" Cc: "steiner@sgi.com" Cc: "jeremy@goop.org" Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 9dd4ee4735f..3963f590c3d 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -626,10 +626,10 @@ int __init verify_local_APIC(void) /* * The ID register is read/write in a real APIC. */ - reg0 = read_apic_id(); + reg0 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); - reg1 = read_apic_id(); + reg1 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); apic_write(APIC_ID, reg0); if (reg1 != (reg0 ^ APIC_ID_MASK)) @@ -1137,7 +1137,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) maxlvt = lapic_get_maxlvt(); - apic_pm_state.apic_id = read_apic_id(); + apic_pm_state.apic_id = apic_read(APIC_ID); apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); apic_pm_state.apic_ldr = apic_read(APIC_LDR); apic_pm_state.apic_dfr = apic_read(APIC_DFR); -- cgit v1.2.3 From 1b374e4d6f8b3eb2fcd034fcc24ea8ba1dfde7aa Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:49 -0700 Subject: x64, x2apic/intr-remap: basic apic ops support Introduce basic apic operations which handle the apic programming. This will be used later to introduce another specific operations for x2apic. For the perfomance critial accesses like IPI's, EOI etc, we use the native operations as they are already referenced by different indirections like genapic, irq_chip etc. 64bit Paravirt ops can also define their apic operations accordingly. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 ++++++ arch/x86/kernel/apic_64.c | 34 ++++++++++++++++++++++++++++++++-- arch/x86/kernel/io_apic_64.c | 8 ++++---- arch/x86/kernel/paravirt.c | 8 +++++--- arch/x86/kernel/smpboot.c | 28 +++++++++++----------------- 5 files changed, 58 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3e58b676d23..2a83c07bd88 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -145,6 +145,12 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } +void apic_icr_write(u32 low, u32 id) +{ + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); + apic_write_around(APIC_ICR, low); +} + void apic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 3963f590c3d..9bb040689b3 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -119,13 +119,13 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } -void apic_wait_icr_idle(void) +void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) cpu_relax(); } -u32 safe_apic_wait_icr_idle(void) +u32 safe_xapic_wait_icr_idle(void) { u32 send_status; int timeout; @@ -141,6 +141,36 @@ u32 safe_apic_wait_icr_idle(void) return send_status; } +void xapic_icr_write(u32 low, u32 id) +{ + apic_write(APIC_ICR2, id << 24); + apic_write(APIC_ICR, low); +} + +u64 xapic_icr_read(void) +{ + u32 icr1, icr2; + + icr2 = apic_read(APIC_ICR2); + icr1 = apic_read(APIC_ICR); + + return (icr1 | ((u64)icr2 << 32)); +} + +static struct apic_ops xapic_ops = { + .read = native_apic_mem_read, + .write = native_apic_mem_write, + .write_atomic = native_apic_mem_write_atomic, + .icr_read = xapic_icr_read, + .icr_write = xapic_icr_write, + .wait_icr_idle = xapic_wait_icr_idle, + .safe_wait_icr_idle = safe_xapic_wait_icr_idle, +}; + +struct apic_ops __read_mostly *apic_ops = &xapic_ops; + +EXPORT_SYMBOL_GPL(apic_ops); + /** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */ diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 84dd63c13d6..b62d42ef928 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -1157,6 +1157,7 @@ static __apicdebuginit void print_APIC_bitfield (int base) void __apicdebuginit print_local_APIC(void * dummy) { unsigned int v, ver, maxlvt; + unsigned long icr; if (apic_verbosity == APIC_QUIET) return; @@ -1200,10 +1201,9 @@ void __apicdebuginit print_local_APIC(void * dummy) v = apic_read(APIC_ESR); printk(KERN_DEBUG "... APIC ESR: %08x\n", v); - v = apic_read(APIC_ICR); - printk(KERN_DEBUG "... APIC ICR: %08x\n", v); - v = apic_read(APIC_ICR2); - printk(KERN_DEBUG "... APIC ICR2: %08x\n", v); + icr = apic_icr_read(); + printk(KERN_DEBUG "... APIC ICR: %08x\n", icr); + printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32); v = apic_read(APIC_LVTT); printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index e0f571d58c1..b80105a0f47 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -360,9 +360,11 @@ struct pv_cpu_ops pv_cpu_ops = { struct pv_apic_ops pv_apic_ops = { #ifdef CONFIG_X86_LOCAL_APIC - .apic_write = native_apic_write, - .apic_write_atomic = native_apic_write_atomic, - .apic_read = native_apic_read, +#ifnded CONFIG_X86_64 + .apic_write = native_apic_mem_write, + .apic_write_atomic = native_apic_mem_write_atomic, + .apic_read = native_apic_mem_read, +#endif .setup_boot_clock = setup_boot_APIC_clock, .setup_secondary_clock = setup_secondary_APIC_clock, .startup_ipi_hook = paravirt_nop, diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f35c2d8016a..c55263b3df0 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -123,7 +123,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); static atomic_t init_deasserted; -static int boot_cpu_logical_apicid; /* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; @@ -165,6 +164,8 @@ static void unmap_cpu_to_node(int cpu) #endif #ifdef CONFIG_X86_32 +static int boot_cpu_logical_apicid; + u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; @@ -546,8 +547,7 @@ static inline void __inquire_remote_apic(int apicid) printk(KERN_CONT "a previous APIC delivery may have failed\n"); - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]); + apic_icr_write(APIC_DM_REMRD | regs[i], apicid); timeout = 0; do { @@ -579,11 +579,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) int maxlvt; /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid)); - /* Boot on the stack */ /* Kick the second */ - apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL); + apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid); Dprintk("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); @@ -639,13 +637,11 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) /* * Turn INIT on target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); - /* * Send IPI */ - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT - | APIC_DM_INIT); + apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, + phys_apicid); Dprintk("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); @@ -655,10 +651,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) Dprintk("Deasserting INIT.\n"); /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); - /* Send IPI */ - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); Dprintk("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); @@ -703,12 +697,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) */ /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); - /* Boot on the stack */ /* Kick the second */ - apic_write_around(APIC_ICR, APIC_DM_STARTUP - | (start_eip >> 12)); + apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12), + phys_apicid); /* * Give the other CPU some time to accept the IPI. @@ -1147,7 +1139,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) * Setup boot CPU information */ smp_store_cpu_info(0); /* Final full version of the data */ +#ifdef CONFIG_X86_32 boot_cpu_logical_apicid = logical_smp_processor_id(); +#endif current_thread_info()->cpu = 0; /* needed? */ set_cpu_sibling_map(0); -- cgit v1.2.3 From 32e1d0a0651004f5fe47f85a2a5c725ad579a90c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:50 -0700 Subject: x64, x2apic/intr-remap: cpuid bits for x2apic feature cpuid feature for x2apic. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/feature_names.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index e43ad4ad4cb..0bf4d37a048 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c @@ -45,7 +45,7 @@ const char * const x86_cap_flags[NCAPINTS*32] = { /* Intel-defined (#2) */ "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, - NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt", + NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", NULL, "popcnt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ -- cgit v1.2.3 From 13c88fb58d0112d47f7839f24a755715c6218822 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:52 -0700 Subject: x64, x2apic/intr-remap: x2apic ops for x2apic mode support x2apic ops for x2apic mode support. This uses MSR interface and differs slightly from the xapic register layout. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 9bb040689b3..a969ef78e12 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -171,6 +171,41 @@ struct apic_ops __read_mostly *apic_ops = &xapic_ops; EXPORT_SYMBOL_GPL(apic_ops); +static void x2apic_wait_icr_idle(void) +{ + /* no need to wait for icr idle in x2apic */ + return; +} + +static u32 safe_x2apic_wait_icr_idle(void) +{ + /* no need to wait for icr idle in x2apic */ + return 0; +} + +void x2apic_icr_write(u32 low, u32 id) +{ + wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low); +} + +u64 x2apic_icr_read(void) +{ + unsigned long val; + + rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val); + return val; +} + +static struct apic_ops x2apic_ops = { + .read = native_apic_msr_read, + .write = native_apic_msr_write, + .write_atomic = native_apic_msr_write, + .icr_read = x2apic_icr_read, + .icr_write = x2apic_icr_write, + .wait_icr_idle = x2apic_wait_icr_idle, + .safe_wait_icr_idle = safe_x2apic_wait_icr_idle, +}; + /** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */ -- cgit v1.2.3 From cff73a6ffaed726780b001937d2a42efde553922 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:53 -0700 Subject: x64, x2apic/intr-remap: introcude self IPI to genapic routines Introduce self IPI op for genapic. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_64.c | 2 +- arch/x86/kernel/genapic_flat_64.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 7414871751a..6657de609dc 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -61,7 +61,7 @@ void __init setup_apic_routing(void) /* Same for both flat and physical. */ -void send_IPI_self(int vector) +void apic_send_IPI_self(int vector) { __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); } diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 400ed8df8b4..73558682213 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -131,6 +131,7 @@ struct genapic apic_flat = { .send_IPI_all = flat_send_IPI_all, .send_IPI_allbutself = flat_send_IPI_allbutself, .send_IPI_mask = flat_send_IPI_mask, + .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, .read_apic_id = read_xapic_id, @@ -196,6 +197,7 @@ struct genapic apic_physflat = { .send_IPI_all = physflat_send_IPI_all, .send_IPI_allbutself = physflat_send_IPI_allbutself, .send_IPI_mask = physflat_send_IPI_mask, + .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, .read_apic_id = read_xapic_id, -- cgit v1.2.3 From 12a67cf6851871ca8df42025c94f140c303d0f7f Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:54 -0700 Subject: x64, x2apic/intr-remap: x2apic cluster mode support x2apic cluster mode support. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/genapic_64.c | 2 + arch/x86/kernel/genx2apic_cluster.c | 135 ++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 arch/x86/kernel/genx2apic_cluster.c (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 55ff016e9f6..bde3e9b6fec 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -95,6 +95,7 @@ obj-$(CONFIG_OLPC) += olpc.o # 64 bit specific files ifeq ($(CONFIG_X86_64),y) obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o + obj-y += genx2apic_cluster.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o obj-$(CONFIG_AUDIT) += audit_64.o diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 6657de609dc..1029e178cdf 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -38,6 +38,8 @@ void __init setup_apic_routing(void) { if (uv_system_type == UV_NON_UNIQUE_APIC) genapic = &apic_x2apic_uv_x; + else if (cpu_has_x2apic && intr_remapping_enabled) + genapic = &apic_x2apic_cluster; else #ifdef CONFIG_ACPI /* diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c new file mode 100644 index 00000000000..ed0fdede800 --- /dev/null +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); + +/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ + +static cpumask_t x2apic_target_cpus(void) +{ + return cpumask_of_cpu(0); +} + +/* + * for now each logical cpu is in its own vector allocation domain. + */ +static cpumask_t x2apic_vector_allocation_domain(int cpu) +{ + cpumask_t domain = CPU_MASK_NONE; + cpu_set(cpu, domain); + return domain; +} + +static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, + unsigned int dest) +{ + unsigned long cfg; + + cfg = __prepare_ICR(0, vector, dest); + + /* + * send the IPI. + */ + x2apic_icr_write(cfg, apicid); +} + +/* + * for now, we send the IPI's one by one in the cpumask. + * TBD: Based on the cpu mask, we can send the IPI's to the cluster group + * at once. We have 16 cpu's in a cluster. This will minimize IPI register + * writes. + */ +static void x2apic_send_IPI_mask(cpumask_t mask, int vector) +{ + unsigned long flags; + unsigned long query_cpu; + + local_irq_save(flags); + for_each_cpu_mask(query_cpu, mask) { + __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_logical_apicid, query_cpu), + vector, APIC_DEST_LOGICAL); + } + local_irq_restore(flags); +} + +static void x2apic_send_IPI_allbutself(int vector) +{ + cpumask_t mask = cpu_online_map; + + cpu_clear(smp_processor_id(), mask); + + if (!cpus_empty(mask)) + x2apic_send_IPI_mask(mask, vector); +} + +static void x2apic_send_IPI_all(int vector) +{ + x2apic_send_IPI_mask(cpu_online_map, vector); +} + +static int x2apic_apic_id_registered(void) +{ + return 1; +} + +static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) +{ + int cpu; + + /* + * We're using fixed IRQ delivery, can only return one phys APIC ID. + * May as well be the first. + */ + cpu = first_cpu(cpumask); + if ((unsigned)cpu < NR_CPUS) + return per_cpu(x86_cpu_to_logical_apicid, cpu); + else + return BAD_APICID; +} + +static unsigned int x2apic_read_id(void) +{ + return apic_read(APIC_ID); +} + +static unsigned int phys_pkg_id(int index_msb) +{ + return x2apic_read_id() >> index_msb; +} + +static void x2apic_send_IPI_self(int vector) +{ + apic_write(APIC_SELF_IPI, vector); +} + +static void init_x2apic_ldr(void) +{ + int cpu = smp_processor_id(); + + per_cpu(x86_cpu_to_logical_apicid, cpu) = apic_read(APIC_LDR); + return; +} + +struct genapic apic_x2apic_cluster = { + .name = "cluster x2apic", + .int_delivery_mode = dest_LowestPrio, + .int_dest_mode = (APIC_DEST_LOGICAL != 0), + .target_cpus = x2apic_target_cpus, + .vector_allocation_domain = x2apic_vector_allocation_domain, + .apic_id_registered = x2apic_apic_id_registered, + .init_apic_ldr = init_x2apic_ldr, + .send_IPI_all = x2apic_send_IPI_all, + .send_IPI_allbutself = x2apic_send_IPI_allbutself, + .send_IPI_mask = x2apic_send_IPI_mask, + .send_IPI_self = x2apic_send_IPI_self, + .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, + .phys_pkg_id = phys_pkg_id, + .read_apic_id = x2apic_read_id, +}; -- cgit v1.2.3 From 5c520a6724e912a7e6153b7597192edad6752750 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:55 -0700 Subject: x64, x2apic/intr-remap: setup init_apic_ldr for UV Signed-off-by: Suresh Siddha Signed-off-by: Jack Steiner Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_uv_x.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 1ef99be1848..dcd4fb219da 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -120,6 +120,10 @@ static int uv_apic_id_registered(void) return 1; } +static inline void uv_init_apic_ldr(void) +{ +} + static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask) { int cpu; @@ -164,6 +168,7 @@ struct genapic apic_x2apic_uv_x = { .target_cpus = uv_target_cpus, .vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */ .apic_id_registered = uv_apic_id_registered, + .init_apic_ldr = uv_init_apic_ldr, .send_IPI_all = uv_send_IPI_all, .send_IPI_allbutself = uv_send_IPI_allbutself, .send_IPI_mask = uv_send_IPI_mask, -- cgit v1.2.3 From 89027d35aa5b8f45ce0f7fa0911db85b46563da0 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:56 -0700 Subject: x64, x2apic/intr-remap: IO-APIC support for interrupt-remapping IO-APIC support in the presence of interrupt-remapping infrastructure. IO-APIC RTE will be programmed with interrupt-remapping table entry(IRTE) index and the IRTE will contain information about the vector, cpu destination, trigger mode etc, which traditionally was present in the IO-APIC RTE. Introduce a new irq_chip for cleaner irq migration (in the process context as opposed to the current irq migration in the context of an interrupt. interrupt-remapping infrastructure will help us achieve this cleanly). For edge triggered, irq migration is a simple atomic update(of vector and cpu destination) of IRTE and flush the hardware cache. For level triggered, we need to modify the io-apic RTE aswell with the update vector information, along with modifying IRTE with vector and cpu destination. So irq migration for level triggered is little bit more complex compared to edge triggered migration. But the good news is, we use the same algorithm for level triggered migration as we have today, only difference being, we now initiate the irq migration from process context instead of the interrupt context. In future, when we do a directed EOI (combined with cpu EOI broadcast suppression) to the IO-APIC, level triggered irq migration will also be as simple as edge triggered migration and we can do the irq migration with a simple atomic update to IO-APIC RTE. TBD: some tests/changes needed in the presence of fixup_irqs() for level triggered irq migration. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 1 + arch/x86/kernel/io_apic_64.c | 300 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 279 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index a969ef78e12..d5c06917b5b 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -46,6 +46,7 @@ static int disable_apic_timer __cpuinitdata; static int apic_calibrate_pmtmr __initdata; int disable_apic; +int x2apic; /* Local APIC timer works in C2 */ int local_apic_timer_c2_ok; diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index b62d42ef928..9bd02ef049a 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -37,6 +37,7 @@ #include #endif #include +#include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include @@ -312,7 +314,12 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) pin = entry->pin; if (pin == -1) break; - io_apic_write(apic, 0x11 + pin*2, dest); + /* + * With interrupt-remapping, destination information comes + * from interrupt-remapping table entry. + */ + if (!irq_remapped(irq)) + io_apic_write(apic, 0x11 + pin*2, dest); reg = io_apic_read(apic, 0x10 + pin*2); reg &= ~IO_APIC_REDIR_VECTOR_MASK; reg |= vector; @@ -906,18 +913,98 @@ void setup_vector_irq(int cpu) static struct irq_chip ioapic_chip; +#ifdef CONFIG_INTR_REMAP +static struct irq_chip ir_ioapic_chip; +#endif static void ioapic_register_intr(int irq, unsigned long trigger) { - if (trigger) { + if (trigger) irq_desc[irq].status |= IRQ_LEVEL; - set_irq_chip_and_handler_name(irq, &ioapic_chip, - handle_fasteoi_irq, "fasteoi"); - } else { + else irq_desc[irq].status &= ~IRQ_LEVEL; + +#ifdef CONFIG_INTR_REMAP + if (irq_remapped(irq)) { + irq_desc[irq].status |= IRQ_MOVE_PCNTXT; + if (trigger) + set_irq_chip_and_handler_name(irq, &ir_ioapic_chip, + handle_fasteoi_irq, + "fasteoi"); + else + set_irq_chip_and_handler_name(irq, &ir_ioapic_chip, + handle_edge_irq, "edge"); + return; + } +#endif + if (trigger) + set_irq_chip_and_handler_name(irq, &ioapic_chip, + handle_fasteoi_irq, + "fasteoi"); + else set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_edge_irq, "edge"); +} + +static int setup_ioapic_entry(int apic, int irq, + struct IO_APIC_route_entry *entry, + unsigned int destination, int trigger, + int polarity, int vector) +{ + /* + * add it to the IO-APIC irq-routing table: + */ + memset(entry,0,sizeof(*entry)); + +#ifdef CONFIG_INTR_REMAP + if (intr_remapping_enabled) { + struct intel_iommu *iommu = map_ioapic_to_ir(apic); + struct irte irte; + struct IR_IO_APIC_route_entry *ir_entry = + (struct IR_IO_APIC_route_entry *) entry; + int index; + + if (!iommu) + panic("No mapping iommu for ioapic %d\n", apic); + + index = alloc_irte(iommu, irq, 1); + if (index < 0) + panic("Failed to allocate IRTE for ioapic %d\n", apic); + + memset(&irte, 0, sizeof(irte)); + + irte.present = 1; + irte.dst_mode = INT_DEST_MODE; + irte.trigger_mode = trigger; + irte.dlvry_mode = INT_DELIVERY_MODE; + irte.vector = vector; + irte.dest_id = IRTE_DEST(destination); + + modify_irte(irq, &irte); + + ir_entry->index2 = (index >> 15) & 0x1; + ir_entry->zero = 0; + ir_entry->format = 1; + ir_entry->index = (index & 0x7fff); + } else +#endif + { + entry->delivery_mode = INT_DELIVERY_MODE; + entry->dest_mode = INT_DEST_MODE; + entry->dest = destination; } + + entry->mask = 0; /* enable IRQ */ + entry->trigger = trigger; + entry->polarity = polarity; + entry->vector = vector; + + /* Mask level triggered irqs. + * Use IRQ_DELAYED_DISABLE for edge triggered irqs. + */ + if (trigger) + entry->mask = 1; + return 0; } static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, @@ -942,24 +1029,15 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector, irq, trigger, polarity); - /* - * add it to the IO-APIC irq-routing table: - */ - memset(&entry,0,sizeof(entry)); - - entry.delivery_mode = INT_DELIVERY_MODE; - entry.dest_mode = INT_DEST_MODE; - entry.dest = cpu_mask_to_apicid(mask); - entry.mask = 0; /* enable IRQ */ - entry.trigger = trigger; - entry.polarity = polarity; - entry.vector = cfg->vector; - /* Mask level triggered irqs. - * Use IRQ_DELAYED_DISABLE for edge triggered irqs. - */ - if (trigger) - entry.mask = 1; + if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry, + cpu_mask_to_apicid(mask), trigger, polarity, + cfg->vector)) { + printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", + mp_ioapics[apic].mp_apicid, pin); + __clear_irq_vector(irq); + return; + } ioapic_register_intr(irq, trigger); if (irq < 16) @@ -1011,6 +1089,9 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, { struct IO_APIC_route_entry entry; + if (intr_remapping_enabled) + return; + memset(&entry, 0, sizeof(entry)); /* @@ -1466,6 +1547,147 @@ static int ioapic_retrigger_irq(unsigned int irq) */ #ifdef CONFIG_SMP + +#ifdef CONFIG_INTR_REMAP +static void ir_irq_migration(struct work_struct *work); + +static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration); + +/* + * Migrate the IO-APIC irq in the presence of intr-remapping. + * + * For edge triggered, irq migration is a simple atomic update(of vector + * and cpu destination) of IRTE and flush the hardware cache. + * + * For level triggered, we need to modify the io-apic RTE aswell with the update + * vector information, along with modifying IRTE with vector and destination. + * So irq migration for level triggered is little bit more complex compared to + * edge triggered migration. But the good news is, we use the same algorithm + * for level triggered migration as we have today, only difference being, + * we now initiate the irq migration from process context instead of the + * interrupt context. + * + * In future, when we do a directed EOI (combined with cpu EOI broadcast + * suppression) to the IO-APIC, level triggered irq migration will also be + * as simple as edge triggered migration and we can do the irq migration + * with a simple atomic update to IO-APIC RTE. + */ +static void migrate_ioapic_irq(int irq, cpumask_t mask) +{ + struct irq_cfg *cfg = irq_cfg + irq; + struct irq_desc *desc = irq_desc + irq; + cpumask_t tmp, cleanup_mask; + struct irte irte; + int modify_ioapic_rte = desc->status & IRQ_LEVEL; + unsigned int dest; + unsigned long flags; + + cpus_and(tmp, mask, cpu_online_map); + if (cpus_empty(tmp)) + return; + + if (get_irte(irq, &irte)) + return; + + if (assign_irq_vector(irq, mask)) + return; + + cpus_and(tmp, cfg->domain, mask); + dest = cpu_mask_to_apicid(tmp); + + if (modify_ioapic_rte) { + spin_lock_irqsave(&ioapic_lock, flags); + __target_IO_APIC_irq(irq, dest, cfg->vector); + spin_unlock_irqrestore(&ioapic_lock, flags); + } + + irte.vector = cfg->vector; + irte.dest_id = IRTE_DEST(dest); + + /* + * Modified the IRTE and flushes the Interrupt entry cache. + */ + modify_irte(irq, &irte); + + if (cfg->move_in_progress) { + cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map); + cfg->move_cleanup_count = cpus_weight(cleanup_mask); + send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); + cfg->move_in_progress = 0; + } + + irq_desc[irq].affinity = mask; +} + +static int migrate_irq_remapped_level(int irq) +{ + int ret = -1; + + mask_IO_APIC_irq(irq); + + if (io_apic_level_ack_pending(irq)) { + /* + * Interrupt in progress. Migrating irq now will change the + * vector information in the IO-APIC RTE and that will confuse + * the EOI broadcast performed by cpu. + * So, delay the irq migration to the next instance. + */ + schedule_delayed_work(&ir_migration_work, 1); + goto unmask; + } + + /* everthing is clear. we have right of way */ + migrate_ioapic_irq(irq, irq_desc[irq].pending_mask); + + ret = 0; + irq_desc[irq].status &= ~IRQ_MOVE_PENDING; + cpus_clear(irq_desc[irq].pending_mask); + +unmask: + unmask_IO_APIC_irq(irq); + return ret; +} + +static void ir_irq_migration(struct work_struct *work) +{ + int irq; + + for (irq = 0; irq < NR_IRQS; irq++) { + struct irq_desc *desc = irq_desc + irq; + if (desc->status & IRQ_MOVE_PENDING) { + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + if (!desc->chip->set_affinity || + !(desc->status & IRQ_MOVE_PENDING)) { + desc->status &= ~IRQ_MOVE_PENDING; + spin_unlock_irqrestore(&desc->lock, flags); + continue; + } + + desc->chip->set_affinity(irq, + irq_desc[irq].pending_mask); + spin_unlock_irqrestore(&desc->lock, flags); + } + } +} + +/* + * Migrates the IRQ destination in the process context. + */ +static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) +{ + if (irq_desc[irq].status & IRQ_LEVEL) { + irq_desc[irq].status |= IRQ_MOVE_PENDING; + irq_desc[irq].pending_mask = mask; + migrate_irq_remapped_level(irq); + return; + } + + migrate_ioapic_irq(irq, mask); +} +#endif + asmlinkage void smp_irq_move_cleanup_interrupt(void) { unsigned vector, me; @@ -1522,6 +1744,17 @@ static void irq_complete_move(unsigned int irq) #else static inline void irq_complete_move(unsigned int irq) {} #endif +#ifdef CONFIG_INTR_REMAP +static void ack_x2apic_level(unsigned int irq) +{ + ack_x2APIC_irq(); +} + +static void ack_x2apic_edge(unsigned int irq) +{ + ack_x2APIC_irq(); +} +#endif static void ack_apic_edge(unsigned int irq) { @@ -1596,6 +1829,21 @@ static struct irq_chip ioapic_chip __read_mostly = { .retrigger = ioapic_retrigger_irq, }; +#ifdef CONFIG_INTR_REMAP +static struct irq_chip ir_ioapic_chip __read_mostly = { + .name = "IR-IO-APIC", + .startup = startup_ioapic_irq, + .mask = mask_IO_APIC_irq, + .unmask = unmask_IO_APIC_irq, + .ack = ack_x2apic_edge, + .eoi = ack_x2apic_level, +#ifdef CONFIG_SMP + .set_affinity = set_ir_ioapic_affinity_irq, +#endif + .retrigger = ioapic_retrigger_irq, +}; +#endif + static inline void init_IO_APIC_traps(void) { int irq; @@ -1783,6 +2031,8 @@ static inline void __init check_timer(void) * 8259A. */ if (pin1 == -1) { + if (intr_remapping_enabled) + panic("BIOS bug: timer not connected to IO-APIC"); pin1 = pin2; apic1 = apic2; no_pin1 = 1; @@ -1809,6 +2059,8 @@ static inline void __init check_timer(void) clear_IO_APIC_pin(0, pin1); goto out; } + if (intr_remapping_enabled) + panic("timer doesn't work through Interrupt-remapped IO-APIC"); clear_IO_APIC_pin(apic1, pin1); if (!no_pin1) apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: " @@ -2401,6 +2653,10 @@ void __init setup_ioapic_dest(void) setup_IO_APIC_irq(ioapic, pin, irq, irq_trigger(irq_entry), irq_polarity(irq_entry)); +#ifdef CONFIG_INTR_REMAP + else if (intr_remapping_enabled) + set_ir_ioapic_affinity_irq(irq, TARGET_CPUS); +#endif else set_ioapic_affinity_irq(irq, TARGET_CPUS); } -- cgit v1.2.3 From 75c46fa61bc5b4ccd20a168ff325c58771248fcd Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:57 -0700 Subject: x64, x2apic/intr-remap: MSI and MSI-X support for interrupt remapping infrastructure MSI and MSI-X support for interrupt remapping infrastructure. MSI address register will be programmed with interrupt-remapping table entry(IRTE) index and the IRTE will contain information about the vector, cpu destination, etc. For MSI-X, all the IRTE's will be consecutively allocated in the table, and the address registers will contain the starting index to the block and the data register will contain the subindex with in that block. This also introduces a new irq_chip for cleaner irq migration (in the process context as opposed to the current irq migration in the context of an interrupt. interrupt-remapping infrastructure will help us achieve this). As MSI is edge triggered, irq migration is a simple atomic update(of vector and cpu destination) of IRTE and flushing the hardware cache. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_64.c | 230 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 222 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 9bd02ef049a..877aa2e9d7e 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -2297,6 +2297,9 @@ void destroy_irq(unsigned int irq) dynamic_irq_cleanup(irq); +#ifdef CONFIG_INTR_REMAP + free_irte(irq); +#endif spin_lock_irqsave(&vector_lock, flags); __clear_irq_vector(irq); spin_unlock_irqrestore(&vector_lock, flags); @@ -2315,10 +2318,41 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms tmp = TARGET_CPUS; err = assign_irq_vector(irq, tmp); - if (!err) { - cpus_and(tmp, cfg->domain, tmp); - dest = cpu_mask_to_apicid(tmp); + if (err) + return err; + + cpus_and(tmp, cfg->domain, tmp); + dest = cpu_mask_to_apicid(tmp); + +#ifdef CONFIG_INTR_REMAP + if (irq_remapped(irq)) { + struct irte irte; + int ir_index; + u16 sub_handle; + + ir_index = map_irq_to_irte_handle(irq, &sub_handle); + BUG_ON(ir_index == -1); + + memset (&irte, 0, sizeof(irte)); + + irte.present = 1; + irte.dst_mode = INT_DEST_MODE; + irte.trigger_mode = 0; /* edge */ + irte.dlvry_mode = INT_DELIVERY_MODE; + irte.vector = cfg->vector; + irte.dest_id = IRTE_DEST(dest); + + modify_irte(irq, &irte); + msg->address_hi = MSI_ADDR_BASE_HI; + msg->data = sub_handle; + msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT | + MSI_ADDR_IR_SHV | + MSI_ADDR_IR_INDEX1(ir_index) | + MSI_ADDR_IR_INDEX2(ir_index); + } else +#endif + { msg->address_hi = MSI_ADDR_BASE_HI; msg->address_lo = MSI_ADDR_BASE_LO | @@ -2369,6 +2403,55 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) write_msi_msg(irq, &msg); irq_desc[irq].affinity = mask; } + +#ifdef CONFIG_INTR_REMAP +/* + * Migrate the MSI irq to another cpumask. This migration is + * done in the process context using interrupt-remapping hardware. + */ +static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask) +{ + struct irq_cfg *cfg = irq_cfg + irq; + unsigned int dest; + cpumask_t tmp, cleanup_mask; + struct irte irte; + + cpus_and(tmp, mask, cpu_online_map); + if (cpus_empty(tmp)) + return; + + if (get_irte(irq, &irte)) + return; + + if (assign_irq_vector(irq, mask)) + return; + + cpus_and(tmp, cfg->domain, mask); + dest = cpu_mask_to_apicid(tmp); + + irte.vector = cfg->vector; + irte.dest_id = IRTE_DEST(dest); + + /* + * atomically update the IRTE with the new destination and vector. + */ + modify_irte(irq, &irte); + + /* + * After this point, all the interrupts will start arriving + * at the new destination. So, time to cleanup the previous + * vector allocation. + */ + if (cfg->move_in_progress) { + cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map); + cfg->move_cleanup_count = cpus_weight(cleanup_mask); + send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); + cfg->move_in_progress = 0; + } + + irq_desc[irq].affinity = mask; +} +#endif #endif /* CONFIG_SMP */ /* @@ -2386,26 +2469,157 @@ static struct irq_chip msi_chip = { .retrigger = ioapic_retrigger_irq, }; -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +#ifdef CONFIG_INTR_REMAP +static struct irq_chip msi_ir_chip = { + .name = "IR-PCI-MSI", + .unmask = unmask_msi_irq, + .mask = mask_msi_irq, + .ack = ack_x2apic_edge, +#ifdef CONFIG_SMP + .set_affinity = ir_set_msi_irq_affinity, +#endif + .retrigger = ioapic_retrigger_irq, +}; + +/* + * Map the PCI dev to the corresponding remapping hardware unit + * and allocate 'nvec' consecutive interrupt-remapping table entries + * in it. + */ +static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec) +{ + struct intel_iommu *iommu; + int index; + + iommu = map_dev_to_ir(dev); + if (!iommu) { + printk(KERN_ERR + "Unable to map PCI %s to iommu\n", pci_name(dev)); + return -ENOENT; + } + + index = alloc_irte(iommu, irq, nvec); + if (index < 0) { + printk(KERN_ERR + "Unable to allocate %d IRTE for PCI %s\n", nvec, + pci_name(dev)); + return -ENOSPC; + } + return index; +} +#endif + +static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) { + int ret; struct msi_msg msg; + + ret = msi_compose_msg(dev, irq, &msg); + if (ret < 0) + return ret; + + set_irq_msi(irq, desc); + write_msi_msg(irq, &msg); + +#ifdef CONFIG_INTR_REMAP + if (irq_remapped(irq)) { + struct irq_desc *desc = irq_desc + irq; + /* + * irq migration in process context + */ + desc->status |= IRQ_MOVE_PCNTXT; + set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge"); + } else +#endif + set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); + + return 0; +} + +int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +{ int irq, ret; + irq = create_irq(); if (irq < 0) return irq; - ret = msi_compose_msg(dev, irq, &msg); +#ifdef CONFIG_INTR_REMAP + if (!intr_remapping_enabled) + goto no_ir; + + ret = msi_alloc_irte(dev, irq, 1); + if (ret < 0) + goto error; +no_ir: +#endif + ret = setup_msi_irq(dev, desc, irq); if (ret < 0) { destroy_irq(irq); return ret; } + return 0; - set_irq_msi(irq, desc); - write_msi_msg(irq, &msg); +#ifdef CONFIG_INTR_REMAP +error: + destroy_irq(irq); + return ret; +#endif +} - set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +{ + int irq, ret, sub_handle; + struct msi_desc *desc; +#ifdef CONFIG_INTR_REMAP + struct intel_iommu *iommu = 0; + int index = 0; +#endif + sub_handle = 0; + list_for_each_entry(desc, &dev->msi_list, list) { + irq = create_irq(); + if (irq < 0) + return irq; +#ifdef CONFIG_INTR_REMAP + if (!intr_remapping_enabled) + goto no_ir; + + if (!sub_handle) { + /* + * allocate the consecutive block of IRTE's + * for 'nvec' + */ + index = msi_alloc_irte(dev, irq, nvec); + if (index < 0) { + ret = index; + goto error; + } + } else { + iommu = map_dev_to_ir(dev); + if (!iommu) { + ret = -ENOENT; + goto error; + } + /* + * setup the mapping between the irq and the IRTE + * base index, the sub_handle pointing to the + * appropriate interrupt remap table entry. + */ + set_irte_irq(irq, iommu, index, sub_handle); + } +no_ir: +#endif + ret = setup_msi_irq(dev, desc, irq); + if (ret < 0) + goto error; + sub_handle++; + } return 0; + +error: + destroy_irq(irq); + return ret; } void arch_teardown_msi_irq(unsigned int irq) -- cgit v1.2.3 From 6e1cb38a2aef7680975e71f23de187859ee8b158 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:58 -0700 Subject: x64, x2apic/intr-remap: add x2apic support, including enabling interrupt-remapping x2apic support. Interrupt-remapping must be enabled before enabling x2apic, this is needed to ensure that IO interrupts continue to work properly after the cpu mode is changed to x2apic(which uses 32bit extended physical/cluster apic id). On systems where apicid's are > 255, BIOS can handover the control to OS in x2apic mode. Or if the OS handover was in legacy xapic mode, check if it is capable of x2apic mode. And if we succeed in enabling Interrupt-remapping, then we can enable x2apic mode in the CPU. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 2 + arch/x86/kernel/apic_64.c | 154 ++++++++++++++++++++++++++++++++++++++-- arch/x86/kernel/cpu/common_64.c | 2 + arch/x86/kernel/genapic_64.c | 1 + arch/x86/kernel/mpparse.c | 2 + arch/x86/kernel/setup.c | 2 + arch/x86/kernel/smpboot.c | 5 ++ 7 files changed, 164 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 785700a08e9..8705262ddcd 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1337,7 +1337,9 @@ static void __init acpi_process_madt(void) acpi_ioapic = 1; smp_found_config = 1; +#ifdef CONFIG_X86_32 setup_apic_routing(); +#endif } } if (error == -EINVAL) { diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index d5c06917b5b..dd0501039f0 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -46,8 +48,12 @@ static int disable_apic_timer __cpuinitdata; static int apic_calibrate_pmtmr __initdata; int disable_apic; +int disable_x2apic; int x2apic; +/* x2apic enabled before OS handover */ +int x2apic_preenabled; + /* Local APIC timer works in C2 */ int local_apic_timer_c2_ok; EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); @@ -896,6 +902,125 @@ void __cpuinit end_local_APIC_setup(void) apic_pm_activate(); } +void check_x2apic(void) +{ + int msr, msr2; + + rdmsr(MSR_IA32_APICBASE, msr, msr2); + + if (msr & X2APIC_ENABLE) { + printk("x2apic enabled by BIOS, switching to x2apic ops\n"); + x2apic_preenabled = x2apic = 1; + apic_ops = &x2apic_ops; + } +} + +void enable_x2apic(void) +{ + int msr, msr2; + + rdmsr(MSR_IA32_APICBASE, msr, msr2); + if (!(msr & X2APIC_ENABLE)) { + printk("Enabling x2apic\n"); + wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); + } +} + +void enable_IR_x2apic(void) +{ +#ifdef CONFIG_INTR_REMAP + int ret; + unsigned long flags; + + if (!cpu_has_x2apic) + return; + + if (!x2apic_preenabled && disable_x2apic) { + printk(KERN_INFO + "Skipped enabling x2apic and Interrupt-remapping " + "because of nox2apic\n"); + return; + } + + if (x2apic_preenabled && disable_x2apic) + panic("Bios already enabled x2apic, can't enforce nox2apic"); + + if (!x2apic_preenabled && skip_ioapic_setup) { + printk(KERN_INFO + "Skipped enabling x2apic and Interrupt-remapping " + "because of skipping io-apic setup\n"); + return; + } + + ret = dmar_table_init(); + if (ret) { + printk(KERN_INFO + "dmar_table_init() failed with %d:\n", ret); + + if (x2apic_preenabled) + panic("x2apic enabled by bios. But IR enabling failed"); + else + printk(KERN_INFO + "Not enabling x2apic,Intr-remapping\n"); + return; + } + + local_irq_save(flags); + mask_8259A(); + save_mask_IO_APIC_setup(); + + ret = enable_intr_remapping(1); + + if (ret && x2apic_preenabled) { + local_irq_restore(flags); + panic("x2apic enabled by bios. But IR enabling failed"); + } + + if (ret) + goto end; + + if (!x2apic) { + x2apic = 1; + apic_ops = &x2apic_ops; + enable_x2apic(); + } +end: + if (ret) + /* + * IR enabling failed + */ + restore_IO_APIC_setup(); + else + reinit_intr_remapped_IO_APIC(x2apic_preenabled); + + unmask_8259A(); + local_irq_restore(flags); + + if (!ret) { + if (!x2apic_preenabled) + printk(KERN_INFO + "Enabled x2apic and interrupt-remapping\n"); + else + printk(KERN_INFO + "Enabled Interrupt-remapping\n"); + } else + printk(KERN_ERR + "Failed to enable Interrupt-remapping and x2apic\n"); +#else + if (!cpu_has_x2apic) + return; + + if (x2apic_preenabled) + panic("x2apic enabled prior OS handover," + " enable CONFIG_INTR_REMAP"); + + printk(KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping " + " and x2apic\n"); +#endif + + return; +} + /* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. @@ -943,6 +1068,11 @@ void __init early_init_lapic_mapping(void) */ void __init init_apic_mappings(void) { + if (x2apic) { + boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + return; + } + /* * If no local APIC can be found then set up a fake all * zeroes page to simulate the local APIC and another @@ -981,6 +1111,9 @@ int __init APIC_init_uniprocessor(void) return -1; } + enable_IR_x2apic(); + setup_apic_routing(); + verify_local_APIC(); connect_bsp_APIC(); @@ -1238,10 +1371,14 @@ static int lapic_resume(struct sys_device *dev) maxlvt = lapic_get_maxlvt(); local_irq_save(flags); - rdmsr(MSR_IA32_APICBASE, l, h); - l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; - wrmsr(MSR_IA32_APICBASE, l, h); + if (!x2apic) { + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; + wrmsr(MSR_IA32_APICBASE, l, h); + } else + enable_x2apic(); + apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); apic_write(APIC_DFR, apic_pm_state.apic_dfr); @@ -1381,6 +1518,15 @@ __cpuinit int apic_is_clustered_box(void) return (clusters > 2); } +static __init int setup_nox2apic(char *str) +{ + disable_x2apic = 1; + clear_cpu_cap(&boot_cpu_data, X86_FEATURE_X2APIC); + return 0; +} +early_param("nox2apic", setup_nox2apic); + + /* * APIC command line parameters */ diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 36537ab9e56..e7bf3c2dc5f 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -606,6 +606,8 @@ void __cpuinit cpu_init(void) barrier(); check_efer(); + if (cpu != 0 && x2apic) + enable_x2apic(); /* * set up and load the per-CPU TSS diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 1029e178cdf..792e21ba1a8 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 3b25e49380c..70e1f3e287f 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -545,7 +545,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) generic_bigsmp_probe(); #endif +#ifdef CONFIG_X86_32 setup_apic_routing(); +#endif if (!num_processors) printk(KERN_ERR "MPTABLE: no processors registered!\n"); return num_processors; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 987b6fde3a9..2e78a143dec 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -730,6 +730,8 @@ void __init setup_arch(char **cmdline_p) num_physpages = max_pfn; check_efer(); + if (cpu_has_x2apic) + check_x2apic(); /* How many end-of-memory variables you have, grandma! */ /* need this before calling reserve_initrd */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index c55263b3df0..0c43e1f2e7d 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1145,6 +1145,11 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) current_thread_info()->cpu = 0; /* needed? */ set_cpu_sibling_map(0); +#ifdef CONFIG_X86_64 + enable_IR_x2apic(); + setup_apic_routing(); +#endif + if (smp_sanity_check(max_cpus) < 0) { printk(KERN_INFO "SMP disabled\n"); disable_smp(); -- cgit v1.2.3 From 2d9579a124d746a3e0e0ba45e57d80800ee80807 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:59 -0700 Subject: x64, x2apic/intr-remap: support for x2apic physical mode support x2apic Physical mode support. By default we will use x2apic cluster mode. x2apic physical mode can be selected using "x2apic_phys" boot parameter. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/genapic_64.c | 18 +++++- arch/x86/kernel/genx2apic_phys.c | 122 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 arch/x86/kernel/genx2apic_phys.c (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index bde3e9b6fec..81280e93e79 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_OLPC) += olpc.o ifeq ($(CONFIG_X86_64),y) obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o obj-y += genx2apic_cluster.o + obj-y += genx2apic_phys.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o obj-$(CONFIG_AUDIT) += audit_64.o diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 792e21ba1a8..3940d8161f8 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -30,6 +30,15 @@ DEFINE_PER_CPU(int, x2apic_extra_bits); struct genapic __read_mostly *genapic = &apic_flat; +static int x2apic_phys = 0; + +static int set_x2apic_phys_mode(char *arg) +{ + x2apic_phys = 1; + return 0; +} +early_param("x2apic_phys", set_x2apic_phys_mode); + static enum uv_system_type uv_system_type; /* @@ -39,9 +48,12 @@ void __init setup_apic_routing(void) { if (uv_system_type == UV_NON_UNIQUE_APIC) genapic = &apic_x2apic_uv_x; - else if (cpu_has_x2apic && intr_remapping_enabled) - genapic = &apic_x2apic_cluster; - else + else if (cpu_has_x2apic && intr_remapping_enabled) { + if (x2apic_phys) + genapic = &apic_x2apic_phys; + else + genapic = &apic_x2apic_cluster; + } else #ifdef CONFIG_ACPI /* * Quirk: some x86_64 machines can only use physical APIC mode diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c new file mode 100644 index 00000000000..3c70b9d692b --- /dev/null +++ b/arch/x86/kernel/genx2apic_phys.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ + +static cpumask_t x2apic_target_cpus(void) +{ + return cpumask_of_cpu(0); +} + +static cpumask_t x2apic_vector_allocation_domain(int cpu) +{ + cpumask_t domain = CPU_MASK_NONE; + cpu_set(cpu, domain); + return domain; +} + +static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, + unsigned int dest) +{ + unsigned long cfg; + + cfg = __prepare_ICR(0, vector, dest); + + /* + * send the IPI. + */ + x2apic_icr_write(cfg, apicid); +} + +static void x2apic_send_IPI_mask(cpumask_t mask, int vector) +{ + unsigned long flags; + unsigned long query_cpu; + + local_irq_save(flags); + for_each_cpu_mask(query_cpu, mask) { + __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu), + vector, APIC_DEST_PHYSICAL); + } + local_irq_restore(flags); +} + +static void x2apic_send_IPI_allbutself(int vector) +{ + cpumask_t mask = cpu_online_map; + + cpu_clear(smp_processor_id(), mask); + + if (!cpus_empty(mask)) + x2apic_send_IPI_mask(mask, vector); +} + +static void x2apic_send_IPI_all(int vector) +{ + x2apic_send_IPI_mask(cpu_online_map, vector); +} + +static int x2apic_apic_id_registered(void) +{ + return 1; +} + +static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) +{ + int cpu; + + /* + * We're using fixed IRQ delivery, can only return one phys APIC ID. + * May as well be the first. + */ + cpu = first_cpu(cpumask); + if ((unsigned)cpu < NR_CPUS) + return per_cpu(x86_cpu_to_apicid, cpu); + else + return BAD_APICID; +} + +static unsigned int x2apic_read_id(void) +{ + return apic_read(APIC_ID); +} + +static unsigned int phys_pkg_id(int index_msb) +{ + return x2apic_read_id() >> index_msb; +} + +void x2apic_send_IPI_self(int vector) +{ + apic_write(APIC_SELF_IPI, vector); +} + +void init_x2apic_ldr(void) +{ + return; +} + +struct genapic apic_x2apic_phys = { + .name = "physical x2apic", + .int_delivery_mode = dest_Fixed, + .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + .target_cpus = x2apic_target_cpus, + .vector_allocation_domain = x2apic_vector_allocation_domain, + .apic_id_registered = x2apic_apic_id_registered, + .init_apic_ldr = init_x2apic_ldr, + .send_IPI_all = x2apic_send_IPI_all, + .send_IPI_allbutself = x2apic_send_IPI_allbutself, + .send_IPI_mask = x2apic_send_IPI_mask, + .send_IPI_self = x2apic_send_IPI_self, + .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, + .phys_pkg_id = phys_pkg_id, + .read_apic_id = x2apic_read_id, +}; -- cgit v1.2.3 From 9fa8c481b55e80edd8c637573f87853bb6b600f5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:17:00 -0700 Subject: x64, x2apic/intr-remap: introduce CONFIG_INTR_REMAP Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2cfccc987a2..0bf8391a7f2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1651,6 +1651,14 @@ config DMAR_FLOPPY_WA workaround will setup a 1:1 mapping for the first 16M to make floppy (an ISA device) work. +config INTR_REMAP + bool "Support for Interrupt Remapping (EXPERIMENTAL)" + depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL + help + Supports Interrupt remapping for IO-APIC and MSI devices. + To use x2apic mode in the CPU's which support x2APIC enhancements or + to support platforms with CPU's having > 8 bit APIC ID, say Y. + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" -- cgit v1.2.3 From 372e92d8b3e433888bf76c36f1c7e1405eae1584 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 14:56:18 -0700 Subject: x64, x2apic/intr-remap: Interrupt-remapping and x2apic support On Thu, Jul 10, 2008 at 12:53:20PM -0700, Ingo Molnar wrote: > > Btw., i threw it at the -tip test-cluster and got back a quick build > bugreport: > > arch/x86/xen/enlighten.c: In function 'xen_patch': > arch/x86/xen/enlighten.c:1084: warning: label 'patch_site' defined but not used > arch/x86/xen/enlighten.c: At top level: > arch/x86/xen/enlighten.c:1272: error: expected identifier before '(' token > arch/x86/xen/enlighten.c:1273: error: expected '}' before '.' token > arch/x86/kernel/paravirt.c:376:2: error: invalid preprocessing directive > #ifndedarch/x86/kernel/paravirt.c:384:2: error: #endif without #if > > with this config: > > http://redhat.com/~mingo/misc/config-Thu_Jul_10_21_43_28_CEST_2008.bad fix the typo. Signed-off-by: Suresh Siddha Cc: "Siddha Cc: Suresh B" Cc: "akpm@linux-foundation.org" Cc: "arjan@linux.intel.com" Cc: "andi@firstfloor.org" Cc: "ebiederm@xmission.com" Cc: "jbarnes@virtuousgeek.org" Cc: "steiner@sgi.com" Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/paravirt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index b80105a0f47..4f29ff847eb 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -360,7 +360,7 @@ struct pv_cpu_ops pv_cpu_ops = { struct pv_apic_ops pv_apic_ops = { #ifdef CONFIG_X86_LOCAL_APIC -#ifnded CONFIG_X86_64 +#ifndef CONFIG_X86_64 .apic_write = native_apic_mem_write, .apic_write_atomic = native_apic_mem_write_atomic, .apic_read = native_apic_mem_read, -- cgit v1.2.3 From 277d1f5846d84e16760131a93b7a67ebfa8eded4 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 11 Jul 2008 13:11:55 -0700 Subject: x2apic: uninline uv_init_apic_ldr() Andrew says: > There's no point in declaring it inline if it's always called indirectly. And point taken! Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_uv_x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index dcd4fb219da..c915f750241 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -120,7 +120,7 @@ static int uv_apic_id_registered(void) return 1; } -static inline void uv_init_apic_ldr(void) +static void uv_init_apic_ldr(void) { } -- cgit v1.2.3 From ad66dd340f561bdde2285992314d9e4fd9b6191e Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 11 Jul 2008 13:11:56 -0700 Subject: x2apic: xen64 paravirt basic apic ops Define the Xen specific basic apic ops, in additon to paravirt apic ops, with some misc warning fixes. Signed-off-by: Suresh Siddha Cc: Jeremy Fitzhardinge Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/lguest/boot.c | 4 ++-- arch/x86/xen/enlighten.c | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 50dad44fb54..0c45df20e2b 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -783,11 +783,11 @@ static void lguest_wbinvd(void) * code qualifies for Advanced. It will also never interrupt anything. It * does, however, allow us to get through the Linux boot code. */ #ifdef CONFIG_X86_LOCAL_APIC -static void lguest_apic_write(unsigned long reg, u32 v) +static void lguest_apic_write(u32 reg, u32 v) { } -static u32 lguest_apic_read(unsigned long reg) +static u32 lguest_apic_read(u32 reg) { return 0; } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index dcd4e51f2f1..54e25566753 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -548,16 +548,45 @@ static void xen_io_delay(void) } #ifdef CONFIG_X86_LOCAL_APIC -static u32 xen_apic_read(unsigned long reg) +static u32 xen_apic_read(u32 reg) { return 0; } -static void xen_apic_write(unsigned long reg, u32 val) +static void xen_apic_write(u32 reg, u32 val) { /* Warn to see if there's any stray references */ WARN_ON(1); } + +#ifdef CONFIG_X86_64 +static u64 xen_apic_icr_read(void) +{ + return 0; +} + +static void xen_apic_icr_write(u32 low, u32 id) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static void xen_apic_wait_icr_idle(void) +{ + return; +} + +static struct apic_ops xen_basic_apic_ops = { + .read = xen_apic_read, + .write = xen_apic_write, + .write_atomic = xen_apic_write, + .icr_read = xen_apic_icr_read, + .icr_write = xen_apic_icr_write, + .wait_icr_idle = xen_apic_wait_icr_idle, + .safe_wait_icr_idle = xen_apic_wait_icr_idle, +}; +#endif + #endif static void xen_flush_tlb(void) @@ -1130,9 +1159,11 @@ static const struct pv_irq_ops xen_irq_ops __initdata = { static const struct pv_apic_ops xen_apic_ops __initdata = { #ifdef CONFIG_X86_LOCAL_APIC +#ifndef CONFIG_X86_64 .apic_write = xen_apic_write, .apic_write_atomic = xen_apic_write, .apic_read = xen_apic_read, +#endif .setup_boot_clock = paravirt_nop, .setup_secondary_clock = paravirt_nop, .startup_ipi_hook = paravirt_nop, @@ -1291,6 +1322,12 @@ asmlinkage void __init xen_start_kernel(void) pv_irq_ops = xen_irq_ops; pv_apic_ops = xen_apic_ops; pv_mmu_ops = xen_mmu_ops; +#ifdef CONFIG_X86_64 + /* + * for 64bit, set up the basic apic ops aswell. + */ + apic_ops = &xen_basic_apic_ops; +#endif if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; -- cgit v1.2.3 From c535b6a1a685eb23f96e2c221777d6c1e05080d5 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 11 Jul 2008 18:41:54 -0700 Subject: x86: let 32bit use apic_ops too Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 2a83c07bd88..7413354c9ff 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -145,19 +145,13 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } -void apic_icr_write(u32 low, u32 id) -{ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); - apic_write_around(APIC_ICR, low); -} - -void apic_wait_icr_idle(void) +void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) cpu_relax(); } -u32 safe_apic_wait_icr_idle(void) +u32 safe_xapic_wait_icr_idle(void) { u32 send_status; int timeout; @@ -173,6 +167,35 @@ u32 safe_apic_wait_icr_idle(void) return send_status; } +void xapic_icr_write(u32 low, u32 id) +{ + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); + apic_write_around(APIC_ICR, low); +} + +u64 xapic_icr_read(void) +{ + u32 icr1, icr2; + + icr2 = apic_read(APIC_ICR2); + icr1 = apic_read(APIC_ICR); + + return icr1 | ((u64)icr2 << 32); +} + +static struct apic_ops xapic_ops = { + .read = native_apic_mem_read, + .write = native_apic_mem_write, + .write_atomic = native_apic_mem_write_atomic, + .icr_read = xapic_icr_read, + .icr_write = xapic_icr_write, + .wait_icr_idle = xapic_wait_icr_idle, + .safe_wait_icr_idle = safe_xapic_wait_icr_idle, +}; + +struct apic_ops __read_mostly *apic_ops = &xapic_ops; +EXPORT_SYMBOL_GPL(apic_ops); + /** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */ -- cgit v1.2.3 From 4696ca5bfd2697f5686f96d59cf0b6de14869b4e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 11 Jul 2008 18:43:10 -0700 Subject: x86: mach_apicdef.h need to include before smp.h smp.h internal has include, so need to include that at first when genericarch use them need to have different apicdef.h Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/bigsmp.c | 5 ++--- arch/x86/mach-generic/es7000.c | 3 +-- arch/x86/mach-generic/numaq.c | 4 ++-- arch/x86/mach-generic/summit.c | 5 ++--- 4 files changed, 7 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 59d77171455..b31f2800638 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -5,17 +5,16 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include #include #include -#include #include #include -#include #include +#include +#include #include #include diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 4742626f08c..9b30547d746 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -4,16 +4,15 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include #include #include #include -#include #include #include +#include #include #include #include diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 8091e68764c..95c07efff6b 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -4,7 +4,6 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include @@ -12,8 +11,9 @@ #include #include #include -#include #include +#include +#include #include #include #include diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index a97ea0f35b1..752edd96b1b 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -4,17 +4,16 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include #include #include #include -#include #include -#include #include +#include +#include #include #include -- cgit v1.2.3 From 4c9961d56ec20c27ec5d02e49fd7427748312741 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 11 Jul 2008 18:44:16 -0700 Subject: x86: make read_apic_id return final apicid also remove GET_APIC_ID when read_apic_id is used. need to apply after [PATCH] x86: mach_apicdef.h need to include before smp.h Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 2 +- arch/x86/kernel/apic_32.c | 4 ++-- arch/x86/kernel/apic_64.c | 6 +++--- arch/x86/kernel/genapic_flat_64.c | 2 +- arch/x86/kernel/io_apic_32.c | 5 ++--- arch/x86/kernel/io_apic_64.c | 4 ++-- arch/x86/kernel/smpboot.c | 6 +++--- 7 files changed, 14 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8705262ddcd..b314bcd0840 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -761,7 +761,7 @@ static void __init acpi_register_lapic_address(unsigned long address) set_fixmap_nocache(FIX_APIC_BASE, address); if (boot_cpu_physical_apicid == -1U) { - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); #ifdef CONFIG_X86_32 apic_version[boot_cpu_physical_apicid] = GET_APIC_VERSION(apic_read(APIC_LVR)); diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 7413354c9ff..47ff978aecf 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1230,7 +1230,7 @@ void __init init_apic_mappings(void) * default configuration (or the MP table is broken). */ if (boot_cpu_physical_apicid == -1U) - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); } @@ -1270,7 +1270,7 @@ int __init APIC_init_uniprocessor(void) * might be zero if read from MP tables. Get it from LAPIC. */ #ifdef CONFIG_CRASH_DUMP - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); #endif physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index dd0501039f0..c75f58a66d8 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1060,7 +1060,7 @@ void __init early_init_lapic_mapping(void) * Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); } /** @@ -1069,7 +1069,7 @@ void __init early_init_lapic_mapping(void) void __init init_apic_mappings(void) { if (x2apic) { - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); return; } @@ -1092,7 +1092,7 @@ void __init init_apic_mappings(void) * Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); } /* diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 73558682213..7dac2f275fa 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -101,7 +101,7 @@ static unsigned int read_xapic_id(void) { unsigned int id; - id = GET_XAPIC_ID(apic_read(APIC_ID)); + id = GET_APIC_ID(apic_read(APIC_ID)); return id; } diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index c50adb84ea6..382208d11f8 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -1501,7 +1501,7 @@ void /*__init*/ print_local_APIC(void *dummy) smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, - GET_APIC_ID(read_apic_id())); + GET_APIC_ID(v)); v = apic_read(APIC_LVR); printk(KERN_INFO "... APIC VERSION: %08x\n", v); ver = GET_APIC_VERSION(v); @@ -1709,8 +1709,7 @@ void disable_IO_APIC(void) entry.dest_mode = 0; /* Physical */ entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest.physical.physical_dest = - GET_APIC_ID(read_apic_id()); + entry.dest.physical.physical_dest = read_apic_id(); /* * Add it to the IO-APIC irq-routing table: diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 877aa2e9d7e..2db0f98e2af 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -1246,7 +1246,7 @@ void __apicdebuginit print_local_APIC(void * dummy) printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); - printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id())); + printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, read_apic_id()); v = apic_read(APIC_LVR); printk(KERN_INFO "... APIC VERSION: %08x\n", v); ver = GET_APIC_VERSION(v); @@ -1439,7 +1439,7 @@ void disable_IO_APIC(void) entry.dest_mode = 0; /* Physical */ entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest = GET_APIC_ID(read_apic_id()); + entry.dest = read_apic_id(); /* * Add it to the IO-APIC irq-routing table: diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0c43e1f2e7d..6cd002f3e20 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -211,7 +211,7 @@ static void __cpuinit smp_callin(void) /* * (This works even if the APIC is not enabled.) */ - phys_id = GET_APIC_ID(read_apic_id()); + phys_id = read_apic_id(); cpuid = smp_processor_id(); if (cpu_isset(cpuid, cpu_callin_map)) { panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__, @@ -1157,9 +1157,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) } preempt_disable(); - if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) { + if (read_apic_id() != boot_cpu_physical_apicid) { panic("Boot APIC ID in local APIC unexpected (%d vs %d)", - GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid); + read_apic_id(), boot_cpu_physical_apicid); /* Or can we switch back to PIC here? */ } preempt_enable(); -- cgit v1.2.3 From f910a9dc7c865896815e2a95fe33363e9522f277 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 12 Jul 2008 01:01:20 -0700 Subject: x86: make 64bit have get_apic_id generalize the x2apic code some more. let read_apic_id become a macro (later on a function/inline) GET_APIC_ID(apic_read(APIC_ID)) +#define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) instead of this weird construct: -#define read_apic_id (genapic->read_apic_id) Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_flat_64.c | 26 +++++++++++++++++++++++--- arch/x86/kernel/genx2apic_cluster.c | 20 +++++++++++++++++++- arch/x86/kernel/genx2apic_phys.c | 20 +++++++++++++++++++- arch/x86/kernel/genx2apic_uv_x.c | 23 ++++++++++++++++++++--- 4 files changed, 81 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 7dac2f275fa..2c973cbf054 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -97,11 +97,27 @@ static void flat_send_IPI_all(int vector) __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); } +static unsigned int get_apic_id(unsigned long x) +{ + unsigned int id; + + id = (((x)>>24) & 0xFFu); + return id; +} + +static unsigned long set_apic_id(unsigned int id) +{ + unsigned long x; + + x = ((id & 0xFFu)<<24); + return x; +} + static unsigned int read_xapic_id(void) { unsigned int id; - id = GET_APIC_ID(apic_read(APIC_ID)); + id = get_apic_id(apic_read(APIC_ID)); return id; } @@ -134,7 +150,9 @@ struct genapic apic_flat = { .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = read_xapic_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFu<<24), }; /* @@ -200,5 +218,7 @@ struct genapic apic_physflat = { .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = read_xapic_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFu<<24), }; diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index ed0fdede800..40bc0140d89 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -94,6 +94,22 @@ static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } +static unsigned int get_apic_id(unsigned long x) +{ + unsigned int id; + + id = x; + return id; +} + +static unsigned long set_apic_id(unsigned int id) +{ + unsigned long x; + + x = id; + return x; +} + static unsigned int x2apic_read_id(void) { return apic_read(APIC_ID); @@ -131,5 +147,7 @@ struct genapic apic_x2apic_cluster = { .send_IPI_self = x2apic_send_IPI_self, .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = x2apic_read_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFFFFFFFu), }; diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 3c70b9d692b..2f3c6ca19de 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -84,6 +84,22 @@ static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } +static unsigned int get_apic_id(unsigned long x) +{ + unsigned int id; + + id = x; + return id; +} + +static unsigned long set_apic_id(unsigned int id) +{ + unsigned long x; + + x = id; + return x; +} + static unsigned int x2apic_read_id(void) { return apic_read(APIC_ID); @@ -118,5 +134,7 @@ struct genapic apic_x2apic_phys = { .send_IPI_self = x2apic_send_IPI_self, .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = x2apic_read_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFFFFFFFu), }; diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index c915f750241..3ca29cd8c23 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -139,16 +139,31 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } -static unsigned int uv_read_apic_id(void) +static unsigned int get_apic_id(unsigned long x) { unsigned int id; WARN_ON(preemptible() && num_online_cpus() > 1); - id = apic_read(APIC_ID) | __get_cpu_var(x2apic_extra_bits); + id = x | __get_cpu_var(x2apic_extra_bits); return id; } +static long set_apic_id(unsigned int id) +{ + unsigned long x; + + /* maskout x2apic_extra_bits ? */ + x = id; + return x; +} + +static unsigned int uv_read_apic_id(void) +{ + + return get_apic_id(apic_read(APIC_ID)); +} + static unsigned int phys_pkg_id(int index_msb) { return uv_read_apic_id() >> index_msb; @@ -175,7 +190,9 @@ struct genapic apic_x2apic_uv_x = { /* ZZZ.send_IPI_self = uv_send_IPI_self, */ .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */ - .read_apic_id = uv_read_apic_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFFFFFFFu), }; static __cpuinit void set_x2apic_extra_bits(int pnode) -- cgit v1.2.3 From 94a8c3c2437c8946f1b6c8e0b2c560a7db8ed3c6 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 13 Jul 2008 22:19:35 -0700 Subject: x86: let 32bit use apic_ops too - fix fix for pv - clean up the namespace there too. Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/paravirt.c | 5 ----- arch/x86/kernel/vmi_32.c | 51 +++++++++++++++++++++++++++++++++++++++++++--- arch/x86/xen/enlighten.c | 19 ++++++++--------- 3 files changed, 57 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 4f29ff847eb..e0f139106c7 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -360,11 +360,6 @@ struct pv_cpu_ops pv_cpu_ops = { struct pv_apic_ops pv_apic_ops = { #ifdef CONFIG_X86_LOCAL_APIC -#ifndef CONFIG_X86_64 - .apic_write = native_apic_mem_write, - .apic_write_atomic = native_apic_mem_write_atomic, - .apic_read = native_apic_mem_read, -#endif .setup_boot_clock = setup_boot_APIC_clock, .setup_secondary_clock = setup_secondary_APIC_clock, .startup_ipi_hook = paravirt_nop, diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index b15346092b7..cf307435455 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -676,6 +676,50 @@ static inline int __init probe_vmi_rom(void) return 0; } +#ifdef CONFIG_X86_LOCAL_APIC +static u32 vmi_apic_read(u32 reg) +{ + return 0; +} + +static void vmi_apic_write(u32 reg, u32 val) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static u64 vmi_apic_icr_read(void) +{ + return 0; +} + +static void vmi_apic_icr_write(u32 low, u32 id) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static void vmi_apic_wait_icr_idle(void) +{ + return; +} + +static u32 vmi_safe_apic_wait_icr_idle(void) +{ + return 0; +} + +static struct apic_ops vmi_basic_apic_ops = { + .read = vmi_apic_read, + .write = vmi_apic_write, + .write_atomic = vmi_apic_write, + .icr_read = vmi_apic_icr_read, + .icr_write = vmi_apic_icr_write, + .wait_icr_idle = vmi_apic_wait_icr_idle, + .safe_wait_icr_idle = vmi_safe_apic_wait_icr_idle, +}; +#endif + /* * VMI setup common to all processors */ @@ -904,9 +948,10 @@ static inline int __init activate_vmi(void) #endif #ifdef CONFIG_X86_LOCAL_APIC - para_fill(pv_apic_ops.apic_read, APICRead); - para_fill(pv_apic_ops.apic_write, APICWrite); - para_fill(pv_apic_ops.apic_write_atomic, APICWrite); + para_fill(vmi_basic_apic_ops.read, APICRead); + para_fill(vmi_basic_apic_ops.write, APICWrite); + para_fill(vmi_basic_apic_ops.write_atomic, APICWrite); + apic_ops = &vmi_basic_apic_ops; #endif /* diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 54e25566753..d11dda7ebd7 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -559,7 +559,6 @@ static void xen_apic_write(u32 reg, u32 val) WARN_ON(1); } -#ifdef CONFIG_X86_64 static u64 xen_apic_icr_read(void) { return 0; @@ -576,6 +575,11 @@ static void xen_apic_wait_icr_idle(void) return; } +static u32 xen_safe_apic_wait_icr_idle(void) +{ + return 0; +} + static struct apic_ops xen_basic_apic_ops = { .read = xen_apic_read, .write = xen_apic_write, @@ -583,9 +587,8 @@ static struct apic_ops xen_basic_apic_ops = { .icr_read = xen_apic_icr_read, .icr_write = xen_apic_icr_write, .wait_icr_idle = xen_apic_wait_icr_idle, - .safe_wait_icr_idle = xen_apic_wait_icr_idle, + .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle, }; -#endif #endif @@ -1159,11 +1162,6 @@ static const struct pv_irq_ops xen_irq_ops __initdata = { static const struct pv_apic_ops xen_apic_ops __initdata = { #ifdef CONFIG_X86_LOCAL_APIC -#ifndef CONFIG_X86_64 - .apic_write = xen_apic_write, - .apic_write_atomic = xen_apic_write, - .apic_read = xen_apic_read, -#endif .setup_boot_clock = paravirt_nop, .setup_secondary_clock = paravirt_nop, .startup_ipi_hook = paravirt_nop, @@ -1322,9 +1320,10 @@ asmlinkage void __init xen_start_kernel(void) pv_irq_ops = xen_irq_ops; pv_apic_ops = xen_apic_ops; pv_mmu_ops = xen_mmu_ops; -#ifdef CONFIG_X86_64 + +#ifdef CONFIG_X86_LOCAL_APIC /* - * for 64bit, set up the basic apic ops aswell. + * set up the basic apic ops. */ apic_ops = &xen_basic_apic_ops; #endif -- cgit v1.2.3 From 9a8f0e6b5dfe3b4f330fc82b16a4000f5688fce8 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 18 Jul 2008 09:59:40 -0700 Subject: x86: let 32bit use apic_ops too - fix Fix VMI apic_ops. Signed-off-by: Suresh Siddha Acked-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 5 +++++ arch/x86/kernel/vmi_32.c | 51 +++-------------------------------------------- 2 files changed, 8 insertions(+), 48 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 47ff978aecf..cb54d9e20f9 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -145,6 +145,11 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } +/* + * Paravirt kernels also might be using these below ops. So we still + * use generic apic_read()/apic_write(), which might be pointing to different + * ops in PARAVIRT case. + */ void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index cf307435455..237082833c1 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -676,50 +676,6 @@ static inline int __init probe_vmi_rom(void) return 0; } -#ifdef CONFIG_X86_LOCAL_APIC -static u32 vmi_apic_read(u32 reg) -{ - return 0; -} - -static void vmi_apic_write(u32 reg, u32 val) -{ - /* Warn to see if there's any stray references */ - WARN_ON(1); -} - -static u64 vmi_apic_icr_read(void) -{ - return 0; -} - -static void vmi_apic_icr_write(u32 low, u32 id) -{ - /* Warn to see if there's any stray references */ - WARN_ON(1); -} - -static void vmi_apic_wait_icr_idle(void) -{ - return; -} - -static u32 vmi_safe_apic_wait_icr_idle(void) -{ - return 0; -} - -static struct apic_ops vmi_basic_apic_ops = { - .read = vmi_apic_read, - .write = vmi_apic_write, - .write_atomic = vmi_apic_write, - .icr_read = vmi_apic_icr_read, - .icr_write = vmi_apic_icr_write, - .wait_icr_idle = vmi_apic_wait_icr_idle, - .safe_wait_icr_idle = vmi_safe_apic_wait_icr_idle, -}; -#endif - /* * VMI setup common to all processors */ @@ -948,10 +904,9 @@ static inline int __init activate_vmi(void) #endif #ifdef CONFIG_X86_LOCAL_APIC - para_fill(vmi_basic_apic_ops.read, APICRead); - para_fill(vmi_basic_apic_ops.write, APICWrite); - para_fill(vmi_basic_apic_ops.write_atomic, APICWrite); - apic_ops = &vmi_basic_apic_ops; + para_fill(apic_ops->read, APICRead); + para_fill(apic_ops->write, APICWrite); + para_fill(apic_ops->write_atomic, APICWrite); #endif /* -- cgit v1.2.3 From 511d9d34183662aada3890883e860b151d707e22 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 14 Jul 2008 09:49:14 -0700 Subject: x86: apic_ops for lguest apic_ops for lguest. Signed-off-by: Suresh Siddha Acked-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/lguest/boot.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 0c45df20e2b..675ee7a6475 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -791,6 +791,37 @@ static u32 lguest_apic_read(u32 reg) { return 0; } + +static u64 lguest_apic_icr_read(void) +{ + return 0; +} + +static void lguest_apic_icr_write(u32 low, u32 id) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static void lguest_apic_wait_icr_idle(void) +{ + return; +} + +static u32 lguest_apic_safe_wait_icr_idle(void) +{ + return 0; +} + +static struct apic_ops lguest_basic_apic_ops = { + .read = lguest_apic_read, + .write = lguest_apic_write, + .write_atomic = lguest_apic_write, + .icr_read = lguest_apic_icr_read, + .icr_write = lguest_apic_icr_write, + .wait_icr_idle = lguest_apic_wait_icr_idle, + .safe_wait_icr_idle = lguest_apic_safe_wait_icr_idle, +}; #endif /* STOP! Until an interrupt comes in. */ @@ -990,9 +1021,7 @@ __init void lguest_init(void) #ifdef CONFIG_X86_LOCAL_APIC /* apic read/write intercepts */ - pv_apic_ops.apic_write = lguest_apic_write; - pv_apic_ops.apic_write_atomic = lguest_apic_write; - pv_apic_ops.apic_read = lguest_apic_read; + apic_ops = &lguest_basic_apic_ops; #endif /* time operations */ -- cgit v1.2.3 From f586bf7df9acc26b68b0feefc0dd32fa63516d3a Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 18 Jul 2008 15:58:35 -0700 Subject: x86: APIC: Remove apic_write_around(); use alternatives, merge fix On Fri, Jul 18, 2008 at 02:03:48PM -0700, Ingo Molnar wrote: > > * Yinghai Lu wrote: > > > > git merge tip/x86/x2apic > > CONFLICT (content): Merge conflict in arch/x86/kernel/Makefile > > CONFLICT (content): Merge conflict in arch/x86/kernel/paravirt.c > > CONFLICT (content): Merge conflict in arch/x86/kernel/smpboot.c > > CONFLICT (content): Merge conflict in arch/x86/kernel/vmi_32.c > > CONFLICT (content): Merge conflict in arch/x86/xen/enlighten.c > > CONFLICT (content): Merge conflict in include/asm-x86/apic.h > > CONFLICT (content): Merge conflict in include/asm-x86/paravirt.h > > that's due to the changes in tip/x86/apic and in tip/x86/uv. > > ok, i've just merged x86/apic into x86/x2apic and x86/uv as well, and > pushed out the result. > > Note: it's a first raw merge and completely untested. It will now merge > cleanly into tip/master. There are probably a few details missing. Ingo, thanks for doing this. While I was testing my merge changes, you posted yours... anyhow we need this piece, which is missing from your merge. Signed-off-by: Suresh Siddha Cc: Yinghai Lu Cc: "Maciej W. Rozycki" Cc: Jeremy Fitzhardinge Cc: Zachary Amsden Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 5 ++--- arch/x86/kernel/apic_64.c | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index dcb897f22aa..8728f54a93d 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -174,8 +174,8 @@ u32 safe_xapic_wait_icr_idle(void) void xapic_icr_write(u32 low, u32 id) { - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); - apic_write_around(APIC_ICR, low); + apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id)); + apic_write(APIC_ICR, low); } u64 xapic_icr_read(void) @@ -191,7 +191,6 @@ u64 xapic_icr_read(void) static struct apic_ops xapic_ops = { .read = native_apic_mem_read, .write = native_apic_mem_write, - .write_atomic = native_apic_mem_write_atomic, .icr_read = xapic_icr_read, .icr_write = xapic_icr_write, .wait_icr_idle = xapic_wait_icr_idle, diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 46e612408ac..a850bc63fb1 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -167,7 +167,6 @@ u64 xapic_icr_read(void) static struct apic_ops xapic_ops = { .read = native_apic_mem_read, .write = native_apic_mem_write, - .write_atomic = native_apic_mem_write_atomic, .icr_read = xapic_icr_read, .icr_write = xapic_icr_write, .wait_icr_idle = xapic_wait_icr_idle, @@ -206,7 +205,6 @@ u64 x2apic_icr_read(void) static struct apic_ops x2apic_ops = { .read = native_apic_msr_read, .write = native_apic_msr_write, - .write_atomic = native_apic_msr_write, .icr_read = x2apic_icr_read, .icr_write = x2apic_icr_write, .wait_icr_idle = x2apic_wait_icr_idle, -- cgit v1.2.3 From caf43bf7c6a55e89b6df5179df434d67e24aa32e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 20 Jul 2008 14:06:50 +0200 Subject: x86, xen: fix apic_ops build on UP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/xen/enlighten.c:615: error: variable ‘xen_basic_apic_ops’ has initializer but incomplete type arch/x86/xen/enlighten.c:616: error: unknown field ‘read’ specified in initializer [...] Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 008b7b69581..e4d1459a63d 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -35,6 +35,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From 7be42004065ce4df193aeef5befd26805267d0d9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 20 Jul 2008 17:04:57 +0200 Subject: x86, lguest: fix apic_ops build on UP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/lguest/boot.c:816: error: variable ‘lguest_basic_apic_ops’ has initializer but incomplete type arch/x86/lguest/boot.c:817: error: unknown field ‘read’ specified in initializer [...] Signed-off-by: Ingo Molnar --- arch/x86/lguest/boot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 35c4349cd66..756fc489652 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 1b9b89e7f163336ad84200b66a17284dbf26aced Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 21 Jul 2008 22:08:21 -0700 Subject: x86: add apic probe for genapic 64bit, v2 introducing an APIC handling probing abstraction: static struct genapic *apic_probe[] __initdata = { &apic_x2apic_uv_x, &apic_x2apic_phys, &apic_x2apic_cluster, &apic_physflat, NULL, }; This way we can remove UV, x2apic specific code from genapic_64.c and move them to their specific genapic files. [ v2: fix compiling when CONFIG_ACPI is not set ] Signed-off-by: Yinghai Lu Cc: Jack Steiner Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_64.c | 85 ++++++++++++------------------------- arch/x86/kernel/genapic_flat_64.c | 26 ++++++++++++ arch/x86/kernel/genx2apic_cluster.c | 11 +++++ arch/x86/kernel/genx2apic_phys.c | 21 +++++++++ arch/x86/kernel/genx2apic_uv_x.c | 32 +++++++++++++- 5 files changed, 115 insertions(+), 60 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 3940d8161f8..b3ba969c50d 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -16,62 +16,37 @@ #include #include #include -#include #include #include #include -#ifdef CONFIG_ACPI -#include -#endif - -DEFINE_PER_CPU(int, x2apic_extra_bits); +extern struct genapic apic_flat; +extern struct genapic apic_physflat; +extern struct genapic apic_x2xpic_uv_x; +extern struct genapic apic_x2apic_phys; +extern struct genapic apic_x2apic_cluster; struct genapic __read_mostly *genapic = &apic_flat; -static int x2apic_phys = 0; - -static int set_x2apic_phys_mode(char *arg) -{ - x2apic_phys = 1; - return 0; -} -early_param("x2apic_phys", set_x2apic_phys_mode); - -static enum uv_system_type uv_system_type; +static struct genapic *apic_probe[] __initdata = { + &apic_x2apic_uv_x, + &apic_x2apic_phys, + &apic_x2apic_cluster, + &apic_physflat, + NULL, +}; /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. */ void __init setup_apic_routing(void) { - if (uv_system_type == UV_NON_UNIQUE_APIC) - genapic = &apic_x2apic_uv_x; - else if (cpu_has_x2apic && intr_remapping_enabled) { - if (x2apic_phys) - genapic = &apic_x2apic_phys; - else - genapic = &apic_x2apic_cluster; - } else -#ifdef CONFIG_ACPI - /* - * Quirk: some x86_64 machines can only use physical APIC mode - * regardless of how many processors are present (x86_64 ES7000 - * is an example). - */ - if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID && - (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) - genapic = &apic_physflat; - else -#endif - - if (max_physical_apicid < 8) - genapic = &apic_flat; - else - genapic = &apic_physflat; - - printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); + if (genapic == &apic_flat) { + if (max_physical_apicid >= 8) + genapic = &apic_physflat; + printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); + } } /* Same for both flat and physical. */ @@ -83,23 +58,15 @@ void apic_send_IPI_self(int vector) int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - if (!strcmp(oem_id, "SGI")) { - if (!strcmp(oem_table_id, "UVL")) - uv_system_type = UV_LEGACY_APIC; - else if (!strcmp(oem_table_id, "UVX")) - uv_system_type = UV_X2APIC; - else if (!strcmp(oem_table_id, "UVH")) - uv_system_type = UV_NON_UNIQUE_APIC; + int i; + + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Setting APIC routing to %s.\n", + genapic->name); + return 1; + } } return 0; } - -enum uv_system_type get_uv_system_type(void) -{ - return uv_system_type; -} - -int is_uv_system(void) -{ - return uv_system_type != UV_NONE; -} diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 2c973cbf054..1740b83329f 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -21,6 +21,15 @@ #include #include +#ifdef CONFIG_ACPI +#include +#endif + +static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return 1; +} + static cpumask_t flat_target_cpus(void) { return cpu_online_map; @@ -138,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb) struct genapic apic_flat = { .name = "flat", + .acpi_madt_oem_check = flat_acpi_madt_oem_check, .int_delivery_mode = dest_LowestPrio, .int_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = flat_target_cpus, @@ -160,6 +170,21 @@ struct genapic apic_flat = { * We cannot use logical delivery in this case because the mask * overflows, so use physical mode. */ +static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ +#ifdef CONFIG_ACPI + /* + * Quirk: some x86_64 machines can only use physical APIC mode + * regardless of how many processors are present (x86_64 ES7000 + * is an example). + */ + if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID && + (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) + return 1; +#endif + + return 0; +} static cpumask_t physflat_target_cpus(void) { @@ -206,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask) struct genapic apic_physflat = { .name = "physical flat", + .acpi_madt_oem_check = physflat_acpi_madt_oem_check, .int_delivery_mode = dest_Fixed, .int_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = physflat_target_cpus, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 40bc0140d89..ef3f3182d50 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -4,12 +4,22 @@ #include #include #include +#include + #include #include #include DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); +static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (cpu_has_x2apic && intr_remapping_enabled) + return 1; + + return 0; +} + /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ static cpumask_t x2apic_target_cpus(void) @@ -135,6 +145,7 @@ static void init_x2apic_ldr(void) struct genapic apic_x2apic_cluster = { .name = "cluster x2apic", + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, .int_delivery_mode = dest_LowestPrio, .int_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = x2apic_target_cpus, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 2f3c6ca19de..f35a3bf3a9e 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -4,10 +4,30 @@ #include #include #include +#include + #include #include #include +DEFINE_PER_CPU(int, x2apic_extra_bits); + +static int x2apic_phys; + +static int set_x2apic_phys_mode(char *arg) +{ + x2apic_phys = 1; + return 0; +} +early_param("x2apic_phys", set_x2apic_phys_mode); + +static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys) + return 1; + + return 0; +} /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ @@ -122,6 +142,7 @@ void init_x2apic_ldr(void) struct genapic apic_x2apic_phys = { .name = "physical x2apic", + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, .int_delivery_mode = dest_Fixed, .int_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = x2apic_target_cpus, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index a8e5cb4c4d4..a882bc3a2ce 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -27,6 +27,33 @@ #include #include +static enum uv_system_type uv_system_type; + +static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (!strcmp(oem_id, "SGI")) { + if (!strcmp(oem_table_id, "UVL")) + uv_system_type = UV_LEGACY_APIC; + else if (!strcmp(oem_table_id, "UVX")) + uv_system_type = UV_X2APIC; + else if (!strcmp(oem_table_id, "UVH")) { + uv_system_type = UV_NON_UNIQUE_APIC; + return 1; + } + } + return 0; +} + +enum uv_system_type get_uv_system_type(void) +{ + return uv_system_type; +} + +int is_uv_system(void) +{ + return uv_system_type != UV_NONE; +} + DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); @@ -153,7 +180,7 @@ static unsigned int get_apic_id(unsigned long x) return id; } -static long set_apic_id(unsigned int id) +static unsigned long set_apic_id(unsigned int id) { unsigned long x; @@ -182,6 +209,7 @@ static void uv_send_IPI_self(int vector) struct genapic apic_x2apic_uv_x = { .name = "UV large system", + .acpi_madt_oem_check = uv_acpi_madt_oem_check, .int_delivery_mode = dest_Fixed, .int_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = uv_target_cpus, @@ -433,3 +461,5 @@ void __cpuinit uv_cpu_init(void) if (get_uv_system_type() == UV_NON_UNIQUE_APIC) set_x2apic_extra_bits(uv_hub_info->pnode); } + + -- cgit v1.2.3 From 026e2c05ef58ef413e2d52696f125d5ea1aa8bce Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 22 Jul 2008 11:58:14 +0200 Subject: x86, cyrix: debug Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/cyrix.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 3fd7a67bb06..db5868cd244 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -116,7 +116,7 @@ static void __cpuinit set_cx86_reorder(void) setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ /* Load/Store Serialize to mem access disable (=reorder it) */ - setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80); + setCx86_old(CX86_PCR0, getCx86_old(CX86_PCR0) & ~0x80); /* set load/store serialize from 1GB to 4GB */ ccr3 |= 0xe0; setCx86(CX86_CCR3, ccr3); @@ -127,11 +127,11 @@ static void __cpuinit set_cx86_memwb(void) printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); /* CCR2 bit 2: unlock NW bit */ - setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04); + setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) & ~0x04); /* set 'Not Write-through' */ write_cr0(read_cr0() | X86_CR0_NW); /* CCR2 bit 2: lock NW bit and set WT1 */ - setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14); + setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) | 0x14); } static void __cpuinit set_cx86_inc(void) @@ -144,10 +144,10 @@ static void __cpuinit set_cx86_inc(void) setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ /* PCR1 -- Performance Control */ /* Incrementor on, whatever that is */ - setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02); + setCx86_old(CX86_PCR1, getCx86_old(CX86_PCR1) | 0x02); /* PCR0 -- Performance Control */ /* Incrementor Margin 10 */ - setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04); + setCx86_old(CX86_PCR0, getCx86_old(CX86_PCR0) | 0x04); setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ } @@ -162,14 +162,14 @@ static void __cpuinit geode_configure(void) local_irq_save(flags); /* Suspend on halt power saving and enable #SUSP pin */ - setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88); + setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) | 0x88); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ /* FPU fast, DTE cache, Mem bypass */ - setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38); + setCx86_old(CX86_CCR4, getCx86_old(CX86_CCR4) | 0x38); setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ set_cx86_memwb(); @@ -286,7 +286,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { /* Enable cxMMX extensions (GX1 Datasheet 54) */ - setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1); + setCx86_old(CX86_CCR7, getCx86_old(CX86_CCR7) | 1); /* * GXm : 0x30 ... 0x5f GXm datasheet 51 @@ -309,7 +309,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) if (dir1 > 7) { dir0_msn++; /* M II */ /* Enable MMX extensions (App note 108) */ - setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1); + setCx86_old(CX86_CCR7, getCx86_old(CX86_CCR7)|1); } else { c->coma_bug = 1; /* 6x86MX, it has the bug. */ } @@ -424,7 +424,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) local_irq_save(flags); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ - setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80); /* enable cpuid */ + setCx86_old(CX86_CCR4, getCx86_old(CX86_CCR4) | 0x80); /* enable cpuid */ setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ local_irq_restore(flags); } -- cgit v1.2.3 From bbc1f698a508927d21324b57500e863f9bd562b9 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 21:34:13 +0530 Subject: x86: Introducing asm/syscalls.h Declaring arch-dependent syscalls for x86 architecture Signed-off-by: Jaswinder Singh --- arch/x86/kernel/ioport.c | 1 + arch/x86/kernel/ldt.c | 1 + arch/x86/kernel/process_32.c | 1 + arch/x86/kernel/process_64.c | 1 + arch/x86/kernel/signal_32.c | 1 + arch/x86/kernel/signal_64.c | 1 + arch/x86/kernel/sys_i386_32.c | 2 ++ arch/x86/kernel/sys_x86_64.c | 1 + arch/x86/kernel/tls.c | 1 + arch/x86/kernel/vm86_32.c | 1 + 10 files changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index 50e5e4a31c8..19191430274 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c @@ -14,6 +14,7 @@ #include #include #include +#include /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ static void set_bitmap(unsigned long *bitmap, unsigned int base, diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index a8449571858..c49ff2dc8f8 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef CONFIG_SMP static void flush_ldt(void *current_mm) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 0c3927accb0..6490e498126 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -55,6 +55,7 @@ #include #include #include +#include asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e8a8e1b9981..c78090dd0c5 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -51,6 +51,7 @@ #include #include #include +#include asmlinkage extern void ret_from_fork(void); diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 07faaa5109c..5cede1045ce 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "sigframe.h" diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index bf87684474f..b95a0a60905 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "sigframe.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index 7066cb855a6..1884a8d12bf 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c @@ -22,6 +22,8 @@ #include #include +#include + asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 3b360ef3381..c9288c883e2 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -16,6 +16,7 @@ #include #include +#include asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off) diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index ab6bf375a30..6bb7b8579e7 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "tls.h" diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 38f566fa27d..4eeb5cf9720 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -46,6 +46,7 @@ #include #include #include +#include /* * Known problems: -- cgit v1.2.3 From fb26132b441e75d6ba9996efc29b42081aee0abd Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 21:36:40 +0530 Subject: x86: process_32.c declare cpu_number before they get used Moved DECLARE_PER_CPU(int, cpu_number) from CONFIG_X86_32_SMP to CONFIG_X86_32 because cpu_number is required for both. And include asm/smp.h in process_32.c Signed-off-by: Jaswinder Singh --- arch/x86/kernel/process_32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 6490e498126..7218bccd176 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -56,6 +56,7 @@ #include #include #include +#include asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); -- cgit v1.2.3 From cc0384917bf69079088701a0725c5fc6b554bf35 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 21:52:51 +0530 Subject: x86: time_XX.c declare functions before they get used Declare time_init() in asm-x86/time.h Also did cleanup in asm-x86/timer.h : timer_ack is only required for X86_32 int recalibrate_cpu_khz(void) is for X86_32 Signed-off-by: Jaswinder Singh --- arch/x86/kernel/time_32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index ffe3c664afc..bbecf8b6bf9 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "do_timer.h" -- cgit v1.2.3 From 1e84911c6c37fd1080ef07039e19c346628b31db Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:58:29 +0530 Subject: x86: mtrr/main.c declare range_state as static Signed-off-by: Jaswinder Singh --- arch/x86/kernel/cpu/mtrr/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 6f23969c8fa..b5ade28ca8f 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -729,7 +729,7 @@ struct var_mtrr_range_state { mtrr_type type; }; -struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; +static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; static int __initdata debug_print; static int __init -- cgit v1.2.3 From a31863168660c6b6f6c7ffe05bb6a38e97803326 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 22 Jul 2008 21:53:53 +0200 Subject: x86: consolidate header guards This patch consolidates the header guard names which are also used externally, i.e. in .c files. Signed-off-by: Vegard Nossum --- arch/x86/boot/compressed/misc.c | 2 +- arch/x86/kernel/asm-offsets_64.c | 2 +- arch/x86/kernel/syscall_64.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index bc5553b496f..3ee338c7d1d 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -16,7 +16,7 @@ */ #undef CONFIG_PARAVIRT #ifdef CONFIG_X86_32 -#define _ASM_DESC_H_ 1 +#define ASM_X86__DESC_H 1 #endif #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index aa89387006f..505543a75a5 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -22,7 +22,7 @@ #define __NO_STUBS 1 #undef __SYSCALL -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #define __SYSCALL(nr, sym) [nr] = 1, static char syscalls[] = { #include diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c index 170d43c1748..3d1be4f0fac 100644 --- a/arch/x86/kernel/syscall_64.c +++ b/arch/x86/kernel/syscall_64.c @@ -8,12 +8,12 @@ #define __NO_STUBS #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #include #undef __SYSCALL #define __SYSCALL(nr, sym) [nr] = sym, -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H typedef void (*sys_call_ptr_t)(void); -- cgit v1.2.3 From a80495ec927e8ec2b1ff085592bbe9bed77ffb3b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:33:57 +0530 Subject: x86: mm/init_XX.c declare functions before they get used included in mm/init_32.c for zap_low_mappings() declared free_initmem() in asm-x86/page_XX.h Signed-off-by: Jaswinder Singh --- arch/x86/mm/init_32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d37f29376b0..4974e97dedf 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -47,6 +47,7 @@ #include #include #include +#include unsigned int __VMALLOC_RESERVE = 128 << 20; -- cgit v1.2.3 From 70ef56414ec7e01d787c8e959bb259845df4ee4f Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:36:37 +0530 Subject: x86: mm/fault.c declare do_page_fault before they get used declared do_page_fault() in asm-x86/trap.h for both X86_32 and X86_64 removed do_invalid_op declaration from mm/fault.c as it is already declared in asm-x86/trap.h Signed-off-by: Jaswinder Singh --- arch/x86/mm/fault.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 455f3fe67b4..8f92cac4e6d 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * Page fault error code bits @@ -357,8 +358,6 @@ static int is_errata100(struct pt_regs *regs, unsigned long address) return 0; } -void do_invalid_op(struct pt_regs *, unsigned long); - static int is_f00f_bug(struct pt_regs *regs, unsigned long address) { #ifdef CONFIG_X86_F00F_BUG -- cgit v1.2.3 From 4b6e9f27d0034740e9cfa341b45c229ba30ec0c5 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:39:16 +0530 Subject: x86: mm/ioremap.c declare early_ioremap_debug and early_ioremap_nested as static Signed-off-by: Jaswinder Singh --- arch/x86/mm/ioremap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 24c1d3c3018..19fd9a3c521 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -413,7 +413,7 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr) return; } -int __initdata early_ioremap_debug; +static int __initdata early_ioremap_debug; static int __init early_ioremap_debug_setup(char *str) { @@ -539,7 +539,7 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx) } -int __initdata early_ioremap_nested; +static int __initdata early_ioremap_nested; static int __init check_early_ioremap_leak(void) { -- cgit v1.2.3 From 71e3b818431957371c7f69fa1c576d4a403c1478 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:44:00 +0530 Subject: x86: mach-default/setup.c declare no_broadcast before they get used included mach_ipi.h for no_broadcast declaration fixed minor spacing for no_broadcast Signed-off-by: Jaswinder Singh --- arch/x86/mach-default/setup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c index 3d317836be9..3f2cf11f201 100644 --- a/arch/x86/mach-default/setup.c +++ b/arch/x86/mach-default/setup.c @@ -10,13 +10,15 @@ #include #include +#include + #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) #else #define DEFAULT_SEND_IPI (0) #endif -int no_broadcast=DEFAULT_SEND_IPI; +int no_broadcast = DEFAULT_SEND_IPI; /** * pre_intr_init_hook - initialisation prior to setting up interrupt vectors -- cgit v1.2.3 From 05d3ed0a1fe3ea05ab9f3b8d32576a0bc2e19660 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Mon, 21 Jul 2008 10:15:22 -0400 Subject: x86, pci: iommu fix potential overflow in alloc_iommu() It is possible that alloc_iommu()'s boundary_size overflows as dma_get_seg_boundary can return 0xffffffff. In that case, further usage of boundary_size triggers a BUG_ON() in the iommu code. Signed-off-by: Prarit Bhargava Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index df5f142657d..1062dc1e639 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -93,7 +93,7 @@ static unsigned long alloc_iommu(struct device *dev, int size) base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), PAGE_SIZE) >> PAGE_SHIFT; - boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, + boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, PAGE_SIZE) >> PAGE_SHIFT; spin_lock_irqsave(&iommu_bitmap_lock, flags); -- cgit v1.2.3 From fd60b39f845aa7462453af8aed4f059b162f181f Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Wed, 23 Jul 2008 22:45:01 +0800 Subject: arch/x86/kernel/genx2apic_uv_x.c: Removed duplicated include Removed duplicated include file in arch/x86/kernel/genx2apic_uv_x.c. Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_uv_x.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index a882bc3a2ce..14a9772778e 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 38ffbe66d59051fd9cfcfc8545f164700e2fa3bc Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 23 Jul 2008 14:21:18 -0700 Subject: x86/paravirt/xen: properly fill out the ldt ops LTP testing showed that Xen does not properly implement sys_modify_ldt(). This patch does the final little bits needed to make the ldt work properly. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/ldt.c | 9 ++++++++- arch/x86/kernel/paravirt.c | 4 ++++ arch/x86/xen/enlighten.c | 23 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index 3fee2aa50f3..4895e0634d2 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -51,6 +51,8 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, (mincount - oldsize) * LDT_ENTRY_SIZE); + paravirt_alloc_ldt(newldt, mincount); + #ifdef CONFIG_X86_64 /* CHECKME: Do we really need this ? */ wmb(); @@ -75,6 +77,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) #endif } if (oldsize) { + paravirt_free_ldt(oldldt, oldsize); if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(oldldt); else @@ -86,10 +89,13 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) static inline int copy_ldt(mm_context_t *new, mm_context_t *old) { int err = alloc_ldt(new, old->size, 0); + int i; if (err < 0) return err; - memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE); + + for(i = 0; i < old->size; i++) + write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE); return 0; } @@ -126,6 +132,7 @@ void destroy_context(struct mm_struct *mm) if (mm == current->active_mm) clear_LDT(); #endif + paravirt_free_ldt(mm->context.ldt, mm->context.size); if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 94da4d52d79..d8f2277be5a 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -348,6 +348,10 @@ struct pv_cpu_ops pv_cpu_ops = { .write_ldt_entry = native_write_ldt_entry, .write_gdt_entry = native_write_gdt_entry, .write_idt_entry = native_write_idt_entry, + + .alloc_ldt = paravirt_nop, + .free_ldt = paravirt_nop, + .load_sp0 = native_load_sp0, #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 9ff6e3cbf08..06219e60e9c 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -325,6 +325,26 @@ static unsigned long xen_store_tr(void) return 0; } +static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) +{ + unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); + void *v = ldt; + int i; + + for(i = 0; i < pages; i += PAGE_SIZE) + make_lowmem_page_readonly(v + i); +} + +static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) +{ + unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); + void *v = ldt; + int i; + + for(i = 0; i < pages; i += PAGE_SIZE) + make_lowmem_page_readwrite(v + i); +} + static void xen_set_ldt(const void *addr, unsigned entries) { struct mmuext_op *op; @@ -1220,6 +1240,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { .load_gs_index = xen_load_gs_index, #endif + .alloc_ldt = xen_alloc_ldt, + .free_ldt = xen_free_ldt, + .store_gdt = native_store_gdt, .store_idt = native_store_idt, .store_tr = xen_store_tr, -- cgit v1.2.3 From d5de8841355a48f7f634a04507185eaf1f9755e3 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 23 Jul 2008 13:28:58 -0700 Subject: x86: split spinlock implementations out into their own files ftrace requires certain low-level code, like spinlocks and timestamps, to be compiled without -pg in order to avoid infinite recursion. This patch splits out the core paravirt spinlocks and the Xen spinlocks into separate files which can be compiled without -pg. Also do xen/time.c while we're about it. As a result, we can now use ftrace within a Xen domain. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 4 +- arch/x86/kernel/paravirt-spinlocks.c | 31 ++++++ arch/x86/kernel/paravirt.c | 23 ----- arch/x86/xen/Makefile | 8 +- arch/x86/xen/smp.c | 167 -------------------------------- arch/x86/xen/spinlock.c | 183 +++++++++++++++++++++++++++++++++++ arch/x86/xen/xen-ops.h | 3 + 7 files changed, 226 insertions(+), 193 deletions(-) create mode 100644 arch/x86/kernel/paravirt-spinlocks.c create mode 100644 arch/x86/xen/spinlock.c (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 3db651fc8ec..d679cb2c79b 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -10,7 +10,7 @@ ifdef CONFIG_FTRACE # Do not profile debug and lowlevel utilities CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg -CFLAGS_REMOVE_paravirt.o = -pg +CFLAGS_REMOVE_paravirt-spinlocks.o = -pg endif # @@ -89,7 +89,7 @@ obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o obj-$(CONFIG_KVM_GUEST) += kvm.o obj-$(CONFIG_KVM_CLOCK) += kvmclock.o -obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o +obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o paravirt-spinlocks.o obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c new file mode 100644 index 00000000000..38d7f7f1dbc --- /dev/null +++ b/arch/x86/kernel/paravirt-spinlocks.c @@ -0,0 +1,31 @@ +/* + * Split spinlock implementation out into its own file, so it can be + * compiled in a FTRACE-compatible way. + */ +#include +#include + +#include + +struct pv_lock_ops pv_lock_ops = { +#ifdef CONFIG_SMP + .spin_is_locked = __ticket_spin_is_locked, + .spin_is_contended = __ticket_spin_is_contended, + + .spin_lock = __ticket_spin_lock, + .spin_trylock = __ticket_spin_trylock, + .spin_unlock = __ticket_spin_unlock, +#endif +}; +EXPORT_SYMBOL_GPL(pv_lock_ops); + +void __init paravirt_use_bytelocks(void) +{ +#ifdef CONFIG_SMP + pv_lock_ops.spin_is_locked = __byte_spin_is_locked; + pv_lock_ops.spin_is_contended = __byte_spin_is_contended; + pv_lock_ops.spin_lock = __byte_spin_lock; + pv_lock_ops.spin_trylock = __byte_spin_trylock; + pv_lock_ops.spin_unlock = __byte_spin_unlock; +#endif +} diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 94da4d52d79..0d71de9ff56 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -268,17 +268,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void) return __get_cpu_var(paravirt_lazy_mode); } -void __init paravirt_use_bytelocks(void) -{ -#ifdef CONFIG_SMP - pv_lock_ops.spin_is_locked = __byte_spin_is_locked; - pv_lock_ops.spin_is_contended = __byte_spin_is_contended; - pv_lock_ops.spin_lock = __byte_spin_lock; - pv_lock_ops.spin_trylock = __byte_spin_trylock; - pv_lock_ops.spin_unlock = __byte_spin_unlock; -#endif -} - struct pv_info pv_info = { .name = "bare hardware", .paravirt_enabled = 0, @@ -461,18 +450,6 @@ struct pv_mmu_ops pv_mmu_ops = { .set_fixmap = native_set_fixmap, }; -struct pv_lock_ops pv_lock_ops = { -#ifdef CONFIG_SMP - .spin_is_locked = __ticket_spin_is_locked, - .spin_is_contended = __ticket_spin_is_contended, - - .spin_lock = __ticket_spin_lock, - .spin_trylock = __ticket_spin_trylock, - .spin_unlock = __ticket_spin_unlock, -#endif -}; -EXPORT_SYMBOL_GPL(pv_lock_ops); - EXPORT_SYMBOL_GPL(pv_time_ops); EXPORT_SYMBOL (pv_cpu_ops); EXPORT_SYMBOL (pv_mmu_ops); diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 59c1e539aed..5bfee243cf9 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -1,4 +1,10 @@ +ifdef CONFIG_FTRACE +# Do not profile debug and lowlevel utilities +CFLAGS_REMOVE_spinlock.o = -pg +CFLAGS_REMOVE_time.o = -pg +endif + obj-y := enlighten.o setup.o multicalls.o mmu.o \ time.o xen-asm_$(BITS).o grant-table.o suspend.o -obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP) += smp.o spinlock.o diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index d8faf79a0a1..baca7f2fbd8 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -15,7 +15,6 @@ * This does not handle HOTPLUG_CPU yet. */ #include -#include #include #include @@ -36,8 +35,6 @@ #include "xen-ops.h" #include "mmu.h" -static void __cpuinit xen_init_lock_cpu(int cpu); - cpumask_t xen_cpu_initialized_map; static DEFINE_PER_CPU(int, resched_irq); @@ -419,170 +416,6 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -struct xen_spinlock { - unsigned char lock; /* 0 -> free; 1 -> locked */ - unsigned short spinners; /* count of waiting cpus */ -}; - -static int xen_spin_is_locked(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - - return xl->lock != 0; -} - -static int xen_spin_is_contended(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - - /* Not strictly true; this is only the count of contended - lock-takers entering the slow path. */ - return xl->spinners != 0; -} - -static int xen_spin_trylock(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - u8 old = 1; - - asm("xchgb %b0,%1" - : "+q" (old), "+m" (xl->lock) : : "memory"); - - return old == 0; -} - -static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; -static DEFINE_PER_CPU(struct xen_spinlock *, lock_spinners); - -static inline void spinning_lock(struct xen_spinlock *xl) -{ - __get_cpu_var(lock_spinners) = xl; - wmb(); /* set lock of interest before count */ - asm(LOCK_PREFIX " incw %0" - : "+m" (xl->spinners) : : "memory"); -} - -static inline void unspinning_lock(struct xen_spinlock *xl) -{ - asm(LOCK_PREFIX " decw %0" - : "+m" (xl->spinners) : : "memory"); - wmb(); /* decrement count before clearing lock */ - __get_cpu_var(lock_spinners) = NULL; -} - -static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - int irq = __get_cpu_var(lock_kicker_irq); - int ret; - - /* If kicker interrupts not initialized yet, just spin */ - if (irq == -1) - return 0; - - /* announce we're spinning */ - spinning_lock(xl); - - /* clear pending */ - xen_clear_irq_pending(irq); - - /* check again make sure it didn't become free while - we weren't looking */ - ret = xen_spin_trylock(lock); - if (ret) - goto out; - - /* block until irq becomes pending */ - xen_poll_irq(irq); - kstat_this_cpu.irqs[irq]++; - -out: - unspinning_lock(xl); - return ret; -} - -static void xen_spin_lock(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - int timeout; - u8 oldval; - - do { - timeout = 1 << 10; - - asm("1: xchgb %1,%0\n" - " testb %1,%1\n" - " jz 3f\n" - "2: rep;nop\n" - " cmpb $0,%0\n" - " je 1b\n" - " dec %2\n" - " jnz 2b\n" - "3:\n" - : "+m" (xl->lock), "=q" (oldval), "+r" (timeout) - : "1" (1) - : "memory"); - - } while (unlikely(oldval != 0 && !xen_spin_lock_slow(lock))); -} - -static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) -{ - int cpu; - - for_each_online_cpu(cpu) { - /* XXX should mix up next cpu selection */ - if (per_cpu(lock_spinners, cpu) == xl) { - xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); - break; - } - } -} - -static void xen_spin_unlock(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - - smp_wmb(); /* make sure no writes get moved after unlock */ - xl->lock = 0; /* release lock */ - - /* make sure unlock happens before kick */ - barrier(); - - if (unlikely(xl->spinners)) - xen_spin_unlock_slow(xl); -} - -static __cpuinit void xen_init_lock_cpu(int cpu) -{ - int irq; - const char *name; - - name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); - irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, - cpu, - xen_reschedule_interrupt, - IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, - name, - NULL); - - if (irq >= 0) { - disable_irq(irq); /* make sure it's never delivered */ - per_cpu(lock_kicker_irq, cpu) = irq; - } - - printk("cpu %d spinlock event irq %d\n", cpu, irq); -} - -static void __init xen_init_spinlocks(void) -{ - pv_lock_ops.spin_is_locked = xen_spin_is_locked; - pv_lock_ops.spin_is_contended = xen_spin_is_contended; - pv_lock_ops.spin_lock = xen_spin_lock; - pv_lock_ops.spin_trylock = xen_spin_trylock; - pv_lock_ops.spin_unlock = xen_spin_unlock; -} - static const struct smp_ops xen_smp_ops __initdata = { .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, .smp_prepare_cpus = xen_smp_prepare_cpus, diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c new file mode 100644 index 00000000000..8dc4d31da67 --- /dev/null +++ b/arch/x86/xen/spinlock.c @@ -0,0 +1,183 @@ +/* + * Split spinlock implementation out into its own file, so it can be + * compiled in a FTRACE-compatible way. + */ +#include +#include + +#include + +#include +#include + +#include "xen-ops.h" + +struct xen_spinlock { + unsigned char lock; /* 0 -> free; 1 -> locked */ + unsigned short spinners; /* count of waiting cpus */ +}; + +static int xen_spin_is_locked(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + + return xl->lock != 0; +} + +static int xen_spin_is_contended(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + + /* Not strictly true; this is only the count of contended + lock-takers entering the slow path. */ + return xl->spinners != 0; +} + +static int xen_spin_trylock(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + u8 old = 1; + + asm("xchgb %b0,%1" + : "+q" (old), "+m" (xl->lock) : : "memory"); + + return old == 0; +} + +static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; +static DEFINE_PER_CPU(struct xen_spinlock *, lock_spinners); + +static inline void spinning_lock(struct xen_spinlock *xl) +{ + __get_cpu_var(lock_spinners) = xl; + wmb(); /* set lock of interest before count */ + asm(LOCK_PREFIX " incw %0" + : "+m" (xl->spinners) : : "memory"); +} + +static inline void unspinning_lock(struct xen_spinlock *xl) +{ + asm(LOCK_PREFIX " decw %0" + : "+m" (xl->spinners) : : "memory"); + wmb(); /* decrement count before clearing lock */ + __get_cpu_var(lock_spinners) = NULL; +} + +static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + int irq = __get_cpu_var(lock_kicker_irq); + int ret; + + /* If kicker interrupts not initialized yet, just spin */ + if (irq == -1) + return 0; + + /* announce we're spinning */ + spinning_lock(xl); + + /* clear pending */ + xen_clear_irq_pending(irq); + + /* check again make sure it didn't become free while + we weren't looking */ + ret = xen_spin_trylock(lock); + if (ret) + goto out; + + /* block until irq becomes pending */ + xen_poll_irq(irq); + kstat_this_cpu.irqs[irq]++; + +out: + unspinning_lock(xl); + return ret; +} + +static void xen_spin_lock(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + int timeout; + u8 oldval; + + do { + timeout = 1 << 10; + + asm("1: xchgb %1,%0\n" + " testb %1,%1\n" + " jz 3f\n" + "2: rep;nop\n" + " cmpb $0,%0\n" + " je 1b\n" + " dec %2\n" + " jnz 2b\n" + "3:\n" + : "+m" (xl->lock), "=q" (oldval), "+r" (timeout) + : "1" (1) + : "memory"); + + } while (unlikely(oldval != 0 && !xen_spin_lock_slow(lock))); +} + +static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) +{ + int cpu; + + for_each_online_cpu(cpu) { + /* XXX should mix up next cpu selection */ + if (per_cpu(lock_spinners, cpu) == xl) { + xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); + break; + } + } +} + +static void xen_spin_unlock(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + + smp_wmb(); /* make sure no writes get moved after unlock */ + xl->lock = 0; /* release lock */ + + /* make sure unlock happens before kick */ + barrier(); + + if (unlikely(xl->spinners)) + xen_spin_unlock_slow(xl); +} + +static irqreturn_t dummy_handler(int irq, void *dev_id) +{ + BUG(); + return IRQ_HANDLED; +} + +void __cpuinit xen_init_lock_cpu(int cpu) +{ + int irq; + const char *name; + + name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); + irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, + cpu, + dummy_handler, + IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, + name, + NULL); + + if (irq >= 0) { + disable_irq(irq); /* make sure it's never delivered */ + per_cpu(lock_kicker_irq, cpu) = irq; + } + + printk("cpu %d spinlock event irq %d\n", cpu, irq); +} + +void __init xen_init_spinlocks(void) +{ + pv_lock_ops.spin_is_locked = xen_spin_is_locked; + pv_lock_ops.spin_is_contended = xen_spin_is_contended; + pv_lock_ops.spin_lock = xen_spin_lock; + pv_lock_ops.spin_trylock = xen_spin_trylock; + pv_lock_ops.spin_unlock = xen_spin_unlock; +} diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index dd3c23152a2..8847fb34f17 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -50,6 +50,9 @@ void __init xen_setup_vcpu_info_placement(void); #ifdef CONFIG_SMP void xen_smp_init(void); +void __init xen_init_spinlocks(void); +__cpuinit void xen_init_lock_cpu(int cpu); + extern cpumask_t xen_cpu_initialized_map; #else static inline void xen_smp_init(void) {} -- cgit v1.2.3 From e0a5a5d9b006fd441e61685a051fa85d52fb172c Mon Sep 17 00:00:00 2001 From: Alexander van Heukelum Date: Tue, 22 Jul 2008 18:14:16 +0200 Subject: x86, 64-bit, dwarf2: push pushes 8 bytes and popf pops 8 The CFI_ADJUST_CFA_OFFSET dwarf2 annotation of a push/popf pair in ret_from_fork wrongly used a value of 4. It should have been 8. Fix that. Signed-off-by: Alexander van Heukelum Cc: Andi Kleen Cc: heukelum@fastmail.fm Signed-off-by: Ingo Molnar --- arch/x86/kernel/entry_64.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 89434d43960..cf3a0b2d005 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -275,9 +275,9 @@ ENTRY(native_usergs_sysret64) ENTRY(ret_from_fork) CFI_DEFAULT_STACK push kernel_eflags(%rip) - CFI_ADJUST_CFA_OFFSET 4 + CFI_ADJUST_CFA_OFFSET 8 popf # reset kernel eflags - CFI_ADJUST_CFA_OFFSET -4 + CFI_ADJUST_CFA_OFFSET -8 call schedule_tail GET_THREAD_INFO(%rcx) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx) -- cgit v1.2.3 From 32f71aff77b6470d272f80ac28f43f9601c4d140 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 21 Jul 2008 00:52:49 +0100 Subject: x86: PIC, L-APIC and I/O APIC debug information Dump all the PIC, local APIC and I/O APIC information at the fs_initcall() level, which is after ACPI (if used) has initialised PCI information, making the point of invocation consistent across MP-table and ACPI platforms. Remove explicit calls to print_IO_APIC() from elsewhere. Make the interface of all the functions involved consistent between 32-bit and 64-bit versions and make them all static by default by the means of a New-and-Improved(TM) __apicdebuginit() macro. Note that like print_IO_APIC() all these only output anything if "apic=debug" has been passed to the kernel through the command line. Signed-off-by: Maciej W. Rozycki Cc: Chuck Ebbert Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_32.c | 29 +++++++++++++++++++---------- arch/x86/kernel/io_apic_64.c | 31 +++++++++++++++++++------------ arch/x86/pci/acpi.c | 5 ----- 3 files changed, 38 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index de9aa0e3a9c..d54455ec985 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -50,6 +50,8 @@ #include #include +#define __apicdebuginit(type) static type __init + int (*ioapic_renumber_irq)(int ioapic, int irq); atomic_t irq_mis_count; @@ -1345,7 +1347,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, ioapic_write_entry(apic, pin, entry); } -void __init print_IO_APIC(void) + +__apicdebuginit(void) print_IO_APIC(void) { int apic, i; union IO_APIC_reg_00 reg_00; @@ -1460,9 +1463,7 @@ void __init print_IO_APIC(void) return; } -#if 0 - -static void print_APIC_bitfield(int base) +__apicdebuginit(void) print_APIC_bitfield(int base) { unsigned int v; int i, j; @@ -1483,7 +1484,7 @@ static void print_APIC_bitfield(int base) } } -void /*__init*/ print_local_APIC(void *dummy) +__apicdebuginit(void) print_local_APIC(void *dummy) { unsigned int v, ver, maxlvt; @@ -1567,12 +1568,12 @@ void /*__init*/ print_local_APIC(void *dummy) printk("\n"); } -void print_all_local_APICs(void) +__apicdebuginit(void) print_all_local_APICs(void) { on_each_cpu(print_local_APIC, NULL, 1); } -void /*__init*/ print_PIC(void) +__apicdebuginit(void) print_PIC(void) { unsigned int v; unsigned long flags; @@ -1604,7 +1605,17 @@ void /*__init*/ print_PIC(void) printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); } -#endif /* 0 */ +__apicdebuginit(int) print_all_ICs(void) +{ + print_PIC(); + print_all_local_APICs(); + print_IO_APIC(); + + return 0; +} + +fs_initcall(print_all_ICs); + static void __init enable_IO_APIC(void) { @@ -2333,8 +2344,6 @@ void __init setup_IO_APIC(void) setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - if (!acpi_ioapic) - print_IO_APIC(); } /* diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 8269434d170..8cdcc4f287c 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -53,6 +53,8 @@ #include #include +#define __apicdebuginit(type) static type __init + struct irq_cfg { cpumask_t domain; cpumask_t old_domain; @@ -87,8 +89,6 @@ int first_system_vector = 0xfe; char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE}; -#define __apicdebuginit __init - int sis_apic_bug; /* not actually supported, dummy for compile */ static int no_timer_check; @@ -965,7 +965,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, ioapic_write_entry(apic, pin, entry); } -void __apicdebuginit print_IO_APIC(void) + +__apicdebuginit(void) print_IO_APIC(void) { int apic, i; union IO_APIC_reg_00 reg_00; @@ -1059,9 +1060,7 @@ void __apicdebuginit print_IO_APIC(void) return; } -#if 0 - -static __apicdebuginit void print_APIC_bitfield (int base) +__apicdebuginit(void) print_APIC_bitfield(int base) { unsigned int v; int i, j; @@ -1082,7 +1081,7 @@ static __apicdebuginit void print_APIC_bitfield (int base) } } -void __apicdebuginit print_local_APIC(void * dummy) +__apicdebuginit(void) print_local_APIC(void *dummy) { unsigned int v, ver, maxlvt; @@ -1159,12 +1158,12 @@ void __apicdebuginit print_local_APIC(void * dummy) printk("\n"); } -void print_all_local_APICs (void) +__apicdebuginit(void) print_all_local_APICs(void) { on_each_cpu(print_local_APIC, NULL, 1); } -void __apicdebuginit print_PIC(void) +__apicdebuginit(void) print_PIC(void) { unsigned int v; unsigned long flags; @@ -1196,7 +1195,17 @@ void __apicdebuginit print_PIC(void) printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); } -#endif /* 0 */ +__apicdebuginit(int) print_all_ICs(void) +{ + print_PIC(); + print_all_local_APICs(); + print_IO_APIC(); + + return 0; +} + +fs_initcall(print_all_ICs); + void __init enable_IO_APIC(void) { @@ -1849,8 +1858,6 @@ void __init setup_IO_APIC(void) setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - if (!acpi_ioapic) - print_IO_APIC(); } struct sysfs_ioapic_data { diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 19af06927fb..1d88d2b3977 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -250,10 +250,5 @@ int __init pci_acpi_init(void) acpi_pci_irq_enable(dev); } -#ifdef CONFIG_X86_IO_APIC - if (acpi_ioapic) - print_IO_APIC(); -#endif - return 0; } -- cgit v1.2.3 From 510b37258dfd61693ca6c039865c78bd996e3718 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 22 Jul 2008 13:20:22 -0700 Subject: x86: move declaring x2apic_extra_bits it is for uv only Signed-off-by: Yinghai Lu Cc: Jack Steiner Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_phys.c | 2 -- arch/x86/kernel/genx2apic_uv_x.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index f35a3bf3a9e..3229c68aedd 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -10,8 +10,6 @@ #include #include -DEFINE_PER_CPU(int, x2apic_extra_bits); - static int x2apic_phys; static int set_x2apic_phys_mode(char *arg) diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 14a9772778e..169388c4cce 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -26,6 +26,8 @@ #include #include +DEFINE_PER_CPU(int, x2apic_extra_bits); + static enum uv_system_type uv_system_type; static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -- cgit v1.2.3 From 36a028de785c6e6f15ac84f8b3b087b89137ea26 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 24 Jul 2008 13:52:28 +0200 Subject: x86: apic unification - merge down lapic_get_maxlvt No code change on binary level. Signed-off-by: Cyrill Gorcunov Cc: macro@linux-mips.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 8 ++++++-- arch/x86/kernel/apic_64.c | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d6c89835837..447dd8c5c0e 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -193,9 +193,13 @@ int get_physical_broadcast(void) */ int lapic_get_maxlvt(void) { - unsigned int v = apic_read(APIC_LVR); + unsigned int v; - /* 82489DXs do not report # of LVT entries. */ + v = apic_read(APIC_LVR); + /* + * - we always have APIC integrated on 64bit mode + * - 82489DXs do not report # of LVT entries + */ return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 7f1f030da7e..4fa2a8620c2 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -158,11 +158,14 @@ void __cpuinit enable_NMI_through_LVT0(void) */ int lapic_get_maxlvt(void) { - unsigned int v, maxlvt; + unsigned int v; v = apic_read(APIC_LVR); - maxlvt = GET_APIC_MAXLVT(v); - return maxlvt; + /* + * - we always have APIC integrated on 64bit mode + * - 82489DXs do not report # of LVT entries + */ + return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } /* -- cgit v1.2.3 From d4c63ec060f3315653c0ae5bc3a7fe2419a2282f Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 24 Jul 2008 13:52:29 +0200 Subject: x86: apic unification - merge down enable_NMI_through_LVT0 No code change on binary level. Signed-off-by: Cyrill Gorcunov Cc: macro@linux-mips.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 8 ++++++-- arch/x86/kernel/apic_64.c | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 447dd8c5c0e..01708f128ee 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -172,11 +172,15 @@ u32 safe_apic_wait_icr_idle(void) */ void __cpuinit enable_NMI_through_LVT0(void) { - unsigned int v = APIC_DM_NMI; + unsigned int v; + + /* unmask and set to NMI */ + v = APIC_DM_NMI; - /* Level triggered for 82489DX */ + /* Level triggered for 82489DX (32bit mode) */ if (!lapic_is_integrated()) v |= APIC_LVT_LEVEL_TRIGGER; + apic_write(APIC_LVT0, v); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 4fa2a8620c2..7615b4b9c3f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -150,6 +150,11 @@ void __cpuinit enable_NMI_through_LVT0(void) /* unmask and set to NMI */ v = APIC_DM_NMI; + + /* Level triggered for 82489DX (32bit mode) */ + if (!lapic_is_integrated()) + v |= APIC_LVT_LEVEL_TRIGGER; + apic_write(APIC_LVT0, v); } -- cgit v1.2.3 From 4fe702c7e401f912c0edd294af6e37c02f451bbb Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 10:19:27 +0530 Subject: X86_32: declare pt_regs_access as unsigned long Fixed pt_regs_access to unsigned long as per X86_64 Signed-off-by: Jaswinder Singh --- arch/x86/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e37dccce85d..fc3e8dcd9da 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -69,7 +69,7 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 -static long *pt_regs_access(struct pt_regs *regs, unsigned long regno) +static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); regno >>= 2; -- cgit v1.2.3 From f86c99853b22576ee8dc4fa27ff6f3c0c7ce0ef8 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 10:52:53 +0530 Subject: X86_SMP: smpboot.c declare idle_thread_array and smp_b_stepping as static Signed-off-by: Jaswinder Singh --- arch/x86/kernel/smpboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 4b53a647bc0..a9331a42f76 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -88,7 +88,7 @@ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) #else -struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; +static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; #define get_idle_for_cpu(x) (idle_thread_array[(x)]) #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #endif @@ -129,7 +129,7 @@ static int boot_cpu_logical_apicid; static cpumask_t cpu_sibling_setup_map; /* Set if we find a B stepping CPU */ -int __cpuinitdata smp_b_stepping; +static int __cpuinitdata smp_b_stepping; #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) -- cgit v1.2.3 From 2907829cd0ffdef69083985ba28cf1cf3857c681 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 11:05:56 +0530 Subject: X86_SMP: ipi.c declare functions before they get used move upwards for __send_IPI_shortcut and send_IPI_mask_bitmask Signed-off-by: Jaswinder Singh --- arch/x86/kernel/ipi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 3f7537b669d..f1c688e46f3 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -20,6 +20,8 @@ #ifdef CONFIG_X86_32 #include +#include + /* * the following functions deal with sending IPIs between CPUs. * @@ -147,7 +149,6 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector) } /* must come after the send_IPI functions above for inlining */ -#include static int convert_apicid_to_cpu(int apic_id) { int i; -- cgit v1.2.3 From 3c9339049df5cc3a468c11de6c4101a1ea8c3d83 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 25 Jul 2008 11:32:36 +0200 Subject: x86: fix ds.c build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/ds.c: In function ‘ds_allocate_buffer': arch/x86/kernel/ds.c:339: error: implicit declaration of function ‘PAGE_ALIGN' Signed-off-by: Ingo Molnar --- arch/x86/kernel/ds.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 24a323c9599..ab21c270bfa 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -29,6 +29,7 @@ #include #include #include +#include /* -- cgit v1.2.3 From 286f571837ba9d67625afd015366d79345abb414 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:46 +0200 Subject: x86: apic_*.c: add description to AMD's extended LVT functions Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 3 +++ arch/x86/kernel/apic_64.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d6c89835837..fad94b0decc 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -646,6 +646,9 @@ int setup_profiling_timer(unsigned int multiplier) * * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and * MCE interrupts are supported. Thus MCE offset must be set to 0. + * + * If mask=1, the LVT entry does not generate interrupts while mask=0 + * enables the vector. See also the BKDGs. */ #define APIC_EILVT_LVTOFF_MCE 0 diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 7f1f030da7e..42bf69f8bc8 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -205,6 +205,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) * * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and * MCE interrupts are supported. Thus MCE offset must be set to 0. + * + * If mask=1, the LVT entry does not generate interrupts while mask=0 + * enables the vector. See also the BKDGs. */ #define APIC_EILVT_LVTOFF_MCE 0 -- cgit v1.2.3 From 12f2b2610e812627acf338aaf043fef20bb726ca Mon Sep 17 00:00:00 2001 From: Barry Kasindorf Date: Tue, 22 Jul 2008 21:08:47 +0200 Subject: oprofile: Add support for AMD Family 11h This patch add support for AMD Family 11h CPUs. Signed-off-by: Barry Kasindorf Signed-off-by: Robert Richter Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 3f90289410e..33db99ab90c 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -436,6 +436,10 @@ int __init op_nmi_init(struct oprofile_operations *ops) model = &op_athlon_spec; cpu_type = "x86-64/family10"; break; + case 0x11: + model = &op_athlon_spec; + cpu_type = "x86-64/family11h"; + break; } break; -- cgit v1.2.3 From adf5ec0bca553b763a6b9baed2677a4c7470025b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:48 +0200 Subject: x86/oprofile: introduce model specific init/exit functions This patch implements model specific OProfile init/exit functions for x86 CPUs. Though there is more rework needed at the initialization code, this new introduced functions allow it to keep model specific code in the corresponding op_model_*.c files. The function interface is the same as for oprofile_arch_init/exit(). Signed-off-by: Robert Richter Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 11 ++++++++++- arch/x86/oprofile/op_model_athlon.c | 18 +++++++++++++++--- arch/x86/oprofile/op_x86_model.h | 2 ++ 3 files changed, 27 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 33db99ab90c..75e889156f2 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -1,10 +1,11 @@ /** * @file nmi_int.c * - * @remark Copyright 2002 OProfile authors + * @remark Copyright 2002-2008 OProfile authors * @remark Read the file COPYING * * @author John Levon + * @author Robert Richter */ #include @@ -411,6 +412,7 @@ int __init op_nmi_init(struct oprofile_operations *ops) __u8 vendor = boot_cpu_data.x86_vendor; __u8 family = boot_cpu_data.x86; char *cpu_type; + int ret = 0; if (!cpu_has_apic) return -ENODEV; @@ -466,6 +468,11 @@ int __init op_nmi_init(struct oprofile_operations *ops) return -ENODEV; } + if (model->init) + ret = model->init(ops); + if (ret) + return ret; + init_sysfs(); using_nmi = 1; ops->create_files = nmi_create_files; @@ -482,4 +489,6 @@ void op_nmi_exit(void) { if (using_nmi) exit_sysfs(); + if (model->exit) + model->exit(); } diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 3d534879a9d..dd8b1dcd163 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -1,14 +1,15 @@ /* - * @file op_model_athlon.h + * @file op_model_athlon.c * athlon / K7 / K8 / Family 10h model-specific MSR operations * - * @remark Copyright 2002 OProfile authors + * @remark Copyright 2002-2008 OProfile authors * @remark Read the file COPYING * * @author John Levon * @author Philippe Elie * @author Graydon Hoare - */ + * @author Robert Richter +*/ #include #include @@ -178,7 +179,18 @@ static void athlon_shutdown(struct op_msrs const * const msrs) } } +static int op_amd_init(struct oprofile_operations *ops) +{ + return 0; +} + +static void op_amd_exit(void) +{ +} + struct op_x86_model_spec const op_athlon_spec = { + .init = op_amd_init, + .exit = op_amd_exit, .num_counters = NUM_COUNTERS, .num_controls = NUM_CONTROLS, .fill_in_addresses = &athlon_fill_in_addresses, diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index 45b605fa71d..ee9ca96253f 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -32,6 +32,8 @@ struct pt_regs; * various x86 CPU models' perfctr support. */ struct op_x86_model_spec { + int (*init)(struct oprofile_operations *ops); + void (*exit)(void); unsigned int const num_counters; unsigned int const num_controls; void (*fill_in_addresses)(struct op_msrs * const msrs); -- cgit v1.2.3 From dfa154289701ed315909b4e371a0381c52c8bdc9 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:49 +0200 Subject: x86/oprofile: Minor changes in op_model_athlon.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index dd8b1dcd163..d25d7f19503 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -45,6 +45,8 @@ static unsigned long reset_value[NUM_COUNTERS]; +/* functions for op_athlon_spec */ + static void athlon_fill_in_addresses(struct op_msrs * const msrs) { int i; -- cgit v1.2.3 From 6657fe4f5650ff7174d418d4bfa50c4640e81a2b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:50 +0200 Subject: x86/oprofile: renaming athlon_*() into op_amd_*() These functions contain code for all AMD CPUs. The new names fit better. Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 8 ++++---- arch/x86/oprofile/op_model_athlon.c | 28 ++++++++++++++-------------- arch/x86/oprofile/op_x86_model.h | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 75e889156f2..b29819313f2 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -425,21 +425,21 @@ int __init op_nmi_init(struct oprofile_operations *ops) default: return -ENODEV; case 6: - model = &op_athlon_spec; + model = &op_amd_spec; cpu_type = "i386/athlon"; break; case 0xf: - model = &op_athlon_spec; + model = &op_amd_spec; /* Actually it could be i386/hammer too, but give user space an consistent name. */ cpu_type = "x86-64/hammer"; break; case 0x10: - model = &op_athlon_spec; + model = &op_amd_spec; cpu_type = "x86-64/family10"; break; case 0x11: - model = &op_athlon_spec; + model = &op_amd_spec; cpu_type = "x86-64/family11h"; break; } diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index d25d7f19503..40ecb020c7d 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -45,9 +45,9 @@ static unsigned long reset_value[NUM_COUNTERS]; -/* functions for op_athlon_spec */ +/* functions for op_amd_spec */ -static void athlon_fill_in_addresses(struct op_msrs * const msrs) +static void op_amd_fill_in_addresses(struct op_msrs * const msrs) { int i; @@ -67,7 +67,7 @@ static void athlon_fill_in_addresses(struct op_msrs * const msrs) } -static void athlon_setup_ctrs(struct op_msrs const * const msrs) +static void op_amd_setup_ctrs(struct op_msrs const * const msrs) { unsigned int low, high; int i; @@ -116,7 +116,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs) } -static int athlon_check_ctrs(struct pt_regs * const regs, +static int op_amd_check_ctrs(struct pt_regs * const regs, struct op_msrs const * const msrs) { unsigned int low, high; @@ -137,7 +137,7 @@ static int athlon_check_ctrs(struct pt_regs * const regs, } -static void athlon_start(struct op_msrs const * const msrs) +static void op_amd_start(struct op_msrs const * const msrs) { unsigned int low, high; int i; @@ -151,7 +151,7 @@ static void athlon_start(struct op_msrs const * const msrs) } -static void athlon_stop(struct op_msrs const * const msrs) +static void op_amd_stop(struct op_msrs const * const msrs) { unsigned int low, high; int i; @@ -167,7 +167,7 @@ static void athlon_stop(struct op_msrs const * const msrs) } } -static void athlon_shutdown(struct op_msrs const * const msrs) +static void op_amd_shutdown(struct op_msrs const * const msrs) { int i; @@ -190,15 +190,15 @@ static void op_amd_exit(void) { } -struct op_x86_model_spec const op_athlon_spec = { +struct op_x86_model_spec const op_amd_spec = { .init = op_amd_init, .exit = op_amd_exit, .num_counters = NUM_COUNTERS, .num_controls = NUM_CONTROLS, - .fill_in_addresses = &athlon_fill_in_addresses, - .setup_ctrs = &athlon_setup_ctrs, - .check_ctrs = &athlon_check_ctrs, - .start = &athlon_start, - .stop = &athlon_stop, - .shutdown = &athlon_shutdown + .fill_in_addresses = &op_amd_fill_in_addresses, + .setup_ctrs = &op_amd_setup_ctrs, + .check_ctrs = &op_amd_check_ctrs, + .start = &op_amd_start, + .stop = &op_amd_stop, + .shutdown = &op_amd_shutdown }; diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index ee9ca96253f..05a0261ba0c 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -48,6 +48,6 @@ struct op_x86_model_spec { extern struct op_x86_model_spec const op_ppro_spec; extern struct op_x86_model_spec const op_p4_spec; extern struct op_x86_model_spec const op_p4_ht2_spec; -extern struct op_x86_model_spec const op_athlon_spec; +extern struct op_x86_model_spec const op_amd_spec; #endif /* OP_X86_MODEL_H */ -- cgit v1.2.3 From 56784f11df473b4c1d9d0e37777fd7c0b77b6bca Mon Sep 17 00:00:00 2001 From: Barry Kasindorf Date: Tue, 22 Jul 2008 21:08:55 +0200 Subject: x86/oprofile: add IBS support for AMD CPUs, model specific code This patchset supports the new profiling hardware available in the latest AMD CPUs in the oProfile driver. Signed-off-by: Barry Kasindorf Signed-off-by: Robert Richter Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 257 ++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 40ecb020c7d..229e0b4e21e 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -9,9 +9,13 @@ * @author Philippe Elie * @author Graydon Hoare * @author Robert Richter + * @author Barry Kasindorf */ #include +#include +#include + #include #include #include @@ -43,7 +47,83 @@ #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) +#define IBS_FETCH_CTL_HIGH_MASK 0xFFFFFFFF +/* high dword bit IbsFetchCtl[bit 49] */ +#define IBS_FETCH_VALID_BIT (1UL << 17) +/* high dword bit IbsFetchCtl[bit 52] */ +#define IBS_FETCH_PHY_ADDR_VALID_BIT (1UL << 20) +/* high dword bit IbsFetchCtl[bit 48] */ +#define IBS_FETCH_ENABLE (1UL << 16) + +#define IBS_FETCH_CTL_CNT_MASK 0x00000000FFFF0000UL +#define IBS_FETCH_CTL_MAX_CNT_MASK 0x000000000000FFFFUL + +/*IbsOpCtl masks/bits */ +#define IBS_OP_VALID_BIT (1ULL<<18) /* IbsOpCtl[bit18] */ +#define IBS_OP_ENABLE (1ULL<<17) /* IBS_OP_ENABLE[bit17]*/ + +/* Codes used in cpu_buffer.c */ +#define IBS_FETCH_BEGIN 3 +#define IBS_OP_BEGIN 4 + +/*IbsOpData3 masks */ +#define IBS_CTL_LVT_OFFSET_VALID_BIT (1ULL<<8) + +/*PCI Extended Configuration Constants */ +/* MSR to set the IBS control register APIC LVT offset */ +#define IBS_LVT_OFFSET_PCI 0x1CC + +struct ibs_fetch_sample { + /* MSRC001_1031 IBS Fetch Linear Address Register */ + unsigned int ibs_fetch_lin_addr_low; + unsigned int ibs_fetch_lin_addr_high; + /* MSRC001_1030 IBS Fetch Control Register */ + unsigned int ibs_fetch_ctl_low; + unsigned int ibs_fetch_ctl_high; + /* MSRC001_1032 IBS Fetch Physical Address Register */ + unsigned int ibs_fetch_phys_addr_low; + unsigned int ibs_fetch_phys_addr_high; +}; + +struct ibs_op_sample { + /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */ + unsigned int ibs_op_rip_low; + unsigned int ibs_op_rip_high; + /* MSRC001_1035 IBS Op Data Register */ + unsigned int ibs_op_data1_low; + unsigned int ibs_op_data1_high; + /* MSRC001_1036 IBS Op Data 2 Register */ + unsigned int ibs_op_data2_low; + unsigned int ibs_op_data2_high; + /* MSRC001_1037 IBS Op Data 3 Register */ + unsigned int ibs_op_data3_low; + unsigned int ibs_op_data3_high; + /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */ + unsigned int ibs_dc_linear_low; + unsigned int ibs_dc_linear_high; + /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */ + unsigned int ibs_dc_phys_low; + unsigned int ibs_dc_phys_high; +}; + +/* + * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+ +*/ +static void clear_ibs_nmi(void); + static unsigned long reset_value[NUM_COUNTERS]; +static int ibs_allowed; /* AMD Family10h and later */ + +struct op_ibs_config { + unsigned long op_enabled; + unsigned long fetch_enabled; + unsigned long max_cnt_fetch; + unsigned long max_cnt_op; + unsigned long rand_en; + unsigned long dispatched_ops; +}; + +static struct op_ibs_config ibs_config; /* functions for op_amd_spec */ @@ -121,6 +201,8 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, { unsigned int low, high; int i; + struct ibs_fetch_sample ibs_fetch; + struct ibs_op_sample ibs_op; for (i = 0 ; i < NUM_COUNTERS; ++i) { if (!reset_value[i]) @@ -132,6 +214,65 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } + /*If AMD and IBS is available */ + if (ibs_allowed && ibs_config.fetch_enabled) { + rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); + if (high & IBS_FETCH_VALID_BIT) { + ibs_fetch.ibs_fetch_ctl_high = high; + ibs_fetch.ibs_fetch_ctl_low = low; + rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); + ibs_fetch.ibs_fetch_lin_addr_high = high; + ibs_fetch.ibs_fetch_lin_addr_low = low; + rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high); + ibs_fetch.ibs_fetch_phys_addr_high = high; + ibs_fetch.ibs_fetch_phys_addr_low = low; + + oprofile_add_ibs_sample(regs, + (unsigned int *)&ibs_fetch, + IBS_FETCH_BEGIN); + + /*reenable the IRQ */ + rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); + high &= ~(IBS_FETCH_VALID_BIT); + high |= IBS_FETCH_ENABLE; + low &= IBS_FETCH_CTL_MAX_CNT_MASK; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + } + + if (ibs_allowed && ibs_config.op_enabled) { + rdmsr(MSR_AMD64_IBSOPCTL, low, high); + if (low & IBS_OP_VALID_BIT) { + rdmsr(MSR_AMD64_IBSOPRIP, low, high); + ibs_op.ibs_op_rip_low = low; + ibs_op.ibs_op_rip_high = high; + rdmsr(MSR_AMD64_IBSOPDATA, low, high); + ibs_op.ibs_op_data1_low = low; + ibs_op.ibs_op_data1_high = high; + rdmsr(MSR_AMD64_IBSOPDATA2, low, high); + ibs_op.ibs_op_data2_low = low; + ibs_op.ibs_op_data2_high = high; + rdmsr(MSR_AMD64_IBSOPDATA3, low, high); + ibs_op.ibs_op_data3_low = low; + ibs_op.ibs_op_data3_high = high; + rdmsr(MSR_AMD64_IBSDCLINAD, low, high); + ibs_op.ibs_dc_linear_low = low; + ibs_op.ibs_dc_linear_high = high; + rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high); + ibs_op.ibs_dc_phys_low = low; + ibs_op.ibs_dc_phys_high = high; + + /* reenable the IRQ */ + oprofile_add_ibs_sample(regs, + (unsigned int *)&ibs_op, + IBS_OP_BEGIN); + rdmsr(MSR_AMD64_IBSOPCTL, low, high); + low &= ~(IBS_OP_VALID_BIT); + low |= IBS_OP_ENABLE; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } + } + /* See op_model_ppro.c */ return 1; } @@ -148,6 +289,17 @@ static void op_amd_start(struct op_msrs const * const msrs) CTRL_WRITE(low, high, msrs, i); } } + if (ibs_allowed && ibs_config.fetch_enabled) { + low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; + high = IBS_FETCH_ENABLE; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + + if (ibs_allowed && ibs_config.op_enabled) { + low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_ENABLE; + high = 0; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } } @@ -165,6 +317,18 @@ static void op_amd_stop(struct op_msrs const * const msrs) CTRL_SET_INACTIVE(low); CTRL_WRITE(low, high, msrs, i); } + + if (ibs_allowed && ibs_config.fetch_enabled) { + low = 0; /* clear max count and enable */ + high = 0; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + + if (ibs_allowed && ibs_config.op_enabled) { + low = 0; /* clear max count and enable */ + high = 0; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } } static void op_amd_shutdown(struct op_msrs const * const msrs) @@ -181,6 +345,99 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } +static inline void apic_init_ibs_nmi_per_cpu(void *arg) +{ + setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); +} + +static inline void apic_clear_ibs_nmi_per_cpu(void *arg) +{ + setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); +} + +/* + * initialize the APIC for the IBS interrupts + * if needed on AMD Family10h rev B0 and later + */ +static void setup_ibs(void) +{ + struct pci_dev *gh_device = NULL; + u32 low, high; + u8 vector; + + ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); + + if (!ibs_allowed) + return; + + /* This gets the APIC_EILVT_LVTOFF_IBS value */ + vector = setup_APIC_eilvt_ibs(0, 0, 1); + + /*see if the IBS control register is already set correctly*/ + /*remove this when we know for sure it is done + in the kernel init*/ + rdmsr(MSR_AMD64_IBSCTL, low, high); + if ((low & (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) != + (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) { + + /**** Be sure to run loop until NULL is returned to + decrement reference count on any pci_dev structures + returned ****/ + while ((gh_device = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_10H_NB_MISC, gh_device)) + != NULL) { + /* This code may change if we can find a proper + * way to get at the PCI extended config space */ + pci_write_config_dword( + gh_device, IBS_LVT_OFFSET_PCI, + (vector | IBS_CTL_LVT_OFFSET_VALID_BIT)); + } + } + on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1, 1); +} + + +/* + * unitialize the APIC for the IBS interrupts if needed on AMD Family10h + * rev B0 and later */ +static void clear_ibs_nmi(void) +{ + if (ibs_allowed) + on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1, 1); +} + +static void setup_ibs_files(struct super_block *sb, struct dentry *root) +{ + char buf[12]; + struct dentry *dir; + + if (!ibs_allowed) + return; + + /* setup some reasonable defaults */ + ibs_config.max_cnt_fetch = 250000; + ibs_config.fetch_enabled = 0; + ibs_config.max_cnt_op = 250000; + ibs_config.op_enabled = 0; + ibs_config.dispatched_ops = 1; + snprintf(buf, sizeof(buf), "ibs_fetch"); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "rand_enable", + &ibs_config.rand_en); + oprofilefs_create_ulong(sb, dir, "enable", + &ibs_config.fetch_enabled); + oprofilefs_create_ulong(sb, dir, "max_count", + &ibs_config.max_cnt_fetch); + snprintf(buf, sizeof(buf), "ibs_uops"); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "enable", + &ibs_config.op_enabled); + oprofilefs_create_ulong(sb, dir, "max_count", + &ibs_config.max_cnt_op); + oprofilefs_create_ulong(sb, dir, "dispatched_ops", + &ibs_config.dispatched_ops); +} + static int op_amd_init(struct oprofile_operations *ops) { return 0; -- cgit v1.2.3 From 7939d2bf7e30353d40d14f967b7fe2b2a7be5bd9 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:56 +0200 Subject: x86/oprofile: separating the IBS handler Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 45 +++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 229e0b4e21e..a2c8e2e372b 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -195,27 +195,18 @@ static void op_amd_setup_ctrs(struct op_msrs const * const msrs) } } - -static int op_amd_check_ctrs(struct pt_regs * const regs, - struct op_msrs const * const msrs) +static inline int +op_amd_handle_ibs(struct pt_regs * const regs, + struct op_msrs const * const msrs) { unsigned int low, high; - int i; struct ibs_fetch_sample ibs_fetch; struct ibs_op_sample ibs_op; - for (i = 0 ; i < NUM_COUNTERS; ++i) { - if (!reset_value[i]) - continue; - CTR_READ(low, high, msrs, i); - if (CTR_OVERFLOWED(low)) { - oprofile_add_sample(regs, i); - CTR_WRITE(reset_value[i], msrs, i); - } - } + if (!ibs_allowed) + return 1; - /*If AMD and IBS is available */ - if (ibs_allowed && ibs_config.fetch_enabled) { + if (ibs_config.fetch_enabled) { rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); if (high & IBS_FETCH_VALID_BIT) { ibs_fetch.ibs_fetch_ctl_high = high; @@ -240,7 +231,7 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } - if (ibs_allowed && ibs_config.op_enabled) { + if (ibs_config.op_enabled) { rdmsr(MSR_AMD64_IBSOPCTL, low, high); if (low & IBS_OP_VALID_BIT) { rdmsr(MSR_AMD64_IBSOPRIP, low, high); @@ -273,10 +264,30 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } - /* See op_model_ppro.c */ return 1; } +static int op_amd_check_ctrs(struct pt_regs * const regs, + struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + for (i = 0 ; i < NUM_COUNTERS; ++i) { + if (!reset_value[i]) + continue; + CTR_READ(low, high, msrs, i); + if (CTR_OVERFLOWED(low)) { + oprofile_add_sample(regs, i); + CTR_WRITE(reset_value[i], msrs, i); + } + } + + op_amd_handle_ibs(regs, msrs); + + /* See op_model_ppro.c */ + return 1; +} static void op_amd_start(struct op_msrs const * const msrs) { -- cgit v1.2.3 From 7d77f2dcae37cf232950cd0181fb0a2cddb18130 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:57 +0200 Subject: OProfile: change IBS interrupt initialization Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 84 ++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index a2c8e2e372b..90193b1538a 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -356,9 +356,11 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } +static u8 ibs_eilvt_off; + static inline void apic_init_ibs_nmi_per_cpu(void *arg) { - setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); + ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); } static inline void apic_clear_ibs_nmi_per_cpu(void *arg) @@ -366,45 +368,67 @@ static inline void apic_clear_ibs_nmi_per_cpu(void *arg) setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); } +static int pfm_amd64_setup_eilvt(void) +{ +#define IBSCTL_LVTOFFSETVAL (1 << 8) +#define IBSCTL 0x1cc + struct pci_dev *cpu_cfg; + int nodes; + u32 value = 0; + + /* per CPU setup */ + on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 0, 1); + + nodes = 0; + cpu_cfg = NULL; + do { + cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_10H_NB_MISC, + cpu_cfg); + if (!cpu_cfg) + break; + ++nodes; + pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off + | IBSCTL_LVTOFFSETVAL); + pci_read_config_dword(cpu_cfg, IBSCTL, &value); + if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) { + printk(KERN_DEBUG "Failed to setup IBS LVT offset, " + "IBSCTL = 0x%08x", value); + return 1; + } + } while (1); + + if (!nodes) { + printk(KERN_DEBUG "No CPU node configured for IBS"); + return 1; + } + +#ifdef CONFIG_NUMA + /* Sanity check */ + /* Works only for 64bit with proper numa implementation. */ + if (nodes != num_possible_nodes()) { + printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, " + "found: %d, expected %d", + nodes, num_possible_nodes()); + return 1; + } +#endif + return 0; +} + /* * initialize the APIC for the IBS interrupts - * if needed on AMD Family10h rev B0 and later + * if available (AMD Family10h rev B0 and later) */ static void setup_ibs(void) { - struct pci_dev *gh_device = NULL; - u32 low, high; - u8 vector; - ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); if (!ibs_allowed) return; - /* This gets the APIC_EILVT_LVTOFF_IBS value */ - vector = setup_APIC_eilvt_ibs(0, 0, 1); - - /*see if the IBS control register is already set correctly*/ - /*remove this when we know for sure it is done - in the kernel init*/ - rdmsr(MSR_AMD64_IBSCTL, low, high); - if ((low & (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) != - (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) { - - /**** Be sure to run loop until NULL is returned to - decrement reference count on any pci_dev structures - returned ****/ - while ((gh_device = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_10H_NB_MISC, gh_device)) - != NULL) { - /* This code may change if we can find a proper - * way to get at the PCI extended config space */ - pci_write_config_dword( - gh_device, IBS_LVT_OFFSET_PCI, - (vector | IBS_CTL_LVT_OFFSET_VALID_BIT)); - } - } - on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1, 1); + if (pfm_amd64_setup_eilvt()) + ibs_allowed = 0; } -- cgit v1.2.3 From 90645700ef8393cd9cdc02d83da36726fc88f49e Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:58 +0200 Subject: OProfile: Fix build error in op_model_athlon.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 90193b1538a..284c45661ed 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -73,6 +73,11 @@ /* MSR to set the IBS control register APIC LVT offset */ #define IBS_LVT_OFFSET_PCI 0x1CC +/* The function interface needs to be fixed, something like add + data. Should then be added to linux/oprofile.h. */ +extern void oprofile_add_ibs_sample(struct pt_regs *const regs, + unsigned int * const ibs_sample, u8 code); + struct ibs_fetch_sample { /* MSRC001_1031 IBS Fetch Linear Address Register */ unsigned int ibs_fetch_lin_addr_low; -- cgit v1.2.3 From ebb535de267386f659e0348185b1e361dbba3b59 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:59 +0200 Subject: OProfile: on_each_cpu(): kill unused retry parameter Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 284c45661ed..ce732362dbb 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -382,7 +382,7 @@ static int pfm_amd64_setup_eilvt(void) u32 value = 0; /* per CPU setup */ - on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 0, 1); + on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1); nodes = 0; cpu_cfg = NULL; @@ -443,7 +443,7 @@ static void setup_ibs(void) static void clear_ibs_nmi(void) { if (ibs_allowed) - on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1, 1); + on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); } static void setup_ibs_files(struct super_block *sb, struct dentry *root) -- cgit v1.2.3 From fc2bd7345b4e006a34c2ea3711d8c6b83cba50f7 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:00 +0200 Subject: OProfile: fix setup_ibs_files() function interface Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index ce732362dbb..2650b12a0c5 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -446,13 +446,13 @@ static void clear_ibs_nmi(void) on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); } -static void setup_ibs_files(struct super_block *sb, struct dentry *root) +static int setup_ibs_files(struct super_block * sb, struct dentry * root) { char buf[12]; struct dentry *dir; if (!ibs_allowed) - return; + return 0; /* setup some reasonable defaults */ ibs_config.max_cnt_fetch = 250000; @@ -476,6 +476,8 @@ static void setup_ibs_files(struct super_block *sb, struct dentry *root) &ibs_config.max_cnt_op); oprofilefs_create_ulong(sb, dir, "dispatched_ops", &ibs_config.dispatched_ops); + + return 0; } static int op_amd_init(struct oprofile_operations *ops) -- cgit v1.2.3 From 270d3e1a10e6ef85d5a085377e01d91dbcbe3726 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:01 +0200 Subject: OProfile: enable IBS for AMD CPUs Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 14 ++++++++------ arch/x86/oprofile/op_model_athlon.c | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index b29819313f2..287513a0981 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -468,6 +468,14 @@ int __init op_nmi_init(struct oprofile_operations *ops) return -ENODEV; } + /* default values, can be overwritten by model */ + ops->create_files = nmi_create_files; + ops->setup = nmi_setup; + ops->shutdown = nmi_shutdown; + ops->start = nmi_start; + ops->stop = nmi_stop; + ops->cpu_type = cpu_type; + if (model->init) ret = model->init(ops); if (ret) @@ -475,12 +483,6 @@ int __init op_nmi_init(struct oprofile_operations *ops) init_sysfs(); using_nmi = 1; - ops->create_files = nmi_create_files; - ops->setup = nmi_setup; - ops->shutdown = nmi_shutdown; - ops->start = nmi_start; - ops->stop = nmi_stop; - ops->cpu_type = cpu_type; printk(KERN_INFO "oprofile: using NMI interrupt.\n"); return 0; } diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 2650b12a0c5..0d839031979 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -446,13 +446,25 @@ static void clear_ibs_nmi(void) on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); } +static int (*create_arch_files)(struct super_block * sb, struct dentry * root); + static int setup_ibs_files(struct super_block * sb, struct dentry * root) { char buf[12]; struct dentry *dir; + int ret = 0; + + /* architecture specific files */ + if (create_arch_files) + ret = create_arch_files(sb, root); + + if (ret) + return ret; if (!ibs_allowed) - return 0; + return ret; + + /* model specific files */ /* setup some reasonable defaults */ ibs_config.max_cnt_fetch = 250000; @@ -482,11 +494,15 @@ static int setup_ibs_files(struct super_block * sb, struct dentry * root) static int op_amd_init(struct oprofile_operations *ops) { + setup_ibs(); + create_arch_files = ops->create_files; + ops->create_files = setup_ibs_files; return 0; } static void op_amd_exit(void) { + clear_ibs_nmi(); } struct op_x86_model_spec const op_amd_spec = { -- cgit v1.2.3 From a4c408a41167949f820e2740e56a8f2f7bb6177c Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:02 +0200 Subject: OProfile: fix IBS build error for UP Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 0d839031979..1acb067bd34 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -361,6 +361,26 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } +#ifndef CONFIG_SMP + +/* no IBS support */ + +static void setup_ibs(void) +{ + ibs_allowed = 0; +} + +static void clear_ibs_nmi(void) {} + +static int op_amd_init(struct oprofile_operations *ops) +{ + return 0; +} + +static void op_amd_exit(void) {} + +#else + static u8 ibs_eilvt_off; static inline void apic_init_ibs_nmi_per_cpu(void *arg) @@ -505,6 +525,8 @@ static void op_amd_exit(void) clear_ibs_nmi(); } +#endif + struct op_x86_model_spec const op_amd_spec = { .init = op_amd_init, .exit = op_amd_exit, -- cgit v1.2.3 From 87f0baccc2e4f194c931186d3c8499314494a484 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:03 +0200 Subject: x86/oprofile: macro definition cleanup in op_model_athlon.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 46 ++++++++++++++----------------------- 1 file changed, 17 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 1acb067bd34..a3a2058c372 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -47,32 +47,20 @@ #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) -#define IBS_FETCH_CTL_HIGH_MASK 0xFFFFFFFF -/* high dword bit IbsFetchCtl[bit 49] */ -#define IBS_FETCH_VALID_BIT (1UL << 17) -/* high dword bit IbsFetchCtl[bit 52] */ -#define IBS_FETCH_PHY_ADDR_VALID_BIT (1UL << 20) -/* high dword bit IbsFetchCtl[bit 48] */ -#define IBS_FETCH_ENABLE (1UL << 16) +/* IbsFetchCtl bits/masks */ +#define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ +#define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ +#define IBS_FETCH_LOW_MAX_CNT_MASK 0x0000FFFFUL /* MaxCnt mask */ -#define IBS_FETCH_CTL_CNT_MASK 0x00000000FFFF0000UL -#define IBS_FETCH_CTL_MAX_CNT_MASK 0x000000000000FFFFUL - -/*IbsOpCtl masks/bits */ -#define IBS_OP_VALID_BIT (1ULL<<18) /* IbsOpCtl[bit18] */ -#define IBS_OP_ENABLE (1ULL<<17) /* IBS_OP_ENABLE[bit17]*/ +/*IbsOpCtl bits */ +#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ +#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ /* Codes used in cpu_buffer.c */ +/* This produces duplicate code, need to be fixed */ #define IBS_FETCH_BEGIN 3 #define IBS_OP_BEGIN 4 -/*IbsOpData3 masks */ -#define IBS_CTL_LVT_OFFSET_VALID_BIT (1ULL<<8) - -/*PCI Extended Configuration Constants */ -/* MSR to set the IBS control register APIC LVT offset */ -#define IBS_LVT_OFFSET_PCI 0x1CC - /* The function interface needs to be fixed, something like add data. Should then be added to linux/oprofile.h. */ extern void oprofile_add_ibs_sample(struct pt_regs *const regs, @@ -213,7 +201,7 @@ op_amd_handle_ibs(struct pt_regs * const regs, if (ibs_config.fetch_enabled) { rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); - if (high & IBS_FETCH_VALID_BIT) { + if (high & IBS_FETCH_HIGH_VALID_BIT) { ibs_fetch.ibs_fetch_ctl_high = high; ibs_fetch.ibs_fetch_ctl_low = low; rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); @@ -229,16 +217,16 @@ op_amd_handle_ibs(struct pt_regs * const regs, /*reenable the IRQ */ rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); - high &= ~(IBS_FETCH_VALID_BIT); - high |= IBS_FETCH_ENABLE; - low &= IBS_FETCH_CTL_MAX_CNT_MASK; + high &= ~IBS_FETCH_HIGH_VALID_BIT; + high |= IBS_FETCH_HIGH_ENABLE; + low &= IBS_FETCH_LOW_MAX_CNT_MASK; wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); } } if (ibs_config.op_enabled) { rdmsr(MSR_AMD64_IBSOPCTL, low, high); - if (low & IBS_OP_VALID_BIT) { + if (low & IBS_OP_LOW_VALID_BIT) { rdmsr(MSR_AMD64_IBSOPRIP, low, high); ibs_op.ibs_op_rip_low = low; ibs_op.ibs_op_rip_high = high; @@ -263,8 +251,8 @@ op_amd_handle_ibs(struct pt_regs * const regs, (unsigned int *)&ibs_op, IBS_OP_BEGIN); rdmsr(MSR_AMD64_IBSOPCTL, low, high); - low &= ~(IBS_OP_VALID_BIT); - low |= IBS_OP_ENABLE; + low &= ~IBS_OP_LOW_VALID_BIT; + low |= IBS_OP_LOW_ENABLE; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } } @@ -307,12 +295,12 @@ static void op_amd_start(struct op_msrs const * const msrs) } if (ibs_allowed && ibs_config.fetch_enabled) { low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; - high = IBS_FETCH_ENABLE; + high = IBS_FETCH_HIGH_ENABLE; wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); } if (ibs_allowed && ibs_config.op_enabled) { - low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_ENABLE; + low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_LOW_ENABLE; high = 0; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } -- cgit v1.2.3 From 543a157bbdfae8eb997506031c3b2d4d17957098 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:04 +0200 Subject: x86/oprofile: op_model_athlon.c: fix counter reset when reenabling IBS OP Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index a3a2058c372..9c8c8c58313 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -251,6 +251,7 @@ op_amd_handle_ibs(struct pt_regs * const regs, (unsigned int *)&ibs_op, IBS_OP_BEGIN); rdmsr(MSR_AMD64_IBSOPCTL, low, high); + high = 0; low &= ~IBS_OP_LOW_VALID_BIT; low |= IBS_OP_LOW_ENABLE; wrmsr(MSR_AMD64_IBSOPCTL, low, high); -- cgit v1.2.3 From 09691616850b3614dfb44790e1e1419b6a7f5d13 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:05 +0200 Subject: x86: apic: export symbols for extended interrupt LVT functions This patch adds EXPORT_SYMBOLs to allow OProfile to be built as module. Cc: Arjan van de Ven Signed-off-by: Robert Richter Cc: oprofile-list Cc: Arjan van de Ven Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 1 + arch/x86/kernel/apic_64.c | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index fad94b0decc..ed3a6d7e9de 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -672,6 +672,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } +EXPORT_SYMBOL(setup_APIC_eilvt_ibs); /* * Local APIC start and shutdown diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 42bf69f8bc8..45ec90e37b9 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -232,6 +232,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } +EXPORT_SYMBOL(setup_APIC_eilvt_ibs); /* * Program the next event, relative to now -- cgit v1.2.3 From 6aa360e6c16c145edf1837690e0f7aaea6b86ef3 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 23 Jul 2008 15:28:14 +0200 Subject: x86: apic: changing export symbols to *_GPL This fits better here. Signed-off-by: Robert Richter Cc: Arjan van de Ven Cc: Barry Kasindorf Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 +- arch/x86/kernel/apic_64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index ed3a6d7e9de..0059e7a8a9e 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -672,7 +672,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } -EXPORT_SYMBOL(setup_APIC_eilvt_ibs); +EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); /* * Local APIC start and shutdown diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 45ec90e37b9..e571351f2a9 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -232,7 +232,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } -EXPORT_SYMBOL(setup_APIC_eilvt_ibs); +EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); /* * Program the next event, relative to now -- cgit v1.2.3 From 852402cc27bfa1200164e9e8dc7f6e5f0a4fbd46 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:06 +0200 Subject: x86/oprofile: add CONFIG_OPROFILE_IBS option Signed-off-by: Robert Richter Cc: oprofile-list Cc: Robert Richter Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/Kconfig | 14 ++++++++++++++ arch/x86/oprofile/op_model_athlon.c | 33 +++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/Kconfig b/arch/Kconfig index b0fabfa864f..2651af48b2e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -13,6 +13,20 @@ config OPROFILE If unsure, say N. +config OPROFILE_IBS + bool "OProfile AMD IBS support (EXPERIMENTAL)" + default n + depends on OPROFILE && SMP && X86 + help + Instruction-Based Sampling (IBS) is a new profiling + technique that provides rich, precise program performance + information. IBS is introduced by AMD Family10h processors + (AMD Opteron Quad-Core processor “Barcelona”) to overcome + the limitations of conventional performance counter + sampling. + + If unsure, say N. + config HAVE_OPROFILE def_bool n diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 9c8c8c58313..fb6015c1132 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -47,6 +47,10 @@ #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) +static unsigned long reset_value[NUM_COUNTERS]; + +#ifdef CONFIG_OPROFILE_IBS + /* IbsFetchCtl bits/masks */ #define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ #define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ @@ -104,7 +108,6 @@ struct ibs_op_sample { */ static void clear_ibs_nmi(void); -static unsigned long reset_value[NUM_COUNTERS]; static int ibs_allowed; /* AMD Family10h and later */ struct op_ibs_config { @@ -118,6 +121,8 @@ struct op_ibs_config { static struct op_ibs_config ibs_config; +#endif + /* functions for op_amd_spec */ static void op_amd_fill_in_addresses(struct op_msrs * const msrs) @@ -188,6 +193,8 @@ static void op_amd_setup_ctrs(struct op_msrs const * const msrs) } } +#ifdef CONFIG_OPROFILE_IBS + static inline int op_amd_handle_ibs(struct pt_regs * const regs, struct op_msrs const * const msrs) @@ -261,6 +268,8 @@ op_amd_handle_ibs(struct pt_regs * const regs, return 1; } +#endif + static int op_amd_check_ctrs(struct pt_regs * const regs, struct op_msrs const * const msrs) { @@ -277,7 +286,9 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } +#ifdef CONFIG_OPROFILE_IBS op_amd_handle_ibs(regs, msrs); +#endif /* See op_model_ppro.c */ return 1; @@ -294,6 +305,8 @@ static void op_amd_start(struct op_msrs const * const msrs) CTRL_WRITE(low, high, msrs, i); } } + +#ifdef CONFIG_OPROFILE_IBS if (ibs_allowed && ibs_config.fetch_enabled) { low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; high = IBS_FETCH_HIGH_ENABLE; @@ -305,6 +318,7 @@ static void op_amd_start(struct op_msrs const * const msrs) high = 0; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } +#endif } @@ -323,6 +337,7 @@ static void op_amd_stop(struct op_msrs const * const msrs) CTRL_WRITE(low, high, msrs, i); } +#ifdef CONFIG_OPROFILE_IBS if (ibs_allowed && ibs_config.fetch_enabled) { low = 0; /* clear max count and enable */ high = 0; @@ -334,6 +349,7 @@ static void op_amd_stop(struct op_msrs const * const msrs) high = 0; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } +#endif } static void op_amd_shutdown(struct op_msrs const * const msrs) @@ -350,17 +366,10 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } -#ifndef CONFIG_SMP +#ifndef CONFIG_OPROFILE_IBS /* no IBS support */ -static void setup_ibs(void) -{ - ibs_allowed = 0; -} - -static void clear_ibs_nmi(void) {} - static int op_amd_init(struct oprofile_operations *ops) { return 0; @@ -441,8 +450,12 @@ static void setup_ibs(void) if (!ibs_allowed) return; - if (pfm_amd64_setup_eilvt()) + if (pfm_amd64_setup_eilvt()) { ibs_allowed = 0; + return; + } + + printk(KERN_INFO "oprofile: AMD IBS detected\n"); } -- cgit v1.2.3 From 6852fd9b86d05063c6ef49d2e12e061cc7f6a105 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:08 +0200 Subject: x86/oprofile: reanaming op_model_athlon.c to op_model_amd.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/Makefile | 2 +- arch/x86/oprofile/op_model_amd.c | 543 ++++++++++++++++++++++++++++++++++++ arch/x86/oprofile/op_model_athlon.c | 543 ------------------------------------ 3 files changed, 544 insertions(+), 544 deletions(-) create mode 100644 arch/x86/oprofile/op_model_amd.c delete mode 100644 arch/x86/oprofile/op_model_athlon.c (limited to 'arch') diff --git a/arch/x86/oprofile/Makefile b/arch/x86/oprofile/Makefile index 30f3eb36666..446902b2a6b 100644 --- a/arch/x86/oprofile/Makefile +++ b/arch/x86/oprofile/Makefile @@ -7,6 +7,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ timer_int.o ) oprofile-y := $(DRIVER_OBJS) init.o backtrace.o -oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ +oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \ op_model_ppro.o op_model_p4.o oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c new file mode 100644 index 00000000000..d9faf607b3a --- /dev/null +++ b/arch/x86/oprofile/op_model_amd.c @@ -0,0 +1,543 @@ +/* + * @file op_model_amd.c + * athlon / K7 / K8 / Family 10h model-specific MSR operations + * + * @remark Copyright 2002-2008 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + * @author Philippe Elie + * @author Graydon Hoare + * @author Robert Richter + * @author Barry Kasindorf +*/ + +#include +#include +#include + +#include +#include +#include + +#include "op_x86_model.h" +#include "op_counter.h" + +#define NUM_COUNTERS 4 +#define NUM_CONTROLS 4 + +#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0) +#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0) +#define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0) +#define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) + +#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0) +#define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) +#define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) +#define CTRL_SET_ACTIVE(n) (n |= (1<<22)) +#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) +#define CTRL_CLEAR_LO(x) (x &= (1<<21)) +#define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0) +#define CTRL_SET_ENABLE(val) (val |= 1<<20) +#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16)) +#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17)) +#define CTRL_SET_UM(val, m) (val |= (m << 8)) +#define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff)) +#define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf)) +#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) +#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) + +static unsigned long reset_value[NUM_COUNTERS]; + +#ifdef CONFIG_OPROFILE_IBS + +/* IbsFetchCtl bits/masks */ +#define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ +#define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ +#define IBS_FETCH_LOW_MAX_CNT_MASK 0x0000FFFFUL /* MaxCnt mask */ + +/*IbsOpCtl bits */ +#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ +#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ + +/* Codes used in cpu_buffer.c */ +/* This produces duplicate code, need to be fixed */ +#define IBS_FETCH_BEGIN 3 +#define IBS_OP_BEGIN 4 + +/* The function interface needs to be fixed, something like add + data. Should then be added to linux/oprofile.h. */ +extern void oprofile_add_ibs_sample(struct pt_regs *const regs, + unsigned int * const ibs_sample, u8 code); + +struct ibs_fetch_sample { + /* MSRC001_1031 IBS Fetch Linear Address Register */ + unsigned int ibs_fetch_lin_addr_low; + unsigned int ibs_fetch_lin_addr_high; + /* MSRC001_1030 IBS Fetch Control Register */ + unsigned int ibs_fetch_ctl_low; + unsigned int ibs_fetch_ctl_high; + /* MSRC001_1032 IBS Fetch Physical Address Register */ + unsigned int ibs_fetch_phys_addr_low; + unsigned int ibs_fetch_phys_addr_high; +}; + +struct ibs_op_sample { + /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */ + unsigned int ibs_op_rip_low; + unsigned int ibs_op_rip_high; + /* MSRC001_1035 IBS Op Data Register */ + unsigned int ibs_op_data1_low; + unsigned int ibs_op_data1_high; + /* MSRC001_1036 IBS Op Data 2 Register */ + unsigned int ibs_op_data2_low; + unsigned int ibs_op_data2_high; + /* MSRC001_1037 IBS Op Data 3 Register */ + unsigned int ibs_op_data3_low; + unsigned int ibs_op_data3_high; + /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */ + unsigned int ibs_dc_linear_low; + unsigned int ibs_dc_linear_high; + /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */ + unsigned int ibs_dc_phys_low; + unsigned int ibs_dc_phys_high; +}; + +/* + * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+ +*/ +static void clear_ibs_nmi(void); + +static int ibs_allowed; /* AMD Family10h and later */ + +struct op_ibs_config { + unsigned long op_enabled; + unsigned long fetch_enabled; + unsigned long max_cnt_fetch; + unsigned long max_cnt_op; + unsigned long rand_en; + unsigned long dispatched_ops; +}; + +static struct op_ibs_config ibs_config; + +#endif + +/* functions for op_amd_spec */ + +static void op_amd_fill_in_addresses(struct op_msrs * const msrs) +{ + int i; + + for (i = 0; i < NUM_COUNTERS; i++) { + if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) + msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; + else + msrs->counters[i].addr = 0; + } + + for (i = 0; i < NUM_CONTROLS; i++) { + if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) + msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; + else + msrs->controls[i].addr = 0; + } +} + + +static void op_amd_setup_ctrs(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + /* clear all counters */ + for (i = 0 ; i < NUM_CONTROLS; ++i) { + if (unlikely(!CTRL_IS_RESERVED(msrs, i))) + continue; + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR_LO(low); + CTRL_CLEAR_HI(high); + CTRL_WRITE(low, high, msrs, i); + } + + /* avoid a false detection of ctr overflows in NMI handler */ + for (i = 0; i < NUM_COUNTERS; ++i) { + if (unlikely(!CTR_IS_RESERVED(msrs, i))) + continue; + CTR_WRITE(1, msrs, i); + } + + /* enable active counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) { + reset_value[i] = counter_config[i].count; + + CTR_WRITE(counter_config[i].count, msrs, i); + + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR_LO(low); + CTRL_CLEAR_HI(high); + CTRL_SET_ENABLE(low); + CTRL_SET_USR(low, counter_config[i].user); + CTRL_SET_KERN(low, counter_config[i].kernel); + CTRL_SET_UM(low, counter_config[i].unit_mask); + CTRL_SET_EVENT_LOW(low, counter_config[i].event); + CTRL_SET_EVENT_HIGH(high, counter_config[i].event); + CTRL_SET_HOST_ONLY(high, 0); + CTRL_SET_GUEST_ONLY(high, 0); + + CTRL_WRITE(low, high, msrs, i); + } else { + reset_value[i] = 0; + } + } +} + +#ifdef CONFIG_OPROFILE_IBS + +static inline int +op_amd_handle_ibs(struct pt_regs * const regs, + struct op_msrs const * const msrs) +{ + unsigned int low, high; + struct ibs_fetch_sample ibs_fetch; + struct ibs_op_sample ibs_op; + + if (!ibs_allowed) + return 1; + + if (ibs_config.fetch_enabled) { + rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); + if (high & IBS_FETCH_HIGH_VALID_BIT) { + ibs_fetch.ibs_fetch_ctl_high = high; + ibs_fetch.ibs_fetch_ctl_low = low; + rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); + ibs_fetch.ibs_fetch_lin_addr_high = high; + ibs_fetch.ibs_fetch_lin_addr_low = low; + rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high); + ibs_fetch.ibs_fetch_phys_addr_high = high; + ibs_fetch.ibs_fetch_phys_addr_low = low; + + oprofile_add_ibs_sample(regs, + (unsigned int *)&ibs_fetch, + IBS_FETCH_BEGIN); + + /*reenable the IRQ */ + rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); + high &= ~IBS_FETCH_HIGH_VALID_BIT; + high |= IBS_FETCH_HIGH_ENABLE; + low &= IBS_FETCH_LOW_MAX_CNT_MASK; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + } + + if (ibs_config.op_enabled) { + rdmsr(MSR_AMD64_IBSOPCTL, low, high); + if (low & IBS_OP_LOW_VALID_BIT) { + rdmsr(MSR_AMD64_IBSOPRIP, low, high); + ibs_op.ibs_op_rip_low = low; + ibs_op.ibs_op_rip_high = high; + rdmsr(MSR_AMD64_IBSOPDATA, low, high); + ibs_op.ibs_op_data1_low = low; + ibs_op.ibs_op_data1_high = high; + rdmsr(MSR_AMD64_IBSOPDATA2, low, high); + ibs_op.ibs_op_data2_low = low; + ibs_op.ibs_op_data2_high = high; + rdmsr(MSR_AMD64_IBSOPDATA3, low, high); + ibs_op.ibs_op_data3_low = low; + ibs_op.ibs_op_data3_high = high; + rdmsr(MSR_AMD64_IBSDCLINAD, low, high); + ibs_op.ibs_dc_linear_low = low; + ibs_op.ibs_dc_linear_high = high; + rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high); + ibs_op.ibs_dc_phys_low = low; + ibs_op.ibs_dc_phys_high = high; + + /* reenable the IRQ */ + oprofile_add_ibs_sample(regs, + (unsigned int *)&ibs_op, + IBS_OP_BEGIN); + rdmsr(MSR_AMD64_IBSOPCTL, low, high); + high = 0; + low &= ~IBS_OP_LOW_VALID_BIT; + low |= IBS_OP_LOW_ENABLE; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } + } + + return 1; +} + +#endif + +static int op_amd_check_ctrs(struct pt_regs * const regs, + struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + for (i = 0 ; i < NUM_COUNTERS; ++i) { + if (!reset_value[i]) + continue; + CTR_READ(low, high, msrs, i); + if (CTR_OVERFLOWED(low)) { + oprofile_add_sample(regs, i); + CTR_WRITE(reset_value[i], msrs, i); + } + } + +#ifdef CONFIG_OPROFILE_IBS + op_amd_handle_ibs(regs, msrs); +#endif + + /* See op_model_ppro.c */ + return 1; +} + +static void op_amd_start(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + for (i = 0 ; i < NUM_COUNTERS ; ++i) { + if (reset_value[i]) { + CTRL_READ(low, high, msrs, i); + CTRL_SET_ACTIVE(low); + CTRL_WRITE(low, high, msrs, i); + } + } + +#ifdef CONFIG_OPROFILE_IBS + if (ibs_allowed && ibs_config.fetch_enabled) { + low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; + high = IBS_FETCH_HIGH_ENABLE; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + + if (ibs_allowed && ibs_config.op_enabled) { + low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_LOW_ENABLE; + high = 0; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } +#endif +} + + +static void op_amd_stop(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + /* Subtle: stop on all counters to avoid race with + * setting our pm callback */ + for (i = 0 ; i < NUM_COUNTERS ; ++i) { + if (!reset_value[i]) + continue; + CTRL_READ(low, high, msrs, i); + CTRL_SET_INACTIVE(low); + CTRL_WRITE(low, high, msrs, i); + } + +#ifdef CONFIG_OPROFILE_IBS + if (ibs_allowed && ibs_config.fetch_enabled) { + low = 0; /* clear max count and enable */ + high = 0; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + + if (ibs_allowed && ibs_config.op_enabled) { + low = 0; /* clear max count and enable */ + high = 0; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } +#endif +} + +static void op_amd_shutdown(struct op_msrs const * const msrs) +{ + int i; + + for (i = 0 ; i < NUM_COUNTERS ; ++i) { + if (CTR_IS_RESERVED(msrs, i)) + release_perfctr_nmi(MSR_K7_PERFCTR0 + i); + } + for (i = 0 ; i < NUM_CONTROLS ; ++i) { + if (CTRL_IS_RESERVED(msrs, i)) + release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); + } +} + +#ifndef CONFIG_OPROFILE_IBS + +/* no IBS support */ + +static int op_amd_init(struct oprofile_operations *ops) +{ + return 0; +} + +static void op_amd_exit(void) {} + +#else + +static u8 ibs_eilvt_off; + +static inline void apic_init_ibs_nmi_per_cpu(void *arg) +{ + ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); +} + +static inline void apic_clear_ibs_nmi_per_cpu(void *arg) +{ + setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); +} + +static int pfm_amd64_setup_eilvt(void) +{ +#define IBSCTL_LVTOFFSETVAL (1 << 8) +#define IBSCTL 0x1cc + struct pci_dev *cpu_cfg; + int nodes; + u32 value = 0; + + /* per CPU setup */ + on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1); + + nodes = 0; + cpu_cfg = NULL; + do { + cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_10H_NB_MISC, + cpu_cfg); + if (!cpu_cfg) + break; + ++nodes; + pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off + | IBSCTL_LVTOFFSETVAL); + pci_read_config_dword(cpu_cfg, IBSCTL, &value); + if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) { + printk(KERN_DEBUG "Failed to setup IBS LVT offset, " + "IBSCTL = 0x%08x", value); + return 1; + } + } while (1); + + if (!nodes) { + printk(KERN_DEBUG "No CPU node configured for IBS"); + return 1; + } + +#ifdef CONFIG_NUMA + /* Sanity check */ + /* Works only for 64bit with proper numa implementation. */ + if (nodes != num_possible_nodes()) { + printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, " + "found: %d, expected %d", + nodes, num_possible_nodes()); + return 1; + } +#endif + return 0; +} + +/* + * initialize the APIC for the IBS interrupts + * if available (AMD Family10h rev B0 and later) + */ +static void setup_ibs(void) +{ + ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); + + if (!ibs_allowed) + return; + + if (pfm_amd64_setup_eilvt()) { + ibs_allowed = 0; + return; + } + + printk(KERN_INFO "oprofile: AMD IBS detected\n"); +} + + +/* + * unitialize the APIC for the IBS interrupts if needed on AMD Family10h + * rev B0 and later */ +static void clear_ibs_nmi(void) +{ + if (ibs_allowed) + on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); +} + +static int (*create_arch_files)(struct super_block * sb, struct dentry * root); + +static int setup_ibs_files(struct super_block * sb, struct dentry * root) +{ + char buf[12]; + struct dentry *dir; + int ret = 0; + + /* architecture specific files */ + if (create_arch_files) + ret = create_arch_files(sb, root); + + if (ret) + return ret; + + if (!ibs_allowed) + return ret; + + /* model specific files */ + + /* setup some reasonable defaults */ + ibs_config.max_cnt_fetch = 250000; + ibs_config.fetch_enabled = 0; + ibs_config.max_cnt_op = 250000; + ibs_config.op_enabled = 0; + ibs_config.dispatched_ops = 1; + snprintf(buf, sizeof(buf), "ibs_fetch"); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "rand_enable", + &ibs_config.rand_en); + oprofilefs_create_ulong(sb, dir, "enable", + &ibs_config.fetch_enabled); + oprofilefs_create_ulong(sb, dir, "max_count", + &ibs_config.max_cnt_fetch); + snprintf(buf, sizeof(buf), "ibs_uops"); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "enable", + &ibs_config.op_enabled); + oprofilefs_create_ulong(sb, dir, "max_count", + &ibs_config.max_cnt_op); + oprofilefs_create_ulong(sb, dir, "dispatched_ops", + &ibs_config.dispatched_ops); + + return 0; +} + +static int op_amd_init(struct oprofile_operations *ops) +{ + setup_ibs(); + create_arch_files = ops->create_files; + ops->create_files = setup_ibs_files; + return 0; +} + +static void op_amd_exit(void) +{ + clear_ibs_nmi(); +} + +#endif + +struct op_x86_model_spec const op_amd_spec = { + .init = op_amd_init, + .exit = op_amd_exit, + .num_counters = NUM_COUNTERS, + .num_controls = NUM_CONTROLS, + .fill_in_addresses = &op_amd_fill_in_addresses, + .setup_ctrs = &op_amd_setup_ctrs, + .check_ctrs = &op_amd_check_ctrs, + .start = &op_amd_start, + .stop = &op_amd_stop, + .shutdown = &op_amd_shutdown +}; diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c deleted file mode 100644 index fb6015c1132..00000000000 --- a/arch/x86/oprofile/op_model_athlon.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * @file op_model_athlon.c - * athlon / K7 / K8 / Family 10h model-specific MSR operations - * - * @remark Copyright 2002-2008 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - * @author Graydon Hoare - * @author Robert Richter - * @author Barry Kasindorf -*/ - -#include -#include -#include - -#include -#include -#include - -#include "op_x86_model.h" -#include "op_counter.h" - -#define NUM_COUNTERS 4 -#define NUM_CONTROLS 4 - -#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0) -#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0) -#define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0) -#define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) - -#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0) -#define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) -#define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) -#define CTRL_SET_ACTIVE(n) (n |= (1<<22)) -#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) -#define CTRL_CLEAR_LO(x) (x &= (1<<21)) -#define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0) -#define CTRL_SET_ENABLE(val) (val |= 1<<20) -#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16)) -#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17)) -#define CTRL_SET_UM(val, m) (val |= (m << 8)) -#define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff)) -#define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf)) -#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) -#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) - -static unsigned long reset_value[NUM_COUNTERS]; - -#ifdef CONFIG_OPROFILE_IBS - -/* IbsFetchCtl bits/masks */ -#define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ -#define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ -#define IBS_FETCH_LOW_MAX_CNT_MASK 0x0000FFFFUL /* MaxCnt mask */ - -/*IbsOpCtl bits */ -#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ -#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ - -/* Codes used in cpu_buffer.c */ -/* This produces duplicate code, need to be fixed */ -#define IBS_FETCH_BEGIN 3 -#define IBS_OP_BEGIN 4 - -/* The function interface needs to be fixed, something like add - data. Should then be added to linux/oprofile.h. */ -extern void oprofile_add_ibs_sample(struct pt_regs *const regs, - unsigned int * const ibs_sample, u8 code); - -struct ibs_fetch_sample { - /* MSRC001_1031 IBS Fetch Linear Address Register */ - unsigned int ibs_fetch_lin_addr_low; - unsigned int ibs_fetch_lin_addr_high; - /* MSRC001_1030 IBS Fetch Control Register */ - unsigned int ibs_fetch_ctl_low; - unsigned int ibs_fetch_ctl_high; - /* MSRC001_1032 IBS Fetch Physical Address Register */ - unsigned int ibs_fetch_phys_addr_low; - unsigned int ibs_fetch_phys_addr_high; -}; - -struct ibs_op_sample { - /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */ - unsigned int ibs_op_rip_low; - unsigned int ibs_op_rip_high; - /* MSRC001_1035 IBS Op Data Register */ - unsigned int ibs_op_data1_low; - unsigned int ibs_op_data1_high; - /* MSRC001_1036 IBS Op Data 2 Register */ - unsigned int ibs_op_data2_low; - unsigned int ibs_op_data2_high; - /* MSRC001_1037 IBS Op Data 3 Register */ - unsigned int ibs_op_data3_low; - unsigned int ibs_op_data3_high; - /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */ - unsigned int ibs_dc_linear_low; - unsigned int ibs_dc_linear_high; - /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */ - unsigned int ibs_dc_phys_low; - unsigned int ibs_dc_phys_high; -}; - -/* - * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+ -*/ -static void clear_ibs_nmi(void); - -static int ibs_allowed; /* AMD Family10h and later */ - -struct op_ibs_config { - unsigned long op_enabled; - unsigned long fetch_enabled; - unsigned long max_cnt_fetch; - unsigned long max_cnt_op; - unsigned long rand_en; - unsigned long dispatched_ops; -}; - -static struct op_ibs_config ibs_config; - -#endif - -/* functions for op_amd_spec */ - -static void op_amd_fill_in_addresses(struct op_msrs * const msrs) -{ - int i; - - for (i = 0; i < NUM_COUNTERS; i++) { - if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) - msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; - else - msrs->counters[i].addr = 0; - } - - for (i = 0; i < NUM_CONTROLS; i++) { - if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) - msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; - else - msrs->controls[i].addr = 0; - } -} - - -static void op_amd_setup_ctrs(struct op_msrs const * const msrs) -{ - unsigned int low, high; - int i; - - /* clear all counters */ - for (i = 0 ; i < NUM_CONTROLS; ++i) { - if (unlikely(!CTRL_IS_RESERVED(msrs, i))) - continue; - CTRL_READ(low, high, msrs, i); - CTRL_CLEAR_LO(low); - CTRL_CLEAR_HI(high); - CTRL_WRITE(low, high, msrs, i); - } - - /* avoid a false detection of ctr overflows in NMI handler */ - for (i = 0; i < NUM_COUNTERS; ++i) { - if (unlikely(!CTR_IS_RESERVED(msrs, i))) - continue; - CTR_WRITE(1, msrs, i); - } - - /* enable active counters */ - for (i = 0; i < NUM_COUNTERS; ++i) { - if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) { - reset_value[i] = counter_config[i].count; - - CTR_WRITE(counter_config[i].count, msrs, i); - - CTRL_READ(low, high, msrs, i); - CTRL_CLEAR_LO(low); - CTRL_CLEAR_HI(high); - CTRL_SET_ENABLE(low); - CTRL_SET_USR(low, counter_config[i].user); - CTRL_SET_KERN(low, counter_config[i].kernel); - CTRL_SET_UM(low, counter_config[i].unit_mask); - CTRL_SET_EVENT_LOW(low, counter_config[i].event); - CTRL_SET_EVENT_HIGH(high, counter_config[i].event); - CTRL_SET_HOST_ONLY(high, 0); - CTRL_SET_GUEST_ONLY(high, 0); - - CTRL_WRITE(low, high, msrs, i); - } else { - reset_value[i] = 0; - } - } -} - -#ifdef CONFIG_OPROFILE_IBS - -static inline int -op_amd_handle_ibs(struct pt_regs * const regs, - struct op_msrs const * const msrs) -{ - unsigned int low, high; - struct ibs_fetch_sample ibs_fetch; - struct ibs_op_sample ibs_op; - - if (!ibs_allowed) - return 1; - - if (ibs_config.fetch_enabled) { - rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); - if (high & IBS_FETCH_HIGH_VALID_BIT) { - ibs_fetch.ibs_fetch_ctl_high = high; - ibs_fetch.ibs_fetch_ctl_low = low; - rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); - ibs_fetch.ibs_fetch_lin_addr_high = high; - ibs_fetch.ibs_fetch_lin_addr_low = low; - rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high); - ibs_fetch.ibs_fetch_phys_addr_high = high; - ibs_fetch.ibs_fetch_phys_addr_low = low; - - oprofile_add_ibs_sample(regs, - (unsigned int *)&ibs_fetch, - IBS_FETCH_BEGIN); - - /*reenable the IRQ */ - rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); - high &= ~IBS_FETCH_HIGH_VALID_BIT; - high |= IBS_FETCH_HIGH_ENABLE; - low &= IBS_FETCH_LOW_MAX_CNT_MASK; - wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); - } - } - - if (ibs_config.op_enabled) { - rdmsr(MSR_AMD64_IBSOPCTL, low, high); - if (low & IBS_OP_LOW_VALID_BIT) { - rdmsr(MSR_AMD64_IBSOPRIP, low, high); - ibs_op.ibs_op_rip_low = low; - ibs_op.ibs_op_rip_high = high; - rdmsr(MSR_AMD64_IBSOPDATA, low, high); - ibs_op.ibs_op_data1_low = low; - ibs_op.ibs_op_data1_high = high; - rdmsr(MSR_AMD64_IBSOPDATA2, low, high); - ibs_op.ibs_op_data2_low = low; - ibs_op.ibs_op_data2_high = high; - rdmsr(MSR_AMD64_IBSOPDATA3, low, high); - ibs_op.ibs_op_data3_low = low; - ibs_op.ibs_op_data3_high = high; - rdmsr(MSR_AMD64_IBSDCLINAD, low, high); - ibs_op.ibs_dc_linear_low = low; - ibs_op.ibs_dc_linear_high = high; - rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high); - ibs_op.ibs_dc_phys_low = low; - ibs_op.ibs_dc_phys_high = high; - - /* reenable the IRQ */ - oprofile_add_ibs_sample(regs, - (unsigned int *)&ibs_op, - IBS_OP_BEGIN); - rdmsr(MSR_AMD64_IBSOPCTL, low, high); - high = 0; - low &= ~IBS_OP_LOW_VALID_BIT; - low |= IBS_OP_LOW_ENABLE; - wrmsr(MSR_AMD64_IBSOPCTL, low, high); - } - } - - return 1; -} - -#endif - -static int op_amd_check_ctrs(struct pt_regs * const regs, - struct op_msrs const * const msrs) -{ - unsigned int low, high; - int i; - - for (i = 0 ; i < NUM_COUNTERS; ++i) { - if (!reset_value[i]) - continue; - CTR_READ(low, high, msrs, i); - if (CTR_OVERFLOWED(low)) { - oprofile_add_sample(regs, i); - CTR_WRITE(reset_value[i], msrs, i); - } - } - -#ifdef CONFIG_OPROFILE_IBS - op_amd_handle_ibs(regs, msrs); -#endif - - /* See op_model_ppro.c */ - return 1; -} - -static void op_amd_start(struct op_msrs const * const msrs) -{ - unsigned int low, high; - int i; - for (i = 0 ; i < NUM_COUNTERS ; ++i) { - if (reset_value[i]) { - CTRL_READ(low, high, msrs, i); - CTRL_SET_ACTIVE(low); - CTRL_WRITE(low, high, msrs, i); - } - } - -#ifdef CONFIG_OPROFILE_IBS - if (ibs_allowed && ibs_config.fetch_enabled) { - low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; - high = IBS_FETCH_HIGH_ENABLE; - wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); - } - - if (ibs_allowed && ibs_config.op_enabled) { - low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_LOW_ENABLE; - high = 0; - wrmsr(MSR_AMD64_IBSOPCTL, low, high); - } -#endif -} - - -static void op_amd_stop(struct op_msrs const * const msrs) -{ - unsigned int low, high; - int i; - - /* Subtle: stop on all counters to avoid race with - * setting our pm callback */ - for (i = 0 ; i < NUM_COUNTERS ; ++i) { - if (!reset_value[i]) - continue; - CTRL_READ(low, high, msrs, i); - CTRL_SET_INACTIVE(low); - CTRL_WRITE(low, high, msrs, i); - } - -#ifdef CONFIG_OPROFILE_IBS - if (ibs_allowed && ibs_config.fetch_enabled) { - low = 0; /* clear max count and enable */ - high = 0; - wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); - } - - if (ibs_allowed && ibs_config.op_enabled) { - low = 0; /* clear max count and enable */ - high = 0; - wrmsr(MSR_AMD64_IBSOPCTL, low, high); - } -#endif -} - -static void op_amd_shutdown(struct op_msrs const * const msrs) -{ - int i; - - for (i = 0 ; i < NUM_COUNTERS ; ++i) { - if (CTR_IS_RESERVED(msrs, i)) - release_perfctr_nmi(MSR_K7_PERFCTR0 + i); - } - for (i = 0 ; i < NUM_CONTROLS ; ++i) { - if (CTRL_IS_RESERVED(msrs, i)) - release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); - } -} - -#ifndef CONFIG_OPROFILE_IBS - -/* no IBS support */ - -static int op_amd_init(struct oprofile_operations *ops) -{ - return 0; -} - -static void op_amd_exit(void) {} - -#else - -static u8 ibs_eilvt_off; - -static inline void apic_init_ibs_nmi_per_cpu(void *arg) -{ - ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); -} - -static inline void apic_clear_ibs_nmi_per_cpu(void *arg) -{ - setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); -} - -static int pfm_amd64_setup_eilvt(void) -{ -#define IBSCTL_LVTOFFSETVAL (1 << 8) -#define IBSCTL 0x1cc - struct pci_dev *cpu_cfg; - int nodes; - u32 value = 0; - - /* per CPU setup */ - on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1); - - nodes = 0; - cpu_cfg = NULL; - do { - cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_10H_NB_MISC, - cpu_cfg); - if (!cpu_cfg) - break; - ++nodes; - pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off - | IBSCTL_LVTOFFSETVAL); - pci_read_config_dword(cpu_cfg, IBSCTL, &value); - if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) { - printk(KERN_DEBUG "Failed to setup IBS LVT offset, " - "IBSCTL = 0x%08x", value); - return 1; - } - } while (1); - - if (!nodes) { - printk(KERN_DEBUG "No CPU node configured for IBS"); - return 1; - } - -#ifdef CONFIG_NUMA - /* Sanity check */ - /* Works only for 64bit with proper numa implementation. */ - if (nodes != num_possible_nodes()) { - printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, " - "found: %d, expected %d", - nodes, num_possible_nodes()); - return 1; - } -#endif - return 0; -} - -/* - * initialize the APIC for the IBS interrupts - * if available (AMD Family10h rev B0 and later) - */ -static void setup_ibs(void) -{ - ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); - - if (!ibs_allowed) - return; - - if (pfm_amd64_setup_eilvt()) { - ibs_allowed = 0; - return; - } - - printk(KERN_INFO "oprofile: AMD IBS detected\n"); -} - - -/* - * unitialize the APIC for the IBS interrupts if needed on AMD Family10h - * rev B0 and later */ -static void clear_ibs_nmi(void) -{ - if (ibs_allowed) - on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); -} - -static int (*create_arch_files)(struct super_block * sb, struct dentry * root); - -static int setup_ibs_files(struct super_block * sb, struct dentry * root) -{ - char buf[12]; - struct dentry *dir; - int ret = 0; - - /* architecture specific files */ - if (create_arch_files) - ret = create_arch_files(sb, root); - - if (ret) - return ret; - - if (!ibs_allowed) - return ret; - - /* model specific files */ - - /* setup some reasonable defaults */ - ibs_config.max_cnt_fetch = 250000; - ibs_config.fetch_enabled = 0; - ibs_config.max_cnt_op = 250000; - ibs_config.op_enabled = 0; - ibs_config.dispatched_ops = 1; - snprintf(buf, sizeof(buf), "ibs_fetch"); - dir = oprofilefs_mkdir(sb, root, buf); - oprofilefs_create_ulong(sb, dir, "rand_enable", - &ibs_config.rand_en); - oprofilefs_create_ulong(sb, dir, "enable", - &ibs_config.fetch_enabled); - oprofilefs_create_ulong(sb, dir, "max_count", - &ibs_config.max_cnt_fetch); - snprintf(buf, sizeof(buf), "ibs_uops"); - dir = oprofilefs_mkdir(sb, root, buf); - oprofilefs_create_ulong(sb, dir, "enable", - &ibs_config.op_enabled); - oprofilefs_create_ulong(sb, dir, "max_count", - &ibs_config.max_cnt_op); - oprofilefs_create_ulong(sb, dir, "dispatched_ops", - &ibs_config.dispatched_ops); - - return 0; -} - -static int op_amd_init(struct oprofile_operations *ops) -{ - setup_ibs(); - create_arch_files = ops->create_files; - ops->create_files = setup_ibs_files; - return 0; -} - -static void op_amd_exit(void) -{ - clear_ibs_nmi(); -} - -#endif - -struct op_x86_model_spec const op_amd_spec = { - .init = op_amd_init, - .exit = op_amd_exit, - .num_counters = NUM_COUNTERS, - .num_controls = NUM_CONTROLS, - .fill_in_addresses = &op_amd_fill_in_addresses, - .setup_ctrs = &op_amd_setup_ctrs, - .check_ctrs = &op_amd_check_ctrs, - .start = &op_amd_start, - .stop = &op_amd_stop, - .shutdown = &op_amd_shutdown -}; -- cgit v1.2.3 From 1ddb5518052e4e28ab489237443f7443b3fd69ca Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:55 +0200 Subject: x86: convert pci-dma.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index cbecb05551b..88ddd04cfa9 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -82,7 +82,7 @@ void __init dma32_reserve_bootmem(void) * using 512M as goal */ align = 64ULL<<20; - size = round_up(dma32_bootmem_size, align); + size = roundup(dma32_bootmem_size, align); dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align, 512ULL<<20); if (dma32_bootmem_ptr) -- cgit v1.2.3 From 15ae2d76ceb037a1e3fcd8fc9b4fe3177f9f3831 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:56 +0200 Subject: x86: convert pageattr.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 65c6e46bf05..0d254adcc82 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -78,7 +78,7 @@ static inline unsigned long highmap_start_pfn(void) static inline unsigned long highmap_end_pfn(void) { - return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; + return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; } #endif -- cgit v1.2.3 From d86bb0dac792c6a9c92944b6db2687980c808094 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:57 +0200 Subject: x86: convert init_64.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index ec37121f670..e4805771b5b 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -258,7 +258,7 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size) void __init cleanup_highmap(void) { unsigned long vaddr = __START_KERNEL_map; - unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1; + unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1; pmd_t *pmd = level2_kernel_pgt; pmd_t *last_pmd = pmd + PTRS_PER_PMD; @@ -474,14 +474,14 @@ static void __init find_early_table_space(unsigned long end) unsigned long puds, pmds, ptes, tables, start; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); + tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); if (direct_gbpages) { unsigned long extra; extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; } else pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); + tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); if (cpu_has_pse) { unsigned long extra; @@ -489,7 +489,7 @@ static void __init find_early_table_space(unsigned long end) ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; - tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE); + tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); /* * RED-PEN putting page tables only on node 0 could -- cgit v1.2.3 From be3e89ee6df8607356f705901dd90bcf3836c86e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:58 +0200 Subject: x86: convert numa_64.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/numa_64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index a4dd793d600..cebcbf152d4 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -79,7 +79,7 @@ static int __init allocate_cachealigned_memnodemap(void) return 0; addr = 0x8000; - nodemap_size = round_up(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); + nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); nodemap_addr = find_e820_area(addr, max_pfn< Date: Fri, 25 Jul 2008 16:48:59 +0200 Subject: x86: convert discontig_32.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/discontig_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index 62fa440678d..847c164725f 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c @@ -328,7 +328,7 @@ void __init initmem_init(unsigned long start_pfn, get_memcfg_numa(); - kva_pages = round_up(calculate_numa_remap_pages(), PTRS_PER_PTE); + kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE); kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE); do { -- cgit v1.2.3 From 5c05917e7fe313a187ad6ebb94c1c6cf42862a0b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 24 Jul 2008 17:29:40 -0700 Subject: x86: usb debug port early console, v4 based on work from Eric, and add some timeout so don't dead loop when debug device is not installed v2: fix checkpatch warning v3: move ehci struct def to linux/usrb/ehci_def.h from host/ehci.h also add CONFIG_EARLY_PRINTK_DBGP to disable it by default v4: address comments from Ingo, seperate ehci reg def moving to another patch also add auto detect port that connect to debug device for Nvidia southbridge Signed-off-by: Yinghai Lu Cc: Andrew Morton Cc: Andi Kleen Cc: "Arjan van de Ven" Cc: "Eric W. Biederman" Cc: "Greg KH" Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.debug | 13 + arch/x86/kernel/early_printk.c | 762 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 772 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 092f019e033..93422d2ecf6 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -43,6 +43,19 @@ config EARLY_PRINTK with klogd/syslogd or the X server. You should normally N here, unless you want to debug such a crash. +config EARLY_PRINTK_DBGP + bool "Early printk via EHCI debug port" + default n + depends on EARLY_PRINTK + help + Write kernel log output directly into the EHCI debug port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. You need usb debug device. + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index ff9e7350da5..28155acf706 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -3,11 +3,19 @@ #include #include #include +#include +#include +#include +#include #include #include #include #include #include +#include +#include +#include +#include /* Simple VGA output */ #define VGABASE (__ISA_IO_base + 0xb8000) @@ -78,6 +86,7 @@ static int early_serial_base = 0x3f8; /* ttyS0 */ static int early_serial_putc(unsigned char ch) { unsigned timeout = 0xffff; + while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) cpu_relax(); outb(ch, early_serial_base + TXR); @@ -151,6 +160,721 @@ static struct console early_serial_console = { .index = -1, }; +#ifdef CONFIG_EARLY_PRINTK_DBGP + +static struct ehci_caps __iomem *ehci_caps; +static struct ehci_regs __iomem *ehci_regs; +static struct ehci_dbg_port __iomem *ehci_debug; +static unsigned int dbgp_endpoint_out; + +struct ehci_dev { + u32 bus; + u32 slot; + u32 func; +}; + +static struct ehci_dev ehci_dev; + +#define USB_DEBUG_DEVNUM 127 + +#define DBGP_DATA_TOGGLE 0x8800 + +static inline u32 dbgp_pid_update(u32 x, u32 tok) +{ + return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff); +} + +static inline u32 dbgp_len_update(u32 x, u32 len) +{ + return (x & ~0x0f) | (len & 0x0f); +} + +/* + * USB Packet IDs (PIDs) + */ + +/* token */ +#define USB_PID_OUT 0xe1 +#define USB_PID_IN 0x69 +#define USB_PID_SOF 0xa5 +#define USB_PID_SETUP 0x2d +/* handshake */ +#define USB_PID_ACK 0xd2 +#define USB_PID_NAK 0x5a +#define USB_PID_STALL 0x1e +#define USB_PID_NYET 0x96 +/* data */ +#define USB_PID_DATA0 0xc3 +#define USB_PID_DATA1 0x4b +#define USB_PID_DATA2 0x87 +#define USB_PID_MDATA 0x0f +/* Special */ +#define USB_PID_PREAMBLE 0x3c +#define USB_PID_ERR 0x3c +#define USB_PID_SPLIT 0x78 +#define USB_PID_PING 0xb4 +#define USB_PID_UNDEF_0 0xf0 + +#define USB_PID_DATA_TOGGLE 0x88 +#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE) + +#define PCI_CAP_ID_EHCI_DEBUG 0xa + +#define HUB_ROOT_RESET_TIME 50 /* times are in msec */ +#define HUB_SHORT_RESET_TIME 10 +#define HUB_LONG_RESET_TIME 200 +#define HUB_RESET_TIMEOUT 500 + +#define DBGP_MAX_PACKET 8 + +static int dbgp_wait_until_complete(void) +{ + u32 ctrl; + int loop = 0x100000; + + do { + ctrl = readl(&ehci_debug->control); + /* Stop when the transaction is finished */ + if (ctrl & DBGP_DONE) + break; + } while (--loop > 0); + + if (!loop) + return -1; + + /* + * Now that we have observed the completed transaction, + * clear the done bit. + */ + writel(ctrl | DBGP_DONE, &ehci_debug->control); + return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl); +} + +static void dbgp_mdelay(int ms) +{ + int i; + + while (ms--) { + for (i = 0; i < 1000; i++) + outb(0x1, 0x80); + } +} + +static void dbgp_breath(void) +{ + /* Sleep to give the debug port a chance to breathe */ +} + +static int dbgp_wait_until_done(unsigned ctrl) +{ + u32 pids, lpid; + int ret; + int loop = 3; + +retry: + writel(ctrl | DBGP_GO, &ehci_debug->control); + ret = dbgp_wait_until_complete(); + pids = readl(&ehci_debug->pids); + lpid = DBGP_PID_GET(pids); + + if (ret < 0) + return ret; + + /* + * If the port is getting full or it has dropped data + * start pacing ourselves, not necessary but it's friendly. + */ + if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET)) + dbgp_breath(); + + /* If I get a NACK reissue the transmission */ + if (lpid == USB_PID_NAK) { + if (--loop > 0) + goto retry; + } + + return ret; +} + +static void dbgp_set_data(const void *buf, int size) +{ + const unsigned char *bytes = buf; + u32 lo, hi; + int i; + + lo = hi = 0; + for (i = 0; i < 4 && i < size; i++) + lo |= bytes[i] << (8*i); + for (; i < 8 && i < size; i++) + hi |= bytes[i] << (8*(i - 4)); + writel(lo, &ehci_debug->data03); + writel(hi, &ehci_debug->data47); +} + +static void dbgp_get_data(void *buf, int size) +{ + unsigned char *bytes = buf; + u32 lo, hi; + int i; + + lo = readl(&ehci_debug->data03); + hi = readl(&ehci_debug->data47); + for (i = 0; i < 4 && i < size; i++) + bytes[i] = (lo >> (8*i)) & 0xff; + for (; i < 8 && i < size; i++) + bytes[i] = (hi >> (8*(i - 4))) & 0xff; +} + +static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, + const char *bytes, int size) +{ + u32 pids, addr, ctrl; + int ret; + + if (size > DBGP_MAX_PACKET) + return -1; + + addr = DBGP_EPADDR(devnum, endpoint); + + pids = readl(&ehci_debug->pids); + pids = dbgp_pid_update(pids, USB_PID_OUT); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, size); + ctrl |= DBGP_OUT; + ctrl |= DBGP_GO; + + dbgp_set_data(bytes, size); + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + return ret; +} + +static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, + int size) +{ + u32 pids, addr, ctrl; + int ret; + + if (size > DBGP_MAX_PACKET) + return -1; + + addr = DBGP_EPADDR(devnum, endpoint); + + pids = readl(&ehci_debug->pids); + pids = dbgp_pid_update(pids, USB_PID_IN); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, size); + ctrl &= ~DBGP_OUT; + ctrl |= DBGP_GO; + + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + if (size > ret) + size = ret; + dbgp_get_data(data, size); + return ret; +} + +static int dbgp_control_msg(unsigned devnum, int requesttype, int request, + int value, int index, void *data, int size) +{ + u32 pids, addr, ctrl; + struct usb_ctrlrequest req; + int read; + int ret; + + read = (requesttype & USB_DIR_IN) != 0; + if (size > (read ? DBGP_MAX_PACKET:0)) + return -1; + + /* Compute the control message */ + req.bRequestType = requesttype; + req.bRequest = request; + req.wValue = value; + req.wIndex = index; + req.wLength = size; + + pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP); + addr = DBGP_EPADDR(devnum, 0); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, sizeof(req)); + ctrl |= DBGP_OUT; + ctrl |= DBGP_GO; + + /* Send the setup message */ + dbgp_set_data(&req, sizeof(req)); + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + /* Read the result */ + return dbgp_bulk_read(devnum, 0, data, size); +} + + +/* Find a PCI capability */ +static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap) +{ + u8 pos; + int bytes; + + if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & + PCI_STATUS_CAP_LIST)) + return 0; + + pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); + for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { + u8 id; + + pos &= ~3; + id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); + if (id == 0xff) + break; + if (id == cap) + return pos; + + pos = read_pci_config_byte(num, slot, func, + pos+PCI_CAP_LIST_NEXT); + } + return 0; +} + +static u32 __init __find_dbgp(u32 bus, u32 slot, u32 func) +{ + u32 class; + + class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION); + if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI) + return 0; + + return find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG); +} + +static u32 __init find_dbgp(int ehci_num, u32 *rbus, u32 *rslot, u32 *rfunc) +{ + u32 bus, slot, func; + + for (bus = 0; bus < 256; bus++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + unsigned cap; + + cap = __find_dbgp(bus, slot, func); + + if (!cap) + continue; + if (ehci_num-- != 0) + continue; + *rbus = bus; + *rslot = slot; + *rfunc = func; + return cap; + } + } + } + return 0; +} + +static int ehci_reset_port(int port) +{ + u32 portsc; + u32 delay_time, delay; + int loop; + + /* Reset the usb debug port */ + portsc = readl(&ehci_regs->port_status[port - 1]); + portsc &= ~PORT_PE; + portsc |= PORT_RESET; + writel(portsc, &ehci_regs->port_status[port - 1]); + + delay = HUB_ROOT_RESET_TIME; + for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; + delay_time += delay) { + dbgp_mdelay(delay); + + portsc = readl(&ehci_regs->port_status[port - 1]); + if (portsc & PORT_RESET) { + /* force reset to complete */ + loop = 2; + writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), + &ehci_regs->port_status[port - 1]); + do { + portsc = readl(&ehci_regs->port_status[port-1]); + } while ((portsc & PORT_RESET) && (--loop > 0)); + } + + /* Device went away? */ + if (!(portsc & PORT_CONNECT)) + return -ENOTCONN; + + /* bomb out completely if something weird happend */ + if ((portsc & PORT_CSC)) + return -EINVAL; + + /* If we've finished resetting, then break out of the loop */ + if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) + return 0; + } + return -EBUSY; +} + +static int ehci_wait_for_port(int port) +{ + u32 status; + int ret, reps; + + for (reps = 0; reps < 3; reps++) { + dbgp_mdelay(100); + status = readl(&ehci_regs->status); + if (status & STS_PCD) { + ret = ehci_reset_port(port); + if (ret == 0) + return 0; + } + } + return -ENOTCONN; +} + +#ifdef DBGP_DEBUG +# define dbgp_printk early_printk +#else +static inline void dbgp_printk(const char *fmt, ...) { } +#endif + +typedef void (*set_debug_port_t)(int port); + +static void default_set_debug_port(int port) +{ +} + +static set_debug_port_t set_debug_port = default_set_debug_port; + +static void nvidia_set_debug_port(int port) +{ + u32 dword; + dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, + 0x74); + dword &= ~(0x0f<<12); + dword |= ((port & 0x0f)<<12); + write_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, 0x74, + dword); + dbgp_printk("set debug port to %d\n", port); +} + +static void __init detect_set_debug_port(void) +{ + u32 vendorid; + + vendorid = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, + 0x00); + + if ((vendorid & 0xffff) == 0x10de) { + dbgp_printk("using nvidia set_debug_port\n"); + set_debug_port = nvidia_set_debug_port; + } +} + +static int __init ehci_setup(void) +{ + struct usb_debug_descriptor dbgp_desc; + u32 cmd, ctrl, status, portsc, hcs_params; + u32 debug_port, new_debug_port = 0, n_ports; + u32 devnum; + int ret, i; + int loop; + int port_map_tried; + int playtimes = 3; + +try_next_time: + port_map_tried = 0; + +try_next_port: + + hcs_params = readl(&ehci_caps->hcs_params); + debug_port = HCS_DEBUG_PORT(hcs_params); + n_ports = HCS_N_PORTS(hcs_params); + + dbgp_printk("debug_port: %d\n", debug_port); + dbgp_printk("n_ports: %d\n", n_ports); + + for (i = 1; i <= n_ports; i++) { + portsc = readl(&ehci_regs->port_status[i-1]); + dbgp_printk("portstatus%d: %08x\n", i, portsc); + } + + if (port_map_tried && (new_debug_port != debug_port)) { + if (--playtimes) { + set_debug_port(new_debug_port); + goto try_next_time; + } + return -1; + } + + loop = 10; + /* Reset the EHCI controller */ + cmd = readl(&ehci_regs->command); + cmd |= CMD_RESET; + writel(cmd, &ehci_regs->command); + do { + cmd = readl(&ehci_regs->command); + } while ((cmd & CMD_RESET) && (--loop > 0)); + + if (!loop) { + dbgp_printk("can not reset ehci\n"); + return -1; + } + dbgp_printk("ehci reset done\n"); + + /* Claim ownership, but do not enable yet */ + ctrl = readl(&ehci_debug->control); + ctrl |= DBGP_OWNER; + ctrl &= ~(DBGP_ENABLED | DBGP_INUSE); + writel(ctrl, &ehci_debug->control); + + /* Start the ehci running */ + cmd = readl(&ehci_regs->command); + cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET); + cmd |= CMD_RUN; + writel(cmd, &ehci_regs->command); + + /* Ensure everything is routed to the EHCI */ + writel(FLAG_CF, &ehci_regs->configured_flag); + + /* Wait until the controller is no longer halted */ + loop = 10; + do { + status = readl(&ehci_regs->status); + } while ((status & STS_HALT) && (--loop > 0)); + + if (!loop) { + dbgp_printk("ehci can be started\n"); + return -1; + } + dbgp_printk("ehci started\n"); + + /* Wait for a device to show up in the debug port */ + ret = ehci_wait_for_port(debug_port); + if (ret < 0) { + dbgp_printk("No device found in debug port\n"); + goto next_debug_port; + } + dbgp_printk("ehci wait for port done\n"); + + /* Enable the debug port */ + ctrl = readl(&ehci_debug->control); + ctrl |= DBGP_CLAIM; + writel(ctrl, &ehci_debug->control); + ctrl = readl(&ehci_debug->control); + if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) { + dbgp_printk("No device in debug port\n"); + writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control); + goto err; + } + dbgp_printk("debug ported enabled\n"); + + /* Completely transfer the debug device to the debug controller */ + portsc = readl(&ehci_regs->port_status[debug_port - 1]); + portsc &= ~PORT_PE; + writel(portsc, &ehci_regs->port_status[debug_port - 1]); + + dbgp_mdelay(100); + + /* Find the debug device and make it device number 127 */ + for (devnum = 0; devnum <= 127; devnum++) { + ret = dbgp_control_msg(devnum, + USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0, + &dbgp_desc, sizeof(dbgp_desc)); + if (ret > 0) + break; + } + if (devnum > 127) { + dbgp_printk("Could not find attached debug device\n"); + goto err; + } + if (ret < 0) { + dbgp_printk("Attached device is not a debug device\n"); + goto err; + } + dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint; + + /* Move the device to 127 if it isn't already there */ + if (devnum != USB_DEBUG_DEVNUM) { + ret = dbgp_control_msg(devnum, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0); + if (ret < 0) { + dbgp_printk("Could not move attached device to %d\n", + USB_DEBUG_DEVNUM); + goto err; + } + devnum = USB_DEBUG_DEVNUM; + dbgp_printk("debug device renamed to 127\n"); + } + + /* Enable the debug interface */ + ret = dbgp_control_msg(USB_DEBUG_DEVNUM, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0); + if (ret < 0) { + dbgp_printk(" Could not enable the debug device\n"); + goto err; + } + dbgp_printk("debug interface enabled\n"); + + /* Perform a small write to get the even/odd data state in sync + */ + ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ", 1); + if (ret < 0) { + dbgp_printk("dbgp_bulk_write failed: %d\n", ret); + goto err; + } + dbgp_printk("small write doned\n"); + + return 0; +err: + /* Things didn't work so remove my claim */ + ctrl = readl(&ehci_debug->control); + ctrl &= ~(DBGP_CLAIM | DBGP_OUT); + writel(ctrl, &ehci_debug->control); + return -1; + +next_debug_port: + port_map_tried |= (1<<(debug_port - 1)); + new_debug_port = ((debug_port-1+1)%n_ports) + 1; + if (port_map_tried != ((1<> 29) & 0x7; + bar = (bar * 4) + 0xc; + offset = (debug_port >> 16) & 0xfff; + dbgp_printk("bar: %02x offset: %03x\n", bar, offset); + if (bar != PCI_BASE_ADDRESS_0) { + dbgp_printk("only debug ports on bar 1 handled.\n"); + + return -1; + } + + bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); + dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset); + if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) { + dbgp_printk("only simple 32bit mmio bars supported\n"); + + return -1; + } + + /* double check if the mem space is enabled */ + byte = read_pci_config_byte(bus, slot, func, 0x04); + if (!(byte & 0x2)) { + byte |= 0x02; + write_pci_config_byte(bus, slot, func, 0x04, byte); + dbgp_printk("mmio for ehci enabled\n"); + } + + /* + * FIXME I don't have the bar size so just guess PAGE_SIZE is more + * than enough. 1K is the biggest I have seen. + */ + set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); + ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); + ehci_bar += bar_val & ~PAGE_MASK; + dbgp_printk("ehci_bar: %p\n", ehci_bar); + + ehci_caps = ehci_bar; + ehci_regs = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase)); + ehci_debug = ehci_bar + offset; + ehci_dev.bus = bus; + ehci_dev.slot = slot; + ehci_dev.func = func; + + detect_set_debug_port(); + + ret = ehci_setup(); + if (ret < 0) { + dbgp_printk("ehci_setup failed\n"); + ehci_debug = 0; + + return -1; + } + + return 0; +} + +static void early_dbgp_write(struct console *con, const char *str, u32 n) +{ + int chunk, ret; + + if (!ehci_debug) + return; + while (n > 0) { + chunk = n; + if (chunk > DBGP_MAX_PACKET) + chunk = DBGP_MAX_PACKET; + ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, + dbgp_endpoint_out, str, chunk); + str += chunk; + n -= chunk; + } +} + +static struct console early_dbgp_console = { + .name = "earlydbg", + .write = early_dbgp_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; +#endif + /* Console interface to a host file on AMD's SimNow! */ static int simnow_fd; @@ -165,6 +889,7 @@ enum { static noinline long simnow(long cmd, long a, long b, long c) { long ret; + asm volatile("cpuid" : "=a" (ret) : "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2)); @@ -174,6 +899,7 @@ static noinline long simnow(long cmd, long a, long b, long c) static void __init simnow_init(char *str) { char *fn = "klog"; + if (*str == '=') fn = ++str; /* error ignored */ @@ -208,10 +934,11 @@ asmlinkage void early_printk(const char *fmt, ...) va_end(ap); } -static int __initdata keep_early; static int __init setup_early_printk(char *buf) { + int keep_early; + if (!buf) return 0; @@ -219,8 +946,7 @@ static int __init setup_early_printk(char *buf) return 0; early_console_initialized = 1; - if (strstr(buf, "keep")) - keep_early = 1; + keep_early = (strstr(buf, "keep") != NULL); if (!strncmp(buf, "serial", 6)) { early_serial_init(buf + 6); @@ -238,6 +964,17 @@ static int __init setup_early_printk(char *buf) simnow_init(buf + 6); early_console = &simnow_console; keep_early = 1; +#ifdef CONFIG_EARLY_PRINTK_DBGP + } else if (!strncmp(buf, "dbgp", 4)) { + if (early_dbgp_init(buf+4) < 0) + return 0; + early_console = &early_dbgp_console; + /* + * usb subsys will reset ehci controller, so don't keep + * that early console + */ + keep_early = 0; +#endif #ifdef CONFIG_HVC_XEN } else if (!strncmp(buf, "xen", 3)) { early_console = &xenboot_console; @@ -251,4 +988,23 @@ static int __init setup_early_printk(char *buf) register_console(early_console); return 0; } + +void __init enable_debug_console(char *buf) +{ +#ifdef DBGP_DEBUG + struct console *old_early_console = NULL; + + if (early_console_initialized && early_console) { + old_early_console = early_console; + unregister_console(early_console); + early_console_initialized = 0; + } + + setup_early_printk(buf); + + if (early_console == old_early_console && old_early_console) + register_console(old_early_console); +#endif +} + early_param("earlyprintk", setup_early_printk); -- cgit v1.2.3 From a4dbc34d181e87a0d724dee365921e9251f831d4 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:14:28 -0700 Subject: x86: add setup_ioapic_ids for numaq in x86_quirks Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_32.c | 5 ++--- arch/x86/kernel/numaq_32.c | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 98e4db5373f..72ba06314c7 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -1728,10 +1729,8 @@ static void __init setup_ioapic_ids_from_mpc(void) unsigned char old_id; unsigned long flags; -#ifdef CONFIG_X86_NUMAQ - if (found_numaq) + if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids()) return; -#endif /* * Don't check I/O APIC IDs for xAPIC systems. They have diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index b8c45610b20..2434467ddf7 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c @@ -229,6 +229,12 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, } } +static int __init numaq_setup_ioapic_ids(void) +{ + /* so can skip it */ + return 1; +} + static struct x86_quirks numaq_x86_quirks __initdata = { .arch_pre_time_init = numaq_pre_time_init, .arch_time_init = NULL, @@ -243,6 +249,7 @@ static struct x86_quirks numaq_x86_quirks __initdata = { .mpc_oem_bus_info = mpc_oem_bus_info, .mpc_oem_pci_bus = mpc_oem_pci_bus, .smp_read_mpc_oem = smp_read_mpc_oem, + .setup_ioapic_ids = numaq_setup_ioapic_ids, }; void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, -- cgit v1.2.3 From 1176fa919292887aa738d317d61fe2bba4d764f2 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:21 -0700 Subject: x86: mach-bigsmp to bigsmp Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/bigsmp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index b31f2800638..df37fc9d6a2 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -12,10 +12,10 @@ #include #include #include -#include +#include #include -#include -#include +#include +#include #include static int dmi_bigsmp; /* can be set by dmi scanners */ -- cgit v1.2.3 From c7e7964c9828083aeb41c2664cbf5a32acbfa9d1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:33 -0700 Subject: x86: mach_es7000 to es7000 Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/es7000/Makefile | 5 + arch/x86/es7000/es7000.h | 114 +++++++++++++++++ arch/x86/es7000/es7000plat.c | 262 ++++++++++++++++++++++++++++++++++++++ arch/x86/mach-es7000/Makefile | 5 - arch/x86/mach-es7000/es7000.h | 114 ----------------- arch/x86/mach-es7000/es7000plat.c | 262 -------------------------------------- arch/x86/mach-generic/Makefile | 2 +- arch/x86/mach-generic/es7000.c | 10 +- 8 files changed, 387 insertions(+), 387 deletions(-) create mode 100644 arch/x86/es7000/Makefile create mode 100644 arch/x86/es7000/es7000.h create mode 100644 arch/x86/es7000/es7000plat.c delete mode 100644 arch/x86/mach-es7000/Makefile delete mode 100644 arch/x86/mach-es7000/es7000.h delete mode 100644 arch/x86/mach-es7000/es7000plat.c (limited to 'arch') diff --git a/arch/x86/es7000/Makefile b/arch/x86/es7000/Makefile new file mode 100644 index 00000000000..3ef8b43b62f --- /dev/null +++ b/arch/x86/es7000/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the linux kernel. +# + +obj-$(CONFIG_X86_ES7000) := es7000plat.o diff --git a/arch/x86/es7000/es7000.h b/arch/x86/es7000/es7000.h new file mode 100644 index 00000000000..4e62f6fa95b --- /dev/null +++ b/arch/x86/es7000/es7000.h @@ -0,0 +1,114 @@ +/* + * Written by: Garry Forsgren, Unisys Corporation + * Natalie Protasevich, Unisys Corporation + * This file contains the code to configure and interface + * with Unisys ES7000 series hardware system manager. + * + * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Unisys Corporation, Township Line & Union Meeting + * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: + * + * http://www.unisys.com + */ + +/* + * ES7000 chipsets + */ + +#define NON_UNISYS 0 +#define ES7000_CLASSIC 1 +#define ES7000_ZORRO 2 + + +#define MIP_REG 1 +#define MIP_PSAI_REG 4 + +#define MIP_BUSY 1 +#define MIP_SPIN 0xf0000 +#define MIP_VALID 0x0100000000000000ULL +#define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) + +#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) + +struct mip_reg_info { + unsigned long long mip_info; + unsigned long long delivery_info; + unsigned long long host_reg; + unsigned long long mip_reg; +}; + +struct part_info { + unsigned char type; + unsigned char length; + unsigned char part_id; + unsigned char apic_mode; + unsigned long snum; + char ptype[16]; + char sname[64]; + char pname[64]; +}; + +struct psai { + unsigned long long entry_type; + unsigned long long addr; + unsigned long long bep_addr; +}; + +struct es7000_mem_info { + unsigned char type; + unsigned char length; + unsigned char resv[6]; + unsigned long long start; + unsigned long long size; +}; + +struct es7000_oem_table { + unsigned long long hdr; + struct mip_reg_info mip; + struct part_info pif; + struct es7000_mem_info shm; + struct psai psai; +}; + +#ifdef CONFIG_ACPI + +struct oem_table { + struct acpi_table_header Header; + u32 OEMTableAddr; + u32 OEMTableSize; +}; + +extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); +#endif + +struct mip_reg { + unsigned long long off_0; + unsigned long long off_8; + unsigned long long off_10; + unsigned long long off_18; + unsigned long long off_20; + unsigned long long off_28; + unsigned long long off_30; + unsigned long long off_38; +}; + +#define MIP_SW_APIC 0x1020b +#define MIP_FUNC(VALUE) (VALUE & 0xff) + +extern int parse_unisys_oem (char *oemptr); +extern void setup_unisys(void); +extern int es7000_start_cpu(int cpu, unsigned long eip); +extern void es7000_sw_apic(void); diff --git a/arch/x86/es7000/es7000plat.c b/arch/x86/es7000/es7000plat.c new file mode 100644 index 00000000000..7789fde13c3 --- /dev/null +++ b/arch/x86/es7000/es7000plat.c @@ -0,0 +1,262 @@ +/* + * Written by: Garry Forsgren, Unisys Corporation + * Natalie Protasevich, Unisys Corporation + * This file contains the code to configure and interface + * with Unisys ES7000 series hardware system manager. + * + * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Unisys Corporation, Township Line & Union Meeting + * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: + * + * http://www.unisys.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "es7000.h" +#include + +/* + * ES7000 Globals + */ + +static volatile unsigned long *psai = NULL; +static struct mip_reg *mip_reg; +static struct mip_reg *host_reg; +static int mip_port; +static unsigned long mip_addr, host_addr; + +int es7000_plat; + +/* + * GSI override for ES7000 platforms. + */ + +static unsigned int base; + +static int +es7000_rename_gsi(int ioapic, int gsi) +{ + if (es7000_plat == ES7000_ZORRO) + return gsi; + + if (!base) { + int i; + for (i = 0; i < nr_ioapics; i++) + base += nr_ioapic_registers[i]; + } + + if (!ioapic && (gsi < 16)) + gsi += base; + return gsi; +} + +void __init +setup_unisys(void) +{ + /* + * Determine the generation of the ES7000 currently running. + * + * es7000_plat = 1 if the machine is a 5xx ES7000 box + * es7000_plat = 2 if the machine is a x86_64 ES7000 box + * + */ + if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2)) + es7000_plat = ES7000_ZORRO; + else + es7000_plat = ES7000_CLASSIC; + ioapic_renumber_irq = es7000_rename_gsi; +} + +/* + * Parse the OEM Table + */ + +int __init +parse_unisys_oem (char *oemptr) +{ + int i; + int success = 0; + unsigned char type, size; + unsigned long val; + char *tp = NULL; + struct psai *psaip = NULL; + struct mip_reg_info *mi; + struct mip_reg *host, *mip; + + tp = oemptr; + + tp += 8; + + for (i=0; i <= 6; i++) { + type = *tp++; + size = *tp++; + tp -= 2; + switch (type) { + case MIP_REG: + mi = (struct mip_reg_info *)tp; + val = MIP_RD_LO(mi->host_reg); + host_addr = val; + host = (struct mip_reg *)val; + host_reg = __va(host); + val = MIP_RD_LO(mi->mip_reg); + mip_port = MIP_PORT(mi->mip_info); + mip_addr = val; + mip = (struct mip_reg *)val; + mip_reg = __va(mip); + pr_debug("es7000_mipcfg: host_reg = 0x%lx \n", + (unsigned long)host_reg); + pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n", + (unsigned long)mip_reg); + success++; + break; + case MIP_PSAI_REG: + psaip = (struct psai *)tp; + if (tp != NULL) { + if (psaip->addr) + psai = __va(psaip->addr); + else + psai = NULL; + success++; + } + break; + default: + break; + } + tp += size; + } + + if (success < 2) { + es7000_plat = NON_UNISYS; + } else + setup_unisys(); + return es7000_plat; +} + +#ifdef CONFIG_ACPI +int __init +find_unisys_acpi_oem_table(unsigned long *oem_addr) +{ + struct acpi_table_header *header = NULL; + int i = 0; + while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { + if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { + struct oem_table *t = (struct oem_table *)header; + *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr, + t->OEMTableSize); + return 0; + } + } + return -1; +} +#endif + +static void +es7000_spin(int n) +{ + int i = 0; + + while (i++ < n) + rep_nop(); +} + +static int __init +es7000_mip_write(struct mip_reg *mip_reg) +{ + int status = 0; + int spin; + + spin = MIP_SPIN; + while (((unsigned long long)host_reg->off_38 & + (unsigned long long)MIP_VALID) != 0) { + if (--spin <= 0) { + printk("es7000_mip_write: Timeout waiting for Host Valid Flag"); + return -1; + } + es7000_spin(MIP_SPIN); + } + + memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); + outb(1, mip_port); + + spin = MIP_SPIN; + + while (((unsigned long long)mip_reg->off_38 & + (unsigned long long)MIP_VALID) == 0) { + if (--spin <= 0) { + printk("es7000_mip_write: Timeout waiting for MIP Valid Flag"); + return -1; + } + es7000_spin(MIP_SPIN); + } + + status = ((unsigned long long)mip_reg->off_0 & + (unsigned long long)0xffff0000000000ULL) >> 48; + mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & + (unsigned long long)~MIP_VALID); + return status; +} + +int +es7000_start_cpu(int cpu, unsigned long eip) +{ + unsigned long vect = 0, psaival = 0; + + if (psai == NULL) + return -1; + + vect = ((unsigned long)__pa(eip)/0x1000) << 16; + psaival = (0x1000000 | vect | cpu); + + while (*psai & 0x1000000) + ; + + *psai = psaival; + + return 0; + +} + +void __init +es7000_sw_apic(void) +{ + if (es7000_plat) { + int mip_status; + struct mip_reg es7000_mip_reg; + + printk("ES7000: Enabling APIC mode.\n"); + memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); + es7000_mip_reg.off_0 = MIP_SW_APIC; + es7000_mip_reg.off_38 = (MIP_VALID); + while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) + printk("es7000_sw_apic: command failed, status = %x\n", + mip_status); + return; + } +} diff --git a/arch/x86/mach-es7000/Makefile b/arch/x86/mach-es7000/Makefile deleted file mode 100644 index 3ef8b43b62f..00000000000 --- a/arch/x86/mach-es7000/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-$(CONFIG_X86_ES7000) := es7000plat.o diff --git a/arch/x86/mach-es7000/es7000.h b/arch/x86/mach-es7000/es7000.h deleted file mode 100644 index c8d5aa132fa..00000000000 --- a/arch/x86/mach-es7000/es7000.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Written by: Garry Forsgren, Unisys Corporation - * Natalie Protasevich, Unisys Corporation - * This file contains the code to configure and interface - * with Unisys ES7000 series hardware system manager. - * - * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Unisys Corporation, Township Line & Union Meeting - * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: - * - * http://www.unisys.com - */ - -/* - * ES7000 chipsets - */ - -#define NON_UNISYS 0 -#define ES7000_CLASSIC 1 -#define ES7000_ZORRO 2 - - -#define MIP_REG 1 -#define MIP_PSAI_REG 4 - -#define MIP_BUSY 1 -#define MIP_SPIN 0xf0000 -#define MIP_VALID 0x0100000000000000ULL -#define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) - -#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) - -struct mip_reg_info { - unsigned long long mip_info; - unsigned long long delivery_info; - unsigned long long host_reg; - unsigned long long mip_reg; -}; - -struct part_info { - unsigned char type; - unsigned char length; - unsigned char part_id; - unsigned char apic_mode; - unsigned long snum; - char ptype[16]; - char sname[64]; - char pname[64]; -}; - -struct psai { - unsigned long long entry_type; - unsigned long long addr; - unsigned long long bep_addr; -}; - -struct es7000_mem_info { - unsigned char type; - unsigned char length; - unsigned char resv[6]; - unsigned long long start; - unsigned long long size; -}; - -struct es7000_oem_table { - unsigned long long hdr; - struct mip_reg_info mip; - struct part_info pif; - struct es7000_mem_info shm; - struct psai psai; -}; - -#ifdef CONFIG_ACPI - -struct oem_table { - struct acpi_table_header Header; - u32 OEMTableAddr; - u32 OEMTableSize; -}; - -extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); -#endif - -struct mip_reg { - unsigned long long off_0; - unsigned long long off_8; - unsigned long long off_10; - unsigned long long off_18; - unsigned long long off_20; - unsigned long long off_28; - unsigned long long off_30; - unsigned long long off_38; -}; - -#define MIP_SW_APIC 0x1020b -#define MIP_FUNC(VALUE) (VALUE & 0xff) - -extern int parse_unisys_oem (char *oemptr); -extern void setup_unisys(void); -extern int es7000_start_cpu(int cpu, unsigned long eip); -extern void es7000_sw_apic(void); diff --git a/arch/x86/mach-es7000/es7000plat.c b/arch/x86/mach-es7000/es7000plat.c deleted file mode 100644 index 50189af14b8..00000000000 --- a/arch/x86/mach-es7000/es7000plat.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Written by: Garry Forsgren, Unisys Corporation - * Natalie Protasevich, Unisys Corporation - * This file contains the code to configure and interface - * with Unisys ES7000 series hardware system manager. - * - * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Unisys Corporation, Township Line & Union Meeting - * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: - * - * http://www.unisys.com - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "es7000.h" -#include - -/* - * ES7000 Globals - */ - -static volatile unsigned long *psai = NULL; -static struct mip_reg *mip_reg; -static struct mip_reg *host_reg; -static int mip_port; -static unsigned long mip_addr, host_addr; - -int es7000_plat; - -/* - * GSI override for ES7000 platforms. - */ - -static unsigned int base; - -static int -es7000_rename_gsi(int ioapic, int gsi) -{ - if (es7000_plat == ES7000_ZORRO) - return gsi; - - if (!base) { - int i; - for (i = 0; i < nr_ioapics; i++) - base += nr_ioapic_registers[i]; - } - - if (!ioapic && (gsi < 16)) - gsi += base; - return gsi; -} - -void __init -setup_unisys(void) -{ - /* - * Determine the generation of the ES7000 currently running. - * - * es7000_plat = 1 if the machine is a 5xx ES7000 box - * es7000_plat = 2 if the machine is a x86_64 ES7000 box - * - */ - if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2)) - es7000_plat = ES7000_ZORRO; - else - es7000_plat = ES7000_CLASSIC; - ioapic_renumber_irq = es7000_rename_gsi; -} - -/* - * Parse the OEM Table - */ - -int __init -parse_unisys_oem (char *oemptr) -{ - int i; - int success = 0; - unsigned char type, size; - unsigned long val; - char *tp = NULL; - struct psai *psaip = NULL; - struct mip_reg_info *mi; - struct mip_reg *host, *mip; - - tp = oemptr; - - tp += 8; - - for (i=0; i <= 6; i++) { - type = *tp++; - size = *tp++; - tp -= 2; - switch (type) { - case MIP_REG: - mi = (struct mip_reg_info *)tp; - val = MIP_RD_LO(mi->host_reg); - host_addr = val; - host = (struct mip_reg *)val; - host_reg = __va(host); - val = MIP_RD_LO(mi->mip_reg); - mip_port = MIP_PORT(mi->mip_info); - mip_addr = val; - mip = (struct mip_reg *)val; - mip_reg = __va(mip); - pr_debug("es7000_mipcfg: host_reg = 0x%lx \n", - (unsigned long)host_reg); - pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n", - (unsigned long)mip_reg); - success++; - break; - case MIP_PSAI_REG: - psaip = (struct psai *)tp; - if (tp != NULL) { - if (psaip->addr) - psai = __va(psaip->addr); - else - psai = NULL; - success++; - } - break; - default: - break; - } - tp += size; - } - - if (success < 2) { - es7000_plat = NON_UNISYS; - } else - setup_unisys(); - return es7000_plat; -} - -#ifdef CONFIG_ACPI -int __init -find_unisys_acpi_oem_table(unsigned long *oem_addr) -{ - struct acpi_table_header *header = NULL; - int i = 0; - while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { - if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { - struct oem_table *t = (struct oem_table *)header; - *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr, - t->OEMTableSize); - return 0; - } - } - return -1; -} -#endif - -static void -es7000_spin(int n) -{ - int i = 0; - - while (i++ < n) - rep_nop(); -} - -static int __init -es7000_mip_write(struct mip_reg *mip_reg) -{ - int status = 0; - int spin; - - spin = MIP_SPIN; - while (((unsigned long long)host_reg->off_38 & - (unsigned long long)MIP_VALID) != 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for Host Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); - outb(1, mip_port); - - spin = MIP_SPIN; - - while (((unsigned long long)mip_reg->off_38 & - (unsigned long long)MIP_VALID) == 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for MIP Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - status = ((unsigned long long)mip_reg->off_0 & - (unsigned long long)0xffff0000000000ULL) >> 48; - mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & - (unsigned long long)~MIP_VALID); - return status; -} - -int -es7000_start_cpu(int cpu, unsigned long eip) -{ - unsigned long vect = 0, psaival = 0; - - if (psai == NULL) - return -1; - - vect = ((unsigned long)__pa(eip)/0x1000) << 16; - psaival = (0x1000000 | vect | cpu); - - while (*psai & 0x1000000) - ; - - *psai = psaival; - - return 0; - -} - -void __init -es7000_sw_apic(void) -{ - if (es7000_plat) { - int mip_status; - struct mip_reg es7000_mip_reg; - - printk("ES7000: Enabling APIC mode.\n"); - memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); - es7000_mip_reg.off_0 = MIP_SW_APIC; - es7000_mip_reg.off_38 = (MIP_VALID); - while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) - printk("es7000_sw_apic: command failed, status = %x\n", - mip_status); - return; - } -} diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile index 0dbd7803a1d..4706de7676b 100644 --- a/arch/x86/mach-generic/Makefile +++ b/arch/x86/mach-generic/Makefile @@ -9,4 +9,4 @@ obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT) += summit.o obj-$(CONFIG_X86_BIGSMP) += bigsmp.o obj-$(CONFIG_X86_ES7000) += es7000.o -obj-$(CONFIG_X86_ES7000) += ../../x86/mach-es7000/ +obj-$(CONFIG_X86_ES7000) += ../../x86/es7000/ diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 9b30547d746..520cca0ee04 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -11,12 +11,12 @@ #include #include #include -#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include static int probe_es7000(void) { -- cgit v1.2.3 From e8c48efdb971cfb1b043076cf68be535d461a20b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:44 -0700 Subject: x86: mach_summit to summit Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/summit_32.c | 2 +- arch/x86/mach-generic/summit.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c index d67ce5f044b..7b987852e87 100644 --- a/arch/x86/kernel/summit_32.c +++ b/arch/x86/kernel/summit_32.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include static struct rio_table_hdr *rio_table_hdr __initdata; static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata; diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 752edd96b1b..6ad6b67a723 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -11,11 +11,11 @@ #include #include #include -#include +#include #include -#include -#include -#include +#include +#include +#include static int probe_summit(void) { -- cgit v1.2.3 From edb181ac4b0c7c1240503da46349a3fb69af9ef6 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:55 -0700 Subject: x86: mach-numaq to numaq Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/numaq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 95c07efff6b..8cf58394975 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -11,12 +11,12 @@ #include #include #include -#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include static int mps_oem_check(struct mp_config_table *mpc, char *oem, -- cgit v1.2.3 From 39eacc20f93614f7bab63eb1d45060503afc46d0 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Fri, 25 Jul 2008 23:30:13 +0800 Subject: arch/x86/kernel/visws_quirks.c: Removed duplicated #include Removed duplicated #include in arch/x86/kernel/visws_quirks.c. asm/apic.h asm/arch_hooks.h asm/io.h asm/visws/cobalt.h asm/visws/lithium.h asm/visws/piix4.h linux/init.h linux/interrupt.h linux/smp.h Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/visws_quirks.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 41e01b145c4..0c75691bcf5 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -29,41 +29,26 @@ #include #include #include -#include #include #include #include "mach_apic.h" -#include -#include - #include -#include -#include -#include -#include #include #include -#include #include -#include #include #include -#include #include #include extern int no_broadcast; -#include #include -#include -#include -#include char visws_board_type = -1; char visws_board_rev = -1; -- cgit v1.2.3 From 9749986a878e91182ff027ff0010ab8e3211031a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 26 Jul 2008 17:28:11 +0200 Subject: x86: usb debug port early console, fix fix: arch/x86/kernel/built-in.o: In function `nvidia_set_debug_port': early_printk.c:(.text+0xf8b1): undefined reference to `read_pci_config' early_printk.c:(.text+0xf8dc): undefined reference to `write_pci_config' arch/x86/kernel/built-in.o: In function `setup_early_printk': early_printk.c:(.init.text+0x5487): undefined reference to `early_pci_allowed' early_printk.c:(.init.text+0x54cb): undefined reference to `read_pci_config' early_printk.c:(.init.text+0x54ec): undefined reference to `read_pci_config_16' [...] Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 93422d2ecf6..2a3dfbd5e67 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -46,7 +46,7 @@ config EARLY_PRINTK config EARLY_PRINTK_DBGP bool "Early printk via EHCI debug port" default n - depends on EARLY_PRINTK + depends on EARLY_PRINTK && PCI help Write kernel log output directly into the EHCI debug port. -- cgit v1.2.3 From b56afe1d41653fb07ab1b5af5ccc12001c4dd5a0 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 24 Jul 2008 12:15:45 -0300 Subject: x86, xen: Use native_pte_flags instead of native_pte_val for .pte_flags Using native_pte_val triggers the BUG_ON() in the paravirt_ops version of pte_flags(). Signed-off-by: Eduardo Habkost Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 06219e60e9c..e2767c28dac 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1347,7 +1347,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { .ptep_modify_prot_commit = __ptep_modify_prot_commit, .pte_val = xen_pte_val, - .pte_flags = native_pte_val, + .pte_flags = native_pte_flags, .pgd_val = xen_pgd_val, .make_pte = xen_make_pte, -- cgit v1.2.3 From 3964cd3a6721f18ef1dd67b9a0a89dc5b36683b9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 26 Jul 2008 19:35:20 +0200 Subject: x86: visws_quirks, fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/visws_quirks.c: In function ‘visws_early_detect’: arch/x86/kernel/visws_quirks.c:290: error: ‘skip_ioapic_setup’ undeclared (first use in this function) arch/x86/kernel/visws_quirks.c:290: error: (Each undeclared identifier is reported only once arch/x86/kernel/visws_quirks.c:290: error: for each function it appears in.) Signed-off-by: Ingo Molnar --- arch/x86/kernel/visws_quirks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 0c75691bcf5..3059eb45a91 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 36a033082b5243d45d508c5ccd47a754edbc6821 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 14 Mar 2008 17:46:38 -0700 Subject: x86: tracehook_signal_handler This makes the x86 signal handling code use tracehook_signal_handler() in place of calling into ptrace guts. The call is moved after the sa_mask processing, but there is no other change. This cleanup doesn't matter to existing debuggers, but is the sensible thing: have all facets of the handler setup complete before the debugger inspects the task again. Signed-off-by: Roland McGrath --- arch/x86/kernel/signal_32.c | 6 ++++-- arch/x86/kernel/signal_64.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd893..22aae1683c1 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -558,8 +559,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * handler too. */ regs->flags &= ~X86_EFLAGS_TF; - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); @@ -568,6 +567,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + return 0; } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index b45ef8ddd65..3beb2db88c5 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -444,8 +445,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * handler too. */ regs->flags &= ~X86_EFLAGS_TF; - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -453,6 +452,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); } return ret; -- cgit v1.2.3 From eeea3c3ff8af7f6960a0515d46dff6479bdb91f9 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 16 Mar 2008 23:36:28 -0700 Subject: x86: tracehook syscall This changes x86 syscall tracing to use the new tracehook.h entry points. There is no change, only cleanup. Signed-off-by: Roland McGrath --- arch/x86/kernel/ptrace.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e37dccce85d..19a7d2c4056 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1375,30 +1376,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) force_sig_info(SIGTRAP, &info, tsk); } -static void syscall_trace(struct pt_regs *regs) -{ - if (!(current->ptrace & PT_PTRACED)) - return; - -#if 0 - printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n", - current->comm, - regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0), - current_thread_info()->flags, current->ptrace); -#endif - - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} #ifdef CONFIG_X86_32 # define IS_IA32 1 @@ -1432,8 +1409,9 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs) if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) ret = -1L; - if (ret || test_thread_flag(TIF_SYSCALL_TRACE)) - syscall_trace(regs); + if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) && + tracehook_report_syscall_entry(regs)) + ret = -1L; if (unlikely(current->audit_context)) { if (IS_IA32) @@ -1459,7 +1437,7 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (test_thread_flag(TIF_SYSCALL_TRACE)) - syscall_trace(regs); + tracehook_report_syscall_exit(regs, 0); /* * If TIF_SYSCALL_EMU is set, we only get here because of @@ -1475,6 +1453,6 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) * system call instruction. */ if (test_thread_flag(TIF_SINGLESTEP) && - (current->ptrace & PT_PTRACED)) + tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) send_sigtrap(current, regs, 0); } -- cgit v1.2.3 From 4dfcbb997aa9f3a6a3ed8c192f0dac28b027e08f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 19 Apr 2008 15:37:09 -0700 Subject: x86 signals: use asm/syscall.h Replace local inlines with the asm/syscall.h interfaces that do the same things. Signed-off-by: Roland McGrath --- arch/x86/kernel/signal_64.c | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 3beb2db88c5..cb7cf0216ab 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "sigframe.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -346,35 +347,6 @@ give_sigsegv: return -EFAULT; } -/* - * Return -1L or the syscall number that @regs is executing. - */ -static long current_syscall(struct pt_regs *regs) -{ - /* - * We always sign-extend a -1 value being set here, - * so this is always either -1L or a syscall number. - */ - return regs->orig_ax; -} - -/* - * Return a value that is -EFOO if the system call in @regs->orig_ax - * returned an error. This only works for @regs from @current. - */ -static long current_syscall_ret(struct pt_regs *regs) -{ -#ifdef CONFIG_IA32_EMULATION - if (test_thread_flag(TIF_IA32)) - /* - * Sign-extend the value so (int)-EFOO becomes (long)-EFOO - * and will match correctly in comparisons. - */ - return (int) regs->ax; -#endif - return regs->ax; -} - /* * OK, we're invoking a handler */ @@ -386,9 +358,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, int ret; /* Are we from a system call? */ - if (current_syscall(regs) >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* If so, check system call restarting.. */ - switch (current_syscall_ret(regs)) { + switch (syscall_get_error(current, regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->ax = -EINTR; @@ -511,9 +483,9 @@ static void do_signal(struct pt_regs *regs) } /* Did we come from a system call? */ - if (current_syscall(regs) >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* Restart the system call - no handlers present */ - switch (current_syscall_ret(regs)) { + switch (syscall_get_error(current, regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: -- cgit v1.2.3 From 59e52130f04537d2c80ea44bb007cadd1ad29543 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 19 Apr 2008 19:10:57 -0700 Subject: x86: tracehook: TIF_NOTIFY_RESUME This adds TIF_NOTIFY_RESUME support for x86, both 64-bit and 32-bit. When set, we call tracehook_notify_resume() on the way to user mode. Signed-off-by: Roland McGrath --- arch/x86/kernel/signal_32.c | 5 +++++ arch/x86/kernel/signal_64.c | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 22aae1683c1..4445d26efd4 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -663,5 +663,10 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } + clear_thread_flag(TIF_IRET); } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index cb7cf0216ab..d01e3f6ef26 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -523,6 +523,11 @@ void do_notify_resume(struct pt_regs *regs, void *unused, /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); + + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) -- cgit v1.2.3 From 99bbc4b1e677ac695431e8d9c8e710ef391c567f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 20 Apr 2008 14:35:12 -0700 Subject: x86: tracehook: CONFIG_HAVE_ARCH_TRACEHOOK The x86 arch code has all the prerequisites, so set HAVE_ARCH_TRACEHOOK. Signed-off-by: Roland McGrath --- arch/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b6fa2877b17..f463a8a3b21 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -30,6 +30,7 @@ config X86 select HAVE_FTRACE select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_ARCH_KGDB if !X86_VOYAGER + select HAVE_ARCH_TRACEHOOK select HAVE_EFFICIENT_UNALIGNED_ACCESS config ARCH_DEFCONFIG -- cgit v1.2.3 From d25ae38b7e005af03843833bbd811ffe8c5f8cb4 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 19:39:03 -0700 Subject: x86: add apic probe for genapic 64bit - fix intr_remapping_enabled get assigned later, so need to check that in setup_apic_routing Signed-off-by: Yinghai Lu Cc: Jack Steiner Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_64.c | 6 ++++++ arch/x86/kernel/genx2apic_cluster.c | 2 +- arch/x86/kernel/genx2apic_phys.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index b3ba969c50d..6c9bfc9e1e9 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,11 @@ static struct genapic *apic_probe[] __initdata = { */ void __init setup_apic_routing(void) { + if (genapic == &apic_x2apic_phys || genapic == &apic_x2apic_cluster) { + if (!intr_remapping_enabled) + genapic = &apic_flat; + } + if (genapic == &apic_flat) { if (max_physical_apicid >= 8) genapic = &apic_physflat; diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index ef3f3182d50..fed9f68efd6 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -14,7 +14,7 @@ DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - if (cpu_has_x2apic && intr_remapping_enabled) + if (cpu_has_x2apic) return 1; return 0; diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 3229c68aedd..958d537b4cc 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -21,7 +21,7 @@ early_param("x2apic_phys", set_x2apic_phys_mode); static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys) + if (cpu_has_x2apic && x2apic_phys) return 1; return 0; -- cgit v1.2.3 From a05d2ebab28011c2f3f520833f4bfdd2fd1b9c02 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 27 Jul 2008 08:45:02 -0700 Subject: xen: fix allocation and use of large ldts When the ldt gets to more than 1 page in size, the kernel uses vmalloc to allocate it. This means that: - when making the ldt RO, we must update the pages in both the vmalloc mapping and the linear mapping to make sure there are no RW aliases. - we need to use arbitrary_virt_to_machine to compute the machine addr for each update Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 51 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e2767c28dac..b011e4a5dbb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -325,24 +325,55 @@ static unsigned long xen_store_tr(void) return 0; } +/* + * If 'v' is a vmalloc mapping, then find the linear mapping of the + * page (if any) and also set its protections to match: + */ +static void set_aliased_prot(void *v, pgprot_t prot) +{ + int level; + pte_t *ptep; + pte_t pte; + unsigned long pfn; + struct page *page; + + ptep = lookup_address((unsigned long)v, &level); + BUG_ON(ptep == NULL); + + pfn = pte_pfn(*ptep); + page = pfn_to_page(pfn); + + pte = pfn_pte(pfn, prot); + + if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0)) + BUG(); + + if (!PageHighMem(page)) { + void *av = __va(PFN_PHYS(pfn)); + + if (av != v) + if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0)) + BUG(); + } else + kmap_flush_unused(); +} + static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) { - unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); - void *v = ldt; + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; int i; - for(i = 0; i < pages; i += PAGE_SIZE) - make_lowmem_page_readonly(v + i); + for(i = 0; i < entries; i += entries_per_page) + set_aliased_prot(ldt + i, PAGE_KERNEL_RO); } static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) { - unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); - void *v = ldt; + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; int i; - for(i = 0; i < pages; i += PAGE_SIZE) - make_lowmem_page_readwrite(v + i); + for(i = 0; i < entries; i += entries_per_page) + set_aliased_prot(ldt + i, PAGE_KERNEL); } static void xen_set_ldt(const void *addr, unsigned entries) @@ -446,7 +477,7 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, const void *ptr) { unsigned long lp = (unsigned long)&dt[entrynum]; - xmaddr_t mach_lp = virt_to_machine(lp); + xmaddr_t mach_lp = arbitrary_virt_to_machine(lp); u64 entry = *(u64 *)ptr; preempt_disable(); @@ -579,7 +610,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry, } static void xen_load_sp0(struct tss_struct *tss, - struct thread_struct *thread) + struct thread_struct *thread) { struct multicall_space mcs = xen_mc_entry(0); MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); -- cgit v1.2.3 From 7225e75144b9718cbbe1820d9c011c809d5773fd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 26 Jul 2008 17:54:22 -0700 Subject: documentation: move mtrr.txt to Doc/x86/ subdir Move mtrr.txt to the Documentation/x86/ subdirectory. Add 00-INDEX to the Documentation/x86/ subdirectory. Signed-off-by: Randy Dunlap Cc: Adrian Bunk Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 03980cb0429..06f935469d0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1131,7 +1131,7 @@ config MTRR You can safely say Y even if your machine doesn't have MTRRs, you'll just add about 9 KB to your kernel. - See for more information. + See for more information. config MTRR_SANITIZER bool -- cgit v1.2.3 From 8cb22bcb1f3ef70d4d48092e9b057175ad9ec78d Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Fri, 18 Jul 2008 16:03:52 -0500 Subject: x86: L3 cache index disable for 2.6.26 New versions of AMD processors have support to disable parts of their L3 caches if too many MCEs are generated by the L3 cache. This patch provides a /sysfs interface under the cache hierarchy to display which caches indices are disabled (if any) and to monitoring applications to disable a cache index. This patch does not set an automatic policy to disable the L3 cache. Policy decisions would need to be made by a RAS handler. This patch merely makes it easier to see what indices are currently disabled. Signed-off-by: Mark Langsdorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 87 ++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index ff517f0b8cc..d6ea50e270e 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -16,6 +16,7 @@ #include #include +#include #define LVL_1_INST 1 #define LVL_1_DATA 2 @@ -130,6 +131,7 @@ struct _cpuid4_info { union _cpuid4_leaf_ebx ebx; union _cpuid4_leaf_ecx ecx; unsigned long size; + unsigned long can_disable; cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */ }; @@ -251,6 +253,13 @@ static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, (ebx->split.ways_of_associativity + 1) - 1; } +static void __cpuinit amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) +{ + if (index < 3) + return; + this_leaf->can_disable = 1; +} + static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) { union _cpuid4_leaf_eax eax; @@ -258,9 +267,12 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le union _cpuid4_leaf_ecx ecx; unsigned edx; - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { amd_cpuid4(index, &eax, &ebx, &ecx); - else + if (boot_cpu_data.x86 >= 0x10) + amd_check_l3_disable(index, this_leaf); + + } else cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); if (eax.split.type == CACHE_TYPE_NULL) return -EIO; /* better error ? */ @@ -637,6 +649,61 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { } } +#define to_object(k) container_of(k, struct _index_kobject, kobj) +#define to_attr(a) container_of(a, struct _cache_attr, attr) + +static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) +{ + struct pci_dev *dev; + if (this_leaf->can_disable) { + int i; + ssize_t ret = 0; + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + dev = k8_northbridges[node]; + + for (i = 0; i < 2; i++) { + unsigned int reg; + pci_read_config_dword(dev, 0x1BC + i * 4, ®); + ret += sprintf(buf, "%sEntry: %d\n", buf, i); + ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", + buf, + reg & 0x80000000 ? "Disabled" : "Allowed", + reg & 0x40000000 ? "Disabled" : "Allowed"); + ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", buf, + (reg & 0x30000) >> 16, reg & 0xfff); + + } + return ret; + } + return sprintf(buf, "Feature not enabled\n"); +} + +static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) +{ + struct pci_dev *dev; + if (this_leaf->can_disable) { + /* write the MSR value */ + unsigned int ret; + unsigned int index, val; + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + dev = k8_northbridges[node]; + + if (strlen(buf) > 15) + return -EINVAL; + ret = sscanf(buf, "%x %x", &index, &val); + if (ret != 2) + return -EINVAL; + if (index > 1) + return -EINVAL; + val |= 0xc0000000; + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); + wbinvd(); + pci_write_config_dword(dev, 0x1BC + index * 4, val); + return 1; + } + return 0; +} + struct _cache_attr { struct attribute attr; ssize_t (*show)(struct _cpuid4_info *, char *); @@ -657,6 +724,8 @@ define_one_ro(size); define_one_ro(shared_cpu_map); define_one_ro(shared_cpu_list); +static struct _cache_attr cache_disable = __ATTR(cache_disable, 0644, show_cache_disable, store_cache_disable); + static struct attribute * default_attrs[] = { &type.attr, &level.attr, @@ -667,12 +736,10 @@ static struct attribute * default_attrs[] = { &size.attr, &shared_cpu_map.attr, &shared_cpu_list.attr, + &cache_disable.attr, NULL }; -#define to_object(k) container_of(k, struct _index_kobject, kobj) -#define to_attr(a) container_of(a, struct _cache_attr, attr) - static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf) { struct _cache_attr *fattr = to_attr(attr); @@ -689,7 +756,15 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf) static ssize_t store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { - return 0; + struct _cache_attr *fattr = to_attr(attr); + struct _index_kobject *this_leaf = to_object(kobj); + ssize_t ret; + + ret = fattr->store ? + fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), + buf, count) : + 0; + return ret; } static struct sysfs_ops sysfs_ops = { -- cgit v1.2.3 From 7a4983bb5f94f6521aa3236fe5c035cf9bef543f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 21 Jul 2008 13:34:21 +0200 Subject: x86: L3 cache index disable for 2.6.26, cleanups No change in functionality. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 115 ++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 54 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index d6ea50e270e..a61c9e399ba 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -253,14 +253,16 @@ static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, (ebx->split.ways_of_associativity + 1) - 1; } -static void __cpuinit amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) +static void __cpuinit +amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) { if (index < 3) return; this_leaf->can_disable = 1; } -static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) +static int +__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) { union _cpuid4_leaf_eax eax; union _cpuid4_leaf_ebx ebx; @@ -271,19 +273,20 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le amd_cpuid4(index, &eax, &ebx, &ecx); if (boot_cpu_data.x86 >= 0x10) amd_check_l3_disable(index, this_leaf); - - } else - cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); + } else { + cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); + } + if (eax.split.type == CACHE_TYPE_NULL) return -EIO; /* better error ? */ this_leaf->eax = eax; this_leaf->ebx = ebx; this_leaf->ecx = ecx; - this_leaf->size = (ecx.split.number_of_sets + 1) * - (ebx.split.coherency_line_size + 1) * - (ebx.split.physical_line_partition + 1) * - (ebx.split.ways_of_associativity + 1); + this_leaf->size = (ecx.split.number_of_sets + 1) * + (ebx.split.coherency_line_size + 1) * + (ebx.split.physical_line_partition + 1) * + (ebx.split.ways_of_associativity + 1); return 0; } @@ -649,59 +652,63 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { } } -#define to_object(k) container_of(k, struct _index_kobject, kobj) -#define to_attr(a) container_of(a, struct _cache_attr, attr) +#define to_object(k) container_of(k, struct _index_kobject, kobj) +#define to_attr(a) container_of(a, struct _cache_attr, attr) static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) { - struct pci_dev *dev; - if (this_leaf->can_disable) { - int i; - ssize_t ret = 0; - int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - dev = k8_northbridges[node]; - - for (i = 0; i < 2; i++) { - unsigned int reg; - pci_read_config_dword(dev, 0x1BC + i * 4, ®); - ret += sprintf(buf, "%sEntry: %d\n", buf, i); - ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", - buf, - reg & 0x80000000 ? "Disabled" : "Allowed", - reg & 0x40000000 ? "Disabled" : "Allowed"); - ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", buf, - (reg & 0x30000) >> 16, reg & 0xfff); + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + struct pci_dev *dev = k8_northbridges[node]; + ssize_t ret = 0; + int i; - } - return ret; + if (!this_leaf->can_disable) + return sprintf(buf, "Feature not enabled\n"); + + for (i = 0; i < 2; i++) { + unsigned int reg; + + pci_read_config_dword(dev, 0x1BC + i * 4, ®); + + ret += sprintf(buf, "%sEntry: %d\n", buf, i); + ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", + buf, + reg & 0x80000000 ? "Disabled" : "Allowed", + reg & 0x40000000 ? "Disabled" : "Allowed"); + ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", + buf, (reg & 0x30000) >> 16, reg & 0xfff); } - return sprintf(buf, "Feature not enabled\n"); + return ret; } -static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) +static ssize_t +store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, + size_t count) { - struct pci_dev *dev; - if (this_leaf->can_disable) { - /* write the MSR value */ - unsigned int ret; - unsigned int index, val; - int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - dev = k8_northbridges[node]; - - if (strlen(buf) > 15) - return -EINVAL; - ret = sscanf(buf, "%x %x", &index, &val); - if (ret != 2) - return -EINVAL; - if (index > 1) - return -EINVAL; - val |= 0xc0000000; - pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); - wbinvd(); - pci_write_config_dword(dev, 0x1BC + index * 4, val); - return 1; - } - return 0; + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + struct pci_dev *dev = k8_northbridges[node]; + unsigned int ret, index, val; + + if (!this_leaf->can_disable) + return 0; + + /* write the MSR value */ + + if (strlen(buf) > 15) + return -EINVAL; + + ret = sscanf(buf, "%x %x", &index, &val); + if (ret != 2) + return -EINVAL; + if (index > 1) + return -EINVAL; + + val |= 0xc0000000; + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); + wbinvd(); + pci_write_config_dword(dev, 0x1BC + index * 4, val); + + return 1; } struct _cache_attr { -- cgit v1.2.3 From a24e8d36f5fc047dac9af6200322ed393f2e3175 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Tue, 22 Jul 2008 13:06:02 -0500 Subject: x86: L3 cache index disable for 2.6.26 On Monday 21 July 2008, Ingo Molnar wrote: > > applied to tip/x86/cpu, thanks Mark. > > > > I've done some coding style fixes for the new functions you've > > introduced, see that commit below. > > -tip testing found the following build failure: > > arch/x86/kernel/built-in.o: In function `show_cache_disable': > intel_cacheinfo.c:(.text+0xbbf2): undefined reference to `k8_northbridges' > arch/x86/kernel/built-in.o: In function `store_cache_disable': > intel_cacheinfo.c:(.text+0xbd91): undefined reference to `k8_northbridges' > > please send a delta fix patch against the tip/x86/cpu branch: > > http://people.redhat.com/mingo/tip.git/README > > which has your patch plus the cleanup applied. delta fix patch follows. It removes the dependency on k8_northbridges. -Mark Langsdorf Operating System Research Center AMD Signed-off-by: Mark Langsdorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 43 +++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index a61c9e399ba..a0c6c6ffed4 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -13,10 +13,10 @@ #include #include #include +#include #include #include -#include #define LVL_1_INST 1 #define LVL_1_DATA 2 @@ -135,6 +135,12 @@ struct _cpuid4_info { cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */ }; +static struct pci_device_id k8_nb_id[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, + {} +}; + unsigned short num_cache_leaves; /* AMD doesn't have CPUID4. Emulate it here to report the same @@ -655,16 +661,39 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { #define to_object(k) container_of(k, struct _index_kobject, kobj) #define to_attr(a) container_of(a, struct _cache_attr, attr) +static struct pci_dev *get_k8_northbridge(int node) +{ + struct pci_dev *dev = NULL; + int i; + + for (i = 0; i <= node; i++) { + do { + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + if (!dev) + break; + } while (!pci_match_id(&k8_nb_id[0], dev)); + if (!dev) + break; + } + return dev; +} + static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) { int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - struct pci_dev *dev = k8_northbridges[node]; + struct pci_dev *dev = NULL; ssize_t ret = 0; int i; if (!this_leaf->can_disable) return sprintf(buf, "Feature not enabled\n"); + dev = get_k8_northbridge(node); + if (!dev) { + printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n"); + return -EINVAL; + } + for (i = 0; i < 2; i++) { unsigned int reg; @@ -686,14 +715,12 @@ store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) { int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - struct pci_dev *dev = k8_northbridges[node]; + struct pci_dev *dev = NULL; unsigned int ret, index, val; if (!this_leaf->can_disable) return 0; - /* write the MSR value */ - if (strlen(buf) > 15) return -EINVAL; @@ -704,6 +731,12 @@ store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, return -EINVAL; val |= 0xc0000000; + dev = get_k8_northbridge(node); + if (!dev) { + printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n"); + return -EINVAL; + } + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); wbinvd(); pci_write_config_dword(dev, 0x1BC + index * 4, val); -- cgit v1.2.3 From cdcf772ed163651cacac8098b4974aba7f9e1c73 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 28 Jul 2008 16:20:08 +0200 Subject: x86 l3 cache index disable for 2 6 26 fix Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 39 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index a0c6c6ffed4..535d662716d 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -1,8 +1,8 @@ /* - * Routines to indentify caches on Intel CPU. + * Routines to indentify caches on Intel CPU. * - * Changes: - * Venkatesh Pallipadi : Adding cache identification through cpuid(4) + * Changes: + * Venkatesh Pallipadi : Adding cache identification through cpuid(4) * Ashok Raj : Work with CPU hotplug infrastructure. * Andi Kleen / Andreas Herrmann : CPUID4 emulation on AMD. */ @@ -136,9 +136,9 @@ struct _cpuid4_info { }; static struct pci_device_id k8_nb_id[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, - {} + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, + {} }; unsigned short num_cache_leaves; @@ -190,9 +190,10 @@ static unsigned short assocs[] __cpuinitdata = { static unsigned char levels[] __cpuinitdata = { 1, 1, 2, 3 }; static unsigned char types[] __cpuinitdata = { 1, 2, 3, 3 }; -static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, - union _cpuid4_leaf_ebx *ebx, - union _cpuid4_leaf_ecx *ecx) +static void __cpuinit +amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, + union _cpuid4_leaf_ebx *ebx, + union _cpuid4_leaf_ecx *ecx) { unsigned dummy; unsigned line_size, lines_per_tag, assoc, size_in_kb; @@ -264,7 +265,7 @@ amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) { if (index < 3) return; - this_leaf->can_disable = 1; + this_leaf->can_disable = 1; } static int @@ -474,7 +475,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) /* pointer to _cpuid4_info array (for each cache leaf) */ static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info); -#define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y])) +#define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y])) #ifdef CONFIG_SMP static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) @@ -511,7 +512,7 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) this_leaf = CPUID4_INFO_IDX(cpu, index); for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) { - sibling_leaf = CPUID4_INFO_IDX(sibling, index); + sibling_leaf = CPUID4_INFO_IDX(sibling, index); cpu_clear(cpu, sibling_leaf->shared_cpu_map); } } @@ -593,7 +594,7 @@ struct _index_kobject { /* pointer to array of kobjects for cpuX/cache/indexY */ static DEFINE_PER_CPU(struct _index_kobject *, index_kobject); -#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(index_kobject, x))[y])) +#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(index_kobject, x))[y])) #define show_one_plus(file_name, object, val) \ static ssize_t show_##file_name \ @@ -675,7 +676,7 @@ static struct pci_dev *get_k8_northbridge(int node) if (!dev) break; } - return dev; + return dev; } static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) @@ -736,7 +737,7 @@ store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n"); return -EINVAL; } - + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); wbinvd(); pci_write_config_dword(dev, 0x1BC + index * 4, val); @@ -789,7 +790,7 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf) ret = fattr->show ? fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), buf) : - 0; + 0; return ret; } @@ -800,9 +801,9 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr, struct _index_kobject *this_leaf = to_object(kobj); ssize_t ret; - ret = fattr->store ? - fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), - buf, count) : + ret = fattr->store ? + fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), + buf, count) : 0; return ret; } -- cgit v1.2.3 From d89961e2dc87b6e30b8e3f60bd2af5cd92cf4643 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 24 Jul 2008 13:48:58 -0700 Subject: xen: suppress known wrmsrs In general, Xen doesn't support wrmsr from an unprivileged domain; it just ends up ignoring the instruction and printing a message on the console. Given that there are sets of MSRs we know the kernel will try to write to, but we don't care, just eat them in xen_write_msr to cut down on console noise. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index b011e4a5dbb..b795470ec06 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -854,6 +854,19 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) ret = -EFAULT; break; #endif + + case MSR_STAR: + case MSR_CSTAR: + case MSR_LSTAR: + case MSR_SYSCALL_MASK: + case MSR_IA32_SYSENTER_CS: + case MSR_IA32_SYSENTER_ESP: + case MSR_IA32_SYSENTER_EIP: + /* Fast syscall setup is all done in hypercalls, so + these are all ignored. Stub them out here to stop + Xen console noise. */ + break; + default: ret = native_write_msr_safe(msr, low, high); } -- cgit v1.2.3 From 239bd83104ec6bcba90221d8b0973d2565142ef8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 28 Jul 2008 16:45:49 +0200 Subject: x86: L3 cache index disable for 2.6.26, fix #2 fix !PCI build failure: arch/x86/kernel/cpu/intel_cacheinfo.c: In function 'get_k8_northbridge': arch/x86/kernel/cpu/intel_cacheinfo.c:675: error: implicit declaration of function 'pci_match_id' Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index d763d24187c..1677b55371a 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -135,11 +135,13 @@ struct _cpuid4_info { cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */ }; +#ifdef CONFIG_PCI static struct pci_device_id k8_nb_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, {} }; +#endif unsigned short num_cache_leaves; @@ -663,6 +665,7 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { #define to_object(k) container_of(k, struct _index_kobject, kobj) #define to_attr(a) container_of(a, struct _cache_attr, attr) +#ifdef CONFIG_PCI static struct pci_dev *get_k8_northbridge(int node) { struct pci_dev *dev = NULL; @@ -679,6 +682,12 @@ static struct pci_dev *get_k8_northbridge(int node) } return dev; } +#else +static struct pci_dev *get_k8_northbridge(int node) +{ + return NULL; +} +#endif static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) { -- cgit v1.2.3 From 9a56a0f80b52cb41c5e0add47c7ce0bb2ef25eb0 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:13 +0200 Subject: x86: moved Intel microcode patch loader declarations to seperate header file Intel specific microcode declarations have been moved to a seperate header file. There are no code changes to the code itself and no side effects to other parts. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 6994c751590..0d654bd3292 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -93,6 +93,7 @@ #include #include #include +#include MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); -- cgit v1.2.3 From 8e61028dfdc6b8ca996abfe8f9baef6792ea2904 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:14 +0200 Subject: x86: typedef removal Removed typedefs. No functional changes to the code. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 0d654bd3292..74e6a77bf19 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -102,17 +102,17 @@ MODULE_LICENSE("GPL"); #define MICROCODE_VERSION "1.14a" #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ +#define MC_HEADER_SIZE (sizeof (struct microcode_header)) /* 48 bytes */ #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ #define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ #define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ #define DWSIZE (sizeof (u32)) #define get_totalsize(mc) \ - (((microcode_t *)mc)->hdr.totalsize ? \ - ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) + (((struct microcode *)mc)->hdr.totalsize ? \ + ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) #define get_datasize(mc) \ - (((microcode_t *)mc)->hdr.datasize ? \ - ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) + (((struct microcode *)mc)->hdr.datasize ? \ + ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) #define sigmatch(s1, s2, p1, p2) \ (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) @@ -130,7 +130,7 @@ static struct ucode_cpu_info { unsigned int sig; unsigned int pf; unsigned int rev; - microcode_t *mc; + struct microcode *mc; } ucode_cpu_info[NR_CPUS]; static void collect_cpu_info(int cpu_num) @@ -171,7 +171,7 @@ static void collect_cpu_info(int cpu_num) } static inline int microcode_update_match(int cpu_num, - microcode_header_t *mc_header, int sig, int pf) + struct microcode_header *mc_header, int sig, int pf) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -183,7 +183,7 @@ static inline int microcode_update_match(int cpu_num, static int microcode_sanity_check(void *mc) { - microcode_header_t *mc_header = mc; + struct microcode_header *mc_header = mc; struct extended_sigtable *ext_header = NULL; struct extended_signature *ext_sig; unsigned long total_size, data_size, ext_table_size; @@ -268,7 +268,7 @@ static int microcode_sanity_check(void *mc) static int get_maching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - microcode_header_t *mc_header = mc; + struct microcode_header *mc_header = mc; struct extended_sigtable *ext_header; unsigned long total_size = get_totalsize(mc_header); int ext_sigcount, i; @@ -355,7 +355,7 @@ static unsigned int user_buffer_size; /* it's size */ static long get_next_ucode(void **mc, long offset) { - microcode_header_t mc_header; + struct microcode_header mc_header; unsigned long total_size; /* No more data */ @@ -497,13 +497,13 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); static long get_next_ucode_from_buffer(void **mc, const u8 *buf, unsigned long size, long offset) { - microcode_header_t *mc_header; + struct microcode_header *mc_header; unsigned long total_size; /* No more data */ if (offset >= size) return 0; - mc_header = (microcode_header_t *)(buf + offset); + mc_header = (struct microcode_header *)(buf + offset); total_size = get_totalsize(mc_header); if (offset + total_size > size) { -- cgit v1.2.3 From c3b71bcec0380836caac9b524fa1585b469b7456 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:15 +0200 Subject: x86: move per CPU microcode structure declaration to header file This structure will be later used by other modules as well and needs therfore to be moved out to a header file. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 74e6a77bf19..4e7b2f65fed 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -125,13 +125,7 @@ static DEFINE_SPINLOCK(microcode_update_lock); /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ static DEFINE_MUTEX(microcode_mutex); -static struct ucode_cpu_info { - int valid; - unsigned int sig; - unsigned int pf; - unsigned int rev; - struct microcode *mc; -} ucode_cpu_info[NR_CPUS]; +static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; static void collect_cpu_info(int cpu_num) { -- cgit v1.2.3 From 1abae31096007cc993f67ae2576fe8f812270ad6 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:16 +0200 Subject: x86: move microcode.c to microcode_intel.c Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/microcode.c | 855 -------------------------------------- arch/x86/kernel/microcode_intel.c | 855 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 856 insertions(+), 856 deletions(-) delete mode 100644 arch/x86/kernel/microcode.c create mode 100644 arch/x86/kernel/microcode_intel.c (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 3db651fc8ec..a9be2a0dde8 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -51,7 +51,7 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_MICROCODE) += microcode_intel.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c deleted file mode 100644 index 4e7b2f65fed..00000000000 --- a/arch/x86/kernel/microcode.c +++ /dev/null @@ -1,855 +0,0 @@ -/* - * Intel CPU Microcode Update Driver for Linux - * - * Copyright (C) 2000-2006 Tigran Aivazian - * 2006 Shaohua Li - * - * This driver allows to upgrade microcode on Intel processors - * belonging to IA-32 family - PentiumPro, Pentium II, - * Pentium III, Xeon, Pentium 4, etc. - * - * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture - * Software Developer's Manual - * Order Number 253668 or free download from: - * - * http://developer.intel.com/design/pentium4/manuals/253668.htm - * - * For more information, go to http://www.urbanmyth.org/microcode - * - * 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. - * - * 1.0 16 Feb 2000, Tigran Aivazian - * Initial release. - * 1.01 18 Feb 2000, Tigran Aivazian - * Added read() support + cleanups. - * 1.02 21 Feb 2000, Tigran Aivazian - * Added 'device trimming' support. open(O_WRONLY) zeroes - * and frees the saved copy of applied microcode. - * 1.03 29 Feb 2000, Tigran Aivazian - * Made to use devfs (/dev/cpu/microcode) + cleanups. - * 1.04 06 Jun 2000, Simon Trimmer - * Added misc device support (now uses both devfs and misc). - * Added MICROCODE_IOCFREE ioctl to clear memory. - * 1.05 09 Jun 2000, Simon Trimmer - * Messages for error cases (non Intel & no suitable microcode). - * 1.06 03 Aug 2000, Tigran Aivazian - * Removed ->release(). Removed exclusive open and status bitmap. - * Added microcode_rwsem to serialize read()/write()/ioctl(). - * Removed global kernel lock usage. - * 1.07 07 Sep 2000, Tigran Aivazian - * Write 0 to 0x8B msr and then cpuid before reading revision, - * so that it works even if there were no update done by the - * BIOS. Otherwise, reading from 0x8B gives junk (which happened - * to be 0 on my machine which is why it worked even when I - * disabled update by the BIOS) - * Thanks to Eric W. Biederman for the fix. - * 1.08 11 Dec 2000, Richard Schaal and - * Tigran Aivazian - * Intel Pentium 4 processor support and bugfixes. - * 1.09 30 Oct 2001, Tigran Aivazian - * Bugfix for HT (Hyper-Threading) enabled processors - * whereby processor resources are shared by all logical processors - * in a single CPU package. - * 1.10 28 Feb 2002 Asit K Mallick and - * Tigran Aivazian , - * Serialize updates as required on HT processors due to speculative - * nature of implementation. - * 1.11 22 Mar 2002 Tigran Aivazian - * Fix the panic when writing zero-length microcode chunk. - * 1.12 29 Sep 2003 Nitin Kamble , - * Jun Nakajima - * Support for the microcode updates in the new format. - * 1.13 10 Oct 2003 Tigran Aivazian - * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl - * because we no longer hold a copy of applied microcode - * in kernel memory. - * 1.14 25 Jun 2004 Tigran Aivazian - * Fix sigmatch() macro to handle old CPUs with pf == 0. - * Thanks to Stuart Swales for pointing out this bug. - */ - -//#define DEBUG /* pr_debug */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); -MODULE_AUTHOR("Tigran Aivazian "); -MODULE_LICENSE("GPL"); - -#define MICROCODE_VERSION "1.14a" - -#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof (struct microcode_header)) /* 48 bytes */ -#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ -#define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ -#define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ -#define DWSIZE (sizeof (u32)) -#define get_totalsize(mc) \ - (((struct microcode *)mc)->hdr.totalsize ? \ - ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) -#define get_datasize(mc) \ - (((struct microcode *)mc)->hdr.datasize ? \ - ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) - -#define sigmatch(s1, s2, p1, p2) \ - (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) - -#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) - -/* serialize access to the physical write to MSR 0x79 */ -static DEFINE_SPINLOCK(microcode_update_lock); - -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DEFINE_MUTEX(microcode_mutex); - -static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; - -static void collect_cpu_info(int cpu_num) -{ - struct cpuinfo_x86 *c = &cpu_data(cpu_num); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - unsigned int val[2]; - - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu_num); - uci->pf = uci->rev = 0; - uci->mc = NULL; - uci->valid = 1; - - if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || - cpu_has(c, X86_FEATURE_IA64)) { - printk(KERN_ERR "microcode: CPU%d not a capable Intel " - "processor\n", cpu_num); - uci->valid = 0; - return; - } - - uci->sig = cpuid_eax(0x00000001); - - if ((c->x86_model >= 5) || (c->x86 > 6)) { - /* get processor flags from MSR 0x17 */ - rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); - uci->pf = 1 << ((val[1] >> 18) & 7); - } - - wrmsr(MSR_IA32_UCODE_REV, 0, 0); - /* see notes above for revision 1.07. Apparent chip bug */ - sync_core(); - /* get the current revision from MSR 0x8B */ - rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); - pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", - uci->sig, uci->pf, uci->rev); -} - -static inline int microcode_update_match(int cpu_num, - struct microcode_header *mc_header, int sig, int pf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - - if (!sigmatch(sig, uci->sig, pf, uci->pf) - || mc_header->rev <= uci->rev) - return 0; - return 1; -} - -static int microcode_sanity_check(void *mc) -{ - struct microcode_header *mc_header = mc; - struct extended_sigtable *ext_header = NULL; - struct extended_signature *ext_sig; - unsigned long total_size, data_size, ext_table_size; - int sum, orig_sum, ext_sigcount = 0, i; - - total_size = get_totalsize(mc_header); - data_size = get_datasize(mc_header); - if (data_size + MC_HEADER_SIZE > total_size) { - printk(KERN_ERR "microcode: error! " - "Bad data size in microcode data file\n"); - return -EINVAL; - } - - if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { - printk(KERN_ERR "microcode: error! " - "Unknown microcode update format\n"); - return -EINVAL; - } - ext_table_size = total_size - (MC_HEADER_SIZE + data_size); - if (ext_table_size) { - if ((ext_table_size < EXT_HEADER_SIZE) - || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { - printk(KERN_ERR "microcode: error! " - "Small exttable size in microcode data file\n"); - return -EINVAL; - } - ext_header = mc + MC_HEADER_SIZE + data_size; - if (ext_table_size != exttable_size(ext_header)) { - printk(KERN_ERR "microcode: error! " - "Bad exttable size in microcode data file\n"); - return -EFAULT; - } - ext_sigcount = ext_header->count; - } - - /* check extended table checksum */ - if (ext_table_size) { - int ext_table_sum = 0; - int *ext_tablep = (int *)ext_header; - - i = ext_table_size / DWSIZE; - while (i--) - ext_table_sum += ext_tablep[i]; - if (ext_table_sum) { - printk(KERN_WARNING "microcode: aborting, " - "bad extended signature table checksum\n"); - return -EINVAL; - } - } - - /* calculate the checksum */ - orig_sum = 0; - i = (MC_HEADER_SIZE + data_size) / DWSIZE; - while (i--) - orig_sum += ((int *)mc)[i]; - if (orig_sum) { - printk(KERN_ERR "microcode: aborting, bad checksum\n"); - return -EINVAL; - } - if (!ext_table_size) - return 0; - /* check extended signature checksum */ - for (i = 0; i < ext_sigcount; i++) { - ext_sig = (void *)ext_header + EXT_HEADER_SIZE + - EXT_SIGNATURE_SIZE * i; - sum = orig_sum - - (mc_header->sig + mc_header->pf + mc_header->cksum) - + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); - if (sum) { - printk(KERN_ERR "microcode: aborting, bad checksum\n"); - return -EINVAL; - } - } - return 0; -} - -/* - * return 0 - no update found - * return 1 - found update - * return < 0 - error - */ -static int get_maching_microcode(void *mc, int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - struct microcode_header *mc_header = mc; - struct extended_sigtable *ext_header; - unsigned long total_size = get_totalsize(mc_header); - int ext_sigcount, i; - struct extended_signature *ext_sig; - void *new_mc; - - if (microcode_update_match(cpu, mc_header, - mc_header->sig, mc_header->pf)) - goto find; - - if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE) - return 0; - - ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; - ext_sigcount = ext_header->count; - ext_sig = (void *)ext_header + EXT_HEADER_SIZE; - for (i = 0; i < ext_sigcount; i++) { - if (microcode_update_match(cpu, mc_header, - ext_sig->sig, ext_sig->pf)) - goto find; - ext_sig++; - } - return 0; -find: - pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev); - new_mc = vmalloc(total_size); - if (!new_mc) { - printk(KERN_ERR "microcode: error! Can not allocate memory\n"); - return -ENOMEM; - } - - /* free previous update file */ - vfree(uci->mc); - - memcpy(new_mc, mc, total_size); - uci->mc = new_mc; - return 1; -} - -static void apply_microcode(int cpu) -{ - unsigned long flags; - unsigned int val[2]; - int cpu_num = raw_smp_processor_id(); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - - /* We should bind the task to the CPU */ - BUG_ON(cpu_num != cpu); - - if (uci->mc == NULL) - return; - - /* serialize access to the physical write to MSR 0x79 */ - spin_lock_irqsave(µcode_update_lock, flags); - - /* write microcode via MSR 0x79 */ - wrmsr(MSR_IA32_UCODE_WRITE, - (unsigned long) uci->mc->bits, - (unsigned long) uci->mc->bits >> 16 >> 16); - wrmsr(MSR_IA32_UCODE_REV, 0, 0); - - /* see notes above for revision 1.07. Apparent chip bug */ - sync_core(); - - /* get the current revision from MSR 0x8B */ - rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); - - spin_unlock_irqrestore(µcode_update_lock, flags); - if (val[1] != uci->mc->hdr.rev) { - printk(KERN_ERR "microcode: CPU%d update from revision " - "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); - return; - } - printk(KERN_INFO "microcode: CPU%d updated from revision " - "0x%x to 0x%x, date = %08x \n", - cpu_num, uci->rev, val[1], uci->mc->hdr.date); - uci->rev = val[1]; -} - -#ifdef CONFIG_MICROCODE_OLD_INTERFACE -static void __user *user_buffer; /* user area microcode data buffer */ -static unsigned int user_buffer_size; /* it's size */ - -static long get_next_ucode(void **mc, long offset) -{ - struct microcode_header mc_header; - unsigned long total_size; - - /* No more data */ - if (offset >= user_buffer_size) - return 0; - if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) { - printk(KERN_ERR "microcode: error! Can not read user data\n"); - return -EFAULT; - } - total_size = get_totalsize(&mc_header); - if (offset + total_size > user_buffer_size) { - printk(KERN_ERR "microcode: error! Bad total size in microcode " - "data file\n"); - return -EINVAL; - } - *mc = vmalloc(total_size); - if (!*mc) - return -ENOMEM; - if (copy_from_user(*mc, user_buffer + offset, total_size)) { - printk(KERN_ERR "microcode: error! Can not read user data\n"); - vfree(*mc); - return -EFAULT; - } - return offset + total_size; -} - -static int do_microcode_update (void) -{ - long cursor = 0; - int error = 0; - void *new_mc = NULL; - int cpu; - cpumask_t old; - cpumask_of_cpu_ptr_declare(newmask); - - old = current->cpus_allowed; - - while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { - error = microcode_sanity_check(new_mc); - if (error) - goto out; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - for_each_online_cpu(cpu) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!uci->valid) - continue; - cpumask_of_cpu_ptr_next(newmask, cpu); - set_cpus_allowed_ptr(current, newmask); - error = get_maching_microcode(new_mc, cpu); - if (error < 0) - goto out; - if (error == 1) - apply_microcode(cpu); - } - vfree(new_mc); - } -out: - if (cursor > 0) - vfree(new_mc); - if (cursor < 0) - error = cursor; - set_cpus_allowed_ptr(current, &old); - return error; -} - -static int microcode_open (struct inode *unused1, struct file *unused2) -{ - cycle_kernel_lock(); - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) -{ - ssize_t ret; - - if ((len >> PAGE_SHIFT) > num_physpages) { - printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); - return -EINVAL; - } - - get_online_cpus(); - mutex_lock(µcode_mutex); - - user_buffer = (void __user *) buf; - user_buffer_size = (int) len; - - ret = do_microcode_update(); - if (!ret) - ret = (ssize_t)len; - - mutex_unlock(µcode_mutex); - put_online_cpus(); - - return ret; -} - -static const struct file_operations microcode_fops = { - .owner = THIS_MODULE, - .write = microcode_write, - .open = microcode_open, -}; - -static struct miscdevice microcode_dev = { - .minor = MICROCODE_MINOR, - .name = "microcode", - .fops = µcode_fops, -}; - -static int __init microcode_dev_init (void) -{ - int error; - - error = misc_register(µcode_dev); - if (error) { - printk(KERN_ERR - "microcode: can't misc_register on minor=%d\n", - MICROCODE_MINOR); - return error; - } - - return 0; -} - -static void microcode_dev_exit (void) -{ - misc_deregister(µcode_dev); -} - -MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); -#else -#define microcode_dev_init() 0 -#define microcode_dev_exit() do { } while(0) -#endif - -static long get_next_ucode_from_buffer(void **mc, const u8 *buf, - unsigned long size, long offset) -{ - struct microcode_header *mc_header; - unsigned long total_size; - - /* No more data */ - if (offset >= size) - return 0; - mc_header = (struct microcode_header *)(buf + offset); - total_size = get_totalsize(mc_header); - - if (offset + total_size > size) { - printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); - return -EINVAL; - } - - *mc = vmalloc(total_size); - if (!*mc) { - printk(KERN_ERR "microcode: error! Can not allocate memory\n"); - return -ENOMEM; - } - memcpy(*mc, buf + offset, total_size); - return offset + total_size; -} - -/* fake device for request_firmware */ -static struct platform_device *microcode_pdev; - -static int cpu_request_microcode(int cpu) -{ - char name[30]; - struct cpuinfo_x86 *c = &cpu_data(cpu); - const struct firmware *firmware; - const u8 *buf; - unsigned long size; - long offset = 0; - int error; - void *mc; - - /* We should bind the task to the CPU */ - BUG_ON(cpu != raw_smp_processor_id()); - sprintf(name,"intel-ucode/%02x-%02x-%02x", - c->x86, c->x86_model, c->x86_mask); - error = request_firmware(&firmware, name, µcode_pdev->dev); - if (error) { - pr_debug("microcode: data file %s load failed\n", name); - return error; - } - buf = firmware->data; - size = firmware->size; - while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) - > 0) { - error = microcode_sanity_check(mc); - if (error) - break; - error = get_maching_microcode(mc, cpu); - if (error < 0) - break; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - if (error == 1) { - apply_microcode(cpu); - error = 0; - } - vfree(mc); - } - if (offset > 0) - vfree(mc); - if (offset < 0) - error = offset; - release_firmware(firmware); - - return error; -} - -static int apply_microcode_check_cpu(int cpu) -{ - struct cpuinfo_x86 *c = &cpu_data(cpu); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - cpumask_t old; - cpumask_of_cpu_ptr(newmask, cpu); - unsigned int val[2]; - int err = 0; - - /* Check if the microcode is available */ - if (!uci->mc) - return 0; - - old = current->cpus_allowed; - set_cpus_allowed_ptr(current, newmask); - - /* Check if the microcode we have in memory matches the CPU */ - if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || - cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001)) - err = -EINVAL; - - if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) { - /* get processor flags from MSR 0x17 */ - rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); - if (uci->pf != (1 << ((val[1] >> 18) & 7))) - err = -EINVAL; - } - - if (!err) { - wrmsr(MSR_IA32_UCODE_REV, 0, 0); - /* see notes above for revision 1.07. Apparent chip bug */ - sync_core(); - /* get the current revision from MSR 0x8B */ - rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); - if (uci->rev != val[1]) - err = -EINVAL; - } - - if (!err) - apply_microcode(cpu); - else - printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" - " sig=0x%x, pf=0x%x, rev=0x%x\n", - cpu, uci->sig, uci->pf, uci->rev); - - set_cpus_allowed_ptr(current, &old); - return err; -} - -static void microcode_init_cpu(int cpu, int resume) -{ - cpumask_t old; - cpumask_of_cpu_ptr(newmask, cpu); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - old = current->cpus_allowed; - - set_cpus_allowed_ptr(current, newmask); - mutex_lock(µcode_mutex); - collect_cpu_info(cpu); - if (uci->valid && system_state == SYSTEM_RUNNING && !resume) - cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); - set_cpus_allowed_ptr(current, &old); -} - -static void microcode_fini_cpu(int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - mutex_lock(µcode_mutex); - uci->valid = 0; - vfree(uci->mc); - uci->mc = NULL; - mutex_unlock(µcode_mutex); -} - -static ssize_t reload_store(struct sys_device *dev, - struct sysdev_attribute *attr, - const char *buf, size_t sz) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - char *end; - unsigned long val = simple_strtoul(buf, &end, 0); - int err = 0; - int cpu = dev->id; - - if (end == buf) - return -EINVAL; - if (val == 1) { - cpumask_t old; - cpumask_of_cpu_ptr(newmask, cpu); - - old = current->cpus_allowed; - - get_online_cpus(); - set_cpus_allowed_ptr(current, newmask); - - mutex_lock(µcode_mutex); - if (uci->valid) - err = cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); - put_online_cpus(); - set_cpus_allowed_ptr(current, &old); - } - if (err) - return err; - return sz; -} - -static ssize_t version_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->rev); -} - -static ssize_t pf_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->pf); -} - -static SYSDEV_ATTR(reload, 0200, NULL, reload_store); -static SYSDEV_ATTR(version, 0400, version_show, NULL); -static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); - -static struct attribute *mc_default_attrs[] = { - &attr_reload.attr, - &attr_version.attr, - &attr_processor_flags.attr, - NULL -}; - -static struct attribute_group mc_attr_group = { - .attrs = mc_default_attrs, - .name = "microcode", -}; - -static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) -{ - int err, cpu = sys_dev->id; - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d added\n", cpu); - memset(uci, 0, sizeof(*uci)); - - err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); - if (err) - return err; - - microcode_init_cpu(cpu, resume); - - return 0; -} - -static int mc_sysdev_add(struct sys_device *sys_dev) -{ - return __mc_sysdev_add(sys_dev, 0); -} - -static int mc_sysdev_remove(struct sys_device *sys_dev) -{ - int cpu = sys_dev->id; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d removed\n", cpu); - microcode_fini_cpu(cpu); - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - return 0; -} - -static int mc_sysdev_resume(struct sys_device *dev) -{ - int cpu = dev->id; - - if (!cpu_online(cpu)) - return 0; - pr_debug("microcode: CPU%d resumed\n", cpu); - /* only CPU 0 will apply ucode here */ - apply_microcode(0); - return 0; -} - -static struct sysdev_driver mc_sysdev_driver = { - .add = mc_sysdev_add, - .remove = mc_sysdev_remove, - .resume = mc_sysdev_resume, -}; - -static __cpuinit int -mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - struct sys_device *sys_dev; - - sys_dev = get_cpu_sysdev(cpu); - switch (action) { - case CPU_UP_CANCELED_FROZEN: - /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); - break; - case CPU_ONLINE: - case CPU_DOWN_FAILED: - mc_sysdev_add(sys_dev); - break; - case CPU_ONLINE_FROZEN: - /* System-wide resume is in progress, try to apply microcode */ - if (apply_microcode_check_cpu(cpu)) { - /* The application of microcode failed */ - microcode_fini_cpu(cpu); - __mc_sysdev_add(sys_dev, 1); - break; - } - case CPU_DOWN_FAILED_FROZEN: - if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) - printk(KERN_ERR "microcode: Failed to create the sysfs " - "group for CPU%d\n", cpu); - break; - case CPU_DOWN_PREPARE: - mc_sysdev_remove(sys_dev); - break; - case CPU_DOWN_PREPARE_FROZEN: - /* Suspend is in progress, only remove the interface */ - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block __refdata mc_cpu_notifier = { - .notifier_call = mc_cpu_callback, -}; - -static int __init microcode_init (void) -{ - int error; - - printk(KERN_INFO - "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); - - error = microcode_dev_init(); - if (error) - return error; - microcode_pdev = platform_device_register_simple("microcode", -1, - NULL, 0); - if (IS_ERR(microcode_pdev)) { - microcode_dev_exit(); - return PTR_ERR(microcode_pdev); - } - - get_online_cpus(); - error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - if (error) { - microcode_dev_exit(); - platform_device_unregister(microcode_pdev); - return error; - } - - register_hotcpu_notifier(&mc_cpu_notifier); - return 0; -} - -static void __exit microcode_exit (void) -{ - microcode_dev_exit(); - - unregister_hotcpu_notifier(&mc_cpu_notifier); - - get_online_cpus(); - sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - - platform_device_unregister(microcode_pdev); -} - -module_init(microcode_init) -module_exit(microcode_exit) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c new file mode 100644 index 00000000000..4e7b2f65fed --- /dev/null +++ b/arch/x86/kernel/microcode_intel.c @@ -0,0 +1,855 @@ +/* + * Intel CPU Microcode Update Driver for Linux + * + * Copyright (C) 2000-2006 Tigran Aivazian + * 2006 Shaohua Li + * + * This driver allows to upgrade microcode on Intel processors + * belonging to IA-32 family - PentiumPro, Pentium II, + * Pentium III, Xeon, Pentium 4, etc. + * + * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture + * Software Developer's Manual + * Order Number 253668 or free download from: + * + * http://developer.intel.com/design/pentium4/manuals/253668.htm + * + * For more information, go to http://www.urbanmyth.org/microcode + * + * 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. + * + * 1.0 16 Feb 2000, Tigran Aivazian + * Initial release. + * 1.01 18 Feb 2000, Tigran Aivazian + * Added read() support + cleanups. + * 1.02 21 Feb 2000, Tigran Aivazian + * Added 'device trimming' support. open(O_WRONLY) zeroes + * and frees the saved copy of applied microcode. + * 1.03 29 Feb 2000, Tigran Aivazian + * Made to use devfs (/dev/cpu/microcode) + cleanups. + * 1.04 06 Jun 2000, Simon Trimmer + * Added misc device support (now uses both devfs and misc). + * Added MICROCODE_IOCFREE ioctl to clear memory. + * 1.05 09 Jun 2000, Simon Trimmer + * Messages for error cases (non Intel & no suitable microcode). + * 1.06 03 Aug 2000, Tigran Aivazian + * Removed ->release(). Removed exclusive open and status bitmap. + * Added microcode_rwsem to serialize read()/write()/ioctl(). + * Removed global kernel lock usage. + * 1.07 07 Sep 2000, Tigran Aivazian + * Write 0 to 0x8B msr and then cpuid before reading revision, + * so that it works even if there were no update done by the + * BIOS. Otherwise, reading from 0x8B gives junk (which happened + * to be 0 on my machine which is why it worked even when I + * disabled update by the BIOS) + * Thanks to Eric W. Biederman for the fix. + * 1.08 11 Dec 2000, Richard Schaal and + * Tigran Aivazian + * Intel Pentium 4 processor support and bugfixes. + * 1.09 30 Oct 2001, Tigran Aivazian + * Bugfix for HT (Hyper-Threading) enabled processors + * whereby processor resources are shared by all logical processors + * in a single CPU package. + * 1.10 28 Feb 2002 Asit K Mallick and + * Tigran Aivazian , + * Serialize updates as required on HT processors due to speculative + * nature of implementation. + * 1.11 22 Mar 2002 Tigran Aivazian + * Fix the panic when writing zero-length microcode chunk. + * 1.12 29 Sep 2003 Nitin Kamble , + * Jun Nakajima + * Support for the microcode updates in the new format. + * 1.13 10 Oct 2003 Tigran Aivazian + * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl + * because we no longer hold a copy of applied microcode + * in kernel memory. + * 1.14 25 Jun 2004 Tigran Aivazian + * Fix sigmatch() macro to handle old CPUs with pf == 0. + * Thanks to Stuart Swales for pointing out this bug. + */ + +//#define DEBUG /* pr_debug */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); +MODULE_AUTHOR("Tigran Aivazian "); +MODULE_LICENSE("GPL"); + +#define MICROCODE_VERSION "1.14a" + +#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ +#define MC_HEADER_SIZE (sizeof (struct microcode_header)) /* 48 bytes */ +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ +#define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ +#define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ +#define DWSIZE (sizeof (u32)) +#define get_totalsize(mc) \ + (((struct microcode *)mc)->hdr.totalsize ? \ + ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) +#define get_datasize(mc) \ + (((struct microcode *)mc)->hdr.datasize ? \ + ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) + +#define sigmatch(s1, s2, p1, p2) \ + (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) + +#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) + +/* serialize access to the physical write to MSR 0x79 */ +static DEFINE_SPINLOCK(microcode_update_lock); + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +static DEFINE_MUTEX(microcode_mutex); + +static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; + +static void collect_cpu_info(int cpu_num) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu_num); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + unsigned int val[2]; + + /* We should bind the task to the CPU */ + BUG_ON(raw_smp_processor_id() != cpu_num); + uci->pf = uci->rev = 0; + uci->mc = NULL; + uci->valid = 1; + + if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || + cpu_has(c, X86_FEATURE_IA64)) { + printk(KERN_ERR "microcode: CPU%d not a capable Intel " + "processor\n", cpu_num); + uci->valid = 0; + return; + } + + uci->sig = cpuid_eax(0x00000001); + + if ((c->x86_model >= 5) || (c->x86 > 6)) { + /* get processor flags from MSR 0x17 */ + rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); + uci->pf = 1 << ((val[1] >> 18) & 7); + } + + wrmsr(MSR_IA32_UCODE_REV, 0, 0); + /* see notes above for revision 1.07. Apparent chip bug */ + sync_core(); + /* get the current revision from MSR 0x8B */ + rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); + pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", + uci->sig, uci->pf, uci->rev); +} + +static inline int microcode_update_match(int cpu_num, + struct microcode_header *mc_header, int sig, int pf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + + if (!sigmatch(sig, uci->sig, pf, uci->pf) + || mc_header->rev <= uci->rev) + return 0; + return 1; +} + +static int microcode_sanity_check(void *mc) +{ + struct microcode_header *mc_header = mc; + struct extended_sigtable *ext_header = NULL; + struct extended_signature *ext_sig; + unsigned long total_size, data_size, ext_table_size; + int sum, orig_sum, ext_sigcount = 0, i; + + total_size = get_totalsize(mc_header); + data_size = get_datasize(mc_header); + if (data_size + MC_HEADER_SIZE > total_size) { + printk(KERN_ERR "microcode: error! " + "Bad data size in microcode data file\n"); + return -EINVAL; + } + + if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { + printk(KERN_ERR "microcode: error! " + "Unknown microcode update format\n"); + return -EINVAL; + } + ext_table_size = total_size - (MC_HEADER_SIZE + data_size); + if (ext_table_size) { + if ((ext_table_size < EXT_HEADER_SIZE) + || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { + printk(KERN_ERR "microcode: error! " + "Small exttable size in microcode data file\n"); + return -EINVAL; + } + ext_header = mc + MC_HEADER_SIZE + data_size; + if (ext_table_size != exttable_size(ext_header)) { + printk(KERN_ERR "microcode: error! " + "Bad exttable size in microcode data file\n"); + return -EFAULT; + } + ext_sigcount = ext_header->count; + } + + /* check extended table checksum */ + if (ext_table_size) { + int ext_table_sum = 0; + int *ext_tablep = (int *)ext_header; + + i = ext_table_size / DWSIZE; + while (i--) + ext_table_sum += ext_tablep[i]; + if (ext_table_sum) { + printk(KERN_WARNING "microcode: aborting, " + "bad extended signature table checksum\n"); + return -EINVAL; + } + } + + /* calculate the checksum */ + orig_sum = 0; + i = (MC_HEADER_SIZE + data_size) / DWSIZE; + while (i--) + orig_sum += ((int *)mc)[i]; + if (orig_sum) { + printk(KERN_ERR "microcode: aborting, bad checksum\n"); + return -EINVAL; + } + if (!ext_table_size) + return 0; + /* check extended signature checksum */ + for (i = 0; i < ext_sigcount; i++) { + ext_sig = (void *)ext_header + EXT_HEADER_SIZE + + EXT_SIGNATURE_SIZE * i; + sum = orig_sum + - (mc_header->sig + mc_header->pf + mc_header->cksum) + + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); + if (sum) { + printk(KERN_ERR "microcode: aborting, bad checksum\n"); + return -EINVAL; + } + } + return 0; +} + +/* + * return 0 - no update found + * return 1 - found update + * return < 0 - error + */ +static int get_maching_microcode(void *mc, int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct microcode_header *mc_header = mc; + struct extended_sigtable *ext_header; + unsigned long total_size = get_totalsize(mc_header); + int ext_sigcount, i; + struct extended_signature *ext_sig; + void *new_mc; + + if (microcode_update_match(cpu, mc_header, + mc_header->sig, mc_header->pf)) + goto find; + + if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE) + return 0; + + ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; + ext_sigcount = ext_header->count; + ext_sig = (void *)ext_header + EXT_HEADER_SIZE; + for (i = 0; i < ext_sigcount; i++) { + if (microcode_update_match(cpu, mc_header, + ext_sig->sig, ext_sig->pf)) + goto find; + ext_sig++; + } + return 0; +find: + pr_debug("microcode: CPU%d found a matching microcode update with" + " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev); + new_mc = vmalloc(total_size); + if (!new_mc) { + printk(KERN_ERR "microcode: error! Can not allocate memory\n"); + return -ENOMEM; + } + + /* free previous update file */ + vfree(uci->mc); + + memcpy(new_mc, mc, total_size); + uci->mc = new_mc; + return 1; +} + +static void apply_microcode(int cpu) +{ + unsigned long flags; + unsigned int val[2]; + int cpu_num = raw_smp_processor_id(); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + + /* We should bind the task to the CPU */ + BUG_ON(cpu_num != cpu); + + if (uci->mc == NULL) + return; + + /* serialize access to the physical write to MSR 0x79 */ + spin_lock_irqsave(µcode_update_lock, flags); + + /* write microcode via MSR 0x79 */ + wrmsr(MSR_IA32_UCODE_WRITE, + (unsigned long) uci->mc->bits, + (unsigned long) uci->mc->bits >> 16 >> 16); + wrmsr(MSR_IA32_UCODE_REV, 0, 0); + + /* see notes above for revision 1.07. Apparent chip bug */ + sync_core(); + + /* get the current revision from MSR 0x8B */ + rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); + + spin_unlock_irqrestore(µcode_update_lock, flags); + if (val[1] != uci->mc->hdr.rev) { + printk(KERN_ERR "microcode: CPU%d update from revision " + "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); + return; + } + printk(KERN_INFO "microcode: CPU%d updated from revision " + "0x%x to 0x%x, date = %08x \n", + cpu_num, uci->rev, val[1], uci->mc->hdr.date); + uci->rev = val[1]; +} + +#ifdef CONFIG_MICROCODE_OLD_INTERFACE +static void __user *user_buffer; /* user area microcode data buffer */ +static unsigned int user_buffer_size; /* it's size */ + +static long get_next_ucode(void **mc, long offset) +{ + struct microcode_header mc_header; + unsigned long total_size; + + /* No more data */ + if (offset >= user_buffer_size) + return 0; + if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + return -EFAULT; + } + total_size = get_totalsize(&mc_header); + if (offset + total_size > user_buffer_size) { + printk(KERN_ERR "microcode: error! Bad total size in microcode " + "data file\n"); + return -EINVAL; + } + *mc = vmalloc(total_size); + if (!*mc) + return -ENOMEM; + if (copy_from_user(*mc, user_buffer + offset, total_size)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + vfree(*mc); + return -EFAULT; + } + return offset + total_size; +} + +static int do_microcode_update (void) +{ + long cursor = 0; + int error = 0; + void *new_mc = NULL; + int cpu; + cpumask_t old; + cpumask_of_cpu_ptr_declare(newmask); + + old = current->cpus_allowed; + + while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { + error = microcode_sanity_check(new_mc); + if (error) + goto out; + /* + * It's possible the data file has multiple matching ucode, + * lets keep searching till the latest version + */ + for_each_online_cpu(cpu) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!uci->valid) + continue; + cpumask_of_cpu_ptr_next(newmask, cpu); + set_cpus_allowed_ptr(current, newmask); + error = get_maching_microcode(new_mc, cpu); + if (error < 0) + goto out; + if (error == 1) + apply_microcode(cpu); + } + vfree(new_mc); + } +out: + if (cursor > 0) + vfree(new_mc); + if (cursor < 0) + error = cursor; + set_cpus_allowed_ptr(current, &old); + return error; +} + +static int microcode_open (struct inode *unused1, struct file *unused2) +{ + cycle_kernel_lock(); + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) +{ + ssize_t ret; + + if ((len >> PAGE_SHIFT) > num_physpages) { + printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); + return -EINVAL; + } + + get_online_cpus(); + mutex_lock(µcode_mutex); + + user_buffer = (void __user *) buf; + user_buffer_size = (int) len; + + ret = do_microcode_update(); + if (!ret) + ret = (ssize_t)len; + + mutex_unlock(µcode_mutex); + put_online_cpus(); + + return ret; +} + +static const struct file_operations microcode_fops = { + .owner = THIS_MODULE, + .write = microcode_write, + .open = microcode_open, +}; + +static struct miscdevice microcode_dev = { + .minor = MICROCODE_MINOR, + .name = "microcode", + .fops = µcode_fops, +}; + +static int __init microcode_dev_init (void) +{ + int error; + + error = misc_register(µcode_dev); + if (error) { + printk(KERN_ERR + "microcode: can't misc_register on minor=%d\n", + MICROCODE_MINOR); + return error; + } + + return 0; +} + +static void microcode_dev_exit (void) +{ + misc_deregister(µcode_dev); +} + +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); +#else +#define microcode_dev_init() 0 +#define microcode_dev_exit() do { } while(0) +#endif + +static long get_next_ucode_from_buffer(void **mc, const u8 *buf, + unsigned long size, long offset) +{ + struct microcode_header *mc_header; + unsigned long total_size; + + /* No more data */ + if (offset >= size) + return 0; + mc_header = (struct microcode_header *)(buf + offset); + total_size = get_totalsize(mc_header); + + if (offset + total_size > size) { + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); + return -EINVAL; + } + + *mc = vmalloc(total_size); + if (!*mc) { + printk(KERN_ERR "microcode: error! Can not allocate memory\n"); + return -ENOMEM; + } + memcpy(*mc, buf + offset, total_size); + return offset + total_size; +} + +/* fake device for request_firmware */ +static struct platform_device *microcode_pdev; + +static int cpu_request_microcode(int cpu) +{ + char name[30]; + struct cpuinfo_x86 *c = &cpu_data(cpu); + const struct firmware *firmware; + const u8 *buf; + unsigned long size; + long offset = 0; + int error; + void *mc; + + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + sprintf(name,"intel-ucode/%02x-%02x-%02x", + c->x86, c->x86_model, c->x86_mask); + error = request_firmware(&firmware, name, µcode_pdev->dev); + if (error) { + pr_debug("microcode: data file %s load failed\n", name); + return error; + } + buf = firmware->data; + size = firmware->size; + while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) + > 0) { + error = microcode_sanity_check(mc); + if (error) + break; + error = get_maching_microcode(mc, cpu); + if (error < 0) + break; + /* + * It's possible the data file has multiple matching ucode, + * lets keep searching till the latest version + */ + if (error == 1) { + apply_microcode(cpu); + error = 0; + } + vfree(mc); + } + if (offset > 0) + vfree(mc); + if (offset < 0) + error = offset; + release_firmware(firmware); + + return error; +} + +static int apply_microcode_check_cpu(int cpu) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + unsigned int val[2]; + int err = 0; + + /* Check if the microcode is available */ + if (!uci->mc) + return 0; + + old = current->cpus_allowed; + set_cpus_allowed_ptr(current, newmask); + + /* Check if the microcode we have in memory matches the CPU */ + if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || + cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001)) + err = -EINVAL; + + if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) { + /* get processor flags from MSR 0x17 */ + rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); + if (uci->pf != (1 << ((val[1] >> 18) & 7))) + err = -EINVAL; + } + + if (!err) { + wrmsr(MSR_IA32_UCODE_REV, 0, 0); + /* see notes above for revision 1.07. Apparent chip bug */ + sync_core(); + /* get the current revision from MSR 0x8B */ + rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); + if (uci->rev != val[1]) + err = -EINVAL; + } + + if (!err) + apply_microcode(cpu); + else + printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" + " sig=0x%x, pf=0x%x, rev=0x%x\n", + cpu, uci->sig, uci->pf, uci->rev); + + set_cpus_allowed_ptr(current, &old); + return err; +} + +static void microcode_init_cpu(int cpu, int resume) +{ + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + old = current->cpus_allowed; + + set_cpus_allowed_ptr(current, newmask); + mutex_lock(µcode_mutex); + collect_cpu_info(cpu); + if (uci->valid && system_state == SYSTEM_RUNNING && !resume) + cpu_request_microcode(cpu); + mutex_unlock(µcode_mutex); + set_cpus_allowed_ptr(current, &old); +} + +static void microcode_fini_cpu(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + mutex_lock(µcode_mutex); + uci->valid = 0; + vfree(uci->mc); + uci->mc = NULL; + mutex_unlock(µcode_mutex); +} + +static ssize_t reload_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t sz) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + char *end; + unsigned long val = simple_strtoul(buf, &end, 0); + int err = 0; + int cpu = dev->id; + + if (end == buf) + return -EINVAL; + if (val == 1) { + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + + old = current->cpus_allowed; + + get_online_cpus(); + set_cpus_allowed_ptr(current, newmask); + + mutex_lock(µcode_mutex); + if (uci->valid) + err = cpu_request_microcode(cpu); + mutex_unlock(µcode_mutex); + put_online_cpus(); + set_cpus_allowed_ptr(current, &old); + } + if (err) + return err; + return sz; +} + +static ssize_t version_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->rev); +} + +static ssize_t pf_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->pf); +} + +static SYSDEV_ATTR(reload, 0200, NULL, reload_store); +static SYSDEV_ATTR(version, 0400, version_show, NULL); +static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); + +static struct attribute *mc_default_attrs[] = { + &attr_reload.attr, + &attr_version.attr, + &attr_processor_flags.attr, + NULL +}; + +static struct attribute_group mc_attr_group = { + .attrs = mc_default_attrs, + .name = "microcode", +}; + +static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) +{ + int err, cpu = sys_dev->id; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d added\n", cpu); + memset(uci, 0, sizeof(*uci)); + + err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); + if (err) + return err; + + microcode_init_cpu(cpu, resume); + + return 0; +} + +static int mc_sysdev_add(struct sys_device *sys_dev) +{ + return __mc_sysdev_add(sys_dev, 0); +} + +static int mc_sysdev_remove(struct sys_device *sys_dev) +{ + int cpu = sys_dev->id; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d removed\n", cpu); + microcode_fini_cpu(cpu); + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + return 0; +} + +static int mc_sysdev_resume(struct sys_device *dev) +{ + int cpu = dev->id; + + if (!cpu_online(cpu)) + return 0; + pr_debug("microcode: CPU%d resumed\n", cpu); + /* only CPU 0 will apply ucode here */ + apply_microcode(0); + return 0; +} + +static struct sysdev_driver mc_sysdev_driver = { + .add = mc_sysdev_add, + .remove = mc_sysdev_remove, + .resume = mc_sysdev_resume, +}; + +static __cpuinit int +mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + switch (action) { + case CPU_UP_CANCELED_FROZEN: + /* The CPU refused to come up during a system resume */ + microcode_fini_cpu(cpu); + break; + case CPU_ONLINE: + case CPU_DOWN_FAILED: + mc_sysdev_add(sys_dev); + break; + case CPU_ONLINE_FROZEN: + /* System-wide resume is in progress, try to apply microcode */ + if (apply_microcode_check_cpu(cpu)) { + /* The application of microcode failed */ + microcode_fini_cpu(cpu); + __mc_sysdev_add(sys_dev, 1); + break; + } + case CPU_DOWN_FAILED_FROZEN: + if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) + printk(KERN_ERR "microcode: Failed to create the sysfs " + "group for CPU%d\n", cpu); + break; + case CPU_DOWN_PREPARE: + mc_sysdev_remove(sys_dev); + break; + case CPU_DOWN_PREPARE_FROZEN: + /* Suspend is in progress, only remove the interface */ + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __refdata mc_cpu_notifier = { + .notifier_call = mc_cpu_callback, +}; + +static int __init microcode_init (void) +{ + int error; + + printk(KERN_INFO + "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); + + error = microcode_dev_init(); + if (error) + return error; + microcode_pdev = platform_device_register_simple("microcode", -1, + NULL, 0); + if (IS_ERR(microcode_pdev)) { + microcode_dev_exit(); + return PTR_ERR(microcode_pdev); + } + + get_online_cpus(); + error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + if (error) { + microcode_dev_exit(); + platform_device_unregister(microcode_pdev); + return error; + } + + register_hotcpu_notifier(&mc_cpu_notifier); + return 0; +} + +static void __exit microcode_exit (void) +{ + microcode_dev_exit(); + + unregister_hotcpu_notifier(&mc_cpu_notifier); + + get_online_cpus(); + sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + + platform_device_unregister(microcode_pdev); +} + +module_init(microcode_init) +module_exit(microcode_exit) -- cgit v1.2.3 From 3e135d887c973b525d43fbb67dfc5972694882f6 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:17 +0200 Subject: x86: code split to two parts Split off existing code into two seperate files. One file holds general code, the other file vendor specific parts. No functional changes, only refactoring. Temporarily Introduced a new module name 'ucode' for result, due to already taken name 'microcode'. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 3 +- arch/x86/kernel/microcode.c | 463 ++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/microcode_intel.c | 387 ++----------------------------- 3 files changed, 488 insertions(+), 365 deletions(-) create mode 100644 arch/x86/kernel/microcode.c (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a9be2a0dde8..abb32aed7f4 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -51,7 +51,8 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += microcode_intel.o +obj-$(CONFIG_MICROCODE) += ucode.o +ucode-objs := microcode.o microcode_intel.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c new file mode 100644 index 00000000000..c1047d7f7ed --- /dev/null +++ b/arch/x86/kernel/microcode.c @@ -0,0 +1,463 @@ +/* + * Intel CPU Microcode Update Driver for Linux + * + * Copyright (C) 2000-2006 Tigran Aivazian + * 2006 Shaohua Li + * + * This driver allows to upgrade microcode on Intel processors + * belonging to IA-32 family - PentiumPro, Pentium II, + * Pentium III, Xeon, Pentium 4, etc. + * + * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture + * Software Developer's Manual + * Order Number 253668 or free download from: + * + * http://developer.intel.com/design/pentium4/manuals/253668.htm + * + * For more information, go to http://www.urbanmyth.org/microcode + * + * 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. + * + * 1.0 16 Feb 2000, Tigran Aivazian + * Initial release. + * 1.01 18 Feb 2000, Tigran Aivazian + * Added read() support + cleanups. + * 1.02 21 Feb 2000, Tigran Aivazian + * Added 'device trimming' support. open(O_WRONLY) zeroes + * and frees the saved copy of applied microcode. + * 1.03 29 Feb 2000, Tigran Aivazian + * Made to use devfs (/dev/cpu/microcode) + cleanups. + * 1.04 06 Jun 2000, Simon Trimmer + * Added misc device support (now uses both devfs and misc). + * Added MICROCODE_IOCFREE ioctl to clear memory. + * 1.05 09 Jun 2000, Simon Trimmer + * Messages for error cases (non Intel & no suitable microcode). + * 1.06 03 Aug 2000, Tigran Aivazian + * Removed ->release(). Removed exclusive open and status bitmap. + * Added microcode_rwsem to serialize read()/write()/ioctl(). + * Removed global kernel lock usage. + * 1.07 07 Sep 2000, Tigran Aivazian + * Write 0 to 0x8B msr and then cpuid before reading revision, + * so that it works even if there were no update done by the + * BIOS. Otherwise, reading from 0x8B gives junk (which happened + * to be 0 on my machine which is why it worked even when I + * disabled update by the BIOS) + * Thanks to Eric W. Biederman for the fix. + * 1.08 11 Dec 2000, Richard Schaal and + * Tigran Aivazian + * Intel Pentium 4 processor support and bugfixes. + * 1.09 30 Oct 2001, Tigran Aivazian + * Bugfix for HT (Hyper-Threading) enabled processors + * whereby processor resources are shared by all logical processors + * in a single CPU package. + * 1.10 28 Feb 2002 Asit K Mallick and + * Tigran Aivazian , + * Serialize updates as required on HT processors due to speculative + * nature of implementation. + * 1.11 22 Mar 2002 Tigran Aivazian + * Fix the panic when writing zero-length microcode chunk. + * 1.12 29 Sep 2003 Nitin Kamble , + * Jun Nakajima + * Support for the microcode updates in the new format. + * 1.13 10 Oct 2003 Tigran Aivazian + * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl + * because we no longer hold a copy of applied microcode + * in kernel memory. + * 1.14 25 Jun 2004 Tigran Aivazian + * Fix sigmatch() macro to handle old CPUs with pf == 0. + * Thanks to Stuart Swales for pointing out this bug. + */ + +//#define DEBUG /* pr_debug */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +MODULE_DESCRIPTION("Microcode Update Driver"); +MODULE_AUTHOR("Tigran Aivazian "); +MODULE_LICENSE("GPL"); + +#define MICROCODE_VERSION "1.14a" + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +DEFINE_MUTEX(microcode_mutex); + +struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; + +extern long get_next_ucode(void **mc, long offset); +extern int microcode_sanity_check(void *mc); +extern int get_matching_microcode(void *mc, int cpu); +extern void collect_cpu_info(int cpu_num); +extern int cpu_request_microcode(int cpu); +extern void microcode_fini_cpu(int cpu); +extern void apply_microcode(int cpu); +extern int apply_microcode_check_cpu(int cpu); + +#ifdef CONFIG_MICROCODE_OLD_INTERFACE +void __user *user_buffer; /* user area microcode data buffer */ +unsigned int user_buffer_size; /* it's size */ + +static int do_microcode_update (void) +{ + long cursor = 0; + int error = 0; + void *new_mc = NULL; + int cpu; + cpumask_t old; + cpumask_of_cpu_ptr_declare(newmask); + + old = current->cpus_allowed; + + while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { + error = microcode_sanity_check(new_mc); + if (error) + goto out; + /* + * It's possible the data file has multiple matching ucode, + * lets keep searching till the latest version + */ + for_each_online_cpu(cpu) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!uci->valid) + continue; + cpumask_of_cpu_ptr_next(newmask, cpu); + set_cpus_allowed_ptr(current, newmask); + error = get_maching_microcode(new_mc, cpu); + if (error < 0) + goto out; + if (error == 1) + apply_microcode(cpu); + } + vfree(new_mc); + } +out: + if (cursor > 0) + vfree(new_mc); + if (cursor < 0) + error = cursor; + set_cpus_allowed_ptr(current, &old); + return error; +} + +static int microcode_open (struct inode *unused1, struct file *unused2) +{ + cycle_kernel_lock(); + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) +{ + ssize_t ret; + + if ((len >> PAGE_SHIFT) > num_physpages) { + printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); + return -EINVAL; + } + + get_online_cpus(); + mutex_lock(µcode_mutex); + + user_buffer = (void __user *) buf; + user_buffer_size = (int) len; + + ret = do_microcode_update(); + if (!ret) + ret = (ssize_t)len; + + mutex_unlock(µcode_mutex); + put_online_cpus(); + + return ret; +} + +static const struct file_operations microcode_fops = { + .owner = THIS_MODULE, + .write = microcode_write, + .open = microcode_open, +}; + +static struct miscdevice microcode_dev = { + .minor = MICROCODE_MINOR, + .name = "microcode", + .fops = µcode_fops, +}; + +static int __init microcode_dev_init (void) +{ + int error; + + error = misc_register(µcode_dev); + if (error) { + printk(KERN_ERR + "microcode: can't misc_register on minor=%d\n", + MICROCODE_MINOR); + return error; + } + + return 0; +} + +static void microcode_dev_exit (void) +{ + misc_deregister(µcode_dev); +} + +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); +#else +#define microcode_dev_init() 0 +#define microcode_dev_exit() do { } while(0) +#endif + +/* fake device for request_firmware */ +struct platform_device *microcode_pdev; + +static void microcode_init_cpu(int cpu, int resume) +{ + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + old = current->cpus_allowed; + + set_cpus_allowed_ptr(current, newmask); + mutex_lock(µcode_mutex); + collect_cpu_info(cpu); + if (uci->valid && system_state == SYSTEM_RUNNING && !resume) + cpu_request_microcode(cpu); + mutex_unlock(µcode_mutex); + set_cpus_allowed_ptr(current, &old); +} + +static ssize_t reload_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t sz) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + char *end; + unsigned long val = simple_strtoul(buf, &end, 0); + int err = 0; + int cpu = dev->id; + + if (end == buf) + return -EINVAL; + if (val == 1) { + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + + old = current->cpus_allowed; + + get_online_cpus(); + set_cpus_allowed_ptr(current, newmask); + + mutex_lock(µcode_mutex); + if (uci->valid) + err = cpu_request_microcode(cpu); + mutex_unlock(µcode_mutex); + put_online_cpus(); + set_cpus_allowed_ptr(current, &old); + } + if (err) + return err; + return sz; +} + +static ssize_t version_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->rev); +} + +static ssize_t pf_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->pf); +} + +static SYSDEV_ATTR(reload, 0200, NULL, reload_store); +static SYSDEV_ATTR(version, 0400, version_show, NULL); +static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); + +static struct attribute *mc_default_attrs[] = { + &attr_reload.attr, + &attr_version.attr, + &attr_processor_flags.attr, + NULL +}; + +static struct attribute_group mc_attr_group = { + .attrs = mc_default_attrs, + .name = "microcode", +}; + +static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) +{ + int err, cpu = sys_dev->id; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d added\n", cpu); + memset(uci, 0, sizeof(*uci)); + + err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); + if (err) + return err; + + microcode_init_cpu(cpu, resume); + + return 0; +} + +static int mc_sysdev_add(struct sys_device *sys_dev) +{ + return __mc_sysdev_add(sys_dev, 0); +} + +static int mc_sysdev_remove(struct sys_device *sys_dev) +{ + int cpu = sys_dev->id; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d removed\n", cpu); + microcode_fini_cpu(cpu); + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + return 0; +} + +static int mc_sysdev_resume(struct sys_device *dev) +{ + int cpu = dev->id; + + if (!cpu_online(cpu)) + return 0; + pr_debug("microcode: CPU%d resumed\n", cpu); + /* only CPU 0 will apply ucode here */ + apply_microcode(0); + return 0; +} + +static struct sysdev_driver mc_sysdev_driver = { + .add = mc_sysdev_add, + .remove = mc_sysdev_remove, + .resume = mc_sysdev_resume, +}; + +static __cpuinit int +mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + switch (action) { + case CPU_UP_CANCELED_FROZEN: + /* The CPU refused to come up during a system resume */ + microcode_fini_cpu(cpu); + break; + case CPU_ONLINE: + case CPU_DOWN_FAILED: + mc_sysdev_add(sys_dev); + break; + case CPU_ONLINE_FROZEN: + /* System-wide resume is in progress, try to apply microcode */ + if (apply_microcode_check_cpu(cpu)) { + /* The application of microcode failed */ + microcode_fini_cpu(cpu); + __mc_sysdev_add(sys_dev, 1); + break; + } + case CPU_DOWN_FAILED_FROZEN: + if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) + printk(KERN_ERR "microcode: Failed to create the sysfs " + "group for CPU%d\n", cpu); + break; + case CPU_DOWN_PREPARE: + mc_sysdev_remove(sys_dev); + break; + case CPU_DOWN_PREPARE_FROZEN: + /* Suspend is in progress, only remove the interface */ + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __refdata mc_cpu_notifier = { + .notifier_call = mc_cpu_callback, +}; + +static int __init microcode_init (void) +{ + int error; + + printk(KERN_INFO + "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); + + error = microcode_dev_init(); + if (error) + return error; + microcode_pdev = platform_device_register_simple("microcode", -1, + NULL, 0); + if (IS_ERR(microcode_pdev)) { + microcode_dev_exit(); + return PTR_ERR(microcode_pdev); + } + + get_online_cpus(); + error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + if (error) { + microcode_dev_exit(); + platform_device_unregister(microcode_pdev); + return error; + } + + register_hotcpu_notifier(&mc_cpu_notifier); + return 0; +} + +static void __exit microcode_exit (void) +{ + microcode_dev_exit(); + + unregister_hotcpu_notifier(&mc_cpu_notifier); + + get_online_cpus(); + sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + + platform_device_unregister(microcode_pdev); +} + +module_init(microcode_init) +module_exit(microcode_exit) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 4e7b2f65fed..eded0a154ea 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -95,18 +95,16 @@ #include #include -MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); +MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define MICROCODE_VERSION "1.14a" - #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof (struct microcode_header)) /* 48 bytes */ +#define MC_HEADER_SIZE (sizeof(struct microcode_header)) /* 48 bytes */ #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ -#define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ -#define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ -#define DWSIZE (sizeof (u32)) +#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ +#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ +#define DWSIZE (sizeof(u32)) #define get_totalsize(mc) \ (((struct microcode *)mc)->hdr.totalsize ? \ ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) @@ -123,11 +121,11 @@ MODULE_LICENSE("GPL"); static DEFINE_SPINLOCK(microcode_update_lock); /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DEFINE_MUTEX(microcode_mutex); +extern struct mutex microcode_mutex; -static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; -static void collect_cpu_info(int cpu_num) +void collect_cpu_info(int cpu_num) { struct cpuinfo_x86 *c = &cpu_data(cpu_num); struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -140,7 +138,7 @@ static void collect_cpu_info(int cpu_num) uci->valid = 1; if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || - cpu_has(c, X86_FEATURE_IA64)) { + cpu_has(c, X86_FEATURE_IA64)) { printk(KERN_ERR "microcode: CPU%d not a capable Intel " "processor\n", cpu_num); uci->valid = 0; @@ -175,7 +173,7 @@ static inline int microcode_update_match(int cpu_num, return 1; } -static int microcode_sanity_check(void *mc) +int microcode_sanity_check(void *mc) { struct microcode_header *mc_header = mc; struct extended_sigtable *ext_header = NULL; @@ -259,7 +257,7 @@ static int microcode_sanity_check(void *mc) * return 1 - found update * return < 0 - error */ -static int get_maching_microcode(void *mc, int cpu) +int get_matching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct microcode_header *mc_header = mc; @@ -288,7 +286,7 @@ static int get_maching_microcode(void *mc, int cpu) return 0; find: pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev); + " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev); new_mc = vmalloc(total_size); if (!new_mc) { printk(KERN_ERR "microcode: error! Can not allocate memory\n"); @@ -303,7 +301,7 @@ find: return 1; } -static void apply_microcode(int cpu) +void apply_microcode(int cpu) { unsigned long flags; unsigned int val[2]; @@ -344,10 +342,10 @@ static void apply_microcode(int cpu) } #ifdef CONFIG_MICROCODE_OLD_INTERFACE -static void __user *user_buffer; /* user area microcode data buffer */ -static unsigned int user_buffer_size; /* it's size */ +extern void __user *user_buffer; /* user area microcode data buffer */ +extern unsigned int user_buffer_size; /* it's size */ -static long get_next_ucode(void **mc, long offset) +long get_next_ucode(void **mc, long offset) { struct microcode_header mc_header; unsigned long total_size; @@ -375,117 +373,6 @@ static long get_next_ucode(void **mc, long offset) } return offset + total_size; } - -static int do_microcode_update (void) -{ - long cursor = 0; - int error = 0; - void *new_mc = NULL; - int cpu; - cpumask_t old; - cpumask_of_cpu_ptr_declare(newmask); - - old = current->cpus_allowed; - - while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { - error = microcode_sanity_check(new_mc); - if (error) - goto out; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - for_each_online_cpu(cpu) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!uci->valid) - continue; - cpumask_of_cpu_ptr_next(newmask, cpu); - set_cpus_allowed_ptr(current, newmask); - error = get_maching_microcode(new_mc, cpu); - if (error < 0) - goto out; - if (error == 1) - apply_microcode(cpu); - } - vfree(new_mc); - } -out: - if (cursor > 0) - vfree(new_mc); - if (cursor < 0) - error = cursor; - set_cpus_allowed_ptr(current, &old); - return error; -} - -static int microcode_open (struct inode *unused1, struct file *unused2) -{ - cycle_kernel_lock(); - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) -{ - ssize_t ret; - - if ((len >> PAGE_SHIFT) > num_physpages) { - printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); - return -EINVAL; - } - - get_online_cpus(); - mutex_lock(µcode_mutex); - - user_buffer = (void __user *) buf; - user_buffer_size = (int) len; - - ret = do_microcode_update(); - if (!ret) - ret = (ssize_t)len; - - mutex_unlock(µcode_mutex); - put_online_cpus(); - - return ret; -} - -static const struct file_operations microcode_fops = { - .owner = THIS_MODULE, - .write = microcode_write, - .open = microcode_open, -}; - -static struct miscdevice microcode_dev = { - .minor = MICROCODE_MINOR, - .name = "microcode", - .fops = µcode_fops, -}; - -static int __init microcode_dev_init (void) -{ - int error; - - error = misc_register(µcode_dev); - if (error) { - printk(KERN_ERR - "microcode: can't misc_register on minor=%d\n", - MICROCODE_MINOR); - return error; - } - - return 0; -} - -static void microcode_dev_exit (void) -{ - misc_deregister(µcode_dev); -} - -MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); -#else -#define microcode_dev_init() 0 -#define microcode_dev_exit() do { } while(0) #endif static long get_next_ucode_from_buffer(void **mc, const u8 *buf, @@ -515,9 +402,9 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf, } /* fake device for request_firmware */ -static struct platform_device *microcode_pdev; +extern struct platform_device *microcode_pdev; -static int cpu_request_microcode(int cpu) +int cpu_request_microcode(int cpu) { char name[30]; struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -530,7 +417,7 @@ static int cpu_request_microcode(int cpu) /* We should bind the task to the CPU */ BUG_ON(cpu != raw_smp_processor_id()); - sprintf(name,"intel-ucode/%02x-%02x-%02x", + sprintf(name, "intel-ucode/%02x-%02x-%02x", c->x86, c->x86_model, c->x86_mask); error = request_firmware(&firmware, name, µcode_pdev->dev); if (error) { @@ -544,7 +431,7 @@ static int cpu_request_microcode(int cpu) error = microcode_sanity_check(mc); if (error) break; - error = get_maching_microcode(mc, cpu); + error = get_matching_microcode(mc, cpu); if (error < 0) break; /* @@ -566,7 +453,7 @@ static int cpu_request_microcode(int cpu) return error; } -static int apply_microcode_check_cpu(int cpu) +int apply_microcode_check_cpu(int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -615,241 +502,13 @@ static int apply_microcode_check_cpu(int cpu) return err; } -static void microcode_init_cpu(int cpu, int resume) -{ - cpumask_t old; - cpumask_of_cpu_ptr(newmask, cpu); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - old = current->cpus_allowed; - - set_cpus_allowed_ptr(current, newmask); - mutex_lock(µcode_mutex); - collect_cpu_info(cpu); - if (uci->valid && system_state == SYSTEM_RUNNING && !resume) - cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); - set_cpus_allowed_ptr(current, &old); -} - -static void microcode_fini_cpu(int cpu) +void microcode_fini_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; mutex_lock(µcode_mutex); uci->valid = 0; - vfree(uci->mc); + kfree(uci->mc); uci->mc = NULL; mutex_unlock(µcode_mutex); } - -static ssize_t reload_store(struct sys_device *dev, - struct sysdev_attribute *attr, - const char *buf, size_t sz) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - char *end; - unsigned long val = simple_strtoul(buf, &end, 0); - int err = 0; - int cpu = dev->id; - - if (end == buf) - return -EINVAL; - if (val == 1) { - cpumask_t old; - cpumask_of_cpu_ptr(newmask, cpu); - - old = current->cpus_allowed; - - get_online_cpus(); - set_cpus_allowed_ptr(current, newmask); - - mutex_lock(µcode_mutex); - if (uci->valid) - err = cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); - put_online_cpus(); - set_cpus_allowed_ptr(current, &old); - } - if (err) - return err; - return sz; -} - -static ssize_t version_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->rev); -} - -static ssize_t pf_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->pf); -} - -static SYSDEV_ATTR(reload, 0200, NULL, reload_store); -static SYSDEV_ATTR(version, 0400, version_show, NULL); -static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); - -static struct attribute *mc_default_attrs[] = { - &attr_reload.attr, - &attr_version.attr, - &attr_processor_flags.attr, - NULL -}; - -static struct attribute_group mc_attr_group = { - .attrs = mc_default_attrs, - .name = "microcode", -}; - -static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) -{ - int err, cpu = sys_dev->id; - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d added\n", cpu); - memset(uci, 0, sizeof(*uci)); - - err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); - if (err) - return err; - - microcode_init_cpu(cpu, resume); - - return 0; -} - -static int mc_sysdev_add(struct sys_device *sys_dev) -{ - return __mc_sysdev_add(sys_dev, 0); -} - -static int mc_sysdev_remove(struct sys_device *sys_dev) -{ - int cpu = sys_dev->id; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d removed\n", cpu); - microcode_fini_cpu(cpu); - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - return 0; -} - -static int mc_sysdev_resume(struct sys_device *dev) -{ - int cpu = dev->id; - - if (!cpu_online(cpu)) - return 0; - pr_debug("microcode: CPU%d resumed\n", cpu); - /* only CPU 0 will apply ucode here */ - apply_microcode(0); - return 0; -} - -static struct sysdev_driver mc_sysdev_driver = { - .add = mc_sysdev_add, - .remove = mc_sysdev_remove, - .resume = mc_sysdev_resume, -}; - -static __cpuinit int -mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - struct sys_device *sys_dev; - - sys_dev = get_cpu_sysdev(cpu); - switch (action) { - case CPU_UP_CANCELED_FROZEN: - /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); - break; - case CPU_ONLINE: - case CPU_DOWN_FAILED: - mc_sysdev_add(sys_dev); - break; - case CPU_ONLINE_FROZEN: - /* System-wide resume is in progress, try to apply microcode */ - if (apply_microcode_check_cpu(cpu)) { - /* The application of microcode failed */ - microcode_fini_cpu(cpu); - __mc_sysdev_add(sys_dev, 1); - break; - } - case CPU_DOWN_FAILED_FROZEN: - if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) - printk(KERN_ERR "microcode: Failed to create the sysfs " - "group for CPU%d\n", cpu); - break; - case CPU_DOWN_PREPARE: - mc_sysdev_remove(sys_dev); - break; - case CPU_DOWN_PREPARE_FROZEN: - /* Suspend is in progress, only remove the interface */ - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block __refdata mc_cpu_notifier = { - .notifier_call = mc_cpu_callback, -}; - -static int __init microcode_init (void) -{ - int error; - - printk(KERN_INFO - "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); - - error = microcode_dev_init(); - if (error) - return error; - microcode_pdev = platform_device_register_simple("microcode", -1, - NULL, 0); - if (IS_ERR(microcode_pdev)) { - microcode_dev_exit(); - return PTR_ERR(microcode_pdev); - } - - get_online_cpus(); - error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - if (error) { - microcode_dev_exit(); - platform_device_unregister(microcode_pdev); - return error; - } - - register_hotcpu_notifier(&mc_cpu_notifier); - return 0; -} - -static void __exit microcode_exit (void) -{ - microcode_dev_exit(); - - unregister_hotcpu_notifier(&mc_cpu_notifier); - - get_online_cpus(); - sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - - platform_device_unregister(microcode_pdev); -} - -module_init(microcode_init) -module_exit(microcode_exit) -- cgit v1.2.3 From d4ee36686853d5714437c4409f17ad42bfaf4211 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:18 +0200 Subject: x86: structure declaration renaming Renamed common structures to vendor specific naming scheme so other vendors will be able to use the same naming convention. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 46 ++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index eded0a154ea..ca9861bf067 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -100,17 +100,19 @@ MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof(struct microcode_header)) /* 48 bytes */ +#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) /* 48 bytes */ #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ #define DWSIZE (sizeof(u32)) #define get_totalsize(mc) \ - (((struct microcode *)mc)->hdr.totalsize ? \ - ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) + (((struct microcode_intel *)mc)->hdr.totalsize ? \ + ((struct microcode_intel *)mc)->hdr.totalsize : \ + DEFAULT_UCODE_TOTALSIZE) + #define get_datasize(mc) \ - (((struct microcode *)mc)->hdr.datasize ? \ - ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) + (((struct microcode_intel *)mc)->hdr.datasize ? \ + ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) #define sigmatch(s1, s2, p1, p2) \ (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) @@ -134,7 +136,7 @@ void collect_cpu_info(int cpu_num) /* We should bind the task to the CPU */ BUG_ON(raw_smp_processor_id() != cpu_num); uci->pf = uci->rev = 0; - uci->mc = NULL; + uci->mc.mc_intel = NULL; uci->valid = 1; if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || @@ -163,7 +165,7 @@ void collect_cpu_info(int cpu_num) } static inline int microcode_update_match(int cpu_num, - struct microcode_header *mc_header, int sig, int pf) + struct microcode_header_intel *mc_header, int sig, int pf) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -175,7 +177,7 @@ static inline int microcode_update_match(int cpu_num, int microcode_sanity_check(void *mc) { - struct microcode_header *mc_header = mc; + struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header = NULL; struct extended_signature *ext_sig; unsigned long total_size, data_size, ext_table_size; @@ -260,7 +262,7 @@ int microcode_sanity_check(void *mc) int get_matching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - struct microcode_header *mc_header = mc; + struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header; unsigned long total_size = get_totalsize(mc_header); int ext_sigcount, i; @@ -294,10 +296,10 @@ find: } /* free previous update file */ - vfree(uci->mc); + vfree(uci->mc.mc_intel); memcpy(new_mc, mc, total_size); - uci->mc = new_mc; + uci->mc.mc_intel = new_mc; return 1; } @@ -311,7 +313,7 @@ void apply_microcode(int cpu) /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); - if (uci->mc == NULL) + if (uci->mc.mc_intel == NULL) return; /* serialize access to the physical write to MSR 0x79 */ @@ -319,8 +321,8 @@ void apply_microcode(int cpu) /* write microcode via MSR 0x79 */ wrmsr(MSR_IA32_UCODE_WRITE, - (unsigned long) uci->mc->bits, - (unsigned long) uci->mc->bits >> 16 >> 16); + (unsigned long) uci->mc.mc_intel->bits, + (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16); wrmsr(MSR_IA32_UCODE_REV, 0, 0); /* see notes above for revision 1.07. Apparent chip bug */ @@ -330,14 +332,14 @@ void apply_microcode(int cpu) rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); spin_unlock_irqrestore(µcode_update_lock, flags); - if (val[1] != uci->mc->hdr.rev) { + if (val[1] != uci->mc.mc_intel->hdr.rev) { printk(KERN_ERR "microcode: CPU%d update from revision " "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); return; } printk(KERN_INFO "microcode: CPU%d updated from revision " "0x%x to 0x%x, date = %08x \n", - cpu_num, uci->rev, val[1], uci->mc->hdr.date); + cpu_num, uci->rev, val[1], uci->mc.mc_intel->hdr.date); uci->rev = val[1]; } @@ -347,7 +349,7 @@ extern unsigned int user_buffer_size; /* it's size */ long get_next_ucode(void **mc, long offset) { - struct microcode_header mc_header; + struct microcode_header_intel mc_header; unsigned long total_size; /* No more data */ @@ -378,13 +380,13 @@ long get_next_ucode(void **mc, long offset) static long get_next_ucode_from_buffer(void **mc, const u8 *buf, unsigned long size, long offset) { - struct microcode_header *mc_header; + struct microcode_header_intel *mc_header; unsigned long total_size; /* No more data */ if (offset >= size) return 0; - mc_header = (struct microcode_header *)(buf + offset); + mc_header = (struct microcode_header_intel *)(buf + offset); total_size = get_totalsize(mc_header); if (offset + total_size > size) { @@ -463,7 +465,7 @@ int apply_microcode_check_cpu(int cpu) int err = 0; /* Check if the microcode is available */ - if (!uci->mc) + if (!uci->mc.mc_intel) return 0; old = current->cpus_allowed; @@ -508,7 +510,7 @@ void microcode_fini_cpu(int cpu) mutex_lock(µcode_mutex); uci->valid = 0; - kfree(uci->mc); - uci->mc = NULL; + kfree(uci->mc.mc_intel); + uci->mc.mc_intel = NULL; mutex_unlock(µcode_mutex); } -- cgit v1.2.3 From 8d86f390d9bb5b39f0a315838d1616de6363e1b9 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:21 +0200 Subject: x86: major refactoring Refactored code by introducing a two-module solution. There is one general module in which vendor specific modules can hook into. However, that is exclusive, there is only one vendor specific module allowed at a time. A CPU vendor check makes sure only the correct module for the underlying system gets called. Functinally in terms of patch loading itself there are no changes. This refactoring provides a basis for future implementations of other vendors' patch loaders. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 25 +++++++++--- arch/x86/kernel/Makefile | 4 +- arch/x86/kernel/microcode.c | 80 +++++++++++++++++++++++---------------- arch/x86/kernel/microcode_intel.c | 50 +++++++++++++++++++----- 4 files changed, 109 insertions(+), 50 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b6fa2877b17..6b0b885cf47 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -782,7 +782,7 @@ config X86_REBOOTFIXUPS Say N otherwise. config MICROCODE - tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" + tristate "/dev/cpu/microcode - microcode support" select FW_LOADER ---help--- If you say Y here, you will be able to update the microcode on @@ -791,14 +791,29 @@ config MICROCODE actual microcode binary data itself which is not shipped with the Linux kernel. - For latest news and information on obtaining all the required - ingredients for this driver, check: - . + This option selects the general module only, you need to select + at least one vendor specific module as well. To compile this driver as a module, choose M here: the module will be called microcode. -config MICROCODE_OLD_INTERFACE +config MICROCODE_INTEL + tristate "Intel microcode patch loading support" + depends on MICROCODE + default MICROCODE + select FW_LOADER + --help--- + This options enables microcode patch loading support for Intel + processors. + + For latest news and information on obtaining all the required + Intel ingredients for this driver, check: + . + + This driver is only available as a module: the module + will be called microcode_intel. + + config MICROCODE_OLD_INTERFACE def_bool y depends on MICROCODE diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index abb32aed7f4..f2f9f6da8c1 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -51,8 +51,8 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += ucode.o -ucode-objs := microcode.o microcode_intel.o +obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index c1047d7f7ed..1e42e79ca69 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -99,25 +99,22 @@ MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define MICROCODE_VERSION "1.14a" +#define MICROCODE_VERSION "2.00" -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -DEFINE_MUTEX(microcode_mutex); +struct microcode_ops *microcode_ops; -struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +static DEFINE_MUTEX(microcode_mutex); +EXPORT_SYMBOL_GPL(microcode_mutex); -extern long get_next_ucode(void **mc, long offset); -extern int microcode_sanity_check(void *mc); -extern int get_matching_microcode(void *mc, int cpu); -extern void collect_cpu_info(int cpu_num); -extern int cpu_request_microcode(int cpu); -extern void microcode_fini_cpu(int cpu); -extern void apply_microcode(int cpu); -extern int apply_microcode_check_cpu(int cpu); +static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +EXPORT_SYMBOL_GPL(ucode_cpu_info); #ifdef CONFIG_MICROCODE_OLD_INTERFACE -void __user *user_buffer; /* user area microcode data buffer */ -unsigned int user_buffer_size; /* it's size */ +static void __user *user_buffer; /* user area microcode data buffer */ +EXPORT_SYMBOL_GPL(user_buffer); +static unsigned int user_buffer_size; /* it's size */ +EXPORT_SYMBOL_GPL(user_buffer_size); static int do_microcode_update (void) { @@ -130,8 +127,8 @@ static int do_microcode_update (void) old = current->cpus_allowed; - while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { - error = microcode_sanity_check(new_mc); + while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) { + error = microcode_ops->microcode_sanity_check(new_mc); if (error) goto out; /* @@ -145,11 +142,12 @@ static int do_microcode_update (void) continue; cpumask_of_cpu_ptr_next(newmask, cpu); set_cpus_allowed_ptr(current, newmask); - error = get_maching_microcode(new_mc, cpu); + error = microcode_ops->get_matching_microcode(new_mc, + cpu); if (error < 0) goto out; if (error == 1) - apply_microcode(cpu); + microcode_ops->apply_microcode(cpu); } vfree(new_mc); } @@ -232,7 +230,8 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); #endif /* fake device for request_firmware */ -struct platform_device *microcode_pdev; +static struct platform_device *microcode_pdev; +EXPORT_SYMBOL_GPL(microcode_pdev); static void microcode_init_cpu(int cpu, int resume) { @@ -244,9 +243,9 @@ static void microcode_init_cpu(int cpu, int resume) set_cpus_allowed_ptr(current, newmask); mutex_lock(µcode_mutex); - collect_cpu_info(cpu); + microcode_ops->collect_cpu_info(cpu); if (uci->valid && system_state == SYSTEM_RUNNING && !resume) - cpu_request_microcode(cpu); + microcode_ops->cpu_request_microcode(cpu); mutex_unlock(µcode_mutex); set_cpus_allowed_ptr(current, &old); } @@ -274,7 +273,7 @@ static ssize_t reload_store(struct sys_device *dev, mutex_lock(µcode_mutex); if (uci->valid) - err = cpu_request_microcode(cpu); + err = microcode_ops->cpu_request_microcode(cpu); mutex_unlock(µcode_mutex); put_online_cpus(); set_cpus_allowed_ptr(current, &old); @@ -349,7 +348,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev) return 0; pr_debug("microcode: CPU%d removed\n", cpu); - microcode_fini_cpu(cpu); + microcode_ops->microcode_fini_cpu(cpu); sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); return 0; } @@ -362,7 +361,7 @@ static int mc_sysdev_resume(struct sys_device *dev) return 0; pr_debug("microcode: CPU%d resumed\n", cpu); /* only CPU 0 will apply ucode here */ - apply_microcode(0); + microcode_ops->apply_microcode(0); return 0; } @@ -382,7 +381,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) switch (action) { case CPU_UP_CANCELED_FROZEN: /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); + microcode_ops->microcode_fini_cpu(cpu); break; case CPU_ONLINE: case CPU_DOWN_FAILED: @@ -390,9 +389,9 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) break; case CPU_ONLINE_FROZEN: /* System-wide resume is in progress, try to apply microcode */ - if (apply_microcode_check_cpu(cpu)) { + if (microcode_ops->apply_microcode_check_cpu(cpu)) { /* The application of microcode failed */ - microcode_fini_cpu(cpu); + microcode_ops->microcode_fini_cpu(cpu); __mc_sysdev_add(sys_dev, 1); break; } @@ -416,12 +415,17 @@ static struct notifier_block __refdata mc_cpu_notifier = { .notifier_call = mc_cpu_callback, }; -static int __init microcode_init (void) +static int microcode_init(void *opaque, struct module *module) { + struct microcode_ops *ops = (struct microcode_ops *)opaque; int error; - printk(KERN_INFO - "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); + if (microcode_ops) { + printk(KERN_ERR "microcode: already loaded the other module\n"); + return -EEXIST; + } + + microcode_ops = ops; error = microcode_dev_init(); if (error) @@ -443,8 +447,15 @@ static int __init microcode_init (void) } register_hotcpu_notifier(&mc_cpu_notifier); + + printk(KERN_INFO + "Microcode Update Driver: v" MICROCODE_VERSION + " " + " \n"); + return 0; } +EXPORT_SYMBOL_GPL(microcode_init); static void __exit microcode_exit (void) { @@ -457,7 +468,10 @@ static void __exit microcode_exit (void) put_online_cpus(); platform_device_unregister(microcode_pdev); -} -module_init(microcode_init) -module_exit(microcode_exit) + microcode_ops = NULL; + + printk(KERN_INFO + "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); +} +EXPORT_SYMBOL_GPL(microcode_exit); diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index ca9861bf067..831db5363db 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -127,7 +127,7 @@ extern struct mutex microcode_mutex; extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; -void collect_cpu_info(int cpu_num) +static void collect_cpu_info(int cpu_num) { struct cpuinfo_x86 *c = &cpu_data(cpu_num); struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -175,7 +175,7 @@ static inline int microcode_update_match(int cpu_num, return 1; } -int microcode_sanity_check(void *mc) +static int microcode_sanity_check(void *mc) { struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header = NULL; @@ -259,7 +259,7 @@ int microcode_sanity_check(void *mc) * return 1 - found update * return < 0 - error */ -int get_matching_microcode(void *mc, int cpu) +static int get_matching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct microcode_header_intel *mc_header = mc; @@ -288,7 +288,8 @@ int get_matching_microcode(void *mc, int cpu) return 0; find: pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev); + " version 0x%x (current=0x%x)\n", + cpu, mc_header->rev, uci->rev); new_mc = vmalloc(total_size); if (!new_mc) { printk(KERN_ERR "microcode: error! Can not allocate memory\n"); @@ -303,7 +304,7 @@ find: return 1; } -void apply_microcode(int cpu) +static void apply_microcode(int cpu) { unsigned long flags; unsigned int val[2]; @@ -347,7 +348,7 @@ void apply_microcode(int cpu) extern void __user *user_buffer; /* user area microcode data buffer */ extern unsigned int user_buffer_size; /* it's size */ -long get_next_ucode(void **mc, long offset) +static long get_next_ucode(void **mc, long offset) { struct microcode_header_intel mc_header; unsigned long total_size; @@ -406,7 +407,7 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf, /* fake device for request_firmware */ extern struct platform_device *microcode_pdev; -int cpu_request_microcode(int cpu) +static int cpu_request_microcode(int cpu) { char name[30]; struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -455,7 +456,7 @@ int cpu_request_microcode(int cpu) return error; } -int apply_microcode_check_cpu(int cpu) +static int apply_microcode_check_cpu(int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -504,13 +505,42 @@ int apply_microcode_check_cpu(int cpu) return err; } -void microcode_fini_cpu(int cpu) +static void microcode_fini_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; mutex_lock(µcode_mutex); uci->valid = 0; - kfree(uci->mc.mc_intel); + vfree(uci->mc.mc_intel); uci->mc.mc_intel = NULL; mutex_unlock(µcode_mutex); } + +static struct microcode_ops microcode_intel_ops = { + .get_next_ucode = get_next_ucode, + .get_matching_microcode = get_matching_microcode, + .microcode_sanity_check = microcode_sanity_check, + .apply_microcode_check_cpu = apply_microcode_check_cpu, + .cpu_request_microcode = cpu_request_microcode, + .collect_cpu_info = collect_cpu_info, + .apply_microcode = apply_microcode, + .microcode_fini_cpu = microcode_fini_cpu, +}; + +static int __init microcode_intel_module_init(void) +{ + struct cpuinfo_x86 *c = &cpu_data(get_cpu()); + + if (c->x86_vendor == X86_VENDOR_INTEL) + return microcode_init(µcode_intel_ops, THIS_MODULE); + else + return -ENODEV; +} + +static void __exit microcode_intel_module_exit(void) +{ + microcode_exit(); +} + +module_init(microcode_intel_module_init) +module_exit(microcode_intel_module_exit) -- cgit v1.2.3 From 80cc9f1020f49c9e5b50898c102fd444de70a0a3 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:22 +0200 Subject: x86: AMD microcode patch loading support This patch introduces microcode patch loading for AMD processors. It is based on previous corresponding work for Intel processors. It hooks into the general patch loading module. Main difference is that a container file format is used to hold all patch data for multiple processors as well as an equivalent CPU table, which comes seperately, as opposed to Intel's microcode patching solution. Kconfig and Makefile have been changed provice config and build option for new source file. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 21 +- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/microcode_amd.c | 521 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 539 insertions(+), 4 deletions(-) create mode 100644 arch/x86/kernel/microcode_amd.c (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6b0b885cf47..7bb461758d3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -786,10 +786,12 @@ config MICROCODE select FW_LOADER ---help--- If you say Y here, you will be able to update the microcode on - Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II, - Pentium III, Pentium 4, Xeon etc. You will obviously need the - actual microcode binary data itself which is not shipped with the - Linux kernel. + certain Intel and AMD processors. The Intel support is for the + IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, + Pentium 4, Xeon etc. The AMD support is for family 0x10 and + 0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra. + You will obviously need the actual microcode binary data itself + which is not shipped with the Linux kernel. This option selects the general module only, you need to select at least one vendor specific module as well. @@ -813,6 +815,17 @@ config MICROCODE_INTEL This driver is only available as a module: the module will be called microcode_intel. +config MICROCODE_AMD + tristate "AMD microcode patch loading support" + depends on MICROCODE + select FW_LOADER + --help--- + If you select this option, microcode patch loading support for AMD + processors will be enabled. + + This driver is only available as a module: the module + will be called microcode_amd. + config MICROCODE_OLD_INTERFACE def_bool y depends on MICROCODE diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index f2f9f6da8c1..be454f348c3 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o +obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c new file mode 100644 index 00000000000..db199e3fdd1 --- /dev/null +++ b/arch/x86/kernel/microcode_amd.c @@ -0,0 +1,521 @@ +/* + * AMD CPU Microcode Update Driver for Linux + * Copyright (C) 2008 Advanced Micro Devices Inc. + * + * Author: Peter Oruba + * + * Based on work by: + * Tigran Aivazian + * + * This driver allows to upgrade microcode on AMD + * family 0x10 and 0x11 processors. + * + * Licensed unter the terms of the GNU General Public + * License version 2. See file COPYING for details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +MODULE_DESCRIPTION("AMD Microcode Update Driver"); +MODULE_AUTHOR("Peter Oruba "); +MODULE_LICENSE("GPLv2"); + +#define UCODE_MAGIC 0x00414d44 +#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 +#define UCODE_UCODE_TYPE 0x00000001 + +#define UCODE_MAX_SIZE (2048) +#define DEFAULT_UCODE_DATASIZE (896) /* 896 bytes */ +#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) /* 64 bytes */ +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 960 bytes */ +#define DWSIZE (sizeof(u32)) +/* For now we support a fixed ucode total size only */ +#define get_totalsize(mc) \ + ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \ + + MC_HEADER_SIZE) + +extern int microcode_init(void *opaque, struct module *module); +extern void microcode_exit(void); + +/* serialize access to the physical write */ +static DEFINE_SPINLOCK(microcode_update_lock); + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +extern struct mutex (microcode_mutex); + +struct equiv_cpu_entry *equiv_cpu_table; + +extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; + +static void collect_cpu_info_amd(int cpu) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + /* We should bind the task to the CPU */ + BUG_ON(raw_smp_processor_id() != cpu); + uci->rev = 0; + uci->pf = 0; + uci->mc.mc_amd = NULL; + uci->valid = 1; + + if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { + printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n", + cpu); + uci->valid = 0; + return; + } + + asm volatile("movl %1, %%ecx; rdmsr" + : "=a" (uci->rev) + : "i" (0x0000008B) : "ecx"); + + printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n", + uci->rev); +} + +static int get_matching_microcode_amd(void *mc, int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct microcode_header_amd *mc_header = mc; + unsigned long total_size = get_totalsize(mc_header); + void *new_mc; + struct pci_dev *nb_pci_dev, *sb_pci_dev; + unsigned int current_cpu_id; + unsigned int equiv_cpu_id = 0x00; + unsigned int i = 0; + + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + + /* This is a tricky part. We might be called from a write operation */ + /* to the device file instead of the usual process of firmware */ + /* loading. This routine needs to be able to distinguish both */ +/* cases. This is done by checking if there alread is a equivalent */ + /* CPU table installed. If not, we're written through */ + /* /dev/cpu/microcode. */ +/* Since we ignore all checks. The error case in which going through */ +/* firmware loading and that table is not loaded has already been */ + /* checked earlier. */ + if (equiv_cpu_table == NULL) { + printk(KERN_INFO "microcode: CPU%d microcode update with " + "version 0x%x (current=0x%x)\n", + cpu, mc_header->patch_id, uci->rev); + goto out; + } + + current_cpu_id = cpuid_eax(0x00000001); + + while (equiv_cpu_table[i].installed_cpu != 0) { + if (current_cpu_id == equiv_cpu_table[i].installed_cpu) { + equiv_cpu_id = equiv_cpu_table[i].equiv_cpu; + break; + } + i++; + } + + if (!equiv_cpu_id) { + printk(KERN_ERR "microcode: CPU%d cpu_id " + "not found in equivalent cpu table \n", cpu); + return 0; + } + + if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) { + printk(KERN_ERR + "microcode: CPU%d patch does not match " + "(patch is %x, cpu extended is %x) \n", + cpu, mc_header->processor_rev_id[0], + (equiv_cpu_id & 0xff)); + return 0; + } + + if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) { + printk(KERN_ERR "microcode: CPU%d patch does not match " + "(patch is %x, cpu base id is %x) \n", + cpu, mc_header->processor_rev_id[1], + ((equiv_cpu_id >> 16) & 0xff)); + + return 0; + } + + /* ucode may be northbridge specific */ + if (mc_header->nb_dev_id) { + nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, + (mc_header->nb_dev_id & 0xff), + NULL); + if ((!nb_pci_dev) || + (mc_header->nb_rev_id != nb_pci_dev->revision)) { + printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu); + pci_dev_put(nb_pci_dev); + return 0; + } + pci_dev_put(nb_pci_dev); + } + + /* ucode may be southbridge specific */ + if (mc_header->sb_dev_id) { + sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, + (mc_header->sb_dev_id & 0xff), + NULL); + if ((!sb_pci_dev) || + (mc_header->sb_rev_id != sb_pci_dev->revision)) { + printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu); + pci_dev_put(sb_pci_dev); + return 0; + } + pci_dev_put(sb_pci_dev); + } + + if (mc_header->patch_id <= uci->rev) + return 0; + + printk(KERN_INFO "microcode: CPU%d found a matching microcode " + "update with version 0x%x (current=0x%x)\n", + cpu, mc_header->patch_id, uci->rev); + +out: + new_mc = vmalloc(UCODE_MAX_SIZE); + if (!new_mc) { + printk(KERN_ERR "microcode: error, can't allocate memory\n"); + return -ENOMEM; + } + memset(new_mc, 0, UCODE_MAX_SIZE); + + /* free previous update file */ + vfree(uci->mc.mc_amd); + + memcpy(new_mc, mc, total_size); + + uci->mc.mc_amd = new_mc; + return 1; +} + +static void apply_microcode_amd(int cpu) +{ + unsigned long flags; + unsigned int eax, edx; + unsigned int rev; + int cpu_num = raw_smp_processor_id(); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + + /* We should bind the task to the CPU */ + BUG_ON(cpu_num != cpu); + + if (uci->mc.mc_amd == NULL) + return; + + spin_lock_irqsave(µcode_update_lock, flags); + + edx = (unsigned int)(((unsigned long) + &(uci->mc.mc_amd->hdr.data_code)) >> 32); + eax = (unsigned int)(((unsigned long) + &(uci->mc.mc_amd->hdr.data_code)) & 0xffffffffL); + + asm volatile("movl %0, %%ecx; wrmsr" : + : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx"); + + /* get patch id after patching */ + asm volatile("movl %1, %%ecx; rdmsr" + : "=a" (rev) + : "i" (0x0000008B) : "ecx"); + + spin_unlock_irqrestore(µcode_update_lock, flags); + + /* check current patch id and patch's id for match */ + if (rev != uci->mc.mc_amd->hdr.patch_id) { + printk(KERN_ERR "microcode: CPU%d update from revision " + "0x%x to 0x%x failed\n", cpu_num, + uci->mc.mc_amd->hdr.patch_id, rev); + return; + } + + printk(KERN_INFO "microcode: CPU%d updated from revision " + "0x%x to 0x%x \n", + cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id); + + uci->rev = rev; +} + +#ifdef CONFIG_MICROCODE_OLD_INTERFACE +extern void __user *user_buffer; /* user area microcode data buffer */ +extern unsigned int user_buffer_size; /* it's size */ + +static long get_next_ucode_amd(void **mc, long offset) +{ + struct microcode_header_amd mc_header; + unsigned long total_size; + + /* No more data */ + if (offset >= user_buffer_size) + return 0; + if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + return -EFAULT; + } + total_size = get_totalsize(&mc_header); + if (offset + total_size > user_buffer_size) { + printk(KERN_ERR "microcode: error! Bad total size in microcode " + "data file\n"); + return -EINVAL; + } + *mc = vmalloc(UCODE_MAX_SIZE); + if (!*mc) + return -ENOMEM; + memset(*mc, 0, UCODE_MAX_SIZE); + + if (copy_from_user(*mc, user_buffer + offset, total_size)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + vfree(*mc); + return -EFAULT; + } + return offset + total_size; +} +#else +#define get_next_ucode_amd() NULL +#endif + +static long get_next_ucode_from_buffer_amd(void **mc, void *buf, + unsigned long size, long offset) +{ + struct microcode_header_amd *mc_header; + unsigned long total_size; + unsigned char *buf_pos = buf; + + /* No more data */ + if (offset >= size) + return 0; + + if (buf_pos[offset] != UCODE_UCODE_TYPE) { + printk(KERN_ERR "microcode: error! " + "Wrong microcode payload type field\n"); + return -EINVAL; + } + + mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]); + + total_size = (unsigned long) (buf_pos[offset+4] + + (buf_pos[offset+5] << 8)); + + printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n", + size, total_size, offset); + + if (offset + total_size > size) { + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); + return -EINVAL; + } + + *mc = vmalloc(UCODE_MAX_SIZE); + if (!*mc) { + printk(KERN_ERR "microcode: error! " + "Can not allocate memory for microcode patch\n"); + return -ENOMEM; + } + + memset(*mc, 0, UCODE_MAX_SIZE); + memcpy(*mc, buf + offset + 8, total_size); + + return offset + total_size + 8; +} + +static long install_equiv_cpu_table(void *buf, unsigned long size, long offset) +{ + unsigned int *buf_pos = buf; + + /* No more data */ + if (offset >= size) + return 0; + + if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) { + printk(KERN_ERR "microcode: error! " + "Wrong microcode equivalnet cpu table type field\n"); + return 0; + } + + if (size == 0) { + printk(KERN_ERR "microcode: error! " + "Wrong microcode equivalnet cpu table length\n"); + return 0; + } + + equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size); + if (!equiv_cpu_table) { + printk(KERN_ERR "microcode: error, can't allocate memory for equiv CPU table\n"); + return 0; + } + + memset(equiv_cpu_table, 0, size); + memcpy(equiv_cpu_table, &buf_pos[3], size); + + return size + 12; /* add header length */ +} + +/* fake device for request_firmware */ +extern struct platform_device *microcode_pdev; + +static int cpu_request_microcode_amd(int cpu) +{ + char name[30]; + const struct firmware *firmware; + void *buf; + unsigned int *buf_pos; + unsigned long size; + long offset = 0; + int error; + void *mc; + + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + + sprintf(name, "amd-ucode/microcode_amd.bin"); + error = request_firmware(&firmware, "amd-ucode/microcode_amd.bin", + µcode_pdev->dev); + if (error) { + printk(KERN_ERR "microcode: ucode data file %s load failed\n", + name); + return error; + } + + buf_pos = buf = firmware->data; + size = firmware->size; + + if (buf_pos[0] != UCODE_MAGIC) { + printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n"); + return -EINVAL; + } + + offset = install_equiv_cpu_table(buf, buf_pos[2], offset); + + if (!offset) { + printk(KERN_ERR "microcode: installing equivalent cpu table failed\n"); + return -EINVAL; + } + + while ((offset = + get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) { + error = get_matching_microcode_amd(mc, cpu); + if (error < 0) + break; + /* + * It's possible the data file has multiple matching ucode, + * lets keep searching till the latest version + */ + if (error == 1) { + apply_microcode_amd(cpu); + error = 0; + } + vfree(mc); + } + if (offset > 0) { + vfree(mc); + vfree(equiv_cpu_table); + equiv_cpu_table = NULL; + } + if (offset < 0) + error = offset; + release_firmware(firmware); + + return error; +} + +static int apply_microcode_check_cpu_amd(int cpu) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + unsigned int rev; + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + int err = 0; + + /* Check if the microcode is available */ + if (!uci->mc.mc_amd) + return 0; + + old = current->cpus_allowed; + set_cpus_allowed(current, newmask); + + /* Check if the microcode we have in memory matches the CPU */ + if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 16) + err = -EINVAL; + + if (!err) { + asm volatile("movl %1, %%ecx; rdmsr" + : "=a" (rev) + : "i" (0x0000008B) : "ecx"); + + if (uci->rev != rev) + err = -EINVAL; + } + + if (!err) + apply_microcode_amd(cpu); + else + printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" + " rev=0x%x\n", + cpu, uci->rev); + + set_cpus_allowed(current, old); + return err; +} + +static void microcode_fini_cpu_amd(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + mutex_lock(µcode_mutex); + uci->valid = 0; + vfree(uci->mc.mc_amd); + uci->mc.mc_amd = NULL; + mutex_unlock(µcode_mutex); +} + +static struct microcode_ops microcode_amd_ops = { + .get_next_ucode = get_next_ucode_amd, + .get_matching_microcode = get_matching_microcode_amd, + .microcode_sanity_check = NULL, + .apply_microcode_check_cpu = apply_microcode_check_cpu_amd, + .cpu_request_microcode = cpu_request_microcode_amd, + .collect_cpu_info = collect_cpu_info_amd, + .apply_microcode = apply_microcode_amd, + .microcode_fini_cpu = microcode_fini_cpu_amd, +}; + +static int __init microcode_amd_module_init(void) +{ + struct cpuinfo_x86 *c = &cpu_data(get_cpu()); + + equiv_cpu_table = NULL; + if (c->x86_vendor == X86_VENDOR_AMD) + return microcode_init(µcode_amd_ops, THIS_MODULE); + else + return -ENODEV; +} + +static void __exit microcode_amd_module_exit(void) +{ + microcode_exit(); +} + +module_init(microcode_amd_module_init) +module_exit(microcode_amd_module_exit) -- cgit v1.2.3 From 45b1e23eca1c53fa79a611a2bc8c93697ede6c97 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 29 Jul 2008 09:42:17 +0200 Subject: x86, microcode support: fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/microcode.c:412: error: static declaration of ‘microcode_init’ follows non-static declaration include/asm/microcode.h:1: error: previous declaration of ‘microcode_init’ was here arch/x86/kernel/microcode.c:454: error: static declaration of ‘microcode_exit’ follows non-static declaration include/asm/microcode.h:2: error: previous declaration of ‘microcode_exit’ was here Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 1e42e79ca69..9a881845b35 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -415,7 +415,7 @@ static struct notifier_block __refdata mc_cpu_notifier = { .notifier_call = mc_cpu_callback, }; -static int microcode_init(void *opaque, struct module *module) +int microcode_init(void *opaque, struct module *module) { struct microcode_ops *ops = (struct microcode_ops *)opaque; int error; @@ -457,7 +457,7 @@ static int microcode_init(void *opaque, struct module *module) } EXPORT_SYMBOL_GPL(microcode_init); -static void __exit microcode_exit (void) +void __exit microcode_exit (void) { microcode_dev_exit(); -- cgit v1.2.3 From 224e946b81166d732f3e9b414cb69612072fb500 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 29 Jul 2008 09:52:55 +0200 Subject: x86, microcode: fix symbol exports fix tons of build errors: arch/x86/kernel/built-in.o: In function `microcode_fini_cpu': microcode_intel.c:(.text+0x11598): undefined reference to `microcode_mutex' microcode_intel.c:(.text+0x115a4): undefined reference to `ucode_cpu_info' microcode_intel.c:(.text+0x115ae): undefined reference to `ucode_cpu_info' microcode_intel.c:(.text+0x115bc): undefined reference to `microcode_mutex' [...] Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 9a881845b35..758b958a663 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -104,16 +104,16 @@ MODULE_LICENSE("GPL"); struct microcode_ops *microcode_ops; /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DEFINE_MUTEX(microcode_mutex); +DEFINE_MUTEX(microcode_mutex); EXPORT_SYMBOL_GPL(microcode_mutex); -static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; EXPORT_SYMBOL_GPL(ucode_cpu_info); #ifdef CONFIG_MICROCODE_OLD_INTERFACE -static void __user *user_buffer; /* user area microcode data buffer */ +void __user *user_buffer; /* user area microcode data buffer */ EXPORT_SYMBOL_GPL(user_buffer); -static unsigned int user_buffer_size; /* it's size */ +unsigned int user_buffer_size; /* it's size */ EXPORT_SYMBOL_GPL(user_buffer_size); static int do_microcode_update (void) @@ -230,7 +230,7 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); #endif /* fake device for request_firmware */ -static struct platform_device *microcode_pdev; +struct platform_device *microcode_pdev; EXPORT_SYMBOL_GPL(microcode_pdev); static void microcode_init_cpu(int cpu, int resume) -- cgit v1.2.3 From 5d7b605245b1aa1a9cd6549b1f57d69273eb0c37 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 29 Jul 2008 10:07:36 +0200 Subject: x86, microcode: fix module license string fix: FATAL: modpost: GPL-incompatible module microcode_amd.ko uses GPL-only symbol 'set_cpus_allowed_ptr' Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index db199e3fdd1..fd9e68e8889 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -40,7 +40,7 @@ MODULE_DESCRIPTION("AMD Microcode Update Driver"); MODULE_AUTHOR("Peter Oruba "); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2"); #define UCODE_MAGIC 0x00414d44 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 -- cgit v1.2.3 From a648bf4632628c787abb0514277f2a231fca39ca Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:18 -0700 Subject: x86, xsave: xsave cpuid feature bits Add xsave CPU feature bits. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/feature_names.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index 0bf4d37a048..74154722565 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c @@ -46,7 +46,7 @@ const char * const x86_cap_flags[NCAPINTS*32] = { "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", NULL, "popcnt", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "xsave", NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", -- cgit v1.2.3 From dc1e35c6e95e8923cf1d3510438b63c600fee1e2 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:19 -0700 Subject: x86, xsave: enable xsave/xrstor on cpus with xsave support Enables xsave/xrstor by turning on cr4.osxsave on cpu's which have the xsave support. For now, features that OS supports/enabled are FP and SSE. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/cpu/common.c | 8 ++++ arch/x86/kernel/i387.c | 12 ++++++ arch/x86/kernel/traps_32.c | 1 - arch/x86/kernel/traps_64.c | 4 -- arch/x86/kernel/xsave.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 arch/x86/kernel/xsave.c (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a07ec14f331..d6ea91abaeb 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -38,7 +38,7 @@ obj-y += tsc.o io_delay.o rtc.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-y += process.o -obj-y += i387.o +obj-y += i387.o xsave.o obj-y += ptrace.o obj-y += ds.o obj-$(CONFIG_X86_32) += tls.o diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d4fa3..fabbcb7020f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -712,6 +712,14 @@ void __cpuinit cpu_init(void) current_thread_info()->status = 0; clear_used_math(); mxcsr_feature_mask_init(); + + /* + * Boot processor to setup the FP and extended state context info. + */ + if (!smp_processor_id()) + init_thread_xstate(); + + xsave_init(); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index eb9ddd8efb8..e22a9a9dce8 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -61,6 +61,11 @@ void __init init_thread_xstate(void) return; } + if (cpu_has_xsave) { + xsave_cntxt_init(); + return; + } + if (cpu_has_fxsr) xstate_size = sizeof(struct i387_fxsave_struct); #ifdef CONFIG_X86_32 @@ -83,6 +88,13 @@ void __cpuinit fpu_init(void) write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */ + /* + * Boot processor to setup the FP and extended state context info. + */ + if (!smp_processor_id()) + init_thread_xstate(); + xsave_init(); + mxcsr_feature_mask_init(); /* clean state in init */ current_thread_info()->status = 0; diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 03df8e45e5a..da5a5964fcc 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -1228,7 +1228,6 @@ void __init trap_init(void) set_bit(SYSCALL_VECTOR, used_vectors); - init_thread_xstate(); /* * Should be a barrier for any external CPU state: */ diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 513caaca711..3580a7938a2 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -1172,10 +1172,6 @@ void __init trap_init(void) #ifdef CONFIG_IA32_EMULATION set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall); #endif - /* - * initialize the per thread extended state: - */ - init_thread_xstate(); /* * Should be a barrier for any external CPU state: */ diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c new file mode 100644 index 00000000000..c68b7c4ca24 --- /dev/null +++ b/arch/x86/kernel/xsave.c @@ -0,0 +1,87 @@ +/* + * xsave/xrstor support. + * + * Author: Suresh Siddha + */ +#include +#include +#include + +/* + * Supported feature mask by the CPU and the kernel. + */ +unsigned int pcntxt_hmask, pcntxt_lmask; + +/* + * Represents init state for the supported extended state. + */ +struct xsave_struct *init_xstate_buf; + +/* + * Enable the extended processor state save/restore feature + */ +void __cpuinit xsave_init(void) +{ + if (!cpu_has_xsave) + return; + + set_in_cr4(X86_CR4_OSXSAVE); + + /* + * Enable all the features that the HW is capable of + * and the Linux kernel is aware of. + * + * xsetbv(); + */ + asm volatile(".byte 0x0f,0x01,0xd1" : : "c" (0), + "a" (pcntxt_lmask), "d" (pcntxt_hmask)); +} + +/* + * setup the xstate image representing the init state + */ +void setup_xstate_init(void) +{ + init_xstate_buf = alloc_bootmem(xstate_size); + init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; +} + +/* + * Enable and initialize the xsave feature. + */ +void __init xsave_cntxt_init(void) +{ + unsigned int eax, ebx, ecx, edx; + + cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); + + pcntxt_lmask = eax; + pcntxt_hmask = edx; + + if ((pcntxt_lmask & XSTATE_FPSSE) != XSTATE_FPSSE) { + printk(KERN_ERR "FP/SSE not shown under xsave features %x\n", + pcntxt_lmask); + BUG(); + } + + /* + * for now OS knows only about FP/SSE + */ + pcntxt_lmask = pcntxt_lmask & XCNTXT_LMASK; + pcntxt_hmask = pcntxt_hmask & XCNTXT_HMASK; + + xsave_init(); + + /* + * Recompute the context size for enabled features + */ + cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); + + xstate_size = ebx; + + setup_xstate_init(); + + printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, " + "cntxt size 0x%x\n", + (pcntxt_lmask | ((u64) pcntxt_hmask << 32)), xstate_size); +} -- cgit v1.2.3 From b359e8a434cc3d09847010fc4aeccf48d69740e4 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:20 -0700 Subject: x86, xsave: context switch support using xsave/xrstor Uses xsave/xrstor (instead of traditional fxsave/fxrstor) in context switch when available. Introduces TS_XSAVE flag, which determine the need to use xsave/xrstor instructions during context switch instead of the legacy fxsave/fxrstor instructions. Thread-synchronous status word is already in L1 cache during this code patch and thus minimizes the performance penality compared to (cpu_has_xsave) checks. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 5 ++++- arch/x86/kernel/i387.c | 5 ++++- arch/x86/kernel/traps_64.c | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index fabbcb7020f..6c2b9e756db 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -709,7 +709,10 @@ void __cpuinit cpu_init(void) /* * Force FPU initialization: */ - current_thread_info()->status = 0; + if (cpu_has_xsave) + current_thread_info()->status = TS_XSAVE; + else + current_thread_info()->status = 0; clear_used_math(); mxcsr_feature_mask_init(); diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index e22a9a9dce8..b778e17e4b0 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -97,7 +97,10 @@ void __cpuinit fpu_init(void) mxcsr_feature_mask_init(); /* clean state in init */ - current_thread_info()->status = 0; + if (cpu_has_xsave) + current_thread_info()->status = TS_XSAVE; + else + current_thread_info()->status = 0; clear_used_math(); } #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 3580a7938a2..38eb76156a4 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -1134,7 +1134,7 @@ asmlinkage void math_state_restore(void) /* * Paranoid restore. send a SIGSEGV if we fail to restore the state. */ - if (unlikely(restore_fpu_checking(&me->thread.xstate->fxsave))) { + if (unlikely(restore_fpu_checking(me))) { stts(); force_sig(SIGSEGV, me); return; -- cgit v1.2.3 From 3c1c7f101426cb2ecc79d817a8a65928965fc860 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:21 -0700 Subject: x86, xsave: dynamically allocate sigframes fpstate instead of static allocation dynamically allocate fpstate on the stack, instead of static allocation in the current sigframe layout on the user stack. This will allow the fpstate structure to grow in the future, which includes extended state information supporting xsave/xrstor. signal handlers will be able to access the fpstate pointer from the sigcontext structure asusual, with no change. For the non RT sigframe's (which are supported only for 32bit apps), current static fpstate layout in the sigframe will be unused(so that we don't change the extramask[] offset in the sigframe and thus prevent breaking app's which modify extramask[]). Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 24 ++++++++++++++++-------- arch/x86/kernel/i387.c | 2 ++ arch/x86/kernel/sigframe.h | 14 ++++++++++++-- arch/x86/kernel/signal_32.c | 18 +++++++++++++----- arch/x86/kernel/signal_64.c | 2 +- arch/x86/kernel/xsave.c | 4 ++++ 6 files changed, 48 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 20af4c79579..a05bf0fb741 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -179,9 +179,10 @@ struct sigframe u32 pretcode; int sig; struct sigcontext_ia32 sc; - struct _fpstate_ia32 fpstate; + struct _fpstate_ia32 fpstate_unused; /* look at kernel/sigframe.h */ unsigned int extramask[_COMPAT_NSIG_WORDS-1]; char retcode[8]; + /* fp state follows here */ }; struct rt_sigframe @@ -192,8 +193,8 @@ struct rt_sigframe u32 puc; compat_siginfo_t info; struct ucontext_ia32 uc; - struct _fpstate_ia32 fpstate; char retcode[8]; + /* fp state follows here */ }; #define COPY(x) { \ @@ -402,7 +403,8 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, * Determine which stack to use.. */ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - size_t frame_size) + size_t frame_size, + struct _fpstate_ia32 **fpstate) { unsigned long sp; @@ -421,6 +423,11 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, ka->sa.sa_restorer) sp = (unsigned long) ka->sa.sa_restorer; + if (used_math()) { + sp = sp - sig_xstate_ia32_size; + *fpstate = (struct _fpstate_ia32 *) sp; + } + sp -= frame_size; /* Align the stack pointer according to the i386 ABI, * i.e. so that on function entry ((sp + 4) & 15) == 0. */ @@ -434,6 +441,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, struct sigframe __user *frame; void __user *restorer; int err = 0; + struct _fpstate_ia32 __user *fpstate = NULL; /* copy_to_user optimizes that into a single 8 byte store */ static const struct { @@ -448,7 +456,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, 0, }; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -457,8 +465,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, if (err) goto give_sigsegv; - err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, - set->sig[0]); + err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); if (err) goto give_sigsegv; @@ -522,6 +529,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; void __user *restorer; int err = 0; + struct _fpstate_ia32 __user *fpstate = NULL; /* __copy_to_user optimizes that into a single 8 byte store */ static const struct { @@ -537,7 +545,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 0, }; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -556,7 +564,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, + err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index b778e17e4b0..51fb288a2c9 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -24,6 +24,7 @@ # define save_i387_ia32 save_i387 # define restore_i387_ia32 restore_i387 # define _fpstate_ia32 _fpstate +# define sig_xstate_ia32_size sig_xstate_size # define user_i387_ia32_struct user_i387_struct # define user32_fxsr_struct user_fxsr_struct #endif @@ -36,6 +37,7 @@ static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; unsigned int xstate_size; +unsigned int sig_xstate_ia32_size = sizeof(struct _fpstate_ia32); static struct i387_fxsave_struct fx_scratch __cpuinitdata; void __cpuinit mxcsr_feature_mask_init(void) diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h index 72bbb519d2d..6dd7e2b70a4 100644 --- a/arch/x86/kernel/sigframe.h +++ b/arch/x86/kernel/sigframe.h @@ -3,9 +3,18 @@ struct sigframe { char __user *pretcode; int sig; struct sigcontext sc; - struct _fpstate fpstate; + /* + * fpstate is unused. fpstate is moved/allocated after + * retcode[] below. This movement allows to have the FP state and the + * future state extensions (xsave) stay together. + * And at the same time retaining the unused fpstate, prevents changing + * the offset of extramask[] in the sigframe and thus prevent any + * legacy application accessing/modifying it. + */ + struct _fpstate fpstate_unused; unsigned long extramask[_NSIG_WORDS-1]; char retcode[8]; + /* fp state follows here */ }; struct rt_sigframe { @@ -15,13 +24,14 @@ struct rt_sigframe { void __user *puc; struct siginfo info; struct ucontext uc; - struct _fpstate fpstate; char retcode[8]; + /* fp state follows here */ }; #else struct rt_sigframe { char __user *pretcode; struct ucontext uc; struct siginfo info; + /* fp state follows here */ }; #endif diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd893..19a7a5669b5 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -306,7 +306,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, * Determine which stack to use.. */ static inline void __user * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, + struct _fpstate **fpstate) { unsigned long sp; @@ -332,6 +333,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) sp = (unsigned long) ka->sa.sa_restorer; } + if (used_math()) { + sp = sp - sig_xstate_size; + *fpstate = (struct _fpstate *) sp; + } + sp -= frame_size; /* * Align the stack pointer according to the i386 ABI, @@ -350,8 +356,9 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, void __user *restorer; int err = 0; int usig; + struct _fpstate __user *fpstate = NULL; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -366,7 +373,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, if (err) goto give_sigsegv; - err = setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); + err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); if (err) goto give_sigsegv; @@ -427,8 +434,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, void __user *restorer; int err = 0; int usig; + struct _fpstate __user *fpstate = NULL; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -453,7 +461,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, + err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index ca316b5b742..0deab8eff33 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -281,7 +281,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct task_struct *me = current; if (used_math()) { - fp = get_stack(ka, regs, sizeof(struct _fpstate)); + fp = get_stack(ka, regs, sig_xstate_size); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index c68b7c4ca24..7ad169e3352 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -17,6 +17,10 @@ unsigned int pcntxt_hmask, pcntxt_lmask; */ struct xsave_struct *init_xstate_buf; +#ifdef CONFIG_X86_64 +unsigned int sig_xstate_size = sizeof(struct _fpstate); +#endif + /* * Enable the extended processor state save/restore feature */ -- cgit v1.2.3 From ab5137015fed9b948fe835a2d99a4cfbd50a0c40 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:22 -0700 Subject: x86, xsave: reorganization of signal save/restore fpstate code layout move 64bit routines that saves/restores fpstate in/from user stack from signal_64.c to xsave.c restore_i387_xstate() now handles the condition when user passes NULL fpstate. Other misc changes for prepartion of xsave/xrstor sigcontext support. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 28 ++++----------- arch/x86/kernel/i387.c | 44 +++++++++++++++++------- arch/x86/kernel/signal_32.c | 28 ++++----------- arch/x86/kernel/signal_64.c | 83 ++------------------------------------------- arch/x86/kernel/xsave.c | 79 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 135 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index a05bf0fb741..c596eabbe98 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -216,7 +216,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, unsigned int *peax) { unsigned int tmpflags, gs, oldgs, err = 0; - struct _fpstate_ia32 __user *buf; + void __user *buf; u32 tmp; /* Always make any pending restarted system calls return -EINTR */ @@ -260,26 +260,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, err |= __get_user(tmp, &sc->fpstate); buf = compat_ptr(tmp); - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387_ia32(buf); - } else { - struct task_struct *me = current; - - if (used_math()) { - clear_fpu(me); - clear_used_math(); - } - } + err |= restore_i387_xstate_ia32(buf); err |= __get_user(tmp, &sc->ax); *peax = tmp; return err; - -badframe: - return 1; } asmlinkage long sys32_sigreturn(struct pt_regs *regs) @@ -351,7 +337,7 @@ badframe: */ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, - struct _fpstate_ia32 __user *fpstate, + void __user *fpstate, struct pt_regs *regs, unsigned int mask) { int tmp, err = 0; @@ -382,7 +368,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, err |= __put_user((u32)regs->flags, &sc->flags); err |= __put_user((u32)regs->sp, &sc->sp_at_signal); - tmp = save_i387_ia32(fpstate); + tmp = save_i387_xstate_ia32(fpstate); if (tmp < 0) err = -EFAULT; else { @@ -404,7 +390,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, */ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, - struct _fpstate_ia32 **fpstate) + void **fpstate) { unsigned long sp; @@ -441,7 +427,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, struct sigframe __user *frame; void __user *restorer; int err = 0; - struct _fpstate_ia32 __user *fpstate = NULL; + void __user *fpstate = NULL; /* copy_to_user optimizes that into a single 8 byte store */ static const struct { @@ -529,7 +515,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; void __user *restorer; int err = 0; - struct _fpstate_ia32 __user *fpstate = NULL; + void __user *fpstate = NULL; /* __copy_to_user optimizes that into a single 8 byte store */ static const struct { diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 51fb288a2c9..7daf3a011dd 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -21,9 +21,10 @@ # include # include #else -# define save_i387_ia32 save_i387 -# define restore_i387_ia32 restore_i387 +# define save_i387_xstate_ia32 save_i387_xstate +# define restore_i387_xstate_ia32 restore_i387_xstate # define _fpstate_ia32 _fpstate +# define _xstate_ia32 _xstate # define sig_xstate_ia32_size sig_xstate_size # define user_i387_ia32_struct user_i387_struct # define user32_fxsr_struct user_fxsr_struct @@ -424,7 +425,6 @@ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) struct task_struct *tsk = current; struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; - unlazy_fpu(tsk); fp->status = fp->swd; if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) return -1; @@ -438,8 +438,6 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) struct user_i387_ia32_struct env; int err = 0; - unlazy_fpu(tsk); - convert_from_fxsr(&env, tsk); if (__copy_to_user(buf, &env, sizeof(env))) return -1; @@ -455,10 +453,16 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) return 1; } -int save_i387_ia32(struct _fpstate_ia32 __user *buf) +int save_i387_xstate_ia32(void __user *buf) { + struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; + struct task_struct *tsk = current; + if (!used_math()) return 0; + + if (!access_ok(VERIFY_WRITE, buf, sig_xstate_ia32_size)) + return -EACCES; /* * This will cause a "finit" to be triggered by the next * attempted FPU operation by the 'current' process. @@ -468,13 +472,15 @@ int save_i387_ia32(struct _fpstate_ia32 __user *buf) if (!HAVE_HWFP) { return fpregs_soft_get(current, NULL, 0, sizeof(struct user_i387_ia32_struct), - NULL, buf) ? -1 : 1; + NULL, fp) ? -1 : 1; } + unlazy_fpu(tsk); + if (cpu_has_fxsr) - return save_i387_fxsave(buf); + return save_i387_fxsave(fp); else - return save_i387_fsave(buf); + return save_i387_fsave(fp); } static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) @@ -502,14 +508,26 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) return 0; } -int restore_i387_ia32(struct _fpstate_ia32 __user *buf) +int restore_i387_xstate_ia32(void __user *buf) { int err; struct task_struct *tsk = current; + struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; if (HAVE_HWFP) clear_fpu(tsk); + if (!buf) { + if (used_math()) { + clear_fpu(tsk); + clear_used_math(); + } + + return 0; + } else + if (!access_ok(VERIFY_READ, buf, sig_xstate_ia32_size)) + return -EACCES; + if (!used_math()) { err = init_fpu(tsk); if (err) @@ -518,13 +536,13 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf) if (HAVE_HWFP) { if (cpu_has_fxsr) - err = restore_i387_fxsave(buf); + err = restore_i387_fxsave(fp); else - err = restore_i387_fsave(buf); + err = restore_i387_fsave(fp); } else { err = fpregs_soft_set(current, NULL, 0, sizeof(struct user_i387_ia32_struct), - NULL, buf) != 0; + NULL, fp) != 0; } set_used_math(); diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 19a7a5669b5..690cc616ac0 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -159,28 +159,14 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, } { - struct _fpstate __user *buf; + void __user *buf; err |= __get_user(buf, &sc->fpstate); - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387(buf); - } else { - struct task_struct *me = current; - - if (used_math()) { - clear_fpu(me); - clear_used_math(); - } - } + err |= restore_i387_xstate(buf); } err |= __get_user(*pax, &sc->ax); return err; - -badframe: - return 1; } asmlinkage unsigned long sys_sigreturn(unsigned long __unused) @@ -262,7 +248,7 @@ badframe: * Set up a signal frame. */ static int -setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, +setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, struct pt_regs *regs, unsigned long mask) { int tmp, err = 0; @@ -289,7 +275,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, err |= __put_user(regs->sp, &sc->sp_at_signal); err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); - tmp = save_i387(fpstate); + tmp = save_i387_xstate(fpstate); if (tmp < 0) err = 1; else @@ -307,7 +293,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, */ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, - struct _fpstate **fpstate) + void **fpstate) { unsigned long sp; @@ -356,7 +342,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, void __user *restorer; int err = 0; int usig; - struct _fpstate __user *fpstate = NULL; + void __user *fpstate = NULL; frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); @@ -434,7 +420,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, void __user *restorer; int err = 0; int usig; - struct _fpstate __user *fpstate = NULL; + void __user *fpstate = NULL; frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 0deab8eff33..ddf6123a55c 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -53,69 +53,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, return do_sigaltstack(uss, uoss, regs->sp); } -/* - * Signal frame handlers. - */ - -static inline int save_i387(struct _fpstate __user *buf) -{ - struct task_struct *tsk = current; - int err = 0; - - BUILD_BUG_ON(sizeof(struct user_i387_struct) != - sizeof(tsk->thread.xstate->fxsave)); - - if ((unsigned long)buf % 16) - printk("save_i387: bad fpstate %p\n", buf); - - if (!used_math()) - return 0; - clear_used_math(); /* trigger finit */ - if (task_thread_info(tsk)->status & TS_USEDFPU) { - err = save_i387_checking((struct i387_fxsave_struct __user *) - buf); - if (err) - return err; - task_thread_info(tsk)->status &= ~TS_USEDFPU; - stts(); - } else { - if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, - sizeof(struct i387_fxsave_struct))) - return -1; - } - return 1; -} - -/* - * This restores directly out of user space. Exceptions are handled. - */ -static inline int restore_i387(struct _fpstate __user *buf) -{ - struct task_struct *tsk = current; - int err; - - if (!used_math()) { - err = init_fpu(tsk); - if (err) - return err; - } - - if (!(task_thread_info(current)->status & TS_USEDFPU)) { - clts(); - task_thread_info(current)->status |= TS_USEDFPU; - } - err = restore_fpu_checking((__force struct i387_fxsave_struct *)buf); - if (unlikely(err)) { - /* - * Encountered an error while doing the restore from the - * user buffer, clear the fpu state. - */ - clear_fpu(tsk); - clear_used_math(); - } - return err; -} - /* * Do a signal return; undo the signal stack. */ @@ -160,25 +97,11 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, { struct _fpstate __user * buf; err |= __get_user(buf, &sc->fpstate); - - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387(buf); - } else { - struct task_struct *me = current; - if (used_math()) { - clear_fpu(me); - clear_used_math(); - } - } + err |= restore_i387_xstate(buf); } err |= __get_user(*pax, &sc->ax); return err; - -badframe: - return 1; } asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) @@ -276,7 +199,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { struct rt_sigframe __user *frame; - struct _fpstate __user *fp = NULL; + void __user *fp = NULL; int err = 0; struct task_struct *me = current; @@ -288,7 +211,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; - if (save_i387(fp) < 0) + if (save_i387_xstate(fp) < 0) err |= -1; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 7ad169e3352..608e72d7ca6 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -12,6 +12,85 @@ */ unsigned int pcntxt_hmask, pcntxt_lmask; +#ifdef CONFIG_X86_64 +/* + * Signal frame handlers. + */ + +int save_i387_xstate(void __user *buf) +{ + struct task_struct *tsk = current; + int err = 0; + + if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) + return -EACCES; + + BUILD_BUG_ON(sizeof(struct user_i387_struct) != + sizeof(tsk->thread.xstate->fxsave)); + + if ((unsigned long)buf % 16) + printk("save_i387_xstate: bad fpstate %p\n", buf); + + if (!used_math()) + return 0; + clear_used_math(); /* trigger finit */ + if (task_thread_info(tsk)->status & TS_USEDFPU) { + err = save_i387_checking((struct i387_fxsave_struct __user *) + buf); + if (err) + return err; + task_thread_info(tsk)->status &= ~TS_USEDFPU; + stts(); + } else { + if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, + xstate_size)) + return -1; + } + return 1; +} + +/* + * This restores directly out of user space. Exceptions are handled. + */ +int restore_i387_xstate(void __user *buf) +{ + struct task_struct *tsk = current; + int err; + + if (!buf) { + if (used_math()) { + clear_fpu(tsk); + clear_used_math(); + } + + return 0; + } else + if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) + return -EACCES; + + if (!used_math()) { + err = init_fpu(tsk); + if (err) + return err; + } + + if (!(task_thread_info(current)->status & TS_USEDFPU)) { + clts(); + task_thread_info(current)->status |= TS_USEDFPU; + } + err = fxrstor_checking((__force struct i387_fxsave_struct *)buf); + if (unlikely(err)) { + /* + * Encountered an error while doing the restore from the + * user buffer, clear the fpu state. + */ + clear_fpu(tsk); + clear_used_math(); + } + return err; +} +#endif + /* * Represents init state for the supported extended state. */ -- cgit v1.2.3 From c37b5efea43f9e500363f9973dd00e3d2cdcc685 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:25 -0700 Subject: x86, xsave: save/restore the extended state context in sigframe On cpu's supporting xsave/xrstor, fpstate pointer in the sigcontext, will include the extended state information along with fpstate information. Presence of extended state information is indicated by the presence of FP_XSTATE_MAGIC1 at fpstate.sw_reserved.magic1 and FP_XSTATE_MAGIC2 at fpstate + (fpstate.sw_reserved.extended_size - FP_XSTATE_MAGIC2_SIZE). Extended feature bit mask that is saved in the memory layout is represented by the fpstate.sw_reserved.xstate_bv For RT signal frames, UC_FP_XSTATE in the uc_flags also indicate the presence of extended state information in the sigcontext's fpstate pointer. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 5 +- arch/x86/kernel/i387.c | 82 +++++++++++++++++++-- arch/x86/kernel/signal_32.c | 5 +- arch/x86/kernel/signal_64.c | 7 +- arch/x86/kernel/xsave.c | 172 +++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 251 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index c596eabbe98..f25a1012400 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -544,7 +544,10 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, goto give_sigsegv; /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); + if (cpu_has_xsave) + err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + else + err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->sp), diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 7daf3a011dd..cbb9dc474a2 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -26,6 +26,7 @@ # define _fpstate_ia32 _fpstate # define _xstate_ia32 _xstate # define sig_xstate_ia32_size sig_xstate_size +# define fx_sw_reserved_ia32 fx_sw_reserved # define user_i387_ia32_struct user_i387_struct # define user32_fxsr_struct user_fxsr_struct #endif @@ -447,12 +448,30 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) if (err) return -1; - if (__copy_to_user(&buf->_fxsr_env[0], fx, - sizeof(struct i387_fxsave_struct))) + if (__copy_to_user(&buf->_fxsr_env[0], fx, xstate_size)) return -1; return 1; } +static int save_i387_xsave(void __user *buf) +{ + struct _fpstate_ia32 __user *fx = buf; + int err = 0; + + if (save_i387_fxsave(fx) < 0) + return -1; + + err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved_ia32, + sizeof(struct _fpx_sw_bytes)); + err |= __put_user(FP_XSTATE_MAGIC2, + (__u32 __user *) (buf + sig_xstate_ia32_size + - FP_XSTATE_MAGIC2_SIZE)); + if (err) + return -1; + + return 1; +} + int save_i387_xstate_ia32(void __user *buf) { struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; @@ -477,6 +496,8 @@ int save_i387_xstate_ia32(void __user *buf) unlazy_fpu(tsk); + if (cpu_has_xsave) + return save_i387_xsave(fp); if (cpu_has_fxsr) return save_i387_fxsave(fp); else @@ -491,14 +512,15 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) sizeof(struct i387_fsave_struct)); } -static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) +static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf, + unsigned int size) { struct task_struct *tsk = current; struct user_i387_ia32_struct env; int err; err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], - sizeof(struct i387_fxsave_struct)); + size); /* mxcsr reserved bits must be masked to zero for security reasons */ tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; if (err || __copy_from_user(&env, buf, sizeof(env))) @@ -508,6 +530,51 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) return 0; } +static int restore_i387_xsave(void __user *buf) +{ + struct _fpx_sw_bytes fx_sw_user; + struct _fpstate_ia32 __user *fx_user = + ((struct _fpstate_ia32 __user *) buf); + struct i387_fxsave_struct __user *fx = + (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; + struct xsave_hdr_struct *xsave_hdr = + ¤t->thread.xstate->xsave.xsave_hdr; + unsigned int lmask, hmask; + int err; + + if (check_for_xstate(fx, buf, &fx_sw_user)) + goto fx_only; + + lmask = fx_sw_user.xstate_bv; + hmask = fx_sw_user.xstate_bv >> 32; + + err = restore_i387_fxsave(buf, fx_sw_user.xstate_size); + + xsave_hdr->xstate_bv &= (pcntxt_lmask | (((u64) pcntxt_hmask) << 32)); + /* + * These bits must be zero. + */ + xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; + + /* + * Init the state that is not present in the memory layout + * and enabled by the OS. + */ + lmask = ~(pcntxt_lmask & ~lmask); + hmask = ~(pcntxt_hmask & ~hmask); + xsave_hdr->xstate_bv &= (lmask | (((u64) hmask) << 32)); + + return err; +fx_only: + /* + * Couldn't find the extended state information in the memory + * layout. Restore the FP/SSE and init the other extended state + * enabled by the OS. + */ + xsave_hdr->xstate_bv = XSTATE_FPSSE; + return restore_i387_fxsave(buf, sizeof(struct i387_fxsave_struct)); +} + int restore_i387_xstate_ia32(void __user *buf) { int err; @@ -535,8 +602,11 @@ int restore_i387_xstate_ia32(void __user *buf) } if (HAVE_HWFP) { - if (cpu_has_fxsr) - err = restore_i387_fxsave(fp); + if (cpu_has_xsave) + err = restore_i387_xsave(buf); + else if (cpu_has_fxsr) + err = restore_i387_fxsave(fp, sizeof(struct + i387_fxsave_struct)); else err = restore_i387_fsave(fp); } else { diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 690cc616ac0..0f98d69fbdb 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -441,7 +441,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, goto give_sigsegv; /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); + if (cpu_has_xsave) + err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + else + err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->sp), diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index ddf6123a55c..2621b98f5bf 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -192,7 +192,7 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) sp = current->sas_ss_sp + current->sas_ss_size; } - return (void __user *)round_down(sp - size, 16); + return (void __user *)round_down(sp - size, 64); } static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -226,7 +226,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); + if (cpu_has_xsave) + err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + else + err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->sp), diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 608e72d7ca6..dd66d0714c1 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -6,12 +6,68 @@ #include #include #include +#ifdef CONFIG_IA32_EMULATION +#include +#endif /* * Supported feature mask by the CPU and the kernel. */ unsigned int pcntxt_hmask, pcntxt_lmask; +struct _fpx_sw_bytes fx_sw_reserved; +#ifdef CONFIG_IA32_EMULATION +struct _fpx_sw_bytes fx_sw_reserved_ia32; +#endif + +/* + * Check for the presence of extended state information in the + * user fpstate pointer in the sigcontext. + */ +int check_for_xstate(struct i387_fxsave_struct __user *buf, + void __user *fpstate, + struct _fpx_sw_bytes *fx_sw_user) +{ + int min_xstate_size = sizeof(struct i387_fxsave_struct) + + sizeof(struct xsave_hdr_struct); + unsigned int magic2; + int err; + + err = __copy_from_user(fx_sw_user, &buf->sw_reserved[0], + sizeof(struct _fpx_sw_bytes)); + + if (err) + return err; + + /* + * First Magic check failed. + */ + if (fx_sw_user->magic1 != FP_XSTATE_MAGIC1) + return -1; + + /* + * Check for error scenarios. + */ + if (fx_sw_user->xstate_size < min_xstate_size || + fx_sw_user->xstate_size > xstate_size || + fx_sw_user->xstate_size > fx_sw_user->extended_size) + return -1; + + err = __get_user(magic2, (__u32 *) (((void *)fpstate) + + fx_sw_user->extended_size - + FP_XSTATE_MAGIC2_SIZE)); + /* + * Check for the presence of second magic word at the end of memory + * layout. This detects the case where the user just copied the legacy + * fpstate layout with out copying the extended state information + * in the memory layout. + */ + if (err || magic2 != FP_XSTATE_MAGIC2) + return -1; + + return 0; +} + #ifdef CONFIG_X86_64 /* * Signal frame handlers. @@ -28,15 +84,18 @@ int save_i387_xstate(void __user *buf) BUILD_BUG_ON(sizeof(struct user_i387_struct) != sizeof(tsk->thread.xstate->fxsave)); - if ((unsigned long)buf % 16) + if ((unsigned long)buf % 64) printk("save_i387_xstate: bad fpstate %p\n", buf); if (!used_math()) return 0; clear_used_math(); /* trigger finit */ if (task_thread_info(tsk)->status & TS_USEDFPU) { - err = save_i387_checking((struct i387_fxsave_struct __user *) - buf); + if (task_thread_info(tsk)->status & TS_XSAVE) + err = xsave_user(buf); + else + err = fxsave_user(buf); + if (err) return err; task_thread_info(tsk)->status &= ~TS_USEDFPU; @@ -46,23 +105,77 @@ int save_i387_xstate(void __user *buf) xstate_size)) return -1; } + + if (task_thread_info(tsk)->status & TS_XSAVE) { + struct _fpstate __user *fx = buf; + + err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, + sizeof(struct _fpx_sw_bytes)); + + err |= __put_user(FP_XSTATE_MAGIC2, + (__u32 __user *) (buf + sig_xstate_size + - FP_XSTATE_MAGIC2_SIZE)); + } + return 1; } +/* + * Restore the extended state if present. Otherwise, restore the FP/SSE + * state. + */ +int restore_user_xstate(void __user *buf) +{ + struct _fpx_sw_bytes fx_sw_user; + unsigned int lmask, hmask; + int err; + + if (((unsigned long)buf % 64) || + check_for_xstate(buf, buf, &fx_sw_user)) + goto fx_only; + + lmask = fx_sw_user.xstate_bv; + hmask = fx_sw_user.xstate_bv >> 32; + + /* + * restore the state passed by the user. + */ + err = xrestore_user(buf, lmask, hmask); + if (err) + return err; + + /* + * init the state skipped by the user. + */ + lmask = pcntxt_lmask & ~lmask; + hmask = pcntxt_hmask & ~hmask; + + xrstor_state(init_xstate_buf, lmask, hmask); + + return 0; + +fx_only: + /* + * couldn't find the extended state information in the + * memory layout. Restore just the FP/SSE and init all + * the other extended state. + */ + xrstor_state(init_xstate_buf, pcntxt_lmask & ~XSTATE_FPSSE, + pcntxt_hmask); + return fxrstor_checking((__force struct i387_fxsave_struct *)buf); +} + /* * This restores directly out of user space. Exceptions are handled. */ int restore_i387_xstate(void __user *buf) { struct task_struct *tsk = current; - int err; + int err = 0; if (!buf) { - if (used_math()) { - clear_fpu(tsk); - clear_used_math(); - } - + if (used_math()) + goto clear; return 0; } else if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) @@ -78,12 +191,17 @@ int restore_i387_xstate(void __user *buf) clts(); task_thread_info(current)->status |= TS_USEDFPU; } - err = fxrstor_checking((__force struct i387_fxsave_struct *)buf); + if (task_thread_info(tsk)->status & TS_XSAVE) + err = restore_user_xstate(buf); + else + err = fxrstor_checking((__force struct i387_fxsave_struct *) + buf); if (unlikely(err)) { /* * Encountered an error while doing the restore from the * user buffer, clear the fpu state. */ +clear: clear_fpu(tsk); clear_used_math(); } @@ -91,6 +209,38 @@ int restore_i387_xstate(void __user *buf) } #endif +/* + * Prepare the SW reserved portion of the fxsave memory layout, indicating + * the presence of the extended state information in the memory layout + * pointed by the fpstate pointer in the sigcontext. + * This will be saved when ever the FP and extended state context is + * saved on the user stack during the signal handler delivery to the user. + */ +void prepare_fx_sw_frame(void) +{ + int size_extended = (xstate_size - sizeof(struct i387_fxsave_struct)) + + FP_XSTATE_MAGIC2_SIZE; + + sig_xstate_size = sizeof(struct _fpstate) + size_extended; + +#ifdef CONFIG_IA32_EMULATION + sig_xstate_ia32_size = sizeof(struct _fpstate_ia32) + size_extended; +#endif + + memset(&fx_sw_reserved, 0, sizeof(fx_sw_reserved)); + + fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; + fx_sw_reserved.extended_size = sig_xstate_size; + fx_sw_reserved.xstate_bv = pcntxt_lmask | + (((u64) (pcntxt_hmask)) << 32); + fx_sw_reserved.xstate_size = xstate_size; +#ifdef CONFIG_IA32_EMULATION + memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved, + sizeof(struct _fpx_sw_bytes)); + fx_sw_reserved_ia32.extended_size = sig_xstate_ia32_size; +#endif +} + /* * Represents init state for the supported extended state. */ @@ -162,6 +312,8 @@ void __init xsave_cntxt_init(void) xstate_size = ebx; + prepare_fx_sw_frame(); + setup_xstate_init(); printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, " -- cgit v1.2.3 From 42deec6f2c3688fdaf986225ac901b817cd91568 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:26 -0700 Subject: x86, xsave: update xsave header bits during ptrace fpregs set FP/SSE bits may be zero in the xsave header(representing the init state). Update these bits during the ptrace fpregs set operation, to indicate the non-init state. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/i387.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index cbb9dc474a2..e0ed59f5c19 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -214,6 +214,13 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, */ target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; + /* + * update the header bits in the xsave header, indicating the + * presence of FP and SSE state. + */ + if (cpu_has_xsave) + target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; + return ret; } @@ -414,6 +421,12 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, if (!ret) convert_to_fxsr(target, &env); + /* + * update the header bit in the xsave header, indicating the + * presence of FP. + */ + if (cpu_has_xsave) + target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FP; return ret; } -- cgit v1.2.3 From 6152e4b1c99a3689fc318d092cd144597f7dbd14 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 29 Jul 2008 17:23:16 -0700 Subject: x86, xsave: keep the XSAVE feature mask as an u64 The XSAVE feature mask is a 64-bit number; keep it that way, in order to avoid the mistake done with rdmsr/wrmsr. Use the xsetbv() function provided in the previous patch. Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/i387.c | 12 +++++------- arch/x86/kernel/xsave.c | 45 +++++++++++++++++---------------------------- 2 files changed, 22 insertions(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index e0ed59f5c19..45723f1fe19 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -552,18 +552,17 @@ static int restore_i387_xsave(void __user *buf) (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; struct xsave_hdr_struct *xsave_hdr = ¤t->thread.xstate->xsave.xsave_hdr; - unsigned int lmask, hmask; + u64 mask; int err; if (check_for_xstate(fx, buf, &fx_sw_user)) goto fx_only; - lmask = fx_sw_user.xstate_bv; - hmask = fx_sw_user.xstate_bv >> 32; + mask = fx_sw_user.xstate_bv; err = restore_i387_fxsave(buf, fx_sw_user.xstate_size); - xsave_hdr->xstate_bv &= (pcntxt_lmask | (((u64) pcntxt_hmask) << 32)); + xsave_hdr->xstate_bv &= pcntxt_mask; /* * These bits must be zero. */ @@ -573,9 +572,8 @@ static int restore_i387_xsave(void __user *buf) * Init the state that is not present in the memory layout * and enabled by the OS. */ - lmask = ~(pcntxt_lmask & ~lmask); - hmask = ~(pcntxt_hmask & ~hmask); - xsave_hdr->xstate_bv &= (lmask | (((u64) hmask) << 32)); + mask = ~(pcntxt_mask & ~mask); + xsave_hdr->xstate_bv &= mask; return err; fx_only: diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index dd66d0714c1..7415f3e38a5 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -9,11 +9,12 @@ #ifdef CONFIG_IA32_EMULATION #include #endif +#include /* * Supported feature mask by the CPU and the kernel. */ -unsigned int pcntxt_hmask, pcntxt_lmask; +u64 pcntxt_mask; struct _fpx_sw_bytes fx_sw_reserved; #ifdef CONFIG_IA32_EMULATION @@ -127,30 +128,28 @@ int save_i387_xstate(void __user *buf) int restore_user_xstate(void __user *buf) { struct _fpx_sw_bytes fx_sw_user; - unsigned int lmask, hmask; + u64 mask; int err; if (((unsigned long)buf % 64) || check_for_xstate(buf, buf, &fx_sw_user)) goto fx_only; - lmask = fx_sw_user.xstate_bv; - hmask = fx_sw_user.xstate_bv >> 32; + mask = fx_sw_user.xstate_bv; /* * restore the state passed by the user. */ - err = xrestore_user(buf, lmask, hmask); + err = xrestore_user(buf, mask); if (err) return err; /* * init the state skipped by the user. */ - lmask = pcntxt_lmask & ~lmask; - hmask = pcntxt_hmask & ~hmask; + mask = pcntxt_mask & ~mask; - xrstor_state(init_xstate_buf, lmask, hmask); + xrstor_state(init_xstate_buf, mask); return 0; @@ -160,8 +159,7 @@ fx_only: * memory layout. Restore just the FP/SSE and init all * the other extended state. */ - xrstor_state(init_xstate_buf, pcntxt_lmask & ~XSTATE_FPSSE, - pcntxt_hmask); + xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE); return fxrstor_checking((__force struct i387_fxsave_struct *)buf); } @@ -231,8 +229,7 @@ void prepare_fx_sw_frame(void) fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; fx_sw_reserved.extended_size = sig_xstate_size; - fx_sw_reserved.xstate_bv = pcntxt_lmask | - (((u64) (pcntxt_hmask)) << 32); + fx_sw_reserved.xstate_bv = pcntxt_mask; fx_sw_reserved.xstate_size = xstate_size; #ifdef CONFIG_IA32_EMULATION memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved, @@ -263,11 +260,8 @@ void __cpuinit xsave_init(void) /* * Enable all the features that the HW is capable of * and the Linux kernel is aware of. - * - * xsetbv(); */ - asm volatile(".byte 0x0f,0x01,0xd1" : : "c" (0), - "a" (pcntxt_lmask), "d" (pcntxt_hmask)); + xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); } /* @@ -287,36 +281,31 @@ void __init xsave_cntxt_init(void) unsigned int eax, ebx, ecx, edx; cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); + pcntxt_mask = eax + ((u64)edx << 32); - pcntxt_lmask = eax; - pcntxt_hmask = edx; - - if ((pcntxt_lmask & XSTATE_FPSSE) != XSTATE_FPSSE) { - printk(KERN_ERR "FP/SSE not shown under xsave features %x\n", - pcntxt_lmask); + if ((pcntxt_mask & XSTATE_FPSSE) != XSTATE_FPSSE) { + printk(KERN_ERR "FP/SSE not shown under xsave features 0x%llx\n", + pcntxt_mask); BUG(); } /* * for now OS knows only about FP/SSE */ - pcntxt_lmask = pcntxt_lmask & XCNTXT_LMASK; - pcntxt_hmask = pcntxt_hmask & XCNTXT_HMASK; - + pcntxt_mask = pcntxt_mask & XCNTXT_MASK; xsave_init(); /* * Recompute the context size for enabled features */ cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); - xstate_size = ebx; prepare_fx_sw_frame(); setup_xstate_init(); - printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, " + printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%llx, " "cntxt size 0x%x\n", - (pcntxt_lmask | ((u64) pcntxt_hmask << 32)), xstate_size); + pcntxt_mask, xstate_size); } -- cgit v1.2.3 From 0d1edf46ba229b46efacf75c0544b88c05a7b266 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 28 Jul 2008 11:53:57 -0700 Subject: xen: compile irq functions without -pg for ftrace For some reason I managed to miss a bunch of irq-related functions which also need to be compiled without -pg when using ftrace. This patch moves them into their own file, and starts a cleanup process I've been meaning to do anyway. Signed-off-by: Jeremy Fitzhardinge Cc: Sam Ravnborg Cc: "Alex Nixon (Intern)" Cc: Eduardo Habkost Signed-off-by: Ingo Molnar --- arch/x86/xen/Makefile | 3 +- arch/x86/xen/enlighten.c | 122 +-------------------------------------- arch/x86/xen/irq.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++ arch/x86/xen/xen-asm_32.S | 2 +- arch/x86/xen/xen-asm_64.S | 2 +- arch/x86/xen/xen-ops.h | 1 + 6 files changed, 150 insertions(+), 123 deletions(-) create mode 100644 arch/x86/xen/irq.c (limited to 'arch') diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 5bfee243cf9..9ee745fa552 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -2,9 +2,10 @@ ifdef CONFIG_FTRACE # Do not profile debug and lowlevel utilities CFLAGS_REMOVE_spinlock.o = -pg CFLAGS_REMOVE_time.o = -pg +CFLAGS_REMOVE_irq.o = -pg endif -obj-y := enlighten.o setup.o multicalls.o mmu.o \ +obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ time.o xen-asm_$(BITS).o grant-table.o suspend.o obj-$(CONFIG_SMP) += smp.o spinlock.o diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index b795470ec06..cf8b3a93122 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -226,94 +225,6 @@ static unsigned long xen_get_debugreg(int reg) return HYPERVISOR_get_debugreg(reg); } -static unsigned long xen_save_fl(void) -{ - struct vcpu_info *vcpu; - unsigned long flags; - - vcpu = x86_read_percpu(xen_vcpu); - - /* flag has opposite sense of mask */ - flags = !vcpu->evtchn_upcall_mask; - - /* convert to IF type flag - -0 -> 0x00000000 - -1 -> 0xffffffff - */ - return (-flags) & X86_EFLAGS_IF; -} - -static void xen_restore_fl(unsigned long flags) -{ - struct vcpu_info *vcpu; - - /* convert from IF type flag */ - flags = !(flags & X86_EFLAGS_IF); - - /* There's a one instruction preempt window here. We need to - make sure we're don't switch CPUs between getting the vcpu - pointer and updating the mask. */ - preempt_disable(); - vcpu = x86_read_percpu(xen_vcpu); - vcpu->evtchn_upcall_mask = flags; - preempt_enable_no_resched(); - - /* Doesn't matter if we get preempted here, because any - pending event will get dealt with anyway. */ - - if (flags == 0) { - preempt_check_resched(); - barrier(); /* unmask then check (avoid races) */ - if (unlikely(vcpu->evtchn_upcall_pending)) - force_evtchn_callback(); - } -} - -static void xen_irq_disable(void) -{ - /* There's a one instruction preempt window here. We need to - make sure we're don't switch CPUs between getting the vcpu - pointer and updating the mask. */ - preempt_disable(); - x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; - preempt_enable_no_resched(); -} - -static void xen_irq_enable(void) -{ - struct vcpu_info *vcpu; - - /* We don't need to worry about being preempted here, since - either a) interrupts are disabled, so no preemption, or b) - the caller is confused and is trying to re-enable interrupts - on an indeterminate processor. */ - - vcpu = x86_read_percpu(xen_vcpu); - vcpu->evtchn_upcall_mask = 0; - - /* Doesn't matter if we get preempted here, because any - pending event will get dealt with anyway. */ - - barrier(); /* unmask then check (avoid races) */ - if (unlikely(vcpu->evtchn_upcall_pending)) - force_evtchn_callback(); -} - -static void xen_safe_halt(void) -{ - /* Blocking includes an implicit local_irq_enable(). */ - if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) - BUG(); -} - -static void xen_halt(void) -{ - if (irqs_disabled()) - HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); - else - xen_safe_halt(); -} - static void xen_leave_lazy(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); @@ -1308,36 +1219,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { }, }; -static void __init __xen_init_IRQ(void) -{ -#ifdef CONFIG_X86_64 - int i; - - /* Create identity vector->irq map */ - for(i = 0; i < NR_VECTORS; i++) { - int cpu; - - for_each_possible_cpu(cpu) - per_cpu(vector_irq, cpu)[i] = i; - } -#endif /* CONFIG_X86_64 */ - - xen_init_IRQ(); -} - -static const struct pv_irq_ops xen_irq_ops __initdata = { - .init_IRQ = __xen_init_IRQ, - .save_fl = xen_save_fl, - .restore_fl = xen_restore_fl, - .irq_disable = xen_irq_disable, - .irq_enable = xen_irq_enable, - .safe_halt = xen_safe_halt, - .halt = xen_halt, -#ifdef CONFIG_X86_64 - .adjust_exception_frame = xen_adjust_exception_frame, -#endif -}; - static const struct pv_apic_ops xen_apic_ops __initdata = { #ifdef CONFIG_X86_LOCAL_APIC .apic_write = xen_apic_write, @@ -1740,10 +1621,11 @@ asmlinkage void __init xen_start_kernel(void) pv_init_ops = xen_init_ops; pv_time_ops = xen_time_ops; pv_cpu_ops = xen_cpu_ops; - pv_irq_ops = xen_irq_ops; pv_apic_ops = xen_apic_ops; pv_mmu_ops = xen_mmu_ops; + xen_init_irq_ops(); + if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit; diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c new file mode 100644 index 00000000000..28b85ab8422 --- /dev/null +++ b/arch/x86/xen/irq.c @@ -0,0 +1,143 @@ +#include + +#include +#include +#include + +#include +#include + +#include "xen-ops.h" + +/* + * Force a proper event-channel callback from Xen after clearing the + * callback mask. We do this in a very simple manner, by making a call + * down into Xen. The pending flag will be checked by Xen on return. + */ +void xen_force_evtchn_callback(void) +{ + (void)HYPERVISOR_xen_version(0, NULL); +} + +static void __init __xen_init_IRQ(void) +{ +#ifdef CONFIG_X86_64 + int i; + + /* Create identity vector->irq map */ + for(i = 0; i < NR_VECTORS; i++) { + int cpu; + + for_each_possible_cpu(cpu) + per_cpu(vector_irq, cpu)[i] = i; + } +#endif /* CONFIG_X86_64 */ + + xen_init_IRQ(); +} + +static unsigned long xen_save_fl(void) +{ + struct vcpu_info *vcpu; + unsigned long flags; + + vcpu = x86_read_percpu(xen_vcpu); + + /* flag has opposite sense of mask */ + flags = !vcpu->evtchn_upcall_mask; + + /* convert to IF type flag + -0 -> 0x00000000 + -1 -> 0xffffffff + */ + return (-flags) & X86_EFLAGS_IF; +} + +static void xen_restore_fl(unsigned long flags) +{ + struct vcpu_info *vcpu; + + /* convert from IF type flag */ + flags = !(flags & X86_EFLAGS_IF); + + /* There's a one instruction preempt window here. We need to + make sure we're don't switch CPUs between getting the vcpu + pointer and updating the mask. */ + preempt_disable(); + vcpu = x86_read_percpu(xen_vcpu); + vcpu->evtchn_upcall_mask = flags; + preempt_enable_no_resched(); + + /* Doesn't matter if we get preempted here, because any + pending event will get dealt with anyway. */ + + if (flags == 0) { + preempt_check_resched(); + barrier(); /* unmask then check (avoid races) */ + if (unlikely(vcpu->evtchn_upcall_pending)) + xen_force_evtchn_callback(); + } +} + +static void xen_irq_disable(void) +{ + /* There's a one instruction preempt window here. We need to + make sure we're don't switch CPUs between getting the vcpu + pointer and updating the mask. */ + preempt_disable(); + x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; + preempt_enable_no_resched(); +} + +static void xen_irq_enable(void) +{ + struct vcpu_info *vcpu; + + /* We don't need to worry about being preempted here, since + either a) interrupts are disabled, so no preemption, or b) + the caller is confused and is trying to re-enable interrupts + on an indeterminate processor. */ + + vcpu = x86_read_percpu(xen_vcpu); + vcpu->evtchn_upcall_mask = 0; + + /* Doesn't matter if we get preempted here, because any + pending event will get dealt with anyway. */ + + barrier(); /* unmask then check (avoid races) */ + if (unlikely(vcpu->evtchn_upcall_pending)) + xen_force_evtchn_callback(); +} + +static void xen_safe_halt(void) +{ + /* Blocking includes an implicit local_irq_enable(). */ + if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) + BUG(); +} + +static void xen_halt(void) +{ + if (irqs_disabled()) + HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); + else + xen_safe_halt(); +} + +static const struct pv_irq_ops xen_irq_ops __initdata = { + .init_IRQ = __xen_init_IRQ, + .save_fl = xen_save_fl, + .restore_fl = xen_restore_fl, + .irq_disable = xen_irq_disable, + .irq_enable = xen_irq_enable, + .safe_halt = xen_safe_halt, + .halt = xen_halt, +#ifdef CONFIG_X86_64 + .adjust_exception_frame = xen_adjust_exception_frame, +#endif +}; + +void __init xen_init_irq_ops() +{ + pv_irq_ops = xen_irq_ops; +} diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index 2497a30f41d..42786f59d9c 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -298,7 +298,7 @@ check_events: push %eax push %ecx push %edx - call force_evtchn_callback + call xen_force_evtchn_callback pop %edx pop %ecx pop %eax diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 7f58304fafb..3b9bda46487 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -122,7 +122,7 @@ check_events: push %r9 push %r10 push %r11 - call force_evtchn_callback + call xen_force_evtchn_callback pop %r11 pop %r10 pop %r9 diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 8847fb34f17..3c70ebc50b1 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -31,6 +31,7 @@ void xen_vcpu_restore(void); void __init xen_build_dynamic_phys_to_machine(void); +void xen_init_irq_ops(void); void xen_setup_timer(int cpu); void xen_setup_cpu_clockevents(void); unsigned long xen_tsc_khz(void); -- cgit v1.2.3 From cef43bf6b3afd819f7cdcba356af0e8220fb3789 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 28 Jul 2008 13:33:44 -0700 Subject: xen: fix allocation and use of large ldts, cleanup Add a proper comment for set_aliased_prot() and fix an unsigned long/void * warning. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index cf8b3a93122..04ec69e4d02 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -237,8 +237,10 @@ static unsigned long xen_store_tr(void) } /* - * If 'v' is a vmalloc mapping, then find the linear mapping of the - * page (if any) and also set its protections to match: + * Set the page permissions for a particular virtual address. If the + * address is a vmalloc mapping (or other non-linear mapping), then + * find the linear mapping of the page and also set its protections to + * match. */ static void set_aliased_prot(void *v, pgprot_t prot) { @@ -387,8 +389,7 @@ static void xen_load_gs_index(unsigned int idx) static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, const void *ptr) { - unsigned long lp = (unsigned long)&dt[entrynum]; - xmaddr_t mach_lp = arbitrary_virt_to_machine(lp); + xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]); u64 entry = *(u64 *)ptr; preempt_disable(); -- cgit v1.2.3 From 169ad16bb87c10a3f7c108bb7008ebc0270f617a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 28 Jul 2008 18:32:09 -0300 Subject: xen_alloc_ptpage: cast PFN_PHYS() argument to unsigned long Currently paravirt_ops alloc_p*() uses u32 for the pfn args. We should change that later, but while the pfn parameter is still u32, we need to cast the PFN_PHYS() argument at xen_alloc_ptpage() to unsigned long, otherwise it will lose bits on the shift. I think PFN_PHYS() should behave better when fed with smaller integers, but a cast to unsigned long won't be enough for all cases on 32-bit PAE, and a cast to u64 would be overkill for most users of PFN_PHYS(). We could have two different flavors of PFN_PHYS: one for low pages only (unsigned long) and another that works for any page (u64)), but while we don't have it, we will need the cast to unsigned long on xen_alloc_ptpage(). Signed-off-by: Eduardo Habkost Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 04ec69e4d02..53afa14eb31 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -822,7 +822,7 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) SetPagePinned(page); if (!PageHighMem(page)) { - make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); + make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); if (level == PT_PTE) pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); } else -- cgit v1.2.3 From 7de08b4e1ed8d80e6086f71b7e99fc4b397aae39 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:51 -0300 Subject: x86: coding styles fixes to arch/x86/kernel/process_64.c Fix about 50 errors and many warnings without change process_64.o arch/x86/kernel/process_64.o: text data bss dec hex filename 5236 8 24 5268 1494 process_64.o.after 5236 8 24 5268 1494 process_64.o.before md5: 9c35e9debdea4e471288c6e8ca267a75 process_64.o.after 9c35e9debdea4e471288c6e8ca267a75 process_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 101 +++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 51 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 3fb62a7d9a1..4da8514dd25 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -37,11 +37,11 @@ #include #include #include +#include +#include -#include #include #include -#include #include #include #include @@ -88,7 +88,7 @@ void exit_idle(void) #ifdef CONFIG_HOTPLUG_CPU DECLARE_PER_CPU(int, cpu_state); -#include +#include /* We halt the CPU with physical CPU hotplug */ static inline void play_dead(void) { @@ -152,7 +152,7 @@ void cpu_idle(void) } /* Prints also some state that isn't saved in the pt_regs */ -void __show_regs(struct pt_regs * regs) +void __show_regs(struct pt_regs *regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; unsigned long d0, d1, d2, d3, d6, d7; @@ -177,28 +177,28 @@ void __show_regs(struct pt_regs * regs) printk("RBP: %016lx R08: %016lx R09: %016lx\n", regs->bp, regs->r8, regs->r9); printk("R10: %016lx R11: %016lx R12: %016lx\n", - regs->r10, regs->r11, regs->r12); + regs->r10, regs->r11, regs->r12); printk("R13: %016lx R14: %016lx R15: %016lx\n", - regs->r13, regs->r14, regs->r15); + regs->r13, regs->r14, regs->r15); - asm("movl %%ds,%0" : "=r" (ds)); - asm("movl %%cs,%0" : "=r" (cs)); - asm("movl %%es,%0" : "=r" (es)); + asm("movl %%ds,%0" : "=r" (ds)); + asm("movl %%cs,%0" : "=r" (cs)); + asm("movl %%es,%0" : "=r" (es)); asm("movl %%fs,%0" : "=r" (fsindex)); asm("movl %%gs,%0" : "=r" (gsindex)); rdmsrl(MSR_FS_BASE, fs); - rdmsrl(MSR_GS_BASE, gs); - rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); + rdmsrl(MSR_GS_BASE, gs); + rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); cr4 = read_cr4(); - printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", - fs,fsindex,gs,gsindex,shadowgs); - printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); + printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", + fs, fsindex, gs, gsindex, shadowgs); + printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); get_debugreg(d0, 0); @@ -314,10 +314,10 @@ void prepare_to_copy(struct task_struct *tsk) int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, - struct task_struct * p, struct pt_regs * regs) + struct task_struct *p, struct pt_regs *regs) { int err; - struct pt_regs * childregs; + struct pt_regs *childregs; struct task_struct *me = current; childregs = ((struct pt_regs *) @@ -362,10 +362,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, if (test_thread_flag(TIF_IA32)) err = do_set_thread_area(p, -1, (struct user_desc __user *)childregs->si, 0); - else -#endif - err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); - if (err) + else +#endif + err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); + if (err) goto out; } err = 0; @@ -544,7 +544,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) unsigned fsindex, gsindex; /* we're going to use this soon, after a few expensive things */ - if (next_p->fpu_counter>5) + if (next_p->fpu_counter > 5) prefetch(next->xstate); /* @@ -552,13 +552,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ load_sp0(tss, next); - /* + /* * Switch DS and ES. * This won't pick up thread selector changes, but I guess that is ok. */ savesegment(es, prev->es); if (unlikely(next->es | prev->es)) - loadsegment(es, next->es); + loadsegment(es, next->es); savesegment(ds, prev->ds); if (unlikely(next->ds | prev->ds)) @@ -584,7 +584,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ arch_leave_lazy_cpu_mode(); - /* + /* * Switch FS and GS. * * Segment register != 0 always requires a reload. Also @@ -593,13 +593,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ if (unlikely(fsindex | next->fsindex | prev->fs)) { loadsegment(fs, next->fsindex); - /* + /* * Check if the user used a selector != 0; if yes * clear 64bit base, since overloaded base is always * mapped to the Null selector */ if (fsindex) - prev->fs = 0; + prev->fs = 0; } /* when next process has a 64bit base use it */ if (next->fs) @@ -609,7 +609,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) if (unlikely(gsindex | next->gsindex | prev->gs)) { load_gs_index(next->gsindex); if (gsindex) - prev->gs = 0; + prev->gs = 0; } if (next->gs) wrmsrl(MSR_KERNEL_GS_BASE, next->gs); @@ -618,12 +618,12 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* Must be after DS reload */ unlazy_fpu(prev_p); - /* + /* * Switch the PDA and FPU contexts. */ prev->usersp = read_pda(oldrsp); write_pda(oldrsp, next->usersp); - write_pda(pcurrent, next_p); + write_pda(pcurrent, next_p); write_pda(kernelstack, (unsigned long)task_stack_page(next_p) + @@ -664,7 +664,7 @@ long sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp, struct pt_regs *regs) { long error; - char * filename; + char *filename; filename = getname(name); error = PTR_ERR(filename); @@ -722,55 +722,55 @@ asmlinkage long sys_vfork(struct pt_regs *regs) unsigned long get_wchan(struct task_struct *p) { unsigned long stack; - u64 fp,ip; + u64 fp, ip; int count = 0; - if (!p || p == current || p->state==TASK_RUNNING) - return 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; stack = (unsigned long)task_stack_page(p); if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); - do { + do { if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) - return 0; + return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) return ip; - fp = *(u64 *)fp; - } while (count++ < 16); + fp = *(u64 *)fp; + } while (count++ < 16); return 0; } long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) -{ - int ret = 0; +{ + int ret = 0; int doit = task == current; int cpu; - switch (code) { + switch (code) { case ARCH_SET_GS: if (addr >= TASK_SIZE_OF(task)) - return -EPERM; + return -EPERM; cpu = get_cpu(); - /* handle small bases via the GDT because that's faster to + /* handle small bases via the GDT because that's faster to switch. */ - if (addr <= 0xffffffff) { - set_32bit_tls(task, GS_TLS, addr); - if (doit) { + if (addr <= 0xffffffff) { + set_32bit_tls(task, GS_TLS, addr); + if (doit) { load_TLS(&task->thread, cpu); - load_gs_index(GS_TLS_SEL); + load_gs_index(GS_TLS_SEL); } - task->thread.gsindex = GS_TLS_SEL; + task->thread.gsindex = GS_TLS_SEL; task->thread.gs = 0; - } else { + } else { task->thread.gsindex = 0; task->thread.gs = addr; if (doit) { load_gs_index(0); ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); - } + } } put_cpu(); break; @@ -824,8 +824,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) rdmsrl(MSR_KERNEL_GS_BASE, base); else base = task->thread.gs; - } - else + } else base = task->thread.gs; ret = put_user(base, (unsigned long __user *)addr); break; -- cgit v1.2.3 From 8092c654de9a964c14d89da56834f73a80548a58 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:52 -0300 Subject: x86: add KERN_INFO to printks on process_64.c Fix many coding style warnings. Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 4da8514dd25..3560d7f4d74 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -161,24 +161,24 @@ void __show_regs(struct pt_regs *regs) printk("\n"); print_modules(); - printk("Pid: %d, comm: %.20s %s %s %.*s\n", + printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n", current->pid, current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); - printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); + printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); printk_address(regs->ip, 1); - printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->sp, - regs->flags); - printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", + printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, + regs->sp, regs->flags); + printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", regs->ax, regs->bx, regs->cx); - printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", + printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n", regs->dx, regs->si, regs->di); - printk("RBP: %016lx R08: %016lx R09: %016lx\n", + printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n", regs->bp, regs->r8, regs->r9); - printk("R10: %016lx R11: %016lx R12: %016lx\n", + printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n", regs->r10, regs->r11, regs->r12); - printk("R13: %016lx R14: %016lx R15: %016lx\n", + printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n", regs->r13, regs->r14, regs->r15); asm("movl %%ds,%0" : "=r" (ds)); @@ -196,24 +196,26 @@ void __show_regs(struct pt_regs *regs) cr3 = read_cr3(); cr4 = read_cr4(); - printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", + printk(KERN_INFO "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", fs, fsindex, gs, gsindex, shadowgs); - printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); - printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); + printk(KERN_INFO "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, + es, cr0); + printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, + cr4); get_debugreg(d0, 0); get_debugreg(d1, 1); get_debugreg(d2, 2); - printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); + printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); get_debugreg(d3, 3); get_debugreg(d6, 6); get_debugreg(d7, 7); - printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); + printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); } void show_regs(struct pt_regs *regs) { - printk("CPU %d:", smp_processor_id()); + printk(KERN_INFO "CPU %d:", smp_processor_id()); __show_regs(regs); show_trace(NULL, regs, (void *)(regs + 1), regs->bp); } -- cgit v1.2.3 From 08aadf069d0482ade033badefa8f03eb2fcddd9c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:53 -0300 Subject: x86: coding style fixes to arch/x86/kernel/crash_dump_64.c Fix conding style without change crash_dump_64.o arch/x86/kernel/crash_dump_64.o text data bss dec hex filename 129 0 0 129 81 crash_dump_64.o.after 129 0 0 129 81 crash_dump_64.o.before md5: 885b52c1b92737e6b12e5107e90fc1f1 crash_dump_64.o.after 885b52c1b92737e6b12e5107e90fc1f1 crash_dump_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/crash_dump_64.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index 15e6c6bc4a4..d3e524c8452 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -7,9 +7,8 @@ #include #include - -#include -#include +#include +#include /** * copy_oldmem_page - copy one page from "oldmem" @@ -25,7 +24,7 @@ * in the current kernel. We stitch up a pte, similar to kmap_atomic. */ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, - size_t csize, unsigned long offset, int userbuf) + size_t csize, unsigned long offset, int userbuf) { void *vaddr; -- cgit v1.2.3 From caa007dd3687d38a0252484d9d0a8f9d929ba932 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:54 -0300 Subject: x86: coding style fixes to arch/x86/kernel/signal_64.c Fix all errors and many warnings reported by checkpatch.pl without change signal_64.o arch/x86/kernel/signal_64.o text data bss dec hex filename 5143 0 8 5151 141f signal_64.o.after 5143 0 8 5151 141f signal_64.o.before md5: e68718092b3641cb27e79e55ce57e3ad signal_64.o.after e68718092b3641cb27e79e55ce57e3ad signal_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/sigframe.h | 5 ++++ arch/x86/kernel/signal_64.c | 62 ++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h index 72bbb519d2d..8b4956e800a 100644 --- a/arch/x86/kernel/sigframe.h +++ b/arch/x86/kernel/sigframe.h @@ -24,4 +24,9 @@ struct rt_sigframe { struct ucontext uc; struct siginfo info; }; + +int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs); +int ia32_setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs); #endif diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index b45ef8ddd65..87a9c2f28d9 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -19,9 +19,10 @@ #include #include #include +#include + #include #include -#include #include #include #include @@ -41,11 +42,6 @@ # define FIX_EFLAGS __FIX_EFLAGS #endif -int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs); -int ia32_setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs * regs); - asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) @@ -119,7 +115,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; -#define COPY(x) err |= __get_user(regs->x, &sc->x) +#define COPY(x) (err |= __get_user(regs->x, &sc->x)) COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(dx); COPY(cx); COPY(ip); @@ -149,7 +145,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, } { - struct _fpstate __user * buf; + struct _fpstate __user *buf; err |= __get_user(buf, &sc->fpstate); if (buf) { @@ -189,7 +185,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) goto badframe; @@ -199,16 +195,17 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) return ax; badframe: - signal_fault(regs,frame,"sigreturn"); + signal_fault(regs, frame, "sigreturn"); return 0; -} +} /* * Set up a signal frame. */ static inline int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, + unsigned long mask, struct task_struct *me) { int err = 0; @@ -264,35 +261,35 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) } static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs) + sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; - struct _fpstate __user *fp = NULL; + struct _fpstate __user *fp = NULL; int err = 0; struct task_struct *me = current; if (used_math()) { - fp = get_stack(ka, regs, sizeof(struct _fpstate)); + fp = get_stack(ka, regs, sizeof(struct _fpstate)); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; - if (save_i387(fp) < 0) - err |= -1; + if (save_i387(fp) < 0) + err |= -1; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - if (ka->sa.sa_flags & SA_SIGINFO) { + if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; } - + /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); @@ -302,9 +299,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); - if (sizeof(*set) == 16) { + if (sizeof(*set) == 16) { __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); - __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); + __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); } else err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -315,7 +312,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { /* could use a vstub here */ - goto give_sigsegv; + goto give_sigsegv; } if (err) @@ -323,7 +320,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->di = sig; - /* In case the signal handler was declared without prototypes */ + /* In case the signal handler was declared without prototypes */ regs->ax = 0; /* This also works for non SA_SIGINFO handlers because they expect the @@ -376,7 +373,7 @@ static long current_syscall_ret(struct pt_regs *regs) /* * OK, we're invoking a handler - */ + */ static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, @@ -420,7 +417,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); else ret = ia32_setup_frame(sig, ka, oldset, regs); - } else + } else #endif ret = setup_rt_frame(sig, ka, info, oldset, regs); @@ -448,9 +445,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); + sigaddset(¤t->blocked, sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } @@ -552,14 +549,15 @@ void do_notify_resume(struct pt_regs *regs, void *unused, } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) -{ - struct task_struct *me = current; +{ + struct task_struct *me = current; if (show_unhandled_signals && printk_ratelimit()) { printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", - me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); + me->comm, me->pid, where, frame, regs->ip, + regs->sp, regs->orig_ax); print_vma_addr(" in ", regs->ip); printk("\n"); } - force_sig(SIGSEGV, me); -} + force_sig(SIGSEGV, me); +} -- cgit v1.2.3 From 4df9e510a9fda29aca71d8acac853b98aa6884d1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:55 -0300 Subject: x86: coding style fixes to arch/x86/kernel/traps_64.c Fix all errors and many warnings reported by checkpath.pl. Except the change of include to the traps.o before and after changes are the same. Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/traps_64.c | 59 +++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 3f18d73f420..fe36d96ba70 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #if defined(CONFIG_EDAC) #include @@ -45,9 +47,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -85,7 +84,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) void printk_address(unsigned long address, int reliable) { - printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address); + printk(" [<%016lx>] %s%pS\n", address, reliable ? + "" : "? ", (void *) address); } static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, @@ -98,7 +98,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, [STACKFAULT_STACK - 1] = "#SS", [MCE_STACK - 1] = "#MC", #if DEBUG_STKSZ > EXCEPTION_STKSZ - [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" + [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / + EXCEPTION_STKSZ - 2] = "#DB[?]" #endif }; unsigned k; @@ -163,7 +164,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, } /* - * x86-64 can have up to three kernel stacks: + * x86-64 can have up to three kernel stacks: * process stack * interrupt stack * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack @@ -219,7 +220,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, const struct stacktrace_ops *ops, void *data) { const unsigned cpu = get_cpu(); - unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr; + unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; unsigned used = 0; struct thread_info *tinfo; @@ -237,7 +238,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (!bp) { if (task == current) { /* Grab bp right from our regs */ - asm("movq %%rbp, %0" : "=r" (bp) :); + asm("movq %%rbp, %0" : "=r" (bp) : ); } else { /* bp is the last reg pushed by switch_to */ bp = *(unsigned long *) task->thread.sp; @@ -357,11 +358,13 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack; int i; const int cpu = smp_processor_id(); - unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr); - unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); + unsigned long *irqstack_end = + (unsigned long *) (cpu_pda(cpu)->irqstackptr); + unsigned long *irqstack = + (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); - // debugging aid: "show_stack(NULL, NULL);" prints the - // back trace for this cpu. + /* debugging aid: "show_stack(NULL, NULL);" prints the + back trace for this cpu. */ if (sp == NULL) { if (task) @@ -404,7 +407,7 @@ void dump_stack(void) #ifdef CONFIG_FRAME_POINTER if (!bp) - asm("movq %%rbp, %0" : "=r" (bp):); + asm("movq %%rbp, %0" : "=r" (bp) : ); #endif printk("Pid: %d, comm: %.20s %s %s %.*s\n", @@ -414,7 +417,6 @@ void dump_stack(void) init_utsname()->version); show_trace(NULL, NULL, &stack, bp); } - EXPORT_SYMBOL(dump_stack); void show_registers(struct pt_regs *regs) @@ -493,7 +495,7 @@ unsigned __kprobes long oops_begin(void) raw_local_irq_save(flags); cpu = smp_processor_id(); if (!__raw_spin_trylock(&die_lock)) { - if (cpu == die_owner) + if (cpu == die_owner) /* nested oops. should stop eventually */; else __raw_spin_lock(&die_lock); @@ -638,7 +640,7 @@ kernel_trap: } #define DO_ERROR(trapnr, signr, str, name) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ == NOTIFY_STOP) \ @@ -648,7 +650,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ } #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ siginfo_t info; \ info.si_signo = signr; \ @@ -683,7 +685,7 @@ asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code) preempt_conditional_cli(regs); } -asmlinkage void do_double_fault(struct pt_regs * regs, long error_code) +asmlinkage void do_double_fault(struct pt_regs *regs, long error_code) { static const char str[] = "double fault"; struct task_struct *tsk = current; @@ -778,9 +780,10 @@ io_check_error(unsigned char reason, struct pt_regs *regs) } static notrace __kprobes void -unknown_nmi_error(unsigned char reason, struct pt_regs * regs) +unknown_nmi_error(unsigned char reason, struct pt_regs *regs) { - if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) + if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == + NOTIFY_STOP) return; printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n", reason); @@ -882,7 +885,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) else if (user_mode(eregs)) regs = task_pt_regs(current); /* Exception from kernel and interrupts are enabled. Move to - kernel process stack. */ + kernel process stack. */ else if (eregs->flags & X86_EFLAGS_IF) regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs)); if (eregs != regs) @@ -891,7 +894,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) } /* runs on IST stack. */ -asmlinkage void __kprobes do_debug(struct pt_regs * regs, +asmlinkage void __kprobes do_debug(struct pt_regs *regs, unsigned long error_code) { struct task_struct *tsk = current; @@ -1035,7 +1038,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs) asmlinkage void bad_intr(void) { - printk("bad interrupt"); + printk("bad interrupt"); } asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) @@ -1047,7 +1050,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) conditional_sti(regs); if (!user_mode(regs) && - kernel_math_error(regs, "kernel simd math error", 19)) + kernel_math_error(regs, "kernel simd math error", 19)) return; /* @@ -1092,7 +1095,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs) +asmlinkage void do_spurious_interrupt_bug(struct pt_regs *regs) { } @@ -1142,8 +1145,10 @@ void __init trap_init(void) set_intr_gate(0, ÷_error); set_intr_gate_ist(1, &debug, DEBUG_STACK); set_intr_gate_ist(2, &nmi, NMI_STACK); - set_system_gate_ist(3, &int3, DEBUG_STACK); /* int3 can be called from all */ - set_system_gate(4, &overflow); /* int4 can be called from all */ + /* int3 can be called from all */ + set_system_gate_ist(3, &int3, DEBUG_STACK); + /* int4 can be called from all */ + set_system_gate(4, &overflow); set_intr_gate(5, &bounds); set_intr_gate(6, &invalid_op); set_intr_gate(7, &device_not_available); -- cgit v1.2.3 From e9c8abb66cc37801bdb5d4360bb78d180c3bbb73 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:56 -0300 Subject: x86: coding style fixes to arch/x86/kernel/sys_x86_64.c Fix all errors and many warnings reported by checkpatch.pl without change sys_x86_64.o arch/x86/kernel/sys_x86_64.o: text data bss dec hex filename 1567 0 0 1567 61f sys_x86_64.o.after 1567 0 0 1567 61f sys_x86_64.o.before md5: de28ffedcb5851dfd7ec87a03afec1fd sys_x86_64.o.after de28ffedcb5851dfd7ec87a03afec1fd sys_x86_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/sys_x86_64.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 3b360ef3381..56eb8f916e9 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -13,15 +13,16 @@ #include #include #include +#include -#include #include -asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long off) +asmlinkage long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off) { long error; - struct file * file; + struct file *file; error = -EINVAL; if (off & ~PAGE_MASK) @@ -56,9 +57,9 @@ static void find_start_end(unsigned long flags, unsigned long *begin, unmapped base down for this case. This can give conflicts with the heap, but we assume that glibc malloc knows how to fall back to mmap. Give it 1GB - of playground for now. -AK */ - *begin = 0x40000000; - *end = 0x80000000; + of playground for now. -AK */ + *begin = 0x40000000; + *end = 0x80000000; if (current->flags & PF_RANDOMIZE) { new_begin = randomize_range(*begin, *begin + 0x02000000, 0); if (new_begin) @@ -66,9 +67,9 @@ static void find_start_end(unsigned long flags, unsigned long *begin, } } else { *begin = TASK_UNMAPPED_BASE; - *end = TASK_SIZE; + *end = TASK_SIZE; } -} +} unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, @@ -78,11 +79,11 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct vm_area_struct *vma; unsigned long start_addr; unsigned long begin, end; - + if (flags & MAP_FIXED) return addr; - find_start_end(flags, &begin, &end); + find_start_end(flags, &begin, &end); if (len > end) return -ENOMEM; @@ -96,12 +97,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, } if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32)) && len <= mm->cached_hole_size) { - mm->cached_hole_size = 0; + mm->cached_hole_size = 0; mm->free_area_cache = begin; } addr = mm->free_area_cache; - if (addr < begin) - addr = begin; + if (addr < begin) + addr = begin; start_addr = addr; full_search: @@ -127,7 +128,7 @@ full_search: return addr; } if (addr + mm->cached_hole_size < vma->vm_start) - mm->cached_hole_size = vma->vm_start - addr; + mm->cached_hole_size = vma->vm_start - addr; addr = vma->vm_end; } @@ -177,7 +178,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, vma = find_vma(mm, addr-len); if (!vma || addr <= vma->vm_start) /* remember the address as a hint for next time */ - return (mm->free_area_cache = addr-len); + return mm->free_area_cache = addr-len; } if (mm->mmap_base < len) @@ -194,7 +195,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, vma = find_vma(mm, addr); if (!vma || addr+len <= vma->vm_start) /* remember the address as a hint for next time */ - return (mm->free_area_cache = addr); + return mm->free_area_cache = addr; /* remember the largest hole we saw so far */ if (addr + mm->cached_hole_size < vma->vm_start) @@ -224,13 +225,13 @@ bottomup: } -asmlinkage long sys_uname(struct new_utsname __user * name) +asmlinkage long sys_uname(struct new_utsname __user *name) { int err; down_read(&uts_sem); - err = copy_to_user(name, utsname(), sizeof (*name)); + err = copy_to_user(name, utsname(), sizeof(*name)); up_read(&uts_sem); - if (personality(current->personality) == PER_LINUX32) - err |= copy_to_user(&name->machine, "i686", 5); + if (personality(current->personality) == PER_LINUX32) + err |= copy_to_user(&name->machine, "i686", 5); return err ? -EFAULT : 0; } -- cgit v1.2.3 From 64a76f667d987a559ad0726b4692c987800b22bc Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 29 Jul 2008 12:47:38 -0700 Subject: hpet: /dev/hpet - fixes and cleanup Minor /dev/hpet updates and bugfixes: * Remove dead code, mostly remnants of an incomplete/unusable kernel interface ... noted when addressing "sparse" warnings: + hpet_unregister() and a routine it calls + hpet_task and all references, including hpet_task_lock + hpet_data.hd_flags (and HPET_DATA_PLATFORM) * Correct and improve boot message: + displays *counter* (shared between comparators) bit width, not *timer* bit widths (which are often mixed) + relabel "timers" as "comparators"; this is less confusing, they are not independent like normal timers are (sigh) + display MHz not Hz; it's never less than 10 MHz. * Tighten and correct the userspace interface code + don't accidentally program comparators in 64-bit mode using 32-bit values ... always force comparators into 32-bit mode + provide the correct bit definition flagging comparators with periodic capability ... the ABI is unchanged * Update Documentation/hpet.txt + be more correct and current + expand description a bit + don't mention that now-gone kernel interface Plus, add a FIXME comment for something that could cause big trouble on systems with more capable HPETs than at least Intel seems to ship. It seems that few folk use this userspace interface; it's not very usable given the general lack of HPET IRQ routing. I'm told that the only real point of it any more is to mmap for fast timestamps; IMO that's handled better through the gettimeofday() vsyscall. Signed-off-by: David Brownell Acked-by: Clemens Ladisch Signed-off-by: Ingo Molnar --- arch/x86/kernel/hpet.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ad2b15a1334..82d459186fd 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -115,13 +115,17 @@ static void hpet_reserve_platform_timers(unsigned long id) hd.hd_phys_address = hpet_address; hd.hd_address = hpet; hd.hd_nirqs = nrtimers; - hd.hd_flags = HPET_DATA_PLATFORM; hpet_reserve_timer(&hd, 0); #ifdef CONFIG_HPET_EMULATE_RTC hpet_reserve_timer(&hd, 1); #endif + /* + * NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254 + * is wrong for i8259!) not the output IRQ. Many BIOS writers + * don't bother configuring *any* comparator interrupts. + */ hd.hd_irq[0] = HPET_LEGACY_8254; hd.hd_irq[1] = HPET_LEGACY_RTC; -- cgit v1.2.3 From a677f58a8c8c541bf7d02c658545084040f3708d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 29 Jul 2008 00:37:10 -0700 Subject: x86: print per_cpu data address to make sure per_cpu data on correct node. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup_percpu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index f7745f94c00..61f3966632a 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -180,9 +180,16 @@ void __init setup_per_cpu_areas(void) printk(KERN_INFO "cpu %d has no node %d or node-local memory\n", cpu, node); + if (ptr) + printk(KERN_DEBUG "per cpu data for cpu%d at %016lx\n", + cpu, __pa(ptr)); } - else + else { ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); + if (ptr) + printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n", + cpu, node, __pa(ptr)); + } #endif per_cpu_offset(cpu) = ptr - __per_cpu_start; memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); -- cgit v1.2.3 From a0ac87d61ba20932e54f08464d3f3439d78fa878 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:04 +0200 Subject: x86: AMD microcode patch loader style corrections Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 07e52beacb4..6789530ef33 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -47,9 +47,9 @@ MODULE_LICENSE("GPL v2"); #define UCODE_UCODE_TYPE 0x00000001 #define UCODE_MAX_SIZE (2048) -#define DEFAULT_UCODE_DATASIZE (896) /* 896 bytes */ -#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) /* 64 bytes */ -#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 960 bytes */ +#define DEFAULT_UCODE_DATASIZE (896) +#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) #define DWSIZE (sizeof(u32)) /* For now we support a fixed ucode total size only */ #define get_totalsize(mc) \ -- cgit v1.2.3 From f516526febb75500f280def2108688d388df4e1e Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:05 +0200 Subject: x86: Intel microcode patch loader style corrections Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 6da4a85ff46..a61986e8b69 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -55,8 +55,8 @@ * in a single CPU package. * 1.10 28 Feb 2002 Asit K Mallick and * Tigran Aivazian , - * Serialize updates as required on HT processors due to speculative - * nature of implementation. + * Serialize updates as required on HT processors due to + * speculative nature of implementation. * 1.11 22 Mar 2002 Tigran Aivazian * Fix the panic when writing zero-length microcode chunk. * 1.12 29 Sep 2003 Nitin Kamble , @@ -71,7 +71,7 @@ * Thanks to Stuart Swales for pointing out this bug. */ -//#define DEBUG /* pr_debug */ +/* #define DEBUG */ /* pr_debug */ #include #include #include @@ -99,11 +99,11 @@ MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) /* 48 bytes */ -#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ -#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ -#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ +#define DEFAULT_UCODE_DATASIZE (2000) +#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) +#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) +#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) #define DWSIZE (sizeof(u32)) #define get_totalsize(mc) \ (((struct microcode_intel *)mc)->hdr.totalsize ? \ -- cgit v1.2.3 From 831f9bd3151ebd22959a0cb2a20b44a06b26d4ed Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:06 +0200 Subject: x86: moved function declarations out from AMD microcode patch loader to heade file Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 6789530ef33..2b98e6ab1bf 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -56,9 +56,6 @@ MODULE_LICENSE("GPL v2"); ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \ + MC_HEADER_SIZE) -extern int microcode_init(void *opaque, struct module *module); -extern void microcode_exit(void); - /* serialize access to the physical write */ static DEFINE_SPINLOCK(microcode_update_lock); -- cgit v1.2.3 From daa9c0fee1cbe1d49fbe29af3d4bb16312043b1e Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:07 +0200 Subject: x86: minor pointer type cast in AMD microcode patch loader Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 2b98e6ab1bf..33b2a217a8c 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -394,7 +394,8 @@ static int cpu_request_microcode_amd(int cpu) return error; } - buf_pos = buf = firmware->data; + buf_pos = (unsigned int *)firmware->data; + buf = (void *)firmware->data; size = firmware->size; if (buf_pos[0] != UCODE_MAGIC) { -- cgit v1.2.3 From 7ab6af7ab69df8c9c5fbc380004fb81187742096 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 30 Jul 2008 17:36:48 -0700 Subject: x86_32: use apic_ops at print_local_APIC() Use apic_icr_read at print_local_APIC() in io_apic_32.c Signed-off-by: Hiroshi Shimamoto Cc: Suresh Siddha Cc: Yinghai Lu Signed-off-by: Ingo Molnar Cc: Suresh Siddha Cc: Yinghai Lu --- arch/x86/kernel/io_apic_32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 98e4db5373f..39e063a9a28 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -1486,6 +1486,7 @@ static void print_APIC_bitfield(int base) void /*__init*/ print_local_APIC(void *dummy) { unsigned int v, ver, maxlvt; + u64 icr; if (apic_verbosity == APIC_QUIET) return; @@ -1536,10 +1537,9 @@ void /*__init*/ print_local_APIC(void *dummy) printk(KERN_DEBUG "... APIC ESR: %08x\n", v); } - v = apic_read(APIC_ICR); - printk(KERN_DEBUG "... APIC ICR: %08x\n", v); - v = apic_read(APIC_ICR2); - printk(KERN_DEBUG "... APIC ICR2: %08x\n", v); + icr = apic_icr_read(); + printk(KERN_DEBUG "... APIC ICR: %08x\n", icr); + printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32); v = apic_read(APIC_LVTT); printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); -- cgit v1.2.3 From 90936cfe6c8f7e90a6f8b0c5cb44d3a012dfd313 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:07:44 +0200 Subject: x86, tsc: fix section mismatch warning WARNING: vmlinux.o(.text+0x7950): Section mismatch in reference from the function native_calibrate_tsc() to the function .init.text:tsc_read_refs() The function native_calibrate_tsc() references the function __init tsc_read_refs(). This is often because native_calibrate_tsc lacks a __init annotation or the annotation of tsc_read_refs is wrong. tsc_read_refs is called from native_calibrate_tsc which is not __init and native_calibrate_tsc cannot be marked __init Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/tsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 7603c055390..46af7167673 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -104,7 +104,7 @@ __setup("notsc", notsc_setup); /* * Read TSC and the reference counters. Take care of SMI disturbance */ -static u64 __init tsc_read_refs(u64 *pm, u64 *hpet) +static u64 tsc_read_refs(u64 *pm, u64 *hpet) { u64 t1, t2; int i; -- cgit v1.2.3 From 85a14437ed24244c78f9a70d58b8299753b03c92 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:12:37 +0200 Subject: x86: fix MP_processor_info section mismatch warning WARNING: arch/x86/kernel/built-in.o(.cpuinit.text+0x1fe7): Section mismatch in reference from the function MP_processor_info() to the variable .init.data:x86_quirks The function __cpuinit MP_processor_info() references a variable __initdata x86_quirks. If x86_quirks is only used by MP_processor_info then annotate x86_quirks with a matching annotation. MP_processor_info uses x86_quirks which is __init and is used only from smp_read_mpc and construct_default_ISA_mptable which are __init Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/mpparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 6ae005ccaed..78509ee8cc7 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -49,7 +49,7 @@ static int __init mpf_checksum(unsigned char *mp, int len) return sum & 0xFF; } -static void __cpuinit MP_processor_info(struct mpc_config_processor *m) +static void __init MP_processor_info(struct mpc_config_processor *m) { int apicid; char *bootup_cpu = ""; -- cgit v1.2.3 From bafc1dae8215c862c2e6ae913ddadc20581e59b9 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:11:13 +0200 Subject: x86: mmconf: fix section mismatch warning WARNING: arch/x86/kernel/built-in.o(.cpuinit.text+0x1591): Section mismatch in reference from the function init_amd() to the function .init.text:check_enable_amd_mmconf_dmi() The function __cpuinit init_amd() references a function __init check_enable_amd_mmconf_dmi(). If check_enable_amd_mmconf_dmi is only used by init_amd then annotate check_enable_amd_mmconf_dmi with a matching annotation. check_enable_amd_mmconf_dmi is only called from init_amd which is __cpuinit Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/mmconf-fam10h_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c index fdfdc550b36..efc2f361fe8 100644 --- a/arch/x86/kernel/mmconf-fam10h_64.c +++ b/arch/x86/kernel/mmconf-fam10h_64.c @@ -238,7 +238,7 @@ static struct dmi_system_id __devinitdata mmconf_dmi_table[] = { {} }; -void __init check_enable_amd_mmconf_dmi(void) +void __cpuinit check_enable_amd_mmconf_dmi(void) { dmi_check_system(mmconf_dmi_table); } -- cgit v1.2.3 From d406d21d90dce2e66c7eb4a44605aac947fe55fb Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:09:38 +0200 Subject: x86: mpparse.c: fix section mismatch warning WARNING: vmlinux.o(.text+0x118f7): Section mismatch in reference from the function construct_ioapic_table() to the function .init.text:MP_bus_info() The function construct_ioapic_table() references the function __init MP_bus_info(). This is often because construct_ioapic_table lacks a __init annotation or the annotation of MP_bus_info is wrong. construct_ioapic_table is called only from construct_default_ISA_mptable which is __init Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/mpparse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 78509ee8cc7..2c1963b3962 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -484,7 +484,7 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) } -static void construct_ioapic_table(int mpc_default_type) +static void __init construct_ioapic_table(int mpc_default_type) { struct mpc_config_ioapic ioapic; struct mpc_config_bus bus; @@ -529,7 +529,7 @@ static void construct_ioapic_table(int mpc_default_type) construct_default_ioirq_mptable(mpc_default_type); } #else -static inline void construct_ioapic_table(int mpc_default_type) { } +static inline void __init construct_ioapic_table(int mpc_default_type) { } #endif static inline void __init construct_default_ISA_mptable(int mpc_default_type) -- cgit v1.2.3 From 4c942654a4514d7d0a9b592a7d1b198a212e8a03 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 10 Aug 2008 20:57:45 +0800 Subject: arch/x86/kernel/acpi/boot.c: removed duplicated #include Removed duplicated include file in arch/x86/kernel/acpi/boot.c. Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index fa88a1d7129..d8d118935b0 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -58,7 +58,6 @@ EXPORT_SYMBOL(acpi_disabled); #ifdef CONFIG_X86_64 #include -#include #else /* X86 */ -- cgit v1.2.3 From 8aeb4022633f7d0eca5e13a9622bd73df92bbf2a Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 10 Aug 2008 21:09:22 +0800 Subject: arch/x86/kernel/cpuid.c: removed duplicated #include Removed duplicated include file in arch/x86/kernel/cpuid.c. Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpuid.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 14b11b3be31..3fa4e926b51 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 2ae111cdd8d83ebf9de72e36e68a8c84b6ebbeea Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 11 Aug 2008 18:34:08 +0400 Subject: x86: apic interrupts - move assignments to irqinit_32.c, v2 64bit mode APIC interrupt handlers are set within irqinit_64.c. Lets do tha same for 32bit mode which would help in furter code merging. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 48 ------------------------------------------ arch/x86/kernel/irqinit_32.c | 49 +++++++++++++++++++++++++++++++++++++++++++ arch/x86/mach-default/setup.c | 15 ------------- 3 files changed, 49 insertions(+), 63 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index f93c18f5b79..9e341c9d941 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1354,54 +1354,6 @@ void smp_error_interrupt(struct pt_regs *regs) irq_exit(); } -#ifdef CONFIG_SMP -void __init smp_intr_init(void) -{ - /* - * IRQ0 must be given a fixed assignment and initialized, - * because it's used before the IO-APIC is set up. - */ - set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); - - /* - * The reschedule interrupt is a CPU-to-CPU reschedule-helper - * IPI, driven by wakeup. - */ - alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); - - /* IPI for invalidation */ - alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); - - /* IPI for generic function call */ - alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); - - /* IPI for single call function */ - set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, - call_function_single_interrupt); -} -#endif - -/* - * Initialize APIC interrupts - */ -void __init apic_intr_init(void) -{ -#ifdef CONFIG_SMP - smp_intr_init(); -#endif - /* self generated IPI for local APIC timer */ - alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); - - /* IPI vectors for APIC spurious and error interrupts */ - alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); - alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); - - /* thermal monitor LVT interrupt */ -#ifdef CONFIG_X86_MCE_P4THERMAL - alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); -#endif -} - /** * connect_bsp_APIC - attach the APIC to the interrupt system */ diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index d66914287ee..9200a1e2752 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c @@ -74,6 +74,15 @@ void __init init_ISA_irqs (void) } } +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + /* Overridden in paravirt.c */ void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); @@ -98,6 +107,46 @@ void __init native_init_IRQ(void) set_intr_gate(vector, interrupt[i]); } +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP) + /* + * IRQ0 must be given a fixed assignment and initialized, + * because it's used before the IO-APIC is set up. + */ + set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); + + /* + * The reschedule interrupt is a CPU-to-CPU reschedule-helper + * IPI, driven by wakeup. + */ + alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); + + /* IPI for invalidation */ + alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); + + /* IPI for generic function call */ + alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); + + /* IPI for single call function */ + set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt); +#endif + +#ifdef CONFIG_X86_LOCAL_APIC + /* self generated IPI for local APIC timer */ + alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); + + /* IPI vectors for APIC spurious and error interrupts */ + alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); + alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); +#endif + +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL) + /* thermal monitor LVT interrupt */ + alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); +#endif + + if (!acpi_ioapic) + setup_irq(2, &irq2); + /* setup after call gates are initialised (usually add in * the architecture specific gates) */ diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c index 3d317836be9..b00f5ad10ca 100644 --- a/arch/x86/mach-default/setup.c +++ b/arch/x86/mach-default/setup.c @@ -36,15 +36,6 @@ void __init pre_intr_init_hook(void) init_ISA_irqs(); } -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { - .handler = no_action, - .mask = CPU_MASK_NONE, - .name = "cascade", -}; - /** * intr_init_hook - post gate setup interrupt initialisation * @@ -60,12 +51,6 @@ void __init intr_init_hook(void) if (x86_quirks->arch_intr_init()) return; } -#ifdef CONFIG_X86_LOCAL_APIC - apic_intr_init(); -#endif - - if (!acpi_ioapic) - setup_irq(2, &irq2); } /** -- cgit v1.2.3 From 7c13e6a3d15a4ebcc3f40df5f4d19665479f8ca3 Mon Sep 17 00:00:00 2001 From: Dimitri Sivanich Date: Mon, 11 Aug 2008 10:46:46 -0500 Subject: x86: remove EXPERIMENTAL restriction from CONFIG_HOTPLUG_CPU This removes the EXPERIMENTAL restriction from CONFIG_HOTPLUG_CPU on the x86 architecture. Signed-off-by: Dimitri Sivanich Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3d0f2b6a5a1..7917962ab7f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1371,14 +1371,14 @@ config PHYSICAL_ALIGN Don't change this unless you know what you are doing. config HOTPLUG_CPU - bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER + bool "Support for hot-pluggable CPUs" + depends on SMP && HOTPLUG && !X86_VOYAGER ---help--- - Say Y here to experiment with turning CPUs off and on, and to - enable suspend on SMP systems. CPUs can be controlled through - /sys/devices/system/cpu. - Say N if you want to disable CPU hotplug and don't need to - suspend. + Say Y here to allow turning CPUs off and on. CPUs can be + controlled through /sys/devices/system/cpu. + ( Note: power management support will enable this option + automatically on SMP systems. ) + Say N if you want to disable CPU hotplug. config COMPAT_VDSO def_bool y -- cgit v1.2.3 From 012f09e7942716d5f4339f1fd9a831a485bb1d4a Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 16:23:08 +0200 Subject: x86: compile pat debugfs interface only if CONFIG_X86_PAT is set Recently I've run a kernel w/o PAT support and wondered why there was a file "x86/pat_memtype_list" in debugfs. Of course it's empty if PAT is disabled ... so just get rid of this interface if PAT is disabled. Signed-off-by: Andreas Herrmann Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 2fe30916d4b..647b1c4de71 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -492,7 +492,7 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot) free_memtype(addr, addr + size); } -#if defined(CONFIG_DEBUG_FS) +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT) /* get Nth element of the linked list */ static struct memtype *memtype_get_idx(loff_t pos) @@ -576,4 +576,4 @@ static int __init pat_memtype_list_init(void) late_initcall(pat_memtype_list_init); -#endif /* CONFIG_DEBUG_FS */ +#endif /* CONFIG_DEBUG_FS && CONFIG_X86_PAT */ -- cgit v1.2.3 From 59f09ba2b62e6f89beeb4c8fc2c83fe14321dda9 Mon Sep 17 00:00:00 2001 From: Philipp Kohlbecher Date: Wed, 6 Aug 2008 15:25:26 +0200 Subject: x86: fix comment in protected mode header Comments in arch/x86/boot/compressed/head_32.S erroneously refer to the real mode pointer as the second and the heap area as the third argument to decompress_kernel(). In fact, these have been the first and second argument, respectively, since v2.6.20. This patch corrects the comments. It introduces no code changes. Signed-off-by: Philipp Kohlbecher Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/head_32.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index ba7736cf2ec..29c5fbf0839 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -137,14 +137,15 @@ relocated: */ movl output_len(%ebx), %eax pushl %eax + # push arguments for decompress_kernel: pushl %ebp # output address movl input_len(%ebx), %eax pushl %eax # input_len leal input_data(%ebx), %eax pushl %eax # input_data leal boot_heap(%ebx), %eax - pushl %eax # heap area as third argument - pushl %esi # real mode pointer as second arg + pushl %eax # heap area + pushl %esi # real mode pointer call decompress_kernel addl $20, %esp popl %ecx -- cgit v1.2.3 From 49800efcb17afdf973f33e8aa8807b7f83993cc6 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 10:27:30 +0200 Subject: x86: pda_init(): fix memory leak when using CPU hotplug pda->irqstackptr is allocated whenever a CPU is set online. But it is never freed. This results in a memory leak of 16K for each CPU offline/online cycle. Fix is to allocate pda->irqstackptr only once. Signed-off-by: Andreas Herrmann Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 6f9b8924bdc..8396fd7628a 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -493,17 +493,20 @@ void pda_init(int cpu) /* others are initialized in smpboot.c */ pda->pcurrent = &init_task; pda->irqstackptr = boot_cpu_stack; + pda->irqstackptr += IRQSTACKSIZE - 64; } else { - pda->irqstackptr = (char *) - __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); - if (!pda->irqstackptr) - panic("cannot allocate irqstack for cpu %d", cpu); + if (!pda->irqstackptr) { + pda->irqstackptr = (char *) + __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); + if (!pda->irqstackptr) + panic("cannot allocate irqstack for cpu %d", + cpu); + pda->irqstackptr += IRQSTACKSIZE - 64; + } if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) pda->nodenumber = cpu_to_node(cpu); } - - pda->irqstackptr += IRQSTACKSIZE-64; } char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + -- cgit v1.2.3 From b55793f7528ce1b73c25b3ac8a86a6cda2a0f9a4 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 10:29:37 +0200 Subject: x86: cpu_init(): fix memory leak when using CPU hotplug Exception stacks are allocated each time a CPU is set online. But the allocated space is never freed. Thus with one CPU hotplug offline/online cycle there is a memory leak of 24K (6 pages) for a CPU. Fix is to allocate exception stacks only once -- when the CPU is set online for the first time. Signed-off-by: Andreas Herrmann Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 8396fd7628a..cc6efe86249 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -606,19 +606,22 @@ void __cpuinit cpu_init(void) /* * set up and load the per-CPU TSS */ - for (v = 0; v < N_EXCEPTION_STACKS; v++) { + if (!orig_ist->ist[0]) { static const unsigned int order[N_EXCEPTION_STACKS] = { - [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, - [DEBUG_STACK - 1] = DEBUG_STACK_ORDER + [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, + [DEBUG_STACK - 1] = DEBUG_STACK_ORDER }; - if (cpu) { - estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); - if (!estacks) - panic("Cannot allocate exception stack %ld %d\n", - v, cpu); + for (v = 0; v < N_EXCEPTION_STACKS; v++) { + if (cpu) { + estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); + if (!estacks) + panic("Cannot allocate exception " + "stack %ld %d\n", v, cpu); + } + estacks += PAGE_SIZE << order[v]; + orig_ist->ist[v] = t->x86_tss.ist[v] = + (unsigned long)estacks; } - estacks += PAGE_SIZE << order[v]; - orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks; } t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); -- cgit v1.2.3 From 99809963c99e1ed868d9ebeb4a5e7ee1cbe0309f Mon Sep 17 00:00:00 2001 From: Jeff Chua Date: Wed, 6 Aug 2008 19:09:53 +0800 Subject: x86: make sparsemem more available With CONFIG_X86_PC, I can set CONFIG_SPARSEMEM=y. With CONFIG_X86_GENERICARCH, CONFIG_SPARSEMEM depends on CONFIG_NUMA. I'm using the patch below to enable sparsemem instead of flatmem. System booted and is running. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7917962ab7f..e2305c7d881 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1035,7 +1035,7 @@ config HAVE_ARCH_ALLOC_REMAP config ARCH_FLATMEM_ENABLE def_bool y - depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC && !NUMA + depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && !NUMA config ARCH_DISCONTIGMEM_ENABLE def_bool y @@ -1051,7 +1051,7 @@ config ARCH_SPARSEMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) + depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) || X86_GENERICARCH select SPARSEMEM_STATIC if X86_32 select SPARSEMEM_VMEMMAP_ENABLE if X86_64 -- cgit v1.2.3 From 34a1b9fc4995102ecbb3a980b348aebf168d8196 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 12 Aug 2008 13:25:44 +0100 Subject: Fix date output in x86 microcode driver. The microcode stores its date in a uint32_t in some weird order approximating pdp-endian. Rather than printing it like that, print it properly in ISO standard form. Signed-off-by: David Woodhouse Cc: Shaohua Li Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index a61986e8b69..d2d9d74f4cb 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -339,8 +339,11 @@ static void apply_microcode(int cpu) return; } printk(KERN_INFO "microcode: CPU%d updated from revision " - "0x%x to 0x%x, date = %08x \n", - cpu_num, uci->rev, val[1], uci->mc.mc_intel->hdr.date); + "0x%x to 0x%x, date = %04x-%02x-%02x \n", + cpu_num, uci->rev, val[1], + uci->mc.mc_intel->hdr.date & 0xffff, + uci->mc.mc_intel->hdr.date >> 24, + (uci->mc.mc_intel->hdr.date >> 16) & 0xff); uci->rev = val[1]; } -- cgit v1.2.3 From ee2b92a8201a40021ecd1aee6f0625dc03bacc54 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 13 Aug 2008 11:38:13 -0700 Subject: x86, xsave: remove the redundant access_ok() in setup_rt_frame() save_i387_xstate() is already doing the required access_ok(). Remove the redundant access_ok() before it. Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_64.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 2621b98f5bf..6c581698ab5 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -208,9 +208,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; - if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) - goto give_sigsegv; - if (save_i387_xstate(fp) < 0) err |= -1; } else -- cgit v1.2.3 From ed405958057ca6a8c4c9178a7a3b1167fabb45f5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 13 Aug 2008 11:38:14 -0700 Subject: x86, xsave: clear the user buffer before doing fxsave/xsave fxsave/xsave instructions will not touch all the bytes in the fxsave/xsave frame. Clear the user buffer before doing fxsave/xsave directly to user buffer during the sigcontext setup. This is essentially needed in the context of xsave(for example, some of the fields in the xsave header are not touched by the xsave and defined as must be zero). This will also present uniform and clean context to the user (from which user can safely do fxrstor/xrstor). Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 7415f3e38a5..bb097b1644d 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -92,6 +92,12 @@ int save_i387_xstate(void __user *buf) return 0; clear_used_math(); /* trigger finit */ if (task_thread_info(tsk)->status & TS_USEDFPU) { + /* + * Start with clearing the user buffer. This will present a + * clean context for the bytes not touched by the fxsave/xsave. + */ + __clear_user(buf, sig_xstate_size); + if (task_thread_info(tsk)->status & TS_XSAVE) err = xsave_user(buf); else -- cgit v1.2.3 From f65bc214e042916135256620f900e9599d65e0cb Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 13 Aug 2008 11:38:15 -0700 Subject: x86, xsave: use BUG_ON() instead of BUILD_BUG_ON() All these structure sizes are runtime determined. So use a runtime bug check. Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index bb097b1644d..07713d64deb 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -82,8 +82,7 @@ int save_i387_xstate(void __user *buf) if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) return -EACCES; - BUILD_BUG_ON(sizeof(struct user_i387_struct) != - sizeof(tsk->thread.xstate->fxsave)); + BUG_ON(sig_xstate_size < xstate_size); if ((unsigned long)buf % 64) printk("save_i387_xstate: bad fpstate %p\n", buf); -- cgit v1.2.3 From b76d69ed721e8365739c3bd5dd7891efbea88494 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Thu, 14 Aug 2008 17:25:37 -0700 Subject: x86_64: uml: fix rename header guard In unistd_64.h, the guard macro _ASM_X86_64_UNISTD_H_ is renamed to ASM_X86__UNISTD_64_H. This change should be applied to arch/um/sys-x86_64/syscall_table.c. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/um/sys-x86_64/syscall_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c index c128eb89700..32f5fbe2d0d 100644 --- a/arch/um/sys-x86_64/syscall_table.c +++ b/arch/um/sys-x86_64/syscall_table.c @@ -41,12 +41,12 @@ #define stub_rt_sigreturn sys_rt_sigreturn #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #include #undef __SYSCALL #define __SYSCALL(nr, sym) [ nr ] = sym, -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H typedef void (*sys_call_ptr_t)(void); -- cgit v1.2.3 From ed4e5ec177d20504c51aebb93db12d57716cde9c Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:20 +0200 Subject: x86: apic - use SET_APIC_DEST_FIELD instead of hardcoded shift Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 69a876be506..77c5e5eb820 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -150,7 +150,7 @@ u32 safe_xapic_wait_icr_idle(void) void xapic_icr_write(u32 low, u32 id) { - apic_write(APIC_ICR2, id << 24); + apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id)); apic_write(APIC_ICR, low); } -- cgit v1.2.3 From 36fef0949c14445d231a68663e8a01860f7caca3 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:20 +0200 Subject: x86: apic - unify disable_apic_timer Get rid of local_apic_timer_disabled and use disable_apic_timer instead. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 17 ++++++++++++----- arch/x86/kernel/apic_64.c | 16 +++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 12b154822bc..6af20dd12c9 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -63,7 +63,7 @@ int disable_apic; /* Local APIC timer verification ok */ static int local_apic_timer_verify_ok; /* Disable local APIC timer from the kernel commandline or via dmi quirk */ -static int local_apic_timer_disabled; +static int disable_apic_timer __cpuinitdata; /* Local APIC timer works in C2 */ int local_apic_timer_c2_ok; EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); @@ -574,7 +574,7 @@ void __init setup_boot_APIC_clock(void) * timer as a dummy clock event source on SMP systems, so the * broadcast mechanism is used. On UP systems simply ignore it. */ - if (local_apic_timer_disabled) { + if (disable_apic_timer) { /* No broadcast on UP ! */ if (num_possible_cpus() > 1) { lapic_clockevent.mult = 1; @@ -1699,12 +1699,19 @@ static int __init parse_nolapic(char *arg) } early_param("nolapic", parse_nolapic); -static int __init parse_disable_lapic_timer(char *arg) +static int __init parse_disable_apic_timer(char *arg) { - local_apic_timer_disabled = 1; + disable_apic_timer = 1; return 0; } -early_param("nolapic_timer", parse_disable_lapic_timer); +early_param("noapictimer", parse_disable_apic_timer); + +static int __init parse_nolapic_timer(char *arg) +{ + disable_apic_timer = 1; + return 0; +} +early_param("nolapic_timer", parse_nolapic_timer); static int __init parse_lapic_timer_c2_ok(char *arg) { diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 77c5e5eb820..1e925be861e 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -45,6 +45,7 @@ #include #include +/* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int disable_apic_timer __cpuinitdata; static int apic_calibrate_pmtmr __initdata; int disable_apic; @@ -1583,14 +1584,19 @@ static int __init parse_lapic_timer_c2_ok(char *arg) } early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); -static __init int setup_noapictimer(char *str) +static int __init parse_disable_apic_timer(char *arg) { - if (str[0] != ' ' && str[0] != 0) - return 0; disable_apic_timer = 1; - return 1; + return 0; +} +early_param("noapictimer", parse_disable_apic_timer); + +static int __init parse_nolapic_timer(char *arg) +{ + disable_apic_timer = 1; + return 0; } -__setup("noapictimer", setup_noapictimer); +early_param("nolapic_timer", parse_nolapic_timer); static __init int setup_apicpmtimer(char *s) { -- cgit v1.2.3 From f07f4f9046121ac803bc2f0ded3d77b7c2ab481b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:21 +0200 Subject: x86: apic - unify __setup_APIC_LVTT To be able to unify this function we RE-introduce APIC_DIVISOR for 64bit mode. This snipped was eliminated in some time ago in a sake of clenup but now we need it again since it allow up to get rid of #ifdef(s). And lapic_is_integrated call is added in apic_64.c but since we always have APIC integrated on 64bit cpu compiler will ignore this call. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 1e925be861e..ac399d0f65c 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -244,6 +244,9 @@ int lapic_get_maxlvt(void) return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } +/* Clock divisor is set to 1 */ +#define APIC_DIVISOR 1 + /* * This function sets up the local APIC timer, with a timeout of * 'clocks' APIC bus clock. During calibration we actually call @@ -262,6 +265,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) lvtt_value = LOCAL_TIMER_VECTOR; if (!oneshot) lvtt_value |= APIC_LVT_TIMER_PERIODIC; + if (!lapic_is_integrated()) + lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV); + if (!irqen) lvtt_value |= APIC_LVT_MASKED; @@ -276,7 +282,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | APIC_TDR_DIV_16); if (!oneshot) - apic_write(APIC_TMICT, clocks); + apic_write(APIC_TMICT, clocks / APIC_DIVISOR); } /* @@ -446,7 +452,7 @@ static int __init calibrate_APIC_clock(void) lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); - calibration_result = result / HZ; + calibration_result = (result * APIC_DIVISOR) / HZ; /* * Do a sanity check on the APIC calibration result -- cgit v1.2.3 From 9ce122c6e55c44ae9a4c4c777579b87d83e7f898 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:21 +0200 Subject: x86: apic - do not clear APIC twice in lapic_shutdown There is no need to clear APIC twice since disable_local_APIC will clear it anyway. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 6af20dd12c9..a151d66f948 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -830,10 +830,11 @@ void lapic_shutdown(void) return; local_irq_save(flags); - clear_local_APIC(); if (enabled_via_apicbase) disable_local_APIC(); + else + clear_local_APIC(); local_irq_restore(flags); } -- cgit v1.2.3 From 64e474d168e3cf31e44890b4947644d361f84e43 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:22 +0200 Subject: x86: apic - get rid of local_apic_timer_verify_ok We are able to use clock_event_device as it's done in 64bit apic code so lets get rid of local_apic_timer_verify_ok variable. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index a151d66f948..7783c113be2 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -60,8 +60,6 @@ unsigned long mp_lapic_addr; static int force_enable_local_apic; int disable_apic; -/* Local APIC timer verification ok */ -static int local_apic_timer_verify_ok; /* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int disable_apic_timer __cpuinitdata; /* Local APIC timer works in C2 */ @@ -301,7 +299,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, unsigned int v; /* Lapic used for broadcast ? */ - if (!local_apic_timer_verify_ok) + if (evt->features & CLOCK_EVT_FEAT_DUMMY) return; local_irq_save(flags); @@ -514,7 +512,7 @@ static int __init calibrate_APIC_clock(void) return -1; } - local_apic_timer_verify_ok = 1; + levt->features &= ~CLOCK_EVT_FEAT_DUMMY; /* We trust the pm timer based calibration */ if (!pm_referenced) { @@ -548,11 +546,11 @@ static int __init calibrate_APIC_clock(void) if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2) apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); else - local_apic_timer_verify_ok = 0; + levt->features |= CLOCK_EVT_FEAT_DUMMY; } else local_irq_enable(); - if (!local_apic_timer_verify_ok) { + if (levt->features & CLOCK_EVT_FEAT_DUMMY) { printk(KERN_WARNING "APIC timer disabled due to verification failure.\n"); return -1; -- cgit v1.2.3 From c93baa1ae51cdba25a5f5ad37b2348e700e75daf Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:22 +0200 Subject: x86: apic - unify verify_local_APIC Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 7783c113be2..7ef7c782a42 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -878,6 +878,12 @@ int __init verify_local_APIC(void) */ reg0 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); + apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); + reg1 = apic_read(APIC_ID); + apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); + apic_write(APIC_ID, reg0); + if (reg1 != (reg0 ^ APIC_ID_MASK)) + return 0; /* * The next two are just to see if we have sane values. -- cgit v1.2.3 From 296cb9511dcc3895fda84d0cd5b411bd926e4bb3 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:23 +0200 Subject: x86: apic - unify sync_Arb_IDs Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 3 +-- arch/x86/kernel/apic_64.c | 10 ++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 7ef7c782a42..d07488993ee 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -915,8 +915,7 @@ void __init sync_Arb_IDs(void) apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, - APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index ac399d0f65c..41aff346063 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -742,8 +742,11 @@ int __init verify_local_APIC(void) */ void __init sync_Arb_IDs(void) { - /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ - if (modern_apic()) + /* + * Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not + * needed on AMD. + */ + if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) return; /* @@ -752,8 +755,7 @@ void __init sync_Arb_IDs(void) apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG - | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* -- cgit v1.2.3 From 516cbf3730c49739629d66313b20bdc50c98aa2c Mon Sep 17 00:00:00 2001 From: Tim Bird Date: Tue, 12 Aug 2008 12:52:36 -0700 Subject: x86, bootup: add built-in kernel command line for x86 (v2) Allow x86 to support a built-in kernel command line. The built-in command line can override the one provided by the boot loader, for those cases where the boot loader is broken or it is difficult to change the command line in the the boot loader. H. Peter Anvin wrote: > Ingo Molnar wrote: >> Best would be to make it really apparent in the code that nothing >> changes if this config option is not set. Preferably there should be >> no extra code at all in that case. >> > > I would like to see this: [...Nested ifdefs...] OK. This version changes absolutely nothing if CONFIG_CMDLINE_BOOL is not set (the default). Also, no space is appended even when CONFIG_CMDLINE_BOOL is set, but the builtin string is empty. This is less sloppy all the way around, IMHO. Note that I use the same option names as on other arches for this feature. [ mingo@elte.hu: build fix ] Signed-off-by: Tim Bird Cc: Matt Mackall Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 45 +++++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup.c | 16 ++++++++++++++++ 2 files changed, 61 insertions(+) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ac2fb0641a0..fbcb79bbafd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1392,6 +1392,51 @@ config COMPAT_VDSO If unsure, say Y. +config CMDLINE_BOOL + bool "Built-in kernel command line" + default n + help + Allow for specifying boot arguments to the kernel at + build time. On some systems (e.g. embedded ones), it is + necessary or convenient to provide some or all of the + kernel boot arguments with the kernel itself (that is, + to not rely on the boot loader to provide them.) + + To compile command line arguments into the kernel, + set this option to 'Y', then fill in the + the boot arguments in CONFIG_CMDLINE. + + Systems with fully functional boot loaders (i.e. non-embedded) + should leave this option set to 'N'. + +config CMDLINE + string "Built-in kernel command string" + depends on CMDLINE_BOOL + default "" + help + Enter arguments here that should be compiled into the kernel + image and used at boot time. If the boot loader provides a + command line at boot time, it is appended to this string to + form the full kernel command line, when the system boots. + + However, you can use the CONFIG_CMDLINE_OVERRIDE option to + change this behavior. + + In most cases, the command line (whether built-in or provided + by the boot loader) should specify the device for the root + file system. + +config CMDLINE_OVERRIDE + bool "Built-in command line overrides boot loader arguments" + default n + depends on CMDLINE_BOOL + help + Set this option to 'Y' to have the kernel ignore the boot loader + command line, and use ONLY the built-in command line. + + This is used to work around broken boot loaders. This should + be set to 'N' under normal conditions. + endmenu config ARCH_ENABLE_MEMORY_HOTPLUG diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 68b48e3fbcb..2f31cddd27b 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -223,6 +223,9 @@ unsigned long saved_video_mode; #define RAMDISK_LOAD_FLAG 0x4000 static char __initdata command_line[COMMAND_LINE_SIZE]; +#ifdef CONFIG_CMDLINE_BOOL +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; +#endif #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) struct edd edd; @@ -673,6 +676,19 @@ void __init setup_arch(char **cmdline_p) bss_resource.start = virt_to_phys(&__bss_start); bss_resource.end = virt_to_phys(&__bss_stop)-1; +#ifdef CONFIG_CMDLINE_BOOL +#ifdef CONFIG_CMDLINE_OVERRIDE + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); +#else + if (builtin_cmdline[0]) { + /* append boot loader cmdline to builtin */ + strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); + strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + } +#endif +#endif + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; -- cgit v1.2.3 From 1ac2f7d55b7ee1613c90631e87fea22ec06781e5 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 4 Aug 2008 14:51:24 +0800 Subject: introduce two APIs for page attribute Introduce two APIs for page attribute. flushing tlb/cache in every page attribute is expensive. AGP gart usually will do a lot of operations to change a page to uc, new APIs can reduce flush. Signed-off-by: Shaohua Li Cc: airlied@linux.ie Cc: Andrew Morton Cc: Arjan van de Ven Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 58 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 65c6e46bf05..2c5c18c2464 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -752,12 +752,12 @@ static inline int cache_attr(pgprot_t attr) (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); } -static int change_page_attr_set_clr(unsigned long addr, int numpages, +static int do_change_page_attr_set_clr(unsigned long addr, int numpages, pgprot_t mask_set, pgprot_t mask_clr, - int force_split) + int force_split, int *tlb_flush) { struct cpa_data cpa; - int ret, cache, checkalias; + int ret, checkalias; /* * Check, if we are requested to change a not supported @@ -792,9 +792,22 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, /* * Check whether we really changed something: */ - if (!cpa.flushtlb) - goto out; + *tlb_flush = cpa.flushtlb; + cpa_fill_pool(NULL); + + return ret; +} + +static int change_page_attr_set_clr(unsigned long addr, int numpages, + pgprot_t mask_set, pgprot_t mask_clr, + int force_split) +{ + int cache, flush_cache = 0, ret; + ret = do_change_page_attr_set_clr(addr, numpages, mask_set, mask_clr, + force_split, &flush_cache); + if (!flush_cache) + goto out; /* * No need to flush, when we did not set any of the caching * attributes: @@ -811,10 +824,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, cpa_flush_range(addr, numpages, cache); else cpa_flush_all(cache); - out: - cpa_fill_pool(NULL); - return ret; } @@ -852,6 +862,30 @@ int set_memory_uc(unsigned long addr, int numpages) } EXPORT_SYMBOL(set_memory_uc); +int set_memory_uc_noflush(unsigned long addr, int numpages) +{ + int flush; + /* + * for now UC MINUS. see comments in ioremap_nocache() + */ + if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, + _PAGE_CACHE_UC_MINUS, NULL)) + return -EINVAL; + /* + * for now UC MINUS. see comments in ioremap_nocache() + */ + return do_change_page_attr_set_clr(addr, numpages, + __pgprot(_PAGE_CACHE_UC_MINUS), + __pgprot(0), 0, &flush); +} +EXPORT_SYMBOL(set_memory_uc_noflush); + +void set_memory_flush_all(void) +{ + cpa_flush_all(1); +} +EXPORT_SYMBOL(set_memory_flush_all); + int _set_memory_wc(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, @@ -926,6 +960,14 @@ int set_pages_uc(struct page *page, int numpages) } EXPORT_SYMBOL(set_pages_uc); +int set_pages_uc_noflush(struct page *page, int numpages) +{ + unsigned long addr = (unsigned long)page_address(page); + + return set_memory_uc_noflush(addr, numpages); +} +EXPORT_SYMBOL(set_pages_uc_noflush); + int set_pages_wb(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); -- cgit v1.2.3 From 2bd455dbfebfd632a8dcf1d3d1612737986fde0a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 4 Aug 2008 11:26:38 +0800 Subject: x86: remove nesting CONFIG_HOTPLUG_CPU prefill_possible_map() is defined inside CONFIG_HOTPLUG_CPU, so the nesting CONFIG_HOTPLUG_CPU is just redundant. Signed-off-by: Li Zefan Signed-off-by: Ingo Molnar --- arch/x86/kernel/smpboot.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 332512767f4..d5e19c36204 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1271,16 +1271,13 @@ __init void prefill_possible_map(void) if (!num_processors) num_processors = 1; -#ifdef CONFIG_HOTPLUG_CPU if (additional_cpus == -1) { if (disabled_cpus > 0) additional_cpus = disabled_cpus; else additional_cpus = 0; } -#else - additional_cpus = 0; -#endif + possible = num_processors + additional_cpus; if (possible > NR_CPUS) possible = NR_CPUS; -- cgit v1.2.3 From 020878ac427aa053414602cef975c2b5a2e33bf8 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:23:36 +0200 Subject: x86: coding style fixes to arch/x86/boot/compressed/misc.c Before: total: 4 errors, 6 warnings, 439 lines checked After: total: 1 errors, 5 warnings, 441 lines checked Before -#include +#include paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/misc.o.* 8b2394e1fe519a9542e9a7e3e7b69c39 /tmp/misc.o.after 8b2394e1fe519a9542e9a7e3e7b69c39 /tmp/misc.o.before After -#include +#include paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/misc.o.* 59a2d264284be5e72b5af4f3a8ccfb47 /tmp/misc.o.after 8b2394e1fe519a9542e9a7e3e7b69c39 /tmp/misc.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/misc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 9fea7370647..2a3f77e52e2 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -251,7 +251,7 @@ static void __putstr(int error, const char *s) y--; } } else { - vidmem [(x + cols * y) * 2] = c; + vidmem[(x + cols * y) * 2] = c; if (++x >= cols) { x = 0; if (++y >= lines) { @@ -277,7 +277,8 @@ static void *memset(void *s, int c, unsigned n) int i; char *ss = s; - for (i = 0; i < n; i++) ss[i] = c; + for (i = 0; i < n; i++) + ss[i] = c; return s; } @@ -287,7 +288,8 @@ static void *memcpy(void *dest, const void *src, unsigned n) const char *s = src; char *d = dest; - for (i = 0; i < n; i++) d[i] = s[i]; + for (i = 0; i < n; i++) + d[i] = s[i]; return dest; } -- cgit v1.2.3 From 2070dae10f50ec244f58292436ace9a3f9dc1d71 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:24:06 +0200 Subject: x86: coding style fixes to arch/x86/kernel/bios_uv.c paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/bios_uv.o.* 9afe794594831166704744184e192ed8 /tmp/bios_uv.o.after 9afe794594831166704744184e192ed8 /tmp/bios_uv.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/kernel/bios_uv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c index c639bd55391..fdd585f9c53 100644 --- a/arch/x86/kernel/bios_uv.c +++ b/arch/x86/kernel/bios_uv.c @@ -25,11 +25,11 @@ x86_bios_strerror(long status) { const char *str; switch (status) { - case 0: str = "Call completed without error"; break; - case -1: str = "Not implemented"; break; - case -2: str = "Invalid argument"; break; - case -3: str = "Call completed with error"; break; - default: str = "Unknown BIOS status code"; break; + case 0: str = "Call completed without error"; break; + case -1: str = "Not implemented"; break; + case -2: str = "Invalid argument"; break; + case -3: str = "Call completed with error"; break; + default: str = "Unknown BIOS status code"; break; } return str; } -- cgit v1.2.3 From 209b580fd8c3a42b69550c98de434671d41a4ebb Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:24:45 +0200 Subject: x86: coding style fixes to arch/x86/lib/strstr_32.c Before: total: 3 errors, 0 warnings, 31 lines checked After: total: 0 errors, 0 warnings, 31 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/strstr_32.o.* c96006ec3387862e5bacb139207a3098 /tmp/strstr_32.o.after c96006ec3387862e5bacb139207a3098 /tmp/strstr_32.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/lib/strstr_32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/strstr_32.c b/arch/x86/lib/strstr_32.c index 42e8a50303f..8e2d55f754b 100644 --- a/arch/x86/lib/strstr_32.c +++ b/arch/x86/lib/strstr_32.c @@ -23,9 +23,9 @@ __asm__ __volatile__( "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "2:" - :"=a" (__res), "=&c" (d0), "=&S" (d1) - :"0" (0), "1" (0xffffffff), "2" (cs), "g" (ct) - :"dx", "di"); + : "=a" (__res), "=&c" (d0), "=&S" (d1) + : "0" (0), "1" (0xffffffff), "2" (cs), "g" (ct) + : "dx", "di"); return __res; } -- cgit v1.2.3 From 3492cdf0176bde5e35223a1388d59676bc67c145 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:25:13 +0200 Subject: x86: coding style fixes to arch/x86/lib/string_32.c Before: total: 21 errors, 0 warnings, 237 lines checked After: total: 0 errors, 0 warnings, 237 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/string_32.o.* c55d059ef1612b32a8bb2771a72ae0d5 /tmp/string_32.o.after c55d059ef1612b32a8bb2771a72ae0d5 /tmp/string_32.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/lib/string_32.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/string_32.c b/arch/x86/lib/string_32.c index 94972e7c094..82004d2bf05 100644 --- a/arch/x86/lib/string_32.c +++ b/arch/x86/lib/string_32.c @@ -22,7 +22,7 @@ char *strcpy(char *dest, const char *src) "testb %%al,%%al\n\t" "jne 1b" : "=&S" (d0), "=&D" (d1), "=&a" (d2) - :"0" (src), "1" (dest) : "memory"); + : "0" (src), "1" (dest) : "memory"); return dest; } EXPORT_SYMBOL(strcpy); @@ -42,7 +42,7 @@ char *strncpy(char *dest, const char *src, size_t count) "stosb\n" "2:" : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) - :"0" (src), "1" (dest), "2" (count) : "memory"); + : "0" (src), "1" (dest), "2" (count) : "memory"); return dest; } EXPORT_SYMBOL(strncpy); @@ -60,7 +60,7 @@ char *strcat(char *dest, const char *src) "testb %%al,%%al\n\t" "jne 1b" : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) - : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu): "memory"); + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory"); return dest; } EXPORT_SYMBOL(strcat); @@ -105,9 +105,9 @@ int strcmp(const char *cs, const char *ct) "2:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "3:" - :"=a" (res), "=&S" (d0), "=&D" (d1) - :"1" (cs), "2" (ct) - :"memory"); + : "=a" (res), "=&S" (d0), "=&D" (d1) + : "1" (cs), "2" (ct) + : "memory"); return res; } EXPORT_SYMBOL(strcmp); @@ -130,9 +130,9 @@ int strncmp(const char *cs, const char *ct, size_t count) "3:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "4:" - :"=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2) - :"1" (cs), "2" (ct), "3" (count) - :"memory"); + : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + : "1" (cs), "2" (ct), "3" (count) + : "memory"); return res; } EXPORT_SYMBOL(strncmp); @@ -152,9 +152,9 @@ char *strchr(const char *s, int c) "movl $1,%1\n" "2:\tmovl %1,%0\n\t" "decl %0" - :"=a" (res), "=&S" (d0) - :"1" (s), "0" (c) - :"memory"); + : "=a" (res), "=&S" (d0) + : "1" (s), "0" (c) + : "memory"); return res; } EXPORT_SYMBOL(strchr); @@ -169,9 +169,9 @@ size_t strlen(const char *s) "scasb\n\t" "notl %0\n\t" "decl %0" - :"=c" (res), "=&D" (d0) - :"1" (s), "a" (0), "0" (0xffffffffu) - :"memory"); + : "=c" (res), "=&D" (d0) + : "1" (s), "a" (0), "0" (0xffffffffu) + : "memory"); return res; } EXPORT_SYMBOL(strlen); @@ -189,9 +189,9 @@ void *memchr(const void *cs, int c, size_t count) "je 1f\n\t" "movl $1,%0\n" "1:\tdecl %0" - :"=D" (res), "=&c" (d0) - :"a" (c), "0" (cs), "1" (count) - :"memory"); + : "=D" (res), "=&c" (d0) + : "a" (c), "0" (cs), "1" (count) + : "memory"); return res; } EXPORT_SYMBOL(memchr); @@ -228,9 +228,9 @@ size_t strnlen(const char *s, size_t count) "cmpl $-1,%1\n\t" "jne 1b\n" "3:\tsubl %2,%0" - :"=a" (res), "=&d" (d0) - :"c" (s), "1" (count) - :"memory"); + : "=a" (res), "=&d" (d0) + : "c" (s), "1" (count) + : "memory"); return res; } EXPORT_SYMBOL(strnlen); -- cgit v1.2.3 From d9336a9b47d57db835453968efbd0d5cedfe0260 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:25:43 +0200 Subject: x86: coding style fixes to arch/x86/kernel/paravirt_patch_32.c Before: total: 3 errors, 1 warnings, 49 lines checked After: total: 2 errors, 1 warnings, 49 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/paravirt_patch_32.o.* a78eea4264723e18c49dcfbe0ee0aae7 /tmp/paravirt_patch_32.o.after a78eea4264723e18c49dcfbe0ee0aae7 /tmp/paravirt_patch_32.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/kernel/paravirt_patch_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/paravirt_patch_32.c b/arch/x86/kernel/paravirt_patch_32.c index 58262218781..9fe644f4861 100644 --- a/arch/x86/kernel/paravirt_patch_32.c +++ b/arch/x86/kernel/paravirt_patch_32.c @@ -23,7 +23,7 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf, start = start_##ops##_##x; \ end = end_##ops##_##x; \ goto patch_site - switch(type) { + switch (type) { PATCH_SITE(pv_irq_ops, irq_disable); PATCH_SITE(pv_irq_ops, irq_enable); PATCH_SITE(pv_irq_ops, restore_fl); -- cgit v1.2.3 From d33dcb9e7d272cc3171dcc3a21049902185ab03d Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Fri, 1 Aug 2008 12:46:45 +0200 Subject: x86: Microcode patch loader style corrections Style corrections to main microcode module. Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 28dba1a6e4a..39961bb8329 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -55,8 +55,8 @@ * in a single CPU package. * 1.10 28 Feb 2002 Asit K Mallick and * Tigran Aivazian , - * Serialize updates as required on HT processors due to speculative - * nature of implementation. + * Serialize updates as required on HT processors due to + * speculative nature of implementation. * 1.11 22 Mar 2002 Tigran Aivazian * Fix the panic when writing zero-length microcode chunk. * 1.12 29 Sep 2003 Nitin Kamble , @@ -71,7 +71,7 @@ * Thanks to Stuart Swales for pointing out this bug. */ -//#define DEBUG /* pr_debug */ +/*#define DEBUG pr_debug */ #include #include #include @@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(user_buffer); unsigned int user_buffer_size; /* it's size */ EXPORT_SYMBOL_GPL(user_buffer_size); -static int do_microcode_update (void) +static int do_microcode_update(void) { long cursor = 0; int error = 0; @@ -158,18 +158,20 @@ out: return error; } -static int microcode_open (struct inode *unused1, struct file *unused2) +static int microcode_open(struct inode *unused1, struct file *unused2) { cycle_kernel_lock(); return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } -static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) +static ssize_t microcode_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) { ssize_t ret; if ((len >> PAGE_SHIFT) > num_physpages) { - printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); + printk(KERN_ERR "microcode: too much data (max %ld pages)\n", + num_physpages); return -EINVAL; } @@ -201,7 +203,7 @@ static struct miscdevice microcode_dev = { .fops = µcode_fops, }; -static int __init microcode_dev_init (void) +static int __init microcode_dev_init(void) { int error; @@ -216,7 +218,7 @@ static int __init microcode_dev_init (void) return 0; } -static void microcode_dev_exit (void) +static void microcode_dev_exit(void) { misc_deregister(µcode_dev); } @@ -224,7 +226,7 @@ static void microcode_dev_exit (void) MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); #else #define microcode_dev_init() 0 -#define microcode_dev_exit() do { } while(0) +#define microcode_dev_exit() do { } while (0) #endif /* fake device for request_firmware */ @@ -451,7 +453,7 @@ int microcode_init(void *opaque, struct module *module) } EXPORT_SYMBOL_GPL(microcode_init); -void __exit microcode_exit (void) +void __exit microcode_exit(void) { microcode_dev_exit(); -- cgit v1.2.3 From 636a31781684d0f49208aa163f1a5a3a74210eb4 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Fri, 1 Aug 2008 12:46:46 +0200 Subject: x86: Fixed NULL function pointer dereference in AMD microcode patch loader. Dereference took place in code part responsible for manual installation of microcode patches through /dev/cpu/microcode. Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 39961bb8329..ad136ad99cb 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -127,7 +127,8 @@ static int do_microcode_update(void) old = current->cpus_allowed; while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) { - error = microcode_ops->microcode_sanity_check(new_mc); + if (microcode_ops->microcode_sanity_check != NULL) + error = microcode_ops->microcode_sanity_check(new_mc); if (error) goto out; /* -- cgit v1.2.3 From 5843d9a4d0ba89719916c8f07fc9c57b7126be6d Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 1 Aug 2008 03:15:21 +0200 Subject: x86, pat: avoid highmem cache attribute aliasing Highmem code can leave ptes and tlb entries around for a given page even after kunmap, and after it has been freed. >From what I can gather, the PAT code may change the cache attributes of arbitrary physical addresses (ie. including highmem pages), which would result in aliases in the case that it operates on one of these lazy tlb highmem pages. Flushing kmaps should solve the problem. I've also just added code for conditional flushing if we haven't got any dangling highmem aliases -- this should help performance if we change page attributes frequently or systems that aren't using much highmem pages (eg. if < 4G RAM). Should be turned into 2 patches, but just for RFC... Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 2c5c18c2464..4adb33628de 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -777,6 +777,9 @@ static int do_change_page_attr_set_clr(unsigned long addr, int numpages, WARN_ON_ONCE(1); } + /* Must avoid aliasing mappings in the highmem code */ + kmap_flush_unused(); + cpa.vaddr = addr; cpa.numpages = numpages; cpa.mask_set = mask_set; -- cgit v1.2.3 From c9c3dddd8f9a05b25d4ce53e8e80cc0ea1759d18 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 1 Aug 2008 03:51:38 +0400 Subject: x86_64: remove empty lines from stack traces/oopses Signed-off-by: Alexey Dobriyan Cc: ak@suse.de Cc: akpm@osdl.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/traps_64.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 3f18d73f420..8b5b3b81d43 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -339,9 +339,8 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, unsigned long bp, char *log_lvl) { - printk("\nCall Trace:\n"); + printk("Call Trace:\n"); dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); - printk("\n"); } void show_trace(struct task_struct *task, struct pt_regs *regs, @@ -386,6 +385,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, printk(" %016lx", *stack++); touch_nmi_watchdog(); } + printk("\n"); show_trace_log_lvl(task, regs, sp, bp, log_lvl); } @@ -443,7 +443,6 @@ void show_registers(struct pt_regs *regs) printk("Stack: "); show_stack_log_lvl(NULL, regs, (unsigned long *)sp, regs->bp, ""); - printk("\n"); printk(KERN_EMERG "Code: "); -- cgit v1.2.3 From 48e2bd56b1d1ae4b95fb21be778927b64d5c4235 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Sat, 2 Aug 2008 12:50:37 -0300 Subject: x86: coding style fixes to arch/x86/kernel/traps_64.c Fix coding style of traps_64.c with improvements suggested by Ingo. Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/traps_64.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index fe36d96ba70..5df5d2e97ec 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -84,8 +84,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) void printk_address(unsigned long address, int reliable) { - printk(" [<%016lx>] %s%pS\n", address, reliable ? - "" : "? ", (void *) address); + printk(" [<%016lx>] %s%pS\n", + address, reliable ? "" : "? ", (void *) address); } static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, @@ -98,8 +98,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, [STACKFAULT_STACK - 1] = "#SS", [MCE_STACK - 1] = "#MC", #if DEBUG_STKSZ > EXCEPTION_STKSZ - [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / - EXCEPTION_STKSZ - 2] = "#DB[?]" + [N_EXCEPTION_STACKS ... + N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" #endif }; unsigned k; @@ -363,8 +363,10 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); - /* debugging aid: "show_stack(NULL, NULL);" prints the - back trace for this cpu. */ + /* + * debugging aid: "show_stack(NULL, NULL);" prints the + * back trace for this cpu. + */ if (sp == NULL) { if (task) -- cgit v1.2.3 From f88f07e0f0fd6376e081b10930d272a08fbf082f Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 14 Aug 2008 16:58:15 -0400 Subject: x86: alternatives : fix LOCK_PREFIX race with preemptible kernel and CPU hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a kernel thread is preempted in single-cpu mode right after the NOP (nop about to be turned into a lock prefix), then we CPU hotplug a CPU, and then the thread is scheduled back again, a SMP-unsafe atomic operation will be used on shared SMP variables, leading to corruption. No corruption would happen in the reverse case : going from SMP to UP is ok because we split a bit instruction into tiny pieces, which does not present this condition. Changing the 0x90 (single-byte nop) currently used into a 0x3E DS segment override prefix should fix this issue. Since the default of the atomic instructions is to use the DS segment anyway, it should not affect the behavior. The exception to this are references that use ESP/RSP and EBP/RBP as the base register (they will use the SS segment), however, in Linux (a) DS == SS at all times, and (b) we do not distinguish between segment violations reported as #SS as opposed to #GP, so there is no need to disassemble the instruction to figure out the suitable segment. This patch assumes that the 0x3E prefix will leave atomic operations as-is (thus assuming they normally touch data in the DS segment). Since there seem to be no obvious ill-use of other segment override prefixes for atomic operations, it should be safe. It can be verified with a quick grep -r LOCK_PREFIX include/asm-x86/ grep -A 1 -r LOCK_PREFIX arch/x86/ Taken from This source : AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions States "Instructions that Reference a Non-Stack Segment—If an instruction encoding references any base register other than rBP or rSP, or if an instruction contains an immediate offset, the default segment is the data segment (DS). These instructions can use the segment-override prefix to select one of the non-default segments, as shown in Table 1-5." Therefore, forcing the DS segment on the atomic operations, which already use the DS segment, should not change. This source : http://wiki.osdev.org/X86_Instruction_Encoding States "In 64-bit the CS, SS, DS and ES segment overrides are ignored." Confirmed by "AMD 64-Bit Technology" A.7 http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/x86-64_overview.pdf "In 64-bit mode, the DS, ES, SS and CS segment-override prefixes have no effect. These four prefixes are no longer treated as segment-override prefixes in the context of multipleprefix rules. Instead, they are treated as null prefixes." This patch applies to 2.6.27-rc2, but would also have to be applied to earlier kernels (2.6.26, 2.6.25, ...). Performance impact of the fix : tests done on "xaddq" and "xaddl" shows it actually improves performances on Intel Xeon, AMD64, Pentium M. It does not change the performance on Pentium II, Pentium 3 and Pentium 4. Xeon E5405 2.0GHz : NR_TESTS 10000000 test empty cycles : 162207948 test test 1-byte nop xadd cycles : 170755422 test test DS override prefix xadd cycles : 170000118 * test test LOCK xadd cycles : 472012134 AMD64 2.0GHz : NR_TESTS 10000000 test empty cycles : 146674549 test test 1-byte nop xadd cycles : 150273860 test test DS override prefix xadd cycles : 149982382 * test test LOCK xadd cycles : 270000690 Pentium 4 3.0GHz NR_TESTS 10000000 test empty cycles : 290001195 test test 1-byte nop xadd cycles : 310000560 test test DS override prefix xadd cycles : 310000575 * test test LOCK xadd cycles : 1050103740 Pentium M 2.0GHz NR_TESTS 10000000 test empty cycles : 180000523 test test 1-byte nop xadd cycles : 320000345 test test DS override prefix xadd cycles : 310000374 * test test LOCK xadd cycles : 480000357 Pentium 3 550MHz NR_TESTS 10000000 test empty cycles : 510000231 test test 1-byte nop xadd cycles : 620000128 test test DS override prefix xadd cycles : 620000110 * test test LOCK xadd cycles : 800000088 Pentium II 350MHz NR_TESTS 10000000 test empty cycles : 200833494 test test 1-byte nop xadd cycles : 340000130 test test DS override prefix xadd cycles : 340000126 * test test LOCK xadd cycles : 530000078 Speed test modules can be found at http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed-32.c http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed.c Macro-benchmarks 2.0GHz E5405 Core 2 dual Quad-Core Xeon Summary * replace smp lock prefixes with DS segment selector prefixes no lock prefix (s) with lock prefix (s) Speedup make -j1 kernel/ 33.94 +/- 0.07 34.91 +/- 0.27 2.8 % hackbench 50 2.99 +/- 0.01 3.74 +/- 0.01 25.1 % * replace smp lock prefixes with 0x90 nops no lock prefix (s) with lock prefix (s) Speedup make -j1 kernel/ 34.16 +/- 0.32 34.91 +/- 0.27 2.2 % hackbench 50 3.00 +/- 0.01 3.74 +/- 0.01 24.7 % Detail : 1 CPU, replace smp lock prefixes with DS segment selector prefixes make -j1 kernel/ real 0m34.067s user 0m30.630s sys 0m2.980s real 0m33.867s user 0m30.582s sys 0m3.024s real 0m33.939s user 0m30.738s sys 0m2.876s real 0m33.913s user 0m30.806s sys 0m2.808s avg : 33.94s std. dev. : 0.07s hackbench 50 Time: 2.978 Time: 2.982 Time: 3.010 Time: 2.984 Time: 2.982 avg : 2.99 std. dev. : 0.01 1 CPU, noreplace-smp make -j1 kernel/ real 0m35.326s user 0m30.630s sys 0m3.260s real 0m34.325s user 0m30.802s sys 0m3.084s real 0m35.568s user 0m30.722s sys 0m3.168s real 0m34.435s user 0m30.886s sys 0m2.996s avg.: 34.91s std. dev. : 0.27s hackbench 50 Time: 3.733 Time: 3.750 Time: 3.761 Time: 3.737 Time: 3.741 avg : 3.74 std. dev. : 0.01 1 CPU, replace smp lock prefixes with 0x90 nops make -j1 kernel/ real 0m34.139s user 0m30.782s sys 0m2.820s real 0m34.010s user 0m30.630s sys 0m2.976s real 0m34.777s user 0m30.658s sys 0m2.916s real 0m33.924s user 0m30.634s sys 0m2.924s real 0m33.962s user 0m30.774s sys 0m2.800s real 0m34.141s user 0m30.770s sys 0m2.828s avg : 34.16 std. dev. : 0.32 hackbench 50 Time: 2.999 Time: 2.994 Time: 3.004 Time: 2.991 Time: 2.988 avg : 3.00 std. dev. : 0.01 I did more runs (20 runs of each) to compare the nop case to the DS prefix case. Results in seconds. They actually does not seems to show a significant difference. NOP 34.155 33.955 34.012 35.299 35.679 34.141 33.995 35.016 34.254 33.957 33.957 34.008 35.013 34.494 33.893 34.295 34.314 34.854 33.991 34.132 DS 34.080 34.304 34.374 35.095 34.291 34.135 33.940 34.208 35.276 34.288 33.861 33.898 34.610 34.709 33.851 34.256 35.161 34.283 33.865 35.078 Used http://www.graphpad.com/quickcalcs/ttest1.cfm?Format=C to do the T-test (yeah, I'm lazy) : Group Group One (DS prefix) Group Two (nops) Mean 34.37815 34.37070 SD 0.46108 0.51905 SEM 0.10310 0.11606 N 20 20 P value and statistical significance: The two-tailed P value equals 0.9620 By conventional criteria, this difference is considered to be not statistically significant. Confidence interval: The mean of Group One minus Group Two equals 0.00745 95% confidence interval of this difference: From -0.30682 to 0.32172 Intermediate values used in calculations: t = 0.0480 df = 38 standard error of difference = 0.155 So, unless these calculus are completely bogus, the difference between the nop and the DS case seems not to be statistically significant. Signed-off-by: Mathieu Desnoyers Acked-by: H. Peter Anvin CC: Linus Torvalds CC: Jeremy Fitzhardinge CC: Roland McGrath CC: Ingo Molnar Cc: Steven Rostedt CC: Steven Rostedt CC: Thomas Gleixner CC: Peter Zijlstra CC: Andrew Morton CC: David Miller CC: Ulrich Drepper CC: Rusty Russell CC: Gregory Haskins CC: Arnaldo Carvalho de Melo CC: "Luis Claudio R. Goncalves" CC: Clark Williams CC: Christoph Lameter CC: Andi Kleen CC: Harvey Harrison Signed-off-by: H. Peter Anvin --- arch/x86/kernel/alternative.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 2763cb37b55..7ead11f3732 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -241,25 +241,25 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) continue; if (*ptr > text_end) continue; - text_poke(*ptr, ((unsigned char []){0xf0}), 1); /* add lock prefix */ + /* turn DS segment override prefix into lock prefix */ + text_poke(*ptr, ((unsigned char []){0xf0}), 1); }; } static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) { u8 **ptr; - char insn[1]; if (noreplace_smp) return; - add_nops(insn, 1); for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; if (*ptr > text_end) continue; - text_poke(*ptr, insn, 1); + /* turn lock prefix into DS segment override prefix */ + text_poke(*ptr, ((unsigned char []){0x3E}), 1); }; } -- cgit v1.2.3 From 6f6da97faf29f87b3980a6992fb8cab44b4c444d Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 23:05:19 +0400 Subject: x86: apic - sync_Arb_IDs style fixup No changes on binary level Signed-off-by: Cyrill Gorcunov Acked-by: Maciej W. Rozycki Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 +++- arch/x86/kernel/apic_64.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d07488993ee..60575c05151 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -909,13 +909,15 @@ void __init sync_Arb_IDs(void) */ if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) return; + /* * Wait for idle. */ apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | + APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 41aff346063..72e94ab0e36 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -755,7 +755,8 @@ void __init sync_Arb_IDs(void) apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | + APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* -- cgit v1.2.3 From 638c0411922540deaf8797cacf73513b17618405 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 23:05:18 +0400 Subject: x86: apic - unify init_bsp_APIC - remove redundant read of APIC_LVR register in 64bit mode - APIC is always integrated for 64bit mode so gcc will eliminate lapic_is_integrated call Signed-off-by: Cyrill Gorcunov Acked-by: Maciej W. Rozycki Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 +++- arch/x86/kernel/apic_64.c | 14 +++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 60575c05151..16d9721788c 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -925,7 +925,7 @@ void __init sync_Arb_IDs(void) */ void __init init_bsp_APIC(void) { - unsigned long value; + unsigned int value; /* * Don't do the setup now if we have a SMP BIOS as the @@ -946,11 +946,13 @@ void __init init_bsp_APIC(void) value &= ~APIC_VECTOR_MASK; value |= APIC_SPIV_APIC_ENABLED; +#ifdef CONFIG_X86_32 /* This bit is reserved on P4/Xeon and should be cleared */ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15)) value &= ~APIC_SPIV_FOCUS_DISABLED; else +#endif value |= APIC_SPIV_FOCUS_DISABLED; value |= SPURIOUS_APIC_VECTOR; apic_write(APIC_SPIV, value); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 72e94ab0e36..99d18b8976a 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -773,8 +773,6 @@ void __init init_bsp_APIC(void) if (smp_found_config || !cpu_has_apic) return; - value = apic_read(APIC_LVR); - /* * Do not trust the local APIC being empty at bootup. */ @@ -786,7 +784,15 @@ void __init init_bsp_APIC(void) value = apic_read(APIC_SPIV); value &= ~APIC_VECTOR_MASK; value |= APIC_SPIV_APIC_ENABLED; - value |= APIC_SPIV_FOCUS_DISABLED; + +#ifdef CONFIG_X86_32 + /* This bit is reserved on P4/Xeon and should be cleared */ + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && + (boot_cpu_data.x86 == 15)) + value &= ~APIC_SPIV_FOCUS_DISABLED; + else +#endif + value |= APIC_SPIV_FOCUS_DISABLED; value |= SPURIOUS_APIC_VECTOR; apic_write(APIC_SPIV, value); @@ -795,6 +801,8 @@ void __init init_bsp_APIC(void) */ apic_write(APIC_LVT0, APIC_DM_EXTINT); value = APIC_DM_NMI; + if (!lapic_is_integrated()) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; apic_write(APIC_LVT1, value); } -- cgit v1.2.3 From 6764014bc8bb4849f6a4f336477e873ad5861ed2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:50 +0400 Subject: x86: apic - unify clear_local_APIC - Remove redundant masking of APIC_LVTTHMR register in apic_32.c - Add masking of APIC_LVTTHMR register to apic_64.c. We use a bit complicated #ifdef here: CONFIG_X86_MCE_P4THERMAL is 32bit specific and X86_MCE_INTEL is 64bit specific so the appropriate config variable will be set by Kconfig. - the APIC_ESR register clearing in apic_64.c now uses not straightforward way but this is allowed tradeoff. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 +----- arch/x86/kernel/apic_64.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 16d9721788c..3131603a4d6 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -754,7 +754,7 @@ void clear_local_APIC(void) } /* lets not touch this if we didn't frob it */ -#ifdef CONFIG_X86_MCE_P4THERMAL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL) if (maxlvt >= 5) { v = apic_read(APIC_LVTTHMR); apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); @@ -771,10 +771,6 @@ void clear_local_APIC(void) if (maxlvt >= 4) apic_write(APIC_LVTPC, APIC_LVT_MASKED); -#ifdef CONFIG_X86_MCE_P4THERMAL - if (maxlvt >= 5) - apic_write(APIC_LVTTHMR, APIC_LVT_MASKED); -#endif /* Integrated APIC (!82489DX) ? */ if (lapic_is_integrated()) { if (maxlvt > 3) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 99d18b8976a..d834b758362 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -630,6 +630,13 @@ void clear_local_APIC(void) apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); } + /* lets not touch this if we didn't frob it */ +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL) + if (maxlvt >= 5) { + v = apic_read(APIC_LVTTHMR); + apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); + } +#endif /* * Clean APIC state for other OSs: */ @@ -640,8 +647,14 @@ void clear_local_APIC(void) apic_write(APIC_LVTERR, APIC_LVT_MASKED); if (maxlvt >= 4) apic_write(APIC_LVTPC, APIC_LVT_MASKED); - apic_write(APIC_ESR, 0); - apic_read(APIC_ESR); + + /* Integrated APIC (!82489DX) ? */ + if (lapic_is_integrated()) { + if (maxlvt > 3) + /* Clear ESR due to Pentium errata 3AP and 11AP */ + apic_write(APIC_ESR, 0); + apic_read(APIC_ESR); + } } /** -- cgit v1.2.3 From 92206c909ad1d4f9c355b4842722d5a355d6b76b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:51 +0400 Subject: x86: apic - unify lapic_resume Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 29 ++++++++++++++++++----------- arch/x86/kernel/apic_64.c | 19 +++++++++++++++---- 2 files changed, 33 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3131603a4d6..3d40213d3af 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1606,16 +1606,21 @@ static int lapic_resume(struct sys_device *dev) local_irq_save(flags); - /* - * Make sure the APICBASE points to the right address - * - * FIXME! This will be wrong if we ever support suspend on - * SMP! We'll need to do this as part of the CPU restore! - */ - rdmsr(MSR_IA32_APICBASE, l, h); - l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; - wrmsr(MSR_IA32_APICBASE, l, h); +#ifdef CONFIG_X86_64 + if (x2apic) + enable_x2apic(); + else +#endif + /* + * Make sure the APICBASE points to the right address + * + * FIXME! This will be wrong if we ever support suspend on + * SMP! We'll need to do this as part of the CPU restore! + */ + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; + wrmsr(MSR_IA32_APICBASE, l, h); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); @@ -1625,7 +1630,7 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_SPIV, apic_pm_state.apic_spiv); apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); -#ifdef CONFIG_X86_MCE_P4THERMAL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); #endif @@ -1639,7 +1644,9 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); + local_irq_restore(flags); + return 0; } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index d834b758362..e542a2d08de 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1412,13 +1412,22 @@ static int lapic_resume(struct sys_device *dev) maxlvt = lapic_get_maxlvt(); local_irq_save(flags); - if (!x2apic) { + +#ifdef CONFIG_X86_64 + if (x2apic) + enable_x2apic(); + else +#endif + /* + * Make sure the APICBASE points to the right address + * + * FIXME! This will be wrong if we ever support suspend on + * SMP! We'll need to do this as part of the CPU restore! + */ rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); - } else - enable_x2apic(); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); @@ -1428,7 +1437,7 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_SPIV, apic_pm_state.apic_spiv); apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); -#ifdef CONFIG_X86_MCE_INTEL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); #endif @@ -1442,7 +1451,9 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); + local_irq_restore(flags); + return 0; } -- cgit v1.2.3 From 24968cfdd4c3cf61338495dd0f9bb8a6907d2087 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:52 +0400 Subject: x86: apic - unify lapic_suspend Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 +- arch/x86/kernel/apic_64.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3d40213d3af..6cb8aaaf10f 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1582,7 +1582,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); -#ifdef CONFIG_X86_MCE_P4THERMAL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); #endif diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index e542a2d08de..13dea935b4e 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1390,10 +1390,11 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); -#ifdef CONFIG_X86_MCE_INTEL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); #endif + local_irq_save(flags); disable_local_APIC(); local_irq_restore(flags); -- cgit v1.2.3 From 274cfe5912eebe9d4e1a4c451fe617289a181fcf Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:53 +0400 Subject: x86: apic - rearrange functions and comments Rearrange functions and comments to find differences easier. Also use apic_printk in setup_boot_APIC_clock for 64bit mode. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 69 ++++++++++++++++++++++++++--------------------- arch/x86/kernel/apic_64.c | 48 ++++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 40 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 6cb8aaaf10f..9e8702eebd4 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -251,6 +251,9 @@ int lapic_get_maxlvt(void) * this function twice on the boot CPU, once with a bogus timeout * value, second time for real. The other (noncalibrating) CPUs * call this function only once, with the real, calibrated value. + * + * We do reads before writes even if unnecessary, to get around the + * P5 APIC double write bug. */ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) { @@ -279,6 +282,36 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) apic_write(APIC_TMICT, clocks / APIC_DIVISOR); } +/* + * Setup extended LVT, AMD specific (K8, family 10h) + * + * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and + * MCE interrupts are supported. Thus MCE offset must be set to 0. + */ + +#define APIC_EILVT_LVTOFF_MCE 0 +#define APIC_EILVT_LVTOFF_IBS 1 + +static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) +{ + unsigned long reg = (lvt_off << 4) + APIC_EILVT0; + unsigned int v = (mask << 16) | (msg_type << 8) | vector; + + apic_write(reg, v); +} + +u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) +{ + setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); + return APIC_EILVT_LVTOFF_MCE; +} + +u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) +{ + setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); + return APIC_EILVT_LVTOFF_IBS; +} + /* * Program the next event, relative to now */ @@ -298,7 +331,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, unsigned long flags; unsigned int v; - /* Lapic used for broadcast ? */ + /* Lapic used as dummy for broadcast ? */ if (evt->features & CLOCK_EVT_FEAT_DUMMY) return; @@ -680,35 +713,6 @@ int setup_profiling_timer(unsigned int multiplier) return -EINVAL; } -/* - * Setup extended LVT, AMD specific (K8, family 10h) - * - * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and - * MCE interrupts are supported. Thus MCE offset must be set to 0. - */ - -#define APIC_EILVT_LVTOFF_MCE 0 -#define APIC_EILVT_LVTOFF_IBS 1 - -static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) -{ - unsigned long reg = (lvt_off << 4) + APIC_EILVT0; - unsigned int v = (mask << 16) | (msg_type << 8) | vector; - apic_write(reg, v); -} - -u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) -{ - setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); - return APIC_EILVT_LVTOFF_MCE; -} - -u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) -{ - setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); - return APIC_EILVT_LVTOFF_IBS; -} - /* * Local APIC start and shutdown */ @@ -1542,6 +1546,11 @@ void __cpuinit generic_processor_info(int apicid, int version) #ifdef CONFIG_PM static struct { + /* + * 'active' is true if the local APIC was enabled by us and + * not the BIOS; this signifies that we are also responsible + * for disabling it before entering apm/acpi suspend + */ int active; /* r/w apic fields */ unsigned int apic_id; diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 13dea935b4e..46523c0cc6f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -81,6 +81,9 @@ static void lapic_timer_setup(enum clock_event_mode mode, static void lapic_timer_broadcast(cpumask_t mask); static void apic_pm_activate(void); +/* + * The local apic timer can be used for any function which is CPU local. + */ static struct clock_event_device lapic_clockevent = { .name = "lapic", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT @@ -127,6 +130,11 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } +/* + * Paravirt kernels also might be using these below ops. So we still + * use generic apic_read()/apic_write(), which might be pointing to different + * ops in PARAVIRT case. + */ void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) @@ -175,7 +183,6 @@ static struct apic_ops xapic_ops = { }; struct apic_ops __read_mostly *apic_ops = &xapic_ops; - EXPORT_SYMBOL_GPL(apic_ops); static void x2apic_wait_icr_idle(void) @@ -244,6 +251,10 @@ int lapic_get_maxlvt(void) return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } +/* + * Local APIC timer + */ + /* Clock divisor is set to 1 */ #define APIC_DIVISOR 1 @@ -257,7 +268,6 @@ int lapic_get_maxlvt(void) * We do reads before writes even if unnecessary, to get around the * P5 APIC double write bug. */ - static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) { unsigned int lvtt_value, tmp_value; @@ -474,10 +484,10 @@ static int __init calibrate_APIC_clock(void) void __init setup_boot_APIC_clock(void) { /* - * The local apic timer can be disabled via the kernel commandline. - * Register the lapic timer as a dummy clock event source on SMP - * systems, so the broadcast mechanism is used. On UP systems simply - * ignore it. + * The local apic timer can be disabled via the kernel + * commandline or from the CPU detection code. Register the lapic + * timer as a dummy clock event source on SMP systems, so the + * broadcast mechanism is used. On UP systems simply ignore it. */ if (disable_apic_timer) { printk(KERN_INFO "Disabling APIC timer\n"); @@ -489,7 +499,9 @@ void __init setup_boot_APIC_clock(void) return; } - printk(KERN_INFO "Using local APIC timer interrupts.\n"); + apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n" + "calibrating APIC timer ...\n"); + if (calibrate_APIC_clock()) { /* No broadcast on UP ! */ if (num_possible_cpus() > 1) @@ -508,6 +520,7 @@ void __init setup_boot_APIC_clock(void) printk(KERN_WARNING "APIC timer registered as dummy," " due to nmi_watchdog=%d!\n", nmi_watchdog); + /* Setup the lapic or request the broadcast */ setup_APIC_timer(); } @@ -577,6 +590,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) irq_enter(); local_apic_timer_interrupt(); irq_exit(); + set_irq_regs(old_regs); } @@ -1248,6 +1262,13 @@ void __init connect_bsp_APIC(void) enable_apic_mode(); } +/** + * disconnect_bsp_APIC - detach the APIC from the interrupt system + * @virt_wire_setup: indicates, whether virtual wire mode is selected + * + * Virtual wire mode is necessary to deliver legacy interrupts even when the + * APIC is disabled. + */ void disconnect_bsp_APIC(int virt_wire_setup) { /* Go back to Virtual Wire compatibility mode */ @@ -1347,9 +1368,11 @@ int hard_smp_processor_id(void) #ifdef CONFIG_PM static struct { - /* 'active' is true if the local APIC was enabled by us and - not the BIOS; this signifies that we are also responsible - for disabling it before entering apm/acpi suspend */ + /* + * 'active' is true if the local APIC was enabled by us and + * not the BIOS; this signifies that we are also responsible + * for disabling it before entering apm/acpi suspend + */ int active; /* r/w apic fields */ unsigned int apic_id; @@ -1458,6 +1481,11 @@ static int lapic_resume(struct sys_device *dev) return 0; } +/* + * This device has no shutdown method - fully functioning local APICs + * are needed on every CPU up until machine_halt/restart/poweroff. + */ + static struct sysdev_class lapic_sysclass = { .name = "lapic", .resume = lapic_resume, -- cgit v1.2.3 From 9c803869f5f5e3d7ad94b2926474b2882e30073b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:54 +0400 Subject: x86: apic - unify lapic_is_integrated Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 ++++ arch/x86/kernel/apic_64.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 9e8702eebd4..41134d4e6a6 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -128,7 +128,11 @@ static inline int lapic_get_version(void) */ static inline int lapic_is_integrated(void) { +#ifdef CONFIG_X86_64 + return 1; +#else return APIC_INTEGRATED(lapic_get_version()); +#endif } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 46523c0cc6f..18c0b8cd237 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -111,11 +111,15 @@ static inline int lapic_get_version(void) } /* - * Check, if the APIC is integrated or a seperate chip + * Check, if the APIC is integrated or a separate chip */ static inline int lapic_is_integrated(void) { +#ifdef CONFIG_X86_64 return 1; +#else + return APIC_INTEGRATED(lapic_get_version()); +#endif } /* -- cgit v1.2.3 From cf9768d7514d59b3179a886c4a47908d72e6cf76 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:55 +0400 Subject: x86: apic - unify xapic_icr_read Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 18c0b8cd237..5e0738131e5 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -174,7 +174,7 @@ u64 xapic_icr_read(void) icr2 = apic_read(APIC_ICR2); icr1 = apic_read(APIC_ICR); - return (icr1 | ((u64)icr2 << 32)); + return icr1 | ((u64)icr2 << 32); } static struct apic_ops xapic_ops = { -- cgit v1.2.3 From 7b22ff5344fda666e0938e5261ea7b9a3dfce497 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 18 Aug 2008 00:36:18 +0900 Subject: x86 gart: allocate size-aligned address for alloc_coherent, v2 This patch changes GART IOMMU to return a size aligned address wrt dma_alloc_coherent, as DMA-mapping.txt defines: The cpu return address and the DMA bus master address are both guaranteed to be aligned to the smallest PAGE_SIZE order which is greater than or equal to the requested size. This invariant exists (for example) to guarantee that if you allocate a chunk which is smaller than or equal to 64 kilobytes, the extent of the buffer you receive will not cross a 64K boundary. Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index cdab6784907..4d8efb05428 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -82,7 +82,8 @@ AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ -static unsigned long alloc_iommu(struct device *dev, int size) +static unsigned long alloc_iommu(struct device *dev, int size, + unsigned long align_mask) { unsigned long offset, flags; unsigned long boundary_size; @@ -95,11 +96,12 @@ static unsigned long alloc_iommu(struct device *dev, int size) spin_lock_irqsave(&iommu_bitmap_lock, flags); offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, - size, base_index, boundary_size, 0); + size, base_index, boundary_size, align_mask); if (offset == -1) { need_flush = 1; offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, - size, base_index, boundary_size, 0); + size, base_index, boundary_size, + align_mask); } if (offset != -1) { next_bit = offset+size; @@ -236,10 +238,10 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) * Caller needs to check if the iommu is needed and flush. */ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, - size_t size, int dir) + size_t size, int dir, unsigned long align_mask) { unsigned long npages = iommu_num_pages(phys_mem, size); - unsigned long iommu_page = alloc_iommu(dev, npages); + unsigned long iommu_page = alloc_iommu(dev, npages, align_mask); int i; if (iommu_page == -1) { @@ -262,7 +264,11 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, static dma_addr_t gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir) { - dma_addr_t map = dma_map_area(dev, paddr, size, dir); + dma_addr_t map; + unsigned long align_mask; + + align_mask = (1UL << get_order(size)) - 1; + map = dma_map_area(dev, paddr, size, dir, align_mask); flush_gart(); @@ -281,7 +287,8 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) if (!need_iommu(dev, paddr, size)) return paddr; - bus = gart_map_simple(dev, paddr, size, dir); + bus = dma_map_area(dev, paddr, size, dir, 0); + flush_gart(); return bus; } @@ -340,7 +347,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, unsigned long addr = sg_phys(s); if (nonforced_iommu(dev, addr, s->length)) { - addr = dma_map_area(dev, addr, s->length, dir); + addr = dma_map_area(dev, addr, s->length, dir, 0); if (addr == bad_dma_address) { if (i > 0) gart_unmap_sg(dev, sg, i, dir); @@ -362,7 +369,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, int nelems, struct scatterlist *sout, unsigned long pages) { - unsigned long iommu_start = alloc_iommu(dev, pages); + unsigned long iommu_start = alloc_iommu(dev, pages, 0); unsigned long iommu_page = iommu_start; struct scatterlist *s; int i; -- cgit v1.2.3 From d5e629a6f88137fb77c4cc857be5ea7c3f27110d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 17 Aug 2008 21:12:27 -0700 Subject: x86: apic - unify lapic_resume - fix Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 5e0738131e5..ad532dccd11 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1446,6 +1446,7 @@ static int lapic_resume(struct sys_device *dev) enable_x2apic(); else #endif + { /* * Make sure the APICBASE points to the right address * @@ -1456,6 +1457,7 @@ static int lapic_resume(struct sys_device *dev) l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); + } apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); -- cgit v1.2.3 From 8bfcb3960fde049b863266dab8c3617bb5a541aa Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 18 Aug 2008 12:33:20 +0200 Subject: x86: make movsl_mask definition non-CPU specific movsl_mask is currently defined in arch/x86/kernel/cpu/intel.c, which contains code specific to Intel CPUs. However, movsl_mask is used in the non-CPU specific code in arch/x86/lib/usercopy_32.c, which breaks the compilation when support for Intel CPUs is compiled out. This patch solves this problem by moving movsl_mask's definition close to its users in arch/x86/lib/usercopy_32.c. Signed-off-by: Thomas Petazzoni Cc: michael@free-electrons.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel.c | 7 ------- arch/x86/lib/usercopy_32.c | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index b75f2569b8f..5c8959b8a42 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -23,13 +23,6 @@ #include #endif -#ifdef CONFIG_X86_INTEL_USERCOPY -/* - * Alignment at which movsl is preferred for bulk memory copies. - */ -struct movsl_mask movsl_mask __read_mostly; -#endif - static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) { /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 24e60944971..9e68075544f 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -14,6 +14,13 @@ #include #include +#ifdef CONFIG_X86_INTEL_USERCOPY +/* + * Alignment at which movsl is preferred for bulk memory copies. + */ +struct movsl_mask movsl_mask __read_mostly; +#endif + static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned long n) { #ifdef CONFIG_X86_INTEL_USERCOPY -- cgit v1.2.3 From 774400a3ba23b63f4de39e67ce6c4e48935809dc Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 18 Aug 2008 12:33:21 +0200 Subject: x86: move cmpxchg fallbacks to a generic place arch/x86/kernel/cpu/intel.c defines a few fallback functions (cmpxchg_*()) that are used when the CPU doesn't support cmpxchg and/or cmpxchg64 natively. However, while defined in an Intel-specific file, these functions are also used for CPUs from other vendors when they don't support cmpxchg and/or cmpxchg64. This breaks the compilation when support for Intel CPUs is disabled. This patch moves these functions to a new arch/x86/kernel/cpu/cmpxchg.c file, unconditionally compiled when X86_32 is enabled. Signed-off-by: Thomas Petazzoni Cc: michael@free-electrons.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/cmpxchg.c | 72 +++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/intel.c | 64 -------------------------------------- 3 files changed, 73 insertions(+), 65 deletions(-) create mode 100644 arch/x86/kernel/cpu/cmpxchg.c (limited to 'arch') diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index ee76eaad300..25b4c063fbf 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -5,7 +5,7 @@ obj-y := intel_cacheinfo.o addon_cpuid_features.o obj-y += proc.o feature_names.o -obj-$(CONFIG_X86_32) += common.o bugs.o +obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += common_64.o bugs_64.o obj-$(CONFIG_X86_32) += amd.o obj-$(CONFIG_X86_64) += amd_64.o diff --git a/arch/x86/kernel/cpu/cmpxchg.c b/arch/x86/kernel/cpu/cmpxchg.c new file mode 100644 index 00000000000..2056ccf572c --- /dev/null +++ b/arch/x86/kernel/cpu/cmpxchg.c @@ -0,0 +1,72 @@ +/* + * cmpxchg*() fallbacks for CPU not supporting these instructions + */ + +#include +#include +#include + +#ifndef CONFIG_X86_CMPXCHG +unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) +{ + u8 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u8 *)ptr; + if (prev == old) + *(u8 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u8); + +unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) +{ + u16 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u16 *)ptr; + if (prev == old) + *(u16 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u16); + +unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) +{ + u32 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u32 *)ptr; + if (prev == old) + *(u32 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u32); +#endif + +#ifndef CONFIG_X86_CMPXCHG64 +unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new) +{ + u64 prev; + unsigned long flags; + + /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u64 *)ptr; + if (prev == old) + *(u64 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_486_u64); +#endif + diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 5c8959b8a42..77618c717d7 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -307,69 +307,5 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = { cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev); -#ifndef CONFIG_X86_CMPXCHG -unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) -{ - u8 prev; - unsigned long flags; - - /* Poor man's cmpxchg for 386. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u8 *)ptr; - if (prev == old) - *(u8 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_386_u8); - -unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) -{ - u16 prev; - unsigned long flags; - - /* Poor man's cmpxchg for 386. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u16 *)ptr; - if (prev == old) - *(u16 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_386_u16); - -unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) -{ - u32 prev; - unsigned long flags; - - /* Poor man's cmpxchg for 386. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u32 *)ptr; - if (prev == old) - *(u32 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_386_u32); -#endif - -#ifndef CONFIG_X86_CMPXCHG64 -unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new) -{ - u64 prev; - unsigned long flags; - - /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u64 *)ptr; - if (prev == old) - *(u64 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_486_u64); -#endif - /* arch_initcall(intel_cpu_init); */ -- cgit v1.2.3 From 8d02c2110b3fb8e2700b31596a582a2989fd72ba Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 5 Aug 2008 11:45:19 +0200 Subject: x86: configuration options to compile out x86 CPU support code This patch adds some configuration options that allow to compile out CPU vendor-specific code in x86 kernels (in arch/x86/kernel/cpu). The new configuration options are only visible when CONFIG_EMBEDDED is selected, as they are mostly interesting for space savings reasons. An example of size saving, on x86 with only Intel CPU support: text data bss dec hex filename 1125479 118760 212992 1457231 163c4f vmlinux.old 1121355 116536 212992 1450883 162383 vmlinux -4124 -2224 0 -6348 -18CC +/- However, I'm not exactly sure that the Kconfig wording is correct with regard to !64BIT / 64BIT. [ mingo@elte.hu: convert macro to inline ] Signed-off-by: Thomas Petazzoni Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 70 ++++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/Makefile | 19 ++++++------ 2 files changed, 80 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 2c518fbc52e..6156ac25ff8 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -415,3 +415,73 @@ config X86_MINIMUM_CPU_FAMILY config X86_DEBUGCTLMSR def_bool y depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) + +menuconfig PROCESSOR_SELECT + default y + bool "Supported processor vendors" if EMBEDDED + help + This lets you choose what x86 vendor support code your kernel + will include. + +config CPU_SUP_INTEL_32 + default y + bool "Support Intel processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Intel processors + +config CPU_SUP_INTEL_64 + default y + bool "Support Intel processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for Intel processors + +config CPU_SUP_CYRIX_32 + default y + bool "Support Cyrix processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Cyrix processors + +config CPU_SUP_AMD_32 + default y + bool "Support AMD processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for AMD processors + +config CPU_SUP_AMD_64 + default y + bool "Support AMD processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for AMD processors + +config CPU_SUP_CENTAUR_32 + default y + bool "Support Centaur processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Centaur processors + +config CPU_SUP_CENTAUR_64 + default y + bool "Support Centaur processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for Centaur processors + +config CPU_SUP_TRANSMETA_32 + default y + bool "Support Transmeta processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Transmeta processors + +config CPU_SUP_UMC_32 + default y + bool "Support UMC processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for UMC processors diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 25b4c063fbf..a0fc6c14438 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -7,15 +7,16 @@ obj-y += proc.o feature_names.o obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += common_64.o bugs_64.o -obj-$(CONFIG_X86_32) += amd.o -obj-$(CONFIG_X86_64) += amd_64.o -obj-$(CONFIG_X86_32) += cyrix.o -obj-$(CONFIG_X86_32) += centaur.o -obj-$(CONFIG_X86_64) += centaur_64.o -obj-$(CONFIG_X86_32) += transmeta.o -obj-$(CONFIG_X86_32) += intel.o -obj-$(CONFIG_X86_64) += intel_64.o -obj-$(CONFIG_X86_32) += umc.o + +obj-$(CONFIG_CPU_SUP_AMD_32) += amd.o +obj-$(CONFIG_CPU_SUP_AMD_64) += amd_64.o +obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o +obj-$(CONFIG_CPU_SUP_CENTAUR_32) += centaur.o +obj-$(CONFIG_CPU_SUP_CENTAUR_64) += centaur_64.o +obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o +obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o +obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o +obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o obj-$(CONFIG_X86_MCE) += mcheck/ obj-$(CONFIG_MTRR) += mtrr/ -- cgit v1.2.3 From b6c8051311e1a14d229df05ea39d0a1b2ce90cdd Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:49 +0400 Subject: x86: apic - rearrange maxcpu definition Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 ++-- arch/x86/kernel/apic_64.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 41134d4e6a6..8d1febf05da 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -114,6 +114,8 @@ static DEFINE_PER_CPU(struct clock_event_device, lapic_events); static int enabled_via_apicbase; static unsigned long apic_phys; +unsigned int __cpuinitdata maxcpus = NR_CPUS; + /* * Get the LAPIC version @@ -1459,8 +1461,6 @@ void disconnect_bsp_APIC(int virt_wire_setup) } } -unsigned int __cpuinitdata maxcpus = NR_CPUS; - void __cpuinit generic_processor_info(int apicid, int version) { int cpu; diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index ad532dccd11..46acb9b47ae 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -98,10 +98,10 @@ static struct clock_event_device lapic_clockevent = { static DEFINE_PER_CPU(struct clock_event_device, lapic_events); static unsigned long apic_phys; +unsigned int __cpuinitdata maxcpus = NR_CPUS; unsigned long mp_lapic_addr; -unsigned int __cpuinitdata maxcpus = NR_CPUS; /* * Get the LAPIC version */ -- cgit v1.2.3 From f1ee37891dab6014f6b0ec77b18bc07e2369a55f Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:50 +0400 Subject: x86: apic - unify setup_boot_APIC_clock Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 8d1febf05da..80db3e0426c 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -612,6 +612,7 @@ void __init setup_boot_APIC_clock(void) * broadcast mechanism is used. On UP systems simply ignore it. */ if (disable_apic_timer) { + printk(KERN_INFO "Disabling APIC timer\n"); /* No broadcast on UP ! */ if (num_possible_cpus() > 1) { lapic_clockevent.mult = 1; -- cgit v1.2.3 From 990b183e58cb513a62492b6218987750e106cbfb Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:51 +0400 Subject: x86: apic - unify disable_local_APIC Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 +++- arch/x86/kernel/apic_64.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 80db3e0426c..13c4b79441d 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -796,7 +796,7 @@ void clear_local_APIC(void) */ void disable_local_APIC(void) { - unsigned long value; + unsigned int value; clear_local_APIC(); @@ -808,6 +808,7 @@ void disable_local_APIC(void) value &= ~APIC_SPIV_APIC_ENABLED; apic_write(APIC_SPIV, value); +#ifdef CONFIG_X86_32 /* * When LAPIC was disabled by the BIOS and enabled by the kernel, * restore the disabled state. @@ -819,6 +820,7 @@ void disable_local_APIC(void) l &= ~MSR_IA32_APICBASE_ENABLE; wrmsr(MSR_IA32_APICBASE, l, h); } +#endif } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 46acb9b47ae..4fb903b2fc3 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -691,6 +691,20 @@ void disable_local_APIC(void) value = apic_read(APIC_SPIV); value &= ~APIC_SPIV_APIC_ENABLED; apic_write(APIC_SPIV, value); + +#ifdef CONFIG_X86_32 + /* + * When LAPIC was disabled by the BIOS and enabled by the kernel, + * restore the disabled state. + */ + if (enabled_via_apicbase) { + unsigned int l, h; + + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_ENABLE; + wrmsr(MSR_IA32_APICBASE, l, h); + } +#endif } void lapic_shutdown(void) -- cgit v1.2.3 From fe4024dcb0c01e5399394d2807406a2c13fb1eb7 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:52 +0400 Subject: x86: apic - unify lapic_shutdown Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 9 ++++++--- arch/x86/kernel/apic_64.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 13c4b79441d..d4efe86adc7 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -838,10 +838,13 @@ void lapic_shutdown(void) local_irq_save(flags); - if (enabled_via_apicbase) - disable_local_APIC(); - else +#ifdef CONFIG_X86_32 + if (!enabled_via_apicbase) clear_local_APIC(); + else +#endif + disable_local_APIC(); + local_irq_restore(flags); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 4fb903b2fc3..48806546d49 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -707,6 +707,12 @@ void disable_local_APIC(void) #endif } +/* + * If Linux enabled the LAPIC against the BIOS default disable it down before + * re-entering the BIOS on shutdown. Otherwise the BIOS may get confused and + * not power-off. Additionally clear all LVT entries before disable_local_APIC + * for the case where Linux didn't enable the LAPIC. + */ void lapic_shutdown(void) { unsigned long flags; @@ -716,7 +722,13 @@ void lapic_shutdown(void) local_irq_save(flags); - disable_local_APIC(); +#ifdef CONFIG_X86_32 + if (!enabled_via_apicbase) + clear_local_APIC(); + else +#endif + disable_local_APIC(); + local_irq_restore(flags); } -- cgit v1.2.3 From 36c9d6742897fa414f51c4e9d0f20ab4e6bf942c Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:53 +0400 Subject: x86: apic - unify connect_bsp_APIC Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 ++ arch/x86/kernel/apic_64.c | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d4efe86adc7..6d230e9d0a7 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1387,6 +1387,7 @@ void smp_error_interrupt(struct pt_regs *regs) */ void __init connect_bsp_APIC(void) { +#ifdef CONFIG_X86_32 if (pic_mode) { /* * Do not trust the local APIC being empty at bootup. @@ -1401,6 +1402,7 @@ void __init connect_bsp_APIC(void) outb(0x70, 0x22); outb(0x01, 0x23); } +#endif enable_apic_mode(); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 48806546d49..5579e213b5d 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1285,10 +1285,26 @@ asmlinkage void smp_error_interrupt(void) } /** - * * connect_bsp_APIC - attach the APIC to the interrupt system - * */ + * connect_bsp_APIC - attach the APIC to the interrupt system + */ void __init connect_bsp_APIC(void) { +#ifdef CONFIG_X86_32 + if (pic_mode) { + /* + * Do not trust the local APIC being empty at bootup. + */ + clear_local_APIC(); + /* + * PIC mode, enable APIC mode in the IMCR, i.e. connect BSP's + * local APIC to INT and NMI lines. + */ + apic_printk(APIC_VERBOSE, "leaving PIC mode, " + "enabling APIC mode.\n"); + outb(0x70, 0x22); + outb(0x01, 0x23); + } +#endif enable_apic_mode(); } -- cgit v1.2.3 From c43da2f5e92fe3bcc256f0c0d6cb858368da5bd9 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:54 +0400 Subject: x86: apic - unify lapic_setup_esr We use 32bit code former for 64bit mode since it's much better implementation and easier to merge. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 21 +++++++++---------- arch/x86/kernel/apic_64.c | 51 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 6d230e9d0a7..3c1562afa27 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -983,6 +983,16 @@ static void __cpuinit lapic_setup_esr(void) { unsigned long oldvalue, value, maxlvt; if (lapic_is_integrated() && !esr_disable) { + if (esr_disable) { + /* + * Something untraceable is creating bad interrupts on + * secondary quads ... for the moment, just leave the + * ESR disabled - we can't do anything useful with the + * errors anyway - mbligh + */ + printk(KERN_INFO "Leaving ESR disabled.\n"); + return; + } /* !82489DX */ maxlvt = lapic_get_maxlvt(); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ @@ -1003,16 +1013,7 @@ static void __cpuinit lapic_setup_esr(void) "vector: 0x%08lx after: 0x%08lx\n", oldvalue, value); } else { - if (esr_disable) - /* - * Something untraceable is creating bad interrupts on - * secondary quads ... for the moment, just leave the - * ESR disabled - we can't do anything useful with the - * errors anyway - mbligh - */ - printk(KERN_INFO "Leaving ESR disabled.\n"); - else - printk(KERN_INFO "No ESR for 82489DX.\n"); + printk(KERN_INFO "No ESR for 82489DX.\n"); } } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 5579e213b5d..d74abf7e92f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -863,6 +863,45 @@ void __init init_bsp_APIC(void) apic_write(APIC_LVT1, value); } +static void __cpuinit lapic_setup_esr(void) +{ + unsigned long oldvalue, value, maxlvt; + if (lapic_is_integrated() && !esr_disable) { + if (esr_disable) { + /* + * Something untraceable is creating bad interrupts on + * secondary quads ... for the moment, just leave the + * ESR disabled - we can't do anything useful with the + * errors anyway - mbligh + */ + printk(KERN_INFO "Leaving ESR disabled.\n"); + return; + } + /* !82489DX */ + maxlvt = lapic_get_maxlvt(); + if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ + apic_write(APIC_ESR, 0); + oldvalue = apic_read(APIC_ESR); + + /* enables sending errors */ + value = ERROR_APIC_VECTOR; + apic_write(APIC_LVTERR, value); + /* + * spec says clear errors after enabling vector. + */ + if (maxlvt > 3) + apic_write(APIC_ESR, 0); + value = apic_read(APIC_ESR); + if (value != oldvalue) + apic_printk(APIC_VERBOSE, "ESR value before enabling " + "vector: 0x%08lx after: 0x%08lx\n", + oldvalue, value); + } else { + printk(KERN_INFO "No ESR for 82489DX.\n"); + } +} + + /** * setup_local_APIC - setup the local APIC */ @@ -968,18 +1007,6 @@ void __cpuinit setup_local_APIC(void) preempt_enable(); } -static void __cpuinit lapic_setup_esr(void) -{ - unsigned maxlvt = lapic_get_maxlvt(); - - apic_write(APIC_LVTERR, ERROR_APIC_VECTOR); - /* - * spec says clear errors after enabling vector. - */ - if (maxlvt > 3) - apic_write(APIC_ESR, 0); -} - void __cpuinit end_local_APIC_setup(void) { lapic_setup_esr(); -- cgit v1.2.3 From c40aaec6868401671a0ca14ed77e9b2da2d1f223 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:55 +0400 Subject: x86: apic - unify __setup_APIC_LVTT Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 10 +++++++--- arch/x86/kernel/apic_64.c | 12 ++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3c1562afa27..65419c7d437 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -248,8 +248,12 @@ int lapic_get_maxlvt(void) * Local APIC timer */ -/* Clock divisor is set to 16 */ +/* Clock divisor */ +#ifdef CONFG_X86_64 +#define APIC_DIVISOR 1 +#else #define APIC_DIVISOR 16 +#endif /* * This function sets up the local APIC timer, with a timeout of @@ -281,8 +285,8 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) */ tmp_value = apic_read(APIC_TDCR); apic_write(APIC_TDCR, - (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | - APIC_TDR_DIV_16); + (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | + APIC_TDR_DIV_16); if (!oneshot) apic_write(APIC_TMICT, clocks / APIC_DIVISOR); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index d74abf7e92f..fe57db9f3fb 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -259,8 +259,12 @@ int lapic_get_maxlvt(void) * Local APIC timer */ -/* Clock divisor is set to 1 */ +/* Clock divisor */ +#ifdef CONFG_X86_64 #define APIC_DIVISOR 1 +#else +#define APIC_DIVISOR 16 +#endif /* * This function sets up the local APIC timer, with a timeout of @@ -291,9 +295,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) * Divide PICLK by 16 */ tmp_value = apic_read(APIC_TDCR); - apic_write(APIC_TDCR, (tmp_value - & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) - | APIC_TDR_DIV_16); + apic_write(APIC_TDCR, + (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | + APIC_TDR_DIV_16); if (!oneshot) apic_write(APIC_TMICT, clocks / APIC_DIVISOR); -- cgit v1.2.3 From c177b0bc03e0e11623e2099db42903fb0caf0fd3 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:56 +0400 Subject: x86: apic - unify disconnect_bsp_APIC - just #ifdef added Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 66 ++++++++++++++++++++++++----------------------- arch/x86/kernel/apic_64.c | 23 +++++++++++++++-- 2 files changed, 55 insertions(+), 34 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 65419c7d437..3095bb71eae 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1420,6 +1420,7 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { +#ifdef CONFIG_X86_32 if (pic_mode) { /* * Put the board back into PIC mode (has an effect only on @@ -1431,47 +1432,48 @@ void disconnect_bsp_APIC(int virt_wire_setup) "entering PIC mode.\n"); outb(0x70, 0x22); outb(0x00, 0x23); - } else { - /* Go back to Virtual Wire compatibility mode */ - unsigned long value; + return; + } +#endif - /* For the spurious interrupt use vector F, and enable it */ - value = apic_read(APIC_SPIV); - value &= ~APIC_VECTOR_MASK; - value |= APIC_SPIV_APIC_ENABLED; - value |= 0xf; - apic_write(APIC_SPIV, value); + /* Go back to Virtual Wire compatibility mode */ + unsigned int value; - if (!virt_wire_setup) { - /* - * For LVT0 make it edge triggered, active high, - * external and enabled - */ - value = apic_read(APIC_LVT0); - value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | - APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | - APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); - value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; - value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); - apic_write(APIC_LVT0, value); - } else { - /* Disable LVT0 */ - apic_write(APIC_LVT0, APIC_LVT_MASKED); - } + /* For the spurious interrupt use vector F, and enable it */ + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; + value |= APIC_SPIV_APIC_ENABLED; + value |= 0xf; + apic_write(APIC_SPIV, value); + if (!virt_wire_setup) { /* - * For LVT1 make it edge triggered, active high, nmi and - * enabled + * For LVT0 make it edge triggered, active high, + * external and enabled */ - value = apic_read(APIC_LVT1); - value &= ~( - APIC_MODE_MASK | APIC_SEND_PENDING | + value = apic_read(APIC_LVT0); + value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; - value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); - apic_write(APIC_LVT1, value); + value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); + apic_write(APIC_LVT0, value); + } else { + /* Disable LVT0 */ + apic_write(APIC_LVT0, APIC_LVT_MASKED); } + + /* + * For LVT1 make it edge triggered, active high, + * nmi and enabled + */ + value = apic_read(APIC_LVT1); + value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | + APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | + APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); + value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; + value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); + apic_write(APIC_LVT1, value); } void __cpuinit generic_processor_info(int apicid, int version) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index fe57db9f3fb..0d969103fce 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1348,8 +1348,24 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { +#ifdef CONFIG_X86_32 + if (pic_mode) { + /* + * Put the board back into PIC mode (has an effect only on + * certain older boards). Note that APIC interrupts, including + * IPIs, won't work beyond this point! The only exception are + * INIT IPIs. + */ + apic_printk(APIC_VERBOSE, "disabling APIC mode, " + "entering PIC mode.\n"); + outb(0x70, 0x22); + outb(0x00, 0x23); + return; + } +#endif + /* Go back to Virtual Wire compatibility mode */ - unsigned long value; + unsigned int value; /* For the spurious interrupt use vector F, and enable it */ value = apic_read(APIC_SPIV); @@ -1375,7 +1391,10 @@ void disconnect_bsp_APIC(int virt_wire_setup) apic_write(APIC_LVT0, APIC_LVT_MASKED); } - /* For LVT1 make it edge triggered, active high, nmi and enabled */ + /* + * For LVT1 make it edge triggered, active high, + * nmi and enabled + */ value = apic_read(APIC_LVT1); value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | -- cgit v1.2.3 From 1b313f4a6d7bee7b2c034b3f1e203bc360a71cca Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:57 +0400 Subject: x86: apic - generic_processor_info - use physid_set instead of phys_cpu and physids_or - set phys_cpu_present_map bit AFTER check for allowed number of processors - add checking for APIC valid version in 64bit mode (mostly not needed but added for merging purpose) - add apic_version definition for 64bit mode which is used now Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 15 ++++++++------- arch/x86/kernel/apic_64.c | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3095bb71eae..c3a252b1a8b 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1480,7 +1480,6 @@ void __cpuinit generic_processor_info(int apicid, int version) { int cpu; cpumask_t tmp_map; - physid_mask_t phys_cpu; /* * Validate version @@ -1493,9 +1492,6 @@ void __cpuinit generic_processor_info(int apicid, int version) } apic_version[apicid] = version; - phys_cpu = apicid_to_cpu_present(apicid); - physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu); - if (num_processors >= NR_CPUS) { printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." " Processor ignored.\n", NR_CPUS); @@ -1512,17 +1508,19 @@ void __cpuinit generic_processor_info(int apicid, int version) cpus_complement(tmp_map, cpu_present_map); cpu = first_cpu(tmp_map); - if (apicid == boot_cpu_physical_apicid) + physid_set(apicid, phys_cpu_present_map); + if (apicid == boot_cpu_physical_apicid) { /* * x86_bios_cpu_apicid is required to have processors listed * in same order as logical cpu numbers. Hence the first * entry is BSP, and so on. */ cpu = 0; - + } if (apicid > max_physical_apicid) max_physical_apicid = apicid; +#ifdef CONFIG_X86_32 /* * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y * but we need to work other dependencies like SMP_SUSPEND etc @@ -1542,7 +1540,9 @@ void __cpuinit generic_processor_info(int apicid, int version) def_to_bigsmp = 1; } } -#ifdef CONFIG_SMP +#endif + +#if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) /* are we being called early in kernel startup? */ if (early_per_cpu_ptr(x86_cpu_to_apicid)) { u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); @@ -1555,6 +1555,7 @@ void __cpuinit generic_processor_info(int apicid, int version) per_cpu(x86_bios_cpu_apicid, cpu) = apicid; } #endif + cpu_set(cpu, cpu_possible_map); cpu_set(cpu, cpu_present_map); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 0d969103fce..76c20773bed 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1215,6 +1215,8 @@ void __init init_apic_mappings(void) * This initializes the IO-APIC and APIC hardware if this is * a UP kernel. */ +int apic_version[MAX_APICS]; + int __init APIC_init_uniprocessor(void) { if (disable_apic) { @@ -1409,15 +1411,26 @@ void __cpuinit generic_processor_info(int apicid, int version) int cpu; cpumask_t tmp_map; + /* + * Validate version + */ + if (version == 0x0) { + printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! " + "fixing up to 0x10. (tell your hw vendor)\n", + version); + version = 0x10; + } + apic_version[apicid] = version; + if (num_processors >= NR_CPUS) { printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." - " Processor ignored.\n", NR_CPUS); + " Processor ignored.\n", NR_CPUS); return; } if (num_processors >= maxcpus) { printk(KERN_WARNING "WARNING: maxcpus limit of %i reached." - " Processor ignored.\n", maxcpus); + " Processor ignored.\n", maxcpus); return; } @@ -1437,6 +1450,29 @@ void __cpuinit generic_processor_info(int apicid, int version) if (apicid > max_physical_apicid) max_physical_apicid = apicid; +#ifdef CONFIG_X86_32 + /* + * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y + * but we need to work other dependencies like SMP_SUSPEND etc + * before this can be done without some confusion. + * if (CPU_HOTPLUG_ENABLED || num_processors > 8) + * - Ashok Raj + */ + if (max_physical_apicid >= 8) { + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_INTEL: + if (!APIC_XAPIC(version)) { + def_to_bigsmp = 0; + break; + } + /* If P4 and above fall through */ + case X86_VENDOR_AMD: + def_to_bigsmp = 1; + } + } +#endif + +#if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) /* are we being called early in kernel startup? */ if (early_per_cpu_ptr(x86_cpu_to_apicid)) { u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); @@ -1448,6 +1484,7 @@ void __cpuinit generic_processor_info(int apicid, int version) per_cpu(x86_cpu_to_apicid, cpu) = apicid; per_cpu(x86_bios_cpu_apicid, cpu) = apicid; } +#endif cpu_set(cpu, cpu_possible_map); cpu_set(cpu, cpu_present_map); -- cgit v1.2.3 From fa6b95fc7c6f2f3eb1560e1f33cd13197546c5a0 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:58 +0400 Subject: x86: apic - unify end_local_APIC_setup Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 ++++-- arch/x86/kernel/apic_64.c | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index c3a252b1a8b..f1882329b9c 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1155,13 +1155,15 @@ void __cpuinit setup_local_APIC(void) void __cpuinit end_local_APIC_setup(void) { - unsigned long value; - lapic_setup_esr(); + +#ifdef CONFIG_X86_32 + unsigned int value; /* Disable the local apic timer */ value = apic_read(APIC_LVTT); value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); apic_write(APIC_LVTT, value); +#endif setup_apic_nmi_watchdog(NULL); apic_pm_activate(); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 76c20773bed..eec10b34dc4 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1014,6 +1014,15 @@ void __cpuinit setup_local_APIC(void) void __cpuinit end_local_APIC_setup(void) { lapic_setup_esr(); + +#ifdef CONFIG_X86_32 + unsigned int value; + /* Disable the local apic timer */ + value = apic_read(APIC_LVTT); + value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write(APIC_LVTT, value); +#endif + setup_apic_nmi_watchdog(NULL); apic_pm_activate(); } -- cgit v1.2.3 From 0b23e8cf553f5e706b0057363f1319867bcd1a7d Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:59 +0400 Subject: x86: apic - unify local_apic_timer_interrupt Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 ++++ arch/x86/kernel/apic_64.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index f1882329b9c..af227bce23b 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -685,7 +685,11 @@ static void local_apic_timer_interrupt(void) /* * the NMI deadlock-detector uses this. */ +#ifdef CONFIG_X86_64 + add_pda(apic_timer_irqs, 1); +#else per_cpu(irq_stat, cpu).apic_timer_irqs++; +#endif evt->event_handler(evt); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index eec10b34dc4..a9ad2cb4ff9 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -567,7 +567,11 @@ static void local_apic_timer_interrupt(void) /* * the NMI deadlock-detector uses this. */ +#ifdef CONFIG_X86_64 add_pda(apic_timer_irqs, 1); +#else + per_cpu(irq_stat, cpu).apic_timer_irqs++; +#endif evt->event_handler(evt); } -- cgit v1.2.3 From 79af9bec60e6e218a1e48e8830d603d64a7fc441 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:00 +0400 Subject: x86: apic - unify apic_set_verbosity Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 17 ++++++++++++++--- arch/x86/kernel/apic_64.c | 46 +++++++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index af227bce23b..acbc4dea2ee 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1768,13 +1768,24 @@ early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); static int __init apic_set_verbosity(char *arg) { - if (!arg) + if (!arg) { +#ifdef CONFIG_X86_64 + skip_ioapic_setup = 0; + ioapic_force = 1; + return 0; +#endif return -EINVAL; + } - if (strcmp(arg, "debug") == 0) + if (strcmp("debug", arg) == 0) apic_verbosity = APIC_DEBUG; - else if (strcmp(arg, "verbose") == 0) + else if (strcmp("verbose", arg) == 0) apic_verbosity = APIC_VERBOSE; + else { + printk(KERN_WARNING "APIC Verbosity level %s not recognised" + " use apic=verbose or apic=debug\n", arg); + return -EINVAL; + } return 0; } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index a9ad2cb4ff9..999781810c0 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1759,27 +1759,6 @@ early_param("nox2apic", setup_nox2apic); /* * APIC command line parameters */ -static int __init apic_set_verbosity(char *str) -{ - if (str == NULL) { - skip_ioapic_setup = 0; - ioapic_force = 1; - return 0; - } - if (strcmp("debug", str) == 0) - apic_verbosity = APIC_DEBUG; - else if (strcmp("verbose", str) == 0) - apic_verbosity = APIC_VERBOSE; - else { - printk(KERN_WARNING "APIC Verbosity level %s not recognised" - " use apic=verbose or apic=debug\n", str); - return -EINVAL; - } - - return 0; -} -early_param("apic", apic_set_verbosity); - static __init int setup_disableapic(char *str) { disable_apic = 1; @@ -1824,6 +1803,31 @@ static __init int setup_apicpmtimer(char *s) } __setup("apicpmtimer", setup_apicpmtimer); +static int __init apic_set_verbosity(char *arg) +{ + if (!arg) { +#ifdef CONFIG_X86_64 + skip_ioapic_setup = 0; + ioapic_force = 1; + return 0; +#endif + return -EINVAL; + } + + if (strcmp("debug", arg) == 0) + apic_verbosity = APIC_DEBUG; + else if (strcmp("verbose", arg) == 0) + apic_verbosity = APIC_VERBOSE; + else { + printk(KERN_WARNING "APIC Verbosity level %s not recognised" + " use apic=verbose or apic=debug\n", arg); + return -EINVAL; + } + + return 0; +} +early_param("apic", apic_set_verbosity); + static int __init lapic_insert_resource(void) { if (!apic_phys) -- cgit v1.2.3 From 789fa735712d726b5cfa5c6be57171b5637a4872 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:01 +0400 Subject: x86: apic - unify disableapic and nolapic setup handlers Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 11 +++++++++-- arch/x86/kernel/apic_64.c | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index acbc4dea2ee..5680bda62f7 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1737,13 +1737,20 @@ static int __init parse_lapic(char *arg) } early_param("lapic", parse_lapic); -static int __init parse_nolapic(char *arg) +static int __init setup_disableapic(char *arg) { disable_apic = 1; setup_clear_cpu_cap(X86_FEATURE_APIC); return 0; } -early_param("nolapic", parse_nolapic); +early_param("disableapic", setup_disableapic); + +/* same as disableapic, for compatibility */ +static int __init setup_nolapic(char *arg) +{ + return setup_disableapic(arg); +} +early_param("nolapic", setup_nolapic); static int __init parse_disable_apic_timer(char *arg) { diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 999781810c0..7a317180ba2 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1759,7 +1759,7 @@ early_param("nox2apic", setup_nox2apic); /* * APIC command line parameters */ -static __init int setup_disableapic(char *str) +static int __init setup_disableapic(char *arg) { disable_apic = 1; setup_clear_cpu_cap(X86_FEATURE_APIC); @@ -1768,9 +1768,9 @@ static __init int setup_disableapic(char *str) early_param("disableapic", setup_disableapic); /* same as disableapic, for compatibility */ -static __init int setup_nolapic(char *str) +static int __init setup_nolapic(char *arg) { - return setup_disableapic(str); + return setup_disableapic(arg); } early_param("nolapic", setup_nolapic); -- cgit v1.2.3 From 3415610b8e38b26b52a430b8846665c2d6bb3558 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:02 +0400 Subject: x86: apic - rearrange parse_lapic_timer_c2_ok Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 5680bda62f7..885e306420a 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1752,6 +1752,13 @@ static int __init setup_nolapic(char *arg) } early_param("nolapic", setup_nolapic); +static int __init parse_lapic_timer_c2_ok(char *arg) +{ + local_apic_timer_c2_ok = 1; + return 0; +} +early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); + static int __init parse_disable_apic_timer(char *arg) { disable_apic_timer = 1; @@ -1766,13 +1773,6 @@ static int __init parse_nolapic_timer(char *arg) } early_param("nolapic_timer", parse_nolapic_timer); -static int __init parse_lapic_timer_c2_ok(char *arg) -{ - local_apic_timer_c2_ok = 1; - return 0; -} -early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); - static int __init apic_set_verbosity(char *arg) { if (!arg) { -- cgit v1.2.3 From e75bedf415f300a08e9bbcc755784e488574a73e Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:03 +0400 Subject: x86: apic - lapic_resume 32bit - unification fix Just add parenthesis to be identical of current 64bit implementation (so diff will not complain). Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 885e306420a..e975562a76a 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1646,6 +1646,7 @@ static int lapic_resume(struct sys_device *dev) enable_x2apic(); else #endif + { /* * Make sure the APICBASE points to the right address * @@ -1656,6 +1657,7 @@ static int lapic_resume(struct sys_device *dev) l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); + } apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); -- cgit v1.2.3 From 1b4ee4e4096d430c4c12516c1d30a6b0b4f9e9e4 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 23:12:33 +0400 Subject: x86: apic - compilation warnings fix Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 15 +++++++++------ arch/x86/kernel/apic_64.c | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index e975562a76a..b8d80c29165 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1162,11 +1162,13 @@ void __cpuinit end_local_APIC_setup(void) lapic_setup_esr(); #ifdef CONFIG_X86_32 - unsigned int value; - /* Disable the local apic timer */ - value = apic_read(APIC_LVTT); - value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); - apic_write(APIC_LVTT, value); + { + unsigned int value; + /* Disable the local apic timer */ + value = apic_read(APIC_LVTT); + value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write(APIC_LVTT, value); + } #endif setup_apic_nmi_watchdog(NULL); @@ -1426,6 +1428,8 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { + unsigned int value; + #ifdef CONFIG_X86_32 if (pic_mode) { /* @@ -1443,7 +1447,6 @@ void disconnect_bsp_APIC(int virt_wire_setup) #endif /* Go back to Virtual Wire compatibility mode */ - unsigned int value; /* For the spurious interrupt use vector F, and enable it */ value = apic_read(APIC_SPIV); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 7a317180ba2..37e037606f3 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1020,11 +1020,13 @@ void __cpuinit end_local_APIC_setup(void) lapic_setup_esr(); #ifdef CONFIG_X86_32 - unsigned int value; - /* Disable the local apic timer */ - value = apic_read(APIC_LVTT); - value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); - apic_write(APIC_LVTT, value); + { + unsigned int value; + /* Disable the local apic timer */ + value = apic_read(APIC_LVTT); + value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write(APIC_LVTT, value); + } #endif setup_apic_nmi_watchdog(NULL); @@ -1363,6 +1365,8 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { + unsigned int value; + #ifdef CONFIG_X86_32 if (pic_mode) { /* @@ -1380,7 +1384,6 @@ void disconnect_bsp_APIC(int virt_wire_setup) #endif /* Go back to Virtual Wire compatibility mode */ - unsigned int value; /* For the spurious interrupt use vector F, and enable it */ value = apic_read(APIC_SPIV); -- cgit v1.2.3 From 467cd0529a480c9c25f06154b788d1d1ba77828a Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 18 Aug 2008 16:56:29 -0700 Subject: x86: early_printk.c trivial sparse fixes arch/x86/kernel/early_printk.c:404:13: warning: incorrect type in assignment (different base types) arch/x86/kernel/early_printk.c:404:13: expected restricted __le16 [assigned] [usertype] wValue arch/x86/kernel/early_printk.c:404:13: got int [signed] value arch/x86/kernel/early_printk.c:405:13: warning: incorrect type in assignment (different base types) arch/x86/kernel/early_printk.c:405:13: expected restricted __le16 [assigned] [usertype] wIndex arch/x86/kernel/early_printk.c:405:13: got int [signed] index arch/x86/kernel/early_printk.c:406:14: warning: incorrect type in assignment (different base types) arch/x86/kernel/early_printk.c:406:14: expected restricted __le16 [assigned] [usertype] wLength arch/x86/kernel/early_printk.c:406:14: got int [signed] size arch/x86/kernel/early_printk.c:845:16: warning: Using plain integer as NULL pointer arch/x86/kernel/early_printk.c:992:13: warning: symbol 'enable_debug_console' was not declared. Should it be static? Signed-off-by: Harvey Harrison Signed-off-by: Ingo Molnar --- arch/x86/kernel/early_printk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 28155acf706..825e9136b02 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -401,9 +401,9 @@ static int dbgp_control_msg(unsigned devnum, int requesttype, int request, /* Compute the control message */ req.bRequestType = requesttype; req.bRequest = request; - req.wValue = value; - req.wIndex = index; - req.wLength = size; + req.wValue = cpu_to_le16(value); + req.wIndex = cpu_to_le16(index); + req.wLength = cpu_to_le16(size); pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP); addr = DBGP_EPADDR(devnum, 0); @@ -842,7 +842,7 @@ static int __init early_dbgp_init(char *s) ret = ehci_setup(); if (ret < 0) { dbgp_printk("ehci_setup failed\n"); - ehci_debug = 0; + ehci_debug = NULL; return -1; } @@ -989,7 +989,7 @@ static int __init setup_early_printk(char *buf) return 0; } -void __init enable_debug_console(char *buf) +static void __init enable_debug_console(char *buf) { #ifdef DBGP_DEBUG struct console *old_early_console = NULL; -- cgit v1.2.3 From e2fe16d91228a005811335fbc4fbad5d4f5b75af Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 15 Aug 2008 15:36:31 -0700 Subject: x86: boot: stub out unimplemented CPU feature words The CPU feature detection code in the boot code is somewhat minimal, and doesn't include all possible CPUID words. In particular, it doesn't contain the code for CPU feature words 2 (Transmeta), 3 (Linux-specific), 5 (VIA), or 7 (scattered). Zero them out, so we can still set those bits as known at compile time; in particular, this allows creating a Linux-specific NOPL flag and have it required (and therefore resolvable at compile time) in 64-bit mode. Signed-off-by: H. Peter Anvin --- arch/x86/boot/cpucheck.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index 7804389ee00..19b14f7ef9f 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c @@ -46,12 +46,12 @@ static const u32 req_flags[NCAPINTS] = { REQUIRED_MASK0, REQUIRED_MASK1, - REQUIRED_MASK2, - REQUIRED_MASK3, + 0, /* REQUIRED_MASK2 not implemented in this file */ + 0, /* REQUIRED_MASK3 not implemented in this file */ REQUIRED_MASK4, - REQUIRED_MASK5, + 0, /* REQUIRED_MASK5 not implemented in this file */ REQUIRED_MASK6, - REQUIRED_MASK7, + 0, /* REQUIRED_MASK7 not implemented in this file */ }; #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a)) -- cgit v1.2.3 From 7e00df5818964298c9821365a6cb7a8304227c5c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Aug 2008 17:39:32 -0700 Subject: x86: add NOPL as a synthetic CPU feature bit The long noops ("NOPL") are supposed to be detected by family >= 6. Unfortunately, several non-Intel x86 implementations, both hardware and software, don't obey this dictum. Instead, probe for NOPL directly by executing a NOPL instruction and see if we get #UD. Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 32 +++++++++++++++++++++++++++++++- arch/x86/kernel/cpu/common_64.c | 36 ++++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/feature_names.c | 3 ++- 3 files changed, 69 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d4fa3..0785b3c8d04 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include @@ -341,6 +342,35 @@ static void __init early_cpu_detect(void) early_get_cap(c); } +/* + * The NOPL instruction is supposed to exist on all CPUs with + * family >= 6, unfortunately, that's not true in practice because + * of early VIA chips and (more importantly) broken virtualizers that + * are not easy to detect. Hence, probe for it based on first + * principles. + */ +static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +{ + const u32 nopl_signature = 0x888c53b1; /* Random number */ + u32 has_nopl = nopl_signature; + + clear_cpu_cap(c, X86_FEATURE_NOPL); + if (c->x86 >= 6) { + asm volatile("\n" + "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ + "2:\n" + " .section .fixup,\"ax\"\n" + "3: xor %0,%0\n" + " jmp 2b\n" + " .previous\n" + _ASM_EXTABLE(1b,3b) + : "+a" (has_nopl)); + + if (has_nopl == nopl_signature) + set_cpu_cap(c, X86_FEATURE_NOPL); + } +} + static void __cpuinit generic_identify(struct cpuinfo_x86 *c) { u32 tfms, xlvl; @@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) } init_scattered_cpuid_features(c); + detect_nopl(c); } - } static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index dd6e3f15017..c3afba5a81a 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef CONFIG_X86_LOCAL_APIC #include @@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void) } } +/* + * The NOPL instruction is supposed to exist on all CPUs with + * family >= 6, unfortunately, that's not true in practice because + * of early VIA chips and (more importantly) broken virtualizers that + * are not easy to detect. Hence, probe for it based on first + * principles. + * + * Note: no 64-bit chip is known to lack these, but put the code here + * for consistency with 32 bits, and to make it utterly trivial to + * diagnose the problem should it ever surface. + */ +static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +{ + const u32 nopl_signature = 0x888c53b1; /* Random number */ + u32 has_nopl = nopl_signature; + + clear_cpu_cap(c, X86_FEATURE_NOPL); + if (c->x86 >= 6) { + asm volatile("\n" + "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ + "2:\n" + " .section .fixup,\"ax\"\n" + "3: xor %0,%0\n" + " jmp 2b\n" + " .previous\n" + _ASM_EXTABLE(1b,3b) + : "+a" (has_nopl)); + + if (has_nopl == nopl_signature) + set_cpu_cap(c, X86_FEATURE_NOPL); + } +} + static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c); void __init early_cpu_init(void) @@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) c->x86_phys_bits = eax & 0xff; } + detect_nopl(c); + if (c->x86_vendor != X86_VENDOR_UNKNOWN && cpu_devs[c->x86_vendor]->c_early_init) cpu_devs[c->x86_vendor]->c_early_init(c); diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index e43ad4ad4cb..c9017799497 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c @@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = { NULL, NULL, NULL, NULL, "constant_tsc", "up", NULL, "arch_perfmon", "pebs", "bts", NULL, NULL, - "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "rep_good", NULL, NULL, NULL, + "nopl", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ -- cgit v1.2.3 From f1c5d30e1d79bbfb60eaf189db862d3cb2bcac92 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Aug 2008 17:50:33 -0700 Subject: x86: use X86_FEATURE_NOPL in alternatives Use X86_FEATURE_NOPL to determine if it is safe to use P6 NOPs in alternatives. Also, replace table and loop with simple if statement. Signed-off-by: H. Peter Anvin --- arch/x86/kernel/alternative.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 2763cb37b55..65a0c1b4869 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = { extern char __vsyscall_0; const unsigned char *const *find_nop_table(void) { - return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || - boot_cpu_data.x86 < 6 ? k8_nops : p6_nops; + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_has(X86_FEATURE_NOPL)) + return p6_nops; + else + return k8_nops; } #else /* CONFIG_X86_64 */ -static const struct nop { - int cpuid; - const unsigned char *const *noptable; -} noptypes[] = { - { X86_FEATURE_K8, k8_nops }, - { X86_FEATURE_K7, k7_nops }, - { X86_FEATURE_P4, p6_nops }, - { X86_FEATURE_P3, p6_nops }, - { -1, NULL } -}; - const unsigned char *const *find_nop_table(void) { - const unsigned char *const *noptable = intel_nops; - int i; - - for (i = 0; noptypes[i].cpuid >= 0; i++) { - if (boot_cpu_has(noptypes[i].cpuid)) { - noptable = noptypes[i].noptable; - break; - } - } - return noptable; + if (boot_cpu_has(X86_FEATURE_K8)) + return k8_nops; + else if (boot_cpu_has(X86_FEATURE_K7)) + return k7_nops; + else if (boot_cpu_has(X86_FEATURE_NOPL)) + return p6_nops; + else + return intel_nops; } #endif /* CONFIG_X86_64 */ -- cgit v1.2.3 From 20211e4d344729f4d4c93da37a590fc1c3a1fd9b Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Mon, 18 Aug 2008 21:25:38 +0200 Subject: x86: Coding style fixes to arch/x86/oprofile/op_model_p4.c A coding style patch to arch/x86/oprofile/op_model_p4.c that removes 87 errors and 4 warnings. Before: total: 89 errors, 13 warnings, 722 lines checked After: total: 2 errors, 9 warnings, 721 lines checked Compile tested, binary verified as follow: paolo@paolo-desktop:~/linux.trees.git$ size /tmp/op_model_p4.o.* text data bss dec hex filename 2691 968 32 3691 e6b /tmp/op_model_p4.o.after 2691 968 32 3691 e6b /tmp/op_model_p4.o.before paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/op_model_p4.o.* 8c1c9823bab33333e1f7f76574e62561 /tmp/op_model_p4.o.after 8c1c9823bab33333e1f7f76574e62561 /tmp/op_model_p4.o.before Signed-off-by: Paolo Ciarrocchi Cc: robert.richter@amd.com Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_p4.c | 175 ++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 88 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c index 56b4757a1f4..43ac5af338d 100644 --- a/arch/x86/oprofile/op_model_p4.c +++ b/arch/x86/oprofile/op_model_p4.c @@ -10,11 +10,12 @@ #include #include +#include +#include #include -#include #include #include -#include + #include "op_x86_model.h" #include "op_counter.h" @@ -40,7 +41,7 @@ static unsigned int num_controls = NUM_CONTROLS_NON_HT; static inline void setup_num_counters(void) { #ifdef CONFIG_SMP - if (smp_num_siblings == 2){ + if (smp_num_siblings == 2) { num_counters = NUM_COUNTERS_HT2; num_controls = NUM_CONTROLS_HT2; } @@ -86,7 +87,7 @@ struct p4_event_binding { #define CTR_FLAME_2 (1 << 6) #define CTR_IQ_5 (1 << 7) -static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { +static struct p4_counter_binding p4_counters[NUM_COUNTERS_NON_HT] = { { CTR_BPU_0, MSR_P4_BPU_PERFCTR0, MSR_P4_BPU_CCCR0 }, { CTR_MS_0, MSR_P4_MS_PERFCTR0, MSR_P4_MS_CCCR0 }, { CTR_FLAME_0, MSR_P4_FLAME_PERFCTR0, MSR_P4_FLAME_CCCR0 }, @@ -97,32 +98,32 @@ static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { { CTR_IQ_5, MSR_P4_IQ_PERFCTR5, MSR_P4_IQ_CCCR5 } }; -#define NUM_UNUSED_CCCRS NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT +#define NUM_UNUSED_CCCRS (NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT) /* p4 event codes in libop/op_event.h are indices into this table. */ static struct p4_event_binding p4_events[NUM_EVENTS] = { - + { /* BRANCH_RETIRED */ - 0x05, 0x06, + 0x05, 0x06, { {CTR_IQ_4, MSR_P4_CRU_ESCR2}, {CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, - + { /* MISPRED_BRANCH_RETIRED */ - 0x04, 0x03, + 0x04, 0x03, { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, - + { /* TC_DELIVER_MODE */ 0x01, 0x01, - { { CTR_MS_0, MSR_P4_TC_ESCR0}, + { { CTR_MS_0, MSR_P4_TC_ESCR0}, { CTR_MS_2, MSR_P4_TC_ESCR1} } }, - + { /* BPU_FETCH_REQUEST */ - 0x00, 0x03, + 0x00, 0x03, { { CTR_BPU_0, MSR_P4_BPU_ESCR0}, { CTR_BPU_2, MSR_P4_BPU_ESCR1} } }, @@ -146,7 +147,7 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* LOAD_PORT_REPLAY */ - 0x02, 0x04, + 0x02, 0x04, { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } }, @@ -170,43 +171,43 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* BSQ_CACHE_REFERENCE */ - 0x07, 0x0c, + 0x07, 0x0c, { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, { CTR_BPU_2, MSR_P4_BSU_ESCR1} } }, { /* IOQ_ALLOCATION */ - 0x06, 0x03, + 0x06, 0x03, { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { 0, 0 } } }, { /* IOQ_ACTIVE_ENTRIES */ - 0x06, 0x1a, + 0x06, 0x1a, { { CTR_BPU_2, MSR_P4_FSB_ESCR1}, { 0, 0 } } }, { /* FSB_DATA_ACTIVITY */ - 0x06, 0x17, + 0x06, 0x17, { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { CTR_BPU_2, MSR_P4_FSB_ESCR1} } }, { /* BSQ_ALLOCATION */ - 0x07, 0x05, + 0x07, 0x05, { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, { 0, 0 } } }, { /* BSQ_ACTIVE_ENTRIES */ 0x07, 0x06, - { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, + { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, { 0, 0 } } }, { /* X87_ASSIST */ - 0x05, 0x03, + 0x05, 0x03, { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, { CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, @@ -216,21 +217,21 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* PACKED_SP_UOP */ - 0x01, 0x08, + 0x01, 0x08, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* PACKED_DP_UOP */ - 0x01, 0x0c, + 0x01, 0x0c, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, { /* SCALAR_SP_UOP */ - 0x01, 0x0a, + 0x01, 0x0a, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, @@ -242,31 +243,31 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* 64BIT_MMX_UOP */ - 0x01, 0x02, + 0x01, 0x02, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* 128BIT_MMX_UOP */ - 0x01, 0x1a, + 0x01, 0x1a, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, { /* X87_FP_UOP */ - 0x01, 0x04, + 0x01, 0x04, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* X87_SIMD_MOVES_UOP */ - 0x01, 0x2e, + 0x01, 0x2e, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* MACHINE_CLEAR */ - 0x05, 0x02, + 0x05, 0x02, { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, { CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, @@ -276,9 +277,9 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { CTR_BPU_2, MSR_P4_FSB_ESCR1} } }, - + { /* TC_MS_XFER */ - 0x00, 0x05, + 0x00, 0x05, { { CTR_MS_0, MSR_P4_MS_ESCR0}, { CTR_MS_2, MSR_P4_MS_ESCR1} } }, @@ -308,7 +309,7 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* INSTR_RETIRED */ - 0x04, 0x02, + 0x04, 0x02, { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, @@ -319,14 +320,14 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, - { /* UOP_TYPE */ - 0x02, 0x02, + { /* UOP_TYPE */ + 0x02, 0x02, { { CTR_IQ_4, MSR_P4_RAT_ESCR0}, { CTR_IQ_5, MSR_P4_RAT_ESCR1} } }, { /* RETIRED_MISPRED_BRANCH_TYPE */ - 0x02, 0x05, + 0x02, 0x05, { { CTR_MS_0, MSR_P4_TBPU_ESCR0}, { CTR_MS_2, MSR_P4_TBPU_ESCR1} } }, @@ -349,8 +350,8 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1)) #define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3f) << 25)) #define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9)) -#define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) -#define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) +#define ESCR_READ(escr, high, ev, i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high)); } while (0) +#define ESCR_WRITE(escr, high, ev, i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high)); } while (0) #define CCCR_RESERVED_BITS 0x38030FFF #define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS) @@ -360,15 +361,15 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1<<27)) #define CCCR_SET_ENABLE(cccr) ((cccr) |= (1<<12)) #define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1<<12)) -#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) -#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) +#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high)); } while (0) +#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high)); } while (0) #define CCCR_OVF_P(cccr) ((cccr) & (1U<<31)) #define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31))) -#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0) -#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0) -#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0) -#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0) +#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0) +#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0) +#define CTR_READ(l, h, i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h)); } while (0) +#define CTR_WRITE(l, i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1); } while (0) #define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000)) @@ -380,7 +381,7 @@ static unsigned int get_stagger(void) #ifdef CONFIG_SMP int cpu = smp_processor_id(); return (cpu != first_cpu(per_cpu(cpu_sibling_map, cpu))); -#endif +#endif return 0; } @@ -395,25 +396,23 @@ static unsigned long reset_value[NUM_COUNTERS_NON_HT]; static void p4_fill_in_addresses(struct op_msrs * const msrs) { - unsigned int i; + unsigned int i; unsigned int addr, cccraddr, stag; setup_num_counters(); stag = get_stagger(); /* initialize some registers */ - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < num_counters; ++i) msrs->counters[i].addr = 0; - } - for (i = 0; i < num_controls; ++i) { + for (i = 0; i < num_controls; ++i) msrs->controls[i].addr = 0; - } - + /* the counter & cccr registers we pay attention to */ for (i = 0; i < num_counters; ++i) { addr = p4_counters[VIRT_CTR(stag, i)].counter_address; cccraddr = p4_counters[VIRT_CTR(stag, i)].cccr_address; - if (reserve_perfctr_nmi(addr)){ + if (reserve_perfctr_nmi(addr)) { msrs->counters[i].addr = addr; msrs->controls[i].addr = cccraddr; } @@ -447,22 +446,22 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs) if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } - + for (addr = MSR_P4_MS_ESCR0 + stag; - addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { + addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } - + for (addr = MSR_P4_IX_ESCR0 + stag; - addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { + addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } /* there are 2 remaining non-contiguously located ESCRs */ - if (num_counters == NUM_COUNTERS_NON_HT) { + if (num_counters == NUM_COUNTERS_NON_HT) { /* standard non-HT CPUs handle both remaining ESCRs*/ if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR5)) msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; @@ -498,20 +497,20 @@ static void pmc_setup_one_p4_counter(unsigned int ctr) unsigned int stag; stag = get_stagger(); - + /* convert from counter *number* to counter *bit* */ counter_bit = 1 << VIRT_CTR(stag, ctr); - + /* find our event binding structure. */ if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) { - printk(KERN_ERR - "oprofile: P4 event code 0x%lx out of range\n", + printk(KERN_ERR + "oprofile: P4 event code 0x%lx out of range\n", counter_config[ctr].event); return; } - + ev = &(p4_events[counter_config[ctr].event - 1]); - + for (i = 0; i < maxbind; i++) { if (ev->bindings[i].virt_counter & counter_bit) { @@ -526,25 +525,24 @@ static void pmc_setup_one_p4_counter(unsigned int ctr) ESCR_SET_OS_1(escr, counter_config[ctr].kernel); } ESCR_SET_EVENT_SELECT(escr, ev->event_select); - ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); + ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); ESCR_WRITE(escr, high, ev, i); - + /* modify CCCR */ CCCR_READ(cccr, high, VIRT_CTR(stag, ctr)); CCCR_CLEAR(cccr); CCCR_SET_REQUIRED_BITS(cccr); CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); - if (stag == 0) { + if (stag == 0) CCCR_SET_PMI_OVF_0(cccr); - } else { + else CCCR_SET_PMI_OVF_1(cccr); - } CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr)); return; } } - printk(KERN_ERR + printk(KERN_ERR "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n", counter_config[ctr].event, stag, ctr); } @@ -559,14 +557,14 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) stag = get_stagger(); rdmsr(MSR_IA32_MISC_ENABLE, low, high); - if (! MISC_PMC_ENABLED_P(low)) { + if (!MISC_PMC_ENABLED_P(low)) { printk(KERN_ERR "oprofile: P4 PMC not available\n"); return; } /* clear the cccrs we will use */ for (i = 0 ; i < num_counters ; i++) { - if (unlikely(!CTRL_IS_RESERVED(msrs,i))) + if (unlikely(!CTRL_IS_RESERVED(msrs, i))) continue; rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); CCCR_CLEAR(low); @@ -576,14 +574,14 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) /* clear all escrs (including those outside our concern) */ for (i = num_counters; i < num_controls; i++) { - if (unlikely(!CTRL_IS_RESERVED(msrs,i))) + if (unlikely(!CTRL_IS_RESERVED(msrs, i))) continue; wrmsr(msrs->controls[i].addr, 0, 0); } /* setup all counters */ for (i = 0 ; i < num_counters ; ++i) { - if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs,i))) { + if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs, i))) { reset_value[i] = counter_config[i].count; pmc_setup_one_p4_counter(i); CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i)); @@ -603,11 +601,11 @@ static int p4_check_ctrs(struct pt_regs * const regs, stag = get_stagger(); for (i = 0; i < num_counters; ++i) { - - if (!reset_value[i]) + + if (!reset_value[i]) continue; - /* + /* * there is some eccentricity in the hardware which * requires that we perform 2 extra corrections: * @@ -616,24 +614,24 @@ static int p4_check_ctrs(struct pt_regs * const regs, * * - write the counter back twice to ensure it gets * updated properly. - * + * * the former seems to be related to extra NMIs happening * during the current NMI; the latter is reported as errata * N15 in intel doc 249199-029, pentium 4 specification * update, though their suggested work-around does not * appear to solve the problem. */ - + real = VIRT_CTR(stag, i); CCCR_READ(low, high, real); - CTR_READ(ctr, high, real); + CTR_READ(ctr, high, real); if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) { oprofile_add_sample(regs, i); - CTR_WRITE(reset_value[i], real); + CTR_WRITE(reset_value[i], real); CCCR_CLEAR_OVF(low); CCCR_WRITE(low, high, real); - CTR_WRITE(reset_value[i], real); + CTR_WRITE(reset_value[i], real); } } @@ -683,15 +681,16 @@ static void p4_shutdown(struct op_msrs const * const msrs) int i; for (i = 0 ; i < num_counters ; ++i) { - if (CTR_IS_RESERVED(msrs,i)) + if (CTR_IS_RESERVED(msrs, i)) release_perfctr_nmi(msrs->counters[i].addr); } - /* some of the control registers are specially reserved in + /* + * some of the control registers are specially reserved in * conjunction with the counter registers (hence the starting offset). * This saves a few bits. */ for (i = num_counters ; i < num_controls ; ++i) { - if (CTRL_IS_RESERVED(msrs,i)) + if (CTRL_IS_RESERVED(msrs, i)) release_evntsel_nmi(msrs->controls[i].addr); } } -- cgit v1.2.3 From c171f465b7281f2d3b03e9145ec763d6a8bab176 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 20 Aug 2008 10:44:47 +0200 Subject: x86, cleanup: use X86_CR4_PGE in x86/power/hibernate_asm_32.S Signed-off-by: Uros Bizjak Signed-off-by: Ingo Molnar --- arch/x86/power/hibernate_asm_32.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/power/hibernate_asm_32.S b/arch/x86/power/hibernate_asm_32.S index 4fc7e872c85..d1e9b53f9d3 100644 --- a/arch/x86/power/hibernate_asm_32.S +++ b/arch/x86/power/hibernate_asm_32.S @@ -1,5 +1,3 @@ -.text - /* * This may not use any stack, nor any variable that is not "NoSave": * @@ -12,17 +10,18 @@ #include #include #include +#include - .text +.text ENTRY(swsusp_arch_suspend) - movl %esp, saved_context_esp movl %ebx, saved_context_ebx movl %ebp, saved_context_ebp movl %esi, saved_context_esi movl %edi, saved_context_edi - pushfl ; popl saved_context_eflags + pushfl + popl saved_context_eflags call swsusp_save ret @@ -59,7 +58,7 @@ done: movl mmu_cr4_features, %ecx jecxz 1f # cr4 Pentium and higher, skip if zero movl %ecx, %edx - andl $~(1<<7), %edx; # PGE + andl $~(X86_CR4_PGE), %edx movl %edx, %cr4; # turn off PGE 1: movl %cr3, %eax; # flush TLB @@ -74,7 +73,8 @@ done: movl saved_context_esi, %esi movl saved_context_edi, %edi - pushl saved_context_eflags ; popfl + pushl saved_context_eflags + popfl xorl %eax, %eax -- cgit v1.2.3 From 8343ef2437c599d30568e6b5a257a40bf2f4902b Mon Sep 17 00:00:00 2001 From: Dmitry Adamushko Date: Wed, 20 Aug 2008 00:16:13 +0200 Subject: x86-microcode: fix unbalanced use of get_cpu() Don't use get_cpu() at all. Resort to checking a boot-up CPU (#0) in microcode_{intel,amd}_module_init(). Signed-off-by: Dmitry Adamushko Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 10 ++++++---- arch/x86/kernel/microcode_intel.c | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 33b2a217a8c..a6e76ccf815 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -500,13 +500,15 @@ static struct microcode_ops microcode_amd_ops = { static int __init microcode_amd_module_init(void) { - struct cpuinfo_x86 *c = &cpu_data(get_cpu()); + struct cpuinfo_x86 *c = &cpu_data(0); equiv_cpu_table = NULL; - if (c->x86_vendor == X86_VENDOR_AMD) - return microcode_init(µcode_amd_ops, THIS_MODULE); - else + if (c->x86_vendor != X86_VENDOR_AMD) { + printk(KERN_ERR "microcode: CPU platform is not AMD-capable\n"); return -ENODEV; + } + + return microcode_init(µcode_amd_ops, THIS_MODULE); } static void __exit microcode_amd_module_exit(void) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index d2d9d74f4cb..6dd8907ff22 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -531,12 +531,14 @@ static struct microcode_ops microcode_intel_ops = { static int __init microcode_intel_module_init(void) { - struct cpuinfo_x86 *c = &cpu_data(get_cpu()); + struct cpuinfo_x86 *c = &cpu_data(0); - if (c->x86_vendor == X86_VENDOR_INTEL) - return microcode_init(µcode_intel_ops, THIS_MODULE); - else + if (c->x86_vendor != X86_VENDOR_INTEL) { + printk(KERN_ERR "microcode: CPU platform is not Intel-capable\n"); return -ENODEV; + } + + return microcode_init(µcode_intel_ops, THIS_MODULE); } static void __exit microcode_intel_module_exit(void) -- cgit v1.2.3 From d45de40934897c6ee5b05141f7895bbb28512395 Mon Sep 17 00:00:00 2001 From: Dmitry Adamushko Date: Wed, 20 Aug 2008 00:22:26 +0200 Subject: x86-microcode: generic interface refactoring This is the 1st patch in the series. Here the aim was to avoid any significant changes, logically-wise. So it's mainly about generic interface refactoring: e.g. make microcode_{intel,amd}.c more about arch-specific details and less about policies like make-sure-we-run-on-a-target-cpu (no more set_cpus_allowed_ptr() here) and generic synchronization (no more microcode_mutex here). All in all, more line have been deleted than added. 4 files changed, 145 insertions(+), 198 deletions(-) Signed-off-by: Dmitry Adamushko Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 155 +++++++++++++++++++++++++------------- arch/x86/kernel/microcode_amd.c | 77 +++---------------- arch/x86/kernel/microcode_intel.c | 91 ++++------------------ 3 files changed, 129 insertions(+), 194 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index ad136ad99cb..b2f84ce5eed 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -71,7 +71,7 @@ * Thanks to Stuart Swales for pointing out this bug. */ -/*#define DEBUG pr_debug */ +/* #define DEBUG pr_debug */ #include #include #include @@ -104,8 +104,7 @@ MODULE_LICENSE("GPL"); struct microcode_ops *microcode_ops; /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -DEFINE_MUTEX(microcode_mutex); -EXPORT_SYMBOL_GPL(microcode_mutex); +static DEFINE_MUTEX(microcode_mutex); struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; EXPORT_SYMBOL_GPL(ucode_cpu_info); @@ -234,22 +233,6 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); struct platform_device *microcode_pdev; EXPORT_SYMBOL_GPL(microcode_pdev); -static void microcode_init_cpu(int cpu, int resume) -{ - cpumask_t old; - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - old = current->cpus_allowed; - - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - mutex_lock(µcode_mutex); - microcode_ops->collect_cpu_info(cpu); - if (uci->valid && system_state == SYSTEM_RUNNING && !resume) - microcode_ops->cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); - set_cpus_allowed_ptr(current, &old); -} - static ssize_t reload_store(struct sys_device *dev, struct sysdev_attribute *attr, const char *buf, size_t sz) @@ -266,14 +249,15 @@ static ssize_t reload_store(struct sys_device *dev, cpumask_t old = current->cpus_allowed; get_online_cpus(); - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - - mutex_lock(µcode_mutex); - if (uci->valid) - err = microcode_ops->cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); + if (cpu_online(cpu)) { + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); + mutex_lock(µcode_mutex); + if (uci->valid) + err = microcode_ops->cpu_request_microcode(cpu); + mutex_unlock(µcode_mutex); + set_cpus_allowed_ptr(current, &old); + } put_online_cpus(); - set_cpus_allowed_ptr(current, &old); } if (err) return err; @@ -285,7 +269,7 @@ static ssize_t version_show(struct sys_device *dev, { struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - return sprintf(buf, "0x%x\n", uci->rev); + return sprintf(buf, "0x%x\n", uci->cpu_sig.rev); } static ssize_t pf_show(struct sys_device *dev, @@ -293,7 +277,7 @@ static ssize_t pf_show(struct sys_device *dev, { struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - return sprintf(buf, "0x%x\n", uci->pf); + return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); } static SYSDEV_ATTR(reload, 0200, NULL, reload_store); @@ -312,7 +296,85 @@ static struct attribute_group mc_attr_group = { .name = "microcode", }; -static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) +static void microcode_fini_cpu(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + mutex_lock(µcode_mutex); + microcode_ops->microcode_fini_cpu(cpu); + uci->valid = 0; + mutex_unlock(µcode_mutex); +} + +static void collect_cpu_info(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + memset(uci, 0, sizeof(*uci)); + if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig)) + uci->valid = 1; +} + +static void microcode_resume_cpu(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct cpu_signature nsig; + + pr_debug("microcode: CPU%d resumed\n", cpu); + + if (!uci->mc.valid_mc) + return; + + /* + * Let's verify that the 'cached' ucode does belong + * to this cpu (a bit of paranoia): + */ + if (microcode_ops->collect_cpu_info(cpu, &nsig)) { + microcode_fini_cpu(cpu); + return; + } + + if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { + microcode_fini_cpu(cpu); + /* Should we look for a new ucode here? */ + return; + } + + microcode_ops->apply_microcode(cpu); +} + +void microcode_update_cpu(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + /* We should bind the task to the CPU */ + BUG_ON(raw_smp_processor_id() != cpu); + + mutex_lock(µcode_mutex); + /* + * Check if the system resume is in progress (uci->valid != NULL), + * otherwise just request a firmware: + */ + if (uci->valid) { + microcode_resume_cpu(cpu); + } else { + collect_cpu_info(cpu); + if (uci->valid && system_state == SYSTEM_RUNNING) + microcode_ops->cpu_request_microcode(cpu); + } + mutex_unlock(µcode_mutex); +} + +static void microcode_init_cpu(int cpu) +{ + cpumask_t old = current->cpus_allowed; + + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); + microcode_update_cpu(cpu); + set_cpus_allowed_ptr(current, &old); +} + +static int mc_sysdev_add(struct sys_device *sys_dev) { int err, cpu = sys_dev->id; struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -327,16 +389,10 @@ static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) if (err) return err; - microcode_init_cpu(cpu, resume); - + microcode_init_cpu(cpu); return 0; } -static int mc_sysdev_add(struct sys_device *sys_dev) -{ - return __mc_sysdev_add(sys_dev, 0); -} - static int mc_sysdev_remove(struct sys_device *sys_dev) { int cpu = sys_dev->id; @@ -345,7 +401,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev) return 0; pr_debug("microcode: CPU%d removed\n", cpu); - microcode_ops->microcode_fini_cpu(cpu); + microcode_fini_cpu(cpu); sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); return 0; } @@ -376,33 +432,26 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) sys_dev = get_cpu_sysdev(cpu); switch (action) { - case CPU_UP_CANCELED_FROZEN: - /* The CPU refused to come up during a system resume */ - microcode_ops->microcode_fini_cpu(cpu); - break; case CPU_ONLINE: - case CPU_DOWN_FAILED: - mc_sysdev_add(sys_dev); - break; case CPU_ONLINE_FROZEN: - /* System-wide resume is in progress, try to apply microcode */ - if (microcode_ops->apply_microcode_check_cpu(cpu)) { - /* The application of microcode failed */ - microcode_ops->microcode_fini_cpu(cpu); - __mc_sysdev_add(sys_dev, 1); - break; - } + microcode_init_cpu(cpu); + case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: + pr_debug("microcode: CPU%d added\n", cpu); if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) printk(KERN_ERR "microcode: Failed to create the sysfs " "group for CPU%d\n", cpu); break; case CPU_DOWN_PREPARE: - mc_sysdev_remove(sys_dev); - break; case CPU_DOWN_PREPARE_FROZEN: /* Suspend is in progress, only remove the interface */ sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + pr_debug("microcode: CPU%d removed\n", cpu); + break; + case CPU_DEAD: + case CPU_UP_CANCELED_FROZEN: + /* The CPU refused to come up during a system resume */ + microcode_fini_cpu(cpu); break; } return NOTIFY_OK; diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index a6e76ccf815..4006e5e3adf 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -59,38 +59,28 @@ MODULE_LICENSE("GPL v2"); /* serialize access to the physical write */ static DEFINE_SPINLOCK(microcode_update_lock); -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -extern struct mutex (microcode_mutex); - struct equiv_cpu_entry *equiv_cpu_table; -extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; - -static void collect_cpu_info_amd(int cpu) +static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) { struct cpuinfo_x86 *c = &cpu_data(cpu); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu); - uci->rev = 0; - uci->pf = 0; - uci->mc.mc_amd = NULL; - uci->valid = 1; + memset(csig, 0, sizeof(*csig)); if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n", cpu); - uci->valid = 0; - return; + return -1; } asm volatile("movl %1, %%ecx; rdmsr" - : "=a" (uci->rev) + : "=a" (csig->rev) : "i" (0x0000008B) : "ecx"); printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n", - uci->rev); + csig->rev); + + return 0; } static int get_matching_microcode_amd(void *mc, int cpu) @@ -119,7 +109,7 @@ static int get_matching_microcode_amd(void *mc, int cpu) if (equiv_cpu_table == NULL) { printk(KERN_INFO "microcode: CPU%d microcode update with " "version 0x%x (current=0x%x)\n", - cpu, mc_header->patch_id, uci->rev); + cpu, mc_header->patch_id, uci->cpu_sig.rev); goto out; } @@ -185,12 +175,12 @@ static int get_matching_microcode_amd(void *mc, int cpu) pci_dev_put(sb_pci_dev); } - if (mc_header->patch_id <= uci->rev) + if (mc_header->patch_id <= uci->cpu_sig.rev) return 0; printk(KERN_INFO "microcode: CPU%d found a matching microcode " "update with version 0x%x (current=0x%x)\n", - cpu, mc_header->patch_id, uci->rev); + cpu, mc_header->patch_id, uci->cpu_sig.rev); out: new_mc = vmalloc(UCODE_MAX_SIZE); @@ -250,9 +240,9 @@ static void apply_microcode_amd(int cpu) printk(KERN_INFO "microcode: CPU%d updated from revision " "0x%x to 0x%x \n", - cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id); + cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id); - uci->rev = rev; + uci->cpu_sig.rev = rev; } #ifdef CONFIG_MICROCODE_OLD_INTERFACE @@ -437,61 +427,18 @@ static int cpu_request_microcode_amd(int cpu) return error; } -static int apply_microcode_check_cpu_amd(int cpu) -{ - struct cpuinfo_x86 *c = &cpu_data(cpu); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - unsigned int rev; - cpumask_t old; - int err = 0; - - /* Check if the microcode is available */ - if (!uci->mc.mc_amd) - return 0; - - old = current->cpus_allowed; - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - - /* Check if the microcode we have in memory matches the CPU */ - if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 16) - err = -EINVAL; - - if (!err) { - asm volatile("movl %1, %%ecx; rdmsr" - : "=a" (rev) - : "i" (0x0000008B) : "ecx"); - - if (uci->rev != rev) - err = -EINVAL; - } - - if (!err) - apply_microcode_amd(cpu); - else - printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" - " rev=0x%x\n", - cpu, uci->rev); - - set_cpus_allowed(current, old); - return err; -} - static void microcode_fini_cpu_amd(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - mutex_lock(µcode_mutex); - uci->valid = 0; vfree(uci->mc.mc_amd); uci->mc.mc_amd = NULL; - mutex_unlock(µcode_mutex); } static struct microcode_ops microcode_amd_ops = { .get_next_ucode = get_next_ucode_amd, .get_matching_microcode = get_matching_microcode_amd, .microcode_sanity_check = NULL, - .apply_microcode_check_cpu = apply_microcode_check_cpu_amd, .cpu_request_microcode = cpu_request_microcode_amd, .collect_cpu_info = collect_cpu_info_amd, .apply_microcode = apply_microcode_amd, diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 6dd8907ff22..c9b53202ba3 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -122,46 +122,37 @@ MODULE_LICENSE("GPL"); /* serialize access to the physical write to MSR 0x79 */ static DEFINE_SPINLOCK(microcode_update_lock); -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -extern struct mutex microcode_mutex; - -extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; - -static void collect_cpu_info(int cpu_num) +static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) { struct cpuinfo_x86 *c = &cpu_data(cpu_num); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; unsigned int val[2]; - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu_num); - uci->pf = uci->rev = 0; - uci->mc.mc_intel = NULL; - uci->valid = 1; + memset(csig, 0, sizeof(*csig)); if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || cpu_has(c, X86_FEATURE_IA64)) { printk(KERN_ERR "microcode: CPU%d not a capable Intel " "processor\n", cpu_num); - uci->valid = 0; - return; + return -1; } - uci->sig = cpuid_eax(0x00000001); + csig->sig = cpuid_eax(0x00000001); if ((c->x86_model >= 5) || (c->x86 > 6)) { /* get processor flags from MSR 0x17 */ rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); - uci->pf = 1 << ((val[1] >> 18) & 7); + csig->pf = 1 << ((val[1] >> 18) & 7); } wrmsr(MSR_IA32_UCODE_REV, 0, 0); /* see notes above for revision 1.07. Apparent chip bug */ sync_core(); /* get the current revision from MSR 0x8B */ - rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); + rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", - uci->sig, uci->pf, uci->rev); + csig->sig, csig->pf, csig->rev); + + return 0; } static inline int microcode_update_match(int cpu_num, @@ -169,8 +160,8 @@ static inline int microcode_update_match(int cpu_num, { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - if (!sigmatch(sig, uci->sig, pf, uci->pf) - || mc_header->rev <= uci->rev) + if (!sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf) + || mc_header->rev <= uci->cpu_sig.rev) return 0; return 1; } @@ -289,7 +280,7 @@ static int get_matching_microcode(void *mc, int cpu) find: pr_debug("microcode: CPU%d found a matching microcode update with" " version 0x%x (current=0x%x)\n", - cpu, mc_header->rev, uci->rev); + cpu, mc_header->rev, uci->cpu_sig.rev); new_mc = vmalloc(total_size); if (!new_mc) { printk(KERN_ERR "microcode: error! Can not allocate memory\n"); @@ -335,16 +326,16 @@ static void apply_microcode(int cpu) spin_unlock_irqrestore(µcode_update_lock, flags); if (val[1] != uci->mc.mc_intel->hdr.rev) { printk(KERN_ERR "microcode: CPU%d update from revision " - "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); + "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); return; } printk(KERN_INFO "microcode: CPU%d updated from revision " "0x%x to 0x%x, date = %04x-%02x-%02x \n", - cpu_num, uci->rev, val[1], + cpu_num, uci->cpu_sig.rev, val[1], uci->mc.mc_intel->hdr.date & 0xffff, uci->mc.mc_intel->hdr.date >> 24, (uci->mc.mc_intel->hdr.date >> 16) & 0xff); - uci->rev = val[1]; + uci->cpu_sig.rev = val[1]; } #ifdef CONFIG_MICROCODE_OLD_INTERFACE @@ -459,70 +450,18 @@ static int cpu_request_microcode(int cpu) return error; } -static int apply_microcode_check_cpu(int cpu) -{ - struct cpuinfo_x86 *c = &cpu_data(cpu); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - cpumask_t old; - unsigned int val[2]; - int err = 0; - - /* Check if the microcode is available */ - if (!uci->mc.mc_intel) - return 0; - - old = current->cpus_allowed; - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - - /* Check if the microcode we have in memory matches the CPU */ - if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || - cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001)) - err = -EINVAL; - - if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) { - /* get processor flags from MSR 0x17 */ - rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); - if (uci->pf != (1 << ((val[1] >> 18) & 7))) - err = -EINVAL; - } - - if (!err) { - wrmsr(MSR_IA32_UCODE_REV, 0, 0); - /* see notes above for revision 1.07. Apparent chip bug */ - sync_core(); - /* get the current revision from MSR 0x8B */ - rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); - if (uci->rev != val[1]) - err = -EINVAL; - } - - if (!err) - apply_microcode(cpu); - else - printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" - " sig=0x%x, pf=0x%x, rev=0x%x\n", - cpu, uci->sig, uci->pf, uci->rev); - - set_cpus_allowed_ptr(current, &old); - return err; -} - static void microcode_fini_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - mutex_lock(µcode_mutex); - uci->valid = 0; vfree(uci->mc.mc_intel); uci->mc.mc_intel = NULL; - mutex_unlock(µcode_mutex); } static struct microcode_ops microcode_intel_ops = { .get_next_ucode = get_next_ucode, .get_matching_microcode = get_matching_microcode, .microcode_sanity_check = microcode_sanity_check, - .apply_microcode_check_cpu = apply_microcode_check_cpu, .cpu_request_microcode = cpu_request_microcode, .collect_cpu_info = collect_cpu_info, .apply_microcode = apply_microcode, -- cgit v1.2.3 From b6edbb1e045a7116d5571544dae25c6c37c94a48 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 19 Aug 2008 13:04:19 -0700 Subject: x86_64: use save/loadsegment in ia32 compat Use savesegment and loadsegment consistently in ia32 compat code. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_aout.c | 11 +++++++---- arch/x86/ia32/ia32_signal.c | 21 ++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index a0e1dbe67dc..127ec3f0721 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -85,8 +85,10 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump) dump->regs.ax = regs->ax; dump->regs.ds = current->thread.ds; dump->regs.es = current->thread.es; - asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs; - asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; + savesegment(fs, fs); + dump->regs.fs = fs; + savesegment(gs, gs); + dump->regs.gs = gs; dump->regs.orig_ax = regs->orig_ax; dump->regs.ip = regs->ip; dump->regs.cs = regs->cs; @@ -430,8 +432,9 @@ beyond_if: current->mm->start_stack = (unsigned long)create_aout_tables((char __user *)bprm->p, bprm); /* start thread */ - asm volatile("movl %0,%%fs" :: "r" (0)); \ - asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); + loadsegment(fs, 0); + loadsegment(ds, __USER32_DS); + loadsegment(es, __USER32_DS); load_gs_index(0); (regs)->ip = ex.a_entry; (regs)->sp = current->mm->start_stack; diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 20af4c79579..f1a2ac777fa 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -206,7 +206,7 @@ struct rt_sigframe { unsigned int cur; \ unsigned short pre; \ err |= __get_user(pre, &sc->seg); \ - asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \ + savesegment(seg, cur); \ pre |= mask; \ if (pre != cur) loadsegment(seg, pre); } @@ -235,7 +235,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, */ err |= __get_user(gs, &sc->gs); gs |= 3; - asm("movl %%gs,%0" : "=r" (oldgs)); + savesegment(gs, oldgs); if (gs != oldgs) load_gs_index(gs); @@ -355,14 +355,13 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, { int tmp, err = 0; - tmp = 0; - __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); + savesegment(gs, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->gs); - __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); + savesegment(fs, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->fs); - __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp)); + savesegment(ds, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->ds); - __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp)); + savesegment(es, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->es); err |= __put_user((u32)regs->di, &sc->di); @@ -498,8 +497,8 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, regs->dx = 0; regs->cx = 0; - asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); - asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); + loadsegment(ds, __USER32_DS); + loadsegment(es, __USER32_DS); regs->cs = __USER32_CS; regs->ss = __USER32_DS; @@ -591,8 +590,8 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->dx = (unsigned long) &frame->info; regs->cx = (unsigned long) &frame->uc; - asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); - asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); + loadsegment(ds, __USER32_DS); + loadsegment(es, __USER32_DS); regs->cs = __USER32_CS; regs->ss = __USER32_DS; -- cgit v1.2.3 From 27990eac52dae87b909ef4f7e796fb6ec758bb94 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 19 Aug 2008 13:10:07 -0700 Subject: x86: another user of PTE_FLAGS_MASK Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/mm/dump_pagetables.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index a20d1fa64b4..e7277cbcfb4 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c @@ -148,8 +148,8 @@ static void note_page(struct seq_file *m, struct pg_state *st, * we have now. "break" is either changing perms, levels or * address space marker. */ - prot = pgprot_val(new_prot) & ~(PTE_PFN_MASK); - cur = pgprot_val(st->current_prot) & ~(PTE_PFN_MASK); + prot = pgprot_val(new_prot) & PTE_FLAGS_MASK; + cur = pgprot_val(st->current_prot) & PTE_FLAGS_MASK; if (!st->level) { /* First entry */ -- cgit v1.2.3 From 6e833587e11ed0dbf12e647127f2650e2f80b26d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 19 Aug 2008 13:16:17 -0700 Subject: xen: clean up domain mode predicates There are four operating modes Xen code may find itself running in: - native - hvm domain - pv dom0 - pv domU Clean up predicates for testing for these states to make them more consistent. Signed-off-by: Jeremy Fitzhardinge Cc: Xen-devel Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 53afa14eb31..b106e825d26 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -56,6 +56,9 @@ EXPORT_SYMBOL_GPL(hypercall_page); DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); +enum xen_domain_type xen_domain_type = XEN_NATIVE; +EXPORT_SYMBOL_GPL(xen_domain_type); + /* * Identity map, in addition to plain kernel map. This needs to be * large enough to allocate page table pages to allocate the rest. @@ -1613,6 +1616,8 @@ asmlinkage void __init xen_start_kernel(void) if (!xen_start_info) return; + xen_domain_type = XEN_PV_DOMAIN; + BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0); xen_setup_features(); @@ -1650,7 +1655,7 @@ asmlinkage void __init xen_start_kernel(void) /* Prevent unwanted bits from being set in PTEs. */ __supported_pte_mask &= ~_PAGE_GLOBAL; - if (!is_initial_xendomain()) + if (!xen_initial_domain()) __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); /* Don't do the full vcpu_info placement stuff until we have a @@ -1685,7 +1690,7 @@ asmlinkage void __init xen_start_kernel(void) boot_params.hdr.ramdisk_size = xen_start_info->mod_len; boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line); - if (!is_initial_xendomain()) { + if (!xen_initial_domain()) { add_preferred_console("xenboot", 0, NULL); add_preferred_console("tty", 0, NULL); add_preferred_console("hvc", 0, NULL); -- cgit v1.2.3 From 63d3a75d6f1fcf2f33e6abbe84e1f428c3586152 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 19 Aug 2008 13:19:36 -0700 Subject: x86/paravirt: add spin_lock_flags lock op It is useful for a pv_lock_ops backend to know whether interrupts are enabled or not in the context a spin_lock is being called. This allows it to enable interrupts while spinning, which could be particularly helpful when spinning becomes blocking. The default implementation just calls the normal spin_lock op, ignoring the flags. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/paravirt-spinlocks.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c index 38d7f7f1dbc..206359a8e43 100644 --- a/arch/x86/kernel/paravirt-spinlocks.c +++ b/arch/x86/kernel/paravirt-spinlocks.c @@ -7,12 +7,18 @@ #include +static void default_spin_lock_flags(struct raw_spinlock *lock, unsigned long flags) +{ + __raw_spin_lock(lock); +} + struct pv_lock_ops pv_lock_ops = { #ifdef CONFIG_SMP .spin_is_locked = __ticket_spin_is_locked, .spin_is_contended = __ticket_spin_is_contended, .spin_lock = __ticket_spin_lock, + .spin_lock_flags = default_spin_lock_flags, .spin_trylock = __ticket_spin_trylock, .spin_unlock = __ticket_spin_unlock, #endif -- cgit v1.2.3 From 11ad93e59d114f4b218873f1c93261be725d2e22 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 19 Aug 2008 13:32:51 -0700 Subject: xen: clarify locking used when pinning a pagetable. Add some comments explaining the locking and pinning algorithm when using split pte locks. Also implement a minor optimisation of not pinning the PTE when not using split pte locks. Signed-off-by: Jeremy Fitzhardinge Cc: Xen-devel Signed-off-by: Ingo Molnar --- arch/x86/xen/mmu.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index aa37469da69..d3752b6ce6e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -590,8 +590,6 @@ static int pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), pmdidx_limit = 0; #endif - flush |= (*func)(virt_to_page(pgd), PT_PGD); - for (pgdidx = 0; pgdidx <= pgdidx_limit; pgdidx++) { pud_t *pud; @@ -637,7 +635,11 @@ static int pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), } } } + out: + /* Do the top level last, so that the callbacks can use it as + a cue to do final things like tlb flushes. */ + flush |= (*func)(virt_to_page(pgd), PT_PGD); return flush; } @@ -691,6 +693,26 @@ static int pin_page(struct page *page, enum pt_level level) flush = 0; + /* + * We need to hold the pagetable lock between the time + * we make the pagetable RO and when we actually pin + * it. If we don't, then other users may come in and + * attempt to update the pagetable by writing it, + * which will fail because the memory is RO but not + * pinned, so Xen won't do the trap'n'emulate. + * + * If we're using split pte locks, we can't hold the + * entire pagetable's worth of locks during the + * traverse, because we may wrap the preempt count (8 + * bits). The solution is to mark RO and pin each PTE + * page while holding the lock. This means the number + * of locks we end up holding is never more than a + * batch size (~32 entries, at present). + * + * If we're not using split pte locks, we needn't pin + * the PTE pages independently, because we're + * protected by the overall pagetable lock. + */ ptl = NULL; if (level == PT_PTE) ptl = lock_pte(page); @@ -699,10 +721,9 @@ static int pin_page(struct page *page, enum pt_level level) pfn_pte(pfn, PAGE_KERNEL_RO), level == PT_PGD ? UVMF_TLB_FLUSH : 0); - if (level == PT_PTE) + if (ptl) { xen_do_pin(MMUEXT_PIN_L1_TABLE, pfn); - if (ptl) { /* Queue a deferred unlock for when this batch is completed. */ xen_mc_callback(do_unlock, ptl); @@ -796,10 +817,18 @@ static int unpin_page(struct page *page, enum pt_level level) spinlock_t *ptl = NULL; struct multicall_space mcs; + /* + * Do the converse to pin_page. If we're using split + * pte locks, we must be holding the lock for while + * the pte page is unpinned but still RO to prevent + * concurrent updates from seeing it in this + * partially-pinned state. + */ if (level == PT_PTE) { ptl = lock_pte(page); - xen_do_pin(MMUEXT_UNPIN_TABLE, pfn); + if (ptl) + xen_do_pin(MMUEXT_UNPIN_TABLE, pfn); } mcs = __xen_mc_entry(0); @@ -837,7 +866,7 @@ static void xen_pgd_unpin(pgd_t *pgd) #ifdef CONFIG_X86_PAE /* Need to make sure unshared kernel PMD is unpinned */ - pin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); + unpin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); #endif pgd_walk(pgd, unpin_page, USER_LIMIT); -- cgit v1.2.3 From 7708ad64a24a674f7905aa7a5099a50f055debec Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 19 Aug 2008 13:34:22 -0700 Subject: xen: add xen_ prefixes to make tracing with ftrace easier It's easier to pattern match on Xen function if they all start with xen_. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/mmu.c | 66 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index d3752b6ce6e..d9a35a36309 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -229,14 +229,14 @@ void make_lowmem_page_readwrite(void *vaddr) } -static bool page_pinned(void *ptr) +static bool xen_page_pinned(void *ptr) { struct page *page = virt_to_page(ptr); return PagePinned(page); } -static void extend_mmu_update(const struct mmu_update *update) +static void xen_extend_mmu_update(const struct mmu_update *update) { struct multicall_space mcs; struct mmu_update *u; @@ -265,7 +265,7 @@ void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) /* ptr may be ioremapped for 64-bit pagetable setup */ u.ptr = arbitrary_virt_to_machine(ptr).maddr; u.val = pmd_val_ma(val); - extend_mmu_update(&u); + xen_extend_mmu_update(&u); xen_mc_issue(PARAVIRT_LAZY_MMU); @@ -276,7 +276,7 @@ void xen_set_pmd(pmd_t *ptr, pmd_t val) { /* If page is not pinned, we can just update the entry directly */ - if (!page_pinned(ptr)) { + if (!xen_page_pinned(ptr)) { *ptr = val; return; } @@ -334,7 +334,7 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr, u.ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD; u.val = pte_val_ma(pte); - extend_mmu_update(&u); + xen_extend_mmu_update(&u); xen_mc_issue(PARAVIRT_LAZY_MMU); } @@ -400,7 +400,7 @@ void xen_set_pud_hyper(pud_t *ptr, pud_t val) /* ptr may be ioremapped for 64-bit pagetable setup */ u.ptr = arbitrary_virt_to_machine(ptr).maddr; u.val = pud_val_ma(val); - extend_mmu_update(&u); + xen_extend_mmu_update(&u); xen_mc_issue(PARAVIRT_LAZY_MMU); @@ -411,7 +411,7 @@ void xen_set_pud(pud_t *ptr, pud_t val) { /* If page is not pinned, we can just update the entry directly */ - if (!page_pinned(ptr)) { + if (!xen_page_pinned(ptr)) { *ptr = val; return; } @@ -490,7 +490,7 @@ static void __xen_set_pgd_hyper(pgd_t *ptr, pgd_t val) u.ptr = virt_to_machine(ptr).maddr; u.val = pgd_val_ma(val); - extend_mmu_update(&u); + xen_extend_mmu_update(&u); } /* @@ -519,10 +519,10 @@ void xen_set_pgd(pgd_t *ptr, pgd_t val) /* If page is not pinned, we can just update the entry directly */ - if (!page_pinned(ptr)) { + if (!xen_page_pinned(ptr)) { *ptr = val; if (user_ptr) { - WARN_ON(page_pinned(user_ptr)); + WARN_ON(xen_page_pinned(user_ptr)); *user_ptr = val; } return; @@ -555,8 +555,8 @@ void xen_set_pgd(pgd_t *ptr, pgd_t val) * For 64-bit, we must skip the Xen hole in the middle of the address * space, just after the big x86-64 virtual hole. */ -static int pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), - unsigned long limit) +static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), + unsigned long limit) { int flush = 0; unsigned hole_low, hole_high; @@ -644,7 +644,9 @@ out: return flush; } -static spinlock_t *lock_pte(struct page *page) +/* If we're using split pte locks, then take the page's lock and + return a pointer to it. Otherwise return NULL. */ +static spinlock_t *xen_pte_lock(struct page *page) { spinlock_t *ptl = NULL; @@ -656,7 +658,7 @@ static spinlock_t *lock_pte(struct page *page) return ptl; } -static void do_unlock(void *v) +static void xen_pte_unlock(void *v) { spinlock_t *ptl = v; spin_unlock(ptl); @@ -674,7 +676,7 @@ static void xen_do_pin(unsigned level, unsigned long pfn) MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); } -static int pin_page(struct page *page, enum pt_level level) +static int xen_pin_page(struct page *page, enum pt_level level) { unsigned pgfl = TestSetPagePinned(page); int flush; @@ -715,7 +717,7 @@ static int pin_page(struct page *page, enum pt_level level) */ ptl = NULL; if (level == PT_PTE) - ptl = lock_pte(page); + ptl = xen_pte_lock(page); MULTI_update_va_mapping(mcs.mc, (unsigned long)pt, pfn_pte(pfn, PAGE_KERNEL_RO), @@ -726,7 +728,7 @@ static int pin_page(struct page *page, enum pt_level level) /* Queue a deferred unlock for when this batch is completed. */ - xen_mc_callback(do_unlock, ptl); + xen_mc_callback(xen_pte_unlock, ptl); } } @@ -740,7 +742,7 @@ void xen_pgd_pin(pgd_t *pgd) { xen_mc_batch(); - if (pgd_walk(pgd, pin_page, USER_LIMIT)) { + if (xen_pgd_walk(pgd, xen_pin_page, USER_LIMIT)) { /* re-enable interrupts for kmap_flush_unused */ xen_mc_issue(0); kmap_flush_unused(); @@ -754,14 +756,14 @@ void xen_pgd_pin(pgd_t *pgd) xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(pgd))); if (user_pgd) { - pin_page(virt_to_page(user_pgd), PT_PGD); + xen_pin_page(virt_to_page(user_pgd), PT_PGD); xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(user_pgd))); } } #else /* CONFIG_X86_32 */ #ifdef CONFIG_X86_PAE /* Need to make sure unshared kernel PMD is pinnable */ - pin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); + xen_pin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); #endif xen_do_pin(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(pgd))); #endif /* CONFIG_X86_64 */ @@ -796,7 +798,7 @@ void xen_mm_pin_all(void) * that's before we have page structures to store the bits. So do all * the book-keeping now. */ -static __init int mark_pinned(struct page *page, enum pt_level level) +static __init int xen_mark_pinned(struct page *page, enum pt_level level) { SetPagePinned(page); return 0; @@ -804,10 +806,10 @@ static __init int mark_pinned(struct page *page, enum pt_level level) void __init xen_mark_init_mm_pinned(void) { - pgd_walk(init_mm.pgd, mark_pinned, FIXADDR_TOP); + xen_pgd_walk(init_mm.pgd, xen_mark_pinned, FIXADDR_TOP); } -static int unpin_page(struct page *page, enum pt_level level) +static int xen_unpin_page(struct page *page, enum pt_level level) { unsigned pgfl = TestClearPagePinned(page); @@ -825,7 +827,7 @@ static int unpin_page(struct page *page, enum pt_level level) * partially-pinned state. */ if (level == PT_PTE) { - ptl = lock_pte(page); + ptl = xen_pte_lock(page); if (ptl) xen_do_pin(MMUEXT_UNPIN_TABLE, pfn); @@ -839,7 +841,7 @@ static int unpin_page(struct page *page, enum pt_level level) if (ptl) { /* unlock when batch completed */ - xen_mc_callback(do_unlock, ptl); + xen_mc_callback(xen_pte_unlock, ptl); } } @@ -859,17 +861,17 @@ static void xen_pgd_unpin(pgd_t *pgd) if (user_pgd) { xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(user_pgd))); - unpin_page(virt_to_page(user_pgd), PT_PGD); + xen_unpin_page(virt_to_page(user_pgd), PT_PGD); } } #endif #ifdef CONFIG_X86_PAE /* Need to make sure unshared kernel PMD is unpinned */ - unpin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); + xen_unpin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); #endif - pgd_walk(pgd, unpin_page, USER_LIMIT); + xen_pgd_walk(pgd, xen_unpin_page, USER_LIMIT); xen_mc_issue(0); } @@ -936,7 +938,7 @@ static void drop_other_mm_ref(void *info) } } -static void drop_mm_ref(struct mm_struct *mm) +static void xen_drop_mm_ref(struct mm_struct *mm) { cpumask_t mask; unsigned cpu; @@ -966,7 +968,7 @@ static void drop_mm_ref(struct mm_struct *mm) smp_call_function_mask(mask, drop_other_mm_ref, mm, 1); } #else -static void drop_mm_ref(struct mm_struct *mm) +static void xen_drop_mm_ref(struct mm_struct *mm) { if (current->active_mm == mm) load_cr3(swapper_pg_dir); @@ -990,13 +992,13 @@ static void drop_mm_ref(struct mm_struct *mm) void xen_exit_mmap(struct mm_struct *mm) { get_cpu(); /* make sure we don't move around */ - drop_mm_ref(mm); + xen_drop_mm_ref(mm); put_cpu(); spin_lock(&mm->page_table_lock); /* pgd may not be pinned in the error exit path of execve */ - if (page_pinned(mm->pgd)) + if (xen_page_pinned(mm->pgd)) xen_pgd_unpin(mm->pgd); spin_unlock(&mm->page_table_lock); -- cgit v1.2.3 From 2d96ae6b0dc03a568398c1655fb8967f01f8e40a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 20 Aug 2008 16:43:02 -0700 Subject: arch/x86/pci/irq.c: attempt to clean up code layout Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/pci/irq.c | 67 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index fec0123b33a..d781cc4f725 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1041,35 +1041,44 @@ static void __init pcibios_fixup_irqs(void) if (io_apic_assign_pci_irqs) { int irq; - if (pin) { - /* - * interrupt pins are numbered starting - * from 1 - */ - pin--; - irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, - PCI_SLOT(dev->devfn), pin); - /* - * Busses behind bridges are typically not listed in the MP-table. - * In this case we have to look up the IRQ based on the parent bus, - * parent slot, and pin number. The SMP code detects such bridged - * busses itself so we should get into this branch reliably. - */ - if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ - struct pci_dev *bridge = dev->bus->self; - - pin = (pin + PCI_SLOT(dev->devfn)) % 4; - irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, - PCI_SLOT(bridge->devfn), pin); - if (irq >= 0) - dev_warn(&dev->dev, "using bridge %s INT %c to get IRQ %d\n", - pci_name(bridge), - 'A' + pin, irq); - } - if (irq >= 0) { - dev_info(&dev->dev, "PCI->APIC IRQ transform: INT %c -> IRQ %d\n", 'A' + pin, irq); - dev->irq = irq; - } + if (!pin) + continue; + + /* + * interrupt pins are numbered starting from 1 + */ + pin--; + irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, + PCI_SLOT(dev->devfn), pin); + /* + * Busses behind bridges are typically not listed in the + * MP-table. In this case we have to look up the IRQ + * based on the parent bus, parent slot, and pin number. + * The SMP code detects such bridged busses itself so we + * should get into this branch reliably. + */ + if (irq < 0 && dev->bus->parent) { + /* go back to the bridge */ + struct pci_dev *bridge = dev->bus->self; + int bus; + + pin = (pin + PCI_SLOT(dev->devfn)) % 4; + bus = bridge->bus->number; + irq = IO_APIC_get_PCI_irq_vector(bus, + PCI_SLOT(bridge->devfn), pin); + if (irq >= 0) + dev_warn(&dev->dev, + "using bridge %s INT %c to " + "get IRQ %d\n", + pci_name(bridge), + 'A' + pin, irq); + } + if (irq >= 0) { + dev_info(&dev->dev, + "PCI->APIC IRQ transform: INT %c " + "-> IRQ %d\n", + 'A' + pin, irq); + dev->irq = irq; } } #endif -- cgit v1.2.3 From e621bd18958ef5dbace3129ebe17a0a475e127d9 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Wed, 20 Aug 2008 16:43:03 -0700 Subject: i386: vmalloc size fix Booting kernel with vmalloc=[any size<=16m] will oops on my pc (i386/1G memory). BUG_ON in arch/x86/mm/init_32.c triggered: BUG_ON((unsigned long)high_memory > VMALLOC_START); It's due to the vm area hole. In include/asm-x86/pgtable_32.h: #define VMALLOC_OFFSET (8 * 1024 * 1024) #define VMALLOC_START (((unsigned long)high_memory + 2 * VMALLOC_OFFSET - 1) \ & ~(VMALLOC_OFFSET - 1)) There's several related point: 1. MAXMEM : (-__PAGE_OFFSET - __VMALLOC_RESERVE). The space after VMALLOC_END is included as well, I set it to (VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE) 2. VMALLOC_OFFSET is not considered in __VMALLOC_RESERVE fixed by adding VMALLOC_OFFSET to it. 3. VMALLOC_START : (((unsigned long)high_memory + 2 * VMALLOC_OFFSET - 1) & ~(VMALLOC_OFFSET - 1)) So it's not always 8M, bigger than 8M possible. I set it to ((unsigned long)high_memory + VMALLOC_OFFSET) 4. the VMALLOC_RESERVE is an unused macro, so remove it here. Signed-off-by: Dave Young Cc: akpm@linux-foundation.org Cc: hidave.darkstar@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton --- arch/x86/mm/pgtable_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index cab0abbd1eb..0951db9ee51 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c @@ -123,7 +123,8 @@ static int __init parse_vmalloc(char *arg) if (!arg) return -EINVAL; - __VMALLOC_RESERVE = memparse(arg, &arg); + /* Add VMALLOC_OFFSET to the parsed value due to vm area guard hole*/ + __VMALLOC_RESERVE = memparse(arg, &arg) + VMALLOC_OFFSET; return 0; } early_param("vmalloc", parse_vmalloc); -- cgit v1.2.3 From 11494547b1754c4f3bd7f707ab869e2adf54d52f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 21 Aug 2008 01:01:19 -0700 Subject: x86: fix apic version warning after following patch, commit 1b313f4a6d7bee7b2c034b3f1e203bc360a71cca Author: Cyrill Gorcunov Date: Mon Aug 18 20:45:57 2008 +0400 x86: apic - generic_processor_info - use physid_set instead of phys_cpu and physids_or - set phys_cpu_present_map bit AFTER check for allowed number of processors - add checking for APIC valid version in 64bit mode (mostly not needed but added for merging purpose) - add apic_version definition for 64bit mode which is used now we are getting warning for acpi path on 64 bit system. make the 64-bit side fill in apic_version[] as well. [ mingo@elte.hu: build fix ] Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 12e260e8fb2..d9770a56511 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -239,10 +239,8 @@ static void __cpuinit acpi_register_lapic(int id, u8 enabled) return; } -#ifdef CONFIG_X86_32 if (boot_cpu_physical_apicid != -1U) ver = apic_version[boot_cpu_physical_apicid]; -#endif generic_processor_info(id, ver); } @@ -762,10 +760,8 @@ static void __init acpi_register_lapic_address(unsigned long address) set_fixmap_nocache(FIX_APIC_BASE, address); if (boot_cpu_physical_apicid == -1U) { boot_cpu_physical_apicid = read_apic_id(); -#ifdef CONFIG_X86_32 apic_version[boot_cpu_physical_apicid] = GET_APIC_VERSION(apic_read(APIC_LVR)); -#endif } } -- cgit v1.2.3 From 4e1d112cac08049e764fe3c4f6d3ec92529f9f68 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Wed, 20 Aug 2008 16:43:07 -0700 Subject: arch/x86/kernel/apm_32.c: remove duplicated #include Removed duplicated include file in arch/x86/kernel/apm_32.c. Signed-off-by: Huang Weiyi Acked-by: Pavel Machek Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton --- arch/x86/kernel/apm_32.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 9ee24e6bc4b..b93d069aea7 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -228,7 +228,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 671eef85a3e885dff4ce210d8774ad50a91d5967 Mon Sep 17 00:00:00 2001 From: "Cihula, Joseph" Date: Wed, 20 Aug 2008 16:43:07 -0700 Subject: x86, e820: add support for AddressRangeUnusuable ACPI memory type Add support for the E820_UNUSABLE memory type, which is defined in Revision 3.0b (Oct. 10, 2006) of the ACPI Specification on p. 394 Table 14-1: AddressRangeUnusuable This range of address contains memory in which errors have been detected. This range must not be used by the OSPM. Signed-off-by: Joseph Cihula Signed-off-by: Shane Wang Signed-off-by: Gang Wei Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/kernel/e820.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 9af89078f7b..291e6cd9f9c 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -148,6 +148,9 @@ void __init e820_print_map(char *who) case E820_NVS: printk(KERN_CONT "(ACPI NVS)\n"); break; + case E820_UNUSABLE: + printk("(unusable)\n"); + break; default: printk(KERN_CONT "type %u\n", e820.map[i].type); break; @@ -1260,6 +1263,7 @@ static inline const char *e820_type_to_string(int e820_type) case E820_RAM: return "System RAM"; case E820_ACPI: return "ACPI Tables"; case E820_NVS: return "ACPI Non-volatile Storage"; + case E820_UNUSABLE: return "Unusable memory"; default: return "reserved"; } } -- cgit v1.2.3 From cacf890694a36124ceddce44ff4c7b02d372ce7c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 21 Aug 2008 13:46:33 +0200 Subject: Revert "introduce two APIs for page attribute" This reverts commit 1ac2f7d55b7ee1613c90631e87fea22ec06781e5. --- arch/x86/mm/pageattr.c | 58 +++++++------------------------------------------- 1 file changed, 8 insertions(+), 50 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 4adb33628de..5c06469a065 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -752,12 +752,12 @@ static inline int cache_attr(pgprot_t attr) (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); } -static int do_change_page_attr_set_clr(unsigned long addr, int numpages, +static int change_page_attr_set_clr(unsigned long addr, int numpages, pgprot_t mask_set, pgprot_t mask_clr, - int force_split, int *tlb_flush) + int force_split) { struct cpa_data cpa; - int ret, checkalias; + int ret, cache, checkalias; /* * Check, if we are requested to change a not supported @@ -795,22 +795,9 @@ static int do_change_page_attr_set_clr(unsigned long addr, int numpages, /* * Check whether we really changed something: */ - *tlb_flush = cpa.flushtlb; - cpa_fill_pool(NULL); - - return ret; -} - -static int change_page_attr_set_clr(unsigned long addr, int numpages, - pgprot_t mask_set, pgprot_t mask_clr, - int force_split) -{ - int cache, flush_cache = 0, ret; - - ret = do_change_page_attr_set_clr(addr, numpages, mask_set, mask_clr, - force_split, &flush_cache); - if (!flush_cache) + if (!cpa.flushtlb) goto out; + /* * No need to flush, when we did not set any of the caching * attributes: @@ -827,7 +814,10 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, cpa_flush_range(addr, numpages, cache); else cpa_flush_all(cache); + out: + cpa_fill_pool(NULL); + return ret; } @@ -865,30 +855,6 @@ int set_memory_uc(unsigned long addr, int numpages) } EXPORT_SYMBOL(set_memory_uc); -int set_memory_uc_noflush(unsigned long addr, int numpages) -{ - int flush; - /* - * for now UC MINUS. see comments in ioremap_nocache() - */ - if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, - _PAGE_CACHE_UC_MINUS, NULL)) - return -EINVAL; - /* - * for now UC MINUS. see comments in ioremap_nocache() - */ - return do_change_page_attr_set_clr(addr, numpages, - __pgprot(_PAGE_CACHE_UC_MINUS), - __pgprot(0), 0, &flush); -} -EXPORT_SYMBOL(set_memory_uc_noflush); - -void set_memory_flush_all(void) -{ - cpa_flush_all(1); -} -EXPORT_SYMBOL(set_memory_flush_all); - int _set_memory_wc(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, @@ -963,14 +929,6 @@ int set_pages_uc(struct page *page, int numpages) } EXPORT_SYMBOL(set_pages_uc); -int set_pages_uc_noflush(struct page *page, int numpages) -{ - unsigned long addr = (unsigned long)page_address(page); - - return set_memory_uc_noflush(addr, numpages); -} -EXPORT_SYMBOL(set_pages_uc_noflush); - int set_pages_wb(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); -- cgit v1.2.3 From d75586ad01e6c5a30e7337fb87d61e03556a1ecb Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 21 Aug 2008 10:46:06 +0800 Subject: x86, pageattr: introduce APIs to change pageattr of a page array Add array interface APIs of pageattr. page based cache flush is quite slow for a lot of pages. If pages are more than 1024 (4M), the patch will use a wbinvd(). We have a simple test here (run a 3d game - open arena), nearly all agp memory allocation are small (< 1M), so suppose this will not impact runtime performance. Signed-off-by: Dave Airlie Signed-off-by: Shaohua Li Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 216 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 166 insertions(+), 50 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 5c06469a065..041e81ef673 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -25,15 +25,19 @@ * The current flushing context - we pass it instead of 5 arguments: */ struct cpa_data { - unsigned long vaddr; + unsigned long *vaddr; pgprot_t mask_set; pgprot_t mask_clr; int numpages; - int flushtlb; + int flags; unsigned long pfn; unsigned force_split : 1; + int curpage; }; +#define CPA_FLUSHTLB 1 +#define CPA_ARRAY 2 + #ifdef CONFIG_PROC_FS static unsigned long direct_pages_count[PG_LEVEL_NUM]; @@ -184,6 +188,41 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache) } } +static void cpa_flush_array(unsigned long *start, int numpages, int cache) +{ + unsigned int i, level; + unsigned long *addr; + + BUG_ON(irqs_disabled()); + + on_each_cpu(__cpa_flush_range, NULL, 1); + + if (!cache) + return; + + /* 4M threshold */ + if (numpages >= 1024) { + if (boot_cpu_data.x86_model >= 4) + wbinvd(); + return; + } + /* + * We only need to flush on one CPU, + * clflush is a MESI-coherent instruction that + * will cause all other CPUs to flush the same + * cachelines: + */ + for (i = 0, addr = start; i < numpages; i++, addr++) { + pte_t *pte = lookup_address(*addr, &level); + + /* + * Only flush present addresses: + */ + if (pte && (pte_val(*pte) & _PAGE_PRESENT)) + clflush_cache_range((void *) *addr, PAGE_SIZE); + } +} + /* * Certain areas of memory on x86 require very specific protection flags, * for example the BIOS area or kernel text. Callers don't always get this @@ -392,7 +431,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, */ new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot)); __set_pmd_pte(kpte, address, new_pte); - cpa->flushtlb = 1; + cpa->flags |= CPA_FLUSHTLB; do_split = 0; } @@ -578,11 +617,16 @@ out_unlock: static int __change_page_attr(struct cpa_data *cpa, int primary) { - unsigned long address = cpa->vaddr; + unsigned long address; int do_split, err; unsigned int level; pte_t *kpte, old_pte; + if (cpa->flags & CPA_ARRAY) + address = cpa->vaddr[cpa->curpage]; + else + address = *cpa->vaddr; + repeat: kpte = lookup_address(address, &level); if (!kpte) @@ -594,8 +638,8 @@ repeat: return 0; printk(KERN_WARNING "CPA: called for zero pte. " "vaddr = %lx cpa->vaddr = %lx\n", address, - cpa->vaddr); WARN_ON(1); + *cpa->vaddr); return -EINVAL; } @@ -621,7 +665,7 @@ repeat: */ if (pte_val(old_pte) != pte_val(new_pte)) { set_pte_atomic(kpte, new_pte); - cpa->flushtlb = 1; + cpa->flags |= CPA_FLUSHTLB; } cpa->numpages = 1; return 0; @@ -645,7 +689,7 @@ repeat: */ err = split_large_page(kpte, address); if (!err) { - cpa->flushtlb = 1; + cpa->flags |= CPA_FLUSHTLB; goto repeat; } @@ -658,6 +702,7 @@ static int cpa_process_alias(struct cpa_data *cpa) { struct cpa_data alias_cpa; int ret = 0; + unsigned long temp_cpa_vaddr, vaddr; if (cpa->pfn >= max_pfn_mapped) return 0; @@ -670,16 +715,24 @@ static int cpa_process_alias(struct cpa_data *cpa) * No need to redo, when the primary call touched the direct * mapping already: */ - if (!(within(cpa->vaddr, PAGE_OFFSET, + if (cpa->flags & CPA_ARRAY) + vaddr = cpa->vaddr[cpa->curpage]; + else + vaddr = *cpa->vaddr; + + if (!(within(vaddr, PAGE_OFFSET, PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT)) #ifdef CONFIG_X86_64 - || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32), + || within(vaddr, PAGE_OFFSET + (1UL<<32), PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)) #endif )) { alias_cpa = *cpa; - alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); + temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); + alias_cpa.vaddr = &temp_cpa_vaddr; + alias_cpa.flags &= ~CPA_ARRAY; + ret = __change_page_attr_set_clr(&alias_cpa, 0); } @@ -691,7 +744,7 @@ static int cpa_process_alias(struct cpa_data *cpa) * No need to redo, when the primary call touched the high * mapping already: */ - if (within(cpa->vaddr, (unsigned long) _text, (unsigned long) _end)) + if (within(vaddr, (unsigned long) _text, (unsigned long) _end)) return 0; /* @@ -702,8 +755,9 @@ static int cpa_process_alias(struct cpa_data *cpa) return 0; alias_cpa = *cpa; - alias_cpa.vaddr = - (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; + temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; + alias_cpa.vaddr = &temp_cpa_vaddr; + alias_cpa.flags &= ~CPA_ARRAY; /* * The high mapping range is imprecise, so ignore the return value. @@ -723,6 +777,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) * preservation check. */ cpa->numpages = numpages; + /* for array changes, we can't use large page */ + if (cpa->flags & CPA_ARRAY) + cpa->numpages = 1; ret = __change_page_attr(cpa, checkalias); if (ret) @@ -741,7 +798,11 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) */ BUG_ON(cpa->numpages > numpages); numpages -= cpa->numpages; - cpa->vaddr += cpa->numpages * PAGE_SIZE; + if (cpa->flags & CPA_ARRAY) + cpa->curpage++; + else + *cpa->vaddr += cpa->numpages * PAGE_SIZE; + } return 0; } @@ -752,9 +813,9 @@ static inline int cache_attr(pgprot_t attr) (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); } -static int change_page_attr_set_clr(unsigned long addr, int numpages, +static int change_page_attr_set_clr(unsigned long *addr, int numpages, pgprot_t mask_set, pgprot_t mask_clr, - int force_split) + int force_split, int array) { struct cpa_data cpa; int ret, cache, checkalias; @@ -769,12 +830,22 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, return 0; /* Ensure we are PAGE_SIZE aligned */ - if (addr & ~PAGE_MASK) { - addr &= PAGE_MASK; - /* - * People should not be passing in unaligned addresses: - */ - WARN_ON_ONCE(1); + if (!array) { + if (*addr & ~PAGE_MASK) { + *addr &= PAGE_MASK; + /* + * People should not be passing in unaligned addresses: + */ + WARN_ON_ONCE(1); + } + } else { + int i; + for (i = 0; i < numpages; i++) { + if (addr[i] & ~PAGE_MASK) { + addr[i] &= PAGE_MASK; + WARN_ON_ONCE(1); + } + } } /* Must avoid aliasing mappings in the highmem code */ @@ -784,9 +855,13 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, cpa.numpages = numpages; cpa.mask_set = mask_set; cpa.mask_clr = mask_clr; - cpa.flushtlb = 0; + cpa.flags = 0; + cpa.curpage = 0; cpa.force_split = force_split; + if (array) + cpa.flags |= CPA_ARRAY; + /* No alias checking for _NX bit modifications */ checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; @@ -795,7 +870,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, /* * Check whether we really changed something: */ - if (!cpa.flushtlb) + if (!(cpa.flags & CPA_FLUSHTLB)) goto out; /* @@ -810,9 +885,12 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, * error case we fall back to cpa_flush_all (which uses * wbindv): */ - if (!ret && cpu_has_clflush) - cpa_flush_range(addr, numpages, cache); - else + if (!ret && cpu_has_clflush) { + if (cpa.flags & CPA_ARRAY) + cpa_flush_array(addr, numpages, cache); + else + cpa_flush_range(*addr, numpages, cache); + } else cpa_flush_all(cache); out: @@ -821,16 +899,18 @@ out: return ret; } -static inline int change_page_attr_set(unsigned long addr, int numpages, - pgprot_t mask) +static inline int change_page_attr_set(unsigned long *addr, int numpages, + pgprot_t mask, int array) { - return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0); + return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0, + array); } -static inline int change_page_attr_clear(unsigned long addr, int numpages, - pgprot_t mask) +static inline int change_page_attr_clear(unsigned long *addr, int numpages, + pgprot_t mask, int array) { - return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0); + return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0, + array); } int _set_memory_uc(unsigned long addr, int numpages) @@ -838,8 +918,8 @@ int _set_memory_uc(unsigned long addr, int numpages) /* * for now UC MINUS. see comments in ioremap_nocache() */ - return change_page_attr_set(addr, numpages, - __pgprot(_PAGE_CACHE_UC_MINUS)); + return change_page_attr_set(&addr, numpages, + __pgprot(_PAGE_CACHE_UC_MINUS), 0); } int set_memory_uc(unsigned long addr, int numpages) @@ -855,10 +935,31 @@ int set_memory_uc(unsigned long addr, int numpages) } EXPORT_SYMBOL(set_memory_uc); +int set_memory_array_uc(unsigned long *addr, int addrinarray) +{ + int i; + /* + * for now UC MINUS. see comments in ioremap_nocache() + */ + for (i = 0; i < addrinarray; i++) { + if (reserve_memtype(addr[i], addr[i] + PAGE_SIZE, + _PAGE_CACHE_UC_MINUS, NULL)) + goto out; + } + + return change_page_attr_set(addr, addrinarray, + __pgprot(_PAGE_CACHE_UC_MINUS), 1); +out: + while (--i >= 0) + free_memtype(addr[i], addr[i] + PAGE_SIZE); + return -EINVAL; +} +EXPORT_SYMBOL(set_memory_array_uc); + int _set_memory_wc(unsigned long addr, int numpages) { - return change_page_attr_set(addr, numpages, - __pgprot(_PAGE_CACHE_WC)); + return change_page_attr_set(&addr, numpages, + __pgprot(_PAGE_CACHE_WC), 0); } int set_memory_wc(unsigned long addr, int numpages) @@ -876,8 +977,8 @@ EXPORT_SYMBOL(set_memory_wc); int _set_memory_wb(unsigned long addr, int numpages) { - return change_page_attr_clear(addr, numpages, - __pgprot(_PAGE_CACHE_MASK)); + return change_page_attr_clear(&addr, numpages, + __pgprot(_PAGE_CACHE_MASK), 0); } int set_memory_wb(unsigned long addr, int numpages) @@ -888,37 +989,48 @@ int set_memory_wb(unsigned long addr, int numpages) } EXPORT_SYMBOL(set_memory_wb); +int set_memory_array_wb(unsigned long *addr, int addrinarray) +{ + int i; + for (i = 0; i < addrinarray; i++) + free_memtype(addr[i], addr[i] + PAGE_SIZE); + + return change_page_attr_clear(addr, addrinarray, + __pgprot(_PAGE_CACHE_MASK), 1); +} +EXPORT_SYMBOL(set_memory_array_wb); + int set_memory_x(unsigned long addr, int numpages) { - return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX)); + return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_NX), 0); } EXPORT_SYMBOL(set_memory_x); int set_memory_nx(unsigned long addr, int numpages) { - return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX)); + return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_NX), 0); } EXPORT_SYMBOL(set_memory_nx); int set_memory_ro(unsigned long addr, int numpages) { - return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); + return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_RW), 0); } int set_memory_rw(unsigned long addr, int numpages) { - return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); + return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_RW), 0); } int set_memory_np(unsigned long addr, int numpages) { - return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT)); + return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0); } int set_memory_4k(unsigned long addr, int numpages) { - return change_page_attr_set_clr(addr, numpages, __pgprot(0), - __pgprot(0), 1); + return change_page_attr_set_clr(&addr, numpages, __pgprot(0), + __pgprot(0), 1, 0); } int set_pages_uc(struct page *page, int numpages) @@ -971,20 +1083,24 @@ int set_pages_rw(struct page *page, int numpages) static int __set_pages_p(struct page *page, int numpages) { - struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), + unsigned long tempaddr = (unsigned long) page_address(page); + struct cpa_data cpa = { .vaddr = &tempaddr, .numpages = numpages, .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), - .mask_clr = __pgprot(0)}; + .mask_clr = __pgprot(0), + .flags = 0}; return __change_page_attr_set_clr(&cpa, 1); } static int __set_pages_np(struct page *page, int numpages) { - struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), + unsigned long tempaddr = (unsigned long) page_address(page); + struct cpa_data cpa = { .vaddr = &tempaddr, .numpages = numpages, .mask_set = __pgprot(0), - .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)}; + .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), + .flags = 0}; return __change_page_attr_set_clr(&cpa, 1); } -- cgit v1.2.3 From ab7e79243746e2a9c5f00243e60108189c44c9eb Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 21 Aug 2008 10:46:21 +0800 Subject: x86: fix pageattr-test We changed the interface of some pageattr, this patch makes pageattr-test compile. Signed-off-by: Dave Airlie Signed-off-by: Shaohua Li Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr-test.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c index 0dcd42eb94e..6ae1f28a7ff 100644 --- a/arch/x86/mm/pageattr-test.c +++ b/arch/x86/mm/pageattr-test.c @@ -118,6 +118,7 @@ static int pageattr_test(void) unsigned int level; int i, k; int err; + unsigned long test_addr; if (print) printk(KERN_INFO "CPA self-test:\n"); @@ -172,7 +173,8 @@ static int pageattr_test(void) continue; } - err = change_page_attr_set(addr[i], len[i], PAGE_TESTBIT); + test_addr = addr[i]; + err = change_page_attr_set(&test_addr, len[i], PAGE_TESTBIT, 0); if (err < 0) { printk(KERN_ERR "CPA %d failed %d\n", i, err); failed++; @@ -204,7 +206,8 @@ static int pageattr_test(void) failed++; continue; } - err = change_page_attr_clear(addr[i], len[i], PAGE_TESTBIT); + test_addr = addr[i]; + err = change_page_attr_clear(&test_addr, len[i], PAGE_TESTBIT, 0); if (err < 0) { printk(KERN_ERR "CPA reverting failed: %d\n", err); failed++; -- cgit v1.2.3 From 168d2f464ab9860f0d1e66cf1f9684973222f1c6 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 20 Aug 2008 17:02:18 -0700 Subject: xen: save previous spinlock when blocking A spinlock can be interrupted while spinning, so make sure we preserve the previous lock of interest if we're taking a lock from within an interrupt handler. We also need to deal with the case where the blocking path gets interrupted between testing to see if the lock is free and actually blocking. If we get interrupted there and end up in the state where the lock is free but the irq isn't pending, then we'll block indefinitely in the hypervisor. This fix is to make sure that any nested lock-takers will always leave the irq pending if there's any chance the outer lock became free. Signed-off-by: Jeremy Fitzhardinge Acked-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/xen/spinlock.c | 65 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 8dc4d31da67..4884bc603aa 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -47,25 +47,41 @@ static int xen_spin_trylock(struct raw_spinlock *lock) static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; static DEFINE_PER_CPU(struct xen_spinlock *, lock_spinners); -static inline void spinning_lock(struct xen_spinlock *xl) +/* + * Mark a cpu as interested in a lock. Returns the CPU's previous + * lock of interest, in case we got preempted by an interrupt. + */ +static inline struct xen_spinlock *spinning_lock(struct xen_spinlock *xl) { + struct xen_spinlock *prev; + + prev = __get_cpu_var(lock_spinners); __get_cpu_var(lock_spinners) = xl; + wmb(); /* set lock of interest before count */ + asm(LOCK_PREFIX " incw %0" : "+m" (xl->spinners) : : "memory"); + + return prev; } -static inline void unspinning_lock(struct xen_spinlock *xl) +/* + * Mark a cpu as no longer interested in a lock. Restores previous + * lock of interest (NULL for none). + */ +static inline void unspinning_lock(struct xen_spinlock *xl, struct xen_spinlock *prev) { asm(LOCK_PREFIX " decw %0" : "+m" (xl->spinners) : : "memory"); - wmb(); /* decrement count before clearing lock */ - __get_cpu_var(lock_spinners) = NULL; + wmb(); /* decrement count before restoring lock */ + __get_cpu_var(lock_spinners) = prev; } static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) { struct xen_spinlock *xl = (struct xen_spinlock *)lock; + struct xen_spinlock *prev; int irq = __get_cpu_var(lock_kicker_irq); int ret; @@ -74,23 +90,42 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) return 0; /* announce we're spinning */ - spinning_lock(xl); + prev = spinning_lock(xl); - /* clear pending */ - xen_clear_irq_pending(irq); + do { + /* clear pending */ + xen_clear_irq_pending(irq); + + /* check again make sure it didn't become free while + we weren't looking */ + ret = xen_spin_trylock(lock); + if (ret) { + /* + * If we interrupted another spinlock while it + * was blocking, make sure it doesn't block + * without rechecking the lock. + */ + if (prev != NULL) + xen_set_irq_pending(irq); + goto out; + } - /* check again make sure it didn't become free while - we weren't looking */ - ret = xen_spin_trylock(lock); - if (ret) - goto out; + /* + * Block until irq becomes pending. If we're + * interrupted at this point (after the trylock but + * before entering the block), then the nested lock + * handler guarantees that the irq will be left + * pending if there's any chance the lock became free; + * xen_poll_irq() returns immediately if the irq is + * pending. + */ + xen_poll_irq(irq); + } while (!xen_test_irq_pending(irq)); /* check for spurious wakeups */ - /* block until irq becomes pending */ - xen_poll_irq(irq); kstat_this_cpu.irqs[irq]++; out: - unspinning_lock(xl); + unspinning_lock(xl, prev); return ret; } -- cgit v1.2.3 From 994025caba3e6beade9bde84dd1b70d9d250f27b Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 20 Aug 2008 17:02:19 -0700 Subject: xen: add debugfs support Add support for exporting statistics on mmu updates, multicall batching and pv spinlocks into debugfs. The base path is xen/ and each subsystem adds its own directory: mmu, multicalls, spinlocks. In each directory, writing 1 to "zero_stats" will cause the corresponding stats to be zeroed the next time they're updated. Signed-off-by: Jeremy Fitzhardinge Acked-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/xen/Kconfig | 10 ++- arch/x86/xen/Makefile | 3 +- arch/x86/xen/debugfs.c | 123 ++++++++++++++++++++++++++++++++++ arch/x86/xen/debugfs.h | 10 +++ arch/x86/xen/mmu.c | 163 ++++++++++++++++++++++++++++++++++++++++++++- arch/x86/xen/multicalls.c | 115 +++++++++++++++++++++++++++++++- arch/x86/xen/spinlock.c | 165 +++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 580 insertions(+), 9 deletions(-) create mode 100644 arch/x86/xen/debugfs.c create mode 100644 arch/x86/xen/debugfs.h (limited to 'arch') diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index 3815e425f47..d3e68465ace 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig @@ -27,4 +27,12 @@ config XEN_MAX_DOMAIN_MEMORY config XEN_SAVE_RESTORE bool depends on PM - default y \ No newline at end of file + default y + +config XEN_DEBUG_FS + bool "Enable Xen debug and tuning parameters in debugfs" + depends on XEN && DEBUG_FS + default n + help + Enable statistics output and various tuning options in debugfs. + Enabling this option may incur a significant performance overhead. \ No newline at end of file diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 9ee745fa552..313947940a1 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -8,4 +8,5 @@ endif obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ time.o xen-asm_$(BITS).o grant-table.o suspend.o -obj-$(CONFIG_SMP) += smp.o spinlock.o +obj-$(CONFIG_SMP) += smp.o spinlock.o +obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o \ No newline at end of file diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c new file mode 100644 index 00000000000..b53225d2cac --- /dev/null +++ b/arch/x86/xen/debugfs.c @@ -0,0 +1,123 @@ +#include +#include +#include + +#include "debugfs.h" + +static struct dentry *d_xen_debug; + +struct dentry * __init xen_init_debugfs(void) +{ + if (!d_xen_debug) { + d_xen_debug = debugfs_create_dir("xen", NULL); + + if (!d_xen_debug) + pr_warning("Could not create 'xen' debugfs directory\n"); + } + + return d_xen_debug; +} + +struct array_data +{ + void *array; + unsigned elements; +}; + +static int u32_array_open(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return nonseekable_open(inode, file); +} + +static size_t format_array(char *buf, size_t bufsize, const char *fmt, + u32 *array, unsigned array_size) +{ + size_t ret = 0; + unsigned i; + + for(i = 0; i < array_size; i++) { + size_t len; + + len = snprintf(buf, bufsize, fmt, array[i]); + len++; /* ' ' or '\n' */ + ret += len; + + if (buf) { + buf += len; + bufsize -= len; + buf[-1] = (i == array_size-1) ? '\n' : ' '; + } + } + + ret++; /* \0 */ + if (buf) + *buf = '\0'; + + return ret; +} + +static char *format_array_alloc(const char *fmt, u32 *array, unsigned array_size) +{ + size_t len = format_array(NULL, 0, fmt, array, array_size); + char *ret; + + ret = kmalloc(len, GFP_KERNEL); + if (ret == NULL) + return NULL; + + format_array(ret, len, fmt, array, array_size); + return ret; +} + +static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len, + loff_t *ppos) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct array_data *data = inode->i_private; + size_t size; + + if (*ppos == 0) { + if (file->private_data) { + kfree(file->private_data); + file->private_data = NULL; + } + + file->private_data = format_array_alloc("%u", data->array, data->elements); + } + + size = 0; + if (file->private_data) + size = strlen(file->private_data); + + return simple_read_from_buffer(buf, len, ppos, file->private_data, size); +} + +static int xen_array_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + + return 0; +} + +static struct file_operations u32_array_fops = { + .owner = THIS_MODULE, + .open = u32_array_open, + .release= xen_array_release, + .read = u32_array_read, +}; + +struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode, + struct dentry *parent, + u32 *array, unsigned elements) +{ + struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL); + + if (data == NULL) + return NULL; + + data->array = array; + data->elements = elements; + + return debugfs_create_file(name, mode, parent, data, &u32_array_fops); +} diff --git a/arch/x86/xen/debugfs.h b/arch/x86/xen/debugfs.h new file mode 100644 index 00000000000..e2813208483 --- /dev/null +++ b/arch/x86/xen/debugfs.h @@ -0,0 +1,10 @@ +#ifndef _XEN_DEBUGFS_H +#define _XEN_DEBUGFS_H + +struct dentry * __init xen_init_debugfs(void); + +struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode, + struct dentry *parent, + u32 *array, unsigned elements); + +#endif /* _XEN_DEBUGFS_H */ diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index d9a35a36309..f5af913fd7b 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -40,6 +40,7 @@ */ #include #include +#include #include #include @@ -57,6 +58,61 @@ #include "multicalls.h" #include "mmu.h" +#include "debugfs.h" + +#define MMU_UPDATE_HISTO 30 + +#ifdef CONFIG_XEN_DEBUG_FS + +static struct { + u32 pgd_update; + u32 pgd_update_pinned; + u32 pgd_update_batched; + + u32 pud_update; + u32 pud_update_pinned; + u32 pud_update_batched; + + u32 pmd_update; + u32 pmd_update_pinned; + u32 pmd_update_batched; + + u32 pte_update; + u32 pte_update_pinned; + u32 pte_update_batched; + + u32 mmu_update; + u32 mmu_update_extended; + u32 mmu_update_histo[MMU_UPDATE_HISTO]; + + u32 prot_commit; + u32 prot_commit_batched; + + u32 set_pte_at; + u32 set_pte_at_batched; + u32 set_pte_at_pinned; + u32 set_pte_at_current; + u32 set_pte_at_kernel; +} mmu_stats; + +static u8 zero_stats; + +static inline void check_zero(void) +{ + if (unlikely(zero_stats)) { + memset(&mmu_stats, 0, sizeof(mmu_stats)); + zero_stats = 0; + } +} + +#define ADD_STATS(elem, val) \ + do { check_zero(); mmu_stats.elem += (val); } while(0) + +#else /* !CONFIG_XEN_DEBUG_FS */ + +#define ADD_STATS(elem, val) do { (void)(val); } while(0) + +#endif /* CONFIG_XEN_DEBUG_FS */ /* * Just beyond the highest usermode address. STACK_TOP_MAX has a @@ -243,11 +299,21 @@ static void xen_extend_mmu_update(const struct mmu_update *update) mcs = xen_mc_extend_args(__HYPERVISOR_mmu_update, sizeof(*u)); - if (mcs.mc != NULL) + if (mcs.mc != NULL) { + ADD_STATS(mmu_update_extended, 1); + ADD_STATS(mmu_update_histo[mcs.mc->args[1]], -1); + mcs.mc->args[1]++; - else { + + if (mcs.mc->args[1] < MMU_UPDATE_HISTO) + ADD_STATS(mmu_update_histo[mcs.mc->args[1]], 1); + else + ADD_STATS(mmu_update_histo[0], 1); + } else { + ADD_STATS(mmu_update, 1); mcs = __xen_mc_entry(sizeof(*u)); MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); + ADD_STATS(mmu_update_histo[1], 1); } u = mcs.args; @@ -267,6 +333,8 @@ void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) u.val = pmd_val_ma(val); xen_extend_mmu_update(&u); + ADD_STATS(pmd_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + xen_mc_issue(PARAVIRT_LAZY_MMU); preempt_enable(); @@ -274,6 +342,8 @@ void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) void xen_set_pmd(pmd_t *ptr, pmd_t val) { + ADD_STATS(pmd_update, 1); + /* If page is not pinned, we can just update the entry directly */ if (!xen_page_pinned(ptr)) { @@ -281,6 +351,8 @@ void xen_set_pmd(pmd_t *ptr, pmd_t val) return; } + ADD_STATS(pmd_update_pinned, 1); + xen_set_pmd_hyper(ptr, val); } @@ -300,12 +372,18 @@ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, if (mm == &init_mm) preempt_disable(); + ADD_STATS(set_pte_at, 1); +// ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep)); + ADD_STATS(set_pte_at_current, mm == current->mm); + ADD_STATS(set_pte_at_kernel, mm == &init_mm); + if (mm == current->mm || mm == &init_mm) { if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { struct multicall_space mcs; mcs = xen_mc_entry(0); MULTI_update_va_mapping(mcs.mc, addr, pteval, 0); + ADD_STATS(set_pte_at_batched, 1); xen_mc_issue(PARAVIRT_LAZY_MMU); goto out; } else @@ -336,6 +414,9 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr, u.val = pte_val_ma(pte); xen_extend_mmu_update(&u); + ADD_STATS(prot_commit, 1); + ADD_STATS(prot_commit_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + xen_mc_issue(PARAVIRT_LAZY_MMU); } @@ -402,6 +483,8 @@ void xen_set_pud_hyper(pud_t *ptr, pud_t val) u.val = pud_val_ma(val); xen_extend_mmu_update(&u); + ADD_STATS(pud_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + xen_mc_issue(PARAVIRT_LAZY_MMU); preempt_enable(); @@ -409,6 +492,8 @@ void xen_set_pud_hyper(pud_t *ptr, pud_t val) void xen_set_pud(pud_t *ptr, pud_t val) { + ADD_STATS(pud_update, 1); + /* If page is not pinned, we can just update the entry directly */ if (!xen_page_pinned(ptr)) { @@ -416,11 +501,17 @@ void xen_set_pud(pud_t *ptr, pud_t val) return; } + ADD_STATS(pud_update_pinned, 1); + xen_set_pud_hyper(ptr, val); } void xen_set_pte(pte_t *ptep, pte_t pte) { + ADD_STATS(pte_update, 1); +// ADD_STATS(pte_update_pinned, xen_page_pinned(ptep)); + ADD_STATS(pte_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + #ifdef CONFIG_X86_PAE ptep->pte_high = pte.pte_high; smp_wmb(); @@ -517,6 +608,8 @@ void xen_set_pgd(pgd_t *ptr, pgd_t val) { pgd_t *user_ptr = xen_get_user_pgd(ptr); + ADD_STATS(pgd_update, 1); + /* If page is not pinned, we can just update the entry directly */ if (!xen_page_pinned(ptr)) { @@ -528,6 +621,9 @@ void xen_set_pgd(pgd_t *ptr, pgd_t val) return; } + ADD_STATS(pgd_update_pinned, 1); + ADD_STATS(pgd_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + /* If it's pinned, then we can at least batch the kernel and user updates together. */ xen_mc_batch(); @@ -1003,3 +1099,66 @@ void xen_exit_mmap(struct mm_struct *mm) spin_unlock(&mm->page_table_lock); } + +#ifdef CONFIG_XEN_DEBUG_FS + +static struct dentry *d_mmu_debug; + +static int __init xen_mmu_debugfs(void) +{ + struct dentry *d_xen = xen_init_debugfs(); + + if (d_xen == NULL) + return -ENOMEM; + + d_mmu_debug = debugfs_create_dir("mmu", d_xen); + + debugfs_create_u8("zero_stats", 0644, d_mmu_debug, &zero_stats); + + debugfs_create_u32("pgd_update", 0444, d_mmu_debug, &mmu_stats.pgd_update); + debugfs_create_u32("pgd_update_pinned", 0444, d_mmu_debug, + &mmu_stats.pgd_update_pinned); + debugfs_create_u32("pgd_update_batched", 0444, d_mmu_debug, + &mmu_stats.pgd_update_pinned); + + debugfs_create_u32("pud_update", 0444, d_mmu_debug, &mmu_stats.pud_update); + debugfs_create_u32("pud_update_pinned", 0444, d_mmu_debug, + &mmu_stats.pud_update_pinned); + debugfs_create_u32("pud_update_batched", 0444, d_mmu_debug, + &mmu_stats.pud_update_pinned); + + debugfs_create_u32("pmd_update", 0444, d_mmu_debug, &mmu_stats.pmd_update); + debugfs_create_u32("pmd_update_pinned", 0444, d_mmu_debug, + &mmu_stats.pmd_update_pinned); + debugfs_create_u32("pmd_update_batched", 0444, d_mmu_debug, + &mmu_stats.pmd_update_pinned); + + debugfs_create_u32("pte_update", 0444, d_mmu_debug, &mmu_stats.pte_update); +// debugfs_create_u32("pte_update_pinned", 0444, d_mmu_debug, +// &mmu_stats.pte_update_pinned); + debugfs_create_u32("pte_update_batched", 0444, d_mmu_debug, + &mmu_stats.pte_update_pinned); + + debugfs_create_u32("mmu_update", 0444, d_mmu_debug, &mmu_stats.mmu_update); + debugfs_create_u32("mmu_update_extended", 0444, d_mmu_debug, + &mmu_stats.mmu_update_extended); + xen_debugfs_create_u32_array("mmu_update_histo", 0444, d_mmu_debug, + mmu_stats.mmu_update_histo, 20); + + debugfs_create_u32("set_pte_at", 0444, d_mmu_debug, &mmu_stats.set_pte_at); + debugfs_create_u32("set_pte_at_batched", 0444, d_mmu_debug, + &mmu_stats.set_pte_at_batched); + debugfs_create_u32("set_pte_at_current", 0444, d_mmu_debug, + &mmu_stats.set_pte_at_current); + debugfs_create_u32("set_pte_at_kernel", 0444, d_mmu_debug, + &mmu_stats.set_pte_at_kernel); + + debugfs_create_u32("prot_commit", 0444, d_mmu_debug, &mmu_stats.prot_commit); + debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, + &mmu_stats.prot_commit_batched); + + return 0; +} +fs_initcall(xen_mmu_debugfs); + +#endif /* CONFIG_XEN_DEBUG_FS */ diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c index 9efd1c6c977..8ea8a0d0b0d 100644 --- a/arch/x86/xen/multicalls.c +++ b/arch/x86/xen/multicalls.c @@ -21,16 +21,20 @@ */ #include #include +#include #include #include "multicalls.h" +#include "debugfs.h" + +#define MC_BATCH 32 #define MC_DEBUG 1 -#define MC_BATCH 32 #define MC_ARGS (MC_BATCH * 16) + struct mc_buffer { struct multicall_entry entries[MC_BATCH]; #if MC_DEBUG @@ -47,6 +51,76 @@ struct mc_buffer { static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags); +/* flush reasons 0- slots, 1- args, 2- callbacks */ +enum flush_reasons +{ + FL_SLOTS, + FL_ARGS, + FL_CALLBACKS, + + FL_N_REASONS +}; + +#ifdef CONFIG_XEN_DEBUG_FS +#define NHYPERCALLS 40 /* not really */ + +static struct { + unsigned histo[MC_BATCH+1]; + + unsigned issued; + unsigned arg_total; + unsigned hypercalls; + unsigned histo_hypercalls[NHYPERCALLS]; + + unsigned flush[FL_N_REASONS]; +} mc_stats; + +static u8 zero_stats; + +static inline void check_zero(void) +{ + if (unlikely(zero_stats)) { + memset(&mc_stats, 0, sizeof(mc_stats)); + zero_stats = 0; + } +} + +static void mc_add_stats(const struct mc_buffer *mc) +{ + int i; + + check_zero(); + + mc_stats.issued++; + mc_stats.hypercalls += mc->mcidx; + mc_stats.arg_total += mc->argidx; + + mc_stats.histo[mc->mcidx]++; + for(i = 0; i < mc->mcidx; i++) { + unsigned op = mc->entries[i].op; + if (op < NHYPERCALLS) + mc_stats.histo_hypercalls[op]++; + } +} + +static void mc_stats_flush(enum flush_reasons idx) +{ + check_zero(); + + mc_stats.flush[idx]++; +} + +#else /* !CONFIG_XEN_DEBUG_FS */ + +static inline void mc_add_stats(const struct mc_buffer *mc) +{ +} + +static inline void mc_stats_flush(enum flush_reasons idx) +{ +} +#endif /* CONFIG_XEN_DEBUG_FS */ + void xen_mc_flush(void) { struct mc_buffer *b = &__get_cpu_var(mc_buffer); @@ -60,6 +134,8 @@ void xen_mc_flush(void) something in the middle */ local_irq_save(flags); + mc_add_stats(b); + if (b->mcidx) { #if MC_DEBUG memcpy(b->debug, b->entries, @@ -115,6 +191,7 @@ struct multicall_space __xen_mc_entry(size_t args) if (b->mcidx == MC_BATCH || (argidx + args) > MC_ARGS) { + mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS); xen_mc_flush(); argidx = roundup(b->argidx, sizeof(u64)); } @@ -158,10 +235,44 @@ void xen_mc_callback(void (*fn)(void *), void *data) struct mc_buffer *b = &__get_cpu_var(mc_buffer); struct callback *cb; - if (b->cbidx == MC_BATCH) + if (b->cbidx == MC_BATCH) { + mc_stats_flush(FL_CALLBACKS); xen_mc_flush(); + } cb = &b->callbacks[b->cbidx++]; cb->fn = fn; cb->data = data; } + +#ifdef CONFIG_XEN_DEBUG_FS + +static struct dentry *d_mc_debug; + +static int __init xen_mc_debugfs(void) +{ + struct dentry *d_xen = xen_init_debugfs(); + + if (d_xen == NULL) + return -ENOMEM; + + d_mc_debug = debugfs_create_dir("multicalls", d_xen); + + debugfs_create_u8("zero_stats", 0644, d_mc_debug, &zero_stats); + + debugfs_create_u32("batches", 0444, d_mc_debug, &mc_stats.issued); + debugfs_create_u32("hypercalls", 0444, d_mc_debug, &mc_stats.hypercalls); + debugfs_create_u32("arg_total", 0444, d_mc_debug, &mc_stats.arg_total); + + xen_debugfs_create_u32_array("batch_histo", 0444, d_mc_debug, + mc_stats.histo, MC_BATCH); + xen_debugfs_create_u32_array("hypercall_histo", 0444, d_mc_debug, + mc_stats.histo_hypercalls, NHYPERCALLS); + xen_debugfs_create_u32_array("flush_reasons", 0444, d_mc_debug, + mc_stats.flush, FL_N_REASONS); + + return 0; +} +fs_initcall(xen_mc_debugfs); + +#endif /* CONFIG_XEN_DEBUG_FS */ diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 4884bc603aa..0d8f3b2d9be 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -4,6 +4,8 @@ */ #include #include +#include +#include #include @@ -11,6 +13,93 @@ #include #include "xen-ops.h" +#include "debugfs.h" + +#ifdef CONFIG_XEN_DEBUG_FS +static struct xen_spinlock_stats +{ + u64 taken; + u32 taken_slow; + u32 taken_slow_nested; + u32 taken_slow_pickup; + u32 taken_slow_spurious; + + u64 released; + u32 released_slow; + u32 released_slow_kicked; + +#define HISTO_BUCKETS 20 + u32 histo_spin_fast[HISTO_BUCKETS+1]; + u32 histo_spin[HISTO_BUCKETS+1]; + + u64 spinning_time; + u64 total_time; +} spinlock_stats; + +static u8 zero_stats; + +static unsigned lock_timeout = 1 << 10; +#define TIMEOUT lock_timeout + +static inline void check_zero(void) +{ + if (unlikely(zero_stats)) { + memset(&spinlock_stats, 0, sizeof(spinlock_stats)); + zero_stats = 0; + } +} + +#define ADD_STATS(elem, val) \ + do { check_zero(); spinlock_stats.elem += (val); } while(0) + +static inline u64 spin_time_start(void) +{ + return xen_clocksource_read(); +} + +static void __spin_time_accum(u64 delta, u32 *array) +{ + unsigned index = ilog2(delta); + + check_zero(); + + if (index < HISTO_BUCKETS) + array[index]++; + else + array[HISTO_BUCKETS]++; +} + +static inline void spin_time_accum_fast(u64 start) +{ + u32 delta = xen_clocksource_read() - start; + + __spin_time_accum(delta, spinlock_stats.histo_spin_fast); + spinlock_stats.spinning_time += delta; +} + +static inline void spin_time_accum(u64 start) +{ + u32 delta = xen_clocksource_read() - start; + + __spin_time_accum(delta, spinlock_stats.histo_spin); + spinlock_stats.total_time += delta; +} +#else /* !CONFIG_XEN_DEBUG_FS */ +#define TIMEOUT (1 << 10) +#define ADD_STATS(elem, val) do { (void)(val); } while(0) + +static inline u64 spin_time_start(void) +{ + return 0; +} + +static inline void spin_time_accum_fast(u64 start) +{ +} +static inline void spin_time_accum(u64 start) +{ +} +#endif /* CONFIG_XEN_DEBUG_FS */ struct xen_spinlock { unsigned char lock; /* 0 -> free; 1 -> locked */ @@ -92,6 +181,9 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) /* announce we're spinning */ prev = spinning_lock(xl); + ADD_STATS(taken_slow, 1); + ADD_STATS(taken_slow_nested, prev != NULL); + do { /* clear pending */ xen_clear_irq_pending(irq); @@ -100,6 +192,8 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) we weren't looking */ ret = xen_spin_trylock(lock); if (ret) { + ADD_STATS(taken_slow_pickup, 1); + /* * If we interrupted another spinlock while it * was blocking, make sure it doesn't block @@ -120,6 +214,7 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) * pending. */ xen_poll_irq(irq); + ADD_STATS(taken_slow_spurious, !xen_test_irq_pending(irq)); } while (!xen_test_irq_pending(irq)); /* check for spurious wakeups */ kstat_this_cpu.irqs[irq]++; @@ -132,11 +227,18 @@ out: static void xen_spin_lock(struct raw_spinlock *lock) { struct xen_spinlock *xl = (struct xen_spinlock *)lock; - int timeout; + unsigned timeout; u8 oldval; + u64 start_spin; + + ADD_STATS(taken, 1); + + start_spin = spin_time_start(); do { - timeout = 1 << 10; + u64 start_spin_fast = spin_time_start(); + + timeout = TIMEOUT; asm("1: xchgb %1,%0\n" " testb %1,%1\n" @@ -151,16 +253,22 @@ static void xen_spin_lock(struct raw_spinlock *lock) : "1" (1) : "memory"); - } while (unlikely(oldval != 0 && !xen_spin_lock_slow(lock))); + spin_time_accum_fast(start_spin_fast); + } while (unlikely(oldval != 0 && (TIMEOUT == ~0 || !xen_spin_lock_slow(lock)))); + + spin_time_accum(start_spin); } static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) { int cpu; + ADD_STATS(released_slow, 1); + for_each_online_cpu(cpu) { /* XXX should mix up next cpu selection */ if (per_cpu(lock_spinners, cpu) == xl) { + ADD_STATS(released_slow_kicked, 1); xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); break; } @@ -171,6 +279,8 @@ static void xen_spin_unlock(struct raw_spinlock *lock) { struct xen_spinlock *xl = (struct xen_spinlock *)lock; + ADD_STATS(released, 1); + smp_wmb(); /* make sure no writes get moved after unlock */ xl->lock = 0; /* release lock */ @@ -216,3 +326,52 @@ void __init xen_init_spinlocks(void) pv_lock_ops.spin_trylock = xen_spin_trylock; pv_lock_ops.spin_unlock = xen_spin_unlock; } + +#ifdef CONFIG_XEN_DEBUG_FS + +static struct dentry *d_spin_debug; + +static int __init xen_spinlock_debugfs(void) +{ + struct dentry *d_xen = xen_init_debugfs(); + + if (d_xen == NULL) + return -ENOMEM; + + d_spin_debug = debugfs_create_dir("spinlocks", d_xen); + + debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats); + + debugfs_create_u32("timeout", 0644, d_spin_debug, &lock_timeout); + + debugfs_create_u64("taken", 0444, d_spin_debug, &spinlock_stats.taken); + debugfs_create_u32("taken_slow", 0444, d_spin_debug, + &spinlock_stats.taken_slow); + debugfs_create_u32("taken_slow_nested", 0444, d_spin_debug, + &spinlock_stats.taken_slow_nested); + debugfs_create_u32("taken_slow_pickup", 0444, d_spin_debug, + &spinlock_stats.taken_slow_pickup); + debugfs_create_u32("taken_slow_spurious", 0444, d_spin_debug, + &spinlock_stats.taken_slow_spurious); + + debugfs_create_u64("released", 0444, d_spin_debug, &spinlock_stats.released); + debugfs_create_u32("released_slow", 0444, d_spin_debug, + &spinlock_stats.released_slow); + debugfs_create_u32("released_slow_kicked", 0444, d_spin_debug, + &spinlock_stats.released_slow_kicked); + + debugfs_create_u64("time_spinning", 0444, d_spin_debug, + &spinlock_stats.spinning_time); + debugfs_create_u64("time_total", 0444, d_spin_debug, + &spinlock_stats.total_time); + + xen_debugfs_create_u32_array("histo_total", 0444, d_spin_debug, + spinlock_stats.histo_spin, HISTO_BUCKETS + 1); + xen_debugfs_create_u32_array("histo_spinning", 0444, d_spin_debug, + spinlock_stats.histo_spin_fast, HISTO_BUCKETS + 1); + + return 0; +} +fs_initcall(xen_spinlock_debugfs); + +#endif /* CONFIG_XEN_DEBUG_FS */ -- cgit v1.2.3 From 1e696f638b523958ee3d95e655becdb4c4b6fcde Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 20 Aug 2008 17:02:20 -0700 Subject: xen: allow interrupts to be enabled while doing a blocking spin If spin_lock is called in an interrupts-enabled context, we can safely enable interrupts while spinning. We don't bother for the actual spin loop, but if we timeout and fall back to blocking, it's definitely worthwhile enabling interrupts if possible. Signed-off-by: Jeremy Fitzhardinge Acked-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/xen/spinlock.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 0d8f3b2d9be..e6061f2e64f 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -23,6 +23,7 @@ static struct xen_spinlock_stats u32 taken_slow_nested; u32 taken_slow_pickup; u32 taken_slow_spurious; + u32 taken_slow_irqenable; u64 released; u32 released_slow; @@ -167,12 +168,13 @@ static inline void unspinning_lock(struct xen_spinlock *xl, struct xen_spinlock __get_cpu_var(lock_spinners) = prev; } -static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) +static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enable) { struct xen_spinlock *xl = (struct xen_spinlock *)lock; struct xen_spinlock *prev; int irq = __get_cpu_var(lock_kicker_irq); int ret; + unsigned long flags; /* If kicker interrupts not initialized yet, just spin */ if (irq == -1) @@ -181,6 +183,12 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) /* announce we're spinning */ prev = spinning_lock(xl); + flags = __raw_local_save_flags(); + if (irq_enable) { + ADD_STATS(taken_slow_irqenable, 1); + raw_local_irq_enable(); + } + ADD_STATS(taken_slow, 1); ADD_STATS(taken_slow_nested, prev != NULL); @@ -220,11 +228,12 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) kstat_this_cpu.irqs[irq]++; out: + raw_local_irq_restore(flags); unspinning_lock(xl, prev); return ret; } -static void xen_spin_lock(struct raw_spinlock *lock) +static inline void __xen_spin_lock(struct raw_spinlock *lock, bool irq_enable) { struct xen_spinlock *xl = (struct xen_spinlock *)lock; unsigned timeout; @@ -254,11 +263,23 @@ static void xen_spin_lock(struct raw_spinlock *lock) : "memory"); spin_time_accum_fast(start_spin_fast); - } while (unlikely(oldval != 0 && (TIMEOUT == ~0 || !xen_spin_lock_slow(lock)))); + + } while (unlikely(oldval != 0 && + (TIMEOUT == ~0 || !xen_spin_lock_slow(lock, irq_enable)))); spin_time_accum(start_spin); } +static void xen_spin_lock(struct raw_spinlock *lock) +{ + __xen_spin_lock(lock, false); +} + +static void xen_spin_lock_flags(struct raw_spinlock *lock, unsigned long flags) +{ + __xen_spin_lock(lock, !raw_irqs_disabled_flags(flags)); +} + static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) { int cpu; @@ -323,6 +344,7 @@ void __init xen_init_spinlocks(void) pv_lock_ops.spin_is_locked = xen_spin_is_locked; pv_lock_ops.spin_is_contended = xen_spin_is_contended; pv_lock_ops.spin_lock = xen_spin_lock; + pv_lock_ops.spin_lock_flags = xen_spin_lock_flags; pv_lock_ops.spin_trylock = xen_spin_trylock; pv_lock_ops.spin_unlock = xen_spin_unlock; } @@ -353,6 +375,8 @@ static int __init xen_spinlock_debugfs(void) &spinlock_stats.taken_slow_pickup); debugfs_create_u32("taken_slow_spurious", 0444, d_spin_debug, &spinlock_stats.taken_slow_spurious); + debugfs_create_u32("taken_slow_irqenable", 0444, d_spin_debug, + &spinlock_stats.taken_slow_irqenable); debugfs_create_u64("released", 0444, d_spin_debug, &spinlock_stats.released); debugfs_create_u32("released_slow", 0444, d_spin_debug, -- cgit v1.2.3 From f8eca41f0afcc7042dc3398c8ba5878c59b1cf1b Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 20 Aug 2008 17:02:21 -0700 Subject: xen: measure how long spinlocks spend blocking Measure how long spinlocks spend blocked. Also rename some fields to be more consistent. Signed-off-by: Jeremy Fitzhardinge Acked-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/xen/spinlock.c | 62 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index e6061f2e64f..d072823bc06 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -29,12 +29,14 @@ static struct xen_spinlock_stats u32 released_slow; u32 released_slow_kicked; -#define HISTO_BUCKETS 20 - u32 histo_spin_fast[HISTO_BUCKETS+1]; - u32 histo_spin[HISTO_BUCKETS+1]; - - u64 spinning_time; - u64 total_time; +#define HISTO_BUCKETS 30 + u32 histo_spin_total[HISTO_BUCKETS+1]; + u32 histo_spin_spinning[HISTO_BUCKETS+1]; + u32 histo_spin_blocked[HISTO_BUCKETS+1]; + + u64 time_total; + u64 time_spinning; + u64 time_blocked; } spinlock_stats; static u8 zero_stats; @@ -70,20 +72,28 @@ static void __spin_time_accum(u64 delta, u32 *array) array[HISTO_BUCKETS]++; } -static inline void spin_time_accum_fast(u64 start) +static inline void spin_time_accum_spinning(u64 start) +{ + u32 delta = xen_clocksource_read() - start; + + __spin_time_accum(delta, spinlock_stats.histo_spin_spinning); + spinlock_stats.time_spinning += delta; +} + +static inline void spin_time_accum_total(u64 start) { u32 delta = xen_clocksource_read() - start; - __spin_time_accum(delta, spinlock_stats.histo_spin_fast); - spinlock_stats.spinning_time += delta; + __spin_time_accum(delta, spinlock_stats.histo_spin_total); + spinlock_stats.time_total += delta; } -static inline void spin_time_accum(u64 start) +static inline void spin_time_accum_blocked(u64 start) { u32 delta = xen_clocksource_read() - start; - __spin_time_accum(delta, spinlock_stats.histo_spin); - spinlock_stats.total_time += delta; + __spin_time_accum(delta, spinlock_stats.histo_spin_blocked); + spinlock_stats.time_blocked += delta; } #else /* !CONFIG_XEN_DEBUG_FS */ #define TIMEOUT (1 << 10) @@ -94,10 +104,13 @@ static inline u64 spin_time_start(void) return 0; } -static inline void spin_time_accum_fast(u64 start) +static inline void spin_time_accum_total(u64 start) +{ +} +static inline void spin_time_accum_spinning(u64 start) { } -static inline void spin_time_accum(u64 start) +static inline void spin_time_accum_blocked(u64 start) { } #endif /* CONFIG_XEN_DEBUG_FS */ @@ -175,11 +188,14 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl int irq = __get_cpu_var(lock_kicker_irq); int ret; unsigned long flags; + u64 start; /* If kicker interrupts not initialized yet, just spin */ if (irq == -1) return 0; + start = spin_time_start(); + /* announce we're spinning */ prev = spinning_lock(xl); @@ -230,6 +246,8 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl out: raw_local_irq_restore(flags); unspinning_lock(xl, prev); + spin_time_accum_blocked(start); + return ret; } @@ -262,12 +280,12 @@ static inline void __xen_spin_lock(struct raw_spinlock *lock, bool irq_enable) : "1" (1) : "memory"); - spin_time_accum_fast(start_spin_fast); + spin_time_accum_spinning(start_spin_fast); } while (unlikely(oldval != 0 && (TIMEOUT == ~0 || !xen_spin_lock_slow(lock, irq_enable)))); - spin_time_accum(start_spin); + spin_time_accum_total(start_spin); } static void xen_spin_lock(struct raw_spinlock *lock) @@ -385,14 +403,18 @@ static int __init xen_spinlock_debugfs(void) &spinlock_stats.released_slow_kicked); debugfs_create_u64("time_spinning", 0444, d_spin_debug, - &spinlock_stats.spinning_time); + &spinlock_stats.time_spinning); + debugfs_create_u64("time_blocked", 0444, d_spin_debug, + &spinlock_stats.time_blocked); debugfs_create_u64("time_total", 0444, d_spin_debug, - &spinlock_stats.total_time); + &spinlock_stats.time_total); xen_debugfs_create_u32_array("histo_total", 0444, d_spin_debug, - spinlock_stats.histo_spin, HISTO_BUCKETS + 1); + spinlock_stats.histo_spin_total, HISTO_BUCKETS + 1); xen_debugfs_create_u32_array("histo_spinning", 0444, d_spin_debug, - spinlock_stats.histo_spin_fast, HISTO_BUCKETS + 1); + spinlock_stats.histo_spin_spinning, HISTO_BUCKETS + 1); + xen_debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug, + spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1); return 0; } -- cgit v1.2.3 From f86399396ce7a4f4069828b7dceac5aa5113dfb5 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 30 Jul 2008 18:32:27 -0300 Subject: x86, paravirt_ops: use unsigned long instead of u32 for alloc_p*() pfn args This patch changes the pfn args from 'u32' to 'unsigned long' on alloc_p*() functions on paravirt_ops, and the corresponding implementations for Xen and VMI. The prototypes for CONFIG_PARAVIRT=n are already using unsigned long, so paravirt.h now matches the prototypes on asm-x86/pgalloc.h. It shouldn't result in any changes on generated code on 32-bit, with or without CONFIG_PARAVIRT. On both cases, 'codiff -f' didn't show any change after applying this patch. On 64-bit, there are (expected) binary changes only when CONFIG_PARAVIRT is enabled, as the patch is really supposed to change the size of the pfn args. [ v2: KVM_GUEST: use the right parameter type on kvm_release_pt() ] Signed-off-by: Eduardo Habkost Acked-by: Jeremy Fitzhardinge Acked-by: Zachary Amsden Signed-off-by: Ingo Molnar --- arch/x86/kernel/kvm.c | 2 +- arch/x86/kernel/vmi_32.c | 10 +++++----- arch/x86/xen/enlighten.c | 20 ++++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 8b7a3cf37d2..478bca986ec 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -178,7 +178,7 @@ static void kvm_flush_tlb(void) kvm_deferred_mmu_op(&ftlb, sizeof ftlb); } -static void kvm_release_pt(u32 pfn) +static void kvm_release_pt(unsigned long pfn) { struct kvm_mmu_op_release_pt rpt = { .header.op = KVM_MMU_OP_RELEASE_PT, diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index 0a1b1a9d922..340b03643b9 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -392,13 +392,13 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type) } #endif -static void vmi_allocate_pte(struct mm_struct *mm, u32 pfn) +static void vmi_allocate_pte(struct mm_struct *mm, unsigned long pfn) { vmi_set_page_type(pfn, VMI_PAGE_L1); vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0); } -static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn) +static void vmi_allocate_pmd(struct mm_struct *mm, unsigned long pfn) { /* * This call comes in very early, before mem_map is setup. @@ -409,20 +409,20 @@ static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn) vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0); } -static void vmi_allocate_pmd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count) +static void vmi_allocate_pmd_clone(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count) { vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE); vmi_check_page_type(clonepfn, VMI_PAGE_L2); vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count); } -static void vmi_release_pte(u32 pfn) +static void vmi_release_pte(unsigned long pfn) { vmi_ops.release_page(pfn, VMI_PAGE_L1); vmi_set_page_type(pfn, VMI_PAGE_NORMAL); } -static void vmi_release_pmd(u32 pfn) +static void vmi_release_pmd(unsigned long pfn) { vmi_ops.release_page(pfn, VMI_PAGE_L2); vmi_set_page_type(pfn, VMI_PAGE_NORMAL); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 9ff6e3cbf08..db970bdc5e3 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -812,7 +812,7 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) /* Early in boot, while setting up the initial pagetable, assume everything is pinned. */ -static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn) +static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) { #ifdef CONFIG_FLATMEM BUG_ON(mem_map); /* should only be used early */ @@ -822,7 +822,7 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn) /* Early release_pte assumes that all pts are pinned, since there's only init_mm and anything attached to that is pinned. */ -static void xen_release_pte_init(u32 pfn) +static void xen_release_pte_init(unsigned long pfn) { make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } @@ -838,7 +838,7 @@ static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) /* This needs to make sure the new pte page is pinned iff its being attached to a pinned pagetable. */ -static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) +static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level) { struct page *page = pfn_to_page(pfn); @@ -856,12 +856,12 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) } } -static void xen_alloc_pte(struct mm_struct *mm, u32 pfn) +static void xen_alloc_pte(struct mm_struct *mm, unsigned long pfn) { xen_alloc_ptpage(mm, pfn, PT_PTE); } -static void xen_alloc_pmd(struct mm_struct *mm, u32 pfn) +static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn) { xen_alloc_ptpage(mm, pfn, PT_PMD); } @@ -909,7 +909,7 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) } /* This should never happen until we're OK to use struct page */ -static void xen_release_ptpage(u32 pfn, unsigned level) +static void xen_release_ptpage(unsigned long pfn, unsigned level) { struct page *page = pfn_to_page(pfn); @@ -923,23 +923,23 @@ static void xen_release_ptpage(u32 pfn, unsigned level) } } -static void xen_release_pte(u32 pfn) +static void xen_release_pte(unsigned long pfn) { xen_release_ptpage(pfn, PT_PTE); } -static void xen_release_pmd(u32 pfn) +static void xen_release_pmd(unsigned long pfn) { xen_release_ptpage(pfn, PT_PMD); } #if PAGETABLE_LEVELS == 4 -static void xen_alloc_pud(struct mm_struct *mm, u32 pfn) +static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn) { xen_alloc_ptpage(mm, pfn, PT_PUD); } -static void xen_release_pud(u32 pfn) +static void xen_release_pud(unsigned long pfn) { xen_release_ptpage(pfn, PT_PUD); } -- cgit v1.2.3 From 9a79f4f491f92bc713e1f28f96516b141b752600 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Fri, 22 Aug 2008 00:10:13 +0200 Subject: x86: {reverve,free}_memtype() take a physical address The new set_memory_array_{uc,wb}() pass virtual addresses to {reserve,free}_memtype() it seems. Signed-off-by: Rene Herman Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 1785591808b..fed6ba2a8e7 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -947,7 +947,7 @@ int set_memory_array_uc(unsigned long *addr, int addrinarray) * for now UC MINUS. see comments in ioremap_nocache() */ for (i = 0; i < addrinarray; i++) { - if (reserve_memtype(addr[i], addr[i] + PAGE_SIZE, + if (reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE, _PAGE_CACHE_UC_MINUS, NULL)) goto out; } @@ -956,7 +956,7 @@ int set_memory_array_uc(unsigned long *addr, int addrinarray) __pgprot(_PAGE_CACHE_UC_MINUS), 1); out: while (--i >= 0) - free_memtype(addr[i], addr[i] + PAGE_SIZE); + free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE); return -EINVAL; } EXPORT_SYMBOL(set_memory_array_uc); @@ -998,7 +998,7 @@ int set_memory_array_wb(unsigned long *addr, int addrinarray) { int i; for (i = 0; i < addrinarray; i++) - free_memtype(addr[i], addr[i] + PAGE_SIZE); + free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE); return change_page_attr_clear(addr, addrinarray, __pgprot(_PAGE_CACHE_MASK), 1); -- cgit v1.2.3 From c5e147cf5aeb31aa1a9030be9727914855fc4133 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Fri, 22 Aug 2008 01:02:20 +0200 Subject: x86: have set_memory_array_{uc,wb} coalesce memtypes. Actually, might as well simply reconstruct the memtype list at free time I guess. How is this for a coalescing version of the array functions? Compiles, boots and provides me with: root@7ixe4:~# wc -l /debug/x86/pat_memtype_list 53 /debug/x86/pat_memtype_list otherwise (down from 16384+). Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index fed6ba2a8e7..497108825da 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -942,21 +942,38 @@ EXPORT_SYMBOL(set_memory_uc); int set_memory_array_uc(unsigned long *addr, int addrinarray) { + unsigned long start; + unsigned long end; int i; /* * for now UC MINUS. see comments in ioremap_nocache() */ for (i = 0; i < addrinarray; i++) { - if (reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE, - _PAGE_CACHE_UC_MINUS, NULL)) + start = __pa(addr[i]); + for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { + if (end != __pa(addr[i + 1])) + break; + i++; + } + if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) goto out; } return change_page_attr_set(addr, addrinarray, __pgprot(_PAGE_CACHE_UC_MINUS), 1); out: - while (--i >= 0) - free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE); + for (i = 0; i < addrinarray; i++) { + unsigned long tmp = __pa(addr[i]); + + if (tmp == start) + break; + for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { + if (end != __pa(addr[i + 1])) + break; + i++; + } + free_memtype(tmp, end); + } return -EINVAL; } EXPORT_SYMBOL(set_memory_array_uc); @@ -997,9 +1014,18 @@ EXPORT_SYMBOL(set_memory_wb); int set_memory_array_wb(unsigned long *addr, int addrinarray) { int i; - for (i = 0; i < addrinarray; i++) - free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE); + for (i = 0; i < addrinarray; i++) { + unsigned long start = __pa(addr[i]); + unsigned long end; + + for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { + if (end != __pa(addr[i + 1])) + break; + i++; + } + free_memtype(start, end); + } return change_page_attr_clear(addr, addrinarray, __pgprot(_PAGE_CACHE_MASK), 1); } -- cgit v1.2.3 From 5b792d320f28ff83dd4c13f984807e26235f7703 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 21 Aug 2008 13:43:51 -0700 Subject: x86, microcode_amd: fix shift warning microcode_amd.c uses ">> 32" on a 32-bit value, so gcc warns about that. The code could use something like this *untested* patch. linux-next-20080821/arch/x86/kernel/microcode_amd.c:229: warning: right shift count >= width of type Signed-off-by: Randy Dunlap Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 4006e5e3adf..d606a05545c 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -206,6 +206,7 @@ static void apply_microcode_amd(int cpu) unsigned int rev; int cpu_num = raw_smp_processor_id(); struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + unsigned long addr; /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); @@ -215,10 +216,9 @@ static void apply_microcode_amd(int cpu) spin_lock_irqsave(µcode_update_lock, flags); - edx = (unsigned int)(((unsigned long) - &(uci->mc.mc_amd->hdr.data_code)) >> 32); - eax = (unsigned int)(((unsigned long) - &(uci->mc.mc_amd->hdr.data_code)) & 0xffffffffL); + addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code; + edx = (unsigned int)(((unsigned long)upper_32_bits(addr))); + eax = (unsigned int)(((unsigned long)lower_32_bits(addr))); asm volatile("movl %0, %%ecx; wrmsr" : : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx"); -- cgit v1.2.3 From ee7686bc043921a488d9bf89fe93241c5457a74e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 21 Aug 2008 13:17:56 -0700 Subject: x86: build fix in "xen spinlock updates and performance measurements" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ingo Molnar wrote: > -tip testing found this build failure: > > arch/x86/xen/spinlock.c: In function ‘spin_time_start’: > arch/x86/xen/spinlock.c:60: error: implicit declaration of function ‘xen_clocksource_read’ > > i've excluded these new commits for now from tip/master - could you > please send a delta fix against tip/x86/xen? Make xen_clocksource_read non-static. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/time.c | 4 +--- arch/x86/xen/xen-ops.h | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 685b77470fc..20182d9072c 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -30,8 +30,6 @@ #define TIMER_SLOP 100000 #define NS_PER_TICK (1000000000LL / HZ) -static cycle_t xen_clocksource_read(void); - /* runstate info updated by Xen */ static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); @@ -213,7 +211,7 @@ unsigned long xen_tsc_khz(void) return xen_khz; } -static cycle_t xen_clocksource_read(void) +cycle_t xen_clocksource_read(void) { struct pvclock_vcpu_time_info *src; cycle_t ret; diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 3c70ebc50b1..1e8bfdaa20d 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -2,6 +2,7 @@ #define XEN_OPS_H #include +#include #include #include @@ -33,6 +34,7 @@ void __init xen_build_dynamic_phys_to_machine(void); void xen_init_irq_ops(void); void xen_setup_timer(int cpu); +cycle_t xen_clocksource_read(void); void xen_setup_cpu_clockevents(void); unsigned long xen_tsc_khz(void); void __init xen_time_init(void); -- cgit v1.2.3 From 94581094e774402a11887719bac10505236c2d51 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:39 +0200 Subject: x86: add alloc_coherent dma_ops callback to GART driver [ v2 - x86: make gart_alloc_coherent return zeroed memory FUJITA Tomonori pointed it out that the dma_alloc_coherent function should return memory set to zero. This patch adds this to the GART implementation too. ] Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 49285f8fd4d..076e64b2d4f 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -499,6 +499,26 @@ error: return 0; } +/* allocate and map a coherent mapping */ +static void * +gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, + gfp_t flag) +{ + void *vaddr; + + vaddr = (void *)__get_free_pages(flag | __GFP_ZERO, get_order(size)); + if (!vaddr) + return NULL; + + *dma_addr = gart_map_single(dev, __pa(vaddr), size, DMA_BIDIRECTIONAL); + if (*dma_addr != bad_dma_address) + return vaddr; + + free_pages((unsigned long)vaddr, get_order(size)); + + return NULL; +} + static int no_agp; static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) @@ -701,6 +721,7 @@ static struct dma_mapping_ops gart_dma_ops = { .sync_sg_for_device = NULL, .map_sg = gart_map_sg, .unmap_sg = gart_unmap_sg, + .alloc_coherent = gart_alloc_coherent, }; void gart_iommu_shutdown(void) -- cgit v1.2.3 From 43a5a5a09b8cfd56047706cf904718d073ccfd33 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:40 +0200 Subject: x86: add free_coherent dma_ops callback to GART driver Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 076e64b2d4f..ef753e23358 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -519,6 +519,15 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, return NULL; } +/* free a coherent mapping */ +static void +gart_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_addr) +{ + gart_unmap_single(dev, dma_addr, size, DMA_BIDIRECTIONAL); + free_pages((unsigned long)vaddr, get_order(size)); +} + static int no_agp; static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) @@ -722,6 +731,7 @@ static struct dma_mapping_ops gart_dma_ops = { .map_sg = gart_map_sg, .unmap_sg = gart_unmap_sg, .alloc_coherent = gart_alloc_coherent, + .free_coherent = gart_free_coherent, }; void gart_iommu_shutdown(void) -- cgit v1.2.3 From e4ad68b651f22fa71820c0b30bb2807999b2b49f Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:41 +0200 Subject: x86: add free_coherent dma_ops callback to Calgary IOMMU driver Signed-off-by: Joerg Roedel Acked-by: Muli Ben-Yehuda Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-calgary_64.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 218d783ed7a..afb020fdb19 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -511,8 +511,22 @@ error: return ret; } +static void calgary_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + unsigned int npages; + struct iommu_table *tbl = find_iommu_table(dev); + + size = PAGE_ALIGN(size); + npages = size >> PAGE_SHIFT; + + iommu_free(tbl, dma_handle, npages); + free_pages((unsigned long)vaddr, get_order(size)); +} + static struct dma_mapping_ops calgary_dma_ops = { .alloc_coherent = calgary_alloc_coherent, + .free_coherent = calgary_free_coherent, .map_single = calgary_map_single, .unmap_single = calgary_unmap_single, .map_sg = calgary_map_sg, -- cgit v1.2.3 From c5e835f9641e9fcb95d1afb24906821e98b2c6a8 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:42 +0200 Subject: x86: add alloc_coherent dma_ops callback to NOMMU driver Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-nommu.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 3f91f71cdc3..b8ce83c9821 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -72,7 +72,62 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, return nents; } +static void * +nommu_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_addr, gfp_t gfp) +{ + unsigned long dma_mask; + int node; + struct page *page; + + if (hwdev->dma_mask == NULL) + return NULL; + + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + gfp |= __GFP_ZERO; + + dma_mask = hwdev->coherent_dma_mask; + if (!dma_mask) + dma_mask = *(hwdev->dma_mask); + + if (dma_mask < DMA_24BIT_MASK) + return NULL; + + node = dev_to_node(hwdev); + +#ifdef CONFIG_X86_64 + if (dma_mask <= DMA_32BIT_MASK) + gfp |= GFP_DMA32; +#endif + + /* No alloc-free penalty for ISA devices */ + if (dma_mask == DMA_24BIT_MASK) + gfp |= GFP_DMA; + +again: + page = alloc_pages_node(node, gfp, get_order(size)); + if (!page) + return NULL; + + if ((page_to_phys(page) + size > dma_mask) && !(gfp & GFP_DMA)) { + free_pages((unsigned long)page_address(page), get_order(size)); + gfp |= GFP_DMA; + goto again; + } + + *dma_addr = page_to_phys(page); + if (check_addr("alloc_coherent", hwdev, *dma_addr, size)) { + flush_write_buffers(); + return page_address(page); + } + + free_pages((unsigned long)page_address(page), get_order(size)); + + return NULL; +} + struct dma_mapping_ops nommu_dma_ops = { + .alloc_coherent = nommu_alloc_coherent, .map_single = nommu_map_single, .map_sg = nommu_map_sg, .is_phys = 1, -- cgit v1.2.3 From a3a76532e0caa093c279806d8fe8608232538af0 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:43 +0200 Subject: x86: add free_coherent dma_ops callback to NOMMU driver Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-nommu.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index b8ce83c9821..73853d3fdca 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -126,8 +126,15 @@ again: return NULL; } +static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_addr) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + struct dma_mapping_ops nommu_dma_ops = { .alloc_coherent = nommu_alloc_coherent, + .free_coherent = nommu_free_coherent, .map_single = nommu_map_single, .map_sg = nommu_map_sg, .is_phys = 1, -- cgit v1.2.3 From c647c3bb2d16246a87f49035985ddb7c1eb030df Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:44 +0200 Subject: x86: cleanup dma_*_coherent functions All dma_ops implementations support the alloc_coherent and free_coherent callbacks now. This allows a big simplification of the dma_alloc_coherent function which is done with this patch. The dma_free_coherent functions is also cleaned up and calls now the free_coherent callback of the dma_ops implementation. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-dma.c | 121 +++++----------------------------------------- 1 file changed, 12 insertions(+), 109 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 87d4d6964ec..613332b26e3 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -241,33 +241,15 @@ int dma_supported(struct device *dev, u64 mask) } EXPORT_SYMBOL(dma_supported); -/* Allocate DMA memory on node near device */ -static noinline struct page * -dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order) -{ - int node; - - node = dev_to_node(dev); - - return alloc_pages_node(node, gfp, order); -} - /* * Allocate memory for a coherent mapping. */ -void * + void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) { struct dma_mapping_ops *ops = get_dma_ops(dev); - void *memory = NULL; - struct page *page; - unsigned long dma_mask = 0; - dma_addr_t bus; - int noretry = 0; - - /* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + void *memory; if (dma_alloc_from_coherent(dev, size, dma_handle, &memory)) return memory; @@ -276,89 +258,10 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, dev = &fallback_dev; gfp |= GFP_DMA; } - dma_mask = dev->coherent_dma_mask; - if (dma_mask == 0) - dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK; - - /* Device not DMA able */ - if (dev->dma_mask == NULL) - return NULL; - - /* Don't invoke OOM killer or retry in lower 16MB DMA zone */ - if (gfp & __GFP_DMA) - noretry = 1; - -#ifdef CONFIG_X86_64 - /* Why <=? Even when the mask is smaller than 4GB it is often - larger than 16MB and in this case we have a chance of - finding fitting memory in the next higher zone first. If - not retry with true GFP_DMA. -AK */ - if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) { - gfp |= GFP_DMA32; - if (dma_mask < DMA_32BIT_MASK) - noretry = 1; - } -#endif - again: - page = dma_alloc_pages(dev, - noretry ? gfp | __GFP_NORETRY : gfp, get_order(size)); - if (page == NULL) - return NULL; - - { - int high, mmu; - bus = page_to_phys(page); - memory = page_address(page); - high = (bus + size) >= dma_mask; - mmu = high; - if (force_iommu && !(gfp & GFP_DMA)) - mmu = 1; - else if (high) { - free_pages((unsigned long)memory, - get_order(size)); - - /* Don't use the 16MB ZONE_DMA unless absolutely - needed. It's better to use remapping first. */ - if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) { - gfp = (gfp & ~GFP_DMA32) | GFP_DMA; - goto again; - } - - /* Let low level make its own zone decisions */ - gfp &= ~(GFP_DMA32|GFP_DMA); - - if (ops->alloc_coherent) - return ops->alloc_coherent(dev, size, - dma_handle, gfp); - return NULL; - } - - memset(memory, 0, size); - if (!mmu) { - *dma_handle = bus; - return memory; - } - } - - if (ops->alloc_coherent) { - free_pages((unsigned long)memory, get_order(size)); - gfp &= ~(GFP_DMA|GFP_DMA32); - return ops->alloc_coherent(dev, size, dma_handle, gfp); - } - - if (ops->map_simple) { - *dma_handle = ops->map_simple(dev, virt_to_phys(memory), - size, - PCI_DMA_BIDIRECTIONAL); - if (*dma_handle != bad_dma_address) - return memory; - } - - if (panic_on_overflow) - panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", - (unsigned long)size); - free_pages((unsigned long)memory, get_order(size)); + if (ops->alloc_coherent) + return ops->alloc_coherent(dev, size, + dma_handle, gfp); return NULL; } EXPORT_SYMBOL(dma_alloc_coherent); @@ -368,17 +271,17 @@ EXPORT_SYMBOL(dma_alloc_coherent); * The caller must ensure that the device has finished accessing the mapping. */ void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t bus) + void *vaddr, dma_addr_t bus) { struct dma_mapping_ops *ops = get_dma_ops(dev); - int order = get_order(size); - WARN_ON(irqs_disabled()); /* for portability */ - if (dma_release_from_coherent(dev, order, vaddr)) + WARN_ON(irqs_disabled()); /* for portability */ + + if (dma_release_from_coherent(dev, get_order(size), vaddr)) return; - if (ops->unmap_single) - ops->unmap_single(dev, bus, size, 0); - free_pages((unsigned long)vaddr, order); + + if (ops->free_coherent) + ops->free_coherent(dev, size, vaddr, bus); } EXPORT_SYMBOL(dma_free_coherent); -- cgit v1.2.3 From 6c505ce3930c6a6b455cda53fab3e88ae44f8221 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:45 +0200 Subject: x86: move dma_*_coherent functions to include file All the x86 DMA-API functions are defined in asm/dma-mapping.h. This patch moves the dma_*_coherent functions also to this header file because they are now small enough to do so. This is done as a separate patch because it also includes some renaming and restructuring of the dma-mapping.h file. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-dma.c | 49 +++---------------------------------------- arch/x86/kernel/pci-gart_64.c | 4 ++-- 2 files changed, 5 insertions(+), 48 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 613332b26e3..0a1408abcc6 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -41,11 +41,12 @@ EXPORT_SYMBOL(bad_dma_address); /* Dummy device used for NULL arguments (normally ISA). Better would be probably a smaller DMA mask, but this is bug-to-bug compatible to older i386. */ -struct device fallback_dev = { +struct device x86_dma_fallback_dev = { .bus_id = "fallback device", .coherent_dma_mask = DMA_32BIT_MASK, - .dma_mask = &fallback_dev.coherent_dma_mask, + .dma_mask = &x86_dma_fallback_dev.coherent_dma_mask, }; +EXPORT_SYMBOL(x86_dma_fallback_dev); int dma_set_mask(struct device *dev, u64 mask) { @@ -241,50 +242,6 @@ int dma_supported(struct device *dev, u64 mask) } EXPORT_SYMBOL(dma_supported); -/* - * Allocate memory for a coherent mapping. - */ - void * -dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - gfp_t gfp) -{ - struct dma_mapping_ops *ops = get_dma_ops(dev); - void *memory; - - if (dma_alloc_from_coherent(dev, size, dma_handle, &memory)) - return memory; - - if (!dev) { - dev = &fallback_dev; - gfp |= GFP_DMA; - } - - if (ops->alloc_coherent) - return ops->alloc_coherent(dev, size, - dma_handle, gfp); - return NULL; -} -EXPORT_SYMBOL(dma_alloc_coherent); - -/* - * Unmap coherent memory. - * The caller must ensure that the device has finished accessing the mapping. - */ -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t bus) -{ - struct dma_mapping_ops *ops = get_dma_ops(dev); - - WARN_ON(irqs_disabled()); /* for portability */ - - if (dma_release_from_coherent(dev, get_order(size), vaddr)) - return; - - if (ops->free_coherent) - ops->free_coherent(dev, size, vaddr, bus); -} -EXPORT_SYMBOL(dma_free_coherent); - static int __init pci_iommu_init(void) { calgary_iommu_init(); diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index ef753e23358..e81df25dc06 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -276,7 +276,7 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) unsigned long bus; if (!dev) - dev = &fallback_dev; + dev = &x86_dma_fallback_dev; if (!need_iommu(dev, paddr, size)) return paddr; @@ -427,7 +427,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) return 0; if (!dev) - dev = &fallback_dev; + dev = &x86_dma_fallback_dev; out = 0; start = 0; -- cgit v1.2.3 From 2cd54961caff9fe9109807c6603a0af0729b9591 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Aug 2008 16:32:46 +0200 Subject: x86, AMD IOMMU: remove obsolete FIXME comment Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index de39e1f2ede..d15081c3823 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1038,8 +1038,6 @@ out: /* * The exported free_coherent function for dma_ops. - * FIXME: fix the generic x86 DMA layer so that it actually calls that - * function. */ static void free_coherent(struct device *dev, size_t size, void *virt_addr, dma_addr_t dma_addr) -- cgit v1.2.3 From 766af9fa812f49feb4a3e62cf92f3d37f33c7fb6 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 22 Aug 2008 00:12:09 +0900 Subject: dma-mapping.h, x86: remove last user of dma_mapping_ops->map_simple pci-dma.c doesn't use map_simple hook any more so we can remove it from struct dma_mapping_ops now. Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index e81df25dc06..cfd7ec25e37 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -720,7 +720,6 @@ extern int agp_amd64_init(void); static struct dma_mapping_ops gart_dma_ops = { .map_single = gart_map_single, - .map_simple = gart_map_simple, .unmap_single = gart_unmap_single, .sync_single_for_cpu = NULL, .sync_single_for_device = NULL, -- cgit v1.2.3 From 421076e2bec1b917bdcf83da35b24f6349bf35db Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 22 Aug 2008 16:29:10 +0900 Subject: x86: dma_*_coherent rework patchset v2, fix alloc_coherent dma_ops callback was added to GART, however, it doesn't return a size aligned address wrt dma_alloc_coherent, as DMA-mapping.txt defines. This patch fixes it. This patch also removes unused gart_map_simple (dma_mapping_ops->map_simple has gone). Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 338c4f24155..4d0864900b8 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -261,20 +261,6 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK); } -static dma_addr_t -gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir) -{ - dma_addr_t map; - unsigned long align_mask; - - align_mask = (1UL << get_order(size)) - 1; - map = dma_map_area(dev, paddr, size, dir, align_mask); - - flush_gart(); - - return map; -} - /* Map a single area into the IOMMU */ static dma_addr_t gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) @@ -512,12 +498,21 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, gfp_t flag) { void *vaddr; + unsigned long align_mask; vaddr = (void *)__get_free_pages(flag | __GFP_ZERO, get_order(size)); if (!vaddr) return NULL; - *dma_addr = gart_map_single(dev, __pa(vaddr), size, DMA_BIDIRECTIONAL); + align_mask = (1UL << get_order(size)) - 1; + + if (!dev) + dev = &x86_dma_fallback_dev; + + *dma_addr = dma_map_area(dev, __pa(vaddr), size, DMA_BIDIRECTIONAL, + align_mask); + flush_gart(); + if (*dma_addr != bad_dma_address) return vaddr; -- cgit v1.2.3 From b05f78f5c713eda2c34e495d92495ee4f1c3b5e1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 22 Aug 2008 01:32:50 -0700 Subject: x86_64: printout msr -v2 commandline show_msr=1 for bsp, show_msr=32 for all 32 cpus. [ mingo@elte.hu: added documentation ] Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 51 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/paravirt.c | 1 + 2 files changed, 52 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index dd6e3f15017..bca2d6980e8 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -394,6 +394,49 @@ static __init int setup_noclflush(char *arg) } __setup("noclflush", setup_noclflush); +struct msr_range { + unsigned min; + unsigned max; +}; + +static struct msr_range msr_range_array[] __cpuinitdata = { + { 0x00000000, 0x00000418}, + { 0xc0000000, 0xc000040b}, + { 0xc0010000, 0xc0010142}, + { 0xc0011000, 0xc001103b}, +}; + +static void __cpuinit print_cpu_msr(void) +{ + unsigned index; + u64 val; + int i; + unsigned index_min, index_max; + + for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) { + index_min = msr_range_array[i].min; + index_max = msr_range_array[i].max; + for (index = index_min; index < index_max; index++) { + if (rdmsrl_amd_safe(index, &val)) + continue; + printk(KERN_INFO " MSR%08x: %016llx\n", index, val); + } + } +} + +static int show_msr __cpuinitdata; +static __init int setup_show_msr(char *arg) +{ + int num; + + get_option(&arg, &num); + + if (num > 0) + show_msr = num; + return 1; +} +__setup("show_msr=", setup_show_msr); + void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) { if (c->x86_model_id[0]) @@ -403,6 +446,14 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) printk(KERN_CONT " stepping %02x\n", c->x86_mask); else printk(KERN_CONT "\n"); + +#ifdef CONFIG_SMP + if (c->cpu_index < show_msr) + print_cpu_msr(); +#else + if (show_msr) + print_cpu_msr(); +#endif } static __init int setup_disablecpuid(char *arg) diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 94da4d52d79..c6044682e1e 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -330,6 +330,7 @@ struct pv_cpu_ops pv_cpu_ops = { #endif .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, + .read_msr_amd = native_read_msr_amd_safe, .write_msr = native_write_msr_safe, .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, -- cgit v1.2.3 From 25258ef762bc4a05fa9c4523f7dae56e3fd01864 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 20 Aug 2008 11:31:07 -0700 Subject: x86: export pv_lock_ops non-GPL None of the spinlock API is exported GPL, so there's no reason for pv_lock_ops to be. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar Cc: drago01 --- arch/x86/kernel/paravirt-spinlocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c index 206359a8e43..0e9f1982b1d 100644 --- a/arch/x86/kernel/paravirt-spinlocks.c +++ b/arch/x86/kernel/paravirt-spinlocks.c @@ -23,7 +23,7 @@ struct pv_lock_ops pv_lock_ops = { .spin_unlock = __ticket_spin_unlock, #endif }; -EXPORT_SYMBOL_GPL(pv_lock_ops); +EXPORT_SYMBOL(pv_lock_ops); void __init paravirt_use_bytelocks(void) { -- cgit v1.2.3 From 01de05af94db5d5214b0a5e191068d19c82059a8 Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Fri, 22 Aug 2008 12:08:17 -0700 Subject: x86: have set_memory_array_{uc,wb} coalesce memtypes, fix Fix the start addr for free_memtype calls in the error path. Signed-off-by: Venkatesh Pallipadi Acked-by: Rene Herman Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 497108825da..4b6968ba086 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -967,7 +967,7 @@ out: if (tmp == start) break; - for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { + for (end = tmp + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { if (end != __pa(addr[i + 1])) break; i++; -- cgit v1.2.3 From bbb65d2d365efe9951290e61678dcf81ec60add4 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Sat, 23 Aug 2008 17:47:10 +0200 Subject: x86: use cpuid vector 0xb when available for detecting cpu topology cpuid leaf 0xb provides extended topology enumeration. This interface provides the 32-bit x2APIC id of the logical processor and it also provides a new mechanism to detect SMT and core siblings (which provides increased addressability). Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/addon_cpuid_features.c | 86 ++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/common_64.c | 3 ++ arch/x86/kernel/cpu/intel.c | 13 +++-- arch/x86/kernel/cpu/intel_64.c | 5 +- 4 files changed, 103 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 84a8220a607..aa9641ae670 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -7,6 +7,8 @@ #include #include +#include + struct cpuid_bit { u16 feature; u8 reg; @@ -48,6 +50,90 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) } } +/* leaf 0xb SMT level */ +#define SMT_LEVEL 0 + +/* leaf 0xb sub-leaf types */ +#define INVALID_TYPE 0 +#define SMT_TYPE 1 +#define CORE_TYPE 2 + +#define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff) +#define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f) +#define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff) + +/* + * Check for extended topology enumeration cpuid leaf 0xb and if it + * exists, use it for populating initial_apicid and cpu topology + * detection. + */ +void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) +{ + unsigned int eax, ebx, ecx, edx, sub_index; + unsigned int ht_mask_width, core_plus_mask_width; + unsigned int core_select_mask, core_level_siblings; + + if (c->cpuid_level < 0xb) + return; + + cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); + + /* + * check if the cpuid leaf 0xb is actually implemented. + */ + if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) + return; + + set_cpu_cap(c, X86_FEATURE_XTOPOLOGY); + + /* + * initial apic id, which also represents 32-bit extended x2apic id. + */ + c->initial_apicid = edx; + + /* + * Populate HT related information from sub-leaf level 0. + */ + core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); + core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); + + sub_index = 1; + do { + cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx); + + /* + * Check for the Core type in the implemented sub leaves. + */ + if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) { + core_level_siblings = LEVEL_MAX_SIBLINGS(ebx); + core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); + break; + } + + sub_index++; + } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE); + + core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; + +#ifdef CONFIG_X86_32 + c->cpu_core_id = phys_pkg_id(c->initial_apicid, ht_mask_width) + & core_select_mask; + c->phys_proc_id = phys_pkg_id(c->initial_apicid, core_plus_mask_width); +#else + c->cpu_core_id = phys_pkg_id(ht_mask_width) & core_select_mask; + c->phys_proc_id = phys_pkg_id(core_plus_mask_width); +#endif + c->x86_max_cores = (core_level_siblings / smp_num_siblings); + + + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + c->phys_proc_id); + if (c->x86_max_cores > 1) + printk(KERN_INFO "CPU: Processor Core ID: %d\n", + c->cpu_core_id); + return; +} + #ifdef CONFIG_X86_PAT void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) { diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index af569a964e7..a2888c7b56a 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -128,6 +128,9 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) u32 eax, ebx, ecx, edx; int index_msb, core_bits; + if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) + return; + cpuid(1, &eax, &ebx, &ecx, &edx); diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 77618c717d7..58a6f1a0b29 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -176,9 +176,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if (p) strcpy(c->x86_model_id, p); - c->x86_max_cores = num_cpu_cores(c); - - detect_ht(c); + detect_extended_topology(c); + + if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) { + /* + * let's use the legacy cpuid vector 0x1 and 0x4 for topology + * detection. + */ + c->x86_max_cores = num_cpu_cores(c); + detect_ht(c); + } /* Work around errata */ Intel_errata_workarounds(c); diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c index 1019c58d39f..42d501a8c41 100644 --- a/arch/x86/kernel/cpu/intel_64.c +++ b/arch/x86/kernel/cpu/intel_64.c @@ -80,7 +80,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if (c->x86 == 6) set_cpu_cap(c, X86_FEATURE_REP_GOOD); set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - c->x86_max_cores = intel_num_cpu_cores(c); + + detect_extended_topology(c); + if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) + c->x86_max_cores = intel_num_cpu_cores(c); srat_detect_node(); } -- cgit v1.2.3 From e17941b0c140562d92e5a3bc12b4ad88281c7926 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Sat, 23 Aug 2008 17:47:11 +0200 Subject: x86: use x2apic id reported by cpuid during topology discovery use x2apic id reported by cpuid during topology discovery, instead of the apic id configured in the APIC. For most of the systems, x2apic id reported by cpuid leaf 0xb will be same as the physical apic id reported by the APIC_ID register of the APIC. We follow the suggested guidelines and use the apic id reported by the cpuid. No change to non-generic UV platforms, will use the apic id reported in the APIC_ID register as the cpuid reported apic id's may not be unique. Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_cluster.c | 7 +------ arch/x86/kernel/genx2apic_phys.c | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index ef3f3182d50..0bf0a8624b8 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -120,14 +120,9 @@ static unsigned long set_apic_id(unsigned int id) return x; } -static unsigned int x2apic_read_id(void) -{ - return apic_read(APIC_ID); -} - static unsigned int phys_pkg_id(int index_msb) { - return x2apic_read_id() >> index_msb; + return current_cpu_data.initial_apicid >> index_msb; } static void x2apic_send_IPI_self(int vector) diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 3229c68aedd..e2401ab0c46 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -118,14 +118,9 @@ static unsigned long set_apic_id(unsigned int id) return x; } -static unsigned int x2apic_read_id(void) -{ - return apic_read(APIC_ID); -} - static unsigned int phys_pkg_id(int index_msb) { - return x2apic_read_id() >> index_msb; + return current_cpu_data.initial_apicid >> index_msb; } void x2apic_send_IPI_self(int vector) -- cgit v1.2.3 From 072bd413b88c17509c7aa7dbc398ab8bade633b3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 18 Aug 2008 20:36:17 -0700 Subject: sparc64: Add JBUS NUMA detection. Signed-off-by: David S. Miller --- arch/sparc64/mm/init.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'arch') diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index b4aeb0f696d..75d82e293c8 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -938,6 +938,10 @@ int of_node_to_nid(struct device_node *dp) int count, nid; u64 grp; + /* This is the right thing to do on currently supported + * SUN4U NUMA platforms as well, as the PCI controller does + * not sit behind any particular memory controller. + */ if (!mlgroups) return -1; @@ -1206,8 +1210,44 @@ out: return err; } +static int __init numa_parse_jbus(void) +{ + unsigned long cpu, index; + + /* NUMA node id is encoded in bits 36 and higher, and there is + * a 1-to-1 mapping from CPU ID to NUMA node ID. + */ + index = 0; + for_each_present_cpu(cpu) { + numa_cpu_lookup_table[cpu] = index; + numa_cpumask_lookup_table[index] = cpumask_of_cpu(cpu); + node_masks[index].mask = ~((1UL << 36UL) - 1UL); + node_masks[index].val = cpu << 36UL; + + index++; + } + num_node_masks = index; + + add_node_ranges(); + + for (index = 0; index < num_node_masks; index++) { + allocate_node_data(index); + node_set_online(index); + } + + return 0; +} + static int __init numa_parse_sun4u(void) { + if (tlb_type == cheetah || tlb_type == cheetah_plus) { + unsigned long ver; + + __asm__ ("rdpr %%ver, %0" : "=r" (ver)); + if ((ver >> 32UL) == __JALAPENO_ID || + (ver >> 32UL) == __SERRANO_ID) + return numa_parse_jbus(); + } return -1; } -- cgit v1.2.3 From 2481d76615d5e15340ccfb0243fe8779766dfc6e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 19 Aug 2008 21:56:35 -0700 Subject: sparc: Add mutex for set property calls. On some platforms, the I2C controller is shared between the OS and OBP. OBP uses this I2C controller to access the EEPROM, and thus is programmed when the kernel calls prom_setprop(). Wrap such calls with the new of_set_property_mutex. Relevant I2C bus drivers can grab this mutex around top-level I2C operations to provide the proper protection. Signed-off-by: David S. Miller --- arch/sparc/include/asm/prom.h | 2 ++ arch/sparc/kernel/prom.c | 6 ++++++ arch/sparc64/kernel/prom.c | 6 ++++++ 3 files changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index fd55522481c..b5efc4d8523 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -18,6 +18,7 @@ */ #include #include +#include #include #define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 @@ -73,6 +74,7 @@ struct of_irq_controller { extern struct device_node *of_find_node_by_cpuid(int cpuid); extern int of_set_property(struct device_node *node, const char *name, void *val, int len); +extern struct mutex of_set_property_mutex; extern int of_getintprop_default(struct device_node *np, const char *name, int def); diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index cd4fb79aa3a..43e86240682 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -54,6 +54,9 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); +DEFINE_MUTEX(of_set_property_mutex); +EXPORT_SYMBOL(of_set_property_mutex); + int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; @@ -77,7 +80,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *old_val = prop->value; int ret; + mutex_lock(&of_set_property_mutex); ret = prom_setprop(dp->node, (char *) name, val, len); + mutex_unlock(&of_set_property_mutex); + err = -EINVAL; if (ret >= 0) { prop->value = new_val; diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 3c048ac4e63..922dd612612 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -59,6 +59,9 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); +DEFINE_MUTEX(of_set_property_mutex); +EXPORT_SYMBOL(of_set_property_mutex); + int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; @@ -82,7 +85,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *old_val = prop->value; int ret; + mutex_lock(&of_set_property_mutex); ret = prom_setprop(dp->node, name, val, len); + mutex_unlock(&of_set_property_mutex); + err = -EINVAL; if (ret >= 0) { prop->value = new_val; -- cgit v1.2.3 From 44266215e3c8209613cea014721015113b7cd2d9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 20 Aug 2008 16:34:39 -0700 Subject: sparc: Implement irq_of_parse_and_map() and irq_dispose_mapping(). This allows more OF layer code to be shared between powerpc and sparc. Signed-off-by: David S. Miller --- arch/sparc/include/asm/prom.h | 8 ++++++++ arch/sparc/kernel/of_device.c | 11 +++++++++++ arch/sparc64/kernel/of_device.c | 11 +++++++++++ 3 files changed, 30 insertions(+) (limited to 'arch') diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index b5efc4d8523..58b85fa5606 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -96,6 +96,14 @@ static inline void of_node_put(struct device_node *node) { } +/* These routines are here to provide compatibility with how powerpc + * handles IRQ mapping for OF device nodes. We precompute and permanently + * register them in the of_device objects, whereas powerpc computes them + * on request. + */ +extern int irq_of_parse_and_map(struct device_node *node, int index); +#define irq_dispose_mapping(irq) do { } while (0) + /* * NB: This is here while we transition from using asm/prom.h * to linux/of.h diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index cc4c235c4f5..56e9a718ef8 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -29,6 +29,17 @@ struct of_device *of_find_device_by_node(struct device_node *dp) } EXPORT_SYMBOL(of_find_device_by_node); +int irq_of_parse_and_map(struct device_node *node, int index) +{ + struct of_device *op = of_find_device_by_node(node); + + if (!op || index >= op->num_irqs) + return 0xffffffff; + + return op->irqs[index]; +} +EXPORT_SYMBOL(irq_of_parse_and_map); + #ifdef CONFIG_PCI struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index f8b50cbf4bf..8a0d82343a2 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -55,6 +55,17 @@ struct of_device *of_find_device_by_node(struct device_node *dp) } EXPORT_SYMBOL(of_find_device_by_node); +int irq_of_parse_and_map(struct device_node *node, int index) +{ + struct of_device *op = of_find_device_by_node(node); + + if (!op || index >= op->num_irqs) + return 0xffffffff; + + return op->irqs[index]; +} +EXPORT_SYMBOL(irq_of_parse_and_map); + #ifdef CONFIG_PCI struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); -- cgit v1.2.3 From 15df0f3302fdecaa97da0b95d72b3a9a59be8692 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 20 Aug 2008 23:03:24 -0700 Subject: sparc: Add GPIO layer support. Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 6 ++++++ arch/sparc/include/asm/gpio.h | 36 ++++++++++++++++++++++++++++++++++++ arch/sparc64/Kconfig | 6 ++++++ 3 files changed, 48 insertions(+) create mode 100644 arch/sparc/include/asm/gpio.h (limited to 'arch') diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index a214002114e..cb1dd356b27 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -20,6 +20,11 @@ config GENERIC_ISA_DMA bool default y +config GENERIC_GPIO + bool + help + Generic GPIO API support + config ARCH_NO_VIRT_TO_BUS def_bool y @@ -69,6 +74,7 @@ config SPARC select HAVE_OPROFILE select HAVE_ARCH_KGDB if !SMP select HAVE_ARCH_TRACEHOOK + select ARCH_WANT_OPTIONAL_GPIOLIB # Identify this as a Sparc32 build config SPARC32 diff --git a/arch/sparc/include/asm/gpio.h b/arch/sparc/include/asm/gpio.h new file mode 100644 index 00000000000..a0e3ac0af59 --- /dev/null +++ b/arch/sparc/include/asm/gpio.h @@ -0,0 +1,36 @@ +#ifndef __ASM_SPARC_GPIO_H +#define __ASM_SPARC_GPIO_H + +#include +#include + +#ifdef CONFIG_GPIOLIB + +static inline int gpio_get_value(unsigned int gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned int gpio, int value) +{ + __gpio_set_value(gpio, value); +} + +static inline int gpio_cansleep(unsigned int gpio) +{ + return __gpio_cansleep(gpio); +} + +static inline int gpio_to_irq(unsigned int gpio) +{ + return -ENOSYS; +} + +static inline int irq_to_gpio(unsigned int irq) +{ + return -EINVAL; +} + +#endif /* CONFIG_GPIOLIB */ + +#endif /* __ASM_SPARC_GPIO_H */ diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 923a98959fa..489b6912fa0 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -18,6 +18,7 @@ config SPARC64 select HAVE_ARCH_KGDB select USE_GENERIC_SMP_HELPERS if SMP select HAVE_ARCH_TRACEHOOK + select ARCH_WANT_OPTIONAL_GPIOLIB config GENERIC_TIME bool @@ -31,6 +32,11 @@ config GENERIC_CLOCKEVENTS bool default y +config GENERIC_GPIO + bool + help + Generic GPIO API support + config 64BIT def_bool y -- cgit v1.2.3 From fe06ccaad20257e3bd348b2df9e811fd92211a80 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 20:10:23 -0700 Subject: sparc64: Split syscall_trace() into two functions. Christoph Hellwig noticed that having both entry and exit logic in one function no longer makes sense, and having seperate ones simplifies things a lot. Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.h | 3 ++- arch/sparc64/kernel/ptrace.c | 38 +++++++++++++++++++------------------ arch/sparc64/kernel/sparc64_ksyms.c | 1 - arch/sparc64/kernel/syscalls.S | 20 ++++++++----------- 4 files changed, 30 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index fc294a29289..2255244442f 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -22,7 +22,8 @@ extern void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags); -extern asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p); +extern asmlinkage int syscall_trace_enter(struct pt_regs *regs); +extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); extern void bad_trap_tl1(struct pt_regs *regs, long lvl); diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index bd578cc4856..db2ddf2e829 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -1050,31 +1050,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } -asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) +asmlinkage int syscall_trace_enter(struct pt_regs *regs) { int ret = 0; /* do the secure computing check first */ secure_computing(regs->u_regs[UREG_G1]); - if (unlikely(current->audit_context) && syscall_exit_p) { - unsigned long tstate = regs->tstate; - int result = AUDITSC_SUCCESS; - - if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) - result = AUDITSC_FAILURE; - - audit_syscall_exit(result, regs->u_regs[UREG_I0]); - } - - if (test_thread_flag(TIF_SYSCALL_TRACE)) { - if (syscall_exit_p) - tracehook_report_syscall_exit(regs, 0); - else - ret = tracehook_report_syscall_entry(regs); - } + if (test_thread_flag(TIF_SYSCALL_TRACE)) + ret = tracehook_report_syscall_entry(regs); - if (unlikely(current->audit_context) && !syscall_exit_p && !ret) + if (unlikely(current->audit_context) && !ret) audit_syscall_entry((test_thread_flag(TIF_32BIT) ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64), @@ -1086,3 +1072,19 @@ asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) return ret; } + +asmlinkage void syscall_trace_leave(struct pt_regs *regs) +{ + if (unlikely(current->audit_context)) { + unsigned long tstate = regs->tstate; + int result = AUDITSC_SUCCESS; + + if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) + result = AUDITSC_FAILURE; + + audit_syscall_exit(result, regs->u_regs[UREG_I0]); + } + + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, 0); +} diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 0804f71df6c..d44b2eeb25d 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -68,7 +68,6 @@ extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); extern __kernel_size_t strlen(const char *); -extern void syscall_trace(struct pt_regs *, int); extern void sys_sigsuspend(void); extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); diff --git a/arch/sparc64/kernel/syscalls.S b/arch/sparc64/kernel/syscalls.S index a2f24270ed8..7a6786a7136 100644 --- a/arch/sparc64/kernel/syscalls.S +++ b/arch/sparc64/kernel/syscalls.S @@ -65,9 +65,8 @@ sys32_rt_sigreturn: andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 be,pt %icc, rtrap nop - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 + call syscall_trace_leave + add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap nop @@ -159,9 +158,8 @@ linux_sparc_ni_syscall: or %l7, %lo(sys_ni_syscall), %l7 linux_syscall_trace32: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - clr %o1 + call syscall_trace_enter + add %sp, PTREGS_OFF, %o0 brnz,pn %o0, 3f mov -ENOSYS, %o0 srl %i0, 0, %o0 @@ -172,9 +170,8 @@ linux_syscall_trace32: srl %i3, 0, %o3 linux_syscall_trace: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - clr %o1 + call syscall_trace_enter + add %sp, PTREGS_OFF, %o0 brnz,pn %o0, 3f mov -ENOSYS, %o0 mov %i0, %o0 @@ -275,9 +272,8 @@ ret_sys_call: b,pt %xcc, rtrap stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] linux_syscall_trace2: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 + call syscall_trace_leave + add %sp, PTREGS_OFF, %o0 stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ba,pt %xcc, rtrap stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] -- cgit v1.2.3 From 8394b3a84bf3e4665da4e535d34980aa6ba78969 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 20:13:42 -0700 Subject: sparc64: Kill duplicated sys_pause() implementation. sys32_pause() is identical to the generically provided sys_pause() in kernel/signal.c Noticed by Christoph Hellwig. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sys_sparc32.c | 8 -------- arch/sparc64/kernel/systbls.S | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 3d118531baf..3320c9d0075 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -575,14 +575,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } -/* These are here just in case some old sparc32 binary calls it. */ -asmlinkage long sys32_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 0fdbf3ba956..5daee4b04dd 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -23,7 +23,7 @@ sys_call_table32: /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod /*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 -/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause +/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid -- cgit v1.2.3 From b28422e32b9127ab4178ce05a419069db3d11d19 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 21:32:42 -0700 Subject: sparc64: Convert UltraSPARC-III memory controller driver to OF driver probing. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 119 +++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 41 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 6d4f02e8a4c..b9cd736a11f 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -1,6 +1,6 @@ -/* memctrlr.c: Driver for UltraSPARC-III memory controller. +/* chmc.c: Driver for UltraSPARC-III memory controller. * - * Copyright (C) 2001, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 2001, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include @@ -13,13 +13,25 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include +#define DRV_MODULE_NAME "chmc" +#define PFX DRV_MODULE_NAME ": " +#define DRV_MODULE_VERSION "0.2" + +MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); +MODULE_DESCRIPTION("UltraSPARC-III memory controller driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_MODULE_VERSION); + #define CHMCTRL_NDGRPS 2 #define CHMCTRL_NDIMMS 4 @@ -343,16 +355,25 @@ static void fetch_decode_regs(struct mctrl_info *mp) read_mcreg(mp, CHMCTRL_DECODE4)); } -static int init_one_mctrl(struct device_node *dp) +static int __devinit chmc_probe(struct of_device *op, + const struct of_device_id *match) { - struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL); - int portid = of_getintprop_default(dp, "portid", -1); - const struct linux_prom64_registers *regs; + struct device_node *dp = op->node; + struct mctrl_info *mp; + unsigned long ver; const void *pval; - int len; + int len, portid; + + __asm__ ("rdpr %%ver, %0" : "=r" (ver)); + if ((ver >> 32UL) == __JALAPENO_ID || + (ver >> 32UL) == __SERRANO_ID) + return -ENODEV; + mp = kzalloc(sizeof(*mp), GFP_KERNEL); if (!mp) - return -1; + return -ENOMEM; + + portid = of_getintprop_default(dp, "portid", -1); if (portid == -1) goto fail; @@ -362,18 +383,19 @@ static int init_one_mctrl(struct device_node *dp) if (!pval) mp->layout_size = 0; else { - if (mp->layout_size > sizeof(mp->layout_prop)) + if (mp->layout_size > sizeof(mp->layout_prop)) { + printk(KERN_ERR PFX "Unexpected memory-layout property " + "size %d.\n", mp->layout_size); goto fail; + } memcpy(&mp->layout_prop, pval, len); } - regs = of_get_property(dp, "reg", NULL); - if (!regs || regs->reg_size != 0x48) - goto fail; - - mp->regs = ioremap(regs->phys_addr, regs->reg_size); - if (mp->regs == NULL) + mp->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); + if (!mp->regs) { + printk(KERN_ERR PFX "Could not map registers.\n"); goto fail; + } if (mp->layout_size != 0UL) { mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); @@ -388,54 +410,69 @@ static int init_one_mctrl(struct device_node *dp) list_add(&mp->list, &mctrl_list); /* Report the device. */ - printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n", + printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", dp->full_name, - mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); + (mp->layout_size ? "ACTIVE" : "INACTIVE")); + + dev_set_drvdata(&op->dev, mp); return 0; fail: if (mp) { if (mp->regs != NULL) - iounmap(mp->regs); + of_iounmap(&op->resource[0], mp->regs, 0x48); kfree(mp); } return -1; } -static int __init chmc_init(void) +static int __devexit chmc_remove(struct of_device *op) { - struct device_node *dp; + struct mctrl_info *mp = dev_get_drvdata(&op->dev); - /* This driver is only for cheetah platforms. */ - if (tlb_type != cheetah && tlb_type != cheetah_plus) - return -ENODEV; + if (mp) { + list_del(&mp->list); + of_iounmap(&op->resource[0], mp->regs, 0x48); + kfree(mp); + } + return 0; +} - for_each_node_by_name(dp, "memory-controller") - init_one_mctrl(dp); +static struct of_device_id chmc_match[] = { + { + .name = "memory-controller", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, chmc_match); - for_each_node_by_name(dp, "mc-us3") - init_one_mctrl(dp); +static struct of_platform_driver chmc_driver = { + .name = "chmc", + .match_table = chmc_match, + .probe = chmc_probe, + .remove = __devexit_p(chmc_remove), +}; - return 0; +static inline bool chmc_platform(void) +{ + if (tlb_type == cheetah || tlb_type == cheetah_plus) + return true; + return false; } -static void __exit chmc_cleanup(void) +static int __init chmc_init(void) { - struct list_head *head = &mctrl_list; - struct list_head *tmp = head->next; + if (!chmc_platform()) + return -ENODEV; - for (;;) { - struct mctrl_info *p = - list_entry(tmp, struct mctrl_info, list); - if (tmp == head) - break; - tmp = tmp->next; + return of_register_driver(&chmc_driver, &of_bus_type); +} - list_del(&p->list); - iounmap(p->regs); - kfree(p); - } +static void __exit chmc_cleanup(void) +{ + if (chmc_platform()) + of_unregister_driver(&chmc_driver); } module_init(chmc_init); -- cgit v1.2.3 From 83ef64b9dea6e3ed287a45d56166913bffcd2497 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 21:45:44 -0700 Subject: sparc64: Use consistent chmc_ prefix in variables, types, and functions. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 237 +++++++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 117 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index b9cd736a11f..2f73ddc8676 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -35,35 +35,35 @@ MODULE_VERSION(DRV_MODULE_VERSION); #define CHMCTRL_NDGRPS 2 #define CHMCTRL_NDIMMS 4 -#define DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) +#define CHMC_DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) /* OBP memory-layout property format. */ -struct obp_map { +struct chmc_obp_map { unsigned char dimm_map[144]; unsigned char pin_map[576]; }; #define DIMM_LABEL_SZ 8 -struct obp_mem_layout { +struct chmc_obp_mem_layout { /* One max 8-byte string label per DIMM. Usually * this matches the label on the motherboard where * that DIMM resides. */ - char dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ]; + char dimm_labels[CHMC_DIMMS_PER_MC][DIMM_LABEL_SZ]; /* If symmetric use map[0], else it is * asymmetric and map[1] should be used. */ - char symmetric; + char symmetric; - struct obp_map map[2]; + struct chmc_obp_map map[2]; }; #define CHMCTRL_NBANKS 4 -struct bank_info { - struct mctrl_info *mp; +struct chmc_bank_info { + struct chmc *p; int bank_id; u64 raw_reg; @@ -77,28 +77,28 @@ struct bank_info { unsigned long size; }; -struct mctrl_info { - struct list_head list; - int portid; +struct chmc { + struct list_head list; + int portid; - struct obp_mem_layout layout_prop; - int layout_size; + struct chmc_obp_mem_layout layout_prop; + int layout_size; - void __iomem *regs; + void __iomem *regs; - u64 timing_control1; - u64 timing_control2; - u64 timing_control3; - u64 timing_control4; - u64 memaddr_control; + u64 timing_control1; + u64 timing_control2; + u64 timing_control3; + u64 timing_control4; + u64 memaddr_control; - struct bank_info logical_banks[CHMCTRL_NBANKS]; + struct chmc_bank_info logical_banks[CHMCTRL_NBANKS]; }; static LIST_HEAD(mctrl_list); /* Does BANK decode PHYS_ADDR? */ -static int bank_match(struct bank_info *bp, unsigned long phys_addr) +static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) { unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; @@ -130,14 +130,13 @@ static int bank_match(struct bank_info *bp, unsigned long phys_addr) } /* Given PHYS_ADDR, search memory controller banks for a match. */ -static struct bank_info *find_bank(unsigned long phys_addr) +static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) { struct list_head *mctrl_head = &mctrl_list; struct list_head *mctrl_entry = mctrl_head->next; for (;;) { - struct mctrl_info *mp = - list_entry(mctrl_entry, struct mctrl_info, list); + struct chmc *p = list_entry(mctrl_entry, struct chmc, list); int bank_no; if (mctrl_entry == mctrl_head) @@ -145,10 +144,10 @@ static struct bank_info *find_bank(unsigned long phys_addr) mctrl_entry = mctrl_entry->next; for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { - struct bank_info *bp; + struct chmc_bank_info *bp; - bp = &mp->logical_banks[bank_no]; - if (bank_match(bp, phys_addr)) + bp = &p->logical_banks[bank_no]; + if (chmc_bank_match(bp, phys_addr)) return bp; } } @@ -163,11 +162,11 @@ int chmc_getunumber(int syndrome_code, unsigned long phys_addr, char *buf, int buflen) { - struct bank_info *bp; - struct obp_mem_layout *prop; + struct chmc_bank_info *bp; + struct chmc_obp_mem_layout *prop; int bank_in_controller, first_dimm; - bp = find_bank(phys_addr); + bp = chmc_find_bank(phys_addr); if (bp == NULL || syndrome_code < SYNDROME_MIN || syndrome_code > SYNDROME_MAX) { @@ -178,13 +177,13 @@ int chmc_getunumber(int syndrome_code, return 0; } - prop = &bp->mp->layout_prop; + prop = &bp->p->layout_prop; bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); first_dimm *= CHMCTRL_NDIMMS; if (syndrome_code != SYNDROME_MIN) { - struct obp_map *map; + struct chmc_obp_map *map; int qword, where_in_line, where, map_index, map_offset; unsigned int map_val; @@ -252,7 +251,7 @@ int chmc_getunumber(int syndrome_code, * the code is executing, you must use special ASI load/store else * you go through the global mapping. */ -static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) +static u64 chmc_read_mcreg(struct chmc *p, unsigned long offset) { unsigned long ret, this_cpu; @@ -260,14 +259,14 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) this_cpu = real_hard_smp_processor_id(); - if (mp->portid == this_cpu) { + if (p->portid == this_cpu) { __asm__ __volatile__("ldxa [%1] %2, %0" : "=r" (ret) : "r" (offset), "i" (ASI_MCU_CTRL_REG)); } else { __asm__ __volatile__("ldxa [%1] %2, %0" : "=r" (ret) - : "r" (mp->regs + offset), + : "r" (p->regs + offset), "i" (ASI_PHYS_BYPASS_EC_E)); } @@ -277,164 +276,168 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) } #if 0 /* currently unused */ -static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val) +static void chmc_write_mcreg(struct chmc *p, unsigned long offset, u64 val) { - if (mp->portid == smp_processor_id()) { + if (p->portid == smp_processor_id()) { __asm__ __volatile__("stxa %0, [%1] %2" : : "r" (val), "r" (offset), "i" (ASI_MCU_CTRL_REG)); } else { __asm__ __volatile__("ldxa %0, [%1] %2" : : "r" (val), - "r" (mp->regs + offset), + "r" (p->regs + offset), "i" (ASI_PHYS_BYPASS_EC_E)); } } #endif -static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val) +static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 val) { - struct bank_info *p = &mp->logical_banks[which_bank]; - - p->mp = mp; - p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank; - p->raw_reg = val; - p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; - p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; - p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; - p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; - p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; - - p->base = (p->um); - p->base &= ~(p->uk); - p->base <<= PA_UPPER_BITS_SHIFT; - - switch(p->lk) { + struct chmc_bank_info *bp = &p->logical_banks[which_bank]; + + bp->p = p; + bp->bank_id = (CHMCTRL_NBANKS * p->portid) + which_bank; + bp->raw_reg = val; + bp->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; + bp->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; + bp->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; + bp->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; + bp->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; + + bp->base = (bp->um); + bp->base &= ~(bp->uk); + bp->base <<= PA_UPPER_BITS_SHIFT; + + switch(bp->lk) { case 0xf: default: - p->interleave = 1; + bp->interleave = 1; break; case 0xe: - p->interleave = 2; + bp->interleave = 2; break; case 0xc: - p->interleave = 4; + bp->interleave = 4; break; case 0x8: - p->interleave = 8; + bp->interleave = 8; break; case 0x0: - p->interleave = 16; + bp->interleave = 16; break; }; /* UK[10] is reserved, and UK[11] is not set for the SDRAM * bank size definition. */ - p->size = (((unsigned long)p->uk & - ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; - p->size /= p->interleave; + bp->size = (((unsigned long)bp->uk & + ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; + bp->size /= bp->interleave; } -static void fetch_decode_regs(struct mctrl_info *mp) +static void chmc_fetch_decode_regs(struct chmc *p) { - if (mp->layout_size == 0) + if (p->layout_size == 0) return; - interpret_one_decode_reg(mp, 0, - read_mcreg(mp, CHMCTRL_DECODE1)); - interpret_one_decode_reg(mp, 1, - read_mcreg(mp, CHMCTRL_DECODE2)); - interpret_one_decode_reg(mp, 2, - read_mcreg(mp, CHMCTRL_DECODE3)); - interpret_one_decode_reg(mp, 3, - read_mcreg(mp, CHMCTRL_DECODE4)); + chmc_interpret_one_decode_reg(p, 0, + chmc_read_mcreg(p, CHMCTRL_DECODE1)); + chmc_interpret_one_decode_reg(p, 1, + chmc_read_mcreg(p, CHMCTRL_DECODE2)); + chmc_interpret_one_decode_reg(p, 2, + chmc_read_mcreg(p, CHMCTRL_DECODE3)); + chmc_interpret_one_decode_reg(p, 3, + chmc_read_mcreg(p, CHMCTRL_DECODE4)); } static int __devinit chmc_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct mctrl_info *mp; unsigned long ver; const void *pval; int len, portid; + struct chmc *p; + int err; + err = -ENODEV; __asm__ ("rdpr %%ver, %0" : "=r" (ver)); if ((ver >> 32UL) == __JALAPENO_ID || (ver >> 32UL) == __SERRANO_ID) - return -ENODEV; - - mp = kzalloc(sizeof(*mp), GFP_KERNEL); - if (!mp) - return -ENOMEM; + goto out; portid = of_getintprop_default(dp, "portid", -1); if (portid == -1) - goto fail; + goto out; - mp->portid = portid; pval = of_get_property(dp, "memory-layout", &len); - mp->layout_size = len; - if (!pval) - mp->layout_size = 0; - else { - if (mp->layout_size > sizeof(mp->layout_prop)) { - printk(KERN_ERR PFX "Unexpected memory-layout property " - "size %d.\n", mp->layout_size); - goto fail; - } - memcpy(&mp->layout_prop, pval, len); + if (pval && len > sizeof(p->layout_prop)) { + printk(KERN_ERR PFX "Unexpected memory-layout property " + "size %d.\n", len); + goto out; + } + + err = -ENOMEM; + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) { + printk(KERN_ERR PFX "Could not allocate struct chmc.\n"); + goto out; } - mp->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); - if (!mp->regs) { + p->portid = portid; + p->layout_size = len; + if (!pval) + p->layout_size = 0; + else + memcpy(&p->layout_prop, pval, len); + + p->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); + if (!p->regs) { printk(KERN_ERR PFX "Could not map registers.\n"); - goto fail; + goto out_free; } - if (mp->layout_size != 0UL) { - mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); - mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2); - mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3); - mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4); - mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL); + if (p->layout_size != 0UL) { + p->timing_control1 = chmc_read_mcreg(p, CHMCTRL_TCTRL1); + p->timing_control2 = chmc_read_mcreg(p, CHMCTRL_TCTRL2); + p->timing_control3 = chmc_read_mcreg(p, CHMCTRL_TCTRL3); + p->timing_control4 = chmc_read_mcreg(p, CHMCTRL_TCTRL4); + p->memaddr_control = chmc_read_mcreg(p, CHMCTRL_MACTRL); } - fetch_decode_regs(mp); + chmc_fetch_decode_regs(p); - list_add(&mp->list, &mctrl_list); + list_add(&p->list, &mctrl_list); /* Report the device. */ printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", dp->full_name, - (mp->layout_size ? "ACTIVE" : "INACTIVE")); + (p->layout_size ? "ACTIVE" : "INACTIVE")); - dev_set_drvdata(&op->dev, mp); + dev_set_drvdata(&op->dev, p); - return 0; + err = 0; -fail: - if (mp) { - if (mp->regs != NULL) - of_iounmap(&op->resource[0], mp->regs, 0x48); - kfree(mp); - } - return -1; +out: + return err; + +out_free: + kfree(p); + goto out; } static int __devexit chmc_remove(struct of_device *op) { - struct mctrl_info *mp = dev_get_drvdata(&op->dev); + struct chmc *p = dev_get_drvdata(&op->dev); - if (mp) { - list_del(&mp->list); - of_iounmap(&op->resource[0], mp->regs, 0x48); - kfree(mp); + if (p) { + list_del(&p->list); + of_iounmap(&op->resource[0], p->regs, 0x48); + kfree(p); } return 0; } -- cgit v1.2.3 From 881d021ab0d675f519b68df916fde969940ef988 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 22:08:34 -0700 Subject: sparc64: Add generic interface for registering a dimm printing handler. The way to do this varies by platform type and the exact memory controller the cpu uses. For Spitfire cpus we currently just use prom_getunumber() and hope that works. For Cheetah cpus we have a memory controller driver that can compute this information. Signed-off-by: David S. Miller --- arch/sparc/include/asm/memctrl.h | 9 ++++++ arch/sparc64/kernel/chmc.c | 21 ++++++++++---- arch/sparc64/kernel/traps.c | 62 ++++++++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 arch/sparc/include/asm/memctrl.h (limited to 'arch') diff --git a/arch/sparc/include/asm/memctrl.h b/arch/sparc/include/asm/memctrl.h new file mode 100644 index 00000000000..4065c56af7b --- /dev/null +++ b/arch/sparc/include/asm/memctrl.h @@ -0,0 +1,9 @@ +#ifndef _SPARC_MEMCTRL_H +#define _SPARC_MEMCTRL_H + +typedef int (*dimm_printer_t)(int synd_code, unsigned long paddr, char *buf, int buflen); + +int register_dimm_printer(dimm_printer_t func); +void unregister_dimm_printer(dimm_printer_t func); + +#endif /* _SPARC_MEMCTRL_H */ diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 2f73ddc8676..a3c79fd5dd3 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -22,6 +22,7 @@ #include #include #include +#include #define DRV_MODULE_NAME "chmc" #define PFX DRV_MODULE_NAME ": " @@ -158,9 +159,9 @@ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) /* This is the main purpose of this driver. */ #define SYNDROME_MIN -1 #define SYNDROME_MAX 144 -int chmc_getunumber(int syndrome_code, - unsigned long phys_addr, - char *buf, int buflen) +static int chmc_print_dimm(int syndrome_code, + unsigned long phys_addr, + char *buf, int buflen) { struct chmc_bank_info *bp; struct chmc_obp_mem_layout *prop; @@ -466,16 +467,26 @@ static inline bool chmc_platform(void) static int __init chmc_init(void) { + int ret; + if (!chmc_platform()) return -ENODEV; - return of_register_driver(&chmc_driver, &of_bus_type); + ret = register_dimm_printer(chmc_print_dimm); + if (!ret) { + ret = of_register_driver(&chmc_driver, &of_bus_type); + if (ret) + unregister_dimm_printer(chmc_print_dimm); + } + return ret; } static void __exit chmc_cleanup(void) { - if (chmc_platform()) + if (chmc_platform()) { + unregister_dimm_printer(chmc_print_dimm); of_unregister_driver(&chmc_driver); + } } module_init(chmc_init); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 3d924121c79..17880ccfa3c 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "entry.h" #include "kstack.h" @@ -128,6 +129,55 @@ void do_BUG(const char *file, int line) } #endif +static DEFINE_SPINLOCK(dimm_handler_lock); +static dimm_printer_t dimm_handler; + +static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen) +{ + unsigned long flags; + int ret = -ENODEV; + + spin_lock_irqsave(&dimm_handler_lock, flags); + if (dimm_handler) { + ret = dimm_handler(synd_code, paddr, buf, buflen); + } else if (tlb_type == spitfire) { + if (prom_getunumber(synd_code, paddr, buf, buflen) == -1) + ret = -EINVAL; + else + ret = 0; + } else + ret = -ENODEV; + spin_unlock_irqrestore(&dimm_handler_lock, flags); + + return ret; +} + +int register_dimm_printer(dimm_printer_t func) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&dimm_handler_lock, flags); + if (!dimm_handler) + dimm_handler = func; + else + ret = -EEXIST; + spin_unlock_irqrestore(&dimm_handler_lock, flags); + + return ret; +} + +void unregister_dimm_printer(dimm_printer_t func) +{ + unsigned long flags; + + spin_lock_irqsave(&dimm_handler_lock, flags); + if (dimm_handler == func) + dimm_handler = NULL; + spin_unlock_irqrestore(&dimm_handler_lock, flags); +} + + void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) { siginfo_t info; @@ -375,8 +425,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un if (udbl & bit) { scode = ecc_syndrome_table[udbl & 0xff]; - if (prom_getunumber(scode, afar, - memmod_str, sizeof(memmod_str)) == -1) + if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) p = syndrome_unknown; else p = memmod_str; @@ -387,8 +436,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un if (udbh & bit) { scode = ecc_syndrome_table[udbh & 0xff]; - if (prom_getunumber(scode, afar, - memmod_str, sizeof(memmod_str)) == -1) + if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) p = syndrome_unknown; else p = memmod_str; @@ -1061,8 +1109,6 @@ static const char *cheetah_get_string(unsigned long bit) return "???"; } -extern int chmc_getunumber(int, unsigned long, char *, int); - static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, unsigned long afsr, unsigned long afar, int recoverable) { @@ -1104,7 +1150,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; syndrome = cheetah_ecc_syntab[syndrome]; - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); + ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); if (ret != -1) printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", (recoverable ? KERN_WARNING : KERN_CRIT), @@ -1115,7 +1161,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; syndrome = cheetah_mtag_syntab[syndrome]; - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); + ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); if (ret != -1) printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", (recoverable ? KERN_WARNING : KERN_CRIT), -- cgit v1.2.3 From 41660e9ac639c97840258d3c5294f618ca8cc46f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 22:17:29 -0700 Subject: sparc64: Allow chmc to be built as a module. Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 11 +++++++++++ arch/sparc64/kernel/Makefile | 3 ++- arch/sparc64/kernel/sparc64_ksyms.c | 2 ++ arch/sparc64/kernel/traps.c | 3 ++- 4 files changed, 17 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 489b6912fa0..8df73714caf 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -191,6 +191,17 @@ config US2E_FREQ If in doubt, say N. +config US3_MC + tristate "UltraSPARC-III Memory Controller driver" + default y + help + This adds a driver for the UltraSPARC-III memory controller. + Loading this driver allows exact mnemonic strings to be + printed in the event of a memory error, so that the faulty DIMM + on the motherboard can be matched to the error. + + If in doubt, say Y, as this information can be very useful. + # Global things across all Sun machines. config GENERIC_LOCKBREAK bool diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 418b5782096..313735fa5f2 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -11,7 +11,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o \ - power.o sbus.o sparc64_ksyms.o chmc.o \ + power.o sbus.o sparc64_ksyms.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o @@ -25,6 +25,7 @@ obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o +obj-$(CONFIG_US3_MC) += chmc.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o obj-$(CONFIG_AUDIT) += audit.o diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index d44b2eeb25d..3b2890c207f 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -299,3 +299,5 @@ EXPORT_SYMBOL(xor_niagara_2); EXPORT_SYMBOL(xor_niagara_3); EXPORT_SYMBOL(xor_niagara_4); EXPORT_SYMBOL(xor_niagara_5); + +EXPORT_SYMBOL_GPL(real_hard_smp_processor_id); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 17880ccfa3c..71644da6cad 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -166,6 +166,7 @@ int register_dimm_printer(dimm_printer_t func) return ret; } +EXPORT_SYMBOL_GPL(register_dimm_printer); void unregister_dimm_printer(dimm_printer_t func) { @@ -176,7 +177,7 @@ void unregister_dimm_printer(dimm_printer_t func) dimm_handler = NULL; spin_unlock_irqrestore(&dimm_handler_lock, flags); } - +EXPORT_SYMBOL_GPL(unregister_dimm_printer); void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) { -- cgit v1.2.3 From 93be71b672f167b1e8c23725114f86305354f0ac Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Fri, 22 Aug 2008 11:52:11 +0100 Subject: x86: add cpu hotplug hooks into smp_ops Signed-off-by: Alex Nixon Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_32.c | 4 ++-- arch/x86/kernel/process_64.c | 4 ++-- arch/x86/kernel/smp.c | 6 +++++- arch/x86/kernel/smpboot.c | 8 ++++---- 4 files changed, 13 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 3b7a1ddcc0b..e382fe0ccd6 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -91,7 +91,7 @@ static void cpu_exit_clear(void) } /* We don't actually take CPU down, just spin without interrupts. */ -static inline void play_dead(void) +void native_play_dead(void) { /* This must be done before dead CPU ack */ cpu_exit_clear(); @@ -107,7 +107,7 @@ static inline void play_dead(void) wbinvd_halt(); } #else -static inline void play_dead(void) +void native_play_dead(void) { BUG(); } diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 71553b664e2..dfd3f575208 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -90,7 +90,7 @@ DECLARE_PER_CPU(int, cpu_state); #include /* We halt the CPU with physical CPU hotplug */ -static inline void play_dead(void) +void native_play_dead(void) { idle_task_exit(); mb(); @@ -102,7 +102,7 @@ static inline void play_dead(void) wbinvd_halt(); } #else -static inline void play_dead(void) +void native_play_dead(void) { BUG(); } diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 361b7a4c640..18f9b19f5f8 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -214,12 +214,16 @@ void smp_call_function_single_interrupt(struct pt_regs *regs) struct smp_ops smp_ops = { .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu, .smp_prepare_cpus = native_smp_prepare_cpus, - .cpu_up = native_cpu_up, .smp_cpus_done = native_smp_cpus_done, .smp_send_stop = native_smp_send_stop, .smp_send_reschedule = native_smp_send_reschedule, + .cpu_up = native_cpu_up, + .cpu_die = native_cpu_die, + .cpu_disable = native_cpu_disable, + .play_dead = native_play_dead, + .send_call_func_ipi = native_send_call_func_ipi, .send_call_func_single_ipi = native_send_call_func_single_ipi, }; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7985c5b3f91..c414cee296b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1346,7 +1346,7 @@ static void __ref remove_cpu_from_maps(int cpu) numa_remove_cpu(cpu); } -int __cpu_disable(void) +int native_cpu_disable(void) { int cpu = smp_processor_id(); @@ -1385,7 +1385,7 @@ int __cpu_disable(void) return 0; } -void __cpu_die(unsigned int cpu) +void native_cpu_die(unsigned int cpu) { /* We don't do anything here: idle task is faking death itself. */ unsigned int i; @@ -1403,12 +1403,12 @@ void __cpu_die(unsigned int cpu) printk(KERN_ERR "CPU %u didn't die...\n", cpu); } #else /* ... !CONFIG_HOTPLUG_CPU */ -int __cpu_disable(void) +int native_cpu_disable(void) { return -ENOSYS; } -void __cpu_die(unsigned int cpu) +void native_cpu_die(unsigned int cpu) { /* We said "no" in __cpu_disable */ BUG(); -- cgit v1.2.3 From 379002586368ae22916f668011c9118c8ce8189c Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Fri, 22 Aug 2008 11:52:12 +0100 Subject: x86_32: clean up play_dead The removal of the CPU from the various maps was redundant as it already happened in cpu_disable. After cleaning this up, cpu_uninit only resets the tlb state, so rename it and create a noop version for the X86_64 case (so the two play_deads can be unified later). Signed-off-by: Alex Nixon Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 6 +----- arch/x86/kernel/process_32.c | 17 ++++------------- 2 files changed, 5 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d4fa3..18f5551b32d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -714,14 +714,10 @@ void __cpuinit cpu_init(void) mxcsr_feature_mask_init(); } -#ifdef CONFIG_HOTPLUG_CPU -void __cpuinit cpu_uninit(void) +void reset_lazy_tlbstate(void) { int cpu = raw_smp_processor_id(); - cpu_clear(cpu, cpu_initialized); - /* lazy TLB state */ per_cpu(cpu_tlbstate, cpu).state = 0; per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; } -#endif diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index e382fe0ccd6..d55eb49584b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -75,26 +75,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk) #ifdef CONFIG_HOTPLUG_CPU #include -static void cpu_exit_clear(void) +/* We don't actually take CPU down, just spin without interrupts. */ +void native_play_dead(void) { int cpu = raw_smp_processor_id(); idle_task_exit(); - cpu_uninit(); - irq_ctx_exit(cpu); + reset_lazy_tlbstate(); - cpu_clear(cpu, cpu_callout_map); - cpu_clear(cpu, cpu_callin_map); - - numa_remove_cpu(cpu); -} + irq_ctx_exit(cpu); -/* We don't actually take CPU down, just spin without interrupts. */ -void native_play_dead(void) -{ - /* This must be done before dead CPU ack */ - cpu_exit_clear(); mb(); /* Ack it */ __get_cpu_var(cpu_state) = CPU_DEAD; -- cgit v1.2.3 From a21f5d88c17a40941f6239d1959d89e8493e8e01 Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Fri, 22 Aug 2008 11:52:13 +0100 Subject: x86: unify x86_32 and x86_64 play_dead into one function Add the new play_dead into smpboot.c, as it fits more cleanly in there alongside other CONFIG_HOTPLUG functions. Separate out the common code into its own function. Signed-off-by: Alex Nixon Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_32.c | 32 -------------------------------- arch/x86/kernel/process_64.c | 23 ----------------------- arch/x86/kernel/smpboot.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 55 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index d55eb49584b..633cf06578f 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -72,38 +72,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return ((unsigned long *)tsk->thread.sp)[3]; } -#ifdef CONFIG_HOTPLUG_CPU -#include - -/* We don't actually take CPU down, just spin without interrupts. */ -void native_play_dead(void) -{ - int cpu = raw_smp_processor_id(); - - idle_task_exit(); - - reset_lazy_tlbstate(); - - irq_ctx_exit(cpu); - - mb(); - /* Ack it */ - __get_cpu_var(cpu_state) = CPU_DEAD; - - /* - * With physical CPU hotplug, we should halt the cpu - */ - local_irq_disable(); - /* mask all interrupts, flush any and all caches, and halt */ - wbinvd_halt(); -} -#else -void native_play_dead(void) -{ - BUG(); -} -#endif /* CONFIG_HOTPLUG_CPU */ - /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index dfd3f575208..aa28ed01cdf 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -85,29 +85,6 @@ void exit_idle(void) __exit_idle(); } -#ifdef CONFIG_HOTPLUG_CPU -DECLARE_PER_CPU(int, cpu_state); - -#include -/* We halt the CPU with physical CPU hotplug */ -void native_play_dead(void) -{ - idle_task_exit(); - mb(); - /* Ack it */ - __get_cpu_var(cpu_state) = CPU_DEAD; - - local_irq_disable(); - /* mask all interrupts, flush any and all caches, and halt */ - wbinvd_halt(); -} -#else -void native_play_dead(void) -{ - BUG(); -} -#endif /* CONFIG_HOTPLUG_CPU */ - /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index c414cee296b..28b4287296a 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1402,6 +1402,29 @@ void native_cpu_die(unsigned int cpu) } printk(KERN_ERR "CPU %u didn't die...\n", cpu); } + +void play_dead_common(void) +{ + idle_task_exit(); + reset_lazy_tlbstate(); + irq_ctx_exit(raw_smp_processor_id()); + + mb(); + /* Ack it */ + __get_cpu_var(cpu_state) = CPU_DEAD; + + /* + * With physical CPU hotplug, we should halt the cpu + */ + local_irq_disable(); +} + +void native_play_dead(void) +{ + play_dead_common(); + wbinvd_halt(); +} + #else /* ... !CONFIG_HOTPLUG_CPU */ int native_cpu_disable(void) { @@ -1413,4 +1436,10 @@ void native_cpu_die(unsigned int cpu) /* We said "no" in __cpu_disable */ BUG(); } + +void native_play_dead(void) +{ + BUG(); +} + #endif -- cgit v1.2.3 From 8227dce7dc2cfdcc28ee0eadfb482a7ee77fba03 Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Fri, 22 Aug 2008 11:52:14 +0100 Subject: x86: separate generic cpu disabling code from APIC writes in cpu_disable It allows paravirt implementations of cpu_disable to share the cpu_disable_common code, without having to take on board APIC writes, which may not be appropriate. Signed-off-by: Alex Nixon Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/smpboot.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 28b4287296a..66b04e59881 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1346,25 +1346,9 @@ static void __ref remove_cpu_from_maps(int cpu) numa_remove_cpu(cpu); } -int native_cpu_disable(void) +void cpu_disable_common(void) { int cpu = smp_processor_id(); - - /* - * Perhaps use cpufreq to drop frequency, but that could go - * into generic code. - * - * We won't take down the boot processor on i386 due to some - * interrupts only being able to be serviced by the BSP. - * Especially so if we're not using an IOAPIC -zwane - */ - if (cpu == 0) - return -EBUSY; - - if (nmi_watchdog == NMI_LOCAL_APIC) - stop_apic_nmi_watchdog(NULL); - clear_local_APIC(); - /* * HACK: * Allow any queued timer interrupts to get serviced @@ -1382,6 +1366,28 @@ int native_cpu_disable(void) remove_cpu_from_maps(cpu); unlock_vector_lock(); fixup_irqs(cpu_online_map); +} + +int native_cpu_disable(void) +{ + int cpu = smp_processor_id(); + + /* + * Perhaps use cpufreq to drop frequency, but that could go + * into generic code. + * + * We won't take down the boot processor on i386 due to some + * interrupts only being able to be serviced by the BSP. + * Especially so if we're not using an IOAPIC -zwane + */ + if (cpu == 0) + return -EBUSY; + + if (nmi_watchdog == NMI_LOCAL_APIC) + stop_apic_nmi_watchdog(NULL); + clear_local_APIC(); + + cpu_disable_common(); return 0; } -- cgit v1.2.3 From ed21763e7b0b3fb50e4efd9d4bc17ef5b035d304 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 22 Aug 2008 20:23:38 +0200 Subject: x86: cleanup in amd_cpu_notify() small coding style fix. Signed-off-by: Robert Richter Signed-off-by: Ingo Molnar --- arch/x86/pci/amd_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 6a0fca78c36..22e057665e5 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -580,7 +580,7 @@ static int __cpuinit amd_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (long)hcpu; - switch(action) { + switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0); -- cgit v1.2.3 From d68d82afd4c88e25763b23cd9cd4974573a3706f Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Fri, 22 Aug 2008 11:52:15 +0100 Subject: xen: implement CPU hotplugging Note the changes from 2.6.18-xen CPU hotplugging: A vcpu_down request from the remote admin via Xenbus both hotunplugs the CPU, and disables it by removing it from the cpu_present map, and removing its entry in /sys. A vcpu_up request from the remote admin only re-enables the CPU, and does not immediately bring the CPU up. A udev event is emitted, which can be caught by the user if he wishes to automatically re-up CPUs when available, or implement a more complex policy. Signed-off-by: Alex Nixon Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/smp.c | 60 +++++++++++++++++++++++++++++++++++++++---------- arch/x86/xen/spinlock.c | 5 +++++ arch/x86/xen/time.c | 8 +++++++ arch/x86/xen/xen-ops.h | 6 +++++ 4 files changed, 67 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index baca7f2fbd8..be5cbb2b7c6 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -11,8 +11,6 @@ * useful topology information for the kernel to make use of. As a * result, all CPUs are treated as if they're single-core and * single-threaded. - * - * This does not handle HOTPLUG_CPU yet. */ #include #include @@ -61,11 +59,12 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static __cpuinit void cpu_bringup_and_idle(void) +static __cpuinit void cpu_bringup(void) { int cpu = smp_processor_id(); cpu_init(); + touch_softlockup_watchdog(); preempt_disable(); xen_enable_sysenter(); @@ -86,6 +85,11 @@ static __cpuinit void cpu_bringup_and_idle(void) local_irq_enable(); wmb(); /* make sure everything is out */ +} + +static __cpuinit void cpu_bringup_and_idle(void) +{ + cpu_bringup(); cpu_idle(); } @@ -209,8 +213,6 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) cpu_set(cpu, cpu_present_map); } - - //init_xenbus_allowed_cpumask(); } static __cpuinit int @@ -278,12 +280,6 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) struct task_struct *idle = idle_task(cpu); int rc; -#if 0 - rc = cpu_up_check(cpu); - if (rc) - return rc; -#endif - #ifdef CONFIG_X86_64 /* Allocate node local memory for AP pdas */ WARN_ON(cpu == 0); @@ -336,6 +332,42 @@ static void xen_smp_cpus_done(unsigned int max_cpus) { } +int xen_cpu_disable(void) +{ + unsigned int cpu = smp_processor_id(); + if (cpu == 0) + return -EBUSY; + + cpu_disable_common(); + + load_cr3(swapper_pg_dir); + return 0; +} + +void xen_cpu_die(unsigned int cpu) +{ + while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) { + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ/10); + } + unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); + unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); + unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL); + unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL); + xen_uninit_lock_cpu(cpu); + xen_teardown_timer(cpu); + + if (num_online_cpus() == 1) + alternatives_smp_switch(0); +} + +void xen_play_dead(void) +{ + play_dead_common(); + HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); + cpu_bringup(); +} + static void stop_self(void *v) { int cpu = smp_processor_id(); @@ -419,9 +451,13 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id) static const struct smp_ops xen_smp_ops __initdata = { .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, .smp_prepare_cpus = xen_smp_prepare_cpus, - .cpu_up = xen_cpu_up, .smp_cpus_done = xen_smp_cpus_done, + .cpu_up = xen_cpu_up, + .cpu_die = xen_cpu_die, + .cpu_disable = xen_cpu_disable, + .play_dead = xen_play_dead, + .smp_send_stop = xen_smp_send_stop, .smp_send_reschedule = xen_smp_send_reschedule, diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index d072823bc06..dd71e3a021c 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -357,6 +357,11 @@ void __cpuinit xen_init_lock_cpu(int cpu) printk("cpu %d spinlock event irq %d\n", cpu, irq); } +void xen_uninit_lock_cpu(int cpu) +{ + unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); +} + void __init xen_init_spinlocks(void) { pv_lock_ops.spin_is_locked = xen_spin_is_locked; diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 20182d9072c..004ba86326a 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -450,6 +450,14 @@ void xen_setup_timer(int cpu) setup_runstate_info(cpu); } +void xen_teardown_timer(int cpu) +{ + struct clock_event_device *evt; + BUG_ON(cpu == 0); + evt = &per_cpu(xen_clock_events, cpu); + unbind_from_irqhandler(evt->irq, NULL); +} + void xen_setup_cpu_clockevents(void) { BUG_ON(preemptible()); diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 1e8bfdaa20d..8dbd97fd7f1 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -34,6 +34,7 @@ void __init xen_build_dynamic_phys_to_machine(void); void xen_init_irq_ops(void); void xen_setup_timer(int cpu); +void xen_teardown_timer(int cpu); cycle_t xen_clocksource_read(void); void xen_setup_cpu_clockevents(void); unsigned long xen_tsc_khz(void); @@ -50,11 +51,16 @@ void xen_mark_init_mm_pinned(void); void __init xen_setup_vcpu_info_placement(void); +void xen_play_dead(void); +void xen_cpu_die(unsigned int cpu); +int xen_cpu_disable(void); + #ifdef CONFIG_SMP void xen_smp_init(void); void __init xen_init_spinlocks(void); __cpuinit void xen_init_lock_cpu(int cpu); +void xen_uninit_lock_cpu(int cpu); extern cpumask_t xen_cpu_initialized_map; #else -- cgit v1.2.3 From c7ffa6c26277b403920e2255d10df849bd613380 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 25 Aug 2008 13:11:27 +0300 Subject: x86: default to reboot via ACPI Triple-fault and keyboard reset may assert INIT instead of RESET; however INIT is blocked when Intel VT is enabled. This leads to a partially reset machine when invoking emergency_restart via sysrq-b: the processor is still working but other parts of the system are dead. Default to rebooting via ACPI, which correctly asserts RESET and reboots the machine. This is safe since we will fall back to keyboard reset and triple fault if acpi is not enabled or if the reset is not successful. Signed-off-by: Avi Kivity Signed-off-by: Ingo Molnar --- arch/x86/kernel/reboot.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 724adfc63cb..f4c93f1cfc1 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -29,7 +29,11 @@ EXPORT_SYMBOL(pm_power_off); static const struct desc_ptr no_idt = {}; static int reboot_mode; -enum reboot_type reboot_type = BOOT_KBD; +/* + * Keyboard reset and triple fault may result in INIT, not RESET, which + * doesn't work when we're in vmx root mode. Try ACPI first. + */ +enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) -- cgit v1.2.3 From 85269eb5542b425b99d79dc4c312dce0157eac7e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Aug 2008 13:38:30 -0700 Subject: sparc64: Add JBUS UltraSPARC-IIIi support to memory controller driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 536 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 453 insertions(+), 83 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index a3c79fd5dd3..3e14952e940 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -33,6 +33,12 @@ MODULE_DESCRIPTION("UltraSPARC-III memory controller driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); +static int mc_type; +#define MC_TYPE_SAFARI 1 +#define MC_TYPE_JBUS 2 + +static dimm_printer_t us3mc_dimm_printer; + #define CHMCTRL_NDGRPS 2 #define CHMCTRL_NDIMMS 4 @@ -96,8 +102,386 @@ struct chmc { struct chmc_bank_info logical_banks[CHMCTRL_NBANKS]; }; +#define JBUSMC_REGS_SIZE 8 + +#define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000 +#define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000 +#define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000 +#define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000 +#define JB_MC_REG1_XOR 0x0000010000000000 +#define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000 +#define JB_MC_REG1_ADDR_GEN_2_SHIFT 37 +#define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000 +#define JB_MC_REG1_ADDR_GEN_1_SHIFT 34 +#define JB_MC_REG1_INTERLEAVE 0x0000000001800000 +#define JB_MC_REG1_INTERLEAVE_SHIFT 23 +#define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000 +#define JB_MC_REG1_DIMM2_PTYPE_SHIFT 21 +#define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000 +#define JB_MC_REG1_DIMM1_PTYPE_SHIFT 20 + +#define PART_TYPE_X8 0 +#define PART_TYPE_X4 1 + +#define INTERLEAVE_NONE 0 +#define INTERLEAVE_SAME 1 +#define INTERLEAVE_INTERNAL 2 +#define INTERLEAVE_BOTH 3 + +#define ADDR_GEN_128MB 0 +#define ADDR_GEN_256MB 1 +#define ADDR_GEN_512MB 2 +#define ADDR_GEN_1GB 3 + +#define JB_NUM_DIMM_GROUPS 2 +#define JB_NUM_DIMMS_PER_GROUP 2 +#define JB_NUM_DIMMS (JB_NUM_DIMM_GROUPS * JB_NUM_DIMMS_PER_GROUP) + +struct jbusmc_obp_map { + unsigned char dimm_map[18]; + unsigned char pin_map[144]; +}; + +struct jbusmc_obp_mem_layout { + /* One max 8-byte string label per DIMM. Usually + * this matches the label on the motherboard where + * that DIMM resides. + */ + char dimm_labels[JB_NUM_DIMMS][DIMM_LABEL_SZ]; + + /* If symmetric use map[0], else it is + * asymmetric and map[1] should be used. + */ + char symmetric; + + struct jbusmc_obp_map map; + + char _pad; +}; + +struct jbusmc_dimm_group { + struct jbusmc *controller; + int index; + u64 base_addr; + u64 size; +}; + +struct jbusmc { + void __iomem *regs; + u64 mc_reg_1; + u32 portid; + struct jbusmc_obp_mem_layout layout; + int layout_len; + int num_dimm_groups; + struct jbusmc_dimm_group dimm_groups[JB_NUM_DIMM_GROUPS]; + struct list_head list; +}; + +static DEFINE_SPINLOCK(mctrl_list_lock); static LIST_HEAD(mctrl_list); +static void mc_list_add(struct list_head *list) +{ + spin_lock(&mctrl_list_lock); + list_add(list, &mctrl_list); + spin_unlock(&mctrl_list_lock); +} + +static void mc_list_del(struct list_head *list) +{ + spin_lock(&mctrl_list_lock); + list_del_init(list); + spin_unlock(&mctrl_list_lock); +} + +#define SYNDROME_MIN -1 +#define SYNDROME_MAX 144 + +/* Covert syndrome code into the way the bits are positioned + * on the bus. + */ +static int syndrome_to_qword_code(int syndrome_code) +{ + if (syndrome_code < 128) + syndrome_code += 16; + else if (syndrome_code < 128 + 9) + syndrome_code -= (128 - 7); + else if (syndrome_code < (128 + 9 + 3)) + syndrome_code -= (128 + 9 - 4); + else + syndrome_code -= (128 + 9 + 3); + return syndrome_code; +} + +/* All this magic has to do with how a cache line comes over the wire + * on Safari and JBUS. A 64-bit line comes over in 1 or more quadword + * cycles, each of which transmit ECC/MTAG info as well as the actual + * data. + */ +#define L2_LINE_SIZE 64 +#define L2_LINE_ADDR_MSK (L2_LINE_SIZE - 1) +#define QW_PER_LINE 4 +#define QW_BYTES (L2_LINE_SIZE / QW_PER_LINE) +#define QW_BITS 144 +#define SAFARI_LAST_BIT (576 - 1) +#define JBUS_LAST_BIT (144 - 1) + +static void get_pin_and_dimm_str(int syndrome_code, unsigned long paddr, + int *pin_p, char **dimm_str_p, void *_prop, + int base_dimm_offset) +{ + int qword_code = syndrome_to_qword_code(syndrome_code); + int cache_line_offset; + int offset_inverse; + int dimm_map_index; + int map_val; + + if (mc_type == MC_TYPE_JBUS) { + struct jbusmc_obp_mem_layout *p = _prop; + + /* JBUS */ + cache_line_offset = qword_code; + offset_inverse = (JBUS_LAST_BIT - cache_line_offset); + dimm_map_index = offset_inverse / 8; + map_val = p->map.dimm_map[dimm_map_index]; + map_val = ((map_val >> ((7 - (offset_inverse & 7)))) & 1); + *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; + *pin_p = p->map.pin_map[cache_line_offset]; + } else { + struct chmc_obp_mem_layout *p = _prop; + struct chmc_obp_map *mp; + int qword; + + /* Safari */ + if (p->symmetric) + mp = &p->map[0]; + else + mp = &p->map[1]; + + qword = (paddr & L2_LINE_ADDR_MSK) / QW_BYTES; + cache_line_offset = ((3 - qword) * QW_BITS) + qword_code; + offset_inverse = (SAFARI_LAST_BIT - cache_line_offset); + dimm_map_index = offset_inverse >> 2; + map_val = mp->dimm_map[dimm_map_index]; + map_val = ((map_val >> ((3 - (offset_inverse & 3)) << 1)) & 0x3); + *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; + *pin_p = mp->pin_map[cache_line_offset]; + } +} + +static struct jbusmc_dimm_group *jbusmc_find_dimm_group(unsigned long phys_addr) +{ + struct jbusmc *p; + + list_for_each_entry(p, &mctrl_list, list) { + int i; + + for (i = 0; i < p->num_dimm_groups; i++) { + struct jbusmc_dimm_group *dp = &p->dimm_groups[i]; + + if (phys_addr < dp->base_addr || + (dp->base_addr + dp->size) <= phys_addr) + continue; + + return dp; + } + } + return NULL; +} + +static int jbusmc_print_dimm(int syndrome_code, + unsigned long phys_addr, + char *buf, int buflen) +{ + struct jbusmc_obp_mem_layout *prop; + struct jbusmc_dimm_group *dp; + struct jbusmc *p; + int first_dimm; + + dp = jbusmc_find_dimm_group(phys_addr); + if (dp == NULL || + syndrome_code < SYNDROME_MIN || + syndrome_code > SYNDROME_MAX) { + buf[0] = '?'; + buf[1] = '?'; + buf[2] = '?'; + buf[3] = '\0'; + } + p = dp->controller; + prop = &p->layout; + + first_dimm = dp->index * JB_NUM_DIMMS_PER_GROUP; + + if (syndrome_code != SYNDROME_MIN) { + char *dimm_str; + int pin; + + get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, + &dimm_str, prop, first_dimm); + sprintf(buf, "%s, pin %3d", dimm_str, pin); + } else { + int dimm; + + /* Multi-bit error, we just dump out all the + * dimm labels associated with this dimm group. + */ + for (dimm = 0; dimm < JB_NUM_DIMMS_PER_GROUP; dimm++) { + sprintf(buf, "%s ", + prop->dimm_labels[first_dimm + dimm]); + buf += strlen(buf); + } + } + + return 0; +} + +static u64 __devinit jbusmc_dimm_group_size(u64 base, + const struct linux_prom64_registers *mem_regs, + int num_mem_regs) +{ + u64 max = base + (8UL * 1024 * 1024 * 1024); + u64 max_seen = base; + int i; + + for (i = 0; i < num_mem_regs; i++) { + const struct linux_prom64_registers *ent; + u64 this_base; + u64 this_end; + + ent = &mem_regs[i]; + this_base = ent->phys_addr; + this_end = this_base + ent->reg_size; + if (base < this_base || base >= this_end) + continue; + if (this_end > max) + this_end = max; + if (this_end > max_seen) + max_seen = this_end; + } + + return max_seen - base; +} + +static void __devinit jbusmc_construct_one_dimm_group(struct jbusmc *p, + unsigned long index, + const struct linux_prom64_registers *mem_regs, + int num_mem_regs) +{ + struct jbusmc_dimm_group *dp = &p->dimm_groups[index]; + + dp->controller = p; + dp->index = index; + + dp->base_addr = (p->portid * (64UL * 1024 * 1024 * 1024)); + dp->base_addr += (index * (8UL * 1024 * 1024 * 1024)); + dp->size = jbusmc_dimm_group_size(dp->base_addr, mem_regs, num_mem_regs); +} + +static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p, + const struct linux_prom64_registers *mem_regs, + int num_mem_regs) +{ + if (p->mc_reg_1 & JB_MC_REG1_DIMM1_BANK0) { + jbusmc_construct_one_dimm_group(p, 0, mem_regs, num_mem_regs); + p->num_dimm_groups++; + } + if (p->mc_reg_1 & JB_MC_REG1_DIMM2_BANK2) { + jbusmc_construct_one_dimm_group(p, 1, mem_regs, num_mem_regs); + p->num_dimm_groups++; + } +} + +static int __devinit jbusmc_probe(struct of_device *op, + const struct of_device_id *match) +{ + const struct linux_prom64_registers *mem_regs; + struct device_node *mem_node; + int err, len, num_mem_regs; + struct jbusmc *p; + const u32 *prop; + const void *ml; + + err = -ENODEV; + mem_node = of_find_node_by_path("/memory"); + if (!mem_node) { + printk(KERN_ERR PFX "Cannot find /memory node.\n"); + goto out; + } + mem_regs = of_get_property(mem_node, "reg", &len); + if (!mem_regs) { + printk(KERN_ERR PFX "Cannot get reg property of /memory node.\n"); + goto out; + } + num_mem_regs = len / sizeof(*mem_regs); + + err = -ENOMEM; + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) { + printk(KERN_ERR PFX "Cannot allocate struct jbusmc.\n"); + goto out; + } + + INIT_LIST_HEAD(&p->list); + + err = -ENODEV; + prop = of_get_property(op->node, "portid", &len); + if (!prop || len != 4) { + printk(KERN_ERR PFX "Cannot find portid.\n"); + goto out_free; + } + + p->portid = *prop; + + prop = of_get_property(op->node, "memory-control-register-1", &len); + if (!prop || len != 8) { + printk(KERN_ERR PFX "Cannot get memory control register 1.\n"); + goto out_free; + } + + p->mc_reg_1 = ((u64)prop[0] << 32) | (u64) prop[1]; + + err = -ENOMEM; + p->regs = of_ioremap(&op->resource[0], 0, JBUSMC_REGS_SIZE, "jbusmc"); + if (!p->regs) { + printk(KERN_ERR PFX "Cannot map jbusmc regs.\n"); + goto out_free; + } + + err = -ENODEV; + ml = of_get_property(op->node, "memory-layout", &p->layout_len); + if (!ml) { + printk(KERN_ERR PFX "Cannot get memory layout property.\n"); + goto out_iounmap; + } + if (p->layout_len > sizeof(p->layout)) { + printk(KERN_ERR PFX "Unexpected memory-layout size %d\n", + p->layout_len); + goto out_iounmap; + } + memcpy(&p->layout, ml, p->layout_len); + + jbusmc_construct_dimm_groups(p, mem_regs, num_mem_regs); + + mc_list_add(&p->list); + + printk(KERN_INFO PFX "UltraSPARC-IIIi memory controller at %s\n", + op->node->full_name); + + dev_set_drvdata(&op->dev, p); + + err = 0; + +out: + return err; + +out_iounmap: + of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); + +out_free: + kfree(p); + goto out; +} + /* Does BANK decode PHYS_ADDR? */ static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) { @@ -133,17 +517,11 @@ static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) /* Given PHYS_ADDR, search memory controller banks for a match. */ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) { - struct list_head *mctrl_head = &mctrl_list; - struct list_head *mctrl_entry = mctrl_head->next; + struct chmc *p; - for (;;) { - struct chmc *p = list_entry(mctrl_entry, struct chmc, list); + list_for_each_entry(p, &mctrl_list, list) { int bank_no; - if (mctrl_entry == mctrl_head) - break; - mctrl_entry = mctrl_entry->next; - for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { struct chmc_bank_info *bp; @@ -157,8 +535,6 @@ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) } /* This is the main purpose of this driver. */ -#define SYNDROME_MIN -1 -#define SYNDROME_MAX 144 static int chmc_print_dimm(int syndrome_code, unsigned long phys_addr, char *buf, int buflen) @@ -184,54 +560,12 @@ static int chmc_print_dimm(int syndrome_code, first_dimm *= CHMCTRL_NDIMMS; if (syndrome_code != SYNDROME_MIN) { - struct chmc_obp_map *map; - int qword, where_in_line, where, map_index, map_offset; - unsigned int map_val; - - /* Yaay, single bit error so we can figure out - * the exact dimm. - */ - if (prop->symmetric) - map = &prop->map[0]; - else - map = &prop->map[1]; - - /* Covert syndrome code into the way the bits are - * positioned on the bus. - */ - if (syndrome_code < 144 - 16) - syndrome_code += 16; - else if (syndrome_code < 144) - syndrome_code -= (144 - 7); - else if (syndrome_code < (144 + 3)) - syndrome_code -= (144 + 3 - 4); - else - syndrome_code -= 144 + 3; + char *dimm_str; + int pin; - /* All this magic has to do with how a cache line - * comes over the wire on Safari. A 64-bit line - * comes over in 4 quadword cycles, each of which - * transmit ECC/MTAG info as well as the actual - * data. 144 bits per quadword, 576 total. - */ -#define LINE_SIZE 64 -#define LINE_ADDR_MSK (LINE_SIZE - 1) -#define QW_PER_LINE 4 -#define QW_BYTES (LINE_SIZE / QW_PER_LINE) -#define QW_BITS 144 -#define LAST_BIT (576 - 1) - - qword = (phys_addr & LINE_ADDR_MSK) / QW_BYTES; - where_in_line = ((3 - qword) * QW_BITS) + syndrome_code; - where = (LAST_BIT - where_in_line); - map_index = where >> 2; - map_offset = where & 0x3; - map_val = map->dimm_map[map_index]; - map_val = ((map_val >> ((3 - map_offset) << 1)) & (2 - 1)); - - sprintf(buf, "%s, pin %3d", - prop->dimm_labels[first_dimm + map_val], - map->pin_map[where_in_line]); + get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, + &dimm_str, prop, first_dimm); + sprintf(buf, "%s, pin %3d", dimm_str, pin); } else { int dimm; @@ -412,9 +746,8 @@ static int __devinit chmc_probe(struct of_device *op, chmc_fetch_decode_regs(p); - list_add(&p->list, &mctrl_list); + mc_list_add(&p->list); - /* Report the device. */ printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", dp->full_name, (p->layout_size ? "ACTIVE" : "INACTIVE")); @@ -431,63 +764,100 @@ out_free: goto out; } -static int __devexit chmc_remove(struct of_device *op) +static int __devinit us3mc_probe(struct of_device *op, + const struct of_device_id *match) +{ + if (mc_type == MC_TYPE_SAFARI) + return chmc_probe(op, match); + else if (mc_type == MC_TYPE_JBUS) + return jbusmc_probe(op, match); + return -ENODEV; +} + +static void __devexit chmc_destroy(struct of_device *op, struct chmc *p) +{ + list_del(&p->list); + of_iounmap(&op->resource[0], p->regs, 0x48); + kfree(p); +} + +static void __devexit jbusmc_destroy(struct of_device *op, struct jbusmc *p) { - struct chmc *p = dev_get_drvdata(&op->dev); + mc_list_del(&p->list); + of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); + kfree(p); +} + +static int __devexit us3mc_remove(struct of_device *op) +{ + void *p = dev_get_drvdata(&op->dev); if (p) { - list_del(&p->list); - of_iounmap(&op->resource[0], p->regs, 0x48); - kfree(p); + if (mc_type == MC_TYPE_SAFARI) + chmc_destroy(op, p); + else if (mc_type == MC_TYPE_JBUS) + jbusmc_destroy(op, p); } return 0; } -static struct of_device_id chmc_match[] = { +static struct of_device_id us3mc_match[] = { { .name = "memory-controller", }, {}, }; -MODULE_DEVICE_TABLE(of, chmc_match); +MODULE_DEVICE_TABLE(of, us3mc_match); -static struct of_platform_driver chmc_driver = { - .name = "chmc", - .match_table = chmc_match, - .probe = chmc_probe, - .remove = __devexit_p(chmc_remove), +static struct of_platform_driver us3mc_driver = { + .name = "us3mc", + .match_table = us3mc_match, + .probe = us3mc_probe, + .remove = __devexit_p(us3mc_remove), }; -static inline bool chmc_platform(void) +static inline bool us3mc_platform(void) { if (tlb_type == cheetah || tlb_type == cheetah_plus) return true; return false; } -static int __init chmc_init(void) +static int __init us3mc_init(void) { + unsigned long ver; int ret; - if (!chmc_platform()) + if (!us3mc_platform()) return -ENODEV; - ret = register_dimm_printer(chmc_print_dimm); + __asm__ ("rdpr %%ver, %0" : "=r" (ver)); + if ((ver >> 32UL) == __JALAPENO_ID || + (ver >> 32UL) == __SERRANO_ID) { + mc_type = MC_TYPE_JBUS; + us3mc_dimm_printer = jbusmc_print_dimm; + } else { + mc_type = MC_TYPE_SAFARI; + us3mc_dimm_printer = chmc_print_dimm; + } + + ret = register_dimm_printer(us3mc_dimm_printer); + if (!ret) { - ret = of_register_driver(&chmc_driver, &of_bus_type); + ret = of_register_driver(&us3mc_driver, &of_bus_type); if (ret) - unregister_dimm_printer(chmc_print_dimm); + unregister_dimm_printer(us3mc_dimm_printer); } return ret; } -static void __exit chmc_cleanup(void) +static void __exit us3mc_cleanup(void) { - if (chmc_platform()) { - unregister_dimm_printer(chmc_print_dimm); - of_unregister_driver(&chmc_driver); + if (us3mc_platform()) { + unregister_dimm_printer(us3mc_dimm_printer); + of_unregister_driver(&us3mc_driver); } } -module_init(chmc_init); -module_exit(chmc_cleanup); +module_init(us3mc_init); +module_exit(us3mc_cleanup); -- cgit v1.2.3 From 783c98b911fce8d47aa2906468ca39d44d46d7ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Aug 2008 16:21:08 -0700 Subject: sparc64: Use the cond_syscall()s in kernel/sys_ni.c instead of home-grown copy. This also allows arch/sparc64/kernel/pci.c to be properly CONFIG_PCI conditional compiled in the Makefile. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 4 ++-- arch/sparc64/kernel/pci.c | 18 ------------------ 2 files changed, 2 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 313735fa5f2..360a348e5bb 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -10,13 +10,13 @@ extra-y := head.o init_task.o vmlinux.lds obj-y := process.o setup.o cpu.o idprom.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ - unaligned.o central.o pci.o starfire.o \ + unaligned.o central.o starfire.o \ power.o sbus.o sparc64_ksyms.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += ebus.o pci_common.o \ +obj-$(CONFIG_PCI) += ebus.o pci.o pci_common.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 55096195458..9bb4b8cbcac 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -28,22 +28,6 @@ #include "pci_impl.h" -#ifndef CONFIG_PCI -/* A "nop" PCI implementation. */ -asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - return 0; -} -asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - return 0; -} -#else - /* List of all PCI controllers found in the system. */ struct pci_pbm_info *pci_pbm_root = NULL; @@ -1215,5 +1199,3 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar, *start = rp->start - offset; *end = rp->end - offset; } - -#endif /* !(CONFIG_PCI) */ -- cgit v1.2.3 From 51e0f004a9ab9104acbe323c0b20e0279bf9be85 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Aug 2008 16:44:58 -0700 Subject: sparc64: Fix irq_of_parse_and_map() and irq_dispose_mapping(). Stephen Rothwell noticed that I committed an earlier version of the patch that didn't have two things fixed: 1) irq_of_parse_and_map() should return "unsigned int" not "int" and it should return zero for "no irq" 2) irq_dispose_mapping() should be an inline function, not a macro, for type checking With feedback and suggestions from Anton Vorontsov. Signed-off-by: David S. Miller --- arch/sparc/include/asm/prom.h | 6 ++++-- arch/sparc/kernel/of_device.c | 4 ++-- arch/sparc64/kernel/of_device.c | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index 58b85fa5606..900d44714f8 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -101,8 +101,10 @@ static inline void of_node_put(struct device_node *node) * register them in the of_device objects, whereas powerpc computes them * on request. */ -extern int irq_of_parse_and_map(struct device_node *node, int index); -#define irq_dispose_mapping(irq) do { } while (0) +extern unsigned int irq_of_parse_and_map(struct device_node *node, int index); +static inline void irq_dispose_mapping(unsigned int virq) +{ +} /* * NB: This is here while we transition from using asm/prom.h diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 56e9a718ef8..aace71f7d6e 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -29,12 +29,12 @@ struct of_device *of_find_device_by_node(struct device_node *dp) } EXPORT_SYMBOL(of_find_device_by_node); -int irq_of_parse_and_map(struct device_node *node, int index) +unsigned int irq_of_parse_and_map(struct device_node *node, int index) { struct of_device *op = of_find_device_by_node(node); if (!op || index >= op->num_irqs) - return 0xffffffff; + return 0; return op->irqs[index]; } diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 8a0d82343a2..a30f2af0bf2 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -55,12 +55,12 @@ struct of_device *of_find_device_by_node(struct device_node *dp) } EXPORT_SYMBOL(of_find_device_by_node); -int irq_of_parse_and_map(struct device_node *node, int index) +unsigned int irq_of_parse_and_map(struct device_node *node, int index) { struct of_device *op = of_find_device_by_node(node); if (!op || index >= op->num_irqs) - return 0xffffffff; + return 0; return op->irqs[index]; } -- cgit v1.2.3 From bdd314616f7218e325aa9637a46159ecba44cfeb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 25 Aug 2008 17:44:03 -0700 Subject: x86: msr-on-cpu: remove unnecessary level of abstraction Remove an unnecessary level of abstraction in the msr-on-cpu library. Although this duplicates some code, the duplicated code is less than the additional code, and this way should be faster. Additionally, change the order of the functions to make the regular structure of this file more obvious. Signed-off-by: H. Peter Anvin --- arch/x86/lib/msr-on-cpu.c | 78 ++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 42 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/msr-on-cpu.c b/arch/x86/lib/msr-on-cpu.c index 01b868ba82f..321cf720dbb 100644 --- a/arch/x86/lib/msr-on-cpu.c +++ b/arch/x86/lib/msr-on-cpu.c @@ -16,37 +16,46 @@ static void __rdmsr_on_cpu(void *info) rdmsr(rv->msr_no, rv->l, rv->h); } -static void __rdmsr_safe_on_cpu(void *info) +static void __wrmsr_on_cpu(void *info) { struct msr_info *rv = info; - rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); + wrmsr(rv->msr_no, rv->l, rv->h); } -static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) { - int err = 0; + int err; struct msr_info rv; rv.msr_no = msr_no; - if (safe) { - err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, - &rv, 1); - err = err ? err : rv.err; - } else { - err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); - } + err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); *l = rv.l; *h = rv.h; return err; } -static void __wrmsr_on_cpu(void *info) +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +{ + int err; + struct msr_info rv; + + rv.msr_no = msr_no; + rv.l = l; + rv.h = h; + err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); + + return err; +} + +/* These "safe" variants are slower and should be used when the target MSR + may not actually exist. */ +static void __rdmsr_safe_on_cpu(void *info) { struct msr_info *rv = info; - wrmsr(rv->msr_no, rv->l, rv->h); + rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); } static void __wrmsr_safe_on_cpu(void *info) @@ -56,45 +65,30 @@ static void __wrmsr_safe_on_cpu(void *info) rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h); } -static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) +int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) { - int err = 0; + int err; struct msr_info rv; rv.msr_no = msr_no; - rv.l = l; - rv.h = h; - if (safe) { - err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, - &rv, 1); - err = err ? err : rv.err; - } else { - err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); - } - - return err; -} + err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); + *l = rv.l; + *h = rv.h; -int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) -{ - return _wrmsr_on_cpu(cpu, msr_no, l, h, 0); + return err ? err : rv.err; } -int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - return _rdmsr_on_cpu(cpu, msr_no, l, h, 0); -} - -/* These "safe" variants are slower and should be used when the target MSR - may not actually exist. */ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) { - return _wrmsr_on_cpu(cpu, msr_no, l, h, 1); -} + int err; + struct msr_info rv; -int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - return _rdmsr_on_cpu(cpu, msr_no, l, h, 1); + rv.msr_no = msr_no; + rv.l = l; + rv.h = h; + err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1); + + return err ? err : rv.err; } EXPORT_SYMBOL(rdmsr_on_cpu); -- cgit v1.2.3 From a81726087428b541aa64604b8a94104a4d4aa8f9 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 26 Aug 2008 15:13:45 -0700 Subject: x86: acpi: move acpi_mcfg_64bit_base_addr into CONFIG_PCI_MMCONFIG acpi_mcfg_64bit_base_addr is used when CONFIG_PCI_MMCONFIG is enabled. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index f20470823d3..e5032d7b391 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -96,8 +96,6 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; #warning ACPI uses CMPXCHG, i486 and later hardware #endif -static int acpi_mcfg_64bit_base_addr __initdata = FALSE; - /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -159,6 +157,8 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) struct acpi_mcfg_allocation *pci_mmcfg_config; int pci_mmcfg_config_num; +static int acpi_mcfg_64bit_base_addr __initdata = FALSE; + static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg) { if (!strcmp(mcfg->header.oem_id, "SGI")) -- cgit v1.2.3 From 11c231a962c740b3216eb6565149ae5a7944cba7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Sat, 23 Aug 2008 17:47:11 +0200 Subject: x86: use x2apic id reported by cpuid during topology discovery, fix v2: Fix for !SMP build Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/addon_cpuid_features.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index aa9641ae670..a2d1a545767 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -69,6 +69,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) */ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) { +#ifdef CONFIG_SMP unsigned int eax, ebx, ecx, edx, sub_index; unsigned int ht_mask_width, core_plus_mask_width; unsigned int core_select_mask, core_level_siblings; @@ -132,6 +133,7 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) printk(KERN_INFO "CPU: Processor Core ID: %d\n", c->cpu_core_id); return; +#endif } #ifdef CONFIG_X86_PAT -- cgit v1.2.3 From 83b8e28b14d63db928cb39e5c5ed2a548246bd71 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 27 Aug 2008 14:57:36 -0700 Subject: x86: xsave: restore xcr0 during resume Add the missing XCR0(XFEATURE_ENABLED_MASK) restore during resume. Reported-by: Venkatesh Pallipadi Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin --- arch/x86/power/cpu_32.c | 7 +++++++ arch/x86/power/cpu_64.c | 7 +++++++ 2 files changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c index 7dc5d5cf50a..02f36f53558 100644 --- a/arch/x86/power/cpu_32.c +++ b/arch/x86/power/cpu_32.c @@ -11,6 +11,7 @@ #include #include #include +#include static struct saved_context saved_context; @@ -124,6 +125,12 @@ static void __restore_processor_state(struct saved_context *ctxt) if (boot_cpu_has(X86_FEATURE_SEP)) enable_sep_cpu(); + /* + * restore XCR0 for xsave capable cpu's. + */ + if (cpu_has_xsave) + xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); + fix_processor_context(); do_fpu_end(); mtrr_ap_init(); diff --git a/arch/x86/power/cpu_64.c b/arch/x86/power/cpu_64.c index 66bdfb591fd..e3b6cf70d62 100644 --- a/arch/x86/power/cpu_64.c +++ b/arch/x86/power/cpu_64.c @@ -14,6 +14,7 @@ #include #include #include +#include static void fix_processor_context(void); @@ -122,6 +123,12 @@ static void __restore_processor_state(struct saved_context *ctxt) wrmsrl(MSR_GS_BASE, ctxt->gs_base); wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base); + /* + * restore XCR0 for xsave capable cpu's. + */ + if (cpu_has_xsave) + xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); + fix_processor_context(); do_fpu_end(); -- cgit v1.2.3 From 7414aa41a63348c3bc72d8c37b716024c29b6d50 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 27 Aug 2008 17:56:44 -0700 Subject: x86: generate names for /proc/cpuinfo from We have had a number of cases where (and its predecessors) have diverged substantially from the names list in /proc/cpuinfo. This patch generates the latter from the former. It retains the option for explicitly overriding the strings, but by making that require a separate action it should at least be less likely to happen. It would be good to do a future pass and rename strings that are gratuituously different in the kernel (/proc/cpuinfo is a userspace interface and must remain constant.) Signed-off-by: H. Peter Anvin --- arch/x86/boot/mkcpustr.c | 2 +- arch/x86/kernel/cpu/Makefile | 11 ++++- arch/x86/kernel/cpu/feature_names.c | 84 ------------------------------------- arch/x86/kernel/cpu/mkcapflags.pl | 32 ++++++++++++++ arch/x86/kernel/cpu/powerflags.c | 20 +++++++++ 5 files changed, 63 insertions(+), 86 deletions(-) delete mode 100644 arch/x86/kernel/cpu/feature_names.c create mode 100644 arch/x86/kernel/cpu/mkcapflags.pl create mode 100644 arch/x86/kernel/cpu/powerflags.c (limited to 'arch') diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c index bbe76953bae..4589caa3e9d 100644 --- a/arch/x86/boot/mkcpustr.c +++ b/arch/x86/boot/mkcpustr.c @@ -15,7 +15,7 @@ #include -#include "../kernel/cpu/feature_names.c" +#include "../kernel/cpu/capflags.c" #if NCAPFLAGS > 8 # error "Need to adjust the boot code handling of CPUID strings" diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index a0fc6c14438..3ede19a4e0b 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -3,7 +3,7 @@ # obj-y := intel_cacheinfo.o addon_cpuid_features.o -obj-y += proc.o feature_names.o +obj-y += proc.o capflags.o powerflags.o obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += common_64.o bugs_64.o @@ -23,3 +23,12 @@ obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o + +quiet_cmd_mkcapflags = MKCAP $@ + cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@ + +cpufeature = $(src)/../../../../include/asm-x86/cpufeature.h + +targets += capflags.c +$(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.pl FORCE + $(call if_changed,mkcapflags) diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c deleted file mode 100644 index c9017799497..00000000000 --- a/arch/x86/kernel/cpu/feature_names.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Strings for the various x86 capability flags. - * - * This file must not contain any executable code. - */ - -#include - -/* - * These flag bits must match the definitions in . - * NULL means this bit is undefined or reserved; either way it doesn't - * have meaning as far as Linux is concerned. Note that it's important - * to realize there is a difference between this table and CPUID -- if - * applications want to get the raw CPUID data, they should access - * /dev/cpu//cpuid instead. - */ -const char * const x86_cap_flags[NCAPINTS*32] = { - /* Intel-defined */ - "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", - "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", - "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", - "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", - - /* AMD-defined */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, - NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", - "3dnowext", "3dnow", - - /* Transmeta-defined */ - "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Other (Linux-defined) */ - "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", - NULL, NULL, NULL, NULL, - "constant_tsc", "up", NULL, "arch_perfmon", - "pebs", "bts", NULL, NULL, - "rep_good", NULL, NULL, NULL, - "nopl", NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Intel-defined (#2) */ - "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", - "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, - NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* VIA/Cyrix/Centaur-defined */ - NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", - "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* AMD-defined (#2) */ - "lahf_lm", "cmp_legacy", "svm", "extapic", - "cr8_legacy", "abm", "sse4a", "misalignsse", - "3dnowprefetch", "osvw", "ibs", "sse5", - "skinit", "wdt", NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Auxiliary (Linux-defined) */ - "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -const char *const x86_power_flags[32] = { - "ts", /* temperature sensor */ - "fid", /* frequency id control */ - "vid", /* voltage id control */ - "ttp", /* thermal trip */ - "tm", - "stc", - "100mhzsteps", - "hwpstate", - "", /* tsc invariant mapped to constant_tsc */ - /* nothing */ -}; diff --git a/arch/x86/kernel/cpu/mkcapflags.pl b/arch/x86/kernel/cpu/mkcapflags.pl new file mode 100644 index 00000000000..dfea390e160 --- /dev/null +++ b/arch/x86/kernel/cpu/mkcapflags.pl @@ -0,0 +1,32 @@ +#!/usr/bin/perl +# +# Generate the x86_cap_flags[] array from include/asm-x86/cpufeature.h +# + +($in, $out) = @ARGV; + +open(IN, "< $in\0") or die "$0: cannot open: $in: $!\n"; +open(OUT, "> $out\0") or die "$0: cannot create: $out: $!\n"; + +print OUT "#include \n\n"; +print OUT "const char * const x86_cap_flags[NCAPINTS*32] = {\n"; + +while (defined($line = )) { + if ($line =~ /^\s*\#\s*define\s+(X86_FEATURE_(\S+))\s+(.*)$/) { + $macro = $1; + $feature = $2; + $tail = $3; + if ($tail =~ /\/\*\s*\"([^"]*)\".*\*\//) { + $feature = $1; + } + + if ($feature ne '') { + printf OUT "\t%-32s = \"%s\",\n", + "[$macro]", "\L$feature"; + } + } +} +print OUT "};\n"; + +close(IN); +close(OUT); diff --git a/arch/x86/kernel/cpu/powerflags.c b/arch/x86/kernel/cpu/powerflags.c new file mode 100644 index 00000000000..5abbea297e0 --- /dev/null +++ b/arch/x86/kernel/cpu/powerflags.c @@ -0,0 +1,20 @@ +/* + * Strings for the various x86 power flags + * + * This file must not contain any executable code. + */ + +#include + +const char *const x86_power_flags[32] = { + "ts", /* temperature sensor */ + "fid", /* frequency id control */ + "vid", /* voltage id control */ + "ttp", /* thermal trip */ + "tm", + "stc", + "100mhzsteps", + "hwpstate", + "", /* tsc invariant mapped to constant_tsc */ + /* nothing */ +}; -- cgit v1.2.3 From 2c7e9fd4c6cb7f4b0bc7162e9a30847e51a1ca1b Mon Sep 17 00:00:00 2001 From: Joe Korty Date: Wed, 27 Aug 2008 10:35:06 -0400 Subject: x86: make poll_idle behave more like the other idle methods Make poll_idle() behave more like the other idle methods. Currently, poll_idle() returns immediately. The other idle methods all wait indefinately for some condition to come true before returning. poll_idle should emulate these other methods and also wait for a return condition, in this case, for need_resched() to become 'true'. Without this delay the idle loop spends all of its time in the outer loop that calls poll_idle. This outer loop, these days, does real work, some of it under rcu locks. That work should only be done when idle is entered and when idle exits, not continuously while idle is spinning. Signed-off-by: Joe Korty Signed-off-by: Ingo Molnar --- arch/x86/kernel/process.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7fc4d5b0a6a..4e09d26748c 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -185,7 +185,8 @@ static void mwait_idle(void) static void poll_idle(void) { local_irq_enable(); - cpu_relax(); + while (!need_resched()) + cpu_relax(); } /* -- cgit v1.2.3 From 8cb51ba8e06570a5fff674b3744d12a1b089f2d0 Mon Sep 17 00:00:00 2001 From: Austin Zhang Date: Thu, 7 Aug 2008 09:57:03 +0800 Subject: crypto: crc32c - Use Intel CRC32 instruction From NHM processor onward, Intel processors can support hardware accelerated CRC32c algorithm with the new CRC32 instruction in SSE 4.2 instruction set. The patch detects the availability of the feature, and chooses the most proper way to calculate CRC32c checksum. Byte code instructions are used for compiler compatibility. No MMX / XMM registers is involved in the implementation. Signed-off-by: Austin Zhang Signed-off-by: Kent Liu Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 2 + arch/x86/crypto/crc32c-intel.c | 197 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 arch/x86/crypto/crc32c-intel.c (limited to 'arch') diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 3874c2de540..903de4aa509 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -10,6 +10,8 @@ obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o +obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o + aes-i586-y := aes-i586-asm_32.o aes_glue.o twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o diff --git a/arch/x86/crypto/crc32c-intel.c b/arch/x86/crypto/crc32c-intel.c new file mode 100644 index 00000000000..070afc5b6c9 --- /dev/null +++ b/arch/x86/crypto/crc32c-intel.c @@ -0,0 +1,197 @@ +/* + * Using hardware provided CRC32 instruction to accelerate the CRC32 disposal. + * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE) + * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at: + * http://www.intel.com/products/processor/manuals/ + * Intel(R) 64 and IA-32 Architectures Software Developer's Manual + * Volume 2A: Instruction Set Reference, A-M + * + * Copyright (c) 2008 Austin Zhang + * Copyright (c) 2008 Kent Liu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include + +#include + +#define CHKSUM_BLOCK_SIZE 1 +#define CHKSUM_DIGEST_SIZE 4 + +#define SCALE_F sizeof(unsigned long) + +#ifdef CONFIG_X86_64 +#define REX_PRE "0x48, " +#else +#define REX_PRE +#endif + +static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length) +{ + while (length--) { + __asm__ __volatile__( + ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1" + :"=S"(crc) + :"0"(crc), "c"(*data) + ); + data++; + } + + return crc; +} + +static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len) +{ + unsigned int iquotient = len / SCALE_F; + unsigned int iremainder = len % SCALE_F; + unsigned long *ptmp = (unsigned long *)p; + + while (iquotient--) { + __asm__ __volatile__( + ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;" + :"=S"(crc) + :"0"(crc), "c"(*ptmp) + ); + ptmp++; + } + + if (iremainder) + crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp, + iremainder); + + return crc; +} + +/* + * Setting the seed allows arbitrary accumulators and flexible XOR policy + * If your algorithm starts with ~0, then XOR with ~0 before you set + * the seed. + */ +static int crc32c_intel_setkey(struct crypto_ahash *hash, const u8 *key, + unsigned int keylen) +{ + u32 *mctx = crypto_ahash_ctx(hash); + + if (keylen != sizeof(u32)) { + crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + *mctx = le32_to_cpup((__le32 *)key); + return 0; +} + +static int crc32c_intel_init(struct ahash_request *req) +{ + u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + u32 *crcp = ahash_request_ctx(req); + + *crcp = *mctx; + + return 0; +} + +static int crc32c_intel_update(struct ahash_request *req) +{ + struct crypto_hash_walk walk; + u32 *crcp = ahash_request_ctx(req); + u32 crc = *crcp; + int nbytes; + + for (nbytes = crypto_hash_walk_first(req, &walk); nbytes; + nbytes = crypto_hash_walk_done(&walk, 0)) + crc = crc32c_intel_le_hw(crc, walk.data, nbytes); + + *crcp = crc; + return 0; +} + +static int crc32c_intel_final(struct ahash_request *req) +{ + u32 *crcp = ahash_request_ctx(req); + + *(__le32 *)req->result = ~cpu_to_le32p(crcp); + return 0; +} + +static int crc32c_intel_digest(struct ahash_request *req) +{ + struct crypto_hash_walk walk; + u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + u32 crc = *mctx; + int nbytes; + + for (nbytes = crypto_hash_walk_first(req, &walk); nbytes; + nbytes = crypto_hash_walk_done(&walk, 0)) + crc = crc32c_intel_le_hw(crc, walk.data, nbytes); + + *(__le32 *)req->result = ~cpu_to_le32(crc); + return 0; +} + +static int crc32c_intel_cra_init(struct crypto_tfm *tfm) +{ + u32 *key = crypto_tfm_ctx(tfm); + + *key = ~0; + + tfm->crt_ahash.reqsize = sizeof(u32); + + return 0; +} + +static struct crypto_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-intel", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_AHASH, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_init = crc32c_intel_cra_init, + .cra_type = &crypto_ahash_type, + .cra_u = { + .ahash = { + .digestsize = CHKSUM_DIGEST_SIZE, + .setkey = crc32c_intel_setkey, + .init = crc32c_intel_init, + .update = crc32c_intel_update, + .final = crc32c_intel_final, + .digest = crc32c_intel_digest, + } + } +}; + + +static int __init crc32c_intel_mod_init(void) +{ + if (cpu_has_xmm4_2) + return crypto_register_alg(&alg); + else + return -ENODEV; +} + +static void __exit crc32c_intel_mod_fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(crc32c_intel_mod_init); +module_exit(crc32c_intel_mod_fini); + +MODULE_AUTHOR("Austin Zhang , Kent Liu "); +MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware."); +MODULE_LICENSE("GPL"); + +MODULE_ALIAS("crc32c"); +MODULE_ALIAS("crc32c-intel"); + -- cgit v1.2.3 From d886e87cb82b0f6636476c1104bb84d7c8dc87d9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Aug 2008 16:42:51 +0200 Subject: sound: make OSS sound core optional sound/sound_core.c implements soundcore.ko and contains two parts - sound_class which is shared by both ALSA and OSS and device redirection support for OSS. It's always compiled when any sound support is enabled although it's necessary only when OSS (the actual one or emulation) is enabled. This is slightly wasteful and as device redirection always registers character device region for major 14, it prevents alternative implementation. This patch introduces a new config SOUND_OSS_CORE which is selected iff OSS support is actually necessary and build the OSS core part conditionally. If OSS is disabled, soundcore merely contains sound_class but leaving it that way seems to be the simplest approach as otherwise sound_class should be in ALSA core file if OSS is disabled but should be in soundcore if OSS is enabled. Also, there's also the user confusion factor. Signed-off-by: Tejun Heo Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- arch/um/Kconfig.char | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index 1b238ebae6b..70dabd1e065 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -203,6 +203,10 @@ config SOUND tristate default UML_SOUND +config SOUND_OSS_CORE + bool + default UML_SOUND + config HOSTAUDIO tristate default UML_SOUND -- cgit v1.2.3 From 902663f6ea4a2603bee0d88450aae2d653a46f5d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Aug 2008 22:25:03 -0700 Subject: sparc: Delete bare sbus char bpp driver, obsoleted by parport_sunbpp Signed-off-by: David S. Miller --- arch/sparc/include/asm/Kbuild | 1 - arch/sparc/include/asm/bpp.h | 73 ------------------------------------------- arch/sparc/kernel/ebus.c | 1 - arch/sparc64/kernel/ebus.c | 1 - 4 files changed, 76 deletions(-) delete mode 100644 arch/sparc/include/asm/bpp.h (limited to 'arch') diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index a5f0ce734ff..c314fced46d 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -22,7 +22,6 @@ header-y += unistd_64.h header-y += apc.h header-y += asi.h -header-y += bpp.h header-y += display7seg.h header-y += envctrl.h header-y += fbio.h diff --git a/arch/sparc/include/asm/bpp.h b/arch/sparc/include/asm/bpp.h deleted file mode 100644 index 31f515e499a..00000000000 --- a/arch/sparc/include/asm/bpp.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _SPARC_BPP_H -#define _SPARC_BPP_H - -/* - * Copyright (c) 1995 Picture Elements - * Stephen Williams - * Gus Baldauf - * - * Linux/SPARC port by Peter Zaitcev. - * Integration into SPARC tree by Tom Dyas. - */ - -#include - -/* - * This is a driver that supports IEEE Std 1284-1994 communications - * with compliant or compatible devices. It will use whatever features - * the device supports, prefering those that are typically faster. - * - * When the device is opened, it is left in COMPATIBILITY mode, and - * writes work like any printer device. The driver only attempt to - * negotiate 1284 modes when needed so that plugs can be pulled, - * switch boxes switched, etc., without disrupting things. It will - * also leave the device in compatibility mode when closed. - */ - - - -/* - * This driver also supplies ioctls to manually manipulate the - * pins. This is great for testing devices, or writing code to deal - * with bizzarro-mode of the ACME Special TurboThingy Plus. - * - * NOTE: These ioctl currently do not interact well with - * read/write. Caveat emptor. - * - * PUT_PINS allows us to assign the sense of all the pins, including - * the data pins if being driven by the host. The GET_PINS returns the - * pins that the peripheral drives, including data if appropriate. - */ - -# define BPP_PUT_PINS _IOW('B', 1, int) -# define BPP_GET_PINS _IOR('B', 2, char) /* that's bogus - should've been _IO */ -# define BPP_PUT_DATA _IOW('B', 3, int) -# define BPP_GET_DATA _IOR('B', 4, char) /* ditto */ - -/* - * Set the data bus to input mode. Disengage the data bin driver and - * be prepared to read values from the peripheral. If the arg is 0, - * then revert the bus to output mode. - */ -# define BPP_SET_INPUT _IOW('B', 5, int) - -/* - * These bits apply to the PUT operation... - */ -# define BPP_PP_nStrobe 0x0001 -# define BPP_PP_nAutoFd 0x0002 -# define BPP_PP_nInit 0x0004 -# define BPP_PP_nSelectIn 0x0008 - -/* - * These apply to the GET operation, which also reads the current value - * of the previously put values. A bit mask of these will be returned - * as a bit mask in the return code of the ioctl(). - */ -# define BPP_GP_nAck 0x0100 -# define BPP_GP_Busy 0x0200 -# define BPP_GP_PError 0x0400 -# define BPP_GP_Select 0x0800 -# define BPP_GP_nFault 0x1000 - -#endif diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 97294232259..7e9397fc608 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -20,7 +20,6 @@ #include #include #include -#include struct linux_ebus *ebus_chain = NULL; diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 60d36d14255..214da1bd8a5 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 7f06a3b2c162573c924f425053227a52b4bd7cb1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Aug 2008 22:26:21 -0700 Subject: sparc: Kill videopix SBUS driver. This has been marked BROKEN for a long time and it's more likely to get rewritten from scratch than to be fixed up and made usable. Signed-off-by: David S. Miller --- arch/sparc/include/asm/Kbuild | 1 - arch/sparc/include/asm/vfc_ioctls.h | 58 ------------------------------------- 2 files changed, 59 deletions(-) delete mode 100644 arch/sparc/include/asm/vfc_ioctls.h (limited to 'arch') diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index c314fced46d..2ba7183bc1f 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -40,5 +40,4 @@ header-y += reg_64.h header-y += traps.h header-y += uctx.h header-y += utrap.h -header-y += vfc_ioctls.h header-y += watchdog.h diff --git a/arch/sparc/include/asm/vfc_ioctls.h b/arch/sparc/include/asm/vfc_ioctls.h deleted file mode 100644 index af8b69007b2..00000000000 --- a/arch/sparc/include/asm/vfc_ioctls.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 1996 by Manish Vachharajani */ - -#ifndef _LINUX_VFC_IOCTLS_H_ -#define _LINUX_VFC_IOCTLS_H_ - - /* IOCTLs */ -#define VFC_IOCTL(a) (('j' << 8) | a) -#define VFCGCTRL (VFC_IOCTL (0)) /* get vfc attributes */ -#define VFCSCTRL (VFC_IOCTL (1)) /* set vfc attributes */ -#define VFCGVID (VFC_IOCTL (2)) /* get video decoder attributes */ -#define VFCSVID (VFC_IOCTL (3)) /* set video decoder attributes */ -#define VFCHUE (VFC_IOCTL (4)) /* set hue */ -#define VFCPORTCHG (VFC_IOCTL (5)) /* change port */ -#define VFCRDINFO (VFC_IOCTL (6)) /* read info */ - - /* Options for setting the vfc attributes and status */ -#define MEMPRST 0x1 /* reset FIFO ptr. */ -#define CAPTRCMD 0x2 /* start capture and wait */ -#define DIAGMODE 0x3 /* diag mode */ -#define NORMMODE 0x4 /* normal mode */ -#define CAPTRSTR 0x5 /* start capture */ -#define CAPTRWAIT 0x6 /* wait for capture to finish */ - - - /* Options for the decoder */ -#define STD_NTSC 0x1 /* NTSC mode */ -#define STD_PAL 0x2 /* PAL mode */ -#define COLOR_ON 0x3 /* force color ON */ -#define MONO 0x4 /* force color OFF */ - - /* Values returned by ioctl 2 */ - -#define NO_LOCK 1 -#define NTSC_COLOR 2 -#define NTSC_NOCOLOR 3 -#define PAL_COLOR 4 -#define PAL_NOCOLOR 5 - -/* Not too sure what this does yet */ - /* Options for setting Field number */ -#define ODD_FIELD 0x1 -#define EVEN_FIELD 0x0 -#define ACTIVE_ONLY 0x2 -#define NON_ACTIVE 0x0 - -/* Debug options */ -#define VFC_I2C_SEND 0 -#define VFC_I2C_RECV 1 - -struct vfc_debug_inout -{ - unsigned long addr; - unsigned long ret; - unsigned long len; - unsigned char __user *buffer; -}; - -#endif /* _LINUX_VFC_IOCTLS_H_ */ -- cgit v1.2.3 From 334ae614772b1147435dce9be3911f9040dff0d9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 17:01:57 -0700 Subject: sparc: Kill SBUS DVMA layer. This thing was completely pointless. Just find the OF device in the parent of drivers that want to program this device, and map the DMA regs inside such drivers too. This also moves the dummy claim_dma_lock() and release_dma_lock() implementation to floppy_32.h, which makes it handle this issue just like floppy_64.h does. Signed-off-by: David S. Miller --- arch/sparc/include/asm/dma.h | 141 +++++++++++++++++- arch/sparc/include/asm/dma_32.h | 288 ------------------------------------ arch/sparc/include/asm/dma_64.h | 205 ------------------------- arch/sparc/include/asm/floppy_32.h | 11 ++ arch/sparc/kernel/sparc_ksyms.c | 1 - arch/sparc64/kernel/sparc64_ksyms.c | 1 - 6 files changed, 147 insertions(+), 500 deletions(-) delete mode 100644 arch/sparc/include/asm/dma_32.h delete mode 100644 arch/sparc/include/asm/dma_64.h (limited to 'arch') diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h index aa1d90ac04c..49356344679 100644 --- a/arch/sparc/include/asm/dma.h +++ b/arch/sparc/include/asm/dma.h @@ -1,8 +1,139 @@ -#ifndef ___ASM_SPARC_DMA_H -#define ___ASM_SPARC_DMA_H -#if defined(__sparc__) && defined(__arch64__) -#include +#ifndef _ASM_SPARC_DMA_H +#define _ASM_SPARC_DMA_H + +/* These are irrelevant for Sparc DMA, but we leave it in so that + * things can compile. + */ +#define MAX_DMA_CHANNELS 8 +#define DMA_MODE_READ 1 +#define DMA_MODE_WRITE 2 +#define MAX_DMA_ADDRESS (~0UL) + +/* Useful constants */ +#define SIZE_16MB (16*1024*1024) +#define SIZE_64K (64*1024) + +/* SBUS DMA controller reg offsets */ +#define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */ +#define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */ +#define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */ +#define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */ + +/* Fields in the cond_reg register */ +/* First, the version identification bits */ +#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ +#define DMA_VERS0 0x00000000 /* Sunray DMA version */ +#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ +#define DMA_VERS1 0x80000000 /* DMA rev 1 */ +#define DMA_VERS2 0xa0000000 /* DMA rev 2 */ +#define DMA_VERHME 0xb0000000 /* DMA hme gate array */ +#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ + +#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ +#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ +#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ +#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ +#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ +#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ +#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ +#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ +#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ +#define DMA_ST_WRITE 0x00000100 /* write from device to memory */ +#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ +#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ +#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ +#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ +#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ +#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ +#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ +#define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */ +#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ +#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ +#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ +#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ +#define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */ +#define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */ +#define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */ +#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ +#define DMA_BRST64 0x000c0000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ +#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */ +#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */ +#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ +#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ +#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ +#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ +#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ +#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ +#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ +#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ +#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ +#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ +#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ +#define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */ + +/* Values describing the burst-size property from the PROM */ +#define DMA_BURST1 0x01 +#define DMA_BURST2 0x02 +#define DMA_BURST4 0x04 +#define DMA_BURST8 0x08 +#define DMA_BURST16 0x10 +#define DMA_BURST32 0x20 +#define DMA_BURST64 0x40 +#define DMA_BURSTBITS 0x7f + +/* From PCI */ + +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; #else -#include +#define isa_dma_bridge_buggy (0) #endif + +#ifdef CONFIG_SPARC32 + +#include + +/* Routines for data transfer buffers. */ +BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long) +BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long) + +#define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len) +#define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len) + +/* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */ +BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus) +BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) +BTFIXUPDEF_CALL(void, mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus) +BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) + +#define mmu_get_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_get_scsi_one)(vaddr,len,sbus) +#define mmu_get_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_get_scsi_sgl)(sg,sz,sbus) +#define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus) +#define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus) + +/* + * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep. + * + * The mmu_map_dma_area establishes two mappings in one go. + * These mappings point to pages normally mapped at 'va' (linear address). + * First mapping is for CPU visible address at 'a', uncached. + * This is an alias, but it works because it is an uncached mapping. + * Second mapping is for device visible address, or "bus" address. + * The bus address is returned at '*pba'. + * + * These functions seem distinct, but are hard to split. On sun4c, + * at least for now, 'a' is equal to bus address, and retured in *pba. + * On sun4m, page attributes depend on the CPU type, so we have to + * know if we are mapping RAM or I/O, so it has to be an additional argument + * to a separate mapping function for CPU visible mappings. + */ +BTFIXUPDEF_CALL(int, mmu_map_dma_area, dma_addr_t *, unsigned long, unsigned long, int len) +BTFIXUPDEF_CALL(struct page *, mmu_translate_dvma, unsigned long busa) +BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, unsigned long busa, int len) + +#define mmu_map_dma_area(pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(pba,va,a,len) +#define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len) +#define mmu_translate_dvma(ba) BTFIXUP_CALL(mmu_translate_dvma)(ba) #endif + +#endif /* !(_ASM_SPARC_DMA_H) */ diff --git a/arch/sparc/include/asm/dma_32.h b/arch/sparc/include/asm/dma_32.h deleted file mode 100644 index cf7189c0079..00000000000 --- a/arch/sparc/include/asm/dma_32.h +++ /dev/null @@ -1,288 +0,0 @@ -/* include/asm/dma.h - * - * Copyright 1995 (C) David S. Miller (davem@davemloft.net) - */ - -#ifndef _ASM_SPARC_DMA_H -#define _ASM_SPARC_DMA_H - -#include -#include - -#include /* for invalidate's, etc. */ -#include -#include -#include -#include -#include -#include - -struct page; -extern spinlock_t dma_spin_lock; - -static inline unsigned long claim_dma_lock(void) -{ - unsigned long flags; - spin_lock_irqsave(&dma_spin_lock, flags); - return flags; -} - -static inline void release_dma_lock(unsigned long flags) -{ - spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -/* These are irrelevant for Sparc DMA, but we leave it in so that - * things can compile. - */ -#define MAX_DMA_CHANNELS 8 -#define MAX_DMA_ADDRESS (~0UL) -#define DMA_MODE_READ 1 -#define DMA_MODE_WRITE 2 - -/* Useful constants */ -#define SIZE_16MB (16*1024*1024) -#define SIZE_64K (64*1024) - -/* SBUS DMA controller reg offsets */ -#define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */ -#define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */ -#define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */ -#define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */ - -/* DVMA chip revisions */ -enum dvma_rev { - dvmarev0, - dvmaesc1, - dvmarev1, - dvmarev2, - dvmarev3, - dvmarevplus, - dvmahme -}; - -#define DMA_HASCOUNT(rev) ((rev)==dvmaesc1) - -/* Linux DMA information structure, filled during probe. */ -struct sbus_dma { - struct sbus_dma *next; - struct sbus_dev *sdev; - void __iomem *regs; - - /* Status, misc info */ - int node; /* Prom node for this DMA device */ - int running; /* Are we doing DMA now? */ - int allocated; /* Are we "owned" by anyone yet? */ - - /* Transfer information. */ - unsigned long addr; /* Start address of current transfer */ - int nbytes; /* Size of current transfer */ - int realbytes; /* For splitting up large transfers, etc. */ - - /* DMA revision */ - enum dvma_rev revision; -}; - -extern struct sbus_dma *dma_chain; - -/* Broken hardware... */ -#ifdef CONFIG_SUN4 -/* Have to sort this out. Does rev0 work fine on sun4[cmd] without isbroken? - * Or is rev0 present only on sun4 boxes? -jj */ -#define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev0 || (dma)->revision == dvmarev1) -#else -#define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev1) -#endif -#define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) - -/* Main routines in dma.c */ -extern void dvma_init(struct sbus_bus *); - -/* Fields in the cond_reg register */ -/* First, the version identification bits */ -#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ -#define DMA_VERS0 0x00000000 /* Sunray DMA version */ -#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ -#define DMA_VERS1 0x80000000 /* DMA rev 1 */ -#define DMA_VERS2 0xa0000000 /* DMA rev 2 */ -#define DMA_VERHME 0xb0000000 /* DMA hme gate array */ -#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ - -#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ -#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ -#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ -#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ -#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ -#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ -#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ -#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ -#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ -#define DMA_RST_BPP DMA_RST_SCSI /* Reset the BPP controller */ -#define DMA_ST_WRITE 0x00000100 /* write from device to memory */ -#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ -#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ -#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ -#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ -#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ -#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ -#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ -#define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */ -#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ -#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ -#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ -#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ -#define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */ -#define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */ -#define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */ -#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ -#define DMA_BRST64 0x00080000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ -#define DMA_BRST32 0x00040000 /* SCSI/BPP: 32byte bursts */ -#define DMA_BRST16 0x00000000 /* SCSI/BPP: 16byte bursts */ -#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ -#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ -#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ -#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ -#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ -#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ -#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ -#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ -#define DMA_BPP_ON DMA_SCSI_ON /* Enable BPP dma */ -#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ -#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ -#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ -#define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */ - -/* Values describing the burst-size property from the PROM */ -#define DMA_BURST1 0x01 -#define DMA_BURST2 0x02 -#define DMA_BURST4 0x04 -#define DMA_BURST8 0x08 -#define DMA_BURST16 0x10 -#define DMA_BURST32 0x20 -#define DMA_BURST64 0x40 -#define DMA_BURSTBITS 0x7f - -/* Determine highest possible final transfer address given a base */ -#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL)) - -/* Yes, I hack a lot of elisp in my spare time... */ -#define DMA_ERROR_P(regs) ((((regs)->cond_reg) & DMA_HNDL_ERROR)) -#define DMA_IRQ_P(regs) ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))) -#define DMA_WRITE_P(regs) ((((regs)->cond_reg) & DMA_ST_WRITE)) -#define DMA_OFF(regs) ((((regs)->cond_reg) &= (~DMA_ENABLE))) -#define DMA_INTSOFF(regs) ((((regs)->cond_reg) &= (~DMA_INT_ENAB))) -#define DMA_INTSON(regs) ((((regs)->cond_reg) |= (DMA_INT_ENAB))) -#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV)) -#define DMA_SETSTART(regs, addr) ((((regs)->st_addr) = (char *) addr)) -#define DMA_BEGINDMA_W(regs) \ - ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB)))) -#define DMA_BEGINDMA_R(regs) \ - ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE))))) - -/* For certain DMA chips, we need to disable ints upon irq entry - * and turn them back on when we are done. So in any ESP interrupt - * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT - * when leaving the handler. You have been warned... - */ -#define DMA_IRQ_ENTRY(dma, dregs) do { \ - if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \ - } while (0) - -#define DMA_IRQ_EXIT(dma, dregs) do { \ - if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \ - } while(0) - -#if 0 /* P3 this stuff is inline in ledma.c:init_restart_ledma() */ -/* Pause until counter runs out or BIT isn't set in the DMA condition - * register. - */ -static inline void sparc_dma_pause(struct sparc_dma_registers *regs, - unsigned long bit) -{ - int ctr = 50000; /* Let's find some bugs ;) */ - - /* Busy wait until the bit is not set any more */ - while((regs->cond_reg&bit) && (ctr>0)) { - ctr--; - __delay(5); - } - - /* Check for bogus outcome. */ - if(!ctr) - panic("DMA timeout"); -} - -/* Reset the friggin' thing... */ -#define DMA_RESET(dma) do { \ - struct sparc_dma_registers *regs = dma->regs; \ - /* Let the current FIFO drain itself */ \ - sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN)); \ - /* Reset the logic */ \ - regs->cond_reg |= (DMA_RST_SCSI); /* assert */ \ - __delay(400); /* let the bits set ;) */ \ - regs->cond_reg &= ~(DMA_RST_SCSI); /* de-assert */ \ - sparc_dma_enable_interrupts(regs); /* Re-enable interrupts */ \ - /* Enable FAST transfers if available */ \ - if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS; \ - dma->running = 0; \ -} while(0) -#endif - -#define for_each_dvma(dma) \ - for((dma) = dma_chain; (dma); (dma) = (dma)->next) - -extern int get_dma_list(char *); -extern int request_dma(unsigned int, __const__ char *); -extern void free_dma(unsigned int); - -/* From PCI */ - -#ifdef CONFIG_PCI -extern int isa_dma_bridge_buggy; -#else -#define isa_dma_bridge_buggy (0) -#endif - -/* Routines for data transfer buffers. */ -BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long) -BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long) - -#define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len) -#define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len) - -/* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */ -BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus) -BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) -BTFIXUPDEF_CALL(void, mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus) -BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) - -#define mmu_get_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_get_scsi_one)(vaddr,len,sbus) -#define mmu_get_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_get_scsi_sgl)(sg,sz,sbus) -#define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus) -#define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus) - -/* - * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep. - * - * The mmu_map_dma_area establishes two mappings in one go. - * These mappings point to pages normally mapped at 'va' (linear address). - * First mapping is for CPU visible address at 'a', uncached. - * This is an alias, but it works because it is an uncached mapping. - * Second mapping is for device visible address, or "bus" address. - * The bus address is returned at '*pba'. - * - * These functions seem distinct, but are hard to split. On sun4c, - * at least for now, 'a' is equal to bus address, and retured in *pba. - * On sun4m, page attributes depend on the CPU type, so we have to - * know if we are mapping RAM or I/O, so it has to be an additional argument - * to a separate mapping function for CPU visible mappings. - */ -BTFIXUPDEF_CALL(int, mmu_map_dma_area, dma_addr_t *, unsigned long, unsigned long, int len) -BTFIXUPDEF_CALL(struct page *, mmu_translate_dvma, unsigned long busa) -BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, unsigned long busa, int len) - -#define mmu_map_dma_area(pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(pba,va,a,len) -#define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len) -#define mmu_translate_dvma(ba) BTFIXUP_CALL(mmu_translate_dvma)(ba) - -#endif /* !(_ASM_SPARC_DMA_H) */ diff --git a/arch/sparc/include/asm/dma_64.h b/arch/sparc/include/asm/dma_64.h deleted file mode 100644 index 46a8aecffc0..00000000000 --- a/arch/sparc/include/asm/dma_64.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * include/asm/dma.h - * - * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu) - */ - -#ifndef _ASM_SPARC64_DMA_H -#define _ASM_SPARC64_DMA_H - -#include -#include -#include - -#include -#include -#include - -/* These are irrelevant for Sparc DMA, but we leave it in so that - * things can compile. - */ -#define MAX_DMA_CHANNELS 8 -#define DMA_MODE_READ 1 -#define DMA_MODE_WRITE 2 -#define MAX_DMA_ADDRESS (~0UL) - -/* Useful constants */ -#define SIZE_16MB (16*1024*1024) -#define SIZE_64K (64*1024) - -/* SBUS DMA controller reg offsets */ -#define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */ -#define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */ -#define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */ -#define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */ - -/* DVMA chip revisions */ -enum dvma_rev { - dvmarev0, - dvmaesc1, - dvmarev1, - dvmarev2, - dvmarev3, - dvmarevplus, - dvmahme -}; - -#define DMA_HASCOUNT(rev) ((rev)==dvmaesc1) - -/* Linux DMA information structure, filled during probe. */ -struct sbus_dma { - struct sbus_dma *next; - struct sbus_dev *sdev; - void __iomem *regs; - - /* Status, misc info */ - int node; /* Prom node for this DMA device */ - int running; /* Are we doing DMA now? */ - int allocated; /* Are we "owned" by anyone yet? */ - - /* Transfer information. */ - u32 addr; /* Start address of current transfer */ - int nbytes; /* Size of current transfer */ - int realbytes; /* For splitting up large transfers, etc. */ - - /* DMA revision */ - enum dvma_rev revision; -}; - -extern struct sbus_dma *dma_chain; - -/* Broken hardware... */ -#define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev1) -#define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) - -/* Main routines in dma.c */ -extern void dvma_init(struct sbus_bus *); - -/* Fields in the cond_reg register */ -/* First, the version identification bits */ -#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ -#define DMA_VERS0 0x00000000 /* Sunray DMA version */ -#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ -#define DMA_VERS1 0x80000000 /* DMA rev 1 */ -#define DMA_VERS2 0xa0000000 /* DMA rev 2 */ -#define DMA_VERHME 0xb0000000 /* DMA hme gate array */ -#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ - -#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ -#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ -#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ -#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ -#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ -#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ -#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ -#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ -#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ -#define DMA_ST_WRITE 0x00000100 /* write from device to memory */ -#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ -#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ -#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ -#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ -#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ -#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ -#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ -#define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */ -#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ -#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ -#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ -#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ -#define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */ -#define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */ -#define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */ -#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ -#define DMA_BRST64 0x000c0000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ -#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */ -#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */ -#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ -#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ -#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ -#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ -#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ -#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ -#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ -#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ -#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ -#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ -#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ -#define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */ - -/* Values describing the burst-size property from the PROM */ -#define DMA_BURST1 0x01 -#define DMA_BURST2 0x02 -#define DMA_BURST4 0x04 -#define DMA_BURST8 0x08 -#define DMA_BURST16 0x10 -#define DMA_BURST32 0x20 -#define DMA_BURST64 0x40 -#define DMA_BURSTBITS 0x7f - -/* Determine highest possible final transfer address given a base */ -#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL)) - -/* Yes, I hack a lot of elisp in my spare time... */ -#define DMA_ERROR_P(regs) ((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR)) -#define DMA_IRQ_P(regs) ((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)) -#define DMA_WRITE_P(regs) ((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE)) -#define DMA_OFF(__regs) \ -do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ - tmp &= ~DMA_ENABLE; \ - sbus_writel(tmp, (__regs) + DMA_CSR); \ -} while(0) -#define DMA_INTSOFF(__regs) \ -do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ - tmp &= ~DMA_INT_ENAB; \ - sbus_writel(tmp, (__regs) + DMA_CSR); \ -} while(0) -#define DMA_INTSON(__regs) \ -do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ - tmp |= DMA_INT_ENAB; \ - sbus_writel(tmp, (__regs) + DMA_CSR); \ -} while(0) -#define DMA_PUNTFIFO(__regs) \ -do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ - tmp |= DMA_FIFO_INV; \ - sbus_writel(tmp, (__regs) + DMA_CSR); \ -} while(0) -#define DMA_SETSTART(__regs, __addr) \ - sbus_writel((u32)(__addr), (__regs) + DMA_ADDR); -#define DMA_BEGINDMA_W(__regs) \ -do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ - tmp |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB); \ - sbus_writel(tmp, (__regs) + DMA_CSR); \ -} while(0) -#define DMA_BEGINDMA_R(__regs) \ -do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ - tmp |= (DMA_ENABLE|DMA_INT_ENAB); \ - tmp &= ~DMA_ST_WRITE; \ - sbus_writel(tmp, (__regs) + DMA_CSR); \ -} while(0) - -/* For certain DMA chips, we need to disable ints upon irq entry - * and turn them back on when we are done. So in any ESP interrupt - * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT - * when leaving the handler. You have been warned... - */ -#define DMA_IRQ_ENTRY(dma, dregs) do { \ - if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \ - } while (0) - -#define DMA_IRQ_EXIT(dma, dregs) do { \ - if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \ - } while(0) - -#define for_each_dvma(dma) \ - for((dma) = dma_chain; (dma); (dma) = (dma)->next) - -/* From PCI */ - -#ifdef CONFIG_PCI -extern int isa_dma_bridge_buggy; -#else -#define isa_dma_bridge_buggy (0) -#endif - -#endif /* !(_ASM_SPARC64_DMA_H) */ diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h index ae3f00bf22f..ff2b91c6eef 100644 --- a/arch/sparc/include/asm/floppy_32.h +++ b/arch/sparc/include/asm/floppy_32.h @@ -385,4 +385,15 @@ static int sparc_eject(void) #define EXTRA_FLOPPY_PARAMS +static DEFINE_SPINLOCK(dma_spin_lock); + +#define claim_dma_lock() \ +({ unsigned long flags; \ + spin_lock_irqsave(&dma_spin_lock, flags); \ + flags; \ +}) + +#define release_dma_lock(__flags) \ + spin_unlock_irqrestore(&dma_spin_lock, __flags); + #endif /* !(__ASM_SPARC_FLOPPY_H) */ diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index b23cea5ca5d..8a392d3d89e 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -154,7 +154,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); -EXPORT_SYMBOL(dma_chain); EXPORT_SYMBOL(sbus_set_sbus64); EXPORT_SYMBOL(sbus_alloc_consistent); EXPORT_SYMBOL(sbus_free_consistent); diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 3b2890c207f..8e6ac5c1b7b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -161,7 +161,6 @@ EXPORT_SYMBOL(auxio_set_lte); #endif #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); -EXPORT_SYMBOL(dma_chain); EXPORT_SYMBOL(sbus_set_sbus64); EXPORT_SYMBOL(sbus_alloc_consistent); EXPORT_SYMBOL(sbus_free_consistent); -- cgit v1.2.3 From e003934876e75f96f1445565d8c9084c07943253 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Aug 2008 22:47:20 -0700 Subject: sparc32: Make IOMMU and IO-UNIT init work with device nodes. And stick the iommu archdata pointer into the generic OF device tree of_device struct as well. We still have to pass the sbus_bus object down into the routines so that the SBUS bus objects get the iommu cookies set properly. After drivers get converted to being pure OF drivers, that can go away. Signed-off-by: David S. Miller --- arch/sparc/include/asm/io-unit.h | 2 ++ arch/sparc/include/asm/iommu_32.h | 2 ++ arch/sparc/kernel/ioport.c | 17 ++++++----------- arch/sparc/mm/io-unit.c | 29 +++++++++++++++-------------- arch/sparc/mm/iommu.c | 35 ++++++++++++++++++++--------------- 5 files changed, 45 insertions(+), 40 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/io-unit.h b/arch/sparc/include/asm/io-unit.h index 96823b47fd4..5df63ef95cf 100644 --- a/arch/sparc/include/asm/io-unit.h +++ b/arch/sparc/include/asm/io-unit.h @@ -59,4 +59,6 @@ extern __u32 iounit_map_dma_init(struct sbus_bus *, int); #define iounit_map_dma_finish(sbus, addr, len) mmu_release_scsi_one(addr, len, sbus) extern __u32 iounit_map_dma_page(__u32, void *, struct sbus_bus *); +extern void iounit_init(struct sbus_bus *sbus); + #endif /* !(_SPARC_IO_UNIT_H) */ diff --git a/arch/sparc/include/asm/iommu_32.h b/arch/sparc/include/asm/iommu_32.h index 70c589c05a1..6b115a174c0 100644 --- a/arch/sparc/include/asm/iommu_32.h +++ b/arch/sparc/include/asm/iommu_32.h @@ -118,4 +118,6 @@ static inline void iommu_invalidate_page(struct iommu_regs *regs, unsigned long regs->pageflush = (ba & PAGE_MASK); } +extern void iommu_init(struct device_node *dp, struct sbus_bus *sbus); + #endif /* !(_SPARC_IOMMU_H) */ diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 2a8a847764d..f6158c4a399 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -46,6 +46,8 @@ #include #include #include +#include +#include #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ @@ -515,18 +517,11 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) if (sparc_cpu_model != sun4d && parent != NULL && - !strcmp(parent->name, "iommu")) { - extern void iommu_init(int iommu_node, struct sbus_bus *sbus); + !strcmp(parent->name, "iommu")) + iommu_init(parent, sbus); - iommu_init(parent->node, sbus); - } - - if (sparc_cpu_model == sun4d) { - extern void iounit_init(int sbi_node, int iounit_node, - struct sbus_bus *sbus); - - iounit_init(dp->node, parent->node, sbus); - } + if (sparc_cpu_model == sun4d) + iounit_init(sbus); #endif } diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index f167835db3d..1093514a577 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -34,13 +34,18 @@ #define IOPERM (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID) #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM) -void __init -iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) +void __init iounit_init(struct sbus_bus *sbus) { - iopte_t *xpt, *xptend; + struct device_node *dp = sbus->ofdev.node; struct iounit_struct *iounit; - struct linux_prom_registers iommu_promregs[PROMREG_MAX]; - struct resource r; + iopte_t *xpt, *xptend; + struct of_device *op; + + op = of_find_device_by_node(dp); + if (!op) { + prom_printf("SUN4D: Cannot find SBI of_device.\n"); + prom_halt(); + } iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC); if (!iounit) { @@ -55,18 +60,14 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) iounit->rotor[1] = IOUNIT_BMAP2_START; iounit->rotor[2] = IOUNIT_BMAPM_START; - xpt = NULL; - if(prom_getproperty(sbi_node, "reg", (void *) iommu_promregs, - sizeof(iommu_promregs)) != -1) { - prom_apply_generic_ranges(io_node, 0, iommu_promregs, 3); - memset(&r, 0, sizeof(r)); - r.flags = iommu_promregs[2].which_io; - r.start = iommu_promregs[2].phys_addr; - xpt = (iopte_t *) sbus_ioremap(&r, 0, PAGE_SIZE * 16, "XPT"); + xpt = of_ioremap(&op->resource[2], 0, PAGE_SIZE * 16, "XPT"); + if (!xpt) { + prom_printf("SUN4D: Cannot map External Page Table."); + prom_halt(); } - if(!xpt) panic("Cannot map External Page Table."); sbus->ofdev.dev.archdata.iommu = iounit; + op->dev.archdata.iommu = iounit; iounit->page_table = xpt; spin_lock_init(&iounit->lock); diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 4b934270f05..a86c9f552fa 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -55,30 +55,34 @@ static pgprot_t dvma_prot; /* Consistent mapping pte flags */ #define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID) #define MKIOPTE(pfn, perm) (((((pfn)<<8) & IOPTE_PAGE) | (perm)) & ~IOPTE_WAZ) -void __init -iommu_init(int iommund, struct sbus_bus *sbus) +void __init iommu_init(struct device_node *parent, struct sbus_bus *sbus) { - unsigned int impl, vers; - unsigned long tmp; + struct of_device *parent_op, *op; struct iommu_struct *iommu; - struct linux_prom_registers iommu_promregs[PROMREG_MAX]; - struct resource r; + unsigned int impl, vers; unsigned long *bitmap; + unsigned long tmp; + + parent_op = of_find_device_by_node(parent); + if (!parent_op) { + prom_printf("Unable to find IOMMU of_device\n"); + prom_halt(); + } + + op = of_find_device_by_node(sbus->ofdev.node); + if (!op) { + prom_printf("Unable to find SBUS of_device\n"); + prom_halt(); + } iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); if (!iommu) { prom_printf("Unable to allocate iommu structure\n"); prom_halt(); } - iommu->regs = NULL; - if (prom_getproperty(iommund, "reg", (void *) iommu_promregs, - sizeof(iommu_promregs)) != -1) { - memset(&r, 0, sizeof(r)); - r.flags = iommu_promregs[0].which_io; - r.start = iommu_promregs[0].phys_addr; - iommu->regs = (struct iommu_regs *) - sbus_ioremap(&r, 0, PAGE_SIZE * 3, "iommu_regs"); - } + + iommu->regs = of_ioremap(&parent_op->resource[0], 0, PAGE_SIZE * 3, + "iommu_regs"); if (!iommu->regs) { prom_printf("Cannot map IOMMU registers\n"); prom_halt(); @@ -133,6 +137,7 @@ iommu_init(int iommund, struct sbus_bus *sbus) (int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES); sbus->ofdev.dev.archdata.iommu = iommu; + op->dev.archdata.iommu = iommu; } /* This begs to be btfixup-ed by srmmu. */ -- cgit v1.2.3 From 7a715f46012f3552294154978aed59cba9804928 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 18:37:58 -0700 Subject: sparc: Make SBUS DMA interfaces take struct device. This is the first step in converting all the SBUS drivers over to generic dma_*(). Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 20 +++++++--------- arch/sparc/include/asm/sbus_64.h | 48 ++++++++++++------------------------- arch/sparc/kernel/ioport.c | 43 +++++++++++++++------------------ arch/sparc/kernel/sparc_ksyms.c | 2 -- arch/sparc64/kernel/sparc64_ksyms.c | 2 -- 5 files changed, 42 insertions(+), 73 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index a7b4fa21931..61d99f1bb23 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -109,8 +109,8 @@ extern void sbus_set_sbus64(struct sbus_dev *, int); extern void sbus_fill_device_irq(struct sbus_dev *); /* These yield IOMMU mappings in consistent mode. */ -extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); -extern void sbus_free_consistent(struct sbus_dev *, long, void *, u32); +extern void *sbus_alloc_consistent(struct device *, long, u32 *dma_addrp); +extern void sbus_free_consistent(struct device *, long, void *, u32); void prom_adjust_ranges(struct linux_prom_ranges *, int, struct linux_prom_ranges *, int); @@ -120,18 +120,14 @@ void prom_adjust_ranges(struct linux_prom_ranges *, int, #define SBUS_DMA_NONE DMA_NONE /* All the rest use streaming mode mappings. */ -extern dma_addr_t sbus_map_single(struct sbus_dev *, void *, size_t, int); -extern void sbus_unmap_single(struct sbus_dev *, dma_addr_t, size_t, int); -extern int sbus_map_sg(struct sbus_dev *, struct scatterlist *, int, int); -extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int, int); +extern dma_addr_t sbus_map_single(struct device *, void *, size_t, int); +extern void sbus_unmap_single(struct device *, dma_addr_t, size_t, int); +extern int sbus_map_sg(struct device *, struct scatterlist *, int, int); +extern void sbus_unmap_sg(struct device *, struct scatterlist *, int, int); /* Finally, allow explicit synchronization of streamable mappings. */ -extern void sbus_dma_sync_single_for_cpu(struct sbus_dev *, dma_addr_t, size_t, int); -#define sbus_dma_sync_single sbus_dma_sync_single_for_cpu -extern void sbus_dma_sync_single_for_device(struct sbus_dev *, dma_addr_t, size_t, int); -extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, int, int); -#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu -extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int); +extern void sbus_dma_sync_single_for_cpu(struct device *, dma_addr_t, size_t, int); +extern void sbus_dma_sync_single_for_device(struct device *, dma_addr_t, size_t, int); /* Eric Brower (ebrower@usa.net) * Translate SBus interrupt levels to ino values-- diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index b606c14343f..b22e99da49d 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -100,17 +100,16 @@ extern struct sbus_bus *sbus_root; extern void sbus_set_sbus64(struct sbus_dev *, int); extern void sbus_fill_device_irq(struct sbus_dev *); -static inline void *sbus_alloc_consistent(struct sbus_dev *sdev , size_t size, +static inline void *sbus_alloc_consistent(struct device *dev , size_t size, dma_addr_t *dma_handle) { - return dma_alloc_coherent(&sdev->ofdev.dev, size, - dma_handle, GFP_ATOMIC); + return dma_alloc_coherent(dev, size, dma_handle, GFP_ATOMIC); } -static inline void sbus_free_consistent(struct sbus_dev *sdev, size_t size, +static inline void sbus_free_consistent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { - return dma_free_coherent(&sdev->ofdev.dev, size, vaddr, dma_handle); + return dma_free_coherent(dev, size, vaddr, dma_handle); } #define SBUS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL @@ -119,68 +118,51 @@ static inline void sbus_free_consistent(struct sbus_dev *sdev, size_t size, #define SBUS_DMA_NONE DMA_NONE /* All the rest use streaming mode mappings. */ -static inline dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, +static inline dma_addr_t sbus_map_single(struct device *dev, void *ptr, size_t size, int direction) { - return dma_map_single(&sdev->ofdev.dev, ptr, size, + return dma_map_single(dev, ptr, size, (enum dma_data_direction) direction); } -static inline void sbus_unmap_single(struct sbus_dev *sdev, +static inline void sbus_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, int direction) { - dma_unmap_single(&sdev->ofdev.dev, dma_addr, size, + dma_unmap_single(dev, dma_addr, size, (enum dma_data_direction) direction); } -static inline int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, +static inline int sbus_map_sg(struct device *dev, struct scatterlist *sg, int nents, int direction) { - return dma_map_sg(&sdev->ofdev.dev, sg, nents, + return dma_map_sg(dev, sg, nents, (enum dma_data_direction) direction); } -static inline void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, +static inline void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int direction) { - dma_unmap_sg(&sdev->ofdev.dev, sg, nents, + dma_unmap_sg(dev, sg, nents, (enum dma_data_direction) direction); } /* Finally, allow explicit synchronization of streamable mappings. */ -static inline void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, +static inline void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, int direction) { - dma_sync_single_for_cpu(&sdev->ofdev.dev, dma_handle, size, + dma_sync_single_for_cpu(dev, dma_handle, size, (enum dma_data_direction) direction); } -#define sbus_dma_sync_single sbus_dma_sync_single_for_cpu -static inline void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, +static inline void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, int direction) { /* No flushing needed to sync cpu writes to the device. */ } -static inline void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, - struct scatterlist *sg, - int nents, int direction) -{ - dma_sync_sg_for_cpu(&sdev->ofdev.dev, sg, nents, - (enum dma_data_direction) direction); -} -#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu - -static inline void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, - struct scatterlist *sg, - int nents, int direction) -{ - /* No flushing needed to sync cpu writes to the device. */ -} - extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index f6158c4a399..aa73b3b71e8 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -300,11 +300,10 @@ void __init sbus_fill_device_irq(struct sbus_dev *sdev) * Allocate a chunk of memory suitable for DMA. * Typically devices use them for control blocks. * CPU may access them without any explicit flushing. - * - * XXX Some clever people know that sdev is not used and supply NULL. Watch. */ -void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) +void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp) { + struct of_device *op = to_of_device(dev); unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; unsigned long va; struct resource *res; @@ -341,10 +340,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) if (mmu_map_dma_area(dma_addrp, va, res->start, len_total) != 0) goto err_noiommu; - /* Set the resource name, if known. */ - if (sdev) { - res->name = sdev->prom_name; - } + res->name = op->node->name; return (void *)(unsigned long)res->start; @@ -358,7 +354,7 @@ err_nopages: return NULL; } -void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) +void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba) { struct resource *res; struct page *pgv; @@ -396,8 +392,10 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) * CPU view of this memory may be inconsistent with * a device view and explicit flushing is necessary. */ -dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int direction) +dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int direction) { + struct sbus_dev *sdev = to_sbus_device(dev); + /* XXX why are some lengths signed, others unsigned? */ if (len <= 0) { return 0; @@ -409,13 +407,16 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int dire return mmu_get_scsi_one(va, len, sdev->bus); } -void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t ba, size_t n, int direction) +void sbus_unmap_single(struct device *dev, dma_addr_t ba, size_t n, int direction) { + struct sbus_dev *sdev = to_sbus_device(dev); mmu_release_scsi_one(ba, n, sdev->bus); } -int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) +int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction) { + struct sbus_dev *sdev = to_sbus_device(dev); + mmu_get_scsi_sgl(sg, n, sdev->bus); /* @@ -425,16 +426,19 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direct return n; } -void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) +void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direction) { + struct sbus_dev *sdev = to_sbus_device(dev); + mmu_release_scsi_sgl(sg, n, sdev->bus); } /* */ -void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction) +void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size, int direction) { #if 0 + struct sbus_dev *sdev = to_sbus_device(dev); unsigned long va; struct resource *res; @@ -452,9 +456,10 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t ba, size_t s #endif } -void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction) +void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t size, int direction) { #if 0 + struct sbus_dev *sdev = to_sbus_device(dev); unsigned long va; struct resource *res; @@ -472,16 +477,6 @@ void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t ba, size_ #endif } -void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) -{ - printk("sbus_dma_sync_sg_for_cpu: not implemented yet\n"); -} - -void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) -{ - printk("sbus_dma_sync_sg_for_device: not implemented yet\n"); -} - /* Support code for sbus_init(). */ /* * XXX This functions appears to be a distorted version of diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 8a392d3d89e..9d85a83586a 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -163,8 +163,6 @@ EXPORT_SYMBOL(sbus_map_sg); EXPORT_SYMBOL(sbus_unmap_sg); EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); EXPORT_SYMBOL(sbus_dma_sync_single_for_device); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); EXPORT_SYMBOL(sbus_iounmap); EXPORT_SYMBOL(sbus_ioremap); #endif diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 8e6ac5c1b7b..1c56c8b854d 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -170,8 +170,6 @@ EXPORT_SYMBOL(sbus_map_sg); EXPORT_SYMBOL(sbus_unmap_sg); EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); EXPORT_SYMBOL(sbus_dma_sync_single_for_device); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); #endif EXPORT_SYMBOL(outsb); EXPORT_SYMBOL(outsw); -- cgit v1.2.3 From 260489fa8a9735c76073ace95f03ffaf10cca884 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Aug 2008 23:00:58 -0700 Subject: sparc32: Make mmu_{get,release}_*() take a struct device pointer. Signed-off-by: David S. Miller --- arch/sparc/include/asm/dma.h | 22 +++++++++++++--------- arch/sparc/kernel/ioport.c | 17 ++++------------- arch/sparc/mm/io-unit.c | 16 ++++++++-------- arch/sparc/mm/iommu.c | 45 ++++++++++++++++++++++---------------------- 4 files changed, 47 insertions(+), 53 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h index 49356344679..5955177ec75 100644 --- a/arch/sparc/include/asm/dma.h +++ b/arch/sparc/include/asm/dma.h @@ -100,16 +100,20 @@ BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long) #define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len) #define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len) +struct page; +struct device; +struct scatterlist; + /* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */ -BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus) -BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) -BTFIXUPDEF_CALL(void, mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus) -BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) - -#define mmu_get_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_get_scsi_one)(vaddr,len,sbus) -#define mmu_get_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_get_scsi_sgl)(sg,sz,sbus) -#define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus) -#define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus) +BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, struct device *, char *, unsigned long) +BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct device *, struct scatterlist *, int) +BTFIXUPDEF_CALL(void, mmu_release_scsi_one, struct device *, __u32, unsigned long) +BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist *, int) + +#define mmu_get_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_get_scsi_one)(dev,vaddr,len) +#define mmu_get_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_get_scsi_sgl)(dev,sg,sz) +#define mmu_release_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_release_scsi_one)(dev,vaddr,len) +#define mmu_release_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_release_scsi_sgl)(dev,sg,sz) /* * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep. diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index aa73b3b71e8..11dccf94515 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -394,8 +394,6 @@ void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba) */ dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int direction) { - struct sbus_dev *sdev = to_sbus_device(dev); - /* XXX why are some lengths signed, others unsigned? */ if (len <= 0) { return 0; @@ -404,20 +402,17 @@ dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int directi if (len > 256*1024) { /* __get_free_pages() limit */ return 0; } - return mmu_get_scsi_one(va, len, sdev->bus); + return mmu_get_scsi_one(dev, va, len); } void sbus_unmap_single(struct device *dev, dma_addr_t ba, size_t n, int direction) { - struct sbus_dev *sdev = to_sbus_device(dev); - mmu_release_scsi_one(ba, n, sdev->bus); + mmu_release_scsi_one(dev, ba, n); } int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction) { - struct sbus_dev *sdev = to_sbus_device(dev); - - mmu_get_scsi_sgl(sg, n, sdev->bus); + mmu_get_scsi_sgl(dev, sg, n); /* * XXX sparc64 can return a partial length here. sun4c should do this @@ -428,9 +423,7 @@ int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direction) { - struct sbus_dev *sdev = to_sbus_device(dev); - - mmu_release_scsi_sgl(sg, n, sdev->bus); + mmu_release_scsi_sgl(dev, sg, n); } /* @@ -438,7 +431,6 @@ void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direct void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size, int direction) { #if 0 - struct sbus_dev *sdev = to_sbus_device(dev); unsigned long va; struct resource *res; @@ -459,7 +451,6 @@ void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t size, int direction) { #if 0 - struct sbus_dev *sdev = to_sbus_device(dev); unsigned long va; struct resource *res; diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 1093514a577..4239655a6aa 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -125,10 +125,10 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan); return vaddr; } -static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus *sbus) +static __u32 iounit_get_scsi_one(struct device *dev, char *vaddr, unsigned long len) { + struct iounit_struct *iounit = dev->archdata.iommu; unsigned long ret, flags; - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; spin_lock_irqsave(&iounit->lock, flags); ret = iounit_get_area(iounit, (unsigned long)vaddr, len); @@ -136,10 +136,10 @@ static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus return ret; } -static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void iounit_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) { + struct iounit_struct *iounit = dev->archdata.iommu; unsigned long flags; - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; /* FIXME: Cache some resolved pages - often several sg entries are to the same page */ spin_lock_irqsave(&iounit->lock, flags); @@ -152,10 +152,10 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus spin_unlock_irqrestore(&iounit->lock, flags); } -static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus) +static void iounit_release_scsi_one(struct device *dev, __u32 vaddr, unsigned long len) { + struct iounit_struct *iounit = dev->archdata.iommu; unsigned long flags; - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; spin_lock_irqsave(&iounit->lock, flags); len = ((vaddr & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT; @@ -166,11 +166,11 @@ static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_ spin_unlock_irqrestore(&iounit->lock, flags); } -static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) { + struct iounit_struct *iounit = dev->archdata.iommu; unsigned long flags; unsigned long vaddr, len; - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; spin_lock_irqsave(&iounit->lock, flags); while (sz != 0) { diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index a86c9f552fa..8e9ab930f09 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -169,9 +169,9 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte) } } -static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus) +static u32 iommu_get_one(struct device *dev, struct page *page, int npages) { - struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu; + struct iommu_struct *iommu = dev->archdata.iommu; int ioptex; iopte_t *iopte, *iopte0; unsigned int busa, busa0; @@ -199,8 +199,7 @@ static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus) return busa0; } -static u32 iommu_get_scsi_one(char *vaddr, unsigned int len, - struct sbus_bus *sbus) +static u32 iommu_get_scsi_one(struct device *dev, char *vaddr, unsigned int len) { unsigned long off; int npages; @@ -210,22 +209,22 @@ static u32 iommu_get_scsi_one(char *vaddr, unsigned int len, off = (unsigned long)vaddr & ~PAGE_MASK; npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT; page = virt_to_page((unsigned long)vaddr & PAGE_MASK); - busa = iommu_get_one(page, npages, sbus); + busa = iommu_get_one(dev, page, npages); return busa + off; } -static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) +static __u32 iommu_get_scsi_one_noflush(struct device *dev, char *vaddr, unsigned long len) { - return iommu_get_scsi_one(vaddr, len, sbus); + return iommu_get_scsi_one(dev, vaddr, len); } -static __u32 iommu_get_scsi_one_gflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) +static __u32 iommu_get_scsi_one_gflush(struct device *dev, char *vaddr, unsigned long len) { flush_page_for_dma(0); - return iommu_get_scsi_one(vaddr, len, sbus); + return iommu_get_scsi_one(dev, vaddr, len); } -static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) +static __u32 iommu_get_scsi_one_pflush(struct device *dev, char *vaddr, unsigned long len) { unsigned long page = ((unsigned long) vaddr) & PAGE_MASK; @@ -233,23 +232,23 @@ static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sb flush_page_for_dma(page); page += PAGE_SIZE; } - return iommu_get_scsi_one(vaddr, len, sbus); + return iommu_get_scsi_one(dev, vaddr, len); } -static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void iommu_get_scsi_sgl_noflush(struct device *dev, struct scatterlist *sg, int sz) { int n; while (sz != 0) { --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; + sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; sg->dvma_length = (__u32) sg->length; sg = sg_next(sg); } } -static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void iommu_get_scsi_sgl_gflush(struct device *dev, struct scatterlist *sg, int sz) { int n; @@ -257,13 +256,13 @@ static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbu while (sz != 0) { --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; + sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; sg->dvma_length = (__u32) sg->length; sg = sg_next(sg); } } -static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void iommu_get_scsi_sgl_pflush(struct device *dev, struct scatterlist *sg, int sz) { unsigned long page, oldpage = 0; int n, i; @@ -288,15 +287,15 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu } } - sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; + sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; sg->dvma_length = (__u32) sg->length; sg = sg_next(sg); } } -static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus) +static void iommu_release_one(struct device *dev, u32 busa, int npages) { - struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu; + struct iommu_struct *iommu = dev->archdata.iommu; int ioptex; int i; @@ -310,17 +309,17 @@ static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus) bit_map_clear(&iommu->usemap, ioptex, npages); } -static void iommu_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus) +static void iommu_release_scsi_one(struct device *dev, __u32 vaddr, unsigned long len) { unsigned long off; int npages; off = vaddr & ~PAGE_MASK; npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT; - iommu_release_one(vaddr & PAGE_MASK, npages, sbus); + iommu_release_one(dev, vaddr & PAGE_MASK, npages); } -static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void iommu_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) { int n; @@ -328,7 +327,7 @@ static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - iommu_release_one(sg->dvma_address & PAGE_MASK, n, sbus); + iommu_release_one(dev, sg->dvma_address & PAGE_MASK, n); sg->dvma_address = 0x21212121; sg = sg_next(sg); } -- cgit v1.2.3 From 944c67dff7a88f0a775e5b604937f9e30d2de555 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 18:01:36 -0700 Subject: sparc32: Implement more generic dma_*() interfaces. These dispatch to either PCI or SBUS routines based upon the device bus type. This will allow us to let SBUS drivers call these routines. Signed-off-by: David S. Miller --- arch/sparc/include/asm/dma-mapping_32.h | 59 ++++++++- arch/sparc/kernel/Makefile | 2 +- arch/sparc/kernel/dma.c | 227 ++++++++++++++++++++++++++++++++ arch/sparc/kernel/dma.h | 14 ++ arch/sparc/kernel/ioport.c | 2 + 5 files changed, 298 insertions(+), 6 deletions(-) create mode 100644 arch/sparc/kernel/dma.c create mode 100644 arch/sparc/kernel/dma.h (limited to 'arch') diff --git a/arch/sparc/include/asm/dma-mapping_32.h b/arch/sparc/include/asm/dma-mapping_32.h index f3a641e6b2c..8a57ea0573e 100644 --- a/arch/sparc/include/asm/dma-mapping_32.h +++ b/arch/sparc/include/asm/dma-mapping_32.h @@ -1,11 +1,60 @@ #ifndef _ASM_SPARC_DMA_MAPPING_H #define _ASM_SPARC_DMA_MAPPING_H +#include -#ifdef CONFIG_PCI -#include -#else -#include -#endif /* PCI */ +struct device; +struct scatterlist; +struct page; + +#define DMA_ERROR_CODE (~(dma_addr_t)0x0) + +extern int dma_supported(struct device *dev, u64 mask); +extern int dma_set_mask(struct device *dev, u64 dma_mask); +extern void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); +extern void dma_free_coherent(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle); +extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, + size_t size, + enum dma_data_direction direction); +extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, + enum dma_data_direction direction); +extern dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction); +extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, enum dma_data_direction direction); +extern int dma_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction); +extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction); +extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, + size_t size, + enum dma_data_direction direction); +extern void dma_sync_single_for_device(struct device *dev, + dma_addr_t dma_handle, + size_t size, + enum dma_data_direction direction); +extern void dma_sync_single_range_for_cpu(struct device *dev, + dma_addr_t dma_handle, + unsigned long offset, + size_t size, + enum dma_data_direction direction); +extern void dma_sync_single_range_for_device(struct device *dev, + dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction); +extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction direction); +extern void dma_sync_sg_for_device(struct device *dev, + struct scatterlist *sg, int nelems, + enum dma_data_direction direction); +extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); +extern int dma_get_cache_alignment(void); + +#define dma_alloc_noncoherent dma_alloc_coherent +#define dma_free_noncoherent dma_free_coherent #endif /* _ASM_SPARC_DMA_MAPPING_H */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 6e03a2a7863..eaf7cf4296a 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -13,7 +13,7 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ time.o windows.o cpu.o devices.o \ tadpole.o tick14.o ptrace.o \ unaligned.o una_asm.o muldiv.o \ - prom.o of_device.o devres.o + prom.o of_device.o devres.o dma.o devres-y = ../../../kernel/irq/devres.o diff --git a/arch/sparc/kernel/dma.c b/arch/sparc/kernel/dma.c new file mode 100644 index 00000000000..ebc8403b035 --- /dev/null +++ b/arch/sparc/kernel/dma.c @@ -0,0 +1,227 @@ +/* dma.c: PCI and SBUS DMA accessors for 32-bit sparc. + * + * Copyright (C) 2008 David S. Miller + */ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_PCI +#include +#endif + +#include "dma.h" + +int dma_supported(struct device *dev, u64 mask) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_dma_supported(to_pci_dev(dev), mask); +#endif + return 0; +} +EXPORT_SYMBOL(dma_supported); + +int dma_set_mask(struct device *dev, u64 dma_mask) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_set_dma_mask(to_pci_dev(dev), dma_mask); +#endif + return -EOPNOTSUPP; +} +EXPORT_SYMBOL(dma_set_mask); + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); +#endif + return sbus_alloc_consistent(dev, size, dma_handle); +} +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_coherent(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_free_consistent(to_pci_dev(dev), size, + cpu_addr, dma_handle); + return; + } +#endif + sbus_free_consistent(dev, size, cpu_addr, dma_handle); +} +EXPORT_SYMBOL(dma_free_coherent); + +dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_map_single(to_pci_dev(dev), cpu_addr, + size, (int)direction); +#endif + return sbus_map_single(dev, cpu_addr, size, (int)direction); +} +EXPORT_SYMBOL(dma_map_single); + +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, + enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_unmap_single(to_pci_dev(dev), dma_addr, + size, (int)direction); + return; + } +#endif + sbus_unmap_single(dev, dma_addr, size, (int)direction); +} +EXPORT_SYMBOL(dma_unmap_single); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_map_page(to_pci_dev(dev), page, offset, + size, (int)direction); +#endif + return sbus_map_single(dev, page_address(page) + offset, + size, (int)direction); +} +EXPORT_SYMBOL(dma_map_page); + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_unmap_page(to_pci_dev(dev), dma_address, + size, (int)direction); + return; + } +#endif + sbus_unmap_single(dev, dma_address, size, (int)direction); +} +EXPORT_SYMBOL(dma_unmap_page); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); +#endif + return sbus_map_sg(dev, sg, nents, direction); +} +EXPORT_SYMBOL(dma_map_sg); + +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_unmap_sg(to_pci_dev(dev), sg, nents, (int)direction); + return; + } +#endif + sbus_unmap_sg(dev, sg, nents, (int)direction); +} +EXPORT_SYMBOL(dma_unmap_sg); + +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, + size, (int)direction); + return; + } +#endif + sbus_dma_sync_single_for_cpu(dev, dma_handle, size, (int) direction); +} +EXPORT_SYMBOL(dma_sync_single_for_cpu); + +void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, + size, (int)direction); + return; + } +#endif + sbus_dma_sync_single_for_device(dev, dma_handle, size, (int) direction); +} +EXPORT_SYMBOL(dma_sync_single_for_device); + +void dma_sync_single_range_for_cpu(struct device *dev, + dma_addr_t dma_handle, + unsigned long offset, + size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); +} +EXPORT_SYMBOL(dma_sync_single_range_for_cpu); + +void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_device(dev, dma_handle+offset, size, direction); +} +EXPORT_SYMBOL(dma_sync_single_range_for_device); + +void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, + nelems, (int)direction); + return; + } +#endif + BUG(); +} +EXPORT_SYMBOL(dma_sync_sg_for_cpu); + +void dma_sync_sg_for_device(struct device *dev, + struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, + nelems, (int)direction); + return; + } +#endif + BUG(); +} +EXPORT_SYMBOL(dma_sync_sg_for_device); + +int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return (dma_addr == DMA_ERROR_CODE); +} +EXPORT_SYMBOL(dma_mapping_error); + +int dma_get_cache_alignment(void) +{ + return 32; +} +EXPORT_SYMBOL(dma_get_cache_alignment); diff --git a/arch/sparc/kernel/dma.h b/arch/sparc/kernel/dma.h new file mode 100644 index 00000000000..f8d8951adb5 --- /dev/null +++ b/arch/sparc/kernel/dma.h @@ -0,0 +1,14 @@ +void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp); +void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba); +dma_addr_t sbus_map_single(struct device *dev, void *va, + size_t len, int direction); +void sbus_unmap_single(struct device *dev, dma_addr_t ba, + size_t n, int direction); +int sbus_map_sg(struct device *dev, struct scatterlist *sg, + int n, int direction); +void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, + int n, int direction); +void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, + size_t size, int direction); +void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, + size_t size, int direction); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 11dccf94515..0b3035978e0 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -49,6 +49,8 @@ #include #include +#include "dma.h" + #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ static struct resource *_sparc_find_resource(struct resource *r, -- cgit v1.2.3 From 738f2b7b813913e651f39387d007dd961755dee2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 18:09:11 -0700 Subject: sparc: Convert all SBUS drivers to dma_*() interfaces. And all the SBUS dma interfaces are deleted. A private implementation remains inside of the 32-bit sparc port which exists only for the sake of the implementation of dma_*(). Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 17 ---------- arch/sparc/include/asm/sbus_64.h | 63 ------------------------------------- arch/sparc/kernel/sparc_ksyms.c | 8 ----- arch/sparc64/kernel/sparc64_ksyms.c | 8 ----- 4 files changed, 96 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index 61d99f1bb23..b09284b5ee0 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -109,26 +109,9 @@ extern void sbus_set_sbus64(struct sbus_dev *, int); extern void sbus_fill_device_irq(struct sbus_dev *); /* These yield IOMMU mappings in consistent mode. */ -extern void *sbus_alloc_consistent(struct device *, long, u32 *dma_addrp); -extern void sbus_free_consistent(struct device *, long, void *, u32); void prom_adjust_ranges(struct linux_prom_ranges *, int, struct linux_prom_ranges *, int); -#define SBUS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL -#define SBUS_DMA_TODEVICE DMA_TO_DEVICE -#define SBUS_DMA_FROMDEVICE DMA_FROM_DEVICE -#define SBUS_DMA_NONE DMA_NONE - -/* All the rest use streaming mode mappings. */ -extern dma_addr_t sbus_map_single(struct device *, void *, size_t, int); -extern void sbus_unmap_single(struct device *, dma_addr_t, size_t, int); -extern int sbus_map_sg(struct device *, struct scatterlist *, int, int); -extern void sbus_unmap_sg(struct device *, struct scatterlist *, int, int); - -/* Finally, allow explicit synchronization of streamable mappings. */ -extern void sbus_dma_sync_single_for_cpu(struct device *, dma_addr_t, size_t, int); -extern void sbus_dma_sync_single_for_device(struct device *, dma_addr_t, size_t, int); - /* Eric Brower (ebrower@usa.net) * Translate SBus interrupt levels to ino values-- * this is used when converting sbus "interrupts" OBP diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index b22e99da49d..9a2f27188f6 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -100,69 +100,6 @@ extern struct sbus_bus *sbus_root; extern void sbus_set_sbus64(struct sbus_dev *, int); extern void sbus_fill_device_irq(struct sbus_dev *); -static inline void *sbus_alloc_consistent(struct device *dev , size_t size, - dma_addr_t *dma_handle) -{ - return dma_alloc_coherent(dev, size, dma_handle, GFP_ATOMIC); -} - -static inline void sbus_free_consistent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - return dma_free_coherent(dev, size, vaddr, dma_handle); -} - -#define SBUS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL -#define SBUS_DMA_TODEVICE DMA_TO_DEVICE -#define SBUS_DMA_FROMDEVICE DMA_FROM_DEVICE -#define SBUS_DMA_NONE DMA_NONE - -/* All the rest use streaming mode mappings. */ -static inline dma_addr_t sbus_map_single(struct device *dev, void *ptr, - size_t size, int direction) -{ - return dma_map_single(dev, ptr, size, - (enum dma_data_direction) direction); -} - -static inline void sbus_unmap_single(struct device *dev, - dma_addr_t dma_addr, size_t size, - int direction) -{ - dma_unmap_single(dev, dma_addr, size, - (enum dma_data_direction) direction); -} - -static inline int sbus_map_sg(struct device *dev, struct scatterlist *sg, - int nents, int direction) -{ - return dma_map_sg(dev, sg, nents, - (enum dma_data_direction) direction); -} - -static inline void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, - int nents, int direction) -{ - dma_unmap_sg(dev, sg, nents, - (enum dma_data_direction) direction); -} - -/* Finally, allow explicit synchronization of streamable mappings. */ -static inline void sbus_dma_sync_single_for_cpu(struct device *dev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - dma_sync_single_for_cpu(dev, dma_handle, size, - (enum dma_data_direction) direction); -} - -static inline void sbus_dma_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - /* No flushing needed to sync cpu writes to the device. */ -} - extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 9d85a83586a..b1d2c975b32 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -155,14 +155,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(sbus_set_sbus64); -EXPORT_SYMBOL(sbus_alloc_consistent); -EXPORT_SYMBOL(sbus_free_consistent); -EXPORT_SYMBOL(sbus_map_single); -EXPORT_SYMBOL(sbus_unmap_single); -EXPORT_SYMBOL(sbus_map_sg); -EXPORT_SYMBOL(sbus_unmap_sg); -EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_single_for_device); EXPORT_SYMBOL(sbus_iounmap); EXPORT_SYMBOL(sbus_ioremap); #endif diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 1c56c8b854d..901c26437b6 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -162,14 +162,6 @@ EXPORT_SYMBOL(auxio_set_lte); #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(sbus_set_sbus64); -EXPORT_SYMBOL(sbus_alloc_consistent); -EXPORT_SYMBOL(sbus_free_consistent); -EXPORT_SYMBOL(sbus_map_single); -EXPORT_SYMBOL(sbus_unmap_single); -EXPORT_SYMBOL(sbus_map_sg); -EXPORT_SYMBOL(sbus_unmap_sg); -EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_single_for_device); #endif EXPORT_SYMBOL(outsb); EXPORT_SYMBOL(outsw); -- cgit v1.2.3 From 63237eeb5ac92d618a0a6055f4b1f65c5d14682b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Aug 2008 23:33:42 -0700 Subject: sparc: Move SBUS DMA attribute interfaces out of asm/sbus.h This is in preparation for the subsequent asm/sbus.h removal. Also, make these routines take a "struct device" or no arguments, as appropriate. Signed-off-by: David S. Miller --- arch/sparc/include/asm/io_32.h | 11 +++++++++++ arch/sparc/include/asm/io_64.h | 11 +++++++++++ arch/sparc/include/asm/sbus_32.h | 4 ---- arch/sparc/include/asm/sbus_64.h | 4 ---- arch/sparc/kernel/ioport.c | 2 +- arch/sparc64/kernel/sbus.c | 16 +++++++++++++--- 6 files changed, 36 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h index 10d7da45007..3ab3164bd73 100644 --- a/arch/sparc/include/asm/io_32.h +++ b/arch/sparc/include/asm/io_32.h @@ -308,6 +308,17 @@ extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size); #define RTC_PORT(x) (rtc_port + (x)) #define RTC_ALWAYS_BCD 0 +static inline int sbus_can_dma_64bit(void) +{ + return 0; /* actually, sparc_cpu_model==sun4d */ +} +static inline int sbus_can_burst64(void) +{ + return 0; /* actually, sparc_cpu_model==sun4d */ +} +struct device; +extern void sbus_set_sbus64(struct device *, int); + #endif #define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1 diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h index 0bff078ffdd..73a9c5d4195 100644 --- a/arch/sparc/include/asm/io_64.h +++ b/arch/sparc/include/asm/io_64.h @@ -495,6 +495,17 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *); #define sbus_iounmap(__addr, __size) \ release_region((unsigned long)(__addr), (__size)) +static inline int sbus_can_dma_64bit(void) +{ + return 1; +} +static inline int sbus_can_burst64(void) +{ + return 1; +} +struct device; +extern void sbus_set_sbus64(struct device *, int); + /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem * access diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index b09284b5ee0..435ae394d2b 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -102,10 +102,6 @@ sbus_is_slave(struct sbus_dev *dev) for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ for ((device) = (bus)->devices; (device); (device) = (device)->next) -/* Driver DVMA interfaces. */ -#define sbus_can_dma_64bit(sdev) (0) /* actually, sparc_cpu_model==sun4d */ -#define sbus_can_burst64(sdev) (0) /* actually, sparc_cpu_model==sun4d */ -extern void sbus_set_sbus64(struct sbus_dev *, int); extern void sbus_fill_device_irq(struct sbus_dev *); /* These yield IOMMU mappings in consistent mode. */ diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index 9a2f27188f6..79719c2e5fa 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -94,10 +94,6 @@ extern struct sbus_bus *sbus_root; for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ for ((device) = (bus)->devices; (device); (device) = (device)->next) -/* Driver DVMA interfaces. */ -#define sbus_can_dma_64bit(sdev) (1) -#define sbus_can_burst64(sdev) (1) -extern void sbus_set_sbus64(struct sbus_dev *, int); extern void sbus_fill_device_irq(struct sbus_dev *); extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 0b3035978e0..e87ed519ffa 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -250,7 +250,7 @@ static void _sparc_free_io(struct resource *res) #ifdef CONFIG_SBUS -void sbus_set_sbus64(struct sbus_dev *sdev, int x) +void sbus_set_sbus64(struct device *dev, int x) { printk("sbus_set_sbus64: unsupported\n"); } diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index e33a8a660e9..aa47022e13f 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -52,13 +52,23 @@ #define STRBUF_TAG_VALID 0x02UL /* Enable 64-bit DVMA mode for the given device. */ -void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) +void sbus_set_sbus64(struct device *dev, int bursts) { - struct iommu *iommu = sdev->ofdev.dev.archdata.iommu; - int slot = sdev->slot; + struct iommu *iommu = dev->archdata.iommu; + struct of_device *op = to_of_device(dev); + const struct linux_prom_registers *regs; unsigned long cfg_reg; + int slot; u64 val; + regs = of_get_property(op->node, "reg", NULL); + if (!regs) { + printk(KERN_ERR "sbus_set_sbus64: Cannot find regs for %s\n", + op->node->full_name); + return; + } + slot = regs->which_io; + cfg_reg = iommu->write_complete_reg; switch (slot) { case 0: -- cgit v1.2.3 From 10a104f9c591c3b1175bbb03ecb0bc8f2a4a16ee Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 01:55:54 -0700 Subject: sparc64: Convert SBUS floppy probing to use OF device objects. Signed-off-by: David S. Miller --- arch/sparc/include/asm/floppy_64.h | 45 +++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index c39db1060bc..d8fb0602745 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h @@ -1,6 +1,6 @@ /* floppy.h: Sparc specific parts of the Floppy driver. * - * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net) * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * * Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be) @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include @@ -18,7 +20,6 @@ #include #include #include -#include #include @@ -50,7 +51,7 @@ struct sun_flpy_controller { /* You'll only ever find one controller on an Ultra anyways. */ static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1; unsigned long fdc_status; -static struct sbus_dev *floppy_sdev = NULL; +static struct of_device *floppy_op = NULL; struct sun_floppy_ops { unsigned char (*fd_inb) (unsigned long port); @@ -559,22 +560,28 @@ static int __init ebus_fdthree_p(struct linux_ebus_device *edev) static unsigned long __init sun_floppy_init(void) { - char state[128]; - struct sbus_bus *bus; - struct sbus_dev *sdev = NULL; static int initialized = 0; + struct device_node *dp; + struct of_device *op; + const char *prop; + char state[128]; if (initialized) return sun_floppy_types[0]; initialized = 1; - for_all_sbusdev (sdev, bus) { - if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) + op = NULL; + + for_each_node_by_name(dp, "SUNW,fdtwo") { + if (strcmp(dp->parent->name, "sbus")) + continue; + op = of_find_device_by_node(dp); + if (op) break; } - if(sdev) { - floppy_sdev = sdev; - FLOPPY_IRQ = sdev->irqs[0]; + if (op) { + floppy_op = op; + FLOPPY_IRQ = op->irqs[0]; } else { #ifdef CONFIG_PCI struct linux_ebus *ebus; @@ -593,7 +600,9 @@ static unsigned long __init sun_floppy_init(void) if (!edev) return 0; - state_prop = of_get_property(edev->prom_node, "status", NULL); + op = &edev->ofdev; + + state_prop = of_get_property(op->node, "status", NULL); if (state_prop && !strncmp(state_prop, "disabled", 8)) return 0; @@ -720,22 +729,22 @@ static unsigned long __init sun_floppy_init(void) return 0; #endif } - prom_getproperty(sdev->prom_node, "status", state, sizeof(state)); - if(!strncmp(state, "disabled", 8)) + prop = of_get_property(op->node, "status", NULL); + if (prop && !strncmp(state, "disabled", 8)) return 0; /* - * We cannot do sbus_ioremap here: it does request_region, + * We cannot do of_ioremap here: it does request_region, * which the generic floppy driver tries to do once again. * But we must use the sdev resource values as they have * had parent ranges applied. */ sun_fdc = (struct sun_flpy_controller *) - (sdev->resource[0].start + - ((sdev->resource[0].flags & 0x1ffUL) << 32UL)); + (op->resource[0].start + + ((op->resource[0].flags & 0x1ffUL) << 32UL)); /* Last minute sanity check... */ - if(sbus_readb(&sun_fdc->status1_82077) == 0xff) { + if (sbus_readb(&sun_fdc->status1_82077) == 0xff) { sun_fdc = (struct sun_flpy_controller *)-1; return 0; } -- cgit v1.2.3 From aba945e76b9caeae5b6cfff179ca7bebb9bac805 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 02:20:35 -0700 Subject: sparc32: Kill mmu_translate_dvma() usage. Just simply use virt_to_page() on the provided virtual address pointer. Kill #if 0'd code. Signed-off-by: David S. Miller --- arch/sparc/kernel/ioport.c | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index e87ed519ffa..82ef2016191 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -383,7 +383,7 @@ void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba) kfree(res); /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ - pgv = mmu_translate_dvma(ba); + pgv = virt_to_page(p); mmu_unmap_dma_area(ba, n); __free_pages(pgv, get_order(n)); @@ -428,46 +428,12 @@ void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direct mmu_release_scsi_sgl(dev, sg, n); } -/* - */ void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size, int direction) { -#if 0 - unsigned long va; - struct resource *res; - - /* We do not need the resource, just print a message if invalid. */ - res = _sparc_find_resource(&_sparc_dvma, ba); - if (res == NULL) - panic("sbus_dma_sync_single: 0x%x\n", ba); - - va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */ - /* - * XXX This bogosity will be fixed with the iommu rewrite coming soon - * to a kernel near you. - Anton - */ - /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ -#endif } void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t size, int direction) { -#if 0 - unsigned long va; - struct resource *res; - - /* We do not need the resource, just print a message if invalid. */ - res = _sparc_find_resource(&_sparc_dvma, ba); - if (res == NULL) - panic("sbus_dma_sync_single: 0x%x\n", ba); - - va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */ - /* - * XXX This bogosity will be fixed with the iommu rewrite coming soon - * to a kernel near you. - Anton - */ - /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ -#endif } /* Support code for sbus_init(). */ -- cgit v1.2.3 From b1387c35bef6da55f6f2c27dfb748c86a4ef7ef9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 02:29:50 -0700 Subject: sparc32: Kill mmu_translate_dvma and implementations. No longer used. Signed-off-by: David S. Miller --- arch/sparc/include/asm/dma.h | 2 -- arch/sparc/mm/io-unit.c | 14 -------------- arch/sparc/mm/iommu.c | 10 ---------- arch/sparc/mm/sun4c.c | 8 -------- 4 files changed, 34 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h index 5955177ec75..ee4ac181bf2 100644 --- a/arch/sparc/include/asm/dma.h +++ b/arch/sparc/include/asm/dma.h @@ -132,12 +132,10 @@ BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist * to a separate mapping function for CPU visible mappings. */ BTFIXUPDEF_CALL(int, mmu_map_dma_area, dma_addr_t *, unsigned long, unsigned long, int len) -BTFIXUPDEF_CALL(struct page *, mmu_translate_dvma, unsigned long busa) BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, unsigned long busa, int len) #define mmu_map_dma_area(pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(pba,va,a,len) #define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len) -#define mmu_translate_dvma(ba) BTFIXUP_CALL(mmu_translate_dvma)(ba) #endif #endif /* !(_ASM_SPARC_DMA_H) */ diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 4239655a6aa..6b469820fb9 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -233,19 +233,6 @@ static void iounit_unmap_dma_area(unsigned long addr, int len) { /* XXX Somebody please fill this in */ } - -/* XXX We do not pass sbus device here, bad. */ -static struct page *iounit_translate_dvma(unsigned long addr) -{ - struct sbus_bus *sbus = sbus_root; /* They are all the same */ - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; - int i; - iopte_t *iopte; - - i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); - iopte = (iopte_t *)(iounit->page_table + i); - return pfn_to_page(iopte_val(*iopte) >> (PAGE_SHIFT-4)); /* XXX sun4d guru, help */ -} #endif static char *iounit_lockarea(char *vaddr, unsigned long len) @@ -272,7 +259,6 @@ void __init ld_mmu_iounit(void) #ifdef CONFIG_SBUS BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_translate_dvma, iounit_translate_dvma, BTFIXUPCALL_NORM); #endif } diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 8e9ab930f09..832d99f3347 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -421,15 +421,6 @@ static void iommu_unmap_dma_area(unsigned long busa, int len) iommu_invalidate(iommu->regs); bit_map_clear(&iommu->usemap, ioptex, len >> PAGE_SHIFT); } - -static struct page *iommu_translate_dvma(unsigned long busa) -{ - struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu; - iopte_t *iopte = iommu->page_table; - - iopte += ((busa - iommu->start) >> PAGE_SHIFT); - return pfn_to_page((iopte_val(*iopte) & IOPTE_PAGE) >> (PAGE_SHIFT-4)); -} #endif static char *iommu_lockarea(char *vaddr, unsigned long len) @@ -465,7 +456,6 @@ void __init ld_mmu_iommu(void) #ifdef CONFIG_SBUS BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_translate_dvma, iommu_translate_dvma, BTFIXUPCALL_NORM); #endif if (viking_mxcc_present || srmmu_modtype == HyperSparc) { diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index d1782f6368b..65af3119f5a 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -555,13 +555,6 @@ static int sun4c_map_dma_area(dma_addr_t *pba, unsigned long va, return 0; } -static struct page *sun4c_translate_dvma(unsigned long busa) -{ - /* Fortunately for us, bus_addr == uncached_virt in sun4c. */ - unsigned long pte = sun4c_get_pte(busa); - return pfn_to_page(pte & SUN4C_PFN_MASK); -} - static void sun4c_unmap_dma_area(unsigned long busa, int len) { /* Fortunately for us, bus_addr == uncached_virt in sun4c. */ @@ -2263,7 +2256,6 @@ void __init ld_mmu_sun4c(void) BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_translate_dvma, sun4c_translate_dvma, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(sparc_mapiorange, sun4c_mapiorange, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(sparc_unmapiorange, sun4c_unmapiorange, BTFIXUPCALL_NORM); -- cgit v1.2.3 From 4b1c5df2af38b2681b7c1a058534d17c54aaf6cf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 18:40:38 -0700 Subject: sparc32: Make mmu_map_dma_area and mmu_unmap_dma_area take a device pointer. This lets us kill this "map it in every IOMMU" crazy code, and also some of the final references to sbus_root. Signed-off-by: David S. Miller --- arch/sparc/include/asm/dma.h | 8 ++++---- arch/sparc/kernel/ioport.c | 4 ++-- arch/sparc/mm/io-unit.c | 14 +++++--------- arch/sparc/mm/iommu.c | 10 +++++----- arch/sparc/mm/sun4c.c | 6 +++--- 5 files changed, 19 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h index ee4ac181bf2..d1ae56be9fa 100644 --- a/arch/sparc/include/asm/dma.h +++ b/arch/sparc/include/asm/dma.h @@ -131,11 +131,11 @@ BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist * know if we are mapping RAM or I/O, so it has to be an additional argument * to a separate mapping function for CPU visible mappings. */ -BTFIXUPDEF_CALL(int, mmu_map_dma_area, dma_addr_t *, unsigned long, unsigned long, int len) -BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, unsigned long busa, int len) +BTFIXUPDEF_CALL(int, mmu_map_dma_area, struct device *, dma_addr_t *, unsigned long, unsigned long, int len) +BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, struct device *, unsigned long busa, int len) -#define mmu_map_dma_area(pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(pba,va,a,len) -#define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len) +#define mmu_map_dma_area(dev,pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(dev,pba,va,a,len) +#define mmu_unmap_dma_area(dev,ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(dev,ba,len) #endif #endif /* !(_ASM_SPARC_DMA_H) */ diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 82ef2016191..d65fb9b0668 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -339,7 +339,7 @@ void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp) * XXX That's where sdev would be used. Currently we load * all iommu tables with the same translations. */ - if (mmu_map_dma_area(dma_addrp, va, res->start, len_total) != 0) + if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) goto err_noiommu; res->name = op->node->name; @@ -384,7 +384,7 @@ void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba) /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ pgv = virt_to_page(p); - mmu_unmap_dma_area(ba, n); + mmu_unmap_dma_area(dev, ba, n); __free_pages(pgv, get_order(n)); } diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 6b469820fb9..0f97ab30df3 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -186,12 +186,12 @@ static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg, } #ifdef CONFIG_SBUS -static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, int len) +static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, __u32 addr, int len) { + struct iounit_struct *iounit = dev->archdata.iommu; unsigned long page, end; pgprot_t dvma_prot; iopte_t *iopte; - struct sbus_bus *sbus; *pba = addr; @@ -213,12 +213,8 @@ static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, in i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); - for_each_sbus(sbus) { - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; - - iopte = (iopte_t *)(iounit->page_table + i); - *iopte = MKIOPTE(__pa(page)); - } + iopte = (iopte_t *)(iounit->page_table + i); + *iopte = MKIOPTE(__pa(page)); } addr += PAGE_SIZE; va += PAGE_SIZE; @@ -229,7 +225,7 @@ static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, in return 0; } -static void iounit_unmap_dma_area(unsigned long addr, int len) +static void iounit_unmap_dma_area(struct device *dev, unsigned long addr, int len) { /* XXX Somebody please fill this in */ } diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 832d99f3347..2970cea877b 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -334,11 +334,11 @@ static void iommu_release_scsi_sgl(struct device *dev, struct scatterlist *sg, i } #ifdef CONFIG_SBUS -static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va, - unsigned long addr, int len) +static int iommu_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, + unsigned long addr, int len) { + struct iommu_struct *iommu = dev->archdata.iommu; unsigned long page, end; - struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu; iopte_t *iopte = iommu->page_table; iopte_t *first; int ioptex; @@ -401,9 +401,9 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va, return 0; } -static void iommu_unmap_dma_area(unsigned long busa, int len) +static void iommu_unmap_dma_area(struct device *dev, unsigned long busa, int len) { - struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu; + struct iommu_struct *iommu = dev->archdata.iommu; iopte_t *iopte = iommu->page_table; unsigned long end; int ioptex = (busa - iommu->start) >> PAGE_SHIFT; diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 65af3119f5a..f289e7ce902 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -532,8 +532,8 @@ static inline void sun4c_init_ss2_cache_bug(void) } /* Addr is always aligned on a page boundary for us already. */ -static int sun4c_map_dma_area(dma_addr_t *pba, unsigned long va, - unsigned long addr, int len) +static int sun4c_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, + unsigned long addr, int len) { unsigned long page, end; @@ -555,7 +555,7 @@ static int sun4c_map_dma_area(dma_addr_t *pba, unsigned long va, return 0; } -static void sun4c_unmap_dma_area(unsigned long busa, int len) +static void sun4c_unmap_dma_area(struct device *dev, unsigned long busa, int len) { /* Fortunately for us, bus_addr == uncached_virt in sun4c. */ /* XXX Implement this */ -- cgit v1.2.3 From 7e7e2f035663c5ceb029bfb9d91e75099b0a5625 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 02:45:36 -0700 Subject: sparc32: Convert apc to OF driver. Signed-off-by: David S. Miller --- arch/sparc/kernel/apc.c | 72 ++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 34 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 5267d48fb2c..0a20cd85fd3 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -12,9 +12,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -29,11 +30,10 @@ #define APC_OBPNAME "power-management" #define APC_DEVNAME "apc" -volatile static u8 __iomem *regs; -static int apc_regsize; +static u8 __iomem *regs; static int apc_no_idle __initdata = 0; -#define apc_readb(offs) (sbus_readb(regs+offs)) +#define apc_readb(offs) (sbus_readb(regs+offs)) #define apc_writeb(val, offs) (sbus_writeb(val, regs+offs)) /* Specify "apc=noidle" on the kernel command line to @@ -69,9 +69,9 @@ static void apc_swift_idle(void) #endif } -static inline void apc_free(void) +static inline void apc_free(struct of_device *op) { - sbus_iounmap(regs, apc_regsize); + of_iounmap(&op->resource[0], regs, resource_size(&op->resource[0])); } static int apc_open(struct inode *inode, struct file *f) @@ -153,52 +153,56 @@ static const struct file_operations apc_fops = { static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops }; -static int __init apc_probe(void) +static int __devinit apc_probe(struct of_device *op, + const struct of_device_id *match) { - struct sbus_bus *sbus = NULL; - struct sbus_dev *sdev = NULL; - int iTmp = 0; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, APC_OBPNAME)) { - goto sbus_done; - } - } - } + int err; -sbus_done: - if (!sdev) { - return -ENODEV; - } - - apc_regsize = sdev->reg_addrs[0].reg_size; - regs = sbus_ioremap(&sdev->resource[0], 0, - apc_regsize, APC_OBPNAME); - if(!regs) { + regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), APC_OBPNAME); + if (!regs) { printk(KERN_ERR "%s: unable to map registers\n", APC_DEVNAME); return -ENODEV; } - iTmp = misc_register(&apc_miscdev); - if (iTmp != 0) { + err = misc_register(&apc_miscdev); + if (err) { printk(KERN_ERR "%s: unable to register device\n", APC_DEVNAME); - apc_free(); + apc_free(op); return -ENODEV; } /* Assign power management IDLE handler */ - if(!apc_no_idle) + if (!apc_no_idle) pm_idle = apc_swift_idle; printk(KERN_INFO "%s: power management initialized%s\n", - APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); + APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); + return 0; } +static struct of_device_id apc_match[] = { + { + .name = APC_OBPNAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, apc_match); + +static struct of_platform_driver apc_driver = { + .name = "apc", + .match_table = apc_match, + .probe = apc_probe, +}; + +static int __init apc_init(void) +{ + return of_register_driver(&apc_driver, &of_bus_type); +} + /* This driver is not critical to the boot process * and is easiest to ioremap when SBus is already * initialized, so we install ourselves thusly: */ -__initcall(apc_probe); - +__initcall(apc_init); -- cgit v1.2.3 From f1b6aa87b7eb8573d04f8cb21574fe565e86a380 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 02:48:26 -0700 Subject: sparc32: Convert pmc to OF driver. Signed-off-by: David S. Miller --- arch/sparc/kernel/pmc.c | 57 ++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 7eca8871ff4..9976e82e323 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -10,9 +10,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -30,10 +31,9 @@ #define PMC_IDLE_REG 0x00 #define PMC_IDLE_ON 0x01 -volatile static u8 __iomem *regs; -static int pmc_regsize; +static u8 __iomem *regs; -#define pmc_readb(offs) (sbus_readb(regs+offs)) +#define pmc_readb(offs) (sbus_readb(regs+offs)) #define pmc_writeb(val, offs) (sbus_writeb(val, regs+offs)) /* @@ -53,31 +53,11 @@ void pmc_swift_idle(void) #endif } -static inline void pmc_free(void) +static int __devinit pmc_probe(struct of_device *op, + const struct of_device_id *match) { - sbus_iounmap(regs, pmc_regsize); -} - -static int __init pmc_probe(void) -{ - struct sbus_bus *sbus = NULL; - struct sbus_dev *sdev = NULL; - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, PMC_OBPNAME)) { - goto sbus_done; - } - } - } - -sbus_done: - if (!sdev) { - return -ENODEV; - } - - pmc_regsize = sdev->reg_addrs[0].reg_size; - regs = sbus_ioremap(&sdev->resource[0], 0, - pmc_regsize, PMC_OBPNAME); + regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), PMC_OBPNAME); if (!regs) { printk(KERN_ERR "%s: unable to map registers\n", PMC_DEVNAME); return -ENODEV; @@ -92,8 +72,27 @@ sbus_done: return 0; } +static struct of_device_id pmc_match[] = { + { + .name = PMC_OBPNAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, pmc_match); + +static struct of_platform_driver pmc_driver = { + .name = "pmc", + .match_table = pmc_match, + .probe = pmc_probe, +}; + +static int __init pmc_init(void) +{ + return of_register_driver(&pmc_driver, &of_bus_type); +} + /* This driver is not critical to the boot process * and is easiest to ioremap when SBus is already * initialized, so we install ourselves thusly: */ -__initcall(pmc_probe); +__initcall(pmc_init); -- cgit v1.2.3 From 71d3721189c0f4fad105a81e052bddfb826b693b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 02:50:57 -0700 Subject: sparc32: Convert sun4d IRQ code to use generic device tree probing. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4d_irq.c | 83 +++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 1290b5998f8..7424967142f 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -409,47 +409,55 @@ static void sun4d_set_udt(int cpu) /* Setup IRQ distribution scheme. */ void __init sun4d_distribute_irqs(void) { + struct device_node *dp; + #ifdef DISTRIBUTE_IRQS - struct sbus_bus *sbus; - unsigned long sbus_serving_map; + cpumask_t sbus_serving_map; sbus_serving_map = cpu_present_map; - for_each_sbus(sbus) { - if ((sbus->board * 2) == boot_cpu_id && (cpu_present_map & (1 << (sbus->board * 2 + 1)))) - sbus_tid[sbus->board] = (sbus->board * 2 + 1); - else if (cpu_present_map & (1 << (sbus->board * 2))) - sbus_tid[sbus->board] = (sbus->board * 2); - else if (cpu_present_map & (1 << (sbus->board * 2 + 1))) - sbus_tid[sbus->board] = (sbus->board * 2 + 1); + for_each_node_by_name(dp, "sbi") { + int board = of_getintprop_default(dp, "board#", 0); + + if ((board * 2) == boot_cpu_id && cpu_isset(board * 2 + 1, cpu_present_map)) + sbus_tid[board] = (board * 2 + 1); + else if (cpu_isset(board * 2, cpu_present_map)) + sbus_tid[board] = (board * 2); + else if (cpu_isset(board * 2 + 1, cpu_present_map)) + sbus_tid[board] = (board * 2 + 1); else - sbus_tid[sbus->board] = 0xff; - if (sbus_tid[sbus->board] != 0xff) - sbus_serving_map &= ~(1 << sbus_tid[sbus->board]); + sbus_tid[board] = 0xff; + if (sbus_tid[board] != 0xff) + cpu_clear(sbus_tid[board], sbus_serving_map); } - for_each_sbus(sbus) - if (sbus_tid[sbus->board] == 0xff) { + for_each_node_by_name(dp, "sbi") { + int board = of_getintprop_default(dp, "board#", 0); + if (sbus_tid[board] == 0xff) { int i = 31; - if (!sbus_serving_map) + if (cpus_empty(sbus_serving_map)) sbus_serving_map = cpu_present_map; - while (!(sbus_serving_map & (1 << i))) + while (cpu_isset(i, sbus_serving_map)) i--; - sbus_tid[sbus->board] = i; - sbus_serving_map &= ~(1 << i); + sbus_tid[board] = i; + cpu_clear(i, sbus_serving_map); } - for_each_sbus(sbus) { - printk("sbus%d IRQs directed to CPU%d\n", sbus->board, sbus_tid[sbus->board]); - set_sbi_tid(sbus->devid, sbus_tid[sbus->board] << 3); + } + for_each_node_by_name(dp, "sbi") { + int devid = of_getintprop_default(dp, "device-id", 0); + int board = of_getintprop_default(dp, "board#", 0); + printk("sbus%d IRQs directed to CPU%d\n", board, sbus_tid[board]); + set_sbi_tid(devid, sbus_tid[board] << 3); } #else - struct sbus_bus *sbus; int cpuid = cpu_logical_map(1); if (cpuid == -1) cpuid = cpu_logical_map(0); - for_each_sbus(sbus) { - sbus_tid[sbus->board] = cpuid; - set_sbi_tid(sbus->devid, cpuid << 3); + for_each_node_by_name(dp, "sbi") { + int devid = of_getintprop_default(dp, "device-id", 0); + int board = of_getintprop_default(dp, "board#", 0); + sbus_tid[board] = cpuid; + set_sbi_tid(devid, cpuid << 3); } printk("All sbus IRQs directed to CPU%d\n", cpuid); #endif @@ -541,29 +549,34 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) void __init sun4d_init_sbi_irq(void) { - struct sbus_bus *sbus; - unsigned mask; + struct device_node *dp; nsbi = 0; - for_each_sbus(sbus) + for_each_node_by_name(dp, "sbi") nsbi++; sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); if (!sbus_actions) { prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); prom_halt(); } - for_each_sbus(sbus) { + for_each_node_by_name(dp, "sbi") { + int devid = of_getintprop_default(dp, "device-id", 0); + int board = of_getintprop_default(dp, "board#", 0); + unsigned int mask; + #ifdef CONFIG_SMP - extern unsigned char boot_cpu_id; + { + extern unsigned char boot_cpu_id; - set_sbi_tid(sbus->devid, boot_cpu_id << 3); - sbus_tid[sbus->board] = boot_cpu_id; + set_sbi_tid(devid, boot_cpu_id << 3); + sbus_tid[board] = boot_cpu_id; + } #endif /* Get rid of pending irqs from PROM */ - mask = acquire_sbi(sbus->devid, 0xffffffff); + mask = acquire_sbi(devid, 0xffffffff); if (mask) { - printk ("Clearing pending IRQs %08x on SBI %d\n", mask, sbus->board); - release_sbi(sbus->devid, mask); + printk ("Clearing pending IRQs %08x on SBI %d\n", mask, board); + release_sbi(devid, mask); } } } -- cgit v1.2.3 From 33c4655c00e6af3ec4023f2cafd63dd4a42de49b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 02:56:39 -0700 Subject: sparc: Kill SBUS layer IRQ hooks. IRQs are obtained by drivers from the of_device struct. Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 17 ------------- arch/sparc/include/asm/sbus_64.h | 3 --- arch/sparc/kernel/ioport.c | 53 ---------------------------------------- arch/sparc/kernel/sun4c_irq.c | 13 ---------- arch/sparc/kernel/sun4d_irq.c | 21 ---------------- arch/sparc/kernel/sun4m_irq.c | 13 ---------- arch/sparc64/kernel/sbus.c | 24 ------------------ 7 files changed, 144 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index 435ae394d2b..81ea0f687b1 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -76,9 +76,6 @@ struct sbus_bus { struct linux_prom_ranges sbus_ranges[PROMREG_MAX]; int num_sbus_ranges; - - int devid; - int board; }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) @@ -102,26 +99,12 @@ sbus_is_slave(struct sbus_dev *dev) for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ for ((device) = (bus)->devices; (device); (device) = (device)->next) -extern void sbus_fill_device_irq(struct sbus_dev *); - /* These yield IOMMU mappings in consistent mode. */ void prom_adjust_ranges(struct linux_prom_ranges *, int, struct linux_prom_ranges *, int); -/* Eric Brower (ebrower@usa.net) - * Translate SBus interrupt levels to ino values-- - * this is used when converting sbus "interrupts" OBP - * node values to "intr" node values, and is platform - * dependent. If only we could call OBP with - * "sbus-intr>cpu (sbint -- ino)" from kernel... - * See .../drivers/sbus/sbus.c for details. - */ -BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int) -#define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint) - extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); -extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); extern int sbus_arch_preinit(void); extern void sbus_arch_postinit(void); diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index 79719c2e5fa..2b2562e0e5c 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -94,11 +94,8 @@ extern struct sbus_bus *sbus_root; for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ for ((device) = (bus)->devices; (device); (device) = (device)->next) -extern void sbus_fill_device_irq(struct sbus_dev *); - extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); -extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); extern int sbus_arch_preinit(void); extern void sbus_arch_postinit(void); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index d65fb9b0668..0e478301e8e 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -255,49 +255,6 @@ void sbus_set_sbus64(struct device *dev, int x) printk("sbus_set_sbus64: unsupported\n"); } -extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); -void __init sbus_fill_device_irq(struct sbus_dev *sdev) -{ - struct linux_prom_irqs irqs[PROMINTR_MAX]; - int len; - - len = prom_getproperty(sdev->prom_node, "intr", - (char *)irqs, sizeof(irqs)); - if (len != -1) { - sdev->num_irqs = len / 8; - if (sdev->num_irqs == 0) { - sdev->irqs[0] = 0; - } else if (sparc_cpu_model == sun4d) { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = - sun4d_build_irq(sdev, irqs[len].pri); - } else { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = irqs[len].pri; - } - } else { - int interrupts[PROMINTR_MAX]; - - /* No "intr" node found-- check for "interrupts" node. - * This node contains SBus interrupt levels, not IPLs - * as in "intr", and no vector values. We convert - * SBus interrupt levels to PILs (platform specific). - */ - len = prom_getproperty(sdev->prom_node, "interrupts", - (char *)interrupts, sizeof(interrupts)); - if (len == -1) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - sdev->num_irqs = len / sizeof(int); - for (len = 0; len < sdev->num_irqs; len++) { - sdev->irqs[len] = - sbint_to_irq(sdev, interrupts[len]); - } - } - } -} - /* * Allocate a chunk of memory suitable for DMA. * Typically devices use them for control blocks. @@ -479,16 +436,6 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) #endif } -void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) -{ - if (sparc_cpu_model == sun4d) { - struct device_node *parent = dp->parent; - - sbus->devid = of_getintprop_default(parent, "device-id", 0); - sbus->board = of_getintprop_default(parent, "board#", 0); - } -} - int __init sbus_arch_preinit(void) { register_proc_sparc_ioport(); diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 340fc395fe2..a5a32a0b10d 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -66,18 +66,6 @@ static struct resource sun4c_intr_eb = { "sun4c_intr" }; */ unsigned char *interrupt_enable = NULL; -static int sun4c_pil_map[] = { 0, 1, 2, 3, 5, 7, 8, 9 }; - -static unsigned int sun4c_sbint_to_irq(struct sbus_dev *sdev, - unsigned int sbint) -{ - if (sbint >= sizeof(sun4c_pil_map)) { - printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); - BUG(); - } - return sun4c_pil_map[sbint]; -} - static void sun4c_disable_irq(unsigned int irq_nr) { unsigned long flags; @@ -243,7 +231,6 @@ void __init sun4c_init_IRQ(void) if (!interrupt_enable) panic("Cannot map interrupt_enable"); - BTFIXUPSET_CALL(sbint_to_irq, sun4c_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 7424967142f..acfb447c00d 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -257,26 +257,6 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs) set_irq_regs(old_regs); } -unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq) -{ - int sbusl = pil_to_sbus[irq]; - - if (sbusl) - return ((sdev->bus->board + 1) << 5) + (sbusl << 2) + sdev->slot; - else - return irq; -} - -static unsigned int sun4d_sbint_to_irq(struct sbus_dev *sdev, - unsigned int sbint) -{ - if (sbint >= sizeof(sbus_to_pil)) { - printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); - BUG(); - } - return sun4d_build_irq(sdev, sbus_to_pil[sbint]); -} - int sun4d_request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void *dev_id) @@ -585,7 +565,6 @@ void __init sun4d_init_IRQ(void) { local_irq_disable(); - BTFIXUPSET_CALL(sbint_to_irq, sun4d_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 94e02de960e..d66334b853e 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -152,18 +152,6 @@ static unsigned long irq_mask[] = { SUN4M_INT_SBUS(6) /* 14 irq 13 */ }; -static int sun4m_pil_map[] = { 0, 2, 3, 5, 7, 9, 11, 13 }; - -static unsigned int sun4m_sbint_to_irq(struct sbus_dev *sdev, - unsigned int sbint) -{ - if (sbint >= sizeof(sun4m_pil_map)) { - printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); - BUG(); - } - return sun4m_pil_map[sbint] | 0x30; -} - static unsigned long sun4m_get_irqmask(unsigned int irq) { unsigned long mask; @@ -447,7 +435,6 @@ void __init sun4m_init_IRQ(void) &sun4m_interrupts->undirected_target; sun4m_interrupts->undirected_target = 0; } - BTFIXUPSET_CALL(sbint_to_irq, sun4m_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index aa47022e13f..60fac2d64b1 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -650,26 +650,6 @@ fatal_memory_error: prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); } -void sbus_fill_device_irq(struct sbus_dev *sdev) -{ - struct device_node *dp = of_find_node_by_phandle(sdev->prom_node); - const struct linux_prom_irqs *irqs; - - irqs = of_get_property(dp, "interrupts", NULL); - if (!irqs) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - unsigned int pri = irqs[0].pri; - - sdev->num_irqs = 1; - if (pri < 0x20) - pri += sdev->slot * 8; - - sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); - } -} - void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) { } @@ -679,10 +659,6 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) sbus_iommu_init(dp->node, sbus); } -void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) -{ -} - int __init sbus_arch_preinit(void) { return 0; -- cgit v1.2.3 From 104364810ff5b0844a2183fbca989f70e86d486b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 03:38:42 -0700 Subject: sparc: Remove SBUS layer resource and irq handling. All the drivers use OF device objects now for this information. Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 15 --------------- arch/sparc/include/asm/sbus_64.h | 16 ---------------- arch/sparc/kernel/ioport.c | 27 --------------------------- arch/sparc64/kernel/sbus.c | 4 ---- 4 files changed, 62 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index 81ea0f687b1..8f5900baca3 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -51,17 +51,6 @@ struct sbus_dev { int prom_node; char prom_name[64]; int slot; - - struct resource resource[PROMREG_MAX]; - - struct linux_prom_registers reg_addrs[PROMREG_MAX]; - int num_registers; - - struct linux_prom_ranges device_ranges[PROMREG_MAX]; - int num_device_ranges; - - unsigned int irqs[4]; - int num_irqs; }; #define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) @@ -73,9 +62,6 @@ struct sbus_bus { int prom_node; /* PROM device tree node for this SBus */ char prom_name[64]; /* Usually "sbus" or "sbi" */ int clock_freq; - - struct linux_prom_ranges sbus_ranges[PROMREG_MAX]; - int num_sbus_ranges; }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) @@ -103,7 +89,6 @@ sbus_is_slave(struct sbus_dev *dev) void prom_adjust_ranges(struct linux_prom_ranges *, int, struct linux_prom_ranges *, int); -extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); extern int sbus_arch_preinit(void); extern void sbus_arch_postinit(void); diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index 2b2562e0e5c..75f95ff6d01 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -51,17 +51,6 @@ struct sbus_dev { int prom_node; char prom_name[64]; int slot; - - struct resource resource[PROMREG_MAX]; - - struct linux_prom_registers reg_addrs[PROMREG_MAX]; - int num_registers; - - struct linux_prom_ranges device_ranges[PROMREG_MAX]; - int num_device_ranges; - - unsigned int irqs[4]; - int num_irqs; }; #define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) @@ -73,10 +62,6 @@ struct sbus_bus { int prom_node; /* OBP node of SBUS */ char prom_name[64]; /* Usually "sbus" or "sbi" */ int clock_freq; - - struct linux_prom_ranges sbus_ranges[PROMREG_MAX]; - int num_sbus_ranges; - int portid; }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) @@ -94,7 +79,6 @@ extern struct sbus_bus *sbus_root; for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ for ((device) = (bus)->devices; (device); (device) = (device)->next) -extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); extern int sbus_arch_preinit(void); extern void sbus_arch_postinit(void); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 0e478301e8e..d82a810564b 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -394,33 +394,6 @@ void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t s } /* Support code for sbus_init(). */ -/* - * XXX This functions appears to be a distorted version of - * prom_sbus_ranges_init(), with all sun4d stuff cut away. - * Ask DaveM what is going on here, how is sun4d supposed to work... XXX - */ -/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ -void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) -{ - int parent_node = pn->node; - - if (sparc_cpu_model == sun4d) { - struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; - int num_iounit_ranges, len; - - len = prom_getproperty(parent_node, "ranges", - (char *) iounit_ranges, - sizeof (iounit_ranges)); - if (len != -1) { - num_iounit_ranges = - (len / sizeof(struct linux_prom_ranges)); - prom_adjust_ranges(sbus->sbus_ranges, - sbus->num_sbus_ranges, - iounit_ranges, num_iounit_ranges); - } - } -} - void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) { #ifndef CONFIG_SUN4 diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 60fac2d64b1..0193e382319 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -650,10 +650,6 @@ fatal_memory_error: prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); } -void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) -{ -} - void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) { sbus_iommu_init(dp->node, sbus); -- cgit v1.2.3 From 98261dd1a393777f4400d8ad5a29e97cb30e5422 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 03:47:56 -0700 Subject: sparc: Remove dinky old-style SBUS probing facilities. No drivers or code uses this stuff any more, every driver has been converted over to OF device probing. Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 13 ------------- arch/sparc/include/asm/sbus_64.h | 13 ------------- arch/sparc/kernel/sparc_ksyms.c | 1 - arch/sparc64/kernel/sparc64_ksyms.c | 1 - 4 files changed, 28 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index 8f5900baca3..9f35ae870b5 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -65,8 +65,6 @@ struct sbus_bus { }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) -extern struct sbus_bus *sbus_root; - static inline int sbus_is_slave(struct sbus_dev *dev) { @@ -74,17 +72,6 @@ sbus_is_slave(struct sbus_dev *dev) return 0; } -/* Device probing routines could find these handy */ -#define for_each_sbus(bus) \ - for((bus) = sbus_root; (bus); (bus)=(bus)->next) - -#define for_each_sbusdev(device, bus) \ - for((device) = (bus)->devices; (device); (device)=(device)->next) - -#define for_all_sbusdev(device, bus) \ - for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ - for ((device) = (bus)->devices; (device); (device) = (device)->next) - /* These yield IOMMU mappings in consistent mode. */ void prom_adjust_ranges(struct linux_prom_ranges *, int, struct linux_prom_ranges *, int); diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index 75f95ff6d01..ec3509a3d97 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -66,19 +66,6 @@ struct sbus_bus { }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) -extern struct sbus_bus *sbus_root; - -/* Device probing routines could find these handy */ -#define for_each_sbus(bus) \ - for((bus) = sbus_root; (bus); (bus)=(bus)->next) - -#define for_each_sbusdev(device, bus) \ - for((device) = (bus)->devices; (device); (device)=(device)->next) - -#define for_all_sbusdev(device, bus) \ - for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ - for ((device) = (bus)->devices; (device); (device) = (device)->next) - extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); extern int sbus_arch_preinit(void); extern void sbus_arch_postinit(void); diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index b1d2c975b32..84aaac43594 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -153,7 +153,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one)); EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); #ifdef CONFIG_SBUS -EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(sbus_set_sbus64); EXPORT_SYMBOL(sbus_iounmap); EXPORT_SYMBOL(sbus_ioremap); diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 901c26437b6..08c58a8457b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -160,7 +160,6 @@ EXPORT_SYMBOL(auxio_set_led); EXPORT_SYMBOL(auxio_set_lte); #endif #ifdef CONFIG_SBUS -EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(sbus_set_sbus64); #endif EXPORT_SYMBOL(outsb); -- cgit v1.2.3 From 454eeb2dd7bd0418451ea33a606d0fa50aa36718 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:05:35 -0700 Subject: sparc: Convert remaining sbus_ioremap() and sbus_iounmap() users. Use of_ioremap() and of_iounmap() instead. Signed-off-by: David S. Miller --- arch/sparc/include/asm/floppy_32.h | 5 ++++- arch/sparc/kernel/auxio.c | 6 ++++-- arch/sparc/kernel/sun4c_irq.c | 5 +++-- arch/sparc/kernel/sun4d_irq.c | 5 +++-- arch/sparc/kernel/sun4m_irq.c | 11 ++++++----- arch/sparc/kernel/time.c | 5 +++-- 6 files changed, 23 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h index ff2b91c6eef..c792830636d 100644 --- a/arch/sparc/include/asm/floppy_32.h +++ b/arch/sparc/include/asm/floppy_32.h @@ -6,6 +6,9 @@ #ifndef __ASM_SPARC_FLOPPY_H #define __ASM_SPARC_FLOPPY_H +#include +#include + #include #include #include @@ -343,7 +346,7 @@ static int sun_floppy_init(void) r.flags = fd_regs[0].which_io; r.start = fd_regs[0].phys_addr; sun_fdc = (struct sun_flpy_controller *) - sbus_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); + of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); /* Last minute sanity check... */ if(sun_fdc->status_82072 == 0xff) { diff --git a/arch/sparc/kernel/auxio.c b/arch/sparc/kernel/auxio.c index baf4ed3fb0f..09c857215a5 100644 --- a/arch/sparc/kernel/auxio.c +++ b/arch/sparc/kernel/auxio.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -59,7 +61,7 @@ void __init auxio_probe(void) r.flags = auxregs[0].which_io & 0xF; r.start = auxregs[0].phys_addr; r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1; - auxio_register = sbus_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); + auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); /* Fix the address on sun4m and sun4c. */ if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || sparc_cpu_model == sun4c) @@ -128,7 +130,7 @@ void __init auxio_power_probe(void) r.flags = regs.which_io & 0xF; r.start = regs.phys_addr; r.end = regs.phys_addr + regs.reg_size - 1; - auxio_power_register = (unsigned char *) sbus_ioremap(&r, 0, + auxio_power_register = (unsigned char *) of_ioremap(&r, 0, regs.reg_size, "auxpower"); /* Display a quick message on the console. */ diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index a5a32a0b10d..a74582455cc 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "irq.h" #include @@ -34,7 +36,6 @@ #include #include #include -#include #if 0 static struct resource sun4c_timer_eb = { "sun4c_timer" }; @@ -224,7 +225,7 @@ void __init sun4c_init_IRQ(void) memset(&phyres, 0, sizeof(struct resource)); phyres.flags = int_regs[0].which_io; phyres.start = int_regs[0].phys_addr; - interrupt_enable = (char *) sbus_ioremap(&phyres, 0, + interrupt_enable = (char *) of_ioremap(&phyres, 0, int_regs[0].reg_size, "sun4c_intr"); } } diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index acfb447c00d..c4a2bfb750a 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -34,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -475,7 +476,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) r.start = CSR_BASE(0)+BW_TIMER_LIMIT; #endif r.flags = 0xf; - sun4d_timers = (struct sun4d_timer_regs *) sbus_ioremap(&r, 0, + sun4d_timers = (struct sun4d_timer_regs *) of_ioremap(&r, 0, PAGE_SIZE, "user timer"); sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index d66334b853e..3481feca335 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -35,7 +37,6 @@ #include #include #include -#include #include #include "irq.h" @@ -327,13 +328,13 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) /* Map the per-cpu Counter registers. */ r.flags = cnt_regs[0].which_io; r.start = cnt_regs[0].phys_addr; - sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0, + sun4m_timers = (struct sun4m_timer_regs *) of_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt"); /* Map the system Counter register. */ /* XXX Here we expect consequent calls to yeld adjusent maps. */ r.flags = cnt_regs[4].which_io; r.start = cnt_regs[4].phys_addr; - sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); + of_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4m_timers->l10_cur_count; @@ -411,13 +412,13 @@ void __init sun4m_init_IRQ(void) /* Map the interrupt registers for all possible cpus. */ r.flags = int_regs[0].which_io; r.start = int_regs[0].phys_addr; - sun4m_interrupts = (struct sun4m_intregs *) sbus_ioremap(&r, 0, + sun4m_interrupts = (struct sun4m_intregs *) of_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); /* Map the system interrupt control registers. */ r.flags = int_regs[4].which_io; r.start = int_regs[4].phys_addr; - sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); + of_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); sun4m_interrupts->set = ~SUN4M_INT_MASKALL; for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 0762f5db192..a713bb43db8 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -260,7 +261,7 @@ static inline void sun4_clock_probe(void) if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) { sp_clock_typ = MSTK48T02; r.start = sun4_clock_physaddr; - mstk48t02_regs = sbus_ioremap(&r, 0, + mstk48t02_regs = of_ioremap(&r, 0, sizeof(struct mostek48t02), NULL); mstk48t08_regs = NULL; /* To catch weirdness */ intersil_clock = NULL; /* just in case */ @@ -274,7 +275,7 @@ static inline void sun4_clock_probe(void) sp_clock_typ = INTERSIL; r.start = sun4_clock_physaddr; intersil_clock = (struct intersil *) - sbus_ioremap(&r, 0, sizeof(*intersil_clock), "intersil"); + of_ioremap(&r, 0, sizeof(*intersil_clock), "intersil"); mstk48t02_regs = 0; /* just be sure */ mstk48t08_regs = NULL; /* ditto */ /* initialise the clock */ -- cgit v1.2.3 From 615deeb27b7c3f51b464b47e8b9a8e433ab2d0ca Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:11:16 -0700 Subject: sparc: Kill sbus_ioremap() and sbus_iounmap(). No more users. Signed-off-by: David S. Miller --- arch/sparc/include/asm/io_32.h | 8 -------- arch/sparc/include/asm/io_64.h | 13 ------------- arch/sparc/kernel/ioport.c | 16 ---------------- arch/sparc/kernel/sparc_ksyms.c | 2 -- 4 files changed, 39 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h index 3ab3164bd73..93fe21e02c8 100644 --- a/arch/sparc/include/asm/io_32.h +++ b/arch/sparc/include/asm/io_32.h @@ -292,14 +292,6 @@ struct pci_dev; extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); extern void pci_iounmap(struct pci_dev *dev, void __iomem *); -/* - * Bus number may be in res->flags... somewhere. - */ -extern void __iomem *sbus_ioremap(struct resource *res, unsigned long offset, - unsigned long size, char *name); -extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size); - - /* * At the moment, we do not use CMOS_READ anywhere outside of rtc.c, * so rtc_port is static in it. This should not change unless a new diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h index 73a9c5d4195..4aee21dc9c6 100644 --- a/arch/sparc/include/asm/io_64.h +++ b/arch/sparc/include/asm/io_64.h @@ -482,19 +482,6 @@ struct pci_dev; extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); extern void pci_iounmap(struct pci_dev *dev, void __iomem *); -/* Similarly for SBUS. */ -#define sbus_ioremap(__res, __offset, __size, __name) \ -({ unsigned long __ret; \ - __ret = (__res)->start + (((__res)->flags & 0x1ffUL) << 32UL); \ - __ret += (unsigned long) (__offset); \ - if (! request_region((__ret), (__size), (__name))) \ - __ret = 0UL; \ - (void __iomem *) __ret; \ -}) - -#define sbus_iounmap(__addr, __size) \ - release_region((unsigned long)(__addr), (__size)) - static inline int sbus_can_dma_64bit(void) { return 1; diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index d82a810564b..e6177dde103 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -143,15 +143,6 @@ void iounmap(volatile void __iomem *virtual) } } -/* - */ -void __iomem *sbus_ioremap(struct resource *phyres, unsigned long offset, - unsigned long size, char *name) -{ - return _sparc_alloc_io(phyres->flags & 0xF, - phyres->start + offset, size, name); -} - void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name) { @@ -167,13 +158,6 @@ void of_iounmap(struct resource *res, void __iomem *base, unsigned long size) } EXPORT_SYMBOL(of_iounmap); -/* - */ -void sbus_iounmap(volatile void __iomem *addr, unsigned long size) -{ - iounmap(addr); -} - /* * Meat of mapping */ diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 84aaac43594..f2722ee3967 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -154,8 +154,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_set_sbus64); -EXPORT_SYMBOL(sbus_iounmap); -EXPORT_SYMBOL(sbus_ioremap); #endif #ifdef CONFIG_PCI EXPORT_SYMBOL(ebus_chain); -- cgit v1.2.3 From 9b9644c6d91e9fd8edecba3ae57a35285cfce9db Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:17:24 -0700 Subject: sparc: Kill sbus_devaddr() and sbus_dev_slot(). Unused. Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 18 ------------------ arch/sparc/include/asm/sbus_64.h | 18 ------------------ 2 files changed, 36 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index 9f35ae870b5..fdaf1a74492 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -21,24 +21,6 @@ * you can get a SBus 'slot' number and an offset within that slot. */ -/* The base address at which to calculate device OBIO addresses. */ -#define SUN_SBUS_BVADDR 0xf8000000 -#define SBUS_OFF_MASK 0x01ffffff - -/* These routines are used to calculate device address from slot - * numbers + offsets, and vice versa. - */ - -static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset) -{ - return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<25)+(offset)); -} - -static inline int sbus_dev_slot(unsigned long dev_addr) -{ - return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>25); -} - struct sbus_bus; /* Linux SBUS device tables */ diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index ec3509a3d97..6b3b055fca7 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -21,24 +21,6 @@ * you can get a SBus 'slot' number and an offset within that slot. */ -/* The base address at which to calculate device OBIO addresses. */ -#define SUN_SBUS_BVADDR 0x00000000 -#define SBUS_OFF_MASK 0x0fffffff - -/* These routines are used to calculate device address from slot - * numbers + offsets, and vice versa. - */ - -static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset) -{ - return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<28)+(offset)); -} - -static inline int sbus_dev_slot(unsigned long dev_addr) -{ - return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>28); -} - struct sbus_bus; /* Linux SBUS device tables */ -- cgit v1.2.3 From c6e5f661eee0ff62e7fdb263cfeee73c20dd6e99 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:18:02 -0700 Subject: sparc: Kill OBP property members of sbus_dev and sbus_bus Unused. Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 6 ------ arch/sparc/include/asm/sbus_64.h | 7 ------- 2 files changed, 13 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index fdaf1a74492..99f79e4a709 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -30,9 +30,6 @@ struct sbus_dev { struct sbus_dev *next; struct sbus_dev *child; struct sbus_dev *parent; - int prom_node; - char prom_name[64]; - int slot; }; #define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) @@ -41,9 +38,6 @@ struct sbus_bus { struct of_device ofdev; struct sbus_dev *devices; /* Link to devices on this SBus */ struct sbus_bus *next; /* next SBus, if more than one SBus */ - int prom_node; /* PROM device tree node for this SBus */ - char prom_name[64]; /* Usually "sbus" or "sbi" */ - int clock_freq; }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h index 6b3b055fca7..b7b76945247 100644 --- a/arch/sparc/include/asm/sbus_64.h +++ b/arch/sparc/include/asm/sbus_64.h @@ -30,9 +30,6 @@ struct sbus_dev { struct sbus_dev *next; struct sbus_dev *child; struct sbus_dev *parent; - int prom_node; - char prom_name[64]; - int slot; }; #define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) @@ -41,10 +38,6 @@ struct sbus_bus { struct of_device ofdev; struct sbus_dev *devices; /* Tree of SBUS devices */ struct sbus_bus *next; /* Next SBUS in system */ - int prom_node; /* OBP node of SBUS */ - char prom_name[64]; /* Usually "sbus" or "sbi" */ - int clock_freq; - int portid; }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) -- cgit v1.2.3 From d32bcdd7a90f19bc067a272b353800108d092c5e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:18:55 -0700 Subject: sparc32: Kill sbus_is_slave(). Unused. Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus_32.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h index 99f79e4a709..d960f3e61ec 100644 --- a/arch/sparc/include/asm/sbus_32.h +++ b/arch/sparc/include/asm/sbus_32.h @@ -41,13 +41,6 @@ struct sbus_bus { }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) -static inline int -sbus_is_slave(struct sbus_dev *dev) -{ - /* XXX Have to write this for sun4c's */ - return 0; -} - /* These yield IOMMU mappings in consistent mode. */ void prom_adjust_ranges(struct linux_prom_ranges *, int, struct linux_prom_ranges *, int); -- cgit v1.2.3 From f8e4d32cb5153a9d6a8e8864e357dad1349f3b85 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:20:14 -0700 Subject: sparc: Kill sbus_arch_preinit(). 32-bit sparc just needed it to register the ioport procfs bits, do this via an arch_initcall() instead. Signed-off-by: David S. Miller --- arch/sparc/kernel/ioport.c | 12 +++--------- arch/sparc64/kernel/sbus.c | 5 ----- 2 files changed, 3 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index e6177dde103..24645f9f56f 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -393,21 +393,15 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) #endif } -int __init sbus_arch_preinit(void) +static int __init sparc_register_ioport(void) { register_proc_sparc_ioport(); -#ifdef CONFIG_SUN4 - { - extern void sun4_dvma_init(void); - sun4_dvma_init(); - } - return 1; -#else return 0; -#endif } +arch_initcall(sparc_register_ioport); + void __init sbus_arch_postinit(void) { if (sparc_cpu_model == sun4d) { diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 0193e382319..0b3e7bc96f6 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -655,11 +655,6 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) sbus_iommu_init(dp->node, sbus); } -int __init sbus_arch_preinit(void) -{ - return 0; -} - void __init sbus_arch_postinit(void) { extern void firetruck_init(void); -- cgit v1.2.3 From 5059625ed8862e897760b86effff0f8a35989c0d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:22:37 -0700 Subject: sparc: Add OF archdata propagation helper. Add a helper function that, given a bus of_device node, propagates all iommu, stc, and host_controller values down to the child nodes. Signed-off-by: David S. Miller --- arch/sparc/include/asm/of_device.h | 2 ++ arch/sparc/kernel/of_device.c | 22 ++++++++++++++++++++++ arch/sparc64/kernel/of_device.c | 22 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) (limited to 'arch') diff --git a/arch/sparc/include/asm/of_device.h b/arch/sparc/include/asm/of_device.h index bba777a416d..a5d9811f969 100644 --- a/arch/sparc/include/asm/of_device.h +++ b/arch/sparc/include/asm/of_device.h @@ -30,6 +30,8 @@ struct of_device extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); +extern void of_propagate_archdata(struct of_device *bus); + /* This is just here during the transition */ #include diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index aace71f7d6e..8fdc1b3113b 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -40,6 +40,28 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index) } EXPORT_SYMBOL(irq_of_parse_and_map); +/* Take the archdata values for IOMMU, STC, and HOSTDATA found in + * BUS and propagate to all child of_device objects. + */ +void of_propagate_archdata(struct of_device *bus) +{ + struct dev_archdata *bus_sd = &bus->dev.archdata; + struct device_node *bus_dp = bus->node; + struct device_node *dp; + + for (dp = bus_dp->child; dp; dp = dp->sibling) { + struct of_device *op = of_find_device_by_node(dp); + + op->dev.archdata.iommu = bus_sd->iommu; + op->dev.archdata.stc = bus_sd->stc; + op->dev.archdata.host_controller = bus_sd->host_controller; + op->dev.archdata.numa_node = bus_sd->numa_node; + + if (dp->child) + of_propagate_archdata(op); + } +} + #ifdef CONFIG_PCI struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index a30f2af0bf2..b22475f85a5 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -66,6 +66,28 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index) } EXPORT_SYMBOL(irq_of_parse_and_map); +/* Take the archdata values for IOMMU, STC, and HOSTDATA found in + * BUS and propagate to all child of_device objects. + */ +void of_propagate_archdata(struct of_device *bus) +{ + struct dev_archdata *bus_sd = &bus->dev.archdata; + struct device_node *bus_dp = bus->node; + struct device_node *dp; + + for (dp = bus_dp->child; dp; dp = dp->sibling) { + struct of_device *op = of_find_device_by_node(dp); + + op->dev.archdata.iommu = bus_sd->iommu; + op->dev.archdata.stc = bus_sd->stc; + op->dev.archdata.host_controller = bus_sd->host_controller; + op->dev.archdata.numa_node = bus_sd->numa_node; + + if (dp->child) + of_propagate_archdata(op); + } +} + #ifdef CONFIG_PCI struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); -- cgit v1.2.3 From 046e26a8ba10b8ceff822f8d91451ab6c1e08c4e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:54:04 -0700 Subject: sparc: Remove generic SBUS probing layer. The individual SBUS IOMMU arch code now sets the IOMMU information directly into the OF device objects. Signed-off-by: David S. Miller --- arch/sparc/include/asm/io-unit.h | 2 - arch/sparc/include/asm/iommu_32.h | 2 - arch/sparc/include/asm/irq_64.h | 1 - arch/sparc/kernel/ioport.c | 23 ------- arch/sparc/mm/io-unit.c | 30 ++++++---- arch/sparc/mm/iommu.c | 40 +++++++------ arch/sparc64/kernel/sbus.c | 122 +++++++++++++++++++++----------------- 7 files changed, 108 insertions(+), 112 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/io-unit.h b/arch/sparc/include/asm/io-unit.h index 5df63ef95cf..96823b47fd4 100644 --- a/arch/sparc/include/asm/io-unit.h +++ b/arch/sparc/include/asm/io-unit.h @@ -59,6 +59,4 @@ extern __u32 iounit_map_dma_init(struct sbus_bus *, int); #define iounit_map_dma_finish(sbus, addr, len) mmu_release_scsi_one(addr, len, sbus) extern __u32 iounit_map_dma_page(__u32, void *, struct sbus_bus *); -extern void iounit_init(struct sbus_bus *sbus); - #endif /* !(_SPARC_IO_UNIT_H) */ diff --git a/arch/sparc/include/asm/iommu_32.h b/arch/sparc/include/asm/iommu_32.h index 6b115a174c0..70c589c05a1 100644 --- a/arch/sparc/include/asm/iommu_32.h +++ b/arch/sparc/include/asm/iommu_32.h @@ -118,6 +118,4 @@ static inline void iommu_invalidate_page(struct iommu_regs *regs, unsigned long regs->pageflush = (ba & PAGE_MASK); } -extern void iommu_init(struct device_node *dp, struct sbus_bus *sbus); - #endif /* !(_SPARC_IOMMU_H) */ diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index e3dd9303643..71673eca366 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -56,7 +56,6 @@ extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p, unsigned long imap_base, unsigned long iclr_base); extern void sun4u_destroy_msi(unsigned int virt_irq); -extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); extern unsigned char virt_irq_alloc(unsigned int dev_handle, unsigned int dev_ino); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 24645f9f56f..bca2d6fd5c4 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -377,22 +377,6 @@ void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t s { } -/* Support code for sbus_init(). */ -void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) -{ -#ifndef CONFIG_SUN4 - struct device_node *parent = dp->parent; - - if (sparc_cpu_model != sun4d && - parent != NULL && - !strcmp(parent->name, "iommu")) - iommu_init(parent, sbus); - - if (sparc_cpu_model == sun4d) - iounit_init(sbus); -#endif -} - static int __init sparc_register_ioport(void) { register_proc_sparc_ioport(); @@ -402,13 +386,6 @@ static int __init sparc_register_ioport(void) arch_initcall(sparc_register_ioport); -void __init sbus_arch_postinit(void) -{ - if (sparc_cpu_model == sun4d) { - extern void sun4d_init_sbi_irq(void); - sun4d_init_sbi_irq(); - } -} #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 0f97ab30df3..caf551ad9d8 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -34,18 +34,10 @@ #define IOPERM (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID) #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM) -void __init iounit_init(struct sbus_bus *sbus) +static void __init iounit_iommu_init(struct of_device *op) { - struct device_node *dp = sbus->ofdev.node; struct iounit_struct *iounit; iopte_t *xpt, *xptend; - struct of_device *op; - - op = of_find_device_by_node(dp); - if (!op) { - prom_printf("SUN4D: Cannot find SBI of_device.\n"); - prom_halt(); - } iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC); if (!iounit) { @@ -66,7 +58,6 @@ void __init iounit_init(struct sbus_bus *sbus) prom_halt(); } - sbus->ofdev.dev.archdata.iommu = iounit; op->dev.archdata.iommu = iounit; iounit->page_table = xpt; spin_lock_init(&iounit->lock); @@ -76,6 +67,25 @@ void __init iounit_init(struct sbus_bus *sbus) iopte_val(*xpt++) = 0; } +static int __init iounit_init(void) +{ + extern void sun4d_init_sbi_irq(void); + struct device_node *dp; + + for_each_node_by_name(dp, "sbi") { + struct of_device *op = of_find_device_by_node(dp); + + iounit_iommu_init(op); + of_propagate_archdata(op); + } + + sun4d_init_sbi_irq(); + + return 0; +} + +subsys_initcall(iounit_init); + /* One has to hold iounit->lock to call this */ static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned long vaddr, int size) { diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 2970cea877b..7c55450b55b 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -55,33 +55,20 @@ static pgprot_t dvma_prot; /* Consistent mapping pte flags */ #define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID) #define MKIOPTE(pfn, perm) (((((pfn)<<8) & IOPTE_PAGE) | (perm)) & ~IOPTE_WAZ) -void __init iommu_init(struct device_node *parent, struct sbus_bus *sbus) +static void __init sbus_iommu_init(struct of_device *op) { - struct of_device *parent_op, *op; struct iommu_struct *iommu; unsigned int impl, vers; unsigned long *bitmap; unsigned long tmp; - parent_op = of_find_device_by_node(parent); - if (!parent_op) { - prom_printf("Unable to find IOMMU of_device\n"); - prom_halt(); - } - - op = of_find_device_by_node(sbus->ofdev.node); - if (!op) { - prom_printf("Unable to find SBUS of_device\n"); - prom_halt(); - } - iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); if (!iommu) { prom_printf("Unable to allocate iommu structure\n"); prom_halt(); } - iommu->regs = of_ioremap(&parent_op->resource[0], 0, PAGE_SIZE * 3, + iommu->regs = of_ioremap(&op->resource[0], 0, PAGE_SIZE * 3, "iommu_regs"); if (!iommu->regs) { prom_printf("Cannot map IOMMU registers\n"); @@ -132,14 +119,29 @@ void __init iommu_init(struct device_node *parent, struct sbus_bus *sbus) else iommu->usemap.num_colors = 1; - printk("IOMMU: impl %d vers %d table 0x%p[%d B] map [%d b]\n", - impl, vers, iommu->page_table, - (int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES); + printk(KERN_INFO "IOMMU: impl %d vers %d table 0x%p[%d B] map [%d b]\n", + impl, vers, iommu->page_table, + (int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES); - sbus->ofdev.dev.archdata.iommu = iommu; op->dev.archdata.iommu = iommu; } +static int __init iommu_init(void) +{ + struct device_node *dp; + + for_each_node_by_name(dp, "iommu") { + struct of_device *op = of_find_device_by_node(dp); + + sbus_iommu_init(op); + of_propagate_archdata(op); + } + + return 0; +} + +subsys_initcall(iommu_init); + /* This begs to be btfixup-ed by srmmu. */ /* Flush the iotlb entries to ram. */ /* This could be better if we didn't have to flush whole pages. */ diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 0b3e7bc96f6..60605eaf49b 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -201,10 +201,9 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap) return imap + diff; } -unsigned int sbus_build_irq(void *buscookie, unsigned int ino) +static unsigned int sbus_build_irq(struct of_device *op, unsigned int ino) { - struct sbus_bus *sbus = (struct sbus_bus *)buscookie; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long imap, iclr; int sbus_level = 0; @@ -265,12 +264,12 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) { - struct sbus_bus *sbus = dev_id; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct of_device *op = dev_id; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; - int reported; + int reported, portid; afsr_reg = reg_base + SYSIO_UE_AFSR; afar_reg = reg_base + SYSIO_UE_AFAR; @@ -285,9 +284,11 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); upa_writeq(error_bits, afsr_reg); + portid = of_getintprop_default(op->node, "portid", -1); + /* Log the error. */ printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", - sbus->portid, + portid, (((error_bits & SYSIO_UEAFSR_PPIO) ? "PIO" : ((error_bits & SYSIO_UEAFSR_PDRD) ? @@ -295,12 +296,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) ((error_bits & SYSIO_UEAFSR_PDWR) ? "DVMA Write" : "???"))))); printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", - sbus->portid, + portid, (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, (afsr & SYSIO_UEAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); - printk("SYSIO[%x]: Secondary UE errors [", sbus->portid); + printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); + printk("SYSIO[%x]: Secondary UE errors [", portid); reported = 0; if (afsr & SYSIO_UEAFSR_SPIO) { reported++; @@ -337,12 +338,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) { - struct sbus_bus *sbus = dev_id; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct of_device *op = dev_id; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; - int reported; + int reported, portid; afsr_reg = reg_base + SYSIO_CE_AFSR; afar_reg = reg_base + SYSIO_CE_AFAR; @@ -357,8 +358,10 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); upa_writeq(error_bits, afsr_reg); + portid = of_getintprop_default(op->node, "portid", -1); + printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", - sbus->portid, + portid, (((error_bits & SYSIO_CEAFSR_PPIO) ? "PIO" : ((error_bits & SYSIO_CEAFSR_PDRD) ? @@ -370,14 +373,14 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) * XXX UDB CE trap handler does... -DaveM */ printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", - sbus->portid, + portid, (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, (afsr & SYSIO_CEAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); + printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); - printk("SYSIO[%x]: Secondary CE errors [", sbus->portid); + printk("SYSIO[%x]: Secondary CE errors [", portid); reported = 0; if (afsr & SYSIO_CEAFSR_SPIO) { reported++; @@ -414,11 +417,11 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) { - struct sbus_bus *sbus = dev_id; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct of_device *op = dev_id; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long afsr_reg, afar_reg, reg_base; unsigned long afsr, afar, error_bits; - int reported; + int reported, portid; reg_base = iommu->write_complete_reg - 0x2000UL; afsr_reg = reg_base + SYSIO_SBUS_AFSR; @@ -433,9 +436,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); upa_writeq(error_bits, afsr_reg); + portid = of_getintprop_default(op->node, "portid", -1); + /* Log the error. */ printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", - sbus->portid, + portid, (((error_bits & SYSIO_SBAFSR_PLE) ? "Late PIO Error" : ((error_bits & SYSIO_SBAFSR_PTO) ? @@ -444,11 +449,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) "Error Ack" : "???")))), (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); printk("SYSIO[%x]: size[%lx] MID[%lx]\n", - sbus->portid, + portid, (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, (afsr & SYSIO_SBAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); - printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid); + printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); + printk("SYSIO[%x]: Secondary SBUS errors [", portid); reported = 0; if (afsr & SYSIO_SBAFSR_SLE) { reported++; @@ -480,34 +485,37 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) #define SYSIO_CE_INO 0x35 #define SYSIO_SBUSERR_INO 0x36 -static void __init sysio_register_error_handlers(struct sbus_bus *sbus) +static void __init sysio_register_error_handlers(struct of_device *op) { - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned int irq; u64 control; + int portid; + + portid = of_getintprop_default(op->node, "portid", -1); - irq = sbus_build_irq(sbus, SYSIO_UE_INO); + irq = sbus_build_irq(op, SYSIO_UE_INO); if (request_irq(irq, sysio_ue_handler, 0, - "SYSIO_UE", sbus) < 0) { + "SYSIO_UE", op) < 0) { prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", - sbus->portid); + portid); prom_halt(); } - irq = sbus_build_irq(sbus, SYSIO_CE_INO); + irq = sbus_build_irq(op, SYSIO_CE_INO); if (request_irq(irq, sysio_ce_handler, 0, - "SYSIO_CE", sbus) < 0) { + "SYSIO_CE", op) < 0) { prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", - sbus->portid); + portid); prom_halt(); } - irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); + irq = sbus_build_irq(op, SYSIO_SBUSERR_INO); if (request_irq(irq, sysio_sbus_error_handler, 0, - "SYSIO_SBERR", sbus) < 0) { + "SYSIO_SBERR", op) < 0) { prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", - sbus->portid); + portid); prom_halt(); } @@ -523,19 +531,15 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) } /* Boot time initialization. */ -static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) +static void __init sbus_iommu_init(struct of_device *op) { const struct linux_prom64_registers *pr; - struct device_node *dp; + struct device_node *dp = op->node; struct iommu *iommu; struct strbuf *strbuf; unsigned long regs, reg_base; + int i, portid; u64 control; - int i; - - dp = of_find_node_by_phandle(__node); - - sbus->portid = of_getintprop_default(dp, "upa-portid", -1); pr = of_get_property(dp, "reg", NULL); if (!pr) { @@ -552,9 +556,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) if (!strbuf) goto fatal_memory_error; - sbus->ofdev.dev.archdata.iommu = iommu; - sbus->ofdev.dev.archdata.stc = strbuf; - sbus->ofdev.dev.archdata.numa_node = -1; + op->dev.archdata.iommu = iommu; + op->dev.archdata.stc = strbuf; + op->dev.archdata.numa_node = -1; reg_base = regs + SYSIO_IOMMUREG_BASE; iommu->iommu_control = reg_base + IOMMU_CONTROL; @@ -582,8 +586,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) */ iommu->write_complete_reg = regs + 0x2000UL; - printk("SYSIO: UPA portID %x, at %016lx\n", - sbus->portid, regs); + portid = of_getintprop_default(op->node, "portid", -1); + printk(KERN_INFO "SYSIO: UPA portID %x, at %016lx\n", + portid, regs); /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) @@ -641,23 +646,30 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) /* Now some Xfire specific grot... */ if (this_is_starfire) - starfire_hookup(sbus->portid); + starfire_hookup(portid); - sysio_register_error_handlers(sbus); + sysio_register_error_handlers(op); return; fatal_memory_error: prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); } -void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) -{ - sbus_iommu_init(dp->node, sbus); -} - -void __init sbus_arch_postinit(void) +static int __init sbus_init(void) { extern void firetruck_init(void); + struct device_node *dp; + + for_each_node_by_name(dp, "sbus") { + struct of_device *op = of_find_device_by_node(dp); + + sbus_iommu_init(op); + of_propagate_archdata(op); + } firetruck_init(); + + return 0; } + +subsys_initcall(sbus_init); -- cgit v1.2.3 From 47a2d7288538e7f334a0be318317b138f0e3dfbe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 19:45:20 -0700 Subject: sparc: Kill sbus_bus_type. No longer used. Signed-off-by: David S. Miller --- arch/sparc/include/asm/of_platform.h | 1 - arch/sparc/kernel/of_device.c | 9 --------- arch/sparc64/kernel/of_device.c | 9 --------- 3 files changed, 19 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/of_platform.h b/arch/sparc/include/asm/of_platform.h index 2348ab90a57..71ada5238b9 100644 --- a/arch/sparc/include/asm/of_platform.h +++ b/arch/sparc/include/asm/of_platform.h @@ -14,7 +14,6 @@ */ extern struct bus_type ebus_bus_type; -extern struct bus_type sbus_bus_type; #define of_bus_type of_platform_bus_type /* for compatibility */ diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 8fdc1b3113b..576fa2ffa69 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -67,11 +67,6 @@ struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); #endif -#ifdef CONFIG_SBUS -struct bus_type sbus_bus_type; -EXPORT_SYMBOL(sbus_bus_type); -#endif - struct bus_type of_platform_bus_type; EXPORT_SYMBOL(of_platform_bus_type); @@ -593,10 +588,6 @@ static int __init of_bus_driver_init(void) if (!err) err = of_bus_type_init(&ebus_bus_type, "ebus"); #endif -#ifdef CONFIG_SBUS - if (!err) - err = of_bus_type_init(&sbus_bus_type, "sbus"); -#endif if (!err) scan_of_devices(); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index b22475f85a5..6ae92536517 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -93,11 +93,6 @@ struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); #endif -#ifdef CONFIG_SBUS -struct bus_type sbus_bus_type; -EXPORT_SYMBOL(sbus_bus_type); -#endif - struct bus_type of_platform_bus_type; EXPORT_SYMBOL(of_platform_bus_type); @@ -874,10 +869,6 @@ static int __init of_bus_driver_init(void) if (!err) err = of_bus_type_init(&ebus_bus_type, "ebus"); #endif -#ifdef CONFIG_SBUS - if (!err) - err = of_bus_type_init(&sbus_bus_type, "sbus"); -#endif if (!err) scan_of_devices(); -- cgit v1.2.3 From 0ad626a2a4c3d8e565b3a6f10eeda5b43560fbdb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Aug 2008 21:14:05 -0700 Subject: sparc32: Kill iounit_map_dma_*(). Unused. Signed-off-by: David S. Miller --- arch/sparc/include/asm/io-unit.h | 4 ---- arch/sparc/kernel/sparc_ksyms.c | 3 --- arch/sparc/mm/io-unit.c | 48 ---------------------------------------- 3 files changed, 55 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/io-unit.h b/arch/sparc/include/asm/io-unit.h index 96823b47fd4..01ab2f613e9 100644 --- a/arch/sparc/include/asm/io-unit.h +++ b/arch/sparc/include/asm/io-unit.h @@ -55,8 +55,4 @@ struct iounit_struct { #define IOUNIT_BMAPM_START IOUNIT_BMAP2_END #define IOUNIT_BMAPM_END ((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT) -extern __u32 iounit_map_dma_init(struct sbus_bus *, int); -#define iounit_map_dma_finish(sbus, addr, len) mmu_release_scsi_one(addr, len, sbus) -extern __u32 iounit_map_dma_page(__u32, void *, struct sbus_bus *); - #endif /* !(_SPARC_IO_UNIT_H) */ diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index f2722ee3967..a9478dbef2e 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -134,9 +134,6 @@ EXPORT_SYMBOL(set_auxio); EXPORT_SYMBOL(get_auxio); #endif EXPORT_SYMBOL(io_remap_pfn_range); - /* P3: iounit_xxx may be needed, sun4d users */ -/* EXPORT_SYMBOL(iounit_map_dma_init); */ -/* EXPORT_SYMBOL(iounit_map_dma_page); */ #ifndef CONFIG_SMP EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32)); diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index caf551ad9d8..53900230c2d 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -267,51 +267,3 @@ void __init ld_mmu_iounit(void) BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM); #endif } - -__u32 iounit_map_dma_init(struct sbus_bus *sbus, int size) -{ - int i, j, k, npages; - unsigned long rotor, scan, limit; - unsigned long flags; - __u32 ret; - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; - - npages = (size + (PAGE_SIZE-1)) >> PAGE_SHIFT; - i = 0x0213; - spin_lock_irqsave(&iounit->lock, flags); -next: j = (i & 15); - rotor = iounit->rotor[j - 1]; - limit = iounit->limit[j]; - scan = rotor; -nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan); - if (scan + npages > limit) { - if (limit != rotor) { - limit = rotor; - scan = iounit->limit[j - 1]; - goto nexti; - } - i >>= 4; - if (!(i & 15)) - panic("iounit_map_dma_init: Couldn't find free iopte slots for %d bytes\n", size); - goto next; - } - for (k = 1, scan++; k < npages; k++) - if (test_bit(scan++, iounit->bmap)) - goto nexti; - iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1]; - scan -= npages; - ret = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT); - for (k = 0; k < npages; k++, scan++) - set_bit(scan, iounit->bmap); - spin_unlock_irqrestore(&iounit->lock, flags); - return ret; -} - -__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus) -{ - int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT; - struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; - - iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK)); - return vaddr + (((unsigned long)addr) & ~PAGE_MASK); -} -- cgit v1.2.3 From 9dc69230a96a84ca8e6eef89cd34fad0dd8a1a09 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 19:54:01 -0700 Subject: sparc: Kill now spurious includes of sbus.h In order to make this week I also had to add an include of linux/dma-mapping.h to asm/pci_32.h because drivers/pci/pci.c really depends upon getting this header somehow. Signed-off-by: David S. Miller --- arch/sparc/include/asm/dma.h | 2 -- arch/sparc/include/asm/pci_32.h | 2 ++ arch/sparc/kernel/ioport.c | 1 - arch/sparc/kernel/pcic.c | 1 - arch/sparc/kernel/sparc_ksyms.c | 1 - arch/sparc/kernel/sun4d_smp.c | 1 - arch/sparc/mm/io-unit.c | 3 ++- arch/sparc/mm/iommu.c | 3 ++- arch/sparc/mm/nosrmmu.c | 1 - arch/sparc/mm/srmmu.c | 1 - arch/sparc/prom/ranges.c | 1 - arch/sparc64/kernel/irq.c | 1 - arch/sparc64/kernel/sbus.c | 4 +++- arch/sparc64/kernel/sparc64_ksyms.c | 1 - 14 files changed, 9 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h index d1ae56be9fa..b554927bbaf 100644 --- a/arch/sparc/include/asm/dma.h +++ b/arch/sparc/include/asm/dma.h @@ -91,8 +91,6 @@ extern int isa_dma_bridge_buggy; #ifdef CONFIG_SPARC32 -#include - /* Routines for data transfer buffers. */ BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long) BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long) diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h index 0ee949d220c..b41c4c19815 100644 --- a/arch/sparc/include/asm/pci_32.h +++ b/arch/sparc/include/asm/pci_32.h @@ -3,6 +3,8 @@ #ifdef __KERNEL__ +#include + /* Can be used to override the logic in pci_scan_bus for skipping * already-configured bus numbers - to be used for buggy BIOSes * or architectures with incomplete PCI setup by the loader. diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index bca2d6fd5c4..4f025b36934 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index a6a6f982337..9a0aa4ec579 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -18,7 +18,6 @@ #include #include -#include /* for sanity check... */ #include /* for cache flushing. */ #include diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index a9478dbef2e..50ec48ddef6 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -43,7 +43,6 @@ #include #include #ifdef CONFIG_SBUS -#include #include #endif #ifdef CONFIG_PCI diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index dfde77ff084..bf7147a9308 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 53900230c2d..daadf5f8805 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -12,10 +12,11 @@ #include /* pte_offset_map => kmap_atomic */ #include #include +#include +#include #include #include -#include #include #include #include diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 7c55450b55b..e7a499e3aa3 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -13,10 +13,11 @@ #include #include /* pte_offset_map => kmap_atomic */ #include +#include +#include #include #include -#include #include #include #include diff --git a/arch/sparc/mm/nosrmmu.c b/arch/sparc/mm/nosrmmu.c index 3701f70fc30..4f061bb6ce7 100644 --- a/arch/sparc/mm/nosrmmu.c +++ b/arch/sparc/mm/nosrmmu.c @@ -9,7 +9,6 @@ #include #include #include -#include static char shouldnothappen[] __initdata = "SUN4 kernel can only run on SUN4\n"; diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index ee30462598f..6a5d7cabc04 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c index f9b7def35f6..64579a37641 100644 --- a/arch/sparc/prom/ranges.c +++ b/arch/sparc/prom/ranges.c @@ -9,7 +9,6 @@ #include #include #include -#include #include struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 9b6689d9d57..2817a272b4c 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 60605eaf49b..9d7dfb8cc27 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -11,15 +11,17 @@ #include #include #include +#include +#include #include -#include #include #include #include #include #include #include +#include #include #include "iommu_common.h" diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 08c58a8457b..142c16983d1 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -44,7 +44,6 @@ #include #include #ifdef CONFIG_SBUS -#include #include #endif #ifdef CONFIG_PCI -- cgit v1.2.3 From 7eb1aae555663118f8d81bb26dca896d9cd8166c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 05:04:18 -0700 Subject: sparc: Delete asm/sbus*.h No longer used. Signed-off-by: David S. Miller --- arch/sparc/include/asm/sbus.h | 8 ------- arch/sparc/include/asm/sbus_32.h | 52 ---------------------------------------- arch/sparc/include/asm/sbus_64.h | 48 ------------------------------------- 3 files changed, 108 deletions(-) delete mode 100644 arch/sparc/include/asm/sbus.h delete mode 100644 arch/sparc/include/asm/sbus_32.h delete mode 100644 arch/sparc/include/asm/sbus_64.h (limited to 'arch') diff --git a/arch/sparc/include/asm/sbus.h b/arch/sparc/include/asm/sbus.h deleted file mode 100644 index f82481ab44d..00000000000 --- a/arch/sparc/include/asm/sbus.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ___ASM_SPARC_SBUS_H -#define ___ASM_SPARC_SBUS_H -#if defined(__sparc__) && defined(__arch64__) -#include -#else -#include -#endif -#endif diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h deleted file mode 100644 index d960f3e61ec..00000000000 --- a/arch/sparc/include/asm/sbus_32.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * sbus.h: Defines for the Sun SBus. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#ifndef _SPARC_SBUS_H -#define _SPARC_SBUS_H - -#include -#include -#include - -#include -#include -#include - -/* We scan which devices are on the SBus using the PROM node device - * tree. SBus devices are described in two different ways. You can - * either get an absolute address at which to access the device, or - * you can get a SBus 'slot' number and an offset within that slot. - */ - -struct sbus_bus; - -/* Linux SBUS device tables */ -struct sbus_dev { - struct of_device ofdev; - struct sbus_bus *bus; - struct sbus_dev *next; - struct sbus_dev *child; - struct sbus_dev *parent; -}; -#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) - -/* This struct describes the SBus(s) found on this machine. */ -struct sbus_bus { - struct of_device ofdev; - struct sbus_dev *devices; /* Link to devices on this SBus */ - struct sbus_bus *next; /* next SBus, if more than one SBus */ -}; -#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) - -/* These yield IOMMU mappings in consistent mode. */ -void prom_adjust_ranges(struct linux_prom_ranges *, int, - struct linux_prom_ranges *, int); - -extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); -extern int sbus_arch_preinit(void); -extern void sbus_arch_postinit(void); - -#endif /* !(_SPARC_SBUS_H) */ diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h deleted file mode 100644 index b7b76945247..00000000000 --- a/arch/sparc/include/asm/sbus_64.h +++ /dev/null @@ -1,48 +0,0 @@ -/* sbus.h: Defines for the Sun SBus. - * - * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net) - */ - -#ifndef _SPARC64_SBUS_H -#define _SPARC64_SBUS_H - -#include -#include -#include - -#include -#include -#include -#include - -/* We scan which devices are on the SBus using the PROM node device - * tree. SBus devices are described in two different ways. You can - * either get an absolute address at which to access the device, or - * you can get a SBus 'slot' number and an offset within that slot. - */ - -struct sbus_bus; - -/* Linux SBUS device tables */ -struct sbus_dev { - struct of_device ofdev; - struct sbus_bus *bus; - struct sbus_dev *next; - struct sbus_dev *child; - struct sbus_dev *parent; -}; -#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) - -/* This struct describes the SBus(s) found on this machine. */ -struct sbus_bus { - struct of_device ofdev; - struct sbus_dev *devices; /* Tree of SBUS devices */ - struct sbus_bus *next; /* Next SBUS in system */ -}; -#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) - -extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); -extern int sbus_arch_preinit(void); -extern void sbus_arch_postinit(void); - -#endif /* !(_SPARC64_SBUS_H) */ -- cgit v1.2.3 From 90de9dea3bfb80d0db9e6d1ff26f7ea7b2f1f0f5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 17:28:37 -0700 Subject: sparc64: Select RTC_CLASS Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 8df73714caf..19f0cc8a21e 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -19,6 +19,7 @@ config SPARC64 select USE_GENERIC_SMP_HELPERS if SMP select HAVE_ARCH_TRACEHOOK select ARCH_WANT_OPTIONAL_GPIOLIB + select RTC_CLASS config GENERIC_TIME bool -- cgit v1.2.3 From a0b31b578f9ab34826703762113f9d42f3ae9819 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 17:34:31 -0700 Subject: sparc64: Check for RTC class device in update_persistent_clock(). As we convert the various by-hand sparc64 RTC drivers to use the generic RTC framework and drivers, we need to keep the NTP set_rtc_mmss() support via update_persistent_clock() working. In the end, after all the RTC device cases are converted, this local set_rtc_mmss() function will be deleted. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index cc16fdcf98a..184321b88a6 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -405,6 +405,11 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; int update_persistent_clock(struct timespec now) { + struct rtc_device *rtc = rtc_class_open("rtc0"); + + if (rtc) + return rtc_set_mmss(rtc, now.tv_sec); + return set_rtc_mmss(now.tv_sec); } -- cgit v1.2.3 From 1518e7ed08019539498f772faa1f9368fed91361 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 21:06:27 -0700 Subject: sparc64: Convert Mostek rtc to use generic RTC layer driver. Based largely upon a patch by Krzysztof Helt Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 1 + arch/sparc64/kernel/sparc64_ksyms.c | 3 - arch/sparc64/kernel/time.c | 416 +++++++++--------------------------- 3 files changed, 103 insertions(+), 317 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 19f0cc8a21e..0a4e342c041 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -20,6 +20,7 @@ config SPARC64 select HAVE_ARCH_TRACEHOOK select ARCH_WANT_OPTIONAL_GPIOLIB select RTC_CLASS + select RTC_DRV_M48T59 config GENERIC_TIME bool diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 142c16983d1..4c3a6a87c8a 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -152,8 +151,6 @@ EXPORT_SYMBOL(flush_dcache_page); EXPORT_SYMBOL(__flush_dcache_range); #endif -EXPORT_SYMBOL(mostek_lock); -EXPORT_SYMBOL(mstk48t02_regs); #ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(auxio_set_led); EXPORT_SYMBOL(auxio_set_lte); diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 184321b88a6..9c2c3d84443 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -30,13 +30,14 @@ #include #include #include +#include #include #include #include #include +#include #include -#include #include #include #include @@ -50,17 +51,12 @@ #include "entry.h" -DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); -void __iomem *mstk48t02_regs = NULL; #ifdef CONFIG_PCI unsigned long ds1287_regs = 0UL; static void __iomem *bq4802_regs; #endif -static void __iomem *mstk48t08_regs; -static void __iomem *mstk48t59_regs; - static int set_rtc_mmss(unsigned long); #define TICK_PRIV_BIT (1UL << 63) @@ -413,144 +409,10 @@ int update_persistent_clock(struct timespec now) return set_rtc_mmss(now.tv_sec); } -/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ -static void __init kick_start_clock(void) -{ - void __iomem *regs = mstk48t02_regs; - u8 sec, tmp; - int i, count; - - prom_printf("CLOCK: Clock was stopped. Kick start "); - - spin_lock_irq(&mostek_lock); - - /* Turn on the kick start bit to start the oscillator. */ - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - tmp = mostek_read(regs + MOSTEK_SEC); - tmp &= ~MSTK_STOP; - mostek_write(regs + MOSTEK_SEC, tmp); - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp |= MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - /* Delay to allow the clock oscillator to start. */ - sec = MSTK_REG_SEC(regs); - for (i = 0; i < 3; i++) { - while (sec == MSTK_REG_SEC(regs)) - for (count = 0; count < 100000; count++) - /* nothing */ ; - prom_printf("."); - sec = MSTK_REG_SEC(regs); - } - prom_printf("\n"); - - spin_lock_irq(&mostek_lock); - - /* Turn off kick start and set a "valid" time and date. */ - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp &= ~MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - MSTK_SET_REG_SEC(regs,0); - MSTK_SET_REG_MIN(regs,0); - MSTK_SET_REG_HOUR(regs,0); - MSTK_SET_REG_DOW(regs,5); - MSTK_SET_REG_DOM(regs,1); - MSTK_SET_REG_MONTH(regs,8); - MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - /* Ensure the kick start bit is off. If it isn't, turn it off. */ - while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) { - prom_printf("CLOCK: Kick start still on!\n"); - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp &= ~MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - } - - prom_printf("CLOCK: Kick start procedure successful.\n"); -} - -/* Return nonzero if the clock chip battery is low. */ -static int __init has_low_battery(void) -{ - void __iomem *regs = mstk48t02_regs; - u8 data1, data2; - - spin_lock_irq(&mostek_lock); - - data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */ - mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */ - data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */ - mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */ - - spin_unlock_irq(&mostek_lock); - - return (data1 == data2); /* Was the write blocked? */ -} - -static void __init mostek_set_system_time(void __iomem *mregs) -{ - unsigned int year, mon, day, hour, min, sec; - u8 tmp; - - spin_lock_irq(&mostek_lock); - - /* Traditional Mostek chip. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); -} - /* Probe for the real time clock chip. */ static void __init set_system_time(void) { unsigned int year, mon, day, hour, min, sec; - void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; @@ -559,16 +421,11 @@ static void __init set_system_time(void) void __iomem *bregs = 0UL; #endif - if (!mregs && !dregs && !bregs) { + if (!dregs && !bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } - if (mregs) { - mostek_set_system_time(mregs); - return; - } - if (bregs) { unsigned char val = readb(bregs + 0x0e); unsigned int century; @@ -689,12 +546,9 @@ retry: return -EOPNOTSUPP; } -static int __init clock_model_matches(const char *model) +static int __init rtc_model_matches(const char *model) { - if (strcmp(model, "mk48t02") && - strcmp(model, "mk48t08") && - strcmp(model, "mk48t59") && - strcmp(model, "m5819") && + if (strcmp(model, "m5819") && strcmp(model, "m5819p") && strcmp(model, "m5823") && strcmp(model, "ds1287") && @@ -704,7 +558,7 @@ static int __init clock_model_matches(const char *model) return 1; } -static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; const char *model = of_get_property(dp, "model", NULL); @@ -715,14 +569,7 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id if (!model) model = compat; - if (!model || !clock_model_matches(model)) - return -ENODEV; - - /* On an Enterprise system there can be multiple mostek clocks. - * We should only match the one that is on the central FHC bus. - */ - if (!strcmp(dp->parent->name, "fhc") && - strcmp(dp->parent->parent->name, "central") != 0) + if (!model || !rtc_model_matches(model)) return -ENODEV; size = (op->resource[0].end - op->resource[0].start) + 1; @@ -738,32 +585,12 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id ds1287_regs = (unsigned long) regs; } else if (!strcmp(model, "bq4802")) { bq4802_regs = regs; - } else -#endif - if (model[5] == '0' && model[6] == '2') { - mstk48t02_regs = regs; - } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = regs; - mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; - } else { - mstk48t59_regs = regs; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } - +#endif printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); local_irq_save(flags); - if (mstk48t02_regs != NULL) { - /* Report a low battery voltage condition. */ - if (has_low_battery()) - prom_printf("NVRAM: Low battery voltage!\n"); - - /* Kick start the clock if it is completely stopped. */ - if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) - kick_start_clock(); - } - set_system_time(); local_irq_restore(flags); @@ -771,21 +598,102 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id return 0; } -static struct of_device_id clock_match[] = { +static struct of_device_id rtc_match[] = { { - .name = "eeprom", + .name = "rtc", + }, + {}, +}; + +static struct of_platform_driver rtc_driver = { + .match_table = rtc_match, + .probe = rtc_probe, + .driver = { + .name = "rtc", }, +}; + +static unsigned char mostek_read_byte(struct device *dev, u32 ofs) +{ + struct platform_device *pdev = to_platform_device(dev); + void __iomem *regs; + unsigned char val; + + regs = (void __iomem *) pdev->resource[0].start; + val = readb(regs + ofs); + + /* the year 0 is 1968 */ + if (ofs == M48T59_YEAR) { + val += 0x68; + if ((val & 0xf) > 9) + val += 6; + } + return val; +} + +static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) +{ + struct platform_device *pdev = to_platform_device(dev); + void __iomem *regs; + + regs = (void __iomem *) pdev->resource[0].start; + if (ofs == M48T59_YEAR) { + if (val < 0x68) + val += 0x32; + else + val -= 0x68; + if ((val & 0xf) > 9) + val += 6; + if ((val & 0xf0) > 0x9A) + val += 0x60; + } + writeb(val, regs + ofs); +} + +static struct m48t59_plat_data m48t59_data = { + .read_byte = mostek_read_byte, + .write_byte = mostek_write_byte, +}; + +static struct platform_device m48t59_rtc = { + .name = "rtc-m48t59", + .id = 0, + .num_resources = 1, + .dev = { + .platform_data = &m48t59_data, + }, +}; + +static int __devinit mostek_probe(struct of_device *op, const struct of_device_id *match) +{ + struct device_node *dp = op->node; + + /* On an Enterprise system there can be multiple mostek clocks. + * We should only match the one that is on the central FHC bus. + */ + if (!strcmp(dp->parent->name, "fhc") && + strcmp(dp->parent->parent->name, "central") != 0) + return -ENODEV; + + printk(KERN_INFO "%s: Mostek regs at 0x%lx\n", + dp->full_name, op->resource[0].start); + + m48t59_rtc.resource = &op->resource[0]; + return platform_device_register(&m48t59_rtc); +} + +static struct of_device_id mostek_match[] = { { - .name = "rtc", + .name = "eeprom", }, {}, }; -static struct of_platform_driver clock_driver = { - .match_table = clock_match, - .probe = clock_probe, +static struct of_platform_driver mostek_driver = { + .match_table = mostek_match, + .probe = mostek_probe, .driver = { - .name = "clock", + .name = "mostek", }, }; @@ -806,7 +714,10 @@ static int __init clock_init(void) return 0; } - return of_register_driver(&clock_driver, &of_platform_bus_type); + (void) of_register_driver(&rtc_driver, &of_platform_bus_type); + (void) of_register_driver(&mostek_driver, &of_platform_bus_type); + + return 0; } /* Must be after subsys_initcall() so that busses are probed. Must @@ -1078,7 +989,6 @@ unsigned long long sched_clock(void) static int set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, chip_minutes; - void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; @@ -1087,62 +997,15 @@ static int set_rtc_mmss(unsigned long nowtime) void __iomem *bregs = 0UL; #endif unsigned long flags; - u8 tmp; /* * Not having a register set can lead to trouble. * Also starfire doesn't have a tod clock. */ - if (!mregs && !dregs && !bregs) + if (!dregs && !bregs) return -1; - if (mregs) { - spin_lock_irqsave(&mostek_lock, flags); - - /* Read the current RTC minutes. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - chip_minutes = MSTK_REG_MIN(mregs); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(mregs + MOSTEK_CREG, tmp); - - MSTK_SET_REG_SEC(mregs,real_seconds); - MSTK_SET_REG_MIN(mregs,real_minutes); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irqrestore(&mostek_lock, flags); - - return 0; - } else { - spin_unlock_irqrestore(&mostek_lock, flags); - - return -1; - } - } else if (bregs) { + if (bregs) { int retval = 0; unsigned char val = readb(bregs + 0x0e); @@ -1485,74 +1348,6 @@ static int cmos_set_rtc_time(struct rtc_time *rtc_tm) } #endif /* CONFIG_PCI */ -static void mostek_get_rtc_time(struct rtc_time *rtc_tm) -{ - void __iomem *regs = mstk48t02_regs; - u8 tmp; - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(regs + MOSTEK_CREG, tmp); - - rtc_tm->tm_sec = MSTK_REG_SEC(regs); - rtc_tm->tm_min = MSTK_REG_MIN(regs); - rtc_tm->tm_hour = MSTK_REG_HOUR(regs); - rtc_tm->tm_mday = MSTK_REG_DOM(regs); - rtc_tm->tm_mon = MSTK_REG_MONTH(regs); - rtc_tm->tm_year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); - rtc_tm->tm_wday = MSTK_REG_DOW(regs); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - rtc_tm->tm_mon--; - rtc_tm->tm_wday--; - rtc_tm->tm_year -= 1900; -} - -static int mostek_set_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned char mon, day, hrs, min, sec, wday; - void __iomem *regs = mstk48t02_regs; - unsigned int yrs; - u8 tmp; - - yrs = rtc_tm->tm_year + 1900; - mon = rtc_tm->tm_mon + 1; - day = rtc_tm->tm_mday; - wday = rtc_tm->tm_wday + 1; - hrs = rtc_tm->tm_hour; - min = rtc_tm->tm_min; - sec = rtc_tm->tm_sec; - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - MSTK_SET_REG_SEC(regs, sec); - MSTK_SET_REG_MIN(regs, min); - MSTK_SET_REG_HOUR(regs, hrs); - MSTK_SET_REG_DOW(regs, wday); - MSTK_SET_REG_DOM(regs, day); - MSTK_SET_REG_MONTH(regs, mon); - MSTK_SET_REG_YEAR(regs, yrs - MSTK_YEAR_ZERO); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - return 0; -} - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1580,11 +1375,6 @@ static struct mini_rtc_ops cmos_rtc_ops = { }; #endif /* CONFIG_PCI */ -static struct mini_rtc_ops mostek_rtc_ops = { - .get_rtc_time = mostek_get_rtc_time, - .set_rtc_time = mostek_set_rtc_time, -}; - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1717,8 +1507,6 @@ static int __init rtc_mini_init(void) else if (ds1287_regs) mini_rtc_ops = &cmos_rtc_ops; #endif /* CONFIG_PCI */ - else if (mstk48t02_regs) - mini_rtc_ops = &mostek_rtc_ops; else return -ENODEV; -- cgit v1.2.3 From e8b75c4fd6e3bec57d268b76a0a9a8f58f1612e3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 16:46:23 -0700 Subject: sparc: asm/mostek.h is now 32-bit only No need for the 64-bit header version any more. Signed-off-by: David S. Miller --- arch/sparc/include/asm/mostek.h | 173 +++++++++++++++++++++++++++++++++++-- arch/sparc/include/asm/mostek_32.h | 171 ------------------------------------ arch/sparc/include/asm/mostek_64.h | 143 ------------------------------ 3 files changed, 168 insertions(+), 319 deletions(-) delete mode 100644 arch/sparc/include/asm/mostek_32.h delete mode 100644 arch/sparc/include/asm/mostek_64.h (limited to 'arch') diff --git a/arch/sparc/include/asm/mostek.h b/arch/sparc/include/asm/mostek.h index 433be3e0a69..a99590c4c50 100644 --- a/arch/sparc/include/asm/mostek.h +++ b/arch/sparc/include/asm/mostek.h @@ -1,8 +1,171 @@ -#ifndef ___ASM_SPARC_MOSTEK_H -#define ___ASM_SPARC_MOSTEK_H -#if defined(__sparc__) && defined(__arch64__) -#include +/* + * mostek.h: Describes the various Mostek time of day clock registers. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) + * Added intersil code 05/25/98 Chris Davis (cdavis@cois.on.ca) + */ + +#ifndef _SPARC_MOSTEK_H +#define _SPARC_MOSTEK_H + +#include +#include + +/* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) + * + * Data + * Address Function + * Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0 + * 7ff - - - - - - - - Year 00-99 + * 7fe 0 0 0 - - - - - Month 01-12 + * 7fd 0 0 - - - - - - Date 01-31 + * 7fc 0 FT 0 0 0 - - - Day 01-07 + * 7fb KS 0 - - - - - - Hours 00-23 + * 7fa 0 - - - - - - - Minutes 00-59 + * 7f9 ST - - - - - - - Seconds 00-59 + * 7f8 W R S - - - - - Control + * + * * ST is STOP BIT + * * W is WRITE BIT + * * R is READ BIT + * * S is SIGN BIT + * * FT is FREQ TEST BIT + * * KS is KICK START BIT + */ + +/* The Mostek 48t02 real time clock and NVRAM chip. The registers + * other than the control register are in binary coded decimal. Some + * control bits also live outside the control register. + */ +#define mostek_read(_addr) readb(_addr) +#define mostek_write(_addr,_val) writeb(_val, _addr) +#define MOSTEK_EEPROM 0x0000UL +#define MOSTEK_IDPROM 0x07d8UL +#define MOSTEK_CREG 0x07f8UL +#define MOSTEK_SEC 0x07f9UL +#define MOSTEK_MIN 0x07faUL +#define MOSTEK_HOUR 0x07fbUL +#define MOSTEK_DOW 0x07fcUL +#define MOSTEK_DOM 0x07fdUL +#define MOSTEK_MONTH 0x07feUL +#define MOSTEK_YEAR 0x07ffUL + +struct mostek48t02 { + volatile char eeprom[2008]; /* This is the eeprom, don't touch! */ + struct idprom idprom; /* The idprom lives here. */ + volatile unsigned char creg; /* Control register */ + volatile unsigned char sec; /* Seconds (0-59) */ + volatile unsigned char min; /* Minutes (0-59) */ + volatile unsigned char hour; /* Hour (0-23) */ + volatile unsigned char dow; /* Day of the week (1-7) */ + volatile unsigned char dom; /* Day of the month (1-31) */ + volatile unsigned char month; /* Month of year (1-12) */ + volatile unsigned char year; /* Year (0-99) */ +}; + +extern spinlock_t mostek_lock; +extern void __iomem *mstk48t02_regs; + +/* Control register values. */ +#define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ +#define MSTK_CREG_READ 0x40 /* Stop updates to allow a clean read. */ +#define MSTK_CREG_SIGN 0x20 /* Slow/speed clock in calibration mode. */ + +/* Control bits that live in the other registers. */ +#define MSTK_STOP 0x80 /* Stop the clock oscillator. (sec) */ +#define MSTK_KICK_START 0x80 /* Kick start the clock chip. (hour) */ +#define MSTK_FREQ_TEST 0x40 /* Frequency test mode. (day) */ + +#define MSTK_YEAR_ZERO 1968 /* If year reg has zero, it is 1968. */ +#define MSTK_CVT_YEAR(yr) ((yr) + MSTK_YEAR_ZERO) + +/* Masks that define how much space each value takes up. */ +#define MSTK_SEC_MASK 0x7f +#define MSTK_MIN_MASK 0x7f +#define MSTK_HOUR_MASK 0x3f +#define MSTK_DOW_MASK 0x07 +#define MSTK_DOM_MASK 0x3f +#define MSTK_MONTH_MASK 0x1f +#define MSTK_YEAR_MASK 0xffU + +/* Binary coded decimal conversion macros. */ +#define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) +#define MSTK_DECIMAL_TO_REGVAL(x) ((((x) / 0x0A) << 0x04) + ((x) % 0x0A)) + +/* Generic register set and get macros for internal use. */ +#define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(((struct mostek48t02 *)regs)->var & MSTK_ ## mask ## _MASK)) +#define MSTK_SET(regs,var,value,mask) do { ((struct mostek48t02 *)regs)->var &= ~(MSTK_ ## mask ## _MASK); ((struct mostek48t02 *)regs)->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0) + +/* Macros to make register access easier on our fingers. These give you + * the decimal value of the register requested if applicable. You pass + * the a pointer to a 'struct mostek48t02'. + */ +#define MSTK_REG_CREG(regs) (((struct mostek48t02 *)regs)->creg) +#define MSTK_REG_SEC(regs) MSTK_GET(regs,sec,SEC) +#define MSTK_REG_MIN(regs) MSTK_GET(regs,min,MIN) +#define MSTK_REG_HOUR(regs) MSTK_GET(regs,hour,HOUR) +#define MSTK_REG_DOW(regs) MSTK_GET(regs,dow,DOW) +#define MSTK_REG_DOM(regs) MSTK_GET(regs,dom,DOM) +#define MSTK_REG_MONTH(regs) MSTK_GET(regs,month,MONTH) +#define MSTK_REG_YEAR(regs) MSTK_GET(regs,year,YEAR) + +#define MSTK_SET_REG_SEC(regs,value) MSTK_SET(regs,sec,value,SEC) +#define MSTK_SET_REG_MIN(regs,value) MSTK_SET(regs,min,value,MIN) +#define MSTK_SET_REG_HOUR(regs,value) MSTK_SET(regs,hour,value,HOUR) +#define MSTK_SET_REG_DOW(regs,value) MSTK_SET(regs,dow,value,DOW) +#define MSTK_SET_REG_DOM(regs,value) MSTK_SET(regs,dom,value,DOM) +#define MSTK_SET_REG_MONTH(regs,value) MSTK_SET(regs,month,value,MONTH) +#define MSTK_SET_REG_YEAR(regs,value) MSTK_SET(regs,year,value,YEAR) + + +/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the + * same (basically) layout of the 48t02 chip except for the extra + * NVRAM on board (8 KB against the 48t02's 2 KB). + */ +struct mostek48t08 { + char offset[6*1024]; /* Magic things may be here, who knows? */ + struct mostek48t02 regs; /* Here is what we are interested in. */ +}; + +#ifdef CONFIG_SUN4 +enum sparc_clock_type { MSTK48T02, MSTK48T08, \ +INTERSIL, MSTK_INVALID }; #else -#include +enum sparc_clock_type { MSTK48T02, MSTK48T08, \ +MSTK_INVALID }; #endif + +#ifdef CONFIG_SUN4 +/* intersil on a sun 4/260 code data from harris doc */ +struct intersil_dt { + volatile unsigned char int_csec; + volatile unsigned char int_hour; + volatile unsigned char int_min; + volatile unsigned char int_sec; + volatile unsigned char int_month; + volatile unsigned char int_day; + volatile unsigned char int_year; + volatile unsigned char int_dow; +}; + +struct intersil { + struct intersil_dt clk; + struct intersil_dt cmp; + volatile unsigned char int_intr_reg; + volatile unsigned char int_cmd_reg; +}; + +#define INTERSIL_STOP 0x0 +#define INTERSIL_START 0x8 +#define INTERSIL_INTR_DISABLE 0x0 +#define INTERSIL_INTR_ENABLE 0x10 +#define INTERSIL_32K 0x0 +#define INTERSIL_NORMAL 0x0 +#define INTERSIL_24H 0x4 +#define INTERSIL_INT_100HZ 0x2 + +/* end of intersil info */ #endif + +#endif /* !(_SPARC_MOSTEK_H) */ diff --git a/arch/sparc/include/asm/mostek_32.h b/arch/sparc/include/asm/mostek_32.h deleted file mode 100644 index a99590c4c50..00000000000 --- a/arch/sparc/include/asm/mostek_32.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * mostek.h: Describes the various Mostek time of day clock registers. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) - * Added intersil code 05/25/98 Chris Davis (cdavis@cois.on.ca) - */ - -#ifndef _SPARC_MOSTEK_H -#define _SPARC_MOSTEK_H - -#include -#include - -/* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) - * - * Data - * Address Function - * Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0 - * 7ff - - - - - - - - Year 00-99 - * 7fe 0 0 0 - - - - - Month 01-12 - * 7fd 0 0 - - - - - - Date 01-31 - * 7fc 0 FT 0 0 0 - - - Day 01-07 - * 7fb KS 0 - - - - - - Hours 00-23 - * 7fa 0 - - - - - - - Minutes 00-59 - * 7f9 ST - - - - - - - Seconds 00-59 - * 7f8 W R S - - - - - Control - * - * * ST is STOP BIT - * * W is WRITE BIT - * * R is READ BIT - * * S is SIGN BIT - * * FT is FREQ TEST BIT - * * KS is KICK START BIT - */ - -/* The Mostek 48t02 real time clock and NVRAM chip. The registers - * other than the control register are in binary coded decimal. Some - * control bits also live outside the control register. - */ -#define mostek_read(_addr) readb(_addr) -#define mostek_write(_addr,_val) writeb(_val, _addr) -#define MOSTEK_EEPROM 0x0000UL -#define MOSTEK_IDPROM 0x07d8UL -#define MOSTEK_CREG 0x07f8UL -#define MOSTEK_SEC 0x07f9UL -#define MOSTEK_MIN 0x07faUL -#define MOSTEK_HOUR 0x07fbUL -#define MOSTEK_DOW 0x07fcUL -#define MOSTEK_DOM 0x07fdUL -#define MOSTEK_MONTH 0x07feUL -#define MOSTEK_YEAR 0x07ffUL - -struct mostek48t02 { - volatile char eeprom[2008]; /* This is the eeprom, don't touch! */ - struct idprom idprom; /* The idprom lives here. */ - volatile unsigned char creg; /* Control register */ - volatile unsigned char sec; /* Seconds (0-59) */ - volatile unsigned char min; /* Minutes (0-59) */ - volatile unsigned char hour; /* Hour (0-23) */ - volatile unsigned char dow; /* Day of the week (1-7) */ - volatile unsigned char dom; /* Day of the month (1-31) */ - volatile unsigned char month; /* Month of year (1-12) */ - volatile unsigned char year; /* Year (0-99) */ -}; - -extern spinlock_t mostek_lock; -extern void __iomem *mstk48t02_regs; - -/* Control register values. */ -#define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ -#define MSTK_CREG_READ 0x40 /* Stop updates to allow a clean read. */ -#define MSTK_CREG_SIGN 0x20 /* Slow/speed clock in calibration mode. */ - -/* Control bits that live in the other registers. */ -#define MSTK_STOP 0x80 /* Stop the clock oscillator. (sec) */ -#define MSTK_KICK_START 0x80 /* Kick start the clock chip. (hour) */ -#define MSTK_FREQ_TEST 0x40 /* Frequency test mode. (day) */ - -#define MSTK_YEAR_ZERO 1968 /* If year reg has zero, it is 1968. */ -#define MSTK_CVT_YEAR(yr) ((yr) + MSTK_YEAR_ZERO) - -/* Masks that define how much space each value takes up. */ -#define MSTK_SEC_MASK 0x7f -#define MSTK_MIN_MASK 0x7f -#define MSTK_HOUR_MASK 0x3f -#define MSTK_DOW_MASK 0x07 -#define MSTK_DOM_MASK 0x3f -#define MSTK_MONTH_MASK 0x1f -#define MSTK_YEAR_MASK 0xffU - -/* Binary coded decimal conversion macros. */ -#define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) -#define MSTK_DECIMAL_TO_REGVAL(x) ((((x) / 0x0A) << 0x04) + ((x) % 0x0A)) - -/* Generic register set and get macros for internal use. */ -#define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(((struct mostek48t02 *)regs)->var & MSTK_ ## mask ## _MASK)) -#define MSTK_SET(regs,var,value,mask) do { ((struct mostek48t02 *)regs)->var &= ~(MSTK_ ## mask ## _MASK); ((struct mostek48t02 *)regs)->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0) - -/* Macros to make register access easier on our fingers. These give you - * the decimal value of the register requested if applicable. You pass - * the a pointer to a 'struct mostek48t02'. - */ -#define MSTK_REG_CREG(regs) (((struct mostek48t02 *)regs)->creg) -#define MSTK_REG_SEC(regs) MSTK_GET(regs,sec,SEC) -#define MSTK_REG_MIN(regs) MSTK_GET(regs,min,MIN) -#define MSTK_REG_HOUR(regs) MSTK_GET(regs,hour,HOUR) -#define MSTK_REG_DOW(regs) MSTK_GET(regs,dow,DOW) -#define MSTK_REG_DOM(regs) MSTK_GET(regs,dom,DOM) -#define MSTK_REG_MONTH(regs) MSTK_GET(regs,month,MONTH) -#define MSTK_REG_YEAR(regs) MSTK_GET(regs,year,YEAR) - -#define MSTK_SET_REG_SEC(regs,value) MSTK_SET(regs,sec,value,SEC) -#define MSTK_SET_REG_MIN(regs,value) MSTK_SET(regs,min,value,MIN) -#define MSTK_SET_REG_HOUR(regs,value) MSTK_SET(regs,hour,value,HOUR) -#define MSTK_SET_REG_DOW(regs,value) MSTK_SET(regs,dow,value,DOW) -#define MSTK_SET_REG_DOM(regs,value) MSTK_SET(regs,dom,value,DOM) -#define MSTK_SET_REG_MONTH(regs,value) MSTK_SET(regs,month,value,MONTH) -#define MSTK_SET_REG_YEAR(regs,value) MSTK_SET(regs,year,value,YEAR) - - -/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the - * same (basically) layout of the 48t02 chip except for the extra - * NVRAM on board (8 KB against the 48t02's 2 KB). - */ -struct mostek48t08 { - char offset[6*1024]; /* Magic things may be here, who knows? */ - struct mostek48t02 regs; /* Here is what we are interested in. */ -}; - -#ifdef CONFIG_SUN4 -enum sparc_clock_type { MSTK48T02, MSTK48T08, \ -INTERSIL, MSTK_INVALID }; -#else -enum sparc_clock_type { MSTK48T02, MSTK48T08, \ -MSTK_INVALID }; -#endif - -#ifdef CONFIG_SUN4 -/* intersil on a sun 4/260 code data from harris doc */ -struct intersil_dt { - volatile unsigned char int_csec; - volatile unsigned char int_hour; - volatile unsigned char int_min; - volatile unsigned char int_sec; - volatile unsigned char int_month; - volatile unsigned char int_day; - volatile unsigned char int_year; - volatile unsigned char int_dow; -}; - -struct intersil { - struct intersil_dt clk; - struct intersil_dt cmp; - volatile unsigned char int_intr_reg; - volatile unsigned char int_cmd_reg; -}; - -#define INTERSIL_STOP 0x0 -#define INTERSIL_START 0x8 -#define INTERSIL_INTR_DISABLE 0x0 -#define INTERSIL_INTR_ENABLE 0x10 -#define INTERSIL_32K 0x0 -#define INTERSIL_NORMAL 0x0 -#define INTERSIL_24H 0x4 -#define INTERSIL_INT_100HZ 0x2 - -/* end of intersil info */ -#endif - -#endif /* !(_SPARC_MOSTEK_H) */ diff --git a/arch/sparc/include/asm/mostek_64.h b/arch/sparc/include/asm/mostek_64.h deleted file mode 100644 index c5652de2ace..00000000000 --- a/arch/sparc/include/asm/mostek_64.h +++ /dev/null @@ -1,143 +0,0 @@ -/* mostek.h: Describes the various Mostek time of day clock registers. - * - * Copyright (C) 1995 David S. Miller (davem@davemloft.net) - * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) - */ - -#ifndef _SPARC64_MOSTEK_H -#define _SPARC64_MOSTEK_H - -#include - -/* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) - * - * Data - * Address Function - * Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0 - * 7ff - - - - - - - - Year 00-99 - * 7fe 0 0 0 - - - - - Month 01-12 - * 7fd 0 0 - - - - - - Date 01-31 - * 7fc 0 FT 0 0 0 - - - Day 01-07 - * 7fb KS 0 - - - - - - Hours 00-23 - * 7fa 0 - - - - - - - Minutes 00-59 - * 7f9 ST - - - - - - - Seconds 00-59 - * 7f8 W R S - - - - - Control - * - * * ST is STOP BIT - * * W is WRITE BIT - * * R is READ BIT - * * S is SIGN BIT - * * FT is FREQ TEST BIT - * * KS is KICK START BIT - */ - -/* The Mostek 48t02 real time clock and NVRAM chip. The registers - * other than the control register are in binary coded decimal. Some - * control bits also live outside the control register. - * - * We now deal with physical addresses for I/O to the chip. -DaveM - */ -static inline u8 mostek_read(void __iomem *addr) -{ - u8 ret; - - __asm__ __volatile__("lduba [%1] %2, %0" - : "=r" (ret) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)); - return ret; -} - -static inline void mostek_write(void __iomem *addr, u8 val) -{ - __asm__ __volatile__("stba %0, [%1] %2" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)); -} - -#define MOSTEK_EEPROM 0x0000UL -#define MOSTEK_IDPROM 0x07d8UL -#define MOSTEK_CREG 0x07f8UL -#define MOSTEK_SEC 0x07f9UL -#define MOSTEK_MIN 0x07faUL -#define MOSTEK_HOUR 0x07fbUL -#define MOSTEK_DOW 0x07fcUL -#define MOSTEK_DOM 0x07fdUL -#define MOSTEK_MONTH 0x07feUL -#define MOSTEK_YEAR 0x07ffUL - -extern spinlock_t mostek_lock; -extern void __iomem *mstk48t02_regs; - -/* Control register values. */ -#define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ -#define MSTK_CREG_READ 0x40 /* Stop updates to allow a clean read. */ -#define MSTK_CREG_SIGN 0x20 /* Slow/speed clock in calibration mode. */ - -/* Control bits that live in the other registers. */ -#define MSTK_STOP 0x80 /* Stop the clock oscillator. (sec) */ -#define MSTK_KICK_START 0x80 /* Kick start the clock chip. (hour) */ -#define MSTK_FREQ_TEST 0x40 /* Frequency test mode. (day) */ - -#define MSTK_YEAR_ZERO 1968 /* If year reg has zero, it is 1968. */ -#define MSTK_CVT_YEAR(yr) ((yr) + MSTK_YEAR_ZERO) - -/* Masks that define how much space each value takes up. */ -#define MSTK_SEC_MASK 0x7f -#define MSTK_MIN_MASK 0x7f -#define MSTK_HOUR_MASK 0x3f -#define MSTK_DOW_MASK 0x07 -#define MSTK_DOM_MASK 0x3f -#define MSTK_MONTH_MASK 0x1f -#define MSTK_YEAR_MASK 0xffU - -/* Binary coded decimal conversion macros. */ -#define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) -#define MSTK_DECIMAL_TO_REGVAL(x) ((((x) / 0x0A) << 0x04) + ((x) % 0x0A)) - -/* Generic register set and get macros for internal use. */ -#define MSTK_GET(regs,name) \ - (MSTK_REGVAL_TO_DECIMAL(mostek_read(regs + MOSTEK_ ## name) & MSTK_ ## name ## _MASK)) -#define MSTK_SET(regs,name,value) \ -do { u8 __val = mostek_read(regs + MOSTEK_ ## name); \ - __val &= ~(MSTK_ ## name ## _MASK); \ - __val |= (MSTK_DECIMAL_TO_REGVAL(value) & \ - (MSTK_ ## name ## _MASK)); \ - mostek_write(regs + MOSTEK_ ## name, __val); \ -} while(0) - -/* Macros to make register access easier on our fingers. These give you - * the decimal value of the register requested if applicable. You pass - * the a pointer to a 'struct mostek48t02'. - */ -#define MSTK_REG_CREG(regs) (mostek_read((regs) + MOSTEK_CREG)) -#define MSTK_REG_SEC(regs) MSTK_GET(regs,SEC) -#define MSTK_REG_MIN(regs) MSTK_GET(regs,MIN) -#define MSTK_REG_HOUR(regs) MSTK_GET(regs,HOUR) -#define MSTK_REG_DOW(regs) MSTK_GET(regs,DOW) -#define MSTK_REG_DOM(regs) MSTK_GET(regs,DOM) -#define MSTK_REG_MONTH(regs) MSTK_GET(regs,MONTH) -#define MSTK_REG_YEAR(regs) MSTK_GET(regs,YEAR) - -#define MSTK_SET_REG_SEC(regs,value) MSTK_SET(regs,SEC,value) -#define MSTK_SET_REG_MIN(regs,value) MSTK_SET(regs,MIN,value) -#define MSTK_SET_REG_HOUR(regs,value) MSTK_SET(regs,HOUR,value) -#define MSTK_SET_REG_DOW(regs,value) MSTK_SET(regs,DOW,value) -#define MSTK_SET_REG_DOM(regs,value) MSTK_SET(regs,DOM,value) -#define MSTK_SET_REG_MONTH(regs,value) MSTK_SET(regs,MONTH,value) -#define MSTK_SET_REG_YEAR(regs,value) MSTK_SET(regs,YEAR,value) - - -/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the - * same (basically) layout of the 48t02 chip except for the extra - * NVRAM on board (8 KB against the 48t02's 2 KB). - */ -#define MOSTEK_48T08_OFFSET 0x0000UL /* Lower NVRAM portions */ -#define MOSTEK_48T08_48T02 0x1800UL /* Offset to 48T02 chip */ - -/* SUN5 systems usually have 48t59 model clock chipsets. But we keep the older - * clock chip definitions around just in case. - */ -#define MOSTEK_48T59_OFFSET 0x0000UL /* Lower NVRAM portions */ -#define MOSTEK_48T59_48T02 0x1800UL /* Offset to 48T02 chip */ - -#endif /* !(_SPARC64_MOSTEK_H) */ -- cgit v1.2.3 From da86783dda5ad8c64b945157108d1ace7aa79bbf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 22:16:15 -0700 Subject: sparc64: Use generic CMOS driver. Based largely upon a patch by Krzysztof Helt Signed-off-by: David S. Miller --- arch/sparc/include/asm/mc146818rtc_64.h | 10 +- arch/sparc64/Kconfig | 1 + arch/sparc64/kernel/time.c | 372 +++++++++++--------------------- 3 files changed, 123 insertions(+), 260 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/mc146818rtc_64.h b/arch/sparc/include/asm/mc146818rtc_64.h index e9c0fcc25c6..7238d174e0e 100644 --- a/arch/sparc/include/asm/mc146818rtc_64.h +++ b/arch/sparc/include/asm/mc146818rtc_64.h @@ -7,12 +7,8 @@ #include #ifndef RTC_PORT -#ifdef CONFIG_PCI -extern unsigned long ds1287_regs; -#else -#define ds1287_regs (0UL) -#endif -#define RTC_PORT(x) (ds1287_regs + (x)) +extern unsigned long cmos_regs; +#define RTC_PORT(x) (cmos_regs + (x)) #define RTC_ALWAYS_BCD 0 #endif @@ -29,6 +25,4 @@ outb_p((addr),RTC_PORT(0)); \ outb_p((val),RTC_PORT(1)); \ }) -#define RTC_IRQ 8 - #endif /* __ASM_SPARC64_MC146818RTC_H */ diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 0a4e342c041..e0d783bbae0 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -21,6 +21,7 @@ config SPARC64 select ARCH_WANT_OPTIONAL_GPIOLIB select RTC_CLASS select RTC_DRV_M48T59 + select RTC_DRV_CMOS config GENERIC_TIME bool diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 9c2c3d84443..abdeead4e5b 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -52,10 +52,7 @@ #include "entry.h" DEFINE_SPINLOCK(rtc_lock); -#ifdef CONFIG_PCI -unsigned long ds1287_regs = 0UL; static void __iomem *bq4802_regs; -#endif static int set_rtc_mmss(unsigned long); @@ -413,69 +410,38 @@ int update_persistent_clock(struct timespec now) static void __init set_system_time(void) { unsigned int year, mon, day, hour, min, sec; -#ifdef CONFIG_PCI - unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; -#else - unsigned long dregs = 0UL; - void __iomem *bregs = 0UL; -#endif + unsigned char val = readb(bregs + 0x0e); + unsigned int century; - if (!dregs && !bregs) { + if (!bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } - if (bregs) { - unsigned char val = readb(bregs + 0x0e); - unsigned int century; + /* BQ4802 RTC chip. */ - /* BQ4802 RTC chip. */ + writeb(val | 0x08, bregs + 0x0e); - writeb(val | 0x08, bregs + 0x0e); + sec = readb(bregs + 0x00); + min = readb(bregs + 0x02); + hour = readb(bregs + 0x04); + day = readb(bregs + 0x06); + mon = readb(bregs + 0x09); + year = readb(bregs + 0x0a); + century = readb(bregs + 0x0f); - sec = readb(bregs + 0x00); - min = readb(bregs + 0x02); - hour = readb(bregs + 0x04); - day = readb(bregs + 0x06); - mon = readb(bregs + 0x09); - year = readb(bregs + 0x0a); - century = readb(bregs + 0x0f); + writeb(val, bregs + 0x0e); - writeb(val, bregs + 0x0e); - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - BCD_TO_BIN(century); + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + BCD_TO_BIN(century); - year += (century * 100); - } else { - /* Dallas 12887 RTC chip. */ - - do { - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - if ((year += 1900) < 1970) - year += 100; - } + year += (century * 100); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); @@ -546,48 +512,79 @@ retry: return -EOPNOTSUPP; } -static int __init rtc_model_matches(const char *model) -{ - if (strcmp(model, "m5819") && - strcmp(model, "m5819p") && - strcmp(model, "m5823") && - strcmp(model, "ds1287") && - strcmp(model, "bq4802")) - return 0; +unsigned long cmos_regs; +EXPORT_SYMBOL(cmos_regs); - return 1; -} +struct resource rtc_cmos_resource; + +static struct platform_device rtc_cmos_device = { + .name = "rtc_cmos", + .id = -1, + .resource = &rtc_cmos_resource, + .num_resources = 1, +}; static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) { - struct device_node *dp = op->node; - const char *model = of_get_property(dp, "model", NULL); - const char *compat = of_get_property(dp, "compatible", NULL); - unsigned long size, flags; - void __iomem *regs; + struct resource *r; - if (!model) - model = compat; + printk(KERN_INFO "%s: RTC regs at 0x%lx\n", + op->node->full_name, op->resource[0].start); - if (!model || !rtc_model_matches(model)) - return -ENODEV; + /* The CMOS RTC driver only accepts IORESOURCE_IO, so cons + * up a fake resource so that the probe works for all cases. + * When the RTC is behind an ISA bus it will have IORESOURCE_IO + * already, whereas when it's behind EBUS is will be IORESOURCE_MEM. + */ + + r = &rtc_cmos_resource; + r->flags = IORESOURCE_IO; + r->name = op->resource[0].name; + r->start = op->resource[0].start; + r->end = op->resource[0].end; + + cmos_regs = op->resource[0].start; + return platform_device_register(&rtc_cmos_device); +} + +static struct of_device_id rtc_match[] = { + { + .name = "rtc", + .compatible = "m5819", + }, + { + .name = "rtc", + .compatible = "isa-m5819p", + }, + { + .name = "rtc", + .compatible = "isa-m5823p", + }, + { + .name = "rtc", + .compatible = "ds1287", + }, + {}, +}; + +static struct of_platform_driver rtc_driver = { + .match_table = rtc_match, + .probe = rtc_probe, + .driver = { + .name = "rtc", + }, +}; - size = (op->resource[0].end - op->resource[0].start) + 1; - regs = of_ioremap(&op->resource[0], 0, size, "clock"); - if (!regs) +static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) +{ + struct device_node *dp = op->node; + unsigned long flags; + + bq4802_regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "bq4802"); + if (!bq4802_regs) return -ENOMEM; -#ifdef CONFIG_PCI - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = (unsigned long) regs; - } else if (!strcmp(model, "bq4802")) { - bq4802_regs = regs; - } -#endif - printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); + printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, bq4802_regs); local_irq_save(flags); @@ -598,18 +595,18 @@ static int __devinit rtc_probe(struct of_device *op, const struct of_device_id * return 0; } -static struct of_device_id rtc_match[] = { +static struct of_device_id bq4802_match[] = { { .name = "rtc", + .compatible = "bq4802", }, - {}, }; -static struct of_platform_driver rtc_driver = { - .match_table = rtc_match, - .probe = rtc_probe, +static struct of_platform_driver bq4802_driver = { + .match_table = bq4802_match, + .probe = bq4802_probe, .driver = { - .name = "rtc", + .name = "bq4802", }, }; @@ -716,6 +713,7 @@ static int __init clock_init(void) (void) of_register_driver(&rtc_driver, &of_platform_bus_type); (void) of_register_driver(&mostek_driver, &of_platform_bus_type); + (void) of_register_driver(&bq4802_driver, &of_platform_bus_type); return 0; } @@ -989,96 +987,51 @@ unsigned long long sched_clock(void) static int set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, chip_minutes; -#ifdef CONFIG_PCI - unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; -#else - unsigned long dregs = 0UL; - void __iomem *bregs = 0UL; -#endif unsigned long flags; + unsigned char val; + int retval = 0; /* * Not having a register set can lead to trouble. * Also starfire doesn't have a tod clock. */ - if (!dregs && !bregs) + if (!bregs) return -1; - if (bregs) { - int retval = 0; - unsigned char val = readb(bregs + 0x0e); + spin_lock_irqsave(&rtc_lock, flags); - /* BQ4802 RTC chip. */ + val = readb(bregs + 0x0e); - writeb(val | 0x08, bregs + 0x0e); + /* BQ4802 RTC chip. */ - chip_minutes = readb(bregs + 0x02); - BCD_TO_BIN(chip_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; - real_minutes %= 60; + writeb(val | 0x08, bregs + 0x0e); - if (abs(real_minutes - chip_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - writeb(real_seconds, bregs + 0x00); - writeb(real_minutes, bregs + 0x02); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - chip_minutes, real_minutes); - retval = -1; - } + chip_minutes = readb(bregs + 0x02); + BCD_TO_BIN(chip_minutes); + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) + real_minutes += 30; + real_minutes %= 60; - writeb(val, bregs + 0x0e); - - return retval; + if (abs(real_minutes - chip_minutes) < 30) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + writeb(real_seconds, bregs + 0x00); + writeb(real_minutes, bregs + 0x02); } else { - int retval = 0; - unsigned char save_control, save_freq_select; - - /* Stolen from arch/i386/kernel/time.c, see there for - * credits and descriptive comments. - */ - spin_lock_irqsave(&rtc_lock, flags); - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - chip_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(chip_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - chip_minutes, real_minutes); - retval = -1; - } + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + chip_minutes, real_minutes); + retval = -1; + } - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock_irqrestore(&rtc_lock, flags); + writeb(val, bregs + 0x0e); - return retval; - } + spin_unlock_irqrestore(&rtc_lock, flags); + + return retval; } #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ @@ -1202,7 +1155,6 @@ static int hypervisor_set_rtc_time(struct rtc_time *time) return hypervisor_set_time(seconds); } -#ifdef CONFIG_PCI static void bq4802_get_rtc_time(struct rtc_time *time) { unsigned char val = readb(bq4802_regs + 0x0e); @@ -1275,79 +1227,6 @@ static int bq4802_set_rtc_time(struct rtc_time *time) return 0; } -static void cmos_get_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned char ctrl; - - rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); - rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); - rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); - rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); - rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); - rtc_tm->tm_year = CMOS_READ(RTC_YEAR); - rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); - - ctrl = CMOS_READ(RTC_CONTROL); - if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(rtc_tm->tm_sec); - BCD_TO_BIN(rtc_tm->tm_min); - BCD_TO_BIN(rtc_tm->tm_hour); - BCD_TO_BIN(rtc_tm->tm_mday); - BCD_TO_BIN(rtc_tm->tm_mon); - BCD_TO_BIN(rtc_tm->tm_year); - BCD_TO_BIN(rtc_tm->tm_wday); - } - - if (rtc_tm->tm_year <= 69) - rtc_tm->tm_year += 100; - - rtc_tm->tm_mon--; -} - -static int cmos_set_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned char mon, day, hrs, min, sec; - unsigned char save_control, save_freq_select; - unsigned int yrs; - - yrs = rtc_tm->tm_year; - mon = rtc_tm->tm_mon + 1; - day = rtc_tm->tm_mday; - hrs = rtc_tm->tm_hour; - min = rtc_tm->tm_min; - sec = rtc_tm->tm_sec; - - if (yrs >= 100) - yrs -= 100; - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - BIN_TO_BCD(day); - BIN_TO_BCD(mon); - BIN_TO_BCD(yrs); - } - - save_control = CMOS_READ(RTC_CONTROL); - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - CMOS_WRITE(yrs, RTC_YEAR); - CMOS_WRITE(mon, RTC_MONTH); - CMOS_WRITE(day, RTC_DAY_OF_MONTH); - CMOS_WRITE(hrs, RTC_HOURS); - CMOS_WRITE(min, RTC_MINUTES); - CMOS_WRITE(sec, RTC_SECONDS); - - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return 0; -} -#endif /* CONFIG_PCI */ - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1363,18 +1242,11 @@ static struct mini_rtc_ops hypervisor_rtc_ops = { .set_rtc_time = hypervisor_set_rtc_time, }; -#ifdef CONFIG_PCI static struct mini_rtc_ops bq4802_rtc_ops = { .get_rtc_time = bq4802_get_rtc_time, .set_rtc_time = bq4802_set_rtc_time, }; -static struct mini_rtc_ops cmos_rtc_ops = { - .get_rtc_time = cmos_get_rtc_time, - .set_rtc_time = cmos_set_rtc_time, -}; -#endif /* CONFIG_PCI */ - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1501,12 +1373,8 @@ static int __init rtc_mini_init(void) mini_rtc_ops = &hypervisor_rtc_ops; else if (this_is_starfire) mini_rtc_ops = &starfire_rtc_ops; -#ifdef CONFIG_PCI else if (bq4802_regs) mini_rtc_ops = &bq4802_rtc_ops; - else if (ds1287_regs) - mini_rtc_ops = &cmos_rtc_ops; -#endif /* CONFIG_PCI */ else return -ENODEV; -- cgit v1.2.3 From 29b503f11cd648b3628be3a546f97da95a6670ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 21:54:34 -0700 Subject: sparc64: Use generic BQ4802 RTC driver. Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 1 + arch/sparc64/kernel/time.c | 201 +++------------------------------------------ 2 files changed, 12 insertions(+), 190 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index e0d783bbae0..a4ec899faa4 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -22,6 +22,7 @@ config SPARC64 select RTC_CLASS select RTC_DRV_M48T59 select RTC_DRV_CMOS + select RTC_DRV_BQ4802 config GENERIC_TIME bool diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index abdeead4e5b..5e199a0e437 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -52,9 +52,6 @@ #include "entry.h" DEFINE_SPINLOCK(rtc_lock); -static void __iomem *bq4802_regs; - -static int set_rtc_mmss(unsigned long); #define TICK_PRIV_BIT (1UL << 63) #define TICKCMP_IRQ_BIT (1UL << 63) @@ -403,50 +400,7 @@ int update_persistent_clock(struct timespec now) if (rtc) return rtc_set_mmss(rtc, now.tv_sec); - return set_rtc_mmss(now.tv_sec); -} - -/* Probe for the real time clock chip. */ -static void __init set_system_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - void __iomem *bregs = bq4802_regs; - unsigned char val = readb(bregs + 0x0e); - unsigned int century; - - if (!bregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - /* BQ4802 RTC chip. */ - - writeb(val | 0x08, bregs + 0x0e); - - sec = readb(bregs + 0x00); - min = readb(bregs + 0x02); - hour = readb(bregs + 0x04); - day = readb(bregs + 0x06); - mon = readb(bregs + 0x09); - year = readb(bregs + 0x0a); - century = readb(bregs + 0x0f); - - writeb(val, bregs + 0x0e); - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - BCD_TO_BIN(century); - - year += (century * 100); - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); + return -1; } /* davem suggests we keep this within the 4M locked kernel image */ @@ -575,24 +529,20 @@ static struct of_platform_driver rtc_driver = { }, }; +static struct platform_device rtc_bq4802_device = { + .name = "rtc-bq4802", + .id = -1, + .num_resources = 1, +}; + static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) { - struct device_node *dp = op->node; - unsigned long flags; - - bq4802_regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "bq4802"); - if (!bq4802_regs) - return -ENOMEM; - - printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, bq4802_regs); - local_irq_save(flags); - - set_system_time(); - - local_irq_restore(flags); + printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n", + op->node->full_name, op->resource[0].start); - return 0; + rtc_bq4802_device.resource = &op->resource[0]; + return platform_device_register(&rtc_bq4802_device); } static struct of_device_id bq4802_match[] = { @@ -984,56 +934,6 @@ unsigned long long sched_clock(void) >> SPARC64_NSEC_PER_CYC_SHIFT; } -static int set_rtc_mmss(unsigned long nowtime) -{ - int real_seconds, real_minutes, chip_minutes; - void __iomem *bregs = bq4802_regs; - unsigned long flags; - unsigned char val; - int retval = 0; - - /* - * Not having a register set can lead to trouble. - * Also starfire doesn't have a tod clock. - */ - if (!bregs) - return -1; - - spin_lock_irqsave(&rtc_lock, flags); - - val = readb(bregs + 0x0e); - - /* BQ4802 RTC chip. */ - - writeb(val | 0x08, bregs + 0x0e); - - chip_minutes = readb(bregs + 0x02); - BCD_TO_BIN(chip_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - writeb(real_seconds, bregs + 0x00); - writeb(real_minutes, bregs + 0x02); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - chip_minutes, real_minutes); - retval = -1; - } - - writeb(val, bregs + 0x0e); - - spin_unlock_irqrestore(&rtc_lock, flags); - - return retval; -} - #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ static unsigned char mini_rtc_status; /* bitmapped status byte. */ @@ -1155,78 +1055,6 @@ static int hypervisor_set_rtc_time(struct rtc_time *time) return hypervisor_set_time(seconds); } -static void bq4802_get_rtc_time(struct rtc_time *time) -{ - unsigned char val = readb(bq4802_regs + 0x0e); - unsigned int century; - - writeb(val | 0x08, bq4802_regs + 0x0e); - - time->tm_sec = readb(bq4802_regs + 0x00); - time->tm_min = readb(bq4802_regs + 0x02); - time->tm_hour = readb(bq4802_regs + 0x04); - time->tm_mday = readb(bq4802_regs + 0x06); - time->tm_mon = readb(bq4802_regs + 0x09); - time->tm_year = readb(bq4802_regs + 0x0a); - time->tm_wday = readb(bq4802_regs + 0x08); - century = readb(bq4802_regs + 0x0f); - - writeb(val, bq4802_regs + 0x0e); - - BCD_TO_BIN(time->tm_sec); - BCD_TO_BIN(time->tm_min); - BCD_TO_BIN(time->tm_hour); - BCD_TO_BIN(time->tm_mday); - BCD_TO_BIN(time->tm_mon); - BCD_TO_BIN(time->tm_year); - BCD_TO_BIN(time->tm_wday); - BCD_TO_BIN(century); - - time->tm_year += (century * 100); - time->tm_year -= 1900; - - time->tm_mon--; -} - -static int bq4802_set_rtc_time(struct rtc_time *time) -{ - unsigned char val = readb(bq4802_regs + 0x0e); - unsigned char sec, min, hrs, day, mon, yrs, century; - unsigned int year; - - year = time->tm_year + 1900; - century = year / 100; - yrs = year % 100; - - mon = time->tm_mon + 1; /* tm_mon starts at zero */ - day = time->tm_mday; - hrs = time->tm_hour; - min = time->tm_min; - sec = time->tm_sec; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - BIN_TO_BCD(day); - BIN_TO_BCD(mon); - BIN_TO_BCD(yrs); - BIN_TO_BCD(century); - - writeb(val | 0x08, bq4802_regs + 0x0e); - - writeb(sec, bq4802_regs + 0x00); - writeb(min, bq4802_regs + 0x02); - writeb(hrs, bq4802_regs + 0x04); - writeb(day, bq4802_regs + 0x06); - writeb(mon, bq4802_regs + 0x09); - writeb(yrs, bq4802_regs + 0x0a); - writeb(century, bq4802_regs + 0x0f); - - writeb(val, bq4802_regs + 0x0e); - - return 0; -} - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1242,11 +1070,6 @@ static struct mini_rtc_ops hypervisor_rtc_ops = { .set_rtc_time = hypervisor_set_rtc_time, }; -static struct mini_rtc_ops bq4802_rtc_ops = { - .get_rtc_time = bq4802_get_rtc_time, - .set_rtc_time = bq4802_set_rtc_time, -}; - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1373,8 +1196,6 @@ static int __init rtc_mini_init(void) mini_rtc_ops = &hypervisor_rtc_ops; else if (this_is_starfire) mini_rtc_ops = &starfire_rtc_ops; - else if (bq4802_regs) - mini_rtc_ops = &bq4802_rtc_ops; else return -ENODEV; -- cgit v1.2.3 From 84d6bd5ef79a6ccc21af97b870f6ef94fbc9b11e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 01:34:27 -0700 Subject: sparc64: Use generic sun4v RTC driver. Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 1 + arch/sparc64/kernel/time.c | 83 +++++----------------------------------------- 2 files changed, 9 insertions(+), 75 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index a4ec899faa4..16149ce8a41 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -23,6 +23,7 @@ config SPARC64 select RTC_DRV_M48T59 select RTC_DRV_CMOS select RTC_DRV_BQ4802 + select RTC_DRV_SUN4V config GENERIC_TIME bool diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 5e199a0e437..15d16dbca1d 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -424,48 +424,6 @@ static int starfire_set_time(u32 val) return 0; } -static u32 hypervisor_get_time(void) -{ - unsigned long ret, time; - int retries = 10000; - -retry: - ret = sun4v_tod_get(&time); - if (ret == HV_EOK) - return time; - if (ret == HV_EWOULDBLOCK) { - if (--retries > 0) { - udelay(100); - goto retry; - } - printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); - return 0; - } - printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); - return 0; -} - -static int hypervisor_set_time(u32 secs) -{ - unsigned long ret; - int retries = 10000; - -retry: - ret = sun4v_tod_set(secs); - if (ret == HV_EOK) - return 0; - if (ret == HV_EWOULDBLOCK) { - if (--retries > 0) { - udelay(100); - goto retry; - } - printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); - return -EAGAIN; - } - printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); - return -EOPNOTSUPP; -} - unsigned long cmos_regs; EXPORT_SYMBOL(cmos_regs); @@ -644,6 +602,11 @@ static struct of_platform_driver mostek_driver = { }, }; +static struct platform_device rtc_sun4v_device = { + .name = "rtc-sun4v", + .id = -1, +}; + static int __init clock_init(void) { if (this_is_starfire) { @@ -653,13 +616,8 @@ static int __init clock_init(void) -xtime.tv_sec, -xtime.tv_nsec); return 0; } - if (tlb_type == hypervisor) { - xtime.tv_sec = hypervisor_get_time(); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - return 0; - } + if (tlb_type == hypervisor) + return platform_device_register(&rtc_sun4v_device); (void) of_register_driver(&rtc_driver, &of_platform_bus_type); (void) of_register_driver(&mostek_driver, &of_platform_bus_type); @@ -1037,24 +995,6 @@ static int starfire_set_rtc_time(struct rtc_time *time) return starfire_set_time(seconds); } -static void hypervisor_get_rtc_time(struct rtc_time *time) -{ - u32 seconds = hypervisor_get_time(); - - to_tm(seconds, time); - time->tm_year -= 1900; - time->tm_mon -= 1; -} - -static int hypervisor_set_rtc_time(struct rtc_time *time) -{ - u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, - time->tm_mday, time->tm_hour, - time->tm_min, time->tm_sec); - - return hypervisor_set_time(seconds); -} - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1065,11 +1005,6 @@ static struct mini_rtc_ops starfire_rtc_ops = { .set_rtc_time = starfire_set_rtc_time, }; -static struct mini_rtc_ops hypervisor_rtc_ops = { - .get_rtc_time = hypervisor_get_rtc_time, - .set_rtc_time = hypervisor_set_rtc_time, -}; - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1192,9 +1127,7 @@ static int __init rtc_mini_init(void) { int retval; - if (tlb_type == hypervisor) - mini_rtc_ops = &hypervisor_rtc_ops; - else if (this_is_starfire) + if (this_is_starfire) mini_rtc_ops = &starfire_rtc_ops; else return -ENODEV; -- cgit v1.2.3 From f2be6de88d247cd57010944f62267b53c47d5ae3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 01:35:19 -0700 Subject: sparc64: Use generic starfire RTC driver. Also, delete the mini RTC driver, no longer used. Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 1 + arch/sparc64/kernel/time.c | 293 ++------------------------------------------- 2 files changed, 9 insertions(+), 285 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 16149ce8a41..4a90809b40f 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -24,6 +24,7 @@ config SPARC64 select RTC_DRV_CMOS select RTC_DRV_BQ4802 select RTC_DRV_SUN4V + select RTC_DRV_STARFIRE config GENERIC_TIME bool diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 15d16dbca1d..ea05038a8c1 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -403,27 +403,6 @@ int update_persistent_clock(struct timespec now) return -1; } -/* davem suggests we keep this within the 4M locked kernel image */ -static u32 starfire_get_time(void) -{ - static char obp_gettod[32]; - static u32 unix_tod; - - sprintf(obp_gettod, "h# %08x unix-gettod", - (unsigned int) (long) &unix_tod); - prom_feval(obp_gettod); - - return unix_tod; -} - -static int starfire_set_time(u32 val) -{ - /* Do nothing, time is set using the service processor - * console on this platform. - */ - return 0; -} - unsigned long cmos_regs; EXPORT_SYMBOL(cmos_regs); @@ -607,15 +586,16 @@ static struct platform_device rtc_sun4v_device = { .id = -1, }; +static struct platform_device rtc_starfire_device = { + .name = "rtc-starfire", + .id = -1, +}; + static int __init clock_init(void) { - if (this_is_starfire) { - xtime.tv_sec = starfire_get_time(); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - return 0; - } + if (this_is_starfire) + return platform_device_register(&rtc_starfire_device); + if (tlb_type == hypervisor) return platform_device_register(&rtc_sun4v_device); @@ -892,265 +872,8 @@ unsigned long long sched_clock(void) >> SPARC64_NSEC_PER_CYC_SHIFT; } -#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ -static unsigned char mini_rtc_status; /* bitmapped status byte. */ - -#define FEBRUARY 2 -#define STARTOFTIME 1970 -#define SECDAY 86400L -#define SECYR (SECDAY * 365) -#define leapyear(year) ((year) % 4 == 0 && \ - ((year) % 100 != 0 || (year) % 400 == 0)) -#define days_in_year(a) (leapyear(a) ? 366 : 365) -#define days_in_month(a) (month_days[(a) - 1]) - -static int month_days[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -/* - * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) - */ -static void GregorianDay(struct rtc_time * tm) -{ - int leapsToDate; - int lastYear; - int day; - int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - - lastYear = tm->tm_year - 1; - - /* - * Number of leap corrections to apply up to end of last year - */ - leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400; - - /* - * This year is a leap year if it is divisible by 4 except when it is - * divisible by 100 unless it is divisible by 400 - * - * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was - */ - day = tm->tm_mon > 2 && leapyear(tm->tm_year); - - day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + - tm->tm_mday; - - tm->tm_wday = day % 7; -} - -static void to_tm(int tim, struct rtc_time *tm) -{ - register int i; - register long hms, day; - - day = tim / SECDAY; - hms = tim % SECDAY; - - /* Hours, minutes, seconds are easy */ - tm->tm_hour = hms / 3600; - tm->tm_min = (hms % 3600) / 60; - tm->tm_sec = (hms % 3600) % 60; - - /* Number of years in days */ - for (i = STARTOFTIME; day >= days_in_year(i); i++) - day -= days_in_year(i); - tm->tm_year = i; - - /* Number of months in days left */ - if (leapyear(tm->tm_year)) - days_in_month(FEBRUARY) = 29; - for (i = 1; day >= days_in_month(i); i++) - day -= days_in_month(i); - days_in_month(FEBRUARY) = 28; - tm->tm_mon = i; - - /* Days are what is left over (+1) from all that. */ - tm->tm_mday = day + 1; - - /* - * Determine the day of week - */ - GregorianDay(tm); -} - -/* Both Starfire and SUN4V give us seconds since Jan 1st, 1970, - * aka Unix time. So we have to convert to/from rtc_time. - */ -static void starfire_get_rtc_time(struct rtc_time *time) -{ - u32 seconds = starfire_get_time(); - - to_tm(seconds, time); - time->tm_year -= 1900; - time->tm_mon -= 1; -} - -static int starfire_set_rtc_time(struct rtc_time *time) -{ - u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, - time->tm_mday, time->tm_hour, - time->tm_min, time->tm_sec); - - return starfire_set_time(seconds); -} - -struct mini_rtc_ops { - void (*get_rtc_time)(struct rtc_time *); - int (*set_rtc_time)(struct rtc_time *); -}; - -static struct mini_rtc_ops starfire_rtc_ops = { - .get_rtc_time = starfire_get_rtc_time, - .set_rtc_time = starfire_set_rtc_time, -}; - -static struct mini_rtc_ops *mini_rtc_ops; - -static inline void mini_get_rtc_time(struct rtc_time *time) -{ - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - mini_rtc_ops->get_rtc_time(time); - spin_unlock_irqrestore(&rtc_lock, flags); -} - -static inline int mini_set_rtc_time(struct rtc_time *time) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&rtc_lock, flags); - err = mini_rtc_ops->set_rtc_time(time); - spin_unlock_irqrestore(&rtc_lock, flags); - - return err; -} - -static int mini_rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct rtc_time wtime; - void __user *argp = (void __user *)arg; - - switch (cmd) { - - case RTC_PLL_GET: - return -EINVAL; - - case RTC_PLL_SET: - return -EINVAL; - - case RTC_UIE_OFF: /* disable ints from RTC updates. */ - return 0; - - case RTC_UIE_ON: /* enable ints for RTC updates. */ - return -EINVAL; - - case RTC_RD_TIME: /* Read the time/date from RTC */ - /* this doesn't get week-day, who cares */ - memset(&wtime, 0, sizeof(wtime)); - mini_get_rtc_time(&wtime); - - return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0; - - case RTC_SET_TIME: /* Set the RTC */ - { - int year, days; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&wtime, argp, sizeof(wtime))) - return -EFAULT; - - year = wtime.tm_year + 1900; - days = month_days[wtime.tm_mon] + - ((wtime.tm_mon == 1) && leapyear(year)); - - if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || - (wtime.tm_mday < 1)) - return -EINVAL; - - if (wtime.tm_mday < 0 || wtime.tm_mday > days) - return -EINVAL; - - if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || - wtime.tm_min < 0 || wtime.tm_min >= 60 || - wtime.tm_sec < 0 || wtime.tm_sec >= 60) - return -EINVAL; - - return mini_set_rtc_time(&wtime); - } - } - - return -EINVAL; -} - -static int mini_rtc_open(struct inode *inode, struct file *file) -{ - lock_kernel(); - if (mini_rtc_status & RTC_IS_OPEN) { - unlock_kernel(); - return -EBUSY; - } - - mini_rtc_status |= RTC_IS_OPEN; - unlock_kernel(); - - return 0; -} - -static int mini_rtc_release(struct inode *inode, struct file *file) -{ - mini_rtc_status &= ~RTC_IS_OPEN; - return 0; -} - - -static const struct file_operations mini_rtc_fops = { - .owner = THIS_MODULE, - .ioctl = mini_rtc_ioctl, - .open = mini_rtc_open, - .release = mini_rtc_release, -}; - -static struct miscdevice rtc_mini_dev = -{ - .minor = RTC_MINOR, - .name = "rtc", - .fops = &mini_rtc_fops, -}; - -static int __init rtc_mini_init(void) -{ - int retval; - - if (this_is_starfire) - mini_rtc_ops = &starfire_rtc_ops; - else - return -ENODEV; - - printk(KERN_INFO "Mini RTC Driver\n"); - - retval = misc_register(&rtc_mini_dev); - if (retval < 0) - return retval; - - return 0; -} - -static void __exit rtc_mini_exit(void) -{ - misc_deregister(&rtc_mini_dev); -} - int __devinit read_current_timer(unsigned long *timer_val) { *timer_val = tick_ops->get_tick(); return 0; } - -module_init(rtc_mini_init); -module_exit(rtc_mini_exit); -- cgit v1.2.3 From ae05f87ee2f403228bca6d28fef29d6be0bfbedc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 22:42:34 -0700 Subject: sparc64: Propagate PCI device archdata into OF device tree for EBUS. In order to convert EBUS drivers doing DMA into pure OF drivers, we need the of_device->dev.archdata setup properly. EBUS instances that can provide DMA for device nodes sit on PCI, so detect and propagate the information there. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 9bb4b8cbcac..71d423a1c17 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -337,6 +337,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, struct pci_bus *bus, int devfn) { struct dev_archdata *sd; + struct of_device *op; struct pci_dev *dev; const char *type; u32 class; @@ -350,14 +351,17 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, sd->stc = &pbm->stc; sd->host_controller = pbm; sd->prom_node = node; - sd->op = of_find_device_by_node(node); + sd->op = op = of_find_device_by_node(node); sd->numa_node = pbm->numa_node; - sd = &sd->op->dev.archdata; + sd = &op->dev.archdata; sd->iommu = pbm->iommu; sd->stc = &pbm->stc; sd->numa_node = pbm->numa_node; + if (!strcmp(node->name, "ebus")) + of_propagate_archdata(op); + type = of_get_property(node, "device_type", NULL); if (type == NULL) type = ""; -- cgit v1.2.3 From aae7fb87ec4d2df6cb551670b1765cf4e5795a3b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 23:10:21 -0700 Subject: sparc: Move EBUS DMA interfaces into seperate header file. These have no dependencies on the EBUS probing layer, the clients setup the registers and all of those details. The EBUS DMA layer just programs and manages the DMA controller found in EBUS. Signed-off-by: David S. Miller --- arch/sparc/include/asm/ebus_64.h | 31 ------------------------------- arch/sparc/include/asm/ebus_dma.h | 35 +++++++++++++++++++++++++++++++++++ arch/sparc/include/asm/floppy_64.h | 1 + arch/sparc/include/asm/parport.h | 2 +- arch/sparc64/kernel/ebus.c | 1 + 5 files changed, 38 insertions(+), 32 deletions(-) create mode 100644 arch/sparc/include/asm/ebus_dma.h (limited to 'arch') diff --git a/arch/sparc/include/asm/ebus_64.h b/arch/sparc/include/asm/ebus_64.h index 14c6a111f60..cd102b8e28d 100644 --- a/arch/sparc/include/asm/ebus_64.h +++ b/arch/sparc/include/asm/ebus_64.h @@ -48,37 +48,6 @@ struct linux_ebus { }; #define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) -struct ebus_dma_info { - spinlock_t lock; - void __iomem *regs; - - unsigned int flags; -#define EBUS_DMA_FLAG_USE_EBDMA_HANDLER 0x00000001 -#define EBUS_DMA_FLAG_TCI_DISABLE 0x00000002 - - /* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is - * set. - */ - void (*callback)(struct ebus_dma_info *p, int event, void *cookie); - void *client_cookie; - unsigned int irq; -#define EBUS_DMA_EVENT_ERROR 1 -#define EBUS_DMA_EVENT_DMA 2 -#define EBUS_DMA_EVENT_DEVICE 4 - - unsigned char name[64]; -}; - -extern int ebus_dma_register(struct ebus_dma_info *p); -extern int ebus_dma_irq_enable(struct ebus_dma_info *p, int on); -extern void ebus_dma_unregister(struct ebus_dma_info *p); -extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, - size_t len); -extern void ebus_dma_prepare(struct ebus_dma_info *p, int write); -extern unsigned int ebus_dma_residue(struct ebus_dma_info *p); -extern unsigned int ebus_dma_addr(struct ebus_dma_info *p); -extern void ebus_dma_enable(struct ebus_dma_info *p, int on); - extern struct linux_ebus *ebus_chain; extern void ebus_init(void); diff --git a/arch/sparc/include/asm/ebus_dma.h b/arch/sparc/include/asm/ebus_dma.h new file mode 100644 index 00000000000..f07a5b541c9 --- /dev/null +++ b/arch/sparc/include/asm/ebus_dma.h @@ -0,0 +1,35 @@ +#ifndef __ASM_SPARC_EBUS_DMA_H +#define __ASM_SPARC_EBUS_DMA_H + +struct ebus_dma_info { + spinlock_t lock; + void __iomem *regs; + + unsigned int flags; +#define EBUS_DMA_FLAG_USE_EBDMA_HANDLER 0x00000001 +#define EBUS_DMA_FLAG_TCI_DISABLE 0x00000002 + + /* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is + * set. + */ + void (*callback)(struct ebus_dma_info *p, int event, void *cookie); + void *client_cookie; + unsigned int irq; +#define EBUS_DMA_EVENT_ERROR 1 +#define EBUS_DMA_EVENT_DMA 2 +#define EBUS_DMA_EVENT_DEVICE 4 + + unsigned char name[64]; +}; + +extern int ebus_dma_register(struct ebus_dma_info *p); +extern int ebus_dma_irq_enable(struct ebus_dma_info *p, int on); +extern void ebus_dma_unregister(struct ebus_dma_info *p); +extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, + size_t len); +extern void ebus_dma_prepare(struct ebus_dma_info *p, int write); +extern unsigned int ebus_dma_residue(struct ebus_dma_info *p); +extern unsigned int ebus_dma_addr(struct ebus_dma_info *p); +extern void ebus_dma_enable(struct ebus_dma_info *p, int on); + +#endif /* __ASM_SPARC_EBUS_DMA_H */ diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index d8fb0602745..8c7a06e8824 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h @@ -294,6 +294,7 @@ static int sun_fd_eject(int drive) #ifdef CONFIG_PCI #include +#include #include static struct ebus_dma_info sun_pci_fd_ebus_dma; diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index d9830621c90..70dce0273f9 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h @@ -8,7 +8,7 @@ #include -#include +#include #include #include diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 214da1bd8a5..88408741c32 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 3ae627a19ef0d7b5521a070e309ac7ebe57638d3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 23:26:23 -0700 Subject: sparc64: Convert EBUS floppy support to pure OF driver. Signed-off-by: David S. Miller --- arch/sparc/include/asm/floppy_64.h | 86 ++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 50 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index 8c7a06e8824..36439d67ad7 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h @@ -9,19 +9,11 @@ #ifndef __ASM_SPARC64_FLOPPY_H #define __ASM_SPARC64_FLOPPY_H -#include -#include #include #include +#include -#include -#include -#include -#include -#include #include -#include - /* * Define this to enable exchanging drive 0 and 1 if only drive 1 is @@ -292,13 +284,11 @@ static int sun_fd_eject(int drive) return 0; } -#ifdef CONFIG_PCI -#include #include #include static struct ebus_dma_info sun_pci_fd_ebus_dma; -static struct pci_dev *sun_pci_ebus_dev; +static struct device *sun_floppy_dev; static int sun_pci_broken_drive = -1; struct sun_pci_dma_op { @@ -379,7 +369,7 @@ static void sun_pci_fd_enable_dma(void) sun_pci_dma_pending.addr = -1U; sun_pci_dma_current.addr = - pci_map_single(sun_pci_ebus_dev, + dma_map_single(sun_floppy_dev, sun_pci_dma_current.buf, sun_pci_dma_current.len, sun_pci_dma_current.direction); @@ -396,7 +386,7 @@ static void sun_pci_fd_disable_dma(void) { ebus_dma_enable(&sun_pci_fd_ebus_dma, 0); if (sun_pci_dma_current.addr != -1U) - pci_unmap_single(sun_pci_ebus_dev, + dma_unmap_single(sun_floppy_dev, sun_pci_dma_current.addr, sun_pci_dma_current.len, sun_pci_dma_current.direction); @@ -406,9 +396,9 @@ static void sun_pci_fd_disable_dma(void) static void sun_pci_fd_set_dma_mode(int mode) { if (mode == DMA_MODE_WRITE) - sun_pci_dma_pending.direction = PCI_DMA_TODEVICE; + sun_pci_dma_pending.direction = DMA_TO_DEVICE; else - sun_pci_dma_pending.direction = PCI_DMA_FROMDEVICE; + sun_pci_dma_pending.direction = DMA_FROM_DEVICE; ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE); } @@ -540,24 +530,19 @@ static int sun_pci_fd_test_drive(unsigned long port, int drive) #undef MSR #undef DOR -#endif /* CONFIG_PCI */ - -#ifdef CONFIG_PCI -static int __init ebus_fdthree_p(struct linux_ebus_device *edev) +static int __init ebus_fdthree_p(struct device_node *dp) { - if (!strcmp(edev->prom_node->name, "fdthree")) + if (!strcmp(dp->name, "fdthree")) return 1; - if (!strcmp(edev->prom_node->name, "floppy")) { + if (!strcmp(dp->name, "floppy")) { const char *compat; - compat = of_get_property(edev->prom_node, - "compatible", NULL); + compat = of_get_property(dp, "compatible", NULL); if (compat && !strcmp(compat, "fdthree")) return 1; } return 0; } -#endif static unsigned long __init sun_floppy_init(void) { @@ -584,44 +569,45 @@ static unsigned long __init sun_floppy_init(void) floppy_op = op; FLOPPY_IRQ = op->irqs[0]; } else { -#ifdef CONFIG_PCI - struct linux_ebus *ebus; - struct linux_ebus_device *edev = NULL; - unsigned long config = 0; + struct device_node *ebus_dp; void __iomem *auxio_reg; const char *state_prop; + unsigned long config; - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (ebus_fdthree_p(edev)) - goto ebus_done; + dp = NULL; + for_each_node_by_name(ebus_dp, "ebus") { + for (dp = ebus_dp->child; dp; dp = dp->sibling) { + if (ebus_fdthree_p(dp)) + goto found_fdthree; } } - ebus_done: - if (!edev) + found_fdthree: + if (!dp) return 0; - op = &edev->ofdev; + op = of_find_device_by_node(dp); + if (!op) + return 0; state_prop = of_get_property(op->node, "status", NULL); if (state_prop && !strncmp(state_prop, "disabled", 8)) return 0; - FLOPPY_IRQ = edev->irqs[0]; + FLOPPY_IRQ = op->irqs[0]; /* Make sure the high density bit is set, some systems * (most notably Ultra5/Ultra10) come up with it clear. */ - auxio_reg = (void __iomem *) edev->resource[2].start; + auxio_reg = (void __iomem *) op->resource[2].start; writel(readl(auxio_reg)|0x2, auxio_reg); - sun_pci_ebus_dev = ebus->self; + sun_floppy_dev = &op->dev; spin_lock_init(&sun_pci_fd_ebus_dma.lock); /* XXX ioremap */ sun_pci_fd_ebus_dma.regs = (void __iomem *) - edev->resource[1].start; + op->resource[1].start; if (!sun_pci_fd_ebus_dma.regs) return 0; @@ -635,7 +621,7 @@ static unsigned long __init sun_floppy_init(void) return 0; /* XXX ioremap */ - sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start; + sun_fdc = (struct sun_flpy_controller *) op->resource[0].start; sun_fdops.fd_inb = sun_pci_fd_inb; sun_fdops.fd_outb = sun_pci_fd_outb; @@ -672,12 +658,15 @@ static unsigned long __init sun_floppy_init(void) /* * Find NS87303 SuperIO config registers (through ecpp). */ - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "ecpp")) { - config = edev->resource[1].start; - goto config_done; - } + config = 0; + for (dp = ebus_dp->child; dp; dp = dp->sibling) { + if (!strcmp(dp->name, "ecpp")) { + struct of_device *ecpp_op; + + ecpp_op = of_find_device_by_node(dp); + if (ecpp_op) + config = ecpp_op->resource[1].start; + goto config_done; } } config_done: @@ -726,9 +715,6 @@ static unsigned long __init sun_floppy_init(void) #endif /* PCI_FDC_SWAP_DRIVES */ return sun_floppy_types[0]; -#else - return 0; -#endif } prop = of_get_property(op->node, "status", NULL); if (prop && !strncmp(state, "disabled", 8)) -- cgit v1.2.3 From 356d164757310cd822d71da2027d50ec39798b7f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 00:36:11 -0700 Subject: sparc: Kill EBUS driver layer. All that remains is the EBUS DMA programming library for sparc64. Signed-off-by: David S. Miller --- arch/sparc/include/asm/ebus.h | 8 - arch/sparc/include/asm/ebus_32.h | 99 --------- arch/sparc/include/asm/ebus_64.h | 64 ------ arch/sparc/kernel/Makefile | 1 - arch/sparc/kernel/ebus.c | 392 ------------------------------------ arch/sparc/kernel/pcic.c | 8 +- arch/sparc/kernel/sparc_ksyms.c | 4 - arch/sparc64/kernel/Makefile | 4 +- arch/sparc64/kernel/ebus.c | 295 +-------------------------- arch/sparc64/kernel/pci.c | 4 +- arch/sparc64/kernel/sparc64_ksyms.c | 4 - 11 files changed, 6 insertions(+), 877 deletions(-) delete mode 100644 arch/sparc/include/asm/ebus.h delete mode 100644 arch/sparc/include/asm/ebus_32.h delete mode 100644 arch/sparc/include/asm/ebus_64.h delete mode 100644 arch/sparc/kernel/ebus.c (limited to 'arch') diff --git a/arch/sparc/include/asm/ebus.h b/arch/sparc/include/asm/ebus.h deleted file mode 100644 index 83a6d16c22e..00000000000 --- a/arch/sparc/include/asm/ebus.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ___ASM_SPARC_EBUS_H -#define ___ASM_SPARC_EBUS_H -#if defined(__sparc__) && defined(__arch64__) -#include -#else -#include -#endif -#endif diff --git a/arch/sparc/include/asm/ebus_32.h b/arch/sparc/include/asm/ebus_32.h deleted file mode 100644 index f91f0b267ce..00000000000 --- a/arch/sparc/include/asm/ebus_32.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ebus.h: PCI to Ebus pseudo driver software state. - * - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * - * Adopted for sparc by V. Roganov and G. Raiko. - */ - -#ifndef __SPARC_EBUS_H -#define __SPARC_EBUS_H - -#ifndef _LINUX_IOPORT_H -#include -#endif -#include -#include -#include - -struct linux_ebus_child { - struct linux_ebus_child *next; - struct linux_ebus_device *parent; - struct linux_ebus *bus; - struct device_node *prom_node; - struct resource resource[PROMREG_MAX]; - int num_addrs; - unsigned int irqs[PROMINTR_MAX]; - int num_irqs; -}; - -struct linux_ebus_device { - struct of_device ofdev; - struct linux_ebus_device *next; - struct linux_ebus_child *children; - struct linux_ebus *bus; - struct device_node *prom_node; - struct resource resource[PROMREG_MAX]; - int num_addrs; - unsigned int irqs[PROMINTR_MAX]; - int num_irqs; -}; -#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev) - -struct linux_ebus { - struct of_device ofdev; - struct linux_ebus *next; - struct linux_ebus_device *devices; - struct linux_pbm_info *parent; - struct pci_dev *self; - struct device_node *prom_node; -}; -#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) - -struct linux_ebus_dma { - unsigned int dcsr; - unsigned int dacr; - unsigned int dbcr; -}; - -#define EBUS_DCSR_INT_PEND 0x00000001 -#define EBUS_DCSR_ERR_PEND 0x00000002 -#define EBUS_DCSR_DRAIN 0x00000004 -#define EBUS_DCSR_INT_EN 0x00000010 -#define EBUS_DCSR_RESET 0x00000080 -#define EBUS_DCSR_WRITE 0x00000100 -#define EBUS_DCSR_EN_DMA 0x00000200 -#define EBUS_DCSR_CYC_PEND 0x00000400 -#define EBUS_DCSR_DIAG_RD_DONE 0x00000800 -#define EBUS_DCSR_DIAG_WR_DONE 0x00001000 -#define EBUS_DCSR_EN_CNT 0x00002000 -#define EBUS_DCSR_TC 0x00004000 -#define EBUS_DCSR_DIS_CSR_DRN 0x00010000 -#define EBUS_DCSR_BURST_SZ_MASK 0x000c0000 -#define EBUS_DCSR_BURST_SZ_1 0x00080000 -#define EBUS_DCSR_BURST_SZ_4 0x00000000 -#define EBUS_DCSR_BURST_SZ_8 0x00040000 -#define EBUS_DCSR_BURST_SZ_16 0x000c0000 -#define EBUS_DCSR_DIAG_EN 0x00100000 -#define EBUS_DCSR_DIS_ERR_PEND 0x00400000 -#define EBUS_DCSR_TCI_DIS 0x00800000 -#define EBUS_DCSR_EN_NEXT 0x01000000 -#define EBUS_DCSR_DMA_ON 0x02000000 -#define EBUS_DCSR_A_LOADED 0x04000000 -#define EBUS_DCSR_NA_LOADED 0x08000000 -#define EBUS_DCSR_DEV_ID_MASK 0xf0000000 - -extern struct linux_ebus *ebus_chain; - -extern void ebus_init(void); - -#define for_each_ebus(bus) \ - for((bus) = ebus_chain; (bus); (bus) = (bus)->next) - -#define for_each_ebusdev(dev, bus) \ - for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) - -#define for_each_edevchild(dev, child) \ - for((child) = (dev)->children; (child); (child) = (child)->next) - -#endif /* !(__SPARC_EBUS_H) */ diff --git a/arch/sparc/include/asm/ebus_64.h b/arch/sparc/include/asm/ebus_64.h deleted file mode 100644 index cd102b8e28d..00000000000 --- a/arch/sparc/include/asm/ebus_64.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ebus.h: PCI to Ebus pseudo driver software state. - * - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#ifndef __SPARC64_EBUS_H -#define __SPARC64_EBUS_H - -#include - -#include -#include - -struct linux_ebus_child { - struct linux_ebus_child *next; - struct linux_ebus_device *parent; - struct linux_ebus *bus; - struct device_node *prom_node; - struct resource resource[PROMREG_MAX]; - int num_addrs; - unsigned int irqs[PROMINTR_MAX]; - int num_irqs; -}; - -struct linux_ebus_device { - struct of_device ofdev; - struct linux_ebus_device *next; - struct linux_ebus_child *children; - struct linux_ebus *bus; - struct device_node *prom_node; - struct resource resource[PROMREG_MAX]; - int num_addrs; - unsigned int irqs[PROMINTR_MAX]; - int num_irqs; -}; -#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev) - -struct linux_ebus { - struct of_device ofdev; - struct linux_ebus *next; - struct linux_ebus_device *devices; - struct pci_dev *self; - int index; - int is_rio; - struct device_node *prom_node; -}; -#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) - -extern struct linux_ebus *ebus_chain; - -extern void ebus_init(void); - -#define for_each_ebus(bus) \ - for((bus) = ebus_chain; (bus); (bus) = (bus)->next) - -#define for_each_ebusdev(dev, bus) \ - for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) - -#define for_each_edevchild(dev, child) \ - for((child) = (dev)->children; (child); (child) = (child)->next) - -#endif /* !(__SPARC64_EBUS_H) */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index eaf7cf4296a..a430231647e 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += pcic.o obj-$(CONFIG_SUN4) += sun4setup.o obj-$(CONFIG_SMP) += trampoline.o smp.o sun4m_smp.o sun4d_smp.o obj-$(CONFIG_SUN_AUXIO) += auxio.o -obj-$(CONFIG_PCI) += ebus.o obj-$(CONFIG_SUN_PM) += apc.o pmc.o obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o obj-$(CONFIG_SPARC_LED) += led.o diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c deleted file mode 100644 index 7e9397fc608..00000000000 --- a/arch/sparc/kernel/ebus.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * ebus.c: PCI to EBus bridge device. - * - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * - * Adopted for sparc by V. Roganov and G. Raiko. - * Fixes for different platforms by Pete Zaitcev. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -struct linux_ebus *ebus_chain = NULL; - -/* We are together with pcic.c under CONFIG_PCI. */ -extern unsigned int pcic_pin_to_irq(unsigned int, const char *name); - -/* - * IRQ Blacklist - * Here we list PROMs and systems that are known to supply crap as IRQ numbers. - */ -struct ebus_device_irq { - char *name; - unsigned int pin; -}; - -struct ebus_system_entry { - char *esname; - struct ebus_device_irq *ipt; -}; - -static struct ebus_device_irq je1_1[] = { - { "8042", 3 }, - { "SUNW,CS4231", 0 }, - { "parallel", 0 }, - { "se", 2 }, - { NULL, 0 } -}; - -/* - * Gleb's JE1 supplied reasonable pin numbers, but mine did not (OBP 2.32). - * Blacklist the sucker... Note that Gleb's system will work. - */ -static struct ebus_system_entry ebus_blacklist[] = { - { "SUNW,JavaEngine1", je1_1 }, - { NULL, NULL } -}; - -static struct ebus_device_irq *ebus_blackp = NULL; - -/* - */ -static inline unsigned long ebus_alloc(size_t size) -{ - return (unsigned long)kmalloc(size, GFP_ATOMIC); -} - -/* - */ -static int __init ebus_blacklist_irq(const char *name) -{ - struct ebus_device_irq *dp; - - if ((dp = ebus_blackp) != NULL) { - for (; dp->name != NULL; dp++) { - if (strcmp(name, dp->name) == 0) { - return pcic_pin_to_irq(dp->pin, name); - } - } - } - return 0; -} - -static void __init fill_ebus_child(struct device_node *dp, - struct linux_ebus_child *dev) -{ - const int *regs; - const int *irqs; - int i, len; - - dev->prom_node = dp; - regs = of_get_property(dp, "reg", &len); - if (!regs) - len = 0; - dev->num_addrs = len / sizeof(regs[0]); - - for (i = 0; i < dev->num_addrs; i++) { - if (regs[i] >= dev->parent->num_addrs) { - prom_printf("UGH: property for %s was %d, need < %d\n", - dev->prom_node->name, len, - dev->parent->num_addrs); - panic(__func__); - } - - /* XXX resource */ - dev->resource[i].start = - dev->parent->resource[regs[i]].start; - } - - for (i = 0; i < PROMINTR_MAX; i++) - dev->irqs[i] = PCI_IRQ_NONE; - - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { - dev->num_irqs = 1; - } else { - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { - dev->num_irqs = 0; - dev->irqs[0] = 0; - if (dev->parent->num_irqs != 0) { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[0]; - } - } else { - dev->num_irqs = len / sizeof(irqs[0]); - if (irqs[0] == 0 || irqs[0] >= 8) { - /* - * XXX Zero is a valid pin number... - * This works as long as Ebus is not wired - * to INTA#. - */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_node->name, irqs[0]); - dev->num_irqs = 0; - dev->irqs[0] = 0; - } else { - dev->irqs[0] = - pcic_pin_to_irq(irqs[0], - dev->prom_node->name); - } - } - } -} - -static void __init fill_ebus_device(struct device_node *dp, - struct linux_ebus_device *dev) -{ - const struct linux_prom_registers *regs; - struct linux_ebus_child *child; - struct dev_archdata *sd; - const int *irqs; - int i, n, len; - unsigned long baseaddr; - - dev->prom_node = dp; - - regs = of_get_property(dp, "reg", &len); - if (!regs) - len = 0; - if (len % sizeof(struct linux_prom_registers)) { - prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_node->name, len, - (int)sizeof(struct linux_prom_registers)); - panic(__func__); - } - dev->num_addrs = len / sizeof(struct linux_prom_registers); - - for (i = 0; i < dev->num_addrs; i++) { - /* - * XXX Collect JE-1 PROM - * - * Example - JS-E with 3.11: - * /ebus - * regs - * 0x00000000, 0x0, 0x00000000, 0x0, 0x00000000, - * 0x82000010, 0x0, 0xf0000000, 0x0, 0x01000000, - * 0x82000014, 0x0, 0x38800000, 0x0, 0x00800000, - * ranges - * 0x00, 0x00000000, 0x02000010, 0x0, 0x0, 0x01000000, - * 0x01, 0x01000000, 0x02000014, 0x0, 0x0, 0x00800000, - * /ebus/8042 - * regs - * 0x00000001, 0x00300060, 0x00000008, - * 0x00000001, 0x00300060, 0x00000008, - */ - n = regs[i].which_io; - if (n >= 4) { - /* XXX This is copied from old JE-1 by Gleb. */ - n = (regs[i].which_io - 0x10) >> 2; - } else { - ; - } - -/* - * XXX Now as we have regions, why don't we make an on-demand allocation... - */ - dev->resource[i].start = 0; - if ((baseaddr = dev->bus->self->resource[n].start + - regs[i].phys_addr) != 0) { - /* dev->resource[i].name = dev->prom_name; */ - if ((baseaddr = (unsigned long) ioremap(baseaddr, - regs[i].reg_size)) == 0) { - panic("ebus: unable to remap dev %s", - dev->prom_node->name); - } - } - dev->resource[i].start = baseaddr; /* XXX Unaligned */ - } - - for (i = 0; i < PROMINTR_MAX; i++) - dev->irqs[i] = PCI_IRQ_NONE; - - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { - dev->num_irqs = 1; - } else { - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { - dev->num_irqs = 0; - if ((dev->irqs[0] = dev->bus->self->irq) != 0) { - dev->num_irqs = 1; -/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ - } - } else { - dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ - if (irqs[0] == 0 || irqs[0] >= 8) { - /* See above for the parent. XXX */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_node->name, irqs[0]); - dev->num_irqs = 0; - dev->irqs[0] = 0; - } else { - dev->irqs[0] = - pcic_pin_to_irq(irqs[0], - dev->prom_node->name); - } - } - } - - sd = &dev->ofdev.dev.archdata; - sd->prom_node = dp; - sd->op = &dev->ofdev; - sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; - - dev->ofdev.node = dp; - dev->ofdev.dev.parent = &dev->bus->ofdev.dev; - dev->ofdev.dev.bus = &ebus_bus_type; - sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node); - - /* Register with core */ - if (of_device_register(&dev->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - if ((dp = dp->child) != NULL) { - dev->children = (struct linux_ebus_child *) - ebus_alloc(sizeof(struct linux_ebus_child)); - - child = dev->children; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child); - - while ((dp = dp->sibling) != NULL) { - child->next = (struct linux_ebus_child *) - ebus_alloc(sizeof(struct linux_ebus_child)); - - child = child->next; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child); - } - } -} - -void __init ebus_init(void) -{ - const struct linux_prom_pci_registers *regs; - struct linux_pbm_info *pbm; - struct linux_ebus_device *dev; - struct linux_ebus *ebus; - struct ebus_system_entry *sp; - struct pci_dev *pdev; - struct pcidev_cookie *cookie; - struct device_node *dp; - struct resource *p; - unsigned short pci_command; - int len, reg, nreg; - int num_ebus = 0; - - dp = of_find_node_by_path("/"); - for (sp = ebus_blacklist; sp->esname != NULL; sp++) { - if (strcmp(dp->name, sp->esname) == 0) { - ebus_blackp = sp->ipt; - break; - } - } - - pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL); - if (!pdev) - return; - - cookie = pdev->sysdata; - dp = cookie->prom_node; - - ebus_chain = ebus = (struct linux_ebus *) - ebus_alloc(sizeof(struct linux_ebus)); - ebus->next = NULL; - - while (dp) { - struct device_node *nd; - - ebus->prom_node = dp; - ebus->self = pdev; - ebus->parent = pbm = cookie->pbm; - - /* Enable BUS Master. */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - pci_command |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, pci_command); - - regs = of_get_property(dp, "reg", &len); - if (!regs) { - prom_printf("%s: can't find reg property\n", - __func__); - prom_halt(); - } - nreg = len / sizeof(struct linux_prom_pci_registers); - - p = &ebus->self->resource[0]; - for (reg = 0; reg < nreg; reg++) { - if (!(regs[reg].which_io & 0x03000000)) - continue; - - (p++)->start = regs[reg].phys_lo; - } - - ebus->ofdev.node = dp; - ebus->ofdev.dev.parent = &pdev->dev; - ebus->ofdev.dev.bus = &ebus_bus_type; - sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus); - - /* Register with core */ - if (of_device_register(&ebus->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - - nd = dp->child; - if (!nd) - goto next_ebus; - - ebus->devices = (struct linux_ebus_device *) - ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = ebus->devices; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(nd, dev); - - while ((nd = nd->sibling) != NULL) { - dev->next = (struct linux_ebus_device *) - ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = dev->next; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(nd, dev); - } - - next_ebus: - pdev = pci_get_device(PCI_VENDOR_ID_SUN, - PCI_DEVICE_ID_SUN_EBUS, pdev); - if (!pdev) - break; - - cookie = pdev->sysdata; - dp = cookie->prom_node; - - ebus->next = (struct linux_ebus *) - ebus_alloc(sizeof(struct linux_ebus)); - ebus = ebus->next; - ebus->next = NULL; - ++num_ebus; - } - if (pdev) - pci_dev_put(pdev); -} diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 9a0aa4ec579..e5950b03df1 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -17,7 +17,6 @@ #include #include -#include #include /* for cache flushing. */ #include @@ -429,7 +428,6 @@ static int __init pcic_init(void) pcic_pbm_scan_bus(pcic); - ebus_init(); return 0; } @@ -492,10 +490,6 @@ static void pcic_map_pci_device(struct linux_pcic *pcic, * do ioremap() before accessing PC-style I/O, * we supply virtual, ready to access address. * - * Ebus devices do not come here even if - * CheerIO makes a similar conversion. - * See ebus.c for details. - * * Note that request_region() * works for these devices. * @@ -676,7 +670,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) } /* - * pcic_pin_to_irq() is exported to ebus.c. + * pcic_pin_to_irq() is exported to bus probing code */ unsigned int pcic_pin_to_irq(unsigned int pin, const char *name) diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 50ec48ddef6..6007ac5a736 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -45,9 +45,6 @@ #ifdef CONFIG_SBUS #include #endif -#ifdef CONFIG_PCI -#include -#endif #include #include @@ -152,7 +149,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); EXPORT_SYMBOL(sbus_set_sbus64); #endif #ifdef CONFIG_PCI -EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(insb); EXPORT_SYMBOL(outsb); EXPORT_SYMBOL(insw); diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 360a348e5bb..928aa7c8058 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -11,12 +11,12 @@ obj-y := process.o setup.o cpu.o idprom.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o starfire.o \ - power.o sbus.o sparc64_ksyms.o \ + power.o sbus.o sparc64_ksyms.o ebus.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += ebus.o pci.o pci_common.o \ +obj-$(CONFIG_PCI) += pci.o pci_common.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 88408741c32..77dbf6d45fa 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -1,5 +1,4 @@ -/* - * ebus.c: PCI to EBus bridge device. +/* ebus.c: EBUS DMA library code. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -9,24 +8,12 @@ #include #include #include -#include -#include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -/* EBUS dma library. */ - #define EBDMA_CSR 0x00UL /* Control/Status */ #define EBDMA_ADDR 0x04UL /* DMA Address */ #define EBDMA_COUNT 0x08UL /* DMA Count */ @@ -268,283 +255,3 @@ void ebus_dma_enable(struct ebus_dma_info *p, int on) spin_unlock_irqrestore(&p->lock, flags); } EXPORT_SYMBOL(ebus_dma_enable); - -struct linux_ebus *ebus_chain = NULL; - -static inline void *ebus_alloc(size_t size) -{ - void *mem; - - mem = kzalloc(size, GFP_ATOMIC); - if (!mem) - panic("ebus_alloc: out of memory"); - return mem; -} - -static void __init fill_ebus_child(struct device_node *dp, - struct linux_ebus_child *dev, - int non_standard_regs) -{ - struct of_device *op; - const int *regs; - int i, len; - - dev->prom_node = dp; - printk(" (%s)", dp->name); - - regs = of_get_property(dp, "reg", &len); - if (!regs) - dev->num_addrs = 0; - else - dev->num_addrs = len / sizeof(regs[0]); - - if (non_standard_regs) { - /* This is to handle reg properties which are not - * in the parent relative format. One example are - * children of the i2c device on CompactPCI systems. - * - * So, for such devices we just record the property - * raw in the child resources. - */ - for (i = 0; i < dev->num_addrs; i++) - dev->resource[i].start = regs[i]; - } else { - for (i = 0; i < dev->num_addrs; i++) { - int rnum = regs[i]; - if (rnum >= dev->parent->num_addrs) { - prom_printf("UGH: property for %s was %d, need < %d\n", - dp->name, len, dev->parent->num_addrs); - prom_halt(); - } - dev->resource[i].start = dev->parent->resource[i].start; - dev->resource[i].end = dev->parent->resource[i].end; - dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dp->name; - } - } - - op = of_find_device_by_node(dp); - if (!op) { - dev->num_irqs = 0; - } else { - dev->num_irqs = op->num_irqs; - for (i = 0; i < dev->num_irqs; i++) - dev->irqs[i] = op->irqs[i]; - } - - if (!dev->num_irqs) { - /* - * Oh, well, some PROMs don't export interrupts - * property to children of EBus devices... - * - * Be smart about PS/2 keyboard and mouse. - */ - if (!strcmp(dev->parent->prom_node->name, "8042")) { - if (!strcmp(dev->prom_node->name, "kb_ps2")) { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[0]; - } else { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[1]; - } - } - } -} - -static int __init child_regs_nonstandard(struct linux_ebus_device *dev) -{ - if (!strcmp(dev->prom_node->name, "i2c") || - !strcmp(dev->prom_node->name, "SUNW,lombus")) - return 1; - return 0; -} - -static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) -{ - struct linux_ebus_child *child; - struct dev_archdata *sd; - struct of_device *op; - int i, len; - - dev->prom_node = dp; - - printk(" [%s", dp->name); - - op = of_find_device_by_node(dp); - if (!op) { - dev->num_addrs = 0; - dev->num_irqs = 0; - } else { - const int *regs = of_get_property(dp, "reg", &len); - - if (!regs) - len = 0; - dev->num_addrs = len / sizeof(struct linux_prom_registers); - - for (i = 0; i < dev->num_addrs; i++) - memcpy(&dev->resource[i], - &op->resource[i], - sizeof(struct resource)); - - dev->num_irqs = op->num_irqs; - for (i = 0; i < dev->num_irqs; i++) - dev->irqs[i] = op->irqs[i]; - } - - sd = &dev->ofdev.dev.archdata; - sd->prom_node = dp; - sd->op = &dev->ofdev; - sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; - sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; - sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node; - - dev->ofdev.node = dp; - dev->ofdev.dev.parent = &dev->bus->ofdev.dev; - dev->ofdev.dev.bus = &ebus_bus_type; - dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node); - - /* Register with core */ - if (of_device_register(&dev->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - dp = dp->child; - if (dp) { - printk(" ->"); - dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); - - child = dev->children; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child, - child_regs_nonstandard(dev)); - - while ((dp = dp->sibling) != NULL) { - child->next = ebus_alloc(sizeof(struct linux_ebus_child)); - - child = child->next; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child, - child_regs_nonstandard(dev)); - } - } - printk("]"); -} - -static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) -{ - struct pci_dev *pdev = start; - - while ((pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev))) - if (pdev->device == PCI_DEVICE_ID_SUN_EBUS || - pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS) - break; - - *is_rio_p = !!(pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS)); - - return pdev; -} - -void __init ebus_init(void) -{ - struct linux_ebus_device *dev; - struct linux_ebus *ebus; - struct pci_dev *pdev; - struct device_node *dp; - int is_rio; - int num_ebus = 0; - - pdev = find_next_ebus(NULL, &is_rio); - if (!pdev) { - printk("ebus: No EBus's found.\n"); - return; - } - - dp = pci_device_to_OF_node(pdev); - - ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); - ebus->next = NULL; - ebus->is_rio = is_rio; - - while (dp) { - struct device_node *child; - - /* SUNW,pci-qfe uses four empty ebuses on it. - I think we should not consider them here, - as they have half of the properties this - code expects and once we do PCI hot-plug, - we'd have to tweak with the ebus_chain - in the runtime after initialization. -jj */ - if (!dp->child) { - pdev = find_next_ebus(pdev, &is_rio); - if (!pdev) { - if (ebus == ebus_chain) { - ebus_chain = NULL; - printk("ebus: No EBus's found.\n"); - return; - } - break; - } - ebus->is_rio = is_rio; - dp = pci_device_to_OF_node(pdev); - continue; - } - printk("ebus%d:", num_ebus); - - ebus->index = num_ebus; - ebus->prom_node = dp; - ebus->self = pdev; - - ebus->ofdev.node = dp; - ebus->ofdev.dev.parent = &pdev->dev; - ebus->ofdev.dev.bus = &ebus_bus_type; - dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus); - - /* Register with core */ - if (of_device_register(&ebus->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - - child = dp->child; - if (!child) - goto next_ebus; - - ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = ebus->devices; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(child, dev); - - while ((child = child->sibling) != NULL) { - dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = dev->next; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(child, dev); - } - - next_ebus: - printk("\n"); - - pdev = find_next_ebus(pdev, &is_rio); - if (!pdev) - break; - - dp = pci_device_to_OF_node(pdev); - - ebus->next = ebus_alloc(sizeof(struct linux_ebus)); - ebus = ebus->next; - ebus->next = NULL; - ebus->is_rio = is_rio; - ++num_ebus; - } - pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ -} diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 71d423a1c17..218778617ee 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -18,11 +18,12 @@ #include #include #include +#include +#include #include #include #include -#include #include #include @@ -808,7 +809,6 @@ static int __init pcibios_init(void) pci_scan_each_controller_bus(); - ebus_init(); power_init(); return 0; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 4c3a6a87c8a..30bba8b0a3b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -45,9 +45,6 @@ #ifdef CONFIG_SBUS #include #endif -#ifdef CONFIG_PCI -#include -#endif #include #include #include @@ -165,7 +162,6 @@ EXPORT_SYMBOL(insb); EXPORT_SYMBOL(insw); EXPORT_SYMBOL(insl); #ifdef CONFIG_PCI -EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_map_single); -- cgit v1.2.3 From e0ac612e6997429a21887475709ca6d6224971f2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 00:37:36 -0700 Subject: sparc: Kill ebus_bus_type. No longer used. Signed-off-by: David S. Miller --- arch/sparc/include/asm/of_platform.h | 2 -- arch/sparc/kernel/of_device.c | 10 ---------- arch/sparc64/kernel/of_device.c | 10 ---------- 3 files changed, 22 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/of_platform.h b/arch/sparc/include/asm/of_platform.h index 71ada5238b9..90da99059f8 100644 --- a/arch/sparc/include/asm/of_platform.h +++ b/arch/sparc/include/asm/of_platform.h @@ -13,8 +13,6 @@ * */ -extern struct bus_type ebus_bus_type; - #define of_bus_type of_platform_bus_type /* for compatibility */ #endif diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 576fa2ffa69..c59014886af 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -62,11 +62,6 @@ void of_propagate_archdata(struct of_device *bus) } } -#ifdef CONFIG_PCI -struct bus_type ebus_bus_type; -EXPORT_SYMBOL(ebus_bus_type); -#endif - struct bus_type of_platform_bus_type; EXPORT_SYMBOL(of_platform_bus_type); @@ -584,11 +579,6 @@ static int __init of_bus_driver_init(void) int err; err = of_bus_type_init(&of_platform_bus_type, "of"); -#ifdef CONFIG_PCI - if (!err) - err = of_bus_type_init(&ebus_bus_type, "ebus"); -#endif - if (!err) scan_of_devices(); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 6ae92536517..e427086e3b5 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -88,11 +88,6 @@ void of_propagate_archdata(struct of_device *bus) } } -#ifdef CONFIG_PCI -struct bus_type ebus_bus_type; -EXPORT_SYMBOL(ebus_bus_type); -#endif - struct bus_type of_platform_bus_type; EXPORT_SYMBOL(of_platform_bus_type); @@ -865,11 +860,6 @@ static int __init of_bus_driver_init(void) int err; err = of_bus_type_init(&of_platform_bus_type, "of"); -#ifdef CONFIG_PCI - if (!err) - err = of_bus_type_init(&ebus_bus_type, "ebus"); -#endif - if (!err) scan_of_devices(); -- cgit v1.2.3 From c510b9bfa1c34c1452f7a4389ff6de4f72a78193 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 01:18:56 -0700 Subject: sparc64: Don't invoke power_init() from pcibios_init(). That's just silly, use device_initcall() instead. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 4 ---- arch/sparc64/kernel/power.c | 16 +++++----------- 2 files changed, 5 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 218778617ee..83c50a62970 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -799,8 +799,6 @@ static void __init pci_scan_each_controller_bus(void) pbm->scan_bus(pbm); } -extern void power_init(void); - static int __init pcibios_init(void) { pci_controller_probe(); @@ -809,8 +807,6 @@ static int __init pcibios_init(void) pci_scan_each_controller_bus(); - power_init(); - return 0; } diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 3bb987a6d03..7536255ab57 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -1,29 +1,22 @@ /* power.c: Power management driver. * - * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include #include #include -#include -#include -#include #include #include -#include #include #include -#include #include #include #include #include #include -#include - /* * sysctl - toggle power-off restriction for serial console * systems in machine_power_off() @@ -111,8 +104,9 @@ static struct of_platform_driver power_driver = { }, }; -void __init power_init(void) +static int __init power_init(void) { - of_register_driver(&power_driver, &of_platform_bus_type); - return; + return of_register_driver(&power_driver, &of_platform_bus_type); } + +device_initcall(power_init); -- cgit v1.2.3 From 6d19c88f53bb3471a15152ea4fbdbebd36c0046c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 02:30:24 -0700 Subject: sparc64: Convert SCHIZO PCI controller driver into a real driver. The idea is to convert all of the PCI controller drivers into genuine OF drivers, then we can get rid of this terrible probing table and infrastructure in arch/sparc64/kernel/pci.c Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 15 ++--- arch/sparc64/kernel/pci_schizo.c | 117 ++++++++++++++++++++++++++------------- 2 files changed, 84 insertions(+), 48 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 83c50a62970..73f1d42d486 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -167,9 +167,6 @@ void pci_config_write32(u32 *addr, u32 val) /* Probe for all PCI controllers in the system. */ extern void sabre_init(struct device_node *, const char *); extern void psycho_init(struct device_node *, const char *); -extern void schizo_init(struct device_node *, const char *); -extern void schizo_plus_init(struct device_node *, const char *); -extern void tomatillo_init(struct device_node *, const char *); extern void sun4v_pci_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); @@ -182,12 +179,6 @@ static struct { { "pci108e,a001", sabre_init }, { "SUNW,psycho", psycho_init }, { "pci108e,8000", psycho_init }, - { "SUNW,schizo", schizo_init }, - { "pci108e,8001", schizo_init }, - { "SUNW,schizo+", schizo_plus_init }, - { "pci108e,8002", schizo_plus_init }, - { "SUNW,tomatillo", tomatillo_init }, - { "pci108e,a801", tomatillo_init }, { "SUNW,sun4v-pci", sun4v_pci_init }, { "pciex108e,80f0", fire_pci_init }, }; @@ -795,8 +786,10 @@ static void __init pci_scan_each_controller_bus(void) { struct pci_pbm_info *pbm; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) - pbm->scan_bus(pbm); + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + if (pbm->scan_bus) + pbm->scan_bus(pbm); + } } static int __init pcibios_init(void) diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 9248c6737f0..b95dd548583 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1,6 +1,6 @@ /* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. * - * Copyright (C) 2001, 2002, 2003, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 2001, 2002, 2003, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include @@ -13,14 +13,15 @@ #include #include -#include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" +#define DRIVER_NAME "schizo" +#define PFX DRIVER_NAME ": " + /* All SCHIZO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter * is a physical address. @@ -1084,7 +1085,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void __init schizo_scan_bus(struct pci_pbm_info *pbm) +static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = @@ -1187,9 +1188,9 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) break; default: - prom_printf("SCHIZO: strange virtual-dma size.\n"); - prom_halt(); - }; + printk(KERN_ERR PFX "Strange virtual-dma size.\n"); + return -EINVAL; + } /* Register addresses, SCHIZO has iommu ctx flushing. */ iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; @@ -1212,7 +1213,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); } @@ -1222,8 +1223,10 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) */ err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, pbm->numa_node); - if (err) + if (err) { + printk(KERN_ERR PFX "iommu_table_init() fails with %d\n", err); return err; + } schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); @@ -1236,7 +1239,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) case 128: control |= SCHIZO_IOMMU_TSBSZ_128K; break; - }; + } control |= SCHIZO_IOMMU_CTRL_ENAB; schizo_write(iommu->iommu_control, control); @@ -1334,9 +1337,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } } -static int __init schizo_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid, - int chip_type) +static int __devinit schizo_pbm_init(struct pci_controller_info *p, + struct device_node *dp, u32 portid, + int chip_type) { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; @@ -1382,7 +1385,6 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = schizo_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; @@ -1420,6 +1422,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, schizo_pbm_strbuf_init(pbm); + schizo_scan_bus(pbm); + return 0; } @@ -1433,8 +1437,7 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } -static void __init __schizo_init(struct device_node *dp, char *model_name, - int chip_type) +static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_type) { struct pci_controller_info *p; struct pci_pbm_info *pbm; @@ -1447,48 +1450,88 @@ static void __init __schizo_init(struct device_node *dp, char *model_name, if (portid_compare(pbm->portid, portid, chip_type)) { if (schizo_pbm_init(pbm->parent, dp, portid, chip_type)) - goto fatal_memory_error; - return; + return -ENOMEM; + return 0; } } p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + goto out_free; + } p->pbm_A.iommu = iommu; iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n"); + goto out_free; + } p->pbm_B.iommu = iommu; if (schizo_pbm_init(p, dp, portid, chip_type)) - goto fatal_memory_error; + goto out_free; - return; + return 0; -fatal_memory_error: - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + if (p->pbm_B.iommu) + kfree(p->pbm_B.iommu); + kfree(p); + } + return -ENOMEM; } -void __init schizo_init(struct device_node *dp, char *model_name) +static int __devinit schizo_probe(struct of_device *op, + const struct of_device_id *match) { - __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO); + return __schizo_init(op->node, (unsigned long) match->data); } -void __init schizo_plus_init(struct device_node *dp, char *model_name) -{ - __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); -} +/* The ordering of this table is very important. Some Tomatillo + * nodes announce that they are compatible with both pci108e,a801 + * and pci108e,8001. So list the chips in reverse chronological + * order. + */ +static struct of_device_id schizo_match[] = { + { + .name = "pci", + .compatible = "pci108e,a801", + .data = (void *) PBM_CHIP_TYPE_TOMATILLO, + }, + { + .name = "pci", + .compatible = "pci108e,8002", + .data = (void *) PBM_CHIP_TYPE_SCHIZO_PLUS, + }, + { + .name = "pci", + .compatible = "pci108e,8001", + .data = (void *) PBM_CHIP_TYPE_SCHIZO, + }, + {}, +}; -void __init tomatillo_init(struct device_node *dp, char *model_name) +static struct of_platform_driver schizo_driver = { + .name = DRIVER_NAME, + .match_table = schizo_match, + .probe = schizo_probe, +}; + +static int __init schizo_init(void) { - __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO); + return of_register_driver(&schizo_driver, &of_bus_type); } + +subsys_initcall(schizo_init); -- cgit v1.2.3 From 3822b50964d6702b7d8ba18ffd132d4bf786a17e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 02:50:29 -0700 Subject: sparc64: Convert SUN4V PCI controller driver into a real driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 - arch/sparc64/kernel/pci_sun4v.c | 123 +++++++++++++++++++++++++++------------- 2 files changed, 83 insertions(+), 42 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 73f1d42d486..445f5882546 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -167,7 +167,6 @@ void pci_config_write32(u32 *addr, u32 val) /* Probe for all PCI controllers in the system. */ extern void sabre_init(struct device_node *, const char *); extern void psycho_init(struct device_node *, const char *); -extern void sun4v_pci_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); static struct { @@ -179,7 +178,6 @@ static struct { { "pci108e,a001", sabre_init }, { "SUNW,psycho", psycho_init }, { "pci108e,8000", psycho_init }, - { "SUNW,sun4v-pci", sun4v_pci_init }, { "pciex108e,80f0", fire_pci_init }, }; #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index a104c80d319..c1e72beade2 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -13,12 +13,10 @@ #include #include #include +#include #include #include -#include -#include -#include #include #include @@ -27,6 +25,9 @@ #include "pci_sun4v.h" +#define DRIVER_NAME "pci_sun4v" +#define PFX DRIVER_NAME ": " + static unsigned long vpci_major = 1; static unsigned long vpci_minor = 1; @@ -583,7 +584,7 @@ static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm, return cnt; } -static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) +static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { struct iommu *iommu = pbm->iommu; struct property *prop; @@ -603,9 +604,9 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) } if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { - prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n", - vdma[0], vdma[1]); - prom_halt(); + printk(KERN_ERR PFX "Strange virtual-dma[%08x:%08x].\n", + vdma[0], vdma[1]); + return -EINVAL; }; dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); @@ -625,8 +626,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) sz = (sz + 7UL) & ~7UL; iommu->arena.map = kzalloc(sz, GFP_KERNEL); if (!iommu->arena.map) { - prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); - prom_halt(); + printk(KERN_ERR PFX "Error, kmalloc(arena.map) failed.\n"); + return -ENOMEM; } iommu->arena.limit = num_tsb_entries; @@ -634,6 +635,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) if (sz) printk("%s: Imported %lu TSB entries from OBP\n", pbm->name, sz); + + return 0; } #ifdef CONFIG_PCI_MSI @@ -890,10 +893,11 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) } #endif /* !(CONFIG_PCI_MSI) */ -static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 devhandle) +static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, + struct device_node *dp, u32 devhandle) { struct pci_pbm_info *pbm; + int err; if (devhandle & 0x40) pbm = &p->pbm_B; @@ -905,7 +909,6 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, pbm->numa_node = of_node_to_nid(dp); - pbm->scan_bus = pci_sun4v_scan_bus; pbm->pci_ops = &sun4v_pci_ops; pbm->config_space_reg_bits = 12; @@ -924,50 +927,58 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); pci_get_pbm_props(pbm); - pci_sun4v_iommu_init(pbm); + + err = pci_sun4v_iommu_init(pbm); + if (err) + return err; + pci_sun4v_msi_init(pbm); + + pci_sun4v_scan_bus(pbm); + + return 0; } -void __init sun4v_pci_init(struct device_node *dp, char *model_name) +static int __devinit pci_sun4v_probe(struct of_device *op, + const struct of_device_id *match) { + const struct linux_prom64_registers *regs; static int hvapi_negotiated = 0; struct pci_controller_info *p; struct pci_pbm_info *pbm; + struct device_node *dp; struct iommu *iommu; - struct property *prop; - struct linux_prom64_registers *regs; u32 devhandle; int i; + dp = op->node; + if (!hvapi_negotiated++) { int err = sun4v_hvapi_register(HV_GRP_PCI, vpci_major, &vpci_minor); if (err) { - prom_printf("SUN4V_PCI: Could not register hvapi, " - "err=%d\n", err); - prom_halt(); + printk(KERN_ERR PFX "Could not register hvapi, " + "err=%d\n", err); + return err; } - printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n", + printk(KERN_INFO PFX "Registered hvapi major[%lu] minor[%lu]\n", vpci_major, vpci_minor); dma_ops = &sun4v_dma_ops; } - prop = of_find_property(dp, "reg", NULL); - if (!prop) { - prom_printf("SUN4V_PCI: Could not find config registers\n"); - prom_halt(); + regs = of_get_property(dp, "reg", NULL); + if (!regs) { + printk(KERN_ERR PFX "Could not find config registers\n"); + return -ENODEV; } - regs = prop->value; - devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (pbm->devhandle == (devhandle ^ 0x40)) { - pci_sun4v_pbm_init(pbm->parent, dp, devhandle); - return; + return pci_sun4v_pbm_init(pbm->parent, dp, devhandle); } } @@ -975,31 +986,63 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name) unsigned long page = get_zeroed_page(GFP_ATOMIC); if (!page) - goto fatal_memory_error; + return -ENOMEM; per_cpu(iommu_batch, i).pglist = (u64 *) page; } p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Could not allocate pci_controller_info\n"); + goto out_free; + } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Could not allocate pbm A iommu\n"); + goto out_free; + } p->pbm_A.iommu = iommu; iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Could not allocate pbm B iommu\n"); + goto out_free; + } p->pbm_B.iommu = iommu; - pci_sun4v_pbm_init(p, dp, devhandle); - return; + return pci_sun4v_pbm_init(p, dp, devhandle); -fatal_memory_error: - prom_printf("SUN4V_PCI: Fatal memory allocation error.\n"); - prom_halt(); +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + if (p->pbm_B.iommu) + kfree(p->pbm_B.iommu); + kfree(p); + } + return -ENOMEM; } + +static struct of_device_id pci_sun4v_match[] = { + { + .name = "pci", + .compatible = "SUNW,sun4v-pci", + }, + {}, +}; + +static struct of_platform_driver pci_sun4v_driver = { + .name = DRIVER_NAME, + .match_table = pci_sun4v_match, + .probe = pci_sun4v_probe, +}; + +static int __init pci_sun4v_init(void) +{ + return of_register_driver(&pci_sun4v_driver, &of_bus_type); +} + +subsys_initcall(pci_sun4v_init); -- cgit v1.2.3 From b20bfe41badcbf38512fbe1118fe2e0817098e77 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 03:13:20 -0700 Subject: sparc64: Convert PSYCHO PCI controller driver into a real driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 3 -- arch/sparc64/kernel/pci_psycho.c | 95 +++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 445f5882546..c66c9bbc975 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -166,7 +166,6 @@ void pci_config_write32(u32 *addr, u32 val) /* Probe for all PCI controllers in the system. */ extern void sabre_init(struct device_node *, const char *); -extern void psycho_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); static struct { @@ -176,8 +175,6 @@ static struct { { "SUNW,sabre", sabre_init }, { "pci108e,a000", sabre_init }, { "pci108e,a001", sabre_init }, - { "SUNW,psycho", psycho_init }, - { "pci108e,8000", psycho_init }, { "pciex108e,80f0", fire_pci_init }, }; #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index ef5fe29202c..4e8f87aad20 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -17,11 +17,13 @@ #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" +#define DRIVER_NAME "psycho" +#define PFX DRIVER_NAME ": " + /* All PSYCHO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter * is a physical address. @@ -840,7 +842,7 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm) control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); control |= PSYCHO_IOMMU_CTRL_DENAB; psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); } @@ -850,8 +852,10 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm) */ err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, pbm->numa_node); - if (err) + if (err) { + printk(KERN_ERR PFX "iommu_table_init() fails\n"); return err; + } psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(iommu->page_table)); @@ -982,7 +986,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = psycho_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; @@ -1002,7 +1005,7 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->prom_node = dp; pbm->name = dp->full_name; - printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", + printk(KERN_INFO "%s: PSYCHO PCI Bus Module ver[%x:%x]\n", pbm->name, pbm->chip_version, pbm->chip_revision); @@ -1011,24 +1014,28 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pci_get_pbm_props(pbm); psycho_pbm_strbuf_init(pbm, is_pbm_a); + + psycho_scan_bus(pbm); } #define PSYCHO_CONFIGSPACE 0x001000000UL -void __init psycho_init(struct device_node *dp, char *model_name) +static int __devinit psycho_probe(struct of_device *op, + const struct of_device_id *match) { - struct linux_prom64_registers *pr_regs; + const struct linux_prom64_registers *pr_regs; + struct device_node *dp = op->node; struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; - struct property *prop; + int is_pbm_a, err; + const u32 *p32; u32 upa_portid; - int is_pbm_a; upa_portid = 0xff; - prop = of_find_property(dp, "upa-portid", NULL); - if (prop) - upa_portid = *(u32 *) prop->value; + p32 = of_get_property(dp, "upa-portid", NULL); + if (p32) + upa_portid = *p32; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { struct pci_controller_info *p = pbm->parent; @@ -1036,24 +1043,34 @@ void __init psycho_init(struct device_node *dp, char *model_name) if (p->pbm_A.portid == upa_portid) { is_pbm_a = (p->pbm_A.prom_node == NULL); psycho_pbm_init(p, dp, is_pbm_a); - return; + return 0; } } + err = -ENOMEM; p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } + iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); + goto out_free; + } p->pbm_A.iommu = p->pbm_B.iommu = iommu; p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; - prop = of_find_property(dp, "reg", NULL); - pr_regs = prop->value; + pr_regs = of_get_property(dp, "reg", NULL); + err = -ENODEV; + if (!pr_regs) { + printk(KERN_ERR PFX "No reg property.\n"); + goto out_free; + } p->pbm_A.controller_regs = pr_regs[2].phys_addr; p->pbm_B.controller_regs = pr_regs[2].phys_addr; @@ -1063,14 +1080,42 @@ void __init psycho_init(struct device_node *dp, char *model_name) psycho_controller_hwinit(&p->pbm_A); - if (psycho_iommu_init(&p->pbm_A)) - goto fatal_memory_error; + err = psycho_iommu_init(&p->pbm_A); + if (err) + goto out_free; is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + psycho_pbm_init(p, dp, is_pbm_a); - return; -fatal_memory_error: - prom_printf("PSYCHO: Fatal memory allocation error.\n"); - prom_halt(); + return 0; + +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + kfree(p); + } + return err; +} + +static struct of_device_id psycho_match[] = { + { + .name = "pci", + .compatible = "pci108e,8000", + }, + {}, +}; + +static struct of_platform_driver psycho_driver = { + .name = DRIVER_NAME, + .match_table = psycho_match, + .probe = psycho_probe, +}; + +static int __init psycho_init(void) +{ + return of_register_driver(&psycho_driver, &of_bus_type); } + +subsys_initcall(psycho_init); -- cgit v1.2.3 From edbe805b2b1044659e0727136213bdf42bd1b9d0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 03:14:01 -0700 Subject: sparc64: Convert SABRE PCI controller driver into a real driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 4 -- arch/sparc64/kernel/pci_sabre.c | 126 +++++++++++++++++++++++++++------------- 2 files changed, 85 insertions(+), 45 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c66c9bbc975..c2ff2de4da5 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -165,16 +165,12 @@ void pci_config_write32(u32 *addr, u32 val) } /* Probe for all PCI controllers in the system. */ -extern void sabre_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); static struct { char *model_name; void (*init)(struct device_node *, const char *); } pci_controller_table[] __initdata = { - { "SUNW,sabre", sabre_init }, - { "pci108e,a000", sabre_init }, - { "pci108e,a001", sabre_init }, { "pciex108e,80f0", fire_pci_init }, }; #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index ade5184e75d..7cce4d8f4aa 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -16,13 +16,14 @@ #include #include #include -#include -#include #include #include "pci_impl.h" #include "iommu_common.h" +#define DRIVER_NAME "sabre" +#define PFX DRIVER_NAME ": " + /* All SABRE registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter * is a physical address. @@ -656,8 +657,8 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) * to live at bus 0. */ if (once != 0) { - prom_printf("SABRE: Multiple controllers unsupported.\n"); - prom_halt(); + printk(KERN_ERR PFX "Multiple controllers unsupported.\n"); + return; } once++; @@ -705,8 +706,10 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, */ err = iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask, pbm->numa_node); - if (err) + if (err) { + printk(KERN_ERR PFX "iommu_table_init() failed\n"); return err; + } sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, __pa(iommu->page_table)); @@ -722,9 +725,8 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, control |= SABRE_IOMMU_TSBSZ_128K; break; default: - prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); - prom_halt(); - break; + printk(KERN_ERR PFX "Illegal TSB size %d\n", tsbsize); + return -EINVAL; } sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); @@ -739,7 +741,6 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = sabre_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; @@ -751,46 +752,49 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pci_get_pbm_props(pbm); pci_determine_mem_io_space(pbm); + + sabre_scan_bus(pbm); } -void __init sabre_init(struct device_node *dp, char *model_name) +static int __devinit sabre_probe(struct of_device *op, + const struct of_device_id *match) { const struct linux_prom64_registers *pr_regs; + struct device_node *dp = op->node; struct pci_controller_info *p; struct pci_pbm_info *pbm; + u32 upa_portid, dma_mask; struct iommu *iommu; - int tsbsize; + int tsbsize, err; const u32 *vdma; - u32 upa_portid, dma_mask; u64 clear_irq; - hummingbird_p = 0; - if (!strcmp(model_name, "pci108e,a001")) - hummingbird_p = 1; - else if (!strcmp(model_name, "SUNW,sabre")) { - const char *compat = of_get_property(dp, "compatible", NULL); - if (compat && !strcmp(compat, "pci108e,a001")) - hummingbird_p = 1; - if (!hummingbird_p) { - struct device_node *dp; - - /* Of course, Sun has to encode things a thousand - * different ways, inconsistently. - */ - for_each_node_by_type(dp, "cpu") { - if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe")) - hummingbird_p = 1; - } + hummingbird_p = (match->data != NULL); + if (!hummingbird_p) { + struct device_node *cpu_dp; + + /* Of course, Sun has to encode things a thousand + * different ways, inconsistently. + */ + for_each_node_by_type(cpu_dp, "cpu") { + if (!strcmp(cpu_dp->name, "SUNW,UltraSPARC-IIe")) + hummingbird_p = 1; } } + err = -ENOMEM; p = kzalloc(sizeof(*p), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); + goto out_free; + } + pbm = &p->pbm_A; pbm->iommu = iommu; @@ -806,6 +810,11 @@ void __init sabre_init(struct device_node *dp, char *model_name) */ pr_regs = of_get_property(dp, "reg", NULL); + err = -ENODEV; + if (!pr_regs) { + printk(KERN_ERR PFX "No reg property\n"); + goto out_free; + } /* * First REG in property is base of entire SABRE register space. @@ -832,6 +841,10 @@ void __init sabre_init(struct device_node *dp, char *model_name) (pbm->controller_regs + SABRE_CONFIGSPACE); vdma = of_get_property(dp, "virtual-dma", NULL); + if (!vdma) { + printk(KERN_ERR PFX "No virtual-dma property\n"); + goto out_free; + } dma_mask = vdma[0]; switch(vdma[1]) { @@ -849,20 +862,51 @@ void __init sabre_init(struct device_node *dp, char *model_name) tsbsize = 128; break; default: - prom_printf("SABRE: strange virtual-dma size.\n"); - prom_halt(); + printk(KERN_ERR PFX "Strange virtual-dma size.\n"); + goto out_free; } - if (sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask)) - goto fatal_memory_error; + err = sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); + if (err) + goto out_free; /* * Look for APB underneath. */ sabre_pbm_init(p, pbm, dp); - return; + return 0; -fatal_memory_error: - prom_printf("SABRE: Fatal memory allocation error.\n"); - prom_halt(); +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + kfree(p); + } + return err; } + +static struct of_device_id sabre_match[] = { + { + .name = "pci", + .compatible = "pci108e,a001", + .data = (void *) 1, + }, + { + .name = "pci", + .compatible = "pci108e,a000", + }, + {}, +}; + +static struct of_platform_driver sabre_driver = { + .name = DRIVER_NAME, + .match_table = sabre_match, + .probe = sabre_probe, +}; + +static int __init sabre_init(void) +{ + return of_register_driver(&sabre_driver, &of_bus_type); +} + +subsys_initcall(sabre_init); -- cgit v1.2.3 From c8049966b7f903ce61e94efbbddf581cf8860b85 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 03:12:38 -0700 Subject: sparc64: Convert FIRE PCI controller driver into a real driver. And now all the by-hand PCI controller probing junk in pci.c can die too. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 96 ------------------------------------------ arch/sparc64/kernel/pci_fire.c | 80 +++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 118 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c2ff2de4da5..2da32e4c985 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -164,79 +164,6 @@ void pci_config_write32(u32 *addr, u32 val) spin_unlock_irqrestore(&pci_poke_lock, flags); } -/* Probe for all PCI controllers in the system. */ -extern void fire_pci_init(struct device_node *, const char *); - -static struct { - char *model_name; - void (*init)(struct device_node *, const char *); -} pci_controller_table[] __initdata = { - { "pciex108e,80f0", fire_pci_init }, -}; -#define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) - -static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) -{ - int i; - - for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { - if (!strncmp(model_name, - pci_controller_table[i].model_name, - namelen)) { - pci_controller_table[i].init(dp, model_name); - return 1; - } - } - - return 0; -} - -static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) -{ - struct device_node *dp; - int count = 0; - - for_each_node_by_name(dp, "pci") { - struct property *prop; - int len; - - prop = of_find_property(dp, "model", &len); - if (!prop) - prop = of_find_property(dp, "compatible", &len); - - if (prop) { - const char *model = prop->value; - int item_len = 0; - - /* Our value may be a multi-valued string in the - * case of some compatible properties. For sanity, - * only try the first one. - */ - while (model[item_len] && len) { - len--; - item_len++; - } - - if (handler(model, item_len, dp)) - count++; - } - } - - return count; -} - -/* Find each controller in the system, attach and initialize - * software state structure for each and link into the - * pci_pbm_root. Setup the controller enough such - * that bus scanning can be done. - */ -static void __init pci_controller_probe(void) -{ - printk("PCI: Probing for controllers.\n"); - - pci_controller_scan(pci_controller_init); -} - static int ofpci_verbose; static int __init ofpci_debug(char *str) @@ -773,29 +700,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) return bus; } -static void __init pci_scan_each_controller_bus(void) -{ - struct pci_pbm_info *pbm; - - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (pbm->scan_bus) - pbm->scan_bus(pbm); - } -} - -static int __init pcibios_init(void) -{ - pci_controller_probe(); - if (pci_pbm_root == NULL) - return 0; - - pci_scan_each_controller_bus(); - - return 0; -} - -subsys_initcall(pcibios_init); - void __devinit pcibios_fixup_bus(struct pci_bus *pbus) { struct pci_pbm_info *pbm = pbus->sysdata; diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index d23bb6f53cd..adc3fe44b08 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -8,13 +8,16 @@ #include #include #include +#include -#include #include #include #include "pci_impl.h" +#define DRIVER_NAME "fire" +#define PFX DRIVER_NAME ": " + #define fire_read(__reg) \ ({ u64 __ret; \ __asm__ __volatile__("ldxa [%1] %2, %0" \ @@ -452,7 +455,6 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = pci_fire_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 12; @@ -481,6 +483,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pci_fire_msi_init(pbm); + pci_fire_scan_bus(pbm); + return 0; } @@ -491,43 +495,75 @@ static inline int portid_compare(u32 x, u32 y) return 0; } -void __init fire_pci_init(struct device_node *dp, const char *model_name) +static int __devinit fire_probe(struct of_device *op, + const struct of_device_id *match) { + struct device_node *dp = op->node; struct pci_controller_info *p; - u32 portid = of_getintprop_default(dp, "portid", 0xff); - struct iommu *iommu; struct pci_pbm_info *pbm; + struct iommu *iommu; + u32 portid; + int err; + portid = of_getintprop_default(dp, "portid", 0xff); for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (portid_compare(pbm->portid, portid)) { - if (pci_fire_pbm_init(pbm->parent, dp, portid)) - goto fatal_memory_error; - return; - } + if (portid_compare(pbm->portid, portid)) + return pci_fire_pbm_init(pbm->parent, dp, portid); } + err = -ENOMEM; p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + goto out_free; + } p->pbm_A.iommu = iommu; iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + goto out_free; + } p->pbm_B.iommu = iommu; - if (pci_fire_pbm_init(p, dp, portid)) - goto fatal_memory_error; + return pci_fire_pbm_init(p, dp, portid); - return; +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + if (p->pbm_B.iommu) + kfree(p->pbm_B.iommu); + kfree(p); + } + return err; +} + +static struct of_device_id fire_match[] = { + { + .name = "pci", + .compatible = "pciex108e,80f0", + }, + {}, +}; -fatal_memory_error: - prom_printf("PCI_FIRE: Fatal memory allocation error.\n"); - prom_halt(); +static struct of_platform_driver fire_driver = { + .name = DRIVER_NAME, + .match_table = fire_match, + .probe = fire_probe, +}; + +static int __init fire_init(void) +{ + return of_register_driver(&fire_driver, &of_bus_type); } + +subsys_initcall(fire_init); -- cgit v1.2.3 From 933b2a1d8d458d6fe12b5efd63a0432852c44d6d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 12:34:20 -0700 Subject: sparc: Stop setting NO_DMA. This fixes the build with PCI disabled, we do want the generic DMA facilities and interfaces even when just SBUS is enabled. Based upon a build failure report by Robert Reif. Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index cb1dd356b27..abcd82bfcb9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -235,9 +235,6 @@ source "drivers/pci/Kconfig" endif -config NO_DMA - def_bool !PCI - config SUN_OPENPROMFS tristate "Openprom tree appears in /proc/openprom" help -- cgit v1.2.3 From fd098316ef533e8441576f020ead4beab93154ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 01:23:17 -0700 Subject: sparc: Annotate of_device_id arrays with const or __initdata. As suggested by Stephen Rothwell. Signed-off-by: David S. Miller --- arch/sparc/include/asm/parport.h | 2 +- arch/sparc/kernel/apc.c | 2 +- arch/sparc/kernel/pmc.c | 2 +- arch/sparc/kernel/time.c | 2 +- arch/sparc64/kernel/auxio.c | 2 +- arch/sparc64/kernel/chmc.c | 2 +- arch/sparc64/kernel/pci_fire.c | 2 +- arch/sparc64/kernel/pci_psycho.c | 2 +- arch/sparc64/kernel/pci_sabre.c | 2 +- arch/sparc64/kernel/pci_schizo.c | 2 +- arch/sparc64/kernel/pci_sun4v.c | 2 +- arch/sparc64/kernel/power.c | 2 +- arch/sparc64/kernel/time.c | 6 +++--- 13 files changed, 15 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index 70dce0273f9..dff3f0253aa 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h @@ -215,7 +215,7 @@ static int __devexit ecpp_remove(struct of_device *op) return 0; } -static struct of_device_id ecpp_match[] = { +static const struct of_device_id ecpp_match[] = { { .name = "ecpp", }, diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 0a20cd85fd3..4dd1ba752ce 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -182,7 +182,7 @@ static int __devinit apc_probe(struct of_device *op, return 0; } -static struct of_device_id apc_match[] = { +static struct of_device_id __initdata apc_match[] = { { .name = APC_OBPNAME, }, diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 9976e82e323..814eb3ce039 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -72,7 +72,7 @@ static int __devinit pmc_probe(struct of_device *op, return 0; } -static struct of_device_id pmc_match[] = { +static struct of_device_id __initdata pmc_match[] = { { .name = PMC_OBPNAME, }, diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index a713bb43db8..339c4762fbc 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -338,7 +338,7 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id return 0; } -static struct of_device_id clock_match[] = { +static struct of_device_id __initdata clock_match[] = { { .name = "eeprom", }, diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index dd5c7bf8761..858beda8652 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -109,7 +109,7 @@ void auxio_set_lte(int on) } } -static struct of_device_id auxio_match[] = { +static struct of_device_id __initdata auxio_match[] = { { .name = "auxio", }, diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 3e14952e940..2ed401087ca 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -801,7 +801,7 @@ static int __devexit us3mc_remove(struct of_device *op) return 0; } -static struct of_device_id us3mc_match[] = { +static const struct of_device_id us3mc_match[] = { { .name = "memory-controller", }, diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index adc3fe44b08..477928aad53 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -547,7 +547,7 @@ out_free: return err; } -static struct of_device_id fire_match[] = { +static struct of_device_id __initdata fire_match[] = { { .name = "pci", .compatible = "pciex108e,80f0", diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 4e8f87aad20..708212a6e7e 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1099,7 +1099,7 @@ out_free: return err; } -static struct of_device_id psycho_match[] = { +static struct of_device_id __initdata psycho_match[] = { { .name = "pci", .compatible = "pci108e,8000", diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 7cce4d8f4aa..cc476e9a275 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -885,7 +885,7 @@ out_free: return err; } -static struct of_device_id sabre_match[] = { +static struct of_device_id __initdata sabre_match[] = { { .name = "pci", .compatible = "pci108e,a001", diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index b95dd548583..18fdd887b4a 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1504,7 +1504,7 @@ static int __devinit schizo_probe(struct of_device *op, * and pci108e,8001. So list the chips in reverse chronological * order. */ -static struct of_device_id schizo_match[] = { +static struct of_device_id __initdata schizo_match[] = { { .name = "pci", .compatible = "pci108e,a801", diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index c1e72beade2..fea51a054be 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -1026,7 +1026,7 @@ out_free: return -ENOMEM; } -static struct of_device_id pci_sun4v_match[] = { +static struct of_device_id __initdata pci_sun4v_match[] = { { .name = "pci", .compatible = "SUNW,sun4v-pci", diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 7536255ab57..7559ad395a3 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -89,7 +89,7 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id return 0; } -static struct of_device_id power_match[] = { +static struct of_device_id __initdata power_match[] = { { .name = "power", }, diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index ea05038a8c1..209e7d28c3a 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -438,7 +438,7 @@ static int __devinit rtc_probe(struct of_device *op, const struct of_device_id * return platform_device_register(&rtc_cmos_device); } -static struct of_device_id rtc_match[] = { +static struct of_device_id __initdata rtc_match[] = { { .name = "rtc", .compatible = "m5819", @@ -482,7 +482,7 @@ static int __devinit bq4802_probe(struct of_device *op, const struct of_device_i return platform_device_register(&rtc_bq4802_device); } -static struct of_device_id bq4802_match[] = { +static struct of_device_id __initdata bq4802_match[] = { { .name = "rtc", .compatible = "bq4802", @@ -566,7 +566,7 @@ static int __devinit mostek_probe(struct of_device *op, const struct of_device_i return platform_device_register(&m48t59_rtc); } -static struct of_device_id mostek_match[] = { +static struct of_device_id __initdata mostek_match[] = { { .name = "eeprom", }, -- cgit v1.2.3 From d7472c389ee1044d04af8a5b7c51aa7af96ed2db Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 01:33:52 -0700 Subject: sparc64: Simplify error handling in PCI controller probing. Based upon suggestions from Stephen Rothwell. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_fire.c | 21 ++++++++++----------- arch/sparc64/kernel/pci_psycho.c | 21 +++++++++++---------- arch/sparc64/kernel/pci_sabre.c | 25 +++++++++++++------------ arch/sparc64/kernel/pci_schizo.c | 32 ++++++++++++++++++-------------- arch/sparc64/kernel/pci_sun4v.c | 31 ++++++++++++++++--------------- 5 files changed, 68 insertions(+), 62 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 477928aad53..4fb1ef92cb1 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -515,13 +515,13 @@ static int __devinit fire_probe(struct of_device *op, p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = iommu; @@ -529,21 +529,20 @@ static int __devinit fire_probe(struct of_device *op, iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free; + goto out_free_iommu_A; } p->pbm_B.iommu = iommu; return pci_fire_pbm_init(p, dp, portid); -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - if (p->pbm_B.iommu) - kfree(p->pbm_B.iommu); - kfree(p); - } +out_free_iommu_A: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: return err; } diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 708212a6e7e..5ee84c5b963 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1051,13 +1051,13 @@ static int __devinit psycho_probe(struct of_device *op, p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = p->pbm_B.iommu = iommu; @@ -1069,7 +1069,7 @@ static int __devinit psycho_probe(struct of_device *op, err = -ENODEV; if (!pr_regs) { printk(KERN_ERR PFX "No reg property.\n"); - goto out_free; + goto out_free_iommu; } p->pbm_A.controller_regs = pr_regs[2].phys_addr; @@ -1082,7 +1082,7 @@ static int __devinit psycho_probe(struct of_device *op, err = psycho_iommu_init(&p->pbm_A); if (err) - goto out_free; + goto out_free_iommu; is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); @@ -1090,12 +1090,13 @@ static int __devinit psycho_probe(struct of_device *op, return 0; -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - kfree(p); - } +out_free_iommu: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: return err; } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index cc476e9a275..eee8fdca382 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -786,13 +786,13 @@ static int __devinit sabre_probe(struct of_device *op, p = kzalloc(sizeof(*p), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); - goto out_free; + goto out_free_controller; } pbm = &p->pbm_A; @@ -813,7 +813,7 @@ static int __devinit sabre_probe(struct of_device *op, err = -ENODEV; if (!pr_regs) { printk(KERN_ERR PFX "No reg property\n"); - goto out_free; + goto out_free_iommu; } /* @@ -843,7 +843,7 @@ static int __devinit sabre_probe(struct of_device *op, vdma = of_get_property(dp, "virtual-dma", NULL); if (!vdma) { printk(KERN_ERR PFX "No virtual-dma property\n"); - goto out_free; + goto out_free_iommu; } dma_mask = vdma[0]; @@ -863,12 +863,12 @@ static int __devinit sabre_probe(struct of_device *op, break; default: printk(KERN_ERR PFX "Strange virtual-dma size.\n"); - goto out_free; + goto out_free_iommu; } err = sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); if (err) - goto out_free; + goto out_free_iommu; /* * Look for APB underneath. @@ -876,12 +876,13 @@ static int __devinit sabre_probe(struct of_device *op, sabre_pbm_init(p, pbm, dp); return 0; -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - kfree(p); - } +out_free_iommu: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: return err; } diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 18fdd887b4a..bd7612aae17 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1443,14 +1443,16 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; + int err; portid = of_getintprop_default(dp, "portid", 0xff); + err = -ENOMEM; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid, chip_type)) { if (schizo_pbm_init(pbm->parent, dp, portid, chip_type)) - return -ENOMEM; + goto out_err; return 0; } } @@ -1458,13 +1460,13 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = iommu; @@ -1472,25 +1474,27 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n"); - goto out_free; + goto out_free_iommu_A; } p->pbm_B.iommu = iommu; if (schizo_pbm_init(p, dp, portid, chip_type)) - goto out_free; + goto out_free_iommu_B; return 0; -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - if (p->pbm_B.iommu) - kfree(p->pbm_B.iommu); - kfree(p); - } - return -ENOMEM; +out_free_iommu_B: + kfree(p->pbm_B.iommu); + +out_free_iommu_A: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: + return err; } static int __devinit schizo_probe(struct of_device *op, diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index fea51a054be..21864f06532 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -949,7 +949,7 @@ static int __devinit pci_sun4v_probe(struct of_device *op, struct device_node *dp; struct iommu *iommu; u32 devhandle; - int i; + int i, err; dp = op->node; @@ -970,9 +970,10 @@ static int __devinit pci_sun4v_probe(struct of_device *op, } regs = of_get_property(dp, "reg", NULL); + err = -ENODEV; if (!regs) { printk(KERN_ERR PFX "Could not find config registers\n"); - return -ENODEV; + goto out_err; } devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; @@ -982,11 +983,12 @@ static int __devinit pci_sun4v_probe(struct of_device *op, } } + err = -ENOMEM; for_each_possible_cpu(i) { unsigned long page = get_zeroed_page(GFP_ATOMIC); if (!page) - return -ENOMEM; + goto out_err; per_cpu(iommu_batch, i).pglist = (u64 *) page; } @@ -994,13 +996,13 @@ static int __devinit pci_sun4v_probe(struct of_device *op, p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Could not allocate pci_controller_info\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Could not allocate pbm A iommu\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = iommu; @@ -1008,22 +1010,21 @@ static int __devinit pci_sun4v_probe(struct of_device *op, iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Could not allocate pbm B iommu\n"); - goto out_free; + goto out_free_iommu_A; } p->pbm_B.iommu = iommu; return pci_sun4v_pbm_init(p, dp, devhandle); -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - if (p->pbm_B.iommu) - kfree(p->pbm_B.iommu); - kfree(p); - } - return -ENOMEM; +out_free_iommu_A: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: + return err; } static struct of_device_id __initdata pci_sun4v_match[] = { -- cgit v1.2.3 From 10d29ff9070caf5810d37ab06e30f7acad278f1e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 01:40:12 -0700 Subject: sparc64: Delete starfire_cpu_setup(). It does nothing. Signed-off-by: David S. Miller --- arch/sparc/include/asm/starfire.h | 1 - arch/sparc64/kernel/central.c | 5 +---- arch/sparc64/kernel/starfire.c | 5 ----- 3 files changed, 1 insertion(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/starfire.h b/arch/sparc/include/asm/starfire.h index 07bafd31e33..d56ce60a599 100644 --- a/arch/sparc/include/asm/starfire.h +++ b/arch/sparc/include/asm/starfire.h @@ -12,7 +12,6 @@ extern int this_is_starfire; extern void check_if_starfire(void); -extern void starfire_cpu_setup(void); extern int starfire_hard_smp_processor_id(void); extern void starfire_hookup(int); extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid); diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index f2e87d0d7e1..68c91b232be 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -306,11 +306,8 @@ void __init central_probe(void) int err; dp = of_find_node_by_name(NULL, "central"); - if (!dp) { - if (this_is_starfire) - starfire_cpu_setup(); + if (!dp) return; - } /* Ok we got one, grab some memory for software state. */ central_bus = (struct linux_central *) diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c index 7461581b3bb..060d0f3a615 100644 --- a/arch/sparc64/kernel/starfire.c +++ b/arch/sparc64/kernel/starfire.c @@ -28,11 +28,6 @@ void check_if_starfire(void) this_is_starfire = 1; } -void starfire_cpu_setup(void) -{ - /* Currently, nothing to do. */ -} - int starfire_hard_smp_processor_id(void) { return upa_readl(0x1fff40000d0UL); -- cgit v1.2.3 From b69416b51be0757c82f1c5a0a3f0995a4484dab4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 20:56:15 -0700 Subject: sparc64: Rewrite central driver. This driver is now limited to just doing the basic clock board and FHC chip initialization and registering the platform devices for the per-board LEDs, which are driven by the new LEDS_STARFIRE driver. The IRQ register handling is already confined purely to the device tree code. Signed-off-by: David S. Miller --- arch/sparc/include/asm/fhc.h | 43 +-- arch/sparc64/kernel/central.c | 616 +++++++++++++++--------------------------- arch/sparc64/kernel/sbus.c | 3 - arch/sparc64/mm/init.c | 3 - 4 files changed, 214 insertions(+), 451 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/fhc.h b/arch/sparc/include/asm/fhc.h index 788cbc46a11..57f1b303ad5 100644 --- a/arch/sparc/include/asm/fhc.h +++ b/arch/sparc/include/asm/fhc.h @@ -1,5 +1,4 @@ -/* - * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire. +/* fhc.h: FHC and Clock board register definitions. * * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) */ @@ -7,14 +6,6 @@ #ifndef _SPARC64_FHC_H #define _SPARC64_FHC_H -#include - -#include -#include -#include - -struct linux_fhc; - /* Clock board register offsets. */ #define CLOCK_CTRL 0x00UL /* Main control */ #define CLOCK_STAT1 0x10UL /* Status one */ @@ -29,21 +20,7 @@ struct linux_fhc; #define CLOCK_CTRL_MLED 0x02 /* Mid LED, 1 == on */ #define CLOCK_CTRL_RLED 0x01 /* RIght LED, 1 == on */ -struct linux_central { - struct linux_fhc *child; - unsigned long cfreg; - unsigned long clkregs; - unsigned long clkver; - int slots; - struct device_node *prom_node; - - struct linux_prom_ranges central_ranges[PROMREG_MAX]; - int num_central_ranges; -}; - /* Firehose controller register offsets */ -struct fhc_regs { - unsigned long pregs; /* FHC internal regs */ #define FHC_PREGS_ID 0x00UL /* FHC ID */ #define FHC_ID_VERS 0xf0000000 /* Version of this FHC */ #define FHC_ID_PARTID 0x0ffff000 /* Part ID code (0x0f9f == FHC) */ @@ -90,32 +67,14 @@ struct fhc_regs { #define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */ #define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */ #define FHC_PREGS_JCMD 0x100UL /* FHC JTAG Command Register */ - unsigned long ireg; /* FHC IGN reg */ #define FHC_IREG_IGN 0x00UL /* This FHC's IGN */ - unsigned long ffregs; /* FHC fanfail regs */ #define FHC_FFREGS_IMAP 0x00UL /* FHC Fanfail IMAP */ #define FHC_FFREGS_ICLR 0x10UL /* FHC Fanfail ICLR */ - unsigned long sregs; /* FHC system regs */ #define FHC_SREGS_IMAP 0x00UL /* FHC System IMAP */ #define FHC_SREGS_ICLR 0x10UL /* FHC System ICLR */ - unsigned long uregs; /* FHC uart regs */ #define FHC_UREGS_IMAP 0x00UL /* FHC Uart IMAP */ #define FHC_UREGS_ICLR 0x10UL /* FHC Uart ICLR */ - unsigned long tregs; /* FHC TOD regs */ #define FHC_TREGS_IMAP 0x00UL /* FHC TOD IMAP */ #define FHC_TREGS_ICLR 0x10UL /* FHC TOD ICLR */ -}; - -struct linux_fhc { - struct linux_fhc *next; - struct linux_central *parent; /* NULL if not central FHC */ - struct fhc_regs fhc_regs; - int board; - int jtag_master; - struct device_node *prom_node; - - struct linux_prom_ranges fhc_ranges[PROMREG_MAX]; - int num_fhc_ranges; -}; #endif /* !(_SPARC64_FHC_H) */ diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index 68c91b232be..05f1c916db0 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -1,458 +1,268 @@ /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire. * - * Copyright (C) 1997, 1999 David S. Miller (davem@davemloft.net) + * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net) */ #include #include #include -#include -#include -#include #include -#include +#include +#include -#include #include -#include - -static struct linux_central *central_bus = NULL; -static struct linux_fhc *fhc_list = NULL; +#include + +struct clock_board { + void __iomem *clock_freq_regs; + void __iomem *clock_regs; + void __iomem *clock_ver_reg; + int num_slots; + struct resource leds_resource; + struct platform_device leds_pdev; +}; + +struct fhc { + void __iomem *pregs; + bool central; + bool jtag_master; + int board_num; + struct resource leds_resource; + struct platform_device leds_pdev; +}; + +static int __devinit clock_board_calc_nslots(struct clock_board *p) +{ + u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0; -#define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child) + switch (reg) { + case 0x40: + return 16; -static void central_probe_failure(int line) -{ - prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n", - line); - prom_halt(); -} + case 0xc0: + return 8; -static void central_ranges_init(struct linux_central *central) -{ - struct device_node *dp = central->prom_node; - const void *pval; - int len; - - central->num_central_ranges = 0; - pval = of_get_property(dp, "ranges", &len); - if (pval) { - memcpy(central->central_ranges, pval, len); - central->num_central_ranges = - (len / sizeof(struct linux_prom_ranges)); + case 0x80: + reg = 0; + if (p->clock_ver_reg) + reg = upa_readb(p->clock_ver_reg); + if (reg) { + if (reg & 0x80) + return 4; + else + return 5; + } + /* Fallthrough */ + default: + return 4; } } -static void fhc_ranges_init(struct linux_fhc *fhc) +static int __devinit clock_board_probe(struct of_device *op, + const struct of_device_id *match) { - struct device_node *dp = fhc->prom_node; - const void *pval; - int len; - - fhc->num_fhc_ranges = 0; - pval = of_get_property(dp, "ranges", &len); - if (pval) { - memcpy(fhc->fhc_ranges, pval, len); - fhc->num_fhc_ranges = - (len / sizeof(struct linux_prom_ranges)); - } -} + struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); + int err = -ENOMEM; -/* Range application routines are exported to various drivers, - * so do not __init this. - */ -static void adjust_regs(struct linux_prom_registers *regp, int nregs, - struct linux_prom_ranges *rangep, int nranges) -{ - int regc, rngc; - - for (regc = 0; regc < nregs; regc++) { - for (rngc = 0; rngc < nranges; rngc++) - if (regp[regc].which_io == rangep[rngc].ot_child_space) - break; /* Fount it */ - if (rngc == nranges) /* oops */ - central_probe_failure(__LINE__); - regp[regc].which_io = rangep[rngc].ot_parent_space; - regp[regc].phys_addr -= rangep[rngc].ot_child_base; - regp[regc].phys_addr += rangep[rngc].ot_parent_base; + if (!p) { + printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n"); + goto out; } -} -/* Apply probed fhc ranges to registers passed, if no ranges return. */ -static void apply_fhc_ranges(struct linux_fhc *fhc, - struct linux_prom_registers *regs, - int nregs) -{ - if (fhc->num_fhc_ranges) - adjust_regs(regs, nregs, fhc->fhc_ranges, - fhc->num_fhc_ranges); -} + p->clock_freq_regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), + "clock_board_freq"); + if (!p->clock_freq_regs) { + printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n"); + goto out_free; + } -/* Apply probed central ranges to registers passed, if no ranges return. */ -static void apply_central_ranges(struct linux_central *central, - struct linux_prom_registers *regs, int nregs) -{ - if (central->num_central_ranges) - adjust_regs(regs, nregs, central->central_ranges, - central->num_central_ranges); -} + p->clock_regs = of_ioremap(&op->resource[1], 0, + resource_size(&op->resource[1]), + "clock_board_regs"); + if (!p->clock_regs) { + printk(KERN_ERR "clock_board: Cannot map clock_regs\n"); + goto out_unmap_clock_freq_regs; + } -static void * __init central_alloc_bootmem(unsigned long size) -{ - void *ret; + if (op->resource[2].flags) { + p->clock_ver_reg = of_ioremap(&op->resource[2], 0, + resource_size(&op->resource[2]), + "clock_ver_reg"); + if (!p->clock_ver_reg) { + printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n"); + goto out_unmap_clock_regs; + } + } - ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); - if (ret != NULL) - memset(ret, 0, size); + p->num_slots = clock_board_calc_nslots(p); - return ret; -} + p->leds_resource.start = (unsigned long) + (p->clock_regs + CLOCK_CTRL); + p->leds_resource.end = p->leds_resource.end; + p->leds_resource.name = "leds"; -static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) -{ - unsigned long ret = ((unsigned long) r->which_io) << 32; + p->leds_pdev.name = "sunfire-clockboard-leds"; + p->leds_pdev.resource = &p->leds_resource; + p->leds_pdev.num_resources = 1; + p->leds_pdev.dev.parent = &op->dev; - return ret | (unsigned long) r->phys_addr; -} - -static void __init probe_other_fhcs(void) -{ - struct device_node *dp; - const struct linux_prom64_registers *fpregs; - - for_each_node_by_name(dp, "fhc") { - struct linux_fhc *fhc; - int board; - u32 tmp; - - if (dp->parent && - dp->parent->parent != NULL) - continue; - - fhc = (struct linux_fhc *) - central_alloc_bootmem(sizeof(struct linux_fhc)); - if (fhc == NULL) - central_probe_failure(__LINE__); - - /* Link it into the FHC chain. */ - fhc->next = fhc_list; - fhc_list = fhc; - - /* Toplevel FHCs have no parent. */ - fhc->parent = NULL; - - fhc->prom_node = dp; - fhc_ranges_init(fhc); - - /* Non-central FHC's have 64-bit OBP format registers. */ - fpregs = of_get_property(dp, "reg", NULL); - if (!fpregs) - central_probe_failure(__LINE__); - - /* Only central FHC needs special ranges applied. */ - fhc->fhc_regs.pregs = fpregs[0].phys_addr; - fhc->fhc_regs.ireg = fpregs[1].phys_addr; - fhc->fhc_regs.ffregs = fpregs[2].phys_addr; - fhc->fhc_regs.sregs = fpregs[3].phys_addr; - fhc->fhc_regs.uregs = fpregs[4].phys_addr; - fhc->fhc_regs.tregs = fpregs[5].phys_addr; - - board = of_getintprop_default(dp, "board#", -1); - fhc->board = board; - - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); - if ((tmp & FHC_JTAG_CTRL_MENAB) != 0) - fhc->jtag_master = 1; - else - fhc->jtag_master = 0; - - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n", - board, - (tmp & FHC_ID_VERS) >> 28, - (tmp & FHC_ID_PARTID) >> 12, - (tmp & FHC_ID_MANUF) >> 1, - (fhc->jtag_master ? "(JTAG Master)" : "")); - - /* This bit must be set in all non-central FHC's in - * the system. When it is clear, this identifies - * the central board. - */ - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - tmp |= FHC_CONTROL_IXIST; - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + err = platform_device_register(&p->leds_pdev); + if (err) { + printk(KERN_ERR "clock_board: Could not register LEDS " + "platform device\n"); + goto out_unmap_clock_ver_reg; } -} -static void probe_clock_board(struct linux_central *central, - struct linux_fhc *fhc, - struct device_node *fp) -{ - struct device_node *dp; - struct linux_prom_registers cregs[3]; - const struct linux_prom_registers *pr; - int nslots, tmp, nregs; - - dp = fp->child; - while (dp) { - if (!strcmp(dp->name, "clock-board")) - break; - dp = dp->sibling; - } - if (!dp) - central_probe_failure(__LINE__); + printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n", + p->num_slots); - pr = of_get_property(dp, "reg", &nregs); - if (!pr) - central_probe_failure(__LINE__); + err = 0; +out: + return err; - memcpy(cregs, pr, nregs); - nregs /= sizeof(struct linux_prom_registers); +out_unmap_clock_ver_reg: + if (p->clock_ver_reg) + of_iounmap(&op->resource[2], p->clock_ver_reg, + resource_size(&op->resource[2])); - apply_fhc_ranges(fhc, &cregs[0], nregs); - apply_central_ranges(central, &cregs[0], nregs); - central->cfreg = prom_reg_to_paddr(&cregs[0]); - central->clkregs = prom_reg_to_paddr(&cregs[1]); +out_unmap_clock_regs: + of_iounmap(&op->resource[1], p->clock_regs, + resource_size(&op->resource[1])); - if (nregs == 2) - central->clkver = 0UL; - else - central->clkver = prom_reg_to_paddr(&cregs[2]); +out_unmap_clock_freq_regs: + of_iounmap(&op->resource[0], p->clock_freq_regs, + resource_size(&op->resource[0])); - tmp = upa_readb(central->clkregs + CLOCK_STAT1); - tmp &= 0xc0; - switch(tmp) { - case 0x40: - nslots = 16; - break; - case 0xc0: - nslots = 8; - break; - case 0x80: - if (central->clkver != 0UL && - upa_readb(central->clkver) != 0) { - if ((upa_readb(central->clkver) & 0x80) != 0) - nslots = 4; - else - nslots = 5; - break; - } - default: - nslots = 4; - break; - }; - central->slots = nslots; - printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n", - central->slots, upa_readb(central->cfreg), - (central->clkver ? upa_readb(central->clkver) : 0x00)); +out_free: + kfree(p); + goto out; } -static void ZAP(unsigned long iclr, unsigned long imap) +static struct of_device_id __initdata clock_board_match[] = { + { + .name = "clock-board", + }, + {}, +}; + +static struct of_platform_driver clock_board_driver = { + .match_table = clock_board_match, + .probe = clock_board_probe, + .driver = { + .name = "clock_board", + }, +}; + +static int __devinit fhc_probe(struct of_device *op, + const struct of_device_id *match) { - u32 imap_tmp; - - upa_writel(0, iclr); - upa_readl(iclr); - imap_tmp = upa_readl(imap); - imap_tmp &= ~(0x80000000); - upa_writel(imap_tmp, imap); - upa_readl(imap); -} + struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); + int err = -ENOMEM; + u32 reg; -static void init_all_fhc_hw(void) -{ - struct linux_fhc *fhc; - - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) { - u32 tmp; - - /* Clear all of the interrupt mapping registers - * just in case OBP left them in a foul state. - */ - ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR, - fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP); - ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR, - fhc->fhc_regs.sregs + FHC_SREGS_IMAP); - ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR, - fhc->fhc_regs.uregs + FHC_UREGS_IMAP); - ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR, - fhc->fhc_regs.tregs + FHC_TREGS_IMAP); - - /* Setup FHC control register. */ - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - - /* All non-central boards have this bit set. */ - if (! IS_CENTRAL_FHC(fhc)) - tmp |= FHC_CONTROL_IXIST; - - /* For all FHCs, clear the firmware synchronization - * line and both low power mode enables. - */ - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | - FHC_CONTROL_SLINE); - - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + if (!p) { + printk(KERN_ERR "fhc: Cannot allocate struct fhc\n"); + goto out; } -} + if (!strcmp(op->node->parent->name, "central")) + p->central = true; -void __init central_probe(void) -{ - struct linux_prom_registers fpregs[6]; - const struct linux_prom_registers *pr; - struct linux_fhc *fhc; - struct device_node *dp, *fp; - int err; - - dp = of_find_node_by_name(NULL, "central"); - if (!dp) - return; - - /* Ok we got one, grab some memory for software state. */ - central_bus = (struct linux_central *) - central_alloc_bootmem(sizeof(struct linux_central)); - if (central_bus == NULL) - central_probe_failure(__LINE__); - - fhc = (struct linux_fhc *) - central_alloc_bootmem(sizeof(struct linux_fhc)); - if (fhc == NULL) - central_probe_failure(__LINE__); - - /* First init central. */ - central_bus->child = fhc; - central_bus->prom_node = dp; - central_ranges_init(central_bus); - - /* And then central's FHC. */ - fhc->next = fhc_list; - fhc_list = fhc; - - fhc->parent = central_bus; - fp = dp->child; - while (fp) { - if (!strcmp(fp->name, "fhc")) - break; - fp = fp->sibling; + p->pregs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), + "fhc_pregs"); + if (!p->pregs) { + printk(KERN_ERR "fhc: Cannot map pregs\n"); + goto out_free; } - if (!fp) - central_probe_failure(__LINE__); - - fhc->prom_node = fp; - fhc_ranges_init(fhc); - - /* Now, map in FHC register set. */ - pr = of_get_property(fp, "reg", NULL); - if (!pr) - central_probe_failure(__LINE__); - memcpy(fpregs, pr, sizeof(fpregs)); - - apply_central_ranges(central_bus, &fpregs[0], 6); - - fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]); - fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]); - fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]); - fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]); - fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]); - fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]); - - /* Obtain board number from board status register, Central's - * FHC lacks "board#" property. - */ - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR); - fhc->board = (((err >> 16) & 0x01) | - ((err >> 12) & 0x0e)); - - fhc->jtag_master = 0; - - /* Attach the clock board registers for CENTRAL. */ - probe_clock_board(central_bus, fhc, fp); - - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", - fhc->board, - ((err & FHC_ID_VERS) >> 28), - ((err & FHC_ID_PARTID) >> 12), - ((err & FHC_ID_MANUF) >> 1)); - - probe_other_fhcs(); - - init_all_fhc_hw(); -} -static inline void fhc_ledblink(struct linux_fhc *fhc, int on) -{ - u32 tmp; + if (p->central) { + reg = upa_readl(p->pregs + FHC_PREGS_BSR); + p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e); + } else { + p->board_num = of_getintprop_default(op->node, "board#", -1); + if (p->board_num == -1) { + printk(KERN_ERR "fhc: No board# property\n"); + goto out_unmap_pregs; + } + if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB) + p->jtag_master = true; + } - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + if (!p->central) { + p->leds_resource.start = (unsigned long) + (p->pregs + FHC_PREGS_CTRL); + p->leds_resource.end = p->leds_resource.end; + p->leds_resource.name = "leds"; + + p->leds_pdev.name = "sunfire-fhc-leds"; + p->leds_pdev.resource = &p->leds_resource; + p->leds_pdev.num_resources = 1; + p->leds_pdev.dev.parent = &op->dev; + + err = platform_device_register(&p->leds_pdev); + if (err) { + printk(KERN_ERR "fhc: Could not register LEDS " + "platform device\n"); + goto out_unmap_pregs; + } + } + reg = upa_readl(p->pregs + FHC_PREGS_CTRL); - /* NOTE: reverse logic on this bit */ - if (on) - tmp &= ~(FHC_CONTROL_RLED); - else - tmp |= FHC_CONTROL_RLED; - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); + if (!p->central) + reg |= FHC_CONTROL_IXIST; - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); -} + reg &= ~(FHC_CONTROL_AOFF | + FHC_CONTROL_BOFF | + FHC_CONTROL_SLINE); -static inline void central_ledblink(struct linux_central *central, int on) -{ - u8 tmp; + upa_writel(reg, p->pregs + FHC_PREGS_CTRL); + upa_readl(p->pregs + FHC_PREGS_CTRL); - tmp = upa_readb(central->clkregs + CLOCK_CTRL); + reg = upa_readl(p->pregs + FHC_PREGS_ID); + printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n", + p->board_num, + (reg & FHC_ID_VERS) >> 28, + (reg & FHC_ID_PARTID) >> 12, + (reg & FHC_ID_MANUF) >> 1, + (p->jtag_master ? + "(JTAG Master)" : + (p->central ? "(Central)" : ""))); - /* NOTE: reverse logic on this bit */ - if (on) - tmp &= ~(CLOCK_CTRL_RLED); - else - tmp |= CLOCK_CTRL_RLED; + err = 0; - upa_writeb(tmp, central->clkregs + CLOCK_CTRL); - upa_readb(central->clkregs + CLOCK_CTRL); -} +out: + return err; -static struct timer_list sftimer; -static int led_state; +out_unmap_pregs: + of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0])); -static void sunfire_timer(unsigned long __ignored) -{ - struct linux_fhc *fhc; - - central_ledblink(central_bus, led_state); - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) - if (! IS_CENTRAL_FHC(fhc)) - fhc_ledblink(fhc, led_state); - led_state = ! led_state; - sftimer.expires = jiffies + (HZ >> 1); - add_timer(&sftimer); +out_free: + kfree(p); + goto out; } -/* After PCI/SBUS busses have been probed, this is called to perform - * final initialization of all FireHose Controllers in the system. - */ -void firetruck_init(void) +static struct of_device_id __initdata fhc_match[] = { + { + .name = "fhc", + }, + {}, +}; + +static struct of_platform_driver fhc_driver = { + .match_table = fhc_match, + .probe = fhc_probe, + .driver = { + .name = "fhc", + }, +}; + +static int __init sunfire_init(void) { - struct linux_central *central = central_bus; - u8 ctrl; - - /* No central bus, nothing to do. */ - if (central == NULL) - return; - - /* OBP leaves it on, turn it off so clock board timer LED - * is in sync with FHC ones. - */ - ctrl = upa_readb(central->clkregs + CLOCK_CTRL); - ctrl &= ~(CLOCK_CTRL_RLED); - upa_writeb(ctrl, central->clkregs + CLOCK_CTRL); - - led_state = 0; - init_timer(&sftimer); - sftimer.data = 0; - sftimer.function = &sunfire_timer; - sftimer.expires = jiffies + (HZ >> 1); - add_timer(&sftimer); + (void) of_register_driver(&fhc_driver, &of_platform_bus_type); + (void) of_register_driver(&clock_board_driver, &of_platform_bus_type); + return 0; } + +subsys_initcall(sunfire_init); diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 9d7dfb8cc27..2ead310066d 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -659,7 +659,6 @@ fatal_memory_error: static int __init sbus_init(void) { - extern void firetruck_init(void); struct device_node *dp; for_each_node_by_name(dp, "sbus") { @@ -669,8 +668,6 @@ static int __init sbus_init(void) of_propagate_archdata(op); } - firetruck_init(); - return 0; } diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 75d82e293c8..8cc1892c554 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1673,8 +1673,6 @@ void __cpuinit sun4v_ktsb_register(void) /* paging_init() sets up the page tables */ -extern void central_probe(void); - static unsigned long last_valid_pfn; pgd_t swapper_pg_dir[2048]; @@ -1844,7 +1842,6 @@ void __init paging_init(void) printk("Booting Linux...\n"); - central_probe(); cpu_probe(); } -- cgit v1.2.3 From 5110bd21b8af4199b8332c0ab0b23367556653d3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 31 Aug 2008 20:59:37 -0700 Subject: sparc: remove CONFIG_SUN4 While doing some easy cleanups on the sparc code I noticed that the CONFIG_SUN4 code seems to be worse than the rest - there were some "I don't know how it should work, but the current code definitely cannot work." places. And while I have seen people running Linux on machines like a SPARCstation 5 a few years ago I don't recall having seen sun4 machines, even less ones running Linux. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 15 --- arch/sparc/include/asm/asmmacro.h | 5 - arch/sparc/include/asm/elf_32.h | 7 +- arch/sparc/include/asm/mostek.h | 40 +------ arch/sparc/include/asm/oplib_32.h | 1 - arch/sparc/include/asm/page_32.h | 5 +- arch/sparc/include/asm/pgtable_32.h | 4 - arch/sparc/include/asm/sun4paddr.h | 56 ---------- arch/sparc/include/asm/sun4prom.h | 83 --------------- arch/sparc/include/asm/system_32.h | 8 +- arch/sparc/include/asm/system_64.h | 5 +- arch/sparc/include/asm/thread_info_32.h | 4 - arch/sparc/include/asm/timer_32.h | 8 +- arch/sparc/include/asm/vac-ops.h | 7 -- arch/sparc/kernel/Makefile | 1 - arch/sparc/kernel/devices.c | 2 +- arch/sparc/kernel/entry.S | 54 ---------- arch/sparc/kernel/head.S | 28 +---- arch/sparc/kernel/idprom.c | 7 -- arch/sparc/kernel/process.c | 2 +- arch/sparc/kernel/prom.c | 1 - arch/sparc/kernel/setup.c | 8 +- arch/sparc/kernel/sun4c_irq.c | 58 +++------- arch/sparc/kernel/sun4setup.c | 75 ------------- arch/sparc/kernel/sys_sparc.c | 8 +- arch/sparc/kernel/time.c | 162 +--------------------------- arch/sparc/mm/Makefile | 9 +- arch/sparc/mm/btfixup.c | 6 +- arch/sparc/mm/fault.c | 2 +- arch/sparc/mm/nosrmmu.c | 58 ---------- arch/sparc/mm/sun4c.c | 182 ++++++++------------------------ arch/sparc/prom/Makefile | 2 - arch/sparc/prom/bootstr.c | 4 - arch/sparc/prom/console.c | 3 - arch/sparc/prom/init.c | 12 --- arch/sparc/prom/memory.c | 14 --- arch/sparc/prom/sun4prom.c | 161 ---------------------------- 37 files changed, 82 insertions(+), 1025 deletions(-) delete mode 100644 arch/sparc/include/asm/sun4paddr.h delete mode 100644 arch/sparc/include/asm/sun4prom.h delete mode 100644 arch/sparc/kernel/sun4setup.c delete mode 100644 arch/sparc/mm/nosrmmu.c delete mode 100644 arch/sparc/prom/sun4prom.c (limited to 'arch') diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index abcd82bfcb9..a4c7fb7afc8 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -210,17 +210,6 @@ config SUN_PM Enable power management and CPU standby features on supported SPARC platforms. -config SUN4 - bool "Support for SUN4 machines (disables SUN4[CDM] support)" - depends on !SMP - default n - help - Say Y here if, and only if, your machine is a sun4. Note that - a kernel compiled with this option will run only on sun4. - (And the current version will probably work only on sun4/330.) - -if !SUN4 - config PCI bool "Support for PCI and PS/2 keyboard/mouse" help @@ -233,8 +222,6 @@ config PCI_SYSCALL source "drivers/pci/Kconfig" -endif - config SUN_OPENPROMFS tristate "Openprom tree appears in /proc/openprom" help @@ -266,9 +253,7 @@ source "net/Kconfig" source "drivers/Kconfig" -if !SUN4 source "drivers/sbus/char/Kconfig" -endif # This one must be before the filesystem configs. -DaveM diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h index a619a4d97aa..a995bf8aba3 100644 --- a/arch/sparc/include/asm/asmmacro.h +++ b/arch/sparc/include/asm/asmmacro.h @@ -34,12 +34,7 @@ /* sun4 probably wants half word accesses to ASI_SEGMAP, while sun4c+ likes byte accesses. These are to avoid ifdef mania. */ -#ifdef CONFIG_SUN4 -#define lduXa lduha -#define stXa stha -#else #define lduXa lduba #define stXa stba -#endif #endif /* !(_SPARC_ASMMACRO_H) */ diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h index d043f80bc2f..b7ab6054782 100644 --- a/arch/sparc/include/asm/elf_32.h +++ b/arch/sparc/include/asm/elf_32.h @@ -105,11 +105,8 @@ typedef struct { #define ELF_DATA ELFDATA2MSB #define USE_ELF_CORE_DUMP -#ifndef CONFIG_SUN4 + #define ELF_EXEC_PAGESIZE 4096 -#else -#define ELF_EXEC_PAGESIZE 8192 -#endif /* This is the location that an ET_DYN program is loaded if exec'ed. Typical @@ -126,7 +123,7 @@ typedef struct { /* Sun4c has none of the capabilities, most sun4m's have them all. * XXX This is gross, set some global variable at boot time. -DaveM */ -#define ELF_HWCAP ((ARCH_SUN4C_SUN4) ? 0 : \ +#define ELF_HWCAP ((ARCH_SUN4C) ? 0 : \ (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \ HWCAP_SPARC_SWAP | \ ((srmmu_modtype != Cypress && \ diff --git a/arch/sparc/include/asm/mostek.h b/arch/sparc/include/asm/mostek.h index a99590c4c50..98b44dd93e4 100644 --- a/arch/sparc/include/asm/mostek.h +++ b/arch/sparc/include/asm/mostek.h @@ -128,44 +128,6 @@ struct mostek48t08 { struct mostek48t02 regs; /* Here is what we are interested in. */ }; -#ifdef CONFIG_SUN4 -enum sparc_clock_type { MSTK48T02, MSTK48T08, \ -INTERSIL, MSTK_INVALID }; -#else -enum sparc_clock_type { MSTK48T02, MSTK48T08, \ -MSTK_INVALID }; -#endif - -#ifdef CONFIG_SUN4 -/* intersil on a sun 4/260 code data from harris doc */ -struct intersil_dt { - volatile unsigned char int_csec; - volatile unsigned char int_hour; - volatile unsigned char int_min; - volatile unsigned char int_sec; - volatile unsigned char int_month; - volatile unsigned char int_day; - volatile unsigned char int_year; - volatile unsigned char int_dow; -}; - -struct intersil { - struct intersil_dt clk; - struct intersil_dt cmp; - volatile unsigned char int_intr_reg; - volatile unsigned char int_cmd_reg; -}; - -#define INTERSIL_STOP 0x0 -#define INTERSIL_START 0x8 -#define INTERSIL_INTR_DISABLE 0x0 -#define INTERSIL_INTR_ENABLE 0x10 -#define INTERSIL_32K 0x0 -#define INTERSIL_NORMAL 0x0 -#define INTERSIL_24H 0x4 -#define INTERSIL_INT_100HZ 0x2 - -/* end of intersil info */ -#endif +enum sparc_clock_type { MSTK48T02, MSTK48T08, MSTK_INVALID }; #endif /* !(_SPARC_MOSTEK_H) */ diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index b2631da259e..699da05235c 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -21,7 +21,6 @@ enum prom_major_version { PROM_V2, /* sun4c and early sun4m V2 prom */ PROM_V3, /* sun4m and later, up to sun4d/sun4e machines V3 */ PROM_P1275, /* IEEE compliant ISA based Sun PROM, only sun4u */ - PROM_SUN4, /* Old sun4 proms are totally different, but we'll shoehorn it to make it fit */ }; extern enum prom_major_version prom_vers; diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h index cf5fb70ca1c..d1806edc095 100644 --- a/arch/sparc/include/asm/page_32.h +++ b/arch/sparc/include/asm/page_32.h @@ -8,11 +8,8 @@ #ifndef _SPARC_PAGE_H #define _SPARC_PAGE_H -#ifdef CONFIG_SUN4 -#define PAGE_SHIFT 13 -#else #define PAGE_SHIFT 12 -#endif + #ifndef __ASSEMBLY__ /* I have my suspicions... -DaveM */ #define PAGE_SIZE (1UL << PAGE_SHIFT) diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 08237fda887..e0cabe790ec 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h @@ -14,11 +14,7 @@ #include #include #include -#ifdef CONFIG_SUN4 -#include -#else #include -#endif #include #include #include diff --git a/arch/sparc/include/asm/sun4paddr.h b/arch/sparc/include/asm/sun4paddr.h deleted file mode 100644 index d52985f19f4..00000000000 --- a/arch/sparc/include/asm/sun4paddr.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * sun4paddr.h: Various physical addresses on sun4 machines - * - * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) - * Copyright (C) 1998 Chris Davis (cdavis@cois.on.ca) - * - * Now supports more sun4's - */ - -#ifndef _SPARC_SUN4PADDR_H -#define _SPARC_SUN4PADDR_H - -#define SUN4_IE_PHYSADDR 0xf5000000 -#define SUN4_UNUSED_PHYSADDR 0 - -/* these work for me */ -#define SUN4_200_MEMREG_PHYSADDR 0xf4000000 -#define SUN4_200_CLOCK_PHYSADDR 0xf3000000 -#define SUN4_200_BWTWO_PHYSADDR 0xfd000000 -#define SUN4_200_ETH_PHYSADDR 0xf6000000 -#define SUN4_200_SI_PHYSADDR 0xff200000 - -/* these were here before */ -#define SUN4_300_MEMREG_PHYSADDR 0xf4000000 -#define SUN4_300_CLOCK_PHYSADDR 0xf2000000 -#define SUN4_300_TIMER_PHYSADDR 0xef000000 -#define SUN4_300_ETH_PHYSADDR 0xf9000000 -#define SUN4_300_BWTWO_PHYSADDR 0xfb400000 -#define SUN4_300_DMA_PHYSADDR 0xfa001000 -#define SUN4_300_ESP_PHYSADDR 0xfa000000 - -/* Are these right? */ -#define SUN4_400_MEMREG_PHYSADDR 0xf4000000 -#define SUN4_400_CLOCK_PHYSADDR 0xf2000000 -#define SUN4_400_TIMER_PHYSADDR 0xef000000 -#define SUN4_400_ETH_PHYSADDR 0xf9000000 -#define SUN4_400_BWTWO_PHYSADDR 0xfb400000 -#define SUN4_400_DMA_PHYSADDR 0xfa001000 -#define SUN4_400_ESP_PHYSADDR 0xfa000000 - -/* - these are the actual values set and used in the code. Unused items set - to SUN_UNUSED_PHYSADDR - */ - -extern int sun4_memreg_physaddr; /* memory register (ecc?) */ -extern int sun4_clock_physaddr; /* system clock */ -extern int sun4_timer_physaddr; /* timer, where applicable */ -extern int sun4_eth_physaddr; /* onboard ethernet (ie/le) */ -extern int sun4_si_physaddr; /* sun3 scsi adapter */ -extern int sun4_bwtwo_physaddr; /* onboard bw2 */ -extern int sun4_dma_physaddr; /* scsi dma */ -extern int sun4_esp_physaddr; /* esp scsi */ -extern int sun4_ie_physaddr; /* interrupt enable */ - -#endif /* !(_SPARC_SUN4PADDR_H) */ diff --git a/arch/sparc/include/asm/sun4prom.h b/arch/sparc/include/asm/sun4prom.h deleted file mode 100644 index 9c8b4cbf629..00000000000 --- a/arch/sparc/include/asm/sun4prom.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * sun4prom.h -- interface to sun4 PROM monitor. We don't use most of this, - * so most of these are just placeholders. - */ - -#ifndef _SUN4PROM_H_ -#define _SUN4PROM_H_ - -/* - * Although this looks similar to an romvec for a OpenProm machine, it is - * actually closer to what was used in the Sun2 and Sun3. - * - * V2 entries exist only in version 2 PROMs and later, V3 in version 3 and later. - * - * Many of the function prototypes are guesses. Some are certainly wrong. - * Use with care. - */ - -typedef struct { - char *initSP; /* Initial system stack ptr */ - void (*startmon)(void); /* Initial PC for hardware */ - int *diagberr; /* Bus err handler for diags */ - struct linux_arguments_v0 **bootParam; /* Info for bootstrapped pgm */ - unsigned int *memorysize; /* Usable memory in bytes */ - unsigned char (*getchar)(void); /* Get char from input device */ - void (*putchar)(char); /* Put char to output device */ - int (*mayget)(void); /* Maybe get char, or -1 */ - int (*mayput)(int); /* Maybe put char, or -1 */ - unsigned char *echo; /* Should getchar echo? */ - unsigned char *insource; /* Input source selector */ - unsigned char *outsink; /* Output sink selector */ - int (*getkey)(void); /* Get next key if one exists */ - void (*initgetkey)(void); /* Initialize get key */ - unsigned int *translation; /* Kbd translation selector */ - unsigned char *keybid; /* Keyboard ID byte */ - int *screen_x; /* V2: Screen x pos (r/o) */ - int *screen_y; /* V2: Screen y pos (r/o) */ - struct keybuf *keybuf; /* Up/down keycode buffer */ - char *monid; /* Monitor version ID */ - void (*fbwritechar)(char); /* Write a character to FB */ - int *fbAddr; /* Address of frame buffer */ - char **font; /* Font table for FB */ - void (*fbwritestr)(char *); /* Write string to FB */ - void (*reboot)(char *); /* e.g. reboot("sd()vmlinux") */ - unsigned char *linebuf; /* The line input buffer */ - unsigned char **lineptr; /* Cur pointer into linebuf */ - int *linesize; /* length of line in linebuf */ - void (*getline)(char *); /* Get line from user */ - unsigned char (*getnextchar)(void); /* Get next char from linebuf */ - unsigned char (*peeknextchar)(void); /* Peek at next char */ - int *fbthere; /* =1 if frame buffer there */ - int (*getnum)(void); /* Grab hex num from line */ - int (*printf)(char *, ...); /* See prom_printf() instead */ - void (*printhex)(int); /* Format N digits in hex */ - unsigned char *leds; /* RAM copy of LED register */ - void (*setLEDs)(unsigned char *); /* Sets LED's and RAM copy */ - void (*NMIaddr)(void *); /* Addr for level 7 vector */ - void (*abortentry)(void); /* Entry for keyboard abort */ - int *nmiclock; /* Counts up in msec */ - int *FBtype; /* Frame buffer type */ - unsigned int romvecversion; /* Version number for this romvec */ - struct globram *globram; /* monitor global variables ??? */ - void * kbdaddr; /* Addr of keyboard in use */ - int *keyrinit; /* ms before kbd repeat */ - unsigned char *keyrtick; /* ms between repetitions */ - unsigned int *memoryavail; /* V1: Main mem usable size */ - long *resetaddr; /* where to jump on a reset */ - long *resetmap; /* pgmap entry for resetaddr */ - void (*exittomon)(void); /* Exit from user program */ - unsigned char **memorybitmap; /* V1: &{0 or &bits} */ - void (*setcxsegmap)(int ctxt, char *va, int pmeg); /* Set seg in any context */ - void (**vector_cmd)(void *); /* V2: Handler for 'v' cmd */ - unsigned long *expectedtrapsig; /* V3: Location of the expected trap signal */ - unsigned long *trapvectorbasetable; /* V3: Address of the trap vector table */ - int unused1; - int unused2; - int unused3; - int unused4; -} linux_sun4_romvec; - -extern linux_sun4_romvec *sun4_romvec; - -#endif /* _SUN4PROM_H_ */ diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h index b4b024445fc..4e18ef27233 100644 --- a/arch/sparc/include/asm/system_32.h +++ b/arch/sparc/include/asm/system_32.h @@ -34,13 +34,7 @@ enum sparc_cpu { extern enum sparc_cpu sparc_cpu_model; -#ifndef CONFIG_SUN4 -#define ARCH_SUN4C_SUN4 (sparc_cpu_model==sun4c) -#define ARCH_SUN4 0 -#else -#define ARCH_SUN4C_SUN4 1 -#define ARCH_SUN4 1 -#endif +#define ARCH_SUN4C (sparc_cpu_model==sun4c) #define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */ diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h index db9e742a406..98acb3b9d4a 100644 --- a/arch/sparc/include/asm/system_64.h +++ b/arch/sparc/include/asm/system_64.h @@ -26,9 +26,8 @@ enum sparc_cpu { #define sparc_cpu_model sun4u -/* This cannot ever be a sun4c nor sun4 :) That's just history. */ -#define ARCH_SUN4C_SUN4 0 -#define ARCH_SUN4 0 +/* This cannot ever be a sun4c :) That's just history. */ +#define ARCH_SUN4C 0 extern char reboot_command[]; diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index cbb892d0dff..29899fd5b1b 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h @@ -80,11 +80,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); /* * thread information allocation */ -#if PAGE_SHIFT == 13 -#define THREAD_INFO_ORDER 0 -#else /* PAGE_SHIFT */ #define THREAD_INFO_ORDER 1 -#endif #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 361e53898dd..adab3def007 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -9,7 +9,6 @@ #define _SPARC_TIMER_H #include /* For SUN4M_NCPUS */ -#include #include /* Timer structures. The interrupt timer has two properties which @@ -34,12 +33,7 @@ struct sun4c_timer_info { __volatile__ unsigned int timer_limit14; }; -#define SUN4C_TIMER_PHYSADDR 0xf3000000 -#ifdef CONFIG_SUN4 -#define SUN_TIMER_PHYSADDR SUN4_300_TIMER_PHYSADDR -#else -#define SUN_TIMER_PHYSADDR SUN4C_TIMER_PHYSADDR -#endif +#define SUN_TIMER_PHYSADDR 0xf3000000 /* A sun4m has two blocks of registers which are probably of the same * structure. LSI Logic's L64851 is told to _decrement_ from the limit diff --git a/arch/sparc/include/asm/vac-ops.h b/arch/sparc/include/asm/vac-ops.h index d10527611f1..a63e88ef042 100644 --- a/arch/sparc/include/asm/vac-ops.h +++ b/arch/sparc/include/asm/vac-ops.h @@ -76,11 +76,7 @@ * cacheable bit in the pte's of all such pages. */ -#ifdef CONFIG_SUN4 -#define S4CVAC_BADBITS 0x0001e000 -#else #define S4CVAC_BADBITS 0x0000f000 -#endif /* The following is true if vaddr1 and vaddr2 would cause * a 'bad alias'. @@ -94,10 +90,7 @@ */ struct sun4c_vac_props { unsigned int num_bytes; /* Size of the cache */ - unsigned int num_lines; /* Number of cache lines */ unsigned int do_hwflushes; /* Hardware flushing available? */ - enum { VAC_NONE, VAC_WRITE_THROUGH, - VAC_WRITE_BACK } type; /* What type of VAC? */ unsigned int linesize; /* Size of each line in bytes */ unsigned int log2lsize; /* log2(linesize) */ unsigned int on; /* VAC is enabled */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index a430231647e..2d658209509 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -18,7 +18,6 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ devres-y = ../../../kernel/irq/devres.o obj-$(CONFIG_PCI) += pcic.o -obj-$(CONFIG_SUN4) += sun4setup.o obj-$(CONFIG_SMP) += trampoline.o smp.o sun4m_smp.o sun4d_smp.o obj-$(CONFIG_SUN_AUXIO) += auxio.o obj-$(CONFIG_SUN_PM) += apc.o pmc.o diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index b240b8863fd..ad656b044b8 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -143,7 +143,7 @@ void __init device_scan(void) #endif clock_stop_probe(); - if (ARCH_SUN4C_SUN4) + if (ARCH_SUN4C) sun4c_probe_memerr_reg(); return; diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index e8cdf715a54..68689facaaa 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -20,11 +20,7 @@ #include #include #include -#ifdef CONFIG_SUN4 -#include -#else #include -#endif #include #include #include @@ -775,11 +771,7 @@ vac_linesize_patch_32: subcc %l7, 32, %l7 * Ugly, but we cant use hardware flushing on the sun4 and we'd require * two instructions (Anton) */ -#ifdef CONFIG_SUN4 -vac_hwflush_patch1_on: nop -#else vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 -#endif vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG @@ -798,42 +790,10 @@ vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG ! %l7 = 1 for textfault ! We want error in %l5, vaddr in %l6 sun4c_fault: -#ifdef CONFIG_SUN4 - sethi %hi(sun4c_memerr_reg), %l4 - ld [%l4+%lo(sun4c_memerr_reg)], %l4 ! memerr ctrl reg addr - ld [%l4], %l6 ! memerr ctrl reg - ld [%l4 + 4], %l5 ! memerr vaddr reg - andcc %l6, 0x80, %g0 ! check for error type - st %g0, [%l4 + 4] ! clear the error - be 0f ! normal error - sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr - - call prom_halt ! something weird happened - ! what exactly did happen? - ! what should we do here? - -0: or %l4, %lo(AC_BUS_ERROR), %l4 ! bus err reg addr - lduba [%l4] ASI_CONTROL, %l6 ! bus err reg - - cmp %l7, 1 ! text fault? - be 1f ! yes - nop - - ld [%l1], %l4 ! load instruction that caused fault - srl %l4, 21, %l4 - andcc %l4, 1, %g0 ! store instruction? - - be 1f ! no - sethi %hi(SUN4C_SYNC_BADWRITE), %l4 ! yep - ! %lo(SUN4C_SYNC_BADWRITE) = 0 - or %l4, %l6, %l6 ! set write bit to emulate sun4c -1: -#else sethi %hi(AC_SYNC_ERR), %l4 add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 lda [%l6] ASI_CONTROL, %l5 ! Address lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit -#endif andn %l5, 0xfff, %l5 ! Encode all info into l7 srl %l6, 14, %l4 @@ -880,12 +840,7 @@ sun4c_fault: or %l4, %lo(swapper_pg_dir), %l4 sll %l6, 2, %l6 ld [%l4 + %l6], %l4 -#ifdef CONFIG_SUN4 - sethi %hi(PAGE_MASK), %l6 - andcc %l4, %l6, %g0 -#else andcc %l4, PAGE_MASK, %g0 -#endif be sun4c_fault_fromuser lduXa [%l5] ASI_SEGMAP, %l4 @@ -937,11 +892,7 @@ invalid_segment_patch1: ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr ! Flush segment from the cache. -#ifdef CONFIG_SUN4 - sethi %hi((128 * 1024)), %l7 -#else sethi %hi((64 * 1024)), %l7 -#endif 9: vac_hwflush_patch1: vac_linesize_patch: @@ -1029,12 +980,7 @@ invalid_segment_patch2: or %l4, %lo(swapper_pg_dir), %l4 sll %l3, 2, %l3 ld [%l4 + %l3], %l4 -#ifndef CONFIG_SUN4 and %l4, PAGE_MASK, %l4 -#else - sethi %hi(PAGE_MASK), %l6 - and %l4, %l6, %l4 -#endif srl %l5, (PAGE_SHIFT - 2), %l6 and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 50d9a16af79..2d325fd8457 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -63,15 +63,9 @@ cputypvar_sun4m: .align 4 -#ifndef CONFIG_SUN4 sun4_notsup: - .asciz "Sparc-Linux sun4 needs a specially compiled kernel, turn CONFIG_SUN4 on.\n\n" + .asciz "Sparc-Linux sun4 support does no longer exist.\n\n" .align 4 -#else -sun4cdm_notsup: - .asciz "Kernel compiled with CONFIG_SUN4 cannot run on SUN4C/SUN4M/SUN4D\nTurn CONFIG_SUN4 off.\n\n" - .align 4 -#endif sun4e_notsup: .asciz "Sparc-Linux sun4e support does not exist\n\n" @@ -780,15 +774,6 @@ execute_in_high_mem: nop found_version: -#ifdef CONFIG_SUN4 -/* For people who try sun4 kernels, even if Configure.help advises them. */ - ld [%g7 + 0x68], %o1 - set sun4cdm_notsup, %o0 - call %o1 - nop - b halt_me - nop -#endif /* Get the machine type via the mysterious romvec node operations. */ add %g7, 0x1c, %l1 @@ -1150,15 +1135,6 @@ sun4c_continue_boot: nop sun4_init: -#ifdef CONFIG_SUN4 -/* There, happy now Adrian? */ - set cputypval, %o2 ! Let everyone know we - set ' ', %o0 ! are a "sun4 " architecture - stb %o0, [%o2 + 0x4] - - b got_prop - nop -#else sethi %hi(SUN4_PROM_VECTOR+0x84), %o1 ld [%o1 + %lo(SUN4_PROM_VECTOR+0x84)], %o1 set sun4_notsup, %o0 @@ -1170,7 +1146,7 @@ sun4_init: nop 1: ba 1b ! Cannot exit into KMON nop -#endif + no_sun4e_here: ld [%g7 + 0x68], %o1 set sun4e_notsup, %o0 diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c index fc511f3c4c1..223a6582e1e 100644 --- a/arch/sparc/kernel/idprom.c +++ b/arch/sparc/kernel/idprom.c @@ -12,10 +12,6 @@ #include #include #include /* Fun with Sun released architectures. */ -#ifdef CONFIG_SUN4 -#include -extern void sun4setup(void); -#endif struct idprom *idprom; static struct idprom idprom_buffer; @@ -101,7 +97,4 @@ void __init idprom_init(void) idprom->id_ethaddr[0], idprom->id_ethaddr[1], idprom->id_ethaddr[2], idprom->id_ethaddr[3], idprom->id_ethaddr[4], idprom->id_ethaddr[5]); -#ifdef CONFIG_SUN4 - sun4setup(); -#endif } diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 4bb430940a6..e8c43ffe317 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -75,7 +75,7 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ for (;;) { - if (ARCH_SUN4C_SUN4) { + if (ARCH_SUN4C) { static int count = HZ; static unsigned long last_jiffies; static unsigned long last_faults; diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 43e86240682..eee5efcfe50 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -442,7 +442,6 @@ static void __init of_console_init(void) switch (prom_vers) { case PROM_V0: - case PROM_SUN4: skip = 0; switch (*romvec->pv_stdout) { case PROMDEV_SCREEN: diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 9e451b21202..8d5fbce1635 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -224,12 +224,6 @@ void __init setup_arch(char **cmdline_p) if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; } if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; } -#ifdef CONFIG_SUN4 - if (sparc_cpu_model != sun4) { - prom_printf("This kernel is for Sun4 architecture only.\n"); - prom_halt(); - } -#endif printk("ARCH: "); switch(sparc_cpu_model) { case sun4: @@ -263,7 +257,7 @@ void __init setup_arch(char **cmdline_p) boot_flags_init(*cmdline_p); idprom_init(); - if (ARCH_SUN4C_SUN4) + if (ARCH_SUN4C) sun4c_probe_vac(); load_mmu(); diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index a74582455cc..722d2516f28 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -130,22 +129,10 @@ static void sun4c_enable_irq(unsigned int irq_nr) volatile struct sun4c_timer_info *sun4c_timers; -#ifdef CONFIG_SUN4 -/* This is an ugly hack to work around the - current timer code, and make it work with - the sun4/260 intersil - */ -volatile struct sun4c_timer_info sun4_timer; -#endif - static void sun4c_clear_clock_irq(void) { volatile unsigned int clear_intr; -#ifdef CONFIG_SUN4 - if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) - clear_intr = sun4_timer.timer_limit10; - else -#endif + clear_intr = sun4c_timers->timer_limit10; } @@ -166,11 +153,6 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) /* Map the Timer chip, this is implemented in hardware inside * the cache chip on the sun4c. */ -#ifdef CONFIG_SUN4 - if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) - sun4c_timers = &sun4_timer; - else -#endif sun4c_timers = ioremap(SUN_TIMER_PHYSADDR, sizeof(struct sun4c_timer_info)); @@ -206,28 +188,22 @@ void __init sun4c_init_IRQ(void) { struct linux_prom_registers int_regs[2]; int ie_node; - - if (ARCH_SUN4) { - interrupt_enable = (char *) - ioremap(sun4_ie_physaddr, PAGE_SIZE); - } else { - struct resource phyres; - - ie_node = prom_searchsiblings (prom_getchild(prom_root_node), - "interrupt-enable"); - if(ie_node == 0) - panic("Cannot find /interrupt-enable node"); - - /* Depending on the "address" property is bad news... */ - interrupt_enable = NULL; - if (prom_getproperty(ie_node, "reg", (char *) int_regs, - sizeof(int_regs)) != -1) { - memset(&phyres, 0, sizeof(struct resource)); - phyres.flags = int_regs[0].which_io; - phyres.start = int_regs[0].phys_addr; - interrupt_enable = (char *) of_ioremap(&phyres, 0, - int_regs[0].reg_size, "sun4c_intr"); - } + struct resource phyres; + + ie_node = prom_searchsiblings (prom_getchild(prom_root_node), + "interrupt-enable"); + if(ie_node == 0) + panic("Cannot find /interrupt-enable node"); + + /* Depending on the "address" property is bad news... */ + interrupt_enable = NULL; + if (prom_getproperty(ie_node, "reg", (char *) int_regs, + sizeof(int_regs)) != -1) { + memset(&phyres, 0, sizeof(struct resource)); + phyres.flags = int_regs[0].which_io; + phyres.start = int_regs[0].phys_addr; + interrupt_enable = (char *) of_ioremap(&phyres, 0, + int_regs[0].reg_size, "sun4c_intr"); } if (!interrupt_enable) panic("Cannot map interrupt_enable"); diff --git a/arch/sparc/kernel/sun4setup.c b/arch/sparc/kernel/sun4setup.c deleted file mode 100644 index 229a52f55f1..00000000000 --- a/arch/sparc/kernel/sun4setup.c +++ /dev/null @@ -1,75 +0,0 @@ -/* sun4setup.c: Setup the hardware address of various items in the sun4 - * architecture. Called from idprom_init - * - * Copyright (C) 1998 Chris G. Davis (cdavis@cois.on.ca) - */ - -#include -#include -#include -#include -#include - -int sun4_memreg_physaddr; -int sun4_ie_physaddr; -int sun4_clock_physaddr; -int sun4_timer_physaddr; -int sun4_eth_physaddr; -int sun4_si_physaddr; -int sun4_bwtwo_physaddr; -int sun4_zs0_physaddr; -int sun4_zs1_physaddr; -int sun4_dma_physaddr; -int sun4_esp_physaddr; -int sun4_ie_physaddr; - -void __init sun4setup(void) -{ - printk("Sun4 Hardware Setup v1.0 18/May/98 Chris Davis (cdavis@cois.on.ca). "); - /* - setup standard sun4 info - */ - sun4_ie_physaddr=SUN4_IE_PHYSADDR; - - /* - setup model specific info - */ - switch(idprom->id_machtype) { - case (SM_SUN4 | SM_4_260 ): - printk("Setup for a SUN4/260\n"); - sun4_memreg_physaddr=SUN4_200_MEMREG_PHYSADDR; - sun4_clock_physaddr=SUN4_200_CLOCK_PHYSADDR; - sun4_timer_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_eth_physaddr=SUN4_200_ETH_PHYSADDR; - sun4_si_physaddr=SUN4_200_SI_PHYSADDR; - sun4_bwtwo_physaddr=SUN4_200_BWTWO_PHYSADDR; - sun4_dma_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_esp_physaddr=SUN4_UNUSED_PHYSADDR; - break; - case (SM_SUN4 | SM_4_330 ): - printk("Setup for a SUN4/330\n"); - sun4_memreg_physaddr=SUN4_300_MEMREG_PHYSADDR; - sun4_clock_physaddr=SUN4_300_CLOCK_PHYSADDR; - sun4_timer_physaddr=SUN4_300_TIMER_PHYSADDR; - sun4_eth_physaddr=SUN4_300_ETH_PHYSADDR; - sun4_si_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_bwtwo_physaddr=SUN4_300_BWTWO_PHYSADDR; - sun4_dma_physaddr=SUN4_300_DMA_PHYSADDR; - sun4_esp_physaddr=SUN4_300_ESP_PHYSADDR; - break; - case (SM_SUN4 | SM_4_470 ): - printk("Setup for a SUN4/470\n"); - sun4_memreg_physaddr=SUN4_400_MEMREG_PHYSADDR; - sun4_clock_physaddr=SUN4_400_CLOCK_PHYSADDR; - sun4_timer_physaddr=SUN4_400_TIMER_PHYSADDR; - sun4_eth_physaddr=SUN4_400_ETH_PHYSADDR; - sun4_si_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_bwtwo_physaddr=SUN4_400_BWTWO_PHYSADDR; - sun4_dma_physaddr=SUN4_400_DMA_PHYSADDR; - sun4_esp_physaddr=SUN4_400_ESP_PHYSADDR; - break; - default: - ; - } -} - diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 4d73421559c..03035c852a4 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -53,7 +53,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi /* See asm-sparc/uaccess.h */ if (len > TASK_SIZE - PAGE_SIZE) return -ENOMEM; - if (ARCH_SUN4C_SUN4 && len > 0x20000000) + if (ARCH_SUN4C && len > 0x20000000) return -ENOMEM; if (!addr) addr = TASK_UNMAPPED_BASE; @@ -65,7 +65,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { /* At this point: (!vmm || addr < vmm->vm_end). */ - if (ARCH_SUN4C_SUN4 && addr < 0xe0000000 && 0x20000000 - len < addr) { + if (ARCH_SUN4C && addr < 0xe0000000 && 0x20000000 - len < addr) { addr = PAGE_OFFSET; vmm = find_vma(current->mm, PAGE_OFFSET); } @@ -81,7 +81,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi asmlinkage unsigned long sparc_brk(unsigned long brk) { - if(ARCH_SUN4C_SUN4) { + if(ARCH_SUN4C) { if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000)) return current->mm->brk; } @@ -221,7 +221,7 @@ out: int sparc_mmap_check(unsigned long addr, unsigned long len) { - if (ARCH_SUN4C_SUN4 && + if (ARCH_SUN4C && (len > 0x20000000 || (addr < 0xe0000000 && addr + len > 0x20000000))) return -EINVAL; diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 339c4762fbc..f0a2874b04e 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -54,27 +53,6 @@ static struct mostek48t08 __iomem *mstk48t08_regs = NULL; static int set_rtc_mmss(unsigned long); static int sbus_do_settimeofday(struct timespec *tv); -#ifdef CONFIG_SUN4 -struct intersil *intersil_clock; -#define intersil_cmd(intersil_reg, intsil_cmd) intersil_reg->int_cmd_reg = \ - (intsil_cmd) - -#define intersil_intr(intersil_reg, intsil_cmd) intersil_reg->int_intr_reg = \ - (intsil_cmd) - -#define intersil_start(intersil_reg) intersil_cmd(intersil_reg, \ - ( INTERSIL_START | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\ - INTERSIL_INTR_ENABLE)) - -#define intersil_stop(intersil_reg) intersil_cmd(intersil_reg, \ - ( INTERSIL_STOP | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\ - INTERSIL_INTR_ENABLE)) - -#define intersil_read_intr(intersil_reg, towhere) towhere = \ - intersil_reg->int_intr_reg - -#endif - unsigned long profile_pc(struct pt_regs *regs) { extern char __copy_user_begin[], __copy_user_end[]; @@ -117,15 +95,7 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) /* Protect counter clear so that do_gettimeoffset works */ write_seqlock(&xtime_lock); -#ifdef CONFIG_SUN4 - if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) || - (idprom->id_machtype == (SM_SUN4 | SM_4_110))) { - int temp; - intersil_read_intr(intersil_clock, temp); - /* re-enable the irq */ - enable_pil_irq(10); - } -#endif + clear_clock_irq(); do_timer(1); @@ -250,55 +220,6 @@ static void __devinit mostek_set_system_time(void) spin_unlock_irq(&mostek_lock); } -/* Probe for the real time clock chip on Sun4 */ -static inline void sun4_clock_probe(void) -{ -#ifdef CONFIG_SUN4 - int temp; - struct resource r; - - memset(&r, 0, sizeof(r)); - if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) { - sp_clock_typ = MSTK48T02; - r.start = sun4_clock_physaddr; - mstk48t02_regs = of_ioremap(&r, 0, - sizeof(struct mostek48t02), NULL); - mstk48t08_regs = NULL; /* To catch weirdness */ - intersil_clock = NULL; /* just in case */ - - /* Kick start the clock if it is completely stopped. */ - if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) - kick_start_clock(); - } else if( idprom->id_machtype == (SM_SUN4 | SM_4_260)) { - /* intersil setup code */ - printk("Clock: INTERSIL at %8x ",sun4_clock_physaddr); - sp_clock_typ = INTERSIL; - r.start = sun4_clock_physaddr; - intersil_clock = (struct intersil *) - of_ioremap(&r, 0, sizeof(*intersil_clock), "intersil"); - mstk48t02_regs = 0; /* just be sure */ - mstk48t08_regs = NULL; /* ditto */ - /* initialise the clock */ - - intersil_intr(intersil_clock,INTERSIL_INT_100HZ); - - intersil_start(intersil_clock); - - intersil_read_intr(intersil_clock, temp); - while (!(temp & 0x80)) - intersil_read_intr(intersil_clock, temp); - - intersil_read_intr(intersil_clock, temp); - while (!(temp & 0x80)) - intersil_read_intr(intersil_clock, temp); - - intersil_stop(intersil_clock); - - } -#endif -} - -#ifndef CONFIG_SUN4 static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; @@ -365,7 +286,6 @@ static int __init clock_init(void) * need to see the clock registers. */ fs_initcall(clock_init); -#endif /* !CONFIG_SUN4 */ static void __init sbus_time_init(void) { @@ -373,51 +293,8 @@ static void __init sbus_time_init(void) BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); - if (ARCH_SUN4) - sun4_clock_probe(); - sparc_init_timers(timer_interrupt); -#ifdef CONFIG_SUN4 - if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { - mostek_set_system_time(); - } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { - /* initialise the intersil on sun4 */ - unsigned int year, mon, day, hour, min, sec; - int temp; - struct intersil *iregs; - - iregs=intersil_clock; - if(!iregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - intersil_intr(intersil_clock,INTERSIL_INT_100HZ); - disable_pil_irq(10); - intersil_stop(iregs); - intersil_read_intr(intersil_clock, temp); - - temp = iregs->clk.int_csec; - - sec = iregs->clk.int_sec; - min = iregs->clk.int_min; - hour = iregs->clk.int_hour; - day = iregs->clk.int_day; - mon = iregs->clk.int_month; - year = MSTK_CVT_YEAR(iregs->clk.int_year); - - enable_pil_irq(10); - intersil_start(iregs); - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec); - } -#endif - /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */ local_irq_enable(); } @@ -532,43 +409,6 @@ static int set_rtc_mmss(unsigned long nowtime) int real_seconds, real_minutes, mostek_minutes; struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; unsigned long flags; -#ifdef CONFIG_SUN4 - struct intersil *iregs = intersil_clock; - int temp; -#endif - - /* Not having a register set can lead to trouble. */ - if (!regs) { -#ifdef CONFIG_SUN4 - if(!iregs) - return -1; - else { - temp = iregs->clk.int_csec; - - mostek_minutes = iregs->clk.int_min; - - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - mostek_minutes) < 30) { - intersil_stop(iregs); - iregs->clk.int_sec=real_seconds; - iregs->clk.int_min=real_minutes; - intersil_start(iregs); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - mostek_minutes, real_minutes); - return -1; - } - - return 0; - } -#endif - } spin_lock_irqsave(&mostek_lock, flags); /* Read the current RTC minutes. */ diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index 109c8b22cb3..ea88955d97f 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile @@ -3,13 +3,8 @@ EXTRA_AFLAGS := -ansi -obj-y := fault.o init.o loadmmu.o generic.o extable.o btfixup.o - -ifeq ($(CONFIG_SUN4),y) -obj-y += nosrmmu.o -else -obj-y += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o -endif +obj-y := fault.o init.o loadmmu.o generic.o extable.o btfixup.o \ + srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o ifdef CONFIG_HIGHMEM obj-y += highmem.o diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c index a312d127d47..5175ac2f482 100644 --- a/arch/sparc/mm/btfixup.c +++ b/arch/sparc/mm/btfixup.c @@ -20,11 +20,7 @@ extern char *srmmu_name; static char version[] __initdata = "Boot time fixup v1.6. 4/Mar/98 Jakub Jelinek (jj@ultra.linux.cz). Patching kernel for "; -#ifdef CONFIG_SUN4 -static char str_sun4c[] __initdata = "sun4\n"; -#else static char str_sun4c[] __initdata = "sun4c\n"; -#endif static char str_srmmu[] __initdata = "srmmu[%s]/"; static char str_iommu[] __initdata = "iommu\n"; static char str_iounit[] __initdata = "io-unit\n"; @@ -86,7 +82,7 @@ void __init btfixup(void) if (!visited) { visited++; printk(version); - if (ARCH_SUN4C_SUN4) + if (ARCH_SUN4C) printk(str_sun4c); else { printk(str_srmmu, srmmu_name); diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c index 3604c2e8670..a507e117466 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault.c @@ -191,7 +191,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, * only copy the information from the master page table, * nothing more. */ - if (!ARCH_SUN4C_SUN4 && address >= TASK_SIZE) + if (!ARCH_SUN4C && address >= TASK_SIZE) goto vmalloc_fault; info.si_code = SEGV_MAPERR; diff --git a/arch/sparc/mm/nosrmmu.c b/arch/sparc/mm/nosrmmu.c deleted file mode 100644 index 4f061bb6ce7..00000000000 --- a/arch/sparc/mm/nosrmmu.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * nosrmmu.c: This file is a bunch of dummies for sun4 compiles, - * so that it does not need srmmu and avoid ifdefs. - * - * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include -#include -#include -#include - -static char shouldnothappen[] __initdata = "SUN4 kernel can only run on SUN4\n"; - -enum mbus_module srmmu_modtype; -void *srmmu_nocache_pool; - -int vac_cache_size = 0; - -static void __init should_not_happen(void) -{ - prom_printf(shouldnothappen); - prom_halt(); -} - -void __init srmmu_frob_mem_map(unsigned long start_mem) -{ - should_not_happen(); -} - -unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long end_mem) -{ - should_not_happen(); - return 0; -} - -void __init ld_mmu_srmmu(void) -{ - should_not_happen(); -} - -void srmmu_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus_type, int rdonly) -{ -} - -void srmmu_unmapioaddr(unsigned long virt_addr) -{ -} - -__u32 iounit_map_dma_init(struct sbus_bus *sbus, int size) -{ - return 0; -} - -__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus) -{ - return 0; -} diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index f289e7ce902..95070a1e1b7 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -52,15 +51,11 @@ extern int num_segmaps, num_contexts; extern unsigned long page_kernel; -#ifdef CONFIG_SUN4 -#define SUN4C_VAC_SIZE sun4c_vacinfo.num_bytes -#else /* That's it, we prom_halt() on sun4c if the cache size is something other than 65536. * So let's save some cycles and just use that everywhere except for that bootup * sanity check. */ #define SUN4C_VAC_SIZE 65536 -#endif #define SUN4C_KERNEL_BUCKETS 32 @@ -285,75 +280,32 @@ void __init sun4c_probe_vac(void) { sun4c_disable_vac(); - if (ARCH_SUN4) { - switch (idprom->id_machtype) { - - case (SM_SUN4|SM_4_110): - sun4c_vacinfo.type = VAC_NONE; - sun4c_vacinfo.num_bytes = 0; - sun4c_vacinfo.linesize = 0; - sun4c_vacinfo.do_hwflushes = 0; - prom_printf("No VAC. Get some bucks and buy a real computer."); - prom_halt(); - break; - - case (SM_SUN4|SM_4_260): - sun4c_vacinfo.type = VAC_WRITE_BACK; - sun4c_vacinfo.num_bytes = 128 * 1024; - sun4c_vacinfo.linesize = 16; - sun4c_vacinfo.do_hwflushes = 0; - break; - - case (SM_SUN4|SM_4_330): - sun4c_vacinfo.type = VAC_WRITE_THROUGH; - sun4c_vacinfo.num_bytes = 128 * 1024; - sun4c_vacinfo.linesize = 16; - sun4c_vacinfo.do_hwflushes = 0; - break; - - case (SM_SUN4|SM_4_470): - sun4c_vacinfo.type = VAC_WRITE_BACK; - sun4c_vacinfo.num_bytes = 128 * 1024; - sun4c_vacinfo.linesize = 32; - sun4c_vacinfo.do_hwflushes = 0; - break; - - default: - prom_printf("Cannot initialize VAC - weird sun4 model idprom->id_machtype = %d", idprom->id_machtype); - prom_halt(); - }; + if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { + /* PROM on SS1 lacks this info, to be super safe we + * hard code it here since this arch is cast in stone. + */ + sun4c_vacinfo.num_bytes = 65536; + sun4c_vacinfo.linesize = 16; } else { - sun4c_vacinfo.type = VAC_WRITE_THROUGH; + sun4c_vacinfo.num_bytes = + prom_getintdefault(prom_root_node, "vac-size", 65536); + sun4c_vacinfo.linesize = + prom_getintdefault(prom_root_node, "vac-linesize", 16); + } + sun4c_vacinfo.do_hwflushes = + prom_getintdefault(prom_root_node, "vac-hwflush", 0); - if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || - (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { - /* PROM on SS1 lacks this info, to be super safe we - * hard code it here since this arch is cast in stone. - */ - sun4c_vacinfo.num_bytes = 65536; - sun4c_vacinfo.linesize = 16; - } else { - sun4c_vacinfo.num_bytes = - prom_getintdefault(prom_root_node, "vac-size", 65536); - sun4c_vacinfo.linesize = - prom_getintdefault(prom_root_node, "vac-linesize", 16); - } + if (sun4c_vacinfo.do_hwflushes == 0) sun4c_vacinfo.do_hwflushes = - prom_getintdefault(prom_root_node, "vac-hwflush", 0); - - if (sun4c_vacinfo.do_hwflushes == 0) - sun4c_vacinfo.do_hwflushes = - prom_getintdefault(prom_root_node, "vac_hwflush", 0); + prom_getintdefault(prom_root_node, "vac_hwflush", 0); - if (sun4c_vacinfo.num_bytes != 65536) { - prom_printf("WEIRD Sun4C VAC cache size, " - "tell sparclinux@vger.kernel.org"); - prom_halt(); - } + if (sun4c_vacinfo.num_bytes != 65536) { + prom_printf("WEIRD Sun4C VAC cache size, " + "tell sparclinux@vger.kernel.org"); + prom_halt(); } - sun4c_vacinfo.num_lines = - (sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize); switch (sun4c_vacinfo.linesize) { case 16: sun4c_vacinfo.log2lsize = 4; @@ -447,49 +399,18 @@ static void __init patch_kernel_fault_handler(void) static void __init sun4c_probe_mmu(void) { - if (ARCH_SUN4) { - switch (idprom->id_machtype) { - case (SM_SUN4|SM_4_110): - prom_printf("No support for 4100 yet\n"); - prom_halt(); - num_segmaps = 256; - num_contexts = 8; - break; - - case (SM_SUN4|SM_4_260): - /* should be 512 segmaps. when it get fixed */ - num_segmaps = 256; - num_contexts = 16; - break; - - case (SM_SUN4|SM_4_330): - num_segmaps = 256; - num_contexts = 16; - break; - - case (SM_SUN4|SM_4_470): - /* should be 1024 segmaps. when it get fixed */ - num_segmaps = 256; - num_contexts = 64; - break; - default: - prom_printf("Invalid SUN4 model\n"); - prom_halt(); - }; + if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { + /* Hardcode these just to be safe, PROM on SS1 does + * not have this info available in the root node. + */ + num_segmaps = 128; + num_contexts = 8; } else { - if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || - (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { - /* Hardcode these just to be safe, PROM on SS1 does - * not have this info available in the root node. - */ - num_segmaps = 128; - num_contexts = 8; - } else { - num_segmaps = - prom_getintdefault(prom_root_node, "mmu-npmg", 128); - num_contexts = - prom_getintdefault(prom_root_node, "mmu-nctx", 0x8); - } + num_segmaps = + prom_getintdefault(prom_root_node, "mmu-npmg", 128); + num_contexts = + prom_getintdefault(prom_root_node, "mmu-nctx", 0x8); } patch_kernel_fault_handler(); } @@ -501,18 +422,14 @@ void __init sun4c_probe_memerr_reg(void) int node; struct linux_prom_registers regs[1]; - if (ARCH_SUN4) { - sun4c_memerr_reg = ioremap(sun4_memreg_physaddr, PAGE_SIZE); - } else { - node = prom_getchild(prom_root_node); - node = prom_searchsiblings(prom_root_node, "memory-error"); - if (!node) - return; - if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0) - return; - /* hmm I think regs[0].which_io is zero here anyways */ - sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size); - } + node = prom_getchild(prom_root_node); + node = prom_searchsiblings(prom_root_node, "memory-error"); + if (!node) + return; + if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0) + return; + /* hmm I think regs[0].which_io is zero here anyways */ + sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size); } static inline void sun4c_init_ss2_cache_bug(void) @@ -521,7 +438,6 @@ static inline void sun4c_init_ss2_cache_bug(void) if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || - (idprom->id_machtype == (SM_SUN4 | SM_4_330)) || (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { /* Whee.. */ printk("SS2 cache bug detected, uncaching trap table page\n"); @@ -617,11 +533,7 @@ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end) { unsigned long vaddr; unsigned char pseg, ctx; -#ifdef CONFIG_SUN4 - /* sun4/110 and 260 have no kadb. */ - if ((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && - (idprom->id_machtype != (SM_SUN4 | SM_4_110))) { -#endif + for (vaddr = KADB_DEBUGGER_BEGVM; vaddr < LINUX_OPPROM_ENDVM; vaddr += SUN4C_REAL_PGDIR_SIZE) { @@ -633,9 +545,7 @@ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end) fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0); } } -#ifdef CONFIG_SUN4 - } -#endif + for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) { pseg = sun4c_get_segmap(vaddr); mmu_entry_pool[pseg].locked = 1; @@ -1041,14 +951,10 @@ static struct thread_info *sun4c_alloc_thread_info(void) * so we must flush the cache to guarantee consistency. */ sun4c_flush_page(pages); -#ifndef CONFIG_SUN4 sun4c_flush_page(pages + PAGE_SIZE); -#endif sun4c_put_pte(addr, BUCKET_PTE(pages)); -#ifndef CONFIG_SUN4 sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE)); -#endif #ifdef CONFIG_DEBUG_STACK_USAGE memset((void *)addr, 0, PAGE_SIZE << THREAD_INFO_ORDER); @@ -1065,13 +971,11 @@ static void sun4c_free_thread_info(struct thread_info *ti) /* We are deleting a mapping, so the flush here is mandatory. */ sun4c_flush_page(tiaddr); -#ifndef CONFIG_SUN4 sun4c_flush_page(tiaddr + PAGE_SIZE); -#endif + sun4c_put_pte(tiaddr, 0); -#ifndef CONFIG_SUN4 sun4c_put_pte(tiaddr + PAGE_SIZE, 0); -#endif + sun4c_bucket[entry] = BUCKET_EMPTY; if (entry < sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry; diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 7f5eacfcfbc..8f7e18546c9 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile @@ -4,5 +4,3 @@ lib-y := bootstr.o devmap.o devops.o init.o memory.o misc.o mp.o \ palloc.o ranges.o segment.o console.o printf.o tree.o - -lib-$(CONFIG_SUN4) += sun4prom.o diff --git a/arch/sparc/prom/bootstr.c b/arch/sparc/prom/bootstr.c index 5a35c768ff7..916831da7e6 100644 --- a/arch/sparc/prom/bootstr.c +++ b/arch/sparc/prom/bootstr.c @@ -6,15 +6,12 @@ #include #include -#include #include #define BARG_LEN 256 static char barg_buf[BARG_LEN] = { 0 }; static char fetched __initdata = 0; -extern linux_sun4_romvec *sun4_romvec; - char * __init prom_getbootargs(void) { @@ -28,7 +25,6 @@ prom_getbootargs(void) switch(prom_vers) { case PROM_V0: - case PROM_SUN4: cp = barg_buf; /* Start from 1 and go over fd(0,0,0)kernel */ for(iter = 1; iter < 8; iter++) { diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c index 790057a3461..b3075d73fc1 100644 --- a/arch/sparc/prom/console.c +++ b/arch/sparc/prom/console.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -30,7 +29,6 @@ prom_nbgetchar(void) spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: - case PROM_SUN4: i = (*(romvec->pv_nbgetchar))(); break; case PROM_V2: @@ -63,7 +61,6 @@ prom_nbputchar(char c) spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: - case PROM_SUN4: i = (*(romvec->pv_nbputchar))(c); break; case PROM_V2: diff --git a/arch/sparc/prom/init.c b/arch/sparc/prom/init.c index 729f8706694..873217c6d82 100644 --- a/arch/sparc/prom/init.c +++ b/arch/sparc/prom/init.c @@ -11,12 +11,10 @@ #include #include -#include struct linux_romvec *romvec; enum prom_major_version prom_vers; unsigned int prom_rev, prom_prev; -linux_sun4_romvec *sun4_romvec; /* The root node of the prom device tree. */ int prom_root_node; @@ -34,10 +32,6 @@ extern void prom_ranges_init(void); void __init prom_init(struct linux_romvec *rp) { -#ifdef CONFIG_SUN4 - extern struct linux_romvec *sun4_prom_init(void); - rp = sun4_prom_init(); -#endif romvec = rp; switch(romvec->pv_romvers) { @@ -50,9 +44,6 @@ void __init prom_init(struct linux_romvec *rp) case 3: prom_vers = PROM_V3; break; - case 40: - prom_vers = PROM_SUN4; - break; default: prom_printf("PROMLIB: Bad PROM version %d\n", romvec->pv_romvers); @@ -76,11 +67,8 @@ void __init prom_init(struct linux_romvec *rp) prom_ranges_init(); -#ifndef CONFIG_SUN4 - /* SUN4 prints this in sun4_prom_init */ printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n", romvec->pv_romvers, prom_rev); -#endif /* Initialization successful. */ return; diff --git a/arch/sparc/prom/memory.c b/arch/sparc/prom/memory.c index 947f047dc95..fac7899a29c 100644 --- a/arch/sparc/prom/memory.c +++ b/arch/sparc/prom/memory.c @@ -10,7 +10,6 @@ #include #include -#include #include #include @@ -46,15 +45,6 @@ static int __init prom_meminit_v2(void) return num_ents; } -static int __init prom_meminit_sun4(void) -{ -#ifdef CONFIG_SUN4 - sp_banks[0].base_addr = 0; - sp_banks[0].num_bytes = *(sun4_romvec->memoryavail); -#endif - return 1; -} - static int sp_banks_cmp(const void *a, const void *b) { const struct sparc_phys_banks *x = a, *y = b; @@ -81,10 +71,6 @@ void __init prom_meminit(void) num_ents = prom_meminit_v2(); break; - case PROM_SUN4: - num_ents = prom_meminit_sun4(); - break; - default: break; } diff --git a/arch/sparc/prom/sun4prom.c b/arch/sparc/prom/sun4prom.c deleted file mode 100644 index 00390a2652a..00000000000 --- a/arch/sparc/prom/sun4prom.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 1996 The Australian National University. - * Copyright (C) 1996 Fujitsu Laboratories Limited - * Copyright (C) 1997 Michael A. Griffith (grif@acm.org) - * Copyright (C) 1997 Sun Weenie (ko@ko.reno.nv.us) - * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * This software may be distributed under the terms of the Gnu - * Public License version 2 or later - * - * fake a really simple Sun prom for the SUN4 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct linux_romvec sun4romvec; -static struct idprom sun4_idprom; - -struct property { - char *name; - char *value; - int length; -}; - -struct node { - int level; - struct property *properties; -}; - -struct property null_properties = { NULL, NULL, -1 }; - -struct property root_properties[] = { - {"device_type", "cpu", 4}, - {"idprom", (char *)&sun4_idprom, sizeof(struct idprom)}, - {NULL, NULL, -1} -}; - -struct node nodes[] = { - { 0, &null_properties }, - { 0, root_properties }, - { -1,&null_properties } -}; - - -static int no_nextnode(int node) -{ - if (nodes[node].level == nodes[node+1].level) - return node+1; - return -1; -} - -static int no_child(int node) -{ - if (nodes[node].level == nodes[node+1].level-1) - return node+1; - return -1; -} - -static struct property *find_property(int node,char *name) -{ - struct property *prop = &nodes[node].properties[0]; - while (prop && prop->name) { - if (strcmp(prop->name,name) == 0) return prop; - prop++; - } - return NULL; -} - -static int no_proplen(int node,char *name) -{ - struct property *prop = find_property(node,name); - if (prop) return prop->length; - return -1; -} - -static int no_getprop(int node,char *name,char *value) -{ - struct property *prop = find_property(node,name); - if (prop) { - memcpy(value,prop->value,prop->length); - return 1; - } - return -1; -} - -static int no_setprop(int node,char *name,char *value,int len) -{ - return -1; -} - -static char *no_nextprop(int node,char *name) -{ - struct property *prop = find_property(node,name); - if (prop) return prop[1].name; - return NULL; -} - -static struct linux_nodeops sun4_nodeops = { - no_nextnode, - no_child, - no_proplen, - no_getprop, - no_setprop, - no_nextprop -}; - -static int synch_hook; - -struct linux_romvec * __init sun4_prom_init(void) -{ - int i; - unsigned char x; - char *p; - - p = (char *)&sun4_idprom; - for (i = 0; i < sizeof(sun4_idprom); i++) { - __asm__ __volatile__ ("lduba [%1] %2, %0" : "=r" (x) : - "r" (AC_IDPROM + i), "i" (ASI_CONTROL)); - *p++ = x; - } - - memset(&sun4romvec,0,sizeof(sun4romvec)); - - sun4_romvec = (linux_sun4_romvec *) SUN4_PROM_VECTOR; - - sun4romvec.pv_romvers = 40; - sun4romvec.pv_nodeops = &sun4_nodeops; - sun4romvec.pv_reboot = sun4_romvec->reboot; - sun4romvec.pv_abort = sun4_romvec->abortentry; - sun4romvec.pv_halt = sun4_romvec->exittomon; - sun4romvec.pv_synchook = (void (**)(void))&synch_hook; - sun4romvec.pv_setctxt = sun4_romvec->setcxsegmap; - sun4romvec.pv_v0bootargs = sun4_romvec->bootParam; - sun4romvec.pv_nbgetchar = sun4_romvec->mayget; - sun4romvec.pv_nbputchar = sun4_romvec->mayput; - sun4romvec.pv_stdin = sun4_romvec->insource; - sun4romvec.pv_stdout = sun4_romvec->outsink; - - /* - * We turn on the LEDs to let folks without monitors or - * terminals know we booted. Nothing too fancy now. They - * are all on, except for LED 5, which blinks. When we - * have more time, we can teach the penguin to say "By your - * command" or "Activating turbo boost, Michael". :-) - */ - sun4_romvec->setLEDs(NULL); - - printk("PROMLIB: Old Sun4 boot PROM monitor %s, romvec version %d\n", - sun4_romvec->monid, - sun4_romvec->romvecversion); - - return &sun4romvec; -} -- cgit v1.2.3 From ba4962d7a6a10c82e55c14589d4ec635bef8446f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 21:48:12 -0700 Subject: sparc64: Clean up CPU chip type probing code. Three main things: 1) Make prober an arch initcall instead of using hard-coded invocation from paging_init() 2) Shrink table size, the fpu ident stuff was never used. 3) Use named struct initialized in table. Signed-off-by: David S. Miller --- arch/sparc/include/asm/cpudata_64.h | 1 - arch/sparc64/kernel/cpu.c | 208 +++++++++++++++++++----------------- arch/sparc64/kernel/entry.h | 4 +- arch/sparc64/mm/init.c | 2 - 4 files changed, 111 insertions(+), 104 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h index 532975ecfe1..7da7c13d23c 100644 --- a/arch/sparc/include/asm/cpudata_64.h +++ b/arch/sparc/include/asm/cpudata_64.h @@ -86,7 +86,6 @@ extern struct trap_per_cpu trap_block[NR_CPUS]; extern void init_cur_cpu_trap(struct thread_info *); extern void setup_tba(void); extern int ncpus_probed; -extern void __init cpu_probe(void); extern const struct seq_operations cpuinfo_op; extern unsigned long real_hard_smp_processor_id(void); diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index 0097c08dc60..0c9ac83ed0a 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c @@ -1,7 +1,7 @@ /* cpu.c: Dinky routines to look for the kind of Sparc cpu * we are on. * - * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include @@ -19,53 +19,86 @@ DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; -struct cpu_iu_info { - short manuf; - short impl; - char* cpu_name; /* should be enough I hope... */ +struct cpu_chip_info { + unsigned short manuf; + unsigned short impl; + const char *cpu_name; + const char *fp_name; }; -struct cpu_fp_info { - short manuf; - short impl; - char fpu_vers; - char* fp_name; +static const struct cpu_chip_info cpu_chips[] = { + { + .manuf = 0x17, + .impl = 0x10, + .cpu_name = "TI UltraSparc I (SpitFire)", + .fp_name = "UltraSparc I integrated FPU", + }, + { + .manuf = 0x22, + .impl = 0x10, + .cpu_name = "TI UltraSparc I (SpitFire)", + .fp_name = "UltraSparc I integrated FPU", + }, + { + .manuf = 0x17, + .impl = 0x11, + .cpu_name = "TI UltraSparc II (BlackBird)", + .fp_name = "UltraSparc II integrated FPU", + }, + { + .manuf = 0x17, + .impl = 0x12, + .cpu_name = "TI UltraSparc IIi (Sabre)", + .fp_name = "UltraSparc IIi integrated FPU", + }, + { + .manuf = 0x17, + .impl = 0x13, + .cpu_name = "TI UltraSparc IIe (Hummingbird)", + .fp_name = "UltraSparc IIe integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x14, + .cpu_name = "TI UltraSparc III (Cheetah)", + .fp_name = "UltraSparc III integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x15, + .cpu_name = "TI UltraSparc III+ (Cheetah+)", + .fp_name = "UltraSparc III+ integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x16, + .cpu_name = "TI UltraSparc IIIi (Jalapeno)", + .fp_name = "UltraSparc IIIi integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x18, + .cpu_name = "TI UltraSparc IV (Jaguar)", + .fp_name = "UltraSparc IV integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x19, + .cpu_name = "TI UltraSparc IV+ (Panther)", + .fp_name = "UltraSparc IV+ integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x22, + .cpu_name = "TI UltraSparc IIIi+ (Serrano)", + .fp_name = "UltraSparc IIIi+ integrated FPU", + }, }; -static struct cpu_fp_info linux_sparc_fpu[] = { - { 0x17, 0x10, 0, "UltraSparc I integrated FPU"}, - { 0x22, 0x10, 0, "UltraSparc I integrated FPU"}, - { 0x17, 0x11, 0, "UltraSparc II integrated FPU"}, - { 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"}, - { 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"}, - { 0x3e, 0x14, 0, "UltraSparc III integrated FPU"}, - { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"}, - { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"}, - { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"}, - { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"}, - { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"}, -}; - -#define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) - -static struct cpu_iu_info linux_sparc_chips[] = { - { 0x17, 0x10, "TI UltraSparc I (SpitFire)"}, - { 0x22, 0x10, "TI UltraSparc I (SpitFire)"}, - { 0x17, 0x11, "TI UltraSparc II (BlackBird)"}, - { 0x17, 0x12, "TI UltraSparc IIi (Sabre)"}, - { 0x17, 0x13, "TI UltraSparc IIe (Hummingbird)"}, - { 0x3e, 0x14, "TI UltraSparc III (Cheetah)"}, - { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"}, - { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"}, - { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"}, - { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"}, - { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"}, -}; +#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) -#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) - -char *sparc_cpu_type; -char *sparc_fpu_type; +const char *sparc_cpu_type; +const char *sparc_fpu_type; static void __init sun4v_cpu_probe(void) { @@ -89,68 +122,45 @@ static void __init sun4v_cpu_probe(void) } } -void __init cpu_probe(void) +static const struct cpu_chip_info * __init find_cpu_chip(unsigned short manuf, + unsigned short impl) { - unsigned long ver, fpu_vers, manuf, impl, fprs; int i; - - if (tlb_type == hypervisor) { - sun4v_cpu_probe(); - return; - } - fprs = fprs_read(); - fprs_write(FPRS_FEF); - __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" - : "=&r" (ver) - : "r" (&fpu_vers)); - fprs_write(fprs); - - manuf = ((ver >> 48) & 0xffff); - impl = ((ver >> 32) & 0xffff); - - fpu_vers = ((fpu_vers >> 17) & 0x7); - -retry: - for (i = 0; i < NSPARCCHIPS; i++) { - if (linux_sparc_chips[i].manuf == manuf) { - if (linux_sparc_chips[i].impl == impl) { - sparc_cpu_type = - linux_sparc_chips[i].cpu_name; - break; - } - } - } + for (i = 0; i < ARRAY_SIZE(cpu_chips); i++) { + const struct cpu_chip_info *p = &cpu_chips[i]; - if (i == NSPARCCHIPS) { - /* Maybe it is a cheetah+ derivative, report it as cheetah+ - * in that case until we learn the real names. - */ - if (manuf == 0x3e && - impl > 0x15) { - impl = 0x15; - goto retry; - } else { - printk("DEBUG: manuf[%lx] impl[%lx]\n", - manuf, impl); - } - sparc_cpu_type = "Unknown CPU"; + if (p->manuf == manuf && p->impl == impl) + return p; } + return NULL; +} - for (i = 0; i < NSPARCFPU; i++) { - if (linux_sparc_fpu[i].manuf == manuf && - linux_sparc_fpu[i].impl == impl) { - if (linux_sparc_fpu[i].fpu_vers == fpu_vers) { - sparc_fpu_type = - linux_sparc_fpu[i].fp_name; - break; - } +static int __init cpu_type_probe(void) +{ + if (tlb_type == hypervisor) { + sun4v_cpu_probe(); + } else { + unsigned long ver, manuf, impl; + const struct cpu_chip_info *p; + + __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); + + manuf = ((ver >> 48) & 0xffff); + impl = ((ver >> 32) & 0xffff); + + p = find_cpu_chip(manuf, impl); + if (p) { + sparc_cpu_type = p->cpu_name; + sparc_fpu_type = p->fp_name; + } else { + printk(KERN_ERR "CPU: Unknown chip, manuf[%lx] impl[%lx]\n", + manuf, impl); + sparc_cpu_type = "Unknown CPU"; + sparc_fpu_type = "Unknown FPU"; } } - - if (i == NSPARCFPU) { - printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n", - manuf, impl, fpu_vers); - sparc_fpu_type = "Unknown FPU"; - } + return 0; } + +arch_initcall(cpu_type_probe); diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index 2255244442f..34d7ab5e10d 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -5,8 +5,8 @@ #include #include -extern char *sparc_cpu_type; -extern char *sparc_fpu_type; +extern const char *sparc_cpu_type; +extern const char *sparc_fpu_type; extern void __init per_cpu_patch(void); extern void __init sun4v_patch(void); diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 8cc1892c554..54193f2d0ab 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1841,8 +1841,6 @@ void __init paging_init(void) } printk("Booting Linux...\n"); - - cpu_probe(); } int __init page_in_phys_avail(unsigned long paddr) -- cgit v1.2.3 From 3d452e55ef905fc6fbf813a66c16de1293e243a1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 01:48:52 -0700 Subject: sparc64: Apply const or __initdata to vio_device_id[] This mirrors the of_device_id[] changes done in fd098316ef533e8441576f020ead4beab93154ce ("sparc: Annotate of_device_id arrays with const or __initdata.") Signed-off-by: David S. Miller --- arch/sparc64/kernel/ds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index d0fa5aa3893..f52e0534d91 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c @@ -1,6 +1,6 @@ /* ds.c: Domain Services driver for Logical Domains * - * Copyright (C) 2007 David S. Miller + * Copyright (C) 2007, 2008 David S. Miller */ #include @@ -1217,7 +1217,7 @@ static int ds_remove(struct vio_dev *vdev) return 0; } -static struct vio_device_id ds_match[] = { +static struct vio_device_id __initdata ds_match[] = { { .type = "domain-services-port", }, -- cgit v1.2.3 From 687124dda0beeb8503ae27a1588e4705b3a588c2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 03:13:17 -0700 Subject: sparc64: Use ENTRY/ENDPROC in hypervisor asm. Signed-off-by: David S. Miller --- arch/sparc64/kernel/head.S | 1 + arch/sparc64/kernel/hvcalls.S | 354 ++++++++++++++---------------------------- 2 files changed, 119 insertions(+), 236 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index c9afef093d5..353226fa023 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/sparc64/kernel/hvcalls.S b/arch/sparc64/kernel/hvcalls.S index a2810f3ac70..e066269d159 100644 --- a/arch/sparc64/kernel/hvcalls.S +++ b/arch/sparc64/kernel/hvcalls.S @@ -3,89 +3,75 @@ * * returns %o0: sysino */ - .globl sun4v_devino_to_sysino - .type sun4v_devino_to_sysino,#function -sun4v_devino_to_sysino: +ENTRY(sun4v_devino_to_sysino) mov HV_FAST_INTR_DEVINO2SYSINO, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino +ENDPROC(sun4v_devino_to_sysino) /* %o0: sysino * * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED}) */ - .globl sun4v_intr_getenabled - .type sun4v_intr_getenabled,#function -sun4v_intr_getenabled: +ENTRY(sun4v_intr_getenabled) mov HV_FAST_INTR_GETENABLED, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_intr_getenabled, .-sun4v_intr_getenabled +ENDPROC(sun4v_intr_getenabled) /* %o0: sysino * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED}) */ - .globl sun4v_intr_setenabled - .type sun4v_intr_setenabled,#function -sun4v_intr_setenabled: +ENTRY(sun4v_intr_setenabled) mov HV_FAST_INTR_SETENABLED, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_intr_setenabled, .-sun4v_intr_setenabled +ENDPROC(sun4v_intr_setenabled) /* %o0: sysino * * returns %o0: intr_state (HV_INTR_STATE_*) */ - .globl sun4v_intr_getstate - .type sun4v_intr_getstate,#function -sun4v_intr_getstate: +ENTRY(sun4v_intr_getstate) mov HV_FAST_INTR_GETSTATE, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_intr_getstate, .-sun4v_intr_getstate +ENDPROC(sun4v_intr_getstate) /* %o0: sysino * %o1: intr_state (HV_INTR_STATE_*) */ - .globl sun4v_intr_setstate - .type sun4v_intr_setstate,#function -sun4v_intr_setstate: +ENTRY(sun4v_intr_setstate) mov HV_FAST_INTR_SETSTATE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_intr_setstate, .-sun4v_intr_setstate +ENDPROC(sun4v_intr_setstate) /* %o0: sysino * * returns %o0: cpuid */ - .globl sun4v_intr_gettarget - .type sun4v_intr_gettarget,#function -sun4v_intr_gettarget: +ENTRY(sun4v_intr_gettarget) mov HV_FAST_INTR_GETTARGET, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_intr_gettarget, .-sun4v_intr_gettarget +ENDPROC(sun4v_intr_gettarget) /* %o0: sysino * %o1: cpuid */ - .globl sun4v_intr_settarget - .type sun4v_intr_settarget,#function -sun4v_intr_settarget: +ENTRY(sun4v_intr_settarget) mov HV_FAST_INTR_SETTARGET, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_intr_settarget, .-sun4v_intr_settarget +ENDPROC(sun4v_intr_settarget) /* %o0: cpuid * %o1: pc @@ -94,37 +80,31 @@ sun4v_intr_settarget: * * returns %o0: status */ - .globl sun4v_cpu_start - .type sun4v_cpu_start,#function -sun4v_cpu_start: +ENTRY(sun4v_cpu_start) mov HV_FAST_CPU_START, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_start, .-sun4v_cpu_start +ENDPROC(sun4v_cpu_start) /* %o0: cpuid * * returns %o0: status */ - .globl sun4v_cpu_stop - .type sun4v_cpu_stop,#function -sun4v_cpu_stop: +ENTRY(sun4v_cpu_stop) mov HV_FAST_CPU_STOP, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_stop, .-sun4v_cpu_stop +ENDPROC(sun4v_cpu_stop) /* returns %o0: status */ - .globl sun4v_cpu_yield - .type sun4v_cpu_yield, #function -sun4v_cpu_yield: +ENTRY(sun4v_cpu_yield) mov HV_FAST_CPU_YIELD, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_yield, .-sun4v_cpu_yield +ENDPROC(sun4v_cpu_yield) /* %o0: type * %o1: queue paddr @@ -132,14 +112,12 @@ sun4v_cpu_yield: * * returns %o0: status */ - .globl sun4v_cpu_qconf - .type sun4v_cpu_qconf,#function -sun4v_cpu_qconf: +ENTRY(sun4v_cpu_qconf) mov HV_FAST_CPU_QCONF, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_qconf, .-sun4v_cpu_qconf +ENDPROC(sun4v_cpu_qconf) /* %o0: num cpus in cpu list * %o1: cpu list paddr @@ -147,23 +125,19 @@ sun4v_cpu_qconf: * * returns %o0: status */ - .globl sun4v_cpu_mondo_send - .type sun4v_cpu_mondo_send,#function -sun4v_cpu_mondo_send: +ENTRY(sun4v_cpu_mondo_send) mov HV_FAST_CPU_MONDO_SEND, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send +ENDPROC(sun4v_cpu_mondo_send) /* %o0: CPU ID * * returns %o0: -status if status non-zero, else * %o0: cpu state as HV_CPU_STATE_* */ - .globl sun4v_cpu_state - .type sun4v_cpu_state,#function -sun4v_cpu_state: +ENTRY(sun4v_cpu_state) mov HV_FAST_CPU_STATE, %o5 ta HV_FAST_TRAP brnz,pn %o0, 1f @@ -171,7 +145,7 @@ sun4v_cpu_state: mov %o1, %o0 1: retl nop - .size sun4v_cpu_state, .-sun4v_cpu_state +ENDPROC(sun4v_cpu_state) /* %o0: virtual address * %o1: must be zero @@ -180,28 +154,24 @@ sun4v_cpu_state: * * returns %o0: status */ - .globl sun4v_mmu_map_perm_addr - .type sun4v_mmu_map_perm_addr,#function -sun4v_mmu_map_perm_addr: +ENTRY(sun4v_mmu_map_perm_addr) mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr +ENDPROC(sun4v_mmu_map_perm_addr) /* %o0: number of TSB descriptions * %o1: TSB descriptions real address * * returns %o0: status */ - .globl sun4v_mmu_tsb_ctx0 - .type sun4v_mmu_tsb_ctx0,#function -sun4v_mmu_tsb_ctx0: +ENTRY(sun4v_mmu_tsb_ctx0) mov HV_FAST_MMU_TSB_CTX0, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0 +ENDPROC(sun4v_mmu_tsb_ctx0) /* %o0: API group number * %o1: pointer to unsigned long major number storage @@ -209,9 +179,7 @@ sun4v_mmu_tsb_ctx0: * * returns %o0: status */ - .globl sun4v_get_version - .type sun4v_get_version,#function -sun4v_get_version: +ENTRY(sun4v_get_version) mov HV_CORE_GET_VER, %o5 mov %o1, %o3 mov %o2, %o4 @@ -219,7 +187,7 @@ sun4v_get_version: stx %o1, [%o3] retl stx %o2, [%o4] - .size sun4v_get_version, .-sun4v_get_version +ENDPROC(sun4v_get_version) /* %o0: API group number * %o1: desired major number @@ -228,51 +196,43 @@ sun4v_get_version: * * returns %o0: status */ - .globl sun4v_set_version - .type sun4v_set_version,#function -sun4v_set_version: +ENTRY(sun4v_set_version) mov HV_CORE_SET_VER, %o5 mov %o3, %o4 ta HV_CORE_TRAP retl stx %o1, [%o4] - .size sun4v_set_version, .-sun4v_set_version +ENDPROC(sun4v_set_version) /* %o0: pointer to unsigned long time * * returns %o0: status */ - .globl sun4v_tod_get - .type sun4v_tod_get,#function -sun4v_tod_get: +ENTRY(sun4v_tod_get) mov %o0, %o4 mov HV_FAST_TOD_GET, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_tod_get, .-sun4v_tod_get +ENDPROC(sun4v_tod_get) /* %o0: time * * returns %o0: status */ - .globl sun4v_tod_set - .type sun4v_tod_set,#function -sun4v_tod_set: +ENTRY(sun4v_tod_set) mov HV_FAST_TOD_SET, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_tod_set, .-sun4v_tod_set +ENDPROC(sun4v_tod_set) /* %o0: pointer to unsigned long status * * returns %o0: signed character */ - .globl sun4v_con_getchar - .type sun4v_con_getchar,#function -sun4v_con_getchar: +ENTRY(sun4v_con_getchar) mov %o0, %o4 mov HV_FAST_CONS_GETCHAR, %o5 clr %o0 @@ -281,20 +241,18 @@ sun4v_con_getchar: stx %o0, [%o4] retl sra %o1, 0, %o0 - .size sun4v_con_getchar, .-sun4v_con_getchar +ENDPROC(sun4v_con_getchar) /* %o0: signed long character * * returns %o0: status */ - .globl sun4v_con_putchar - .type sun4v_con_putchar,#function -sun4v_con_putchar: +ENTRY(sun4v_con_putchar) mov HV_FAST_CONS_PUTCHAR, %o5 ta HV_FAST_TRAP retl sra %o0, 0, %o0 - .size sun4v_con_putchar, .-sun4v_con_putchar +ENDPROC(sun4v_con_putchar) /* %o0: buffer real address * %o1: buffer size @@ -302,9 +260,7 @@ sun4v_con_putchar: * * returns %o0: status */ - .globl sun4v_con_read - .type sun4v_con_read,#function -sun4v_con_read: +ENTRY(sun4v_con_read) mov %o2, %o4 mov HV_FAST_CONS_READ, %o5 ta HV_FAST_TRAP @@ -318,7 +274,7 @@ sun4v_con_read: stx %o1, [%o4] 1: retl nop - .size sun4v_con_read, .-sun4v_con_read +ENDPROC(sun4v_con_read) /* %o0: buffer real address * %o1: buffer size @@ -326,43 +282,37 @@ sun4v_con_read: * * returns %o0: status */ - .globl sun4v_con_write - .type sun4v_con_write,#function -sun4v_con_write: +ENTRY(sun4v_con_write) mov %o2, %o4 mov HV_FAST_CONS_WRITE, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_con_write, .-sun4v_con_write +ENDPROC(sun4v_con_write) /* %o0: soft state * %o1: address of description string * * returns %o0: status */ - .globl sun4v_mach_set_soft_state - .type sun4v_mach_set_soft_state,#function -sun4v_mach_set_soft_state: +ENTRY(sun4v_mach_set_soft_state) mov HV_FAST_MACH_SET_SOFT_STATE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state +ENDPROC(sun4v_mach_set_soft_state) /* %o0: exit code * * Does not return. */ - .globl sun4v_mach_exit - .type sun4v_mach_exit,#function -sun4v_mach_exit: +ENTRY(sun4v_mach_exit) mov HV_FAST_MACH_EXIT, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mach_exit, .-sun4v_mach_exit +ENDPROC(sun4v_mach_exit) /* %o0: buffer real address * %o1: buffer length @@ -370,44 +320,38 @@ sun4v_mach_exit: * * returns %o0: status */ - .globl sun4v_mach_desc - .type sun4v_mach_desc,#function -sun4v_mach_desc: +ENTRY(sun4v_mach_desc) mov %o2, %o4 mov HV_FAST_MACH_DESC, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mach_desc, .-sun4v_mach_desc +ENDPROC(sun4v_mach_desc) /* %o0: new timeout in milliseconds * %o1: pointer to unsigned long orig_timeout * * returns %o0: status */ - .globl sun4v_mach_set_watchdog - .type sun4v_mach_set_watchdog,#function -sun4v_mach_set_watchdog: +ENTRY(sun4v_mach_set_watchdog) mov %o1, %o4 mov HV_FAST_MACH_SET_WATCHDOG, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog +ENDPROC(sun4v_mach_set_watchdog) /* No inputs and does not return. */ - .globl sun4v_mach_sir - .type sun4v_mach_sir,#function -sun4v_mach_sir: +ENTRY(sun4v_mach_sir) mov %o1, %o4 mov HV_FAST_MACH_SIR, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mach_sir, .-sun4v_mach_sir +ENDPROC(sun4v_mach_sir) /* %o0: channel * %o1: ra @@ -415,14 +359,12 @@ sun4v_mach_sir: * * returns %o0: status */ - .globl sun4v_ldc_tx_qconf - .type sun4v_ldc_tx_qconf,#function -sun4v_ldc_tx_qconf: +ENTRY(sun4v_ldc_tx_qconf) mov HV_FAST_LDC_TX_QCONF, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf +ENDPROC(sun4v_ldc_tx_qconf) /* %o0: channel * %o1: pointer to unsigned long ra @@ -430,9 +372,7 @@ sun4v_ldc_tx_qconf: * * returns %o0: status */ - .globl sun4v_ldc_tx_qinfo - .type sun4v_ldc_tx_qinfo,#function -sun4v_ldc_tx_qinfo: +ENTRY(sun4v_ldc_tx_qinfo) mov %o1, %g1 mov %o2, %g2 mov HV_FAST_LDC_TX_QINFO, %o5 @@ -441,7 +381,7 @@ sun4v_ldc_tx_qinfo: stx %o2, [%g2] retl nop - .size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo +ENDPROC(sun4v_ldc_tx_qinfo) /* %o0: channel * %o1: pointer to unsigned long head_off @@ -450,9 +390,7 @@ sun4v_ldc_tx_qinfo: * * returns %o0: status */ - .globl sun4v_ldc_tx_get_state - .type sun4v_ldc_tx_get_state,#function -sun4v_ldc_tx_get_state: +ENTRY(sun4v_ldc_tx_get_state) mov %o1, %g1 mov %o2, %g2 mov %o3, %g3 @@ -463,21 +401,19 @@ sun4v_ldc_tx_get_state: stx %o3, [%g3] retl nop - .size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state +ENDPROC(sun4v_ldc_tx_get_state) /* %o0: channel * %o1: tail_off * * returns %o0: status */ - .globl sun4v_ldc_tx_set_qtail - .type sun4v_ldc_tx_set_qtail,#function -sun4v_ldc_tx_set_qtail: +ENTRY(sun4v_ldc_tx_set_qtail) mov HV_FAST_LDC_TX_SET_QTAIL, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail +ENDPROC(sun4v_ldc_tx_set_qtail) /* %o0: channel * %o1: ra @@ -485,14 +421,12 @@ sun4v_ldc_tx_set_qtail: * * returns %o0: status */ - .globl sun4v_ldc_rx_qconf - .type sun4v_ldc_rx_qconf,#function -sun4v_ldc_rx_qconf: +ENTRY(sun4v_ldc_rx_qconf) mov HV_FAST_LDC_RX_QCONF, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf +ENDPROC(sun4v_ldc_rx_qconf) /* %o0: channel * %o1: pointer to unsigned long ra @@ -500,9 +434,7 @@ sun4v_ldc_rx_qconf: * * returns %o0: status */ - .globl sun4v_ldc_rx_qinfo - .type sun4v_ldc_rx_qinfo,#function -sun4v_ldc_rx_qinfo: +ENTRY(sun4v_ldc_rx_qinfo) mov %o1, %g1 mov %o2, %g2 mov HV_FAST_LDC_RX_QINFO, %o5 @@ -511,7 +443,7 @@ sun4v_ldc_rx_qinfo: stx %o2, [%g2] retl nop - .size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo +ENDPROC(sun4v_ldc_rx_qinfo) /* %o0: channel * %o1: pointer to unsigned long head_off @@ -520,9 +452,7 @@ sun4v_ldc_rx_qinfo: * * returns %o0: status */ - .globl sun4v_ldc_rx_get_state - .type sun4v_ldc_rx_get_state,#function -sun4v_ldc_rx_get_state: +ENTRY(sun4v_ldc_rx_get_state) mov %o1, %g1 mov %o2, %g2 mov %o3, %g3 @@ -533,21 +463,19 @@ sun4v_ldc_rx_get_state: stx %o3, [%g3] retl nop - .size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state +ENDPROC(sun4v_ldc_rx_get_state) /* %o0: channel * %o1: head_off * * returns %o0: status */ - .globl sun4v_ldc_rx_set_qhead - .type sun4v_ldc_rx_set_qhead,#function -sun4v_ldc_rx_set_qhead: +ENTRY(sun4v_ldc_rx_set_qhead) mov HV_FAST_LDC_RX_SET_QHEAD, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead +ENDPROC(sun4v_ldc_rx_set_qhead) /* %o0: channel * %o1: ra @@ -555,14 +483,12 @@ sun4v_ldc_rx_set_qhead: * * returns %o0: status */ - .globl sun4v_ldc_set_map_table - .type sun4v_ldc_set_map_table,#function -sun4v_ldc_set_map_table: +ENTRY(sun4v_ldc_set_map_table) mov HV_FAST_LDC_SET_MAP_TABLE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table +ENDPROC(sun4v_ldc_set_map_table) /* %o0: channel * %o1: pointer to unsigned long ra @@ -570,9 +496,7 @@ sun4v_ldc_set_map_table: * * returns %o0: status */ - .globl sun4v_ldc_get_map_table - .type sun4v_ldc_get_map_table,#function -sun4v_ldc_get_map_table: +ENTRY(sun4v_ldc_get_map_table) mov %o1, %g1 mov %o2, %g2 mov HV_FAST_LDC_GET_MAP_TABLE, %o5 @@ -581,7 +505,7 @@ sun4v_ldc_get_map_table: stx %o2, [%g2] retl nop - .size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table +ENDPROC(sun4v_ldc_get_map_table) /* %o0: channel * %o1: dir_code @@ -592,16 +516,14 @@ sun4v_ldc_get_map_table: * * returns %o0: status */ - .globl sun4v_ldc_copy - .type sun4v_ldc_copy,#function -sun4v_ldc_copy: +ENTRY(sun4v_ldc_copy) mov %o5, %g1 mov HV_FAST_LDC_COPY, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_ldc_copy, .-sun4v_ldc_copy +ENDPROC(sun4v_ldc_copy) /* %o0: channel * %o1: cookie @@ -610,9 +532,7 @@ sun4v_ldc_copy: * * returns %o0: status */ - .globl sun4v_ldc_mapin - .type sun4v_ldc_mapin,#function -sun4v_ldc_mapin: +ENTRY(sun4v_ldc_mapin) mov %o2, %g1 mov %o3, %g2 mov HV_FAST_LDC_MAPIN, %o5 @@ -621,20 +541,18 @@ sun4v_ldc_mapin: stx %o2, [%g2] retl nop - .size sun4v_ldc_mapin, .-sun4v_ldc_mapin +ENDPROC(sun4v_ldc_mapin) /* %o0: ra * * returns %o0: status */ - .globl sun4v_ldc_unmap - .type sun4v_ldc_unmap,#function -sun4v_ldc_unmap: +ENTRY(sun4v_ldc_unmap) mov HV_FAST_LDC_UNMAP, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_unmap, .-sun4v_ldc_unmap +ENDPROC(sun4v_ldc_unmap) /* %o0: channel * %o1: cookie @@ -642,14 +560,12 @@ sun4v_ldc_unmap: * * returns %o0: status */ - .globl sun4v_ldc_revoke - .type sun4v_ldc_revoke,#function -sun4v_ldc_revoke: +ENTRY(sun4v_ldc_revoke) mov HV_FAST_LDC_REVOKE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_revoke, .-sun4v_ldc_revoke +ENDPROC(sun4v_ldc_revoke) /* %o0: device handle * %o1: device INO @@ -657,16 +573,14 @@ sun4v_ldc_revoke: * * returns %o0: status */ - .globl sun4v_vintr_get_cookie - .type sun4v_vintr_get_cookie,#function -sun4v_vintr_get_cookie: +ENTRY(sun4v_vintr_get_cookie) mov %o2, %g1 mov HV_FAST_VINTR_GET_COOKIE, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie +ENDPROC(sun4v_vintr_get_cookie) /* %o0: device handle * %o1: device INO @@ -674,14 +588,12 @@ sun4v_vintr_get_cookie: * * returns %o0: status */ - .globl sun4v_vintr_set_cookie - .type sun4v_vintr_set_cookie,#function -sun4v_vintr_set_cookie: +ENTRY(sun4v_vintr_set_cookie) mov HV_FAST_VINTR_SET_COOKIE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie +ENDPROC(sun4v_vintr_set_cookie) /* %o0: device handle * %o1: device INO @@ -689,16 +601,14 @@ sun4v_vintr_set_cookie: * * returns %o0: status */ - .globl sun4v_vintr_get_valid - .type sun4v_vintr_get_valid,#function -sun4v_vintr_get_valid: +ENTRY(sun4v_vintr_get_valid) mov %o2, %g1 mov HV_FAST_VINTR_GET_VALID, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid +ENDPROC(sun4v_vintr_get_valid) /* %o0: device handle * %o1: device INO @@ -706,14 +616,12 @@ sun4v_vintr_get_valid: * * returns %o0: status */ - .globl sun4v_vintr_set_valid - .type sun4v_vintr_set_valid,#function -sun4v_vintr_set_valid: +ENTRY(sun4v_vintr_set_valid) mov HV_FAST_VINTR_SET_VALID, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid +ENDPROC(sun4v_vintr_set_valid) /* %o0: device handle * %o1: device INO @@ -721,16 +629,14 @@ sun4v_vintr_set_valid: * * returns %o0: status */ - .globl sun4v_vintr_get_state - .type sun4v_vintr_get_state,#function -sun4v_vintr_get_state: +ENTRY(sun4v_vintr_get_state) mov %o2, %g1 mov HV_FAST_VINTR_GET_STATE, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_state, .-sun4v_vintr_get_state +ENDPROC(sun4v_vintr_get_state) /* %o0: device handle * %o1: device INO @@ -738,14 +644,12 @@ sun4v_vintr_get_state: * * returns %o0: status */ - .globl sun4v_vintr_set_state - .type sun4v_vintr_set_state,#function -sun4v_vintr_set_state: +ENTRY(sun4v_vintr_set_state) mov HV_FAST_VINTR_SET_STATE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_state, .-sun4v_vintr_set_state +ENDPROC(sun4v_vintr_set_state) /* %o0: device handle * %o1: device INO @@ -753,16 +657,14 @@ sun4v_vintr_set_state: * * returns %o0: status */ - .globl sun4v_vintr_get_target - .type sun4v_vintr_get_target,#function -sun4v_vintr_get_target: +ENTRY(sun4v_vintr_get_target) mov %o2, %g1 mov HV_FAST_VINTR_GET_TARGET, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_target, .-sun4v_vintr_get_target +ENDPROC(sun4v_vintr_get_target) /* %o0: device handle * %o1: device INO @@ -770,14 +672,12 @@ sun4v_vintr_get_target: * * returns %o0: status */ - .globl sun4v_vintr_set_target - .type sun4v_vintr_set_target,#function -sun4v_vintr_set_target: +ENTRY(sun4v_vintr_set_target) mov HV_FAST_VINTR_SET_TARGET, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_target, .-sun4v_vintr_set_target +ENDPROC(sun4v_vintr_set_target) /* %o0: NCS sub-function * %o1: sub-function arg real-address @@ -785,18 +685,14 @@ sun4v_vintr_set_target: * * returns %o0: status */ - .globl sun4v_ncs_request - .type sun4v_ncs_request,#function -sun4v_ncs_request: +ENTRY(sun4v_ncs_request) mov HV_FAST_NCS_REQUEST, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ncs_request, .-sun4v_ncs_request +ENDPROC(sun4v_ncs_request) - .globl sun4v_svc_send - .type sun4v_svc_send,#function -sun4v_svc_send: +ENTRY(sun4v_svc_send) save %sp, -192, %sp mov %i0, %o0 mov %i1, %o1 @@ -806,11 +702,9 @@ sun4v_svc_send: stx %o1, [%i3] ret restore - .size sun4v_svc_send, .-sun4v_svc_send +ENDPROC(sun4v_svc_send) - .globl sun4v_svc_recv - .type sun4v_svc_recv,#function -sun4v_svc_recv: +ENTRY(sun4v_svc_recv) save %sp, -192, %sp mov %i0, %o0 mov %i1, %o1 @@ -820,62 +714,50 @@ sun4v_svc_recv: stx %o1, [%i3] ret restore - .size sun4v_svc_recv, .-sun4v_svc_recv +ENDPROC(sun4v_svc_recv) - .globl sun4v_svc_getstatus - .type sun4v_svc_getstatus,#function -sun4v_svc_getstatus: +ENTRY(sun4v_svc_getstatus) mov HV_FAST_SVC_GETSTATUS, %o5 mov %o1, %o4 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_svc_getstatus, .-sun4v_svc_getstatus +ENDPROC(sun4v_svc_getstatus) - .globl sun4v_svc_setstatus - .type sun4v_svc_setstatus,#function -sun4v_svc_setstatus: +ENTRY(sun4v_svc_setstatus) mov HV_FAST_SVC_SETSTATUS, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_svc_setstatus, .-sun4v_svc_setstatus +ENDPROC(sun4v_svc_setstatus) - .globl sun4v_svc_clrstatus - .type sun4v_svc_clrstatus,#function -sun4v_svc_clrstatus: +ENTRY(sun4v_svc_clrstatus) mov HV_FAST_SVC_CLRSTATUS, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus +ENDPROC(sun4v_svc_clrstatus) - .globl sun4v_mmustat_conf - .type sun4v_mmustat_conf,#function -sun4v_mmustat_conf: +ENTRY(sun4v_mmustat_conf) mov %o1, %o4 mov HV_FAST_MMUSTAT_CONF, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mmustat_conf, .-sun4v_mmustat_conf +ENDPROC(sun4v_mmustat_conf) - .globl sun4v_mmustat_info - .type sun4v_mmustat_info,#function -sun4v_mmustat_info: +ENTRY(sun4v_mmustat_info) mov %o0, %o4 mov HV_FAST_MMUSTAT_INFO, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mmustat_info, .-sun4v_mmustat_info +ENDPROC(sun4v_mmustat_info) - .globl sun4v_mmu_demap_all - .type sun4v_mmu_demap_all,#function -sun4v_mmu_demap_all: +ENTRY(sun4v_mmu_demap_all) clr %o0 clr %o1 mov HV_MMU_ALL, %o2 @@ -883,4 +765,4 @@ sun4v_mmu_demap_all: ta HV_FAST_TRAP retl nop - .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all +ENDPROC(sun4v_mmu_demap_all) -- cgit v1.2.3 From fefbbc73cac6f7360460cee45e3d4cc209d8d607 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 03:18:49 -0700 Subject: sparc64: Use ENTRY/ENDPROC in PCI SUN4V asm. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_sun4v_asm.S | 99 +++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 49 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_sun4v_asm.S b/arch/sparc64/kernel/pci_sun4v_asm.S index ecb81f389b0..e606d46c681 100644 --- a/arch/sparc64/kernel/pci_sun4v_asm.S +++ b/arch/sparc64/kernel/pci_sun4v_asm.S @@ -1,8 +1,9 @@ /* pci_sun4v_asm: Hypervisor calls for PCI support. * - * Copyright (C) 2006 David S. Miller + * Copyright (C) 2006, 2008 David S. Miller */ +#include #include /* %o0: devhandle @@ -14,8 +15,7 @@ * returns %o0: -status if status was non-zero, else * %o0: num pages mapped */ - .globl pci_sun4v_iommu_map -pci_sun4v_iommu_map: +ENTRY(pci_sun4v_iommu_map) mov %o5, %g1 mov HV_FAST_PCI_IOMMU_MAP, %o5 ta HV_FAST_TRAP @@ -24,6 +24,7 @@ pci_sun4v_iommu_map: mov %o1, %o0 1: retl nop +ENDPROC(pci_sun4v_iommu_map) /* %o0: devhandle * %o1: tsbid @@ -31,12 +32,12 @@ pci_sun4v_iommu_map: * * returns %o0: num ttes demapped */ - .globl pci_sun4v_iommu_demap -pci_sun4v_iommu_demap: +ENTRY(pci_sun4v_iommu_demap) mov HV_FAST_PCI_IOMMU_DEMAP, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 +ENDPROC(pci_sun4v_iommu_demap) /* %o0: devhandle * %o1: tsbid @@ -45,8 +46,7 @@ pci_sun4v_iommu_demap: * * returns %o0: status */ - .globl pci_sun4v_iommu_getmap -pci_sun4v_iommu_getmap: +ENTRY(pci_sun4v_iommu_getmap) mov %o2, %o4 mov HV_FAST_PCI_IOMMU_GETMAP, %o5 ta HV_FAST_TRAP @@ -54,6 +54,7 @@ pci_sun4v_iommu_getmap: stx %o2, [%o3] retl mov %o0, %o0 +ENDPROC(pci_sun4v_iommu_getmap) /* %o0: devhandle * %o1: pci_device @@ -65,14 +66,14 @@ pci_sun4v_iommu_getmap: * If there is an error, the data will be returned * as all 1's. */ - .globl pci_sun4v_config_get -pci_sun4v_config_get: +ENTRY(pci_sun4v_config_get) mov HV_FAST_PCI_CONFIG_GET, %o5 ta HV_FAST_TRAP brnz,a,pn %o1, 1f mov -1, %o2 1: retl mov %o2, %o0 +ENDPROC(pci_sun4v_config_get) /* %o0: devhandle * %o1: pci_device @@ -85,14 +86,14 @@ pci_sun4v_config_get: * status will be zero if the operation completed * successfully, else -1 if not */ - .globl pci_sun4v_config_put -pci_sun4v_config_put: +ENTRY(pci_sun4v_config_put) mov HV_FAST_PCI_CONFIG_PUT, %o5 ta HV_FAST_TRAP brnz,a,pn %o1, 1f mov -1, %o1 1: retl mov %o1, %o0 +ENDPROC(pci_sun4v_config_put) /* %o0: devhandle * %o1: msiqid @@ -104,12 +105,12 @@ pci_sun4v_config_put: * status will be zero if the operation completed * successfully, else -1 if not */ - .globl pci_sun4v_msiq_conf -pci_sun4v_msiq_conf: +ENTRY(pci_sun4v_msiq_conf) mov HV_FAST_PCI_MSIQ_CONF, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_conf) /* %o0: devhandle * %o1: msiqid @@ -118,8 +119,7 @@ pci_sun4v_msiq_conf: * * returns %o0: status */ - .globl pci_sun4v_msiq_info -pci_sun4v_msiq_info: +ENTRY(pci_sun4v_msiq_info) mov %o2, %o4 mov HV_FAST_PCI_MSIQ_INFO, %o5 ta HV_FAST_TRAP @@ -127,6 +127,7 @@ pci_sun4v_msiq_info: stx %o2, [%o3] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_info) /* %o0: devhandle * %o1: msiqid @@ -134,13 +135,13 @@ pci_sun4v_msiq_info: * * returns %o0: status */ - .globl pci_sun4v_msiq_getvalid -pci_sun4v_msiq_getvalid: +ENTRY(pci_sun4v_msiq_getvalid) mov HV_FAST_PCI_MSIQ_GETVALID, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_getvalid) /* %o0: devhandle * %o1: msiqid @@ -148,12 +149,12 @@ pci_sun4v_msiq_getvalid: * * returns %o0: status */ - .globl pci_sun4v_msiq_setvalid -pci_sun4v_msiq_setvalid: +ENTRY(pci_sun4v_msiq_setvalid) mov HV_FAST_PCI_MSIQ_SETVALID, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_setvalid) /* %o0: devhandle * %o1: msiqid @@ -161,13 +162,13 @@ pci_sun4v_msiq_setvalid: * * returns %o0: status */ - .globl pci_sun4v_msiq_getstate -pci_sun4v_msiq_getstate: +ENTRY(pci_sun4v_msiq_getstate) mov HV_FAST_PCI_MSIQ_GETSTATE, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_getstate) /* %o0: devhandle * %o1: msiqid @@ -175,12 +176,12 @@ pci_sun4v_msiq_getstate: * * returns %o0: status */ - .globl pci_sun4v_msiq_setstate -pci_sun4v_msiq_setstate: +ENTRY(pci_sun4v_msiq_setstate) mov HV_FAST_PCI_MSIQ_SETSTATE, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_setstate) /* %o0: devhandle * %o1: msiqid @@ -188,13 +189,13 @@ pci_sun4v_msiq_setstate: * * returns %o0: status */ - .globl pci_sun4v_msiq_gethead -pci_sun4v_msiq_gethead: +ENTRY(pci_sun4v_msiq_gethead) mov HV_FAST_PCI_MSIQ_GETHEAD, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_gethead) /* %o0: devhandle * %o1: msiqid @@ -202,12 +203,12 @@ pci_sun4v_msiq_gethead: * * returns %o0: status */ - .globl pci_sun4v_msiq_sethead -pci_sun4v_msiq_sethead: +ENTRY(pci_sun4v_msiq_sethead) mov HV_FAST_PCI_MSIQ_SETHEAD, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_sethead) /* %o0: devhandle * %o1: msiqid @@ -215,13 +216,13 @@ pci_sun4v_msiq_sethead: * * returns %o0: status */ - .globl pci_sun4v_msiq_gettail -pci_sun4v_msiq_gettail: +ENTRY(pci_sun4v_msiq_gettail) mov HV_FAST_PCI_MSIQ_GETTAIL, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_gettail) /* %o0: devhandle * %o1: msinum @@ -229,13 +230,13 @@ pci_sun4v_msiq_gettail: * * returns %o0: status */ - .globl pci_sun4v_msi_getvalid -pci_sun4v_msi_getvalid: +ENTRY(pci_sun4v_msi_getvalid) mov HV_FAST_PCI_MSI_GETVALID, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_getvalid) /* %o0: devhandle * %o1: msinum @@ -243,12 +244,12 @@ pci_sun4v_msi_getvalid: * * returns %o0: status */ - .globl pci_sun4v_msi_setvalid -pci_sun4v_msi_setvalid: +ENTRY(pci_sun4v_msi_setvalid) mov HV_FAST_PCI_MSI_SETVALID, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_setvalid) /* %o0: devhandle * %o1: msinum @@ -256,13 +257,13 @@ pci_sun4v_msi_setvalid: * * returns %o0: status */ - .globl pci_sun4v_msi_getmsiq -pci_sun4v_msi_getmsiq: +ENTRY(pci_sun4v_msi_getmsiq) mov HV_FAST_PCI_MSI_GETMSIQ, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_getmsiq) /* %o0: devhandle * %o1: msinum @@ -271,12 +272,12 @@ pci_sun4v_msi_getmsiq: * * returns %o0: status */ - .globl pci_sun4v_msi_setmsiq -pci_sun4v_msi_setmsiq: +ENTRY(pci_sun4v_msi_setmsiq) mov HV_FAST_PCI_MSI_SETMSIQ, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_setmsiq) /* %o0: devhandle * %o1: msinum @@ -284,13 +285,13 @@ pci_sun4v_msi_setmsiq: * * returns %o0: status */ - .globl pci_sun4v_msi_getstate -pci_sun4v_msi_getstate: +ENTRY(pci_sun4v_msi_getstate) mov HV_FAST_PCI_MSI_GETSTATE, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_getstate) /* %o0: devhandle * %o1: msinum @@ -298,12 +299,12 @@ pci_sun4v_msi_getstate: * * returns %o0: status */ - .globl pci_sun4v_msi_setstate -pci_sun4v_msi_setstate: +ENTRY(pci_sun4v_msi_setstate) mov HV_FAST_PCI_MSI_SETSTATE, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_setstate) /* %o0: devhandle * %o1: msinum @@ -311,13 +312,13 @@ pci_sun4v_msi_setstate: * * returns %o0: status */ - .globl pci_sun4v_msg_getmsiq -pci_sun4v_msg_getmsiq: +ENTRY(pci_sun4v_msg_getmsiq) mov HV_FAST_PCI_MSG_GETMSIQ, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_getmsiq) /* %o0: devhandle * %o1: msinum @@ -325,12 +326,12 @@ pci_sun4v_msg_getmsiq: * * returns %o0: status */ - .globl pci_sun4v_msg_setmsiq -pci_sun4v_msg_setmsiq: +ENTRY(pci_sun4v_msg_setmsiq) mov HV_FAST_PCI_MSG_SETMSIQ, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_setmsiq) /* %o0: devhandle * %o1: msinum @@ -338,13 +339,13 @@ pci_sun4v_msg_setmsiq: * * returns %o0: status */ - .globl pci_sun4v_msg_getvalid -pci_sun4v_msg_getvalid: +ENTRY(pci_sun4v_msg_getvalid) mov HV_FAST_PCI_MSG_GETVALID, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_getvalid) /* %o0: devhandle * %o1: msinum @@ -352,10 +353,10 @@ pci_sun4v_msg_getvalid: * * returns %o0: status */ - .globl pci_sun4v_msg_setvalid -pci_sun4v_msg_setvalid: +ENTRY(pci_sun4v_msg_setvalid) mov HV_FAST_PCI_MSG_SETVALID, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_setvalid) -- cgit v1.2.3 From 7cc288add44c392dfc8c1dbf0e3a26a69a14fa70 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 18:32:13 -0700 Subject: sparc64: Kill the scan_bus function pointer in struct pci_pbm_info. No longer used. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index c385d126be1..4125f7513c6 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -146,7 +146,6 @@ struct pci_pbm_info { unsigned int pci_first_busno; unsigned int pci_last_busno; struct pci_bus *pci_bus; - void (*scan_bus)(struct pci_pbm_info *); struct pci_ops *pci_ops; int numa_node; @@ -164,7 +163,8 @@ extern int pci_num_pbms; /* PCI bus scanning and fixup support. */ extern void pci_get_pbm_props(struct pci_pbm_info *pbm); -extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); +extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, + struct device *parent); extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); /* Error reporting support. */ -- cgit v1.2.3 From e822358ac24550d889895d5866797ae8c9b188c2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 18:32:22 -0700 Subject: sparc64: Pass proper parent device down into root pci_create_bus() call. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 6 +++--- arch/sparc64/kernel/pci_fire.c | 18 +++++++----------- arch/sparc64/kernel/pci_psycho.c | 14 ++++++++------ arch/sparc64/kernel/pci_sabre.c | 13 ++++++++----- arch/sparc64/kernel/pci_schizo.c | 19 +++++++++++-------- arch/sparc64/kernel/pci_sun4v.c | 14 ++++++++------ 6 files changed, 45 insertions(+), 39 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 2da32e4c985..8e18fdf32a6 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -673,15 +673,15 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) pci_bus_register_of_sysfs(child_bus); } -struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) +struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, + struct device *parent) { struct device_node *node = pbm->prom_node; struct pci_bus *bus; printk("PCI: Scanning PBM %s\n", node->full_name); - /* XXX parent device? XXX */ - bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm); + bus = pci_create_bus(parent, pbm->pci_first_busno, pbm->pci_ops, pbm); if (!bus) { printk(KERN_ERR "Failed to create bus for %s\n", node->full_name); diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 4fb1ef92cb1..1b44153f907 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -33,13 +33,6 @@ "i" (ASI_PHYS_BYPASS_EC_E) \ : "memory") -static void __init pci_fire_scan_bus(struct pci_pbm_info *pbm) -{ - pbm->pci_bus = pci_scan_one_pbm(pbm); - - /* XXX register error interrupt handlers XXX */ -} - #define FIRE_IOMMU_CONTROL 0x40000UL #define FIRE_IOMMU_TSBBASE 0x40008UL #define FIRE_IOMMU_FLUSH 0x40100UL @@ -439,9 +432,10 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) } static int __init pci_fire_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid) + struct of_device *op, u32 portid) { const struct linux_prom64_registers *regs; + struct device_node *dp = op->node; struct pci_pbm_info *pbm; int err; @@ -483,7 +477,9 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pci_fire_msi_init(pbm); - pci_fire_scan_bus(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, &op->dev); + + /* XXX register error interrupt handlers XXX */ return 0; } @@ -508,7 +504,7 @@ static int __devinit fire_probe(struct of_device *op, portid = of_getintprop_default(dp, "portid", 0xff); for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid)) - return pci_fire_pbm_init(pbm->parent, dp, portid); + return pci_fire_pbm_init(pbm->parent, op, portid); } err = -ENOMEM; @@ -534,7 +530,7 @@ static int __devinit fire_probe(struct of_device *op, p->pbm_B.iommu = iommu; - return pci_fire_pbm_init(p, dp, portid); + return pci_fire_pbm_init(p, op, portid); out_free_iommu_A: kfree(p->pbm_A.iommu); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 5ee84c5b963..47db875d023 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -803,11 +803,12 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void __init psycho_scan_bus(struct pci_pbm_info *pbm) +static void __init psycho_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = 0; - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); /* After the PCI bus scan is complete, we can register * the error interrupt handlers. @@ -971,8 +972,9 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL static void __init psycho_pbm_init(struct pci_controller_info *p, - struct device_node *dp, int is_pbm_a) + struct of_device *op, int is_pbm_a) { + struct device_node *dp = op->node; struct property *prop; struct pci_pbm_info *pbm; @@ -1015,7 +1017,7 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, psycho_pbm_strbuf_init(pbm, is_pbm_a); - psycho_scan_bus(pbm); + psycho_scan_bus(pbm, &op->dev); } #define PSYCHO_CONFIGSPACE 0x001000000UL @@ -1042,7 +1044,7 @@ static int __devinit psycho_probe(struct of_device *op, if (p->pbm_A.portid == upa_portid) { is_pbm_a = (p->pbm_A.prom_node == NULL); - psycho_pbm_init(p, dp, is_pbm_a); + psycho_pbm_init(p, op, is_pbm_a); return 0; } } @@ -1086,7 +1088,7 @@ static int __devinit psycho_probe(struct of_device *op, is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); - psycho_pbm_init(p, dp, is_pbm_a); + psycho_pbm_init(p, op, is_pbm_a); return 0; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index eee8fdca382..707d6d6130f 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -634,7 +634,8 @@ static void apb_init(struct pci_bus *sabre_bus) } } -static void __init sabre_scan_bus(struct pci_pbm_info *pbm) +static void __init sabre_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { static int once; @@ -662,7 +663,7 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) } once++; - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); if (!pbm->pci_bus) return; @@ -734,8 +735,10 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, } static void __init sabre_pbm_init(struct pci_controller_info *p, - struct pci_pbm_info *pbm, struct device_node *dp) + struct pci_pbm_info *pbm, struct of_device *op) { + struct device_node *dp = op->node; + pbm->name = dp->full_name; printk("%s: SABRE PCI Bus Module\n", pbm->name); @@ -753,7 +756,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - sabre_scan_bus(pbm); + sabre_scan_bus(pbm, &op->dev); } static int __devinit sabre_probe(struct of_device *op, @@ -873,7 +876,7 @@ static int __devinit sabre_probe(struct of_device *op, /* * Look for APB underneath. */ - sabre_pbm_init(p, pbm, dp); + sabre_pbm_init(p, pbm, op); return 0; out_free_iommu: diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index bd7612aae17..64904b180f4 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1085,14 +1085,15 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm) +static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = (of_find_property(pbm->prom_node, "66mhz-capable", NULL) != NULL); - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) tomatillo_register_error_handlers(pbm); @@ -1338,10 +1339,11 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } static int __devinit schizo_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid, + struct of_device *op, u32 portid, int chip_type) { const struct linux_prom64_registers *regs; + struct device_node *dp = op->node; struct pci_pbm_info *pbm; const char *chipset_name; int is_pbm_a, err; @@ -1422,7 +1424,7 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, schizo_pbm_strbuf_init(pbm); - schizo_scan_bus(pbm); + schizo_scan_bus(pbm, &op->dev); return 0; } @@ -1437,8 +1439,9 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } -static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_type) +static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) { + struct device_node *dp = op->node; struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; @@ -1450,7 +1453,7 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty err = -ENOMEM; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid, chip_type)) { - if (schizo_pbm_init(pbm->parent, dp, + if (schizo_pbm_init(pbm->parent, op, portid, chip_type)) goto out_err; return 0; @@ -1479,7 +1482,7 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty p->pbm_B.iommu = iommu; - if (schizo_pbm_init(p, dp, portid, chip_type)) + if (schizo_pbm_init(p, op, portid, chip_type)) goto out_free_iommu_B; return 0; @@ -1500,7 +1503,7 @@ out_err: static int __devinit schizo_probe(struct of_device *op, const struct of_device_id *match) { - return __schizo_init(op->node, (unsigned long) match->data); + return __schizo_init(op, (unsigned long) match->data); } /* The ordering of this table is very important. Some Tomatillo diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 21864f06532..4839c503c88 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -543,7 +543,8 @@ static const struct dma_ops sun4v_dma_ops = { .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu, }; -static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm) +static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { struct property *prop; struct device_node *dp; @@ -551,7 +552,7 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm) dp = pbm->prom_node; prop = of_find_property(dp, "66mhz-capable", NULL); pbm->is_66mhz_capable = (prop != NULL); - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); /* XXX register error interrupt handlers XXX */ } @@ -894,8 +895,9 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) #endif /* !(CONFIG_PCI_MSI) */ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 devhandle) + struct of_device *op, u32 devhandle) { + struct device_node *dp = op->node; struct pci_pbm_info *pbm; int err; @@ -934,7 +936,7 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, pci_sun4v_msi_init(pbm); - pci_sun4v_scan_bus(pbm); + pci_sun4v_scan_bus(pbm, &op->dev); return 0; } @@ -979,7 +981,7 @@ static int __devinit pci_sun4v_probe(struct of_device *op, for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (pbm->devhandle == (devhandle ^ 0x40)) { - return pci_sun4v_pbm_init(pbm->parent, dp, devhandle); + return pci_sun4v_pbm_init(pbm->parent, op, devhandle); } } @@ -1015,7 +1017,7 @@ static int __devinit pci_sun4v_probe(struct of_device *op, p->pbm_B.iommu = iommu; - return pci_sun4v_pbm_init(p, dp, devhandle); + return pci_sun4v_pbm_init(p, op, devhandle); out_free_iommu_A: kfree(p->pbm_A.iommu); -- cgit v1.2.3 From cdb3592a20b41377a28a0737dc9af95e53024470 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 19:31:16 -0700 Subject: sparc64: Move reboot handling into seperate file and kill power reg programming. We should always use prom_power_off(). Signed-off-by: David S. Miller --- arch/sparc/include/asm/reboot.h | 6 ----- arch/sparc64/kernel/Makefile | 2 +- arch/sparc64/kernel/power.c | 37 --------------------------- arch/sparc64/kernel/process.c | 33 ------------------------ arch/sparc64/kernel/reboot.c | 56 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 77 deletions(-) delete mode 100644 arch/sparc/include/asm/reboot.h create mode 100644 arch/sparc64/kernel/reboot.c (limited to 'arch') diff --git a/arch/sparc/include/asm/reboot.h b/arch/sparc/include/asm/reboot.h deleted file mode 100644 index 3f3f43f5be5..00000000000 --- a/arch/sparc/include/asm/reboot.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SPARC64_REBOOT_H -#define _SPARC64_REBOOT_H - -extern void machine_alt_power_off(void); - -#endif /* _SPARC64_REBOOT_H */ diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 928aa7c8058..fb02807167e 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -7,7 +7,7 @@ EXTRA_CFLAGS := -Werror extra-y := head.o init_task.o vmlinux.lds -obj-y := process.o setup.o cpu.o idprom.o \ +obj-y := process.o setup.o cpu.o idprom.o reboot.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o starfire.o \ diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 7559ad395a3..076cad7f975 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -7,21 +7,11 @@ #include #include #include -#include #include #include -#include #include #include -#include -#include - -/* - * sysctl - toggle power-off restriction for serial console - * systems in machine_power_off() - */ -int scons_pwroff = 1; static void __iomem *power_reg; @@ -33,31 +23,6 @@ static irqreturn_t power_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static void (*poweroff_method)(void) = machine_alt_power_off; - -void machine_power_off(void) -{ - sstate_poweroff(); - if (strcmp(of_console_device->type, "serial") || scons_pwroff) { - if (power_reg) { - /* Both register bits seem to have the - * same effect, so until I figure out - * what the difference is... - */ - writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg); - } else { - if (poweroff_method != NULL) { - poweroff_method(); - /* not reached */ - } - } - } - machine_halt(); -} - -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) { if (irq == 0xffffffff) @@ -78,8 +43,6 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id printk(KERN_INFO "%s: Control reg at %lx\n", op->node->name, res->start); - poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(irq, op->node)) { if (request_irq(irq, power_handler, 0, "power", NULL) < 0) diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 15f4178592e..11bb6c4612d 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,6 @@ #include #include -#include #include #include #include @@ -46,8 +44,6 @@ #include #include #include -#include -#include #include #include #include @@ -115,35 +111,6 @@ void cpu_idle(void) } } -void machine_halt(void) -{ - sstate_halt(); - prom_halt(); - panic("Halt failed!"); -} - -void machine_alt_power_off(void) -{ - sstate_poweroff(); - prom_halt_power_off(); - panic("Power-off failed!"); -} - -void machine_restart(char * cmd) -{ - char *p; - - sstate_reboot(); - p = strchr (reboot_command, '\n'); - if (p) *p = 0; - if (cmd) - prom_reboot(cmd); - if (*reboot_command) - prom_reboot(reboot_command); - prom_reboot(""); - panic("Reboot failed!"); -} - #ifdef CONFIG_COMPAT static void show_regwindow32(struct pt_regs *regs) { diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c new file mode 100644 index 00000000000..04dd34cbb87 --- /dev/null +++ b/arch/sparc64/kernel/reboot.c @@ -0,0 +1,56 @@ +/* reboot.c: reboot/shutdown/halt/poweroff handling + * + * Copyright (C) 2008 David S. Miller + */ +#include +#include +#include +#include + +#include +#include +#include + +/* sysctl - toggle power-off restriction for serial console + * systems in machine_power_off() + */ +int scons_pwroff = 1; + +/* This isn't actually used, it exists merely to satisfy the + * reference in kernel/sys.c + */ +void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); + +void machine_power_off(void) +{ + sstate_poweroff(); + if (strcmp(of_console_device->type, "serial") || scons_pwroff) + prom_halt_power_off(); + + prom_halt(); +} + +void machine_halt(void) +{ + sstate_halt(); + prom_halt(); + panic("Halt failed!"); +} + +void machine_restart(char *cmd) +{ + char *p; + + sstate_reboot(); + p = strchr(reboot_command, '\n'); + if (p) + *p = 0; + if (cmd) + prom_reboot(cmd); + if (*reboot_command) + prom_reboot(reboot_command); + prom_reboot(""); + panic("Reboot failed!"); +} + -- cgit v1.2.3 From 446139a8f7078d96159a936fd6059660db425405 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 2 Sep 2008 00:49:38 -0700 Subject: sparc64: Implement SSTATE purely using notifiers and initcalls. Don't clutter up the tree with sstate_blah() scattered all over the place. Signed-off-by: David S. Miller --- arch/sparc/include/asm/bugs.h | 7 ----- arch/sparc/include/asm/sstate.h | 13 -------- arch/sparc64/kernel/hvapi.c | 3 -- arch/sparc64/kernel/reboot.c | 4 --- arch/sparc64/kernel/sstate.c | 67 +++++++++++++++++++++++++++-------------- arch/sparc64/mm/init.c | 3 -- 6 files changed, 45 insertions(+), 52 deletions(-) delete mode 100644 arch/sparc/include/asm/sstate.h (limited to 'arch') diff --git a/arch/sparc/include/asm/bugs.h b/arch/sparc/include/asm/bugs.h index e179bc12f64..61d86bbbe2b 100644 --- a/arch/sparc/include/asm/bugs.h +++ b/arch/sparc/include/asm/bugs.h @@ -7,10 +7,6 @@ #include #endif -#ifdef CONFIG_SPARC64 -#include -#endif - extern unsigned long loops_per_jiffy; static void __init check_bugs(void) @@ -18,7 +14,4 @@ static void __init check_bugs(void) #if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP) cpu_data(0).udelay_val = loops_per_jiffy; #endif -#ifdef CONFIG_SPARC64 - sstate_running(); -#endif } diff --git a/arch/sparc/include/asm/sstate.h b/arch/sparc/include/asm/sstate.h deleted file mode 100644 index a7c35dbcb28..00000000000 --- a/arch/sparc/include/asm/sstate.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _SPARC64_SSTATE_H -#define _SPARC64_SSTATE_H - -extern void sstate_booting(void); -extern void sstate_running(void); -extern void sstate_halt(void); -extern void sstate_poweroff(void); -extern void sstate_panic(void); -extern void sstate_reboot(void); - -extern void sun4v_sstate_init(void); - -#endif /* _SPARC64_SSTATE_H */ diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c index 691760b5b01..1d272c3b574 100644 --- a/arch/sparc64/kernel/hvapi.c +++ b/arch/sparc64/kernel/hvapi.c @@ -9,7 +9,6 @@ #include #include -#include /* If the hypervisor indicates that the API setting * calls are unsupported, by returning HV_EBADTRAP or @@ -184,8 +183,6 @@ void __init sun4v_hvapi_init(void) if (sun4v_hvapi_register(group, major, &minor)) goto bad; - sun4v_sstate_init(); - return; bad: diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c index 04dd34cbb87..11f24966063 100644 --- a/arch/sparc64/kernel/reboot.c +++ b/arch/sparc64/kernel/reboot.c @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -24,7 +23,6 @@ EXPORT_SYMBOL(pm_power_off); void machine_power_off(void) { - sstate_poweroff(); if (strcmp(of_console_device->type, "serial") || scons_pwroff) prom_halt_power_off(); @@ -33,7 +31,6 @@ void machine_power_off(void) void machine_halt(void) { - sstate_halt(); prom_halt(); panic("Halt failed!"); } @@ -42,7 +39,6 @@ void machine_restart(char *cmd) { char *p; - sstate_reboot(); p = strchr(reboot_command, '\n'); if (p) *p = 0; diff --git a/arch/sparc64/kernel/sstate.c b/arch/sparc64/kernel/sstate.c index 5b6e75b7f05..8cdbe5946b4 100644 --- a/arch/sparc64/kernel/sstate.c +++ b/arch/sparc64/kernel/sstate.c @@ -1,14 +1,15 @@ /* sstate.c: System soft state support. * - * Copyright (C) 2007 David S. Miller + * Copyright (C) 2007, 2008 David S. Miller */ #include #include +#include #include #include -#include +#include #include #include #include @@ -50,31 +51,34 @@ static const char rebooting_msg[32] __attribute__((aligned(32))) = static const char panicing_msg[32] __attribute__((aligned(32))) = "Linux panicing"; -void sstate_booting(void) +static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused) { - do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); -} + const char *msg; -void sstate_running(void) -{ - do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); -} + switch (type) { + case SYS_DOWN: + default: + msg = rebooting_msg; + break; -void sstate_halt(void) -{ - do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg); -} + case SYS_HALT: + msg = halting_msg; + break; -void sstate_poweroff(void) -{ - do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg); -} + case SYS_POWER_OFF: + msg = poweroff_msg; + break; + } -void sstate_reboot(void) -{ - do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg); + do_set_sstate(HV_SOFT_STATE_TRANSITION, msg); + + return NOTIFY_OK; } +static struct notifier_block sstate_reboot_notifier = { + .notifier_call = sstate_reboot_call, +}; + static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) { do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg); @@ -87,18 +91,37 @@ static struct notifier_block sstate_panic_block = { .priority = INT_MAX, }; -void __init sun4v_sstate_init(void) +static int __init sstate_init(void) { unsigned long major, minor; + if (tlb_type != hypervisor) + return 0; + major = 1; minor = 0; if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) - return; + return 0; hv_supports_soft_state = 1; prom_sun4v_guest_soft_state(); + + do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); + atomic_notifier_chain_register(&panic_notifier_list, &sstate_panic_block); + register_reboot_notifier(&sstate_reboot_notifier); + + return 0; } + +core_initcall(sstate_init); + +static int __init sstate_running(void) +{ + do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); + return 0; +} + +late_initcall(sstate_running); diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 54193f2d0ab..7c3c81f60a6 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -1717,8 +1716,6 @@ void __init paging_init(void) kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; - sstate_booting(); - /* Invalidate both kernel TSBs. */ memset(swapper_tsb, 0x40, sizeof(swapper_tsb)); #ifndef CONFIG_DEBUG_PAGEALLOC -- cgit v1.2.3 From 0f73d1bbe6240bcdf14c221bbe2ece63540c5c44 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 20:18:04 -0700 Subject: pci_psycho: Use of_getintprop_default(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 47db875d023..0be850e6e58 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -975,7 +975,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, struct of_device *op, int is_pbm_a) { struct device_node *dp = op->node; - struct property *prop; struct pci_pbm_info *pbm; if (is_pbm_a) @@ -994,14 +993,8 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; - pbm->chip_version = 0; - prop = of_find_property(dp, "version#", NULL); - if (prop) - pbm->chip_version = *(int *) prop->value; - pbm->chip_revision = 0; - prop = of_find_property(dp, "module-revision#", NULL); - if (prop) - pbm->chip_revision = *(int *) prop->value; + pbm->chip_version = of_getintprop_default(dp, "version#", 0); + pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); pbm->parent = p; pbm->prom_node = dp; @@ -1031,13 +1024,9 @@ static int __devinit psycho_probe(struct of_device *op, struct pci_pbm_info *pbm; struct iommu *iommu; int is_pbm_a, err; - const u32 *p32; u32 upa_portid; - upa_portid = 0xff; - p32 = of_get_property(dp, "upa-portid", NULL); - if (p32) - upa_portid = *p32; + upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { struct pci_controller_info *p = pbm->parent; -- cgit v1.2.3 From 463801b3ae97fe1c652ce8da5a61367405d6ec3e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 20:21:15 -0700 Subject: pci_schizo: Use of_get_property() and delete spurious local vars. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_schizo.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 64904b180f4..e1c565744d3 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1152,24 +1152,17 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) { - struct iommu *iommu = pbm->iommu; + static const u32 vdma_default[] = { 0xc0000000, 0x40000000 }; unsigned long i, tagbase, database; - struct property *prop; - u32 vdma[2], dma_mask; + struct iommu *iommu = pbm->iommu; int tsbsize, err; + const u32 *vdma; + u32 dma_mask; u64 control; - prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); - if (prop) { - u32 *val = prop->value; - - vdma[0] = val[0]; - vdma[1] = val[1]; - } else { - /* No property, use default values. */ - vdma[0] = 0xc0000000; - vdma[1] = 0x40000000; - } + vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + if (!vdma) + vdma = vdma_default; dma_mask = vdma[0]; switch (vdma[1]) { @@ -1284,7 +1277,6 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) { - struct property *prop; u64 tmp; schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); @@ -1298,8 +1290,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) pbm->chip_version >= 0x2) tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; - prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL); - if (!prop) + if (!of_find_property(pbm->prom_node, "no-bus-parking", NULL)) tmp |= SCHIZO_PCICTRL_PARK; else tmp &= ~SCHIZO_PCICTRL_PARK; -- cgit v1.2.3 From 8aef72786192a46e20791b2e854ea3ed047bc15c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 20:23:18 -0700 Subject: pci_sun4v: Use of_get_property(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_sun4v.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 4839c503c88..6bed2f6bf7c 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -587,22 +587,15 @@ static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm, static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { + static const u32 vdma_default[] = { 0x80000000, 0x80000000 }; struct iommu *iommu = pbm->iommu; - struct property *prop; unsigned long num_tsb_entries, sz, tsbsize; - u32 vdma[2], dma_mask, dma_offset; - - prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); - if (prop) { - u32 *val = prop->value; - - vdma[0] = val[0]; - vdma[1] = val[1]; - } else { - /* No property, use default values. */ - vdma[0] = 0x80000000; - vdma[1] = 0x80000000; - } + u32 dma_mask, dma_offset; + const u32 *vdma; + + vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + if (!vdma) + vdma = vdma_default; if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { printk(KERN_ERR PFX "Strange virtual-dma[%08x:%08x].\n", -- cgit v1.2.3 From 9723f38eb53eac9a851210b629555a37afa3f15c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 2 Sep 2008 03:15:44 -0700 Subject: sparc32: Fix sun4c build warnings. Reported by Stephen Rothwell. Signed-off-by: David S. Miller --- arch/sparc/mm/sun4c.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 95070a1e1b7..fe65aeeb394 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1108,7 +1108,7 @@ static void sun4c_unlockarea(char *vaddr, unsigned long size) * by implication and fool the page locking code above * if passed to by mistake. */ -static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus *sbus) +static __u32 sun4c_get_scsi_one(struct device *dev, char *bufptr, unsigned long len) { unsigned long page; @@ -1120,7 +1120,7 @@ static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus return (__u32)sun4c_lockarea(bufptr, len); } -static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void sun4c_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) { while (sz != 0) { --sz; @@ -1130,14 +1130,14 @@ static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus * } } -static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct sbus_bus *sbus) +static void sun4c_release_scsi_one(struct device *dev, __u32 bufptr, unsigned long len) { if (bufptr < sun4c_iobuffer_start) return; /* On kernel stack or similar, see above */ sun4c_unlockarea((char *)bufptr, len); } -static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) +static void sun4c_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) { while (sz != 0) { --sz; -- cgit v1.2.3 From 5280267c1dddb8d413595b87dc406624bb497946 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Sep 2008 02:04:41 -0700 Subject: sparc: Fix handling of LANCE and ESP parent nodes in of_device.c The device nodes that sit above 'esp' and 'le' on SBUS lack a 'ranges' property, but we should pass the translation up to the parent node so that the SBUS level ranges get applied. Based upon a bug report from Robert Reif. Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device.c | 26 ++++++++++++++++++++++---- arch/sparc64/kernel/of_device.c | 11 ++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index c59014886af..4ef16075588 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -344,6 +344,27 @@ static int __init build_one_resource(struct device_node *parent, return 1; } +static int __init use_1to1_mapping(struct device_node *pp) +{ + /* If we have a ranges property in the parent, use it. */ + if (of_find_property(pp, "ranges", NULL) != NULL) + return 0; + + /* Some SBUS devices use intermediate nodes to express + * hierarchy within the device itself. These aren't + * real bus nodes, and don't have a 'ranges' property. + * But, we should still pass the translation work up + * to the SBUS itself. + */ + if (!strcmp(pp->name, "dma") || + !strcmp(pp->name, "espdma") || + !strcmp(pp->name, "ledma") || + !strcmp(pp->name, "lebuffer")) + return 0; + + return 1; +} + static int of_resource_verbose; static void __init build_device_resources(struct of_device *op, @@ -389,10 +410,7 @@ static void __init build_device_resources(struct of_device *op, memcpy(addr, reg, na * 4); - /* If the immediate parent has no ranges property to apply, - * just use a 1<->1 mapping. - */ - if (of_find_property(pp, "ranges", NULL) == NULL) { + if (use_1to1_mapping(pp)) { result = of_read_addr(addr, na); goto build_res; } diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index e427086e3b5..c15bcdf75c0 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -438,8 +438,17 @@ static int __init use_1to1_mapping(struct device_node *pp) /* If the parent is the dma node of an ISA bus, pass * the translation up to the root. + * + * Some SBUS devices use intermediate nodes to express + * hierarchy within the device itself. These aren't + * real bus nodes, and don't have a 'ranges' property. + * But, we should still pass the translation work up + * to the SBUS itself. */ - if (!strcmp(pp->name, "dma")) + if (!strcmp(pp->name, "dma") || + !strcmp(pp->name, "espdma") || + !strcmp(pp->name, "ledma") || + !strcmp(pp->name, "lebuffer")) return 0; /* Similarly for all PCI bridges, if we get this far -- cgit v1.2.3 From a57a5c2e8db8d80f460dcad77877895718c9f209 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 4 Sep 2008 01:03:02 +0400 Subject: x86 setup: remove remnants of CONFIG_VIDEO_SELECT (read: vga=) Impact: cleanup Video mode selection became always possible in 2.6.23-rc1 after i386 setup code rewrite in C. Regardless, VIDEO_SELECT is stupid config option because it affects only kernel setup code, not code which always stays in memory. vga= always possible now which is good. Signed-off-by: Alexey Dobriyan Signed-off-by: H. Peter Anvin --- arch/x86/configs/i386_defconfig | 1 - arch/x86/configs/x86_64_defconfig | 1 - 2 files changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 9bc34e2033e..a7ae4385670 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -1482,7 +1482,6 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_VGA_CONSOLE=y CONFIG_VGACON_SOFT_SCROLLBACK=y CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 -CONFIG_VIDEO_SELECT=y CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set CONFIG_LOGO=y diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index ae5124e064d..743e8039273 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -1449,7 +1449,6 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_VGA_CONSOLE=y CONFIG_VGACON_SOFT_SCROLLBACK=y CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 -CONFIG_VIDEO_SELECT=y CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set CONFIG_LOGO=y -- cgit v1.2.3 From c4cbe6f96ebf8eb03884c31504d36dccd2ef1062 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Sep 2008 15:52:38 -0700 Subject: sparc32: use RTC subsystem Use rtc subsystem for sparc32 architecture. Actually, only one driver is needed: m48t59 as it supports the most common clocks on sparc32 machines: m48t08 and m48t02. [ Add proper RTC layer calls to set_rtc_mmss() -DaveM ] Signed-off-by: Krzysztof Helt Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 2 + arch/sparc/kernel/sparc_ksyms.c | 2 - arch/sparc/kernel/time.c | 217 +++++++++++----------------------------- 3 files changed, 62 insertions(+), 159 deletions(-) (limited to 'arch') diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index a4c7fb7afc8..97671dac12a 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -75,6 +75,8 @@ config SPARC select HAVE_ARCH_KGDB if !SMP select HAVE_ARCH_TRACEHOOK select ARCH_WANT_OPTIONAL_GPIOLIB + select RTC_CLASS + select RTC_DRV_M48T59 # Identify this as a Sparc32 build config SPARC32 diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 6007ac5a736..0ce002e3955 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -123,8 +123,6 @@ EXPORT_SYMBOL(phys_cpu_present_map); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(rtc_lock); -EXPORT_SYMBOL(mostek_lock); -EXPORT_SYMBOL(mstk48t02_regs); #ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(set_auxio); EXPORT_SYMBOL(get_auxio); diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index f0a2874b04e..698c45059fa 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,10 +32,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -46,10 +48,6 @@ #include "irq.h" DEFINE_SPINLOCK(rtc_lock); -static enum sparc_clock_type sp_clock_typ; -DEFINE_SPINLOCK(mostek_lock); -void __iomem *mstk48t02_regs = NULL; -static struct mostek48t08 __iomem *mstk48t08_regs = NULL; static int set_rtc_mmss(unsigned long); static int sbus_do_settimeofday(struct timespec *tv); @@ -118,107 +116,55 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) return IRQ_HANDLED; } -/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ -static void __devinit kick_start_clock(void) +static unsigned char mostek_read_byte(struct device *dev, u32 ofs) { - struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; - unsigned char sec; - int i, count; - - prom_printf("CLOCK: Clock was stopped. Kick start "); - - spin_lock_irq(&mostek_lock); - - /* Turn on the kick start bit to start the oscillator. */ - regs->creg |= MSTK_CREG_WRITE; - regs->sec &= ~MSTK_STOP; - regs->hour |= MSTK_KICK_START; - regs->creg &= ~MSTK_CREG_WRITE; - - spin_unlock_irq(&mostek_lock); - - /* Delay to allow the clock oscillator to start. */ - sec = MSTK_REG_SEC(regs); - for (i = 0; i < 3; i++) { - while (sec == MSTK_REG_SEC(regs)) - for (count = 0; count < 100000; count++) - /* nothing */ ; - prom_printf("."); - sec = regs->sec; + struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; + void __iomem *regs = pdata->ioaddr; + unsigned char val = readb(regs + ofs); + + /* the year 0 is 1968 */ + if (ofs == pdata->offset + M48T59_YEAR) { + val += 0x68; + if ((val & 0xf) > 9) + val += 6; } - prom_printf("\n"); - - spin_lock_irq(&mostek_lock); - - /* Turn off kick start and set a "valid" time and date. */ - regs->creg |= MSTK_CREG_WRITE; - regs->hour &= ~MSTK_KICK_START; - MSTK_SET_REG_SEC(regs,0); - MSTK_SET_REG_MIN(regs,0); - MSTK_SET_REG_HOUR(regs,0); - MSTK_SET_REG_DOW(regs,5); - MSTK_SET_REG_DOM(regs,1); - MSTK_SET_REG_MONTH(regs,8); - MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); - regs->creg &= ~MSTK_CREG_WRITE; - - spin_unlock_irq(&mostek_lock); - - /* Ensure the kick start bit is off. If it isn't, turn it off. */ - while (regs->hour & MSTK_KICK_START) { - prom_printf("CLOCK: Kick start still on!\n"); - - spin_lock_irq(&mostek_lock); - regs->creg |= MSTK_CREG_WRITE; - regs->hour &= ~MSTK_KICK_START; - regs->creg &= ~MSTK_CREG_WRITE; - spin_unlock_irq(&mostek_lock); - } - - prom_printf("CLOCK: Kick start procedure successful.\n"); + return val; } -/* Return nonzero if the clock chip battery is low. */ -static inline int has_low_battery(void) +static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) { - struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; - unsigned char data1, data2; - - spin_lock_irq(&mostek_lock); - data1 = regs->eeprom[0]; /* Read some data. */ - regs->eeprom[0] = ~data1; /* Write back the complement. */ - data2 = regs->eeprom[0]; /* Read back the complement. */ - regs->eeprom[0] = data1; /* Restore the original value. */ - spin_unlock_irq(&mostek_lock); - - return (data1 == data2); /* Was the write blocked? */ + struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; + void __iomem *regs = pdata->ioaddr; + + if (ofs == pdata->offset + M48T59_YEAR) { + if (val < 0x68) + val += 0x32; + else + val -= 0x68; + if ((val & 0xf) > 9) + val += 6; + if ((val & 0xf0) > 0x9A) + val += 0x60; + } + writeb(val, regs + ofs); } -static void __devinit mostek_set_system_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - - mregs = (struct mostek48t02 *)mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - spin_lock_irq(&mostek_lock); - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - mregs->creg &= ~MSTK_CREG_READ; - spin_unlock_irq(&mostek_lock); -} +static struct m48t59_plat_data m48t59_data = { + .read_byte = mostek_read_byte, + .write_byte = mostek_write_byte, +}; + +/* resource is set at runtime */ +static struct platform_device m48t59_rtc = { + .name = "rtc-m48t59", + .id = 0, + .num_resources = 1, + .dev = { + .platform_data = &m48t59_data, + }, +}; static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { @@ -228,33 +174,21 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id if (!model) return -ENODEV; + m48t59_rtc.resource = &op->resource[0]; if (!strcmp(model, "mk48t02")) { - sp_clock_typ = MSTK48T02; - /* Map the clock register io area read-only */ - mstk48t02_regs = of_ioremap(&op->resource[0], 0, - sizeof(struct mostek48t02), - "mk48t02"); - mstk48t08_regs = NULL; /* To catch weirdness */ + m48t59_data.ioaddr = of_ioremap(&op->resource[0], 0, + 2048, "rtc-m48t59"); + m48t59_data.type = M48T59RTC_TYPE_M48T02; } else if (!strcmp(model, "mk48t08")) { - sp_clock_typ = MSTK48T08; - mstk48t08_regs = of_ioremap(&op->resource[0], 0, - sizeof(struct mostek48t08), - "mk48t08"); - - mstk48t02_regs = &mstk48t08_regs->regs; + m48t59_data.ioaddr = of_ioremap(&op->resource[0], 0, + 8192, "rtc-m48t59"); + m48t59_data.type = M48T59RTC_TYPE_M48T08; } else return -ENODEV; - /* Report a low battery voltage condition. */ - if (has_low_battery()) - printk(KERN_CRIT "NVRAM: Low battery voltage!\n"); - - /* Kick start the clock if it is completely stopped. */ - if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) - kick_start_clock(); - - mostek_set_system_time(); + if (platform_device_register(&m48t59_rtc) < 0) + printk(KERN_ERR "Registering RTC device failed\n"); return 0; } @@ -270,7 +204,7 @@ static struct of_platform_driver clock_driver = { .match_table = clock_match, .probe = clock_probe, .driver = { - .name = "clock", + .name = "rtc", }, }; @@ -400,43 +334,12 @@ static int sbus_do_settimeofday(struct timespec *tv) return 0; } -/* - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you won't notice until after reboot! - */ -static int set_rtc_mmss(unsigned long nowtime) +static int set_rtc_mmss(unsigned long secs) { - int real_seconds, real_minutes, mostek_minutes; - struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; - unsigned long flags; + struct rtc_device *rtc = rtc_class_open("rtc0"); - spin_lock_irqsave(&mostek_lock, flags); - /* Read the current RTC minutes. */ - regs->creg |= MSTK_CREG_READ; - mostek_minutes = MSTK_REG_MIN(regs); - regs->creg &= ~MSTK_CREG_READ; + if (rtc) + return rtc_set_mmss(rtc, secs); - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - mostek_minutes) < 30) { - regs->creg |= MSTK_CREG_WRITE; - MSTK_SET_REG_SEC(regs,real_seconds); - MSTK_SET_REG_MIN(regs,real_minutes); - regs->creg &= ~MSTK_CREG_WRITE; - spin_unlock_irqrestore(&mostek_lock, flags); - return 0; - } else { - spin_unlock_irqrestore(&mostek_lock, flags); - return -1; - } + return -1; } -- cgit v1.2.3 From 81c4fdb1d64a44ffc17c5c64b32a1be4fc85dd55 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Sep 2008 15:56:27 -0700 Subject: sparc32: Kill remaining asm/mostek.h inclusions. No longer needed. Signed-off-by: David S. Miller --- arch/sparc/kernel/sparc_ksyms.c | 1 - arch/sparc/kernel/tick14.c | 1 - 2 files changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 0ce002e3955..b0dfff84865 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index 707bfda8657..77a4f3aeec6 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From f6e30ffcf3749fd3bdf267156bd0f56eba68f2f8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Sep 2008 15:57:04 -0700 Subject: sparc32: Kill asm/mostek.h. No longer used. Signed-off-by: David S. Miller --- arch/sparc/include/asm/mostek.h | 133 ---------------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 arch/sparc/include/asm/mostek.h (limited to 'arch') diff --git a/arch/sparc/include/asm/mostek.h b/arch/sparc/include/asm/mostek.h deleted file mode 100644 index 98b44dd93e4..00000000000 --- a/arch/sparc/include/asm/mostek.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * mostek.h: Describes the various Mostek time of day clock registers. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) - * Added intersil code 05/25/98 Chris Davis (cdavis@cois.on.ca) - */ - -#ifndef _SPARC_MOSTEK_H -#define _SPARC_MOSTEK_H - -#include -#include - -/* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) - * - * Data - * Address Function - * Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0 - * 7ff - - - - - - - - Year 00-99 - * 7fe 0 0 0 - - - - - Month 01-12 - * 7fd 0 0 - - - - - - Date 01-31 - * 7fc 0 FT 0 0 0 - - - Day 01-07 - * 7fb KS 0 - - - - - - Hours 00-23 - * 7fa 0 - - - - - - - Minutes 00-59 - * 7f9 ST - - - - - - - Seconds 00-59 - * 7f8 W R S - - - - - Control - * - * * ST is STOP BIT - * * W is WRITE BIT - * * R is READ BIT - * * S is SIGN BIT - * * FT is FREQ TEST BIT - * * KS is KICK START BIT - */ - -/* The Mostek 48t02 real time clock and NVRAM chip. The registers - * other than the control register are in binary coded decimal. Some - * control bits also live outside the control register. - */ -#define mostek_read(_addr) readb(_addr) -#define mostek_write(_addr,_val) writeb(_val, _addr) -#define MOSTEK_EEPROM 0x0000UL -#define MOSTEK_IDPROM 0x07d8UL -#define MOSTEK_CREG 0x07f8UL -#define MOSTEK_SEC 0x07f9UL -#define MOSTEK_MIN 0x07faUL -#define MOSTEK_HOUR 0x07fbUL -#define MOSTEK_DOW 0x07fcUL -#define MOSTEK_DOM 0x07fdUL -#define MOSTEK_MONTH 0x07feUL -#define MOSTEK_YEAR 0x07ffUL - -struct mostek48t02 { - volatile char eeprom[2008]; /* This is the eeprom, don't touch! */ - struct idprom idprom; /* The idprom lives here. */ - volatile unsigned char creg; /* Control register */ - volatile unsigned char sec; /* Seconds (0-59) */ - volatile unsigned char min; /* Minutes (0-59) */ - volatile unsigned char hour; /* Hour (0-23) */ - volatile unsigned char dow; /* Day of the week (1-7) */ - volatile unsigned char dom; /* Day of the month (1-31) */ - volatile unsigned char month; /* Month of year (1-12) */ - volatile unsigned char year; /* Year (0-99) */ -}; - -extern spinlock_t mostek_lock; -extern void __iomem *mstk48t02_regs; - -/* Control register values. */ -#define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ -#define MSTK_CREG_READ 0x40 /* Stop updates to allow a clean read. */ -#define MSTK_CREG_SIGN 0x20 /* Slow/speed clock in calibration mode. */ - -/* Control bits that live in the other registers. */ -#define MSTK_STOP 0x80 /* Stop the clock oscillator. (sec) */ -#define MSTK_KICK_START 0x80 /* Kick start the clock chip. (hour) */ -#define MSTK_FREQ_TEST 0x40 /* Frequency test mode. (day) */ - -#define MSTK_YEAR_ZERO 1968 /* If year reg has zero, it is 1968. */ -#define MSTK_CVT_YEAR(yr) ((yr) + MSTK_YEAR_ZERO) - -/* Masks that define how much space each value takes up. */ -#define MSTK_SEC_MASK 0x7f -#define MSTK_MIN_MASK 0x7f -#define MSTK_HOUR_MASK 0x3f -#define MSTK_DOW_MASK 0x07 -#define MSTK_DOM_MASK 0x3f -#define MSTK_MONTH_MASK 0x1f -#define MSTK_YEAR_MASK 0xffU - -/* Binary coded decimal conversion macros. */ -#define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) -#define MSTK_DECIMAL_TO_REGVAL(x) ((((x) / 0x0A) << 0x04) + ((x) % 0x0A)) - -/* Generic register set and get macros for internal use. */ -#define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(((struct mostek48t02 *)regs)->var & MSTK_ ## mask ## _MASK)) -#define MSTK_SET(regs,var,value,mask) do { ((struct mostek48t02 *)regs)->var &= ~(MSTK_ ## mask ## _MASK); ((struct mostek48t02 *)regs)->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0) - -/* Macros to make register access easier on our fingers. These give you - * the decimal value of the register requested if applicable. You pass - * the a pointer to a 'struct mostek48t02'. - */ -#define MSTK_REG_CREG(regs) (((struct mostek48t02 *)regs)->creg) -#define MSTK_REG_SEC(regs) MSTK_GET(regs,sec,SEC) -#define MSTK_REG_MIN(regs) MSTK_GET(regs,min,MIN) -#define MSTK_REG_HOUR(regs) MSTK_GET(regs,hour,HOUR) -#define MSTK_REG_DOW(regs) MSTK_GET(regs,dow,DOW) -#define MSTK_REG_DOM(regs) MSTK_GET(regs,dom,DOM) -#define MSTK_REG_MONTH(regs) MSTK_GET(regs,month,MONTH) -#define MSTK_REG_YEAR(regs) MSTK_GET(regs,year,YEAR) - -#define MSTK_SET_REG_SEC(regs,value) MSTK_SET(regs,sec,value,SEC) -#define MSTK_SET_REG_MIN(regs,value) MSTK_SET(regs,min,value,MIN) -#define MSTK_SET_REG_HOUR(regs,value) MSTK_SET(regs,hour,value,HOUR) -#define MSTK_SET_REG_DOW(regs,value) MSTK_SET(regs,dow,value,DOW) -#define MSTK_SET_REG_DOM(regs,value) MSTK_SET(regs,dom,value,DOM) -#define MSTK_SET_REG_MONTH(regs,value) MSTK_SET(regs,month,value,MONTH) -#define MSTK_SET_REG_YEAR(regs,value) MSTK_SET(regs,year,value,YEAR) - - -/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the - * same (basically) layout of the 48t02 chip except for the extra - * NVRAM on board (8 KB against the 48t02's 2 KB). - */ -struct mostek48t08 { - char offset[6*1024]; /* Magic things may be here, who knows? */ - struct mostek48t02 regs; /* Here is what we are interested in. */ -}; - -enum sparc_clock_type { MSTK48T02, MSTK48T08, MSTK_INVALID }; - -#endif /* !(_SPARC_MOSTEK_H) */ -- cgit v1.2.3 From 94d5b5432b96efa69840b397853cf2cb81ab4fab Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Sep 2008 16:19:46 -0700 Subject: sparc: Remove asm/rtc.h No more users. Signed-off-by: David S. Miller --- arch/sparc/include/asm/rtc.h | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 arch/sparc/include/asm/rtc.h (limited to 'arch') diff --git a/arch/sparc/include/asm/rtc.h b/arch/sparc/include/asm/rtc.h deleted file mode 100644 index f9ecb1fe2ec..00000000000 --- a/arch/sparc/include/asm/rtc.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * rtc.h: Definitions for access to the Mostek real time clock - * - * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) - */ - -#ifndef _RTC_H -#define _RTC_H - -#include - -struct rtc_time -{ - int sec; /* Seconds (0-59) */ - int min; /* Minutes (0-59) */ - int hour; /* Hour (0-23) */ - int dow; /* Day of the week (1-7) */ - int dom; /* Day of the month (1-31) */ - int month; /* Month of year (1-12) */ - int year; /* Year (0-99) */ -}; - -#define RTCGET _IOR('p', 20, struct rtc_time) -#define RTCSET _IOW('p', 21, struct rtc_time) - -#endif -- cgit v1.2.3 From 1aa0365f275f7df6bb1e0b6667ed2b54199fe21d Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 3 Sep 2008 16:29:42 -0700 Subject: sparc32: add init memory poisoning This patch adds init memory poisoning. It looks like totalram_pages was not updated properly in free_initrd_mem so I fixed that as well. Signed-off-by: Robert Reif Signed-off-by: David S. Miller --- arch/sparc/mm/init.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index e103f1bb377..677c1e187a2 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -480,6 +481,7 @@ void free_initmem (void) for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { struct page *p; + memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); p = virt_to_page(addr); ClearPageReserved(p); @@ -488,20 +490,26 @@ void free_initmem (void) totalram_pages++; num_physpages++; } - printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); + printk(KERN_INFO "Freeing unused kernel memory: %dk freed\n", + (&__init_end - &__init_begin) >> 10); } #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { if (start < end) - printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", + (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - struct page *p = virt_to_page(start); + struct page *p; + + memset((void *)start, POISON_FREE_INITMEM, PAGE_SIZE); + p = virt_to_page(start); ClearPageReserved(p); init_page_count(p); __free_page(p); + totalram_pages++; num_physpages++; } } -- cgit v1.2.3 From 92a7507926b0698711ed010288b57582776eec31 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Sep 2008 14:07:11 +0100 Subject: Make suitable for 64-bit platforms. At the moment, 64-bit platforms (other than Alpha) are all redefining things for themselves instead of using . As is ARM, since it has special requirements w.r.t. padding. Make more generic, and they can use it directly. Signed-off-by: David Woodhouse --- arch/alpha/include/asm/statfs.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/alpha/include/asm/statfs.h b/arch/alpha/include/asm/statfs.h index ad15830baef..de35cd438a1 100644 --- a/arch/alpha/include/asm/statfs.h +++ b/arch/alpha/include/asm/statfs.h @@ -1,6 +1,10 @@ #ifndef _ALPHA_STATFS_H #define _ALPHA_STATFS_H +/* Alpha is the only 64-bit platform with 32-bit statfs. And doesn't + even seem to implement statfs64 */ +#define __statfs_word __u32 + #include #endif -- cgit v1.2.3 From a5e48a28d04f0078dbf850159f7c068864f24bb1 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Sep 2008 14:09:15 +0100 Subject: ARM: Use Signed-off-by: David Woodhouse --- arch/arm/include/asm/statfs.h | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/statfs.h b/arch/arm/include/asm/statfs.h index a02e6a8c3d7..079447c05ba 100644 --- a/arch/arm/include/asm/statfs.h +++ b/arch/arm/include/asm/statfs.h @@ -1,42 +1,12 @@ #ifndef _ASMARM_STATFS_H #define _ASMARM_STATFS_H -#ifndef __KERNEL_STRICT_NAMES -# include -typedef __kernel_fsid_t fsid_t; -#endif - -struct statfs { - __u32 f_type; - __u32 f_bsize; - __u32 f_blocks; - __u32 f_bfree; - __u32 f_bavail; - __u32 f_files; - __u32 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -}; - /* * With EABI there is 4 bytes of padding added to this structure. * Let's pack it so the padding goes away to simplify dual ABI support. * Note that user space does NOT have to pack this structure. */ -struct statfs64 { - __u32 f_type; - __u32 f_bsize; - __u64 f_blocks; - __u64 f_bfree; - __u64 f_bavail; - __u64 f_files; - __u64 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -} __attribute__ ((packed,aligned(4))); +#define ARCH_PACK_STATFS64 __attribute__((packed,aligned(4))) +#include #endif -- cgit v1.2.3 From 4dc429243d0ced7db475d826b4606c21cc28c325 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Sep 2008 14:10:03 +0100 Subject: IA64: Use Signed-off-by: David Woodhouse --- arch/ia64/include/asm/statfs.h | 52 ++++-------------------------------------- 1 file changed, 5 insertions(+), 47 deletions(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/statfs.h b/arch/ia64/include/asm/statfs.h index 811097974f3..1e589669de5 100644 --- a/arch/ia64/include/asm/statfs.h +++ b/arch/ia64/include/asm/statfs.h @@ -8,55 +8,13 @@ * David Mosberger-Tang , Hewlett-Packard Co */ -#ifndef __KERNEL_STRICT_NAMES -# include -typedef __kernel_fsid_t fsid_t; -#endif - /* - * This is ugly --- we're already 64-bit, so just duplicate the definitions + * We need compat_statfs64 to be packed, because the i386 ABI won't + * add padding at the end to bring it to a multiple of 8 bytes, but + * the IA64 ABI will. */ -struct statfs { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; - - -struct statfs64 { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; +#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4))) -struct compat_statfs64 { - __u32 f_type; - __u32 f_bsize; - __u64 f_blocks; - __u64 f_bfree; - __u64 f_bavail; - __u64 f_files; - __u64 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -} __attribute__((packed)); +#include #endif /* _ASM_IA64_STATFS_H */ -- cgit v1.2.3 From 7f16a339787d45f997d67c1a4dea3c357f48e121 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 4 Sep 2008 06:19:45 -0700 Subject: x86: boot/compressed/Makefile: fix "make clean" The Kbuild variable "targets" is supposed to be configuration-independent and reflect "all possible targets". This is required to make "make clean" work properly. Therefore, move all manipulation of "targets" as well as custom rules out of the x86-32 ifdef statement. Only leave inside the ifdefs the things that are genuinely configuration-dependent. Signed-off-by: H. Peter Anvin --- arch/x86/boot/compressed/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 92fdd35bd93..1771c804e02 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -27,9 +27,8 @@ $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) -ifeq ($(CONFIG_X86_32),y) -targets += vmlinux.bin.all vmlinux.relocs -hostprogs-y := relocs +targets += vmlinux.bin.all vmlinux.relocs relocs +hostprogs-$(CONFIG_X86_32) += relocs quiet_cmd_relocs = RELOCS $@ cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< @@ -43,6 +42,8 @@ quiet_cmd_relocbin = BUILD $@ $(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE $(call if_changed,relocbin) +ifeq ($(CONFIG_X86_32),y) + ifdef CONFIG_RELOCATABLE $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE $(call if_changed,gzip) @@ -59,6 +60,5 @@ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T endif - $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE $(call if_changed,ld) -- cgit v1.2.3 From 1625324d22409e32e3f8eb86018cad72e1c09d61 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 27 Aug 2008 23:01:16 -0700 Subject: x86: move dir es7000 to es7000_32.c to be aligned with numaq, summit. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/es7000/Makefile | 5 - arch/x86/es7000/es7000.h | 114 -------------- arch/x86/es7000/es7000plat.c | 262 ------------------------------- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/es7000_32.c | 345 +++++++++++++++++++++++++++++++++++++++++ arch/x86/mach-generic/Makefile | 1 - 6 files changed, 346 insertions(+), 382 deletions(-) delete mode 100644 arch/x86/es7000/Makefile delete mode 100644 arch/x86/es7000/es7000.h delete mode 100644 arch/x86/es7000/es7000plat.c create mode 100644 arch/x86/kernel/es7000_32.c (limited to 'arch') diff --git a/arch/x86/es7000/Makefile b/arch/x86/es7000/Makefile deleted file mode 100644 index 3ef8b43b62f..00000000000 --- a/arch/x86/es7000/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-$(CONFIG_X86_ES7000) := es7000plat.o diff --git a/arch/x86/es7000/es7000.h b/arch/x86/es7000/es7000.h deleted file mode 100644 index 4e62f6fa95b..00000000000 --- a/arch/x86/es7000/es7000.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Written by: Garry Forsgren, Unisys Corporation - * Natalie Protasevich, Unisys Corporation - * This file contains the code to configure and interface - * with Unisys ES7000 series hardware system manager. - * - * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Unisys Corporation, Township Line & Union Meeting - * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: - * - * http://www.unisys.com - */ - -/* - * ES7000 chipsets - */ - -#define NON_UNISYS 0 -#define ES7000_CLASSIC 1 -#define ES7000_ZORRO 2 - - -#define MIP_REG 1 -#define MIP_PSAI_REG 4 - -#define MIP_BUSY 1 -#define MIP_SPIN 0xf0000 -#define MIP_VALID 0x0100000000000000ULL -#define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) - -#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) - -struct mip_reg_info { - unsigned long long mip_info; - unsigned long long delivery_info; - unsigned long long host_reg; - unsigned long long mip_reg; -}; - -struct part_info { - unsigned char type; - unsigned char length; - unsigned char part_id; - unsigned char apic_mode; - unsigned long snum; - char ptype[16]; - char sname[64]; - char pname[64]; -}; - -struct psai { - unsigned long long entry_type; - unsigned long long addr; - unsigned long long bep_addr; -}; - -struct es7000_mem_info { - unsigned char type; - unsigned char length; - unsigned char resv[6]; - unsigned long long start; - unsigned long long size; -}; - -struct es7000_oem_table { - unsigned long long hdr; - struct mip_reg_info mip; - struct part_info pif; - struct es7000_mem_info shm; - struct psai psai; -}; - -#ifdef CONFIG_ACPI - -struct oem_table { - struct acpi_table_header Header; - u32 OEMTableAddr; - u32 OEMTableSize; -}; - -extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); -#endif - -struct mip_reg { - unsigned long long off_0; - unsigned long long off_8; - unsigned long long off_10; - unsigned long long off_18; - unsigned long long off_20; - unsigned long long off_28; - unsigned long long off_30; - unsigned long long off_38; -}; - -#define MIP_SW_APIC 0x1020b -#define MIP_FUNC(VALUE) (VALUE & 0xff) - -extern int parse_unisys_oem (char *oemptr); -extern void setup_unisys(void); -extern int es7000_start_cpu(int cpu, unsigned long eip); -extern void es7000_sw_apic(void); diff --git a/arch/x86/es7000/es7000plat.c b/arch/x86/es7000/es7000plat.c deleted file mode 100644 index 7789fde13c3..00000000000 --- a/arch/x86/es7000/es7000plat.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Written by: Garry Forsgren, Unisys Corporation - * Natalie Protasevich, Unisys Corporation - * This file contains the code to configure and interface - * with Unisys ES7000 series hardware system manager. - * - * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Unisys Corporation, Township Line & Union Meeting - * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: - * - * http://www.unisys.com - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "es7000.h" -#include - -/* - * ES7000 Globals - */ - -static volatile unsigned long *psai = NULL; -static struct mip_reg *mip_reg; -static struct mip_reg *host_reg; -static int mip_port; -static unsigned long mip_addr, host_addr; - -int es7000_plat; - -/* - * GSI override for ES7000 platforms. - */ - -static unsigned int base; - -static int -es7000_rename_gsi(int ioapic, int gsi) -{ - if (es7000_plat == ES7000_ZORRO) - return gsi; - - if (!base) { - int i; - for (i = 0; i < nr_ioapics; i++) - base += nr_ioapic_registers[i]; - } - - if (!ioapic && (gsi < 16)) - gsi += base; - return gsi; -} - -void __init -setup_unisys(void) -{ - /* - * Determine the generation of the ES7000 currently running. - * - * es7000_plat = 1 if the machine is a 5xx ES7000 box - * es7000_plat = 2 if the machine is a x86_64 ES7000 box - * - */ - if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2)) - es7000_plat = ES7000_ZORRO; - else - es7000_plat = ES7000_CLASSIC; - ioapic_renumber_irq = es7000_rename_gsi; -} - -/* - * Parse the OEM Table - */ - -int __init -parse_unisys_oem (char *oemptr) -{ - int i; - int success = 0; - unsigned char type, size; - unsigned long val; - char *tp = NULL; - struct psai *psaip = NULL; - struct mip_reg_info *mi; - struct mip_reg *host, *mip; - - tp = oemptr; - - tp += 8; - - for (i=0; i <= 6; i++) { - type = *tp++; - size = *tp++; - tp -= 2; - switch (type) { - case MIP_REG: - mi = (struct mip_reg_info *)tp; - val = MIP_RD_LO(mi->host_reg); - host_addr = val; - host = (struct mip_reg *)val; - host_reg = __va(host); - val = MIP_RD_LO(mi->mip_reg); - mip_port = MIP_PORT(mi->mip_info); - mip_addr = val; - mip = (struct mip_reg *)val; - mip_reg = __va(mip); - pr_debug("es7000_mipcfg: host_reg = 0x%lx \n", - (unsigned long)host_reg); - pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n", - (unsigned long)mip_reg); - success++; - break; - case MIP_PSAI_REG: - psaip = (struct psai *)tp; - if (tp != NULL) { - if (psaip->addr) - psai = __va(psaip->addr); - else - psai = NULL; - success++; - } - break; - default: - break; - } - tp += size; - } - - if (success < 2) { - es7000_plat = NON_UNISYS; - } else - setup_unisys(); - return es7000_plat; -} - -#ifdef CONFIG_ACPI -int __init -find_unisys_acpi_oem_table(unsigned long *oem_addr) -{ - struct acpi_table_header *header = NULL; - int i = 0; - while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { - if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { - struct oem_table *t = (struct oem_table *)header; - *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr, - t->OEMTableSize); - return 0; - } - } - return -1; -} -#endif - -static void -es7000_spin(int n) -{ - int i = 0; - - while (i++ < n) - rep_nop(); -} - -static int __init -es7000_mip_write(struct mip_reg *mip_reg) -{ - int status = 0; - int spin; - - spin = MIP_SPIN; - while (((unsigned long long)host_reg->off_38 & - (unsigned long long)MIP_VALID) != 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for Host Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); - outb(1, mip_port); - - spin = MIP_SPIN; - - while (((unsigned long long)mip_reg->off_38 & - (unsigned long long)MIP_VALID) == 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for MIP Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - status = ((unsigned long long)mip_reg->off_0 & - (unsigned long long)0xffff0000000000ULL) >> 48; - mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & - (unsigned long long)~MIP_VALID); - return status; -} - -int -es7000_start_cpu(int cpu, unsigned long eip) -{ - unsigned long vect = 0, psaival = 0; - - if (psai == NULL) - return -1; - - vect = ((unsigned long)__pa(eip)/0x1000) << 16; - psaival = (0x1000000 | vect | cpu); - - while (*psai & 0x1000000) - ; - - *psai = psaival; - - return 0; - -} - -void __init -es7000_sw_apic(void) -{ - if (es7000_plat) { - int mip_status; - struct mip_reg es7000_mip_reg; - - printk("ES7000: Enabling APIC mode.\n"); - memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); - es7000_mip_reg.off_0 = MIP_SW_APIC; - es7000_mip_reg.off_38 = (MIP_VALID); - while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) - printk("es7000_sw_apic: command failed, status = %x\n", - mip_status); - return; - } -} diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a07ec14f331..dac24c4390d 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o obj-$(CONFIG_X86_NUMAQ) += numaq_32.o +obj-$(CONFIG_X86_ES7000) += es7000_32.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit_32.o obj-y += vsmp_64.o obj-$(CONFIG_KPROBES) += kprobes.o diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c new file mode 100644 index 00000000000..849e5cd485b --- /dev/null +++ b/arch/x86/kernel/es7000_32.c @@ -0,0 +1,345 @@ +/* + * Written by: Garry Forsgren, Unisys Corporation + * Natalie Protasevich, Unisys Corporation + * This file contains the code to configure and interface + * with Unisys ES7000 series hardware system manager. + * + * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Unisys Corporation, Township Line & Union Meeting + * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: + * + * http://www.unisys.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * ES7000 chipsets + */ + +#define NON_UNISYS 0 +#define ES7000_CLASSIC 1 +#define ES7000_ZORRO 2 + + +#define MIP_REG 1 +#define MIP_PSAI_REG 4 + +#define MIP_BUSY 1 +#define MIP_SPIN 0xf0000 +#define MIP_VALID 0x0100000000000000ULL +#define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) + +#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) + +struct mip_reg_info { + unsigned long long mip_info; + unsigned long long delivery_info; + unsigned long long host_reg; + unsigned long long mip_reg; +}; + +struct part_info { + unsigned char type; + unsigned char length; + unsigned char part_id; + unsigned char apic_mode; + unsigned long snum; + char ptype[16]; + char sname[64]; + char pname[64]; +}; + +struct psai { + unsigned long long entry_type; + unsigned long long addr; + unsigned long long bep_addr; +}; + +struct es7000_mem_info { + unsigned char type; + unsigned char length; + unsigned char resv[6]; + unsigned long long start; + unsigned long long size; +}; + +struct es7000_oem_table { + unsigned long long hdr; + struct mip_reg_info mip; + struct part_info pif; + struct es7000_mem_info shm; + struct psai psai; +}; + +#ifdef CONFIG_ACPI + +struct oem_table { + struct acpi_table_header Header; + u32 OEMTableAddr; + u32 OEMTableSize; +}; + +extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); +#endif + +struct mip_reg { + unsigned long long off_0; + unsigned long long off_8; + unsigned long long off_10; + unsigned long long off_18; + unsigned long long off_20; + unsigned long long off_28; + unsigned long long off_30; + unsigned long long off_38; +}; + +#define MIP_SW_APIC 0x1020b +#define MIP_FUNC(VALUE) (VALUE & 0xff) + +/* + * ES7000 Globals + */ + +static volatile unsigned long *psai = NULL; +static struct mip_reg *mip_reg; +static struct mip_reg *host_reg; +static int mip_port; +static unsigned long mip_addr, host_addr; + +int es7000_plat; + +/* + * GSI override for ES7000 platforms. + */ + +static unsigned int base; + +static int +es7000_rename_gsi(int ioapic, int gsi) +{ + if (es7000_plat == ES7000_ZORRO) + return gsi; + + if (!base) { + int i; + for (i = 0; i < nr_ioapics; i++) + base += nr_ioapic_registers[i]; + } + + if (!ioapic && (gsi < 16)) + gsi += base; + return gsi; +} + +void __init +setup_unisys(void) +{ + /* + * Determine the generation of the ES7000 currently running. + * + * es7000_plat = 1 if the machine is a 5xx ES7000 box + * es7000_plat = 2 if the machine is a x86_64 ES7000 box + * + */ + if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2)) + es7000_plat = ES7000_ZORRO; + else + es7000_plat = ES7000_CLASSIC; + ioapic_renumber_irq = es7000_rename_gsi; +} + +/* + * Parse the OEM Table + */ + +int __init +parse_unisys_oem (char *oemptr) +{ + int i; + int success = 0; + unsigned char type, size; + unsigned long val; + char *tp = NULL; + struct psai *psaip = NULL; + struct mip_reg_info *mi; + struct mip_reg *host, *mip; + + tp = oemptr; + + tp += 8; + + for (i=0; i <= 6; i++) { + type = *tp++; + size = *tp++; + tp -= 2; + switch (type) { + case MIP_REG: + mi = (struct mip_reg_info *)tp; + val = MIP_RD_LO(mi->host_reg); + host_addr = val; + host = (struct mip_reg *)val; + host_reg = __va(host); + val = MIP_RD_LO(mi->mip_reg); + mip_port = MIP_PORT(mi->mip_info); + mip_addr = val; + mip = (struct mip_reg *)val; + mip_reg = __va(mip); + pr_debug("es7000_mipcfg: host_reg = 0x%lx \n", + (unsigned long)host_reg); + pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n", + (unsigned long)mip_reg); + success++; + break; + case MIP_PSAI_REG: + psaip = (struct psai *)tp; + if (tp != NULL) { + if (psaip->addr) + psai = __va(psaip->addr); + else + psai = NULL; + success++; + } + break; + default: + break; + } + tp += size; + } + + if (success < 2) { + es7000_plat = NON_UNISYS; + } else + setup_unisys(); + return es7000_plat; +} + +#ifdef CONFIG_ACPI +int __init +find_unisys_acpi_oem_table(unsigned long *oem_addr) +{ + struct acpi_table_header *header = NULL; + int i = 0; + while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { + if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { + struct oem_table *t = (struct oem_table *)header; + *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr, + t->OEMTableSize); + return 0; + } + } + return -1; +} +#endif + +static void +es7000_spin(int n) +{ + int i = 0; + + while (i++ < n) + rep_nop(); +} + +static int __init +es7000_mip_write(struct mip_reg *mip_reg) +{ + int status = 0; + int spin; + + spin = MIP_SPIN; + while (((unsigned long long)host_reg->off_38 & + (unsigned long long)MIP_VALID) != 0) { + if (--spin <= 0) { + printk("es7000_mip_write: Timeout waiting for Host Valid Flag"); + return -1; + } + es7000_spin(MIP_SPIN); + } + + memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); + outb(1, mip_port); + + spin = MIP_SPIN; + + while (((unsigned long long)mip_reg->off_38 & + (unsigned long long)MIP_VALID) == 0) { + if (--spin <= 0) { + printk("es7000_mip_write: Timeout waiting for MIP Valid Flag"); + return -1; + } + es7000_spin(MIP_SPIN); + } + + status = ((unsigned long long)mip_reg->off_0 & + (unsigned long long)0xffff0000000000ULL) >> 48; + mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & + (unsigned long long)~MIP_VALID); + return status; +} + +int +es7000_start_cpu(int cpu, unsigned long eip) +{ + unsigned long vect = 0, psaival = 0; + + if (psai == NULL) + return -1; + + vect = ((unsigned long)__pa(eip)/0x1000) << 16; + psaival = (0x1000000 | vect | cpu); + + while (*psai & 0x1000000) + ; + + *psai = psaival; + + return 0; + +} + +void __init +es7000_sw_apic(void) +{ + if (es7000_plat) { + int mip_status; + struct mip_reg es7000_mip_reg; + + printk("ES7000: Enabling APIC mode.\n"); + memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); + es7000_mip_reg.off_0 = MIP_SW_APIC; + es7000_mip_reg.off_38 = (MIP_VALID); + while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) + printk("es7000_sw_apic: command failed, status = %x\n", + mip_status); + return; + } +} diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile index 4706de7676b..6730f4e7c74 100644 --- a/arch/x86/mach-generic/Makefile +++ b/arch/x86/mach-generic/Makefile @@ -9,4 +9,3 @@ obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT) += summit.o obj-$(CONFIG_X86_BIGSMP) += bigsmp.o obj-$(CONFIG_X86_ES7000) += es7000.o -obj-$(CONFIG_X86_ES7000) += ../../x86/es7000/ -- cgit v1.2.3 From cce3e057242d3d46fea07b9eb3910b0076419be5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 4 Sep 2008 15:18:44 +0000 Subject: x86: TSC: define the PIT latch value separate Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 346cae5ac42..aa11413e7c1 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -122,6 +122,10 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet) return ULLONG_MAX; } +#define CAL_MS 50 +#define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS)) +#define CAL_PIT_LOOPS 5000 + /* * Try to calibrate the TSC against the Programmable * Interrupt Timer and return the frequency of the TSC @@ -144,8 +148,8 @@ static unsigned long pit_calibrate_tsc(void) * (LSB then MSB) to begin countdown. */ outb(0xb0, 0x43); - outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42); - outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42); + outb(CAL_LATCH & 0xff, 0x42); + outb(CAL_LATCH >> 8, 0x42); tsc = t1 = t2 = get_cycles(); @@ -166,18 +170,18 @@ static unsigned long pit_calibrate_tsc(void) /* * Sanity checks: * - * If we were not able to read the PIT more than 5000 + * If we were not able to read the PIT more than PIT_MIN_LOOPS * times, then we have been hit by a massive SMI * * If the maximum is 10 times larger than the minimum, * then we got hit by an SMI as well. */ - if (pitcnt < 5000 || tscmax > 10 * tscmin) + if (pitcnt < CAL_PIT_LOOPS || tscmax > 10 * tscmin) return ULONG_MAX; /* Calculate the PIT value */ delta = t2 - t1; - do_div(delta, 50); + do_div(delta, CAL_MS); return delta; } -- cgit v1.2.3 From d683ef7afe8b6dbac6a3c681cef8a908357793ca Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 4 Sep 2008 15:18:48 +0000 Subject: x86: TSC: separate hpet/pmtimer calculation out Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 56 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index aa11413e7c1..ebb9bf824a0 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -122,6 +122,43 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet) return ULLONG_MAX; } +/* + * Calculate the TSC frequency from HPET reference + */ +static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2) +{ + u64 tmp; + + if (hpet2 < hpet1) + hpet2 += 0x100000000ULL; + hpet2 -= hpet1; + tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); + do_div(tmp, 1000000); + do_div(deltatsc, tmp); + + return (unsigned long) deltatsc; +} + +/* + * Calculate the TSC frequency from PMTimer reference + */ +static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2) +{ + u64 tmp; + + if (!pm1 && !pm2) + return ULONG_MAX; + + if (pm2 < pm1) + pm2 += (u64)ACPI_PM_OVRRUN; + pm2 -= pm1; + tmp = pm2 * 1000000000LL; + do_div(tmp, PMTMR_TICKS_PER_SEC); + do_div(deltatsc, tmp); + + return (unsigned long) deltatsc; +} + #define CAL_MS 50 #define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS)) #define CAL_PIT_LOOPS 5000 @@ -247,22 +284,11 @@ unsigned long native_calibrate_tsc(void) continue; tsc2 = (tsc2 - tsc1) * 1000000LL; + if (hpet) + tsc2 = calc_hpet_ref(tsc2, hpet1, hpet2); + else + tsc2 = calc_pmtimer_ref(tsc2, pm1, pm2); - if (hpet) { - if (hpet2 < hpet1) - hpet2 += 0x100000000ULL; - hpet2 -= hpet1; - tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); - do_div(tsc1, 1000000); - } else { - if (pm2 < pm1) - pm2 += (u64)ACPI_PM_OVRRUN; - pm2 -= pm1; - tsc1 = pm2 * 1000000000LL; - do_div(tsc1, PMTMR_TICKS_PER_SEC); - } - - do_div(tsc2, tsc1); tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); } -- cgit v1.2.3 From 827014be05e4515fa0dfc32e3100c4dab2070a98 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 4 Sep 2008 15:18:53 +0000 Subject: x86: TSC: use one set of reference variables Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index ebb9bf824a0..52284d31fc9 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -104,7 +104,7 @@ __setup("notsc", notsc_setup); /* * Read TSC and the reference counters. Take care of SMI disturbance */ -static u64 tsc_read_refs(u64 *pm, u64 *hpet) +static u64 tsc_read_refs(u64 *p, int hpet) { u64 t1, t2; int i; @@ -112,9 +112,9 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet) for (i = 0; i < MAX_RETRIES; i++) { t1 = get_cycles(); if (hpet) - *hpet = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF; + *p = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF; else - *pm = acpi_pm_read_early(); + *p = acpi_pm_read_early(); t2 = get_cycles(); if ((t2 - t1) < SMI_TRESHOLD) return t2; @@ -228,7 +228,7 @@ static unsigned long pit_calibrate_tsc(void) */ unsigned long native_calibrate_tsc(void) { - u64 tsc1, tsc2, delta, pm1, pm2, hpet1, hpet2; + u64 tsc1, tsc2, delta, ref1, ref2; unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; unsigned long flags; int hpet = is_hpet_enabled(), i; @@ -267,16 +267,16 @@ unsigned long native_calibrate_tsc(void) * read the end value. */ local_irq_save(flags); - tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL); + tsc1 = tsc_read_refs(&ref1, hpet); tsc_pit_khz = pit_calibrate_tsc(); - tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL); + tsc2 = tsc_read_refs(&ref2, hpet); local_irq_restore(flags); /* Pick the lowest PIT TSC calibration so far */ tsc_pit_min = min(tsc_pit_min, tsc_pit_khz); /* hpet or pmtimer available ? */ - if (!hpet && !pm1 && !pm2) + if (!hpet && !ref1 && !ref2) continue; /* Check, whether the sampling was disturbed by an SMI */ @@ -285,9 +285,9 @@ unsigned long native_calibrate_tsc(void) tsc2 = (tsc2 - tsc1) * 1000000LL; if (hpet) - tsc2 = calc_hpet_ref(tsc2, hpet1, hpet2); + tsc2 = calc_hpet_ref(tsc2, ref1, ref2); else - tsc2 = calc_pmtimer_ref(tsc2, pm1, pm2); + tsc2 = calc_pmtimer_ref(tsc2, ref1, ref2); tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); } @@ -301,7 +301,7 @@ unsigned long native_calibrate_tsc(void) "SMI disturbance.\n"); /* We don't have an alternative source, disable TSC */ - if (!hpet && !pm1 && !pm2) { + if (!hpet && !ref1 && !ref2) { printk("TSC: No reference (HPET/PMTIMER) available\n"); return 0; } @@ -321,7 +321,7 @@ unsigned long native_calibrate_tsc(void) } /* We don't have an alternative source, use the PIT calibration value */ - if (!hpet && !pm1 && !pm2) { + if (!hpet && !ref1 && !ref2) { printk(KERN_INFO "TSC: Using PIT calibration value\n"); return tsc_pit_min; } -- cgit v1.2.3 From a977c400957451f3bd92b9ed6022f5fe8a6cbbf5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 4 Sep 2008 15:18:59 +0000 Subject: x86: TSC make the calibration loop smarter The last changes made the calibration loop 250ms long which is far too much. Try to do that more clever. Experiments have shown that using a 10ms delay for the PIT based calibration gives us a good enough value. If we have a reference (HPET/PMTIMER) and the result of the PIT and the reference is close enough, then we can break out of the calibration loop on a match right away and use the reference value. Otherwise we just loop 3 times and decide then, which value to take. One caveat is that for virtualized environments the PIT calibration often does not work at all and I found out that 10us is a bit too short as well for the reference to give a sane result. The solution here is to make the last loop longer when the first two PIT calibrations failed. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 95 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 37 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 52284d31fc9..da033b5b3e1 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -159,9 +159,14 @@ static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2) return (unsigned long) deltatsc; } -#define CAL_MS 50 +#define CAL_MS 10 #define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS)) -#define CAL_PIT_LOOPS 5000 +#define CAL_PIT_LOOPS 1000 + +#define CAL2_MS 50 +#define CAL2_LATCH (CLOCK_TICK_RATE / (1000 / CAL2_MS)) +#define CAL2_PIT_LOOPS 5000 + /* * Try to calibrate the TSC against the Programmable @@ -170,7 +175,7 @@ static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2) * * Return ULONG_MAX on failure to calibrate. */ -static unsigned long pit_calibrate_tsc(void) +static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin) { u64 tsc, t1, t2, delta; unsigned long tscmin, tscmax; @@ -185,8 +190,8 @@ static unsigned long pit_calibrate_tsc(void) * (LSB then MSB) to begin countdown. */ outb(0xb0, 0x43); - outb(CAL_LATCH & 0xff, 0x42); - outb(CAL_LATCH >> 8, 0x42); + outb(latch & 0xff, 0x42); + outb(latch >> 8, 0x42); tsc = t1 = t2 = get_cycles(); @@ -207,18 +212,18 @@ static unsigned long pit_calibrate_tsc(void) /* * Sanity checks: * - * If we were not able to read the PIT more than PIT_MIN_LOOPS + * If we were not able to read the PIT more than loopmin * times, then we have been hit by a massive SMI * * If the maximum is 10 times larger than the minimum, * then we got hit by an SMI as well. */ - if (pitcnt < CAL_PIT_LOOPS || tscmax > 10 * tscmin) + if (pitcnt < loopmin || tscmax > 10 * tscmin) return ULONG_MAX; /* Calculate the PIT value */ delta = t2 - t1; - do_div(delta, CAL_MS); + do_div(delta, ms); return delta; } @@ -230,8 +235,8 @@ unsigned long native_calibrate_tsc(void) { u64 tsc1, tsc2, delta, ref1, ref2; unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; - unsigned long flags; - int hpet = is_hpet_enabled(), i; + unsigned long flags, latch, ms; + int hpet = is_hpet_enabled(), i, loopmin; /* * Run 5 calibration loops to get the lowest frequency value @@ -257,7 +262,13 @@ unsigned long native_calibrate_tsc(void) * calibration delay loop as we have to wait for a certain * amount of time anyway. */ - for (i = 0; i < 5; i++) { + + /* Preset PIT loop values */ + latch = CAL_LATCH; + ms = CAL_MS; + loopmin = CAL_PIT_LOOPS; + + for (i = 0; i < 3; i++) { unsigned long tsc_pit_khz; /* @@ -268,7 +279,7 @@ unsigned long native_calibrate_tsc(void) */ local_irq_save(flags); tsc1 = tsc_read_refs(&ref1, hpet); - tsc_pit_khz = pit_calibrate_tsc(); + tsc_pit_khz = pit_calibrate_tsc(latch, ms, loopmin); tsc2 = tsc_read_refs(&ref2, hpet); local_irq_restore(flags); @@ -290,6 +301,35 @@ unsigned long native_calibrate_tsc(void) tsc2 = calc_pmtimer_ref(tsc2, ref1, ref2); tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); + + /* Check the reference deviation */ + delta = ((u64) tsc_pit_min) * 100; + do_div(delta, tsc_ref_min); + + /* + * If both calibration results are inside a 10% window + * then we can be sure, that the calibration + * succeeded. We break out of the loop right away. We + * use the reference value, as it is more precise. + */ + if (delta >= 90 && delta <= 110) { + printk(KERN_INFO + "TSC: PIT calibration matches %s. %d loops\n", + hpet ? "HPET" : "PMTIMER", i + 1); + return tsc_ref_min; + } + + /* + * Check whether PIT failed more than once. This + * happens in virtualized environments. We need to + * give the virtual PC a slightly longer timeframe for + * the HPET/PMTIMER to make the result precise. + */ + if (i == 1 && tsc_pit_min == ULONG_MAX) { + latch = CAL2_LATCH; + ms = CAL2_MS; + loopmin = CAL2_PIT_LOOPS; + } } /* @@ -309,7 +349,7 @@ unsigned long native_calibrate_tsc(void) /* The alternative source failed as well, disable TSC */ if (tsc_ref_min == ULONG_MAX) { printk(KERN_WARNING "TSC: HPET/PMTIMER calibration " - "failed due to SMI disturbance.\n"); + "failed.\n"); return 0; } @@ -328,37 +368,18 @@ unsigned long native_calibrate_tsc(void) /* The alternative source failed, use the PIT calibration value */ if (tsc_ref_min == ULONG_MAX) { - printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed due " - "to SMI disturbance. Using PIT calibration\n"); + printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. " + "Using PIT calibration\n"); return tsc_pit_min; } - /* Check the reference deviation */ - delta = ((u64) tsc_pit_min) * 100; - do_div(delta, tsc_ref_min); - - /* - * If both calibration results are inside a 5% window, the we - * use the lower frequency of those as it is probably the - * closest estimate. - */ - if (delta >= 95 && delta <= 105) { - printk(KERN_INFO "TSC: PIT calibration confirmed by %s.\n", - hpet ? "HPET" : "PMTIMER"); - printk(KERN_INFO "TSC: using %s calibration value\n", - tsc_pit_min <= tsc_ref_min ? "PIT" : - hpet ? "HPET" : "PMTIMER"); - return tsc_pit_min <= tsc_ref_min ? tsc_pit_min : tsc_ref_min; - } - - printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n", - hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min); - /* * The calibration values differ too much. In doubt, we use * the PIT value as we know that there are PMTIMERs around - * running at double speed. + * running at double speed. At least we let the user know: */ + printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n", + hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min); printk(KERN_INFO "TSC: Using PIT calibration value\n"); return tsc_pit_min; } -- cgit v1.2.3 From 58f7c98850a226d3fb05b1095af9f7c4ea3507ba Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 28 Aug 2008 13:52:25 -0700 Subject: x86: split e820 reserved entries record to late v2 so could let BAR res register at first, or even pnp. v2: insert e820 reserve resources before pnp_system_init Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/e820.c | 20 +++++++++++-- arch/x86/pci/i386.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 291e6cd9f9c..523d6c5605d 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1271,13 +1271,15 @@ static inline const char *e820_type_to_string(int e820_type) /* * Mark e820 reserved areas as busy for the resource manager. */ +struct resource __initdata *e820_res; void __init e820_reserve_resources(void) { int i; - struct resource *res; u64 end; + struct resource *res; res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map); + e820_res = res; for (i = 0; i < e820.nr_map; i++) { end = e820.map[i].addr + e820.map[i].size - 1; #ifndef CONFIG_RESOURCES_64BIT @@ -1291,7 +1293,8 @@ void __init e820_reserve_resources(void) res->end = end; res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - insert_resource(&iomem_resource, res); + if (e820.map[i].type != E820_RESERVED || res->start < (1ULL<<20)) + insert_resource(&iomem_resource, res); res++; } @@ -1303,6 +1306,19 @@ void __init e820_reserve_resources(void) } } +void __init e820_reserve_resources_late(void) +{ + int i; + struct resource *res; + + res = e820_res; + for (i = 0; i < e820.nr_map; i++) { + if (e820.map[i].type == E820_RESERVED && res->start >= (1ULL<<20)) + insert_resource(&iomem_resource, res); + res++; + } +} + char *__init default_machine_specific_memory_setup(void) { char *who = "BIOS-e820"; diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 8791fc55e71..40811efaa25 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -31,8 +31,12 @@ #include #include #include +#include #include +#include +#include +#include #include "pci.h" @@ -77,6 +81,77 @@ pcibios_align_resource(void *data, struct resource *res, } EXPORT_SYMBOL(pcibios_align_resource); +static int check_res_with_valid(struct pci_dev *dev, struct resource *res) +{ + unsigned long base; + unsigned long size; + int i; + + base = res->start; + size = (res->start == 0 && res->end == res->start) ? 0 : + (res->end - res->start + 1); + + if (!base || !size) + return 0; + +#ifdef CONFIG_HPET_TIMER + /* for hpet */ + if (base == hpet_address && (res->flags & IORESOURCE_MEM)) { + dev_info(&dev->dev, "BAR has HPET at %08lx-%08lx\n", + base, base + size - 1); + return 1; + } +#endif + +#ifdef CONFIG_X86_IO_APIC + for (i = 0; i < nr_ioapics; i++) { + unsigned long ioapic_phys = mp_ioapics[i].mp_apicaddr; + + if (base == ioapic_phys && (res->flags & IORESOURCE_MEM)) { + dev_info(&dev->dev, "BAR has ioapic at %08lx-%08lx\n", + base, base + size - 1); + return 1; + } + } +#endif + +#ifdef CONFIG_PCI_MMCONFIG + for (i = 0; i < pci_mmcfg_config_num; i++) { + unsigned long addr; + + addr = pci_mmcfg_config[i].address; + if (base == addr && (res->flags & IORESOURCE_MEM)) { + dev_info(&dev->dev, "BAR has MMCONFIG at %08lx-%08lx\n", + base, base + size - 1); + return 1; + } + } +#endif + + return 0; +} + +static int check_platform(struct pci_dev *dev, struct resource *res) +{ + struct resource *root = NULL; + + /* + * forcibly insert it into the + * resource tree + */ + if (res->flags & IORESOURCE_MEM) + root = &iomem_resource; + else if (res->flags & IORESOURCE_IO) + root = &ioport_resource; + + if (root && check_res_with_valid(dev, res)) { + insert_resource(root, res); + + return 1; + } + + return 0; +} /* * Handle resources of PCI devices. If the world were perfect, we could * just allocate all the resource regions and do nothing more. It isn't. @@ -128,6 +203,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) pr = pci_find_parent_resource(dev, r); if (!r->start || !pr || request_resource(pr, r) < 0) { + if (check_platform(dev, r)) + continue; dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); /* * Something is wrong with the region. @@ -169,6 +246,8 @@ static void __init pcibios_allocate_resources(int pass) r->flags, disabled, pass); pr = pci_find_parent_resource(dev, r); if (!pr || request_resource(pr, r) < 0) { + if (check_platform(dev, r)) + continue; dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); /* We'll assign a new address later */ r->end -= r->start; -- cgit v1.2.3 From a5444d15b611cf2ffe2bc52aaf11f2ac51882f89 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 29 Aug 2008 08:09:23 +0200 Subject: x86: split e820 reserved entries record to late v4 this one replaces: | commit a2bd7274b47124d2fc4dfdb8c0591f545ba749dd | Author: Yinghai Lu | Date: Mon Aug 25 00:56:08 2008 -0700 | | x86: fix HPET regression in 2.6.26 versus 2.6.25, check hpet against BAR, v3 v2: insert e820 reserve resources before pnp_system_init v3: fix merging problem in tip/x86/core v4: address Linus's review about comments and condition in _late() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/e820.c | 12 ++++++-- arch/x86/pci/i386.c | 80 ++------------------------------------------------ 2 files changed, 11 insertions(+), 81 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 523d6c5605d..a7a71339bfb 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1271,12 +1271,12 @@ static inline const char *e820_type_to_string(int e820_type) /* * Mark e820 reserved areas as busy for the resource manager. */ -struct resource __initdata *e820_res; +static struct resource __initdata *e820_res; void __init e820_reserve_resources(void) { int i; - u64 end; struct resource *res; + u64 end; res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map); e820_res = res; @@ -1293,6 +1293,12 @@ void __init e820_reserve_resources(void) res->end = end; res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + + /* + * don't register the region that could be conflicted with + * pci device BAR resource and insert them later in + * pcibios_resource_survey() + */ if (e820.map[i].type != E820_RESERVED || res->start < (1ULL<<20)) insert_resource(&iomem_resource, res); res++; @@ -1313,7 +1319,7 @@ void __init e820_reserve_resources_late(void) res = e820_res; for (i = 0; i < e820.nr_map; i++) { - if (e820.map[i].type == E820_RESERVED && res->start >= (1ULL<<20)) + if (!res->parent && res->end) insert_resource(&iomem_resource, res); res++; } diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 40811efaa25..844df0cbbd3 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -31,11 +31,8 @@ #include #include #include -#include #include -#include -#include #include #include "pci.h" @@ -81,77 +78,6 @@ pcibios_align_resource(void *data, struct resource *res, } EXPORT_SYMBOL(pcibios_align_resource); -static int check_res_with_valid(struct pci_dev *dev, struct resource *res) -{ - unsigned long base; - unsigned long size; - int i; - - base = res->start; - size = (res->start == 0 && res->end == res->start) ? 0 : - (res->end - res->start + 1); - - if (!base || !size) - return 0; - -#ifdef CONFIG_HPET_TIMER - /* for hpet */ - if (base == hpet_address && (res->flags & IORESOURCE_MEM)) { - dev_info(&dev->dev, "BAR has HPET at %08lx-%08lx\n", - base, base + size - 1); - return 1; - } -#endif - -#ifdef CONFIG_X86_IO_APIC - for (i = 0; i < nr_ioapics; i++) { - unsigned long ioapic_phys = mp_ioapics[i].mp_apicaddr; - - if (base == ioapic_phys && (res->flags & IORESOURCE_MEM)) { - dev_info(&dev->dev, "BAR has ioapic at %08lx-%08lx\n", - base, base + size - 1); - return 1; - } - } -#endif - -#ifdef CONFIG_PCI_MMCONFIG - for (i = 0; i < pci_mmcfg_config_num; i++) { - unsigned long addr; - - addr = pci_mmcfg_config[i].address; - if (base == addr && (res->flags & IORESOURCE_MEM)) { - dev_info(&dev->dev, "BAR has MMCONFIG at %08lx-%08lx\n", - base, base + size - 1); - return 1; - } - } -#endif - - return 0; -} - -static int check_platform(struct pci_dev *dev, struct resource *res) -{ - struct resource *root = NULL; - - /* - * forcibly insert it into the - * resource tree - */ - if (res->flags & IORESOURCE_MEM) - root = &iomem_resource; - else if (res->flags & IORESOURCE_IO) - root = &ioport_resource; - - if (root && check_res_with_valid(dev, res)) { - insert_resource(root, res); - - return 1; - } - - return 0; -} /* * Handle resources of PCI devices. If the world were perfect, we could * just allocate all the resource regions and do nothing more. It isn't. @@ -203,8 +129,6 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) pr = pci_find_parent_resource(dev, r); if (!r->start || !pr || request_resource(pr, r) < 0) { - if (check_platform(dev, r)) - continue; dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); /* * Something is wrong with the region. @@ -246,8 +170,6 @@ static void __init pcibios_allocate_resources(int pass) r->flags, disabled, pass); pr = pci_find_parent_resource(dev, r); if (!pr || request_resource(pr, r) < 0) { - if (check_platform(dev, r)) - continue; dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); /* We'll assign a new address later */ r->end -= r->start; @@ -306,6 +228,8 @@ void __init pcibios_resource_survey(void) pcibios_allocate_bus_resources(&pci_root_buses); pcibios_allocate_resources(0); pcibios_allocate_resources(1); + + e820_reserve_resources_late(); } /** -- cgit v1.2.3 From fb481dd56adf3c5b0993b8f052cc9ba966e3959d Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 4 Sep 2008 13:46:11 +0200 Subject: x86: drop -funroll-loops for csum_partial_64.c Impact: performance optimization I did some rebenchmarking with modern compilers and dropping -funroll-loops makes the function consistently go faster by a few percent. So drop that flag. Thanks to Richard Guenther for a hint. Signed-off-by: Andi Kleen Signed-off-by: H. Peter Anvin --- arch/x86/lib/Makefile | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index aa3fa411942..55e11aa6d66 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -17,9 +17,6 @@ ifeq ($(CONFIG_X86_32),y) lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o else obj-y += io_64.o iomap_copy_64.o - - CFLAGS_csum-partial_64.o := -funroll-loops - lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o lib-y += thunk_64.o clear_page_64.o copy_page_64.o lib-y += memmove_64.o memset_64.o -- cgit v1.2.3 From dc44e65943169de2d1a1b494876f48a65a9737f1 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 4 Sep 2008 13:47:38 +0200 Subject: x86: capitalize function call interrupts consistently Impact: aestetic Capitalize function call interrupts consistently. All other descriptions in /proc/interrupts are capitalized except for "function call interrupts". Capitalize it too for consistency. While that's technically a published ABI I think the risk of anyone relying on that text to stay the same is negligible. Signed-off-by: Andi Kleen Signed-off-by: H. Peter Anvin --- arch/x86/kernel/irq_32.c | 2 +- arch/x86/kernel/irq_64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 1cf8c1fcc08..b71e02d42f4 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -325,7 +325,7 @@ skip: for_each_online_cpu(j) seq_printf(p, "%10u ", per_cpu(irq_stat,j).irq_call_count); - seq_printf(p, " function call interrupts\n"); + seq_printf(p, " Function call interrupts\n"); seq_printf(p, "TLB: "); for_each_online_cpu(j) seq_printf(p, "%10u ", diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 1f78b238d8d..f065fe9071b 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -129,7 +129,7 @@ skip: seq_printf(p, "CAL: "); for_each_online_cpu(j) seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count); - seq_printf(p, " function call interrupts\n"); + seq_printf(p, " Function call interrupts\n"); seq_printf(p, "TLB: "); for_each_online_cpu(j) seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count); -- cgit v1.2.3 From fac8f1e4f99dff7a0c3a929f327d66f46de6fa21 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:59:22 +0200 Subject: x86: split e820 reserved entries record to late, v7 try to insert_resource second time, by expanding the resource... for case: e820 reserved entry is partially overlapped with bar res... hope it will never happen Signed-off-by: Ingo Molnar --- arch/x86/kernel/e820.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index a7a71339bfb..e24d1bc47b4 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1320,7 +1320,7 @@ void __init e820_reserve_resources_late(void) res = e820_res; for (i = 0; i < e820.nr_map; i++) { if (!res->parent && res->end) - insert_resource(&iomem_resource, res); + reserve_region_with_split(&iomem_resource, res->start, res->end, res->name); res++; } } -- cgit v1.2.3 From ebd60cd64f8ab1170102c3ab072eb73042b7a33d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:04:32 +0200 Subject: x86: unify using pci_mmcfg_insert_resource even with known_bridge insert them late too. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/pci/mmconfig-shared.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index d9635764ce3..654a2234f8f 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -209,7 +209,7 @@ static int __init pci_mmcfg_check_hostbridge(void) return name != NULL; } -static void __init pci_mmcfg_insert_resources(unsigned long resource_flags) +static void __init pci_mmcfg_insert_resources(void) { #define PCI_MMCFG_RESOURCE_NAME_LEN 19 int i; @@ -233,7 +233,7 @@ static void __init pci_mmcfg_insert_resources(unsigned long resource_flags) cfg->pci_segment); res->start = cfg->address; res->end = res->start + (num_buses << 20) - 1; - res->flags = IORESOURCE_MEM | resource_flags; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; insert_resource(&iomem_resource, res); names += PCI_MMCFG_RESOURCE_NAME_LEN; } @@ -434,11 +434,9 @@ static void __init __pci_mmcfg_init(int early) (pci_mmcfg_config[0].address == 0)) return; - if (pci_mmcfg_arch_init()) { - if (known_bridge) - pci_mmcfg_insert_resources(IORESOURCE_BUSY); + if (pci_mmcfg_arch_init()) pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; - } else { + else { /* * Signal not to attempt to insert mmcfg resources because * the architecture mmcfg setup could not initialize. @@ -475,7 +473,7 @@ static int __init pci_mmcfg_late_insert_resources(void) * marked so it won't cause request errors when __request_region is * called. */ - pci_mmcfg_insert_resources(0); + pci_mmcfg_insert_resources(); return 0; } -- cgit v1.2.3 From 5fef55fddb7317585cabc1eae38dbd57f1c59729 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:43 +0200 Subject: x86: move mtrr cpu cap setting early in early_init_xxxx Krzysztof Helt found MTRR is not detected on k6-2 root cause: we moved mtrr_bp_init() early for mtrr trimming, and in early_detect we only read the CPU capability from cpuid, so some cpu doesn't have that bit in cpuid. So we need to add early_init_xxxx to preset those bit before mtrr_bp_init for those earlier cpus. this patch is for v2.6.27 Reported-by: Krzysztof Helt Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 9 +++++---- arch/x86/kernel/cpu/centaur.c | 11 +++++++++++ arch/x86/kernel/cpu/cyrix.c | 32 ++++++++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index cae9cabc303..18514ed2610 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) if (c->x86_power & (1<<8)) set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); } + + /* Set MTRR capability flag if appropriate */ + if (c->x86_model == 13 || c->x86_model == 9 || + (c->x86_model == 8 && c->x86_mask >= 8)) + set_cpu_cap(c, X86_FEATURE_K6_MTRR); } static void __cpuinit init_amd(struct cpuinfo_x86 *c) @@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) mbytes); } - /* Set MTRR capability flag if appropriate */ - if (c->x86_model == 13 || c->x86_model == 9 || - (c->x86_model == 8 && c->x86_mask >= 8)) - set_cpu_cap(c, X86_FEATURE_K6_MTRR); break; } diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index e0f45edd6a5..a0534c04d38 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -314,6 +314,16 @@ enum { EAMD3D = 1<<20, }; +static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) +{ + switch (c->x86) { + case 5: + /* Emulate MTRRs using Centaur's MCR. */ + set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR); + break; + } +} + static void __cpuinit init_centaur(struct cpuinfo_x86 *c) { @@ -462,6 +472,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) static struct cpu_dev centaur_cpu_dev __cpuinitdata = { .c_vendor = "Centaur", .c_ident = { "CentaurHauls" }, + .c_early_init = early_init_centaur, .c_init = init_centaur, .c_size_cache = centaur_size_cache, }; diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index ada50505a5c..13f8fa16b81 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -15,13 +15,11 @@ /* * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU */ -static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) { unsigned char ccr2, ccr3; - unsigned long flags; /* we test for DEVID by checking whether CCR3 is writable */ - local_irq_save(flags); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, ccr3 ^ 0x80); getCx86(0xc0); /* dummy to change bus */ @@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) *dir0 = getCx86(CX86_DIR0); *dir1 = getCx86(CX86_DIR1); } - local_irq_restore(flags); } +static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +{ + unsigned long flags; + + local_irq_save(flags); + __do_cyrix_devid(dir0, dir1); + local_irq_restore(flags); +} /* * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in * order to identify the Cyrix CPU model after we're out of setup.c @@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void) local_irq_restore(flags); } +static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c) +{ + unsigned char dir0, dir0_msn, dir1 = 0; + + __do_cyrix_devid(&dir0, &dir1); + dir0_msn = dir0 >> 4; /* identifies CPU "family" */ + + switch (dir0_msn) { + case 3: /* 6x86/6x86L */ + /* Emulate MTRRs using Cyrix's ARRs. */ + set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); + break; + case 5: /* 6x86MX/M II */ + /* Emulate MTRRs using Cyrix's ARRs. */ + set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); + break; + } +} static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) { @@ -416,6 +439,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) static struct cpu_dev cyrix_cpu_dev __cpuinitdata = { .c_vendor = "Cyrix", .c_ident = { "CyrixInstead" }, + .c_early_init = early_init_cyrix, .c_init = init_cyrix, .c_identify = cyrix_identify, }; -- cgit v1.2.3 From 5031088dbc0cd30e893eb27d53f0e0eee6eb1c00 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 4 Sep 2008 21:09:43 +0200 Subject: x86: delay early cpu initialization until cpuid is done Move early cpu initialization after cpu early get cap so the early cpu initialization can fix up cpu caps. Signed-off-by: Krzysztof Helt Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0785b3c8d04..8aab8517642 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -335,11 +335,11 @@ static void __init early_cpu_detect(void) get_cpu_vendor(c, 1); + early_get_cap(c); + if (c->x86_vendor != X86_VENDOR_UNKNOWN && cpu_devs[c->x86_vendor]->c_early_init) cpu_devs[c->x86_vendor]->c_early_init(c); - - early_get_cap(c); } /* -- cgit v1.2.3 From 3da99c97763703b23cbf2bd6e96252256d4e4617 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:44 +0200 Subject: x86: make (early)_identify_cpu more the same between 32bit and 64 bit 1. add extended_cpuid_level for 32bit 2. add generic_identify for 64bit 3. add early_identify_cpu for 32bit 4. early_identify_cpu not be called by identify_cpu 5. remove early in get_cpu_vendor for 32bit 6. add get_cpu_cap 7. add cpu_detect for 64bit Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 138 +++++++++++++++------------------------ arch/x86/kernel/cpu/common_64.c | 139 +++++++++++++++++++++++++--------------- 2 files changed, 141 insertions(+), 136 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 8aab8517642..96e1b8698d3 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -96,7 +96,7 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c) unsigned int *v; char *p, *q; - if (cpuid_eax(0x80000000) < 0x80000004) + if (c->extended_cpuid_level < 0x80000004) return 0; v = (unsigned int *) c->x86_model_id; @@ -125,7 +125,7 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) { unsigned int n, dummy, ecx, edx, l2size; - n = cpuid_eax(0x80000000); + n = c->extended_cpuid_level; if (n >= 0x80000005) { cpuid(0x80000005, &dummy, &dummy, &ecx, &edx); @@ -186,7 +186,7 @@ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) } -static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early) +static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) { char *v = c->x86_vendor_id; int i; @@ -198,8 +198,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early) (cpu_devs[i]->c_ident[1] && !strcmp(v, cpu_devs[i]->c_ident[1]))) { c->x86_vendor = i; - if (!early) - this_cpu = cpu_devs[i]; + this_cpu = cpu_devs[i]; return; } } @@ -284,34 +283,30 @@ void __init cpu_detect(struct cpuinfo_x86 *c) } } } -static void __cpuinit early_get_cap(struct cpuinfo_x86 *c) + +static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) { u32 tfms, xlvl; - unsigned int ebx; + u32 ebx; - memset(&c->x86_capability, 0, sizeof c->x86_capability); - if (have_cpuid_p()) { - /* Intel-defined flags: level 0x00000001 */ - if (c->cpuid_level >= 0x00000001) { - u32 capability, excap; - cpuid(0x00000001, &tfms, &ebx, &excap, &capability); - c->x86_capability[0] = capability; - c->x86_capability[4] = excap; - } + /* Intel-defined flags: level 0x00000001 */ + if (c->cpuid_level >= 0x00000001) { + u32 capability, excap; + cpuid(0x00000001, &tfms, &ebx, &excap, &capability); + c->x86_capability[0] = capability; + c->x86_capability[4] = excap; + } - /* AMD-defined flags: level 0x80000001 */ - xlvl = cpuid_eax(0x80000000); - if ((xlvl & 0xffff0000) == 0x80000000) { - if (xlvl >= 0x80000001) { - c->x86_capability[1] = cpuid_edx(0x80000001); - c->x86_capability[6] = cpuid_ecx(0x80000001); - } + /* AMD-defined flags: level 0x80000001 */ + xlvl = cpuid_eax(0x80000000); + c->extended_cpuid_level = xlvl; + if ((xlvl & 0xffff0000) == 0x80000000) { + if (xlvl >= 0x80000001) { + c->x86_capability[1] = cpuid_edx(0x80000001); + c->x86_capability[6] = cpuid_ecx(0x80000001); } - } - } - /* * Do minimum CPU detection early. * Fields really needed: vendor, cpuid_level, family, model, mask, @@ -321,25 +316,29 @@ static void __cpuinit early_get_cap(struct cpuinfo_x86 *c) * WARNING: this function is only called on the BP. Don't add code here * that is supposed to run on all CPUs. */ -static void __init early_cpu_detect(void) +static void __init early_identify_cpu(struct cpuinfo_x86 *c) { - struct cpuinfo_x86 *c = &boot_cpu_data; - c->x86_cache_alignment = 32; c->x86_clflush_size = 32; if (!have_cpuid_p()) return; + c->extended_cpuid_level = 0; + + memset(&c->x86_capability, 0, sizeof c->x86_capability); + cpu_detect(c); - get_cpu_vendor(c, 1); + get_cpu_vendor(c); - early_get_cap(c); + get_cpu_cap(c); if (c->x86_vendor != X86_VENDOR_UNKNOWN && cpu_devs[c->x86_vendor]->c_early_init) cpu_devs[c->x86_vendor]->c_early_init(c); + + validate_pat_support(c); } /* @@ -373,60 +372,32 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) static void __cpuinit generic_identify(struct cpuinfo_x86 *c) { - u32 tfms, xlvl; - unsigned int ebx; - - if (have_cpuid_p()) { - /* Get vendor name */ - cpuid(0x00000000, (unsigned int *)&c->cpuid_level, - (unsigned int *)&c->x86_vendor_id[0], - (unsigned int *)&c->x86_vendor_id[8], - (unsigned int *)&c->x86_vendor_id[4]); - - get_cpu_vendor(c, 0); - /* Initialize the standard set of capabilities */ - /* Note that the vendor-specific code below might override */ - /* Intel-defined flags: level 0x00000001 */ - if (c->cpuid_level >= 0x00000001) { - u32 capability, excap; - cpuid(0x00000001, &tfms, &ebx, &excap, &capability); - c->x86_capability[0] = capability; - c->x86_capability[4] = excap; - c->x86 = (tfms >> 8) & 15; - c->x86_model = (tfms >> 4) & 15; - if (c->x86 == 0xf) - c->x86 += (tfms >> 20) & 0xff; - if (c->x86 >= 0x6) - c->x86_model += ((tfms >> 16) & 0xF) << 4; - c->x86_mask = tfms & 15; - c->initial_apicid = (ebx >> 24) & 0xFF; + if (!have_cpuid_p()) + return; + + c->extended_cpuid_level = 0; + + cpu_detect(c); + + get_cpu_vendor(c); + + get_cpu_cap(c); + + if (c->cpuid_level >= 0x00000001) { + c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF; #ifdef CONFIG_X86_HT - c->apicid = phys_pkg_id(c->initial_apicid, 0); - c->phys_proc_id = c->initial_apicid; + c->apicid = phys_pkg_id(c->initial_apicid, 0); + c->phys_proc_id = c->initial_apicid; #else - c->apicid = c->initial_apicid; + c->apicid = c->initial_apicid; #endif - if (test_cpu_cap(c, X86_FEATURE_CLFLSH)) - c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8; - } else { - /* Have CPUID level 0 only - unheard of */ - c->x86 = 4; - } + } - /* AMD-defined flags: level 0x80000001 */ - xlvl = cpuid_eax(0x80000000); - if ((xlvl & 0xffff0000) == 0x80000000) { - if (xlvl >= 0x80000001) { - c->x86_capability[1] = cpuid_edx(0x80000001); - c->x86_capability[6] = cpuid_ecx(0x80000001); - } - if (xlvl >= 0x80000004) - get_model_name(c); /* Default name */ - } + if (c->extended_cpuid_level >= 0x80000004) + get_model_name(c); /* Default name */ - init_scattered_cpuid_features(c); - detect_nopl(c); - } + init_scattered_cpuid_features(c); + detect_nopl(c); } static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) @@ -651,13 +622,10 @@ void __init early_cpu_init(void) { struct cpu_vendor_dev *cvdev; - for (cvdev = __x86cpuvendor_start ; - cvdev < __x86cpuvendor_end ; - cvdev++) + for (cvdev = __x86cpuvendor_start; cvdev < __x86cpuvendor_end; cvdev++) cpu_devs[cvdev->vendor] = cvdev->cpu_dev; - early_cpu_detect(); - validate_pat_support(&boot_cpu_data); + early_identify_cpu(&boot_cpu_data); } /* Make sure %fs is initialized properly in idle threads */ diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 699ecbfb63e..28719fe0794 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -195,6 +195,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) printk(KERN_ERR "CPU: Your system may be unstable.\n"); } c->x86_vendor = X86_VENDOR_UNKNOWN; + this_cpu = &default_cpu; } static void __init early_cpu_support_print(void) @@ -249,56 +250,18 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) } } -static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c); - -void __init early_cpu_init(void) +void __cpuinit cpu_detect(struct cpuinfo_x86 *c) { - struct cpu_vendor_dev *cvdev; - - for (cvdev = __x86cpuvendor_start ; - cvdev < __x86cpuvendor_end ; - cvdev++) - cpu_devs[cvdev->vendor] = cvdev->cpu_dev; - early_cpu_support_print(); - early_identify_cpu(&boot_cpu_data); -} - -/* Do some early cpuid on the boot CPU to get some parameter that are - needed before check_bugs. Everything advanced is in identify_cpu - below. */ -static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) -{ - u32 tfms, xlvl; - - c->loops_per_jiffy = loops_per_jiffy; - c->x86_cache_size = -1; - c->x86_vendor = X86_VENDOR_UNKNOWN; - c->x86_model = c->x86_mask = 0; /* So far unknown... */ - c->x86_vendor_id[0] = '\0'; /* Unset */ - c->x86_model_id[0] = '\0'; /* Unset */ - c->x86_clflush_size = 64; - c->x86_cache_alignment = c->x86_clflush_size; - c->x86_max_cores = 1; - c->x86_coreid_bits = 0; - c->extended_cpuid_level = 0; - memset(&c->x86_capability, 0, sizeof c->x86_capability); - /* Get vendor name */ cpuid(0x00000000, (unsigned int *)&c->cpuid_level, (unsigned int *)&c->x86_vendor_id[0], (unsigned int *)&c->x86_vendor_id[8], (unsigned int *)&c->x86_vendor_id[4]); - get_cpu_vendor(c); - - /* Initialize the standard set of capabilities */ - /* Note that the vendor-specific code below might override */ - /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { - __u32 misc; - cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4], - &c->x86_capability[0]); + u32 junk, tfms, cap0, misc; + cpuid(0x00000001, &tfms, &misc, &junk, &cap0); c->x86 = (tfms >> 8) & 0xf; c->x86_model = (tfms >> 4) & 0xf; c->x86_mask = tfms & 0xf; @@ -306,17 +269,32 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) c->x86 += (tfms >> 20) & 0xff; if (c->x86 >= 0x6) c->x86_model += ((tfms >> 16) & 0xF) << 4; - if (test_cpu_cap(c, X86_FEATURE_CLFLSH)) + if (cap0 & (1<<19)) c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; } else { /* Have CPUID level 0 only - unheard of */ c->x86 = 4; } +} + + +static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) +{ + u32 tfms, xlvl; + u32 ebx; + + /* Initialize the standard set of capabilities */ + /* Note that the vendor-specific code below might override */ + + /* Intel-defined flags: level 0x00000001 */ + if (c->cpuid_level >= 0x00000001) { + u32 capability, excap; + + cpuid(0x00000001, &tfms, &ebx, &excap, &capability); + c->x86_capability[0] = capability; + c->x86_capability[4] = excap; + } - c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff; -#ifdef CONFIG_SMP - c->phys_proc_id = c->initial_apicid; -#endif /* AMD-defined flags: level 0x80000001 */ xlvl = cpuid_eax(0x80000000); c->extended_cpuid_level = xlvl; @@ -325,8 +303,6 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) c->x86_capability[1] = cpuid_edx(0x80000001); c->x86_capability[6] = cpuid_ecx(0x80000001); } - if (xlvl >= 0x80000004) - get_model_name(c); /* Default name */ } /* Transmeta-defined flags: level 0x80860001 */ @@ -346,8 +322,26 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) c->x86_virt_bits = (eax >> 8) & 0xff; c->x86_phys_bits = eax & 0xff; } +} - detect_nopl(c); +/* Do some early cpuid on the boot CPU to get some parameter that are + needed before check_bugs. Everything advanced is in identify_cpu + below. */ +static void __init early_identify_cpu(struct cpuinfo_x86 *c) +{ + + c->x86_clflush_size = 64; + c->x86_cache_alignment = c->x86_clflush_size; + + memset(&c->x86_capability, 0, sizeof c->x86_capability); + + c->extended_cpuid_level = 0; + + cpu_detect(c); + + get_cpu_vendor(c); + + get_cpu_cap(c); if (c->x86_vendor != X86_VENDOR_UNKNOWN && cpu_devs[c->x86_vendor]->c_early_init) @@ -356,6 +350,39 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) validate_pat_support(c); } +void __init early_cpu_init(void) +{ + struct cpu_vendor_dev *cvdev; + + for (cvdev = __x86cpuvendor_start; cvdev < __x86cpuvendor_end; cvdev++) + cpu_devs[cvdev->vendor] = cvdev->cpu_dev; + + early_cpu_support_print(); + early_identify_cpu(&boot_cpu_data); +} + +static void __cpuinit generic_identify(struct cpuinfo_x86 *c) +{ + c->extended_cpuid_level = 0; + + cpu_detect(c); + + get_cpu_vendor(c); + + get_cpu_cap(c); + + c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff; +#ifdef CONFIG_SMP + c->phys_proc_id = c->initial_apicid; +#endif + + if (c->extended_cpuid_level >= 0x80000004) + get_model_name(c); /* Default name */ + + init_scattered_cpuid_features(c); + detect_nopl(c); +} + /* * This does the hard work of actually picking apart the CPU stuff... */ @@ -363,9 +390,19 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) { int i; - early_identify_cpu(c); + c->loops_per_jiffy = loops_per_jiffy; + c->x86_cache_size = -1; + c->x86_vendor = X86_VENDOR_UNKNOWN; + c->x86_model = c->x86_mask = 0; /* So far unknown... */ + c->x86_vendor_id[0] = '\0'; /* Unset */ + c->x86_model_id[0] = '\0'; /* Unset */ + c->x86_clflush_size = 64; + c->x86_cache_alignment = c->x86_clflush_size; + c->x86_max_cores = 1; + c->x86_coreid_bits = 0; + memset(&c->x86_capability, 0, sizeof c->x86_capability); - init_scattered_cpuid_features(c); + generic_identify(c); c->apicid = phys_pkg_id(0); -- cgit v1.2.3 From 9d31d35b5f9d619bb2482235cc889326de049e29 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:44 +0200 Subject: x86: order functions in cpu/common.c and cpu/common_64.c v2 v2: make 64 bit get c->x86_cache_alignment = c->x86_clfush_size Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 190 ++++++++++++++++++++++------------------ arch/x86/kernel/cpu/common_64.c | 106 +++++++++++----------- 2 files changed, 156 insertions(+), 140 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 96e1b8698d3..10e89ae5a60 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -60,6 +60,18 @@ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; +/* Current gdt points %fs at the "master" per-cpu area: after this, + * it's on the real one. */ +void switch_to_new_gdt(void) +{ + struct desc_ptr gdt_descr; + + gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); + gdt_descr.size = GDT_SIZE - 1; + load_gdt(&gdt_descr); + asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); +} + static int cachesize_override __cpuinitdata = -1; static int disable_x86_serial_nr __cpuinitdata = 1; @@ -123,15 +135,15 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c) void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) { - unsigned int n, dummy, ecx, edx, l2size; + unsigned int n, dummy, ebx, ecx, edx, l2size; n = c->extended_cpuid_level; if (n >= 0x80000005) { - cpuid(0x80000005, &dummy, &dummy, &ecx, &edx); + cpuid(0x80000005, &dummy, &ebx, &ecx, &edx); printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", - edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); - c->x86_cache_size = (ecx>>24)+(edx>>24); + edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); + c->x86_cache_size = (ecx>>24) + (edx>>24); } if (n < 0x80000006) /* Some chips just has a large L1. */ @@ -185,6 +197,51 @@ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) return NULL; /* Not found */ } +#ifdef CONFIG_X86_HT +void __cpuinit detect_ht(struct cpuinfo_x86 *c) +{ + u32 eax, ebx, ecx, edx; + int index_msb, core_bits; + + cpuid(1, &eax, &ebx, &ecx, &edx); + + if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) + return; + + smp_num_siblings = (ebx & 0xff0000) >> 16; + + if (smp_num_siblings == 1) { + printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); + } else if (smp_num_siblings > 1) { + + if (smp_num_siblings > NR_CPUS) { + printk(KERN_WARNING "CPU: Unsupported number of siblings %d", + smp_num_siblings); + smp_num_siblings = 1; + return; + } + + index_msb = get_count_order(smp_num_siblings); + c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); + + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + c->phys_proc_id); + + smp_num_siblings = smp_num_siblings / c->x86_max_cores; + + index_msb = get_count_order(smp_num_siblings); + + core_bits = get_count_order(c->x86_max_cores); + + c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & + ((1 << core_bits) - 1); + + if (c->x86_max_cores > 1) + printk(KERN_INFO "CPU: Processor Core ID: %d\n", + c->cpu_core_id); + } +} +#endif static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) { @@ -258,7 +315,26 @@ static int __cpuinit have_cpuid_p(void) return flag_is_changeable_p(X86_EFLAGS_ID); } -void __init cpu_detect(struct cpuinfo_x86 *c) +static void __init early_cpu_support_print(void) +{ + int i,j; + struct cpu_dev *cpu_devx; + + printk("KERNEL supported cpus:\n"); + for (i = 0; i < X86_VENDOR_NUM; i++) { + cpu_devx = cpu_devs[i]; + if (!cpu_devx) + continue; + for (j = 0; j < 2; j++) { + if (!cpu_devx->c_ident[j]) + continue; + printk(" %s %s\n", cpu_devx->c_vendor, + cpu_devx->c_ident[j]); + } + } +} + +void __cpuinit cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ cpuid(0x00000000, (unsigned int *)&c->cpuid_level, @@ -267,19 +343,20 @@ void __init cpu_detect(struct cpuinfo_x86 *c) (unsigned int *)&c->x86_vendor_id[4]); c->x86 = 4; + /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { u32 junk, tfms, cap0, misc; cpuid(0x00000001, &tfms, &misc, &junk, &cap0); - c->x86 = (tfms >> 8) & 15; - c->x86_model = (tfms >> 4) & 15; + c->x86 = (tfms >> 8) & 0xf; + c->x86_model = (tfms >> 4) & 0xf; + c->x86_mask = tfms & 0xf; if (c->x86 == 0xf) c->x86 += (tfms >> 20) & 0xff; if (c->x86 >= 0x6) - c->x86_model += ((tfms >> 16) & 0xF) << 4; - c->x86_mask = tfms & 15; + c->x86_model += ((tfms >> 16) & 0xf) << 4; if (cap0 & (1<<19)) { - c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; + c->x86_cache_alignment = c->x86_clflush_size; } } } @@ -341,6 +418,17 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) validate_pat_support(c); } +void __init early_cpu_init(void) +{ + struct cpu_vendor_dev *cvdev; + + for (cvdev = __x86cpuvendor_start; cvdev < __x86cpuvendor_end; cvdev++) + cpu_devs[cvdev->vendor] = cvdev->cpu_dev; + + early_cpu_support_print(); + early_identify_cpu(&boot_cpu_data); +} + /* * The NOPL instruction is supposed to exist on all CPUs with * family >= 6, unfortunately, that's not true in practice because @@ -500,7 +588,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) */ if (c != &boot_cpu_data) { /* AND the already accumulated flags with these */ - for (i = 0 ; i < NCAPINTS ; i++) + for (i = 0; i < NCAPINTS; i++) boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; } @@ -529,52 +617,6 @@ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) mtrr_ap_init(); } -#ifdef CONFIG_X86_HT -void __cpuinit detect_ht(struct cpuinfo_x86 *c) -{ - u32 eax, ebx, ecx, edx; - int index_msb, core_bits; - - cpuid(1, &eax, &ebx, &ecx, &edx); - - if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) - return; - - smp_num_siblings = (ebx & 0xff0000) >> 16; - - if (smp_num_siblings == 1) { - printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); - } else if (smp_num_siblings > 1) { - - if (smp_num_siblings > NR_CPUS) { - printk(KERN_WARNING "CPU: Unsupported number of the " - "siblings %d", smp_num_siblings); - smp_num_siblings = 1; - return; - } - - index_msb = get_count_order(smp_num_siblings); - c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); - - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - c->phys_proc_id); - - smp_num_siblings = smp_num_siblings / c->x86_max_cores; - - index_msb = get_count_order(smp_num_siblings) ; - - core_bits = get_count_order(c->x86_max_cores); - - c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & - ((1 << core_bits) - 1); - - if (c->x86_max_cores > 1) - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - c->cpu_core_id); - } -} -#endif - static __init int setup_noclflush(char *arg) { setup_clear_cpu_cap(X86_FEATURE_CLFLSH); @@ -592,17 +634,17 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) vendor = c->x86_vendor_id; if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor))) - printk("%s ", vendor); + printk(KERN_CONT "%s ", vendor); - if (!c->x86_model_id[0]) - printk("%d86", c->x86); + if (c->x86_model_id[0]) + printk(KERN_CONT "%s", c->x86_model_id); else - printk("%s", c->x86_model_id); + printk(KERN_CONT "%d86", c->x86); if (c->x86_mask || c->cpuid_level >= 0) - printk(" stepping %02x\n", c->x86_mask); + printk(KERN_CONT " stepping %02x\n", c->x86_mask); else - printk("\n"); + printk(KERN_CONT "\n"); } static __init int setup_disablecpuid(char *arg) @@ -618,16 +660,6 @@ __setup("clearcpuid=", setup_disablecpuid); cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; -void __init early_cpu_init(void) -{ - struct cpu_vendor_dev *cvdev; - - for (cvdev = __x86cpuvendor_start; cvdev < __x86cpuvendor_end; cvdev++) - cpu_devs[cvdev->vendor] = cvdev->cpu_dev; - - early_identify_cpu(&boot_cpu_data); -} - /* Make sure %fs is initialized properly in idle threads */ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) { @@ -636,18 +668,6 @@ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) return regs; } -/* Current gdt points %fs at the "master" per-cpu area: after this, - * it's on the real one. */ -void switch_to_new_gdt(void) -{ - struct desc_ptr gdt_descr; - - gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); - gdt_descr.size = GDT_SIZE - 1; - load_gdt(&gdt_descr); - asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); -} - /* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 28719fe0794..522a5f2e405 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -103,9 +103,8 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) if (n >= 0x80000005) { cpuid(0x80000005, &dummy, &ebx, &ecx, &edx); - printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), " - "D cache %dK (%d bytes/line)\n", - edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); + printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", + edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); c->x86_cache_size = (ecx>>24) + (edx>>24); /* On K8 L1 TLB is inclusive, so don't count it */ c->x86_tlbsize = 0; @@ -143,8 +142,8 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) } else if (smp_num_siblings > 1) { if (smp_num_siblings > NR_CPUS) { - printk(KERN_WARNING "CPU: Unsupported number of " - "siblings %d", smp_num_siblings); + printk(KERN_WARNING "CPU: Unsupported number of siblings %d", + smp_num_siblings); smp_num_siblings = 1; return; } @@ -182,7 +181,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) if (cpu_devs[i]) { if (!strcmp(v, cpu_devs[i]->c_ident[0]) || (cpu_devs[i]->c_ident[1] && - !strcmp(v, cpu_devs[i]->c_ident[1]))) { + !strcmp(v, cpu_devs[i]->c_ident[1]))) { c->x86_vendor = i; this_cpu = cpu_devs[i]; return; @@ -217,39 +216,6 @@ static void __init early_cpu_support_print(void) } } -/* - * The NOPL instruction is supposed to exist on all CPUs with - * family >= 6, unfortunately, that's not true in practice because - * of early VIA chips and (more importantly) broken virtualizers that - * are not easy to detect. Hence, probe for it based on first - * principles. - * - * Note: no 64-bit chip is known to lack these, but put the code here - * for consistency with 32 bits, and to make it utterly trivial to - * diagnose the problem should it ever surface. - */ -static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) -{ - const u32 nopl_signature = 0x888c53b1; /* Random number */ - u32 has_nopl = nopl_signature; - - clear_cpu_cap(c, X86_FEATURE_NOPL); - if (c->x86 >= 6) { - asm volatile("\n" - "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ - "2:\n" - " .section .fixup,\"ax\"\n" - "3: xor %0,%0\n" - " jmp 2b\n" - " .previous\n" - _ASM_EXTABLE(1b,3b) - : "+a" (has_nopl)); - - if (has_nopl == nopl_signature) - set_cpu_cap(c, X86_FEATURE_NOPL); - } -} - void __cpuinit cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ @@ -258,6 +224,7 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c) (unsigned int *)&c->x86_vendor_id[8], (unsigned int *)&c->x86_vendor_id[4]); + c->x86 = 4; /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { u32 junk, tfms, cap0, misc; @@ -268,12 +235,11 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c) if (c->x86 == 0xf) c->x86 += (tfms >> 20) & 0xff; if (c->x86 >= 0x6) - c->x86_model += ((tfms >> 16) & 0xF) << 4; - if (cap0 & (1<<19)) + c->x86_model += ((tfms >> 16) & 0xf) << 4; + if (cap0 & (1<<19)) { c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; - } else { - /* Have CPUID level 0 only - unheard of */ - c->x86 = 4; + c->x86_cache_alignment = c->x86_clflush_size; + } } } @@ -283,9 +249,6 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) u32 tfms, xlvl; u32 ebx; - /* Initialize the standard set of capabilities */ - /* Note that the vendor-specific code below might override */ - /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { u32 capability, excap; @@ -361,6 +324,39 @@ void __init early_cpu_init(void) early_identify_cpu(&boot_cpu_data); } +/* + * The NOPL instruction is supposed to exist on all CPUs with + * family >= 6, unfortunately, that's not true in practice because + * of early VIA chips and (more importantly) broken virtualizers that + * are not easy to detect. Hence, probe for it based on first + * principles. + * + * Note: no 64-bit chip is known to lack these, but put the code here + * for consistency with 32 bits, and to make it utterly trivial to + * diagnose the problem should it ever surface. + */ +static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +{ + const u32 nopl_signature = 0x888c53b1; /* Random number */ + u32 has_nopl = nopl_signature; + + clear_cpu_cap(c, X86_FEATURE_NOPL); + if (c->x86 >= 6) { + asm volatile("\n" + "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ + "2:\n" + " .section .fixup,\"ax\"\n" + "3: xor %0,%0\n" + " jmp 2b\n" + " .previous\n" + _ASM_EXTABLE(1b,3b) + : "+a" (has_nopl)); + + if (has_nopl == nopl_signature) + set_cpu_cap(c, X86_FEATURE_NOPL); + } +} + static void __cpuinit generic_identify(struct cpuinfo_x86 *c) { c->extended_cpuid_level = 0; @@ -448,7 +444,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) } -void __cpuinit identify_boot_cpu(void) +void __init identify_boot_cpu(void) { identify_cpu(&boot_cpu_data); } @@ -460,13 +456,6 @@ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) mtrr_ap_init(); } -static __init int setup_noclflush(char *arg) -{ - setup_clear_cpu_cap(X86_FEATURE_CLFLSH); - return 1; -} -__setup("noclflush", setup_noclflush); - struct msr_range { unsigned min; unsigned max; @@ -510,6 +499,13 @@ static __init int setup_show_msr(char *arg) } __setup("show_msr=", setup_show_msr); +static __init int setup_noclflush(char *arg) +{ + setup_clear_cpu_cap(X86_FEATURE_CLFLSH); + return 1; +} +__setup("noclflush", setup_noclflush); + void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) { if (c->x86_model_id[0]) -- cgit v1.2.3 From 10a434fcb23a57c385177a0086955fae01003f64 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:45 +0200 Subject: x86: remove cpu_vendor_dev 1. add c_x86_vendor into cpu_dev 2. change cpu_devs to static 3. check c_x86_vendor before put that cpu_dev into array 4. remove alignment for 64bit 5. order the sequence in cpu_devs according to link sequence... so could put intel at first, then amd... Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/Makefile | 4 +-- arch/x86/kernel/cpu/amd.c | 3 +- arch/x86/kernel/cpu/amd_64.c | 4 +-- arch/x86/kernel/cpu/centaur.c | 3 +- arch/x86/kernel/cpu/centaur_64.c | 3 +- arch/x86/kernel/cpu/common.c | 71 ++++++++++++++++++++-------------------- arch/x86/kernel/cpu/common_64.c | 71 ++++++++++++++++++++-------------------- arch/x86/kernel/cpu/cpu.h | 18 ++++------ arch/x86/kernel/cpu/cyrix.c | 6 ++-- arch/x86/kernel/cpu/intel.c | 3 +- arch/x86/kernel/cpu/intel_64.c | 3 +- arch/x86/kernel/cpu/transmeta.c | 3 +- arch/x86/kernel/cpu/umc.c | 3 +- arch/x86/kernel/vmlinux_32.lds.S | 8 ++--- arch/x86/kernel/vmlinux_64.lds.S | 9 +++-- 15 files changed, 106 insertions(+), 106 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 3ede19a4e0b..403e689df0b 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -8,14 +8,14 @@ obj-y += proc.o capflags.o powerflags.o obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += common_64.o bugs_64.o +obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o +obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o obj-$(CONFIG_CPU_SUP_AMD_32) += amd.o obj-$(CONFIG_CPU_SUP_AMD_64) += amd_64.o obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o obj-$(CONFIG_CPU_SUP_CENTAUR_32) += centaur.o obj-$(CONFIG_CPU_SUP_CENTAUR_64) += centaur_64.o obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o -obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o -obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o obj-$(CONFIG_X86_MCE) += mcheck/ diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 18514ed2610..d64ea6097ca 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -298,6 +298,7 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = { .c_early_init = early_init_amd, .c_init = init_amd, .c_size_cache = amd_size_cache, + .c_x86_vendor = X86_VENDOR_AMD, }; -cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev); +cpu_dev_register(amd_cpu_dev); diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index d1692b2a41f..d1c721c0c49 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -218,7 +218,7 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = { .c_ident = { "AuthenticAMD" }, .c_early_init = early_init_amd, .c_init = init_amd, + .c_x86_vendor = X86_VENDOR_AMD, }; -cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev); - +cpu_dev_register(amd_cpu_dev); diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index a0534c04d38..e5f6d89521b 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -475,6 +475,7 @@ static struct cpu_dev centaur_cpu_dev __cpuinitdata = { .c_early_init = early_init_centaur, .c_init = init_centaur, .c_size_cache = centaur_size_cache, + .c_x86_vendor = X86_VENDOR_CENTAUR, }; -cpu_vendor_dev_register(X86_VENDOR_CENTAUR, ¢aur_cpu_dev); +cpu_dev_register(centaur_cpu_dev); diff --git a/arch/x86/kernel/cpu/centaur_64.c b/arch/x86/kernel/cpu/centaur_64.c index 1d181c40e2e..49cfc6d2f2f 100644 --- a/arch/x86/kernel/cpu/centaur_64.c +++ b/arch/x86/kernel/cpu/centaur_64.c @@ -29,7 +29,8 @@ static struct cpu_dev centaur_cpu_dev __cpuinitdata = { .c_ident = { "CentaurHauls" }, .c_early_init = early_init_centaur, .c_init = init_centaur, + .c_x86_vendor = X86_VENDOR_CENTAUR, }; -cpu_vendor_dev_register(X86_VENDOR_CENTAUR, ¢aur_cpu_dev); +cpu_dev_register(centaur_cpu_dev); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 10e89ae5a60..ee1044ca481 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -75,7 +75,7 @@ void switch_to_new_gdt(void) static int cachesize_override __cpuinitdata = -1; static int disable_x86_serial_nr __cpuinitdata = 1; -struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; +static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; static void __cpuinit default_init(struct cpuinfo_x86 *c) { @@ -93,8 +93,9 @@ static void __cpuinit default_init(struct cpuinfo_x86 *c) static struct cpu_dev __cpuinitdata default_cpu = { .c_init = default_init, .c_vendor = "Unknown", + .c_x86_vendor = X86_VENDOR_UNKNOWN, }; -static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu; +static struct cpu_dev *this_cpu __cpuinitdata; static int __init cachesize_setup(char *str) { @@ -250,21 +251,24 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) static int printed; for (i = 0; i < X86_VENDOR_NUM; i++) { - if (cpu_devs[i]) { - if (!strcmp(v, cpu_devs[i]->c_ident[0]) || - (cpu_devs[i]->c_ident[1] && - !strcmp(v, cpu_devs[i]->c_ident[1]))) { - c->x86_vendor = i; - this_cpu = cpu_devs[i]; - return; - } + if (!cpu_devs[i]) + break; + + if (!strcmp(v, cpu_devs[i]->c_ident[0]) || + (cpu_devs[i]->c_ident[1] && + !strcmp(v, cpu_devs[i]->c_ident[1]))) { + this_cpu = cpu_devs[i]; + c->x86_vendor = this_cpu->c_x86_vendor; + return; } } + if (!printed) { printed++; printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n"); printk(KERN_ERR "CPU: Your system may be unstable.\n"); } + c->x86_vendor = X86_VENDOR_UNKNOWN; this_cpu = &default_cpu; } @@ -315,25 +319,6 @@ static int __cpuinit have_cpuid_p(void) return flag_is_changeable_p(X86_EFLAGS_ID); } -static void __init early_cpu_support_print(void) -{ - int i,j; - struct cpu_dev *cpu_devx; - - printk("KERNEL supported cpus:\n"); - for (i = 0; i < X86_VENDOR_NUM; i++) { - cpu_devx = cpu_devs[i]; - if (!cpu_devx) - continue; - for (j = 0; j < 2; j++) { - if (!cpu_devx->c_ident[j]) - continue; - printk(" %s %s\n", cpu_devx->c_vendor, - cpu_devx->c_ident[j]); - } - } -} - void __cpuinit cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ @@ -411,21 +396,35 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) get_cpu_cap(c); - if (c->x86_vendor != X86_VENDOR_UNKNOWN && - cpu_devs[c->x86_vendor]->c_early_init) - cpu_devs[c->x86_vendor]->c_early_init(c); + if (this_cpu->c_early_init) + this_cpu->c_early_init(c); validate_pat_support(c); } void __init early_cpu_init(void) { - struct cpu_vendor_dev *cvdev; + struct cpu_dev **cdev; + int count = 0; + + printk("KERNEL supported cpus:\n"); + for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) { + struct cpu_dev *cpudev = *cdev; + unsigned int j; - for (cvdev = __x86cpuvendor_start; cvdev < __x86cpuvendor_end; cvdev++) - cpu_devs[cvdev->vendor] = cvdev->cpu_dev; + if (count >= X86_VENDOR_NUM) + break; + cpu_devs[count] = cpudev; + count++; + + for (j = 0; j < 2; j++) { + if (!cpudev->c_ident[j]) + continue; + printk(" %s %s\n", cpudev->c_vendor, + cpudev->c_ident[j]); + } + } - early_cpu_support_print(); early_identify_cpu(&boot_cpu_data); } diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 522a5f2e405..b82479c1083 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -66,7 +66,7 @@ void switch_to_new_gdt(void) load_gdt(&gdt_descr); } -struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; +static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; static void __cpuinit default_init(struct cpuinfo_x86 *c) { @@ -76,8 +76,9 @@ static void __cpuinit default_init(struct cpuinfo_x86 *c) static struct cpu_dev __cpuinitdata default_cpu = { .c_init = default_init, .c_vendor = "Unknown", + .c_x86_vendor = X86_VENDOR_UNKNOWN, }; -static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu; +static struct cpu_dev *this_cpu __cpuinitdata; int __cpuinit get_model_name(struct cpuinfo_x86 *c) { @@ -178,44 +179,28 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) static int printed; for (i = 0; i < X86_VENDOR_NUM; i++) { - if (cpu_devs[i]) { - if (!strcmp(v, cpu_devs[i]->c_ident[0]) || - (cpu_devs[i]->c_ident[1] && - !strcmp(v, cpu_devs[i]->c_ident[1]))) { - c->x86_vendor = i; - this_cpu = cpu_devs[i]; - return; - } + if (!cpu_devs[i]) + break; + + if (!strcmp(v, cpu_devs[i]->c_ident[0]) || + (cpu_devs[i]->c_ident[1] && + !strcmp(v, cpu_devs[i]->c_ident[1]))) { + this_cpu = cpu_devs[i]; + c->x86_vendor = this_cpu->c_x86_vendor; + return; } } + if (!printed) { printed++; printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n"); printk(KERN_ERR "CPU: Your system may be unstable.\n"); } + c->x86_vendor = X86_VENDOR_UNKNOWN; this_cpu = &default_cpu; } -static void __init early_cpu_support_print(void) -{ - int i,j; - struct cpu_dev *cpu_devx; - - printk("KERNEL supported cpus:\n"); - for (i = 0; i < X86_VENDOR_NUM; i++) { - cpu_devx = cpu_devs[i]; - if (!cpu_devx) - continue; - for (j = 0; j < 2; j++) { - if (!cpu_devx->c_ident[j]) - continue; - printk(" %s %s\n", cpu_devx->c_vendor, - cpu_devx->c_ident[j]); - } - } -} - void __cpuinit cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ @@ -306,21 +291,35 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) get_cpu_cap(c); - if (c->x86_vendor != X86_VENDOR_UNKNOWN && - cpu_devs[c->x86_vendor]->c_early_init) - cpu_devs[c->x86_vendor]->c_early_init(c); + if (this_cpu->c_early_init) + this_cpu->c_early_init(c); validate_pat_support(c); } void __init early_cpu_init(void) { - struct cpu_vendor_dev *cvdev; + struct cpu_dev **cdev; + int count = 0; + + printk("KERNEL supported cpus:\n"); + for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) { + struct cpu_dev *cpudev = *cdev; + unsigned int j; - for (cvdev = __x86cpuvendor_start; cvdev < __x86cpuvendor_end; cvdev++) - cpu_devs[cvdev->vendor] = cvdev->cpu_dev; + if (count >= X86_VENDOR_NUM) + break; + cpu_devs[count] = cpudev; + count++; + + for (j = 0; j < 2; j++) { + if (!cpudev->c_ident[j]) + continue; + printk(" %s %s\n", cpudev->c_vendor, + cpudev->c_ident[j]); + } + } - early_cpu_support_print(); early_identify_cpu(&boot_cpu_data); } diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index 4d894e8565f..3cc9d92afd8 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h @@ -21,21 +21,15 @@ struct cpu_dev { void (*c_init)(struct cpuinfo_x86 * c); void (*c_identify)(struct cpuinfo_x86 * c); unsigned int (*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size); + int c_x86_vendor; }; -extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM]; +#define cpu_dev_register(cpu_devX) \ + static struct cpu_dev *__cpu_dev_##cpu_devX __used \ + __attribute__((__section__(".x86_cpu_dev.init"))) = \ + &cpu_devX; -struct cpu_vendor_dev { - int vendor; - struct cpu_dev *cpu_dev; -}; - -#define cpu_vendor_dev_register(cpu_vendor_id, cpu_dev) \ - static struct cpu_vendor_dev __cpu_vendor_dev_##cpu_vendor_id __used \ - __attribute__((__section__(".x86cpuvendor.init"))) = \ - { cpu_vendor_id, cpu_dev } - -extern struct cpu_vendor_dev __x86cpuvendor_start[], __x86cpuvendor_end[]; +extern struct cpu_dev *__x86_cpu_dev_start[], *__x86_cpu_dev_end[]; extern int get_model_name(struct cpuinfo_x86 *c); extern void display_cacheinfo(struct cpuinfo_x86 *c); diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 13f8fa16b81..3f8c7283d81 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -442,14 +442,16 @@ static struct cpu_dev cyrix_cpu_dev __cpuinitdata = { .c_early_init = early_init_cyrix, .c_init = init_cyrix, .c_identify = cyrix_identify, + .c_x86_vendor = X86_VENDOR_CYRIX, }; -cpu_vendor_dev_register(X86_VENDOR_CYRIX, &cyrix_cpu_dev); +cpu_dev_register(cyrix_cpu_dev); static struct cpu_dev nsc_cpu_dev __cpuinitdata = { .c_vendor = "NSC", .c_ident = { "Geode by NSC" }, .c_init = init_nsc, + .c_x86_vendor = X86_VENDOR_NSC, }; -cpu_vendor_dev_register(X86_VENDOR_NSC, &nsc_cpu_dev); +cpu_dev_register(nsc_cpu_dev); diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 77618c717d7..c5ac08124ad 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -303,9 +303,10 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = { .c_early_init = early_init_intel, .c_init = init_intel, .c_size_cache = intel_size_cache, + .c_x86_vendor = X86_VENDOR_INTEL, }; -cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev); +cpu_dev_register(intel_cpu_dev); /* arch_initcall(intel_cpu_init); */ diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c index 1019c58d39f..0a8128a240d 100644 --- a/arch/x86/kernel/cpu/intel_64.c +++ b/arch/x86/kernel/cpu/intel_64.c @@ -90,6 +90,7 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = { .c_ident = { "GenuineIntel" }, .c_early_init = early_init_intel, .c_init = init_intel, + .c_x86_vendor = X86_VENDOR_INTEL, }; -cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev); +cpu_dev_register(intel_cpu_dev); diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index b911a2c61b8..7c46e6ecedc 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -102,6 +102,7 @@ static struct cpu_dev transmeta_cpu_dev __cpuinitdata = { .c_ident = { "GenuineTMx86", "TransmetaCPU" }, .c_init = init_transmeta, .c_identify = transmeta_identify, + .c_x86_vendor = X86_VENDOR_TRANSMETA, }; -cpu_vendor_dev_register(X86_VENDOR_TRANSMETA, &transmeta_cpu_dev); +cpu_dev_register(transmeta_cpu_dev); diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c index b1fc90989d7..e777f79e096 100644 --- a/arch/x86/kernel/cpu/umc.c +++ b/arch/x86/kernel/cpu/umc.c @@ -19,7 +19,8 @@ static struct cpu_dev umc_cpu_dev __cpuinitdata = { } }, }, + .c_x86_vendor = X86_VENDOR_UMC, }; -cpu_vendor_dev_register(X86_VENDOR_UMC, &umc_cpu_dev); +cpu_dev_register(umc_cpu_dev); diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S index af5bdad8460..21b4f7eefaa 100644 --- a/arch/x86/kernel/vmlinux_32.lds.S +++ b/arch/x86/kernel/vmlinux_32.lds.S @@ -140,10 +140,10 @@ SECTIONS *(.con_initcall.init) __con_initcall_end = .; } - .x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) { - __x86cpuvendor_start = .; - *(.x86cpuvendor.init) - __x86cpuvendor_end = .; + .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { + __x86_cpu_dev_start = .; + *(.x86_cpu_dev.init) + __x86_cpu_dev_end = .; } SECURITY_INIT . = ALIGN(4); diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 63e5c1a22e8..201e81a91a9 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -168,13 +168,12 @@ SECTIONS *(.con_initcall.init) } __con_initcall_end = .; - . = ALIGN(16); - __x86cpuvendor_start = .; - .x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) { - *(.x86cpuvendor.init) + __x86_cpu_dev_start = .; + .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { + *(.x86_cpu_dev.init) } - __x86cpuvendor_end = .; SECURITY_INIT + __x86_cpu_dev_end = .; . = ALIGN(8); .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { -- cgit v1.2.3 From a0854a46c5eb82588126421a9cbceb973384a644 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:46 +0200 Subject: x86: make 32bit support show_msr like 64 bit Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index ee1044ca481..a79cf5c52b6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -616,6 +616,49 @@ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) mtrr_ap_init(); } +struct msr_range { + unsigned min; + unsigned max; +}; + +static struct msr_range msr_range_array[] __cpuinitdata = { + { 0x00000000, 0x00000418}, + { 0xc0000000, 0xc000040b}, + { 0xc0010000, 0xc0010142}, + { 0xc0011000, 0xc001103b}, +}; + +static void __cpuinit print_cpu_msr(void) +{ + unsigned index; + u64 val; + int i; + unsigned index_min, index_max; + + for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) { + index_min = msr_range_array[i].min; + index_max = msr_range_array[i].max; + for (index = index_min; index < index_max; index++) { + if (rdmsrl_amd_safe(index, &val)) + continue; + printk(KERN_INFO " MSR%08x: %016llx\n", index, val); + } + } +} + +static int show_msr __cpuinitdata; +static __init int setup_show_msr(char *arg) +{ + int num; + + get_option(&arg, &num); + + if (num > 0) + show_msr = num; + return 1; +} +__setup("show_msr=", setup_show_msr); + static __init int setup_noclflush(char *arg) { setup_clear_cpu_cap(X86_FEATURE_CLFLSH); @@ -644,6 +687,14 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) printk(KERN_CONT " stepping %02x\n", c->x86_mask); else printk(KERN_CONT "\n"); + +#ifdef CONFIG_SMP + if (c->cpu_index < show_msr) + print_cpu_msr(); +#else + if (show_msr) + print_cpu_msr(); +#endif } static __init int setup_disablecpuid(char *arg) -- cgit v1.2.3 From 01b2e16a7a9be6573cba5d594d6659b3c6cb46a0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:46 +0200 Subject: x86: make get_mode_name of 64bit the same as 32bit Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index b82479c1083..f1fb94e766b 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -83,6 +83,7 @@ static struct cpu_dev *this_cpu __cpuinitdata; int __cpuinit get_model_name(struct cpuinfo_x86 *c) { unsigned int *v; + char *p, *q; if (c->extended_cpuid_level < 0x80000004) return 0; @@ -92,6 +93,19 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c) cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); c->x86_model_id[48] = 0; + + /* Intel chips right-justify this string for some dumb reason; + undo that brain damage */ + p = q = &c->x86_model_id[0]; + while (*p == ' ') + p++; + if (p != q) { + while (*p) + *q++ = *p++; + while (q <= &c->x86_model_id[48]) + *q++ = '\0'; /* Zero-pad the rest */ + } + return 1; } -- cgit v1.2.3 From 0a488a53d7ca46ac638c30079072c57e50cfcc7b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:47 +0200 Subject: x86: move 32bit related functions together Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 251 ++++++++++++++++++++-------------------- arch/x86/kernel/cpu/common_64.c | 34 +++--- 2 files changed, 143 insertions(+), 142 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a79cf5c52b6..2b2c170e8d6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -22,6 +22,8 @@ #include "cpu.h" +static struct cpu_dev *this_cpu __cpuinitdata; + DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, @@ -58,6 +60,109 @@ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { } }; EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); +static int cachesize_override __cpuinitdata = -1; +static int disable_x86_serial_nr __cpuinitdata = 1; + +static int __init cachesize_setup(char *str) +{ + get_option(&str, &cachesize_override); + return 1; +} +__setup("cachesize=", cachesize_setup); + +/* + * Naming convention should be: [()] + * This table only is used unless init_() below doesn't set it; + * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used + * + */ + +/* Look up CPU names by table lookup. */ +static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) +{ + struct cpu_model_info *info; + + if (c->x86_model >= 16) + return NULL; /* Range check */ + + if (!this_cpu) + return NULL; + + info = this_cpu->c_models; + + while (info && info->family) { + if (info->family == c->x86) + return info->model_names[c->x86_model]; + info++; + } + return NULL; /* Not found */ +} + +static int __init x86_fxsr_setup(char *s) +{ + setup_clear_cpu_cap(X86_FEATURE_FXSR); + setup_clear_cpu_cap(X86_FEATURE_XMM); + return 1; +} +__setup("nofxsr", x86_fxsr_setup); + +static int __init x86_sep_setup(char *s) +{ + setup_clear_cpu_cap(X86_FEATURE_SEP); + return 1; +} +__setup("nosep", x86_sep_setup); + +/* Standard macro to see if a specific flag is changeable */ +static inline int flag_is_changeable_p(u32 flag) +{ + u32 f1, f2; + + asm("pushfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "movl %0,%1\n\t" + "xorl %2,%0\n\t" + "pushl %0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "popfl\n\t" + : "=&r" (f1), "=&r" (f2) + : "ir" (flag)); + + return ((f1^f2) & flag) != 0; +} + +/* Probe for the CPUID instruction */ +static int __cpuinit have_cpuid_p(void) +{ + return flag_is_changeable_p(X86_EFLAGS_ID); +} + +static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +{ + if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) { + /* Disable processor serial number */ + unsigned long lo, hi; + rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi); + lo |= 0x200000; + wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi); + printk(KERN_NOTICE "CPU serial number disabled.\n"); + clear_cpu_cap(c, X86_FEATURE_PN); + + /* Disabling the serial number may affect the cpuid level */ + c->cpuid_level = cpuid_eax(0); + } +} + +static int __init x86_serial_nr_setup(char *s) +{ + disable_x86_serial_nr = 0; + return 1; +} +__setup("serialnumber", x86_serial_nr_setup); + __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; /* Current gdt points %fs at the "master" per-cpu area: after this, @@ -72,9 +177,6 @@ void switch_to_new_gdt(void) asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); } -static int cachesize_override __cpuinitdata = -1; -static int disable_x86_serial_nr __cpuinitdata = 1; - static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; static void __cpuinit default_init(struct cpuinfo_x86 *c) @@ -95,14 +197,6 @@ static struct cpu_dev __cpuinitdata default_cpu = { .c_vendor = "Unknown", .c_x86_vendor = X86_VENDOR_UNKNOWN, }; -static struct cpu_dev *this_cpu __cpuinitdata; - -static int __init cachesize_setup(char *str) -{ - get_option(&str, &cachesize_override); - return 1; -} -__setup("cachesize=", cachesize_setup); int __cpuinit get_model_name(struct cpuinfo_x86 *c) { @@ -133,7 +227,6 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c) return 1; } - void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) { unsigned int n, dummy, ebx, ecx, edx, l2size; @@ -150,7 +243,7 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) if (n < 0x80000006) /* Some chips just has a large L1. */ return; - ecx = cpuid_ecx(0x80000006); + cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); l2size = ecx >> 16; /* do processor-specific cache resizing */ @@ -167,48 +260,23 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) c->x86_cache_size = l2size; printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", - l2size, ecx & 0xFF); -} - -/* - * Naming convention should be: [()] - * This table only is used unless init_() below doesn't set it; - * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used - * - */ - -/* Look up CPU names by table lookup. */ -static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) -{ - struct cpu_model_info *info; - - if (c->x86_model >= 16) - return NULL; /* Range check */ - - if (!this_cpu) - return NULL; - - info = this_cpu->c_models; - - while (info && info->family) { - if (info->family == c->x86) - return info->model_names[c->x86_model]; - info++; - } - return NULL; /* Not found */ + l2size, ecx & 0xFF); } #ifdef CONFIG_X86_HT void __cpuinit detect_ht(struct cpuinfo_x86 *c) { - u32 eax, ebx, ecx, edx; - int index_msb, core_bits; - - cpuid(1, &eax, &ebx, &ecx, &edx); + u32 eax, ebx, ecx, edx; + int index_msb, core_bits; - if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) + if (!cpu_has(c, X86_FEATURE_HT)) return; + if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) + goto out; + + cpuid(1, &eax, &ebx, &ecx, &edx); + smp_num_siblings = (ebx & 0xff0000) >> 16; if (smp_num_siblings == 1) { @@ -225,8 +293,6 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) index_msb = get_count_order(smp_num_siblings); c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - c->phys_proc_id); smp_num_siblings = smp_num_siblings / c->x86_max_cores; @@ -236,10 +302,14 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & ((1 << core_bits) - 1); + } - if (c->x86_max_cores > 1) - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - c->cpu_core_id); +out: + if ((c->x86_max_cores * smp_num_siblings) > 1) { + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + c->phys_proc_id); + printk(KERN_INFO "CPU: Processor Core ID: %d\n", + c->cpu_core_id); } } #endif @@ -273,52 +343,6 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) this_cpu = &default_cpu; } - -static int __init x86_fxsr_setup(char *s) -{ - setup_clear_cpu_cap(X86_FEATURE_FXSR); - setup_clear_cpu_cap(X86_FEATURE_XMM); - return 1; -} -__setup("nofxsr", x86_fxsr_setup); - - -static int __init x86_sep_setup(char *s) -{ - setup_clear_cpu_cap(X86_FEATURE_SEP); - return 1; -} -__setup("nosep", x86_sep_setup); - - -/* Standard macro to see if a specific flag is changeable */ -static inline int flag_is_changeable_p(u32 flag) -{ - u32 f1, f2; - - asm("pushfl\n\t" - "pushfl\n\t" - "popl %0\n\t" - "movl %0,%1\n\t" - "xorl %2,%0\n\t" - "pushl %0\n\t" - "popfl\n\t" - "pushfl\n\t" - "popl %0\n\t" - "popfl\n\t" - : "=&r" (f1), "=&r" (f2) - : "ir" (flag)); - - return ((f1^f2) & flag) != 0; -} - - -/* Probe for the CPUID instruction */ -static int __cpuinit have_cpuid_p(void) -{ - return flag_is_changeable_p(X86_EFLAGS_ID); -} - void __cpuinit cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ @@ -380,16 +404,16 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) */ static void __init early_identify_cpu(struct cpuinfo_x86 *c) { - c->x86_cache_alignment = 32; c->x86_clflush_size = 32; + c->x86_cache_alignment = c->x86_clflush_size; if (!have_cpuid_p()) return; - c->extended_cpuid_level = 0; - memset(&c->x86_capability, 0, sizeof c->x86_capability); + c->extended_cpuid_level = 0; + cpu_detect(c); get_cpu_vendor(c); @@ -487,31 +511,6 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) detect_nopl(c); } -static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) -{ - if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) { - /* Disable processor serial number */ - unsigned long lo, hi; - rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi); - lo |= 0x200000; - wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi); - printk(KERN_NOTICE "CPU serial number disabled.\n"); - clear_cpu_cap(c, X86_FEATURE_PN); - - /* Disabling the serial number may affect the cpuid level */ - c->cpuid_level = cpuid_eax(0); - } -} - -static int __init x86_serial_nr_setup(char *s) -{ - disable_x86_serial_nr = 0; - return 1; -} -__setup("serialnumber", x86_serial_nr_setup); - - - /* * This does the hard work of actually picking apart the CPU stuff... */ diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index f1fb94e766b..b2da0413532 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -37,6 +37,8 @@ #include "cpu.h" +static struct cpu_dev *this_cpu __cpuinitdata; + /* We need valid kernel segments for data and code in long mode too * IRET will check the segment types kkeil 2000/10/28 * Also sysret mandates a special GDT layout @@ -78,7 +80,6 @@ static struct cpu_dev __cpuinitdata default_cpu = { .c_vendor = "Unknown", .c_x86_vendor = X86_VENDOR_UNKNOWN, }; -static struct cpu_dev *this_cpu __cpuinitdata; int __cpuinit get_model_name(struct cpuinfo_x86 *c) { @@ -112,7 +113,7 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c) void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) { - unsigned int n, dummy, ebx, ecx, edx; + unsigned int n, dummy, ebx, ecx, edx, l2size; n = c->extended_cpuid_level; @@ -125,15 +126,17 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) c->x86_tlbsize = 0; } - if (n >= 0x80000006) { - cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); - ecx = cpuid_ecx(0x80000006); - c->x86_cache_size = ecx >> 16; - c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); + if (n < 0x80000006) /* Some chips just has a large L1. */ + return; - printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", - c->x86_cache_size, ecx & 0xFF); - } + cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); + l2size = ecx >> 16; + c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); + + c->x86_cache_size = l2size; + + printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", + l2size, ecx & 0xFF); } void __cpuinit detect_ht(struct cpuinfo_x86 *c) @@ -142,14 +145,13 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) u32 eax, ebx, ecx, edx; int index_msb, core_bits; - cpuid(1, &eax, &ebx, &ecx, &edx); - - if (!cpu_has(c, X86_FEATURE_HT)) return; if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) goto out; + cpuid(1, &eax, &ebx, &ecx, &edx); + smp_num_siblings = (ebx & 0xff0000) >> 16; if (smp_num_siblings == 1) { @@ -175,6 +177,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) c->cpu_core_id = phys_pkg_id(index_msb) & ((1 << core_bits) - 1); } + out: if ((c->x86_max_cores * smp_num_siblings) > 1) { printk(KERN_INFO "CPU: Physical Processor ID: %d\n", @@ -182,7 +185,6 @@ out: printk(KERN_INFO "CPU: Processor Core ID: %d\n", c->cpu_core_id); } - #endif } @@ -405,10 +407,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86_model = c->x86_mask = 0; /* So far unknown... */ c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */ - c->x86_clflush_size = 64; - c->x86_cache_alignment = c->x86_clflush_size; c->x86_max_cores = 1; c->x86_coreid_bits = 0; + c->x86_clflush_size = 64; + c->x86_cache_alignment = c->x86_clflush_size; memset(&c->x86_capability, 0, sizeof c->x86_capability); generic_identify(c); -- cgit v1.2.3 From 6ac40ed0413ef4096720f966e11c7cdf259eee3f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 4 Sep 2008 10:41:22 -0700 Subject: x86: quick TSC calibration Introduce a fast TSC-calibration method on sane hardware. It only uses 17920 PIT timer ticks to calibrate the TSC, plus 256 ticks on each side to make sure the TSC values were very close to the tick, so the whole calibration takes 15ms. Yet, despite only takign 15ms, we can actually give pretty stringent guarantees of accuracy: - the code requires that we hit each 256-counter block at least 50 times, so the TSC error is basically at *MOST* just a few PIT cycles off in any direction. In practice, it's going to be about one microseconds off (which is how long it takes to read the counter) - so over 17920 PIT cycles, we can pretty much guarantee that the calibration error is less than one half of a percent. My testing bears this out: on my machine, the quick-calibration reports 2934.085kHz, while the slow one reports 2933.415. Yes, the slower calibration is still more precise. For me, the slow calibration is stable to within about one hundreth of a percent, so it's (at a guess) roughly an order-and-a-half of magnitude more precise. The longer you wait, the more precise you can be. However, the nice thing about the fast TSC PIT synchronization is that it's pretty much _guaranteed_ to give that 0.5% precision, and fail gracefully (and very quickly) if it doesn't get it. And it really is fairly simple (even if there's a lot of _details_ there, and I didn't get all of those right ont he first try or even the second ;) The patch says "110 insertions", but 63 of those new lines are actually comments. Signed-off-by: Linus Torvalds Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 110 insertions(+), 1 deletions(-) --- arch/x86/kernel/tsc.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index da033b5b3e1..839070ba846 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -227,6 +227,117 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin) return delta; } +/* + * This reads the current MSB of the PIT counter, and + * checks if we are running on sufficiently fast and + * non-virtualized hardware. + * + * Our expectations are: + * + * - the PIT is running at roughly 1.19MHz + * + * - each IO is going to take about 1us on real hardware, + * but we allow it to be much faster (by a factor of 10) or + * _slightly_ slower (ie we allow up to a 2us read+counter + * update - anything else implies a unacceptably slow CPU + * or PIT for the fast calibration to work. + * + * - with 256 PIT ticks to read the value, we have 214us to + * see the same MSB (and overhead like doing a single TSC + * read per MSB value etc). + * + * - We're doing 2 reads per loop (LSB, MSB), and we expect + * them each to take about a microsecond on real hardware. + * So we expect a count value of around 100. But we'll be + * generous, and accept anything over 50. + * + * - if the PIT is stuck, and we see *many* more reads, we + * return early (and the next caller of pit_expect_msb() + * then consider it a failure when they don't see the + * next expected value). + * + * These expectations mean that we know that we have seen the + * transition from one expected value to another with a fairly + * high accuracy, and we didn't miss any events. We can thus + * use the TSC value at the transitions to calculate a pretty + * good value for the TSC frequencty. + */ +static inline int pit_expect_msb(unsigned char val) +{ + int count = 0; + + for (count = 0; count < 50000; count++) { + /* Ignore LSB */ + inb(0x42); + if (inb(0x42) != val) + break; + } + return count > 50; +} + +/* + * How many MSB values do we want to see? We aim for a + * 15ms calibration, which assuming a 2us counter read + * error should give us roughly 150 ppm precision for + * the calibration. + */ +#define QUICK_PIT_MS 15 +#define QUICK_PIT_ITERATIONS (QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256) + +static unsigned long quick_pit_calibrate(void) +{ + /* Set the Gate high, disable speaker */ + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + + /* + * Counter 2, mode 0 (one-shot), binary count + * + * NOTE! Mode 2 decrements by two (and then the + * output is flipped each time, giving the same + * final output frequency as a decrement-by-one), + * so mode 0 is much better when looking at the + * individual counts. + */ + outb(0xb0, 0x43); + + /* Start at 0xffff */ + outb(0xff, 0x42); + outb(0xff, 0x42); + + if (pit_expect_msb(0xff)) { + int i; + u64 t1, t2, delta; + unsigned char expect = 0xfe; + + t1 = get_cycles(); + for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) { + if (!pit_expect_msb(expect)) + goto failed; + } + t2 = get_cycles(); + + /* + * Ok, if we get here, then we've seen the + * MSB of the PIT decrement QUICK_PIT_ITERATIONS + * times, and each MSB had many hits, so we never + * had any sudden jumps. + * + * As a result, we can depend on there not being + * any odd delays anywhere, and the TSC reads are + * reliable. + * + * kHz = ticks / time-in-seconds / 1000; + * kHz = (t2 - t1) / (QPI * 256 / PIT_TICK_RATE) / 1000 + * kHz = ((t2 - t1) * PIT_TICK_RATE) / (QPI * 256 * 1000) + */ + delta = (t2 - t1)*PIT_TICK_RATE; + do_div(delta, QUICK_PIT_ITERATIONS*256*1000); + printk("Fast TSC calibration using PIT\n"); + return delta; + } +failed: + return 0; +} /** * native_calibrate_tsc - calibrate the tsc on boot @@ -235,9 +346,15 @@ unsigned long native_calibrate_tsc(void) { u64 tsc1, tsc2, delta, ref1, ref2; unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; - unsigned long flags, latch, ms; + unsigned long flags, latch, ms, fast_calibrate; int hpet = is_hpet_enabled(), i, loopmin; + local_irq_save(flags); + fast_calibrate = quick_pit_calibrate(); + local_irq_restore(flags); + if (fast_calibrate) + return fast_calibrate; + /* * Run 5 calibration loops to get the lowest frequency value * (the best estimate). We use two different calibration modes -- cgit v1.2.3 From 4156e9a8ef5b521185f451213d33fa661f38512e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 4 Sep 2008 22:47:47 +0200 Subject: x86: quick TSC calibration, improve - make sure the final TSC timestamp is reliable too Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 839070ba846..6dab90f6851 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -316,6 +316,12 @@ static unsigned long quick_pit_calibrate(void) } t2 = get_cycles(); + /* + * Make sure we can rely on the second TSC timestamp: + */ + if (!pit_expect_msb(--expect)) + goto failed; + /* * Ok, if we get here, then we've seen the * MSB of the PIT decrement QUICK_PIT_ITERATIONS -- cgit v1.2.3 From fc0eb9f226d8ecc8e3b563bf808bd6d61a6153a1 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 12:56:56 +0200 Subject: mv643xx_eth: smi sharing is a per-unit property, not a per-port one Which top-level unit's SMI interface to use should be a property of the top-level unit, not of the individual ports. This patch moves the ->shared_smi pointer from the per-port platform data to the global platform data. Signed-off-by: Lennert Buytenhek --- arch/arm/mach-mv78xx0/common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index 953a26c469c..5842d3bb02b 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -330,6 +330,7 @@ void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data) struct mv643xx_eth_shared_platform_data mv78xx0_ge01_shared_data = { .t_clk = 0, .dram = &mv78xx0_mbus_dram_info, + .shared_smi = &mv78xx0_ge00_shared, }; static struct resource mv78xx0_ge01_shared_resources[] = { @@ -370,7 +371,6 @@ static struct platform_device mv78xx0_ge01 = { void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data) { eth_data->shared = &mv78xx0_ge01_shared; - eth_data->shared_smi = &mv78xx0_ge00_shared; mv78xx0_ge01.dev.platform_data = eth_data; platform_device_register(&mv78xx0_ge01_shared); @@ -384,6 +384,7 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data) struct mv643xx_eth_shared_platform_data mv78xx0_ge10_shared_data = { .t_clk = 0, .dram = &mv78xx0_mbus_dram_info, + .shared_smi = &mv78xx0_ge00_shared, }; static struct resource mv78xx0_ge10_shared_resources[] = { @@ -424,7 +425,6 @@ static struct platform_device mv78xx0_ge10 = { void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data) { eth_data->shared = &mv78xx0_ge10_shared; - eth_data->shared_smi = &mv78xx0_ge00_shared; mv78xx0_ge10.dev.platform_data = eth_data; platform_device_register(&mv78xx0_ge10_shared); @@ -438,6 +438,7 @@ void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data) struct mv643xx_eth_shared_platform_data mv78xx0_ge11_shared_data = { .t_clk = 0, .dram = &mv78xx0_mbus_dram_info, + .shared_smi = &mv78xx0_ge00_shared, }; static struct resource mv78xx0_ge11_shared_resources[] = { @@ -478,7 +479,6 @@ static struct platform_device mv78xx0_ge11 = { void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data) { eth_data->shared = &mv78xx0_ge11_shared; - eth_data->shared_smi = &mv78xx0_ge00_shared; mv78xx0_ge11.dev.platform_data = eth_data; platform_device_register(&mv78xx0_ge11_shared); -- cgit v1.2.3 From ac840605f3b1d9b99e1e6629a54994f8e003ff91 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 14:06:47 +0200 Subject: mv643xx_eth: remove force_phy_addr field Currently, there are two different fields in the mv643xx_eth_platform_data struct that together describe the PHY address -- one field (phy_addr) has the address of the PHY, but if that address is zero, a second field (force_phy_addr) needs to be set to distinguish the actual address zero from a zero due to not having filled in the PHY address explicitly (which should mean 'use the default PHY address'). If we are a bit smarter about the encoding of the phy_addr field, we can avoid the need for a second field -- this patch does that. Signed-off-by: Lennert Buytenhek --- arch/arm/mach-kirkwood/db88f6281-bp-setup.c | 2 +- arch/arm/mach-kirkwood/rd88f6192-nas-setup.c | 2 +- arch/arm/mach-kirkwood/rd88f6281-setup.c | 2 +- arch/arm/mach-loki/lb88rc8480-setup.c | 2 +- arch/arm/mach-mv78xx0/db78x00-bp-setup.c | 8 ++++---- arch/arm/mach-orion5x/db88f5281-setup.c | 2 +- arch/arm/mach-orion5x/dns323-setup.c | 2 +- arch/arm/mach-orion5x/kurobox_pro-setup.c | 2 +- arch/arm/mach-orion5x/mss2-setup.c | 2 +- arch/arm/mach-orion5x/mv2120-setup.c | 2 +- arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c | 2 +- arch/arm/mach-orion5x/rd88f5181l-ge-setup.c | 2 +- arch/arm/mach-orion5x/rd88f5182-setup.c | 2 +- arch/arm/mach-orion5x/ts78xx-setup.c | 3 +-- arch/arm/mach-orion5x/tsx09-common.c | 2 +- arch/arm/mach-orion5x/wnr854t-setup.c | 2 +- arch/arm/mach-orion5x/wrt350n-v2-setup.c | 2 +- arch/powerpc/sysdev/mv64x60_dev.c | 6 ++---- 18 files changed, 22 insertions(+), 25 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c index 610fb24d8ae..cd317795f35 100644 --- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c @@ -25,7 +25,7 @@ #include "common.h" static struct mv643xx_eth_platform_data db88f6281_ge00_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv_sata_platform_data db88f6281_sata_data = { diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c index a3012d44597..b1d1a87a682 100644 --- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c @@ -30,7 +30,7 @@ #define RD88F6192_GPIO_USB_VBUS 10 static struct mv643xx_eth_platform_data rd88f6192_ge00_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv_sata_platform_data rd88f6192_sata_data = { diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c index d96487a0f18..b6416615c0b 100644 --- a/arch/arm/mach-kirkwood/rd88f6281-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c @@ -69,7 +69,7 @@ static struct platform_device rd88f6281_nand_flash = { }; static struct mv643xx_eth_platform_data rd88f6281_ge00_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c index 2cc9ac9b488..85f9c1296aa 100644 --- a/arch/arm/mach-loki/lb88rc8480-setup.c +++ b/arch/arm/mach-loki/lb88rc8480-setup.c @@ -67,7 +67,7 @@ static struct platform_device lb88rc8480_boot_flash = { }; static struct mv643xx_eth_platform_data lb88rc8480_ge0_data = { - .phy_addr = 1, + .phy_addr = MV643XX_ETH_PHY_ADDR(1), .mac_addr = { 0x00, 0x50, 0x43, 0x11, 0x22, 0x33 }, }; diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c index a2d0c978360..49f434c39eb 100644 --- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c +++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c @@ -19,19 +19,19 @@ #include "common.h" static struct mv643xx_eth_platform_data db78x00_ge00_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv643xx_eth_platform_data db78x00_ge01_data = { - .phy_addr = 9, + .phy_addr = MV643XX_ETH_PHY_ADDR(9), }; static struct mv643xx_eth_platform_data db78x00_ge10_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, }; static struct mv643xx_eth_platform_data db78x00_ge11_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, }; static struct mv_sata_platform_data db78x00_sata_data = { diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c index ff13e9060b1..d318bea2af9 100644 --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -285,7 +285,7 @@ subsys_initcall(db88f5281_pci_init); * Ethernet ****************************************************************************/ static struct mv643xx_eth_platform_data db88f5281_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index b38c65ccfb1..3e66098340a 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -79,7 +79,7 @@ subsys_initcall(dns323_pci_init); */ static struct mv643xx_eth_platform_data dns323_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /**************************************************************************** diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index e321ec33183..610f2a6297f 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -161,7 +161,7 @@ subsys_initcall(kurobox_pro_pci_init); ****************************************************************************/ static struct mv643xx_eth_platform_data kurobox_pro_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c index 53ff1893b88..68acca98e63 100644 --- a/arch/arm/mach-orion5x/mss2-setup.c +++ b/arch/arm/mach-orion5x/mss2-setup.c @@ -109,7 +109,7 @@ subsys_initcall(mss2_pci_init); ****************************************************************************/ static struct mv643xx_eth_platform_data mss2_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c index 978d4d59939..97c9ccb2ac6 100644 --- a/arch/arm/mach-orion5x/mv2120-setup.c +++ b/arch/arm/mach-orion5x/mv2120-setup.c @@ -39,7 +39,7 @@ * Ethernet ****************************************************************************/ static struct mv643xx_eth_platform_data mv2120_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv_sata_platform_data mv2120_sata_data = { diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index e72fe1e065e..500cdadaf09 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -88,7 +88,7 @@ static struct orion5x_mpp_mode rd88f5181l_fxo_mpp_modes[] __initdata = { }; static struct mv643xx_eth_platform_data rd88f5181l_fxo_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index a1fe3257320..ebde8141649 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -89,7 +89,7 @@ static struct orion5x_mpp_mode rd88f5181l_ge_mpp_modes[] __initdata = { }; static struct mv643xx_eth_platform_data rd88f5181l_ge_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index 4c3bcd76ac8..a04f9e4b633 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -221,7 +221,7 @@ subsys_initcall(rd88f5182_pci_init); ****************************************************************************/ static struct mv643xx_eth_platform_data rd88f5182_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index ae0a5dccd2a..1368e9fd1a0 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -103,8 +103,7 @@ static struct platform_device ts78xx_nor_boot_flash = { * Ethernet ****************************************************************************/ static struct mv643xx_eth_platform_data ts78xx_eth_data = { - .phy_addr = 0, - .force_phy_addr = 1, + .phy_addr = MV643XX_ETH_PHY_ADDR(0), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/tsx09-common.c b/arch/arm/mach-orion5x/tsx09-common.c index 83feac3147a..19cde24fbfd 100644 --- a/arch/arm/mach-orion5x/tsx09-common.c +++ b/arch/arm/mach-orion5x/tsx09-common.c @@ -48,7 +48,7 @@ void qnap_tsx09_power_off(void) ****************************************************************************/ struct mv643xx_eth_platform_data qnap_tsx09_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static int __init qnap_tsx09_parse_hex_nibble(char n) diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c index b6bc43e07ee..7ddc22c2bb5 100644 --- a/arch/arm/mach-orion5x/wnr854t-setup.c +++ b/arch/arm/mach-orion5x/wnr854t-setup.c @@ -92,7 +92,7 @@ static struct platform_device wnr854t_nor_flash = { }; static struct mv643xx_eth_platform_data wnr854t_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c index b10da17b3fb..9a4fd525646 100644 --- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c +++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c @@ -100,7 +100,7 @@ static struct platform_device wrt350n_v2_nor_flash = { }; static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 32e0ad0ebea..b6bd775d2e2 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c @@ -293,10 +293,8 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id, return -ENODEV; prop = of_get_property(phy, "reg", NULL); - if (prop) { - pdata.force_phy_addr = 1; - pdata.phy_addr = *prop; - } + if (prop) + pdata.phy_addr = MV643XX_ETH_PHY_ADDR(*prop); of_node_put(phy); -- cgit v1.2.3 From 97e4db7c8719f67c52793eeca5ec4df4c3407f2a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:08:59 -0700 Subject: x86: make detect_ht depend on CONFIG_X86_HT 64-bit has X86_HT set too, so use that instead of SMP. This also removes a include/asm-x86/processor.h ifdef. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 4 ++-- arch/x86/kernel/cpu/common_64.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7d5a07f0fd2..1f80ce07daa 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -263,9 +263,9 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) l2size, ecx & 0xFF); } -#ifdef CONFIG_X86_HT void __cpuinit detect_ht(struct cpuinfo_x86 *c) { +#ifdef CONFIG_X86_HT u32 eax, ebx, ecx, edx; int index_msb, core_bits; @@ -311,8 +311,8 @@ out: printk(KERN_INFO "CPU: Processor Core ID: %d\n", c->cpu_core_id); } -} #endif +} static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) { diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index bcb48ce05d2..8e630734e1f 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -141,7 +141,7 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) void __cpuinit detect_ht(struct cpuinfo_x86 *c) { -#ifdef CONFIG_SMP +#ifdef CONFIG_X86_HT u32 eax, ebx, ecx, edx; int index_msb, core_bits; -- cgit v1.2.3 From f0fc4aff1fa4db1c201593422dcbf85c9897ec4f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:00 -0700 Subject: x86: make header file the same in arch/x86/kernel/cpu/common_xx.c Make the files more similar in preparation to unification, no code changed. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 22 +++++++++++++++++++--- arch/x86/kernel/cpu/common_64.c | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 1f80ce07daa..6bbdbc24f2b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1,25 +1,41 @@ #include +#include +#include #include +#include +#include +#include +#include +#include #include #include -#include #include -#include -#include #include #include #include +#include #include #include #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include #include +#include #endif +#include +#include +#include +#include +#include +#include +#include +#include + #include "cpu.h" static struct cpu_dev *this_cpu __cpuinitdata; diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 8e630734e1f..5daec699acf 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -24,6 +24,7 @@ #include #include #include +#include #endif #include #include @@ -33,7 +34,6 @@ #include #include #include -#include #include "cpu.h" -- cgit v1.2.3 From 950ad7ff6ec17fc1b47abc95c5c74628eb1adf8b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:01 -0700 Subject: x86: same gdt_page with macro Move the 32-bit and 64-bit gdt_page definitions next to each other, separated with an #ifdef. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 17 +++++++++++++++++ arch/x86/kernel/cpu/common_64.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6bbdbc24f2b..e0ca51f4f2d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -40,6 +40,22 @@ static struct cpu_dev *this_cpu __cpuinitdata; +#ifdef CONFIG_X86_64 +/* We need valid kernel segments for data and code in long mode too + * IRET will check the segment types kkeil 2000/10/28 + * Also sysret mandates a special GDT layout + */ +/* The TLS descriptors are currently at a different place compared to i386. + Hopefully nobody expects them at a fixed place (Wine?) */ +DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { + [GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } }, + [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } }, + [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } }, + [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, + [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, + [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, +} }; +#else DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, @@ -74,6 +90,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, } }; +#endif EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); static int cachesize_override __cpuinitdata = -1; diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 5daec699acf..b4890504284 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -39,6 +39,7 @@ static struct cpu_dev *this_cpu __cpuinitdata; +#ifdef CONFIG_X86_64 /* We need valid kernel segments for data and code in long mode too * IRET will check the segment types kkeil 2000/10/28 * Also sysret mandates a special GDT layout @@ -53,6 +54,42 @@ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, } }; +#else +DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { + [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, + [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, + [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, + [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } }, + /* + * Segments used for calling PnP BIOS have byte granularity. + * They code segments and data segments have fixed 64k limits, + * the transfer segment sizes are set at run time. + */ + /* 32-bit code */ + [GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } }, + /* 16-bit code */ + [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } }, + /* 16-bit data */ + [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } }, + /* 16-bit data */ + [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } }, + /* 16-bit data */ + [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } }, + /* + * The APM segments have byte granularity and their bases + * are set at run time. All have 64k limits. + */ + /* 32-bit code */ + [GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } }, + /* 16-bit code */ + [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } }, + /* data */ + [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } }, + + [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, + [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, +} }; +#endif EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; -- cgit v1.2.3 From ba51dced0b55eb62874e1646d5eeff344c3d4e67 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:02 -0700 Subject: x86: cpu/common.c, let 64-bit code have 32-bit only functions No effect on 64-bit. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 8 +++ arch/x86/kernel/cpu/common_64.c | 111 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index e0ca51f4f2d..9128ba0c8d3 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -93,6 +93,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #endif EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); +#ifdef CONFIG_X86_32 static int cachesize_override __cpuinitdata = -1; static int disable_x86_serial_nr __cpuinitdata = 1; @@ -195,6 +196,13 @@ static int __init x86_serial_nr_setup(char *s) return 1; } __setup("serialnumber", x86_serial_nr_setup); +#else +/* Probe for the CPUID instruction */ +static inline int have_cpuid_p(void) +{ + return 1; +} +#endif __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index b4890504284..40c9d89cc14 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -92,6 +92,117 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #endif EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); +#ifdef CONFIG_X86_32 +static int cachesize_override __cpuinitdata = -1; +static int disable_x86_serial_nr __cpuinitdata = 1; + +static int __init cachesize_setup(char *str) +{ + get_option(&str, &cachesize_override); + return 1; +} +__setup("cachesize=", cachesize_setup); + +/* + * Naming convention should be: [()] + * This table only is used unless init_() below doesn't set it; + * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used + * + */ + +/* Look up CPU names by table lookup. */ +static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) +{ + struct cpu_model_info *info; + + if (c->x86_model >= 16) + return NULL; /* Range check */ + + if (!this_cpu) + return NULL; + + info = this_cpu->c_models; + + while (info && info->family) { + if (info->family == c->x86) + return info->model_names[c->x86_model]; + info++; + } + return NULL; /* Not found */ +} + +static int __init x86_fxsr_setup(char *s) +{ + setup_clear_cpu_cap(X86_FEATURE_FXSR); + setup_clear_cpu_cap(X86_FEATURE_XMM); + return 1; +} +__setup("nofxsr", x86_fxsr_setup); + +static int __init x86_sep_setup(char *s) +{ + setup_clear_cpu_cap(X86_FEATURE_SEP); + return 1; +} +__setup("nosep", x86_sep_setup); + +/* Standard macro to see if a specific flag is changeable */ +static inline int flag_is_changeable_p(u32 flag) +{ + u32 f1, f2; + + asm("pushfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "movl %0,%1\n\t" + "xorl %2,%0\n\t" + "pushl %0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "popfl\n\t" + : "=&r" (f1), "=&r" (f2) + : "ir" (flag)); + + return ((f1^f2) & flag) != 0; +} + +/* Probe for the CPUID instruction */ +static int __cpuinit have_cpuid_p(void) +{ + return flag_is_changeable_p(X86_EFLAGS_ID); +} + +static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +{ + if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) { + /* Disable processor serial number */ + unsigned long lo, hi; + rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi); + lo |= 0x200000; + wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi); + printk(KERN_NOTICE "CPU serial number disabled.\n"); + clear_cpu_cap(c, X86_FEATURE_PN); + + /* Disabling the serial number may affect the cpuid level */ + c->cpuid_level = cpuid_eax(0); + } +} + +static int __init x86_serial_nr_setup(char *s) +{ + disable_x86_serial_nr = 0; + return 1; +} +__setup("serialnumber", x86_serial_nr_setup); +#else +/* Probe for the CPUID instruction */ +static inline int have_cpuid_p(void) +{ + return 1; +} +#endif + __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; /* Current gdt points %fs at the "master" per-cpu area: after this, -- cgit v1.2.3 From d5494d4f517158b1d2eea1ae33f6c264eb12675f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:03 -0700 Subject: x86: cpu/common*.c, make 32-bit have 64-bit only functions Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 138 ++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/common_64.c | 12 ++++ 2 files changed, 150 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9128ba0c8d3..dcd3ebd5ba6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -750,6 +750,143 @@ __setup("clearcpuid=", setup_disablecpuid); cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; +#ifdef CONFIG_X86_64 +struct x8664_pda **_cpu_pda __read_mostly; +EXPORT_SYMBOL(_cpu_pda); + +struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; + +char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; + +unsigned long __supported_pte_mask __read_mostly = ~0UL; +EXPORT_SYMBOL_GPL(__supported_pte_mask); + +static int do_not_nx __cpuinitdata; + +/* noexec=on|off +Control non executable mappings for 64bit processes. + +on Enable(default) +off Disable +*/ +static int __init nonx_setup(char *str) +{ + if (!str) + return -EINVAL; + if (!strncmp(str, "on", 2)) { + __supported_pte_mask |= _PAGE_NX; + do_not_nx = 0; + } else if (!strncmp(str, "off", 3)) { + do_not_nx = 1; + __supported_pte_mask &= ~_PAGE_NX; + } + return 0; +} +early_param("noexec", nonx_setup); + +int force_personality32; + +/* noexec32=on|off +Control non executable heap for 32bit processes. +To control the stack too use noexec=off + +on PROT_READ does not imply PROT_EXEC for 32bit processes (default) +off PROT_READ implies PROT_EXEC +*/ +static int __init nonx32_setup(char *str) +{ + if (!strcmp(str, "on")) + force_personality32 &= ~READ_IMPLIES_EXEC; + else if (!strcmp(str, "off")) + force_personality32 |= READ_IMPLIES_EXEC; + return 1; +} +__setup("noexec32=", nonx32_setup); + +void pda_init(int cpu) +{ + struct x8664_pda *pda = cpu_pda(cpu); + + /* Setup up data that may be needed in __get_free_pages early */ + loadsegment(fs, 0); + loadsegment(gs, 0); + /* Memory clobbers used to order PDA accessed */ + mb(); + wrmsrl(MSR_GS_BASE, pda); + mb(); + + pda->cpunumber = cpu; + pda->irqcount = -1; + pda->kernelstack = (unsigned long)stack_thread_info() - + PDA_STACKOFFSET + THREAD_SIZE; + pda->active_mm = &init_mm; + pda->mmu_state = 0; + + if (cpu == 0) { + /* others are initialized in smpboot.c */ + pda->pcurrent = &init_task; + pda->irqstackptr = boot_cpu_stack; + pda->irqstackptr += IRQSTACKSIZE - 64; + } else { + if (!pda->irqstackptr) { + pda->irqstackptr = (char *) + __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); + if (!pda->irqstackptr) + panic("cannot allocate irqstack for cpu %d", + cpu); + pda->irqstackptr += IRQSTACKSIZE - 64; + } + + if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) + pda->nodenumber = cpu_to_node(cpu); + } +} + +char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + + DEBUG_STKSZ] __page_aligned_bss; + +extern asmlinkage void ignore_sysret(void); + +/* May not be marked __init: used by software suspend */ +void syscall_init(void) +{ + /* + * LSTAR and STAR live in a bit strange symbiosis. + * They both write to the same internal register. STAR allows to + * set CS/DS but only a 32bit target. LSTAR sets the 64bit rip. + */ + wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); + wrmsrl(MSR_LSTAR, system_call); + wrmsrl(MSR_CSTAR, ignore_sysret); + +#ifdef CONFIG_IA32_EMULATION + syscall32_cpu_init(); +#endif + + /* Flags to clear on syscall */ + wrmsrl(MSR_SYSCALL_MASK, + X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL); +} + +void __cpuinit check_efer(void) +{ + unsigned long efer; + + rdmsrl(MSR_EFER, efer); + if (!(efer & EFER_NX) || do_not_nx) + __supported_pte_mask &= ~_PAGE_NX; +} + +unsigned long kernel_eflags; + +/* + * Copies of the original ist values from the tss are only accessed during + * debugging, no special alignment required. + */ +DEFINE_PER_CPU(struct orig_ist, orig_ist); + +#else + /* Make sure %fs is initialized properly in idle threads */ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) { @@ -757,6 +894,7 @@ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) regs->fs = __KERNEL_PERCPU; return regs; } +#endif /* * cpu_init() initializes state that is per-CPU. Some data is already diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 40c9d89cc14..9f2a6ece82d 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -704,6 +704,7 @@ __setup("clearcpuid=", setup_disablecpuid); cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; +#ifdef CONFIG_X86_64 struct x8664_pda **_cpu_pda __read_mostly; EXPORT_SYMBOL(_cpu_pda); @@ -838,6 +839,17 @@ unsigned long kernel_eflags; */ DEFINE_PER_CPU(struct orig_ist, orig_ist); +#else + +/* Make sure %fs is initialized properly in idle threads */ +struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) +{ + memset(regs, 0, sizeof(struct pt_regs)); + regs->fs = __KERNEL_PERCPU; + return regs; +} +#endif + /* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT -- cgit v1.2.3 From 1ba76586f778be327e452180d8378e40ee70f066 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:04 -0700 Subject: x86: cpu/common*.c have same cpu_init(), with copying and #ifdef hard to merge by lines... (as here we have material differences between 32-bit and 64-bit mode) - will try to do it later. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 124 ++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/common_64.c | 88 +++++++++++++++++++++++++++- 2 files changed, 211 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index dcd3ebd5ba6..f44678db161 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -901,7 +901,129 @@ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) * initialized (naturally) in the bootstrap process, such as the GDT * and IDT. We reload them nevertheless, this function acts as a * 'CPU state barrier', nothing should get across. + * A lot of state is already set up in PDA init for 64 bit */ +#ifdef CONFIG_X86_64 +void __cpuinit cpu_init(void) +{ + int cpu = stack_smp_processor_id(); + struct tss_struct *t = &per_cpu(init_tss, cpu); + struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu); + unsigned long v; + char *estacks = NULL; + struct task_struct *me; + int i; + + /* CPU 0 is initialised in head64.c */ + if (cpu != 0) + pda_init(cpu); + else + estacks = boot_exception_stacks; + + me = current; + + if (cpu_test_and_set(cpu, cpu_initialized)) + panic("CPU#%d already initialized!\n", cpu); + + printk(KERN_INFO "Initializing CPU#%d\n", cpu); + + clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); + + /* + * Initialize the per-CPU GDT with the boot GDT, + * and set up the GDT descriptor: + */ + + switch_to_new_gdt(); + load_idt((const struct desc_ptr *)&idt_descr); + + memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); + syscall_init(); + + wrmsrl(MSR_FS_BASE, 0); + wrmsrl(MSR_KERNEL_GS_BASE, 0); + barrier(); + + check_efer(); + if (cpu != 0 && x2apic) + enable_x2apic(); + + /* + * set up and load the per-CPU TSS + */ + if (!orig_ist->ist[0]) { + static const unsigned int order[N_EXCEPTION_STACKS] = { + [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, + [DEBUG_STACK - 1] = DEBUG_STACK_ORDER + }; + for (v = 0; v < N_EXCEPTION_STACKS; v++) { + if (cpu) { + estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); + if (!estacks) + panic("Cannot allocate exception " + "stack %ld %d\n", v, cpu); + } + estacks += PAGE_SIZE << order[v]; + orig_ist->ist[v] = t->x86_tss.ist[v] = + (unsigned long)estacks; + } + } + + t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); + /* + * <= is required because the CPU will access up to + * 8 bits beyond the end of the IO permission bitmap. + */ + for (i = 0; i <= IO_BITMAP_LONGS; i++) + t->io_bitmap[i] = ~0UL; + + atomic_inc(&init_mm.mm_count); + me->active_mm = &init_mm; + if (me->mm) + BUG(); + enter_lazy_tlb(&init_mm, me); + + load_sp0(t, ¤t->thread); + set_tss_desc(cpu, t); + load_TR_desc(); + load_LDT(&init_mm.context); + +#ifdef CONFIG_KGDB + /* + * If the kgdb is connected no debug regs should be altered. This + * is only applicable when KGDB and a KGDB I/O module are built + * into the kernel and you are using early debugging with + * kgdbwait. KGDB will control the kernel HW breakpoint registers. + */ + if (kgdb_connected && arch_kgdb_ops.correct_hw_break) + arch_kgdb_ops.correct_hw_break(); + else { +#endif + /* + * Clear all 6 debug registers: + */ + + set_debugreg(0UL, 0); + set_debugreg(0UL, 1); + set_debugreg(0UL, 2); + set_debugreg(0UL, 3); + set_debugreg(0UL, 6); + set_debugreg(0UL, 7); +#ifdef CONFIG_KGDB + /* If the kgdb is connected no debug regs should be altered. */ + } +#endif + + fpu_init(); + + raw_local_save_flags(kernel_eflags); + + if (is_uv_system()) + uv_cpu_init(); +} + +#else + void __cpuinit cpu_init(void) { int cpu = smp_processor_id(); @@ -982,3 +1104,5 @@ void __cpuinit cpu_uninit(void) per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; } #endif + +#endif diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 9f2a6ece82d..2bd0ed5abb0 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -855,8 +855,9 @@ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) * initialized (naturally) in the bootstrap process, such as the GDT * and IDT. We reload them nevertheless, this function acts as a * 'CPU state barrier', nothing should get across. - * A lot of state is already set up in PDA init. + * A lot of state is already set up in PDA init for 64 bit */ +#ifdef CONFIG_X86_64 void __cpuinit cpu_init(void) { int cpu = stack_smp_processor_id(); @@ -974,3 +975,88 @@ void __cpuinit cpu_init(void) if (is_uv_system()) uv_cpu_init(); } + +#else + +void __cpuinit cpu_init(void) +{ + int cpu = smp_processor_id(); + struct task_struct *curr = current; + struct tss_struct *t = &per_cpu(init_tss, cpu); + struct thread_struct *thread = &curr->thread; + + if (cpu_test_and_set(cpu, cpu_initialized)) { + printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); + for (;;) local_irq_enable(); + } + + printk(KERN_INFO "Initializing CPU#%d\n", cpu); + + if (cpu_has_vme || cpu_has_tsc || cpu_has_de) + clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); + + load_idt(&idt_descr); + switch_to_new_gdt(); + + /* + * Set up and load the per-CPU TSS and LDT + */ + atomic_inc(&init_mm.mm_count); + curr->active_mm = &init_mm; + if (curr->mm) + BUG(); + enter_lazy_tlb(&init_mm, curr); + + load_sp0(t, thread); + set_tss_desc(cpu, t); + load_TR_desc(); + load_LDT(&init_mm.context); + +#ifdef CONFIG_DOUBLEFAULT + /* Set up doublefault TSS pointer in the GDT */ + __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); +#endif + + /* Clear %gs. */ + asm volatile ("mov %0, %%gs" : : "r" (0)); + + /* Clear all 6 debug registers: */ + set_debugreg(0, 0); + set_debugreg(0, 1); + set_debugreg(0, 2); + set_debugreg(0, 3); + set_debugreg(0, 6); + set_debugreg(0, 7); + + /* + * Force FPU initialization: + */ + if (cpu_has_xsave) + current_thread_info()->status = TS_XSAVE; + else + current_thread_info()->status = 0; + clear_used_math(); + mxcsr_feature_mask_init(); + + /* + * Boot processor to setup the FP and extended state context info. + */ + if (!smp_processor_id()) + init_thread_xstate(); + + xsave_init(); +} + +#ifdef CONFIG_HOTPLUG_CPU +void __cpuinit cpu_uninit(void) +{ + int cpu = raw_smp_processor_id(); + cpu_clear(cpu, cpu_initialized); + + /* lazy TLB state */ + per_cpu(cpu_tlbstate, cpu).state = 0; + per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; +} +#endif + +#endif -- cgit v1.2.3 From fab334c1d5f24d23d12f98ad652d399279cd03ce Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:05 -0700 Subject: x86: cpu/common*.c, merge switch_to_new_gdt() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 2 ++ arch/x86/kernel/cpu/common_64.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f44678db161..43d5287bb2a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -215,7 +215,9 @@ void switch_to_new_gdt(void) gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); +#ifdef CONFIG_X86_32 asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); +#endif } static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 2bd0ed5abb0..d7b996518f8 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -214,6 +214,9 @@ void switch_to_new_gdt(void) gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); +#ifdef CONFIG_X86_32 + asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); +#endif } static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; -- cgit v1.2.3 From b9e67f00424e164dcd29391eb48dc941db8691ad Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:06 -0700 Subject: x86: cpu/common.c, merge default_init() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 4 ++++ arch/x86/kernel/cpu/common_64.c | 12 ++++++++++++ 2 files changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 43d5287bb2a..2c4bfa2e56a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -224,6 +224,9 @@ static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; static void __cpuinit default_init(struct cpuinfo_x86 *c) { +#ifdef CONFIG_X86_64 + display_cacheinfo(c); +#else /* Not much we can do here... */ /* Check if at least it has cpuid */ if (c->cpuid_level == -1) { @@ -233,6 +236,7 @@ static void __cpuinit default_init(struct cpuinfo_x86 *c) else if (c->x86 == 3) strcpy(c->x86_model_id, "386"); } +#endif } static struct cpu_dev __cpuinitdata default_cpu = { diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index d7b996518f8..2fda1097481 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -223,7 +223,19 @@ static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; static void __cpuinit default_init(struct cpuinfo_x86 *c) { +#ifdef CONFIG_X86_64 display_cacheinfo(c); +#else + /* Not much we can do here... */ + /* Check if at least it has cpuid */ + if (c->cpuid_level == -1) { + /* No cpuid. It must be an ancient CPU */ + if (c->x86 == 4) + strcpy(c->x86_model_id, "486"); + else if (c->x86 == 3) + strcpy(c->x86_model_id, "386"); + } +#endif } static struct cpu_dev __cpuinitdata default_cpu = { -- cgit v1.2.3 From 140fc72709278989f08eb756d16a70008bdcc409 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:07 -0700 Subject: x86: cpu/common*.c, merge display_cacheinfo() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 8 ++++++++ arch/x86/kernel/cpu/common_64.c | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 2c4bfa2e56a..f9191207718 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -285,6 +285,10 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); c->x86_cache_size = (ecx>>24) + (edx>>24); +#ifdef CONFIG_X86_64 + /* On K8 L1 TLB is inclusive, so don't count it */ + c->x86_tlbsize = 0; +#endif } if (n < 0x80000006) /* Some chips just has a large L1. */ @@ -293,6 +297,9 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); l2size = ecx >> 16; +#ifdef CONFIG_X86_64 + c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); +#else /* do processor-specific cache resizing */ if (this_cpu->c_size_cache) l2size = this_cpu->c_size_cache(c, l2size); @@ -303,6 +310,7 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) if (l2size == 0) return; /* Again, no L2 cache is possible */ +#endif c->x86_cache_size = l2size; diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 2fda1097481..f7a2d524b1e 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -285,8 +285,10 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); c->x86_cache_size = (ecx>>24) + (edx>>24); +#ifdef CONFIG_X86_64 /* On K8 L1 TLB is inclusive, so don't count it */ c->x86_tlbsize = 0; +#endif } if (n < 0x80000006) /* Some chips just has a large L1. */ @@ -294,7 +296,22 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); l2size = ecx >> 16; + +#ifdef CONFIG_X86_64 c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); +#else + + /* do processor-specific cache resizing */ + if (this_cpu->c_size_cache) + l2size = this_cpu->c_size_cache(c, l2size); + + /* Allow user to override all this if necessary. */ + if (cachesize_override != -1) + l2size = cachesize_override; + + if (l2size == 0) + return; /* Again, no L2 cache is possible */ +#endif c->x86_cache_size = l2size; -- cgit v1.2.3 From 1cd78776c7d5487e3000426d0ce1ff203c5d60cd Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:08 -0700 Subject: x86: cpu/common*.c, merge detect_ht() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 13 ++++++++++++- arch/x86/kernel/cpu/common_64.c | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f9191207718..b2018f76c94 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -330,6 +330,9 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) goto out; + if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) + return; + cpuid(1, &eax, &ebx, &ecx, &edx); smp_num_siblings = (ebx & 0xff0000) >> 16; @@ -346,8 +349,11 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) } index_msb = get_count_order(smp_num_siblings); +#ifdef CONFIG_X86_64 + c->phys_proc_id = phys_pkg_id(index_msb); +#else c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); - +#endif smp_num_siblings = smp_num_siblings / c->x86_max_cores; @@ -355,8 +361,13 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) core_bits = get_count_order(c->x86_max_cores); +#ifdef CONFIG_X86_64 + c->cpu_core_id = phys_pkg_id(index_msb) & + ((1 << core_bits) - 1); +#else c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & ((1 << core_bits) - 1); +#endif } out: diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index f7a2d524b1e..7ac0a00743c 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -349,7 +349,11 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) } index_msb = get_count_order(smp_num_siblings); +#ifdef CONFIG_X86_64 c->phys_proc_id = phys_pkg_id(index_msb); +#else + c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); +#endif smp_num_siblings = smp_num_siblings / c->x86_max_cores; @@ -357,8 +361,13 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) core_bits = get_count_order(c->x86_max_cores); +#ifdef CONFIG_X86_64 c->cpu_core_id = phys_pkg_id(index_msb) & ((1 << core_bits) - 1); +#else + c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & + ((1 << core_bits) - 1); +#endif } out: -- cgit v1.2.3 From 5122c890ba969e6efeaba9ed45f5936e62d3c6d5 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:09 -0700 Subject: x86: cpu/common.c: merge get_cpu_cap() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 20 ++++++++++++++++++++ arch/x86/kernel/cpu/common_64.c | 2 ++ 2 files changed, 22 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b2018f76c94..ffc2f5ed09a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -458,6 +458,26 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) c->x86_capability[6] = cpuid_ecx(0x80000001); } } + +#ifdef CONFIG_X86_64 + /* Transmeta-defined flags: level 0x80860001 */ + xlvl = cpuid_eax(0x80860000); + if ((xlvl & 0xffff0000) == 0x80860000) { + /* Don't set x86_cpuid_level here for now to not confuse. */ + if (xlvl >= 0x80860001) + c->x86_capability[2] = cpuid_edx(0x80860001); + } + + if (c->extended_cpuid_level >= 0x80000007) + c->x86_power = cpuid_edx(0x80000007); + + if (c->extended_cpuid_level >= 0x80000008) { + u32 eax = cpuid_eax(0x80000008); + + c->x86_virt_bits = (eax >> 8) & 0xff; + c->x86_phys_bits = eax & 0xff; + } +#endif } /* * Do minimum CPU detection early. diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 7ac0a00743c..75bb7ff99ee 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -461,6 +461,7 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) } } +#ifdef CONFIG_X86_64 /* Transmeta-defined flags: level 0x80860001 */ xlvl = cpuid_eax(0x80860000); if ((xlvl & 0xffff0000) == 0x80860000) { @@ -478,6 +479,7 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) c->x86_virt_bits = (eax >> 8) & 0xff; c->x86_phys_bits = eax & 0xff; } +#endif } /* Do some early cpuid on the boot CPU to get some parameter that are -- cgit v1.2.3 From 6627d2423067f2c6eedb422a59fba9270a3c5e36 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:10 -0700 Subject: x86: cpu/common*.c, merge early_identify_cpu() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 4 ++++ arch/x86/kernel/cpu/common_64.c | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index ffc2f5ed09a..61a70748213 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -490,7 +490,11 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) */ static void __init early_identify_cpu(struct cpuinfo_x86 *c) { +#ifdef CONFIG_X86_64 + c->x86_clflush_size = 64; +#else c->x86_clflush_size = 32; +#endif c->x86_cache_alignment = c->x86_clflush_size; if (!have_cpuid_p()) diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 75bb7ff99ee..6475548d64e 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -482,15 +482,28 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) #endif } -/* Do some early cpuid on the boot CPU to get some parameter that are - needed before check_bugs. Everything advanced is in identify_cpu - below. */ +/* + * Do minimum CPU detection early. + * Fields really needed: vendor, cpuid_level, family, model, mask, + * cache alignment. + * The others are not touched to avoid unwanted side effects. + * + * WARNING: this function is only called on the BP. Don't add code here + * that is supposed to run on all CPUs. + */ static void __init early_identify_cpu(struct cpuinfo_x86 *c) { +#ifdef CONFIG_X86_64 c->x86_clflush_size = 64; +#else + c->x86_clflush_size = 32; +#endif c->x86_cache_alignment = c->x86_clflush_size; + if (!have_cpuid_p()) + return; + memset(&c->x86_capability, 0, sizeof c->x86_capability); c->extended_cpuid_level = 0; -- cgit v1.2.3 From 56f0d033be2ebb983993e5d7f24ae232c9a1e7f9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:11 -0700 Subject: x86: cpu/common*.c: merge print_cpu_info() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 6475548d64e..68b06a39dca 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -730,8 +730,20 @@ __setup("noclflush", setup_noclflush); void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) { + char *vendor = NULL; + + if (c->x86_vendor < X86_VENDOR_NUM) + vendor = this_cpu->c_vendor; + else if (c->cpuid_level >= 0) + vendor = c->x86_vendor_id; + + if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor))) + printk(KERN_CONT "%s ", vendor); + if (c->x86_model_id[0]) printk(KERN_CONT "%s", c->x86_model_id); + else + printk(KERN_CONT "%d86", c->x86); if (c->x86_mask || c->cpuid_level >= 0) printk(KERN_CONT " stepping %02x\n", c->x86_mask); -- cgit v1.2.3 From b89d3b3e2caeab3d895301d1aee3cd2a91eddb79 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:12 -0700 Subject: x86: cpu/common*.c, merge generic_identify() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 15 ++++++++++++--- arch/x86/kernel/cpu/common_64.c | 19 ++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 61a70748213..f35baa7f303 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -548,6 +548,10 @@ void __init early_cpu_init(void) * of early VIA chips and (more importantly) broken virtualizers that * are not easy to detect. Hence, probe for it based on first * principles. + * + * Note: no 64-bit chip is known to lack these, but put the code here + * for consistency with 32 bits, and to make it utterly trivial to + * diagnose the problem should it ever surface. */ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) { @@ -586,11 +590,16 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) if (c->cpuid_level >= 0x00000001) { c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF; -#ifdef CONFIG_X86_HT +#ifdef CONFIG_X86_32 +# ifdef CONFIG_X86_HT c->apicid = phys_pkg_id(c->initial_apicid, 0); - c->phys_proc_id = c->initial_apicid; -#else +# else c->apicid = c->initial_apicid; +# endif +#endif + +#ifdef CONFIG_X86_HT + c->phys_proc_id = c->initial_apicid; #endif } diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 68b06a39dca..869a6ff9f7d 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -581,6 +581,9 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) static void __cpuinit generic_identify(struct cpuinfo_x86 *c) { + if (!have_cpuid_p()) + return; + c->extended_cpuid_level = 0; cpu_detect(c); @@ -589,11 +592,21 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) get_cpu_cap(c); - c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff; -#ifdef CONFIG_SMP - c->phys_proc_id = c->initial_apicid; + if (c->cpuid_level >= 0x00000001) { + c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF; +#ifdef CONFIG_X86_32 +# ifdef CONFIG_X86_HT + c->apicid = phys_pkg_id(c->initial_apicid, 0); +# else + c->apicid = c->initial_apicid; +# endif #endif +#ifdef CONFIG_X86_HT + c->phys_proc_id = c->initial_apicid; +#endif + } + if (c->extended_cpuid_level >= 0x80000004) get_model_name(c); /* Default name */ -- cgit v1.2.3 From 102bbe3ab83c7ac04461d277df23cd5acdb49892 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:13 -0700 Subject: x86: cpu/common*.c, merge identify_cpu() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 89 ++++++++++++++++++++---------- arch/x86/kernel/cpu/common_64.c | 116 ++++++++++++++++++++++++++++++---------- 2 files changed, 147 insertions(+), 58 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f35baa7f303..eef868c97b8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -104,34 +104,6 @@ static int __init cachesize_setup(char *str) } __setup("cachesize=", cachesize_setup); -/* - * Naming convention should be: [()] - * This table only is used unless init_() below doesn't set it; - * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used - * - */ - -/* Look up CPU names by table lookup. */ -static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) -{ - struct cpu_model_info *info; - - if (c->x86_model >= 16) - return NULL; /* Range check */ - - if (!this_cpu) - return NULL; - - info = this_cpu->c_models; - - while (info && info->family) { - if (info->family == c->x86) - return info->model_names[c->x86_model]; - info++; - } - return NULL; /* Not found */ -} - static int __init x86_fxsr_setup(char *s) { setup_clear_cpu_cap(X86_FEATURE_FXSR); @@ -197,13 +169,48 @@ static int __init x86_serial_nr_setup(char *s) } __setup("serialnumber", x86_serial_nr_setup); #else +static inline int flag_is_changeable_p(u32 flag) +{ + return 1; +} /* Probe for the CPUID instruction */ static inline int have_cpuid_p(void) { return 1; } +static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +{ +} #endif +/* + * Naming convention should be: [()] + * This table only is used unless init_() below doesn't set it; + * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used + * + */ + +/* Look up CPU names by table lookup. */ +static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) +{ + struct cpu_model_info *info; + + if (c->x86_model >= 16) + return NULL; /* Range check */ + + if (!this_cpu) + return NULL; + + info = this_cpu->c_models; + + while (info && info->family) { + if (info->family == c->x86) + return info->model_names[c->x86_model]; + info++; + } + return NULL; /* Not found */ +} + __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; /* Current gdt points %fs at the "master" per-cpu area: after this, @@ -620,12 +627,18 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->loops_per_jiffy = loops_per_jiffy; c->x86_cache_size = -1; c->x86_vendor = X86_VENDOR_UNKNOWN; - c->cpuid_level = -1; /* CPUID not detected */ c->x86_model = c->x86_mask = 0; /* So far unknown... */ c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */ c->x86_max_cores = 1; +#ifdef CONFIG_X86_64 + c->x86_coreid_bits = 0; + c->x86_clflush_size = 64; +#else + c->cpuid_level = -1; /* CPUID not detected */ c->x86_clflush_size = 32; +#endif + c->x86_cache_alignment = c->x86_clflush_size; memset(&c->x86_capability, 0, sizeof c->x86_capability); if (!have_cpuid_p()) { @@ -644,6 +657,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) if (this_cpu->c_identify) this_cpu->c_identify(c); +#ifdef CONFIG_X86_64 + c->apicid = phys_pkg_id(0); +#endif + /* * Vendor-specific initialization. In this section we * canonicalize the feature flags, meaning if there are @@ -677,6 +694,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86, c->x86_model); } +#ifdef CONFIG_X86_64 + detect_ht(c); +#endif + /* * On SMP, boot_cpu_data holds the common feature set between * all CPUs; so make sure that we indicate which features are @@ -693,24 +714,34 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) for (i = 0; i < NCAPINTS; i++) c->x86_capability[i] &= ~cleared_cpu_caps[i]; +#ifdef CONFIG_X86_MCE /* Init Machine Check Exception if available. */ mcheck_init(c); +#endif select_idle_routine(c); + +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) + numa_add_cpu(smp_processor_id()); +#endif } void __init identify_boot_cpu(void) { identify_cpu(&boot_cpu_data); +#ifdef CONFIG_X86_32 sysenter_setup(); enable_sep_cpu(); +#endif } void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) { BUG_ON(c == &boot_cpu_data); identify_cpu(c); +#ifdef CONFIG_X86_32 enable_sep_cpu(); +#endif mtrr_ap_init(); } diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 869a6ff9f7d..6a42371a609 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -103,34 +103,6 @@ static int __init cachesize_setup(char *str) } __setup("cachesize=", cachesize_setup); -/* - * Naming convention should be: [()] - * This table only is used unless init_() below doesn't set it; - * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used - * - */ - -/* Look up CPU names by table lookup. */ -static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) -{ - struct cpu_model_info *info; - - if (c->x86_model >= 16) - return NULL; /* Range check */ - - if (!this_cpu) - return NULL; - - info = this_cpu->c_models; - - while (info && info->family) { - if (info->family == c->x86) - return info->model_names[c->x86_model]; - info++; - } - return NULL; /* Not found */ -} - static int __init x86_fxsr_setup(char *s) { setup_clear_cpu_cap(X86_FEATURE_FXSR); @@ -196,13 +168,48 @@ static int __init x86_serial_nr_setup(char *s) } __setup("serialnumber", x86_serial_nr_setup); #else +static inline int flag_is_changeable_p(u32 flag) +{ + return 1; +} /* Probe for the CPUID instruction */ static inline int have_cpuid_p(void) { return 1; } +static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +{ +} #endif +/* + * Naming convention should be: [()] + * This table only is used unless init_() below doesn't set it; + * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used + * + */ + +/* Look up CPU names by table lookup. */ +static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) +{ + struct cpu_model_info *info; + + if (c->x86_model >= 16) + return NULL; /* Range check */ + + if (!this_cpu) + return NULL; + + info = this_cpu->c_models; + + while (info && info->family) { + if (info->family == c->x86) + return info->model_names[c->x86_model]; + info++; + } + return NULL; /* Not found */ +} + __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; /* Current gdt points %fs at the "master" per-cpu area: after this, @@ -628,14 +635,35 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */ c->x86_max_cores = 1; +#ifdef CONFIG_X86_64 c->x86_coreid_bits = 0; c->x86_clflush_size = 64; +#else + c->cpuid_level = -1; /* CPUID not detected */ + c->x86_clflush_size = 32; +#endif c->x86_cache_alignment = c->x86_clflush_size; memset(&c->x86_capability, 0, sizeof c->x86_capability); + if (!have_cpuid_p()) { + /* + * First of all, decide if this is a 486 or higher + * It's a 486 if we can modify the AC flag + */ + if (flag_is_changeable_p(X86_EFLAGS_AC)) + c->x86 = 4; + else + c->x86 = 3; + } + generic_identify(c); + if (this_cpu->c_identify) + this_cpu->c_identify(c); + +#ifdef CONFIG_X86_64 c->apicid = phys_pkg_id(0); +#endif /* * Vendor-specific initialization. In this section we @@ -650,7 +678,29 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) if (this_cpu->c_init) this_cpu->c_init(c); + /* Disable the PN if appropriate */ + squash_the_stupid_serial_number(c); + + /* + * The vendor-specific functions might have changed features. Now + * we do "generic changes." + */ + + /* If the model name is still unset, do table lookup. */ + if (!c->x86_model_id[0]) { + char *p; + p = table_lookup_model(c); + if (p) + strcpy(c->x86_model_id, p); + else + /* Last resort... */ + sprintf(c->x86_model_id, "%02x/%02x", + c->x86, c->x86_model); + } + +#ifdef CONFIG_X86_64 detect_ht(c); +#endif /* * On SMP, boot_cpu_data holds the common feature set between @@ -669,11 +719,12 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86_capability[i] &= ~cleared_cpu_caps[i]; #ifdef CONFIG_X86_MCE + /* Init Machine Check Exception if available. */ mcheck_init(c); #endif select_idle_routine(c); -#ifdef CONFIG_NUMA +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) numa_add_cpu(smp_processor_id()); #endif @@ -682,12 +733,19 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) void __init identify_boot_cpu(void) { identify_cpu(&boot_cpu_data); +#ifdef CONFIG_X86_32 + sysenter_setup(); + enable_sep_cpu(); +#endif } void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) { BUG_ON(c == &boot_cpu_data); identify_cpu(c); +#ifdef CONFIG_X86_32 + enable_sep_cpu(); +#endif mtrr_ap_init(); } -- cgit v1.2.3 From 143b604a2d07ff69cc2bc02ecd9395b28e0b5292 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 5 Sep 2008 09:37:15 +0200 Subject: x86: cpu/common*.c, merge whitespaces Merge leftover whitespaces, to make arch/x86/kernel/cpu/common_64.c exactly identical to arch/x86/kernel/cpu/common.c. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 6a42371a609..eef868c97b8 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -26,6 +26,7 @@ #include #include #endif + #include #include #include @@ -280,7 +281,6 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c) return 1; } - void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) { unsigned int n, dummy, ebx, ecx, edx, l2size; @@ -307,7 +307,6 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_64 c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); #else - /* do processor-specific cache resizing */ if (this_cpu->c_size_cache) l2size = this_cpu->c_size_cache(c, l2size); @@ -334,6 +333,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) if (!cpu_has(c, X86_FEATURE_HT)) return; + if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) goto out; @@ -443,7 +443,6 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c) } } - static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) { u32 tfms, xlvl; @@ -452,7 +451,6 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { u32 capability, excap; - cpuid(0x00000001, &tfms, &ebx, &excap, &capability); c->x86_capability[0] = capability; c->x86_capability[4] = excap; @@ -488,7 +486,6 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) } #endif } - /* * Do minimum CPU detection early. * Fields really needed: vendor, cpuid_level, family, model, mask, @@ -500,7 +497,6 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) */ static void __init early_identify_cpu(struct cpuinfo_x86 *c) { - #ifdef CONFIG_X86_64 c->x86_clflush_size = 64; #else @@ -722,12 +718,12 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* Init Machine Check Exception if available. */ mcheck_init(c); #endif + select_idle_routine(c); #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) numa_add_cpu(smp_processor_id()); #endif - } void __init identify_boot_cpu(void) -- cgit v1.2.3 From f5017cfa3591d8eaf5c792e40ff30f18e498b68c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 20:09:14 -0700 Subject: x86: use cpu/common.c on 64 bit Use cpu/common.c on both 64-bit and 32-bit and remove cpu/common_64.c. We started out with this linecount: 816 arch/x86/kernel/cpu/common_64.c 805 arch/x86/kernel/cpu/common.c and the resulting common.c is 1197 lines long, so there's already 424 lines of code eliminated in this phase of the unification. Signed-off-by: Yinghai Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/Makefile | 6 +- arch/x86/kernel/cpu/common_64.c | 1197 --------------------------------------- 2 files changed, 3 insertions(+), 1200 deletions(-) delete mode 100644 arch/x86/kernel/cpu/common_64.c (limited to 'arch') diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 403e689df0b..d031f248dfc 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -3,10 +3,10 @@ # obj-y := intel_cacheinfo.o addon_cpuid_features.o -obj-y += proc.o capflags.o powerflags.o +obj-y += proc.o capflags.o powerflags.o common.o -obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o -obj-$(CONFIG_X86_64) += common_64.o bugs_64.o +obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o +obj-$(CONFIG_X86_64) += bugs_64.o obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c deleted file mode 100644 index eef868c97b8..00000000000 --- a/arch/x86/kernel/cpu/common_64.c +++ /dev/null @@ -1,1197 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_X86_LOCAL_APIC -#include -#include -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cpu.h" - -static struct cpu_dev *this_cpu __cpuinitdata; - -#ifdef CONFIG_X86_64 -/* We need valid kernel segments for data and code in long mode too - * IRET will check the segment types kkeil 2000/10/28 - * Also sysret mandates a special GDT layout - */ -/* The TLS descriptors are currently at a different place compared to i386. - Hopefully nobody expects them at a fixed place (Wine?) */ -DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { - [GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } }, - [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } }, - [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } }, - [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, - [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, - [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, -} }; -#else -DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { - [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, - [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, - [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, - [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } }, - /* - * Segments used for calling PnP BIOS have byte granularity. - * They code segments and data segments have fixed 64k limits, - * the transfer segment sizes are set at run time. - */ - /* 32-bit code */ - [GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } }, - /* 16-bit code */ - [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } }, - /* 16-bit data */ - [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } }, - /* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } }, - /* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } }, - /* - * The APM segments have byte granularity and their bases - * are set at run time. All have 64k limits. - */ - /* 32-bit code */ - [GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } }, - /* 16-bit code */ - [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } }, - /* data */ - [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } }, - - [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, - [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, -} }; -#endif -EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); - -#ifdef CONFIG_X86_32 -static int cachesize_override __cpuinitdata = -1; -static int disable_x86_serial_nr __cpuinitdata = 1; - -static int __init cachesize_setup(char *str) -{ - get_option(&str, &cachesize_override); - return 1; -} -__setup("cachesize=", cachesize_setup); - -static int __init x86_fxsr_setup(char *s) -{ - setup_clear_cpu_cap(X86_FEATURE_FXSR); - setup_clear_cpu_cap(X86_FEATURE_XMM); - return 1; -} -__setup("nofxsr", x86_fxsr_setup); - -static int __init x86_sep_setup(char *s) -{ - setup_clear_cpu_cap(X86_FEATURE_SEP); - return 1; -} -__setup("nosep", x86_sep_setup); - -/* Standard macro to see if a specific flag is changeable */ -static inline int flag_is_changeable_p(u32 flag) -{ - u32 f1, f2; - - asm("pushfl\n\t" - "pushfl\n\t" - "popl %0\n\t" - "movl %0,%1\n\t" - "xorl %2,%0\n\t" - "pushl %0\n\t" - "popfl\n\t" - "pushfl\n\t" - "popl %0\n\t" - "popfl\n\t" - : "=&r" (f1), "=&r" (f2) - : "ir" (flag)); - - return ((f1^f2) & flag) != 0; -} - -/* Probe for the CPUID instruction */ -static int __cpuinit have_cpuid_p(void) -{ - return flag_is_changeable_p(X86_EFLAGS_ID); -} - -static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) -{ - if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) { - /* Disable processor serial number */ - unsigned long lo, hi; - rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi); - lo |= 0x200000; - wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi); - printk(KERN_NOTICE "CPU serial number disabled.\n"); - clear_cpu_cap(c, X86_FEATURE_PN); - - /* Disabling the serial number may affect the cpuid level */ - c->cpuid_level = cpuid_eax(0); - } -} - -static int __init x86_serial_nr_setup(char *s) -{ - disable_x86_serial_nr = 0; - return 1; -} -__setup("serialnumber", x86_serial_nr_setup); -#else -static inline int flag_is_changeable_p(u32 flag) -{ - return 1; -} -/* Probe for the CPUID instruction */ -static inline int have_cpuid_p(void) -{ - return 1; -} -static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) -{ -} -#endif - -/* - * Naming convention should be: [()] - * This table only is used unless init_() below doesn't set it; - * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used - * - */ - -/* Look up CPU names by table lookup. */ -static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) -{ - struct cpu_model_info *info; - - if (c->x86_model >= 16) - return NULL; /* Range check */ - - if (!this_cpu) - return NULL; - - info = this_cpu->c_models; - - while (info && info->family) { - if (info->family == c->x86) - return info->model_names[c->x86_model]; - info++; - } - return NULL; /* Not found */ -} - -__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; - -/* Current gdt points %fs at the "master" per-cpu area: after this, - * it's on the real one. */ -void switch_to_new_gdt(void) -{ - struct desc_ptr gdt_descr; - - gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); - gdt_descr.size = GDT_SIZE - 1; - load_gdt(&gdt_descr); -#ifdef CONFIG_X86_32 - asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); -#endif -} - -static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; - -static void __cpuinit default_init(struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_X86_64 - display_cacheinfo(c); -#else - /* Not much we can do here... */ - /* Check if at least it has cpuid */ - if (c->cpuid_level == -1) { - /* No cpuid. It must be an ancient CPU */ - if (c->x86 == 4) - strcpy(c->x86_model_id, "486"); - else if (c->x86 == 3) - strcpy(c->x86_model_id, "386"); - } -#endif -} - -static struct cpu_dev __cpuinitdata default_cpu = { - .c_init = default_init, - .c_vendor = "Unknown", - .c_x86_vendor = X86_VENDOR_UNKNOWN, -}; - -int __cpuinit get_model_name(struct cpuinfo_x86 *c) -{ - unsigned int *v; - char *p, *q; - - if (c->extended_cpuid_level < 0x80000004) - return 0; - - v = (unsigned int *) c->x86_model_id; - cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); - cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); - cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); - c->x86_model_id[48] = 0; - - /* Intel chips right-justify this string for some dumb reason; - undo that brain damage */ - p = q = &c->x86_model_id[0]; - while (*p == ' ') - p++; - if (p != q) { - while (*p) - *q++ = *p++; - while (q <= &c->x86_model_id[48]) - *q++ = '\0'; /* Zero-pad the rest */ - } - - return 1; -} - -void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) -{ - unsigned int n, dummy, ebx, ecx, edx, l2size; - - n = c->extended_cpuid_level; - - if (n >= 0x80000005) { - cpuid(0x80000005, &dummy, &ebx, &ecx, &edx); - printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", - edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); - c->x86_cache_size = (ecx>>24) + (edx>>24); -#ifdef CONFIG_X86_64 - /* On K8 L1 TLB is inclusive, so don't count it */ - c->x86_tlbsize = 0; -#endif - } - - if (n < 0x80000006) /* Some chips just has a large L1. */ - return; - - cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); - l2size = ecx >> 16; - -#ifdef CONFIG_X86_64 - c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); -#else - /* do processor-specific cache resizing */ - if (this_cpu->c_size_cache) - l2size = this_cpu->c_size_cache(c, l2size); - - /* Allow user to override all this if necessary. */ - if (cachesize_override != -1) - l2size = cachesize_override; - - if (l2size == 0) - return; /* Again, no L2 cache is possible */ -#endif - - c->x86_cache_size = l2size; - - printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", - l2size, ecx & 0xFF); -} - -void __cpuinit detect_ht(struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_X86_HT - u32 eax, ebx, ecx, edx; - int index_msb, core_bits; - - if (!cpu_has(c, X86_FEATURE_HT)) - return; - - if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) - goto out; - - if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) - return; - - cpuid(1, &eax, &ebx, &ecx, &edx); - - smp_num_siblings = (ebx & 0xff0000) >> 16; - - if (smp_num_siblings == 1) { - printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); - } else if (smp_num_siblings > 1) { - - if (smp_num_siblings > NR_CPUS) { - printk(KERN_WARNING "CPU: Unsupported number of siblings %d", - smp_num_siblings); - smp_num_siblings = 1; - return; - } - - index_msb = get_count_order(smp_num_siblings); -#ifdef CONFIG_X86_64 - c->phys_proc_id = phys_pkg_id(index_msb); -#else - c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); -#endif - - smp_num_siblings = smp_num_siblings / c->x86_max_cores; - - index_msb = get_count_order(smp_num_siblings); - - core_bits = get_count_order(c->x86_max_cores); - -#ifdef CONFIG_X86_64 - c->cpu_core_id = phys_pkg_id(index_msb) & - ((1 << core_bits) - 1); -#else - c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & - ((1 << core_bits) - 1); -#endif - } - -out: - if ((c->x86_max_cores * smp_num_siblings) > 1) { - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - c->phys_proc_id); - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - c->cpu_core_id); - } -#endif -} - -static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) -{ - char *v = c->x86_vendor_id; - int i; - static int printed; - - for (i = 0; i < X86_VENDOR_NUM; i++) { - if (!cpu_devs[i]) - break; - - if (!strcmp(v, cpu_devs[i]->c_ident[0]) || - (cpu_devs[i]->c_ident[1] && - !strcmp(v, cpu_devs[i]->c_ident[1]))) { - this_cpu = cpu_devs[i]; - c->x86_vendor = this_cpu->c_x86_vendor; - return; - } - } - - if (!printed) { - printed++; - printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n"); - printk(KERN_ERR "CPU: Your system may be unstable.\n"); - } - - c->x86_vendor = X86_VENDOR_UNKNOWN; - this_cpu = &default_cpu; -} - -void __cpuinit cpu_detect(struct cpuinfo_x86 *c) -{ - /* Get vendor name */ - cpuid(0x00000000, (unsigned int *)&c->cpuid_level, - (unsigned int *)&c->x86_vendor_id[0], - (unsigned int *)&c->x86_vendor_id[8], - (unsigned int *)&c->x86_vendor_id[4]); - - c->x86 = 4; - /* Intel-defined flags: level 0x00000001 */ - if (c->cpuid_level >= 0x00000001) { - u32 junk, tfms, cap0, misc; - cpuid(0x00000001, &tfms, &misc, &junk, &cap0); - c->x86 = (tfms >> 8) & 0xf; - c->x86_model = (tfms >> 4) & 0xf; - c->x86_mask = tfms & 0xf; - if (c->x86 == 0xf) - c->x86 += (tfms >> 20) & 0xff; - if (c->x86 >= 0x6) - c->x86_model += ((tfms >> 16) & 0xf) << 4; - if (cap0 & (1<<19)) { - c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; - c->x86_cache_alignment = c->x86_clflush_size; - } - } -} - -static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) -{ - u32 tfms, xlvl; - u32 ebx; - - /* Intel-defined flags: level 0x00000001 */ - if (c->cpuid_level >= 0x00000001) { - u32 capability, excap; - cpuid(0x00000001, &tfms, &ebx, &excap, &capability); - c->x86_capability[0] = capability; - c->x86_capability[4] = excap; - } - - /* AMD-defined flags: level 0x80000001 */ - xlvl = cpuid_eax(0x80000000); - c->extended_cpuid_level = xlvl; - if ((xlvl & 0xffff0000) == 0x80000000) { - if (xlvl >= 0x80000001) { - c->x86_capability[1] = cpuid_edx(0x80000001); - c->x86_capability[6] = cpuid_ecx(0x80000001); - } - } - -#ifdef CONFIG_X86_64 - /* Transmeta-defined flags: level 0x80860001 */ - xlvl = cpuid_eax(0x80860000); - if ((xlvl & 0xffff0000) == 0x80860000) { - /* Don't set x86_cpuid_level here for now to not confuse. */ - if (xlvl >= 0x80860001) - c->x86_capability[2] = cpuid_edx(0x80860001); - } - - if (c->extended_cpuid_level >= 0x80000007) - c->x86_power = cpuid_edx(0x80000007); - - if (c->extended_cpuid_level >= 0x80000008) { - u32 eax = cpuid_eax(0x80000008); - - c->x86_virt_bits = (eax >> 8) & 0xff; - c->x86_phys_bits = eax & 0xff; - } -#endif -} -/* - * Do minimum CPU detection early. - * Fields really needed: vendor, cpuid_level, family, model, mask, - * cache alignment. - * The others are not touched to avoid unwanted side effects. - * - * WARNING: this function is only called on the BP. Don't add code here - * that is supposed to run on all CPUs. - */ -static void __init early_identify_cpu(struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_X86_64 - c->x86_clflush_size = 64; -#else - c->x86_clflush_size = 32; -#endif - c->x86_cache_alignment = c->x86_clflush_size; - - if (!have_cpuid_p()) - return; - - memset(&c->x86_capability, 0, sizeof c->x86_capability); - - c->extended_cpuid_level = 0; - - cpu_detect(c); - - get_cpu_vendor(c); - - get_cpu_cap(c); - - if (this_cpu->c_early_init) - this_cpu->c_early_init(c); - - validate_pat_support(c); -} - -void __init early_cpu_init(void) -{ - struct cpu_dev **cdev; - int count = 0; - - printk("KERNEL supported cpus:\n"); - for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) { - struct cpu_dev *cpudev = *cdev; - unsigned int j; - - if (count >= X86_VENDOR_NUM) - break; - cpu_devs[count] = cpudev; - count++; - - for (j = 0; j < 2; j++) { - if (!cpudev->c_ident[j]) - continue; - printk(" %s %s\n", cpudev->c_vendor, - cpudev->c_ident[j]); - } - } - - early_identify_cpu(&boot_cpu_data); -} - -/* - * The NOPL instruction is supposed to exist on all CPUs with - * family >= 6, unfortunately, that's not true in practice because - * of early VIA chips and (more importantly) broken virtualizers that - * are not easy to detect. Hence, probe for it based on first - * principles. - * - * Note: no 64-bit chip is known to lack these, but put the code here - * for consistency with 32 bits, and to make it utterly trivial to - * diagnose the problem should it ever surface. - */ -static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) -{ - const u32 nopl_signature = 0x888c53b1; /* Random number */ - u32 has_nopl = nopl_signature; - - clear_cpu_cap(c, X86_FEATURE_NOPL); - if (c->x86 >= 6) { - asm volatile("\n" - "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ - "2:\n" - " .section .fixup,\"ax\"\n" - "3: xor %0,%0\n" - " jmp 2b\n" - " .previous\n" - _ASM_EXTABLE(1b,3b) - : "+a" (has_nopl)); - - if (has_nopl == nopl_signature) - set_cpu_cap(c, X86_FEATURE_NOPL); - } -} - -static void __cpuinit generic_identify(struct cpuinfo_x86 *c) -{ - if (!have_cpuid_p()) - return; - - c->extended_cpuid_level = 0; - - cpu_detect(c); - - get_cpu_vendor(c); - - get_cpu_cap(c); - - if (c->cpuid_level >= 0x00000001) { - c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF; -#ifdef CONFIG_X86_32 -# ifdef CONFIG_X86_HT - c->apicid = phys_pkg_id(c->initial_apicid, 0); -# else - c->apicid = c->initial_apicid; -# endif -#endif - -#ifdef CONFIG_X86_HT - c->phys_proc_id = c->initial_apicid; -#endif - } - - if (c->extended_cpuid_level >= 0x80000004) - get_model_name(c); /* Default name */ - - init_scattered_cpuid_features(c); - detect_nopl(c); -} - -/* - * This does the hard work of actually picking apart the CPU stuff... - */ -static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) -{ - int i; - - c->loops_per_jiffy = loops_per_jiffy; - c->x86_cache_size = -1; - c->x86_vendor = X86_VENDOR_UNKNOWN; - c->x86_model = c->x86_mask = 0; /* So far unknown... */ - c->x86_vendor_id[0] = '\0'; /* Unset */ - c->x86_model_id[0] = '\0'; /* Unset */ - c->x86_max_cores = 1; -#ifdef CONFIG_X86_64 - c->x86_coreid_bits = 0; - c->x86_clflush_size = 64; -#else - c->cpuid_level = -1; /* CPUID not detected */ - c->x86_clflush_size = 32; -#endif - c->x86_cache_alignment = c->x86_clflush_size; - memset(&c->x86_capability, 0, sizeof c->x86_capability); - - if (!have_cpuid_p()) { - /* - * First of all, decide if this is a 486 or higher - * It's a 486 if we can modify the AC flag - */ - if (flag_is_changeable_p(X86_EFLAGS_AC)) - c->x86 = 4; - else - c->x86 = 3; - } - - generic_identify(c); - - if (this_cpu->c_identify) - this_cpu->c_identify(c); - -#ifdef CONFIG_X86_64 - c->apicid = phys_pkg_id(0); -#endif - - /* - * Vendor-specific initialization. In this section we - * canonicalize the feature flags, meaning if there are - * features a certain CPU supports which CPUID doesn't - * tell us, CPUID claiming incorrect flags, or other bugs, - * we handle them here. - * - * At the end of this section, c->x86_capability better - * indicate the features this CPU genuinely supports! - */ - if (this_cpu->c_init) - this_cpu->c_init(c); - - /* Disable the PN if appropriate */ - squash_the_stupid_serial_number(c); - - /* - * The vendor-specific functions might have changed features. Now - * we do "generic changes." - */ - - /* If the model name is still unset, do table lookup. */ - if (!c->x86_model_id[0]) { - char *p; - p = table_lookup_model(c); - if (p) - strcpy(c->x86_model_id, p); - else - /* Last resort... */ - sprintf(c->x86_model_id, "%02x/%02x", - c->x86, c->x86_model); - } - -#ifdef CONFIG_X86_64 - detect_ht(c); -#endif - - /* - * On SMP, boot_cpu_data holds the common feature set between - * all CPUs; so make sure that we indicate which features are - * common between the CPUs. The first time this routine gets - * executed, c == &boot_cpu_data. - */ - if (c != &boot_cpu_data) { - /* AND the already accumulated flags with these */ - for (i = 0; i < NCAPINTS; i++) - boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; - } - - /* Clear all flags overriden by options */ - for (i = 0; i < NCAPINTS; i++) - c->x86_capability[i] &= ~cleared_cpu_caps[i]; - -#ifdef CONFIG_X86_MCE - /* Init Machine Check Exception if available. */ - mcheck_init(c); -#endif - - select_idle_routine(c); - -#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) - numa_add_cpu(smp_processor_id()); -#endif -} - -void __init identify_boot_cpu(void) -{ - identify_cpu(&boot_cpu_data); -#ifdef CONFIG_X86_32 - sysenter_setup(); - enable_sep_cpu(); -#endif -} - -void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) -{ - BUG_ON(c == &boot_cpu_data); - identify_cpu(c); -#ifdef CONFIG_X86_32 - enable_sep_cpu(); -#endif - mtrr_ap_init(); -} - -struct msr_range { - unsigned min; - unsigned max; -}; - -static struct msr_range msr_range_array[] __cpuinitdata = { - { 0x00000000, 0x00000418}, - { 0xc0000000, 0xc000040b}, - { 0xc0010000, 0xc0010142}, - { 0xc0011000, 0xc001103b}, -}; - -static void __cpuinit print_cpu_msr(void) -{ - unsigned index; - u64 val; - int i; - unsigned index_min, index_max; - - for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) { - index_min = msr_range_array[i].min; - index_max = msr_range_array[i].max; - for (index = index_min; index < index_max; index++) { - if (rdmsrl_amd_safe(index, &val)) - continue; - printk(KERN_INFO " MSR%08x: %016llx\n", index, val); - } - } -} - -static int show_msr __cpuinitdata; -static __init int setup_show_msr(char *arg) -{ - int num; - - get_option(&arg, &num); - - if (num > 0) - show_msr = num; - return 1; -} -__setup("show_msr=", setup_show_msr); - -static __init int setup_noclflush(char *arg) -{ - setup_clear_cpu_cap(X86_FEATURE_CLFLSH); - return 1; -} -__setup("noclflush", setup_noclflush); - -void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) -{ - char *vendor = NULL; - - if (c->x86_vendor < X86_VENDOR_NUM) - vendor = this_cpu->c_vendor; - else if (c->cpuid_level >= 0) - vendor = c->x86_vendor_id; - - if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor))) - printk(KERN_CONT "%s ", vendor); - - if (c->x86_model_id[0]) - printk(KERN_CONT "%s", c->x86_model_id); - else - printk(KERN_CONT "%d86", c->x86); - - if (c->x86_mask || c->cpuid_level >= 0) - printk(KERN_CONT " stepping %02x\n", c->x86_mask); - else - printk(KERN_CONT "\n"); - -#ifdef CONFIG_SMP - if (c->cpu_index < show_msr) - print_cpu_msr(); -#else - if (show_msr) - print_cpu_msr(); -#endif -} - -static __init int setup_disablecpuid(char *arg) -{ - int bit; - if (get_option(&arg, &bit) && bit < NCAPINTS*32) - setup_clear_cpu_cap(bit); - else - return 0; - return 1; -} -__setup("clearcpuid=", setup_disablecpuid); - -cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; - -#ifdef CONFIG_X86_64 -struct x8664_pda **_cpu_pda __read_mostly; -EXPORT_SYMBOL(_cpu_pda); - -struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; - -char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; - -unsigned long __supported_pte_mask __read_mostly = ~0UL; -EXPORT_SYMBOL_GPL(__supported_pte_mask); - -static int do_not_nx __cpuinitdata; - -/* noexec=on|off -Control non executable mappings for 64bit processes. - -on Enable(default) -off Disable -*/ -static int __init nonx_setup(char *str) -{ - if (!str) - return -EINVAL; - if (!strncmp(str, "on", 2)) { - __supported_pte_mask |= _PAGE_NX; - do_not_nx = 0; - } else if (!strncmp(str, "off", 3)) { - do_not_nx = 1; - __supported_pte_mask &= ~_PAGE_NX; - } - return 0; -} -early_param("noexec", nonx_setup); - -int force_personality32; - -/* noexec32=on|off -Control non executable heap for 32bit processes. -To control the stack too use noexec=off - -on PROT_READ does not imply PROT_EXEC for 32bit processes (default) -off PROT_READ implies PROT_EXEC -*/ -static int __init nonx32_setup(char *str) -{ - if (!strcmp(str, "on")) - force_personality32 &= ~READ_IMPLIES_EXEC; - else if (!strcmp(str, "off")) - force_personality32 |= READ_IMPLIES_EXEC; - return 1; -} -__setup("noexec32=", nonx32_setup); - -void pda_init(int cpu) -{ - struct x8664_pda *pda = cpu_pda(cpu); - - /* Setup up data that may be needed in __get_free_pages early */ - loadsegment(fs, 0); - loadsegment(gs, 0); - /* Memory clobbers used to order PDA accessed */ - mb(); - wrmsrl(MSR_GS_BASE, pda); - mb(); - - pda->cpunumber = cpu; - pda->irqcount = -1; - pda->kernelstack = (unsigned long)stack_thread_info() - - PDA_STACKOFFSET + THREAD_SIZE; - pda->active_mm = &init_mm; - pda->mmu_state = 0; - - if (cpu == 0) { - /* others are initialized in smpboot.c */ - pda->pcurrent = &init_task; - pda->irqstackptr = boot_cpu_stack; - pda->irqstackptr += IRQSTACKSIZE - 64; - } else { - if (!pda->irqstackptr) { - pda->irqstackptr = (char *) - __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); - if (!pda->irqstackptr) - panic("cannot allocate irqstack for cpu %d", - cpu); - pda->irqstackptr += IRQSTACKSIZE - 64; - } - - if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) - pda->nodenumber = cpu_to_node(cpu); - } -} - -char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + - DEBUG_STKSZ] __page_aligned_bss; - -extern asmlinkage void ignore_sysret(void); - -/* May not be marked __init: used by software suspend */ -void syscall_init(void) -{ - /* - * LSTAR and STAR live in a bit strange symbiosis. - * They both write to the same internal register. STAR allows to - * set CS/DS but only a 32bit target. LSTAR sets the 64bit rip. - */ - wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); - wrmsrl(MSR_LSTAR, system_call); - wrmsrl(MSR_CSTAR, ignore_sysret); - -#ifdef CONFIG_IA32_EMULATION - syscall32_cpu_init(); -#endif - - /* Flags to clear on syscall */ - wrmsrl(MSR_SYSCALL_MASK, - X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL); -} - -void __cpuinit check_efer(void) -{ - unsigned long efer; - - rdmsrl(MSR_EFER, efer); - if (!(efer & EFER_NX) || do_not_nx) - __supported_pte_mask &= ~_PAGE_NX; -} - -unsigned long kernel_eflags; - -/* - * Copies of the original ist values from the tss are only accessed during - * debugging, no special alignment required. - */ -DEFINE_PER_CPU(struct orig_ist, orig_ist); - -#else - -/* Make sure %fs is initialized properly in idle threads */ -struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) -{ - memset(regs, 0, sizeof(struct pt_regs)); - regs->fs = __KERNEL_PERCPU; - return regs; -} -#endif - -/* - * cpu_init() initializes state that is per-CPU. Some data is already - * initialized (naturally) in the bootstrap process, such as the GDT - * and IDT. We reload them nevertheless, this function acts as a - * 'CPU state barrier', nothing should get across. - * A lot of state is already set up in PDA init for 64 bit - */ -#ifdef CONFIG_X86_64 -void __cpuinit cpu_init(void) -{ - int cpu = stack_smp_processor_id(); - struct tss_struct *t = &per_cpu(init_tss, cpu); - struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu); - unsigned long v; - char *estacks = NULL; - struct task_struct *me; - int i; - - /* CPU 0 is initialised in head64.c */ - if (cpu != 0) - pda_init(cpu); - else - estacks = boot_exception_stacks; - - me = current; - - if (cpu_test_and_set(cpu, cpu_initialized)) - panic("CPU#%d already initialized!\n", cpu); - - printk(KERN_INFO "Initializing CPU#%d\n", cpu); - - clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); - - /* - * Initialize the per-CPU GDT with the boot GDT, - * and set up the GDT descriptor: - */ - - switch_to_new_gdt(); - load_idt((const struct desc_ptr *)&idt_descr); - - memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); - syscall_init(); - - wrmsrl(MSR_FS_BASE, 0); - wrmsrl(MSR_KERNEL_GS_BASE, 0); - barrier(); - - check_efer(); - if (cpu != 0 && x2apic) - enable_x2apic(); - - /* - * set up and load the per-CPU TSS - */ - if (!orig_ist->ist[0]) { - static const unsigned int order[N_EXCEPTION_STACKS] = { - [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, - [DEBUG_STACK - 1] = DEBUG_STACK_ORDER - }; - for (v = 0; v < N_EXCEPTION_STACKS; v++) { - if (cpu) { - estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); - if (!estacks) - panic("Cannot allocate exception " - "stack %ld %d\n", v, cpu); - } - estacks += PAGE_SIZE << order[v]; - orig_ist->ist[v] = t->x86_tss.ist[v] = - (unsigned long)estacks; - } - } - - t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); - /* - * <= is required because the CPU will access up to - * 8 bits beyond the end of the IO permission bitmap. - */ - for (i = 0; i <= IO_BITMAP_LONGS; i++) - t->io_bitmap[i] = ~0UL; - - atomic_inc(&init_mm.mm_count); - me->active_mm = &init_mm; - if (me->mm) - BUG(); - enter_lazy_tlb(&init_mm, me); - - load_sp0(t, ¤t->thread); - set_tss_desc(cpu, t); - load_TR_desc(); - load_LDT(&init_mm.context); - -#ifdef CONFIG_KGDB - /* - * If the kgdb is connected no debug regs should be altered. This - * is only applicable when KGDB and a KGDB I/O module are built - * into the kernel and you are using early debugging with - * kgdbwait. KGDB will control the kernel HW breakpoint registers. - */ - if (kgdb_connected && arch_kgdb_ops.correct_hw_break) - arch_kgdb_ops.correct_hw_break(); - else { -#endif - /* - * Clear all 6 debug registers: - */ - - set_debugreg(0UL, 0); - set_debugreg(0UL, 1); - set_debugreg(0UL, 2); - set_debugreg(0UL, 3); - set_debugreg(0UL, 6); - set_debugreg(0UL, 7); -#ifdef CONFIG_KGDB - /* If the kgdb is connected no debug regs should be altered. */ - } -#endif - - fpu_init(); - - raw_local_save_flags(kernel_eflags); - - if (is_uv_system()) - uv_cpu_init(); -} - -#else - -void __cpuinit cpu_init(void) -{ - int cpu = smp_processor_id(); - struct task_struct *curr = current; - struct tss_struct *t = &per_cpu(init_tss, cpu); - struct thread_struct *thread = &curr->thread; - - if (cpu_test_and_set(cpu, cpu_initialized)) { - printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); - for (;;) local_irq_enable(); - } - - printk(KERN_INFO "Initializing CPU#%d\n", cpu); - - if (cpu_has_vme || cpu_has_tsc || cpu_has_de) - clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); - - load_idt(&idt_descr); - switch_to_new_gdt(); - - /* - * Set up and load the per-CPU TSS and LDT - */ - atomic_inc(&init_mm.mm_count); - curr->active_mm = &init_mm; - if (curr->mm) - BUG(); - enter_lazy_tlb(&init_mm, curr); - - load_sp0(t, thread); - set_tss_desc(cpu, t); - load_TR_desc(); - load_LDT(&init_mm.context); - -#ifdef CONFIG_DOUBLEFAULT - /* Set up doublefault TSS pointer in the GDT */ - __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); -#endif - - /* Clear %gs. */ - asm volatile ("mov %0, %%gs" : : "r" (0)); - - /* Clear all 6 debug registers: */ - set_debugreg(0, 0); - set_debugreg(0, 1); - set_debugreg(0, 2); - set_debugreg(0, 3); - set_debugreg(0, 6); - set_debugreg(0, 7); - - /* - * Force FPU initialization: - */ - if (cpu_has_xsave) - current_thread_info()->status = TS_XSAVE; - else - current_thread_info()->status = 0; - clear_used_math(); - mxcsr_feature_mask_init(); - - /* - * Boot processor to setup the FP and extended state context info. - */ - if (!smp_processor_id()) - init_thread_xstate(); - - xsave_init(); -} - -#ifdef CONFIG_HOTPLUG_CPU -void __cpuinit cpu_uninit(void) -{ - int cpu = raw_smp_processor_id(); - cpu_clear(cpu, cpu_initialized); - - /* lazy TLB state */ - per_cpu(cpu_tlbstate, cpu).state = 0; - per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; -} -#endif - -#endif -- cgit v1.2.3 From bd220a24a9263eaa70d5e6821383085950b5a13c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 5 Sep 2008 00:58:28 -0700 Subject: x86: move nonx_setup etc from common.c to init_64.c like 32 bit put it in init_32.c Signed-off-by: Yinghai Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 54 -------------------------------------------- arch/x86/mm/init_64.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 54 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index eef868c97b8..286c89a991b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -847,51 +847,6 @@ struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; -unsigned long __supported_pte_mask __read_mostly = ~0UL; -EXPORT_SYMBOL_GPL(__supported_pte_mask); - -static int do_not_nx __cpuinitdata; - -/* noexec=on|off -Control non executable mappings for 64bit processes. - -on Enable(default) -off Disable -*/ -static int __init nonx_setup(char *str) -{ - if (!str) - return -EINVAL; - if (!strncmp(str, "on", 2)) { - __supported_pte_mask |= _PAGE_NX; - do_not_nx = 0; - } else if (!strncmp(str, "off", 3)) { - do_not_nx = 1; - __supported_pte_mask &= ~_PAGE_NX; - } - return 0; -} -early_param("noexec", nonx_setup); - -int force_personality32; - -/* noexec32=on|off -Control non executable heap for 32bit processes. -To control the stack too use noexec=off - -on PROT_READ does not imply PROT_EXEC for 32bit processes (default) -off PROT_READ implies PROT_EXEC -*/ -static int __init nonx32_setup(char *str) -{ - if (!strcmp(str, "on")) - force_personality32 &= ~READ_IMPLIES_EXEC; - else if (!strcmp(str, "off")) - force_personality32 |= READ_IMPLIES_EXEC; - return 1; -} -__setup("noexec32=", nonx32_setup); - void pda_init(int cpu) { struct x8664_pda *pda = cpu_pda(cpu); @@ -957,15 +912,6 @@ void syscall_init(void) X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL); } -void __cpuinit check_efer(void) -{ - unsigned long efer; - - rdmsrl(MSR_EFER, efer); - if (!(efer & EFER_NX) || do_not_nx) - __supported_pte_mask &= ~_PAGE_NX; -} - unsigned long kernel_eflags; /* diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index d3746efb060..9c750d6307b 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -88,6 +88,60 @@ early_param("gbpages", parse_direct_gbpages_on); int after_bootmem; +unsigned long __supported_pte_mask __read_mostly = ~0UL; +EXPORT_SYMBOL_GPL(__supported_pte_mask); + +static int do_not_nx __cpuinitdata; + +/* noexec=on|off +Control non executable mappings for 64bit processes. + +on Enable(default) +off Disable +*/ +static int __init nonx_setup(char *str) +{ + if (!str) + return -EINVAL; + if (!strncmp(str, "on", 2)) { + __supported_pte_mask |= _PAGE_NX; + do_not_nx = 0; + } else if (!strncmp(str, "off", 3)) { + do_not_nx = 1; + __supported_pte_mask &= ~_PAGE_NX; + } + return 0; +} +early_param("noexec", nonx_setup); + +void __cpuinit check_efer(void) +{ + unsigned long efer; + + rdmsrl(MSR_EFER, efer); + if (!(efer & EFER_NX) || do_not_nx) + __supported_pte_mask &= ~_PAGE_NX; +} + +int force_personality32; + +/* noexec32=on|off +Control non executable heap for 32bit processes. +To control the stack too use noexec=off + +on PROT_READ does not imply PROT_EXEC for 32bit processes (default) +off PROT_READ implies PROT_EXEC +*/ +static int __init nonx32_setup(char *str) +{ + if (!strcmp(str, "on")) + force_personality32 &= ~READ_IMPLIES_EXEC; + else if (!strcmp(str, "off")) + force_personality32 |= READ_IMPLIES_EXEC; + return 1; +} +__setup("noexec32=", nonx32_setup); + /* * NOTE: This function is marked __ref because it calls __init function * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0. -- cgit v1.2.3 From deed05b7c017e49473e8c386efba196410fd18b3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 5 Sep 2008 10:23:26 +0200 Subject: x86, init_64.c: cleanup Clean up comments. Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 9c750d6307b..1f6806b62eb 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -93,12 +93,13 @@ EXPORT_SYMBOL_GPL(__supported_pte_mask); static int do_not_nx __cpuinitdata; -/* noexec=on|off -Control non executable mappings for 64bit processes. - -on Enable(default) -off Disable -*/ +/* + * noexec=on|off + * Control non-executable mappings for 64-bit processes. + * + * on Enable (default) + * off Disable + */ static int __init nonx_setup(char *str) { if (!str) @@ -125,13 +126,14 @@ void __cpuinit check_efer(void) int force_personality32; -/* noexec32=on|off -Control non executable heap for 32bit processes. -To control the stack too use noexec=off - -on PROT_READ does not imply PROT_EXEC for 32bit processes (default) -off PROT_READ implies PROT_EXEC -*/ +/* + * noexec32=on|off + * Control non executable heap for 32bit processes. + * To control the stack too use noexec=off + * + * on PROT_READ does not imply PROT_EXEC for 32-bit processes (default) + * off PROT_READ implies PROT_EXEC + */ static int __init nonx32_setup(char *str) { if (!strcmp(str, "on")) -- cgit v1.2.3 From 551b4545bf9658dc5ae5a1277dcd4d7bf0028b28 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 5 Sep 2008 17:58:49 +0900 Subject: x86: gart alloc_coherent doesn't need to check NULL device argument asm/dma-mapping.h guarantees that gart alloc_coherent doesn't get NULL device argument. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 4d0864900b8..0b99d4a06f7 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -506,9 +506,6 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, align_mask = (1UL << get_order(size)) - 1; - if (!dev) - dev = &x86_dma_fallback_dev; - *dma_addr = dma_map_area(dev, __pa(vaddr), size, DMA_BIDIRECTIONAL, align_mask); flush_gart(); -- cgit v1.2.3 From 110e0358e7dfd9cc56d47077068f3680dae10b56 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 28 Aug 2008 13:58:39 -0700 Subject: x86: make sure the CPA test code's use of _PAGE_UNUSED1 is obvious The CPA test code uses _PAGE_UNUSED1, so make sure its obvious. Signed-off-by: Jeremy Fitzhardinge Cc: Nick Piggin Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c index 7c301728711..e1d10690921 100644 --- a/arch/x86/mm/pageattr-test.c +++ b/arch/x86/mm/pageattr-test.c @@ -32,7 +32,7 @@ enum { GPS = (1<<30) }; -#define PAGE_TESTBIT __pgprot(_PAGE_UNUSED1) +#define PAGE_CPA_TEST __pgprot(_PAGE_CPA_TEST) static int pte_testbit(pte_t pte) { @@ -174,7 +174,7 @@ static int pageattr_test(void) } test_addr = addr[i]; - err = change_page_attr_set(&test_addr, len[i], PAGE_TESTBIT, 0); + err = change_page_attr_set(&test_addr, len[i], PAGE_CPA_TEST, 0); if (err < 0) { printk(KERN_ERR "CPA %d failed %d\n", i, err); failed++; @@ -207,7 +207,7 @@ static int pageattr_test(void) continue; } test_addr = addr[i]; - err = change_page_attr_clear(&test_addr, len[i], PAGE_TESTBIT, 0); + err = change_page_attr_clear(&test_addr, len[i], PAGE_CPA_TEST, 0); if (err < 0) { printk(KERN_ERR "CPA reverting failed: %d\n", err); failed++; -- cgit v1.2.3 From 913da64b54b2b3bb212a59aba2e6f2b8294ca1fa Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Wed, 3 Sep 2008 14:30:23 +0100 Subject: x86: build fix for !CONFIG_SMP Move reset_lazy_tlbstate into tlb_32.c, and define noop versions of play_dead() in process_{32,64}.c when !CONFIG_SMP. Signed-off-by: Alex Nixon Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 7 ------- arch/x86/kernel/process_32.c | 7 +++++++ arch/x86/kernel/process_64.c | 7 +++++++ arch/x86/kernel/tlb_32.c | 8 ++++++++ 4 files changed, 22 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 18f5551b32d..76d10d5c2fa 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -714,10 +714,3 @@ void __cpuinit cpu_init(void) mxcsr_feature_mask_init(); } -void reset_lazy_tlbstate(void) -{ - int cpu = raw_smp_processor_id(); - - per_cpu(cpu_tlbstate, cpu).state = 0; - per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; -} diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 633cf06578f..b76b38ff962 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -72,6 +72,13 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return ((unsigned long *)tsk->thread.sp)[3]; } +#ifndef CONFIG_SMP +static inline void play_dead(void) +{ + BUG(); +} +#endif + /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index aa28ed01cdf..ec27afa43d7 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -85,6 +85,13 @@ void exit_idle(void) __exit_idle(); } +#ifndef CONFIG_SMP +static inline void play_dead(void) +{ + BUG(); +} +#endif + /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index fec1ecedc9b..e00534b3353 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c @@ -241,3 +241,11 @@ void flush_tlb_all(void) on_each_cpu(do_flush_tlb_all, NULL, 1); } +void reset_lazy_tlbstate(void) +{ + int cpu = raw_smp_processor_id(); + + per_cpu(cpu_tlbstate, cpu).state = 0; + per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; +} + -- cgit v1.2.3 From efd327a2d41214dded03cbfbb6d447530964cddd Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Wed, 3 Sep 2008 14:36:40 +0100 Subject: x86/paravirt: Remove duplicate paravirt_pagetable_setup_{start, done}() They were already called once in arch/x86/kernel/setup.c - we don't need to call them again. Signed-off-by: Alex Nixon Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d37f29376b0..60ec1d08ff2 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -458,11 +458,7 @@ static void __init pagetable_init(void) { pgd_t *pgd_base = swapper_pg_dir; - paravirt_pagetable_setup_start(pgd_base); - permanent_kmaps_init(pgd_base); - - paravirt_pagetable_setup_done(pgd_base); } #ifdef CONFIG_ACPI_SLEEP -- cgit v1.2.3 From 5b7e41ff37267c35b0fcf9162ca0c32c3d8d2c5c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 3 Sep 2008 17:24:03 -0700 Subject: x86: additional defconfig updates Additional updates to the x86 defconfigs. The goals are, as before: - Make them usable to testers, more so than distributors or end users, both of which are likely to have their own config already. - Keep 32 and 64 bits as similar as is practical. Changes: - Use a more generic CPU type (ppro and generic, respectively). - Bump number of CPUs to 64 (few if any NR_CPUS arrays left). - Enable PAT. - Enable OPTIMIZE_INLINE. - Enable microcode update support. - Build SMT scheduler support (in addition to MC). Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/configs/i386_defconfig | 19 +++++++++++-------- arch/x86/configs/x86_64_defconfig | 29 +++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 104275e191a..ef9a52005ec 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc4 -# Mon Aug 25 15:04:00 2008 +# Linux kernel version: 2.6.27-rc5 +# Wed Sep 3 17:23:09 2008 # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -202,7 +202,7 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # CONFIG_M586 is not set # CONFIG_M586TSC is not set # CONFIG_M586MMX is not set -# CONFIG_M686 is not set +CONFIG_M686=y # CONFIG_MPENTIUMII is not set # CONFIG_MPENTIUMIII is not set # CONFIG_MPENTIUMM is not set @@ -221,13 +221,14 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC7 is not set # CONFIG_MPSC is not set -CONFIG_MCORE2=y +# CONFIG_MCORE2 is not set # CONFIG_GENERIC_CPU is not set CONFIG_X86_GENERIC=y CONFIG_X86_CPU=y CONFIG_X86_CMPXCHG=y CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_XADD=y +# CONFIG_X86_PPRO_FENCE is not set CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_INVLPG=y CONFIG_X86_BSWAP=y @@ -235,14 +236,15 @@ CONFIG_X86_POPAD_OK=y CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_USE_PPRO_CHECKSUM=y CONFIG_X86_TSC=y +CONFIG_X86_CMOV=y CONFIG_X86_MINIMUM_CPU_FAMILY=4 CONFIG_X86_DEBUGCTLMSR=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y CONFIG_DMI=y # CONFIG_IOMMU_HELPER is not set -CONFIG_NR_CPUS=4 -# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=64 +CONFIG_SCHED_SMT=y CONFIG_SCHED_MC=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y @@ -254,7 +256,8 @@ CONFIG_VM86=y # CONFIG_TOSHIBA is not set # CONFIG_I8K is not set CONFIG_X86_REBOOTFIXUPS=y -# CONFIG_MICROCODE is not set +CONFIG_MICROCODE=y +CONFIG_MICROCODE_OLD_INTERFACE=y CONFIG_X86_MSR=y CONFIG_X86_CPUID=y # CONFIG_NOHIGHMEM is not set @@ -2115,7 +2118,7 @@ CONFIG_IO_DELAY_0X80=y CONFIG_DEFAULT_IO_DELAY_TYPE=0 CONFIG_DEBUG_BOOT_PARAMS=y # CONFIG_CPA_DEBUG is not set -# CONFIG_OPTIMIZE_INLINING is not set +CONFIG_OPTIMIZE_INLINING=y # # Security options diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 678c8acefe0..e620ea6e2a7 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc4 -# Mon Aug 25 14:40:46 2008 +# Linux kernel version: 2.6.27-rc5 +# Wed Sep 3 17:13:39 2008 # CONFIG_64BIT=y # CONFIG_X86_32 is not set @@ -218,17 +218,14 @@ CONFIG_X86_PC=y # CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC7 is not set # CONFIG_MPSC is not set -CONFIG_MCORE2=y -# CONFIG_GENERIC_CPU is not set +# CONFIG_MCORE2 is not set +CONFIG_GENERIC_CPU=y CONFIG_X86_CPU=y -CONFIG_X86_L1_CACHE_BYTES=64 -CONFIG_X86_INTERNODE_CACHE_BYTES=64 +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_INTERNODE_CACHE_BYTES=128 CONFIG_X86_CMPXCHG=y -CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INTEL_USERCOPY=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_P6_NOP=y CONFIG_X86_TSC=y CONFIG_X86_CMPXCHG64=y CONFIG_X86_CMOV=y @@ -243,9 +240,8 @@ CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y CONFIG_AMD_IOMMU=y CONFIG_SWIOTLB=y CONFIG_IOMMU_HELPER=y -# CONFIG_MAXSMP is not set -CONFIG_NR_CPUS=4 -# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=64 +CONFIG_SCHED_SMT=y CONFIG_SCHED_MC=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y @@ -254,7 +250,8 @@ CONFIG_X86_LOCAL_APIC=y CONFIG_X86_IO_APIC=y # CONFIG_X86_MCE is not set # CONFIG_I8K is not set -# CONFIG_MICROCODE is not set +CONFIG_MICROCODE=y +CONFIG_MICROCODE_OLD_INTERFACE=y CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_NUMA=y @@ -290,7 +287,7 @@ CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_MTRR=y # CONFIG_MTRR_SANITIZER is not set -# CONFIG_X86_PAT is not set +CONFIG_X86_PAT=y CONFIG_EFI=y CONFIG_SECCOMP=y # CONFIG_HZ_100 is not set @@ -2089,7 +2086,7 @@ CONFIG_IO_DELAY_0X80=y CONFIG_DEFAULT_IO_DELAY_TYPE=0 CONFIG_DEBUG_BOOT_PARAMS=y # CONFIG_CPA_DEBUG is not set -# CONFIG_OPTIMIZE_INLINING is not set +CONFIG_OPTIMIZE_INLINING=y # # Security options -- cgit v1.2.3 From e7250b8ae3870f37f660c2f65cafcaba85e3bfd3 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 5 Sep 2008 18:33:26 +0200 Subject: x86: hpet: modify IXP400 quirk to enable interrupts The current quirk is incomplete. Some more chipset fiddling has to be done to enable HPET interrupts. This patch aims to do this. From my tests it seems to work faultlessly. But the official statement is that HPET is not supported on SB4X0. Users will still have to use hpet=force to enable it. Use it at your own risk. Signed-off-by: Andreas Herrmann Signed-off-by: Ingo Molnar --- arch/x86/kernel/quirks.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index d1385881810..f6a11b9b1f9 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -354,9 +354,27 @@ static void ati_force_hpet_resume(void) printk(KERN_DEBUG "Force enabled HPET at resume\n"); } +static u32 ati_ixp4x0_rev(struct pci_dev *dev) +{ + u32 d; + u8 b; + + pci_read_config_byte(dev, 0xac, &b); + b &= ~(1<<5); + pci_write_config_byte(dev, 0xac, b); + pci_read_config_dword(dev, 0x70, &d); + d |= 1<<8; + pci_write_config_dword(dev, 0x70, d); + pci_read_config_dword(dev, 0x8, &d); + d &= 0xff; + dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d); + return d; +} + static void ati_force_enable_hpet(struct pci_dev *dev) { - u32 uninitialized_var(val); + u32 d, val; + u8 b; if (hpet_address || force_hpet_address) return; @@ -366,14 +384,33 @@ static void ati_force_enable_hpet(struct pci_dev *dev) return; } + d = ati_ixp4x0_rev(dev); + if (d < 0x82) + return; + + /* base address */ pci_write_config_dword(dev, 0x14, 0xfed00000); pci_read_config_dword(dev, 0x14, &val); + + /* enable interrupt */ + outb(0x72, 0xcd6); b = inb(0xcd7); + b |= 0x1; + outb(0x72, 0xcd6); outb(b, 0xcd7); + outb(0x72, 0xcd6); b = inb(0xcd7); + if (!(b & 0x1)) + return; + pci_read_config_dword(dev, 0x64, &d); + d |= (1<<10); + pci_write_config_dword(dev, 0x64, d); + pci_read_config_dword(dev, 0x64, &d); + if (!(d & (1<<10))) + return; + force_hpet_address = val; force_hpet_resume_type = ATI_FORCE_HPET_RESUME; dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n", force_hpet_address); cached_dev = dev; - return; } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, ati_force_enable_hpet); -- cgit v1.2.3 From cf169702ba6928cee9d4f4adf3e932b643b8db7a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 2 Sep 2008 13:13:40 +0200 Subject: x86, gart: add detection of AMD family 0x11 northbridges This patch adds the detection of the northbridges in the AMD family 0x11 processors. It also fixes the magic numbers there while changing this code. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/k8.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/k8.c b/arch/x86/kernel/k8.c index 7377ccb2133..304d8bad655 100644 --- a/arch/x86/kernel/k8.c +++ b/arch/x86/kernel/k8.c @@ -16,8 +16,9 @@ EXPORT_SYMBOL(num_k8_northbridges); static u32 *flush_words; struct pci_device_id k8_nb_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, {} }; EXPORT_SYMBOL(k8_nb_ids); -- cgit v1.2.3 From e51af6630848406fc97adbd71443818cdcda297b Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 4 Sep 2008 09:54:37 +0100 Subject: x86: blacklist DMAR on Intel G31/G33 chipsets Some BIOSes (the Intel DG33BU, for example) wrongly claim to have DMAR when they don't. Avoid the resulting crashes when it doesn't work as expected. I'd still be grateful if someone could test it on a DG33BU with the old BIOS though, since I've killed mine. I tested the DMI version, but not this one. Signed-off-by: David Woodhouse Signed-off-by: Ingo Molnar --- arch/x86/kernel/early-quirks.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 4353cf5e6fa..24bb5faf5ef 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -95,6 +95,20 @@ static void __init nvidia_bugs(int num, int slot, int func) } +#ifdef CONFIG_DMAR +static void __init intel_g33_dmar(int num, int slot, int func) +{ + struct acpi_table_header *dmar_tbl; + acpi_status status; + + status = acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_tbl); + if (ACPI_SUCCESS(status)) { + printk(KERN_INFO "BIOS BUG: DMAR advertised on Intel G31/G33 chipset -- ignoring\n"); + dmar_disabled = 1; + } +} +#endif + #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -114,6 +128,10 @@ static struct chipset early_qrk[] __initdata = { PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, +#ifdef CONFIG_DMAR + { PCI_VENDOR_ID_INTEL, 0x29c0, + PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, intel_g33_dmar }, +#endif {} }; -- cgit v1.2.3 From d2f37384fc9957ad0162d5285a5660f0a86ef243 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 5 Sep 2008 21:28:27 -0700 Subject: x86: when building image.iso, use isohybrid if it exists When building image.iso (make isoimage), use the isohybrid tool if it exists. isohybrid is a script included with Syslinux 3.72 and higher, which creates an image that can be booted either as a hard disk (including removable, e.g. USB disk) or as a CD-ROM. If isohybrid doesn't exist, then this has no effect. Signed-off-by: H. Peter Anvin --- arch/x86/boot/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 7ee102f9c4f..cceba1f4636 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -181,6 +181,7 @@ isoimage: $(BOOTIMAGE) mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ $(obj)/isoimage + isohybrid $(obj)/image.iso 2>/dev/null || true rm -rf $(obj)/isoimage zlilo: $(BOOTIMAGE) -- cgit v1.2.3 From 1b05d60d60e81c6594da8298107a05b506f01797 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 6 Sep 2008 01:52:27 -0700 Subject: x86: remove duplicated get_model_name() calling Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 3 --- arch/x86/kernel/cpu/amd_64.c | 3 +-- arch/x86/kernel/cpu/centaur.c | 1 - arch/x86/kernel/cpu/common.c | 9 +++------ arch/x86/kernel/cpu/cpu.h | 1 - arch/x86/kernel/cpu/cyrix.c | 1 - arch/x86/kernel/cpu/transmeta.c | 1 - 7 files changed, 4 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index d64ea6097ca..e0ba2c7c5a1 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -42,7 +42,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) { u32 l, h; int mbytes = num_physpages >> (20-PAGE_SHIFT); - int r; #ifdef CONFIG_SMP unsigned long long value; @@ -75,8 +74,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) */ clear_cpu_cap(c, 0*32+31); - r = get_model_name(c); - switch (c->x86) { case 4: /* diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index d1c721c0c49..c5fbf7477ea 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -157,8 +157,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) if (c->x86 >= 6) set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK); - level = get_model_name(c); - if (!level) { + if (!c->x86_model_id[0]) { switch (c->x86) { case 0xf: /* Should distinguish Models here, but this is only diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index e5f6d89521b..89bfdd9cacc 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -289,7 +289,6 @@ static void __cpuinit init_c3(struct cpuinfo_x86 *c) if (c->x86_model >= 6 && c->x86_model < 9) set_cpu_cap(c, X86_FEATURE_3DNOW); - get_model_name(c); display_cacheinfo(c); } diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 286c89a991b..a8b9b724242 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -252,13 +252,13 @@ static struct cpu_dev __cpuinitdata default_cpu = { .c_x86_vendor = X86_VENDOR_UNKNOWN, }; -int __cpuinit get_model_name(struct cpuinfo_x86 *c) +static void __cpuinit get_model_name(struct cpuinfo_x86 *c) { unsigned int *v; char *p, *q; if (c->extended_cpuid_level < 0x80000004) - return 0; + return; v = (unsigned int *) c->x86_model_id; cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); @@ -277,8 +277,6 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c) while (q <= &c->x86_model_id[48]) *q++ = '\0'; /* Zero-pad the rest */ } - - return 1; } void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) @@ -610,8 +608,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) #endif } - if (c->extended_cpuid_level >= 0x80000004) - get_model_name(c); /* Default name */ + get_model_name(c); /* Default name */ init_scattered_cpuid_features(c); detect_nopl(c); diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index 3cc9d92afd8..de4094a3921 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h @@ -31,7 +31,6 @@ struct cpu_dev { extern struct cpu_dev *__x86_cpu_dev_start[], *__x86_cpu_dev_end[]; -extern int get_model_name(struct cpuinfo_x86 *c); extern void display_cacheinfo(struct cpuinfo_x86 *c); #endif diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 3f8c7283d81..ffd0f5ed071 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -301,7 +301,6 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) */ if ((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <= dir1 && dir1 <= 0x8f)) geode_configure(); - get_model_name(c); /* get CPU marketing name */ return; } else { /* MediaGX */ Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4'; diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 7c46e6ecedc..738e03244f9 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -12,7 +12,6 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) unsigned int cpu_rev, cpu_freq = 0, cpu_flags, new_cpu_rev; char cpu_info[65]; - get_model_name(c); /* Same as AMD/Cyrix */ display_cacheinfo(c); /* Print CMS and CPU revision */ -- cgit v1.2.3 From e3224234717b4228c235cee401af89212f17a3a4 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 6 Sep 2008 01:52:28 -0700 Subject: x86, cpu init: call early_init_xxx in init_xxx so we: 1. could set some cap to ap 2. restore some cap after memset in identify_cpu for boot cpu esp for CONSTANT_TSC this matters, as: before this patch: flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow rep_good nopl pni monitor cx16 lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs after this patch: flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow constant_tsc rep_good nopl pni monitor cx16 lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs so constant_tsc is back... Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 7 ++----- arch/x86/kernel/cpu/amd_64.c | 2 ++ arch/x86/kernel/cpu/centaur_64.c | 2 ++ arch/x86/kernel/cpu/common.c | 7 ++++--- arch/x86/kernel/cpu/intel_64.c | 2 ++ 5 files changed, 12 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index e0ba2c7c5a1..c3175da7bc6 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -26,11 +26,8 @@ __asm__(".align 4\nvide: ret"); static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) { - if (cpuid_eax(0x80000000) >= 0x80000007) { - c->x86_power = cpuid_edx(0x80000007); - if (c->x86_power & (1<<8)) - set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); - } + if (c->x86_power & (1<<8)) + set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); /* Set MTRR capability flag if appropriate */ if (c->x86_model == 13 || c->x86_model == 9 || diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index c5fbf7477ea..8c2d07f06f1 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -140,6 +140,8 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } #endif + early_init_amd(c); + /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_cpu_cap(c, 0*32+31); diff --git a/arch/x86/kernel/cpu/centaur_64.c b/arch/x86/kernel/cpu/centaur_64.c index 49cfc6d2f2f..0e5cf17a3c8 100644 --- a/arch/x86/kernel/cpu/centaur_64.c +++ b/arch/x86/kernel/cpu/centaur_64.c @@ -16,6 +16,8 @@ static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) static void __cpuinit init_centaur(struct cpuinfo_x86 *c) { + early_init_centaur(c); + if (c->x86 == 0x6 && c->x86_model >= 0xf) { c->x86_cache_alignment = c->x86_clflush_size * 2; set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a8b9b724242..e8045c4ef1c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -473,9 +473,6 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) c->x86_capability[2] = cpuid_edx(0x80860001); } - if (c->extended_cpuid_level >= 0x80000007) - c->x86_power = cpuid_edx(0x80000007); - if (c->extended_cpuid_level >= 0x80000008) { u32 eax = cpuid_eax(0x80000008); @@ -483,6 +480,10 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) c->x86_phys_bits = eax & 0xff; } #endif + + if (c->extended_cpuid_level >= 0x80000007) + c->x86_power = cpuid_edx(0x80000007); + } /* * Do minimum CPU detection early. diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c index 0c0a58dfe09..14a2cd98d48 100644 --- a/arch/x86/kernel/cpu/intel_64.c +++ b/arch/x86/kernel/cpu/intel_64.c @@ -54,6 +54,8 @@ static void __cpuinit srat_detect_node(void) static void __cpuinit init_intel(struct cpuinfo_x86 *c) { + early_init_intel(c); + init_intel_cacheinfo(c); if (c->cpuid_level > 9) { unsigned eax = cpuid_eax(10); -- cgit v1.2.3 From bb57925f5057837c248b57a51181fd6b138a32f3 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 5 Sep 2008 16:26:55 -0700 Subject: x86_32: signal: use syscall_get_nr and error Use asm/syscall.h interfaces that do the same things. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index b21070ea33a..3e4a688bb84 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "sigframe.h" @@ -507,9 +508,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, int ret; /* Are we from a system call? */ - if ((long)regs->orig_ax >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* If so, check system call restarting.. */ - switch (regs->ax) { + switch (syscall_get_error(current, regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->ax = -EINTR; @@ -623,9 +624,9 @@ static void do_signal(struct pt_regs *regs) } /* Did we come from a system call? */ - if ((long)regs->orig_ax >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* Restart the system call - no handlers present */ - switch (regs->ax) { + switch (syscall_get_error(current, regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: -- cgit v1.2.3 From 72fa50f4ef9014f4212945b766af84ea94308903 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 5 Sep 2008 16:27:11 -0700 Subject: x86_32: signal: introduce signal_fault() implement signal_fault() for 32bit. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 3e4a688bb84..76d05d70384 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -243,7 +243,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) return ax; badframe: - force_sig(SIGSEGV, current); + signal_fault(regs, frame, "rt sigreturn"); return 0; } @@ -669,3 +669,19 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) clear_thread_flag(TIF_IRET); } + +void signal_fault(struct pt_regs *regs, void __user *frame, char *where) +{ + struct task_struct *me = current; + + if (show_unhandled_signals && printk_ratelimit()) { + printk(KERN_INFO + "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", + me->comm, me->pid, where, frame, + regs->ip, regs->sp, regs->orig_ax); + print_vma_addr(" in ", regs->ip); + printk(KERN_CONT "\n"); + } + + force_sig(SIGSEGV, me); +} -- cgit v1.2.3 From 8fcd8e20f388d787f6abf701b11037b122029d5b Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 5 Sep 2008 16:27:39 -0700 Subject: x86: signal: make NR_restart_syscall make NR_restart_syscall macro for cosmetic unification of handle_signal(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 3 ++- arch/x86/kernel/signal_64.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 76d05d70384..bd9b65031a9 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -572,6 +572,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, return 0; } +#define NR_restart_syscall __NR_restart_syscall /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by @@ -635,7 +636,7 @@ static void do_signal(struct pt_regs *regs) break; case -ERESTART_RESTARTBLOCK: - regs->ax = __NR_restart_syscall; + regs->ax = NR_restart_syscall; regs->ip -= 2; break; } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 823a55bf8c3..19e2b914320 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -362,6 +362,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, return ret; } +#define NR_restart_syscall \ + test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by @@ -423,9 +425,7 @@ static void do_signal(struct pt_regs *regs) regs->ip -= 2; break; case -ERESTART_RESTARTBLOCK: - regs->ax = test_thread_flag(TIF_IA32) ? - __NR_ia32_restart_syscall : - __NR_restart_syscall; + regs->ax = NR_restart_syscall; regs->ip -= 2; break; } -- cgit v1.2.3 From 1d13024e624d0e2e47f117b383917249a41ef5ce Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 5 Sep 2008 16:28:06 -0700 Subject: x86: signal: split out frame setups Make setup_rt_frame() and split out frame setups from handle_signal(). This is for cosmetic unification of handle_signal(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 29 ++++++++++++++++++++--------- arch/x86/kernel/signal_64.c | 30 ++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index bd9b65031a9..48982f7ce88 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -338,8 +338,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, } static int -setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, - struct pt_regs *regs) +__setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, + struct pt_regs *regs) { struct sigframe __user *frame; void __user *restorer; @@ -416,8 +416,8 @@ give_sigsegv: return -EFAULT; } -static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) +static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; void __user *restorer; @@ -501,6 +501,21 @@ give_sigsegv: /* * OK, we're invoking a handler: */ +static int +setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + int ret; + + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + ret = __setup_rt_frame(sig, ka, info, set, regs); + else + ret = __setup_frame(sig, ka, set, regs); + + return ret; +} + static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) @@ -537,11 +552,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, likely(test_and_clear_thread_flag(TIF_FORCED_TF))) regs->flags &= ~X86_EFLAGS_TF; - /* Set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(sig, ka, info, oldset, regs); - else - ret = setup_frame(sig, ka, oldset, regs); + ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret) return ret; diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 19e2b914320..8fbdd23d5cc 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -195,8 +195,8 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) return (void __user *)round_down(sp - size, 64); } -static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) +static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; void __user *fp = NULL; @@ -280,6 +280,24 @@ give_sigsegv: /* * OK, we're invoking a handler */ +static int +setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + int ret; + +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) { + if (ka->sa.sa_flags & SA_SIGINFO) + ret = ia32_setup_rt_frame(sig, ka, info, set, regs); + else + ret = ia32_setup_frame(sig, ka, set, regs); + } else +#endif + ret = __setup_rt_frame(sig, ka, info, set, regs); + + return ret; +} static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, @@ -317,14 +335,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, likely(test_and_clear_thread_flag(TIF_FORCED_TF))) regs->flags &= ~X86_EFLAGS_TF; -#ifdef CONFIG_IA32_EMULATION - if (test_thread_flag(TIF_IA32)) { - if (ka->sa.sa_flags & SA_SIGINFO) - ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); - else - ret = ia32_setup_frame(sig, ka, oldset, regs); - } else -#endif ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret == 0) { -- cgit v1.2.3 From 13ad7725e9955ac68fff670a039da99ab33e86a0 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 5 Sep 2008 16:28:38 -0700 Subject: x86_32: signal: move signal number conversion to upper layer Bring signal number conversion in __setup_frame() and __setup_rt_frame() up into the common part setup_frame(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 48982f7ce88..b668efc18ea 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -344,7 +344,6 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct sigframe __user *frame; void __user *restorer; int err = 0; - int usig; void __user *fpstate = NULL; frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); @@ -352,13 +351,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - usig = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err = __put_user(usig, &frame->sig); + err = __put_user(sig, &frame->sig); if (err) goto give_sigsegv; @@ -422,7 +415,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; void __user *restorer; int err = 0; - int usig; void __user *fpstate = NULL; frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); @@ -430,13 +422,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - usig = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= __put_user(usig, &frame->sig); + err |= __put_user(sig, &frame->sig); err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); @@ -482,7 +468,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->sp = (unsigned long)frame; regs->ip = (unsigned long)ka->sa.sa_handler; - regs->ax = (unsigned long)usig; + regs->ax = (unsigned long)sig; regs->dx = (unsigned long)&frame->info; regs->cx = (unsigned long)&frame->uc; @@ -506,12 +492,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { int ret; + int usig; + + usig = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - ret = __setup_rt_frame(sig, ka, info, set, regs); + ret = __setup_rt_frame(usig, ka, info, set, regs); else - ret = __setup_frame(sig, ka, set, regs); + ret = __setup_frame(usig, ka, set, regs); return ret; } -- cgit v1.2.3 From 464f04c9e9b3b1c4f5ffb89c51d8ba2a2034c846 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Sat, 6 Sep 2008 12:40:21 +0400 Subject: x86: fix ghost EDD devices in /sys again > This is regression but old enough. Apparently I had for whatever reasons > EDD turned off till recently. This is 2.6.27-rc5 just in case. > > In 2006 I fixed ghost devices due to buggy BIOS: > > http://marc.info/?l=linux-kernel&m=114087765422490&w=2 > > Later edd.S has been rewritten in C, and apparently this patch has been > lost: > > {pts/1}% ls /sys/firmware/edd > int13_dev80/ int13_dev84/ int13_dev88/ int13_dev8c/ > int13_dev81/ int13_dev85/ int13_dev89/ int13_dev8d/ > int13_dev82/ int13_dev86/ int13_dev8a/ int13_dev8e/ > int13_dev83/ int13_dev87/ int13_dev8b/ int13_dev8f/ > > But I have just a single disk. This is the same system BTW. Some BIOSes do not always set CF on error before return from int13. The patch adds additional check for status being zero (AH == 0). This was fixed for edd.S in http://marc.info/?l=linux-kernel&m=114087765422490&w=2, but lost again when edd.S was rewritten in C. Signed-off-by: Andrey Borzenkov Signed-off-by: Ingo Molnar --- arch/x86/boot/edd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c index d93cbc6464d..bf4ae6ff518 100644 --- a/arch/x86/boot/edd.c +++ b/arch/x86/boot/edd.c @@ -32,7 +32,9 @@ static int read_mbr(u8 devno, void *buf) : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) : : "esi", "edi", "memory"); - return -(u8)ax; /* 0 or -1 */ + /* Some BIOSes do not set carry flag on error but still return + * error in AH. The condition below is expected to catch both */ + return -!!ax; /* 0 or -1 */ } static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) -- cgit v1.2.3 From 0722bba8f14eb5271c8b67e97def74da50eceb15 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 1 Sep 2008 18:14:51 +0200 Subject: x86: kill sys32_pause It's an unused duplicate of the generic sys_pause. Signed-off-by: Christoph Hellwig Signed-off-by: Ingo Molnar --- arch/x86/ia32/sys_ia32.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index d3c64088b98..beda4232ce6 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -556,15 +556,6 @@ asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig, return ret; } -/* These are here just in case some old ia32 binary calls it. */ -asmlinkage long sys32_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - - #ifdef CONFIG_SYSCTL_SYSCALL struct sysctl_ia32 { unsigned int name; -- cgit v1.2.3 From a19aac8548d85cf15d744335b8e82201da760d80 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 30 Aug 2008 06:03:34 +0400 Subject: x86: make setup_xstate_init() __init WARNING: vmlinux.o(.text+0x22453): Section mismatch in reference from the function setup_xstate_init() to the function .init.text:__alloc_bootmem() The function setup_xstate_init() references the function __init __alloc_bootmem(). This is often because setup_xstate_init lacks a __init annotation or the annotation of __alloc_bootmem is wrong. Signed-off-by: Alexey Dobriyan Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 07713d64deb..ed5274a5bb0 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -272,7 +272,7 @@ void __cpuinit xsave_init(void) /* * setup the xstate image representing the init state */ -void setup_xstate_init(void) +static void __init setup_xstate_init(void) { init_xstate_buf = alloc_bootmem(xstate_size); init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; -- cgit v1.2.3 From 30cec97967beb5aa08e893e8ff69623d5fecd9b7 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 29 Aug 2008 12:49:55 +0100 Subject: x86: init annotations in early_printk() setup Signed-off-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/kernel/early_printk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 825e9136b02..02fc5b40c14 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -120,7 +120,7 @@ static __init void early_serial_init(char *s) if (!strncmp(s, "0x", 2)) { early_serial_base = simple_strtoul(s, &e, 16); } else { - static int bases[] = { 0x3f8, 0x2f8 }; + static const int __initconst bases[] = { 0x3f8, 0x2f8 }; if (!strncmp(s, "ttyS", 4)) s += 4; @@ -920,7 +920,7 @@ static struct console simnow_console = { /* Direct interface for emergencies */ static struct console *early_console = &early_vga_console; -static int early_console_initialized; +static int __initdata early_console_initialized; asmlinkage void early_printk(const char *fmt, ...) { -- cgit v1.2.3 From 17b746278da8d6642bc487ec35efe4be2333f03f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 29 Aug 2008 12:51:32 +0100 Subject: x86: pgd_{c,d}tor() cleanup Giving pgd_ctor() a properly typed parameter allows eliminating a local variable. Adjust pgd_dtor() to match. Signed-off-by: Jan Beulich Acked-by: Jeremy Fitzhardinge Cc: "Jeremy Fitzhardinge" Signed-off-by: Ingo Molnar --- arch/x86/mm/pgtable.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index d50302774fe..86f2ffc43c3 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -63,10 +63,8 @@ static inline void pgd_list_del(pgd_t *pgd) #define UNSHARED_PTRS_PER_PGD \ (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD) -static void pgd_ctor(void *p) +static void pgd_ctor(pgd_t *pgd) { - pgd_t *pgd = p; - /* If the pgd points to a shared pagetable level (either the ptes in non-PAE, or shared PMD in PAE), then just copy the references from swapper_pg_dir. */ @@ -87,7 +85,7 @@ static void pgd_ctor(void *p) pgd_list_add(pgd); } -static void pgd_dtor(void *pgd) +static void pgd_dtor(pgd_t *pgd) { unsigned long flags; /* can be called from interrupt context */ -- cgit v1.2.3 From cc643d4687533345fd8ebcba836f9ee25df7c458 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 29 Aug 2008 12:53:45 +0100 Subject: x86: adjust vmalloc_sync_all() for Xen (2nd try) Since the fourth PDPT entry cannot be shared under Xen, vmalloc_sync_all() must iterate over pmd-s rather than pgd-s here. Luckily, the code isn't used for native PAE (SHARED_KERNEL_PMD is 1) and the change is benign to non-PAE. Also do a little more cleanup in that function. Signed-off-by: Jan Beulich Signed-off-by: Ingo Molnar Cc: Jeremy Fitzhardinge --- arch/x86/mm/fault.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 455f3fe67b4..356ed2dec3a 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -915,15 +915,15 @@ LIST_HEAD(pgd_list); void vmalloc_sync_all(void) { -#ifdef CONFIG_X86_32 - unsigned long start = VMALLOC_START & PGDIR_MASK; unsigned long address; +#ifdef CONFIG_X86_32 if (SHARED_KERNEL_PMD) return; - BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK); - for (address = start; address >= TASK_SIZE; address += PGDIR_SIZE) { + for (address = VMALLOC_START & PMD_MASK; + address >= TASK_SIZE && address < FIXADDR_TOP; + address += PMD_SIZE) { unsigned long flags; struct page *page; @@ -936,10 +936,8 @@ void vmalloc_sync_all(void) spin_unlock_irqrestore(&pgd_lock, flags); } #else /* CONFIG_X86_64 */ - unsigned long start = VMALLOC_START & PGDIR_MASK; - unsigned long address; - - for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) { + for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END; + address += PGDIR_SIZE) { const pgd_t *pgd_ref = pgd_offset_k(address); unsigned long flags; struct page *page; -- cgit v1.2.3 From 2d9cd6c27f00958a31622b8e9909d5e35f069b28 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 29 Aug 2008 13:15:04 +0100 Subject: x86-64: add two __cpuinit annotations Signed-off-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/cpu/mcheck/mce_64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index e8045c4ef1c..5cde4b18448 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -845,7 +845,7 @@ struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; -void pda_init(int cpu) +void __cpuinit pda_init(int cpu) { struct x8664_pda *pda = cpu_pda(cpu); diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 726a5fcdf34..4b031a4ac85 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -860,7 +860,7 @@ error: return err; } -static void mce_remove_device(unsigned int cpu) +static __cpuinit void mce_remove_device(unsigned int cpu) { int i; -- cgit v1.2.3 From 15e2fc9bbf946f999c78fe24cb1bc03c7256acab Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Sep 2008 14:11:47 +0100 Subject: PowerPC: Use Signed-off-by: David Woodhouse --- arch/powerpc/include/asm/statfs.h | 54 --------------------------------------- 1 file changed, 54 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/include/asm/statfs.h b/arch/powerpc/include/asm/statfs.h index 67024026c10..5244834583a 100644 --- a/arch/powerpc/include/asm/statfs.h +++ b/arch/powerpc/include/asm/statfs.h @@ -1,60 +1,6 @@ #ifndef _ASM_POWERPC_STATFS_H #define _ASM_POWERPC_STATFS_H -/* For ppc32 we just use the generic definitions, not so simple on ppc64 */ - -#ifndef __powerpc64__ #include -#else - -#ifndef __KERNEL_STRICT_NAMES -#include -typedef __kernel_fsid_t fsid_t; -#endif - -/* - * We're already 64-bit, so duplicate the definition - */ -struct statfs { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; - -struct statfs64 { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; -struct compat_statfs64 { - __u32 f_type; - __u32 f_bsize; - __u64 f_blocks; - __u64 f_bfree; - __u64 f_bavail; - __u64 f_files; - __u64 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -}; -#endif /* ! __powerpc64__ */ #endif -- cgit v1.2.3 From 52d90f4dad1352a6077ad6e93650ecea9b258f56 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Sep 2008 14:12:19 +0100 Subject: SPARC: Use Signed-off-by: David Woodhouse --- arch/sparc/include/asm/Kbuild | 2 -- arch/sparc/include/asm/statfs.h | 8 +++--- arch/sparc/include/asm/statfs_32.h | 6 ----- arch/sparc/include/asm/statfs_64.h | 54 -------------------------------------- 4 files changed, 3 insertions(+), 67 deletions(-) delete mode 100644 arch/sparc/include/asm/statfs_32.h delete mode 100644 arch/sparc/include/asm/statfs_64.h (limited to 'arch') diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index a5f0ce734ff..3f1cb7ad0d6 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -15,8 +15,6 @@ header-y += signal_32.h header-y += signal_64.h header-y += stat_32.h header-y += stat_64.h -header-y += statfs_32.h -header-y += statfs_64.h header-y += unistd_32.h header-y += unistd_64.h diff --git a/arch/sparc/include/asm/statfs.h b/arch/sparc/include/asm/statfs.h index 5e937a73743..55e607ad461 100644 --- a/arch/sparc/include/asm/statfs.h +++ b/arch/sparc/include/asm/statfs.h @@ -1,8 +1,6 @@ #ifndef ___ASM_SPARC_STATFS_H #define ___ASM_SPARC_STATFS_H -#if defined(__sparc__) && defined(__arch64__) -#include -#else -#include -#endif + +#include + #endif diff --git a/arch/sparc/include/asm/statfs_32.h b/arch/sparc/include/asm/statfs_32.h deleted file mode 100644 index 304520fa886..00000000000 --- a/arch/sparc/include/asm/statfs_32.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SPARC_STATFS_H -#define _SPARC_STATFS_H - -#include - -#endif diff --git a/arch/sparc/include/asm/statfs_64.h b/arch/sparc/include/asm/statfs_64.h deleted file mode 100644 index 79b3c890a5f..00000000000 --- a/arch/sparc/include/asm/statfs_64.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _SPARC64_STATFS_H -#define _SPARC64_STATFS_H - -#ifndef __KERNEL_STRICT_NAMES - -#include - -typedef __kernel_fsid_t fsid_t; - -#endif - -struct statfs { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; - -struct statfs64 { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; - -struct compat_statfs64 { - __u32 f_type; - __u32 f_bsize; - __u64 f_blocks; - __u64 f_bfree; - __u64 f_bavail; - __u64 f_files; - __u64 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -}; - -#endif -- cgit v1.2.3 From 5cfba5df8c76851ab311a2818a5e688f20833cac Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Sep 2008 14:12:51 +0100 Subject: S390: Update comments about why we don't use Signed-off-by: David Woodhouse --- arch/s390/include/asm/statfs.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/statfs.h b/arch/s390/include/asm/statfs.h index 099a4557919..06cc70307ec 100644 --- a/arch/s390/include/asm/statfs.h +++ b/arch/s390/include/asm/statfs.h @@ -12,19 +12,16 @@ #ifndef __s390x__ #include #else +/* + * We can't use because in 64-bit mode + * we mix ints of different sizes in our struct statfs. + */ #ifndef __KERNEL_STRICT_NAMES - #include - typedef __kernel_fsid_t fsid_t; - #endif -/* - * This is ugly -- we're already 64-bit clean, so just duplicate the - * definitions. - */ struct statfs { int f_type; int f_bsize; -- cgit v1.2.3 From 6b213e1bc27da6f6280386b1ff0e817e602c7b7a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 16 Jun 2008 12:39:13 +0100 Subject: Remove redundant CONFIG_ARCH_SUPPORTS_AOUT We don't need this any more; arguably we never really did. Signed-off-by: David Woodhouse --- arch/alpha/Kconfig | 3 --- arch/arm/Kconfig | 3 --- arch/h8300/Kconfig | 3 --- arch/m32r/Kconfig | 3 --- arch/m68k/Kconfig | 3 --- arch/m68knommu/Kconfig | 3 --- arch/mn10300/Kconfig | 3 --- arch/parisc/Kconfig | 3 --- arch/um/Kconfig.i386 | 3 --- arch/um/Kconfig.x86_64 | 3 --- arch/x86/Kconfig | 5 +---- 11 files changed, 1 insertion(+), 34 deletions(-) (limited to 'arch') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 1bec55d63ef..46f0ddfb78e 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -68,9 +68,6 @@ config AUTO_IRQ_AFFINITY depends on SMP default y -config ARCH_SUPPORTS_AOUT - def_bool y - source "init/Kconfig" diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 70dba166890..8803c39112b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -140,9 +140,6 @@ config GENERIC_CALIBRATE_DELAY bool default y -config ARCH_SUPPORTS_AOUT - def_bool y - config ARCH_MAY_HAVE_PC_FDC bool diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 396ab059efa..107cb5bb9f3 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -66,9 +66,6 @@ config TIME_LOW_RES bool default y -config ARCH_SUPPORTS_AOUT - def_bool y - config NO_IOPORT def_bool y diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index a5f864c445b..8a165cc1b73 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -36,9 +36,6 @@ config NO_IOPORT config NO_DMA def_bool y -config ARCH_SUPPORTS_AOUT - def_bool y - config HZ int default 100 diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 8c5e1de68fc..d42b996a24a 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -53,9 +53,6 @@ config NO_IOPORT config NO_DMA def_bool SUN3 -config ARCH_SUPPORTS_AOUT - def_bool y - config HZ int default 100 diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 2e7515e8db9..0a8998315e5 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -73,9 +73,6 @@ config GENERIC_CLOCKEVENTS config NO_IOPORT def_bool y -config ARCH_SUPPORTS_AOUT - def_bool y - source "init/Kconfig" menu "Processor type and features" diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index e856218da90..dd557c9cf00 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -53,9 +53,6 @@ config QUICKLIST config ARCH_HAS_ILOG2_U32 def_bool y -config ARCH_SUPPORTS_AOUT - def_bool n - # Use the generic interrupt handling code in kernel/irq/ config GENERIC_HARDIRQS def_bool y diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index a7d4fd353c2..8313fccced5 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -76,9 +76,6 @@ config IRQ_PER_CPU bool default y -config ARCH_SUPPORTS_AOUT - def_bool y - # unless you want to implement ACPI on PA-RISC ... ;-) config PM bool diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index e09edfa560d..2a44e5c0a3b 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -42,6 +42,3 @@ config ARCH_REUSE_HOST_VSYSCALL_AREA config GENERIC_HWEIGHT bool default y - -config ARCH_SUPPORTS_AOUT - def_bool y diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64 index 5696e7b374b..40b3407cfe1 100644 --- a/arch/um/Kconfig.x86_64 +++ b/arch/um/Kconfig.x86_64 @@ -37,6 +37,3 @@ config SMP_BROKEN config GENERIC_HWEIGHT bool default y - -config ARCH_SUPPORTS_AOUT - def_bool y diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed92864d132..2e8fa40b3cd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -151,9 +151,6 @@ config AUDIT_ARCH bool default X86_64 -config ARCH_SUPPORTS_AOUT - def_bool y - config ARCH_SUPPORTS_OPTIMIZED_INLINING def_bool y @@ -1759,7 +1756,7 @@ config IA32_EMULATION config IA32_AOUT tristate "IA32 a.out support" - depends on IA32_EMULATION && ARCH_SUPPORTS_AOUT + depends on IA32_EMULATION help Support old a.out binaries in the 32bit emulation. -- cgit v1.2.3 From e17c6d56160e4fb9e8c2830e30cc9741d4309989 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 17 Jun 2008 12:19:34 +0100 Subject: Introduce HAVE_AOUT symbol to remove hard-coded arch list for BINFMT_AOUT HAVE_AOUT doesn't quite do the same thing as the recently removed ARCH_SUPPORTS_AOUT config option. That was set even on platforms where binfmt_aout isn't supported, although it's not entirely clear why. So it's best just to introduce a new symbol, handled consistently with other similar HAVE_xxx symbols; with a simple 'select' in the arch Kconfig. Signed-off-by: David Woodhouse --- arch/alpha/Kconfig | 1 + arch/arm/Kconfig | 1 + arch/m68k/Kconfig | 1 + arch/um/Kconfig.i386 | 5 +++-- arch/x86/Kconfig | 1 + 5 files changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 46f0ddfb78e..ee35226c44e 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -5,6 +5,7 @@ config ALPHA bool default y + select HAVE_AOUT select HAVE_IDE select HAVE_OPROFILE help diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8803c39112b..2f7ef54ef3a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration" config ARM bool default y + select HAVE_AOUT select HAVE_IDE select RTC_LIB select SYS_SUPPORTS_APM_EMULATION diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index d42b996a24a..41e5bf02e23 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -5,6 +5,7 @@ config M68K bool default y + select HAVE_AOUT select HAVE_IDE config MMU diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 2a44e5c0a3b..1f57c113df6 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -9,8 +9,9 @@ config UML_X86 default y config X86_32 - bool - default y + bool + default y + select HAVE_AOUT config RWSEM_XCHGADD_ALGORITHM def_bool y diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2e8fa40b3cd..59b1d65a85e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -18,6 +18,7 @@ config X86_64 ### Arch settings config X86 def_bool y + select HAVE_AOUT if X86_32 select HAVE_UNSTABLE_SCHED_CLOCK select HAVE_IDE select HAVE_OPROFILE -- cgit v1.2.3 From 9d5a9e74655b9d04d0ec9c8e47801163b7b74211 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 28 Jun 2008 00:12:52 +0300 Subject: Remove asm/a.out.h files for all architectures without a.out support. This patch also includes the required removal of (unused) inclusion of 's in the arch/ code for these architectures. [dwmw2: updated for 2.6.27-rc] Signed-off-by: Adrian Bunk Signed-off-by: David Woodhouse --- arch/avr32/include/asm/a.out.h | 20 -------------------- arch/blackfin/include/asm/a.out.h | 19 ------------------- arch/cris/arch-v10/boot/tools/build.c | 1 - arch/h8300/include/asm/a.out.h | 20 -------------------- arch/h8300/kernel/process.c | 1 - arch/ia64/include/asm/a.out.h | 32 -------------------------------- arch/ia64/mm/init.c | 1 - arch/m68knommu/include/asm/a.out.h | 1 - arch/m68knommu/kernel/process.c | 1 - arch/m68knommu/kernel/traps.c | 1 - arch/mips/kernel/process.c | 1 - arch/mips/kernel/syscall.c | 1 - arch/powerpc/include/asm/a.out.h | 20 -------------------- arch/powerpc/kernel/softemu8xx.c | 1 - arch/powerpc/kernel/traps.c | 1 - arch/powerpc/platforms/chrp/setup.c | 1 - arch/powerpc/platforms/maple/setup.c | 1 - arch/powerpc/platforms/powermac/setup.c | 1 - arch/powerpc/platforms/pseries/setup.c | 1 - 19 files changed, 125 deletions(-) delete mode 100644 arch/avr32/include/asm/a.out.h delete mode 100644 arch/blackfin/include/asm/a.out.h delete mode 100644 arch/h8300/include/asm/a.out.h delete mode 100644 arch/ia64/include/asm/a.out.h delete mode 100644 arch/m68knommu/include/asm/a.out.h delete mode 100644 arch/powerpc/include/asm/a.out.h (limited to 'arch') diff --git a/arch/avr32/include/asm/a.out.h b/arch/avr32/include/asm/a.out.h deleted file mode 100644 index e46375a34a7..00000000000 --- a/arch/avr32/include/asm/a.out.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __ASM_AVR32_A_OUT_H -#define __ASM_AVR32_A_OUT_H - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#endif /* __ASM_AVR32_A_OUT_H */ diff --git a/arch/blackfin/include/asm/a.out.h b/arch/blackfin/include/asm/a.out.h deleted file mode 100644 index 6c3d652ebd3..00000000000 --- a/arch/blackfin/include/asm/a.out.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __BFIN_A_OUT_H__ -#define __BFIN_A_OUT_H__ - -struct exec { - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#endif /* __BFIN_A_OUT_H__ */ diff --git a/arch/cris/arch-v10/boot/tools/build.c b/arch/cris/arch-v10/boot/tools/build.c index 2f9bbb26d60..c8adef36416 100644 --- a/arch/cris/arch-v10/boot/tools/build.c +++ b/arch/cris/arch-v10/boot/tools/build.c @@ -30,7 +30,6 @@ #include #include /* contains read/write */ #include -#include #include #define MINIX_HEADER 32 diff --git a/arch/h8300/include/asm/a.out.h b/arch/h8300/include/asm/a.out.h deleted file mode 100644 index ded780f0a49..00000000000 --- a/arch/h8300/include/asm/a.out.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __H8300_A_OUT_H__ -#define __H8300_A_OUT_H__ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#endif /* __H8300_A_OUT_H__ */ diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index dfbe7ab9ffe..a8ef654a5a0 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ia64/include/asm/a.out.h b/arch/ia64/include/asm/a.out.h deleted file mode 100644 index 193dcfb6759..00000000000 --- a/arch/ia64/include/asm/a.out.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _ASM_IA64_A_OUT_H -#define _ASM_IA64_A_OUT_H - -/* - * No a.out format has been (or should be) defined so this file is - * just a dummy that allows us to get binfmt_elf compiled. It - * probably would be better to clean up binfmt_elf.c so it does not - * necessarily depend on there being a.out support. - * - * Modified 1998-2002 - * David Mosberger-Tang , Hewlett-Packard Co. - */ - -#include - -struct exec { - unsigned long a_info; - unsigned long a_text; - unsigned long a_data; - unsigned long a_bss; - unsigned long a_entry; -}; - -#define N_TXTADDR(x) 0 -#define N_DATADDR(x) 0 -#define N_BSSADDR(x) 0 -#define N_DRSIZE(x) 0 -#define N_TRSIZE(x) 0 -#define N_SYMSIZE(x) 0 -#define N_TXTOFF(x) 0 - -#endif /* _ASM_IA64_A_OUT_H */ diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 200100ea761..f482a9098e3 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/arch/m68knommu/include/asm/a.out.h b/arch/m68knommu/include/asm/a.out.h deleted file mode 100644 index ce18ef99de0..00000000000 --- a/arch/m68knommu/include/asm/a.out.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 47502d5ec19..3f2d7745f31 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index 46f8f9d0c40..5d5d56bcd0e 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index b16facd9ea8..17edc69cf5c 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 343015a2f41..37970d9b218 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -7,7 +7,6 @@ * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 2001 MIPS Technologies, Inc. */ -#include #include #include #include diff --git a/arch/powerpc/include/asm/a.out.h b/arch/powerpc/include/asm/a.out.h deleted file mode 100644 index 89cead6b176..00000000000 --- a/arch/powerpc/include/asm/a.out.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _ASM_POWERPC_A_OUT_H -#define _ASM_POWERPC_A_OUT_H - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#endif /* _ASM_POWERPC_A_OUT_H */ diff --git a/arch/powerpc/kernel/softemu8xx.c b/arch/powerpc/kernel/softemu8xx.c index c906c4bf683..23c8c5e7dc4 100644 --- a/arch/powerpc/kernel/softemu8xx.c +++ b/arch/powerpc/kernel/softemu8xx.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 81ccb8dd1a5..f5def6cf5cd 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 1ba7ce5aafa..272d79a8d28 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 364714757cf..d4c61c3c966 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 88ccf3a08a9..82c14d203d8 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 7b01d67b4e4..ec341707e41 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 5df45515512436a808d3476a90e83f2efb022422 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 6 Sep 2008 23:55:40 +0200 Subject: x86, tsc calibration: fix my brown paperbag day ... Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 6dab90f6851..4847a928050 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -319,7 +319,7 @@ static unsigned long quick_pit_calibrate(void) /* * Make sure we can rely on the second TSC timestamp: */ - if (!pit_expect_msb(--expect)) + if (!pit_expect_msb(expect)) goto failed; /* -- cgit v1.2.3 From 5394f80f92642c61fc2a95385be85f2fdcfb5adb Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 7 Sep 2008 01:51:32 -0700 Subject: x86: check for and defend against BIOS memory corruption Some BIOSes have been observed to corrupt memory in the low 64k. This change: - Reserves all memory which does not have to be in that area, to prevent it from being used as general memory by the kernel. Things like the SMP trampoline are still in the memory, however. - Clears the reserved memory so we can observe changes to it. - Adds a function check_for_bios_corruption() which checks and reports on memory becoming unexpectedly non-zero. Currently it's called in the x86 fault handler, and the powermanagement debug output. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 3 ++ arch/x86/kernel/setup.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ arch/x86/mm/fault.c | 2 ++ 3 files changed, 92 insertions(+) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed92864d132..1bb52e2ca02 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -201,6 +201,9 @@ config X86_TRAMPOLINE depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP) default y +config X86_CHECK_BIOS_CORRUPTION + def_bool y + config KTIME_SCALAR def_bool X86_32 source "init/Kconfig" diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 362d4e7f2d3..ee89ebc5aab 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -578,6 +578,89 @@ static struct x86_quirks default_x86_quirks __initdata; struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; +/* + * Some BIOSes seem to corrupt the low 64k of memory during events + * like suspend/resume and unplugging an HDMI cable. Reserve all + * remaining free memory in that area and fill it with a distinct + * pattern. + */ +#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION +#define MAX_SCAN_AREAS 8 +static struct e820entry scan_areas[MAX_SCAN_AREAS]; +static int num_scan_areas; + +static void __init setup_bios_corruption_check(void) +{ + u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */ + + while(addr < 0x10000 && num_scan_areas < MAX_SCAN_AREAS) { + u64 size; + addr = find_e820_area_size(addr, &size, PAGE_SIZE); + + if (addr == 0) + break; + + if ((addr + size) > 0x10000) + size = 0x10000 - addr; + + if (size == 0) + break; + + e820_update_range(addr, size, E820_RAM, E820_RESERVED); + scan_areas[num_scan_areas].addr = addr; + scan_areas[num_scan_areas].size = size; + num_scan_areas++; + + /* Assume we've already mapped this early memory */ + memset(__va(addr), 0, size); + + addr += size; + } + + printk(KERN_INFO "scanning %d areas for BIOS corruption\n", + num_scan_areas); + update_e820(); +} + +static int __read_mostly bios_corruption_check = 1; + +void check_for_bios_corruption(void) +{ + int i; + int corruption = 0; + + if (!bios_corruption_check) + return; + + for(i = 0; i < num_scan_areas; i++) { + unsigned long *addr = __va(scan_areas[i].addr); + unsigned long size = scan_areas[i].size; + + for(; size; addr++, size -= sizeof(unsigned long)) { + if (!*addr) + continue; + printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n", + addr, __pa(addr), *addr); + corruption = 1; + *addr = 0; + } + } + + if (corruption) + dump_stack(); +} + +static int set_bios_corruption_check(char *arg) +{ + char *end; + + bios_corruption_check = simple_strtol(arg, &end, 10); + + return (*end == 0) ? 0 : -EINVAL; +} +early_param("bios_corruption_check", set_bios_corruption_check); +#endif + /* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures @@ -750,6 +833,10 @@ void __init setup_arch(char **cmdline_p) high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; #endif +#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION + setup_bios_corruption_check(); +#endif + /* max_pfn_mapped is updated here */ max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn< Date: Sun, 7 Sep 2008 01:51:33 -0700 Subject: x86: add periodic corruption check Perodically check for corruption in low phusical memory. Don't bother checking at fault time, since it won't show anything useful. Signed-off-by: Hugh Dickins Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 17 +++++++++++++++++ arch/x86/mm/fault.c | 2 -- arch/x86/mm/init_32.c | 2 ++ arch/x86/mm/init_64.c | 2 ++ 4 files changed, 21 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index ee89ebc5aab..c239b378097 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -623,6 +623,7 @@ static void __init setup_bios_corruption_check(void) } static int __read_mostly bios_corruption_check = 1; +static struct timer_list periodic_check_timer; void check_for_bios_corruption(void) { @@ -650,6 +651,22 @@ void check_for_bios_corruption(void) dump_stack(); } +static void periodic_check_for_corruption(unsigned long data) +{ + check_for_bios_corruption(); + mod_timer(&periodic_check_timer, jiffies + 60*HZ); +} + +void start_periodic_check_for_corruption(void) +{ + if (!bios_corruption_check) + return; + + init_timer(&periodic_check_timer); + periodic_check_timer.function = &periodic_check_for_corruption; + periodic_check_for_corruption(0); +} + static int set_bios_corruption_check(char *arg) { char *end; diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 5140bdf0302..455f3fe67b4 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -848,8 +848,6 @@ no_context: * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ - check_for_bios_corruption(); - #ifdef CONFIG_X86_32 bust_spinlocks(1); #else diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d37f29376b0..657a16ad61b 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -907,6 +907,8 @@ void __init mem_init(void) int codesize, reservedpages, datasize, initsize; int tmp; + start_periodic_check_for_corruption(); + #ifdef CONFIG_FLATMEM BUG_ON(!mem_map); #endif diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index d3746efb060..f4db5276fa2 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -769,6 +769,8 @@ void __init mem_init(void) { long codesize, reservedpages, datasize, initsize; + start_periodic_check_for_corruption(); + pci_iommu_alloc(); /* clear_bss() already clear the empty_zero_page */ -- cgit v1.2.3 From 9f077871ce7237e2387fc76542b3b4033cb05e49 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 7 Sep 2008 01:51:34 -0700 Subject: x86: clean up memory corruption check and add more kernel parameters The corruption check is enabled in Kconfig by default, but disabled at runtime. This patch adds several kernel parameters to control the corruption check's behaviour; these are documented in kernel-parameters.txt. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 26 ++++++++++++++-- arch/x86/kernel/setup.c | 80 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 83 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1bb52e2ca02..cbee4199689 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -201,9 +201,6 @@ config X86_TRAMPOLINE depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP) default y -config X86_CHECK_BIOS_CORRUPTION - def_bool y - config KTIME_SCALAR def_bool X86_32 source "init/Kconfig" @@ -1062,6 +1059,29 @@ config HIGHPTE low memory. Setting this option will put user-space page table entries in high memory. +config X86_CHECK_BIOS_CORRUPTION + bool "Check for low memory corruption" + default y + help + Periodically check for memory corruption in low memory, which + is suspected to be caused by BIOS. Even when enabled in the + configuration, it is disabled at runtime. Enable it by + setting "memory_corruption_check=1" on the kernel command + line. By default it scans the low 64k of memory every 60 + seconds; see the memory_corruption_check_size and + memory_corruption_check_period parameters in + Documentation/kernel-parameters.txt to adjust this. + + When enabled with the default parameters, this option has + almost no overhead, as it reserves a relatively small amount + of memory and scans it infrequently. It both detects corruption + and prevents it from affecting the running system. + + It is, however, intended as a diagnostic tool; if repeatable + BIOS-originated corruption always affects the same memory, + you can use memmap= to prevent the kernel from using that + memory. + config MATH_EMULATION bool prompt "Math emulation" if X86_32 diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index c239b378097..27ae9128885 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -586,22 +586,71 @@ struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; */ #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION #define MAX_SCAN_AREAS 8 + +static int __read_mostly memory_corruption_check = 0; +static unsigned __read_mostly corruption_check_size = 64*1024; +static unsigned __read_mostly corruption_check_period = 60; /* seconds */ + static struct e820entry scan_areas[MAX_SCAN_AREAS]; static int num_scan_areas; + +static int set_corruption_check(char *arg) +{ + char *end; + + memory_corruption_check = simple_strtol(arg, &end, 10); + + return (*end == 0) ? 0 : -EINVAL; +} +early_param("memory_corruption_check", set_corruption_check); + +static int set_corruption_check_period(char *arg) +{ + char *end; + + corruption_check_period = simple_strtoul(arg, &end, 10); + + return (*end == 0) ? 0 : -EINVAL; +} +early_param("memory_corruption_check_period", set_corruption_check_period); + +static int set_corruption_check_size(char *arg) +{ + char *end; + unsigned size; + + size = memparse(arg, &end); + + if (*end == '\0') + corruption_check_size = size; + + return (size == corruption_check_size) ? 0 : -EINVAL; +} +early_param("memory_corruption_check_size", set_corruption_check_size); + + static void __init setup_bios_corruption_check(void) { u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */ - while(addr < 0x10000 && num_scan_areas < MAX_SCAN_AREAS) { + if (corruption_check_size == 0) + memory_corruption_check = 0; + + if (!memory_corruption_check) + return; + + corruption_check_size = round_up(corruption_check_size, PAGE_SIZE); + + while(addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) { u64 size; addr = find_e820_area_size(addr, &size, PAGE_SIZE); if (addr == 0) break; - if ((addr + size) > 0x10000) - size = 0x10000 - addr; + if ((addr + size) > corruption_check_size) + size = corruption_check_size - addr; if (size == 0) break; @@ -617,12 +666,11 @@ static void __init setup_bios_corruption_check(void) addr += size; } - printk(KERN_INFO "scanning %d areas for BIOS corruption\n", + printk(KERN_INFO "Scanning %d areas for low memory corruption\n", num_scan_areas); update_e820(); } -static int __read_mostly bios_corruption_check = 1; static struct timer_list periodic_check_timer; void check_for_bios_corruption(void) @@ -630,7 +678,7 @@ void check_for_bios_corruption(void) int i; int corruption = 0; - if (!bios_corruption_check) + if (!memory_corruption_check) return; for(i = 0; i < num_scan_areas; i++) { @@ -647,35 +695,27 @@ void check_for_bios_corruption(void) } } - if (corruption) - dump_stack(); + WARN(corruption, KERN_ERR "Memory corruption detected in low memory\n"); } static void periodic_check_for_corruption(unsigned long data) { check_for_bios_corruption(); - mod_timer(&periodic_check_timer, jiffies + 60*HZ); + mod_timer(&periodic_check_timer, jiffies + corruption_check_period*HZ); } void start_periodic_check_for_corruption(void) { - if (!bios_corruption_check) + if (!memory_corruption_check || corruption_check_period == 0) return; + printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n", + corruption_check_period); + init_timer(&periodic_check_timer); periodic_check_timer.function = &periodic_check_for_corruption; periodic_check_for_corruption(0); } - -static int set_bios_corruption_check(char *arg) -{ - char *end; - - bios_corruption_check = simple_strtol(arg, &end, 10); - - return (*end == 0) ? 0 : -EINVAL; -} -early_param("bios_corruption_check", set_bios_corruption_check); #endif /* -- cgit v1.2.3 From c885df50f571faf9fd9f395361cfff1b3a16e06e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 7 Sep 2008 02:37:32 -0700 Subject: x86: default corruption check to off, but put parameter default in Kconfig Default the low memory corruption check to off, but make the default setting of the memory_corruption_check kernel parameter a config parameter. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 9 ++++++++- arch/x86/kernel/setup.c | 13 ++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cbee4199689..7820d447bb8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1061,7 +1061,6 @@ config HIGHPTE config X86_CHECK_BIOS_CORRUPTION bool "Check for low memory corruption" - default y help Periodically check for memory corruption in low memory, which is suspected to be caused by BIOS. Even when enabled in the @@ -1082,6 +1081,14 @@ config X86_CHECK_BIOS_CORRUPTION you can use memmap= to prevent the kernel from using that memory. +config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK + bool "Set the default setting of memory_corruption_check" + depends on X86_CHECK_BIOS_CORRUPTION + default y + help + Set whether the default state of memory_corruption_check is + on or off. + config MATH_EMULATION bool prompt "Math emulation" if X86_32 diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 27ae9128885..ec7e56c1b98 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -587,7 +587,8 @@ struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION #define MAX_SCAN_AREAS 8 -static int __read_mostly memory_corruption_check = 0; +static int __read_mostly memory_corruption_check = -1; + static unsigned __read_mostly corruption_check_size = 64*1024; static unsigned __read_mostly corruption_check_period = 60; /* seconds */ @@ -634,6 +635,16 @@ static void __init setup_bios_corruption_check(void) { u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */ + if (memory_corruption_check == -1) { + memory_corruption_check = +#ifdef CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK + 1 +#else + 0 +#endif + ; + } + if (corruption_check_size == 0) memory_corruption_check = 0; -- cgit v1.2.3 From 3baca76f5653482f4b7fe1fc400b01877f6b2d92 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 7 Sep 2008 18:12:59 -0700 Subject: sparc64: fix wrong m48t59 RTC year Correctly calculate offset to the year register for Mostek RTC. Signed-off-by: Krzysztof Helt Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 209e7d28c3a..226a0042d87 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -500,6 +500,7 @@ static struct of_platform_driver bq4802_driver = { static unsigned char mostek_read_byte(struct device *dev, u32 ofs) { struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; void __iomem *regs; unsigned char val; @@ -507,7 +508,7 @@ static unsigned char mostek_read_byte(struct device *dev, u32 ofs) val = readb(regs + ofs); /* the year 0 is 1968 */ - if (ofs == M48T59_YEAR) { + if (ofs == pdata->offset + M48T59_YEAR) { val += 0x68; if ((val & 0xf) > 9) val += 6; @@ -518,10 +519,11 @@ static unsigned char mostek_read_byte(struct device *dev, u32 ofs) static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) { struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; void __iomem *regs; regs = (void __iomem *) pdev->resource[0].start; - if (ofs == M48T59_YEAR) { + if (ofs == pdata->offset + M48T59_YEAR) { if (val < 0x68) val += 0x32; else -- cgit v1.2.3 From 11fdd252bb5b461289fc5c21dc8fc87dc66f3284 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:50 -0700 Subject: x86: cpu make amd.c more like amd_64.c v2 1. make 32bit have early_init_amd_mc and amd_detect_cmp 2. seperate init_amd_k5/k6/k7 ... v2: fix compiling for !CONFIG_SMP Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 396 ++++++++++++++++++++++++------------------- arch/x86/kernel/cpu/amd_64.c | 17 +- arch/x86/kernel/cpu/common.c | 2 +- 3 files changed, 235 insertions(+), 180 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index c3175da7bc6..a3a9e3cbdea 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -24,8 +24,200 @@ extern void vide(void); __asm__(".align 4\nvide: ret"); +static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c) +{ +/* + * General Systems BIOSen alias the cpu frequency registers + * of the Elan at 0x000df000. Unfortuantly, one of the Linux + * drivers subsequently pokes it, and changes the CPU speed. + * Workaround : Remove the unneeded alias. + */ +#define CBAR (0xfffc) /* Configuration Base Address (32-bit) */ +#define CBAR_ENB (0x80000000) +#define CBAR_KEY (0X000000CB) + if (c->x86_model == 9 || c->x86_model == 10) { + if (inl (CBAR) & CBAR_ENB) + outl (0 | CBAR_KEY, CBAR); + } +} + + +static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) +{ + u32 l, h; + int mbytes = num_physpages >> (20-PAGE_SHIFT); + + if (c->x86_model < 6) { + /* Based on AMD doc 20734R - June 2000 */ + if (c->x86_model == 0) { + clear_cpu_cap(c, X86_FEATURE_APIC); + set_cpu_cap(c, X86_FEATURE_PGE); + } + return; + } + + if (c->x86_model == 6 && c->x86_mask == 1) { + const int K6_BUG_LOOP = 1000000; + int n; + void (*f_vide)(void); + unsigned long d, d2; + + printk(KERN_INFO "AMD K6 stepping B detected - "); + + /* + * It looks like AMD fixed the 2.6.2 bug and improved indirect + * calls at the same time. + */ + + n = K6_BUG_LOOP; + f_vide = vide; + rdtscl(d); + while (n--) + f_vide(); + rdtscl(d2); + d = d2-d; + + if (d > 20*K6_BUG_LOOP) + printk("system stability may be impaired when more than 32 MB are used.\n"); + else + printk("probably OK (after B9730xxxx).\n"); + printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n"); + } + + /* K6 with old style WHCR */ + if (c->x86_model < 8 || + (c->x86_model == 8 && c->x86_mask < 8)) { + /* We can only write allocate on the low 508Mb */ + if (mbytes > 508) + mbytes = 508; + + rdmsr(MSR_K6_WHCR, l, h); + if ((l&0x0000FFFF) == 0) { + unsigned long flags; + l = (1<<0)|((mbytes/4)<<1); + local_irq_save(flags); + wbinvd(); + wrmsr(MSR_K6_WHCR, l, h); + local_irq_restore(flags); + printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", + mbytes); + } + return; + } + + if ((c->x86_model == 8 && c->x86_mask > 7) || + c->x86_model == 9 || c->x86_model == 13) { + /* The more serious chips .. */ + + if (mbytes > 4092) + mbytes = 4092; + + rdmsr(MSR_K6_WHCR, l, h); + if ((l&0xFFFF0000) == 0) { + unsigned long flags; + l = ((mbytes>>2)<<22)|(1<<16); + local_irq_save(flags); + wbinvd(); + wrmsr(MSR_K6_WHCR, l, h); + local_irq_restore(flags); + printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n", + mbytes); + } + + return; + } + + if (c->x86_model == 10) { + /* AMD Geode LX is model 10 */ + /* placeholder for any needed mods */ + return; + } +} + +static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) +{ + u32 l, h; + + /* + * Bit 15 of Athlon specific MSR 15, needs to be 0 + * to enable SSE on Palomino/Morgan/Barton CPU's. + * If the BIOS didn't enable it already, enable it here. + */ + if (c->x86_model >= 6 && c->x86_model <= 10) { + if (!cpu_has(c, X86_FEATURE_XMM)) { + printk(KERN_INFO "Enabling disabled K7/SSE Support.\n"); + rdmsr(MSR_K7_HWCR, l, h); + l &= ~0x00008000; + wrmsr(MSR_K7_HWCR, l, h); + set_cpu_cap(c, X86_FEATURE_XMM); + } + } + + /* + * It's been determined by AMD that Athlons since model 8 stepping 1 + * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx + * As per AMD technical note 27212 0.2 + */ + if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) { + rdmsr(MSR_K7_CLK_CTL, l, h); + if ((l & 0xfff00000) != 0x20000000) { + printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l, + ((l & 0x000fffff)|0x20000000)); + wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h); + } + } + + set_cpu_cap(c, X86_FEATURE_K7); +} + +/* + * On a AMD dual core setup the lower bits of the APIC id distingush the cores. + * Assumes number of cores is a power of two. + */ +static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_HT + unsigned bits; + + bits = c->x86_coreid_bits; + + /* Low order bits define the core id (index of core in socket) */ + c->cpu_core_id = c->initial_apicid & ((1 << bits)-1); + /* Convert the initial APIC ID into the socket ID */ + c->phys_proc_id = c->initial_apicid >> bits; +#endif +} + +static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_HT + unsigned bits, ecx; + + /* Multi core CPU? */ + if (c->extended_cpuid_level < 0x80000008) + return; + + ecx = cpuid_ecx(0x80000008); + + c->x86_max_cores = (ecx & 0xff) + 1; + + /* CPU telling us the core id bits shift? */ + bits = (ecx >> 12) & 0xF; + + /* Otherwise recompute */ + if (bits == 0) { + while ((1 << bits) < c->x86_max_cores) + bits++; + } + + c->x86_coreid_bits = bits; +#endif +} + static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) { + early_init_amd_mc(c); + if (c->x86_power & (1<<8)) set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); @@ -37,9 +229,6 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) static void __cpuinit init_amd(struct cpuinfo_x86 *c) { - u32 l, h; - int mbytes = num_physpages >> (20-PAGE_SHIFT); - #ifdef CONFIG_SMP unsigned long long value; @@ -50,7 +239,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) * Errata 63 for SH-B3 steppings * Errata 122 for all steppings (F+ have it disabled by default) */ - if (c->x86 == 15) { + if (c->x86 == 0xf) { rdmsrl(MSR_K7_HWCR, value); value |= 1 << 6; wrmsrl(MSR_K7_HWCR, value); @@ -73,192 +262,55 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) switch (c->x86) { case 4: - /* - * General Systems BIOSen alias the cpu frequency registers - * of the Elan at 0x000df000. Unfortuantly, one of the Linux - * drivers subsequently pokes it, and changes the CPU speed. - * Workaround : Remove the unneeded alias. - */ -#define CBAR (0xfffc) /* Configuration Base Address (32-bit) */ -#define CBAR_ENB (0x80000000) -#define CBAR_KEY (0X000000CB) - if (c->x86_model == 9 || c->x86_model == 10) { - if (inl (CBAR) & CBAR_ENB) - outl (0 | CBAR_KEY, CBAR); - } - break; + init_amd_k5(c); + break; case 5: - if (c->x86_model < 6) { - /* Based on AMD doc 20734R - June 2000 */ - if (c->x86_model == 0) { - clear_cpu_cap(c, X86_FEATURE_APIC); - set_cpu_cap(c, X86_FEATURE_PGE); - } - break; - } - - if (c->x86_model == 6 && c->x86_mask == 1) { - const int K6_BUG_LOOP = 1000000; - int n; - void (*f_vide)(void); - unsigned long d, d2; - - printk(KERN_INFO "AMD K6 stepping B detected - "); - - /* - * It looks like AMD fixed the 2.6.2 bug and improved indirect - * calls at the same time. - */ - - n = K6_BUG_LOOP; - f_vide = vide; - rdtscl(d); - while (n--) - f_vide(); - rdtscl(d2); - d = d2-d; - - if (d > 20*K6_BUG_LOOP) - printk("system stability may be impaired when more than 32 MB are used.\n"); - else - printk("probably OK (after B9730xxxx).\n"); - printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n"); - } - - /* K6 with old style WHCR */ - if (c->x86_model < 8 || - (c->x86_model == 8 && c->x86_mask < 8)) { - /* We can only write allocate on the low 508Mb */ - if (mbytes > 508) - mbytes = 508; - - rdmsr(MSR_K6_WHCR, l, h); - if ((l&0x0000FFFF) == 0) { - unsigned long flags; - l = (1<<0)|((mbytes/4)<<1); - local_irq_save(flags); - wbinvd(); - wrmsr(MSR_K6_WHCR, l, h); - local_irq_restore(flags); - printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", - mbytes); - } - break; - } - - if ((c->x86_model == 8 && c->x86_mask > 7) || - c->x86_model == 9 || c->x86_model == 13) { - /* The more serious chips .. */ - - if (mbytes > 4092) - mbytes = 4092; - - rdmsr(MSR_K6_WHCR, l, h); - if ((l&0xFFFF0000) == 0) { - unsigned long flags; - l = ((mbytes>>2)<<22)|(1<<16); - local_irq_save(flags); - wbinvd(); - wrmsr(MSR_K6_WHCR, l, h); - local_irq_restore(flags); - printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n", - mbytes); - } - - break; - } - - if (c->x86_model == 10) { - /* AMD Geode LX is model 10 */ - /* placeholder for any needed mods */ - break; - } - break; - case 6: /* An Athlon/Duron */ - - /* - * Bit 15 of Athlon specific MSR 15, needs to be 0 - * to enable SSE on Palomino/Morgan/Barton CPU's. - * If the BIOS didn't enable it already, enable it here. - */ - if (c->x86_model >= 6 && c->x86_model <= 10) { - if (!cpu_has(c, X86_FEATURE_XMM)) { - printk(KERN_INFO "Enabling disabled K7/SSE Support.\n"); - rdmsr(MSR_K7_HWCR, l, h); - l &= ~0x00008000; - wrmsr(MSR_K7_HWCR, l, h); - set_cpu_cap(c, X86_FEATURE_XMM); - } - } - - /* - * It's been determined by AMD that Athlons since model 8 stepping 1 - * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx - * As per AMD technical note 27212 0.2 - */ - if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) { - rdmsr(MSR_K7_CLK_CTL, l, h); - if ((l & 0xfff00000) != 0x20000000) { - printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l, - ((l & 0x000fffff)|0x20000000)); - wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h); - } - } - break; - } - - switch (c->x86) { - case 15: - /* Use K8 tuning for Fam10h and Fam11h */ - case 0x10: - case 0x11: - set_cpu_cap(c, X86_FEATURE_K8); + init_amd_k6(c); break; - case 6: - set_cpu_cap(c, X86_FEATURE_K7); + case 6: /* An Athlon/Duron */ + init_amd_k7(c); break; } + + /* K6s reports MCEs but don't actually have all the MSRs */ + if (c->x86 < 6) + clear_cpu_cap(c, X86_FEATURE_MCE); + if (c->x86 >= 6) set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK); - display_cacheinfo(c); + if (!c->x86_model_id[0]) { + switch (c->x86) { + case 0xf: + /* Should distinguish Models here, but this is only + a fallback anyways. */ + strcpy(c->x86_model_id, "Hammer"); + break; + } + } - if (cpuid_eax(0x80000000) >= 0x80000008) - c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; + display_cacheinfo(c); -#ifdef CONFIG_X86_HT - /* - * On a AMD multi core setup the lower bits of the APIC id - * distinguish the cores. - */ - if (c->x86_max_cores > 1) { - int cpu = smp_processor_id(); - unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf; + /* Multi core CPU? */ + if (c->extended_cpuid_level >= 0x80000008) + amd_detect_cmp(c); - if (bits == 0) { - while ((1 << bits) < c->x86_max_cores) - bits++; - } - c->cpu_core_id = c->phys_proc_id & ((1<phys_proc_id >>= bits; - printk(KERN_INFO "CPU %d(%d) -> Core %d\n", - cpu, c->x86_max_cores, c->cpu_core_id); - } -#endif + detect_ht(c); - if (cpuid_eax(0x80000000) >= 0x80000006) { - if ((c->x86 == 0x10) && (cpuid_edx(0x80000006) & 0xf000)) + if (c->extended_cpuid_level >= 0x80000006) { + if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000)) num_cache_leaves = 4; else num_cache_leaves = 3; } - /* K6s reports MCEs but don't actually have all the MSRs */ - if (c->x86 < 6) - clear_cpu_cap(c, X86_FEATURE_MCE); + if (c->x86 >= 0xf && c->x86 <= 0x11) + set_cpu_cap(c, X86_FEATURE_K8); - if (cpu_has_xmm2) + if (cpu_has_xmm2) { + /* MFENCE stops RDTSC speculation */ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); + } } static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index 8c2d07f06f1..7913e48f673 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -174,17 +174,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) if (c->extended_cpuid_level >= 0x80000008) amd_detect_cmp(c); - if (c->extended_cpuid_level >= 0x80000006 && - (cpuid_edx(0x80000006) & 0xf000)) - num_cache_leaves = 4; - else - num_cache_leaves = 3; + if (c->extended_cpuid_level >= 0x80000006) { + if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000)) + num_cache_leaves = 4; + else + num_cache_leaves = 3; + } if (c->x86 >= 0xf && c->x86 <= 0x11) set_cpu_cap(c, X86_FEATURE_K8); - /* MFENCE stops RDTSC speculation */ - set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); + if (cpu_has_xmm2) { + /* MFENCE stops RDTSC speculation */ + set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); + } if (c->x86 == 0x10) { /* do this for boot cpu */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 5cde4b18448..9a57106c199 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -629,8 +629,8 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */ c->x86_max_cores = 1; -#ifdef CONFIG_X86_64 c->x86_coreid_bits = 0; +#ifdef CONFIG_X86_64 c->x86_clflush_size = 64; #else c->cpuid_level = -1; /* CPUID not detected */ -- cgit v1.2.3 From c58606ad551e9a1c85a9bd4f1698ca41ec279b2c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:51 -0700 Subject: x86: remove duplicated force_mwait Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd_64.c | 2 -- arch/x86/kernel/process.c | 1 - 2 files changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index 7913e48f673..466a1eaa81e 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -9,8 +9,6 @@ #include "cpu.h" -int force_mwait __cpuinitdata; - #ifdef CONFIG_NUMA static int __cpuinit nearby_node(int apicid) { diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7fc4d5b0a6a..9f94bb1c811 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -15,7 +15,6 @@ unsigned long idle_nomwait; EXPORT_SYMBOL(idle_nomwait); struct kmem_cache *task_xstate_cachep; -static int force_mwait __cpuinitdata; int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { -- cgit v1.2.3 From 2b86473604f6e9aef0b5e89c56798a90ccddcdbe Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:52 -0700 Subject: x86: add srat_detect_node for amd64 separate that from amd_detect_cmp() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd_64.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index 466a1eaa81e..20c3f12dfe7 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -36,19 +36,23 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP unsigned bits; -#ifdef CONFIG_NUMA - int cpu = smp_processor_id(); - int node = 0; - unsigned apicid = hard_smp_processor_id(); -#endif + bits = c->x86_coreid_bits; /* Low order bits define the core id (index of core in socket) */ c->cpu_core_id = c->initial_apicid & ((1 << bits)-1); /* Convert the initial APIC ID into the socket ID */ c->phys_proc_id = c->initial_apicid >> bits; +#endif +} +static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) +{ #ifdef CONFIG_NUMA + int cpu = smp_processor_id(); + int node; + unsigned apicid = hard_smp_processor_id(); + node = c->phys_proc_id; if (apicid_to_node[apicid] != NUMA_NO_NODE) node = apicid_to_node[apicid]; @@ -76,7 +80,6 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node); #endif -#endif } static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) @@ -169,8 +172,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) display_cacheinfo(c); /* Multi core CPU? */ - if (c->extended_cpuid_level >= 0x80000008) + if (c->extended_cpuid_level >= 0x80000008) { amd_detect_cmp(c); + srat_detect_node(c); + } if (c->extended_cpuid_level >= 0x80000006) { if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000)) -- cgit v1.2.3 From 8d71a2ea0ad4ef9b9076ffd44726bad1f0ccf59b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:53 -0700 Subject: x86: merge header in amd_64.c Singed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 8 ++++++++ arch/x86/kernel/cpu/amd_64.c | 13 ++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index a3a9e3cbdea..3c8090d1005 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -1,11 +1,19 @@ #include #include #include + #include #include #include +#ifdef CONFIG_X86_64 +# include +# include +# include +#endif + #include + #include "cpu.h" /* diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index 20c3f12dfe7..1d83601e85e 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -1,9 +1,16 @@ #include +#include #include -#include -#include -#include +#include +#include +#include + +#ifdef CONFIG_X86_64 +# include +# include +# include +#endif #include -- cgit v1.2.3 From 6c62aa4a3c12989a1f1fcbbe6f1ee5d4de4b2300 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:54 -0700 Subject: x86: make amd.c have 64bit support code Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 137 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 126 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 3c8090d1005..32e73520adf 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -16,6 +16,7 @@ #include "cpu.h" +#ifdef CONFIG_X86_32 /* * B step AMD K6 before B 9730xxxx have hardware bugs that can cause * misexecution of code under Linux. Owners of such processors should @@ -177,6 +178,26 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_K7); } +#endif + +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) +static int __cpuinit nearby_node(int apicid) +{ + int i, node; + + for (i = apicid - 1; i >= 0; i--) { + node = apicid_to_node[i]; + if (node != NUMA_NO_NODE && node_online(node)) + return node; + } + for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) { + node = apicid_to_node[i]; + if (node != NUMA_NO_NODE && node_online(node)) + return node; + } + return first_node(node_online_map); /* Shouldn't happen */ +} +#endif /* * On a AMD dual core setup the lower bits of the APIC id distingush the cores. @@ -196,6 +217,42 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) #endif } +static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) +{ +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) + int cpu = smp_processor_id(); + int node; + unsigned apicid = hard_smp_processor_id(); + + node = c->phys_proc_id; + if (apicid_to_node[apicid] != NUMA_NO_NODE) + node = apicid_to_node[apicid]; + if (!node_online(node)) { + /* Two possibilities here: + - The CPU is missing memory and no node was created. + In that case try picking one from a nearby CPU + - The APIC IDs differ from the HyperTransport node IDs + which the K8 northbridge parsing fills in. + Assume they are all increased by a constant offset, + but in the same order as the HT nodeids. + If that doesn't result in a usable node fall back to the + path for the previous case. */ + + int ht_nodeid = c->initial_apicid; + + if (ht_nodeid >= 0 && + apicid_to_node[ht_nodeid] != NUMA_NO_NODE) + node = apicid_to_node[ht_nodeid]; + /* Pick a nearby node */ + if (!node_online(node)) + node = nearby_node(apicid); + } + numa_set_node(cpu, node); + + printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node); +#endif +} + static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT @@ -226,13 +283,19 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) { early_init_amd_mc(c); + /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */ if (c->x86_power & (1<<8)) set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); +#ifdef CONFIG_X86_64 + set_cpu_cap(c, X86_FEATURE_SYSCALL32); +#else /* Set MTRR capability flag if appropriate */ - if (c->x86_model == 13 || c->x86_model == 9 || - (c->x86_model == 8 && c->x86_mask >= 8)) - set_cpu_cap(c, X86_FEATURE_K6_MTRR); + if (c->x86 == 5) + if (c->x86_model == 13 || c->x86_model == 9 || + (c->x86_model == 8 && c->x86_mask >= 8)) + set_cpu_cap(c, X86_FEATURE_K6_MTRR); +#endif } static void __cpuinit init_amd(struct cpuinfo_x86 *c) @@ -256,18 +319,31 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) early_init_amd(c); - /* - * FIXME: We should handle the K5 here. Set up the write - * range and also turn on MSR 83 bits 4 and 31 (write alloc, - * no bus pipeline) - */ - /* * Bit 31 in normal CPUID used for nonstandard 3DNow ID; * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_cpu_cap(c, 0*32+31); +#ifdef CONFIG_X86_64 + /* On C+ stepping K8 rep microcode works well for copy/memset */ + if (c->x86 == 0xf) { + u32 level; + + level = cpuid_eax(1); + if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58) + set_cpu_cap(c, X86_FEATURE_REP_GOOD); + } + if (c->x86 == 0x10 || c->x86 == 0x11) + set_cpu_cap(c, X86_FEATURE_REP_GOOD); +#else + + /* + * FIXME: We should handle the K5 here. Set up the write + * range and also turn on MSR 83 bits 4 and 31 (write alloc, + * no bus pipeline) + */ + switch (c->x86) { case 4: init_amd_k5(c); @@ -283,7 +359,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) /* K6s reports MCEs but don't actually have all the MSRs */ if (c->x86 < 6) clear_cpu_cap(c, X86_FEATURE_MCE); +#endif + /* Enable workaround for FXSAVE leak */ if (c->x86 >= 6) set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK); @@ -300,10 +378,14 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) display_cacheinfo(c); /* Multi core CPU? */ - if (c->extended_cpuid_level >= 0x80000008) + if (c->extended_cpuid_level >= 0x80000008) { amd_detect_cmp(c); + srat_detect_node(c); + } +#ifdef CONFIG_X86_32 detect_ht(c); +#endif if (c->extended_cpuid_level >= 0x80000006) { if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000)) @@ -319,8 +401,38 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) /* MFENCE stops RDTSC speculation */ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); } + +#ifdef CONFIG_X86_64 + if (c->x86 == 0x10) { + /* do this for boot cpu */ + if (c == &boot_cpu_data) + check_enable_amd_mmconf_dmi(); + + fam10h_check_enable_mmcfg(); + } + + if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) { + unsigned long long tseg; + + /* + * Split up direct mapping around the TSEG SMM area. + * Don't do it for gbpages because there seems very little + * benefit in doing so. + */ + if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) { + printk(KERN_DEBUG "tseg: %010llx\n", tseg); + if ((tseg>>PMD_SHIFT) < + (max_low_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) || + ((tseg>>PMD_SHIFT) < + (max_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) && + (tseg>>PMD_SHIFT) >= (1ULL<<(32 - PMD_SHIFT)))) + set_memory_4k((unsigned long)__va(tseg), 1); + } + } +#endif } +#ifdef CONFIG_X86_32 static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) { /* AMD errata T13 (order #21922) */ @@ -333,10 +445,12 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int } return size; } +#endif static struct cpu_dev amd_cpu_dev __cpuinitdata = { .c_vendor = "AMD", .c_ident = { "AuthenticAMD" }, +#ifdef CONFIG_X86_32 .c_models = { { .vendor = X86_VENDOR_AMD, .family = 4, .model_names = { @@ -349,9 +463,10 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = { } }, }, + .c_size_cache = amd_size_cache, +#endif .c_early_init = early_init_amd, .c_init = init_amd, - .c_size_cache = amd_size_cache, .c_x86_vendor = X86_VENDOR_AMD, }; -- cgit v1.2.3 From 2a02505055fdd44958efd0e140dd87cb9fdecaf1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:55 -0700 Subject: x86: make amd_64 have 32 bit code Signed-off-by: Yinghai Lu Cc: Yinghai Lu Cc: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd_64.c | 259 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 247 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index 1d83601e85e..32e73520adf 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -16,7 +16,171 @@ #include "cpu.h" -#ifdef CONFIG_NUMA +#ifdef CONFIG_X86_32 +/* + * B step AMD K6 before B 9730xxxx have hardware bugs that can cause + * misexecution of code under Linux. Owners of such processors should + * contact AMD for precise details and a CPU swap. + * + * See http://www.multimania.com/poulot/k6bug.html + * http://www.amd.com/K6/k6docs/revgd.html + * + * The following test is erm.. interesting. AMD neglected to up + * the chip setting when fixing the bug but they also tweaked some + * performance at the same time.. + */ + +extern void vide(void); +__asm__(".align 4\nvide: ret"); + +static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c) +{ +/* + * General Systems BIOSen alias the cpu frequency registers + * of the Elan at 0x000df000. Unfortuantly, one of the Linux + * drivers subsequently pokes it, and changes the CPU speed. + * Workaround : Remove the unneeded alias. + */ +#define CBAR (0xfffc) /* Configuration Base Address (32-bit) */ +#define CBAR_ENB (0x80000000) +#define CBAR_KEY (0X000000CB) + if (c->x86_model == 9 || c->x86_model == 10) { + if (inl (CBAR) & CBAR_ENB) + outl (0 | CBAR_KEY, CBAR); + } +} + + +static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) +{ + u32 l, h; + int mbytes = num_physpages >> (20-PAGE_SHIFT); + + if (c->x86_model < 6) { + /* Based on AMD doc 20734R - June 2000 */ + if (c->x86_model == 0) { + clear_cpu_cap(c, X86_FEATURE_APIC); + set_cpu_cap(c, X86_FEATURE_PGE); + } + return; + } + + if (c->x86_model == 6 && c->x86_mask == 1) { + const int K6_BUG_LOOP = 1000000; + int n; + void (*f_vide)(void); + unsigned long d, d2; + + printk(KERN_INFO "AMD K6 stepping B detected - "); + + /* + * It looks like AMD fixed the 2.6.2 bug and improved indirect + * calls at the same time. + */ + + n = K6_BUG_LOOP; + f_vide = vide; + rdtscl(d); + while (n--) + f_vide(); + rdtscl(d2); + d = d2-d; + + if (d > 20*K6_BUG_LOOP) + printk("system stability may be impaired when more than 32 MB are used.\n"); + else + printk("probably OK (after B9730xxxx).\n"); + printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n"); + } + + /* K6 with old style WHCR */ + if (c->x86_model < 8 || + (c->x86_model == 8 && c->x86_mask < 8)) { + /* We can only write allocate on the low 508Mb */ + if (mbytes > 508) + mbytes = 508; + + rdmsr(MSR_K6_WHCR, l, h); + if ((l&0x0000FFFF) == 0) { + unsigned long flags; + l = (1<<0)|((mbytes/4)<<1); + local_irq_save(flags); + wbinvd(); + wrmsr(MSR_K6_WHCR, l, h); + local_irq_restore(flags); + printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", + mbytes); + } + return; + } + + if ((c->x86_model == 8 && c->x86_mask > 7) || + c->x86_model == 9 || c->x86_model == 13) { + /* The more serious chips .. */ + + if (mbytes > 4092) + mbytes = 4092; + + rdmsr(MSR_K6_WHCR, l, h); + if ((l&0xFFFF0000) == 0) { + unsigned long flags; + l = ((mbytes>>2)<<22)|(1<<16); + local_irq_save(flags); + wbinvd(); + wrmsr(MSR_K6_WHCR, l, h); + local_irq_restore(flags); + printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n", + mbytes); + } + + return; + } + + if (c->x86_model == 10) { + /* AMD Geode LX is model 10 */ + /* placeholder for any needed mods */ + return; + } +} + +static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) +{ + u32 l, h; + + /* + * Bit 15 of Athlon specific MSR 15, needs to be 0 + * to enable SSE on Palomino/Morgan/Barton CPU's. + * If the BIOS didn't enable it already, enable it here. + */ + if (c->x86_model >= 6 && c->x86_model <= 10) { + if (!cpu_has(c, X86_FEATURE_XMM)) { + printk(KERN_INFO "Enabling disabled K7/SSE Support.\n"); + rdmsr(MSR_K7_HWCR, l, h); + l &= ~0x00008000; + wrmsr(MSR_K7_HWCR, l, h); + set_cpu_cap(c, X86_FEATURE_XMM); + } + } + + /* + * It's been determined by AMD that Athlons since model 8 stepping 1 + * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx + * As per AMD technical note 27212 0.2 + */ + if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) { + rdmsr(MSR_K7_CLK_CTL, l, h); + if ((l & 0xfff00000) != 0x20000000) { + printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l, + ((l & 0x000fffff)|0x20000000)); + wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h); + } + } + + set_cpu_cap(c, X86_FEATURE_K7); +} +#endif + +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) static int __cpuinit nearby_node(int apicid) { int i, node; @@ -41,7 +205,7 @@ static int __cpuinit nearby_node(int apicid) */ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) { -#ifdef CONFIG_SMP +#ifdef CONFIG_X86_HT unsigned bits; bits = c->x86_coreid_bits; @@ -55,7 +219,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) { -#ifdef CONFIG_NUMA +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) int cpu = smp_processor_id(); int node; unsigned apicid = hard_smp_processor_id(); @@ -91,7 +255,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) { -#ifdef CONFIG_SMP +#ifdef CONFIG_X86_HT unsigned bits, ecx; /* Multi core CPU? */ @@ -112,7 +276,6 @@ static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) } c->x86_coreid_bits = bits; - #endif } @@ -124,15 +287,21 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) if (c->x86_power & (1<<8)) set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); +#ifdef CONFIG_X86_64 set_cpu_cap(c, X86_FEATURE_SYSCALL32); +#else + /* Set MTRR capability flag if appropriate */ + if (c->x86 == 5) + if (c->x86_model == 13 || c->x86_model == 9 || + (c->x86_model == 8 && c->x86_mask >= 8)) + set_cpu_cap(c, X86_FEATURE_K6_MTRR); +#endif } static void __cpuinit init_amd(struct cpuinfo_x86 *c) { - unsigned level; - #ifdef CONFIG_SMP - unsigned long value; + unsigned long long value; /* * Disable TLB flush filter by setting HWCR.FFDIS on K8 @@ -142,26 +311,55 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) * Errata 122 for all steppings (F+ have it disabled by default) */ if (c->x86 == 0xf) { - rdmsrl(MSR_K8_HWCR, value); + rdmsrl(MSR_K7_HWCR, value); value |= 1 << 6; - wrmsrl(MSR_K8_HWCR, value); + wrmsrl(MSR_K7_HWCR, value); } #endif early_init_amd(c); - /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; - 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ + /* + * Bit 31 in normal CPUID used for nonstandard 3DNow ID; + * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway + */ clear_cpu_cap(c, 0*32+31); +#ifdef CONFIG_X86_64 /* On C+ stepping K8 rep microcode works well for copy/memset */ if (c->x86 == 0xf) { + u32 level; + level = cpuid_eax(1); if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58) set_cpu_cap(c, X86_FEATURE_REP_GOOD); } if (c->x86 == 0x10 || c->x86 == 0x11) set_cpu_cap(c, X86_FEATURE_REP_GOOD); +#else + + /* + * FIXME: We should handle the K5 here. Set up the write + * range and also turn on MSR 83 bits 4 and 31 (write alloc, + * no bus pipeline) + */ + + switch (c->x86) { + case 4: + init_amd_k5(c); + break; + case 5: + init_amd_k6(c); + break; + case 6: /* An Athlon/Duron */ + init_amd_k7(c); + break; + } + + /* K6s reports MCEs but don't actually have all the MSRs */ + if (c->x86 < 6) + clear_cpu_cap(c, X86_FEATURE_MCE); +#endif /* Enable workaround for FXSAVE leak */ if (c->x86 >= 6) @@ -176,6 +374,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) break; } } + display_cacheinfo(c); /* Multi core CPU? */ @@ -184,6 +383,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) srat_detect_node(c); } +#ifdef CONFIG_X86_32 + detect_ht(c); +#endif + if (c->extended_cpuid_level >= 0x80000006) { if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000)) num_cache_leaves = 4; @@ -199,6 +402,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); } +#ifdef CONFIG_X86_64 if (c->x86 == 0x10) { /* do this for boot cpu */ if (c == &boot_cpu_data) @@ -225,11 +429,42 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) set_memory_4k((unsigned long)__va(tseg), 1); } } +#endif +} + +#ifdef CONFIG_X86_32 +static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) +{ + /* AMD errata T13 (order #21922) */ + if ((c->x86 == 6)) { + if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */ + size = 64; + if (c->x86_model == 4 && + (c->x86_mask == 0 || c->x86_mask == 1)) /* Tbird rev A1/A2 */ + size = 256; + } + return size; } +#endif static struct cpu_dev amd_cpu_dev __cpuinitdata = { .c_vendor = "AMD", .c_ident = { "AuthenticAMD" }, +#ifdef CONFIG_X86_32 + .c_models = { + { .vendor = X86_VENDOR_AMD, .family = 4, .model_names = + { + [3] = "486 DX/2", + [7] = "486 DX/2-WB", + [8] = "486 DX/4", + [9] = "486 DX/4-WB", + [14] = "Am5x86-WT", + [15] = "Am5x86-WB" + } + }, + }, + .c_size_cache = amd_size_cache, +#endif .c_early_init = early_init_amd, .c_init = init_amd, .c_x86_vendor = X86_VENDOR_AMD, -- cgit v1.2.3 From ff73152ced60871f7d5fb7dee52fa499902a3c6d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:56 -0700 Subject: x86: make 64 bit to use amd.c arch/x86/kernel/cpu/amd.c is now 100% identical to arch/x86/kernel/cpu/amd_64.c, so use amd.c on 64-bit too and fix up the namespace impact. Simplify the Kconfig glue as well. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 10 +- arch/x86/kernel/cpu/Makefile | 3 +- arch/x86/kernel/cpu/amd_64.c | 473 ------------------------------------------- 3 files changed, 2 insertions(+), 484 deletions(-) delete mode 100644 arch/x86/kernel/cpu/amd_64.c (limited to 'arch') diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 6156ac25ff8..ab77d409fee 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -444,17 +444,9 @@ config CPU_SUP_CYRIX_32 help This enables extended support for Cyrix processors -config CPU_SUP_AMD_32 +config CPU_SUP_AMD default y bool "Support AMD processors" if PROCESSOR_SELECT - depends on !64BIT - help - This enables extended support for AMD processors - -config CPU_SUP_AMD_64 - default y - bool "Support AMD processors" if PROCESSOR_SELECT - depends on 64BIT help This enables extended support for AMD processors diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index d031f248dfc..510d1bcb058 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -10,8 +10,7 @@ obj-$(CONFIG_X86_64) += bugs_64.o obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o -obj-$(CONFIG_CPU_SUP_AMD_32) += amd.o -obj-$(CONFIG_CPU_SUP_AMD_64) += amd_64.o +obj-$(CONFIG_CPU_SUP_AMD) += amd.o obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o obj-$(CONFIG_CPU_SUP_CENTAUR_32) += centaur.o obj-$(CONFIG_CPU_SUP_CENTAUR_64) += centaur_64.o diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c deleted file mode 100644 index 32e73520adf..00000000000 --- a/arch/x86/kernel/cpu/amd_64.c +++ /dev/null @@ -1,473 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#ifdef CONFIG_X86_64 -# include -# include -# include -#endif - -#include - -#include "cpu.h" - -#ifdef CONFIG_X86_32 -/* - * B step AMD K6 before B 9730xxxx have hardware bugs that can cause - * misexecution of code under Linux. Owners of such processors should - * contact AMD for precise details and a CPU swap. - * - * See http://www.multimania.com/poulot/k6bug.html - * http://www.amd.com/K6/k6docs/revgd.html - * - * The following test is erm.. interesting. AMD neglected to up - * the chip setting when fixing the bug but they also tweaked some - * performance at the same time.. - */ - -extern void vide(void); -__asm__(".align 4\nvide: ret"); - -static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c) -{ -/* - * General Systems BIOSen alias the cpu frequency registers - * of the Elan at 0x000df000. Unfortuantly, one of the Linux - * drivers subsequently pokes it, and changes the CPU speed. - * Workaround : Remove the unneeded alias. - */ -#define CBAR (0xfffc) /* Configuration Base Address (32-bit) */ -#define CBAR_ENB (0x80000000) -#define CBAR_KEY (0X000000CB) - if (c->x86_model == 9 || c->x86_model == 10) { - if (inl (CBAR) & CBAR_ENB) - outl (0 | CBAR_KEY, CBAR); - } -} - - -static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) -{ - u32 l, h; - int mbytes = num_physpages >> (20-PAGE_SHIFT); - - if (c->x86_model < 6) { - /* Based on AMD doc 20734R - June 2000 */ - if (c->x86_model == 0) { - clear_cpu_cap(c, X86_FEATURE_APIC); - set_cpu_cap(c, X86_FEATURE_PGE); - } - return; - } - - if (c->x86_model == 6 && c->x86_mask == 1) { - const int K6_BUG_LOOP = 1000000; - int n; - void (*f_vide)(void); - unsigned long d, d2; - - printk(KERN_INFO "AMD K6 stepping B detected - "); - - /* - * It looks like AMD fixed the 2.6.2 bug and improved indirect - * calls at the same time. - */ - - n = K6_BUG_LOOP; - f_vide = vide; - rdtscl(d); - while (n--) - f_vide(); - rdtscl(d2); - d = d2-d; - - if (d > 20*K6_BUG_LOOP) - printk("system stability may be impaired when more than 32 MB are used.\n"); - else - printk("probably OK (after B9730xxxx).\n"); - printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n"); - } - - /* K6 with old style WHCR */ - if (c->x86_model < 8 || - (c->x86_model == 8 && c->x86_mask < 8)) { - /* We can only write allocate on the low 508Mb */ - if (mbytes > 508) - mbytes = 508; - - rdmsr(MSR_K6_WHCR, l, h); - if ((l&0x0000FFFF) == 0) { - unsigned long flags; - l = (1<<0)|((mbytes/4)<<1); - local_irq_save(flags); - wbinvd(); - wrmsr(MSR_K6_WHCR, l, h); - local_irq_restore(flags); - printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", - mbytes); - } - return; - } - - if ((c->x86_model == 8 && c->x86_mask > 7) || - c->x86_model == 9 || c->x86_model == 13) { - /* The more serious chips .. */ - - if (mbytes > 4092) - mbytes = 4092; - - rdmsr(MSR_K6_WHCR, l, h); - if ((l&0xFFFF0000) == 0) { - unsigned long flags; - l = ((mbytes>>2)<<22)|(1<<16); - local_irq_save(flags); - wbinvd(); - wrmsr(MSR_K6_WHCR, l, h); - local_irq_restore(flags); - printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n", - mbytes); - } - - return; - } - - if (c->x86_model == 10) { - /* AMD Geode LX is model 10 */ - /* placeholder for any needed mods */ - return; - } -} - -static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) -{ - u32 l, h; - - /* - * Bit 15 of Athlon specific MSR 15, needs to be 0 - * to enable SSE on Palomino/Morgan/Barton CPU's. - * If the BIOS didn't enable it already, enable it here. - */ - if (c->x86_model >= 6 && c->x86_model <= 10) { - if (!cpu_has(c, X86_FEATURE_XMM)) { - printk(KERN_INFO "Enabling disabled K7/SSE Support.\n"); - rdmsr(MSR_K7_HWCR, l, h); - l &= ~0x00008000; - wrmsr(MSR_K7_HWCR, l, h); - set_cpu_cap(c, X86_FEATURE_XMM); - } - } - - /* - * It's been determined by AMD that Athlons since model 8 stepping 1 - * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx - * As per AMD technical note 27212 0.2 - */ - if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) { - rdmsr(MSR_K7_CLK_CTL, l, h); - if ((l & 0xfff00000) != 0x20000000) { - printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l, - ((l & 0x000fffff)|0x20000000)); - wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h); - } - } - - set_cpu_cap(c, X86_FEATURE_K7); -} -#endif - -#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) -static int __cpuinit nearby_node(int apicid) -{ - int i, node; - - for (i = apicid - 1; i >= 0; i--) { - node = apicid_to_node[i]; - if (node != NUMA_NO_NODE && node_online(node)) - return node; - } - for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) { - node = apicid_to_node[i]; - if (node != NUMA_NO_NODE && node_online(node)) - return node; - } - return first_node(node_online_map); /* Shouldn't happen */ -} -#endif - -/* - * On a AMD dual core setup the lower bits of the APIC id distingush the cores. - * Assumes number of cores is a power of two. - */ -static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_X86_HT - unsigned bits; - - bits = c->x86_coreid_bits; - - /* Low order bits define the core id (index of core in socket) */ - c->cpu_core_id = c->initial_apicid & ((1 << bits)-1); - /* Convert the initial APIC ID into the socket ID */ - c->phys_proc_id = c->initial_apicid >> bits; -#endif -} - -static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) -{ -#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) - int cpu = smp_processor_id(); - int node; - unsigned apicid = hard_smp_processor_id(); - - node = c->phys_proc_id; - if (apicid_to_node[apicid] != NUMA_NO_NODE) - node = apicid_to_node[apicid]; - if (!node_online(node)) { - /* Two possibilities here: - - The CPU is missing memory and no node was created. - In that case try picking one from a nearby CPU - - The APIC IDs differ from the HyperTransport node IDs - which the K8 northbridge parsing fills in. - Assume they are all increased by a constant offset, - but in the same order as the HT nodeids. - If that doesn't result in a usable node fall back to the - path for the previous case. */ - - int ht_nodeid = c->initial_apicid; - - if (ht_nodeid >= 0 && - apicid_to_node[ht_nodeid] != NUMA_NO_NODE) - node = apicid_to_node[ht_nodeid]; - /* Pick a nearby node */ - if (!node_online(node)) - node = nearby_node(apicid); - } - numa_set_node(cpu, node); - - printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node); -#endif -} - -static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_X86_HT - unsigned bits, ecx; - - /* Multi core CPU? */ - if (c->extended_cpuid_level < 0x80000008) - return; - - ecx = cpuid_ecx(0x80000008); - - c->x86_max_cores = (ecx & 0xff) + 1; - - /* CPU telling us the core id bits shift? */ - bits = (ecx >> 12) & 0xF; - - /* Otherwise recompute */ - if (bits == 0) { - while ((1 << bits) < c->x86_max_cores) - bits++; - } - - c->x86_coreid_bits = bits; -#endif -} - -static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) -{ - early_init_amd_mc(c); - - /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */ - if (c->x86_power & (1<<8)) - set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); - -#ifdef CONFIG_X86_64 - set_cpu_cap(c, X86_FEATURE_SYSCALL32); -#else - /* Set MTRR capability flag if appropriate */ - if (c->x86 == 5) - if (c->x86_model == 13 || c->x86_model == 9 || - (c->x86_model == 8 && c->x86_mask >= 8)) - set_cpu_cap(c, X86_FEATURE_K6_MTRR); -#endif -} - -static void __cpuinit init_amd(struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_SMP - unsigned long long value; - - /* - * Disable TLB flush filter by setting HWCR.FFDIS on K8 - * bit 6 of msr C001_0015 - * - * Errata 63 for SH-B3 steppings - * Errata 122 for all steppings (F+ have it disabled by default) - */ - if (c->x86 == 0xf) { - rdmsrl(MSR_K7_HWCR, value); - value |= 1 << 6; - wrmsrl(MSR_K7_HWCR, value); - } -#endif - - early_init_amd(c); - - /* - * Bit 31 in normal CPUID used for nonstandard 3DNow ID; - * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway - */ - clear_cpu_cap(c, 0*32+31); - -#ifdef CONFIG_X86_64 - /* On C+ stepping K8 rep microcode works well for copy/memset */ - if (c->x86 == 0xf) { - u32 level; - - level = cpuid_eax(1); - if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58) - set_cpu_cap(c, X86_FEATURE_REP_GOOD); - } - if (c->x86 == 0x10 || c->x86 == 0x11) - set_cpu_cap(c, X86_FEATURE_REP_GOOD); -#else - - /* - * FIXME: We should handle the K5 here. Set up the write - * range and also turn on MSR 83 bits 4 and 31 (write alloc, - * no bus pipeline) - */ - - switch (c->x86) { - case 4: - init_amd_k5(c); - break; - case 5: - init_amd_k6(c); - break; - case 6: /* An Athlon/Duron */ - init_amd_k7(c); - break; - } - - /* K6s reports MCEs but don't actually have all the MSRs */ - if (c->x86 < 6) - clear_cpu_cap(c, X86_FEATURE_MCE); -#endif - - /* Enable workaround for FXSAVE leak */ - if (c->x86 >= 6) - set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK); - - if (!c->x86_model_id[0]) { - switch (c->x86) { - case 0xf: - /* Should distinguish Models here, but this is only - a fallback anyways. */ - strcpy(c->x86_model_id, "Hammer"); - break; - } - } - - display_cacheinfo(c); - - /* Multi core CPU? */ - if (c->extended_cpuid_level >= 0x80000008) { - amd_detect_cmp(c); - srat_detect_node(c); - } - -#ifdef CONFIG_X86_32 - detect_ht(c); -#endif - - if (c->extended_cpuid_level >= 0x80000006) { - if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000)) - num_cache_leaves = 4; - else - num_cache_leaves = 3; - } - - if (c->x86 >= 0xf && c->x86 <= 0x11) - set_cpu_cap(c, X86_FEATURE_K8); - - if (cpu_has_xmm2) { - /* MFENCE stops RDTSC speculation */ - set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); - } - -#ifdef CONFIG_X86_64 - if (c->x86 == 0x10) { - /* do this for boot cpu */ - if (c == &boot_cpu_data) - check_enable_amd_mmconf_dmi(); - - fam10h_check_enable_mmcfg(); - } - - if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) { - unsigned long long tseg; - - /* - * Split up direct mapping around the TSEG SMM area. - * Don't do it for gbpages because there seems very little - * benefit in doing so. - */ - if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) { - printk(KERN_DEBUG "tseg: %010llx\n", tseg); - if ((tseg>>PMD_SHIFT) < - (max_low_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) || - ((tseg>>PMD_SHIFT) < - (max_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) && - (tseg>>PMD_SHIFT) >= (1ULL<<(32 - PMD_SHIFT)))) - set_memory_4k((unsigned long)__va(tseg), 1); - } - } -#endif -} - -#ifdef CONFIG_X86_32 -static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) -{ - /* AMD errata T13 (order #21922) */ - if ((c->x86 == 6)) { - if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */ - size = 64; - if (c->x86_model == 4 && - (c->x86_mask == 0 || c->x86_mask == 1)) /* Tbird rev A1/A2 */ - size = 256; - } - return size; -} -#endif - -static struct cpu_dev amd_cpu_dev __cpuinitdata = { - .c_vendor = "AMD", - .c_ident = { "AuthenticAMD" }, -#ifdef CONFIG_X86_32 - .c_models = { - { .vendor = X86_VENDOR_AMD, .family = 4, .model_names = - { - [3] = "486 DX/2", - [7] = "486 DX/2-WB", - [8] = "486 DX/4", - [9] = "486 DX/4-WB", - [14] = "Am5x86-WT", - [15] = "Am5x86-WB" - } - }, - }, - .c_size_cache = amd_size_cache, -#endif - .c_early_init = early_init_amd, - .c_init = init_amd, - .c_x86_vendor = X86_VENDOR_AMD, -}; - -cpu_dev_register(amd_cpu_dev); -- cgit v1.2.3 From f69feff720497237ae9dd2f4604921bd3080c421 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 7 Sep 2008 17:58:58 -0700 Subject: x86: little clean up of intel.c/intel_64.c Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel.c | 7 +++---- arch/x86/kernel/cpu/intel_64.c | 8 +++----- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 959417b8cd6..4a8ac9d4ff5 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -76,7 +76,7 @@ static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) /* * find out the number of processor cores on the die */ -static int __cpuinit num_cpu_cores(struct cpuinfo_x86 *c) +static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) { unsigned int eax, ebx, ecx, edx; @@ -183,7 +183,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) * let's use the legacy cpuid vector 0x1 and 0x4 for topology * detection. */ - c->x86_max_cores = num_cpu_cores(c); + c->x86_max_cores = intel_num_cpu_cores(c); detect_ht(c); } @@ -210,9 +210,8 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if (cpu_has_xmm2) set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - if (c->x86 == 15) { + if (c->x86 == 15) set_cpu_cap(c, X86_FEATURE_P4); - } if (c->x86 == 6) set_cpu_cap(c, X86_FEATURE_P3); if (cpu_has_ds) { diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c index 14a2cd98d48..aef4f282631 100644 --- a/arch/x86/kernel/cpu/intel_64.c +++ b/arch/x86/kernel/cpu/intel_64.c @@ -71,17 +71,15 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_BTS); if (!(l1 & (1<<12))) set_cpu_cap(c, X86_FEATURE_PEBS); - } - - - if (cpu_has_bts) ds_init_intel(c); + } if (c->x86 == 15) c->x86_cache_alignment = c->x86_clflush_size * 2; if (c->x86 == 6) set_cpu_cap(c, X86_FEATURE_REP_GOOD); - set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); + if (cpu_has_xmm2) + set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); detect_extended_topology(c); if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) -- cgit v1.2.3 From 3a80b6aa271eb08a3da1a04b5cbdcdc19d4a5ae0 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 8 Sep 2008 18:10:10 +0900 Subject: ia64: dma_alloc_coherent always use GFP_DMA This patch makes dma_alloc_coherent use GFP_DMA at all times. This is necessary for swiotlb, which requires the callers to set up the gfp flags properly. swiotlb_alloc_coherent tries to allocate pages with the gfp flags. If the allocated memory isn't fit for dev->coherent_dma_mask, swiotlb_alloc_coherent reserves some of the swiotlb memory area, which is precious resource. So the callers need to set up the gfp flags properly. This patch means that other IA64 IOMMUs' dma_alloc_coherent also use GFP_DMA. These IOMMUs (e.g. SBA IOMMU) don't need GFP_DMA since they can map a memory to any address. But IA64's GFP_DMA is large, generally drivers allocate small memory with dma_alloc_coherent only at startup. So I chose the simplest way to set up the gfp flags for swiotlb. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/ia64/include/asm/dma-mapping.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index 9f0df9bd46b..06ff1ba2146 100644 --- a/arch/ia64/include/asm/dma-mapping.h +++ b/arch/ia64/include/asm/dma-mapping.h @@ -8,7 +8,9 @@ #include #include -#define dma_alloc_coherent platform_dma_alloc_coherent +#define dma_alloc_coherent(dev, size, handle, gfp) \ + platform_dma_alloc_coherent(dev, size, handle, (gfp) | GFP_DMA) + /* coherent mem. is cheap */ static inline void * dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle, -- cgit v1.2.3 From de9f521fb72dd091aa4989fe2e004ecf4785a850 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 8 Sep 2008 18:10:11 +0900 Subject: x86: move pci-nommu's dma_mask check to common code The check to see if dev->dma_mask is NULL in pci-nommu is more appropriate for dma_alloc_coherent(). Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-nommu.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 73853d3fdca..0f51883cc6a 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -80,9 +80,6 @@ nommu_alloc_coherent(struct device *hwdev, size_t size, int node; struct page *page; - if (hwdev->dma_mask == NULL) - return NULL; - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); gfp |= __GFP_ZERO; -- cgit v1.2.3 From 8a53ad675f86ee003482b557da944e070d3c4859 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 8 Sep 2008 18:10:12 +0900 Subject: x86: fix nommu_alloc_coherent allocation with NULL device argument We need to use __GFP_DMA for NULL device argument (fallback_dev) with pci-nommu. It's a hack for ISA (and some old code) so we need to use GFP_DMA. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-nommu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 0f51883cc6a..ada1c87cafc 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -80,7 +80,6 @@ nommu_alloc_coherent(struct device *hwdev, size_t size, int node; struct page *page; - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); gfp |= __GFP_ZERO; dma_mask = hwdev->coherent_dma_mask; @@ -93,7 +92,7 @@ nommu_alloc_coherent(struct device *hwdev, size_t size, node = dev_to_node(hwdev); #ifdef CONFIG_X86_64 - if (dma_mask <= DMA_32BIT_MASK) + if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) gfp |= GFP_DMA32; #endif -- cgit v1.2.3 From 823e7e8c6ef12cd1943dc42fe7595ca74e8cc3d7 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 8 Sep 2008 18:10:13 +0900 Subject: x86: dma_alloc_coherent sets gfp flags properly Non real IOMMU implemenations (which doesn't do virtual mappings, e.g. swiotlb, pci-nommu, etc) need to use proper gfp flags and dma_mask to allocate pages in their own dma_alloc_coherent() (allocated page need to be suitable for device's coherent_dma_mask). This patch makes dma_alloc_coherent do this job so that IOMMUs don't need to take care of it any more. Real IOMMU implemenataions can simply ignore the gfp flags. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-nommu.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index ada1c87cafc..8e398b56f50 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -80,26 +80,11 @@ nommu_alloc_coherent(struct device *hwdev, size_t size, int node; struct page *page; - gfp |= __GFP_ZERO; - - dma_mask = hwdev->coherent_dma_mask; - if (!dma_mask) - dma_mask = *(hwdev->dma_mask); + dma_mask = dma_alloc_coherent_mask(hwdev, gfp); - if (dma_mask < DMA_24BIT_MASK) - return NULL; + gfp |= __GFP_ZERO; node = dev_to_node(hwdev); - -#ifdef CONFIG_X86_64 - if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) - gfp |= GFP_DMA32; -#endif - - /* No alloc-free penalty for ISA devices */ - if (dma_mask == DMA_24BIT_MASK) - gfp |= GFP_DMA; - again: page = alloc_pages_node(node, gfp, get_order(size)); if (!page) -- cgit v1.2.3 From 2737146b3aa2cf8b5d5ae87a18c49fe1c374528b Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Mon, 8 Sep 2008 13:43:33 +0100 Subject: x86, xen: fix build when !CONFIG_HOTPLUG_CPU Signed-off-by: Alex Nixon Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/smp.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index be5cbb2b7c6..bf51a466d62 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -332,6 +332,7 @@ static void xen_smp_cpus_done(unsigned int max_cpus) { } +#ifdef CONFIG_HOTPLUG_CPU int xen_cpu_disable(void) { unsigned int cpu = smp_processor_id(); @@ -368,6 +369,23 @@ void xen_play_dead(void) cpu_bringup(); } +#else /* !CONFIG_HOTPLUG_CPU */ +int xen_cpu_disable(void) +{ + return -ENOSYS; +} + +void xen_cpu_die(unsigned int cpu) +{ + BUG(); +} + +void xen_play_dead(void) +{ + BUG(); +} + +#endif static void stop_self(void *v) { int cpu = smp_processor_id(); -- cgit v1.2.3 From 26fd10517e810dd59ea050b052de24a75ee6dc07 Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Mon, 8 Sep 2008 13:43:34 +0100 Subject: xen: make CPU hotplug functions static There's no need for these functions to be accessed from outside of xen/smp.c Signed-off-by: Alex Nixon Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/smp.c | 12 ++++++------ arch/x86/xen/xen-ops.h | 4 ---- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index bf51a466d62..d77da613b1d 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -333,7 +333,7 @@ static void xen_smp_cpus_done(unsigned int max_cpus) } #ifdef CONFIG_HOTPLUG_CPU -int xen_cpu_disable(void) +static int xen_cpu_disable(void) { unsigned int cpu = smp_processor_id(); if (cpu == 0) @@ -345,7 +345,7 @@ int xen_cpu_disable(void) return 0; } -void xen_cpu_die(unsigned int cpu) +static void xen_cpu_die(unsigned int cpu) { while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) { current->state = TASK_UNINTERRUPTIBLE; @@ -362,7 +362,7 @@ void xen_cpu_die(unsigned int cpu) alternatives_smp_switch(0); } -void xen_play_dead(void) +static void xen_play_dead(void) { play_dead_common(); HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); @@ -370,17 +370,17 @@ void xen_play_dead(void) } #else /* !CONFIG_HOTPLUG_CPU */ -int xen_cpu_disable(void) +static int xen_cpu_disable(void) { return -ENOSYS; } -void xen_cpu_die(unsigned int cpu) +static void xen_cpu_die(unsigned int cpu) { BUG(); } -void xen_play_dead(void) +static void xen_play_dead(void) { BUG(); } diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 8dbd97fd7f1..d7422dc2a55 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -51,10 +51,6 @@ void xen_mark_init_mm_pinned(void); void __init xen_setup_vcpu_info_placement(void); -void xen_play_dead(void); -void xen_cpu_die(unsigned int cpu); -int xen_cpu_disable(void); - #ifdef CONFIG_SMP void xen_smp_init(void); -- cgit v1.2.3 From e545a6140b698b2494daf0b32107bdcc5e901390 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Sun, 7 Sep 2008 16:57:22 +0200 Subject: kernel/cpu.c: create a CPU_STARTING cpu_chain notifier Right now, there is no notifier that is called on a new cpu, before the new cpu begins processing interrupts/softirqs. Various kernel function would need that notification, e.g. kvm works around by calling smp_call_function_single(), rcu polls cpu_online_map. The patch adds a CPU_STARTING notification. It also adds a helper function that sends the message to all cpu_chain handlers. Tested on x86-64. All other archs are untested. Especially on sparc, I'm not sure if I got it right. Signed-off-by: Manfred Spraul Signed-off-by: Ingo Molnar --- arch/alpha/kernel/smp.c | 3 +++ arch/arm/kernel/smp.c | 1 + arch/cris/arch-v32/kernel/smp.c | 1 + arch/ia64/kernel/smpboot.c | 1 + arch/m32r/kernel/smpboot.c | 2 ++ arch/mips/kernel/smp.c | 2 ++ arch/powerpc/kernel/smp.c | 1 + arch/s390/kernel/smp.c | 2 ++ arch/sh/kernel/smp.c | 2 ++ arch/sparc/kernel/sun4d_smp.c | 1 + arch/sparc/kernel/sun4m_smp.c | 2 ++ arch/um/kernel/smp.c | 1 + arch/x86/kernel/smpboot.c | 1 + arch/x86/mach-voyager/voyager_smp.c | 2 ++ 14 files changed, 22 insertions(+) (limited to 'arch') diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 83df541650f..06b6fdab639 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -149,6 +149,9 @@ smp_callin(void) atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; + /* inform the notifiers about the new cpu */ + notify_cpu_starting(cpuid); + /* Must have completely accurate bogos. */ local_irq_enable(); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e9842f6767f..e42a749a56d 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -277,6 +277,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) /* * Enable local interrupts. */ + notify_cpu_starting(cpu); local_irq_enable(); local_fiq_enable(); diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 952a24b2f5a..52e16c6436f 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -178,6 +178,7 @@ void __init smp_callin(void) unmask_irq(IPI_INTR_VECT); unmask_irq(TIMER0_INTR_VECT); preempt_disable(); + notify_cpu_starting(cpu); local_irq_enable(); cpu_set(cpu, cpu_online_map); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index bcea81e432f..333b58f218d 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -401,6 +401,7 @@ smp_callin (void) spin_lock(&vector_lock); /* Setup the per cpu irq handling data structures */ __setup_vector_irq(cpuid); + notify_cpu_starting(cpuid); cpu_set(cpuid, cpu_online_map); per_cpu(cpu_state, cpuid) = CPU_ONLINE; spin_unlock(&vector_lock); diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index 2c03ac1d005..fc2994811f1 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -498,6 +498,8 @@ static void __init smp_online(void) { int cpu_id = smp_processor_id(); + notify_cpu_starting(cpu_id); + local_irq_enable(); /* Get our bogomips. */ diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 4410f172b8a..7b59cfb7e60 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -121,6 +121,8 @@ asmlinkage __cpuinit void start_secondary(void) cpu = smp_processor_id(); cpu_data[cpu].udelay_val = loops_per_jiffy; + notify_cpu_starting(cpu); + mp_ops->smp_finish(); set_cpu_sibling_map(cpu); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 5337ca7bb64..c27b10a1bd7 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -453,6 +453,7 @@ int __devinit start_secondary(void *unused) secondary_cpu_time_init(); ipi_call_lock(); + notify_cpu_starting(cpu); cpu_set(cpu, cpu_online_map); /* Update sibling maps */ base = cpu_first_thread_in_core(cpu); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 00b9b4dec5e..9e8b1f9b8f4 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -585,6 +585,8 @@ int __cpuinit start_secondary(void *cpuvoid) /* Enable pfault pseudo page faults on this cpu. */ pfault_init(); + /* call cpu notifiers */ + notify_cpu_starting(smp_processor_id()); /* Mark this cpu as online */ spin_lock(&call_lock); cpu_set(smp_processor_id(), cpu_online_map); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 60c50841143..001778f9ada 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -82,6 +82,8 @@ asmlinkage void __cpuinit start_secondary(void) preempt_disable(); + notify_cpu_starting(smp_processor_id()); + local_irq_enable(); calibrate_delay(); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 69596402a50..446767e8f56 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -88,6 +88,7 @@ void __init smp4d_callin(void) local_flush_cache_all(); local_flush_tlb_all(); + notify_cpu_starting(cpuid); /* * Unblock the master CPU _only_ when the scheduler state * of all secondary CPUs will be up-to-date, so after diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index a14a76ac7f3..9964890dc1d 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -71,6 +71,8 @@ void __cpuinit smp4m_callin(void) local_flush_cache_all(); local_flush_tlb_all(); + notify_cpu_starting(cpuid); + /* Get our local ticker going. */ smp_setup_percpu_timer(); diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index be2d50c3aa9..04577214284 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -85,6 +85,7 @@ static int idle_proc(void *cpup) while (!cpu_isset(cpu, smp_commenced_mask)) cpu_relax(); + notify_cpu_starting(cpu); cpu_set(cpu, cpu_online_map); default_idle(); return 0; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7985c5b3f91..0b8261c3cac 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -257,6 +257,7 @@ static void __cpuinit smp_callin(void) end_local_APIC_setup(); map_cpu_to_logical_apicid(); + notify_cpu_starting(cpuid); /* * Get our bogomips. * diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index ee0fba09215..199a5f4a873 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -448,6 +448,8 @@ static void __init start_secondary(void *unused) VDEBUG(("VOYAGER SMP: CPU%d, stack at about %p\n", cpuid, &cpuid)); + notify_cpu_starting(cpuid); + /* enable interrupts */ local_irq_enable(); -- cgit v1.2.3 From 365b50f0f09c1a24f1a60e0c027f300ed423c192 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 2 Sep 2008 01:13:31 -0700 Subject: sparc32: Fix coding style of sparc_cpu_model setting code. Signed-off-by: David S. Miller --- arch/sparc/kernel/setup.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 8d5fbce1635..f8391c0d7e9 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -216,13 +216,20 @@ void __init setup_arch(char **cmdline_p) /* Set sparc_cpu_model */ sparc_cpu_model = sun_unknown; - if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; } - if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; } - if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; } - if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; } /* CP-1200 with PROM 2.30 -E */ - if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; } - if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; } - if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; } + if (!strcmp(&cputypval,"sun4 ")) + sparc_cpu_model = sun4; + if (!strcmp(&cputypval,"sun4c")) + sparc_cpu_model = sun4c; + if (!strcmp(&cputypval,"sun4m")) + sparc_cpu_model = sun4m; + if (!strcmp(&cputypval,"sun4s")) + sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */ + if (!strcmp(&cputypval,"sun4d")) + sparc_cpu_model = sun4d; + if (!strcmp(&cputypval,"sun4e")) + sparc_cpu_model = sun4e; + if (!strcmp(&cputypval,"sun4u")) + sparc_cpu_model = sun4u; printk("ARCH: "); switch(sparc_cpu_model) { -- cgit v1.2.3 From 7b1af32f52077402157f8bb8fc22d8da17606095 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 2 Sep 2008 01:17:41 -0700 Subject: sparc32: Move sun4d show_leds() out of asm/obio.h Put it, as well as cpu_leds[] array, into sun4d_irq.c Signed-off-by: David S. Miller --- arch/sparc/include/asm/obio.h | 11 ----------- arch/sparc/kernel/sun4d_irq.c | 1 - arch/sparc/kernel/sun4d_smp.c | 11 +++++++++++ 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h index 1a7544ceb57..4ade0c8a2c7 100644 --- a/arch/sparc/include/asm/obio.h +++ b/arch/sparc/include/asm/obio.h @@ -155,17 +155,6 @@ static inline void bw_set_ctrl(int cpu, unsigned ctrl) "i" (ASI_M_CTL)); } -extern unsigned char cpu_leds[32]; - -static inline void show_leds(int cpuid) -{ - cpuid &= 0x1e; - __asm__ __volatile__ ("stba %0, [%1] %2" : : - "r" ((cpu_leds[cpuid] << 4) | cpu_leds[cpuid+1]), - "r" (ECSR_BASE(cpuid) | BB_LEDS), - "i" (ASI_M_CTL)); -} - static inline unsigned cc_get_ipen(void) { unsigned pending; diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index c4a2bfb750a..12541f51fcf 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -51,7 +51,6 @@ struct sun4d_timer_regs *sun4d_timers; #define MAX_STATIC_ALLOC 4 extern struct irqaction static_irqaction[MAX_STATIC_ALLOC]; extern int static_irq_count; -unsigned char cpu_leds[32]; #ifdef CONFIG_SMP static unsigned char sbus_tid[32]; #endif diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 72fa8daab60..49a08b487ca 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -71,6 +71,17 @@ static void smp_setup_percpu_timer(void); extern void cpu_probe(void); extern void sun4d_distribute_irqs(void); +static unsigned char cpu_leds[32]; + +static inline void show_leds(int cpuid) +{ + cpuid &= 0x1e; + __asm__ __volatile__ ("stba %0, [%1] %2" : : + "r" ((cpu_leds[cpuid] << 4) | cpu_leds[cpuid+1]), + "r" (ECSR_BASE(cpuid) | BB_LEDS), + "i" (ASI_M_CTL)); +} + void __init smp4d_callin(void) { int cpuid = hard_smp4d_processor_id(); -- cgit v1.2.3 From 088a39623660f2875aaf15649bf663bbb5a8a219 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 8 Sep 2008 19:53:28 -0700 Subject: sparc64: Add missing rtc_close() in update_persistent_clock() Noticed by David Brownell. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 226a0042d87..8a2fa0eb660 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -396,9 +396,12 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; int update_persistent_clock(struct timespec now) { struct rtc_device *rtc = rtc_class_open("rtc0"); + int err; - if (rtc) - return rtc_set_mmss(rtc, now.tv_sec); + if (rtc) { + err = rtc_set_mmss(rtc, now.tv_sec); + rtc_class_close(rtc); + } return -1; } -- cgit v1.2.3 From 9c0bbee8a6fc14107e9a7af6750bfe1056cbf4bc Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 9 Sep 2008 11:01:31 +0400 Subject: seccomp: drop now bogus dependency on PROC_FS seccomp is prctl(2)-driven now. Signed-off-by: Alexey Dobriyan Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 68d91c8233f..1e2afe60ba9 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1205,7 +1205,6 @@ config IRQBALANCE config SECCOMP def_bool y prompt "Enable seccomp to safely compute untrusted bytecode" - depends on PROC_FS help This kernel feature is useful for number crunching applications that may need to compute untrusted bytecode during their @@ -1213,7 +1212,7 @@ config SECCOMP the process as file descriptors supporting the read/write syscalls, it's possible to isolate those applications in their own address space using seccomp. Once seccomp is - enabled via /proc//seccomp, it cannot be disabled + enabled via prctl(PR_SET_SECCOMP), it cannot be disabled and the task is only allowed to execute a few safe syscalls defined by each seccomp mode. -- cgit v1.2.3 From 28f7e66fc1da53997a545684b21b91fb3ca3f321 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 8 Sep 2008 12:01:48 -0700 Subject: x86: prevent binutils from being "smart" and generating NOPLs for us binutils, contrary to documented behaviour, will generate long NOPs (a P6-or-higher instruction which is broken on at least some VIA chips, Virtual PC/Virtual Server, and some versions of Qemu) depending on the -mtune= option, which is not supposed to change architectural behaviour. Pass an explicit override to the assembler, in case ends up passing the -mtune= parameter to gas (gcc 4.3.0 does not appear to.) Signed-off-by: H. Peter Anvin --- arch/x86/Makefile_32.cpu | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu index e372b584e91..b72b4f75311 100644 --- a/arch/x86/Makefile_32.cpu +++ b/arch/x86/Makefile_32.cpu @@ -45,3 +45,8 @@ cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx # cpu entries cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic,$(call tune,i686)) +# Bug fix for binutils: this option is required in order to keep +# binutils from generating NOPL instructions against our will. +ifneq ($(CONFIG_X86_P6_NOP),y) +cflags-y += $(call cc-option,-Wa$(comma)-mtune=generic32,) +endif -- cgit v1.2.3 From 4944f7e5c917949451ba7f32aab5d297d8b03c7f Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Tue, 9 Sep 2008 19:43:33 -0700 Subject: sparc: remove unused includes The spinlock code does not use NR_CPUS. Compile tested using allyesconfig and allnoconfig. Signed-off-by: Bjoern B. Brandenburg Signed-off-by: David S. Miller --- arch/sparc/include/asm/spinlock_32.h | 2 -- arch/sparc/include/asm/spinlock_64.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/spinlock_32.h b/arch/sparc/include/asm/spinlock_32.h index de2249b267c..bf2d532593e 100644 --- a/arch/sparc/include/asm/spinlock_32.h +++ b/arch/sparc/include/asm/spinlock_32.h @@ -6,8 +6,6 @@ #ifndef __SPARC_SPINLOCK_H #define __SPARC_SPINLOCK_H -#include /* For NR_CPUS */ - #ifndef __ASSEMBLY__ #include diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h index 0006fe9f8c7..120cfe4577c 100644 --- a/arch/sparc/include/asm/spinlock_64.h +++ b/arch/sparc/include/asm/spinlock_64.h @@ -6,8 +6,6 @@ #ifndef __SPARC64_SPINLOCK_H #define __SPARC64_SPINLOCK_H -#include /* For NR_CPUS */ - #ifndef __ASSEMBLY__ /* To get debugging spinlocks which detect and catch -- cgit v1.2.3 From 185f3b9da24c09c26b784591ed354fe57998a7b1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 9 Sep 2008 16:40:35 -0700 Subject: x86: make intel.c have 64-bit support code prepare for unification. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel.c | 119 ++++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index a66989586a8..365a008080c 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -15,6 +15,11 @@ #include #include +#ifdef CONFIG_X86_64 +#include +#include +#endif + #include "cpu.h" #ifdef CONFIG_X86_LOCAL_APIC @@ -25,14 +30,20 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) { - /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ - if (c->x86 == 15 && c->x86_cache_alignment == 64) - c->x86_cache_alignment = 128; if ((c->x86 == 0xf && c->x86_model >= 0x03) || (c->x86 == 0x6 && c->x86_model >= 0x0e)) set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); + +#ifdef CONFIG_X86_64 + set_cpu_cap(c, X86_FEATURE_SYSENTER32); +#else + /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ + if (c->x86 == 15 && c->x86_cache_alignment == 64) + c->x86_cache_alignment = 128; +#endif } +#ifdef CONFIG_X86_32 /* * Early probe support logic for ppro memory erratum #50 * @@ -73,6 +84,40 @@ static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) } + +#ifdef CONFIG_X86_F00F_BUG +static void __cpuinit trap_init_f00f_bug(void) +{ + __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); + + /* + * Update the IDT descriptor and reload the IDT so that + * it uses the read-only mapped virtual address. + */ + idt_descr.address = fix_to_virt(FIX_F00F_IDT); + load_idt(&idt_descr); +} +#endif +#endif + +static void __cpuinit srat_detect_node(void) +{ +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) + unsigned node; + int cpu = smp_processor_id(); + int apicid = hard_smp_processor_id(); + + /* Don't do the funky fallback heuristics the AMD version employs + for now. */ + node = apicid_to_node[apicid]; + if (node == NUMA_NO_NODE || !node_online(node)) + node = first_node(node_online_map); + numa_set_node(cpu, node); + + printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node); +#endif +} + /* * find out the number of processor cores on the die */ @@ -91,20 +136,6 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) return 1; } -#ifdef CONFIG_X86_F00F_BUG -static void __cpuinit trap_init_f00f_bug(void) -{ - __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); - - /* - * Update the IDT descriptor and reload the IDT so that - * it uses the read-only mapped virtual address. - */ - idt_descr.address = fix_to_virt(FIX_F00F_IDT); - load_idt(&idt_descr); -} -#endif - static void __cpuinit init_intel(struct cpuinfo_x86 *c) { unsigned int l2 = 0; @@ -139,6 +170,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); } +#ifdef CONFIG_X86_32 /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) clear_cpu_cap(c, X86_FEATURE_SEP); @@ -176,18 +208,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if (p) strcpy(c->x86_model_id, p); - detect_extended_topology(c); - - if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) { - /* - * let's use the legacy cpuid vector 0x1 and 0x4 for topology - * detection. - */ - c->x86_max_cores = intel_num_cpu_cores(c); - detect_ht(c); - } - - /* Work around errata */ Intel_errata_workarounds(c); #ifdef CONFIG_X86_INTEL_USERCOPY @@ -206,14 +226,12 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) movsl_mask.mask = 7; break; } +#endif + #endif if (cpu_has_xmm2) set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - if (c->x86 == 15) - set_cpu_cap(c, X86_FEATURE_P4); - if (c->x86 == 6) - set_cpu_cap(c, X86_FEATURE_P3); if (cpu_has_ds) { unsigned int l1; rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); @@ -224,6 +242,17 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) ds_init_intel(c); } +#ifdef CONFIG_X86_64 + if (c->x86 == 15) + c->x86_cache_alignment = c->x86_clflush_size * 2; + if (c->x86 == 6) + set_cpu_cap(c, X86_FEATURE_REP_GOOD); +#else + if (c->x86 == 15) + set_cpu_cap(c, X86_FEATURE_P4); + if (c->x86 == 6) + set_cpu_cap(c, X86_FEATURE_P3); + if (cpu_has_bts) ptrace_bts_init_intel(c); @@ -240,8 +269,25 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_NUMAQ numaq_tsc_disable(); #endif +#endif + + detect_extended_topology(c); + if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) { + /* + * let's use the legacy cpuid vector 0x1 and 0x4 for topology + * detection. + */ + c->x86_max_cores = intel_num_cpu_cores(c); +#ifdef CONFIG_X86_32 + detect_ht(c); +#endif + } + + /* Work around errata */ + srat_detect_node(); } +#ifdef CONFIG_X86_32 static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) { /* @@ -254,10 +300,12 @@ static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned i size = 256; return size; } +#endif static struct cpu_dev intel_cpu_dev __cpuinitdata = { .c_vendor = "Intel", .c_ident = { "GenuineIntel" }, +#ifdef CONFIG_X86_32 .c_models = { { .vendor = X86_VENDOR_INTEL, .family = 4, .model_names = { @@ -307,13 +355,12 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = { } }, }, + .c_size_cache = intel_size_cache, +#endif .c_early_init = early_init_intel, .c_init = init_intel, - .c_size_cache = intel_size_cache, .c_x86_vendor = X86_VENDOR_INTEL, }; cpu_dev_register(intel_cpu_dev); -/* arch_initcall(intel_cpu_init); */ - -- cgit v1.2.3 From 58602c1681bdfa1a0deaa5574b8a72d6e30c0e97 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 9 Sep 2008 16:40:36 -0700 Subject: x86: make intel_64.c the same as intel.c No change in functionality intended - this only adds the 32-bit side. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_64.c | 301 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 284 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c index aef4f282631..365a008080c 100644 --- a/arch/x86/kernel/cpu/intel_64.c +++ b/arch/x86/kernel/cpu/intel_64.c @@ -1,42 +1,108 @@ #include +#include + +#include +#include #include +#include +#include + #include +#include +#include +#include #include +#include +#include + +#ifdef CONFIG_X86_64 #include #include +#endif #include "cpu.h" +#ifdef CONFIG_X86_LOCAL_APIC +#include +#include +#include +#endif + static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) { if ((c->x86 == 0xf && c->x86_model >= 0x03) || - (c->x86 == 0x6 && c->x86_model >= 0x0e)) + (c->x86 == 0x6 && c->x86_model >= 0x0e)) set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); +#ifdef CONFIG_X86_64 set_cpu_cap(c, X86_FEATURE_SYSENTER32); +#else + /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ + if (c->x86 == 15 && c->x86_cache_alignment == 64) + c->x86_cache_alignment = 128; +#endif } +#ifdef CONFIG_X86_32 /* - * find out the number of processor cores on the die + * Early probe support logic for ppro memory erratum #50 + * + * This is called before we do cpu ident work */ -static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) -{ - unsigned int eax, t; - if (c->cpuid_level < 4) +int __cpuinit ppro_with_ram_bug(void) +{ + /* Uses data from early_cpu_detect now */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model == 1 && + boot_cpu_data.x86_mask < 8) { + printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n"); return 1; + } + return 0; +} - cpuid_count(4, 0, &eax, &t, &t, &t); - if (eax & 0x1f) - return ((eax >> 26) + 1); - else - return 1; +/* + * P4 Xeon errata 037 workaround. + * Hardware prefetcher may cause stale data to be loaded into the cache. + */ +static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) +{ + unsigned long lo, hi; + + if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) { + rdmsr(MSR_IA32_MISC_ENABLE, lo, hi); + if ((lo & (1<<9)) == 0) { + printk (KERN_INFO "CPU: C0 stepping P4 Xeon detected.\n"); + printk (KERN_INFO "CPU: Disabling hardware prefetching (Errata 037)\n"); + lo |= (1<<9); /* Disable hw prefetching */ + wrmsr (MSR_IA32_MISC_ENABLE, lo, hi); + } + } +} + + + +#ifdef CONFIG_X86_F00F_BUG +static void __cpuinit trap_init_f00f_bug(void) +{ + __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); + + /* + * Update the IDT descriptor and reload the IDT so that + * it uses the read-only mapped virtual address. + */ + idt_descr.address = fix_to_virt(FIX_F00F_IDT); + load_idt(&idt_descr); } +#endif +#endif static void __cpuinit srat_detect_node(void) { -#ifdef CONFIG_NUMA +#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) unsigned node; int cpu = smp_processor_id(); int apicid = hard_smp_processor_id(); @@ -52,11 +118,51 @@ static void __cpuinit srat_detect_node(void) #endif } +/* + * find out the number of processor cores on the die + */ +static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) +{ + unsigned int eax, ebx, ecx, edx; + + if (c->cpuid_level < 4) + return 1; + + /* Intel has a non-standard dependency on %ecx for this CPUID level. */ + cpuid_count(4, 0, &eax, &ebx, &ecx, &edx); + if (eax & 0x1f) + return ((eax >> 26) + 1); + else + return 1; +} + static void __cpuinit init_intel(struct cpuinfo_x86 *c) { + unsigned int l2 = 0; + char *p = NULL; + early_init_intel(c); - init_intel_cacheinfo(c); +#ifdef CONFIG_X86_F00F_BUG + /* + * All current models of Pentium and Pentium with MMX technology CPUs + * have the F0 0F bug, which lets nonprivileged users lock up the system. + * Note that the workaround only should be initialized once... + */ + c->f00f_bug = 0; + if (!paravirt_enabled() && c->x86 == 5) { + static int f00f_workaround_enabled; + + c->f00f_bug = 1; + if (!f00f_workaround_enabled) { + trap_init_f00f_bug(); + printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); + f00f_workaround_enabled = 1; + } + } +#endif + + l2 = init_intel_cacheinfo(c); if (c->cpuid_level > 9) { unsigned eax = cpuid_eax(10); /* Check for version and the number of counters */ @@ -64,8 +170,70 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); } +#ifdef CONFIG_X86_32 + /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ + if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) + clear_cpu_cap(c, X86_FEATURE_SEP); + + /* + * Names for the Pentium II/Celeron processors + * detectable only by also checking the cache size. + * Dixon is NOT a Celeron. + */ + if (c->x86 == 6) { + switch (c->x86_model) { + case 5: + if (c->x86_mask == 0) { + if (l2 == 0) + p = "Celeron (Covington)"; + else if (l2 == 256) + p = "Mobile Pentium II (Dixon)"; + } + break; + + case 6: + if (l2 == 128) + p = "Celeron (Mendocino)"; + else if (c->x86_mask == 0 || c->x86_mask == 5) + p = "Celeron-A"; + break; + + case 8: + if (l2 == 128) + p = "Celeron (Coppermine)"; + break; + } + } + + if (p) + strcpy(c->x86_model_id, p); + + Intel_errata_workarounds(c); + +#ifdef CONFIG_X86_INTEL_USERCOPY + /* + * Set up the preferred alignment for movsl bulk memory moves + */ + switch (c->x86) { + case 4: /* 486: untested */ + break; + case 5: /* Old Pentia: untested */ + break; + case 6: /* PII/PIII only like movsl with 8-byte alignment */ + movsl_mask.mask = 7; + break; + case 15: /* P4 is OK down to 8-byte alignment */ + movsl_mask.mask = 7; + break; + } +#endif + +#endif + + if (cpu_has_xmm2) + set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); if (cpu_has_ds) { - unsigned int l1, l2; + unsigned int l1; rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); if (!(l1 & (1<<11))) set_cpu_cap(c, X86_FEATURE_BTS); @@ -74,26 +242,125 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) ds_init_intel(c); } +#ifdef CONFIG_X86_64 if (c->x86 == 15) c->x86_cache_alignment = c->x86_clflush_size * 2; if (c->x86 == 6) set_cpu_cap(c, X86_FEATURE_REP_GOOD); - if (cpu_has_xmm2) - set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); +#else + if (c->x86 == 15) + set_cpu_cap(c, X86_FEATURE_P4); + if (c->x86 == 6) + set_cpu_cap(c, X86_FEATURE_P3); + + if (cpu_has_bts) + ptrace_bts_init_intel(c); + + /* + * See if we have a good local APIC by checking for buggy Pentia, + * i.e. all B steppings and the C2 stepping of P54C when using their + * integrated APIC (see 11AP erratum in "Pentium Processor + * Specification Update"). + */ + if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 && + (c->x86_mask < 0x6 || c->x86_mask == 0xb)) + set_cpu_cap(c, X86_FEATURE_11AP); + +#ifdef CONFIG_X86_NUMAQ + numaq_tsc_disable(); +#endif +#endif detect_extended_topology(c); - if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) + if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) { + /* + * let's use the legacy cpuid vector 0x1 and 0x4 for topology + * detection. + */ c->x86_max_cores = intel_num_cpu_cores(c); +#ifdef CONFIG_X86_32 + detect_ht(c); +#endif + } + /* Work around errata */ srat_detect_node(); } +#ifdef CONFIG_X86_32 +static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) +{ + /* + * Intel PIII Tualatin. This comes in two flavours. + * One has 256kb of cache, the other 512. We have no way + * to determine which, so we use a boottime override + * for the 512kb model, and assume 256 otherwise. + */ + if ((c->x86 == 6) && (c->x86_model == 11) && (size == 0)) + size = 256; + return size; +} +#endif + static struct cpu_dev intel_cpu_dev __cpuinitdata = { .c_vendor = "Intel", .c_ident = { "GenuineIntel" }, +#ifdef CONFIG_X86_32 + .c_models = { + { .vendor = X86_VENDOR_INTEL, .family = 4, .model_names = + { + [0] = "486 DX-25/33", + [1] = "486 DX-50", + [2] = "486 SX", + [3] = "486 DX/2", + [4] = "486 SL", + [5] = "486 SX/2", + [7] = "486 DX/2-WB", + [8] = "486 DX/4", + [9] = "486 DX/4-WB" + } + }, + { .vendor = X86_VENDOR_INTEL, .family = 5, .model_names = + { + [0] = "Pentium 60/66 A-step", + [1] = "Pentium 60/66", + [2] = "Pentium 75 - 200", + [3] = "OverDrive PODP5V83", + [4] = "Pentium MMX", + [7] = "Mobile Pentium 75 - 200", + [8] = "Mobile Pentium MMX" + } + }, + { .vendor = X86_VENDOR_INTEL, .family = 6, .model_names = + { + [0] = "Pentium Pro A-step", + [1] = "Pentium Pro", + [3] = "Pentium II (Klamath)", + [4] = "Pentium II (Deschutes)", + [5] = "Pentium II (Deschutes)", + [6] = "Mobile Pentium II", + [7] = "Pentium III (Katmai)", + [8] = "Pentium III (Coppermine)", + [10] = "Pentium III (Cascades)", + [11] = "Pentium III (Tualatin)", + } + }, + { .vendor = X86_VENDOR_INTEL, .family = 15, .model_names = + { + [0] = "Pentium 4 (Unknown)", + [1] = "Pentium 4 (Willamette)", + [2] = "Pentium 4 (Northwood)", + [4] = "Pentium 4 (Foster)", + [5] = "Pentium 4 (Foster)", + } + }, + }, + .c_size_cache = intel_size_cache, +#endif .c_early_init = early_init_intel, .c_init = init_intel, .c_x86_vendor = X86_VENDOR_INTEL, }; cpu_dev_register(intel_cpu_dev); + -- cgit v1.2.3 From 879d792b66d633bbe466974f61d1acc9aa8c78eb Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 9 Sep 2008 16:40:37 -0700 Subject: x86: let intel 64-bit use intel.c now that arch/x86/kernel/cpu/intel_64.c and arch/x86/kernel/cpu/intel.c are equal, drop arch/x86/kernel/cpu/intel_64.c and fix up the glue. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 10 +- arch/x86/kernel/cpu/Makefile | 3 +- arch/x86/kernel/cpu/intel_64.c | 366 ----------------------------------------- 3 files changed, 2 insertions(+), 377 deletions(-) delete mode 100644 arch/x86/kernel/cpu/intel_64.c (limited to 'arch') diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 1b29d6a8756..6761848329f 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -423,17 +423,9 @@ menuconfig PROCESSOR_SELECT This lets you choose what x86 vendor support code your kernel will include. -config CPU_SUP_INTEL_32 +config CPU_SUP_INTEL default y bool "Support Intel processors" if PROCESSOR_SELECT - depends on !64BIT - help - This enables extended support for Intel processors - -config CPU_SUP_INTEL_64 - default y - bool "Support Intel processors" if PROCESSOR_SELECT - depends on 64BIT help This enables extended support for Intel processors diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 510d1bcb058..7f0b45a5d78 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -8,8 +8,7 @@ obj-y += proc.o capflags.o powerflags.o common.o obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += bugs_64.o -obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o -obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o +obj-$(CONFIG_CPU_SUP_INTEL) += intel.o obj-$(CONFIG_CPU_SUP_AMD) += amd.o obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o obj-$(CONFIG_CPU_SUP_CENTAUR_32) += centaur.o diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c deleted file mode 100644 index 365a008080c..00000000000 --- a/arch/x86/kernel/cpu/intel_64.c +++ /dev/null @@ -1,366 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_X86_64 -#include -#include -#endif - -#include "cpu.h" - -#ifdef CONFIG_X86_LOCAL_APIC -#include -#include -#include -#endif - -static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) -{ - if ((c->x86 == 0xf && c->x86_model >= 0x03) || - (c->x86 == 0x6 && c->x86_model >= 0x0e)) - set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); - -#ifdef CONFIG_X86_64 - set_cpu_cap(c, X86_FEATURE_SYSENTER32); -#else - /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ - if (c->x86 == 15 && c->x86_cache_alignment == 64) - c->x86_cache_alignment = 128; -#endif -} - -#ifdef CONFIG_X86_32 -/* - * Early probe support logic for ppro memory erratum #50 - * - * This is called before we do cpu ident work - */ - -int __cpuinit ppro_with_ram_bug(void) -{ - /* Uses data from early_cpu_detect now */ - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && - boot_cpu_data.x86 == 6 && - boot_cpu_data.x86_model == 1 && - boot_cpu_data.x86_mask < 8) { - printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n"); - return 1; - } - return 0; -} - - -/* - * P4 Xeon errata 037 workaround. - * Hardware prefetcher may cause stale data to be loaded into the cache. - */ -static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) -{ - unsigned long lo, hi; - - if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) { - rdmsr(MSR_IA32_MISC_ENABLE, lo, hi); - if ((lo & (1<<9)) == 0) { - printk (KERN_INFO "CPU: C0 stepping P4 Xeon detected.\n"); - printk (KERN_INFO "CPU: Disabling hardware prefetching (Errata 037)\n"); - lo |= (1<<9); /* Disable hw prefetching */ - wrmsr (MSR_IA32_MISC_ENABLE, lo, hi); - } - } -} - - - -#ifdef CONFIG_X86_F00F_BUG -static void __cpuinit trap_init_f00f_bug(void) -{ - __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); - - /* - * Update the IDT descriptor and reload the IDT so that - * it uses the read-only mapped virtual address. - */ - idt_descr.address = fix_to_virt(FIX_F00F_IDT); - load_idt(&idt_descr); -} -#endif -#endif - -static void __cpuinit srat_detect_node(void) -{ -#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) - unsigned node; - int cpu = smp_processor_id(); - int apicid = hard_smp_processor_id(); - - /* Don't do the funky fallback heuristics the AMD version employs - for now. */ - node = apicid_to_node[apicid]; - if (node == NUMA_NO_NODE || !node_online(node)) - node = first_node(node_online_map); - numa_set_node(cpu, node); - - printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node); -#endif -} - -/* - * find out the number of processor cores on the die - */ -static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) -{ - unsigned int eax, ebx, ecx, edx; - - if (c->cpuid_level < 4) - return 1; - - /* Intel has a non-standard dependency on %ecx for this CPUID level. */ - cpuid_count(4, 0, &eax, &ebx, &ecx, &edx); - if (eax & 0x1f) - return ((eax >> 26) + 1); - else - return 1; -} - -static void __cpuinit init_intel(struct cpuinfo_x86 *c) -{ - unsigned int l2 = 0; - char *p = NULL; - - early_init_intel(c); - -#ifdef CONFIG_X86_F00F_BUG - /* - * All current models of Pentium and Pentium with MMX technology CPUs - * have the F0 0F bug, which lets nonprivileged users lock up the system. - * Note that the workaround only should be initialized once... - */ - c->f00f_bug = 0; - if (!paravirt_enabled() && c->x86 == 5) { - static int f00f_workaround_enabled; - - c->f00f_bug = 1; - if (!f00f_workaround_enabled) { - trap_init_f00f_bug(); - printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); - f00f_workaround_enabled = 1; - } - } -#endif - - l2 = init_intel_cacheinfo(c); - if (c->cpuid_level > 9) { - unsigned eax = cpuid_eax(10); - /* Check for version and the number of counters */ - if ((eax & 0xff) && (((eax>>8) & 0xff) > 1)) - set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); - } - -#ifdef CONFIG_X86_32 - /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ - if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) - clear_cpu_cap(c, X86_FEATURE_SEP); - - /* - * Names for the Pentium II/Celeron processors - * detectable only by also checking the cache size. - * Dixon is NOT a Celeron. - */ - if (c->x86 == 6) { - switch (c->x86_model) { - case 5: - if (c->x86_mask == 0) { - if (l2 == 0) - p = "Celeron (Covington)"; - else if (l2 == 256) - p = "Mobile Pentium II (Dixon)"; - } - break; - - case 6: - if (l2 == 128) - p = "Celeron (Mendocino)"; - else if (c->x86_mask == 0 || c->x86_mask == 5) - p = "Celeron-A"; - break; - - case 8: - if (l2 == 128) - p = "Celeron (Coppermine)"; - break; - } - } - - if (p) - strcpy(c->x86_model_id, p); - - Intel_errata_workarounds(c); - -#ifdef CONFIG_X86_INTEL_USERCOPY - /* - * Set up the preferred alignment for movsl bulk memory moves - */ - switch (c->x86) { - case 4: /* 486: untested */ - break; - case 5: /* Old Pentia: untested */ - break; - case 6: /* PII/PIII only like movsl with 8-byte alignment */ - movsl_mask.mask = 7; - break; - case 15: /* P4 is OK down to 8-byte alignment */ - movsl_mask.mask = 7; - break; - } -#endif - -#endif - - if (cpu_has_xmm2) - set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - if (cpu_has_ds) { - unsigned int l1; - rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); - if (!(l1 & (1<<11))) - set_cpu_cap(c, X86_FEATURE_BTS); - if (!(l1 & (1<<12))) - set_cpu_cap(c, X86_FEATURE_PEBS); - ds_init_intel(c); - } - -#ifdef CONFIG_X86_64 - if (c->x86 == 15) - c->x86_cache_alignment = c->x86_clflush_size * 2; - if (c->x86 == 6) - set_cpu_cap(c, X86_FEATURE_REP_GOOD); -#else - if (c->x86 == 15) - set_cpu_cap(c, X86_FEATURE_P4); - if (c->x86 == 6) - set_cpu_cap(c, X86_FEATURE_P3); - - if (cpu_has_bts) - ptrace_bts_init_intel(c); - - /* - * See if we have a good local APIC by checking for buggy Pentia, - * i.e. all B steppings and the C2 stepping of P54C when using their - * integrated APIC (see 11AP erratum in "Pentium Processor - * Specification Update"). - */ - if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 && - (c->x86_mask < 0x6 || c->x86_mask == 0xb)) - set_cpu_cap(c, X86_FEATURE_11AP); - -#ifdef CONFIG_X86_NUMAQ - numaq_tsc_disable(); -#endif -#endif - - detect_extended_topology(c); - if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) { - /* - * let's use the legacy cpuid vector 0x1 and 0x4 for topology - * detection. - */ - c->x86_max_cores = intel_num_cpu_cores(c); -#ifdef CONFIG_X86_32 - detect_ht(c); -#endif - } - - /* Work around errata */ - srat_detect_node(); -} - -#ifdef CONFIG_X86_32 -static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) -{ - /* - * Intel PIII Tualatin. This comes in two flavours. - * One has 256kb of cache, the other 512. We have no way - * to determine which, so we use a boottime override - * for the 512kb model, and assume 256 otherwise. - */ - if ((c->x86 == 6) && (c->x86_model == 11) && (size == 0)) - size = 256; - return size; -} -#endif - -static struct cpu_dev intel_cpu_dev __cpuinitdata = { - .c_vendor = "Intel", - .c_ident = { "GenuineIntel" }, -#ifdef CONFIG_X86_32 - .c_models = { - { .vendor = X86_VENDOR_INTEL, .family = 4, .model_names = - { - [0] = "486 DX-25/33", - [1] = "486 DX-50", - [2] = "486 SX", - [3] = "486 DX/2", - [4] = "486 SL", - [5] = "486 SX/2", - [7] = "486 DX/2-WB", - [8] = "486 DX/4", - [9] = "486 DX/4-WB" - } - }, - { .vendor = X86_VENDOR_INTEL, .family = 5, .model_names = - { - [0] = "Pentium 60/66 A-step", - [1] = "Pentium 60/66", - [2] = "Pentium 75 - 200", - [3] = "OverDrive PODP5V83", - [4] = "Pentium MMX", - [7] = "Mobile Pentium 75 - 200", - [8] = "Mobile Pentium MMX" - } - }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model_names = - { - [0] = "Pentium Pro A-step", - [1] = "Pentium Pro", - [3] = "Pentium II (Klamath)", - [4] = "Pentium II (Deschutes)", - [5] = "Pentium II (Deschutes)", - [6] = "Mobile Pentium II", - [7] = "Pentium III (Katmai)", - [8] = "Pentium III (Coppermine)", - [10] = "Pentium III (Cascades)", - [11] = "Pentium III (Tualatin)", - } - }, - { .vendor = X86_VENDOR_INTEL, .family = 15, .model_names = - { - [0] = "Pentium 4 (Unknown)", - [1] = "Pentium 4 (Willamette)", - [2] = "Pentium 4 (Northwood)", - [4] = "Pentium 4 (Foster)", - [5] = "Pentium 4 (Foster)", - } - }, - }, - .c_size_cache = intel_size_cache, -#endif - .c_early_init = early_init_intel, - .c_init = init_intel, - .c_x86_vendor = X86_VENDOR_INTEL, -}; - -cpu_dev_register(intel_cpu_dev); - -- cgit v1.2.3 From 4052704d92c3172ebc13cc0cc8df8ba2bd446a5c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 9 Sep 2008 16:40:38 -0700 Subject: x86: intel.c put workaround for old cpus together consolidate the code some more. No change in functionality intended. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel.c | 192 ++++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 94 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 365a008080c..5f76bf139fd 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -63,15 +63,54 @@ int __cpuinit ppro_with_ram_bug(void) return 0; } +#ifdef CONFIG_X86_F00F_BUG +static void __cpuinit trap_init_f00f_bug(void) +{ + __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); -/* - * P4 Xeon errata 037 workaround. - * Hardware prefetcher may cause stale data to be loaded into the cache. - */ -static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) + /* + * Update the IDT descriptor and reload the IDT so that + * it uses the read-only mapped virtual address. + */ + idt_descr.address = fix_to_virt(FIX_F00F_IDT); + load_idt(&idt_descr); +} +#endif + +static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) { unsigned long lo, hi; +#ifdef CONFIG_X86_F00F_BUG + /* + * All current models of Pentium and Pentium with MMX technology CPUs + * have the F0 0F bug, which lets nonprivileged users lock up the system. + * Note that the workaround only should be initialized once... + */ + c->f00f_bug = 0; + if (!paravirt_enabled() && c->x86 == 5) { + static int f00f_workaround_enabled; + + c->f00f_bug = 1; + if (!f00f_workaround_enabled) { + trap_init_f00f_bug(); + printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); + f00f_workaround_enabled = 1; + } + } +#endif + + /* + * SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until + * model 3 mask 3 + */ + if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) + clear_cpu_cap(c, X86_FEATURE_SEP); + + /* + * P4 Xeon errata 037 workaround. + * Hardware prefetcher may cause stale data to be loaded into the cache. + */ if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) { rdmsr(MSR_IA32_MISC_ENABLE, lo, hi); if ((lo & (1<<9)) == 0) { @@ -81,23 +120,44 @@ static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) wrmsr (MSR_IA32_MISC_ENABLE, lo, hi); } } -} - + /* + * See if we have a good local APIC by checking for buggy Pentia, + * i.e. all B steppings and the C2 stepping of P54C when using their + * integrated APIC (see 11AP erratum in "Pentium Processor + * Specification Update"). + */ + if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 && + (c->x86_mask < 0x6 || c->x86_mask == 0xb)) + set_cpu_cap(c, X86_FEATURE_11AP); -#ifdef CONFIG_X86_F00F_BUG -static void __cpuinit trap_init_f00f_bug(void) -{ - __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); +#ifdef CONFIG_X86_INTEL_USERCOPY /* - * Update the IDT descriptor and reload the IDT so that - * it uses the read-only mapped virtual address. + * Set up the preferred alignment for movsl bulk memory moves */ - idt_descr.address = fix_to_virt(FIX_F00F_IDT); - load_idt(&idt_descr); -} + switch (c->x86) { + case 4: /* 486: untested */ + break; + case 5: /* Old Pentia: untested */ + break; + case 6: /* PII/PIII only like movsl with 8-byte alignment */ + movsl_mask.mask = 7; + break; + case 15: /* P4 is OK down to 8-byte alignment */ + movsl_mask.mask = 7; + break; + } #endif + +#ifdef CONFIG_X86_NUMAQ + numaq_tsc_disable(); +#endif +} +#else +static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) +{ +} #endif static void __cpuinit srat_detect_node(void) @@ -139,28 +199,10 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) static void __cpuinit init_intel(struct cpuinfo_x86 *c) { unsigned int l2 = 0; - char *p = NULL; early_init_intel(c); -#ifdef CONFIG_X86_F00F_BUG - /* - * All current models of Pentium and Pentium with MMX technology CPUs - * have the F0 0F bug, which lets nonprivileged users lock up the system. - * Note that the workaround only should be initialized once... - */ - c->f00f_bug = 0; - if (!paravirt_enabled() && c->x86 == 5) { - static int f00f_workaround_enabled; - - c->f00f_bug = 1; - if (!f00f_workaround_enabled) { - trap_init_f00f_bug(); - printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); - f00f_workaround_enabled = 1; - } - } -#endif + intel_workarounds(c); l2 = init_intel_cacheinfo(c); if (c->cpuid_level > 9) { @@ -170,17 +212,32 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); } -#ifdef CONFIG_X86_32 - /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ - if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) - clear_cpu_cap(c, X86_FEATURE_SEP); + if (cpu_has_xmm2) + set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); + if (cpu_has_ds) { + unsigned int l1; + rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); + if (!(l1 & (1<<11))) + set_cpu_cap(c, X86_FEATURE_BTS); + if (!(l1 & (1<<12))) + set_cpu_cap(c, X86_FEATURE_PEBS); + ds_init_intel(c); + } +#ifdef CONFIG_X86_64 + if (c->x86 == 15) + c->x86_cache_alignment = c->x86_clflush_size * 2; + if (c->x86 == 6) + set_cpu_cap(c, X86_FEATURE_REP_GOOD); +#else /* * Names for the Pentium II/Celeron processors * detectable only by also checking the cache size. * Dixon is NOT a Celeron. */ if (c->x86 == 6) { + char *p = NULL; + switch (c->x86_model) { case 5: if (c->x86_mask == 0) { @@ -203,51 +260,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) p = "Celeron (Coppermine)"; break; } - } - if (p) - strcpy(c->x86_model_id, p); - - Intel_errata_workarounds(c); - -#ifdef CONFIG_X86_INTEL_USERCOPY - /* - * Set up the preferred alignment for movsl bulk memory moves - */ - switch (c->x86) { - case 4: /* 486: untested */ - break; - case 5: /* Old Pentia: untested */ - break; - case 6: /* PII/PIII only like movsl with 8-byte alignment */ - movsl_mask.mask = 7; - break; - case 15: /* P4 is OK down to 8-byte alignment */ - movsl_mask.mask = 7; - break; + if (p) + strcpy(c->x86_model_id, p); } -#endif - -#endif - if (cpu_has_xmm2) - set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - if (cpu_has_ds) { - unsigned int l1; - rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); - if (!(l1 & (1<<11))) - set_cpu_cap(c, X86_FEATURE_BTS); - if (!(l1 & (1<<12))) - set_cpu_cap(c, X86_FEATURE_PEBS); - ds_init_intel(c); - } - -#ifdef CONFIG_X86_64 - if (c->x86 == 15) - c->x86_cache_alignment = c->x86_clflush_size * 2; - if (c->x86 == 6) - set_cpu_cap(c, X86_FEATURE_REP_GOOD); -#else if (c->x86 == 15) set_cpu_cap(c, X86_FEATURE_P4); if (c->x86 == 6) @@ -256,19 +273,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if (cpu_has_bts) ptrace_bts_init_intel(c); - /* - * See if we have a good local APIC by checking for buggy Pentia, - * i.e. all B steppings and the C2 stepping of P54C when using their - * integrated APIC (see 11AP erratum in "Pentium Processor - * Specification Update"). - */ - if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 && - (c->x86_mask < 0x6 || c->x86_mask == 0xb)) - set_cpu_cap(c, X86_FEATURE_11AP); - -#ifdef CONFIG_X86_NUMAQ - numaq_tsc_disable(); -#endif #endif detect_extended_topology(c); -- cgit v1.2.3 From ec70cae8698632917f06110fdb70c6364281ecc6 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 9 Sep 2008 16:40:39 -0700 Subject: x86: centaur_64.c remove duplicated setting of CONSTANT_TSC Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/centaur_64.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/centaur_64.c b/arch/x86/kernel/cpu/centaur_64.c index 0e5cf17a3c8..a1625f5a1e7 100644 --- a/arch/x86/kernel/cpu/centaur_64.c +++ b/arch/x86/kernel/cpu/centaur_64.c @@ -20,7 +20,6 @@ static void __cpuinit init_centaur(struct cpuinfo_x86 *c) if (c->x86 == 0x6 && c->x86_model >= 0xf) { c->x86_cache_alignment = c->x86_clflush_size * 2; - set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_REP_GOOD); } set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); -- cgit v1.2.3 From b2994ef0de252d41f1511e5f87704bedda12dabc Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 9 Sep 2008 17:18:50 -0700 Subject: x86: signal_64.c: clean up signal_fault() clean up and make signal_fault() same as 32bit. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_64.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 8fbdd23d5cc..552a331313f 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -473,12 +473,14 @@ void do_notify_resume(struct pt_regs *regs, void *unused, void signal_fault(struct pt_regs *regs, void __user *frame, char *where) { struct task_struct *me = current; + if (show_unhandled_signals && printk_ratelimit()) { - printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", - me->comm, me->pid, where, frame, regs->ip, - regs->sp, regs->orig_ax); + printk(KERN_INFO + "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", + me->comm, me->pid, where, frame, + regs->ip, regs->sp, regs->orig_ax); print_vma_addr(" in ", regs->ip); - printk("\n"); + printk(KERN_CONT "\n"); } force_sig(SIGSEGV, me); -- cgit v1.2.3 From 0c40ed71736c20f447843b3c96b715bb9c4904d7 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 9 Sep 2008 17:21:17 -0700 Subject: x86: signal_64.c: arg for restore_i387_xstate() is void __user * restore_i387_xstate() is declared as: int restore_i387_xstate(void __user *buf); so, make the variable buf void __user *. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_64.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 552a331313f..321da93f2fb 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -94,7 +94,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, } { - struct _fpstate __user *buf; + void __user *buf; + err |= __get_user(buf, &sc->fpstate); err |= restore_i387_xstate(buf); } -- cgit v1.2.3 From 764e8d128f9343027cf09afe8a145e8ff186e129 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 9 Sep 2008 17:22:12 -0700 Subject: x86: signal_64.c: make handle_signal() similar Make handle_signal() same as 32bit. No change in functionality intended. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_64.c | 57 +++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 321da93f2fb..43e6862fc7a 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -338,39 +338,40 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ret = setup_rt_frame(sig, ka, info, oldset, regs); - if (ret == 0) { - /* - * This has nothing to do with segment registers, - * despite the name. This magic affects uaccess.h - * macros' behavior. Reset it to the normal setting. - */ - set_fs(USER_DS); + if (ret) + return ret; - /* - * Clear the direction flag as per the ABI for function entry. - */ - regs->flags &= ~X86_EFLAGS_DF; + /* + * This has nothing to do with segment registers, + * despite the name. This magic affects uaccess.h + * macros' behavior. Reset it to the normal setting. + */ + set_fs(USER_DS); - /* - * Clear TF when entering the signal handler, but - * notify any tracer that was single-stepping it. - * The tracer may want to single-step inside the - * handler too. - */ - regs->flags &= ~X86_EFLAGS_TF; + /* + * Clear the direction flag as per the ABI for function entry. + */ + regs->flags &= ~X86_EFLAGS_DF; - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + /* + * Clear TF when entering the signal handler, but + * notify any tracer that was single-stepping it. + * The tracer may want to single-step inside the + * handler too. + */ + regs->flags &= ~X86_EFLAGS_TF; - tracehook_signal_handler(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); - } + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked, sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); - return ret; + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + + return 0; } #define NR_restart_syscall \ -- cgit v1.2.3 From ac4ff656c07ada78316307b0c0ce8a8eb48aa6dd Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 10 Sep 2008 01:06:47 +0900 Subject: x86: convert gart to use is_buffer_dma_capable helper function Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 0b99d4a06f7..1b0c412566e 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -214,24 +214,14 @@ static void iommu_full(struct device *dev, size_t size, int dir) static inline int need_iommu(struct device *dev, unsigned long addr, size_t size) { - u64 mask = *dev->dma_mask; - int high = addr + size > mask; - int mmu = high; - - if (force_iommu) - mmu = 1; - - return mmu; + return force_iommu || + !is_buffer_dma_capable(*dev->dma_mask, addr, size); } static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size) { - u64 mask = *dev->dma_mask; - int high = addr + size > mask; - int mmu = high; - - return mmu; + return !is_buffer_dma_capable(*dev->dma_mask, addr, size); } /* Map a single continuous physical area into the IOMMU. -- cgit v1.2.3 From 49fbf4e9f982c704dc365698c5b5efa780aadcb5 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 10 Sep 2008 01:06:48 +0900 Subject: x86: convert pci-nommu to use is_buffer_dma_capable helper function Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-nommu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 8e398b56f50..1c1c98a31d5 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -14,7 +14,7 @@ static int check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size) { - if (hwdev && bus + size > *hwdev->dma_mask) { + if (hwdev && !is_buffer_dma_capable(*hwdev->dma_mask, bus, size)) { if (*hwdev->dma_mask >= DMA_32BIT_MASK) printk(KERN_ERR "nommu_%s: overflow %Lx+%zu of device mask %Lx\n", @@ -79,6 +79,7 @@ nommu_alloc_coherent(struct device *hwdev, size_t size, unsigned long dma_mask; int node; struct page *page; + dma_addr_t addr; dma_mask = dma_alloc_coherent_mask(hwdev, gfp); @@ -90,14 +91,15 @@ again: if (!page) return NULL; - if ((page_to_phys(page) + size > dma_mask) && !(gfp & GFP_DMA)) { + addr = page_to_phys(page); + if (!is_buffer_dma_capable(dma_mask, addr, size) && !(gfp & GFP_DMA)) { free_pages((unsigned long)page_address(page), get_order(size)); gfp |= GFP_DMA; goto again; } - *dma_addr = page_to_phys(page); - if (check_addr("alloc_coherent", hwdev, *dma_addr, size)) { + if (check_addr("alloc_coherent", hwdev, addr, size)) { + *dma_addr = addr; flush_write_buffers(); return page_address(page); } -- cgit v1.2.3 From 315a6558f30a264c88274fa70626615d1c7851c7 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 9 Sep 2008 14:54:53 +0800 Subject: x86: move VMX MSRs to msr-index.h They are hardware specific MSRs, and we would use them in virtualization feature detection later. Signed-off-by: Sheng Yang Signed-off-by: Ingo Molnar --- arch/x86/kvm/vmx.h | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h index 425a13436b3..b32d4e5b123 100644 --- a/arch/x86/kvm/vmx.h +++ b/arch/x86/kvm/vmx.h @@ -331,21 +331,6 @@ enum vmcs_field { #define AR_RESERVD_MASK 0xfffe0f00 -#define MSR_IA32_VMX_BASIC 0x480 -#define MSR_IA32_VMX_PINBASED_CTLS 0x481 -#define MSR_IA32_VMX_PROCBASED_CTLS 0x482 -#define MSR_IA32_VMX_EXIT_CTLS 0x483 -#define MSR_IA32_VMX_ENTRY_CTLS 0x484 -#define MSR_IA32_VMX_MISC 0x485 -#define MSR_IA32_VMX_CR0_FIXED0 0x486 -#define MSR_IA32_VMX_CR0_FIXED1 0x487 -#define MSR_IA32_VMX_CR4_FIXED0 0x488 -#define MSR_IA32_VMX_CR4_FIXED1 0x489 -#define MSR_IA32_VMX_VMCS_ENUM 0x48a -#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48b -#define MSR_IA32_VMX_EPT_VPID_CAP 0x48c - -#define MSR_IA32_FEATURE_CONTROL 0x3a #define MSR_IA32_FEATURE_CONTROL_LOCKED 0x1 #define MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED 0x4 -- cgit v1.2.3 From e38e05a85828dac23540cd007df5f20985388afc Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 10 Sep 2008 18:53:34 +0800 Subject: x86: extended "flags" to show virtualization HW feature in /proc/cpuinfo The hardware virtualization technology evolves very fast. But currently it's hard to tell if your CPU support a certain kind of HW technology without digging into the source code. The patch add a new catagory in "flags" under /proc/cpuinfo. Now "flags" can indicate the (important) HW virtulization features the CPU supported as well. Current implementation just cover Intel VMX side. Signed-off-by: Sheng Yang Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 5f76bf139fd..99468dbd08d 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -196,6 +196,44 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) return 1; } +static void __cpuinit detect_vmx_virtcap(struct cpuinfo_x86 *c) +{ + /* Intel VMX MSR indicated features */ +#define X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW 0x00200000 +#define X86_VMX_FEATURE_PROC_CTLS_VNMI 0x00400000 +#define X86_VMX_FEATURE_PROC_CTLS_2ND_CTLS 0x80000000 +#define X86_VMX_FEATURE_PROC_CTLS2_VIRT_APIC 0x00000001 +#define X86_VMX_FEATURE_PROC_CTLS2_EPT 0x00000002 +#define X86_VMX_FEATURE_PROC_CTLS2_VPID 0x00000020 + + u32 vmx_msr_low, vmx_msr_high, msr_ctl, msr_ctl2; + + clear_cpu_cap(c, X86_FEATURE_TPR_SHADOW); + clear_cpu_cap(c, X86_FEATURE_VNMI); + clear_cpu_cap(c, X86_FEATURE_FLEXPRIORITY); + clear_cpu_cap(c, X86_FEATURE_EPT); + clear_cpu_cap(c, X86_FEATURE_VPID); + + rdmsr(MSR_IA32_VMX_PROCBASED_CTLS, vmx_msr_low, vmx_msr_high); + msr_ctl = vmx_msr_high | vmx_msr_low; + if (msr_ctl & X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW) + set_cpu_cap(c, X86_FEATURE_TPR_SHADOW); + if (msr_ctl & X86_VMX_FEATURE_PROC_CTLS_VNMI) + set_cpu_cap(c, X86_FEATURE_VNMI); + if (msr_ctl & X86_VMX_FEATURE_PROC_CTLS_2ND_CTLS) { + rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2, + vmx_msr_low, vmx_msr_high); + msr_ctl2 = vmx_msr_high | vmx_msr_low; + if ((msr_ctl2 & X86_VMX_FEATURE_PROC_CTLS2_VIRT_APIC) && + (msr_ctl & X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW)) + set_cpu_cap(c, X86_FEATURE_FLEXPRIORITY); + if (msr_ctl2 & X86_VMX_FEATURE_PROC_CTLS2_EPT) + set_cpu_cap(c, X86_FEATURE_EPT); + if (msr_ctl2 & X86_VMX_FEATURE_PROC_CTLS2_VPID) + set_cpu_cap(c, X86_FEATURE_VPID); + } +} + static void __cpuinit init_intel(struct cpuinfo_x86 *c) { unsigned int l2 = 0; @@ -289,6 +327,9 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) /* Work around errata */ srat_detect_node(); + + if (cpu_has(c, X86_FEATURE_VMX)) + detect_vmx_virtcap(c); } #ifdef CONFIG_X86_32 -- cgit v1.2.3 From f7d0b926ac8c8ec0c7a83ee69409bd2e6bb39f81 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 9 Sep 2008 15:43:22 -0700 Subject: mm: define USE_SPLIT_PTLOCKS rather than repeating expression Define USE_SPLIT_PTLOCKS as a constant expression rather than repeating "NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS" all over the place. Signed-off-by: Jeremy Fitzhardinge Acked-by: Hugh Dickins Signed-off-by: Ingo Molnar --- arch/x86/xen/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index aa37469da69..2e1b6408849 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -646,7 +646,7 @@ static spinlock_t *lock_pte(struct page *page) { spinlock_t *ptl = NULL; -#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS +#if USE_SPLIT_PTLOCKS ptl = __pte_lockptr(page); spin_lock(ptl); #endif -- cgit v1.2.3 From 6a9e91846bf52cc70a0417de19fdfac224c435c4 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 9 Sep 2008 15:43:25 -0700 Subject: xen: fix pinning when not using split pte locks We only pin PTE pages when using split PTE locks, so don't do the pin/unpin when attaching/detaching pte pages to a pinned pagetable. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index b106e825d26..8ca2f88bde1 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -826,7 +826,7 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) if (!PageHighMem(page)) { make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); - if (level == PT_PTE) + if (level == PT_PTE && USE_SPLIT_PTLOCKS) pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); } else /* make sure there are no stray mappings of @@ -894,7 +894,7 @@ static void xen_release_ptpage(u32 pfn, unsigned level) if (PagePinned(page)) { if (!PageHighMem(page)) { - if (level == PT_PTE) + if (level == PT_PTE && USE_SPLIT_PTLOCKS) pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } -- cgit v1.2.3 From 90158d84eb20fa15e3c8010b570f3ea2c925121d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 13:35:08 -0700 Subject: sparc64: Fix return value in update_persistent_clock(). Noticed by Stephen Rothwell. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 8a2fa0eb660..8d2ca04d309 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -396,14 +396,14 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; int update_persistent_clock(struct timespec now) { struct rtc_device *rtc = rtc_class_open("rtc0"); - int err; + int err = -1; if (rtc) { err = rtc_set_mmss(rtc, now.tv_sec); rtc_class_close(rtc); } - return -1; + return err; } unsigned long cmos_regs; -- cgit v1.2.3 From ab138c031f72f6d030afa1a06a3a537e85ae843e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 13:36:13 -0700 Subject: sparc32: Need to close openned RTC device just like sparc64. Otherwise we get refcount problems. Signed-off-by: David S. Miller --- arch/sparc/kernel/time.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 698c45059fa..fa54d585f55 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -337,9 +337,12 @@ static int sbus_do_settimeofday(struct timespec *tv) static int set_rtc_mmss(unsigned long secs) { struct rtc_device *rtc = rtc_class_open("rtc0"); + int err = -1; - if (rtc) - return rtc_set_mmss(rtc, secs); + if (rtc) { + err = rtc_set_mmss(rtc, secs); + rtc_class_close(rtc); + } - return -1; + return err; } -- cgit v1.2.3 From d3ae4b5bc7186a53731d35187ad4ba3bca147cf6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 9 Sep 2008 23:54:02 -0700 Subject: sparc64: Get rid of pci_controller_info. It is just used as a parent to encapsulate two PBM objects. But that layout is only really relevant and necessary for psycho PCI controllers, which unlike all the others share a single IOMMU instance between sibling PCI busses. Signed-off-by: David S. Miller --- arch/sparc/include/asm/iommu_64.h | 3 + arch/sparc64/kernel/pci.c | 4 +- arch/sparc64/kernel/pci_fire.c | 55 ++++--------- arch/sparc64/kernel/pci_impl.h | 16 ++-- arch/sparc64/kernel/pci_psycho.c | 161 ++++++++++++++++++-------------------- arch/sparc64/kernel/pci_sabre.c | 33 ++++---- arch/sparc64/kernel/pci_schizo.c | 84 +++++++++----------- arch/sparc64/kernel/pci_sun4v.c | 66 +++++++--------- 8 files changed, 181 insertions(+), 241 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/iommu_64.h b/arch/sparc/include/asm/iommu_64.h index d7b9afcba08..caf798b5619 100644 --- a/arch/sparc/include/asm/iommu_64.h +++ b/arch/sparc/include/asm/iommu_64.h @@ -48,6 +48,9 @@ struct strbuf { unsigned long strbuf_control; unsigned long strbuf_pflush; unsigned long strbuf_fsync; + unsigned long strbuf_err_stat; + unsigned long strbuf_tag_diag; + unsigned long strbuf_line_diag; unsigned long strbuf_ctxflush; unsigned long strbuf_ctxmatch_base; unsigned long strbuf_flushflag_pa; diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 8e18fdf32a6..3070f6faecc 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -977,14 +977,14 @@ int pcibus_to_node(struct pci_bus *pbus) EXPORT_SYMBOL(pcibus_to_node); #endif -/* Return the domain nuber for this pci bus */ +/* Return the domain number for this pci bus */ int pci_domain_nr(struct pci_bus *pbus) { struct pci_pbm_info *pbm = pbus->sysdata; int ret; - if (pbm == NULL || pbm->parent == NULL) { + if (!pbm) { ret = -ENXIO; } else { ret = pbm->index; diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 1b44153f907..b538bfb0a47 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -431,22 +431,13 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); } -static int __init pci_fire_pbm_init(struct pci_controller_info *p, +static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, u32 portid) { const struct linux_prom64_registers *regs; struct device_node *dp = op->node; - struct pci_pbm_info *pbm; int err; - if ((portid & 1) == 0) - pbm = &p->pbm_A; - else - pbm = &p->pbm_B; - - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - pbm->numa_node = -1; pbm->pci_ops = &sun4u_pci_ops; @@ -455,7 +446,6 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->parent = p; pbm->prom_node = dp; pbm->name = dp->full_name; @@ -481,13 +471,9 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, /* XXX register error interrupt handlers XXX */ - return 0; -} + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; -static inline int portid_compare(u32 x, u32 y) -{ - if (x == (y ^ 1)) - return 1; return 0; } @@ -495,48 +481,41 @@ static int __devinit fire_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; int err; portid = of_getintprop_default(dp, "portid", 0xff); - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (portid_compare(pbm->portid, portid)) - return pci_fire_pbm_init(pbm->parent, op, portid); - } err = -ENOMEM; - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbminfo.\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); goto out_free_controller; } - p->pbm_A.iommu = iommu; + pbm->iommu = iommu; - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free_iommu_A; - } + err = pci_fire_pbm_init(pbm, op, portid); + if (err) + goto out_free_iommu; - p->pbm_B.iommu = iommu; + dev_set_drvdata(&op->dev, pbm); - return pci_fire_pbm_init(p, op, portid); + return 0; -out_free_iommu_A: - kfree(p->pbm_A.iommu); +out_free_iommu: + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 4125f7513c6..4937ce903a8 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -56,15 +56,11 @@ struct sparc64_msiq_cookie { }; #endif -struct pci_controller_info; - struct pci_pbm_info { struct pci_pbm_info *next; + struct pci_pbm_info *sibling; int index; - /* PCI controller we sit under. */ - struct pci_controller_info *parent; - /* Physical address base of controller registers. */ unsigned long controller_regs; @@ -107,6 +103,10 @@ struct pci_pbm_info { /* This will be 12 on PCI-E controllers, 8 elsewhere. */ unsigned long config_space_reg_bits; + unsigned long pci_afsr; + unsigned long pci_afar; + unsigned long pci_csr; + /* State of 66MHz capabilities on this PBM. */ int is_66mhz_capable; int all_devs_66mhz; @@ -151,12 +151,6 @@ struct pci_pbm_info { int numa_node; }; -struct pci_controller_info { - /* The PCI bus modules controlled by us. */ - struct pci_pbm_info pbm_A; - struct pci_pbm_info pbm_B; -}; - extern struct pci_pbm_info *pci_pbm_root; extern int pci_num_pbms; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 0be850e6e58..70a7af092be 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -146,24 +146,16 @@ static unsigned long stc_error_buf[128]; static unsigned long stc_tag_buf[16]; static unsigned long stc_line_buf[16]; -static void __psycho_check_one_stc(struct pci_pbm_info *pbm, - int is_pbm_a) +static void psycho_check_stc_error(struct pci_pbm_info *pbm) { struct strbuf *strbuf = &pbm->stc; - unsigned long regbase = pbm->controller_regs; unsigned long err_base, tag_base, line_base; u64 control; int i; - if (is_pbm_a) { - err_base = regbase + PSYCHO_STC_ERR_A; - tag_base = regbase + PSYCHO_STC_TAG_A; - line_base = regbase + PSYCHO_STC_LINE_A; - } else { - err_base = regbase + PSYCHO_STC_ERR_B; - tag_base = regbase + PSYCHO_STC_TAG_B; - line_base = regbase + PSYCHO_STC_LINE_B; - } + err_base = strbuf->strbuf_err_stat; + tag_base = strbuf->strbuf_tag_diag; + line_base = strbuf->strbuf_line_diag; spin_lock(&stc_buf_lock); @@ -239,15 +231,6 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, spin_unlock(&stc_buf_lock); } -static void __psycho_check_stc_error(struct pci_pbm_info *pbm, - unsigned long afsr, - unsigned long afar, - enum psycho_error_type type) -{ - __psycho_check_one_stc(pbm, - (pbm == &pbm->parent->pbm_A)); -} - /* When an Uncorrectable Error or a PCI Error happens, we * interrogate the IOMMU state to see if it is the cause. */ @@ -386,7 +369,7 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } - __psycho_check_stc_error(pbm, afsr, afar, type); + psycho_check_stc_error(pbm); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -412,7 +395,6 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, static irqreturn_t psycho_ue_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; unsigned long afsr, afar, error_bits; @@ -465,8 +447,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate both IOMMUs for error status. */ - psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); - psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); + psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); + if (pbm->sibling) + psycho_check_iommu_error(pbm->sibling, afsr, afar, UE_ERR); return IRQ_HANDLED; } @@ -573,23 +556,18 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) #define PSYCHO_PCI_AFAR_A 0x2018UL #define PSYCHO_PCI_AFAR_B 0x4018UL -static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm_a) +static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) { - unsigned long csr_reg, csr, csr_error_bits; + unsigned long csr, csr_error_bits; irqreturn_t ret = IRQ_NONE; u16 stat; - if (is_pbm_a) { - csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL; - } else { - csr_reg = pbm->controller_regs + PSYCHO_PCIB_CTRL; - } - csr = psycho_read(csr_reg); + csr = psycho_read(pbm->pci_csr); csr_error_bits = csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); if (csr_error_bits) { /* Clear the errors. */ - psycho_write(csr_reg, csr); + psycho_write(pbm->pci_csr, csr); /* Log 'em. */ if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) @@ -616,19 +594,12 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; - int is_pbm_a, reported; + int reported; - is_pbm_a = (pbm == &pbm->parent->pbm_A); - if (is_pbm_a) { - afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A; - afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A; - } else { - afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B; - afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B; - } + afsr_reg = pbm->pci_afsr; + afar_reg = pbm->pci_afar; /* Latch error status. */ afar = psycho_read(afar_reg); @@ -641,7 +612,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); if (!error_bits) - return psycho_pcierr_intr_other(pbm, is_pbm_a); + return psycho_pcierr_intr_other(pbm); psycho_write(afsr_reg, error_bits); /* Log the error. */ @@ -923,10 +894,16 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; + pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_A; + pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_A; + pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_A; } else { pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; + pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_B; + pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_B; + pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_B; } /* PSYCHO's streaming buffer lacks ctx flushing. */ pbm->stc.strbuf_ctxflush = 0; @@ -971,16 +948,10 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, #define PSYCHO_MEMSPACE_B 0x180000000UL #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL -static void __init psycho_pbm_init(struct pci_controller_info *p, +static void __init psycho_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, int is_pbm_a) { struct device_node *dp = op->node; - struct pci_pbm_info *pbm; - - if (is_pbm_a) - pbm = &p->pbm_A; - else - pbm = &p->pbm_B; pbm->next = pci_pbm_root; pci_pbm_root = pbm; @@ -996,7 +967,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->chip_version = of_getintprop_default(dp, "version#", 0); pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); - pbm->parent = p; pbm->prom_node = dp; pbm->name = dp->full_name; @@ -1013,6 +983,17 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, psycho_scan_bus(pbm, &op->dev); } +static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid) +{ + struct pci_pbm_info *pbm; + + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + if (pbm->portid == upa_portid) + return pbm; + } + return NULL; +} + #define PSYCHO_CONFIGSPACE 0x001000000UL static int __devinit psycho_probe(struct of_device *op, @@ -1020,7 +1001,6 @@ static int __devinit psycho_probe(struct of_device *op, { const struct linux_prom64_registers *pr_regs; struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; int is_pbm_a, err; @@ -1028,33 +1008,26 @@ static int __devinit psycho_probe(struct of_device *op, upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - struct pci_controller_info *p = pbm->parent; - - if (p->pbm_A.portid == upa_portid) { - is_pbm_a = (p->pbm_A.prom_node == NULL); - psycho_pbm_init(p, op, is_pbm_a); - return 0; - } - } - err = -ENOMEM; - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); - goto out_free_controller; + pbm->sibling = psycho_find_sibling(upa_portid); + if (pbm->sibling) { + iommu = pbm->sibling->iommu; + } else { + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); + goto out_free_controller; + } } - p->pbm_A.iommu = p->pbm_B.iommu = iommu; - - p->pbm_A.portid = upa_portid; - p->pbm_B.portid = upa_portid; + pbm->iommu = iommu; + pbm->portid = upa_portid; pr_regs = of_get_property(dp, "reg", NULL); err = -ENODEV; @@ -1063,29 +1036,43 @@ static int __devinit psycho_probe(struct of_device *op, goto out_free_iommu; } - p->pbm_A.controller_regs = pr_regs[2].phys_addr; - p->pbm_B.controller_regs = pr_regs[2].phys_addr; + is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + + pbm->controller_regs = pr_regs[2].phys_addr; + pbm->config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); - p->pbm_A.config_space = p->pbm_B.config_space = - (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); + if (is_pbm_a) { + pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_A; + pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_A; + pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIA_CTRL; + } else { + pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_B; + pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_B; + pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIB_CTRL; + } - psycho_controller_hwinit(&p->pbm_A); + psycho_controller_hwinit(pbm); + if (!pbm->sibling) { + err = psycho_iommu_init(pbm); + if (err) + goto out_free_iommu; + } - err = psycho_iommu_init(&p->pbm_A); - if (err) - goto out_free_iommu; + psycho_pbm_init(pbm, op, is_pbm_a); - is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + if (pbm->sibling) + pbm->sibling->sibling = pbm; - psycho_pbm_init(p, op, is_pbm_a); + dev_set_drvdata(&op->dev, pbm); return 0; out_free_iommu: - kfree(p->pbm_A.iommu); + if (!pbm->sibling) + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 707d6d6130f..8f779b58d65 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -734,8 +734,8 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, return 0; } -static void __init sabre_pbm_init(struct pci_controller_info *p, - struct pci_pbm_info *pbm, struct of_device *op) +static void __init sabre_pbm_init(struct pci_pbm_info *pbm, + struct of_device *op) { struct device_node *dp = op->node; @@ -750,7 +750,6 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->parent = p; pbm->prom_node = dp; pci_get_pbm_props(pbm); @@ -764,7 +763,6 @@ static int __devinit sabre_probe(struct of_device *op, { const struct linux_prom64_registers *pr_regs; struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; u32 upa_portid, dma_mask; struct iommu *iommu; @@ -786,26 +784,22 @@ static int __devinit sabre_probe(struct of_device *op, } err = -ENOMEM; - p = kzalloc(sizeof(*p), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); goto out_err; } - iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); goto out_free_controller; } - pbm = &p->pbm_A; pbm->iommu = iommu; upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - pbm->portid = upa_portid; /* @@ -840,8 +834,7 @@ static int __devinit sabre_probe(struct of_device *op, SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); /* Now map in PCI config space for entire SABRE. */ - pbm->config_space = - (pbm->controller_regs + SABRE_CONFIGSPACE); + pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE; vdma = of_get_property(dp, "virtual-dma", NULL); if (!vdma) { @@ -876,14 +869,20 @@ static int __devinit sabre_probe(struct of_device *op, /* * Look for APB underneath. */ - sabre_pbm_init(p, pbm, op); + sabre_pbm_init(pbm, op); + + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + + dev_set_drvdata(&op->dev, pbm); + return 0; out_free_iommu: - kfree(p->pbm_A.iommu); + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e1c565744d3..67e3640bc69 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -358,11 +358,12 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, spin_unlock_irqrestore(&iommu->lock, flags); } -static void schizo_check_iommu_error(struct pci_controller_info *p, +static void schizo_check_iommu_error(struct pci_pbm_info *pbm, enum schizo_error_type type) { - schizo_check_iommu_error_pbm(&p->pbm_A, type); - schizo_check_iommu_error_pbm(&p->pbm_B, type); + schizo_check_iommu_error_pbm(pbm, type); + if (pbm->sibling) + schizo_check_iommu_error_pbm(pbm->sibling, type); } /* Uncorrectable ECC error status gathering. */ @@ -387,7 +388,6 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, static irqreturn_t schizo_ue_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; unsigned long afsr, afar, error_bits; @@ -450,7 +450,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate IOMMU for error status. */ - schizo_check_iommu_error(p, UE_ERR); + schizo_check_iommu_error(pbm, UE_ERR); return IRQ_HANDLED; } @@ -651,7 +651,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg, afar_reg, base; unsigned long afsr, afar, error_bits; int reported; @@ -745,7 +744,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) * a bug in the IOMMU support code or a PCI device driver. */ if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { - schizo_check_iommu_error(p, PCI_ERR); + schizo_check_iommu_error(pbm, PCI_ERR); pci_scan_for_target_abort(pbm, pbm->pci_bus); } if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) @@ -806,7 +805,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; u64 errlog; errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); @@ -822,7 +820,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", pbm->name); - schizo_check_iommu_error(p, SAFARI_ERR); + schizo_check_iommu_error(pbm, SAFARI_ERR); return IRQ_HANDLED; } @@ -1329,13 +1327,12 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } } -static int __devinit schizo_pbm_init(struct pci_controller_info *p, +static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, u32 portid, int chip_type) { const struct linux_prom64_registers *regs; struct device_node *dp = op->node; - struct pci_pbm_info *pbm; const char *chipset_name; int is_pbm_a, err; @@ -1368,10 +1365,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, regs = of_get_property(dp, "reg", NULL); is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); - if (is_pbm_a) - pbm = &p->pbm_A; - else - pbm = &p->pbm_B; pbm->next = pci_pbm_root; pci_pbm_root = pbm; @@ -1384,7 +1377,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->parent = p; pbm->prom_node = dp; pbm->chip_type = chip_type; @@ -1430,10 +1422,21 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } +static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid, + int chip_type) +{ + struct pci_pbm_info *pbm; + + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + if (portid_compare(pbm->portid, portid, chip_type)) + return pbm; + } + return NULL; +} + static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) { struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; @@ -1442,50 +1445,37 @@ static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type portid = of_getintprop_default(dp, "portid", 0xff); err = -ENOMEM; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (portid_compare(pbm->portid, portid, chip_type)) { - if (schizo_pbm_init(pbm->parent, op, - portid, chip_type)) - goto out_err; - return 0; - } - } - - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + pbm->sibling = schizo_find_sibling(portid, chip_type); + + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free_controller; + goto out_free_pbm; } - p->pbm_A.iommu = iommu; + pbm->iommu = iommu; - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n"); - goto out_free_iommu_A; - } + if (schizo_pbm_init(pbm, op, portid, chip_type)) + goto out_free_iommu; - p->pbm_B.iommu = iommu; + if (pbm->sibling) + pbm->sibling->sibling = pbm; - if (schizo_pbm_init(p, op, portid, chip_type)) - goto out_free_iommu_B; + dev_set_drvdata(&op->dev, pbm); return 0; -out_free_iommu_B: - kfree(p->pbm_B.iommu); - -out_free_iommu_A: - kfree(p->pbm_A.iommu); +out_free_iommu: + kfree(pbm->iommu); -out_free_controller: - kfree(p); +out_free_pbm: + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 6bed2f6bf7c..233b22b8b57 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -42,6 +42,7 @@ struct iommu_batch { }; static DEFINE_PER_CPU(struct iommu_batch, iommu_batch); +static int iommu_batch_initialized; /* Interrupts must be disabled. */ static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry) @@ -887,21 +888,12 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) } #endif /* !(CONFIG_PCI_MSI) */ -static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, +static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, u32 devhandle) { struct device_node *dp = op->node; - struct pci_pbm_info *pbm; int err; - if (devhandle & 0x40) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - pbm->numa_node = of_node_to_nid(dp); pbm->pci_ops = &sun4v_pci_ops; @@ -909,7 +901,6 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; - pbm->parent = p; pbm->prom_node = dp; pbm->devhandle = devhandle; @@ -931,6 +922,9 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, pci_sun4v_scan_bus(pbm, &op->dev); + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + return 0; } @@ -939,7 +933,6 @@ static int __devinit pci_sun4v_probe(struct of_device *op, { const struct linux_prom64_registers *regs; static int hvapi_negotiated = 0; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct device_node *dp; struct iommu *iommu; @@ -972,51 +965,46 @@ static int __devinit pci_sun4v_probe(struct of_device *op, } devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (pbm->devhandle == (devhandle ^ 0x40)) { - return pci_sun4v_pbm_init(pbm->parent, op, devhandle); - } - } - err = -ENOMEM; - for_each_possible_cpu(i) { - unsigned long page = get_zeroed_page(GFP_ATOMIC); + if (!iommu_batch_initialized) { + for_each_possible_cpu(i) { + unsigned long page = get_zeroed_page(GFP_KERNEL); - if (!page) - goto out_err; + if (!page) + goto out_err; - per_cpu(iommu_batch, i).pglist = (u64 *) page; + per_cpu(iommu_batch, i).pglist = (u64 *) page; + } + iommu_batch_initialized = 1; } - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Could not allocate pci_controller_info\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Could not allocate pci_pbm_info\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); if (!iommu) { - printk(KERN_ERR PFX "Could not allocate pbm A iommu\n"); + printk(KERN_ERR PFX "Could not allocate pbm iommu\n"); goto out_free_controller; } - p->pbm_A.iommu = iommu; + pbm->iommu = iommu; - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Could not allocate pbm B iommu\n"); - goto out_free_iommu_A; - } + err = pci_sun4v_pbm_init(pbm, op, devhandle); + if (err) + goto out_free_iommu; - p->pbm_B.iommu = iommu; + dev_set_drvdata(&op->dev, pbm); - return pci_sun4v_pbm_init(p, op, devhandle); + return 0; -out_free_iommu_A: - kfree(p->pbm_A.iommu); +out_free_iommu: + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; -- cgit v1.2.3 From 22fecbae4446ad470b9237ee9b79f80f343b3838 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 00:19:28 -0700 Subject: sparc64: Record OF device instead of device node pointer in pci_pbm_info. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 +- arch/sparc64/kernel/pci_common.c | 8 ++++---- arch/sparc64/kernel/pci_fire.c | 2 +- arch/sparc64/kernel/pci_impl.h | 3 ++- arch/sparc64/kernel/pci_msi.c | 18 +++++++++--------- arch/sparc64/kernel/pci_psycho.c | 4 ++-- arch/sparc64/kernel/pci_sabre.c | 4 ++-- arch/sparc64/kernel/pci_schizo.c | 12 ++++++------ arch/sparc64/kernel/pci_sun4v.c | 6 +++--- 9 files changed, 30 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 3070f6faecc..c6e81dea2cf 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -676,7 +676,7 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, struct device *parent) { - struct device_node *node = pbm->prom_node; + struct device_node *node = pbm->op->node; struct pci_bus *bus; printk("PCI: Scanning PBM %s\n", node->full_name); diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 09a5ec200c6..23b88082d0b 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -314,12 +314,12 @@ struct pci_ops sun4v_pci_ops = { void pci_get_pbm_props(struct pci_pbm_info *pbm) { - const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL); + const u32 *val = of_get_property(pbm->op->node, "bus-range", NULL); pbm->pci_first_busno = val[0]; pbm->pci_last_busno = val[1]; - val = of_get_property(pbm->prom_node, "ino-bitmap", NULL); + val = of_get_property(pbm->op->node, "ino-bitmap", NULL); if (val) { pbm->ino_bitmap = (((u64)val[1] << 32UL) | ((u64)val[0] << 0UL)); @@ -365,7 +365,7 @@ static void pci_register_legacy_regions(struct resource *io_res, static void pci_register_iommu_region(struct pci_pbm_info *pbm) { - const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + const u32 *vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); if (vdma) { struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); @@ -389,7 +389,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) int num_pbm_ranges; saw_mem = saw_io = 0; - pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i); + pbm_ranges = of_get_property(pbm->op->node, "ranges", &i); if (!pbm_ranges) { prom_printf("PCI: Fatal error, missing PBM ranges property " " for %s\n", diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index b538bfb0a47..7e1a9b6717b 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -446,7 +446,7 @@ static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->prom_node = dp; + pbm->op = op; pbm->name = dp->full_name; regs = of_get_property(dp, "reg", NULL); diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 4937ce903a8..b300f39e9e8 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,7 @@ struct pci_pbm_info { char *name; /* OBP specific information. */ - struct device_node *prom_node; + struct of_device *op; u64 ino_bitmap; /* PBM I/O and Memory space resources. */ diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c index 60c71e35021..2e680f34f72 100644 --- a/arch/sparc64/kernel/pci_msi.c +++ b/arch/sparc64/kernel/pci_msi.c @@ -323,7 +323,7 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, const u32 *val; int len; - val = of_get_property(pbm->prom_node, "#msi-eqs", &len); + val = of_get_property(pbm->op->node, "#msi-eqs", &len); if (!val || len != 4) goto no_msi; pbm->msiq_num = *val; @@ -346,16 +346,16 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, u32 msi64_len; } *arng; - val = of_get_property(pbm->prom_node, "msi-eq-size", &len); + val = of_get_property(pbm->op->node, "msi-eq-size", &len); if (!val || len != 4) goto no_msi; pbm->msiq_ent_count = *val; - mqp = of_get_property(pbm->prom_node, + mqp = of_get_property(pbm->op->node, "msi-eq-to-devino", &len); if (!mqp) - mqp = of_get_property(pbm->prom_node, + mqp = of_get_property(pbm->op->node, "msi-eq-devino", &len); if (!mqp || len != sizeof(struct msiq_prop)) goto no_msi; @@ -363,27 +363,27 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, pbm->msiq_first = mqp->first_msiq; pbm->msiq_first_devino = mqp->first_devino; - val = of_get_property(pbm->prom_node, "#msi", &len); + val = of_get_property(pbm->op->node, "#msi", &len); if (!val || len != 4) goto no_msi; pbm->msi_num = *val; - mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); + mrng = of_get_property(pbm->op->node, "msi-ranges", &len); if (!mrng || len != sizeof(struct msi_range_prop)) goto no_msi; pbm->msi_first = mrng->first_msi; - val = of_get_property(pbm->prom_node, "msi-data-mask", &len); + val = of_get_property(pbm->op->node, "msi-data-mask", &len); if (!val || len != 4) goto no_msi; pbm->msi_data_mask = *val; - val = of_get_property(pbm->prom_node, "msix-data-width", &len); + val = of_get_property(pbm->op->node, "msix-data-width", &len); if (!val || len != 4) goto no_msi; pbm->msix_data_width = *val; - arng = of_get_property(pbm->prom_node, "msi-address-ranges", + arng = of_get_property(pbm->op->node, "msi-address-ranges", &len); if (!arng || len != sizeof(struct addr_range_prop)) goto no_msi; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 70a7af092be..4562b3e0b54 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -690,7 +690,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct of_device *op = of_find_device_by_node(pbm->op->node); unsigned long base = pbm->controller_regs; u64 tmp; int err; @@ -967,7 +967,7 @@ static void __init psycho_pbm_init(struct pci_pbm_info *pbm, pbm->chip_version = of_getintprop_default(dp, "version#", 0); pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); - pbm->prom_node = dp; + pbm->op = op; pbm->name = dp->full_name; printk(KERN_INFO "%s: PSYCHO PCI Bus Module ver[%x:%x]\n", diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 8f779b58d65..196049bb14b 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -543,7 +543,7 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) static void sabre_register_error_handlers(struct pci_pbm_info *pbm) { - struct device_node *dp = pbm->prom_node; + struct device_node *dp = pbm->op->node; struct of_device *op; unsigned long base = pbm->controller_regs; u64 tmp; @@ -750,7 +750,7 @@ static void __init sabre_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->prom_node = dp; + pbm->op = op; pci_get_pbm_props(pbm); pci_determine_mem_io_space(pbm); diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 67e3640bc69..c30856541bb 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -862,7 +862,7 @@ static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) */ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct of_device *op = of_find_device_by_node(pbm->op->node); u64 tmp, err_mask, err_no_mask; int err; @@ -958,7 +958,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) static void schizo_register_error_handlers(struct pci_pbm_info *pbm) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct of_device *op = of_find_device_by_node(pbm->op->node); u64 tmp, err_mask, err_no_mask; int err; @@ -1088,7 +1088,7 @@ static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm, { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = - (of_find_property(pbm->prom_node, "66mhz-capable", NULL) + (of_find_property(pbm->op->node, "66mhz-capable", NULL) != NULL); pbm->pci_bus = pci_scan_one_pbm(pbm, parent); @@ -1158,7 +1158,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) u32 dma_mask; u64 control; - vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); if (!vdma) vdma = vdma_default; @@ -1288,7 +1288,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) pbm->chip_version >= 0x2) tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; - if (!of_find_property(pbm->prom_node, "no-bus-parking", NULL)) + if (!of_find_property(pbm->op->node, "no-bus-parking", NULL)) tmp |= SCHIZO_PCICTRL_PARK; else tmp &= ~SCHIZO_PCICTRL_PARK; @@ -1377,7 +1377,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->prom_node = dp; + pbm->op = op; pbm->chip_type = chip_type; pbm->chip_version = of_getintprop_default(dp, "version#", 0); diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 233b22b8b57..97a77bcd255 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -550,7 +550,7 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm, struct property *prop; struct device_node *dp; - dp = pbm->prom_node; + dp = pbm->op->node; prop = of_find_property(dp, "66mhz-capable", NULL); pbm->is_66mhz_capable = (prop != NULL); pbm->pci_bus = pci_scan_one_pbm(pbm, parent); @@ -594,7 +594,7 @@ static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) u32 dma_mask, dma_offset; const u32 *vdma; - vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); if (!vdma) vdma = vdma_default; @@ -901,7 +901,7 @@ static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; - pbm->prom_node = dp; + pbm->op = op; pbm->devhandle = devhandle; -- cgit v1.2.3 From a21cff3e5e39c087b5a4c5efb20f1744475c556e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 03:07:03 -0700 Subject: sparc64: Start commonizing code common between SABRE and PSYCHO. These are very similar chips, in fact they are identical in some macro blocks. So start commonizing code which they can share. We begin with the IOMMU initialization sequence. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 2 +- arch/sparc64/kernel/pci_psycho.c | 65 +++----------------------- arch/sparc64/kernel/pci_sabre.c | 63 +------------------------ arch/sparc64/kernel/psycho_common.c | 93 +++++++++++++++++++++++++++++++++++++ arch/sparc64/kernel/psycho_common.h | 8 ++++ 5 files changed, 111 insertions(+), 120 deletions(-) create mode 100644 arch/sparc64/kernel/psycho_common.c create mode 100644 arch/sparc64/kernel/psycho_common.h (limited to 'arch') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index fb02807167e..c0b8009ab19 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -16,7 +16,7 @@ obj-y := process.o setup.o cpu.o idprom.o reboot.o \ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += pci.o pci_common.o \ +obj-$(CONFIG_PCI) += pci.o pci_common.o psycho_common.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 4562b3e0b54..4681e3d8b5f 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -20,6 +20,7 @@ #include "pci_impl.h" #include "iommu_common.h" +#include "psycho_common.h" #define DRIVER_NAME "psycho" #define PFX DRIVER_NAME ": " @@ -787,63 +788,6 @@ static void __init psycho_scan_bus(struct pci_pbm_info *pbm, psycho_register_error_handlers(pbm); } -static int psycho_iommu_init(struct pci_pbm_info *pbm) -{ - struct iommu *iommu = pbm->iommu; - unsigned long i; - u64 control; - int err; - - /* Register addresses. */ - iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; - iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; - iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; - iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); - - /* PSYCHO's IOMMU lacks ctx flushing. */ - iommu->iommu_ctxflush = 0; - - /* We use the main control register of PSYCHO as the write - * completion register. - */ - iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL; - - /* - * Invalidate TLB Entries. - */ - control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); - control |= PSYCHO_IOMMU_CTRL_DENAB; - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); - for (i = 0; i < 16; i++) { - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diag mode enabled for full-flushing done - * in pci_iommu.c - */ - err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, - pbm->numa_node); - if (err) { - printk(KERN_ERR PFX "iommu_table_init() fails\n"); - return err; - } - - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, - __pa(iommu->page_table)); - - control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); - control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); - control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); - - /* If necessary, hook us up for starfire IRQ translations. */ - if (this_is_starfire) - starfire_hookup(pbm->portid); - - return 0; -} - #define PSYCHO_IRQ_RETRY 0x1a00UL #define PSYCHO_PCIA_DIAG 0x2020UL #define PSYCHO_PCIB_DIAG 0x4020UL @@ -1053,9 +997,14 @@ static int __devinit psycho_probe(struct of_device *op, psycho_controller_hwinit(pbm); if (!pbm->sibling) { - err = psycho_iommu_init(pbm); + err = psycho_iommu_init(pbm, 128, 0xc0000000, + 0xffffffff, PSYCHO_CONTROL); if (err) goto out_free_iommu; + + /* If necessary, hook us up for starfire IRQ translations. */ + if (this_is_starfire) + starfire_hookup(pbm->portid); } psycho_pbm_init(pbm, op, is_pbm_a); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 196049bb14b..a3a276de75a 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -20,6 +20,7 @@ #include "pci_impl.h" #include "iommu_common.h" +#include "psycho_common.h" #define DRIVER_NAME "sabre" #define PFX DRIVER_NAME ": " @@ -674,66 +675,6 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm, sabre_register_error_handlers(pbm); } -static int sabre_iommu_init(struct pci_pbm_info *pbm, - int tsbsize, unsigned long dvma_offset, - u32 dma_mask) -{ - struct iommu *iommu = pbm->iommu; - unsigned long i; - u64 control; - int err; - - /* Register addresses. */ - iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL; - iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE; - iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH; - iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); - iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC; - /* Sabre's IOMMU lacks ctx flushing. */ - iommu->iommu_ctxflush = 0; - - /* Invalidate TLB Entries. */ - control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); - control |= SABRE_IOMMUCTRL_DENAB; - sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); - - for(i = 0; i < 16; i++) { - sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diag mode enabled for full-flushing done - * in pci_iommu.c - */ - err = iommu_table_init(iommu, tsbsize * 1024 * 8, - dvma_offset, dma_mask, pbm->numa_node); - if (err) { - printk(KERN_ERR PFX "iommu_table_init() failed\n"); - return err; - } - - sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, - __pa(iommu->page_table)); - - control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); - control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); - control |= SABRE_IOMMUCTRL_ENAB; - switch(tsbsize) { - case 64: - control |= SABRE_IOMMU_TSBSZ_64K; - break; - case 128: - control |= SABRE_IOMMU_TSBSZ_128K; - break; - default: - printk(KERN_ERR PFX "Illegal TSB size %d\n", tsbsize); - return -EINVAL; - } - sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); - - return 0; -} - static void __init sabre_pbm_init(struct pci_pbm_info *pbm, struct of_device *op) { @@ -862,7 +803,7 @@ static int __devinit sabre_probe(struct of_device *op, goto out_free_iommu; } - err = sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); + err = psycho_iommu_init(pbm, tsbsize, vdma[0], dma_mask, SABRE_WRSYNC); if (err) goto out_free_iommu; diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c new file mode 100644 index 00000000000..07acc13637b --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.c @@ -0,0 +1,93 @@ +/* psycho_common.c: Code common to PSYCHO and derivative PCI controllers. + * + * Copyright (C) 2008 David S. Miller + */ +#include + +#include + +#include "pci_impl.h" +#include "psycho_common.h" + +#define PSYCHO_IOMMU_TAG 0xa580UL +#define PSYCHO_IOMMU_DATA 0xa600UL + +static void psycho_iommu_flush(struct pci_pbm_info *pbm) +{ + int i; + + for (i = 0; i < 16; i++) { + unsigned long off = i * 8; + + upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_TAG + off); + upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_DATA + off); + } +} + +#define PSYCHO_IOMMU_CONTROL 0x0200UL +#define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL +#define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000UL +#define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000UL +#define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000UL +#define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000UL +#define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000UL +#define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000UL +#define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000UL +#define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000UL +#define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL +#define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002UL +#define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001UL +#define PSYCHO_IOMMU_FLUSH 0x0210UL +#define PSYCHO_IOMMU_TSBBASE 0x0208UL + +int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, + u32 dvma_offset, u32 dma_mask, + unsigned long write_complete_offset) +{ + struct iommu *iommu = pbm->iommu; + u64 control; + int err; + + iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; + iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; + iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; + iommu->iommu_tags = pbm->controller_regs + PSYCHO_IOMMU_TAG; + iommu->write_complete_reg = (pbm->controller_regs + + write_complete_offset); + + iommu->iommu_ctxflush = 0; + + control = upa_readq(iommu->iommu_control); + control |= PSYCHO_IOMMU_CTRL_DENAB; + upa_writeq(control, iommu->iommu_control); + + psycho_iommu_flush(pbm); + + /* Leave diag mode enabled for full-flushing done in pci_iommu.c */ + err = iommu_table_init(iommu, tsbsize * 1024 * 8, + dvma_offset, dma_mask, pbm->numa_node); + if (err) + return err; + + upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); + + control = upa_readq(iommu->iommu_control); + control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); + control |= PSYCHO_IOMMU_CTRL_ENAB; + + switch (tsbsize) { + case 64: + control |= PSYCHO_IOMMU_TSBSZ_64K; + break; + case 128: + control |= PSYCHO_IOMMU_TSBSZ_128K; + break; + default: + return -EINVAL; + } + + upa_writeq(control, iommu->iommu_control); + + return 0; + +} diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h new file mode 100644 index 00000000000..bffaff57d5e --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.h @@ -0,0 +1,8 @@ +#ifndef _PSYCHO_COMMON_H +#define _PSYCHO_COMMON_H + +extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, + u32 dvma_offset, u32 dma_mask, + unsigned long write_complete_offset); + +#endif /* _PSYCHO_COMMON_H */ -- cgit v1.2.3 From 1c03a55cdf309d0939e881b313abbe7e9a67d95e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 03:15:56 -0700 Subject: sparc64: Create and use psycho_pbm_init_common(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 32 ++++---------------------------- arch/sparc64/kernel/pci_sabre.c | 19 +------------------ arch/sparc64/kernel/psycho_common.c | 22 ++++++++++++++++++++++ arch/sparc64/kernel/psycho_common.h | 4 ++++ 4 files changed, 31 insertions(+), 46 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 4681e3d8b5f..2de51fb34ee 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -895,35 +895,8 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, static void __init psycho_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, int is_pbm_a) { - struct device_node *dp = op->node; - - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - - pbm->numa_node = -1; - - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; - - pbm->index = pci_num_pbms++; - - pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; - pbm->chip_version = of_getintprop_default(dp, "version#", 0); - pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); - - pbm->op = op; - pbm->name = dp->full_name; - - printk(KERN_INFO "%s: PSYCHO PCI Bus Module ver[%x:%x]\n", - pbm->name, - pbm->chip_version, pbm->chip_revision); - - pci_determine_mem_io_space(pbm); - - pci_get_pbm_props(pbm); - + psycho_pbm_init_common(pbm, op, "PSYCHO", PBM_CHIP_TYPE_PSYCHO); psycho_pbm_strbuf_init(pbm, is_pbm_a); - psycho_scan_bus(pbm, &op->dev); } @@ -1009,6 +982,9 @@ static int __devinit psycho_probe(struct of_device *op, psycho_pbm_init(pbm, op, is_pbm_a); + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + if (pbm->sibling) pbm->sibling->sibling = pbm; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index a3a276de75a..ae11d67388e 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -678,24 +678,7 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm, static void __init sabre_pbm_init(struct pci_pbm_info *pbm, struct of_device *op) { - struct device_node *dp = op->node; - - pbm->name = dp->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->numa_node = -1; - - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; - - pbm->index = pci_num_pbms++; - - pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->op = op; - pci_get_pbm_props(pbm); - - pci_determine_mem_io_space(pbm); - + psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); sabre_scan_bus(pbm, &op->dev); } diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c index 07acc13637b..1b4d462513d 100644 --- a/arch/sparc64/kernel/psycho_common.c +++ b/arch/sparc64/kernel/psycho_common.c @@ -91,3 +91,25 @@ int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, return 0; } + +void psycho_pbm_init_common(struct pci_pbm_info *pbm, struct of_device *op, + const char *chip_name, int chip_type) +{ + struct device_node *dp = op->node; + + pbm->name = dp->full_name; + pbm->numa_node = -1; + pbm->chip_type = chip_type; + pbm->chip_version = of_getintprop_default(dp, "version#", 0); + pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); + pbm->op = op; + pbm->pci_ops = &sun4u_pci_ops; + pbm->config_space_reg_bits = 8; + pbm->index = pci_num_pbms++; + pci_get_pbm_props(pbm); + pci_determine_mem_io_space(pbm); + + printk(KERN_INFO "%s: %s PCI Bus Module ver[%x:%x]\n", + pbm->name, chip_name, + pbm->chip_version, pbm->chip_revision); +} diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h index bffaff57d5e..adfbadb6986 100644 --- a/arch/sparc64/kernel/psycho_common.h +++ b/arch/sparc64/kernel/psycho_common.h @@ -5,4 +5,8 @@ extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, u32 dvma_offset, u32 dma_mask, unsigned long write_complete_offset); +extern void psycho_pbm_init_common(struct pci_pbm_info *pbm, + struct of_device *op, + const char *chip_name, int chip_type); + #endif /* _PSYCHO_COMMON_H */ -- cgit v1.2.3 From e6e003720fd7123482f77dcec19e930d272937fe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 03:52:51 -0700 Subject: sparc64: Commonize large portions of PSYCHO error handling. The IOMMU and streaming cache error interrogation is moved here as well as the PCI error interrupt handler. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 361 ------------------------------------ arch/sparc64/kernel/pci_sabre.c | 223 +--------------------- arch/sparc64/kernel/psycho_common.c | 353 +++++++++++++++++++++++++++++++++++ arch/sparc64/kernel/psycho_common.h | 11 ++ 4 files changed, 369 insertions(+), 579 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 2de51fb34ee..bac9c1ba40e 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -98,9 +98,6 @@ static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, } /* PSYCHO error handling support. */ -enum psycho_error_type { - UE_ERR, CE_ERR, PCI_ERR -}; /* Helper function of IOMMU error checking, which checks out * the state of the streaming buffers. The IOMMU lock is @@ -125,112 +122,10 @@ enum psycho_error_type { #define PSYCHO_STC_DATA_B 0xc000UL #define PSYCHO_STC_ERR_A 0xb400UL #define PSYCHO_STC_ERR_B 0xc400UL -#define PSYCHO_STCERR_WRITE 0x0000000000000002UL /* Write Error */ -#define PSYCHO_STCERR_READ 0x0000000000000001UL /* Read Error */ #define PSYCHO_STC_TAG_A 0xb800UL #define PSYCHO_STC_TAG_B 0xc800UL -#define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL /* Physical Page Number */ -#define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL /* Virtual Page Number */ -#define PSYCHO_STCTAG_VALID 0x0000000000000002UL /* Valid */ -#define PSYCHO_STCTAG_WRITE 0x0000000000000001UL /* Writable */ #define PSYCHO_STC_LINE_A 0xb900UL #define PSYCHO_STC_LINE_B 0xc900UL -#define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL /* LRU Index */ -#define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL /* Dirty Data Start Pointer */ -#define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL /* Line Address */ -#define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL /* Dirty Data End Pointer */ -#define PSYCHO_STCLINE_VALID 0x0000000000000002UL /* Valid */ -#define PSYCHO_STCLINE_FOFN 0x0000000000000001UL /* Fetch Outstanding / Flush Necessary */ - -static DEFINE_SPINLOCK(stc_buf_lock); -static unsigned long stc_error_buf[128]; -static unsigned long stc_tag_buf[16]; -static unsigned long stc_line_buf[16]; - -static void psycho_check_stc_error(struct pci_pbm_info *pbm) -{ - struct strbuf *strbuf = &pbm->stc; - unsigned long err_base, tag_base, line_base; - u64 control; - int i; - - err_base = strbuf->strbuf_err_stat; - tag_base = strbuf->strbuf_tag_diag; - line_base = strbuf->strbuf_line_diag; - - spin_lock(&stc_buf_lock); - - /* This is __REALLY__ dangerous. When we put the - * streaming buffer into diagnostic mode to probe - * it's tags and error status, we _must_ clear all - * of the line tag valid bits before re-enabling - * the streaming buffer. If any dirty data lives - * in the STC when we do this, we will end up - * invalidating it before it has a chance to reach - * main memory. - */ - control = psycho_read(strbuf->strbuf_control); - psycho_write(strbuf->strbuf_control, - (control | PSYCHO_STRBUF_CTRL_DENAB)); - for (i = 0; i < 128; i++) { - unsigned long val; - - val = psycho_read(err_base + (i * 8UL)); - psycho_write(err_base + (i * 8UL), 0UL); - stc_error_buf[i] = val; - } - for (i = 0; i < 16; i++) { - stc_tag_buf[i] = psycho_read(tag_base + (i * 8UL)); - stc_line_buf[i] = psycho_read(line_base + (i * 8UL)); - psycho_write(tag_base + (i * 8UL), 0UL); - psycho_write(line_base + (i * 8UL), 0UL); - } - - /* OK, state is logged, exit diagnostic mode. */ - psycho_write(strbuf->strbuf_control, control); - - for (i = 0; i < 16; i++) { - int j, saw_error, first, last; - - saw_error = 0; - first = i * 8; - last = first + 8; - for (j = first; j < last; j++) { - unsigned long errval = stc_error_buf[j]; - if (errval != 0) { - saw_error++; - printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n", - pbm->name, - j, - (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, - (errval & PSYCHO_STCERR_READ) ? 1 : 0); - } - } - if (saw_error != 0) { - unsigned long tagval = stc_tag_buf[i]; - unsigned long lineval = stc_line_buf[i]; - printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", - pbm->name, - i, - ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), - (tagval & PSYCHO_STCTAG_VPN), - ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), - ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); - printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" - "V(%d)FOFN(%d)]\n", - pbm->name, - i, - ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), - ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), - ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), - ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), - ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), - ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); - } - } - - spin_unlock(&stc_buf_lock); -} /* When an Uncorrectable Error or a PCI Error happens, we * interrogate the IOMMU state to see if it is the cause. @@ -257,122 +152,7 @@ static void psycho_check_stc_error(struct pci_pbm_info *pbm) #define PSYCHO_IOMMU_TSBBASE 0x0208UL #define PSYCHO_IOMMU_FLUSH 0x0210UL #define PSYCHO_IOMMU_TAG 0xa580UL -#define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) -#define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) -#define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) -#define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) -#define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) -#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL #define PSYCHO_IOMMU_DATA 0xa600UL -#define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) -#define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) -#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL -static void psycho_check_iommu_error(struct pci_pbm_info *pbm, - unsigned long afsr, - unsigned long afar, - enum psycho_error_type type) -{ - struct iommu *iommu = pbm->iommu; - unsigned long iommu_tag[16]; - unsigned long iommu_data[16]; - unsigned long flags; - u64 control; - int i; - - spin_lock_irqsave(&iommu->lock, flags); - control = psycho_read(iommu->iommu_control); - if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { - char *type_string; - - /* Clear the error encountered bit. */ - control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; - psycho_write(iommu->iommu_control, control); - - switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("%s: IOMMU Error, type[%s]\n", - pbm->name, type_string); - - /* Put the IOMMU into diagnostic mode and probe - * it's TLB for entries with error status. - * - * It is very possible for another DVMA to occur - * while we do this probe, and corrupt the system - * further. But we are so screwed at this point - * that we are likely to crash hard anyways, so - * get as much diagnostic information to the - * console as we can. - */ - psycho_write(iommu->iommu_control, - control | PSYCHO_IOMMU_CTRL_DENAB); - for (i = 0; i < 16; i++) { - unsigned long base = pbm->controller_regs; - - iommu_tag[i] = - psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); - iommu_data[i] = - psycho_read(base + PSYCHO_IOMMU_DATA + (i * 8UL)); - - /* Now clear out the entry. */ - psycho_write(base + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(base + PSYCHO_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diagnostic mode. */ - psycho_write(iommu->iommu_control, control); - - for (i = 0; i < 16; i++) { - unsigned long tag, data; - - tag = iommu_tag[i]; - if (!(tag & PSYCHO_IOMMU_TAG_ERR)) - continue; - - data = iommu_data[i]; - switch((tag & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("%s: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", - pbm->name, i, type_string, - ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), - ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), - ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); - printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", - pbm->name, i, - ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), - ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); - } - } - psycho_check_stc_error(pbm); - spin_unlock_irqrestore(&iommu->lock, flags); -} /* Uncorrectable Errors. Cause of the error and the address are * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors @@ -540,150 +320,9 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) */ #define PSYCHO_PCI_AFSR_A 0x2010UL #define PSYCHO_PCI_AFSR_B 0x4010UL -#define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL /* Primary Master Abort Error */ -#define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL /* Primary Target Abort Error */ -#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */ -#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */ -#define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort Error */ -#define PSYCHO_PCIAFSR_STA 0x0400000000000000UL /* Secondary Target Abort Error */ -#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */ -#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */ -#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL /* Reserved */ -#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ -#define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL /* Trans was block operation */ -#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL /* Reserved */ -#define PSYCHO_PCIAFSR_MID 0x000000003e000000UL /* MID causing the error */ -#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL /* Reserved */ #define PSYCHO_PCI_AFAR_A 0x2018UL #define PSYCHO_PCI_AFAR_B 0x4018UL -static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) -{ - unsigned long csr, csr_error_bits; - irqreturn_t ret = IRQ_NONE; - u16 stat; - - csr = psycho_read(pbm->pci_csr); - csr_error_bits = - csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); - if (csr_error_bits) { - /* Clear the errors. */ - psycho_write(pbm->pci_csr, csr); - - /* Log 'em. */ - if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) - printk("%s: PCI streaming byte hole error asserted.\n", - pbm->name); - if (csr_error_bits & PSYCHO_PCICTRL_SERR) - printk("%s: PCI SERR signal asserted.\n", pbm->name); - ret = IRQ_HANDLED; - } - pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); - if (stat & (PCI_STATUS_PARITY | - PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | - PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("%s: PCI bus error, PCI_STATUS[%04x]\n", - pbm->name, stat); - pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); - ret = IRQ_HANDLED; - } - return ret; -} - -static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) -{ - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int reported; - - afsr_reg = pbm->pci_afsr; - afar_reg = pbm->pci_afar; - - /* Latch error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | - PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | - PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | - PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); - if (!error_bits) - return psycho_pcierr_intr_other(pbm); - psycho_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("%s: PCI Error, primary error type[%s]\n", - pbm->name, - (((error_bits & PSYCHO_PCIAFSR_PMA) ? - "Master Abort" : - ((error_bits & PSYCHO_PCIAFSR_PTA) ? - "Target Abort" : - ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? - "Excessive Retries" : - ((error_bits & PSYCHO_PCIAFSR_PPERR) ? - "Parity Error" : "???")))))); - printk("%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", - pbm->name, - (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, - (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, - (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); - printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); - printk("%s: PCI Secondary errors [", pbm->name); - reported = 0; - if (afsr & PSYCHO_PCIAFSR_SMA) { - reported++; - printk("(Master Abort)"); - } - if (afsr & PSYCHO_PCIAFSR_STA) { - reported++; - printk("(Target Abort)"); - } - if (afsr & PSYCHO_PCIAFSR_SRTRY) { - reported++; - printk("(Excessive Retries)"); - } - if (afsr & PSYCHO_PCIAFSR_SPERR) { - reported++; - printk("(Parity Error)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* For the error types shown, scan PBM's PCI bus for devices - * which have logged that error type. - */ - - /* If we see a Target Abort, this could be the result of an - * IOMMU translation error of some sort. It is extremely - * useful to log this information as usually it indicates - * a bug in the IOMMU support code or a PCI device driver. - */ - if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { - psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); - pci_scan_for_target_abort(pbm, pbm->pci_bus); - } - if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) - pci_scan_for_master_abort(pbm, pbm->pci_bus); - - /* For excessive retries, PSYCHO/PBM will abort the device - * and there is no way to specifically check for excessive - * retries in the config space status registers. So what - * we hope is that we'll catch it via the master/target - * abort events. - */ - - if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(pbm, pbm->pci_bus); - - return IRQ_HANDLED; -} - /* XXX What about PowerFail/PowerManagement??? -DaveM */ #define PSYCHO_ECC_CTRL 0x0020 #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index ae11d67388e..f8089aa84f6 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -210,95 +210,6 @@ static int hummingbird_p; static struct pci_bus *sabre_root_bus; -/* SABRE error handling support. */ -static void sabre_check_iommu_error(struct pci_pbm_info *pbm, - unsigned long afsr, - unsigned long afar) -{ - struct iommu *iommu = pbm->iommu; - unsigned long iommu_tag[16]; - unsigned long iommu_data[16]; - unsigned long flags; - u64 control; - int i; - - spin_lock_irqsave(&iommu->lock, flags); - control = sabre_read(iommu->iommu_control); - if (control & SABRE_IOMMUCTRL_ERR) { - char *type_string; - - /* Clear the error encountered bit. - * NOTE: On Sabre this is write 1 to clear, - * which is different from Psycho. - */ - sabre_write(iommu->iommu_control, control); - switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) { - case 1: - type_string = "Invalid Error"; - break; - case 3: - type_string = "ECC Error"; - break; - default: - type_string = "Unknown"; - break; - }; - printk("%s: IOMMU Error, type[%s]\n", - pbm->name, type_string); - - /* Enter diagnostic mode and probe for error'd - * entries in the IOTLB. - */ - control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR); - sabre_write(iommu->iommu_control, - (control | SABRE_IOMMUCTRL_DENAB)); - for (i = 0; i < 16; i++) { - unsigned long base = pbm->controller_regs; - - iommu_tag[i] = - sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); - iommu_data[i] = - sabre_read(base + SABRE_IOMMU_DATA + (i * 8UL)); - sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0); - } - sabre_write(iommu->iommu_control, control); - - for (i = 0; i < 16; i++) { - unsigned long tag, data; - - tag = iommu_tag[i]; - if (!(tag & SABRE_IOMMUTAG_ERR)) - continue; - - data = iommu_data[i]; - switch((tag & SABRE_IOMMUTAG_ERRSTS) >> 23UL) { - case 1: - type_string = "Invalid Error"; - break; - case 3: - type_string = "ECC Error"; - break; - default: - type_string = "Unknown"; - break; - }; - printk("%s: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", - pbm->name, i, tag, type_string, - ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), - ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), - ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); - printk("%s: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", - pbm->name, i, data, - ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), - ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), - ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), - ((data & SABRE_IOMMUDATA_PPN) << IOMMU_PAGE_SHIFT)); - } - } - spin_unlock_irqrestore(&iommu->lock, flags); -} - static irqreturn_t sabre_ue_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; @@ -354,7 +265,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate IOMMU for error status. */ - sabre_check_iommu_error(pbm, afsr, afar); + psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); return IRQ_HANDLED; } @@ -415,133 +326,6 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) -{ - unsigned long csr_reg, csr, csr_error_bits; - irqreturn_t ret = IRQ_NONE; - u16 stat; - - csr_reg = pbm->controller_regs + SABRE_PCICTRL; - csr = sabre_read(csr_reg); - csr_error_bits = - csr & SABRE_PCICTRL_SERR; - if (csr_error_bits) { - /* Clear the errors. */ - sabre_write(csr_reg, csr); - - /* Log 'em. */ - if (csr_error_bits & SABRE_PCICTRL_SERR) - printk("%s: PCI SERR signal asserted.\n", - pbm->name); - ret = IRQ_HANDLED; - } - pci_bus_read_config_word(sabre_root_bus, 0, - PCI_STATUS, &stat); - if (stat & (PCI_STATUS_PARITY | - PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | - PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("%s: PCI bus error, PCI_STATUS[%04x]\n", - pbm->name, stat); - pci_bus_write_config_word(sabre_root_bus, 0, - PCI_STATUS, 0xffff); - ret = IRQ_HANDLED; - } - return ret; -} - -static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) -{ - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int reported; - - afsr_reg = pbm->controller_regs + SABRE_PIOAFSR; - afar_reg = pbm->controller_regs + SABRE_PIOAFAR; - - /* Latch error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA | - SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR | - SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA | - SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR); - if (!error_bits) - return sabre_pcierr_intr_other(pbm); - sabre_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("%s: PCI Error, primary error type[%s]\n", - pbm->name, - (((error_bits & SABRE_PIOAFSR_PMA) ? - "Master Abort" : - ((error_bits & SABRE_PIOAFSR_PTA) ? - "Target Abort" : - ((error_bits & SABRE_PIOAFSR_PRTRY) ? - "Excessive Retries" : - ((error_bits & SABRE_PIOAFSR_PPERR) ? - "Parity Error" : "???")))))); - printk("%s: bytemask[%04lx] was_block(%d)\n", - pbm->name, - (afsr & SABRE_PIOAFSR_BMSK) >> 32UL, - (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0); - printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); - printk("%s: PCI Secondary errors [", pbm->name); - reported = 0; - if (afsr & SABRE_PIOAFSR_SMA) { - reported++; - printk("(Master Abort)"); - } - if (afsr & SABRE_PIOAFSR_STA) { - reported++; - printk("(Target Abort)"); - } - if (afsr & SABRE_PIOAFSR_SRTRY) { - reported++; - printk("(Excessive Retries)"); - } - if (afsr & SABRE_PIOAFSR_SPERR) { - reported++; - printk("(Parity Error)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* For the error types shown, scan both PCI buses for devices - * which have logged that error type. - */ - - /* If we see a Target Abort, this could be the result of an - * IOMMU translation error of some sort. It is extremely - * useful to log this information as usually it indicates - * a bug in the IOMMU support code or a PCI device driver. - */ - if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { - sabre_check_iommu_error(pbm, afsr, afar); - pci_scan_for_target_abort(pbm, pbm->pci_bus); - } - if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) - pci_scan_for_master_abort(pbm, pbm->pci_bus); - - /* For excessive retries, SABRE/PBM will abort the device - * and there is no way to specifically check for excessive - * retries in the config space status registers. So what - * we hope is that we'll catch it via the master/target - * abort events. - */ - - if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) - pci_scan_for_parity_error(pbm, pbm->pci_bus); - - return IRQ_HANDLED; -} - static void sabre_register_error_handlers(struct pci_pbm_info *pbm) { struct device_node *dp = pbm->op->node; @@ -588,7 +372,7 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) if (err) printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", pbm->name, err); - err = request_irq(op->irqs[0], sabre_pcierr_intr, 0, + err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, "SABRE_PCIERR", pbm); if (err) printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", @@ -679,6 +463,9 @@ static void __init sabre_pbm_init(struct pci_pbm_info *pbm, struct of_device *op) { psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); + pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; + pbm->pci_afar = pbm->controller_regs + SABRE_PIOAFAR; + pbm->pci_csr = pbm->controller_regs + SABRE_PCICTRL; sabre_scan_bus(pbm, &op->dev); } diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c index 1b4d462513d..6b188dfeeb9 100644 --- a/arch/sparc64/kernel/psycho_common.c +++ b/arch/sparc64/kernel/psycho_common.c @@ -3,15 +3,368 @@ * Copyright (C) 2008 David S. Miller */ #include +#include #include #include "pci_impl.h" +#include "iommu_common.h" #include "psycho_common.h" +#define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002UL +#define PSYCHO_STCERR_WRITE 0x0000000000000002UL +#define PSYCHO_STCERR_READ 0x0000000000000001UL +#define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL +#define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL +#define PSYCHO_STCTAG_VALID 0x0000000000000002UL +#define PSYCHO_STCTAG_WRITE 0x0000000000000001UL +#define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL +#define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL +#define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL +#define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL +#define PSYCHO_STCLINE_VALID 0x0000000000000002UL +#define PSYCHO_STCLINE_FOFN 0x0000000000000001UL + +static DEFINE_SPINLOCK(stc_buf_lock); +static unsigned long stc_error_buf[128]; +static unsigned long stc_tag_buf[16]; +static unsigned long stc_line_buf[16]; + +static void psycho_check_stc_error(struct pci_pbm_info *pbm) +{ + unsigned long err_base, tag_base, line_base; + struct strbuf *strbuf = &pbm->stc; + u64 control; + int i; + + if (!strbuf->strbuf_control) + return; + + err_base = strbuf->strbuf_err_stat; + tag_base = strbuf->strbuf_tag_diag; + line_base = strbuf->strbuf_line_diag; + + spin_lock(&stc_buf_lock); + + /* This is __REALLY__ dangerous. When we put the streaming + * buffer into diagnostic mode to probe it's tags and error + * status, we _must_ clear all of the line tag valid bits + * before re-enabling the streaming buffer. If any dirty data + * lives in the STC when we do this, we will end up + * invalidating it before it has a chance to reach main + * memory. + */ + control = upa_readq(strbuf->strbuf_control); + upa_writeq(control | PSYCHO_STRBUF_CTRL_DENAB, strbuf->strbuf_control); + for (i = 0; i < 128; i++) { + u64 val; + + val = upa_readq(err_base + (i * 8UL)); + upa_writeq(0UL, err_base + (i * 8UL)); + stc_error_buf[i] = val; + } + for (i = 0; i < 16; i++) { + stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); + stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); + upa_writeq(0UL, tag_base + (i * 8UL)); + upa_writeq(0UL, line_base + (i * 8UL)); + } + + /* OK, state is logged, exit diagnostic mode. */ + upa_writeq(control, strbuf->strbuf_control); + + for (i = 0; i < 16; i++) { + int j, saw_error, first, last; + + saw_error = 0; + first = i * 8; + last = first + 8; + for (j = first; j < last; j++) { + u64 errval = stc_error_buf[j]; + if (errval != 0) { + saw_error++; + printk(KERN_ERR "%s: STC_ERR(%d)[wr(%d)" + "rd(%d)]\n", + pbm->name, + j, + (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, + (errval & PSYCHO_STCERR_READ) ? 1 : 0); + } + } + if (saw_error != 0) { + u64 tagval = stc_tag_buf[i]; + u64 lineval = stc_line_buf[i]; + printk(KERN_ERR "%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)" + "V(%d)W(%d)]\n", + pbm->name, + i, + ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), + (tagval & PSYCHO_STCTAG_VPN), + ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), + ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); + printk(KERN_ERR "%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)" + "LADDR(%lx)EP(%lx)V(%d)FOFN(%d)]\n", + pbm->name, + i, + ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), + ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), + ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), + ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), + ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), + ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); + } + } + + spin_unlock(&stc_buf_lock); +} + #define PSYCHO_IOMMU_TAG 0xa580UL #define PSYCHO_IOMMU_DATA 0xa600UL +static void psycho_record_iommu_tags_and_data(struct pci_pbm_info *pbm, + u64 *tag, u64 *data) +{ + int i; + + for (i = 0; i < 16; i++) { + unsigned long base = pbm->controller_regs; + unsigned long off = i * 8UL; + + tag[i] = upa_readq(base + PSYCHO_IOMMU_TAG+off); + data[i] = upa_readq(base + PSYCHO_IOMMU_DATA+off); + + /* Now clear out the entry. */ + upa_writeq(0, base + PSYCHO_IOMMU_TAG + off); + upa_writeq(0, base + PSYCHO_IOMMU_DATA + off); + } +} + +#define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) +#define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) +#define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) +#define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) +#define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) +#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL +#define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) +#define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) +#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL + +static void psycho_dump_iommu_tags_and_data(struct pci_pbm_info *pbm, + u64 *tag, u64 *data) +{ + int i; + + for (i = 0; i < 16; i++) { + u64 tag_val, data_val; + const char *type_str; + tag_val = tag[i]; + if (!(tag_val & PSYCHO_IOMMU_TAG_ERR)) + continue; + + data_val = data[i]; + switch((tag_val & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { + case 0: + type_str = "Protection Error"; + break; + case 1: + type_str = "Invalid Error"; + break; + case 2: + type_str = "TimeOut Error"; + break; + case 3: + default: + type_str = "ECC Error"; + break; + } + + printk(KERN_ERR "%s: IOMMU TAG(%d)[error(%s) wr(%d) " + "str(%d) sz(%dK) vpg(%08lx)]\n", + pbm->name, i, type_str, + ((tag_val & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), + ((tag_val & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), + ((tag_val & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), + (tag_val & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); + printk(KERN_ERR "%s: IOMMU DATA(%d)[valid(%d) cache(%d) " + "ppg(%016lx)]\n", + pbm->name, i, + ((data_val & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), + ((data_val & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), + (data_val & PSYCHO_IOMMU_DATA_PPAGE)<iommu; + unsigned long flags; + + spin_lock_irqsave(&iommu->lock, flags); + control = upa_readq(iommu->iommu_control); + if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { + const char *type_str; + + control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; + upa_writeq(control, iommu->iommu_control); + + switch ((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { + case 0: + type_str = "Protection Error"; + break; + case 1: + type_str = "Invalid Error"; + break; + case 2: + type_str = "TimeOut Error"; + break; + case 3: + default: + type_str = "ECC Error"; + break; + }; + printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", + pbm->name, type_str); + + /* It is very possible for another DVMA to occur while + * we do this probe, and corrupt the system further. + * But we are so screwed at this point that we are + * likely to crash hard anyways, so get as much + * diagnostic information to the console as we can. + */ + psycho_record_iommu_tags_and_data(pbm, iommu_tag, iommu_data); + psycho_dump_iommu_tags_and_data(pbm, iommu_tag, iommu_data); + } + psycho_check_stc_error(pbm); + spin_unlock_irqrestore(&iommu->lock, flags); +} + +#define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000UL +#define PSYCHO_PCICTRL_SERR 0x0000000400000000UL + +static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) +{ + irqreturn_t ret = IRQ_NONE; + u64 csr, csr_error_bits; + u16 stat; + + csr = upa_readq(pbm->pci_csr); + csr_error_bits = csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); + if (csr_error_bits) { + /* Clear the errors. */ + upa_writeq(csr, pbm->pci_csr); + + /* Log 'em. */ + if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) + printk(KERN_ERR "%s: PCI streaming byte hole " + "error asserted.\n", pbm->name); + if (csr_error_bits & PSYCHO_PCICTRL_SERR) + printk(KERN_ERR "%s: PCI SERR signal asserted.\n", + pbm->name); + ret = IRQ_HANDLED; + } + pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); + if (stat & (PCI_STATUS_PARITY | + PCI_STATUS_SIG_TARGET_ABORT | + PCI_STATUS_REC_TARGET_ABORT | + PCI_STATUS_REC_MASTER_ABORT | + PCI_STATUS_SIG_SYSTEM_ERROR)) { + printk(KERN_ERR "%s: PCI bus error, PCI_STATUS[%04x]\n", + pbm->name, stat); + pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); + ret = IRQ_HANDLED; + } + return ret; +} + +#define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL +#define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL +#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL +#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL +#define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL +#define PSYCHO_PCIAFSR_STA 0x0400000000000000UL +#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL +#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL +#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL +#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL +#define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL +#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL +#define PSYCHO_PCIAFSR_MID 0x000000003e000000UL +#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL + +irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) +{ + struct pci_pbm_info *pbm = dev_id; + u64 afsr, afar, error_bits; + int reported; + + afsr = upa_readq(pbm->pci_afsr); + afar = upa_readq(pbm->pci_afar); + error_bits = afsr & + (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | + PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | + PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | + PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); + if (!error_bits) + return psycho_pcierr_intr_other(pbm); + upa_writeq(error_bits, pbm->pci_afsr); + printk(KERN_ERR "%s: PCI Error, primary error type[%s]\n", + pbm->name, + (((error_bits & PSYCHO_PCIAFSR_PMA) ? + "Master Abort" : + ((error_bits & PSYCHO_PCIAFSR_PTA) ? + "Target Abort" : + ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? + "Excessive Retries" : + ((error_bits & PSYCHO_PCIAFSR_PPERR) ? + "Parity Error" : "???")))))); + printk(KERN_ERR "%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", + pbm->name, + (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, + (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, + (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); + printk(KERN_ERR "%s: PCI AFAR [%016lx]\n", pbm->name, afar); + printk(KERN_ERR "%s: PCI Secondary errors [", pbm->name); + reported = 0; + if (afsr & PSYCHO_PCIAFSR_SMA) { + reported++; + printk("(Master Abort)"); + } + if (afsr & PSYCHO_PCIAFSR_STA) { + reported++; + printk("(Target Abort)"); + } + if (afsr & PSYCHO_PCIAFSR_SRTRY) { + reported++; + printk("(Excessive Retries)"); + } + if (afsr & PSYCHO_PCIAFSR_SPERR) { + reported++; + printk("(Parity Error)"); + } + if (!reported) + printk("(none)"); + printk("]\n"); + + if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { + psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); + pci_scan_for_target_abort(pbm, pbm->pci_bus); + } + if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) + pci_scan_for_master_abort(pbm, pbm->pci_bus); + + if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) + pci_scan_for_parity_error(pbm, pbm->pci_bus); + + return IRQ_HANDLED; +} + static void psycho_iommu_flush(struct pci_pbm_info *pbm) { int i; diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h index adfbadb6986..b53aa8dcad2 100644 --- a/arch/sparc64/kernel/psycho_common.h +++ b/arch/sparc64/kernel/psycho_common.h @@ -1,6 +1,17 @@ #ifndef _PSYCHO_COMMON_H #define _PSYCHO_COMMON_H +enum psycho_error_type { + UE_ERR, CE_ERR, PCI_ERR +}; + +extern void psycho_check_iommu_error(struct pci_pbm_info *pbm, + unsigned long afsr, + unsigned long afar, + enum psycho_error_type type); + +extern irqreturn_t psycho_pcierr_intr(int irq, void *dev_id); + extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, u32 dvma_offset, u32 dma_mask, unsigned long write_complete_offset); -- cgit v1.2.3 From 87395fc6781ff269bad7f972b8abf2312a8ccdf6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 04:13:10 -0700 Subject: sparc64: Kill hand-crafted I/O accessors in PCI controller drivers. Use existing upa_{read,write}q() interfaces instead. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_fire.c | 136 +++++++++++++------------------ arch/sparc64/kernel/pci_psycho.c | 69 ++++++---------- arch/sparc64/kernel/pci_sabre.c | 61 ++++++-------- arch/sparc64/kernel/pci_schizo.c | 167 +++++++++++++++++---------------------- 4 files changed, 177 insertions(+), 256 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 7e1a9b6717b..9462b68f489 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -12,27 +12,13 @@ #include #include +#include #include "pci_impl.h" #define DRIVER_NAME "fire" #define PFX DRIVER_NAME ": " -#define fire_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define fire_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - #define FIRE_IOMMU_CONTROL 0x40000UL #define FIRE_IOMMU_TSBBASE 0x40008UL #define FIRE_IOMMU_FLUSH 0x40100UL @@ -65,21 +51,21 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) /* * Invalidate TLB Entries. */ - fire_write(iommu->iommu_flushinv, ~(u64)0); + upa_writeq(~(u64)0, iommu->iommu_flushinv); err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, pbm->numa_node); if (err) return err; - fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL); + upa_writeq(__pa(iommu->page_table) | 0x7UL, iommu->iommu_tsbbase); - control = fire_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); control |= (0x00000400 /* TSB cache snoop enable */ | 0x00000300 /* Cache mode */ | 0x00000002 /* Bypass enable */ | 0x00000001 /* Translation enable */); - fire_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); return 0; } @@ -161,7 +147,7 @@ struct pci_msiq_entry { static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, unsigned long *head) { - *head = fire_read(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); + *head = upa_readq(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); return 0; } @@ -187,8 +173,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> MSIQ_WORD0_DATA0_SHIFT); - fire_write(pbm->pbm_regs + MSI_CLEAR(msi_num), - MSI_CLEAR_EQWR_N); + upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi_num)); /* Clear the entry. */ ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; @@ -204,7 +189,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, unsigned long head) { - fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid), head); + upa_writeq(head, pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); return 0; } @@ -213,17 +198,16 @@ static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, { u64 val; - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); + val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); val &= ~(MSI_MAP_EQNUM); val |= msiqid; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); + upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); - fire_write(pbm->pbm_regs + MSI_CLEAR(msi), - MSI_CLEAR_EQWR_N); + upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi)); - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); + val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); val |= MSI_MAP_VALID; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); + upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); return 0; } @@ -233,12 +217,12 @@ static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) unsigned long msiqid; u64 val; - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); + val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); msiqid = (val & MSI_MAP_EQNUM); val &= ~MSI_MAP_VALID; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); + upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); return 0; } @@ -257,22 +241,19 @@ static int pci_fire_msiq_alloc(struct pci_pbm_info *pbm) memset((char *)pages, 0, PAGE_SIZE << order); pbm->msi_queues = (void *) pages; - fire_write(pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG, - (EVENT_QUEUE_BASE_ADDR_ALL_ONES | - __pa(pbm->msi_queues))); + upa_writeq((EVENT_QUEUE_BASE_ADDR_ALL_ONES | + __pa(pbm->msi_queues)), + pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG); - fire_write(pbm->pbm_regs + IMONDO_DATA0, - pbm->portid << 6); - fire_write(pbm->pbm_regs + IMONDO_DATA1, 0); + upa_writeq(pbm->portid << 6, pbm->pbm_regs + IMONDO_DATA0); + upa_writeq(0, pbm->pbm_regs + IMONDO_DATA1); - fire_write(pbm->pbm_regs + MSI_32BIT_ADDR, - pbm->msi32_start); - fire_write(pbm->pbm_regs + MSI_64BIT_ADDR, - pbm->msi64_start); + upa_writeq(pbm->msi32_start, pbm->pbm_regs + MSI_32BIT_ADDR); + upa_writeq(pbm->msi64_start, pbm->pbm_regs + MSI_64BIT_ADDR); for (i = 0; i < pbm->msiq_num; i++) { - fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(i), 0); - fire_write(pbm->pbm_regs + EVENT_QUEUE_TAIL(i), 0); + upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_HEAD(i)); + upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_TAIL(i)); } return 0; @@ -306,9 +287,9 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, /* XXX iterate amongst the 4 IRQ controllers XXX */ int_ctrlr = (1UL << 6); - val = fire_read(imap_reg); + val = upa_readq(imap_reg); val |= (1UL << 63) | int_ctrlr; - fire_write(imap_reg, val); + upa_writeq(val, imap_reg); fixup = ((pbm->portid << 6) | devino) - int_ctrlr; @@ -316,9 +297,8 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, if (!virt_irq) return -ENOMEM; - fire_write(pbm->pbm_regs + - EVENT_QUEUE_CONTROL_SET(msiqid), - EVENT_QUEUE_CONTROL_SET_EN); + upa_writeq(EVENT_QUEUE_CONTROL_SET_EN, + pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid)); return virt_irq; } @@ -386,49 +366,47 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) { u64 val; - fire_write(pbm->controller_regs + FIRE_PARITY_CONTROL, - FIRE_PARITY_ENAB); + upa_writeq(FIRE_PARITY_ENAB, + pbm->controller_regs + FIRE_PARITY_CONTROL); - fire_write(pbm->controller_regs + FIRE_FATAL_RESET_CTL, - (FIRE_FATAL_RESET_SPARE | + upa_writeq((FIRE_FATAL_RESET_SPARE | FIRE_FATAL_RESET_MB | FIRE_FATAL_RESET_CPE | FIRE_FATAL_RESET_APE | FIRE_FATAL_RESET_PIO | FIRE_FATAL_RESET_JW | FIRE_FATAL_RESET_JI | - FIRE_FATAL_RESET_JR)); + FIRE_FATAL_RESET_JR), + pbm->controller_regs + FIRE_FATAL_RESET_CTL); - fire_write(pbm->controller_regs + FIRE_CORE_INTR_ENABLE, ~(u64)0); + upa_writeq(~(u64)0, pbm->controller_regs + FIRE_CORE_INTR_ENABLE); - val = fire_read(pbm->pbm_regs + FIRE_TLU_CTRL); + val = upa_readq(pbm->pbm_regs + FIRE_TLU_CTRL); val |= (FIRE_TLU_CTRL_TIM | FIRE_TLU_CTRL_QDET | FIRE_TLU_CTRL_CFG); - fire_write(pbm->pbm_regs + FIRE_TLU_CTRL, val); - fire_write(pbm->pbm_regs + FIRE_TLU_DEV_CTRL, 0); - fire_write(pbm->pbm_regs + FIRE_TLU_LINK_CTRL, - FIRE_TLU_LINK_CTRL_CLK); - - fire_write(pbm->pbm_regs + FIRE_LPU_RESET, 0); - fire_write(pbm->pbm_regs + FIRE_LPU_LLCFG, - FIRE_LPU_LLCFG_VC0); - fire_write(pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL, - (FIRE_LPU_FCTRL_UCTRL_N | - FIRE_LPU_FCTRL_UCTRL_P)); - fire_write(pbm->pbm_regs + FIRE_LPU_TXL_FIFOP, - ((0xffff << 16) | (0x0000 << 0))); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2, 3000000); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3, 500000); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4, - (2 << 16) | (140 << 8)); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5, 0); - - fire_write(pbm->pbm_regs + FIRE_DMC_IENAB, ~(u64)0); - fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_A, 0); - fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_B, 0); - - fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); + upa_writeq(val, pbm->pbm_regs + FIRE_TLU_CTRL); + upa_writeq(0, pbm->pbm_regs + FIRE_TLU_DEV_CTRL); + upa_writeq(FIRE_TLU_LINK_CTRL_CLK, + pbm->pbm_regs + FIRE_TLU_LINK_CTRL); + + upa_writeq(0, pbm->pbm_regs + FIRE_LPU_RESET); + upa_writeq(FIRE_LPU_LLCFG_VC0, pbm->pbm_regs + FIRE_LPU_LLCFG); + upa_writeq((FIRE_LPU_FCTRL_UCTRL_N | FIRE_LPU_FCTRL_UCTRL_P), + pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL); + upa_writeq(((0xffff << 16) | (0x0000 << 0)), + pbm->pbm_regs + FIRE_LPU_TXL_FIFOP); + upa_writeq(3000000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2); + upa_writeq(500000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3); + upa_writeq((2 << 16) | (140 << 8), + pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4); + upa_writeq(0, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5); + + upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_DMC_IENAB); + upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_A); + upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_B); + + upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_PEC_IENAB); } static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index bac9c1ba40e..89733468065 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -25,25 +26,6 @@ #define DRIVER_NAME "psycho" #define PFX DRIVER_NAME ": " -/* All PSYCHO registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define psycho_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define psycho_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - /* Misc. PSYCHO PCI controller register offsets and definitions. */ #define PSYCHO_CONTROL 0x0010UL #define PSYCHO_CONTROL_IMPL 0xf000000000000000UL /* Implementation of this PSYCHO*/ @@ -182,8 +164,8 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) int reported; /* Latch uncorrectable error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear the primary/secondary error status bits. */ error_bits = afsr & @@ -191,7 +173,7 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR); if (!error_bits) return IRQ_NONE; - psycho_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Uncorrectable Error, primary error type[%s]\n", @@ -261,8 +243,8 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) int reported; /* Latch error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear primary/secondary error status bits. */ error_bits = afsr & @@ -270,7 +252,7 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR); if (!error_bits) return IRQ_NONE; - psycho_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Correctable Error, primary error type[%s]\n", @@ -373,27 +355,26 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) "err=%d\n", pbm->name, err); /* Enable UE and CE interrupts for controller. */ - psycho_write(base + PSYCHO_ECC_CTRL, - (PSYCHO_ECCCTRL_EE | - PSYCHO_ECCCTRL_UE | - PSYCHO_ECCCTRL_CE)); + upa_writeq((PSYCHO_ECCCTRL_EE | + PSYCHO_ECCCTRL_UE | + PSYCHO_ECCCTRL_CE), base + PSYCHO_ECC_CTRL); /* Enable PCI Error interrupts and clear error * bits for each PBM. */ - tmp = psycho_read(base + PSYCHO_PCIA_CTRL); + tmp = upa_readq(base + PSYCHO_PCIA_CTRL); tmp |= (PSYCHO_PCICTRL_SERR | PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_EEN); tmp &= ~(PSYCHO_PCICTRL_SBH_INT); - psycho_write(base + PSYCHO_PCIA_CTRL, tmp); + upa_writeq(tmp, base + PSYCHO_PCIA_CTRL); - tmp = psycho_read(base + PSYCHO_PCIB_CTRL); + tmp = upa_readq(base + PSYCHO_PCIB_CTRL); tmp |= (PSYCHO_PCICTRL_SERR | PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_EEN); tmp &= ~(PSYCHO_PCICTRL_SBH_INT); - psycho_write(base + PSYCHO_PCIB_CTRL, tmp); + upa_writeq(tmp, base + PSYCHO_PCIB_CTRL); } /* PSYCHO boot time probing and initialization. */ @@ -443,28 +424,28 @@ static void psycho_controller_hwinit(struct pci_pbm_info *pbm) { u64 tmp; - psycho_write(pbm->controller_regs + PSYCHO_IRQ_RETRY, 5); + upa_writeq(5, pbm->controller_regs + PSYCHO_IRQ_RETRY); /* Enable arbiter for all PCI slots. */ - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_CTRL); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(pbm->controller_regs + PSYCHO_PCIA_CTRL, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_CTRL); - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_CTRL); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(pbm->controller_regs + PSYCHO_PCIB_CTRL, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_CTRL); /* Disable DMA write / PIO read synchronization on * both PCI bus segments. * [ U2P Erratum 1243770, STP2223BGA data sheet ] */ - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_DIAG); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(pbm->controller_regs + PSYCHO_PCIA_DIAG, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_DIAG); - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_DIAG); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(pbm->controller_regs + PSYCHO_PCIB_DIAG, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_DIAG); } static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, @@ -509,7 +490,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, */ #undef PSYCHO_STRBUF_RERUN_ENABLE #undef PSYCHO_STRBUF_RERUN_DISABLE - control = psycho_read(pbm->stc.strbuf_control); + control = upa_readq(pbm->stc.strbuf_control); control |= PSYCHO_STRBUF_CTRL_ENAB; control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); #ifdef PSYCHO_STRBUF_RERUN_ENABLE @@ -519,7 +500,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, control |= PSYCHO_STRBUF_CTRL_RRDIS; #endif #endif - psycho_write(pbm->stc.strbuf_control, control); + upa_writeq(control, pbm->stc.strbuf_control); pbm->stc.strbuf_enabled = 1; } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index f8089aa84f6..713257b6963 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -25,25 +26,6 @@ #define DRIVER_NAME "sabre" #define PFX DRIVER_NAME ": " -/* All SABRE registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define sabre_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define sabre_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - /* SABRE PCI controller register offsets and definitions. */ #define SABRE_UE_AFSR 0x0030UL #define SABRE_UEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */ @@ -219,8 +201,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) int reported; /* Latch uncorrectable error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear the primary/secondary error status bits. */ error_bits = afsr & @@ -229,7 +211,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); if (!error_bits) return IRQ_NONE; - sabre_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Uncorrectable Error, primary error type[%s%s]\n", @@ -279,8 +261,8 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) int reported; /* Latch error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear primary/secondary error status bits. */ error_bits = afsr & @@ -288,7 +270,7 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); if (!error_bits) return IRQ_NONE; - sabre_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Correctable Error, primary error type[%s]\n", @@ -354,19 +336,20 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) * registering the handler so that we don't get spurious * interrupts. */ - sabre_write(base + SABRE_UE_AFSR, - (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | - SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | - SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); + upa_writeq((SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | + SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | + SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE), + base + SABRE_UE_AFSR); err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); if (err) printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", pbm->name, err); - sabre_write(base + SABRE_CE_AFSR, - (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | - SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); + upa_writeq((SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | + SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR), + base + SABRE_CE_AFSR); + err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); if (err) @@ -378,9 +361,9 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", pbm->name, err); - tmp = sabre_read(base + SABRE_PCICTRL); + tmp = upa_readq(base + SABRE_PCICTRL); tmp |= SABRE_PCICTRL_ERREN; - sabre_write(base + SABRE_PCICTRL, tmp); + upa_writeq(tmp, base + SABRE_PCICTRL); } static void apb_init(struct pci_bus *sabre_bus) @@ -533,16 +516,16 @@ static int __devinit sabre_probe(struct of_device *op, /* PCI first */ for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) - sabre_write(pbm->controller_regs + clear_irq, 0x0UL); + upa_writeq(0x0UL, pbm->controller_regs + clear_irq); /* Then OBIO */ for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) - sabre_write(pbm->controller_regs + clear_irq, 0x0UL); + upa_writeq(0x0UL, pbm->controller_regs + clear_irq); /* Error interrupts are enabled later after the bus scan. */ - sabre_write(pbm->controller_regs + SABRE_PCICTRL, - (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | - SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); + upa_writeq((SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | + SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN), + pbm->controller_regs + SABRE_PCICTRL); /* Now map in PCI config space for entire SABRE. */ pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index c30856541bb..45d9dba1ba1 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -22,25 +23,6 @@ #define DRIVER_NAME "schizo" #define PFX DRIVER_NAME ": " -/* All SCHIZO registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define schizo_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define schizo_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - /* This is a convention that at least Excalibur and Merlin * follow. I suppose the SCHIZO used in Starcat and friends * will do similar. @@ -164,25 +146,25 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, * invalidating it before it has a chance to reach * main memory. */ - control = schizo_read(strbuf->strbuf_control); - schizo_write(strbuf->strbuf_control, - (control | SCHIZO_STRBUF_CTRL_DENAB)); + control = upa_readq(strbuf->strbuf_control); + upa_writeq((control | SCHIZO_STRBUF_CTRL_DENAB), + strbuf->strbuf_control); for (i = 0; i < 128; i++) { unsigned long val; - val = schizo_read(err_base + (i * 8UL)); - schizo_write(err_base + (i * 8UL), 0UL); + val = upa_readq(err_base + (i * 8UL)); + upa_writeq(0UL, err_base + (i * 8UL)); stc_error_buf[i] = val; } for (i = 0; i < 16; i++) { - stc_tag_buf[i] = schizo_read(tag_base + (i * 8UL)); - stc_line_buf[i] = schizo_read(line_base + (i * 8UL)); - schizo_write(tag_base + (i * 8UL), 0UL); - schizo_write(line_base + (i * 8UL), 0UL); + stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); + stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); + upa_writeq(0UL, tag_base + (i * 8UL)); + upa_writeq(0UL, line_base + (i * 8UL)); } /* OK, state is logged, exit diagnostic mode. */ - schizo_write(strbuf->strbuf_control, control); + upa_writeq(control, strbuf->strbuf_control); for (i = 0; i < 16; i++) { int j, saw_error, first, last; @@ -259,14 +241,14 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, int i; spin_lock_irqsave(&iommu->lock, flags); - control = schizo_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); if (control & SCHIZO_IOMMU_CTRL_XLTEERR) { unsigned long base; char *type_string; /* Clear the error encountered bit. */ control &= ~SCHIZO_IOMMU_CTRL_XLTEERR; - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) { case 0: @@ -296,24 +278,24 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, * get as much diagnostic information to the * console as we can. */ - schizo_write(iommu->iommu_control, - control | SCHIZO_IOMMU_CTRL_DENAB); + upa_writeq(control | SCHIZO_IOMMU_CTRL_DENAB, + iommu->iommu_control); base = pbm->pbm_regs; for (i = 0; i < 16; i++) { iommu_tag[i] = - schizo_read(base + SCHIZO_IOMMU_TAG + (i * 8UL)); + upa_readq(base + SCHIZO_IOMMU_TAG + (i * 8UL)); iommu_data[i] = - schizo_read(base + SCHIZO_IOMMU_DATA + (i * 8UL)); + upa_readq(base + SCHIZO_IOMMU_DATA + (i * 8UL)); /* Now clear out the entry. */ - schizo_write(base + SCHIZO_IOMMU_TAG + (i * 8UL), 0); - schizo_write(base + SCHIZO_IOMMU_DATA + (i * 8UL), 0); + upa_writeq(0, base + SCHIZO_IOMMU_TAG + (i * 8UL)); + upa_writeq(0, base + SCHIZO_IOMMU_DATA + (i * 8UL)); } /* Leave diagnostic mode. */ - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); for (i = 0; i < 16; i++) { unsigned long tag, data; @@ -394,7 +376,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) int reported, limit; /* Latch uncorrectable error status. */ - afar = schizo_read(afar_reg); + afar = upa_readq(afar_reg); /* If either of the error pending bits are set in the * AFSR, the error status is being actively updated by @@ -402,7 +384,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) */ limit = 1000; do { - afsr = schizo_read(afsr_reg); + afsr = upa_readq(afsr_reg); } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); /* Clear the primary/secondary error status bits. */ @@ -411,7 +393,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA); if (!error_bits) return IRQ_NONE; - schizo_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Uncorrectable Error, primary error type[%s]\n", @@ -482,7 +464,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) int reported, limit; /* Latch error status. */ - afar = schizo_read(afar_reg); + afar = upa_readq(afar_reg); /* If either of the error pending bits are set in the * AFSR, the error status is being actively updated by @@ -490,7 +472,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) */ limit = 1000; do { - afsr = schizo_read(afsr_reg); + afsr = upa_readq(afsr_reg); } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); /* Clear primary/secondary error status bits. */ @@ -499,7 +481,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); if (!error_bits) return IRQ_NONE; - schizo_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Correctable Error, primary error type[%s]\n", @@ -601,7 +583,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) u16 stat; csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; - csr = schizo_read(csr_reg); + csr = upa_readq(csr_reg); csr_error_bits = csr & (SCHIZO_PCICTRL_BUS_UNUS | SCHIZO_PCICTRL_TTO_ERR | @@ -611,7 +593,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) SCHIZO_PCICTRL_SERR); if (csr_error_bits) { /* Clear the errors. */ - schizo_write(csr_reg, csr); + upa_writeq(csr, csr_reg); /* Log 'em. */ if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) @@ -661,8 +643,8 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) afar_reg = base + SCHIZO_PCI_AFAR; /* Latch error status. */ - afar = schizo_read(afar_reg); - afsr = schizo_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear primary/secondary error status bits. */ error_bits = afsr & @@ -674,7 +656,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); if (!error_bits) return schizo_pcierr_intr_other(pbm); - schizo_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: PCI Error, primary error type[%s]\n", @@ -807,9 +789,9 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) struct pci_pbm_info *pbm = dev_id; u64 errlog; - errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG, - errlog & ~(SAFARI_ERRLOG_ERROUT)); + errlog = upa_readq(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); + upa_writeq(errlog & ~(SAFARI_ERRLOG_ERROUT), + pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); if (!(errlog & BUS_ERROR_UNMAP)) { printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", @@ -909,10 +891,9 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) } /* Enable UE and CE interrupts for controller. */ - schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); + upa_writeq((SCHIZO_ECCCTRL_EE | + SCHIZO_ECCCTRL_UE | + SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); /* Enable PCI Error interrupts and clear error * bits. @@ -925,10 +906,10 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) err_no_mask = SCHIZO_PCICTRL_DTO_ERR; - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | @@ -937,7 +918,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | SCHIZO_PCIAFSR_STTO); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask); + upa_writeq(err_mask, pbm->pbm_regs + SCHIZO_PCI_AFSR); err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | @@ -949,11 +930,11 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) BUS_ERROR_APERR | BUS_ERROR_UNMAP | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); + upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), + pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL, - (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); + upa_writeq((SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)), + pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL); } static void schizo_register_error_handlers(struct pci_pbm_info *pbm) @@ -1005,10 +986,9 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) } /* Enable UE and CE interrupts for controller. */ - schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); + upa_writeq((SCHIZO_ECCCTRL_EE | + SCHIZO_ECCCTRL_UE | + SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); err_mask = (SCHIZO_PCICTRL_BUS_UNUS | SCHIZO_PCICTRL_ESLCK | @@ -1024,18 +1004,18 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) /* Enable PCI Error interrupts and clear error * bits for each PBM. */ - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, - (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | - SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | - SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | - SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | - SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | - SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); + upa_writeq((SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | + SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | + SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | + SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | + SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | + SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS), + pbm->pbm_regs + SCHIZO_PCI_AFSR); /* Make all Safari error conditions fatal except unmapped * errors which we make generate interrupts. @@ -1062,8 +1042,8 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); #endif - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); + upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), + pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); } static void pbm_config_busmastering(struct pci_pbm_info *pbm) @@ -1133,12 +1113,12 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) * streaming buffer and leave the rerun-disable * setting however OBP set it. */ - control = schizo_read(pbm->stc.strbuf_control); + control = upa_readq(pbm->stc.strbuf_control); control &= ~(SCHIZO_STRBUF_CTRL_LPTR | SCHIZO_STRBUF_CTRL_LENAB | SCHIZO_STRBUF_CTRL_DENAB); control |= SCHIZO_STRBUF_CTRL_ENAB; - schizo_write(pbm->stc.strbuf_control, control); + upa_writeq(control, pbm->stc.strbuf_control); pbm->stc.strbuf_enabled = 1; } @@ -1199,15 +1179,15 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) /* * Invalidate TLB Entries. */ - control = schizo_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); control |= SCHIZO_IOMMU_CTRL_DENAB; - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; for (i = 0; i < 16; i++) { - schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); - schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); + upa_writeq(0, pbm->pbm_regs + tagbase + (i * 8UL)); + upa_writeq(0, pbm->pbm_regs + database + (i * 8UL)); } /* Leave diag mode enabled for full-flushing done @@ -1220,9 +1200,9 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) return err; } - schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); + upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); - control = schizo_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); switch (tsbsize) { case 64: @@ -1234,7 +1214,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) } control |= SCHIZO_IOMMU_CTRL_ENAB; - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); return 0; } @@ -1277,9 +1257,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) { u64 tmp; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); + upa_writeq(5, pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY); - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); /* Enable arbiter for all PCI slots. */ tmp |= 0xff; @@ -1304,13 +1284,13 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) SCHIZO_PCICTRL_RDO_PREF | SCHIZO_PCICTRL_RDL_PREF); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_DIAG); tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | SCHIZO_PCIDIAG_D_RETRY | SCHIZO_PCIDIAG_D_INTSYNC); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_DIAG); if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { /* Clear prefetch lengths to workaround a bug in @@ -1322,8 +1302,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) TOMATILLO_IOC_RDONE_CPENAB | TOMATILLO_IOC_RDLINE_CPENAB); - schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR, - tmp); + upa_writeq(tmp, pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR); } } -- cgit v1.2.3 From 3fbe36d8da0081dbee23c5d477d8142fab98c42e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 23:40:32 -0700 Subject: sparc32: Call parse_early_param() in setup_arch(). Mirror sparc64. This will allow us to use early_param() on sparc32 too. Signed-off-by: David S. Miller --- arch/sparc/kernel/setup.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index f8391c0d7e9..24fe3078bd4 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -213,6 +213,7 @@ void __init setup_arch(char **cmdline_p) /* Initialize PROM console and command line. */ *cmdline_p = prom_getbootargs(); strcpy(boot_command_line, *cmdline_p); + parse_early_param(); /* Set sparc_cpu_model */ sparc_cpu_model = sun_unknown; -- cgit v1.2.3 From 4845afac95a653f8e64c45024cbb94264df54b8f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:14:52 -0700 Subject: sparc64: Add __arch64__ to CHECKFLAGS Otherwise sparse doesn't work. The 32 vs. 64 header ifdef used under arch/sparc/include/asm/ is: #if defined(__sparc__) && defined(__arch64__) And that doesn't work for sparse unless we give it __arch64__ Signed-off-by: David S. Miller --- arch/sparc64/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index b785a395b12..c7214abc0d8 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile @@ -7,7 +7,7 @@ # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) # -CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -m64 +CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64 # Undefine sparc when processing vmlinux.lds - it is used # And teach CPP we are doing 64 bit builds (for this case) -- cgit v1.2.3 From 8f20b20de73eeabe3d35e67e0ce993eceef07492 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:19:22 -0700 Subject: sparc64: Fix sparse warnings in global reg snapshotting. Lots of shadowed local variables and global_reg_snapshot[] needs an extern declaration in asm/ptrace_64.h. Signed-off-by: David S. Miller --- arch/sparc/include/asm/ptrace_64.h | 3 +++ arch/sparc64/kernel/process.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/ptrace_64.h b/arch/sparc/include/asm/ptrace_64.h index 06e4914c13f..3d3e9c161d8 100644 --- a/arch/sparc/include/asm/ptrace_64.h +++ b/arch/sparc/include/asm/ptrace_64.h @@ -113,6 +113,8 @@ struct sparc_trapf { #ifdef __KERNEL__ +#include + static inline int pt_regs_trap_type(struct pt_regs *regs) { return regs->magic & 0x1ff; @@ -138,6 +140,7 @@ struct global_reg_snapshot { struct thread_info *thread; unsigned long pad1; }; +extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; #define __ARCH_WANT_COMPAT_SYS_PTRACE diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 11bb6c4612d..d5e2acef987 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -215,7 +215,6 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; if (regs->tstate & TSTATE_PRIV) { - struct thread_info *tp = current_thread_info(); struct reg_window *rw; rw = (struct reg_window *) @@ -271,7 +270,6 @@ void __trigger_all_cpu_backtrace(void) for_each_online_cpu(cpu) { struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; - struct thread_info *tp; __global_reg_poll(gp); -- cgit v1.2.3 From 17f04fbb0f7153d95ec33da81189b113cc778157 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:33:53 -0700 Subject: sysctl: Use header file for sysctl knob declarations on sparc. This also takes care of a sparse warning as scons_pwroff's definition point. Signed-off-by: David S. Miller --- arch/sparc/include/asm/system_32.h | 1 + arch/sparc/include/asm/system_64.h | 1 + arch/sparc64/kernel/reboot.c | 1 + 3 files changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h index 4e18ef27233..8623fc48fe2 100644 --- a/arch/sparc/include/asm/system_32.h +++ b/arch/sparc/include/asm/system_32.h @@ -49,6 +49,7 @@ extern unsigned long empty_zero_page; extern void sun_do_break(void); extern int serial_console; extern int stop_a_enabled; +extern int scons_pwroff; static inline int con_is_present(void) { diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h index 98acb3b9d4a..8759f2a1b83 100644 --- a/arch/sparc/include/asm/system_64.h +++ b/arch/sparc/include/asm/system_64.h @@ -117,6 +117,7 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ extern void sun_do_break(void); extern int stop_a_enabled; +extern int scons_pwroff; extern void fault_in_user_windows(void); extern void synchronize_user_stack(void); diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c index 11f24966063..ef89d3d6974 100644 --- a/arch/sparc64/kernel/reboot.c +++ b/arch/sparc64/kernel/reboot.c @@ -7,6 +7,7 @@ #include #include +#include #include #include -- cgit v1.2.3 From b0f1e7962f93a78630161c7c9fc263de43c101ac Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:36:32 -0700 Subject: sparc64: Define WANT_PAGE_VIRTUAL As sparse warns, without this struct page pointer subtraction is extremely expensive, and this is a pretty common operation in fast paths. With this define struct page becomes 64 bytes which makes for a simple subtract and shift, instead of a costly divide or reciprocol multiply. Signed-off-by: David S. Miller --- arch/sparc/include/asm/page_64.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index b579b910ef5..4274ed13ddb 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h @@ -38,6 +38,8 @@ #ifndef __ASSEMBLY__ +#define WANT_PAGE_VIRTUAL + extern void _clear_page(void *page); #define clear_page(X) _clear_page((void *)(X)) struct page; -- cgit v1.2.3 From d8ada0a2cd11c991d8193a3f7d37f1806c93c4a0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:39:11 -0700 Subject: sparc64: Fix sparse warnings in kernel/time.c 1) Using "clock" as a local variable shadows a global variable of the same name declared in linux/clocksource.h 2) rtc_cmos_resource should be static Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 8d2ca04d309..80d71a5ce1e 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -409,7 +409,7 @@ int update_persistent_clock(struct timespec now) unsigned long cmos_regs; EXPORT_SYMBOL(cmos_regs); -struct resource rtc_cmos_resource; +static struct resource rtc_cmos_resource; static struct platform_device rtc_cmos_device = { .name = "rtc_cmos", @@ -621,7 +621,7 @@ fs_initcall(clock_init); static unsigned long sparc64_init_timers(void) { struct device_node *dp; - unsigned long clock; + unsigned long freq; dp = of_find_node_by_path("/"); if (tlb_type == spitfire) { @@ -634,17 +634,17 @@ static unsigned long sparc64_init_timers(void) if (manuf == 0x17 && impl == 0x13) { /* Hummingbird, aka Ultra-IIe */ tick_ops = &hbtick_operations; - clock = of_getintprop_default(dp, "stick-frequency", 0); + freq = of_getintprop_default(dp, "stick-frequency", 0); } else { tick_ops = &tick_operations; - clock = local_cpu_data().clock_tick; + freq = local_cpu_data().clock_tick; } } else { tick_ops = &stick_operations; - clock = of_getintprop_default(dp, "stick-frequency", 0); + freq = of_getintprop_default(dp, "stick-frequency", 0); } - return clock; + return freq; } struct freq_table { @@ -836,16 +836,16 @@ EXPORT_SYMBOL(udelay); void __init time_init(void) { - unsigned long clock = sparc64_init_timers(); + unsigned long freq = sparc64_init_timers(); - tb_ticks_per_usec = clock / USEC_PER_SEC; + tb_ticks_per_usec = freq / USEC_PER_SEC; timer_ticks_per_nsec_quotient = - clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT); + clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); clocksource_tick.name = tick_ops->name; clocksource_tick.mult = - clocksource_hz2mult(clock, + clocksource_hz2mult(freq, clocksource_tick.shift); clocksource_tick.read = tick_ops->get_tick; @@ -856,7 +856,7 @@ void __init time_init(void) sparc64_clockevent.name = tick_ops->name; - setup_clockevent_multiplier(clock); + setup_clockevent_multiplier(freq); sparc64_clockevent.max_delta_ns = clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); -- cgit v1.2.3 From 7e0b1e6186c755becf8b19c844c63db1a551898b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:46:40 -0700 Subject: sparc64: Fix sparse warnings in visemul.c 1) edge8 tables should be static 2) add vis_emul() extern decl. to asm/visasm.h Signed-off-by: David S. Miller --- arch/sparc/include/asm/visasm.h | 1 + arch/sparc64/kernel/traps.c | 1 - arch/sparc64/kernel/visemul.c | 12 ++++++------ 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/visasm.h b/arch/sparc/include/asm/visasm.h index de797b9bf55..39ca301920d 100644 --- a/arch/sparc/include/asm/visasm.h +++ b/arch/sparc/include/asm/visasm.h @@ -57,6 +57,7 @@ static inline void save_and_clear_fpu(void) { " " : : "i" (FPRS_FEF|FPRS_DU) : "o5", "g1", "g2", "g3", "g7", "cc"); } +extern int vis_emul(struct pt_regs *, unsigned int); #endif #endif /* _SPARC64_ASI_H */ diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 71644da6cad..9378896589f 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2270,7 +2270,6 @@ void die_if_kernel(char *str, struct pt_regs *regs) extern int handle_popc(u32 insn, struct pt_regs *regs); extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); -extern int vis_emul(struct pt_regs *, unsigned int); void do_illegal_instruction(struct pt_regs *regs) { diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc64/kernel/visemul.c index c3fd64706b5..9e05cb5cb85 100644 --- a/arch/sparc64/kernel/visemul.c +++ b/arch/sparc64/kernel/visemul.c @@ -243,7 +243,7 @@ static inline unsigned int *fps_regaddr(struct fpustate *f, struct edge_tab { u16 left, right; }; -struct edge_tab edge8_tab[8] = { +static struct edge_tab edge8_tab[8] = { { 0xff, 0x80 }, { 0x7f, 0xc0 }, { 0x3f, 0xe0 }, @@ -253,7 +253,7 @@ struct edge_tab edge8_tab[8] = { { 0x03, 0xfe }, { 0x01, 0xff }, }; -struct edge_tab edge8_tab_l[8] = { +static struct edge_tab edge8_tab_l[8] = { { 0xff, 0x01 }, { 0xfe, 0x03 }, { 0xfc, 0x07 }, @@ -263,23 +263,23 @@ struct edge_tab edge8_tab_l[8] = { { 0xc0, 0x7f }, { 0x80, 0xff }, }; -struct edge_tab edge16_tab[4] = { +static struct edge_tab edge16_tab[4] = { { 0xf, 0x8 }, { 0x7, 0xc }, { 0x3, 0xe }, { 0x1, 0xf }, }; -struct edge_tab edge16_tab_l[4] = { +static struct edge_tab edge16_tab_l[4] = { { 0xf, 0x1 }, { 0xe, 0x3 }, { 0xc, 0x7 }, { 0x8, 0xf }, }; -struct edge_tab edge32_tab[2] = { +static struct edge_tab edge32_tab[2] = { { 0x3, 0x2 }, { 0x1, 0x3 }, }; -struct edge_tab edge32_tab_l[2] = { +static struct edge_tab edge32_tab_l[2] = { { 0x3, 0x1 }, { 0x2, 0x3 }, }; -- cgit v1.2.3 From c91e2ecad0a392604ece6e53d38b484918060825 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:52:35 -0700 Subject: sparc64: Fix sparse warnings in prom.c 1) Testing null with '0' 2) returning void-valued expression Signed-off-by: David S. Miller --- arch/sparc64/kernel/prom.c | 85 ++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 922dd612612..5f50e2b17a8 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -38,7 +38,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) { struct device_node *np; - for (np = allnodes; np != 0; np = np->allnext) + for (np = allnodes; np; np = np->allnext) if (np->node == handle) break; @@ -1043,22 +1043,30 @@ static void __init irq_trans_init(struct device_node *dp) for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { struct irq_trans *t = &pci_irq_trans_table[i]; - if (!strcmp(model, t->name)) - return t->init(dp); + if (!strcmp(model, t->name)) { + t->init(dp); + return; + } } } #endif #ifdef CONFIG_SBUS if (!strcmp(dp->name, "sbus") || - !strcmp(dp->name, "sbi")) - return sbus_irq_trans_init(dp); + !strcmp(dp->name, "sbi")) { + sbus_irq_trans_init(dp); + return; + } #endif if (!strcmp(dp->name, "fhc") && - !strcmp(dp->parent->name, "central")) - return central_irq_trans_init(dp); + !strcmp(dp->parent->name, "central")) { + central_irq_trans_init(dp); + return; + } if (!strcmp(dp->name, "virtual-devices") || - !strcmp(dp->name, "niu")) - return sun4v_vdev_irq_trans_init(dp); + !strcmp(dp->name, "niu")) { + sun4v_vdev_irq_trans_init(dp); + return; + } } static int is_root_node(const struct device_node *dp) @@ -1329,32 +1337,49 @@ static void __init __build_path_component(struct device_node *dp, char *tmp_buf) if (parent != NULL) { if (!strcmp(parent->type, "pci") || - !strcmp(parent->type, "pciex")) - return pci_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "sbus")) - return sbus_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "upa")) - return upa_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "ebus")) - return ebus_path_component(dp, tmp_buf); + !strcmp(parent->type, "pciex")) { + pci_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "sbus")) { + sbus_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "upa")) { + upa_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "ebus")) { + ebus_path_component(dp, tmp_buf); + return; + } if (!strcmp(parent->name, "usb") || - !strcmp(parent->name, "hub")) - return usb_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "i2c")) - return i2c_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "firewire")) - return ieee1394_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "virtual-devices")) - return vdev_path_component(dp, tmp_buf); - + !strcmp(parent->name, "hub")) { + usb_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "i2c")) { + i2c_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "firewire")) { + ieee1394_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "virtual-devices")) { + vdev_path_component(dp, tmp_buf); + return; + } /* "isa" is handled with platform naming */ } /* Use platform naming convention. */ - if (tlb_type == hypervisor) - return sun4v_path_component(dp, tmp_buf); - else - return sun4u_path_component(dp, tmp_buf); + if (tlb_type == hypervisor) { + sun4v_path_component(dp, tmp_buf); + return; + } else { + sun4u_path_component(dp, tmp_buf); + } } static char * __init build_path_component(struct device_node *dp) -- cgit v1.2.3 From 21cd8833933ef20a0bbb368ea00876cbfc06141b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:53:41 -0700 Subject: sparc64: Fix sparse warnings in of_device.c Passing unsigned int pointer where plain int pointer is expected. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 5c4fbc23aee..ef05d14bd7f 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -401,8 +401,7 @@ static int __init build_one_resource(struct device_node *parent, int na, int ns, int pna) { const u32 *ranges; - unsigned int rlen; - int rone; + int rone, rlen; ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { -- cgit v1.2.3 From 77d10d0e63dcc4f961cb416447d64281300e5a01 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:57:40 -0700 Subject: sparc64: Fix sparse warnings in pci.c 1) Declare pci_poke_* in pci_impl.h 2) of_create_pci_dev() should be static 3) ->setup_msi_irq() wants an unsigned int pointer not a plain int one 4) void value expression return in arch_teardown_msi_irq() Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 14 ++++++-------- arch/sparc64/kernel/pci_impl.h | 4 ++++ arch/sparc64/kernel/traps.c | 5 +---- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c6e81dea2cf..e12a0586b43 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -242,9 +242,9 @@ static void pci_parse_of_addrs(struct of_device *op, } } -struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, - struct device_node *node, - struct pci_bus *bus, int devfn) +static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus, int devfn) { struct dev_archdata *sd; struct of_device *op; @@ -998,7 +998,7 @@ EXPORT_SYMBOL(pci_domain_nr); int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - int virt_irq; + unsigned int virt_irq; if (!pbm->setup_msi_irq) return -EINVAL; @@ -1012,10 +1012,8 @@ void arch_teardown_msi_irq(unsigned int virt_irq) struct pci_dev *pdev = entry->dev; struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - if (!pbm->teardown_msi_irq) - return; - - return pbm->teardown_msi_irq(virt_irq, pdev); + if (pbm->teardown_msi_irq) + pbm->teardown_msi_irq(virt_irq, pdev); } #endif /* !(CONFIG_PCI_MSI) */ diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index b300f39e9e8..03186824327 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -178,4 +178,8 @@ extern void pci_config_write32(u32 *addr, u32 val); extern struct pci_ops sun4u_pci_ops; extern struct pci_ops sun4v_pci_ops; +extern volatile int pci_poke_in_progress; +extern volatile int pci_poke_cpu; +extern volatile int pci_poke_faulted; + #endif /* !(PCI_IMPL_H) */ diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 9378896589f..342da216423 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -341,10 +341,7 @@ void sun4v_data_access_exception_tl1(struct pt_regs *regs, unsigned long addr, u } #ifdef CONFIG_PCI -/* This is really pathetic... */ -extern volatile int pci_poke_in_progress; -extern volatile int pci_poke_cpu; -extern volatile int pci_poke_faulted; +#include "pci_impl.h" #endif /* When access exceptions happen, we must do this. */ -- cgit v1.2.3 From 8d2aec512304144cbb4f7dbb484626fb598b698e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:01:03 -0700 Subject: sparc64: Fix sparse warnings in pci_sun4v.c 'err' variable shadowing in pci_sun4v_probe() Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_sun4v.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 97a77bcd255..e86c73ec167 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -942,9 +942,9 @@ static int __devinit pci_sun4v_probe(struct of_device *op, dp = op->node; if (!hvapi_negotiated++) { - int err = sun4v_hvapi_register(HV_GRP_PCI, - vpci_major, - &vpci_minor); + err = sun4v_hvapi_register(HV_GRP_PCI, + vpci_major, + &vpci_minor); if (err) { printk(KERN_ERR PFX "Could not register hvapi, " -- cgit v1.2.3 From 7694b024f145c4a598cde5fcccfd3fe5eac4027b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:04:33 -0700 Subject: sparc64: Fix sparse warnings in vio.c Several variables should be marked static. Signed-off-by: David S. Miller --- arch/sparc64/kernel/vio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index a490077891a..92b1f8ec01d 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c @@ -152,7 +152,7 @@ show_pciobppath_attr(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); -struct device_node *cdev_node; +static struct device_node *cdev_node; static struct vio_dev *root_vdev; static u64 cdev_cfg_handle; @@ -371,9 +371,9 @@ static struct mdesc_notifier_client vio_ds_notifier = { .node_name = "domain-services-port", }; -const char *channel_devices_node = "channel-devices"; -const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; -const char *cfg_handle_prop = "cfg-handle"; +static const char *channel_devices_node = "channel-devices"; +static const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; +static const char *cfg_handle_prop = "cfg-handle"; static int __init vio_init(void) { -- cgit v1.2.3 From a9e7bb041084055b70971e3cde3bb21aea593a74 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:06:58 -0700 Subject: sparc64: Remove explicit initialization of mmu_gathers This was just needed to work around an ancient gcc bug that we don't care about any more. It was also causing a sparse warnings: arch/sparc64/mm/tlb.c:22:52: warning: Using plain integer as NULL pointer Signed-off-by: David S. Miller --- arch/sparc64/mm/tlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c index ae24919cba7..d8f21e24a82 100644 --- a/arch/sparc64/mm/tlb.c +++ b/arch/sparc64/mm/tlb.c @@ -19,7 +19,7 @@ /* Heavily inspired by the ppc64 code. */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); void flush_tlb_pending(void) { -- cgit v1.2.3 From b539c4676600dc25c2cd9322ff6bff2c2d455161 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:10:32 -0700 Subject: sparc64: Fix sparse warnings in fault.c 1) set_brkpt() is referenced by nothing and hasn't been used by anyone to my knowledge for many many years. So just delete it. 2) add extern decl for do_sparc64_fault() in asm/pgtable_64.h Signed-off-by: David S. Miller --- arch/sparc/include/asm/pgtable_64.h | 2 ++ arch/sparc64/mm/fault.c | 37 ------------------------------------- 2 files changed, 2 insertions(+), 37 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index bb9ec2cce35..b049abf9902 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -770,6 +770,8 @@ extern void sun4v_patch_tlb_handlers(void); extern unsigned long cmdline_memory_size; +extern asmlinkage void do_sparc64_fault(struct pt_regs *regs); + #endif /* !(__ASSEMBLY__) */ #endif /* !(_SPARC64_PGTABLE_H) */ diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index ea7d7ae76bc..a9e474bf638 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -51,43 +51,6 @@ static inline int notify_page_fault(struct pt_regs *regs) } #endif -/* - * To debug kernel to catch accesses to certain virtual/physical addresses. - * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. - * flags = VM_READ watches memread accesses, flags = VM_WRITE watches memwrite accesses. - * Caller passes in a 64bit aligned addr, with mask set to the bytes that need to be - * watched. This is only useful on a single cpu machine for now. After the watchpoint - * is detected, the process causing it will be killed, thus preventing an infinite loop. - */ -void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode) -{ - unsigned long lsubits; - - __asm__ __volatile__("ldxa [%%g0] %1, %0" - : "=r" (lsubits) - : "i" (ASI_LSU_CONTROL)); - lsubits &= ~(LSU_CONTROL_PM | LSU_CONTROL_VM | - LSU_CONTROL_PR | LSU_CONTROL_VR | - LSU_CONTROL_PW | LSU_CONTROL_VW); - - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (addr), "r" (mode ? VIRT_WATCHPOINT : PHYS_WATCHPOINT), - "i" (ASI_DMMU)); - - lsubits |= ((unsigned long)mask << (mode ? 25 : 33)); - if (flags & VM_READ) - lsubits |= (mode ? LSU_CONTROL_VR : LSU_CONTROL_PR); - if (flags & VM_WRITE) - lsubits |= (mode ? LSU_CONTROL_VW : LSU_CONTROL_PW); - __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (lsubits), "i" (ASI_LSU_CONTROL) - : "memory"); -} - static void __kprobes unhandled_fault(unsigned long address, struct task_struct *tsk, struct pt_regs *regs) -- cgit v1.2.3 From af1ee569d32e4dec5d14758ce025cc374088394d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:19:21 -0700 Subject: sparc64: Kill sparse warnings in mm/init.h 1) Several exported symbols need extern decls, they are exported not for C code but for assembler routines. 2) PAGE_EXEC isn't used, delete 3) Several larger than 32-bit constants need "UL" markers Signed-off-by: David S. Miller --- arch/sparc64/mm/init.c | 36 +++++++----------------------------- arch/sparc64/mm/init.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 29 deletions(-) create mode 100644 arch/sparc64/mm/init.h (limited to 'arch') diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 4fb9de00fc8..3c10daf8fc0 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -50,10 +50,7 @@ #include #include -#define MAX_PHYS_ADDRESS (1UL << 42UL) -#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) -#define KPTE_BITMAP_BYTES \ - ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8) +#include "init.h" unsigned long kern_linear_pte_xor[2] __read_mostly; @@ -415,17 +412,9 @@ void mmu_info(struct seq_file *m) #endif /* CONFIG_DEBUG_DCFLUSH */ } -struct linux_prom_translation { - unsigned long virt; - unsigned long size; - unsigned long data; -}; - -/* Exported for kernel TLB miss handling in ktlb.S */ struct linux_prom_translation prom_trans[512] __read_mostly; unsigned int prom_trans_ents __read_mostly; -/* Exported for SMP bootup purposes. */ unsigned long kern_locked_tte_data; /* The obp translations are saved based on 8k pagesize, since obp can @@ -2064,7 +2053,6 @@ pgprot_t PAGE_COPY __read_mostly; pgprot_t PAGE_SHARED __read_mostly; EXPORT_SYMBOL(PAGE_SHARED); -pgprot_t PAGE_EXEC __read_mostly; unsigned long pg_iobits __read_mostly; unsigned long _PAGE_IE __read_mostly; @@ -2077,14 +2065,6 @@ unsigned long _PAGE_CACHE __read_mostly; EXPORT_SYMBOL(_PAGE_CACHE); #ifdef CONFIG_SPARSEMEM_VMEMMAP - -#define VMEMMAP_CHUNK_SHIFT 22 -#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) -#define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) -#define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) - -#define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ - sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) unsigned long vmemmap_table[VMEMMAP_SIZE]; int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) @@ -2168,7 +2148,6 @@ static void __init sun4u_pgprot_init(void) _PAGE_CACHE_4U | _PAGE_P_4U | __ACCESS_BITS_4U | __DIRTY_BITS_4U | _PAGE_EXEC_4U | _PAGE_L_4U); - PAGE_EXEC = __pgprot(_PAGE_EXEC_4U); _PAGE_IE = _PAGE_IE_4U; _PAGE_E = _PAGE_E_4U; @@ -2179,10 +2158,10 @@ static void __init sun4u_pgprot_init(void) #ifdef CONFIG_DEBUG_PAGEALLOC kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4U) ^ - 0xfffff80000000000; + 0xfffff80000000000UL; #else kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ - 0xfffff80000000000; + 0xfffff80000000000UL; #endif kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_P_4U | _PAGE_W_4U); @@ -2220,7 +2199,6 @@ static void __init sun4v_pgprot_init(void) __ACCESS_BITS_4V | __DIRTY_BITS_4V | _PAGE_EXEC_4V); PAGE_KERNEL_LOCKED = PAGE_KERNEL; - PAGE_EXEC = __pgprot(_PAGE_EXEC_4V); _PAGE_IE = _PAGE_IE_4V; _PAGE_E = _PAGE_E_4V; @@ -2228,20 +2206,20 @@ static void __init sun4v_pgprot_init(void) #ifdef CONFIG_DEBUG_PAGEALLOC kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ - 0xfffff80000000000; + 0xfffff80000000000UL; #else kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ - 0xfffff80000000000; + 0xfffff80000000000UL; #endif kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V | _PAGE_W_4V); #ifdef CONFIG_DEBUG_PAGEALLOC kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ - 0xfffff80000000000; + 0xfffff80000000000UL; #else kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ - 0xfffff80000000000; + 0xfffff80000000000UL; #endif kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V | _PAGE_W_4V); diff --git a/arch/sparc64/mm/init.h b/arch/sparc64/mm/init.h new file mode 100644 index 00000000000..16063870a48 --- /dev/null +++ b/arch/sparc64/mm/init.h @@ -0,0 +1,49 @@ +#ifndef _SPARC64_MM_INIT_H +#define _SPARC64_MM_INIT_H + +/* Most of the symbols in this file are defined in init.c and + * marked non-static so that assembler code can get at them. + */ + +#define MAX_PHYS_ADDRESS (1UL << 42UL) +#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) +#define KPTE_BITMAP_BYTES \ + ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8) + +extern unsigned long kern_linear_pte_xor[2]; +extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; +extern unsigned int sparc64_highest_unlocked_tlb_ent; +extern unsigned long sparc64_kern_pri_context; +extern unsigned long sparc64_kern_pri_nuc_bits; +extern unsigned long sparc64_kern_sec_context; +extern void mmu_info(struct seq_file *m); + +struct linux_prom_translation { + unsigned long virt; + unsigned long size; + unsigned long data; +}; + +/* Exported for kernel TLB miss handling in ktlb.S */ +extern struct linux_prom_translation prom_trans[512]; +extern unsigned int prom_trans_ents; + +/* Exported for SMP bootup purposes. */ +extern unsigned long kern_locked_tte_data; + +extern void prom_world(int enter); + +extern void free_initmem(void); + +#ifdef CONFIG_SPARSEMEM_VMEMMAP +#define VMEMMAP_CHUNK_SHIFT 22 +#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) +#define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) +#define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) + +#define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ + sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) +extern unsigned long vmemmap_table[VMEMMAP_SIZE]; +#endif + +#endif /* _SPARC64_MM_INIT_H */ -- cgit v1.2.3 From 3ab5827eb0fefbfa7234f3f91f78b50f2dfcf8e4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:22:42 -0700 Subject: sparc64: Fix sparse warnings in chmc.c Several constants are larger than 32-bit and need "UL" markers. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 2ed401087ca..967b0488682 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -104,20 +104,20 @@ struct chmc { #define JBUSMC_REGS_SIZE 8 -#define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000 -#define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000 -#define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000 -#define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000 -#define JB_MC_REG1_XOR 0x0000010000000000 -#define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000 +#define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000UL +#define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000UL +#define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000UL +#define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000UL +#define JB_MC_REG1_XOR 0x0000010000000000UL +#define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000UL #define JB_MC_REG1_ADDR_GEN_2_SHIFT 37 -#define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000 +#define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000UL #define JB_MC_REG1_ADDR_GEN_1_SHIFT 34 -#define JB_MC_REG1_INTERLEAVE 0x0000000001800000 +#define JB_MC_REG1_INTERLEAVE 0x0000000001800000UL #define JB_MC_REG1_INTERLEAVE_SHIFT 23 -#define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000 +#define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000UL #define JB_MC_REG1_DIMM2_PTYPE_SHIFT 21 -#define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000 +#define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000UL #define JB_MC_REG1_DIMM1_PTYPE_SHIFT 20 #define PART_TYPE_X8 0 -- cgit v1.2.3 From a0a29b62a9cac6b7d83b7514679f2ed8d33d4372 Mon Sep 17 00:00:00 2001 From: Dmitry Adamushko Date: Thu, 11 Sep 2008 23:27:52 +0200 Subject: x86, microcode rework, v2 this is a rework of the microcode splitup in tip/x86/microcode (1) I think this new interface is cleaner (look at the changes in 'struct microcode_ops' in microcode.h); (2) it's -64 lines of code; Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 84 ++++------ arch/x86/kernel/microcode_amd.c | 329 ++++++++++++++++++-------------------- arch/x86/kernel/microcode_intel.c | 220 +++++++++++-------------- 3 files changed, 285 insertions(+), 348 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index b2f84ce5eed..902dada2eb6 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -110,50 +110,28 @@ struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; EXPORT_SYMBOL_GPL(ucode_cpu_info); #ifdef CONFIG_MICROCODE_OLD_INTERFACE -void __user *user_buffer; /* user area microcode data buffer */ -EXPORT_SYMBOL_GPL(user_buffer); -unsigned int user_buffer_size; /* it's size */ -EXPORT_SYMBOL_GPL(user_buffer_size); - -static int do_microcode_update(void) +static int do_microcode_update(const void __user *buf, size_t size) { - long cursor = 0; + cpumask_t old; int error = 0; - void *new_mc = NULL; int cpu; - cpumask_t old; old = current->cpus_allowed; - while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) { - if (microcode_ops->microcode_sanity_check != NULL) - error = microcode_ops->microcode_sanity_check(new_mc); - if (error) + for_each_online_cpu(cpu) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!uci->valid) + continue; + + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); + error = microcode_ops->request_microcode_user(cpu, buf, size); + if (error < 0) goto out; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - for_each_online_cpu(cpu) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!uci->valid) - continue; - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - error = microcode_ops->get_matching_microcode(new_mc, - cpu); - if (error < 0) - goto out; - if (error == 1) - microcode_ops->apply_microcode(cpu); - } - vfree(new_mc); + if (!error) + microcode_ops->apply_microcode(cpu); } out: - if (cursor > 0) - vfree(new_mc); - if (cursor < 0) - error = cursor; set_cpus_allowed_ptr(current, &old); return error; } @@ -178,10 +156,7 @@ static ssize_t microcode_write(struct file *file, const char __user *buf, get_online_cpus(); mutex_lock(µcode_mutex); - user_buffer = (void __user *) buf; - user_buffer_size = (int) len; - - ret = do_microcode_update(); + ret = do_microcode_update(buf, len); if (!ret) ret = (ssize_t)len; @@ -231,7 +206,6 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); /* fake device for request_firmware */ struct platform_device *microcode_pdev; -EXPORT_SYMBOL_GPL(microcode_pdev); static ssize_t reload_store(struct sys_device *dev, struct sysdev_attribute *attr, @@ -252,8 +226,12 @@ static ssize_t reload_store(struct sys_device *dev, if (cpu_online(cpu)) { set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); mutex_lock(µcode_mutex); - if (uci->valid) - err = microcode_ops->cpu_request_microcode(cpu); + if (uci->valid) { + err = microcode_ops->request_microcode_fw(cpu, + µcode_pdev->dev); + if (!err) + microcode_ops->apply_microcode(cpu); + } mutex_unlock(µcode_mutex); set_cpus_allowed_ptr(current, &old); } @@ -315,7 +293,7 @@ static void collect_cpu_info(int cpu) uci->valid = 1; } -static void microcode_resume_cpu(int cpu) +static int microcode_resume_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct cpu_signature nsig; @@ -323,7 +301,7 @@ static void microcode_resume_cpu(int cpu) pr_debug("microcode: CPU%d resumed\n", cpu); if (!uci->mc.valid_mc) - return; + return 1; /* * Let's verify that the 'cached' ucode does belong @@ -331,21 +309,22 @@ static void microcode_resume_cpu(int cpu) */ if (microcode_ops->collect_cpu_info(cpu, &nsig)) { microcode_fini_cpu(cpu); - return; + return -1; } if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { microcode_fini_cpu(cpu); /* Should we look for a new ucode here? */ - return; + return 1; } - microcode_ops->apply_microcode(cpu); + return 0; } void microcode_update_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + int err = 0; /* We should bind the task to the CPU */ BUG_ON(raw_smp_processor_id() != cpu); @@ -356,12 +335,17 @@ void microcode_update_cpu(int cpu) * otherwise just request a firmware: */ if (uci->valid) { - microcode_resume_cpu(cpu); + err = microcode_resume_cpu(cpu); } else { collect_cpu_info(cpu); if (uci->valid && system_state == SYSTEM_RUNNING) - microcode_ops->cpu_request_microcode(cpu); + err = microcode_ops->request_microcode_fw(cpu, + µcode_pdev->dev); } + + if (!err) + microcode_ops->apply_microcode(cpu); + mutex_unlock(µcode_mutex); } @@ -414,7 +398,7 @@ static int mc_sysdev_resume(struct sys_device *dev) return 0; pr_debug("microcode: CPU%d resumed\n", cpu); /* only CPU 0 will apply ucode here */ - microcode_ops->apply_microcode(0); + microcode_update_cpu(0); return 0; } diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index d606a05545c..6815837a775 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -59,7 +59,7 @@ MODULE_LICENSE("GPL v2"); /* serialize access to the physical write */ static DEFINE_SPINLOCK(microcode_update_lock); -struct equiv_cpu_entry *equiv_cpu_table; +static struct equiv_cpu_entry *equiv_cpu_table; static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) { @@ -83,36 +83,37 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) return 0; } -static int get_matching_microcode_amd(void *mc, int cpu) +static int get_matching_microcode(int cpu, void *mc, int rev) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct microcode_header_amd *mc_header = mc; - unsigned long total_size = get_totalsize(mc_header); - void *new_mc; struct pci_dev *nb_pci_dev, *sb_pci_dev; unsigned int current_cpu_id; unsigned int equiv_cpu_id = 0x00; unsigned int i = 0; - /* We should bind the task to the CPU */ - BUG_ON(cpu != raw_smp_processor_id()); - - /* This is a tricky part. We might be called from a write operation */ - /* to the device file instead of the usual process of firmware */ - /* loading. This routine needs to be able to distinguish both */ -/* cases. This is done by checking if there alread is a equivalent */ - /* CPU table installed. If not, we're written through */ - /* /dev/cpu/microcode. */ -/* Since we ignore all checks. The error case in which going through */ -/* firmware loading and that table is not loaded has already been */ - /* checked earlier. */ + /* + * dimm: do we need this? Why an update via /dev/... is different + * from the one via firmware? + * + * This is a tricky part. We might be called from a write operation + * to the device file instead of the usual process of firmware + * loading. This routine needs to be able to distinguish both + * cases. This is done by checking if there alread is a equivalent + * CPU table installed. If not, we're written through + * /dev/cpu/microcode. + * Since we ignore all checks. The error case in which going through + * firmware loading and that table is not loaded has already been + * checked earlier. + */ + BUG_ON(equiv_cpu_table == NULL); +#if 0 if (equiv_cpu_table == NULL) { printk(KERN_INFO "microcode: CPU%d microcode update with " "version 0x%x (current=0x%x)\n", cpu, mc_header->patch_id, uci->cpu_sig.rev); goto out; } - +#endif current_cpu_id = cpuid_eax(0x00000001); while (equiv_cpu_table[i].installed_cpu != 0) { @@ -175,27 +176,9 @@ static int get_matching_microcode_amd(void *mc, int cpu) pci_dev_put(sb_pci_dev); } - if (mc_header->patch_id <= uci->cpu_sig.rev) + if (mc_header->patch_id <= rev) return 0; - printk(KERN_INFO "microcode: CPU%d found a matching microcode " - "update with version 0x%x (current=0x%x)\n", - cpu, mc_header->patch_id, uci->cpu_sig.rev); - -out: - new_mc = vmalloc(UCODE_MAX_SIZE); - if (!new_mc) { - printk(KERN_ERR "microcode: error, can't allocate memory\n"); - return -ENOMEM; - } - memset(new_mc, 0, UCODE_MAX_SIZE); - - /* free previous update file */ - vfree(uci->mc.mc_amd); - - memcpy(new_mc, mc, total_size); - - uci->mc.mc_amd = new_mc; return 1; } @@ -245,104 +228,65 @@ static void apply_microcode_amd(int cpu) uci->cpu_sig.rev = rev; } -#ifdef CONFIG_MICROCODE_OLD_INTERFACE -extern void __user *user_buffer; /* user area microcode data buffer */ -extern unsigned int user_buffer_size; /* it's size */ - -static long get_next_ucode_amd(void **mc, long offset) -{ - struct microcode_header_amd mc_header; - unsigned long total_size; - - /* No more data */ - if (offset >= user_buffer_size) - return 0; - if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) { - printk(KERN_ERR "microcode: error! Can not read user data\n"); - return -EFAULT; - } - total_size = get_totalsize(&mc_header); - if (offset + total_size > user_buffer_size) { - printk(KERN_ERR "microcode: error! Bad total size in microcode " - "data file\n"); - return -EINVAL; - } - *mc = vmalloc(UCODE_MAX_SIZE); - if (!*mc) - return -ENOMEM; - memset(*mc, 0, UCODE_MAX_SIZE); - - if (copy_from_user(*mc, user_buffer + offset, total_size)) { - printk(KERN_ERR "microcode: error! Can not read user data\n"); - vfree(*mc); - return -EFAULT; - } - return offset + total_size; -} -#else -#define get_next_ucode_amd() NULL -#endif - -static long get_next_ucode_from_buffer_amd(void **mc, void *buf, - unsigned long size, long offset) +static void * get_next_ucode(u8 *buf, unsigned int size, + int (*get_ucode_data)(void *, const void *, size_t), + unsigned int *mc_size) { - struct microcode_header_amd *mc_header; - unsigned long total_size; - unsigned char *buf_pos = buf; + unsigned int total_size; +#define UCODE_UNKNOWN_HDR 8 + u8 hdr[UCODE_UNKNOWN_HDR]; + void *mc; - /* No more data */ - if (offset >= size) - return 0; + if (get_ucode_data(hdr, buf, UCODE_UNKNOWN_HDR)) + return NULL; - if (buf_pos[offset] != UCODE_UCODE_TYPE) { + if (hdr[0] != UCODE_UCODE_TYPE) { printk(KERN_ERR "microcode: error! " "Wrong microcode payload type field\n"); - return -EINVAL; + return NULL; } - mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]); + /* Why not by means of get_totalsize(hdr)? */ + total_size = (unsigned long) (hdr[4] + (hdr[5] << 8)); - total_size = (unsigned long) (buf_pos[offset+4] + - (buf_pos[offset+5] << 8)); + printk(KERN_INFO "microcode: size %u, total_size %u\n", + size, total_size); - printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n", - size, total_size, offset); - - if (offset + total_size > size) { + if (total_size > size || total_size > UCODE_MAX_SIZE) { printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); - return -EINVAL; + return NULL; } - *mc = vmalloc(UCODE_MAX_SIZE); - if (!*mc) { - printk(KERN_ERR "microcode: error! " - "Can not allocate memory for microcode patch\n"); - return -ENOMEM; + mc = vmalloc(UCODE_MAX_SIZE); + if (mc) { + memset(mc, 0, UCODE_MAX_SIZE); + if (get_ucode_data(mc, buf + UCODE_UNKNOWN_HDR, total_size)) { + vfree(mc); + mc = NULL; + } else + *mc_size = total_size + UCODE_UNKNOWN_HDR; } - - memset(*mc, 0, UCODE_MAX_SIZE); - memcpy(*mc, buf + offset + 8, total_size); - - return offset + total_size + 8; +#undef UCODE_UNKNOWN_HDR + return mc; } -static long install_equiv_cpu_table(void *buf, unsigned long size, long offset) + +static int install_equiv_cpu_table(u8 *buf, + int (*get_ucode_data)(void *, const void *, size_t)) { - unsigned int *buf_pos = buf; +#define UCODE_HEADER_SIZE 12 + u8 *hdr[UCODE_HEADER_SIZE]; + unsigned int *buf_pos = (unsigned int *)hdr; + unsigned long size; - /* No more data */ - if (offset >= size) + if (get_ucode_data(&hdr, buf, UCODE_HEADER_SIZE)) return 0; - if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) { - printk(KERN_ERR "microcode: error! " - "Wrong microcode equivalnet cpu table type field\n"); - return 0; - } + size = buf_pos[2]; - if (size == 0) { + if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) { printk(KERN_ERR "microcode: error! " - "Wrong microcode equivalnet cpu table length\n"); + "Wrong microcode equivalnet cpu table\n"); return 0; } @@ -352,79 +296,118 @@ static long install_equiv_cpu_table(void *buf, unsigned long size, long offset) return 0; } - memset(equiv_cpu_table, 0, size); - memcpy(equiv_cpu_table, &buf_pos[3], size); + buf += UCODE_HEADER_SIZE; + if (get_ucode_data(equiv_cpu_table, buf, size)) { + vfree(equiv_cpu_table); + return 0; + } - return size + 12; /* add header length */ + return size + UCODE_HEADER_SIZE; /* add header length */ +#undef UCODE_HEADER_SIZE } -/* fake device for request_firmware */ -extern struct platform_device *microcode_pdev; - -static int cpu_request_microcode_amd(int cpu) +static void free_equiv_cpu_table(void) { - char name[30]; - const struct firmware *firmware; - void *buf; - unsigned int *buf_pos; - unsigned long size; - long offset = 0; - int error; - void *mc; - - /* We should bind the task to the CPU */ - BUG_ON(cpu != raw_smp_processor_id()); - - sprintf(name, "amd-ucode/microcode_amd.bin"); - error = request_firmware(&firmware, "amd-ucode/microcode_amd.bin", - µcode_pdev->dev); - if (error) { - printk(KERN_ERR "microcode: ucode data file %s load failed\n", - name); - return error; - } - - buf_pos = (unsigned int *)firmware->data; - buf = (void *)firmware->data; - size = firmware->size; - - if (buf_pos[0] != UCODE_MAGIC) { - printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n"); - return -EINVAL; + if (equiv_cpu_table) { + vfree(equiv_cpu_table); + equiv_cpu_table = NULL; } +} - offset = install_equiv_cpu_table(buf, buf_pos[2], offset); +static int generic_load_microcode(int cpu, void *data, size_t size, + int (*get_ucode_data)(void *, const void *, size_t)) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + u8 *ucode_ptr = data, *new_mc = NULL, *mc; + int new_rev = uci->cpu_sig.rev; + unsigned int leftover; + unsigned long offset; + offset = install_equiv_cpu_table(ucode_ptr, get_ucode_data); if (!offset) { printk(KERN_ERR "microcode: installing equivalent cpu table failed\n"); return -EINVAL; } - while ((offset = - get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) { - error = get_matching_microcode_amd(mc, cpu); - if (error < 0) + ucode_ptr += offset; + leftover = size - offset; + + while (leftover) { + unsigned int mc_size; + struct microcode_header_amd *mc_header; + + mc = get_next_ucode(ucode_ptr, leftover, get_ucode_data, &mc_size); + if (!mc) break; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - if (error == 1) { - apply_microcode_amd(cpu); - error = 0; - } - vfree(mc); + + mc_header = (struct microcode_header_amd *)mc; + if (get_matching_microcode(cpu, mc, new_rev)) { + new_rev = mc_header->patch_id; + new_mc = mc; + } else + vfree(mc); + + ucode_ptr += mc_size; + leftover -= mc_size; } - if (offset > 0) { - vfree(mc); - vfree(equiv_cpu_table); - equiv_cpu_table = NULL; + + if (new_mc) { + if (!leftover) { + if (uci->mc.mc_amd) + vfree(uci->mc.mc_amd); + uci->mc.mc_amd = (struct microcode_amd *)new_mc; + pr_debug("microcode: CPU%d found a matching microcode update with" + " version 0x%x (current=0x%x)\n", + cpu, uci->mc.mc_amd->hdr.patch_id, uci->cpu_sig.rev); + } else + vfree(new_mc); } - if (offset < 0) - error = offset; + + free_equiv_cpu_table(); + + return (int)leftover; +} + +static int get_ucode_fw(void *to, const void *from, size_t n) +{ + memcpy(to, from, n); + return 0; +} + +static int request_microcode_fw(int cpu, struct device *device) +{ + const char *fw_name = "amd-ucode/microcode_amd.bin"; + const struct firmware *firmware; + int ret; + + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + + ret = request_firmware(&firmware, fw_name, device); + if (ret) { + printk(KERN_ERR "microcode: ucode data file %s load failed\n", fw_name); + return ret; + } + + ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size, + &get_ucode_fw); + release_firmware(firmware); - return error; + return ret; +} + +static int get_ucode_user(void *to, const void *from, size_t n) +{ + return copy_from_user(to, from, n); +} + +static int request_microcode_user(int cpu, const void __user *buf, size_t size) +{ + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + + return generic_load_microcode(cpu, (void*)buf, size, &get_ucode_user); } static void microcode_fini_cpu_amd(int cpu) @@ -436,10 +419,8 @@ static void microcode_fini_cpu_amd(int cpu) } static struct microcode_ops microcode_amd_ops = { - .get_next_ucode = get_next_ucode_amd, - .get_matching_microcode = get_matching_microcode_amd, - .microcode_sanity_check = NULL, - .cpu_request_microcode = cpu_request_microcode_amd, + .request_microcode_user = request_microcode_user, + .request_microcode_fw = request_microcode_fw, .collect_cpu_info = collect_cpu_info_amd, .apply_microcode = apply_microcode_amd, .microcode_fini_cpu = microcode_fini_cpu_amd, diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index c9b53202ba3..f4930b55c6a 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -155,15 +155,15 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) return 0; } -static inline int microcode_update_match(int cpu_num, - struct microcode_header_intel *mc_header, int sig, int pf) +static inline int update_match_cpu(struct cpu_signature *csig, int sig, int pf) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + return (!sigmatch(sig, csig->sig, pf, csig->pf)) ? 0 : 1; +} - if (!sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf) - || mc_header->rev <= uci->cpu_sig.rev) - return 0; - return 1; +static inline int +update_match_revision(struct microcode_header_intel *mc_header, int rev) +{ + return (mc_header->rev <= rev) ? 0 : 1; } static int microcode_sanity_check(void *mc) @@ -248,51 +248,36 @@ static int microcode_sanity_check(void *mc) /* * return 0 - no update found * return 1 - found update - * return < 0 - error */ -static int get_matching_microcode(void *mc, int cpu) +static int +get_matching_microcode(struct cpu_signature *cpu_sig, void *mc, int rev) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header; unsigned long total_size = get_totalsize(mc_header); int ext_sigcount, i; struct extended_signature *ext_sig; - void *new_mc; - if (microcode_update_match(cpu, mc_header, - mc_header->sig, mc_header->pf)) - goto find; + if (!update_match_revision(mc_header, rev)) + return 0; + + if (update_match_cpu(cpu_sig, mc_header->sig, mc_header->pf)) + return 1; + /* Look for ext. headers: */ if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE) return 0; ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; ext_sigcount = ext_header->count; ext_sig = (void *)ext_header + EXT_HEADER_SIZE; + for (i = 0; i < ext_sigcount; i++) { - if (microcode_update_match(cpu, mc_header, - ext_sig->sig, ext_sig->pf)) - goto find; + if (update_match_cpu(cpu_sig, ext_sig->sig, ext_sig->pf)) + return 1; ext_sig++; } return 0; -find: - pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", - cpu, mc_header->rev, uci->cpu_sig.rev); - new_mc = vmalloc(total_size); - if (!new_mc) { - printk(KERN_ERR "microcode: error! Can not allocate memory\n"); - return -ENOMEM; - } - - /* free previous update file */ - vfree(uci->mc.mc_intel); - - memcpy(new_mc, mc, total_size); - uci->mc.mc_intel = new_mc; - return 1; } static void apply_microcode(int cpu) @@ -300,7 +285,7 @@ static void apply_microcode(int cpu) unsigned long flags; unsigned int val[2]; int cpu_num = raw_smp_processor_id(); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); @@ -338,116 +323,105 @@ static void apply_microcode(int cpu) uci->cpu_sig.rev = val[1]; } -#ifdef CONFIG_MICROCODE_OLD_INTERFACE -extern void __user *user_buffer; /* user area microcode data buffer */ -extern unsigned int user_buffer_size; /* it's size */ - -static long get_next_ucode(void **mc, long offset) +static int generic_load_microcode(int cpu, void *data, size_t size, + int (*get_ucode_data)(void *, const void *, size_t)) { - struct microcode_header_intel mc_header; - unsigned long total_size; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + u8 *ucode_ptr = data, *new_mc = NULL, *mc; + int new_rev = uci->cpu_sig.rev; + unsigned int leftover = size; - /* No more data */ - if (offset >= user_buffer_size) - return 0; - if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) { - printk(KERN_ERR "microcode: error! Can not read user data\n"); - return -EFAULT; - } - total_size = get_totalsize(&mc_header); - if (offset + total_size > user_buffer_size) { - printk(KERN_ERR "microcode: error! Bad total size in microcode " - "data file\n"); - return -EINVAL; - } - *mc = vmalloc(total_size); - if (!*mc) - return -ENOMEM; - if (copy_from_user(*mc, user_buffer + offset, total_size)) { - printk(KERN_ERR "microcode: error! Can not read user data\n"); - vfree(*mc); - return -EFAULT; - } - return offset + total_size; -} -#endif + while (leftover) { + struct microcode_header_intel mc_header; + unsigned int mc_size; -static long get_next_ucode_from_buffer(void **mc, const u8 *buf, - unsigned long size, long offset) -{ - struct microcode_header_intel *mc_header; - unsigned long total_size; + if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header))) + break; - /* No more data */ - if (offset >= size) - return 0; - mc_header = (struct microcode_header_intel *)(buf + offset); - total_size = get_totalsize(mc_header); + mc_size = get_totalsize(&mc_header); + if (!mc_size || mc_size > leftover) { + printk(KERN_ERR "microcode: error!" + "Bad data in microcode data file\n"); + break; + } - if (offset + total_size > size) { - printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); - return -EINVAL; + mc = vmalloc(mc_size); + if (!mc) + break; + + if (get_ucode_data(mc, ucode_ptr, mc_size) || + microcode_sanity_check(mc) < 0) { + vfree(mc); + break; + } + + if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { + new_rev = mc_header.rev; + new_mc = mc; + } else + vfree(mc); + + ucode_ptr += mc_size; + leftover -= mc_size; } - *mc = vmalloc(total_size); - if (!*mc) { - printk(KERN_ERR "microcode: error! Can not allocate memory\n"); - return -ENOMEM; + if (new_mc) { + if (!leftover) { + if (uci->mc.mc_intel) + vfree(uci->mc.mc_intel); + uci->mc.mc_intel = (struct microcode_intel *)new_mc; + pr_debug("microcode: CPU%d found a matching microcode update with" + " version 0x%x (current=0x%x)\n", + cpu, uci->mc.mc_intel->hdr.rev, uci->cpu_sig.rev); + } else + vfree(new_mc); } - memcpy(*mc, buf + offset, total_size); - return offset + total_size; + + return (int)leftover; } -/* fake device for request_firmware */ -extern struct platform_device *microcode_pdev; +static int get_ucode_fw(void *to, const void *from, size_t n) +{ + memcpy(to, from, n); + return 0; +} -static int cpu_request_microcode(int cpu) +static int request_microcode_fw(int cpu, struct device *device) { char name[30]; struct cpuinfo_x86 *c = &cpu_data(cpu); const struct firmware *firmware; - const u8 *buf; - unsigned long size; - long offset = 0; - int error; - void *mc; + int ret; /* We should bind the task to the CPU */ BUG_ON(cpu != raw_smp_processor_id()); sprintf(name, "intel-ucode/%02x-%02x-%02x", c->x86, c->x86_model, c->x86_mask); - error = request_firmware(&firmware, name, µcode_pdev->dev); - if (error) { + ret = request_firmware(&firmware, name, device); + if (ret) { pr_debug("microcode: data file %s load failed\n", name); - return error; - } - buf = firmware->data; - size = firmware->size; - while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) - > 0) { - error = microcode_sanity_check(mc); - if (error) - break; - error = get_matching_microcode(mc, cpu); - if (error < 0) - break; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - if (error == 1) { - apply_microcode(cpu); - error = 0; - } - vfree(mc); + return ret; } - if (offset > 0) - vfree(mc); - if (offset < 0) - error = offset; + + ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size, + &get_ucode_fw); + release_firmware(firmware); - return error; + return ret; +} + +static int get_ucode_user(void *to, const void *from, size_t n) +{ + return copy_from_user(to, from, n); +} + +static int request_microcode_user(int cpu, const void __user *buf, size_t size) +{ + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + + return generic_load_microcode(cpu, (void*)buf, size, &get_ucode_user); } static void microcode_fini_cpu(int cpu) @@ -459,10 +433,8 @@ static void microcode_fini_cpu(int cpu) } static struct microcode_ops microcode_intel_ops = { - .get_next_ucode = get_next_ucode, - .get_matching_microcode = get_matching_microcode, - .microcode_sanity_check = microcode_sanity_check, - .cpu_request_microcode = cpu_request_microcode, + .request_microcode_user = request_microcode_user, + .request_microcode_fw = request_microcode_fw, .collect_cpu_info = collect_cpu_info, .apply_microcode = apply_microcode, .microcode_fini_cpu = microcode_fini_cpu, -- cgit v1.2.3 From 3c503701038ac161c269ea43cd67805a3c5669fb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 15:01:31 -0700 Subject: sparc: Fix user_regset 'n' field values. As noticed by Russell King, we were not setting this properly to the number of entries, but rather the total size. This results in the core dumping code allocating waayyyy too much memory. Signed-off-by: David S. Miller --- arch/sparc/kernel/ptrace.c | 4 ++-- arch/sparc64/kernel/ptrace.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index 20699c70141..8ce6285a06d 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -288,7 +288,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 38 * sizeof(u32), + .n = 38, .size = sizeof(u32), .align = sizeof(u32), .get = genregs32_get, .set = genregs32_set }, @@ -304,7 +304,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 99 * sizeof(u32), + .n = 99, .size = sizeof(u32), .align = sizeof(u32), .get = fpregs32_get, .set = fpregs32_set }, diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index db2ddf2e829..f43adbc773c 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -443,7 +443,7 @@ static const struct user_regset sparc64_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 36 * sizeof(u64), + .n = 36, .size = sizeof(u64), .align = sizeof(u64), .get = genregs64_get, .set = genregs64_set }, @@ -455,7 +455,7 @@ static const struct user_regset sparc64_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 35 * sizeof(u64), + .n = 35, .size = sizeof(u64), .align = sizeof(u64), .get = fpregs64_get, .set = fpregs64_set }, @@ -801,7 +801,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 38 * sizeof(u32), + .n = 38, .size = sizeof(u32), .align = sizeof(u32), .get = genregs32_get, .set = genregs32_set }, @@ -817,7 +817,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 99 * sizeof(u32), + .n = 99, .size = sizeof(u32), .align = sizeof(u32), .get = fpregs32_get, .set = fpregs32_set }, -- cgit v1.2.3 From 9b2e43ae4e9609f80034dfe8de895045cac52d77 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:08:30 -0700 Subject: sparc32: Use PROM device probing for sun4m timer registers. Signed-off-by: David S. Miller --- arch/sparc/include/asm/timer_32.h | 43 -------------- arch/sparc/kernel/sun4m_irq.c | 121 ++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 107 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index adab3def007..8906e987ef8 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -35,49 +35,6 @@ struct sun4c_timer_info { #define SUN_TIMER_PHYSADDR 0xf3000000 -/* A sun4m has two blocks of registers which are probably of the same - * structure. LSI Logic's L64851 is told to _decrement_ from the limit - * value. Aurora behaves similarly but its limit value is compacted in - * other fashion (it's wider). Documented fields are defined here. - */ - -/* As with the interrupt register, we have two classes of timer registers - * which are per-cpu and master. Per-cpu timers only hit that cpu and are - * only level 14 ticks, master timer hits all cpus and is level 10. - */ - -#define SUN4M_PRM_CNT_L 0x80000000 -#define SUN4M_PRM_CNT_LVALUE 0x7FFFFC00 - -struct sun4m_timer_percpu_info { - __volatile__ unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */ - __volatile__ unsigned int l14_cur_count; - - /* This register appears to be write only and/or inaccessible - * on Uni-Processor sun4m machines. - */ - __volatile__ unsigned int l14_limit_noclear; /* Data access error is here */ - - __volatile__ unsigned int cntrl; /* =1 after POST on Aurora */ - __volatile__ unsigned char space[PAGE_SIZE - 16]; -}; - -struct sun4m_timer_regs { - struct sun4m_timer_percpu_info cpu_timers[SUN4M_NCPUS]; - volatile unsigned int l10_timer_limit; - volatile unsigned int l10_cur_count; - - /* Again, this appears to be write only and/or inaccessible - * on uni-processor sun4m machines. - */ - volatile unsigned int l10_limit_noclear; - - /* This register too, it must be magic. */ - volatile unsigned int foobar; - - volatile unsigned int cfg; /* equals zero at boot time... */ -}; - #define SUN4D_PRM_CNT_L 0x80000000 #define SUN4D_PRM_CNT_LVALUE 0x7FFFFC00 diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 3481feca335..5b17146f0c1 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -267,95 +267,88 @@ static void sun4m_set_udt(int cpu) } #endif +struct sun4m_timer_percpu { + u32 l14_limit; + u32 l14_count; + u32 l14_limit_noclear; + u32 user_timer_start_stop; +}; + +static struct sun4m_timer_percpu __iomem *timers_percpu[SUN4M_NCPUS]; + +struct sun4m_timer_global { + u32 l10_limit; + u32 l10_count; + u32 l10_limit_noclear; + u32 reserved; + u32 timer_config; +}; + +static struct sun4m_timer_global __iomem *timers_global; + #define OBIO_INTR 0x20 #define TIMER_IRQ (OBIO_INTR | 10) -#define PROFILE_IRQ (OBIO_INTR | 14) -static struct sun4m_timer_regs *sun4m_timers; unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); static void sun4m_clear_clock_irq(void) { - volatile unsigned int clear_intr; - clear_intr = sun4m_timers->l10_timer_limit; + sbus_readl(&timers_global->l10_limit); } static void sun4m_clear_profile_irq(int cpu) { - volatile unsigned int clear; - - clear = sun4m_timers->cpu_timers[cpu].l14_timer_limit; + sbus_readl(&timers_percpu[cpu]->l14_limit); } static void sun4m_load_profile_irq(int cpu, unsigned int limit) { - sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit; + sbus_writel(limit, &timers_percpu[cpu]->l14_limit); } static void __init sun4m_init_timers(irq_handler_t counter_fn) { - int reg_count, irq, cpu; - struct linux_prom_registers cnt_regs[PROMREG_MAX]; - int obio_node, cnt_node; - struct resource r; + struct device_node *dp = of_find_node_by_name(NULL, "counter"); + int i, err, len, num_cpu_timers; + const u32 *addr; - cnt_node = 0; - if((obio_node = - prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 || - (obio_node = prom_getchild (obio_node)) == 0 || - (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) { - prom_printf("Cannot find /obio/counter node\n"); - prom_halt(); + if (!dp) { + printk(KERN_ERR "sun4m_init_timers: No 'counter' node.\n"); + return; } - reg_count = prom_getproperty(cnt_node, "reg", - (void *) cnt_regs, sizeof(cnt_regs)); - reg_count = (reg_count/sizeof(struct linux_prom_registers)); - - /* Apply the obio ranges to the timer registers. */ - prom_apply_obio_ranges(cnt_regs, reg_count); - - cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr; - cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size; - cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io; - for(obio_node = 1; obio_node < 4; obio_node++) { - cnt_regs[obio_node].phys_addr = - cnt_regs[obio_node-1].phys_addr + PAGE_SIZE; - cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size; - cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io; + + addr = of_get_property(dp, "address", &len); + if (!addr) { + printk(KERN_ERR "sun4m_init_timers: No 'address' prop.\n"); + return; } - memset((char*)&r, 0, sizeof(struct resource)); - /* Map the per-cpu Counter registers. */ - r.flags = cnt_regs[0].which_io; - r.start = cnt_regs[0].phys_addr; - sun4m_timers = (struct sun4m_timer_regs *) of_ioremap(&r, 0, - PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt"); - /* Map the system Counter register. */ - /* XXX Here we expect consequent calls to yeld adjusent maps. */ - r.flags = cnt_regs[4].which_io; - r.start = cnt_regs[4].phys_addr; - of_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); - - sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); - master_l10_counter = &sun4m_timers->l10_cur_count; - master_l10_limit = &sun4m_timers->l10_timer_limit; - - irq = request_irq(TIMER_IRQ, - counter_fn, - (IRQF_DISABLED | SA_STATIC_ALLOC), - "timer", NULL); - if (irq) { - prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); - prom_halt(); + num_cpu_timers = (len / sizeof(u32)) - 1; + for (i = 0; i < num_cpu_timers; i++) { + timers_percpu[i] = (void __iomem *) + (unsigned long) addr[i]; } - - if (!cpu_find_by_instance(1, NULL, NULL)) { - for(cpu = 0; cpu < 4; cpu++) - sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0; - sun4m_interrupts->set = SUN4M_INT_E14; - } else { - sun4m_timers->cpu_timers[0].l14_timer_limit = 0; + timers_global = (void __iomem *) + (unsigned long) addr[num_cpu_timers]; + + sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); + + master_l10_counter = &timers_global->l10_count; + master_l10_limit = &timers_global->l10_limit; + + err = request_irq(TIMER_IRQ, counter_fn, + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); + if (err) { + printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", + err); + return; } + + for (i = 0; i < num_cpu_timers; i++) + sbus_writel(0, &timers_percpu[i]->l14_limit); + if (num_cpu_timers == 4) + sbus_writel(SUN4M_INT_E14, &sun4m_interrupts->set); + #ifdef CONFIG_SMP { unsigned long flags; -- cgit v1.2.3 From aef93c8bd506a78983d91cd576a97fee6e934ac1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 14 Sep 2008 02:33:15 -0700 Subject: x86: identify_cpu_without_cpuid v2 Krzysztof found some old cyrix cpu where an mtrr-alike cpu feature was not detected properly. this one is based on Krzysztof' patch, and we call ->c_identify() in early_identify_cpu. need to call c_identify() for cpus without cpuid even earlier ... v2: Krzysztof point out need to give cyrix another chance about cpuid checking again, after ->c_identify() enables cpuid for it Signed-off-by: Yinghai Lu Cc: Krzysztof Helt Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 57 +++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9a57106c199..f5f25b85be9 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -485,6 +485,33 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) c->x86_power = cpuid_edx(0x80000007); } + +static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_32 + int i; + + /* + * First of all, decide if this is a 486 or higher + * It's a 486 if we can modify the AC flag + */ + if (flag_is_changeable_p(X86_EFLAGS_AC)) + c->x86 = 4; + else + c->x86 = 3; + + for (i = 0; i < X86_VENDOR_NUM; i++) + if (cpu_devs[i] && cpu_devs[i]->c_identify) { + c->x86_vendor_id[0] = 0; + cpu_devs[i]->c_identify(c); + if (c->x86_vendor_id[0]) { + get_cpu_vendor(c); + break; + } + } +#endif +} + /* * Do minimum CPU detection early. * Fields really needed: vendor, cpuid_level, family, model, mask, @@ -503,13 +530,16 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) #endif c->x86_cache_alignment = c->x86_clflush_size; - if (!have_cpuid_p()) - return; - memset(&c->x86_capability, 0, sizeof c->x86_capability); - c->extended_cpuid_level = 0; + if (!have_cpuid_p()) + identify_cpu_without_cpuid(c); + + /* cyrix could have cpuid enabled via c_identify()*/ + if (!have_cpuid()) + return; + cpu_detect(c); get_cpu_vendor(c); @@ -583,10 +613,14 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) static void __cpuinit generic_identify(struct cpuinfo_x86 *c) { + c->extended_cpuid_level = 0; + if (!have_cpuid_p()) - return; + identify_cpu_without_cpuid(c); - c->extended_cpuid_level = 0; + /* cyrix could have cpuid enabled via c_identify()*/ + if (!have_cpuid()) + return; cpu_detect(c); @@ -639,17 +673,6 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86_cache_alignment = c->x86_clflush_size; memset(&c->x86_capability, 0, sizeof c->x86_capability); - if (!have_cpuid_p()) { - /* - * First of all, decide if this is a 486 or higher - * It's a 486 if we can modify the AC flag - */ - if (flag_is_changeable_p(X86_EFLAGS_AC)) - c->x86 = 4; - else - c->x86 = 3; - } - generic_identify(c); if (this_cpu->c_identify) -- cgit v1.2.3 From afae865613c8292e8bdcce4f0b161988d761f033 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 14 Sep 2008 02:33:16 -0700 Subject: x86: move transmeta cap read to early_init_transmeta() Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 8 -------- arch/x86/kernel/cpu/transmeta.c | 28 +++++++++++++++------------- 2 files changed, 15 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f5f25b85be9..3e2ce4d33d3 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -465,14 +465,6 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) } #ifdef CONFIG_X86_64 - /* Transmeta-defined flags: level 0x80860001 */ - xlvl = cpuid_eax(0x80860000); - if ((xlvl & 0xffff0000) == 0x80860000) { - /* Don't set x86_cpuid_level here for now to not confuse. */ - if (xlvl >= 0x80860001) - c->x86_capability[2] = cpuid_edx(0x80860001); - } - if (c->extended_cpuid_level >= 0x80000008) { u32 eax = cpuid_eax(0x80000008); diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 738e03244f9..52b3fefbd5a 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -5,6 +5,18 @@ #include #include "cpu.h" +static void __cpuinit early_init_transmeta(struct cpuinfo_x86 *c) +{ + u32 xlvl; + + /* Transmeta-defined flags: level 0x80860001 */ + xlvl = cpuid_eax(0x80860000); + if ((xlvl & 0xffff0000) == 0x80860000) { + if (xlvl >= 0x80860001) + c->x86_capability[2] = cpuid_edx(0x80860001); + } +} + static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) { unsigned int cap_mask, uk, max, dummy; @@ -12,6 +24,8 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) unsigned int cpu_rev, cpu_freq = 0, cpu_flags, new_cpu_rev; char cpu_info[65]; + early_init_transmeta(c); + display_cacheinfo(c); /* Print CMS and CPU revision */ @@ -84,23 +98,11 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) #endif } -static void __cpuinit transmeta_identify(struct cpuinfo_x86 *c) -{ - u32 xlvl; - - /* Transmeta-defined flags: level 0x80860001 */ - xlvl = cpuid_eax(0x80860000); - if ((xlvl & 0xffff0000) == 0x80860000) { - if (xlvl >= 0x80860001) - c->x86_capability[2] = cpuid_edx(0x80860001); - } -} - static struct cpu_dev transmeta_cpu_dev __cpuinitdata = { .c_vendor = "Transmeta", .c_ident = { "GenuineTMx86", "TransmetaCPU" }, + .c_early_init = early_init_transmeta, .c_init = init_transmeta, - .c_identify = transmeta_identify, .c_x86_vendor = X86_VENDOR_TRANSMETA, }; -- cgit v1.2.3 From a9853dd6d285c30a3ddeb3cce8c05e1678400bef Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 14 Sep 2008 14:46:58 +0200 Subject: x86: cpuid, fix typo Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 3e2ce4d33d3..cef3519b3bb 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -529,7 +529,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) identify_cpu_without_cpuid(c); /* cyrix could have cpuid enabled via c_identify()*/ - if (!have_cpuid()) + if (!have_cpuid_p()) return; cpu_detect(c); @@ -611,7 +611,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) identify_cpu_without_cpuid(c); /* cyrix could have cpuid enabled via c_identify()*/ - if (!have_cpuid()) + if (!have_cpuid_p()) return; cpu_detect(c); -- cgit v1.2.3 From a1c75cc5018f17ff6d80ce45a13435b1536f76db Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 14 Sep 2008 14:50:26 +0200 Subject: x86, microcode rework, v2, fix based on patch from Dmitry Adamushko. - add missing vfree() - update debug printks Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 4 +--- arch/x86/kernel/microcode_amd.c | 6 ++++-- arch/x86/kernel/microcode_intel.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 902dada2eb6..0c2634f4fd7 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -70,8 +70,6 @@ * Fix sigmatch() macro to handle old CPUs with pf == 0. * Thanks to Stuart Swales for pointing out this bug. */ - -/* #define DEBUG pr_debug */ #include #include #include @@ -396,7 +394,7 @@ static int mc_sysdev_resume(struct sys_device *dev) if (!cpu_online(cpu)) return 0; - pr_debug("microcode: CPU%d resumed\n", cpu); + /* only CPU 0 will apply ucode here */ microcode_update_cpu(0); return 0; diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 6815837a775..48aec9f48e4 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -92,7 +92,7 @@ static int get_matching_microcode(int cpu, void *mc, int rev) unsigned int i = 0; /* - * dimm: do we need this? Why an update via /dev/... is different + * FIXME! dimm: do we need this? Why an update via /dev/... is different * from the one via firmware? * * This is a tricky part. We might be called from a write operation @@ -246,7 +246,7 @@ static void * get_next_ucode(u8 *buf, unsigned int size, return NULL; } - /* Why not by means of get_totalsize(hdr)? */ + /* FIXME! dimm: Why not by means of get_totalsize(hdr)? */ total_size = (unsigned long) (hdr[4] + (hdr[5] << 8)); printk(KERN_INFO "microcode: size %u, total_size %u\n", @@ -342,6 +342,8 @@ static int generic_load_microcode(int cpu, void *data, size_t size, mc_header = (struct microcode_header_amd *)mc; if (get_matching_microcode(cpu, mc, new_rev)) { + if (new_mc) + vfree(new_mc); new_rev = mc_header->patch_id; new_mc = mc; } else diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index f4930b55c6a..48ed3cef58c 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -70,8 +70,6 @@ * Fix sigmatch() macro to handle old CPUs with pf == 0. * Thanks to Stuart Swales for pointing out this bug. */ - -/* #define DEBUG */ /* pr_debug */ #include #include #include @@ -356,6 +354,8 @@ static int generic_load_microcode(int cpu, void *data, size_t size, } if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { + if (new_mc) + vfree(new_mc); new_rev = mc_header.rev; new_mc = mc; } else -- cgit v1.2.3 From b899219572350685e6163ce7535efb5ad9bcd6a4 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 14 Sep 2008 13:44:41 +0400 Subject: x86: simpler SYSVIPC_COMPAT definition X86_64 part is entirely redundant. Signed-off-by: Alexey Dobriyan Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1e2afe60ba9..4c1475119ce 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1786,7 +1786,7 @@ config COMPAT_FOR_U64_ALIGNMENT config SYSVIPC_COMPAT def_bool y - depends on X86_64 && COMPAT && SYSVIPC + depends on COMPAT && SYSVIPC endmenu -- cgit v1.2.3 From 3d0aedd9538e6be8afec1a9d8b084bf90bc91495 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 12 Sep 2008 17:01:09 -0700 Subject: x86: signal: put give_sigsegv of setup frames together When setup frame fails, force_sigsegv is called and returns -EFAULT. There is similar code in ia32_setup_frame(), ia32_setup_rt_frame(), __setup_frame() and __setup_rt_frame(). Make them identical. No change in functionality intended. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 26 +++++++++----------------- arch/x86/kernel/signal_32.c | 31 ++++++++++++++----------------- arch/x86/kernel/signal_64.c | 17 +++++++++-------- 3 files changed, 32 insertions(+), 42 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 8d64c1bc847..5f42cfcc1c5 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -444,21 +444,21 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return -EFAULT; err |= __put_user(sig, &frame->sig); if (err) - goto give_sigsegv; + return -EFAULT; err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); if (err) - goto give_sigsegv; + return -EFAULT; if (_COMPAT_NSIG_WORDS > 1) { err |= __copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); if (err) - goto give_sigsegv; + return -EFAULT; } if (ka->sa.sa_flags & SA_RESTORER) { @@ -479,7 +479,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, */ err |= __copy_to_user(frame->retcode, &code, 8); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up registers for signal handler */ regs->sp = (unsigned long) frame; @@ -502,10 +502,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, #endif return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; } int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -533,14 +529,14 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return -EFAULT; err |= __put_user(sig, &frame->sig); err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); err |= copy_siginfo_to_user32(&frame->info, info); if (err) - goto give_sigsegv; + return -EFAULT; /* Create the ucontext. */ if (cpu_has_xsave) @@ -556,7 +552,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) - goto give_sigsegv; + return -EFAULT; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; @@ -571,7 +567,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, */ err |= __copy_to_user(frame->retcode, &code, 8); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up registers for signal handler */ regs->sp = (unsigned long) frame; @@ -599,8 +595,4 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, #endif return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; } diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index b668efc18ea..1c22e0067fe 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -349,21 +349,21 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return -EFAULT; err = __put_user(sig, &frame->sig); if (err) - goto give_sigsegv; + return -EFAULT; err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); if (err) - goto give_sigsegv; + return -EFAULT; if (_NSIG_WORDS > 1) { err = __copy_to_user(&frame->extramask, &set->sig[1], sizeof(frame->extramask)); if (err) - goto give_sigsegv; + return -EFAULT; } if (current->mm->context.vdso) @@ -388,7 +388,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up registers for signal handler */ regs->sp = (unsigned long)frame; @@ -403,10 +403,6 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, regs->cs = __USER_CS; return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; } static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -420,14 +416,14 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return -EFAULT; err |= __put_user(sig, &frame->sig); err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) - goto give_sigsegv; + return -EFAULT; /* Create the ucontext. */ if (cpu_has_xsave) @@ -443,7 +439,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up to return from userspace. */ restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); @@ -463,7 +459,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up registers for signal handler */ regs->sp = (unsigned long)frame; @@ -478,10 +474,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->cs = __USER_CS; return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; } /* @@ -506,6 +498,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, else ret = __setup_frame(usig, ka, set, regs); + if (ret) { + force_sigsegv(sig, current); + return -EFAULT; + } + return ret; } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 43e6862fc7a..3b79e179ba3 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -215,12 +215,12 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return -EFAULT; if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, info); if (err) - goto give_sigsegv; + return -EFAULT; } /* Create the ucontext. */ @@ -248,11 +248,11 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { /* could use a vstub here */ - goto give_sigsegv; + return -EFAULT; } if (err) - goto give_sigsegv; + return -EFAULT; /* Set up registers for signal handler */ regs->di = sig; @@ -272,10 +272,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->cs = __USER_CS; return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; } /* @@ -297,6 +293,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, #endif ret = __setup_rt_frame(sig, ka, info, set, regs); + if (ret) { + force_sigsegv(sig, current); + return -EFAULT; + } + return ret; } -- cgit v1.2.3 From 2ba48e16e78216bb5b9fd08a088bfefda478df25 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 12 Sep 2008 17:02:53 -0700 Subject: x86: signal: remove unneeded err handling This patch eliminates unused or unneeded variable handling. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 11 ++++------- arch/x86/kernel/signal_32.c | 11 ++++------- arch/x86/kernel/signal_64.c | 5 ++--- 3 files changed, 10 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 5f42cfcc1c5..e47bed2440e 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -446,18 +446,15 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; - err |= __put_user(sig, &frame->sig); - if (err) + if (__put_user(sig, &frame->sig)) return -EFAULT; - err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); - if (err) + if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) return -EFAULT; if (_COMPAT_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - if (err) + if (__copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask))) return -EFAULT; } diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 1c22e0067fe..d433861a659 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -351,18 +351,15 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; - err = __put_user(sig, &frame->sig); - if (err) + if (__put_user(sig, &frame->sig)) return -EFAULT; - err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); - if (err) + if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) return -EFAULT; if (_NSIG_WORDS > 1) { - err = __copy_to_user(&frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - if (err) + if (__copy_to_user(&frame->extramask, &set->sig[1], + sizeof(frame->extramask))) return -EFAULT; } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 3b79e179ba3..a21c8519729 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -210,7 +210,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; if (save_i387_xstate(fp) < 0) - err |= -1; + return -EFAULT; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; @@ -218,8 +218,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return -EFAULT; if (ka->sa.sa_flags & SA_SIGINFO) { - err |= copy_siginfo_to_user(&frame->info, info); - if (err) + if (copy_siginfo_to_user(&frame->info, info)) return -EFAULT; } -- cgit v1.2.3 From e6babb6b7fed93c93f8fc5ef8ebd3a474fc2df3e Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 12 Sep 2008 17:03:31 -0700 Subject: x86: signal: introduce do_rt_sigreturn() introduce do_rt_sigreturn(), to collect common part of sys_rt_sigreturn(). No change in functionality intended. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 12 +++++++++--- arch/x86/kernel/signal_64.c | 11 ++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index d433861a659..da3cf3270f8 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -215,9 +215,8 @@ badframe: return 0; } -asmlinkage int sys_rt_sigreturn(unsigned long __unused) +static long do_rt_sigreturn(struct pt_regs *regs) { - struct pt_regs *regs = (struct pt_regs *)&__unused; struct rt_sigframe __user *frame; unsigned long ax; sigset_t set; @@ -243,10 +242,17 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) return ax; badframe: - signal_fault(regs, frame, "rt sigreturn"); + signal_fault(regs, frame, "rt_sigreturn"); return 0; } +asmlinkage int sys_rt_sigreturn(unsigned long __unused) +{ + struct pt_regs *regs = (struct pt_regs *)&__unused; + + return do_rt_sigreturn(regs); +} + /* * Set up a signal frame. */ diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index a21c8519729..bf77d4789a2 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -104,11 +104,11 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, return err; } -asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) +static long do_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; - sigset_t set; unsigned long ax; + sigset_t set; frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) @@ -131,10 +131,15 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) return ax; badframe: - signal_fault(regs, frame, "sigreturn"); + signal_fault(regs, frame, "rt_sigreturn"); return 0; } +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) +{ + return do_rt_sigreturn(regs); +} + /* * Set up a signal frame. */ -- cgit v1.2.3 From bee44f294efd8417f5e68553778a6cc957af1547 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 12 Sep 2008 19:42:35 +0900 Subject: x86: make GART to respect device's dma_mask about virtual mappings Currently, GART IOMMU ingores device's dma_mask when it does virtual mappings. So it could give a device a virtual address that the device can't access to. This patch fixes the above problem. Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 1b0c412566e..9972c42ac92 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -83,23 +83,34 @@ static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ static unsigned long alloc_iommu(struct device *dev, int size, - unsigned long align_mask) + unsigned long align_mask, u64 dma_mask) { unsigned long offset, flags; unsigned long boundary_size; unsigned long base_index; + unsigned long limit; base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), PAGE_SIZE) >> PAGE_SHIFT; boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, PAGE_SIZE) >> PAGE_SHIFT; + limit = iommu_device_max_index(iommu_pages, + DIV_ROUND_UP(iommu_bus_base, PAGE_SIZE), + dma_mask >> PAGE_SHIFT); + spin_lock_irqsave(&iommu_bitmap_lock, flags); - offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, + + if (limit <= next_bit) { + need_flush = 1; + next_bit = 0; + } + + offset = iommu_area_alloc(iommu_gart_bitmap, limit, next_bit, size, base_index, boundary_size, align_mask); - if (offset == -1) { + if (offset == -1 && next_bit) { need_flush = 1; - offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, + offset = iommu_area_alloc(iommu_gart_bitmap, limit, 0, size, base_index, boundary_size, align_mask); } @@ -228,12 +239,14 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) * Caller needs to check if the iommu is needed and flush. */ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, - size_t size, int dir, unsigned long align_mask) + size_t size, int dir, unsigned long align_mask, + u64 dma_mask) { unsigned long npages = iommu_num_pages(phys_mem, size); - unsigned long iommu_page = alloc_iommu(dev, npages, align_mask); + unsigned long iommu_page; int i; + iommu_page = alloc_iommu(dev, npages, align_mask, dma_mask); if (iommu_page == -1) { if (!nonforced_iommu(dev, phys_mem, size)) return phys_mem; @@ -263,7 +276,7 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) if (!need_iommu(dev, paddr, size)) return paddr; - bus = dma_map_area(dev, paddr, size, dir, 0); + bus = dma_map_area(dev, paddr, size, dir, 0, dma_get_mask(dev)); flush_gart(); return bus; @@ -314,6 +327,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, { struct scatterlist *s; int i; + u64 dma_mask = dma_get_mask(dev); #ifdef CONFIG_IOMMU_DEBUG printk(KERN_DEBUG "dma_map_sg overflow\n"); @@ -323,7 +337,8 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, unsigned long addr = sg_phys(s); if (nonforced_iommu(dev, addr, s->length)) { - addr = dma_map_area(dev, addr, s->length, dir, 0); + addr = dma_map_area(dev, addr, s->length, dir, 0, + dma_mask); if (addr == bad_dma_address) { if (i > 0) gart_unmap_sg(dev, sg, i, dir); @@ -345,14 +360,16 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, int nelems, struct scatterlist *sout, unsigned long pages) { - unsigned long iommu_start = alloc_iommu(dev, pages, 0); - unsigned long iommu_page = iommu_start; + unsigned long iommu_start; + unsigned long iommu_page; struct scatterlist *s; int i; + iommu_start = alloc_iommu(dev, pages, 0, dma_get_mask(dev)); if (iommu_start == -1) return -1; + iommu_page = iommu_start; for_each_sg(start, s, nelems, i) { unsigned long pages, addr; unsigned long phys_addr = s->dma_address; @@ -497,7 +514,7 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, align_mask = (1UL << get_order(size)) - 1; *dma_addr = dma_map_area(dev, __pa(vaddr), size, DMA_BIDIRECTIONAL, - align_mask); + align_mask, dma_mask); flush_gart(); if (*dma_addr != bad_dma_address) -- cgit v1.2.3 From f10ac8a232496bf9271cfc67c6eea432891f04a6 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 11 Sep 2008 23:08:47 +0900 Subject: x86: avoid unnecessary low zone allocation in Calgary's alloc_coherent x86's common alloc_coherent (dma_alloc_coherent in dma-mapping.h) sets up the gfp flag according to the device dma_mask but Calgary doesn't need it because of virtual mappings. This patch avoids unnecessary low zone allocation. Signed-off-by: FUJITA Tomonori Acked-by: Muli Ben-Yehuda Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-calgary_64.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 8415d92853c..fe7695e4caa 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -491,6 +491,8 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size, npages = size >> PAGE_SHIFT; order = get_order(size); + flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + /* alloc enough pages (and possibly more) */ ret = (void *)__get_free_pages(flag, order); if (!ret) -- cgit v1.2.3 From f6a32a36ab96016675cd414802904feb288d7899 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 11 Sep 2008 23:08:48 +0900 Subject: x86: gart alloc_coherent does virtual mapppings only when necessary gart alloc_coherent need to do virtual mapppings only when an allocated buffer is not DMA-capable for a device. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 9972c42ac92..9739d568209 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -505,15 +505,23 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, gfp_t flag) { void *vaddr; + dma_addr_t paddr; unsigned long align_mask; + u64 dma_mask = dma_alloc_coherent_mask(dev, flag); vaddr = (void *)__get_free_pages(flag | __GFP_ZERO, get_order(size)); if (!vaddr) return NULL; + paddr = virt_to_phys(vaddr); + if (is_buffer_dma_capable(dma_mask, paddr, size)) { + *dma_addr = paddr; + return vaddr; + } + align_mask = (1UL << get_order(size)) - 1; - *dma_addr = dma_map_area(dev, __pa(vaddr), size, DMA_BIDIRECTIONAL, + *dma_addr = dma_map_area(dev, paddr, size, DMA_BIDIRECTIONAL, align_mask, dma_mask); flush_gart(); -- cgit v1.2.3 From d7451fca18e2ec62641ae4bbfe946069f13765a3 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 12 Sep 2008 11:45:22 -0600 Subject: x86, hpet: SB600 - remove HPET resources from PCI device Prevent the HPET resources from appearing in PCI device 14.0 which confuses the PCI resource engine. Signed-off-by: Jordan Crouse Signed-off-by: Ingo Molnar --- arch/x86/pci/fixup.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'arch') diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 4bdaa590375..3c27a809393 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -511,3 +511,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size); + +/* + * SB600: Disable BAR1 on device 14.0 to avoid HPET resources from + * confusing the PCI engine: + */ +static void sb600_disable_hpet_bar(struct pci_dev *dev) +{ + u8 val; + + /* + * The SB600 and SB700 both share the same device + * ID, but the PM register 0x55 does something different + * for the SB700, so make sure we are dealing with the + * SB600 before touching the bit: + */ + + pci_read_config_byte(dev, 0x08, &val); + + if (val < 0x2F) { + outb(0x55, 0xCD6); + val = inb(0xCD7); + + /* Set bit 7 in PM register 0x55 */ + outb(0x55, 0xCD6); + outb(val | 0x80, 0xCD7); + } +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar); -- cgit v1.2.3 From 5649b7c30316a51792808422ac03ee825d26aa5e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 16 Sep 2008 09:29:09 +0200 Subject: x86: add DMI quirk for AMI BIOS which corrupts address 0xc000 during resume Alan Jenkins and Andy Wettstein reported a suspend/resume memory corruption bug and extensively documented it here: http://bugzilla.kernel.org/show_bug.cgi?id=11237 The bug is that the BIOS overwrites 1K of memory at 0xc000 physical, without registering it in e820 as reserved or giving the kernel any idea about this. Detect AMI BIOSen and reserve that 1K. We paint this bug around with a very broad brush (reserving that 1K on all AMI BIOS systems), as the bug was extremely hard to find and needed several weeks and lots of debugging and patching. The bug was found via the CONFIG_X86_CHECK_BIOS_CORRUPTION=y debug feature, if similar bugs are suspected then this feature can be enabled on other systems as well to scan low memory for corrupted memory. Reported-by: Alan Jenkins Reported-by: Andy Wettstein Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index ec7e56c1b98..3109ca37a67 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -729,6 +729,29 @@ void start_periodic_check_for_corruption(void) } #endif +static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) +{ + printk(KERN_NOTICE + "%s detected: BIOS corrupts 0xc000, working it around.\n", + d->ident); + + reserve_early(0xc000, 0xc400, "BIOS quirk"); + + return 0; +} + +/* List of systems that have known low memory corruption BIOS problems */ +static struct dmi_system_id __initdata bad_bios_dmi_table[] = { + { + .callback = dmi_low_memory_corruption, + .ident = "AMI BIOS", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + }, + }, + {} +}; + /* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures @@ -752,6 +775,8 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Command line: %s\n", boot_command_line); #endif + dmi_check_system(bad_bios_dmi_table); + early_cpu_init(); early_ioremap_init(); @@ -1037,3 +1062,5 @@ void __init setup_arch(char **cmdline_p) #endif #endif } + + -- cgit v1.2.3 From 1e22436eba84edfec9c25e5a25d09062c4f91ca9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 16 Sep 2008 09:58:02 +0200 Subject: x86: reserve low 64K on AMI and Phoenix BIOS boxen there's multiple reports about suspend/resume related low memory corruption in this bugzilla: http://bugzilla.kernel.org/show_bug.cgi?id=11237 the common pattern is that the corruption is caused by the BIOS, and that it affects some portion of the first 64K of physical RAM. So add a DMI quirk This will waste 64K RAM on 'good' systems too, but without knowing the exact nature of this BIOS memory corruption this is the safest approach. This might as well solve a wide range of suspend/resume breakages under Linux. Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 3109ca37a67..33719544a22 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -732,10 +732,10 @@ void start_periodic_check_for_corruption(void) static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) { printk(KERN_NOTICE - "%s detected: BIOS corrupts 0xc000, working it around.\n", + "%s detected: BIOS may corrupt low RAM, working it around.\n", d->ident); - reserve_early(0xc000, 0xc400, "BIOS quirk"); + reserve_early(0x0, 0x10000, "BIOS quirk"); return 0; } @@ -749,6 +749,13 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), }, }, + { + .callback = dmi_low_memory_corruption, + .ident = "Phoenix BIOS", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + }, + }, {} }; -- cgit v1.2.3 From fc38151947477596aa27df6c4306ad6008dc6711 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 16 Sep 2008 10:07:34 +0200 Subject: x86: add X86_RESERVE_LOW_64K This bugzilla: http://bugzilla.kernel.org/show_bug.cgi?id=11237 Documents a wide range of systems where the BIOS utilizes the first 64K of physical memory during suspend/resume and other hardware events. Currently we reserve this memory on all AMI and Phoenix BIOS systems. Life is too short to hunt subtle memory corruption problems like this, so we try to be robust by default. Still, allow this to be overriden: allow users who want that first 64K of memory to be available to the kernel disable the quirk, via CONFIG_X86_RESERVE_LOW_64K=n. Also, allow the early reservation to overlap with other early reservations. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 20 ++++++++++++++++++++ arch/x86/kernel/setup.c | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7820d447bb8..633f25dd9ee 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1089,6 +1089,26 @@ config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK Set whether the default state of memory_corruption_check is on or off. +config X86_RESERVE_LOW_64K + bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen" + default y + help + Reserve the first 64K of physical RAM on BIOSes that are known + to potentially corrupt that memory range. A numbers of BIOSes are + known to utilize this area during suspend/resume, so it must not + be used by the kernel. + + Set this to N if you are absolutely sure that you trust the BIOS + to get all its memory reservations and usages right. + + If you have doubts about the BIOS (e.g. suspend/resume does not + work or there's kernel crashes after certain hardware hotplug + events) and it's not AMI or Phoenix, then you might want to enable + X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical + corruption patterns. + + Say Y if unsure. + config MATH_EMULATION bool prompt "Math emulation" if X86_32 diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 33719544a22..786c1886ae5 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -735,13 +735,14 @@ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) "%s detected: BIOS may corrupt low RAM, working it around.\n", d->ident); - reserve_early(0x0, 0x10000, "BIOS quirk"); + reserve_early_overlap_ok(0x0, 0x10000, "BIOS quirk"); return 0; } /* List of systems that have known low memory corruption BIOS problems */ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { +#ifdef CONFIG_X86_RESERVE_LOW_64K { .callback = dmi_low_memory_corruption, .ident = "AMI BIOS", @@ -757,6 +758,7 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { }, }, {} +#endif }; /* -- cgit v1.2.3 From 998564789137921acae9e367b61c5a1dc295653d Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 16 Sep 2008 11:17:03 +0200 Subject: x86 setup: drop SWAP_DEV Impact: None (cleanup) SWAP_DEV is unused since 2.6.23-rc1. The comment was already incorrect since (at least) 2.6.12. Signed-off-by: Paul Bolle Signed-off-by: H. Peter Anvin --- arch/x86/boot/header.S | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index af86e431acf..b993062e9a5 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -30,7 +30,6 @@ SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ /* to be loaded */ ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ -SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ #ifndef SVGA_MODE #define SVGA_MODE ASK_VGA -- cgit v1.2.3 From 97fc0555dae8f4d437c8672c14d7191962429be4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 16 Sep 2008 15:09:26 -0700 Subject: x86 setup: handle more than 8 CPU flag words Checkin e38e05a85828dac23540cd007df5f20985388afc added a 9th CPU flag word, but didn't adjust the boot code to match. This patch adds the necessary boot code support. Note: due to a typo in an #if statement, it didn't trigger the #error this was supposed to do. Signed-off-by: H. Peter Anvin --- arch/x86/boot/cpu.c | 17 +++++++++-------- arch/x86/boot/mkcpustr.c | 38 +++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/cpu.c b/arch/x86/boot/cpu.c index 75298fe2edc..6ec6bb6e995 100644 --- a/arch/x86/boot/cpu.c +++ b/arch/x86/boot/cpu.c @@ -59,17 +59,18 @@ int validate_cpu(void) u32 e = err_flags[i]; for (j = 0; j < 32; j++) { - int n = (i << 5)+j; - if (*msg_strs < n) { + if (msg_strs[0] < i || + (msg_strs[0] == i && msg_strs[1] < j)) { /* Skip to the next string */ - do { - msg_strs++; - } while (*msg_strs); - msg_strs++; + msg_strs += 2; + while (*msg_strs++) + ; } if (e & 1) { - if (*msg_strs == n && msg_strs[1]) - printf("%s ", msg_strs+1); + if (msg_strs[0] == i && + msg_strs[1] == j && + msg_strs[2]) + printf("%s ", msg_strs+2); else printf("%d:%d ", i, j); } diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c index 4589caa3e9d..8ef60f20b37 100644 --- a/arch/x86/boot/mkcpustr.c +++ b/arch/x86/boot/mkcpustr.c @@ -17,31 +17,31 @@ #include "../kernel/cpu/capflags.c" -#if NCAPFLAGS > 8 -# error "Need to adjust the boot code handling of CPUID strings" -#endif - int main(void) { - int i; + int i, j; const char *str; printf("static const char x86_cap_strs[] = \n"); - for (i = 0; i < NCAPINTS*32; i++) { - str = x86_cap_flags[i]; - - if (i == NCAPINTS*32-1) { - /* The last entry must be unconditional; this - also consumes the compiler-added null character */ - if (!str) - str = ""; - printf("\t\"\\x%02x\"\"%s\"\n", i, str); - } else if (str) { - printf("#if REQUIRED_MASK%d & (1 << %d)\n" - "\t\"\\x%02x\"\"%s\\0\"\n" - "#endif\n", - i >> 5, i & 31, i, str); + for (i = 0; i < NCAPINTS; i++) { + for (j = 0; j < 32; j++) { + str = x86_cap_flags[i*32+j]; + + if (i == NCAPINTS-1 && j == 31) { + /* The last entry must be unconditional; this + also consumes the compiler-added null + character */ + if (!str) + str = ""; + printf("\t\"\\x%02x\\x%02x\"\"%s\"\n", + i, j, str); + } else if (str) { + printf("#if REQUIRED_MASK%d & (1 << %d)\n" + "\t\"\\x%02x\\x%02x\"\"%s\\0\"\n" + "#endif\n", + i, j, i, j, str); + } } } printf("\t;\n"); -- cgit v1.2.3 From 90f7d25c6b672137344f447a30a9159945ffea72 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Tue, 16 Sep 2008 11:27:30 -0700 Subject: x86: print DMI information in the oops trace in order to diagnose hard system specific issues, it's useful to have the system name in the oops (as provided by DMI) Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_32.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 0c3927accb0..7b9ee9f0963 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -160,6 +161,7 @@ void __show_registers(struct pt_regs *regs, int all) unsigned long d0, d1, d2, d3, d6, d7; unsigned long sp; unsigned short ss, gs; + const char *board; if (user_mode_vm(regs)) { sp = regs->sp; @@ -172,11 +174,15 @@ void __show_registers(struct pt_regs *regs, int all) } printk("\n"); - printk("Pid: %d, comm: %s %s (%s %.*s)\n", + + board = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!board) + board = ""; + printk("Pid: %d, comm: %s %s (%s %.*s) %s\n", task_pid_nr(current), current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); + init_utsname()->version, board); printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", (u16)regs->cs, regs->ip, regs->flags, -- cgit v1.2.3 From 279b0bbba2bb647348ad90e183b3960aa99eccfd Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 18 Sep 2008 23:55:27 -0700 Subject: x86: fix arch/x86/kernel/cpu/mtrr/main.c warning fix this warning reported by Andrew Morton: > arch/x86/kernel/cpu/mtrr/main.c: In function 'mtrr_bp_init': > arch/x86/kernel/cpu/mtrr/main.c:1170: warning: 'extra_remove_base' may be used uninitialized in this function the warning is bogus but the logic that prevents uninitialized use is a bit convoluted so simplify it all. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index b117d7f8a56..8a7c79234be 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1218,11 +1218,10 @@ static int __init mtrr_cleanup(unsigned address_bits) memset(range, 0, sizeof(range)); extra_remove_size = 0; - if (mtrr_tom2) { - extra_remove_base = 1 << (32 - PAGE_SHIFT); + extra_remove_base = 1 << (32 - PAGE_SHIFT); + if (mtrr_tom2) extra_remove_size = (mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base; - } nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base, extra_remove_size); range_sums = sum_ranges(range, nr_range); -- cgit v1.2.3 From dbcc112e3b5367e81a845b082933506b0ff1d1e2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 15:04:26 +0200 Subject: AMD IOMMU: check for invalid device pointers Currently AMD IOMMU code triggers a BUG_ON if NULL is passed as the device. This is inconsistent with other IOMMU implementations. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 01c68c38840..695e0fc41b1 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -645,6 +645,18 @@ static void set_device_domain(struct amd_iommu *iommu, * *****************************************************************************/ +/* + * This function checks if the driver got a valid device from the caller to + * avoid dereferencing invalid pointers. + */ +static bool check_device(struct device *dev) +{ + if (!dev || !dev->dma_mask) + return false; + + return true; +} + /* * In the dma_ops path we only have the struct device. This function * finds the corresponding IOMMU, the protection domain and the @@ -661,18 +673,19 @@ static int get_device_resources(struct device *dev, struct pci_dev *pcidev; u16 _bdf; - BUG_ON(!dev || dev->bus != &pci_bus_type || !dev->dma_mask); + *iommu = NULL; + *domain = NULL; + *bdf = 0xffff; + + if (dev->bus != &pci_bus_type) + return 0; pcidev = to_pci_dev(dev); _bdf = calc_devid(pcidev->bus->number, pcidev->devfn); /* device not translated by any IOMMU in the system? */ - if (_bdf > amd_iommu_last_bdf) { - *iommu = NULL; - *domain = NULL; - *bdf = 0xffff; + if (_bdf > amd_iommu_last_bdf) return 0; - } *bdf = amd_iommu_alias_table[_bdf]; @@ -826,6 +839,9 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, u16 devid; dma_addr_t addr; + if (!check_device(dev)) + return bad_dma_address; + get_device_resources(dev, &iommu, &domain, &devid); if (iommu == NULL || domain == NULL) @@ -860,7 +876,8 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr, struct protection_domain *domain; u16 devid; - if (!get_device_resources(dev, &iommu, &domain, &devid)) + if (!check_device(dev) || + !get_device_resources(dev, &iommu, &domain, &devid)) /* device not handled by any AMD IOMMU */ return; @@ -910,6 +927,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, phys_addr_t paddr; int mapped_elems = 0; + if (!check_device(dev)) + return 0; + get_device_resources(dev, &iommu, &domain, &devid); if (!iommu || !domain) @@ -967,7 +987,8 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, u16 devid; int i; - if (!get_device_resources(dev, &iommu, &domain, &devid)) + if (!check_device(dev) || + !get_device_resources(dev, &iommu, &domain, &devid)) return; spin_lock_irqsave(&domain->lock, flags); @@ -999,6 +1020,9 @@ static void *alloc_coherent(struct device *dev, size_t size, u16 devid; phys_addr_t paddr; + if (!check_device(dev)) + return NULL; + virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) return 0; @@ -1047,6 +1071,9 @@ static void free_coherent(struct device *dev, size_t size, struct protection_domain *domain; u16 devid; + if (!check_device(dev)) + return; + get_device_resources(dev, &iommu, &domain, &devid); if (!iommu || !domain) -- cgit v1.2.3 From 270cab2426cdc6307725e4f1f46ecf8ab8e69193 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 15:49:46 +0200 Subject: AMD IOMMU: move TLB flushing to the map/unmap helper functions This patch moves the invocation of the flushing functions to the map/unmap helpers because its common code in all dma_ops relevant mapping/unmapping code. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 695e0fc41b1..691e023695a 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -795,6 +795,9 @@ static dma_addr_t __map_single(struct device *dev, } address += offset; + if (unlikely(iommu_has_npcache(iommu))) + iommu_flush_pages(iommu, dma_dom->domain.id, address, size); + out: return address; } @@ -825,6 +828,8 @@ static void __unmap_single(struct amd_iommu *iommu, } dma_ops_free_addresses(dma_dom, dma_addr, pages); + + iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); } /* @@ -853,9 +858,6 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, if (addr == bad_dma_address) goto out; - if (iommu_has_npcache(iommu)) - iommu_flush_pages(iommu, domain->id, addr, size); - if (iommu->need_sync) iommu_completion_wait(iommu); @@ -885,8 +887,6 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr, __unmap_single(iommu, domain->priv, dma_addr, size, dir); - iommu_flush_pages(iommu, domain->id, dma_addr, size); - if (iommu->need_sync) iommu_completion_wait(iommu); @@ -948,9 +948,6 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, mapped_elems++; } else goto unmap; - if (iommu_has_npcache(iommu)) - iommu_flush_pages(iommu, domain->id, s->dma_address, - s->dma_length); } if (iommu->need_sync) @@ -996,8 +993,6 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, for_each_sg(sglist, s, nelems, i) { __unmap_single(iommu, domain->priv, s->dma_address, s->dma_length, dir); - iommu_flush_pages(iommu, domain->id, s->dma_address, - s->dma_length); s->dma_address = s->dma_length = 0; } @@ -1048,9 +1043,6 @@ static void *alloc_coherent(struct device *dev, size_t size, goto out; } - if (iommu_has_npcache(iommu)) - iommu_flush_pages(iommu, domain->id, *dma_addr, size); - if (iommu->need_sync) iommu_completion_wait(iommu); @@ -1082,7 +1074,6 @@ static void free_coherent(struct device *dev, size_t size, spin_lock_irqsave(&domain->lock, flags); __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); - iommu_flush_pages(iommu, domain->id, dma_addr, size); if (iommu->need_sync) iommu_completion_wait(iommu); -- cgit v1.2.3 From 2842e5bf3115193f05dc9dac20f940e7abf44c1a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 18 Sep 2008 15:23:43 +0200 Subject: x86: move GART TLB flushing options to generic code The GART currently implements the iommu=[no]fullflush command line parameters which influence its IO/TLB flushing strategy. This patch makes these parameters generic so that they can be used by the AMD IOMMU too. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-dma.c | 13 +++++++++++++ arch/x86/kernel/pci-gart_64.c | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0a1408abcc6..d2f2c0158dc 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -16,6 +16,15 @@ EXPORT_SYMBOL(dma_ops); static int iommu_sac_force __read_mostly; +/* + * If this is disabled the IOMMU will use an optimized flushing strategy + * of only flushing when an mapping is reused. With it true the GART is + * flushed for every mapping. Problem is that doing the lazy flush seems + * to trigger bugs with some popular PCI cards, in particular 3ware (but + * has been also also seen with Qlogic at least). + */ +int iommu_fullflush; + #ifdef CONFIG_IOMMU_DEBUG int panic_on_overflow __read_mostly = 1; int force_iommu __read_mostly = 1; @@ -171,6 +180,10 @@ static __init int iommu_setup(char *p) } if (!strncmp(p, "nomerge", 7)) iommu_merge = 0; + if (!strncmp(p, "fullflush", 8)) + iommu_fullflush = 1; + if (!strncmp(p, "nofullflush", 11)) + iommu_fullflush = 0; if (!strncmp(p, "forcesac", 8)) iommu_sac_force = 1; if (!strncmp(p, "allowdac", 8)) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 9739d568209..508ef470b27 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -45,15 +45,6 @@ static unsigned long iommu_pages; /* .. and in pages */ static u32 *iommu_gatt_base; /* Remapping table */ -/* - * If this is disabled the IOMMU will use an optimized flushing strategy - * of only flushing when an mapping is reused. With it true the GART is - * flushed for every mapping. Problem is that doing the lazy flush seems - * to trigger bugs with some popular PCI cards, in particular 3ware (but - * has been also also seen with Qlogic at least). - */ -int iommu_fullflush = 1; - /* Allocation bitmap for the remapping area: */ static DEFINE_SPINLOCK(iommu_bitmap_lock); /* Guarded by iommu_bitmap_lock: */ @@ -901,10 +892,6 @@ void __init gart_parse_options(char *p) #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; - if (!strncmp(p, "fullflush", 8)) - iommu_fullflush = 1; - if (!strncmp(p, "nofullflush", 11)) - iommu_fullflush = 0; if (!strncmp(p, "noagp", 5)) no_agp = 1; if (!strncmp(p, "noaperture", 10)) -- cgit v1.2.3 From 1c65577398589bb44ab0980f9b9d30804b48a5db Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 18:40:05 +0200 Subject: AMD IOMMU: implement lazy IO/TLB flushing The IO/TLB flushing on every unmaping operation is the most expensive part in AMD IOMMU code and not strictly necessary. It is sufficient to do the flush before any entries are reused. This is patch implements lazy IO/TLB flushing which does exactly this. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 26 ++++++++++++++++++++++---- arch/x86/kernel/amd_iommu_init.c | 7 ++++++- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 691e023695a..679f2a8e22e 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -203,6 +203,14 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid, return 0; } +/* Flush the whole IO/TLB for a given protection domain */ +static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid) +{ + u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; + + iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1); +} + /**************************************************************************** * * The functions below are used the create the page table mappings for @@ -386,14 +394,18 @@ static unsigned long dma_ops_alloc_addresses(struct device *dev, PAGE_SIZE) >> PAGE_SHIFT; limit = limit < size ? limit : size; - if (dom->next_bit >= limit) + if (dom->next_bit >= limit) { dom->next_bit = 0; + dom->need_flush = true; + } address = iommu_area_alloc(dom->bitmap, limit, dom->next_bit, pages, 0 , boundary_size, 0); - if (address == -1) + if (address == -1) { address = iommu_area_alloc(dom->bitmap, limit, 0, pages, 0, boundary_size, 0); + dom->need_flush = true; + } if (likely(address != -1)) { dom->next_bit = address + pages; @@ -553,6 +565,8 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu, dma_dom->bitmap[0] = 1; dma_dom->next_bit = 0; + dma_dom->need_flush = false; + /* Intialize the exclusion range if necessary */ if (iommu->exclusion_start && iommu->exclusion_start < dma_dom->aperture_size) { @@ -795,7 +809,10 @@ static dma_addr_t __map_single(struct device *dev, } address += offset; - if (unlikely(iommu_has_npcache(iommu))) + if (unlikely(dma_dom->need_flush && !iommu_fullflush)) { + iommu_flush_tlb(iommu, dma_dom->domain.id); + dma_dom->need_flush = false; + } else if (unlikely(iommu_has_npcache(iommu))) iommu_flush_pages(iommu, dma_dom->domain.id, address, size); out: @@ -829,7 +846,8 @@ static void __unmap_single(struct amd_iommu *iommu, dma_ops_free_addresses(dma_dom, dma_addr, pages); - iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); + if (iommu_fullflush) + iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); } /* diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index a69cc0f5204..f2fa8dc81be 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -995,6 +995,11 @@ int __init amd_iommu_init(void) else printk("disabled\n"); + if (iommu_fullflush) + printk(KERN_INFO "AMD IOMMU: IO/TLB flush on unmap enabled\n"); + else + printk(KERN_INFO "AMD IOMMU: Lazy IO/TLB flushing enabled\n"); + out: return ret; @@ -1057,7 +1062,7 @@ void __init amd_iommu_detect(void) static int __init parse_amd_iommu_options(char *str) { for (; *str; ++str) { - if (strcmp(str, "isolate") == 0) + if (strncmp(str, "isolate", 7) == 0) amd_iommu_isolate = 1; } -- cgit v1.2.3 From 5507eef835c9c941e69d6d96e4b43af23eeb4ac9 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 19:01:02 +0200 Subject: AMD IOMMU: add branch hints to completion wait checks This patch adds branch hints to the cecks if a completion_wait is necessary. The completion_waits in the mapping paths are unlikly because they will only happen on software implementations of AMD IOMMU which don't exists today or with lazy IO/TLB flushing when the allocator wraps around the address space. With lazy IO/TLB flushing the completion_wait in the unmapping path is unlikely too. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 679f2a8e22e..d743aa0adcc 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -876,7 +876,7 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, if (addr == bad_dma_address) goto out; - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); out: @@ -905,7 +905,7 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr, __unmap_single(iommu, domain->priv, dma_addr, size, dir); - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); spin_unlock_irqrestore(&domain->lock, flags); @@ -968,7 +968,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, goto unmap; } - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); out: @@ -1014,7 +1014,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, s->dma_address = s->dma_length = 0; } - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); spin_unlock_irqrestore(&domain->lock, flags); @@ -1061,7 +1061,7 @@ static void *alloc_coherent(struct device *dev, size_t size, goto out; } - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); out: @@ -1093,7 +1093,7 @@ static void free_coherent(struct device *dev, size_t size, __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); spin_unlock_irqrestore(&domain->lock, flags); -- cgit v1.2.3 From 6d4f343f84993eb0d5864c0823dc9babd171a33a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 19:18:02 +0200 Subject: AMD IOMMU: align alloc_coherent addresses properly The API definition for dma_alloc_coherent states that the bus address has to be aligned to the next power of 2 boundary greater than the allocation size. This is violated by AMD IOMMU so far and this patch fixes it. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index d743aa0adcc..15792ed082e 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -383,7 +383,8 @@ static unsigned long dma_mask_to_pages(unsigned long mask) */ static unsigned long dma_ops_alloc_addresses(struct device *dev, struct dma_ops_domain *dom, - unsigned int pages) + unsigned int pages, + unsigned long align_mask) { unsigned long limit = dma_mask_to_pages(*dev->dma_mask); unsigned long address; @@ -400,10 +401,10 @@ static unsigned long dma_ops_alloc_addresses(struct device *dev, } address = iommu_area_alloc(dom->bitmap, limit, dom->next_bit, pages, - 0 , boundary_size, 0); + 0 , boundary_size, align_mask); if (address == -1) { address = iommu_area_alloc(dom->bitmap, limit, 0, pages, - 0, boundary_size, 0); + 0, boundary_size, align_mask); dom->need_flush = true; } @@ -787,17 +788,22 @@ static dma_addr_t __map_single(struct device *dev, struct dma_ops_domain *dma_dom, phys_addr_t paddr, size_t size, - int dir) + int dir, + bool align) { dma_addr_t offset = paddr & ~PAGE_MASK; dma_addr_t address, start; unsigned int pages; + unsigned long align_mask = 0; int i; pages = iommu_num_pages(paddr, size); paddr &= PAGE_MASK; - address = dma_ops_alloc_addresses(dev, dma_dom, pages); + if (align) + align_mask = (1UL << get_order(size)) - 1; + + address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask); if (unlikely(address == bad_dma_address)) goto out; @@ -872,7 +878,7 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, return (dma_addr_t)paddr; spin_lock_irqsave(&domain->lock, flags); - addr = __map_single(dev, iommu, domain->priv, paddr, size, dir); + addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false); if (addr == bad_dma_address) goto out; @@ -959,7 +965,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, paddr = sg_phys(s); s->dma_address = __map_single(dev, iommu, domain->priv, - paddr, s->length, dir); + paddr, s->length, dir, false); if (s->dma_address) { s->dma_length = s->length; @@ -1053,7 +1059,7 @@ static void *alloc_coherent(struct device *dev, size_t size, spin_lock_irqsave(&domain->lock, flags); *dma_addr = __map_single(dev, iommu, domain->priv, paddr, - size, DMA_BIDIRECTIONAL); + size, DMA_BIDIRECTIONAL, true); if (*dma_addr == bad_dma_address) { free_pages((unsigned long)virt_addr, get_order(size)); -- cgit v1.2.3 From 335503e57b6b8de04cec5d27eb2c3d09ff98905b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 5 Sep 2008 14:29:07 +0200 Subject: AMD IOMMU: add event buffer allocation This patch adds the allocation of a event buffer for each AMD IOMMU in the system. The hardware will log events like device page faults or other errors to this buffer once this is enabled. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index f2fa8dc81be..41ce8d5d626 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -417,6 +417,30 @@ static void __init free_command_buffer(struct amd_iommu *iommu) free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); } +/* allocates the memory where the IOMMU will log its events to */ +static u8 * __init alloc_event_buffer(struct amd_iommu *iommu) +{ + u64 entry; + iommu->evt_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(EVT_BUFFER_SIZE)); + + if (iommu->evt_buf == NULL) + return NULL; + + entry = (u64)virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK; + memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET, + &entry, sizeof(entry)); + + iommu->evt_buf_size = EVT_BUFFER_SIZE; + + return iommu->evt_buf; +} + +static void __init free_event_buffer(struct amd_iommu *iommu) +{ + free_pages((unsigned long)iommu->evt_buf, get_order(EVT_BUFFER_SIZE)); +} + /* sets a specific bit in the device table entry. */ static void set_dev_entry_bit(u16 devid, u8 bit) { @@ -622,6 +646,7 @@ static int __init init_iommu_devices(struct amd_iommu *iommu) static void __init free_iommu_one(struct amd_iommu *iommu) { free_command_buffer(iommu); + free_event_buffer(iommu); iommu_unmap_mmio_space(iommu); } @@ -661,6 +686,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->cmd_buf) return -ENOMEM; + iommu->evt_buf = alloc_event_buffer(iommu); + if (!iommu->evt_buf) + return -ENOMEM; + init_iommu_from_pci(iommu); init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); -- cgit v1.2.3 From ee893c24edb8ebab9a3fb66566855572579ad616 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 8 Sep 2008 14:48:04 +0200 Subject: AMD IOMMU: save pci segment from ACPI tables This patch adds the pci_seg field to the amd_iommu structure and fills it with the corresponding value from the ACPI table. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 41ce8d5d626..b50234ef91e 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -676,6 +676,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) */ iommu->devid = h->devid; iommu->cap_ptr = h->cap_ptr; + iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; iommu->mmio_base = iommu_map_mmio_space(h->mmio_phys); if (!iommu->mmio_base) -- cgit v1.2.3 From 3eaf28a1cd2686aaa185b54d5a5e18e91b41f7f2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 8 Sep 2008 15:55:10 +0200 Subject: AMD IOMMU: save pci_dev instead of devid We need the pci_dev later anyways to enable MSI for the IOMMU hardware. So remove the devid pointing to the BDF and replace it with the pci_dev structure where the IOMMU is implemented. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index b50234ef91e..a7eb89d8923 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -242,9 +242,12 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit) /* Function to enable the hardware */ void __init iommu_enable(struct amd_iommu *iommu) { - printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at "); - print_devid(iommu->devid, 0); - printk(" cap 0x%hx\n", iommu->cap_ptr); + printk(KERN_INFO "AMD IOMMU: Enabling IOMMU " + "at %02x:%02x.%x cap 0x%hx\n", + iommu->dev->bus->number, + PCI_SLOT(iommu->dev->devfn), + PCI_FUNC(iommu->dev->devfn), + iommu->cap_ptr); iommu_feature_enable(iommu, CONTROL_IOMMU_EN); } @@ -511,15 +514,14 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) */ static void __init init_iommu_from_pci(struct amd_iommu *iommu) { - int bus = PCI_BUS(iommu->devid); - int dev = PCI_SLOT(iommu->devid); - int fn = PCI_FUNC(iommu->devid); int cap_ptr = iommu->cap_ptr; u32 range; - iommu->cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_CAP_HDR_OFFSET); + pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, + &iommu->cap); + pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET, + &range); - range = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET); iommu->first_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_FD(range)); iommu->last_device = calc_devid(MMIO_GET_BUS(range), @@ -674,7 +676,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) /* * Copy data from ACPI table entry to the iommu struct */ - iommu->devid = h->devid; + iommu->dev = pci_get_bus_and_slot(PCI_BUS(h->devid), h->devid & 0xff); + if (!iommu->dev) + return 1; + iommu->cap_ptr = h->cap_ptr; iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; @@ -695,6 +700,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); + pci_enable_device(iommu->dev); + return 0; } -- cgit v1.2.3 From a80dc3e0e0dc8393158de317d66ae0f345dc58f9 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 16:51:41 +0200 Subject: AMD IOMMU: add MSI interrupt support The AMD IOMMU can generate interrupts for various reasons. This patch adds the basic interrupt enabling infrastructure to the driver. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 + arch/x86/kernel/amd_iommu.c | 11 +++++ arch/x86/kernel/amd_iommu_init.c | 99 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 110 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed92864d132..39fd3f42696 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -553,6 +553,7 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT config AMD_IOMMU bool "AMD IOMMU support" select SWIOTLB + select PCI_MSI depends on X86_64 && PCI && ACPI help With this option you can enable support for AMD IOMMU hardware in diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 15792ed082e..0e494b9d5f2 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -49,6 +49,17 @@ static int iommu_has_npcache(struct amd_iommu *iommu) return iommu->cap & IOMMU_CAP_NPCACHE; } +/**************************************************************************** + * + * Interrupt handling functions + * + ****************************************************************************/ + +irqreturn_t amd_iommu_int_handler(int irq, void *data) +{ + return IRQ_NONE; +} + /**************************************************************************** * * IOMMU command queuing functions diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index a7eb89d8923..14a06464a69 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -515,17 +517,20 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) static void __init init_iommu_from_pci(struct amd_iommu *iommu) { int cap_ptr = iommu->cap_ptr; - u32 range; + u32 range, misc; pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, &iommu->cap); pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET, &range); + pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET, + &misc); iommu->first_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_FD(range)); iommu->last_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_LD(range)); + iommu->evt_msi_num = MMIO_MSI_NUM(misc); } /* @@ -696,6 +701,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->evt_buf) return -ENOMEM; + iommu->int_enabled = false; + init_iommu_from_pci(iommu); init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); @@ -741,6 +748,95 @@ static int __init init_iommu_all(struct acpi_table_header *table) return 0; } +/**************************************************************************** + * + * The following functions initialize the MSI interrupts for all IOMMUs + * in the system. Its a bit challenging because there could be multiple + * IOMMUs per PCI BDF but we can call pci_enable_msi(x) only once per + * pci_dev. + * + ****************************************************************************/ + +static int __init iommu_setup_msix(struct amd_iommu *iommu) +{ + struct amd_iommu *curr; + struct msix_entry entries[32]; /* only 32 supported by AMD IOMMU */ + int nvec = 0, i; + + list_for_each_entry(curr, &amd_iommu_list, list) { + if (curr->dev == iommu->dev) { + entries[nvec].entry = curr->evt_msi_num; + entries[nvec].vector = 0; + curr->int_enabled = true; + nvec++; + } + } + + if (pci_enable_msix(iommu->dev, entries, nvec)) { + pci_disable_msix(iommu->dev); + return 1; + } + + for (i = 0; i < nvec; ++i) { + int r = request_irq(entries->vector, amd_iommu_int_handler, + IRQF_SAMPLE_RANDOM, + "AMD IOMMU", + NULL); + if (r) + goto out_free; + } + + return 0; + +out_free: + for (i -= 1; i >= 0; --i) + free_irq(entries->vector, NULL); + + pci_disable_msix(iommu->dev); + + return 1; +} + +static int __init iommu_setup_msi(struct amd_iommu *iommu) +{ + int r; + struct amd_iommu *curr; + + list_for_each_entry(curr, &amd_iommu_list, list) { + if (curr->dev == iommu->dev) + curr->int_enabled = true; + } + + + if (pci_enable_msi(iommu->dev)) + return 1; + + r = request_irq(iommu->dev->irq, amd_iommu_int_handler, + IRQF_SAMPLE_RANDOM, + "AMD IOMMU", + NULL); + + if (r) { + pci_disable_msi(iommu->dev); + return 1; + } + + return 0; +} + +static int __init iommu_init_msi(struct amd_iommu *iommu) +{ + if (iommu->int_enabled) + return 0; + + if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSIX)) + return iommu_setup_msix(iommu); + else if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI)) + return iommu_setup_msi(iommu); + + return 1; +} + /**************************************************************************** * * The next functions belong to the third pass of parsing the ACPI @@ -862,6 +958,7 @@ static void __init enable_iommus(void) list_for_each_entry(iommu, &amd_iommu_list, list) { iommu_set_exclusion_range(iommu); + iommu_init_msi(iommu); iommu_enable(iommu); } } -- cgit v1.2.3 From 90008ee4b811c944455752dcb72b291a5ba81b53 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 16:41:05 +0200 Subject: AMD IOMMU: add event handling code This patch adds code for polling and printing out events generated by the AMD IOMMU. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 87 +++++++++++++++++++++++++++++++++++++++- arch/x86/kernel/amd_iommu_init.c | 1 - 2 files changed, 86 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0e494b9d5f2..0cb8fd2359f 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -55,9 +55,94 @@ static int iommu_has_npcache(struct amd_iommu *iommu) * ****************************************************************************/ +static void iommu_print_event(void *__evt) +{ + u32 *event = __evt; + int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; + int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; + int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; + int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; + u64 address = (u64)(((u64)event[3]) << 32) | event[2]; + + printk(KERN_ERR "AMD IOMMU: Event logged ["); + + switch (type) { + case EVENT_TYPE_ILL_DEV: + printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x " + "address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address, flags); + break; + case EVENT_TYPE_IO_FAULT: + printk("IO_PAGE_FAULT device=%02x:%02x.%x " + "domain=0x%04x address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + domid, address, flags); + break; + case EVENT_TYPE_DEV_TAB_ERR: + printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " + "address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address, flags); + break; + case EVENT_TYPE_PAGE_TAB_ERR: + printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x " + "domain=0x%04x address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + domid, address, flags); + break; + case EVENT_TYPE_ILL_CMD: + printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); + break; + case EVENT_TYPE_CMD_HARD_ERR: + printk("COMMAND_HARDWARE_ERROR address=0x%016llx " + "flags=0x%04x]\n", address, flags); + break; + case EVENT_TYPE_IOTLB_INV_TO: + printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x " + "address=0x%016llx]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address); + break; + case EVENT_TYPE_INV_DEV_REQ: + printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x " + "address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address, flags); + break; + default: + printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type); + } +} + +static void iommu_poll_events(struct amd_iommu *iommu) +{ + u32 head, tail; + unsigned long flags; + + spin_lock_irqsave(&iommu->lock, flags); + + head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); + tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); + + while (head != tail) { + iommu_print_event(iommu->evt_buf + head); + head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size; + } + + writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); + + spin_unlock_irqrestore(&iommu->lock, flags); +} + irqreturn_t amd_iommu_int_handler(int irq, void *data) { - return IRQ_NONE; + struct amd_iommu *iommu; + + list_for_each_entry(iommu, &amd_iommu_list, list) + iommu_poll_events(iommu); + + return IRQ_HANDLED; } /**************************************************************************** diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 14a06464a69..eed488892c0 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -32,7 +32,6 @@ /* * definitions for the ACPI scanning code */ -#define PCI_BUS(x) (((x) >> 8) & 0xff) #define IVRS_HEADER_LENGTH 48 #define ACPI_IVHD_TYPE 0x10 -- cgit v1.2.3 From 126c52be4b1d2eb667a1d140f0ceaff9d353f700 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 16:47:35 +0200 Subject: AMD IOMMU: enable event logging The code to log IOMMU events is in place now. So enable event logging with this patch. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index eed488892c0..1974b73fece 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -253,6 +253,13 @@ void __init iommu_enable(struct amd_iommu *iommu) iommu_feature_enable(iommu, CONTROL_IOMMU_EN); } +/* Function to enable IOMMU event logging and event interrupts */ +void __init iommu_enable_event_logging(struct amd_iommu *iommu) +{ + iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN); + iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); +} + /* * mapping and unmapping functions for the IOMMU MMIO space. Each AMD IOMMU in * the system has one. @@ -958,6 +965,7 @@ static void __init enable_iommus(void) list_for_each_entry(iommu, &amd_iommu_list, list) { iommu_set_exclusion_range(iommu); iommu_init_msi(iommu); + iommu_enable_event_logging(iommu); iommu_enable(iommu); } } -- cgit v1.2.3 From a22131a223147016041b5e5cd0ae5ab61ef4177e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 17:55:28 +0200 Subject: AMD IOMMU: allow IO page faults from devices There is a bit in the device entry to suppress all IO page faults generated by a device. This bit was set until now because there was no event logging. Now that there is event logging this patch allows IO page faults from devices to see them in the kernel log. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 1974b73fece..8c137598555 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -950,7 +950,6 @@ static void init_device_table(void) for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) { set_dev_entry_bit(devid, DEV_ENTRY_VALID); set_dev_entry_bit(devid, DEV_ENTRY_TRANSLATION); - set_dev_entry_bit(devid, DEV_ENTRY_NO_PAGE_FAULT); } } -- cgit v1.2.3 From b39ba6ad004a31bf2a08ba2b08c1e0f9b3530bb7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 18:40:46 +0200 Subject: AMD IOMMU: add dma_supported callback This function determines if the AMD IOMMU implementation is responsible for a given device. So the DMA layer can get this information from the driver. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0cb8fd2359f..a6a6f8ed1cf 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1204,6 +1204,30 @@ free_mem: free_pages((unsigned long)virt_addr, get_order(size)); } +/* + * This function is called by the DMA layer to find out if we can handle a + * particular device. It is part of the dma_ops. + */ +static int amd_iommu_dma_supported(struct device *dev, u64 mask) +{ + u16 bdf; + struct pci_dev *pcidev; + + /* No device or no PCI device */ + if (!dev || dev->bus != &pci_bus_type) + return 0; + + pcidev = to_pci_dev(dev); + + bdf = calc_devid(pcidev->bus->number, pcidev->devfn); + + /* Out of our scope? */ + if (bdf > amd_iommu_last_bdf) + return 0; + + return 1; +} + /* * The function for pre-allocating protection domains. * @@ -1247,6 +1271,7 @@ static struct dma_mapping_ops amd_iommu_dma_ops = { .unmap_single = unmap_single, .map_sg = map_sg, .unmap_sg = unmap_sg, + .dma_supported = amd_iommu_dma_supported, }; /* -- cgit v1.2.3 From bd60b735c658e6e8c656e89771d281bcfcf51279 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 10:24:48 +0200 Subject: AMD IOMMU: don't assign preallocated protection domains to devices In isolation mode the protection domains for the devices are preallocated and preassigned. This is bad if a device should be passed to a virtualization guest because the IOMMU code does not know if it is in use by a driver. This patch changes the code to assign the device to the preallocated domain only if there are dma mapping requests for it. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a6a6f8ed1cf..7c179144745 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -33,6 +33,10 @@ static DEFINE_RWLOCK(amd_iommu_devtable_lock); +/* A list of preallocated protection domains */ +static LIST_HEAD(iommu_pd_list); +static DEFINE_SPINLOCK(iommu_pd_list_lock); + /* * general struct to manage commands send to an IOMMU */ @@ -663,6 +667,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu, dma_dom->next_bit = 0; dma_dom->need_flush = false; + dma_dom->target_dev = 0xffff; /* Intialize the exclusion range if necessary */ if (iommu->exclusion_start && @@ -768,6 +773,33 @@ static bool check_device(struct device *dev) return true; } +/* + * In this function the list of preallocated protection domains is traversed to + * find the domain for a specific device + */ +static struct dma_ops_domain *find_protection_domain(u16 devid) +{ + struct dma_ops_domain *entry, *ret = NULL; + unsigned long flags; + + if (list_empty(&iommu_pd_list)) + return NULL; + + spin_lock_irqsave(&iommu_pd_list_lock, flags); + + list_for_each_entry(entry, &iommu_pd_list, list) { + if (entry->target_dev == devid) { + ret = entry; + list_del(&ret->list); + break; + } + } + + spin_unlock_irqrestore(&iommu_pd_list_lock, flags); + + return ret; +} + /* * In the dma_ops path we only have the struct device. This function * finds the corresponding IOMMU, the protection domain and the @@ -803,9 +835,11 @@ static int get_device_resources(struct device *dev, *iommu = amd_iommu_rlookup_table[*bdf]; if (*iommu == NULL) return 0; - dma_dom = (*iommu)->default_dom; *domain = domain_for_device(*bdf); if (*domain == NULL) { + dma_dom = find_protection_domain(*bdf); + if (!dma_dom) + dma_dom = (*iommu)->default_dom; *domain = &dma_dom->domain; set_device_domain(*iommu, *domain, *bdf); printk(KERN_INFO "AMD IOMMU: Using protection domain %d for " @@ -1257,10 +1291,9 @@ void prealloc_protection_domains(void) if (!dma_dom) continue; init_unity_mappings_for_device(dma_dom, devid); - set_device_domain(iommu, &dma_dom->domain, devid); - printk(KERN_INFO "AMD IOMMU: Allocated domain %d for device ", - dma_dom->domain.id); - print_devid(devid, 1); + dma_dom->target_dev = devid; + + list_add_tail(&dma_dom->list, &iommu_pd_list); } } -- cgit v1.2.3 From 38ddf41b198e21d3ecbe5752e875857b7ce7589e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 10:38:32 +0200 Subject: AMD IOMMU: some set_device_domain cleanups Remove some magic numbers and split the pte_root using standard functions. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 7c179144745..a34d8e915e3 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -739,12 +739,13 @@ static void set_device_domain(struct amd_iommu *iommu, u64 pte_root = virt_to_phys(domain->pt_root); - pte_root |= (domain->mode & 0x07) << 9; - pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | 2; + pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) + << DEV_ENTRY_MODE_SHIFT; + pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; write_lock_irqsave(&amd_iommu_devtable_lock, flags); - amd_iommu_dev_table[devid].data[0] = pte_root; - amd_iommu_dev_table[devid].data[1] = pte_root >> 32; + amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); + amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); amd_iommu_dev_table[devid].data[2] = domain->id; amd_iommu_pd_table[devid] = domain; -- cgit v1.2.3 From 13d9fead3daa0efa1b8bb6ae59650e4453b39128 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 10 Sep 2008 20:19:40 +0900 Subject: AMD IOMMU: avoid unnecessary low zone allocation in alloc_coherent x86's common alloc_coherent (dma_alloc_coherent in dma-mapping.h) sets up the gfp flag according to the device dma_mask but AMD IOMMU doesn't need it for devices that the IOMMU can do virtual mappings for. This patch avoids unnecessary low zone allocation. Signed-off-by: FUJITA Tomonori Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a34d8e915e3..e4866660463 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1173,6 +1173,9 @@ static void *alloc_coherent(struct device *dev, size_t size, if (!check_device(dev)) return NULL; + if (!get_device_resources(dev, &iommu, &domain, &devid)) + flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) return 0; @@ -1180,8 +1183,6 @@ static void *alloc_coherent(struct device *dev, size_t size, memset(virt_addr, 0, size); paddr = virt_to_phys(virt_addr); - get_device_resources(dev, &iommu, &domain, &devid); - if (!iommu || !domain) { *dma_addr = (dma_addr_t)paddr; return virt_addr; -- cgit v1.2.3 From c97ac5359e6897abe22770740294dda185bac30d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 10:59:15 +0200 Subject: AMD IOMMU: replace memset with __GFP_ZERO in alloc_coherent Remove the memset and use __GFP_ZERO at allocation time instead. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index e4866660463..f405a61f61f 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1176,11 +1176,11 @@ static void *alloc_coherent(struct device *dev, size_t size, if (!get_device_resources(dev, &iommu, &domain, &devid)) flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + flag |= __GFP_ZERO; virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) return 0; - memset(virt_addr, 0, size); paddr = virt_to_phys(virt_addr); if (!iommu || !domain) { -- cgit v1.2.3 From 6754086ce67c0a1f5d7eac612102368781e14588 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 12:17:00 +0200 Subject: AMD IOMMU: simplify dma_mask_to_pages The current calculation is very complicated. This patch replaces it with a much simpler version. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index f405a61f61f..db64482b179 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -472,8 +472,7 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom, ****************************************************************************/ static unsigned long dma_mask_to_pages(unsigned long mask) { - return (mask >> PAGE_SHIFT) + - (PAGE_ALIGN(mask & ~PAGE_MASK) >> PAGE_SHIFT); + return PAGE_ALIGN(mask) >> PAGE_SHIFT; } /* -- cgit v1.2.3 From d58befd3a0110c93d70756537b4d01d05a9e6e12 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 12:19:58 +0200 Subject: AMD IOMMU: free domain bitmap with its allocation order The amd_iommu_pd_alloc_bitmap is allocated with a calculated order and freed with order 1. This is not a bug since the calculated order always evaluates to 1, but its unclean code. So replace the 1 with the calculation in the release path. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 8c137598555..e60f4cd29eb 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1144,7 +1144,8 @@ out: return ret; free: - free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, 1); + free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, + get_order(MAX_DOMAIN_ID/8)); free_pages((unsigned long)amd_iommu_pd_table, get_order(rlookup_table_size)); -- cgit v1.2.3 From 199d0d501202f077fe647a5c14fe046b17abc46b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 16:45:59 +0200 Subject: AMD IOMMU: remove unnecessary cast to u64 in the init code The ctrl variable is only u32 and readl also returns a 32 bit value. So the cast to u64 is pointless. Remove it with this patch. Signed-off-by: Joerg Roedel 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 e60f4cd29eb..505fc04e896 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -235,7 +235,7 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit) { u32 ctrl; - ctrl = (u64)readl(iommu->mmio_base + MMIO_CONTROL_OFFSET); + ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET); ctrl &= ~(1 << bit); writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET); } -- cgit v1.2.3 From b514e55569855bbaab782a8ec073630ed4e99c68 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 17:14:27 +0200 Subject: AMD IOMMU: calculate IVHD size with a function The current calculation of the IVHD entry size is hard to read. So move this code to a seperate function to make it more clear what this calculation does. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 505fc04e896..80250e63bd0 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -296,6 +296,14 @@ static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu) * ****************************************************************************/ +/* + * This function calculates the length of a given IVHD entry + */ +static inline int ivhd_entry_length(u8 *ivhd) +{ + return 0x04 << (*ivhd >> 6); +} + /* * This function reads the last device id the IOMMU has to handle from the PCI * capability header for this IOMMU @@ -340,7 +348,7 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h) default: break; } - p += 0x04 << (*p >> 6); + p += ivhd_entry_length(p); } WARN_ON(p != end); @@ -641,7 +649,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, break; } - p += 0x04 << (e->type >> 6); + p += ivhd_entry_length(p); } } -- cgit v1.2.3 From 23c1713fe9e6ac886a4d44415298d0cbb2e83df2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 17:18:17 +0200 Subject: AMD IOMMU: use cmd_buf_size when freeing the command buffer The command buffer release function uses the CMD_BUF_SIZE macro for get_order. Replace this with iommu->cmd_buf_size which is more reliable about the actual size of the buffer. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 80250e63bd0..db0c83af44d 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -433,7 +433,8 @@ static u8 * __init alloc_command_buffer(struct amd_iommu *iommu) static void __init free_command_buffer(struct amd_iommu *iommu) { - free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); + free_pages((unsigned long)iommu->cmd_buf, + get_order(iommu->cmd_buf_size)); } /* allocates the memory where the IOMMU will log its events to */ -- cgit v1.2.3 From 832a90c30485117d65180cc9a8d9869c1b158570 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 18 Sep 2008 15:54:23 +0200 Subject: AMD IOMMU: use coherent_dma_mask in alloc_coherent The alloc_coherent implementation for AMD IOMMU currently uses *dev->dma_mask per default. This patch changes it to prefer dev->coherent_dma_mask if it is set. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index db64482b179..6f7b9744573 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -483,9 +483,10 @@ static unsigned long dma_mask_to_pages(unsigned long mask) static unsigned long dma_ops_alloc_addresses(struct device *dev, struct dma_ops_domain *dom, unsigned int pages, - unsigned long align_mask) + unsigned long align_mask, + u64 dma_mask) { - unsigned long limit = dma_mask_to_pages(*dev->dma_mask); + unsigned long limit = dma_mask_to_pages(dma_mask); unsigned long address; unsigned long size = dom->aperture_size >> PAGE_SHIFT; unsigned long boundary_size; @@ -919,7 +920,8 @@ static dma_addr_t __map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir, - bool align) + bool align, + u64 dma_mask) { dma_addr_t offset = paddr & ~PAGE_MASK; dma_addr_t address, start; @@ -933,7 +935,8 @@ static dma_addr_t __map_single(struct device *dev, if (align) align_mask = (1UL << get_order(size)) - 1; - address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask); + address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask, + dma_mask); if (unlikely(address == bad_dma_address)) goto out; @@ -997,10 +1000,13 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, struct protection_domain *domain; u16 devid; dma_addr_t addr; + u64 dma_mask; if (!check_device(dev)) return bad_dma_address; + dma_mask = *dev->dma_mask; + get_device_resources(dev, &iommu, &domain, &devid); if (iommu == NULL || domain == NULL) @@ -1008,7 +1014,8 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, return (dma_addr_t)paddr; spin_lock_irqsave(&domain->lock, flags); - addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false); + addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false, + dma_mask); if (addr == bad_dma_address) goto out; @@ -1080,10 +1087,13 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, struct scatterlist *s; phys_addr_t paddr; int mapped_elems = 0; + u64 dma_mask; if (!check_device(dev)) return 0; + dma_mask = *dev->dma_mask; + get_device_resources(dev, &iommu, &domain, &devid); if (!iommu || !domain) @@ -1095,7 +1105,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, paddr = sg_phys(s); s->dma_address = __map_single(dev, iommu, domain->priv, - paddr, s->length, dir, false); + paddr, s->length, dir, false, + dma_mask); if (s->dma_address) { s->dma_length = s->length; @@ -1168,6 +1179,7 @@ static void *alloc_coherent(struct device *dev, size_t size, struct protection_domain *domain; u16 devid; phys_addr_t paddr; + u64 dma_mask = dev->coherent_dma_mask; if (!check_device(dev)) return NULL; @@ -1187,10 +1199,13 @@ static void *alloc_coherent(struct device *dev, size_t size, return virt_addr; } + if (!dma_mask) + dma_mask = *dev->dma_mask; + spin_lock_irqsave(&domain->lock, flags); *dma_addr = __map_single(dev, iommu, domain->priv, paddr, - size, DMA_BIDIRECTIONAL, true); + size, DMA_BIDIRECTIONAL, true, dma_mask); if (*dma_addr == bad_dma_address) { free_pages((unsigned long)virt_addr, get_order(size)); -- cgit v1.2.3 From 69c010b24560be5ca7667e94a352183e60ed205e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 21:17:43 -0700 Subject: sparc32: Use PROM device probing for sun4m irq registers. Signed-off-by: David S. Miller --- arch/sparc/kernel/entry.S | 40 +++++------ arch/sparc/kernel/sun4m_irq.c | 163 ++++++++++++++---------------------------- 2 files changed, 74 insertions(+), 129 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 68689facaaa..faf9ccd9ef5 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -272,17 +272,18 @@ smp4m_ticker: */ maybe_smp4m_msg: GET_PROCESSOR4M_ID(o3) - set sun4m_interrupts, %l5 - ld [%l5], %o5 + sethi %hi(sun4m_irq_percpu), %l5 + sll %o3, 2, %o3 + or %l5, %lo(sun4m_irq_percpu), %o5 sethi %hi(0x40000000), %o2 - sll %o3, 12, %o3 ld [%o5 + %o3], %o1 - andcc %o1, %o2, %g0 + ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending + andcc %o3, %o2, %g0 be,a smp4m_ticker cmp %l7, 14 - st %o2, [%o5 + 0x4] + st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x40000000 WRITE_PAUSE - ld [%o5], %g0 + ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -300,16 +301,16 @@ linux_trap_ipi15_sun4m: SAVE_ALL sethi %hi(0x80000000), %o2 GET_PROCESSOR4M_ID(o0) - set sun4m_interrupts, %l5 - ld [%l5], %o5 - sll %o0, 12, %o0 - add %o5, %o0, %o5 - ld [%o5], %o3 + sethi %hi(sun4m_irq_percpu), %l5 + or %l5, %lo(sun4m_irq_percpu), %o5 + sll %o0, 2, %o0 + ld [%o5 + %o0], %o5 + ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending andcc %o3, %o2, %g0 be 1f ! Must be an NMI async memory error - st %o2, [%o5 + 4] + st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 WRITE_PAUSE - ld [%o5], %g0 + ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -323,12 +324,11 @@ linux_trap_ipi15_sun4m: 1: /* NMI async memory error handling. */ sethi %hi(0x80000000), %l4 - sethi %hi(0x4000), %o3 - sub %o5, %o0, %o5 - add %o5, %o3, %l5 - st %l4, [%l5 + 0xc] + sethi %hi(sun4m_irq_global), %o5 + ld [%o5 + %lo(sun4m_irq_global)], %l5 + st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000 WRITE_PAUSE - ld [%l5], %g0 + ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -337,9 +337,9 @@ linux_trap_ipi15_sun4m: WRITE_PAUSE call sun4m_nmi nop - st %l4, [%l5 + 0x8] + st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000 WRITE_PAUSE - ld [%l5], %g0 + ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending WRITE_PAUSE RESTORE_ALL diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 5b17146f0c1..39d40e96d39 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -41,53 +41,25 @@ #include "irq.h" -/* On the sun4m, just like the timers, we have both per-cpu and master - * interrupt registers. - */ - -/* These registers are used for sending/receiving irqs from/to - * different cpu's. - */ -struct sun4m_intreg_percpu { - unsigned int tbt; /* Interrupts still pending for this cpu. */ - - /* These next two registers are WRITE-ONLY and are only - * "on bit" sensitive, "off bits" written have NO affect. - */ - unsigned int clear; /* Clear this cpus irqs here. */ - unsigned int set; /* Set this cpus irqs here. */ - unsigned char space[PAGE_SIZE - 12]; +struct sun4m_irq_percpu { + u32 pending; + u32 clear; + u32 set; }; -/* - * djhr - * Actually the clear and set fields in this struct are misleading.. - * according to the SLAVIO manual (and the same applies for the SEC) - * the clear field clears bits in the mask which will ENABLE that IRQ - * the set field sets bits in the mask to DISABLE the IRQ. - * - * Also the undirected_xx address in the SLAVIO is defined as - * RESERVED and write only.. - * - * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor - * sun4m machines, for MP the layout makes more sense. - */ -struct sun4m_intregs { - struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS]; - unsigned int tbt; /* IRQ's that are still pending. */ - unsigned int irqs; /* Master IRQ bits. */ - - /* Again, like the above, two these registers are WRITE-ONLY. */ - unsigned int clear; /* Clear master IRQ's by setting bits here. */ - unsigned int set; /* Set master IRQ's by setting bits here. */ - - /* This register is both READ and WRITE. */ - unsigned int undirected_target; /* Which cpu gets undirected irqs. */ +struct sun4m_irq_global { + u32 pending; + u32 mask; + u32 mask_clear; + u32 mask_set; + u32 interrupt_target; }; -static unsigned long dummy; +/* Code in entry.S needs to get at these register mappings. */ +struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; +struct sun4m_irq_global __iomem *sun4m_irq_global; -struct sun4m_intregs *sun4m_interrupts; +static unsigned long dummy; unsigned long *irq_rcvreg = &dummy; /* Dave Redman (djhr@tadpole.co.uk) @@ -182,9 +154,9 @@ static void sun4m_disable_irq(unsigned int irq_nr) mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) - sun4m_interrupts->set = mask; + sbus_writel(mask, &sun4m_irq_global->mask_set); else - sun4m_interrupts->cpu_intregs[cpu].set = mask; + sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); local_irq_restore(flags); } @@ -201,13 +173,13 @@ static void sun4m_enable_irq(unsigned int irq_nr) mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) - sun4m_interrupts->clear = mask; + sbus_writel(mask, &sun4m_irq_global->mask_clear); else - sun4m_interrupts->cpu_intregs[cpu].clear = mask; + sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); local_irq_restore(flags); } else { local_irq_save(flags); - sun4m_interrupts->clear = SUN4M_INT_FLOPPY; + sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); local_irq_restore(flags); } } @@ -236,34 +208,30 @@ static unsigned long cpu_pil_to_imask[16] = { */ static void sun4m_disable_pil_irq(unsigned int pil) { - sun4m_interrupts->set = cpu_pil_to_imask[pil]; + sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set); } static void sun4m_enable_pil_irq(unsigned int pil) { - sun4m_interrupts->clear = cpu_pil_to_imask[pil]; + sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear); } #ifdef CONFIG_SMP static void sun4m_send_ipi(int cpu, int level) { - unsigned long mask; - - mask = sun4m_get_irqmask(level); - sun4m_interrupts->cpu_intregs[cpu].set = mask; + unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); } static void sun4m_clear_ipi(int cpu, int level) { - unsigned long mask; - - mask = sun4m_get_irqmask(level); - sun4m_interrupts->cpu_intregs[cpu].clear = mask; + unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); } static void sun4m_set_udt(int cpu) { - sun4m_interrupts->undirected_target = cpu; + sbus_writel(cpu, &sun4m_irq_global->interrupt_target); } #endif @@ -347,7 +315,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) for (i = 0; i < num_cpu_timers; i++) sbus_writel(0, &timers_percpu[i]->l14_limit); if (num_cpu_timers == 4) - sbus_writel(SUN4M_INT_E14, &sun4m_interrupts->set); + sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set); #ifdef CONFIG_SMP { @@ -372,62 +340,38 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) void __init sun4m_init_IRQ(void) { - int ie_node,i; - struct linux_prom_registers int_regs[PROMREG_MAX]; - int num_regs; - struct resource r; - int mid; - - local_irq_disable(); - if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 || - (ie_node = prom_getchild (ie_node)) == 0 || - (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) { - prom_printf("Cannot find /obio/interrupt node\n"); - prom_halt(); + struct device_node *dp = of_find_node_by_name(NULL, "interrupt"); + int len, i, mid, num_cpu_iregs; + const u32 *addr; + + if (!dp) { + printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n"); + return; } - num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs, - sizeof(int_regs)); - num_regs = (num_regs/sizeof(struct linux_prom_registers)); - - /* Apply the obio ranges to these registers. */ - prom_apply_obio_ranges(int_regs, num_regs); - - int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr; - int_regs[4].reg_size = int_regs[num_regs-1].reg_size; - int_regs[4].which_io = int_regs[num_regs-1].which_io; - for(ie_node = 1; ie_node < 4; ie_node++) { - int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE; - int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size; - int_regs[ie_node].which_io = int_regs[ie_node-1].which_io; + + addr = of_get_property(dp, "address", &len); + if (!addr) { + printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); + return; } - memset((char *)&r, 0, sizeof(struct resource)); - /* Map the interrupt registers for all possible cpus. */ - r.flags = int_regs[0].which_io; - r.start = int_regs[0].phys_addr; - sun4m_interrupts = (struct sun4m_intregs *) of_ioremap(&r, 0, - PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); + num_cpu_iregs = (len / sizeof(u32)) - 1; + for (i = 0; i < num_cpu_iregs; i++) { + sun4m_irq_percpu[i] = (void __iomem *) + (unsigned long) addr[i]; + } + sun4m_irq_global = (void __iomem *) + (unsigned long) addr[num_cpu_iregs]; - /* Map the system interrupt control registers. */ - r.flags = int_regs[4].which_io; - r.start = int_regs[4].phys_addr; - of_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); + local_irq_disable(); - sun4m_interrupts->set = ~SUN4M_INT_MASKALL; + sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set); for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) - sun4m_interrupts->cpu_intregs[mid].clear = ~0x17fff; - - if (!cpu_find_by_instance(1, NULL, NULL)) { - /* system wide interrupts go to cpu 0, this should always - * be safe because it is guaranteed to be fitted or OBP doesn't - * come up - * - * Not sure, but writing here on SLAVIO systems may puke - * so I don't do it unless there is more than 1 cpu. - */ - irq_rcvreg = (unsigned long *) - &sun4m_interrupts->undirected_target; - sun4m_interrupts->undirected_target = 0; + sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); + + if (num_cpu_iregs == 4) { + irq_rcvreg = (unsigned long *) &sun4m_irq_global->interrupt_target; + sbus_writel(0, &sun4m_irq_global->interrupt_target); } BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); @@ -442,5 +386,6 @@ void __init sun4m_init_IRQ(void) BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM); #endif + /* Cannot enable interrupts until OBP ticker is disabled. */ } -- cgit v1.2.3 From f5f1085720c4799dd1437f78e28e40c8dd557bba Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:04:55 -0700 Subject: sparc32: Use PROM infrastructure for probing and mapping sun4d timers. Signed-off-by: David S. Miller --- arch/sparc/include/asm/timer_32.h | 13 ---- arch/sparc/kernel/sun4d_irq.c | 139 +++++++++++++++++++++++--------------- 2 files changed, 83 insertions(+), 69 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 8906e987ef8..860a05ef456 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -35,19 +35,6 @@ struct sun4c_timer_info { #define SUN_TIMER_PHYSADDR 0xf3000000 -#define SUN4D_PRM_CNT_L 0x80000000 -#define SUN4D_PRM_CNT_LVALUE 0x7FFFFC00 - -struct sun4d_timer_regs { - volatile unsigned int l10_timer_limit; - volatile unsigned int l10_cur_countx; - volatile unsigned int l10_limit_noclear; - volatile unsigned int ctrl; - volatile unsigned int l10_cur_count; -}; - -extern struct sun4d_timer_regs *sun4d_timers; - extern __volatile__ unsigned int *master_l10_counter; extern __volatile__ unsigned int *master_l10_limit; diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 12541f51fcf..4156bf6657f 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -45,7 +45,16 @@ /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ /* #define DISTRIBUTE_IRQS */ -struct sun4d_timer_regs *sun4d_timers; +struct sun4d_timer_regs { + u32 l10_timer_limit; + u32 l10_cur_countx; + u32 l10_limit_noclear; + u32 ctrl; + u32 l10_cur_count; +}; + +static struct sun4d_timer_regs __iomem *sun4d_timers; + #define TIMER_IRQ 10 #define MAX_STATIC_ALLOC 4 @@ -446,8 +455,7 @@ void __init sun4d_distribute_irqs(void) static void sun4d_clear_clock_irq(void) { - volatile unsigned int clear_intr; - clear_intr = sun4d_timers->l10_timer_limit; + sbus_readl(&sun4d_timers->l10_timer_limit); } static void sun4d_clear_profile_irq(int cpu) @@ -460,71 +468,90 @@ static void sun4d_load_profile_irq(int cpu, unsigned int limit) bw_set_prof_limit(cpu, limit); } -static void __init sun4d_init_timers(irq_handler_t counter_fn) +static void __init sun4d_load_profile_irqs(void) { - int irq; - int cpu; - struct resource r; - int mid; + int cpu = 0, mid; - /* Map the User Timer registers. */ - memset(&r, 0, sizeof(r)); + while (!cpu_find_by_instance(cpu, NULL, &mid)) { + sun4d_load_profile_irq(mid >> 3, 0); + cpu++; + } +} + +static void __init sun4d_fixup_trap_table(void) +{ #ifdef CONFIG_SMP - r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT; -#else - r.start = CSR_BASE(0)+BW_TIMER_LIMIT; + unsigned long flags; + extern unsigned long lvl14_save[4]; + struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; + extern unsigned int real_irq_entry[], smp4d_ticker[]; + extern unsigned int patchme_maybe_smp_msg[]; + + /* Adjust so that we jump directly to smp4d_ticker */ + lvl14_save[2] += smp4d_ticker - real_irq_entry; + + /* For SMP we use the level 14 ticker, however the bootup code + * has copied the firmware's level 14 vector into the boot cpu's + * trap table, we must fix this now or we get squashed. + */ + local_irq_save(flags); + patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ + trap_table->inst_one = lvl14_save[0]; + trap_table->inst_two = lvl14_save[1]; + trap_table->inst_three = lvl14_save[2]; + trap_table->inst_four = lvl14_save[3]; + local_flush_cache_all(); + local_irq_restore(flags); #endif - r.flags = 0xf; - sun4d_timers = (struct sun4d_timer_regs *) of_ioremap(&r, 0, - PAGE_SIZE, "user timer"); +} + +static void __init sun4d_init_timers(irq_handler_t counter_fn) +{ + struct device_node *dp; + struct resource res; + const u32 *reg; + int err; + + dp = of_find_node_by_name(NULL, "cpu-unit"); + if (!dp) { + prom_printf("sun4d_init_timers: Unable to find cpu-unit\n"); + prom_halt(); + } + + /* Which cpu-unit we use is arbitrary, we can view the bootbus timer + * registers via any cpu's mapping. The first 'reg' property is the + * bootbus. + */ + reg = of_get_property(dp, "reg", NULL); + if (!reg) { + prom_printf("sun4d_init_timers: No reg property\n"); + prom_halt(); + } + + res.start = reg[1]; + res.end = reg[2] - 1; + res.flags = reg[0] & 0xff; + sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT, + sizeof(struct sun4d_timer_regs), "user timer"); + if (!sun4d_timers) { + prom_printf("sun4d_init_timers: Can't map timer regs\n"); + prom_halt(); + } + + sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); - sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4d_timers->l10_cur_count; master_l10_limit = &sun4d_timers->l10_timer_limit; - irq = request_irq(TIMER_IRQ, - counter_fn, + err = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); - if (irq) { - prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); + if (err) { + prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err); prom_halt(); } - - /* Enable user timer free run for CPU 0 in BW */ - /* bw_set_ctrl(0, bw_get_ctrl(0) | BW_CTRL_USER_TIMER); */ - - cpu = 0; - while (!cpu_find_by_instance(cpu, NULL, &mid)) { - sun4d_load_profile_irq(mid >> 3, 0); - cpu++; - } - -#ifdef CONFIG_SMP - { - unsigned long flags; - extern unsigned long lvl14_save[4]; - struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; - extern unsigned int real_irq_entry[], smp4d_ticker[]; - extern unsigned int patchme_maybe_smp_msg[]; - - /* Adjust so that we jump directly to smp4d_ticker */ - lvl14_save[2] += smp4d_ticker - real_irq_entry; - - /* For SMP we use the level 14 ticker, however the bootup code - * has copied the firmware's level 14 vector into the boot cpu's - * trap table, we must fix this now or we get squashed. - */ - local_irq_save(flags); - patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ - trap_table->inst_one = lvl14_save[0]; - trap_table->inst_two = lvl14_save[1]; - trap_table->inst_three = lvl14_save[2]; - trap_table->inst_four = lvl14_save[3]; - local_flush_cache_all(); - local_irq_restore(flags); - } -#endif + sun4d_load_profile_irqs(); + sun4d_fixup_trap_table(); } void __init sun4d_init_sbi_irq(void) -- cgit v1.2.3 From f8376e933c4e80663f6f66a5b5dd90390a0feba2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:05:25 -0700 Subject: sparc32: Remove some SMP ifdefs in sun4d_irq.c Always do the sbus_tid[] handling. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4d_irq.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 4156bf6657f..6e3bf6eee54 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -60,9 +60,7 @@ static struct sun4d_timer_regs __iomem *sun4d_timers; #define MAX_STATIC_ALLOC 4 extern struct irqaction static_irqaction[MAX_STATIC_ALLOC]; extern int static_irq_count; -#ifdef CONFIG_SMP static unsigned char sbus_tid[32]; -#endif static struct irqaction *irq_action[NR_IRQS]; extern spinlock_t irq_action_lock; @@ -81,9 +79,9 @@ static int sbus_to_pil[] = { }; static int nsbi; -#ifdef CONFIG_SMP + +/* Exported for sun4d_smp.c */ DEFINE_SPINLOCK(sun4d_imsk_lock); -#endif int show_sun4d_interrupts(struct seq_file *p, void *v) { @@ -349,36 +347,28 @@ out: static void sun4d_disable_irq(unsigned int irq) { -#ifdef CONFIG_SMP int tid = sbus_tid[(irq >> 5) - 1]; unsigned long flags; -#endif - if (irq < NR_IRQS) return; -#ifdef CONFIG_SMP + if (irq < NR_IRQS) + return; + spin_lock_irqsave(&sun4d_imsk_lock, flags); cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7])); spin_unlock_irqrestore(&sun4d_imsk_lock, flags); -#else - cc_set_imsk(cc_get_imsk() | (1 << sbus_to_pil[(irq >> 2) & 7])); -#endif } static void sun4d_enable_irq(unsigned int irq) { -#ifdef CONFIG_SMP int tid = sbus_tid[(irq >> 5) - 1]; unsigned long flags; -#endif - if (irq < NR_IRQS) return; -#ifdef CONFIG_SMP + if (irq < NR_IRQS) + return; + spin_lock_irqsave(&sun4d_imsk_lock, flags); cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7])); spin_unlock_irqrestore(&sun4d_imsk_lock, flags); -#else - cc_set_imsk(cc_get_imsk() & ~(1 << sbus_to_pil[(irq >> 2) & 7])); -#endif } #ifdef CONFIG_SMP @@ -557,6 +547,11 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) void __init sun4d_init_sbi_irq(void) { struct device_node *dp; + int target_cpu = 0; + +#ifdef CONFIG_SMP + target_cpu = boot_cpu_id; +#endif nsbi = 0; for_each_node_by_name(dp, "sbi") @@ -571,14 +566,9 @@ void __init sun4d_init_sbi_irq(void) int board = of_getintprop_default(dp, "board#", 0); unsigned int mask; -#ifdef CONFIG_SMP - { - extern unsigned char boot_cpu_id; - - set_sbi_tid(devid, boot_cpu_id << 3); - sbus_tid[board] = boot_cpu_id; - } -#endif + set_sbi_tid(devid, target_cpu << 3); + sbus_tid[board] = target_cpu; + /* Get rid of pending irqs from PROM */ mask = acquire_sbi(devid, 0xffffffff); if (mask) { -- cgit v1.2.3 From a73554aedb8f69bd2024cbbf74980582bb91afb4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:07:40 -0700 Subject: sparc32: Remove #if 0'd code from sun4c_irq.c Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4c_irq.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 722d2516f28..5602972f357 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -36,11 +36,6 @@ #include #include -#if 0 -static struct resource sun4c_timer_eb = { "sun4c_timer" }; -static struct resource sun4c_intr_eb = { "sun4c_intr" }; -#endif - /* * Bit field defines for the interrupt registers on various * Sparc machines. @@ -173,10 +168,6 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) prom_halt(); } -#if 0 - /* This does not work on 4/330 */ - sun4c_enable_irq(10); -#endif claim_ticker14(NULL, PROFILE_IRQ, 0); } -- cgit v1.2.3 From 1de937a536ea1a132d22dc198a9e07d208d40a29 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:07:56 -0700 Subject: sparc32: Call sun4m_clear_profile_irq() directly from sun4m_smp.c This is the only use of the clear_profile_irq() btfixup entry, which just eats up lots of dead space on other platform types. A subsequent commit will delete the other implementations and the btfixup entry as well. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4m_irq.c | 3 ++- arch/sparc/kernel/sun4m_smp.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 39d40e96d39..8e1ecc6def2 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -264,7 +264,8 @@ static void sun4m_clear_clock_irq(void) sbus_readl(&timers_global->l10_limit); } -static void sun4m_clear_profile_irq(int cpu) +/* Exported for sun4m_smp.c */ +void sun4m_clear_profile_irq(int cpu) { sbus_readl(&timers_percpu[cpu]->l14_limit); } diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index a14a76ac7f3..e3c0be17729 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -313,6 +313,8 @@ void smp4m_cross_call_irq(void) ccall_info.processors_out[i] = 1; } +extern void sun4m_clear_profile_irq(int cpu); + void smp4m_percpu_timer_interrupt(struct pt_regs *regs) { struct pt_regs *old_regs; @@ -320,7 +322,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) old_regs = set_irq_regs(regs); - clear_profile_irq(cpu); + sun4m_clear_profile_irq(cpu); profile_tick(CPU_PROFILING); -- cgit v1.2.3 From 76954261ba907950cb5216e5c3075b5ba03c1a6b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:07:06 -0700 Subject: sparc32: Kill clear_profile_irq btfixup entry. Unused. Signed-off-by: David S. Miller --- arch/sparc/kernel/irq.h | 6 ------ arch/sparc/kernel/pcic.c | 6 ------ arch/sparc/kernel/sun4c_irq.c | 6 ------ arch/sparc/kernel/sun4d_irq.c | 6 ------ arch/sparc/kernel/sun4m_irq.c | 1 - 5 files changed, 25 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 32ef3ebd0a8..db751388153 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -13,7 +13,6 @@ BTFIXUPDEF_CALL(void, enable_irq, unsigned int) BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int) BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int) BTFIXUPDEF_CALL(void, clear_clock_irq, void) -BTFIXUPDEF_CALL(void, clear_profile_irq, int) BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) static inline void __disable_irq(unsigned int irq) @@ -41,11 +40,6 @@ static inline void clear_clock_irq(void) BTFIXUP_CALL(clear_clock_irq)(); } -static inline void clear_profile_irq(int irq) -{ - BTFIXUP_CALL(clear_profile_irq)(irq); -} - static inline void load_profile_irq(int cpu, int limit) { BTFIXUP_CALL(load_profile_irq)(cpu, limit); diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index e5950b03df1..462584e55fb 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -897,11 +897,6 @@ static void pcic_enable_irq(unsigned int irq_nr) local_irq_restore(flags); } -static void pcic_clear_profile_irq(int cpu) -{ - printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); -} - static void pcic_load_profile_irq(int cpu, unsigned int limit) { printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); @@ -927,7 +922,6 @@ void __init sun4m_pci_init_IRQ(void) BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); } diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 5602972f357..6f28a13829c 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -131,11 +131,6 @@ static void sun4c_clear_clock_irq(void) clear_intr = sun4c_timers->timer_limit10; } -static void sun4c_clear_profile_irq(int cpu) -{ - /* Errm.. not sure how to do this.. */ -} - static void sun4c_load_profile_irq(int cpu, unsigned int limit) { /* Errm.. not sure how to do this.. */ @@ -204,7 +199,6 @@ void __init sun4c_init_IRQ(void) BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); sparc_init_timers = sun4c_init_timers; #ifdef CONFIG_SMP diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 6e3bf6eee54..d376d380ac0 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -448,11 +448,6 @@ static void sun4d_clear_clock_irq(void) sbus_readl(&sun4d_timers->l10_timer_limit); } -static void sun4d_clear_profile_irq(int cpu) -{ - bw_get_prof_limit(cpu); -} - static void sun4d_load_profile_irq(int cpu, unsigned int limit) { bw_set_prof_limit(cpu, limit); @@ -585,7 +580,6 @@ void __init sun4d_init_IRQ(void) BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); sparc_init_timers = sun4d_init_timers; #ifdef CONFIG_SMP diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 8e1ecc6def2..ab309eca09c 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -379,7 +379,6 @@ void __init sun4m_init_IRQ(void) BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); sparc_init_timers = sun4m_init_timers; #ifdef CONFIG_SMP -- cgit v1.2.3 From b218fa0e9c2ad94b4e9ab5517a9210f9fa3745e2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:08:26 -0700 Subject: sparc32: Stop calling claim_ticker14() from sun4c_irq.c Since the first argument is always NULL, the only side effect is to disable the PROFILE_IRQ, so just do that directly. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4c_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 6f28a13829c..ae3149ecaec 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -163,7 +163,7 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) prom_halt(); } - claim_ticker14(NULL, PROFILE_IRQ, 0); + sun4c_disable_irq(PROFILE_IRQ); } #ifdef CONFIG_SMP -- cgit v1.2.3 From 5ff0d55f93f8119b71b33d4c444cf5105d4c1d12 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 9 Sep 2008 00:04:35 -0700 Subject: sparc32: Delete claim_ticker14(). No more users. Signed-off-by: David S. Miller --- arch/sparc/kernel/tick14.c | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index 77a4f3aeec6..138bbf5f872 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c @@ -1,30 +1,12 @@ /* tick14.c - * linux/arch/sparc/kernel/tick14.c * * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) * * This file handles the Sparc specific level14 ticker * This is really useful for profiling OBP uses it for keyboard * aborts and other stuff. - * - * */ -#include -#include #include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "irq.h" extern unsigned long lvl14_save[5]; static unsigned long *linux_lvl14 = NULL; @@ -55,31 +37,3 @@ void install_obp_ticker(void) linux_lvl14[2] = obp_lvl14[2]; linux_lvl14[3] = obp_lvl14[3]; } - -void claim_ticker14(irq_handler_t handler, - int irq_nr, unsigned int timeout ) -{ - int cpu = smp_processor_id(); - - /* first we copy the obp handler instructions - */ - __disable_irq(irq_nr); - if (!handler) - return; - - linux_lvl14 = (unsigned long *)lvl14_save[4]; - obp_lvl14[0] = linux_lvl14[0]; - obp_lvl14[1] = linux_lvl14[1]; - obp_lvl14[2] = linux_lvl14[2]; - obp_lvl14[3] = linux_lvl14[3]; - - if (!request_irq(irq_nr, - handler, - (IRQF_DISABLED | SA_STATIC_ALLOC), - "counter14", - NULL)) { - install_linux_ticker(); - load_profile_irq(cpu, timeout); - __enable_irq(irq_nr); - } -} -- cgit v1.2.3 From 45bb5a7cbfa28dedc07730d6ecedbd574faf5459 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:43:48 -0700 Subject: sparc32: Use PROM device probing for sun4c interrupt register. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4c_irq.c | 47 +++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index ae3149ecaec..8033132eda8 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -59,7 +59,7 @@ * * so don't go making it static, like I tried. sigh. */ -unsigned char *interrupt_enable = NULL; +unsigned char __iomem *interrupt_enable = NULL; static void sun4c_disable_irq(unsigned int irq_nr) { @@ -68,7 +68,7 @@ static void sun4c_disable_irq(unsigned int irq_nr) local_irq_save(flags); irq_nr &= (NR_IRQS - 1); - current_mask = *interrupt_enable; + current_mask = sbus_readb(interrupt_enable); switch(irq_nr) { case 1: new_mask = ((current_mask) & (~(SUN4C_INT_E1))); @@ -86,7 +86,7 @@ static void sun4c_disable_irq(unsigned int irq_nr) local_irq_restore(flags); return; } - *interrupt_enable = new_mask; + sbus_writeb(new_mask, interrupt_enable); local_irq_restore(flags); } @@ -97,7 +97,7 @@ static void sun4c_enable_irq(unsigned int irq_nr) local_irq_save(flags); irq_nr &= (NR_IRQS - 1); - current_mask = *interrupt_enable; + current_mask = sbus_readb(interrupt_enable); switch(irq_nr) { case 1: new_mask = ((current_mask) | SUN4C_INT_E1); @@ -115,7 +115,7 @@ static void sun4c_enable_irq(unsigned int irq_nr) local_irq_restore(flags); return; } - *interrupt_enable = new_mask; + sbus_writeb(new_mask, interrupt_enable); local_irq_restore(flags); } @@ -172,27 +172,22 @@ static void sun4c_nop(void) {} void __init sun4c_init_IRQ(void) { - struct linux_prom_registers int_regs[2]; - int ie_node; - struct resource phyres; - - ie_node = prom_searchsiblings (prom_getchild(prom_root_node), - "interrupt-enable"); - if(ie_node == 0) - panic("Cannot find /interrupt-enable node"); - - /* Depending on the "address" property is bad news... */ - interrupt_enable = NULL; - if (prom_getproperty(ie_node, "reg", (char *) int_regs, - sizeof(int_regs)) != -1) { - memset(&phyres, 0, sizeof(struct resource)); - phyres.flags = int_regs[0].which_io; - phyres.start = int_regs[0].phys_addr; - interrupt_enable = (char *) of_ioremap(&phyres, 0, - int_regs[0].reg_size, "sun4c_intr"); + struct device_node *dp; + const u32 *addr; + + dp = of_find_node_by_name(NULL, "interrupt-enable"); + if (!dp) { + prom_printf("sun4c_init_IRQ: Unable to find interrupt-enable\n"); + prom_halt(); + } + + addr = of_get_property(dp, "address", NULL); + if (!addr) { + prom_printf("sun4c_init_IRQ: No address property\n"); + prom_halt(); } - if (!interrupt_enable) - panic("Cannot map interrupt_enable"); + + interrupt_enable = (void __iomem *) (unsigned long) addr[0]; BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); @@ -206,6 +201,6 @@ void __init sun4c_init_IRQ(void) BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP); #endif - *interrupt_enable = (SUN4C_INT_ENABLE); + sbus_writeb(SUN4C_INT_ENABLE, interrupt_enable); /* Cannot enable interrupts until OBP ticker is disabled. */ } -- cgit v1.2.3 From 8bd8deead7f00006781c366887da8cf6a02c69ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:47:43 -0700 Subject: sparc32: Use PROM device probing for sun4c timers. Signed-off-by: David S. Miller --- arch/sparc/include/asm/timer_32.h | 24 ---------------- arch/sparc/kernel/sun4c_irq.c | 59 ++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 44 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 860a05ef456..351f257eec0 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -11,30 +11,6 @@ #include /* For SUN4M_NCPUS */ #include -/* Timer structures. The interrupt timer has two properties which - * are the counter (which is handled in do_timer in sched.c) and the limit. - * This limit is where the timer's counter 'wraps' around. Oddly enough, - * the sun4c timer when it hits the limit wraps back to 1 and not zero - * thus when calculating the value at which it will fire a microsecond you - * must adjust by one. Thanks SUN for designing such great hardware ;( - */ - -/* Note that I am only going to use the timer that interrupts at - * Sparc IRQ 10. There is another one available that can fire at - * IRQ 14. Currently it is left untouched, we keep the PROM's limit - * register value and let the prom take these interrupts. This allows - * L1-A to work. - */ - -struct sun4c_timer_info { - __volatile__ unsigned int cur_count10; - __volatile__ unsigned int timer_limit10; - __volatile__ unsigned int cur_count14; - __volatile__ unsigned int timer_limit14; -}; - -#define SUN_TIMER_PHYSADDR 0xf3000000 - extern __volatile__ unsigned int *master_l10_counter; extern __volatile__ unsigned int *master_l10_limit; diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 8033132eda8..92096ba31d5 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -119,16 +119,18 @@ static void sun4c_enable_irq(unsigned int irq_nr) local_irq_restore(flags); } -#define TIMER_IRQ 10 /* Also at level 14, but we ignore that one. */ -#define PROFILE_IRQ 14 /* Level14 ticker.. used by OBP for polling */ +struct sun4c_timer_info { + u32 l10_count; + u32 l10_limit; + u32 l14_count; + u32 l14_limit; +}; -volatile struct sun4c_timer_info *sun4c_timers; +static struct sun4c_timer_info __iomem *sun4c_timers; static void sun4c_clear_clock_irq(void) { - volatile unsigned int clear_intr; - - clear_intr = sun4c_timers->timer_limit10; + sbus_readl(&sun4c_timers->l10_limit); } static void sun4c_load_profile_irq(int cpu, unsigned int limit) @@ -138,32 +140,49 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit) static void __init sun4c_init_timers(irq_handler_t counter_fn) { - int irq; + const struct linux_prom_irqs *irq; + struct device_node *dp; + const u32 *addr; + int err; - /* Map the Timer chip, this is implemented in hardware inside - * the cache chip on the sun4c. - */ - sun4c_timers = ioremap(SUN_TIMER_PHYSADDR, - sizeof(struct sun4c_timer_info)); + dp = of_find_node_by_name(NULL, "counter-timer"); + if (!dp) { + prom_printf("sun4c_init_timers: Unable to find counter-timer\n"); + prom_halt(); + } + + addr = of_get_property(dp, "address", NULL); + if (!addr) { + prom_printf("sun4c_init_timers: No address property\n"); + prom_halt(); + } + + sun4c_timers = (void __iomem *) (unsigned long) addr[0]; + + irq = of_get_property(dp, "intr", NULL); + if (!irq) { + prom_printf("sun4c_init_timers: No intr property\n"); + prom_halt(); + } /* Have the level 10 timer tick at 100HZ. We don't touch the * level 14 timer limit since we are letting the prom handle * them until we have a real console driver so L1-A works. */ - sun4c_timers->timer_limit10 = (((1000000/HZ) + 1) << 10); - master_l10_counter = &sun4c_timers->cur_count10; - master_l10_limit = &sun4c_timers->timer_limit10; + sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); + + master_l10_counter = &sun4c_timers->l10_count; + master_l10_limit = &sun4c_timers->l10_limit; - irq = request_irq(TIMER_IRQ, - counter_fn, + err = request_irq(irq[0].pri, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); - if (irq) { - prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); + if (err) { + prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); prom_halt(); } - sun4c_disable_irq(PROFILE_IRQ); + sun4c_disable_irq(irq[1].pri); } #ifdef CONFIG_SMP -- cgit v1.2.3 From c7e606a8f863b2119176674610618dad3d80a16d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:48:04 -0700 Subject: sparc32: Delete master_l10_limit. It is only set, never used. Signed-off-by: David S. Miller --- arch/sparc/include/asm/timer_32.h | 1 - arch/sparc/kernel/sun4c_irq.c | 1 - arch/sparc/kernel/sun4d_irq.c | 1 - arch/sparc/kernel/sun4m_irq.c | 1 - arch/sparc/kernel/time.c | 1 - 5 files changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 351f257eec0..2ec030ef381 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -12,7 +12,6 @@ #include extern __volatile__ unsigned int *master_l10_counter; -extern __volatile__ unsigned int *master_l10_limit; /* FIXME: Make do_[gs]ettimeofday btfixup calls */ BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv) diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 92096ba31d5..5dc8a576948 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -172,7 +172,6 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); master_l10_counter = &sun4c_timers->l10_count; - master_l10_limit = &sun4c_timers->l10_limit; err = request_irq(irq[0].pri, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index d376d380ac0..d3cb76ce418 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -526,7 +526,6 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); master_l10_counter = &sun4d_timers->l10_cur_count; - master_l10_limit = &sun4d_timers->l10_timer_limit; err = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index ab309eca09c..c09ec39d68a 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -303,7 +303,6 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); master_l10_counter = &timers_global->l10_count; - master_l10_limit = &timers_global->l10_limit; err = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index fa54d585f55..62c1d94cb43 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -73,7 +73,6 @@ unsigned long profile_pc(struct pt_regs *regs) EXPORT_SYMBOL(profile_pc); __volatile__ unsigned int *master_l10_counter; -__volatile__ unsigned int *master_l10_limit; /* * timer_interrupt() needs to keep up the real-time clock, -- cgit v1.2.3 From e7913de9285a4e40733cdabbe62b6f1fa3bbdf01 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:48:41 -0700 Subject: sparc32: Kill irq_rcvreg from sun4m_irq.c Unused. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4m_irq.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index c09ec39d68a..c6096fc70c6 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -59,9 +59,6 @@ struct sun4m_irq_global { struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; struct sun4m_irq_global __iomem *sun4m_irq_global; -static unsigned long dummy; -unsigned long *irq_rcvreg = &dummy; - /* Dave Redman (djhr@tadpole.co.uk) * The sun4m interrupt registers. */ @@ -369,10 +366,9 @@ void __init sun4m_init_IRQ(void) for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); - if (num_cpu_iregs == 4) { - irq_rcvreg = (unsigned long *) &sun4m_irq_global->interrupt_target; + if (num_cpu_iregs == 4) sbus_writel(0, &sun4m_irq_global->interrupt_target); - } + BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); -- cgit v1.2.3 From 778b1c65bfa2bfe4018394480f97d387e8f00a91 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 15:33:21 -0700 Subject: sparc32: Add more extensive documentation of sun4m interrupts. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4m_irq.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index c6096fc70c6..ec66d4aab09 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -87,6 +87,59 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; #define SUN4M_INT_SBUS(x) (1 << (x+7)) #define SUN4M_INT_VME(x) (1 << (x)) +/* Interrupt level assignment on sun4m: + * + * level source + * ------------------------------------------------------------ + * 1 softint-1 + * 2 softint-2, VME/SBUS level 1 + * 3 softint-3, VME/SBUS level 2 + * 4 softint-4, onboard SCSI + * 5 softint-5, VME/SBUS level 3 + * 6 softint-6, onboard ETHERNET + * 7 softint-7, VME/SBUS level 4 + * 8 softint-8, onboard VIDEO + * 9 softint-9, VME/SBUS level 5, Module Interrupt + * 10 softint-10, system counter/timer + * 11 softint-11, VME/SBUS level 6, Floppy + * 12 softint-12, Keyboard/Mouse, Serial + * 13 softint-13, VME/SBUS level 7, ISDN Audio + * 14 softint-14, per-processor counter/timer + * 15 softint-15, Asynchronous Errors (broadcast) + * + * Each interrupt source is masked distinctly in the sun4m interrupt + * registers. The PIL level alone is therefore ambiguous, since multiple + * interrupt sources map to a single PIL. + * + * This ambiguity is resolved in the 'intr' property for device nodes + * in the OF device tree. Each 'intr' property entry is composed of + * two 32-bit words. The first word is the IRQ priority value, which + * is what we're intersted in. The second word is the IRQ vector, which + * is unused. + * + * The low 4 bits of the IRQ priority indicate the PIL, and the upper + * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled. 0x20 + * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled. + * + * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI + * whereas a value of 0x33 is SBUS level 2. Here are some sample + * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and + * Tadpole S3 GX systems. + * + * esp: 0x24 onboard ESP SCSI + * le: 0x26 onboard Lance ETHERNET + * p9100: 0x32 SBUS level 1 P9100 video + * bpp: 0x33 SBUS level 2 BPP parallel port device + * DBRI: 0x39 SBUS level 5 DBRI ISDN audio + * SUNW,leo: 0x39 SBUS level 5 LEO video + * pcmcia: 0x3b SBUS level 6 PCMCIA controller + * uctrl: 0x3b SBUS level 6 UCTRL device + * modem: 0x3d SBUS level 7 MODEM + * zs: 0x2c onboard keyboard/mouse/serial + * floppy: 0x2b onboard Floppy + * power: 0x22 onboard power device (XXX unknown mask bit XXX) + */ + /* These tables only apply for interrupts greater than 15.. * * any intr value below 0x10 is considered to be a soft-int -- cgit v1.2.3 From a1cd0464c6f5857d87466130753d81b783bd3c52 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 21 Sep 2008 00:28:26 -0700 Subject: sparc: arch/sparc/kernel/pmc.c -- extra #include? I have no SPARC compiler handy to verify, but it looks like this is another file that doesn't need ... Signed-off-by: David S. Miller --- arch/sparc/kernel/pmc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 814eb3ce039..2afcfab4f11 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -24,7 +23,6 @@ * #define PMC_NO_IDLE */ -#define PMC_MINOR MISC_DYNAMIC_MINOR #define PMC_OBPNAME "SUNW,pmc" #define PMC_DEVNAME "pmc" -- cgit v1.2.3 From f3c450be7b0defab59e360eca8a7e201d424d526 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 12 Aug 2008 17:26:35 -0700 Subject: avr32: use the new byteorder headers Signed-off-by: Harvey Harrison [haavard.skinnemoen@atmel.com: fix build breakage] Signed-off-by: Haavard Skinnemoen --- arch/avr32/include/asm/byteorder.h | 22 ++++++++++++++-------- arch/avr32/mach-at32ap/include/mach/io.h | 3 +-- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/avr32/include/asm/byteorder.h b/arch/avr32/include/asm/byteorder.h index d77b48ba733..8e3af02076d 100644 --- a/arch/avr32/include/asm/byteorder.h +++ b/arch/avr32/include/asm/byteorder.h @@ -7,6 +7,9 @@ #include #include +#define __BIG_ENDIAN +#define __SWAB_64_THRU_32__ + #ifdef __CHECKER__ extern unsigned long __builtin_bswap_32(unsigned long x); extern unsigned short __builtin_bswap_16(unsigned short x); @@ -17,15 +20,18 @@ extern unsigned short __builtin_bswap_16(unsigned short x); * the result. */ #if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2) -#define __arch__swab32(x) __builtin_bswap_32(x) -#define __arch__swab16(x) __builtin_bswap_16(x) -#endif +static inline __attribute_const__ __u16 __arch_swab16(__u16 val) +{ + return __builtin_bswap_16(val); +} +#define __arch_swab16 __arch_swab16 -#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __BYTEORDER_HAS_U64__ -# define __SWAB_64_THRU_32__ +static inline __attribute_const__ __u32 __arch_swab32(__u32 val) +{ + return __builtin_bswap_32(val); +} +#define __arch_swab32 __arch_swab32 #endif -#include - +#include #endif /* __ASM_AVR32_BYTEORDER_H */ diff --git a/arch/avr32/mach-at32ap/include/mach/io.h b/arch/avr32/mach-at32ap/include/mach/io.h index 4ec6abc68ea..22ea79b7405 100644 --- a/arch/avr32/mach-at32ap/include/mach/io.h +++ b/arch/avr32/mach-at32ap/include/mach/io.h @@ -1,8 +1,7 @@ #ifndef __ASM_AVR32_ARCH_AT32AP_IO_H #define __ASM_AVR32_ARCH_AT32AP_IO_H -/* For "bizarre" halfword swapping */ -#include +#include #if defined(CONFIG_AP700X_32_BIT_SMC) # define __swizzle_addr_b(addr) (addr ^ 3UL) -- cgit v1.2.3 From 3d256151471ba9fd60a5b896a706eb21a6b1cea1 Mon Sep 17 00:00:00 2001 From: Nikolaus Voss Date: Wed, 3 Sep 2008 12:50:32 +0200 Subject: Add kernel support for oprofile callgraphs on AVR32 This patch adds backtracing capability to oprofile profiling in kernel and user mode on AVR32. This is done by going through the frames on the stack and adding oprofile traces for all return addresses. The code being profiled has to be compiled with frame pointers to make this work. Signed-off-by: Nikolaus Voss Signed-off-by: Haavard Skinnemoen --- arch/avr32/oprofile/Makefile | 2 +- arch/avr32/oprofile/backtrace.c | 81 ++++++++++++++++++++++++++++++++++++ arch/avr32/oprofile/op_model_avr32.c | 4 ++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 arch/avr32/oprofile/backtrace.c (limited to 'arch') diff --git a/arch/avr32/oprofile/Makefile b/arch/avr32/oprofile/Makefile index 1fe81c3c1e8..e0eb520e028 100644 --- a/arch/avr32/oprofile/Makefile +++ b/arch/avr32/oprofile/Makefile @@ -5,4 +5,4 @@ oprofile-y := $(addprefix ../../../drivers/oprofile/, \ event_buffer.o oprofile_files.o \ oprofilefs.o oprofile_stats.o \ timer_int.o) -oprofile-y += op_model_avr32.o +oprofile-y += op_model_avr32.o backtrace.o diff --git a/arch/avr32/oprofile/backtrace.c b/arch/avr32/oprofile/backtrace.c new file mode 100644 index 00000000000..75d9ad6f99c --- /dev/null +++ b/arch/avr32/oprofile/backtrace.c @@ -0,0 +1,81 @@ +/* + * AVR32 specific backtracing code for oprofile + * + * Copyright 2008 Weinmann GmbH + * + * Author: Nikolaus Voss + * + * Based on i386 oprofile backtrace code by John Levon and David Smith + * + * 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 + +/* The first two words of each frame on the stack look like this if we have + * frame pointers */ +struct frame_head { + unsigned long lr; + struct frame_head *fp; +}; + +/* copied from arch/avr32/kernel/process.c */ +static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) +{ + return (p > (unsigned long)tinfo) + && (p < (unsigned long)tinfo + THREAD_SIZE - 3); +} + +/* copied from arch/x86/oprofile/backtrace.c */ +static struct frame_head *dump_user_backtrace(struct frame_head *head) +{ + struct frame_head bufhead[2]; + + /* Also check accessibility of one struct frame_head beyond */ + if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) + return NULL; + if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) + return NULL; + + oprofile_add_trace(bufhead[0].lr); + + /* frame pointers should strictly progress back up the stack + * (towards higher addresses) */ + if (bufhead[0].fp <= head) + return NULL; + + return bufhead[0].fp; +} + +void avr32_backtrace(struct pt_regs * const regs, unsigned int depth) +{ + /* Get first frame pointer */ + struct frame_head *head = (struct frame_head *)(regs->r7); + + if (!user_mode(regs)) { +#ifdef CONFIG_FRAME_POINTER + /* + * Traverse the kernel stack from frame to frame up to + * "depth" steps. + */ + while (depth-- && valid_stack_ptr(task_thread_info(current), + (unsigned long)head)) { + oprofile_add_trace(head->lr); + if (head->fp <= head) + break; + head = head->fp; + } +#endif + } else { + /* Assume we have frame pointers in user mode process */ + while (depth-- && head) + head = dump_user_backtrace(head); + } +} + + diff --git a/arch/avr32/oprofile/op_model_avr32.c b/arch/avr32/oprofile/op_model_avr32.c index df42325c7f8..a3e9b3c4845 100644 --- a/arch/avr32/oprofile/op_model_avr32.c +++ b/arch/avr32/oprofile/op_model_avr32.c @@ -22,6 +22,8 @@ #define AVR32_PERFCTR_IRQ_GROUP 0 #define AVR32_PERFCTR_IRQ_LINE 1 +void avr32_backtrace(struct pt_regs * const regs, unsigned int depth); + enum { PCCNT, PCNT0, PCNT1, NR_counter }; struct avr32_perf_counter { @@ -223,6 +225,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) memcpy(ops, &avr32_perf_counter_ops, sizeof(struct oprofile_operations)); + ops->backtrace = avr32_backtrace; + printk(KERN_INFO "oprofile: using AVR32 performance monitoring.\n"); return 0; -- cgit v1.2.3 From 48c1fd3882286fd9e978ca8725013f2e060b700e Mon Sep 17 00:00:00 2001 From: Marco Stornelli Date: Tue, 16 Sep 2008 09:14:03 +0200 Subject: avr32: added mem kernel command line option support Signed-off-by: Marco Stornelli Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/setup.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'arch') diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index d8e623c426c..5c7083916c3 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c @@ -283,6 +283,25 @@ static int __init early_parse_fbmem(char *p) } early_param("fbmem", early_parse_fbmem); +/* + * Pick out the memory size. We look for mem=size@start, + * where start and size are "size[KkMmGg]" + */ +static int __init early_mem(char *p) +{ + resource_size_t size, start; + + start = system_ram->start; + size = memparse(p, &p); + if (*p == '@') + start = memparse(p + 1, &p); + + system_ram->start = start; + system_ram->end = system_ram->start + size - 1; + return 0; +} +early_param("mem", early_mem); + static int __init parse_tag_core(struct tag *tag) { if (tag->hdr.size > 2) { -- cgit v1.2.3 From 7066412488281fd1c201dceb22a0dfe467012f76 Mon Sep 17 00:00:00 2001 From: Julien May Date: Mon, 4 Aug 2008 14:27:38 +0200 Subject: avr32: Allow fine-grained control over LCDC pins This replaces the pin_config param with an u64 pin_mask in at32_add_device_lcdc, allowing a board-maintainer to indivually select specific lcdc pins. Signed-off-by: Alex Raimondi Signed-off-by: Julien May Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/atstk1002.c | 3 +- arch/avr32/boards/atstk1000/atstk1004.c | 3 +- arch/avr32/mach-at32ap/at32ap700x.c | 95 +++++------------ arch/avr32/mach-at32ap/include/mach/at32ap700x.h | 128 +++++++++++++++++++++++ arch/avr32/mach-at32ap/include/mach/board.h | 2 +- 5 files changed, 158 insertions(+), 73 deletions(-) (limited to 'arch') diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index dfc3443e23a..cccca241fae 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -332,7 +332,8 @@ static int __init atstk1002_init(void) set_hw_addr(at32_add_device_eth(1, ð_data[1])); #else at32_add_device_lcdc(0, &atstk1000_lcdc_data, - fbmem_start, fbmem_size, 0); + fbmem_start, fbmem_size, + ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); #endif at32_add_device_usba(0, NULL); #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index 50a5273e591..2c072cd0c22 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -140,7 +140,8 @@ static int __init atstk1004_init(void) at32_add_device_mci(0, NULL); #endif at32_add_device_lcdc(0, &atstk1000_lcdc_data, - fbmem_start, fbmem_size, 0); + fbmem_start, fbmem_size, + ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); at32_add_device_usba(0, NULL); #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM at32_add_device_ssc(0, ATMEL_SSC_TX); diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index e01dbe4ebb4..c28dd172f62 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1353,13 +1353,14 @@ static struct clk atmel_lcdfb0_pixclk = { struct platform_device *__init at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, unsigned long fbmem_start, unsigned long fbmem_len, - unsigned int pin_config) + u64 pin_mask) { struct platform_device *pdev; struct atmel_lcdfb_info *info; struct fb_monspecs *monspecs; struct fb_videomode *modedb; unsigned int modedb_size; + int i; /* * Do a deep copy of the fb data, monspecs and modedb. Make @@ -1381,75 +1382,29 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, case 0: pdev = &atmel_lcdfb0_device; - switch (pin_config) { - case 0: - select_peripheral(PC(19), PERIPH_A, 0); /* CC */ - select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ - select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ - select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */ - select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */ - select_peripheral(PC(24), PERIPH_A, 0); /* MODE */ - select_peripheral(PC(25), PERIPH_A, 0); /* PWR */ - select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */ - select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */ - select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */ - select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */ - select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */ - select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */ - select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */ - select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */ - select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */ - select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */ - select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */ - select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */ - select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */ - select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */ - select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */ - select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */ - select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */ - select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */ - select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */ - select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */ - select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */ - select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */ - select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ - select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ - break; - case 1: - select_peripheral(PE(0), PERIPH_B, 0); /* CC */ - select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ - select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ - select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */ - select_peripheral(PE(1), PERIPH_B, 0); /* DVAL */ - select_peripheral(PE(2), PERIPH_B, 0); /* MODE */ - select_peripheral(PC(25), PERIPH_A, 0); /* PWR */ - select_peripheral(PE(3), PERIPH_B, 0); /* DATA0 */ - select_peripheral(PE(4), PERIPH_B, 0); /* DATA1 */ - select_peripheral(PE(5), PERIPH_B, 0); /* DATA2 */ - select_peripheral(PE(6), PERIPH_B, 0); /* DATA3 */ - select_peripheral(PE(7), PERIPH_B, 0); /* DATA4 */ - select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */ - select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */ - select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */ - select_peripheral(PE(8), PERIPH_B, 0); /* DATA8 */ - select_peripheral(PE(9), PERIPH_B, 0); /* DATA9 */ - select_peripheral(PE(10), PERIPH_B, 0); /* DATA10 */ - select_peripheral(PE(11), PERIPH_B, 0); /* DATA11 */ - select_peripheral(PE(12), PERIPH_B, 0); /* DATA12 */ - select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */ - select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */ - select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */ - select_peripheral(PE(13), PERIPH_B, 0); /* DATA16 */ - select_peripheral(PE(14), PERIPH_B, 0); /* DATA17 */ - select_peripheral(PE(15), PERIPH_B, 0); /* DATA18 */ - select_peripheral(PE(16), PERIPH_B, 0); /* DATA19 */ - select_peripheral(PE(17), PERIPH_B, 0); /* DATA20 */ - select_peripheral(PE(18), PERIPH_B, 0); /* DATA21 */ - select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ - select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ - break; - default: - goto err_invalid_id; + if (pin_mask == 0ULL) + /* Default to "full" lcdc control signals and 24bit */ + pin_mask = ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL; + + /* LCDC on port C */ + for (i = 19; i < 32; i++) { + if (pin_mask & (1ULL << i)) + at32_select_periph(GPIO_PIOC_BASE + i, + GPIO_PERIPH_A, 0); + } + + /* LCDC on port D */ + for (i = 0; i < 18; i++) { + if (pin_mask & (1ULL << i)) + at32_select_periph(GPIO_PIOD_BASE + i, + GPIO_PERIPH_A, 0); + } + + /* LCDC on port E */ + for (i = 0; i < 19; i++) { + if (pin_mask & (1ULL << (i + 32))) + at32_select_periph(GPIO_PIOE_BASE + i, + GPIO_PERIPH_B, 0); } clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); diff --git a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h index 1e9852d65cc..a77d372f6f3 100644 --- a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h +++ b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h @@ -83,4 +83,132 @@ #define HMATRIX_BASE 0xfff00800 #define SDRAMC_BASE 0xfff03800 +/* LCDC on port C */ +#define ATMEL_LCDC_PC_CC (1ULL << 19) +#define ATMEL_LCDC_PC_HSYNC (1ULL << 20) +#define ATMEL_LCDC_PC_PCLK (1ULL << 21) +#define ATMEL_LCDC_PC_VSYNC (1ULL << 22) +#define ATMEL_LCDC_PC_DVAL (1ULL << 23) +#define ATMEL_LCDC_PC_MODE (1ULL << 24) +#define ATMEL_LCDC_PC_PWR (1ULL << 25) +#define ATMEL_LCDC_PC_DATA0 (1ULL << 26) +#define ATMEL_LCDC_PC_DATA1 (1ULL << 27) +#define ATMEL_LCDC_PC_DATA2 (1ULL << 28) +#define ATMEL_LCDC_PC_DATA3 (1ULL << 29) +#define ATMEL_LCDC_PC_DATA4 (1ULL << 30) +#define ATMEL_LCDC_PC_DATA5 (1ULL << 31) + +/* LCDC on port D */ +#define ATMEL_LCDC_PD_DATA6 (1ULL << 0) +#define ATMEL_LCDC_PD_DATA7 (1ULL << 1) +#define ATMEL_LCDC_PD_DATA8 (1ULL << 2) +#define ATMEL_LCDC_PD_DATA9 (1ULL << 3) +#define ATMEL_LCDC_PD_DATA10 (1ULL << 4) +#define ATMEL_LCDC_PD_DATA11 (1ULL << 5) +#define ATMEL_LCDC_PD_DATA12 (1ULL << 6) +#define ATMEL_LCDC_PD_DATA13 (1ULL << 7) +#define ATMEL_LCDC_PD_DATA14 (1ULL << 8) +#define ATMEL_LCDC_PD_DATA15 (1ULL << 9) +#define ATMEL_LCDC_PD_DATA16 (1ULL << 10) +#define ATMEL_LCDC_PD_DATA17 (1ULL << 11) +#define ATMEL_LCDC_PD_DATA18 (1ULL << 12) +#define ATMEL_LCDC_PD_DATA19 (1ULL << 13) +#define ATMEL_LCDC_PD_DATA20 (1ULL << 14) +#define ATMEL_LCDC_PD_DATA21 (1ULL << 15) +#define ATMEL_LCDC_PD_DATA22 (1ULL << 16) +#define ATMEL_LCDC_PD_DATA23 (1ULL << 17) + +/* LCDC on port E */ +#define ATMEL_LCDC_PE_CC (1ULL << (32 + 0)) +#define ATMEL_LCDC_PE_DVAL (1ULL << (32 + 1)) +#define ATMEL_LCDC_PE_MODE (1ULL << (32 + 2)) +#define ATMEL_LCDC_PE_DATA0 (1ULL << (32 + 3)) +#define ATMEL_LCDC_PE_DATA1 (1ULL << (32 + 4)) +#define ATMEL_LCDC_PE_DATA2 (1ULL << (32 + 5)) +#define ATMEL_LCDC_PE_DATA3 (1ULL << (32 + 6)) +#define ATMEL_LCDC_PE_DATA4 (1ULL << (32 + 7)) +#define ATMEL_LCDC_PE_DATA8 (1ULL << (32 + 8)) +#define ATMEL_LCDC_PE_DATA9 (1ULL << (32 + 9)) +#define ATMEL_LCDC_PE_DATA10 (1ULL << (32 + 10)) +#define ATMEL_LCDC_PE_DATA11 (1ULL << (32 + 11)) +#define ATMEL_LCDC_PE_DATA12 (1ULL << (32 + 12)) +#define ATMEL_LCDC_PE_DATA16 (1ULL << (32 + 13)) +#define ATMEL_LCDC_PE_DATA17 (1ULL << (32 + 14)) +#define ATMEL_LCDC_PE_DATA18 (1ULL << (32 + 15)) +#define ATMEL_LCDC_PE_DATA19 (1ULL << (32 + 16)) +#define ATMEL_LCDC_PE_DATA20 (1ULL << (32 + 17)) +#define ATMEL_LCDC_PE_DATA21 (1ULL << (32 + 18)) + + +#define ATMEL_LCDC(PORT, PIN) (ATMEL_LCDC_##PORT##_##PIN) + + +#define ATMEL_LCDC_PRI_24B_DATA ( \ + ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \ + ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ + ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ + ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ + ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \ + ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ + ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \ + ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ + ATMEL_LCDC(PD, DATA16) | ATMEL_LCDC(PD, DATA17) | \ + ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \ + ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \ + ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) + +#define ATMEL_LCDC_ALT_24B_DATA ( \ + ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \ + ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ + ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ + ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ + ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \ + ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ + ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \ + ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ + ATMEL_LCDC(PE, DATA16) | ATMEL_LCDC(PE, DATA17) | \ + ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \ + ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \ + ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) + +#define ATMEL_LCDC_PRI_15B_DATA ( \ + ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \ + ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ + ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ + ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \ + ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ + ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA16) | \ + ATMEL_LCDC(PD, DATA17) | ATMEL_LCDC(PD, DATA18) | \ + ATMEL_LCDC(PD, DATA19) | ATMEL_LCDC(PD, DATA20)) + +#define ATMEL_LCDC_ALT_15B_DATA ( \ + ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \ + ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ + ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ + ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \ + ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ + ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PE, DATA16) | \ + ATMEL_LCDC(PE, DATA17) | ATMEL_LCDC(PE, DATA18) | \ + ATMEL_LCDC(PE, DATA19) | ATMEL_LCDC(PE, DATA20)) + +#define ATMEL_LCDC_PRI_CONTROL ( \ + ATMEL_LCDC(PC, CC) | ATMEL_LCDC(PC, DVAL) | \ + ATMEL_LCDC(PC, MODE) | ATMEL_LCDC(PC, PWR)) + +#define ATMEL_LCDC_ALT_CONTROL ( \ + ATMEL_LCDC(PE, CC) | ATMEL_LCDC(PE, DVAL) | \ + ATMEL_LCDC(PE, MODE) | ATMEL_LCDC(PC, PWR)) + +#define ATMEL_LCDC_CONTROL ( \ + ATMEL_LCDC(PC, HSYNC) | ATMEL_LCDC(PC, VSYNC) | \ + ATMEL_LCDC(PC, PCLK)) + +#define ATMEL_LCDC_PRI_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_24B_DATA) + +#define ATMEL_LCDC_ALT_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_24B_DATA) + +#define ATMEL_LCDC_PRI_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_15B_DATA) + +#define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA) + #endif /* __ASM_ARCH_AT32AP700X_H__ */ diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index e60e9076544..c48386d66bc 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h @@ -43,7 +43,7 @@ struct atmel_lcdfb_info; struct platform_device * at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, unsigned long fbmem_start, unsigned long fbmem_len, - unsigned int pin_config); + u64 pin_mask); struct usba_platform_data; struct platform_device * -- cgit v1.2.3 From 96706600de83966812b01a3cb310a13da2a1a4e9 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 6 Sep 2008 20:19:02 -0700 Subject: ngw100: export J15 through sysfs The NGW100 board has jumper J15 (near the reset button) which is unused. This patch exports it through the GPIO sysfs support (as /sys/class/gpio/gpio62/value) so that it's easily queried by boot scripts or whatever might want to know if the jumper has been installed (value = 0) or not (value = 1, "default"). Signed-off-by: David Brownell [haavard.skinnemoen@atmel.com: add missing include] Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atngw100/setup.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index b8286f1ce85..abcb0d9559b 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -204,6 +205,15 @@ postcore_initcall(atngw100_init); static int __init atngw100_arch_init(void) { + /* PB30 is the otherwise unused jumper on the mainboard, with an + * external pullup; the jumper grounds it. Use it however you + * like, including letting U-Boot or Linux tweak boot sequences. + */ + at32_select_gpio(GPIO_PIN_PB(30), 0); + gpio_request(GPIO_PIN_PB(30), "j15"); + gpio_direction_input(GPIO_PIN_PB(30)); + gpio_export(GPIO_PIN_PB(30), false); + /* set_irq_type() after the arch_initcall for EIC has run, and * before the I2C subsystem could try using this IRQ. */ -- cgit v1.2.3 From ece2678c62ce13ef11a8b43526ccc5db8d711ed3 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 17:13:28 +0200 Subject: avr32: Provide a way to deselect pins in the portmux Currently, setting up the portmux is completely one-shot: Once a pin is muxed, the portmux driver will complain loudly and refuse to do anything if you try to set up the same pin again. Sometimes, it may be necessary to change the configuration of a pin after it has been set up initially. This patch adds a way to undo the previous configuration, allowing the pin to be reconfigured. Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/include/mach/portmux.h | 1 + arch/avr32/mach-at32ap/pio.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/include/mach/portmux.h b/arch/avr32/mach-at32ap/include/mach/portmux.h index b1abe6b4e4e..4bbf99ec2c4 100644 --- a/arch/avr32/mach-at32ap/include/mach/portmux.h +++ b/arch/avr32/mach-at32ap/include/mach/portmux.h @@ -24,6 +24,7 @@ void at32_select_periph(unsigned int pin, unsigned int periph, unsigned long flags); void at32_select_gpio(unsigned int pin, unsigned long flags); +void at32_deselect_pin(unsigned int pin); void at32_reserve_pin(unsigned int pin); #endif /* __ASM_ARCH_PORTMUX_H__ */ diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 405ee6bad4c..90ef538ae54 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -134,6 +134,25 @@ fail: dump_stack(); } +/* + * Undo a previous pin reservation. Will not affect the hardware + * configuration. + */ +void at32_deselect_pin(unsigned int pin) +{ + struct pio_device *pio; + unsigned int pin_index = pin & 0x1f; + + pio = gpio_to_pio(pin); + if (unlikely(!pio)) { + printk("pio: invalid pin %u\n", pin); + dump_stack(); + return; + } + + clear_bit(pin_index, &pio->pinmux_mask); +} + /* Reserve a pin, preventing anyone else from changing its configuration. */ void __init at32_reserve_pin(unsigned int pin) { -- cgit v1.2.3 From d6634db8fe1784d0a8e4e156970fec034708446e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 21 Sep 2008 23:52:07 +0200 Subject: avr32: Use platform_driver_probe for pio platform driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function of the pio platform driver lives in the init section and so a pio device that is created after the init section is discarded probably results in an oops. Even if this cannot happen, using platform_driver_probe is cleaner. (If this can happen and should be supported the probe function must live in the devinit section instead.) Signed-off-by: Uwe Kleine-König Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 90ef538ae54..ef2561e1539 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -401,7 +401,6 @@ static int __init pio_probe(struct platform_device *pdev) } static struct platform_driver pio_driver = { - .probe = pio_probe, .driver = { .name = "pio", }, @@ -409,7 +408,7 @@ static struct platform_driver pio_driver = { static int __init pio_init(void) { - return platform_driver_register(&pio_driver); + return platform_driver_probe(&pio_driver, pio_probe); } postcore_initcall(pio_init); -- cgit v1.2.3 From 787928e7473246991177e8cd7eeaf4cb1b3a8fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 21 Sep 2008 23:52:08 +0200 Subject: avr32: Use platform_driver_probe for pdc platform driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function of the pdc platform driver lives in the init section and so a pdc device that is created after the init section is discarded probably results in an oops. Even if this cannot happen, using platform_driver_probe is cleaner. (If this can happen and should be supported the probe function must live in the devinit section instead.) Signed-off-by: Uwe Kleine-König Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pdc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/pdc.c b/arch/avr32/mach-at32ap/pdc.c index 1040bda4fda..61ab15aae97 100644 --- a/arch/avr32/mach-at32ap/pdc.c +++ b/arch/avr32/mach-at32ap/pdc.c @@ -35,7 +35,6 @@ static int __init pdc_probe(struct platform_device *pdev) } static struct platform_driver pdc_driver = { - .probe = pdc_probe, .driver = { .name = "pdc", }, @@ -43,6 +42,6 @@ static struct platform_driver pdc_driver = { static int __init pdc_init(void) { - return platform_driver_register(&pdc_driver); + return platform_driver_probe(&pdc_driver, pdc_probe); } arch_initcall(pdc_init); -- cgit v1.2.3 From 5871c6b0a52bb052c3891a787655043b90ae18e3 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 20 Sep 2008 20:35:44 -0700 Subject: x86: use round_jiffies() for the corruption check timer the exact timing of the corruption check isn't too important (it's once a minute timer), use round_jiffies() to align it and avoid extra wakeups. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 786c1886ae5..161f1b33ece 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -712,7 +712,7 @@ void check_for_bios_corruption(void) static void periodic_check_for_corruption(unsigned long data) { check_for_bios_corruption(); - mod_timer(&periodic_check_timer, jiffies + corruption_check_period*HZ); + mod_timer(&periodic_check_timer, round_jiffies(jiffies + corruption_check_period*HZ)); } void start_periodic_check_for_corruption(void) -- cgit v1.2.3 From 2216d199b1430d1c0affb1498a9ebdbd9c0de439 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Sep 2008 02:52:26 -0700 Subject: x86: fix CONFIG_X86_RESERVE_LOW_64K=y The bad_bios_dmi_table() quirk never triggered because we do DMI setup too late. Move it a bit earlier. Also change the CONFIG_X86_RESERVE_LOW_64K quirk to operate on the e820 table directly instead of messing with early reservations - this handles overlaps (which do occur in this low range of RAM) more gracefully. Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 161f1b33ece..d29951c11be 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -735,7 +735,8 @@ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) "%s detected: BIOS may corrupt low RAM, working it around.\n", d->ident); - reserve_early_overlap_ok(0x0, 0x10000, "BIOS quirk"); + e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED); + sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); return 0; } @@ -784,8 +785,6 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Command line: %s\n", boot_command_line); #endif - dmi_check_system(bad_bios_dmi_table); - early_cpu_init(); early_ioremap_init(); @@ -880,6 +879,10 @@ void __init setup_arch(char **cmdline_p) finish_e820_parsing(); + dmi_scan_machine(); + + dmi_check_system(bad_bios_dmi_table); + #ifdef CONFIG_X86_32 probe_roms(); #endif @@ -967,8 +970,6 @@ void __init setup_arch(char **cmdline_p) vsmp_init(); #endif - dmi_scan_machine(); - io_delay_init(); /* -- cgit v1.2.3 From af2d237bf574f89ae5a1b67f2556a324c8f64ff5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 21 Sep 2008 23:27:13 +0900 Subject: x86: check for ioremap() failure in copy_oldmem_page() Add a check for ioremap() failure in copy_oldmem_page(). This patch also includes small coding style fixes. Signed-off-by: Akinobu Mita Signed-off-by: Ingo Molnar --- arch/x86/kernel/crash_dump_64.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index 15e6c6bc4a4..280d6ef3af0 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -33,14 +33,16 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, return 0; vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); + if (!vaddr) + return -ENOMEM; if (userbuf) { - if (copy_to_user(buf, (vaddr + offset), csize)) { + if (copy_to_user(buf, vaddr + offset, csize)) { iounmap(vaddr); return -EFAULT; } } else - memcpy(buf, (vaddr + offset), csize); + memcpy(buf, vaddr + offset, csize); iounmap(vaddr); return csize; -- cgit v1.2.3 From 153dab77e228931f3aff74f21b762927ac710ca7 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 21 Sep 2008 23:25:40 +0900 Subject: x86: use platform_device_register_simple() Cleanup pcspeaker.c Signed-off-by: Akinobu Mita Signed-off-by: Ingo Molnar --- arch/x86/kernel/pcspeaker.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pcspeaker.c b/arch/x86/kernel/pcspeaker.c index bc1f2d3ea27..a311ffcaad1 100644 --- a/arch/x86/kernel/pcspeaker.c +++ b/arch/x86/kernel/pcspeaker.c @@ -1,20 +1,13 @@ #include -#include +#include #include static __init int add_pcspkr(void) { struct platform_device *pd; - int ret; - pd = platform_device_alloc("pcspkr", -1); - if (!pd) - return -ENOMEM; + pd = platform_device_register_simple("pcspkr", -1, NULL, 0); - ret = platform_device_add(pd); - if (ret) - platform_device_put(pd); - - return ret; + return IS_ERR(pd) ? PTR_ERR(pd) : 0; } device_initcall(add_pcspkr); -- cgit v1.2.3 From 16dc552f35bc0ec6fec8ef83f8032eee352d17f5 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 19 Sep 2008 11:45:04 -0700 Subject: x86: use WARN_ONCE in workaround for mtrr mask so could help catch attention about bug in bios about mtrr mask setting. WARN_ONCE got into mainline already, lets use it. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/generic.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index cb7d3b6a80e..4e8d77f01ee 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -401,12 +401,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, tmp |= ~((1<<(hi - 1)) - 1); if (tmp != mask_lo) { - static int once = 1; - - if (once) { - printk(KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); - once = 0; - } + WARN_ONCE(1, KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); mask_lo = tmp; } } -- cgit v1.2.3 From 50041acbe4122817fed9d76a846e78ba6f06c0b5 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 8 Oct 2008 13:39:40 +0800 Subject: Blackfin arch: use new platform data interface of musb to replace old one Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf527/boards/cm_bf527.c | 14 +++++++++++--- arch/blackfin/mach-bf527/boards/ezkit.c | 14 +++++++++++--- arch/blackfin/mach-bf548/boards/cm_bf548.c | 14 +++++++++++--- arch/blackfin/mach-bf548/boards/ezkit.c | 14 +++++++++++--- 4 files changed, 44 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index d22bc777371..986483fb69f 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -43,9 +43,7 @@ #include #include #include -#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) #include -#endif #include #include #include @@ -130,6 +128,16 @@ static struct resource musb_resources[] = { }, }; +static struct musb_hdrc_config musb_config = { + .multipoint = 0, + .dyn_fifo = 0, + .soft_con = 1, + .dma = 1, + .num_eps = 7, + .dma_channels = 7, + .gpio_vrsel = GPIO_PF11, +}; + static struct musb_hdrc_platform_data musb_plat = { #if defined(CONFIG_USB_MUSB_OTG) .mode = MUSB_OTG, @@ -138,7 +146,7 @@ static struct musb_hdrc_platform_data musb_plat = { #elif defined(CONFIG_USB_GADGET_MUSB_HDRC) .mode = MUSB_PERIPHERAL, #endif - .multipoint = 0, + .config = &musb_config, }; static u64 musb_dmamask = ~(u32)0; diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 762f754c06c..a756934482c 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -42,9 +42,7 @@ #include #include #include -#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) #include -#endif #include #include #include @@ -129,6 +127,16 @@ static struct resource musb_resources[] = { }, }; +static struct musb_hdrc_config musb_config = { + .multipoint = 0, + .dyn_fifo = 0, + .soft_con = 1, + .dma = 1, + .num_eps = 7, + .dma_channels = 7, + .gpio_vrsel = GPIO_PG13, +}; + static struct musb_hdrc_platform_data musb_plat = { #if defined(CONFIG_USB_MUSB_OTG) .mode = MUSB_OTG, @@ -137,7 +145,7 @@ static struct musb_hdrc_platform_data musb_plat = { #elif defined(CONFIG_USB_GADGET_MUSB_HDRC) .mode = MUSB_PERIPHERAL, #endif - .multipoint = 0, + .config = &musb_config, }; static u64 musb_dmamask = ~(u32)0; diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c index ce934ee174e..36f56f9ffd0 100644 --- a/arch/blackfin/mach-bf548/boards/cm_bf548.c +++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c @@ -36,9 +36,7 @@ #include #include #include -#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) #include -#endif #include #include #include @@ -268,6 +266,16 @@ static struct resource musb_resources[] = { }, }; +static struct musb_hdrc_config musb_config = { + .multipoint = 0, + .dyn_fifo = 0, + .soft_con = 1, + .dma = 1, + .num_eps = 7, + .dma_channels = 7, + .gpio_vrsel = GPIO_PH6, +}; + static struct musb_hdrc_platform_data musb_plat = { #if defined(CONFIG_USB_MUSB_OTG) .mode = MUSB_OTG, @@ -276,7 +284,7 @@ static struct musb_hdrc_platform_data musb_plat = { #elif defined(CONFIG_USB_GADGET_MUSB_HDRC) .mode = MUSB_PERIPHERAL, #endif - .multipoint = 0, + .config = &musb_config, }; static u64 musb_dmamask = ~(u32)0; diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 39357693046..d22515d080a 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -38,9 +38,7 @@ #include #include #include -#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) #include -#endif #include #include #include @@ -314,6 +312,16 @@ static struct resource musb_resources[] = { }, }; +static struct musb_hdrc_config musb_config = { + .multipoint = 0, + .dyn_fifo = 0, + .soft_con = 1, + .dma = 1, + .num_eps = 7, + .dma_channels = 7, + .gpio_vrsel = GPIO_PE7, +}; + static struct musb_hdrc_platform_data musb_plat = { #if defined(CONFIG_USB_MUSB_OTG) .mode = MUSB_OTG, @@ -322,7 +330,7 @@ static struct musb_hdrc_platform_data musb_plat = { #elif defined(CONFIG_USB_GADGET_MUSB_HDRC) .mode = MUSB_PERIPHERAL, #endif - .multipoint = 0, + .config = &musb_config, }; static u64 musb_dmamask = ~(u32)0; -- cgit v1.2.3 From 31f3d4a317ae1541bf25d0efbf4551855bed0d5b Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Mon, 22 Sep 2008 20:23:55 +0800 Subject: Blackfin arch: add dma mapping stub for musb driver port Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/dma-mapping.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/include/asm/dma-mapping.h b/arch/blackfin/include/asm/dma-mapping.h index 1a13c2fc366..ede748d67ef 100644 --- a/arch/blackfin/include/asm/dma-mapping.h +++ b/arch/blackfin/include/asm/dma-mapping.h @@ -80,4 +80,15 @@ extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, enum dma_data_direction direction); +static inline void dma_sync_single_for_cpu(struct device *dev, + dma_addr_t handle, size_t size, + enum dma_data_direction dir) +{ +} + +static inline void dma_sync_single_for_device(struct device *dev, + dma_addr_t handle, size_t size, + enum dma_data_direction dir) +{ +} #endif /* _BLACKFIN_DMA_MAPPING_H */ -- cgit v1.2.3 From d26dbc5cf94b0a28acc947285c3b54814a73cb2e Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 22 Sep 2008 22:35:07 +0900 Subject: iommu: export iommu_area_reserve helper function x86 has set_bit_string() that does the exact same thing that set_bit_area() in lib/iommu-helper.c does. This patch exports set_bit_area() in lib/iommu-helper.c as iommu_area_reserve(), converts GART, Calgary, and AMD IOMMU to use it. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 2 +- arch/x86/kernel/pci-calgary_64.c | 2 +- arch/x86/kernel/pci-gart_64.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 6f7b9744573..70537d117a9 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -572,7 +572,7 @@ static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, if (start_page + pages > last_page) pages = last_page - start_page; - set_bit_string(dom->bitmap, start_page, pages); + iommu_area_reserve(dom->bitmap, start_page, pages); } static void dma_ops_free_pagetable(struct dma_ops_domain *dma_dom) diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index fe7695e4caa..080d1d27f37 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -261,7 +261,7 @@ static void iommu_range_reserve(struct iommu_table *tbl, badbit, tbl, start_addr, npages); } - set_bit_string(tbl->it_map, index, npages); + iommu_area_reserve(tbl->it_map, index, npages); spin_unlock_irqrestore(&tbl->it_lock, flags); } diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 508ef470b27..3dcb1ad86e3 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -827,7 +827,7 @@ void __init gart_iommu_init(void) * Out of IOMMU space handling. * Reserve some invalid pages at the beginning of the GART. */ - set_bit_string(iommu_gart_bitmap, 0, EMERGENCY_PAGES); + iommu_area_reserve(iommu_gart_bitmap, 0, EMERGENCY_PAGES); agp_memory_reserved = iommu_size; printk(KERN_INFO -- cgit v1.2.3 From 28b166a700899a0f88b1cc283c449fb5bf72a635 Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Mon, 22 Sep 2008 13:14:13 -0400 Subject: x86, NMI watchdog: when booting with reset_devices, clear the performance counters P4s have a quirk that makes necessary to clear P4_CCCR_OVF bit on the CCCR everytime the PMI is triggered. When booting the kernel with reset_devices (more specific kdump case), the counters reach zero and the PMI will be generated. This is not a problem on other processors but on P4s, it'll continue to generate NMIs until that bit is cleared. Since there may be other users of the performance counters, clear and disable all of them when booting with reset_devices option. We have a P4 box here that crashes because of this problem. Since the kdump kernel usually boots with only one processor active, the second logical unit won't be set up, therefore, MSR_P4_IQ_CCCR1 (and other performance counter registers) won't be cleared and P4_CCCR_OVF may be still set because the previous kernel was using this register. An NMI is triggered because of the MSR_P4_IQ_CCCR1 right after the NMI delivery is enabled, triggering the race fixed on my previous email. Signed-off-by: Aristeu Rozanski Acked-by: Don Zickus Acked-by: Prarit Bhargava Acked-by: Vivek Goyal Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perfctr-watchdog.c | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 05cc22dbd4f..62c01006397 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -432,6 +432,27 @@ static const struct wd_ops p6_wd_ops = { #define P4_CCCR_ENABLE (1 << 12) #define P4_CCCR_OVF (1 << 31) +#define P4_CONTROLS 18 +static unsigned int p4_controls[18] = { + MSR_P4_BPU_CCCR0, + MSR_P4_BPU_CCCR1, + MSR_P4_BPU_CCCR2, + MSR_P4_BPU_CCCR3, + MSR_P4_MS_CCCR0, + MSR_P4_MS_CCCR1, + MSR_P4_MS_CCCR2, + MSR_P4_MS_CCCR3, + MSR_P4_FLAME_CCCR0, + MSR_P4_FLAME_CCCR1, + MSR_P4_FLAME_CCCR2, + MSR_P4_FLAME_CCCR3, + MSR_P4_IQ_CCCR0, + MSR_P4_IQ_CCCR1, + MSR_P4_IQ_CCCR2, + MSR_P4_IQ_CCCR3, + MSR_P4_IQ_CCCR4, + MSR_P4_IQ_CCCR5, +}; /* * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter * CRU_ESCR0 (with any non-null event selector) through a complemented @@ -473,6 +494,26 @@ static int setup_p4_watchdog(unsigned nmi_hz) evntsel_msr = MSR_P4_CRU_ESCR0; cccr_msr = MSR_P4_IQ_CCCR0; cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4); + + /* + * If we're on the kdump kernel or other situation, we may + * still have other performance counter registers set to + * interrupt and they'll keep interrupting forever because + * of the P4_CCCR_OVF quirk. So we need to ACK all the + * pending interrupts and disable all the registers here, + * before reenabling the NMI delivery. Refer to p4_rearm() + * about the P4_CCCR_OVF quirk. + */ + if (reset_devices) { + unsigned int low, high; + int i; + + for (i = 0; i < P4_CONTROLS; i++) { + rdmsr(p4_controls[i], low, high); + low &= ~(P4_CCCR_ENABLE | P4_CCCR_OVF); + wrmsr(p4_controls[i], low, high); + } + } } else { /* logical cpu 1 */ perfctr_msr = MSR_P4_IQ_PERFCTR1; -- cgit v1.2.3 From b3e15bdef689641e7f1bb03efbe56112c3ee82e2 Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Mon, 22 Sep 2008 13:13:59 -0400 Subject: x86, NMI watchdog: setup before enabling NMI watchdog There's a small window when NMI watchdog is being set up that if any NMIs are triggered, the NMI code will make make use of not initalized wd_ops elements: void setup_apic_nmi_watchdog(void *unused) { if (__get_cpu_var(wd_enabled)) return; /* cheap hack to support suspend/resume */ /* if cpu0 is not active neither should the other cpus */ if (smp_processor_id() != 0 && atomic_read(&nmi_active) <= 0) return; switch (nmi_watchdog) { case NMI_LOCAL_APIC: /* enable it before to avoid race with handler */ --> __get_cpu_var(wd_enabled) = 1; --> if (lapic_watchdog_init(nmi_hz) < 0) { (...) asmlinkage notrace __kprobes void default_do_nmi(struct pt_regs *regs) { (...) if (nmi_watchdog_tick(regs, reason)) return; (...) notrace __kprobes int nmi_watchdog_tick(struct pt_regs *regs, unsigned reason) { (...) if (!__get_cpu_var(wd_enabled)) return rc; switch (nmi_watchdog) { case NMI_LOCAL_APIC: rc |= lapic_wd_event(nmi_hz); (...) int lapic_wd_event(unsigned nmi_hz) { struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); u64 ctr; --> rdmsrl(wd->perfctr_msr, ctr); and wd->*_msr will be initialized on each processor type specific setup, after enabling NMIs for PMIs. Since the counter was just set, the chances of an performance counter generated NMI is minimal, but any other unknown NMI would trigger the problem. This patch fixes the problem by setting everything up before enabling performance counter generated NMIs and will set wd_enabled using a callback function. Signed-off-by: Aristeu Rozanski Acked-by: Don Zickus Acked-by: Prarit Bhargava Acked-by: Vivek Goyal Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perfctr-watchdog.c | 45 +++++++++++++++++++++++++--------- arch/x86/kernel/nmi.c | 11 +++++++-- 2 files changed, 42 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 62c01006397..6bff382094f 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -295,13 +295,19 @@ static int setup_k7_watchdog(unsigned nmi_hz) /* setup the timer */ wrmsr(evntsel_msr, evntsel, 0); write_watchdog_counter(perfctr_msr, "K7_PERFCTR0",nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - evntsel |= K7_EVNTSEL_ENABLE; - wrmsr(evntsel_msr, evntsel, 0); + /* initialize the wd struct before enabling */ wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = 0; /* unused */ + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= K7_EVNTSEL_ENABLE; + wrmsr(evntsel_msr, evntsel, 0); + return 1; } @@ -379,13 +385,19 @@ static int setup_p6_watchdog(unsigned nmi_hz) wrmsr(evntsel_msr, evntsel, 0); nmi_hz = adjust_for_32bit_ctr(nmi_hz); write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0",nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - evntsel |= P6_EVNTSEL0_ENABLE; - wrmsr(evntsel_msr, evntsel, 0); + /* initialize the wd struct before enabling */ wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = 0; /* unused */ + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= P6_EVNTSEL0_ENABLE; + wrmsr(evntsel_msr, evntsel, 0); + return 1; } @@ -540,12 +552,17 @@ static int setup_p4_watchdog(unsigned nmi_hz) wrmsr(evntsel_msr, evntsel, 0); wrmsr(cccr_msr, cccr_val, 0); write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0", nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - cccr_val |= P4_CCCR_ENABLE; - wrmsr(cccr_msr, cccr_val, 0); + wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = cccr_msr; + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + cccr_val |= P4_CCCR_ENABLE; + wrmsr(cccr_msr, cccr_val, 0); return 1; } @@ -661,13 +678,17 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz) wrmsr(evntsel_msr, evntsel, 0); nmi_hz = adjust_for_32bit_ctr(nmi_hz); write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0", nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; - wrmsr(evntsel_msr, evntsel, 0); wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = 0; /* unused */ + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; + wrmsr(evntsel_msr, evntsel, 0); intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1); return 1; } diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index abb78a2cc4a..2c97f07f1c2 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -299,6 +299,15 @@ void acpi_nmi_disable(void) on_each_cpu(__acpi_nmi_disable, NULL, 1); } +/* + * This function is called as soon the LAPIC NMI watchdog driver has everything + * in place and it's ready to check if the NMIs belong to the NMI watchdog + */ +void cpu_nmi_set_wd_enabled(void) +{ + __get_cpu_var(wd_enabled) = 1; +} + void setup_apic_nmi_watchdog(void *unused) { if (__get_cpu_var(wd_enabled)) @@ -311,8 +320,6 @@ void setup_apic_nmi_watchdog(void *unused) switch (nmi_watchdog) { case NMI_LOCAL_APIC: - /* enable it before to avoid race with handler */ - __get_cpu_var(wd_enabled) = 1; if (lapic_watchdog_init(nmi_hz) < 0) { __get_cpu_var(wd_enabled) = 0; return; -- cgit v1.2.3 From afa9fdc2f5f8e4d98f3e77bfa204412cbc181346 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 20 Sep 2008 01:23:30 +0900 Subject: iommu: remove fullflush and nofullflush in IOMMU generic option This patch against tip/x86/iommu virtually reverts 2842e5bf3115193f05dc9dac20f940e7abf44c1a. But just reverting the commit breaks AMD IOMMU so this patch also includes some fixes. The above commit adds new two options to x86 IOMMU generic kernel boot options, fullflush and nofullflush. But such change that affects all the IOMMUs needs more discussion (all IOMMU parties need the chance to discuss it): http://lkml.org/lkml/2008/9/19/106 Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 4 ++-- arch/x86/kernel/amd_iommu_init.c | 5 ++++- arch/x86/kernel/pci-dma.c | 13 ------------- arch/x86/kernel/pci-gart_64.c | 13 +++++++++++++ 4 files changed, 19 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 70537d117a9..c19212191c9 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -948,7 +948,7 @@ static dma_addr_t __map_single(struct device *dev, } address += offset; - if (unlikely(dma_dom->need_flush && !iommu_fullflush)) { + if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) { iommu_flush_tlb(iommu, dma_dom->domain.id); dma_dom->need_flush = false; } else if (unlikely(iommu_has_npcache(iommu))) @@ -985,7 +985,7 @@ static void __unmap_single(struct amd_iommu *iommu, dma_ops_free_addresses(dma_dom, dma_addr, pages); - if (iommu_fullflush) + if (amd_iommu_unmap_flush) iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); } diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index db0c83af44d..148fcfe22f1 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -122,6 +122,7 @@ LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings we find in ACPI */ unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */ int amd_iommu_isolate; /* if 1, device isolation is enabled */ +bool amd_iommu_unmap_flush; /* if true, flush on every unmap */ LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the system */ @@ -1144,7 +1145,7 @@ int __init amd_iommu_init(void) else printk("disabled\n"); - if (iommu_fullflush) + if (amd_iommu_unmap_flush) printk(KERN_INFO "AMD IOMMU: IO/TLB flush on unmap enabled\n"); else printk(KERN_INFO "AMD IOMMU: Lazy IO/TLB flushing enabled\n"); @@ -1214,6 +1215,8 @@ static int __init parse_amd_iommu_options(char *str) for (; *str; ++str) { if (strncmp(str, "isolate", 7) == 0) amd_iommu_isolate = 1; + if (strncmp(str, "fullflush", 11) == 0) + amd_iommu_unmap_flush = true; } return 1; diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index d2f2c0158dc..0a1408abcc6 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -16,15 +16,6 @@ EXPORT_SYMBOL(dma_ops); static int iommu_sac_force __read_mostly; -/* - * If this is disabled the IOMMU will use an optimized flushing strategy - * of only flushing when an mapping is reused. With it true the GART is - * flushed for every mapping. Problem is that doing the lazy flush seems - * to trigger bugs with some popular PCI cards, in particular 3ware (but - * has been also also seen with Qlogic at least). - */ -int iommu_fullflush; - #ifdef CONFIG_IOMMU_DEBUG int panic_on_overflow __read_mostly = 1; int force_iommu __read_mostly = 1; @@ -180,10 +171,6 @@ static __init int iommu_setup(char *p) } if (!strncmp(p, "nomerge", 7)) iommu_merge = 0; - if (!strncmp(p, "fullflush", 8)) - iommu_fullflush = 1; - if (!strncmp(p, "nofullflush", 11)) - iommu_fullflush = 0; if (!strncmp(p, "forcesac", 8)) iommu_sac_force = 1; if (!strncmp(p, "allowdac", 8)) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 3dcb1ad86e3..9e390f1bd46 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -45,6 +45,15 @@ static unsigned long iommu_pages; /* .. and in pages */ static u32 *iommu_gatt_base; /* Remapping table */ +/* + * If this is disabled the IOMMU will use an optimized flushing strategy + * of only flushing when an mapping is reused. With it true the GART is + * flushed for every mapping. Problem is that doing the lazy flush seems + * to trigger bugs with some popular PCI cards, in particular 3ware (but + * has been also also seen with Qlogic at least). + */ +int iommu_fullflush = 1; + /* Allocation bitmap for the remapping area: */ static DEFINE_SPINLOCK(iommu_bitmap_lock); /* Guarded by iommu_bitmap_lock: */ @@ -892,6 +901,10 @@ void __init gart_parse_options(char *p) #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; + if (!strncmp(p, "fullflush", 8)) + iommu_fullflush = 1; + if (!strncmp(p, "nofullflush", 11)) + iommu_fullflush = 0; if (!strncmp(p, "noagp", 5)) no_agp = 1; if (!strncmp(p, "noaperture", 10)) -- cgit v1.2.3 From a8b71a2810386a5ac8f43d2095fe3355f0d8db37 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 23 Sep 2008 00:35:33 -0700 Subject: x86: fix macro with bad_bios_dmi_table DMI tables need a blank NULL tail. fixes the crash on Ingo's test box. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index d29951c11be..3ce3edfcc3c 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -758,8 +758,8 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), }, }, - {} #endif + {} }; /* -- cgit v1.2.3 From 18dbc9160507dc7df998e00cd1dcd7889557307b Mon Sep 17 00:00:00 2001 From: Dmitry Adamushko Date: Tue, 23 Sep 2008 12:08:44 +0200 Subject: x86: moved microcode.c to microcode_intel.c Combine both generic and arch-specific parts of microcode into a single module (arch-specific parts are config-dependent). Also while we are at it, move arch-specific parts from microcode.h into their respective arch-specific .c files. Signed-off-by: Dmitry Adamushko Cc: "Peter Oruba" Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 10 +- arch/x86/kernel/Makefile | 8 +- arch/x86/kernel/microcode.c | 505 ------------------------------------- arch/x86/kernel/microcode_amd.c | 72 +++--- arch/x86/kernel/microcode_core.c | 509 ++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/microcode_intel.c | 79 +++--- 6 files changed, 608 insertions(+), 575 deletions(-) delete mode 100644 arch/x86/kernel/microcode.c create mode 100644 arch/x86/kernel/microcode_core.c (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0e5bf1eddce..2e608095135 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -801,7 +801,7 @@ config MICROCODE module will be called microcode. config MICROCODE_INTEL - tristate "Intel microcode patch loading support" + bool "Intel microcode patch loading support" depends on MICROCODE default MICROCODE select FW_LOADER @@ -813,20 +813,14 @@ config MICROCODE_INTEL Intel ingredients for this driver, check: . - This driver is only available as a module: the module - will be called microcode_intel. - config MICROCODE_AMD - tristate "AMD microcode patch loading support" + bool "AMD microcode patch loading support" depends on MICROCODE select FW_LOADER --help--- If you select this option, microcode patch loading support for AMD processors will be enabled. - This driver is only available as a module: the module - will be called microcode_amd. - config MICROCODE_OLD_INTERFACE def_bool y depends on MICROCODE diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index be454f348c3..f891996f684 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -51,9 +51,6 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += microcode.o -obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o -obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o @@ -101,6 +98,11 @@ scx200-y += scx200_32.o obj-$(CONFIG_OLPC) += olpc.o +microcode-y := microcode_core.o +microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o +microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o +obj-$(CONFIG_MICROCODE) += microcode.o + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c deleted file mode 100644 index 0c2634f4fd7..00000000000 --- a/arch/x86/kernel/microcode.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Intel CPU Microcode Update Driver for Linux - * - * Copyright (C) 2000-2006 Tigran Aivazian - * 2006 Shaohua Li - * - * This driver allows to upgrade microcode on Intel processors - * belonging to IA-32 family - PentiumPro, Pentium II, - * Pentium III, Xeon, Pentium 4, etc. - * - * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture - * Software Developer's Manual - * Order Number 253668 or free download from: - * - * http://developer.intel.com/design/pentium4/manuals/253668.htm - * - * For more information, go to http://www.urbanmyth.org/microcode - * - * 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. - * - * 1.0 16 Feb 2000, Tigran Aivazian - * Initial release. - * 1.01 18 Feb 2000, Tigran Aivazian - * Added read() support + cleanups. - * 1.02 21 Feb 2000, Tigran Aivazian - * Added 'device trimming' support. open(O_WRONLY) zeroes - * and frees the saved copy of applied microcode. - * 1.03 29 Feb 2000, Tigran Aivazian - * Made to use devfs (/dev/cpu/microcode) + cleanups. - * 1.04 06 Jun 2000, Simon Trimmer - * Added misc device support (now uses both devfs and misc). - * Added MICROCODE_IOCFREE ioctl to clear memory. - * 1.05 09 Jun 2000, Simon Trimmer - * Messages for error cases (non Intel & no suitable microcode). - * 1.06 03 Aug 2000, Tigran Aivazian - * Removed ->release(). Removed exclusive open and status bitmap. - * Added microcode_rwsem to serialize read()/write()/ioctl(). - * Removed global kernel lock usage. - * 1.07 07 Sep 2000, Tigran Aivazian - * Write 0 to 0x8B msr and then cpuid before reading revision, - * so that it works even if there were no update done by the - * BIOS. Otherwise, reading from 0x8B gives junk (which happened - * to be 0 on my machine which is why it worked even when I - * disabled update by the BIOS) - * Thanks to Eric W. Biederman for the fix. - * 1.08 11 Dec 2000, Richard Schaal and - * Tigran Aivazian - * Intel Pentium 4 processor support and bugfixes. - * 1.09 30 Oct 2001, Tigran Aivazian - * Bugfix for HT (Hyper-Threading) enabled processors - * whereby processor resources are shared by all logical processors - * in a single CPU package. - * 1.10 28 Feb 2002 Asit K Mallick and - * Tigran Aivazian , - * Serialize updates as required on HT processors due to - * speculative nature of implementation. - * 1.11 22 Mar 2002 Tigran Aivazian - * Fix the panic when writing zero-length microcode chunk. - * 1.12 29 Sep 2003 Nitin Kamble , - * Jun Nakajima - * Support for the microcode updates in the new format. - * 1.13 10 Oct 2003 Tigran Aivazian - * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl - * because we no longer hold a copy of applied microcode - * in kernel memory. - * 1.14 25 Jun 2004 Tigran Aivazian - * Fix sigmatch() macro to handle old CPUs with pf == 0. - * Thanks to Stuart Swales for pointing out this bug. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -MODULE_DESCRIPTION("Microcode Update Driver"); -MODULE_AUTHOR("Tigran Aivazian "); -MODULE_LICENSE("GPL"); - -#define MICROCODE_VERSION "2.00" - -struct microcode_ops *microcode_ops; - -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DEFINE_MUTEX(microcode_mutex); - -struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; -EXPORT_SYMBOL_GPL(ucode_cpu_info); - -#ifdef CONFIG_MICROCODE_OLD_INTERFACE -static int do_microcode_update(const void __user *buf, size_t size) -{ - cpumask_t old; - int error = 0; - int cpu; - - old = current->cpus_allowed; - - for_each_online_cpu(cpu) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!uci->valid) - continue; - - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - error = microcode_ops->request_microcode_user(cpu, buf, size); - if (error < 0) - goto out; - if (!error) - microcode_ops->apply_microcode(cpu); - } -out: - set_cpus_allowed_ptr(current, &old); - return error; -} - -static int microcode_open(struct inode *unused1, struct file *unused2) -{ - cycle_kernel_lock(); - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -static ssize_t microcode_write(struct file *file, const char __user *buf, - size_t len, loff_t *ppos) -{ - ssize_t ret; - - if ((len >> PAGE_SHIFT) > num_physpages) { - printk(KERN_ERR "microcode: too much data (max %ld pages)\n", - num_physpages); - return -EINVAL; - } - - get_online_cpus(); - mutex_lock(µcode_mutex); - - ret = do_microcode_update(buf, len); - if (!ret) - ret = (ssize_t)len; - - mutex_unlock(µcode_mutex); - put_online_cpus(); - - return ret; -} - -static const struct file_operations microcode_fops = { - .owner = THIS_MODULE, - .write = microcode_write, - .open = microcode_open, -}; - -static struct miscdevice microcode_dev = { - .minor = MICROCODE_MINOR, - .name = "microcode", - .fops = µcode_fops, -}; - -static int __init microcode_dev_init(void) -{ - int error; - - error = misc_register(µcode_dev); - if (error) { - printk(KERN_ERR - "microcode: can't misc_register on minor=%d\n", - MICROCODE_MINOR); - return error; - } - - return 0; -} - -static void microcode_dev_exit(void) -{ - misc_deregister(µcode_dev); -} - -MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); -#else -#define microcode_dev_init() 0 -#define microcode_dev_exit() do { } while (0) -#endif - -/* fake device for request_firmware */ -struct platform_device *microcode_pdev; - -static ssize_t reload_store(struct sys_device *dev, - struct sysdev_attribute *attr, - const char *buf, size_t sz) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - char *end; - unsigned long val = simple_strtoul(buf, &end, 0); - int err = 0; - int cpu = dev->id; - - if (end == buf) - return -EINVAL; - if (val == 1) { - cpumask_t old = current->cpus_allowed; - - get_online_cpus(); - if (cpu_online(cpu)) { - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - mutex_lock(µcode_mutex); - if (uci->valid) { - err = microcode_ops->request_microcode_fw(cpu, - µcode_pdev->dev); - if (!err) - microcode_ops->apply_microcode(cpu); - } - mutex_unlock(µcode_mutex); - set_cpus_allowed_ptr(current, &old); - } - put_online_cpus(); - } - if (err) - return err; - return sz; -} - -static ssize_t version_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->cpu_sig.rev); -} - -static ssize_t pf_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); -} - -static SYSDEV_ATTR(reload, 0200, NULL, reload_store); -static SYSDEV_ATTR(version, 0400, version_show, NULL); -static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); - -static struct attribute *mc_default_attrs[] = { - &attr_reload.attr, - &attr_version.attr, - &attr_processor_flags.attr, - NULL -}; - -static struct attribute_group mc_attr_group = { - .attrs = mc_default_attrs, - .name = "microcode", -}; - -static void microcode_fini_cpu(int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - mutex_lock(µcode_mutex); - microcode_ops->microcode_fini_cpu(cpu); - uci->valid = 0; - mutex_unlock(µcode_mutex); -} - -static void collect_cpu_info(int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - memset(uci, 0, sizeof(*uci)); - if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig)) - uci->valid = 1; -} - -static int microcode_resume_cpu(int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - struct cpu_signature nsig; - - pr_debug("microcode: CPU%d resumed\n", cpu); - - if (!uci->mc.valid_mc) - return 1; - - /* - * Let's verify that the 'cached' ucode does belong - * to this cpu (a bit of paranoia): - */ - if (microcode_ops->collect_cpu_info(cpu, &nsig)) { - microcode_fini_cpu(cpu); - return -1; - } - - if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { - microcode_fini_cpu(cpu); - /* Should we look for a new ucode here? */ - return 1; - } - - return 0; -} - -void microcode_update_cpu(int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - int err = 0; - - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu); - - mutex_lock(µcode_mutex); - /* - * Check if the system resume is in progress (uci->valid != NULL), - * otherwise just request a firmware: - */ - if (uci->valid) { - err = microcode_resume_cpu(cpu); - } else { - collect_cpu_info(cpu); - if (uci->valid && system_state == SYSTEM_RUNNING) - err = microcode_ops->request_microcode_fw(cpu, - µcode_pdev->dev); - } - - if (!err) - microcode_ops->apply_microcode(cpu); - - mutex_unlock(µcode_mutex); -} - -static void microcode_init_cpu(int cpu) -{ - cpumask_t old = current->cpus_allowed; - - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - microcode_update_cpu(cpu); - set_cpus_allowed_ptr(current, &old); -} - -static int mc_sysdev_add(struct sys_device *sys_dev) -{ - int err, cpu = sys_dev->id; - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d added\n", cpu); - memset(uci, 0, sizeof(*uci)); - - err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); - if (err) - return err; - - microcode_init_cpu(cpu); - return 0; -} - -static int mc_sysdev_remove(struct sys_device *sys_dev) -{ - int cpu = sys_dev->id; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d removed\n", cpu); - microcode_fini_cpu(cpu); - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - return 0; -} - -static int mc_sysdev_resume(struct sys_device *dev) -{ - int cpu = dev->id; - - if (!cpu_online(cpu)) - return 0; - - /* only CPU 0 will apply ucode here */ - microcode_update_cpu(0); - return 0; -} - -static struct sysdev_driver mc_sysdev_driver = { - .add = mc_sysdev_add, - .remove = mc_sysdev_remove, - .resume = mc_sysdev_resume, -}; - -static __cpuinit int -mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - struct sys_device *sys_dev; - - sys_dev = get_cpu_sysdev(cpu); - switch (action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - microcode_init_cpu(cpu); - case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: - pr_debug("microcode: CPU%d added\n", cpu); - if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) - printk(KERN_ERR "microcode: Failed to create the sysfs " - "group for CPU%d\n", cpu); - break; - case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: - /* Suspend is in progress, only remove the interface */ - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - pr_debug("microcode: CPU%d removed\n", cpu); - break; - case CPU_DEAD: - case CPU_UP_CANCELED_FROZEN: - /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block __refdata mc_cpu_notifier = { - .notifier_call = mc_cpu_callback, -}; - -int microcode_init(void *opaque, struct module *module) -{ - struct microcode_ops *ops = (struct microcode_ops *)opaque; - int error; - - if (microcode_ops) { - printk(KERN_ERR "microcode: already loaded the other module\n"); - return -EEXIST; - } - - microcode_ops = ops; - - error = microcode_dev_init(); - if (error) - return error; - microcode_pdev = platform_device_register_simple("microcode", -1, - NULL, 0); - if (IS_ERR(microcode_pdev)) { - microcode_dev_exit(); - return PTR_ERR(microcode_pdev); - } - - get_online_cpus(); - error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - if (error) { - microcode_dev_exit(); - platform_device_unregister(microcode_pdev); - return error; - } - - register_hotcpu_notifier(&mc_cpu_notifier); - - printk(KERN_INFO - "Microcode Update Driver: v" MICROCODE_VERSION - " " - " \n"); - - return 0; -} -EXPORT_SYMBOL_GPL(microcode_init); - -void __exit microcode_exit(void) -{ - microcode_dev_exit(); - - unregister_hotcpu_notifier(&mc_cpu_notifier); - - get_online_cpus(); - sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - - platform_device_unregister(microcode_pdev); - - microcode_ops = NULL; - - printk(KERN_INFO - "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); -} -EXPORT_SYMBOL_GPL(microcode_exit); diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 48aec9f48e4..03ea4e52e87 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -46,6 +46,35 @@ MODULE_LICENSE("GPL v2"); #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 #define UCODE_UCODE_TYPE 0x00000001 +struct equiv_cpu_entry { + unsigned int installed_cpu; + unsigned int fixed_errata_mask; + unsigned int fixed_errata_compare; + unsigned int equiv_cpu; +}; + +struct microcode_header_amd { + unsigned int data_code; + unsigned int patch_id; + unsigned char mc_patch_data_id[2]; + unsigned char mc_patch_data_len; + unsigned char init_flag; + unsigned int mc_patch_data_checksum; + unsigned int nb_dev_id; + unsigned int sb_dev_id; + unsigned char processor_rev_id[2]; + unsigned char nb_rev_id; + unsigned char sb_rev_id; + unsigned char bios_api_rev; + unsigned char reserved1[3]; + unsigned int match_reg[8]; +}; + +struct microcode_amd { + struct microcode_header_amd hdr; + unsigned int mpb[0]; +}; + #define UCODE_MAX_SIZE (2048) #define DEFAULT_UCODE_DATASIZE (896) #define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) @@ -189,17 +218,18 @@ static void apply_microcode_amd(int cpu) unsigned int rev; int cpu_num = raw_smp_processor_id(); struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + struct microcode_amd *mc_amd = uci->mc; unsigned long addr; /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); - if (uci->mc.mc_amd == NULL) + if (mc_amd == NULL) return; spin_lock_irqsave(µcode_update_lock, flags); - addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code; + addr = (unsigned long)&mc_amd->hdr.data_code; edx = (unsigned int)(((unsigned long)upper_32_bits(addr))); eax = (unsigned int)(((unsigned long)lower_32_bits(addr))); @@ -214,16 +244,16 @@ static void apply_microcode_amd(int cpu) spin_unlock_irqrestore(µcode_update_lock, flags); /* check current patch id and patch's id for match */ - if (rev != uci->mc.mc_amd->hdr.patch_id) { + if (rev != mc_amd->hdr.patch_id) { printk(KERN_ERR "microcode: CPU%d update from revision " "0x%x to 0x%x failed\n", cpu_num, - uci->mc.mc_amd->hdr.patch_id, rev); + mc_amd->hdr.patch_id, rev); return; } printk(KERN_INFO "microcode: CPU%d updated from revision " "0x%x to 0x%x \n", - cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id); + cpu_num, uci->cpu_sig.rev, mc_amd->hdr.patch_id); uci->cpu_sig.rev = rev; } @@ -355,12 +385,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size, if (new_mc) { if (!leftover) { - if (uci->mc.mc_amd) - vfree(uci->mc.mc_amd); - uci->mc.mc_amd = (struct microcode_amd *)new_mc; + if (uci->mc) + vfree(uci->mc); + uci->mc = new_mc; pr_debug("microcode: CPU%d found a matching microcode update with" " version 0x%x (current=0x%x)\n", - cpu, uci->mc.mc_amd->hdr.patch_id, uci->cpu_sig.rev); + cpu, new_rev, uci->cpu_sig.rev); } else vfree(new_mc); } @@ -416,8 +446,8 @@ static void microcode_fini_cpu_amd(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - vfree(uci->mc.mc_amd); - uci->mc.mc_amd = NULL; + vfree(uci->mc); + uci->mc = NULL; } static struct microcode_ops microcode_amd_ops = { @@ -428,23 +458,7 @@ static struct microcode_ops microcode_amd_ops = { .microcode_fini_cpu = microcode_fini_cpu_amd, }; -static int __init microcode_amd_module_init(void) +struct microcode_ops * __init init_amd_microcode(void) { - struct cpuinfo_x86 *c = &cpu_data(0); - - equiv_cpu_table = NULL; - if (c->x86_vendor != X86_VENDOR_AMD) { - printk(KERN_ERR "microcode: CPU platform is not AMD-capable\n"); - return -ENODEV; - } - - return microcode_init(µcode_amd_ops, THIS_MODULE); -} - -static void __exit microcode_amd_module_exit(void) -{ - microcode_exit(); + return µcode_amd_ops; } - -module_init(microcode_amd_module_init) -module_exit(microcode_amd_module_exit) diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c new file mode 100644 index 00000000000..ff031dbccdf --- /dev/null +++ b/arch/x86/kernel/microcode_core.c @@ -0,0 +1,509 @@ +/* + * Intel CPU Microcode Update Driver for Linux + * + * Copyright (C) 2000-2006 Tigran Aivazian + * 2006 Shaohua Li + * + * This driver allows to upgrade microcode on Intel processors + * belonging to IA-32 family - PentiumPro, Pentium II, + * Pentium III, Xeon, Pentium 4, etc. + * + * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture + * Software Developer's Manual + * Order Number 253668 or free download from: + * + * http://developer.intel.com/design/pentium4/manuals/253668.htm + * + * For more information, go to http://www.urbanmyth.org/microcode + * + * 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. + * + * 1.0 16 Feb 2000, Tigran Aivazian + * Initial release. + * 1.01 18 Feb 2000, Tigran Aivazian + * Added read() support + cleanups. + * 1.02 21 Feb 2000, Tigran Aivazian + * Added 'device trimming' support. open(O_WRONLY) zeroes + * and frees the saved copy of applied microcode. + * 1.03 29 Feb 2000, Tigran Aivazian + * Made to use devfs (/dev/cpu/microcode) + cleanups. + * 1.04 06 Jun 2000, Simon Trimmer + * Added misc device support (now uses both devfs and misc). + * Added MICROCODE_IOCFREE ioctl to clear memory. + * 1.05 09 Jun 2000, Simon Trimmer + * Messages for error cases (non Intel & no suitable microcode). + * 1.06 03 Aug 2000, Tigran Aivazian + * Removed ->release(). Removed exclusive open and status bitmap. + * Added microcode_rwsem to serialize read()/write()/ioctl(). + * Removed global kernel lock usage. + * 1.07 07 Sep 2000, Tigran Aivazian + * Write 0 to 0x8B msr and then cpuid before reading revision, + * so that it works even if there were no update done by the + * BIOS. Otherwise, reading from 0x8B gives junk (which happened + * to be 0 on my machine which is why it worked even when I + * disabled update by the BIOS) + * Thanks to Eric W. Biederman for the fix. + * 1.08 11 Dec 2000, Richard Schaal and + * Tigran Aivazian + * Intel Pentium 4 processor support and bugfixes. + * 1.09 30 Oct 2001, Tigran Aivazian + * Bugfix for HT (Hyper-Threading) enabled processors + * whereby processor resources are shared by all logical processors + * in a single CPU package. + * 1.10 28 Feb 2002 Asit K Mallick and + * Tigran Aivazian , + * Serialize updates as required on HT processors due to + * speculative nature of implementation. + * 1.11 22 Mar 2002 Tigran Aivazian + * Fix the panic when writing zero-length microcode chunk. + * 1.12 29 Sep 2003 Nitin Kamble , + * Jun Nakajima + * Support for the microcode updates in the new format. + * 1.13 10 Oct 2003 Tigran Aivazian + * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl + * because we no longer hold a copy of applied microcode + * in kernel memory. + * 1.14 25 Jun 2004 Tigran Aivazian + * Fix sigmatch() macro to handle old CPUs with pf == 0. + * Thanks to Stuart Swales for pointing out this bug. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +MODULE_DESCRIPTION("Microcode Update Driver"); +MODULE_AUTHOR("Tigran Aivazian "); +MODULE_LICENSE("GPL"); + +#define MICROCODE_VERSION "2.00" + +struct microcode_ops *microcode_ops; + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +static DEFINE_MUTEX(microcode_mutex); + +struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +EXPORT_SYMBOL_GPL(ucode_cpu_info); + +#ifdef CONFIG_MICROCODE_OLD_INTERFACE +static int do_microcode_update(const void __user *buf, size_t size) +{ + cpumask_t old; + int error = 0; + int cpu; + + old = current->cpus_allowed; + + for_each_online_cpu(cpu) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!uci->valid) + continue; + + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); + error = microcode_ops->request_microcode_user(cpu, buf, size); + if (error < 0) + goto out; + if (!error) + microcode_ops->apply_microcode(cpu); + } +out: + set_cpus_allowed_ptr(current, &old); + return error; +} + +static int microcode_open(struct inode *unused1, struct file *unused2) +{ + cycle_kernel_lock(); + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +static ssize_t microcode_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + + if ((len >> PAGE_SHIFT) > num_physpages) { + printk(KERN_ERR "microcode: too much data (max %ld pages)\n", + num_physpages); + return -EINVAL; + } + + get_online_cpus(); + mutex_lock(µcode_mutex); + + ret = do_microcode_update(buf, len); + if (!ret) + ret = (ssize_t)len; + + mutex_unlock(µcode_mutex); + put_online_cpus(); + + return ret; +} + +static const struct file_operations microcode_fops = { + .owner = THIS_MODULE, + .write = microcode_write, + .open = microcode_open, +}; + +static struct miscdevice microcode_dev = { + .minor = MICROCODE_MINOR, + .name = "microcode", + .fops = µcode_fops, +}; + +static int __init microcode_dev_init(void) +{ + int error; + + error = misc_register(µcode_dev); + if (error) { + printk(KERN_ERR + "microcode: can't misc_register on minor=%d\n", + MICROCODE_MINOR); + return error; + } + + return 0; +} + +static void microcode_dev_exit(void) +{ + misc_deregister(µcode_dev); +} + +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); +#else +#define microcode_dev_init() 0 +#define microcode_dev_exit() do { } while (0) +#endif + +/* fake device for request_firmware */ +struct platform_device *microcode_pdev; + +static ssize_t reload_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t sz) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + char *end; + unsigned long val = simple_strtoul(buf, &end, 0); + int err = 0; + int cpu = dev->id; + + if (end == buf) + return -EINVAL; + if (val == 1) { + cpumask_t old = current->cpus_allowed; + + get_online_cpus(); + if (cpu_online(cpu)) { + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); + mutex_lock(µcode_mutex); + if (uci->valid) { + err = microcode_ops->request_microcode_fw(cpu, + µcode_pdev->dev); + if (!err) + microcode_ops->apply_microcode(cpu); + } + mutex_unlock(µcode_mutex); + set_cpus_allowed_ptr(current, &old); + } + put_online_cpus(); + } + if (err) + return err; + return sz; +} + +static ssize_t version_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->cpu_sig.rev); +} + +static ssize_t pf_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); +} + +static SYSDEV_ATTR(reload, 0200, NULL, reload_store); +static SYSDEV_ATTR(version, 0400, version_show, NULL); +static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); + +static struct attribute *mc_default_attrs[] = { + &attr_reload.attr, + &attr_version.attr, + &attr_processor_flags.attr, + NULL +}; + +static struct attribute_group mc_attr_group = { + .attrs = mc_default_attrs, + .name = "microcode", +}; + +static void microcode_fini_cpu(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + mutex_lock(µcode_mutex); + microcode_ops->microcode_fini_cpu(cpu); + uci->valid = 0; + mutex_unlock(µcode_mutex); +} + +static void collect_cpu_info(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + memset(uci, 0, sizeof(*uci)); + if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig)) + uci->valid = 1; +} + +static int microcode_resume_cpu(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct cpu_signature nsig; + + pr_debug("microcode: CPU%d resumed\n", cpu); + + if (!uci->mc) + return 1; + + /* + * Let's verify that the 'cached' ucode does belong + * to this cpu (a bit of paranoia): + */ + if (microcode_ops->collect_cpu_info(cpu, &nsig)) { + microcode_fini_cpu(cpu); + return -1; + } + + if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { + microcode_fini_cpu(cpu); + /* Should we look for a new ucode here? */ + return 1; + } + + return 0; +} + +void microcode_update_cpu(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + int err = 0; + + /* We should bind the task to the CPU */ + BUG_ON(raw_smp_processor_id() != cpu); + + mutex_lock(µcode_mutex); + /* + * Check if the system resume is in progress (uci->valid != NULL), + * otherwise just request a firmware: + */ + if (uci->valid) { + err = microcode_resume_cpu(cpu); + } else { + collect_cpu_info(cpu); + if (uci->valid && system_state == SYSTEM_RUNNING) + err = microcode_ops->request_microcode_fw(cpu, + µcode_pdev->dev); + } + + if (!err) + microcode_ops->apply_microcode(cpu); + + mutex_unlock(µcode_mutex); +} + +static void microcode_init_cpu(int cpu) +{ + cpumask_t old = current->cpus_allowed; + + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); + microcode_update_cpu(cpu); + set_cpus_allowed_ptr(current, &old); +} + +static int mc_sysdev_add(struct sys_device *sys_dev) +{ + int err, cpu = sys_dev->id; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d added\n", cpu); + memset(uci, 0, sizeof(*uci)); + + err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); + if (err) + return err; + + microcode_init_cpu(cpu); + return 0; +} + +static int mc_sysdev_remove(struct sys_device *sys_dev) +{ + int cpu = sys_dev->id; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d removed\n", cpu); + microcode_fini_cpu(cpu); + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + return 0; +} + +static int mc_sysdev_resume(struct sys_device *dev) +{ + int cpu = dev->id; + + if (!cpu_online(cpu)) + return 0; + + /* only CPU 0 will apply ucode here */ + microcode_update_cpu(0); + return 0; +} + +static struct sysdev_driver mc_sysdev_driver = { + .add = mc_sysdev_add, + .remove = mc_sysdev_remove, + .resume = mc_sysdev_resume, +}; + +static __cpuinit int +mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + microcode_init_cpu(cpu); + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: + pr_debug("microcode: CPU%d added\n", cpu); + if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) + printk(KERN_ERR "microcode: Failed to create the sysfs " + "group for CPU%d\n", cpu); + break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + /* Suspend is in progress, only remove the interface */ + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + pr_debug("microcode: CPU%d removed\n", cpu); + break; + case CPU_DEAD: + case CPU_UP_CANCELED_FROZEN: + /* The CPU refused to come up during a system resume */ + microcode_fini_cpu(cpu); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __refdata mc_cpu_notifier = { + .notifier_call = mc_cpu_callback, +}; + +static int __init microcode_init(void) +{ + struct cpuinfo_x86 *c = &cpu_data(0); + int error; + + if (c->x86_vendor == X86_VENDOR_INTEL) + microcode_ops = init_intel_microcode(); + else if (c->x86_vendor != X86_VENDOR_AMD) + microcode_ops = init_amd_microcode(); + + if (!microcode_ops) { + printk(KERN_ERR "microcode: no support for this CPU vendor\n"); + return -ENODEV; + } + + error = microcode_dev_init(); + if (error) + return error; + microcode_pdev = platform_device_register_simple("microcode", -1, + NULL, 0); + if (IS_ERR(microcode_pdev)) { + microcode_dev_exit(); + return PTR_ERR(microcode_pdev); + } + + get_online_cpus(); + error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + if (error) { + microcode_dev_exit(); + platform_device_unregister(microcode_pdev); + return error; + } + + register_hotcpu_notifier(&mc_cpu_notifier); + + printk(KERN_INFO + "Microcode Update Driver: v" MICROCODE_VERSION + " " + " \n"); + + return 0; +} + +static void __exit microcode_exit(void) +{ + microcode_dev_exit(); + + unregister_hotcpu_notifier(&mc_cpu_notifier); + + get_online_cpus(); + sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + + platform_device_unregister(microcode_pdev); + + microcode_ops = NULL; + + printk(KERN_INFO + "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); +} + +module_init(microcode_init); +module_exit(microcode_exit); diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 48ed3cef58c..622dc4a2178 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -97,6 +97,38 @@ MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); +struct microcode_header_intel { + unsigned int hdrver; + unsigned int rev; + unsigned int date; + unsigned int sig; + unsigned int cksum; + unsigned int ldrver; + unsigned int pf; + unsigned int datasize; + unsigned int totalsize; + unsigned int reserved[3]; +}; + +struct microcode_intel { + struct microcode_header_intel hdr; + unsigned int bits[0]; +}; + +/* microcode format is extended from prescott processors */ +struct extended_signature { + unsigned int sig; + unsigned int pf; + unsigned int cksum; +}; + +struct extended_sigtable { + unsigned int count; + unsigned int cksum; + unsigned int reserved[3]; + struct extended_signature sigs[0]; +}; + #define DEFAULT_UCODE_DATASIZE (2000) #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) @@ -284,11 +316,12 @@ static void apply_microcode(int cpu) unsigned int val[2]; int cpu_num = raw_smp_processor_id(); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct microcode_intel *mc_intel = uci->mc; /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); - if (uci->mc.mc_intel == NULL) + if (mc_intel == NULL) return; /* serialize access to the physical write to MSR 0x79 */ @@ -296,8 +329,8 @@ static void apply_microcode(int cpu) /* write microcode via MSR 0x79 */ wrmsr(MSR_IA32_UCODE_WRITE, - (unsigned long) uci->mc.mc_intel->bits, - (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16); + (unsigned long) mc_intel->bits, + (unsigned long) mc_intel->bits >> 16 >> 16); wrmsr(MSR_IA32_UCODE_REV, 0, 0); /* see notes above for revision 1.07. Apparent chip bug */ @@ -307,7 +340,7 @@ static void apply_microcode(int cpu) rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); spin_unlock_irqrestore(µcode_update_lock, flags); - if (val[1] != uci->mc.mc_intel->hdr.rev) { + if (val[1] != mc_intel->hdr.rev) { printk(KERN_ERR "microcode: CPU%d update from revision " "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); return; @@ -315,9 +348,9 @@ static void apply_microcode(int cpu) printk(KERN_INFO "microcode: CPU%d updated from revision " "0x%x to 0x%x, date = %04x-%02x-%02x \n", cpu_num, uci->cpu_sig.rev, val[1], - uci->mc.mc_intel->hdr.date & 0xffff, - uci->mc.mc_intel->hdr.date >> 24, - (uci->mc.mc_intel->hdr.date >> 16) & 0xff); + mc_intel->hdr.date & 0xffff, + mc_intel->hdr.date >> 24, + (mc_intel->hdr.date >> 16) & 0xff); uci->cpu_sig.rev = val[1]; } @@ -367,12 +400,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size, if (new_mc) { if (!leftover) { - if (uci->mc.mc_intel) - vfree(uci->mc.mc_intel); - uci->mc.mc_intel = (struct microcode_intel *)new_mc; + if (uci->mc) + vfree(uci->mc); + uci->mc = (struct microcode_intel *)new_mc; pr_debug("microcode: CPU%d found a matching microcode update with" " version 0x%x (current=0x%x)\n", - cpu, uci->mc.mc_intel->hdr.rev, uci->cpu_sig.rev); + cpu, new_rev, uci->cpu_sig.rev); } else vfree(new_mc); } @@ -428,11 +461,11 @@ static void microcode_fini_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - vfree(uci->mc.mc_intel); - uci->mc.mc_intel = NULL; + vfree(uci->mc); + uci->mc = NULL; } -static struct microcode_ops microcode_intel_ops = { +struct microcode_ops microcode_intel_ops = { .request_microcode_user = request_microcode_user, .request_microcode_fw = request_microcode_fw, .collect_cpu_info = collect_cpu_info, @@ -440,22 +473,8 @@ static struct microcode_ops microcode_intel_ops = { .microcode_fini_cpu = microcode_fini_cpu, }; -static int __init microcode_intel_module_init(void) -{ - struct cpuinfo_x86 *c = &cpu_data(0); - - if (c->x86_vendor != X86_VENDOR_INTEL) { - printk(KERN_ERR "microcode: CPU platform is not Intel-capable\n"); - return -ENODEV; - } - - return microcode_init(µcode_intel_ops, THIS_MODULE); -} - -static void __exit microcode_intel_module_exit(void) +struct microcode_ops * __init init_intel_microcode(void) { - microcode_exit(); + return µcode_intel_ops; } -module_init(microcode_intel_module_init) -module_exit(microcode_intel_module_exit) -- cgit v1.2.3 From da654b74bda14c45a7d98c731bf3c1a43b6b74e2 Mon Sep 17 00:00:00 2001 From: Srinivasa Ds Date: Tue, 23 Sep 2008 15:23:52 +0530 Subject: signals: demultiplexing SIGTRAP signal Currently a SIGTRAP can denote any one of below reasons. - Breakpoint hit - H/W debug register hit - Single step - Signal sent through kill() or rasie() Architectures like powerpc/parisc provides infrastructure to demultiplex SIGTRAP signal by passing down the information for receiving SIGTRAP through si_code of siginfot_t structure. Here is an attempt is generalise this infrastructure by extending it to x86 and x86_64 archs. Signed-off-by: Srinivasa DS Cc: Roland McGrath Cc: akpm@linux-foundation.org Cc: paulus@samba.org Cc: linuxppc-dev@ozlabs.org Signed-off-by: Ingo Molnar --- arch/ia64/include/asm/siginfo.h | 5 ----- arch/powerpc/include/asm/siginfo.h | 5 ----- arch/x86/kernel/ptrace.c | 7 ++++--- arch/x86/kernel/traps_32.c | 4 +++- arch/x86/kernel/traps_64.c | 2 +- 5 files changed, 8 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/siginfo.h b/arch/ia64/include/asm/siginfo.h index 9294e4b0c8b..118d4297900 100644 --- a/arch/ia64/include/asm/siginfo.h +++ b/arch/ia64/include/asm/siginfo.h @@ -113,11 +113,6 @@ typedef struct siginfo { #undef NSIGSEGV #define NSIGSEGV 3 -/* - * SIGTRAP si_codes - */ -#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ -#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */ #undef NSIGTRAP #define NSIGTRAP 4 diff --git a/arch/powerpc/include/asm/siginfo.h b/arch/powerpc/include/asm/siginfo.h index 12f1bce037b..49495b0534e 100644 --- a/arch/powerpc/include/asm/siginfo.h +++ b/arch/powerpc/include/asm/siginfo.h @@ -15,11 +15,6 @@ #include -/* - * SIGTRAP si_codes - */ -#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ -#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */ #undef NSIGTRAP #define NSIGTRAP 4 diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 9e43a48ad6e..bf45cdf1aac 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -1358,7 +1358,8 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) #endif } -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code, int si_code) { struct siginfo info; @@ -1367,7 +1368,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) memset(&info, 0, sizeof(info)); info.si_signo = SIGTRAP; - info.si_code = TRAP_BRKPT; + info.si_code = si_code; /* User-mode ip? */ info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; @@ -1454,5 +1455,5 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) */ if (test_thread_flag(TIF_SINGLESTEP) && tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) - send_sigtrap(current, regs, 0); + send_sigtrap(current, regs, 0, TRAP_BRKPT); } diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index da5a5964fcc..0429c5de5ea 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -891,6 +891,7 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) { struct task_struct *tsk = current; unsigned int condition; + int si_code; trace_hardirqs_fixup(); @@ -935,8 +936,9 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) goto clear_TF_reenable; } + si_code = get_si_code((unsigned long)condition); /* Ok, finally something we can handle */ - send_sigtrap(tsk, regs, error_code); + send_sigtrap(tsk, regs, error_code, si_code); /* * Disable additional traps. They'll be re-enabled when diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 56d6f114778..011d8e1fac6 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -941,7 +941,7 @@ asmlinkage void __kprobes do_debug(struct pt_regs *regs, tsk->thread.error_code = error_code; info.si_signo = SIGTRAP; info.si_errno = 0; - info.si_code = TRAP_BRKPT; + info.si_code = get_si_code(condition); info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; force_sig_info(SIGTRAP, &info, tsk); -- cgit v1.2.3 From b6cffde1a20409f9720d5c9aba28d3efd3a4f04e Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Wed, 17 Sep 2008 15:05:52 +0200 Subject: x86, microcode rework, v2, renaming Renaming based on patch from Dmitry Adamushko. Made code more readable by renaming define and variables related to microcode _container_file_ header to make it distinguishable from microcode _patch_ header. Signed-off-by: Peter Oruba Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 03ea4e52e87..62058e9c8b4 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -304,12 +304,12 @@ static void * get_next_ucode(u8 *buf, unsigned int size, static int install_equiv_cpu_table(u8 *buf, int (*get_ucode_data)(void *, const void *, size_t)) { -#define UCODE_HEADER_SIZE 12 - u8 *hdr[UCODE_HEADER_SIZE]; - unsigned int *buf_pos = (unsigned int *)hdr; +#define UCODE_CONTAINER_HEADER_SIZE 12 + u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE]; + unsigned int *buf_pos = (unsigned int *)container_hdr; unsigned long size; - if (get_ucode_data(&hdr, buf, UCODE_HEADER_SIZE)) + if (get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE)) return 0; size = buf_pos[2]; @@ -326,14 +326,14 @@ static int install_equiv_cpu_table(u8 *buf, return 0; } - buf += UCODE_HEADER_SIZE; + buf += UCODE_CONTAINER_HEADER_SIZE; if (get_ucode_data(equiv_cpu_table, buf, size)) { vfree(equiv_cpu_table); return 0; } - return size + UCODE_HEADER_SIZE; /* add header length */ -#undef UCODE_HEADER_SIZE + return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */ +#undef UCODE_CONTAINER_HEADER_SIZE } static void free_equiv_cpu_table(void) -- cgit v1.2.3 From d4738792fb86600b6cb7220459d9c47e819b3580 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Wed, 17 Sep 2008 15:39:18 +0200 Subject: x86, microcode rework, v2, renaming cont. Renaming based on patch from Dmitry Adamushko. Further clarification by renaming define and variable related to microcode container file. Signed-off-by: Peter Oruba Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 62058e9c8b4..829415208ff 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -263,21 +263,20 @@ static void * get_next_ucode(u8 *buf, unsigned int size, unsigned int *mc_size) { unsigned int total_size; -#define UCODE_UNKNOWN_HDR 8 - u8 hdr[UCODE_UNKNOWN_HDR]; +#define UCODE_CONTAINER_SECTION_HDR 8 + u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; void *mc; - if (get_ucode_data(hdr, buf, UCODE_UNKNOWN_HDR)) + if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR)) return NULL; - if (hdr[0] != UCODE_UCODE_TYPE) { + if (section_hdr[0] != UCODE_UCODE_TYPE) { printk(KERN_ERR "microcode: error! " "Wrong microcode payload type field\n"); return NULL; } - /* FIXME! dimm: Why not by means of get_totalsize(hdr)? */ - total_size = (unsigned long) (hdr[4] + (hdr[5] << 8)); + total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); printk(KERN_INFO "microcode: size %u, total_size %u\n", size, total_size); @@ -290,13 +289,13 @@ static void * get_next_ucode(u8 *buf, unsigned int size, mc = vmalloc(UCODE_MAX_SIZE); if (mc) { memset(mc, 0, UCODE_MAX_SIZE); - if (get_ucode_data(mc, buf + UCODE_UNKNOWN_HDR, total_size)) { + if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size)) { vfree(mc); mc = NULL; } else - *mc_size = total_size + UCODE_UNKNOWN_HDR; + *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; } -#undef UCODE_UNKNOWN_HDR +#undef UCODE_CONTAINER_SECTION_HDR return mc; } -- cgit v1.2.3 From 5fd933303bd1efacbd0acbe452ba9b889440eb40 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 23 Sep 2008 17:19:44 -0700 Subject: x86: signal: cosmetic unification of do_signal() Make do_signal() same. Thia patch modifies only comments in signal_64.c. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_64.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index bf77d4789a2..5a5fbc3b1ee 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -410,7 +410,8 @@ static void do_signal(struct pt_regs *regs) signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - /* Re-enable any watchpoints before delivering the + /* + * Re-enable any watchpoints before delivering the * signal to user space. The processor register will * have been cleared if the watchpoint triggered * inside the kernel. @@ -418,7 +419,7 @@ static void do_signal(struct pt_regs *regs) if (current->thread.debugreg7) set_debugreg(current->thread.debugreg7, 7); - /* Whee! Actually deliver the signal. */ + /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { /* * A signal was successfully delivered; the saved @@ -441,6 +442,7 @@ static void do_signal(struct pt_regs *regs) regs->ax = regs->orig_ax; regs->ip -= 2; break; + case -ERESTART_RESTARTBLOCK: regs->ax = NR_restart_syscall; regs->ip -= 2; -- cgit v1.2.3 From ee847c54ba7fc09f85f13a5bf18f45ea6c19aa83 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 23 Sep 2008 17:21:45 -0700 Subject: x86: signal: cosmetic unification of do_notify_resume() Make do_notify_resume() same. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 8 ++++++++ arch/x86/kernel/signal_64.c | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index da3cf3270f8..b94463f264b 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -663,6 +663,12 @@ static void do_signal(struct pt_regs *regs) void do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) { +#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE) + /* notify userspace of pending MCEs */ + if (thread_info_flags & _TIF_MCE_NOTIFY) + mce_notify_user(); +#endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ + /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); @@ -672,7 +678,9 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) tracehook_notify_resume(regs); } +#ifdef CONFIG_X86_32 clear_thread_flag(TIF_IRET); +#endif /* CONFIG_X86_32 */ } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 5a5fbc3b1ee..9087752f410 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -460,14 +460,18 @@ static void do_signal(struct pt_regs *regs) } } -void do_notify_resume(struct pt_regs *regs, void *unused, - __u32 thread_info_flags) +/* + * notification of userspace execution resumption + * - triggered by the TIF_WORK_MASK flags + */ +void +do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) { -#ifdef CONFIG_X86_MCE +#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE) /* notify userspace of pending MCEs */ if (thread_info_flags & _TIF_MCE_NOTIFY) mce_notify_user(); -#endif /* CONFIG_X86_MCE */ +#endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) @@ -477,6 +481,10 @@ void do_notify_resume(struct pt_regs *regs, void *unused, clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); } + +#ifdef CONFIG_X86_32 + clear_thread_flag(TIF_IRET); +#endif /* CONFIG_X86_32 */ } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) -- cgit v1.2.3 From 86d3237cd1a09136b4fb3a1d73d3c3fd6331cb14 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 23 Sep 2008 17:22:32 -0700 Subject: x86: signal: cosmetic unification of handle_signal() Make handle_signal() same. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 9 +++++++++ arch/x86/kernel/signal_64.c | 2 ++ 2 files changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index b94463f264b..bb05917f232 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -550,6 +550,15 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, if (ret) return ret; +#ifdef CONFIG_X86_64 + /* + * This has nothing to do with segment registers, + * despite the name. This magic affects uaccess.h + * macros' behavior. Reset it to the normal setting. + */ + set_fs(USER_DS); +#endif + /* * Clear the direction flag as per the ABI for function entry. */ diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 9087752f410..963236f2c3c 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -346,12 +346,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, if (ret) return ret; +#ifdef CONFIG_X86_64 /* * This has nothing to do with segment registers, * despite the name. This magic affects uaccess.h * macros' behavior. Reset it to the normal setting. */ set_fs(USER_DS); +#endif /* * Clear the direction flag as per the ABI for function entry. -- cgit v1.2.3 From 493cd9122af5bd0b219974a48f0e31da0c29ff7e Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 23 Sep 2008 14:56:44 -0700 Subject: x86: ds.c ptrace.c integer as NULL pointer sparse fixes fix: arch/x86/kernel/ptrace.c:763:29: warning: Using plain integer as NULL pointer arch/x86/kernel/ptrace.c:777:46: warning: Using plain integer as NULL pointer arch/x86/kernel/ptrace.c:1115:45: warning: Using plain integer as NULL pointer arch/x86/kernel/ds.c:482:26: warning: Using plain integer as NULL pointer arch/x86/kernel/ds.c:487:25: warning: Using plain integer as NULL pointer Signed-off-by: Harvey Harrison Acked-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/ds.c | 4 ++-- arch/x86/kernel/ptrace.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index ab21c270bfa..2b69994fd3a 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -479,12 +479,12 @@ static int ds_release(struct task_struct *task, enum ds_qualifier qual) goto out; kfree(context->buffer[qual]); - context->buffer[qual] = 0; + context->buffer[qual] = NULL; current->mm->total_vm -= context->pages[qual]; current->mm->locked_vm -= context->pages[qual]; context->pages[qual] = 0; - context->owner[qual] = 0; + context->owner[qual] = NULL; /* * we put the context twice: diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index ba19bb49bd0..5df6093ac77 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -734,7 +734,7 @@ static int ptrace_bts_config(struct task_struct *child, goto errout; if (cfg.flags & PTRACE_BTS_O_ALLOC) { - ds_ovfl_callback_t ovfl = 0; + ds_ovfl_callback_t ovfl = NULL; unsigned int sig = 0; /* we ignore the error in case we were not tracing child */ @@ -748,7 +748,7 @@ static int ptrace_bts_config(struct task_struct *child, ovfl = ptrace_bts_ovfl; } - error = ds_request_bts(child, /* base = */ 0, cfg.size, ovfl); + error = ds_request_bts(child, /* base = */ NULL, cfg.size, ovfl); if (error < 0) goto errout; @@ -1086,7 +1086,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_BTS_SIZE: - ret = ds_get_bts_index(child, /* pos = */ 0); + ret = ds_get_bts_index(child, /* pos = */ NULL); break; case PTRACE_BTS_GET: -- cgit v1.2.3 From e51a1ac2dfca9ad869471e88f828281db7e810c0 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 23 Sep 2008 15:20:09 -0700 Subject: x86, olpc: fix endian bug in openfirmware workaround Boardrev is always treated as a u32 everywhere else, no reason to byteswap the 0xc2 value. The only use is to print out if it is a prerelease board, the test being: (olpc_platform_info.boardrev & 0xf) < 8 Which is currently always true as be32_to_cpu(0xc2) & 0xf = 0 but I doubt that was the intention here. The consequences of the bug are pretty minor though (incorrect boardrev displayed in dmesg when ofw support not configured) Also annotate the temporary used to read the boardrev in the ofw case. The confusion was noticed by Sparse: arch/x86/kernel/olpc.c:206:32: warning: cast to restricted __be32 Signed-off-by: Harvey Harrison Signed-off-by: Ingo Molnar --- arch/x86/kernel/olpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c index 3e667227480..7a13fac63a1 100644 --- a/arch/x86/kernel/olpc.c +++ b/arch/x86/kernel/olpc.c @@ -190,12 +190,12 @@ EXPORT_SYMBOL_GPL(olpc_ec_cmd); static void __init platform_detect(void) { size_t propsize; - u32 rev; + __be32 rev; if (ofw("getprop", 4, 1, NULL, "board-revision-int", &rev, 4, &propsize) || propsize != 4) { printk(KERN_ERR "ofw: getprop call failed!\n"); - rev = 0; + rev = cpu_to_be32(0); } olpc_platform_info.boardrev = be32_to_cpu(rev); } @@ -203,7 +203,7 @@ static void __init platform_detect(void) static void __init platform_detect(void) { /* stopgap until OFW support is added to the kernel */ - olpc_platform_info.boardrev = be32_to_cpu(0xc2); + olpc_platform_info.boardrev = 0xc2; } #endif -- cgit v1.2.3 From 2f9284e4e3be7b0b4d8d0638f9805603069a762d Mon Sep 17 00:00:00 2001 From: Dmitry Adamushko Date: Tue, 23 Sep 2008 22:56:35 +0200 Subject: x86, microcode_amd: cleanup, mark request_microcode_user() as unsupported (1) mark mc_size in generic_load_microcode() as unitialized_var to avoid gcc's (false) warning; (2) mark request_microcode_user() as unsupported. The required changes can be added later. Note, we don't break any user-space interfaces here, as there were no kernels with support for AMD-specific ucode update yet. The ucode has to be updated via 'firmware'. Signed-off-by: Dmitry Adamushko Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 829415208ff..7a1f8eeac2c 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -120,29 +120,7 @@ static int get_matching_microcode(int cpu, void *mc, int rev) unsigned int equiv_cpu_id = 0x00; unsigned int i = 0; - /* - * FIXME! dimm: do we need this? Why an update via /dev/... is different - * from the one via firmware? - * - * This is a tricky part. We might be called from a write operation - * to the device file instead of the usual process of firmware - * loading. This routine needs to be able to distinguish both - * cases. This is done by checking if there alread is a equivalent - * CPU table installed. If not, we're written through - * /dev/cpu/microcode. - * Since we ignore all checks. The error case in which going through - * firmware loading and that table is not loaded has already been - * checked earlier. - */ BUG_ON(equiv_cpu_table == NULL); -#if 0 - if (equiv_cpu_table == NULL) { - printk(KERN_INFO "microcode: CPU%d microcode update with " - "version 0x%x (current=0x%x)\n", - cpu, mc_header->patch_id, uci->cpu_sig.rev); - goto out; - } -#endif current_cpu_id = cpuid_eax(0x00000001); while (equiv_cpu_table[i].installed_cpu != 0) { @@ -362,7 +340,7 @@ static int generic_load_microcode(int cpu, void *data, size_t size, leftover = size - offset; while (leftover) { - unsigned int mc_size; + unsigned int uninitialized_var(mc_size); struct microcode_header_amd *mc_header; mc = get_next_ucode(ucode_ptr, leftover, get_ucode_data, &mc_size); @@ -428,17 +406,11 @@ static int request_microcode_fw(int cpu, struct device *device) return ret; } -static int get_ucode_user(void *to, const void *from, size_t n) -{ - return copy_from_user(to, from, n); -} - static int request_microcode_user(int cpu, const void __user *buf, size_t size) { - /* We should bind the task to the CPU */ - BUG_ON(cpu != raw_smp_processor_id()); - - return generic_load_microcode(cpu, (void*)buf, size, &get_ucode_user); + printk(KERN_WARNING "microcode: AMD microcode update via /dev/cpu/microcode" + "is not supported\n"); + return -1; } static void microcode_fini_cpu_amd(int cpu) -- cgit v1.2.3 From 82b078659ed04e1ecdebf8326e189cf76ed361af Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Wed, 24 Sep 2008 11:50:35 +0200 Subject: x86: microcode patch loader bugfix Corrected CPU vendor check condition for AMD microcode patch loader initialization. Signed-off-by: Peter Oruba Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index ff031dbccdf..8db2eb55e9e 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -450,7 +450,7 @@ static int __init microcode_init(void) if (c->x86_vendor == X86_VENDOR_INTEL) microcode_ops = init_intel_microcode(); - else if (c->x86_vendor != X86_VENDOR_AMD) + else if (c->x86_vendor == X86_VENDOR_AMD) microcode_ops = init_amd_microcode(); if (!microcode_ops) { -- cgit v1.2.3 From 8d8c13bdb53977319593d9efc4971a4cacc8bd03 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 24 Sep 2008 19:10:29 -0700 Subject: x86: signal_32.c: introduce signr_convert() Introduce signr_convert(). This function will help unification of setup_rt_frame(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index bb05917f232..b1bc90f19b9 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -482,18 +482,21 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* * OK, we're invoking a handler: */ +static int signr_convert(int sig) +{ + struct thread_info *info = current_thread_info(); + + if (info->exec_domain && info->exec_domain->signal_invmap && sig < 32) + return info->exec_domain->signal_invmap[sig]; + return sig; +} + static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { + int usig = signr_convert(sig); int ret; - int usig; - - usig = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) -- cgit v1.2.3 From b94fd69827b2104a2a4d9d0bc05a8e908a937ae8 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 24 Sep 2008 19:12:54 -0700 Subject: x86: signal_64.c: introduce helper function signr_convert() This helper function is for unification of setup_rt_frame(). No effect in binary. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_64.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 963236f2c3c..c5d80024a8f 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -281,18 +281,24 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* * OK, we're invoking a handler */ +static int signr_convert(int sig) +{ + return sig; +} + static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { + int usig = signr_convert(sig); int ret; #ifdef CONFIG_IA32_EMULATION if (test_thread_flag(TIF_IA32)) { if (ka->sa.sa_flags & SA_SIGINFO) - ret = ia32_setup_rt_frame(sig, ka, info, set, regs); + ret = ia32_setup_rt_frame(usig, ka, info, set, regs); else - ret = ia32_setup_frame(sig, ka, set, regs); + ret = ia32_setup_frame(usig, ka, set, regs); } else #endif ret = __setup_rt_frame(sig, ka, info, set, regs); -- cgit v1.2.3 From 455edbc423db282bb64dec2d7c8968498ea8e619 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 24 Sep 2008 19:13:11 -0700 Subject: x86: signal: introduce helper macro is_ia32 Introduce new macro is_ia32 for unification of setup_rt_frame(). No effect in binary, compiler will optimize. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 13 +++++++++---- arch/x86/kernel/signal_64.c | 13 +++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index b1bc90f19b9..cf62f70cc2a 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -491,6 +491,8 @@ static int signr_convert(int sig) return sig; } +#define is_ia32 1 + static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) @@ -499,10 +501,13 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, int ret; /* Set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - ret = __setup_rt_frame(usig, ka, info, set, regs); - else - ret = __setup_frame(usig, ka, set, regs); + if (is_ia32) { + if (ka->sa.sa_flags & SA_SIGINFO) + ret = __setup_rt_frame(usig, ka, info, set, regs); + else + ret = __setup_frame(usig, ka, set, regs); + } else + ret = __setup_rt_frame(sig, ka, info, set, regs); if (ret) { force_sigsegv(sig, current); diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index c5d80024a8f..53f86d95985 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -286,6 +286,12 @@ static int signr_convert(int sig) return sig; } +#ifdef CONFIG_IA32_EMULATION +#define is_ia32 test_thread_flag(TIF_IA32) +#else +#define is_ia32 0 +#endif + static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) @@ -293,15 +299,14 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, int usig = signr_convert(sig); int ret; -#ifdef CONFIG_IA32_EMULATION - if (test_thread_flag(TIF_IA32)) { + /* Set up the stack frame */ + if (is_ia32) { if (ka->sa.sa_flags & SA_SIGINFO) ret = ia32_setup_rt_frame(usig, ka, info, set, regs); else ret = ia32_setup_frame(usig, ka, set, regs); } else -#endif - ret = __setup_rt_frame(sig, ka, info, set, regs); + ret = __setup_rt_frame(sig, ka, info, set, regs); if (ret) { force_sigsegv(sig, current); -- cgit v1.2.3 From 4694d2391221e14fe671602fe34ea7f24f5a561f Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 24 Sep 2008 19:13:29 -0700 Subject: x86: signal_32.c: introduce macro ia32_setup_frame and ia32_setup_rt_frame Make 32-bit setup_rt_frame() look like 64-bit version for unification. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index cf62f70cc2a..4337cd510f0 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -492,6 +492,8 @@ static int signr_convert(int sig) } #define is_ia32 1 +#define ia32_setup_frame __setup_frame +#define ia32_setup_rt_frame __setup_rt_frame static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -503,9 +505,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up the stack frame */ if (is_ia32) { if (ka->sa.sa_flags & SA_SIGINFO) - ret = __setup_rt_frame(usig, ka, info, set, regs); + ret = ia32_setup_rt_frame(usig, ka, info, set, regs); else - ret = __setup_frame(usig, ka, set, regs); + ret = ia32_setup_frame(usig, ka, set, regs); } else ret = __setup_rt_frame(sig, ka, info, set, regs); -- cgit v1.2.3 From 9f6ac57729724b58df81ca5dc005326759a806fe Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 24 Sep 2008 20:48:35 +0900 Subject: x86: export pci-nommu's alloc_coherent This patch exports nommu_alloc_coherent (renamed dma_generic_alloc_coherent). GART needs this function. Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-dma.c | 31 +++++++++++++++++++++++++++++++ arch/x86/kernel/pci-nommu.c | 39 +-------------------------------------- 2 files changed, 32 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0a1408abcc6..4e612d20170 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -134,6 +134,37 @@ unsigned long iommu_num_pages(unsigned long addr, unsigned long len) EXPORT_SYMBOL(iommu_num_pages); #endif +void *dma_generic_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_addr, gfp_t flag) +{ + unsigned long dma_mask; + struct page *page; + dma_addr_t addr; + + dma_mask = dma_alloc_coherent_mask(dev, flag); + + flag |= __GFP_ZERO; +again: + page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); + if (!page) + return NULL; + + addr = page_to_phys(page); + if (!is_buffer_dma_capable(dma_mask, addr, size)) { + __free_pages(page, get_order(size)); + + if (dma_mask < DMA_32BIT_MASK && !(flag & GFP_DMA)) { + flag = (flag & ~GFP_DMA32) | GFP_DMA; + goto again; + } + + return NULL; + } + + *dma_addr = addr; + return page_address(page); +} + /* * See for the iommu kernel parameter * documentation. diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 1c1c98a31d5..c70ab5a5d4c 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -72,43 +72,6 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, return nents; } -static void * -nommu_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_addr, gfp_t gfp) -{ - unsigned long dma_mask; - int node; - struct page *page; - dma_addr_t addr; - - dma_mask = dma_alloc_coherent_mask(hwdev, gfp); - - gfp |= __GFP_ZERO; - - node = dev_to_node(hwdev); -again: - page = alloc_pages_node(node, gfp, get_order(size)); - if (!page) - return NULL; - - addr = page_to_phys(page); - if (!is_buffer_dma_capable(dma_mask, addr, size) && !(gfp & GFP_DMA)) { - free_pages((unsigned long)page_address(page), get_order(size)); - gfp |= GFP_DMA; - goto again; - } - - if (check_addr("alloc_coherent", hwdev, addr, size)) { - *dma_addr = addr; - flush_write_buffers(); - return page_address(page); - } - - free_pages((unsigned long)page_address(page), get_order(size)); - - return NULL; -} - static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_addr) { @@ -116,7 +79,7 @@ static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, } struct dma_mapping_ops nommu_dma_ops = { - .alloc_coherent = nommu_alloc_coherent, + .alloc_coherent = dma_generic_alloc_coherent, .free_coherent = nommu_free_coherent, .map_single = nommu_map_single, .map_sg = nommu_map_sg, -- cgit v1.2.3 From ecef533ea68b2fb3baaf459beb2f802a240bdb16 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 24 Sep 2008 20:48:36 +0900 Subject: revert "x86: make GART to respect device's dma_mask about virtual mappings" This reverts: commit bee44f294efd8417f5e68553778a6cc957af1547 Author: FUJITA Tomonori Date: Fri Sep 12 19:42:35 2008 +0900 x86: make GART to respect device's dma_mask about virtual mappings I wrote the above commit to fix a GART alloc_coherent regression, that can't handle a device having dma_masks > 24bit < 32bits, introduced by the alloc_coherent rewrite: http://lkml.org/lkml/2008/8/12/200 After the alloc_coherent rewrite, GART alloc_coherent tried to allocate pages with GFP_DMA32. If GART got an address that a device can't access to, GART mapped the address to a virtual I/O address. But GART mapping mechanism didn't take account of dma mask, so GART could use a virtual I/O address that the device can't access to again. Alan pointed out: " This is indeed a specific problem found with things like older AACRAID where control blocks must be below 31bits and the GART is above 0x80000000. " The above commit modified GART mapping mechanism to take care of dma mask. But Andi pointed out, "The GART is somewhere in the 4GB range so you cannot use it to map anything < 4GB. Also GART is pretty small." http://lkml.org/lkml/2008/9/12/43 That means it's possible that GART doesn't have virtual I/O address space that a device can access to. The above commit (to modify GART mapping mechanism to take care of dma mask) can't fix the regression reliably so let's avoid making GART more complicated. We need a solution that always works for dma_masks > 24bit < 32bits. That's how GART worked before the alloc_coherent rewrite. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Acked-by: Alan Cox Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 9e390f1bd46..7e08e466b8a 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -83,34 +83,23 @@ static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ static unsigned long alloc_iommu(struct device *dev, int size, - unsigned long align_mask, u64 dma_mask) + unsigned long align_mask) { unsigned long offset, flags; unsigned long boundary_size; unsigned long base_index; - unsigned long limit; base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), PAGE_SIZE) >> PAGE_SHIFT; boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, PAGE_SIZE) >> PAGE_SHIFT; - limit = iommu_device_max_index(iommu_pages, - DIV_ROUND_UP(iommu_bus_base, PAGE_SIZE), - dma_mask >> PAGE_SHIFT); - spin_lock_irqsave(&iommu_bitmap_lock, flags); - - if (limit <= next_bit) { - need_flush = 1; - next_bit = 0; - } - - offset = iommu_area_alloc(iommu_gart_bitmap, limit, next_bit, + offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, size, base_index, boundary_size, align_mask); - if (offset == -1 && next_bit) { + if (offset == -1) { need_flush = 1; - offset = iommu_area_alloc(iommu_gart_bitmap, limit, 0, + offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, size, base_index, boundary_size, align_mask); } @@ -239,14 +228,12 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) * Caller needs to check if the iommu is needed and flush. */ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, - size_t size, int dir, unsigned long align_mask, - u64 dma_mask) + size_t size, int dir, unsigned long align_mask) { unsigned long npages = iommu_num_pages(phys_mem, size); - unsigned long iommu_page; + unsigned long iommu_page = alloc_iommu(dev, npages, align_mask); int i; - iommu_page = alloc_iommu(dev, npages, align_mask, dma_mask); if (iommu_page == -1) { if (!nonforced_iommu(dev, phys_mem, size)) return phys_mem; @@ -276,7 +263,7 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) if (!need_iommu(dev, paddr, size)) return paddr; - bus = dma_map_area(dev, paddr, size, dir, 0, dma_get_mask(dev)); + bus = dma_map_area(dev, paddr, size, dir, 0); flush_gart(); return bus; @@ -327,7 +314,6 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, { struct scatterlist *s; int i; - u64 dma_mask = dma_get_mask(dev); #ifdef CONFIG_IOMMU_DEBUG printk(KERN_DEBUG "dma_map_sg overflow\n"); @@ -337,8 +323,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, unsigned long addr = sg_phys(s); if (nonforced_iommu(dev, addr, s->length)) { - addr = dma_map_area(dev, addr, s->length, dir, 0, - dma_mask); + addr = dma_map_area(dev, addr, s->length, dir, 0); if (addr == bad_dma_address) { if (i > 0) gart_unmap_sg(dev, sg, i, dir); @@ -360,16 +345,14 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, int nelems, struct scatterlist *sout, unsigned long pages) { - unsigned long iommu_start; - unsigned long iommu_page; + unsigned long iommu_start = alloc_iommu(dev, pages, 0); + unsigned long iommu_page = iommu_start; struct scatterlist *s; int i; - iommu_start = alloc_iommu(dev, pages, 0, dma_get_mask(dev)); if (iommu_start == -1) return -1; - iommu_page = iommu_start; for_each_sg(start, s, nelems, i) { unsigned long pages, addr; unsigned long phys_addr = s->dma_address; @@ -522,7 +505,7 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, align_mask = (1UL << get_order(size)) - 1; *dma_addr = dma_map_area(dev, paddr, size, DMA_BIDIRECTIONAL, - align_mask, dma_mask); + align_mask); flush_gart(); if (*dma_addr != bad_dma_address) -- cgit v1.2.3 From 1d990882153f36723f9e8717c4401689e64c7a36 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 24 Sep 2008 20:48:37 +0900 Subject: x86: restore old GART alloc_coherent behavior Currently, GART alloc_coherent tries to allocate pages with GFP_DMA32 for a device having dma_masks > 24bit < 32bits. If GART gets an address that a device can't access to, GART try to map the address to a virtual I/O address that the device can access to. But Andi pointed out, "The GART is somewhere in the 4GB range so you cannot use it to map anything < 4GB. Also GART is pretty small." http://lkml.org/lkml/2008/9/12/43 That is, it's possible that GART doesn't have virtual I/O address space that a device can access to. The above behavior doesn't work for a device having dma_masks > 24bit < 32bits. This patch restores old GART alloc_coherent behavior (before the alloc_coherent rewrite). Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 7e08e466b8a..25c94fb96d7 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -487,31 +487,28 @@ static void * gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, gfp_t flag) { - void *vaddr; dma_addr_t paddr; unsigned long align_mask; - u64 dma_mask = dma_alloc_coherent_mask(dev, flag); - - vaddr = (void *)__get_free_pages(flag | __GFP_ZERO, get_order(size)); - if (!vaddr) - return NULL; - - paddr = virt_to_phys(vaddr); - if (is_buffer_dma_capable(dma_mask, paddr, size)) { - *dma_addr = paddr; - return vaddr; - } - - align_mask = (1UL << get_order(size)) - 1; - - *dma_addr = dma_map_area(dev, paddr, size, DMA_BIDIRECTIONAL, - align_mask); - flush_gart(); - - if (*dma_addr != bad_dma_address) - return vaddr; - - free_pages((unsigned long)vaddr, get_order(size)); + struct page *page; + + if (force_iommu && !(flag & GFP_DMA)) { + flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + page = alloc_pages(flag | __GFP_ZERO, get_order(size)); + if (!page) + return NULL; + + align_mask = (1UL << get_order(size)) - 1; + paddr = dma_map_area(dev, page_to_phys(page), size, + DMA_BIDIRECTIONAL, align_mask); + + flush_gart(); + if (paddr != bad_dma_address) { + *dma_addr = paddr; + return page_address(page); + } + __free_pages(page, get_order(size)); + } else + return dma_generic_alloc_coherent(dev, size, dma_addr, flag); return NULL; } -- cgit v1.2.3 From 1615965e54eb94d7bcd298d2163739bd79f602d4 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 24 Sep 2008 22:41:10 +0900 Subject: x86 gart: remove unnecessary initialization There is no point to have such initialization in struct dma_mapping_ops. Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 25c94fb96d7..b85a2f9bb34 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -715,12 +715,6 @@ extern int agp_amd64_init(void); static struct dma_mapping_ops gart_dma_ops = { .map_single = gart_map_single, .unmap_single = gart_unmap_single, - .sync_single_for_cpu = NULL, - .sync_single_for_device = NULL, - .sync_single_range_for_cpu = NULL, - .sync_single_range_for_device = NULL, - .sync_sg_for_cpu = NULL, - .sync_sg_for_device = NULL, .map_sg = gart_map_sg, .unmap_sg = gart_unmap_sg, .alloc_coherent = gart_alloc_coherent, -- cgit v1.2.3 From f6476774f1fe32593d3d71903b1e98514efbf685 Mon Sep 17 00:00:00 2001 From: Bill Nottingham Date: Wed, 24 Sep 2008 14:35:17 -0400 Subject: x86_64: be less annoying on boot Remove mostly useless message on every boot. Signed-off-by: Bill Nottingham Signed-off-by: Ingo Molnar --- arch/x86/kernel/head64.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 9bfc4d72fb2..11aa501c9f4 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -112,8 +112,6 @@ void __init x86_64_start_kernel(char * real_mode_data) x86_64_init_pda(); - early_printk("Kernel really alive\n"); - x86_64_start_reservations(real_mode_data); } -- cgit v1.2.3 From 7fc2368d1d0dce7a778beb2fba3acac8fa7a34b6 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 27 Sep 2008 00:30:07 -0700 Subject: x86: don't need to go to chunksize to 4G change back chunksize max to 2g otherwise will get strange layout in 2G ram system like 0 - 4g WB, 2040M - 2048M UC, 2048M - 4G NC instead of 0 - 2g WB, 2040M - 2048M UC Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index b117d7f8a56..cc135572882 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1155,10 +1155,10 @@ struct mtrr_cleanup_result { /* * gran_size: 1M, 2M, ..., 2G - * chunk size: gran_size, ..., 4G - * so we need (2+13)*6 + * chunk size: gran_size, ..., 2G + * so we need (1+12)*6 */ -#define NUM_RESULT 90 +#define NUM_RESULT 78 #define PSHIFT (PAGE_SHIFT - 10) static struct mtrr_cleanup_result __initdata result[NUM_RESULT]; @@ -1276,7 +1276,7 @@ static int __init mtrr_cleanup(unsigned address_bits) memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn)); memset(result, 0, sizeof(result)); for (gran_size = (1ULL<<20); gran_size < (1ULL<<32); gran_size <<= 1) { - for (chunk_size = gran_size; chunk_size < (1ULL<<33); + for (chunk_size = gran_size; chunk_size < (1ULL<<32); chunk_size <<= 1) { int num_reg; -- cgit v1.2.3 From 2313c2793d290a8cc37c428f8622c53f3fe1d6dc Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 27 Sep 2008 00:30:08 -0700 Subject: x86: mtrr_cleanup optimization, v2 fix hpa's t61 with 4g ram: change layout from (n - 1)*chunksize + chunk_size - NC to n*chunksize - NC Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 79 +++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 42 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index cc135572882..93d575ac61a 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -970,6 +970,8 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, /* try to append some small hole */ range0_basek = state->range_startk; range0_sizek = ALIGN(state->range_sizek, chunk_sizek); + + /* no increase */ if (range0_sizek == state->range_sizek) { if (debug_print) printk(KERN_DEBUG "rangeX: %016lx - %016lx\n", @@ -980,13 +982,13 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, return 0; } - range0_sizek -= chunk_sizek; - if (range0_sizek && sizek) { - while (range0_basek + range0_sizek > (basek + sizek)) { - range0_sizek -= chunk_sizek; - if (!range0_sizek) - break; - } + /* only cut back, when it is not the last */ + if (sizek) { + while (range0_basek + range0_sizek > (basek + sizek)) { + range0_sizek -= chunk_sizek; + if (!range0_sizek) + break; + } } if (range0_sizek) { @@ -1000,46 +1002,39 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, } range_basek = range0_basek + range0_sizek; - range_sizek = chunk_sizek; - if (range_basek + range_sizek > basek && - range_basek + range_sizek <= (basek + sizek)) { - /* one hole */ - second_basek = basek; - second_sizek = range_basek + range_sizek - basek; - } + /* one hole in the middle */ + if (range_basek > basek && range_basek <= (basek + sizek)) + second_sizek = range_basek - basek; - /* if last piece, only could one hole near end */ - if ((second_basek || !basek) && - range_sizek - (state->range_sizek - range0_sizek) - second_sizek < - (chunk_sizek >> 1)) { - /* - * one hole in middle (second_sizek is 0) or at end - * (second_sizek is 0 ) - */ - hole_sizek = range_sizek - (state->range_sizek - range0_sizek) - - second_sizek; - hole_basek = range_basek + range_sizek - hole_sizek - - second_sizek; - } else { - /* fallback for big hole, or several holes */ + if (range0_sizek > state->range_sizek) { + unsigned long hole_basek, hole_sizek; + + /* one hole in middle or at end */ + hole_sizek = range0_sizek - state->range_sizek - second_sizek; + if (hole_sizek) { + hole_basek = range_basek - hole_sizek - second_sizek; + if (debug_print) + printk(KERN_DEBUG "hole: %016lx - %016lx\n", + hole_basek<<10, + (hole_basek + hole_sizek)<<10); + state->reg = range_to_mtrr(state->reg, hole_basek, + hole_sizek, + MTRR_TYPE_UNCACHABLE); + } + } else { + /* need to handle left over */ range_sizek = state->range_sizek - range0_sizek; - second_basek = 0; - second_sizek = 0; - } - if (debug_print) - printk(KERN_DEBUG "range: %016lx - %016lx\n", range_basek<<10, - (range_basek + range_sizek)<<10); - state->reg = range_to_mtrr(state->reg, range_basek, range_sizek, + if (range_sizek) { + if (debug_print) + printk(KERN_DEBUG "range: %016lx - %016lx\n", + range_basek<<10, + (range_basek + range_sizek)<<10); + state->reg = range_to_mtrr(state->reg, range_basek, + range_sizek, MTRR_TYPE_WRBACK); - if (hole_sizek) { - if (debug_print) - printk(KERN_DEBUG "hole: %016lx - %016lx\n", - hole_basek<<10, (hole_basek + hole_sizek)<<10); - state->reg = range_to_mtrr(state->reg, hole_basek, hole_sizek, - MTRR_TYPE_UNCACHABLE); - + } } return second_sizek; -- cgit v1.2.3 From 54d45ff4208836e62536fc40b0141586dbf6641f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 27 Sep 2008 00:30:06 -0700 Subject: x86: add mtrr_cleanup_debug command line add mtrr_cleanup_debug to print out more info about layout Signed-off-by: Yinghai Lu Cc: Yinghai Lu Cc: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 93d575ac61a..aff46b99ff0 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -836,6 +836,13 @@ static int __init enable_mtrr_cleanup_setup(char *str) } early_param("enble_mtrr_cleanup", enable_mtrr_cleanup_setup); +static int __init mtrr_cleanup_debug_setup(char *str) +{ + debug_print = 1; + return 0; +} +early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup); + struct var_mtrr_state { unsigned long range_startk; unsigned long range_sizek; @@ -1227,7 +1234,7 @@ static int __init mtrr_cleanup(unsigned address_bits) if (mtrr_chunk_size && mtrr_gran_size) { int num_reg; - debug_print = 1; + debug_print++; /* convert ranges to var ranges state */ num_reg = x86_setup_var_mtrrs(range, nr_range, mtrr_chunk_size, mtrr_gran_size); @@ -1263,7 +1270,7 @@ static int __init mtrr_cleanup(unsigned address_bits) } printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, " "will find optimal one\n"); - debug_print = 0; + debug_print--; memset(result, 0, sizeof(result[0])); } @@ -1366,8 +1373,9 @@ static int __init mtrr_cleanup(unsigned address_bits) chunk_size <<= 10; gran_size = result[i].gran_sizek; gran_size <<= 10; - debug_print = 1; + debug_print++; x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size); + debug_print--; set_var_mtrr_all(address_bits); return 1; } -- cgit v1.2.3 From 237a62247c2879331986a300d6ab36ad21264c68 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Sep 2008 12:13:53 +0200 Subject: x86/iommu: make GART driver checkpatch clean Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index b85a2f9bb34..aa569db73a2 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -27,8 +27,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -175,7 +175,8 @@ static void dump_leak(void) iommu_leak_pages); for (i = 0; i < iommu_leak_pages; i += 2) { printk(KERN_DEBUG "%lu: ", iommu_pages-i); - printk_address((unsigned long) iommu_leak_tab[iommu_pages-i], 0); + printk_address((unsigned long) iommu_leak_tab[iommu_pages-i], + 0); printk(KERN_CONT "%c", (i+1)%2 == 0 ? '\n' : ' '); } printk(KERN_DEBUG "\n"); @@ -688,7 +689,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info) if (!error) error = sysdev_register(&device_gart); if (error) - panic("Could not register gart_sysdev -- would corrupt data on next suspend"); + panic("Could not register gart_sysdev -- " + "would corrupt data on next suspend"); flush_gart(); @@ -710,8 +712,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info) return -1; } -extern int agp_amd64_init(void); - static struct dma_mapping_ops gart_dma_ops = { .map_single = gart_map_single, .unmap_single = gart_unmap_single, @@ -777,8 +777,8 @@ void __init gart_iommu_init(void) (no_agp && init_k8_gatt(&info) < 0)) { if (max_pfn > MAX_DMA32_PFN) { printk(KERN_WARNING "More than 4GB of memory " - "but GART IOMMU not available.\n" - KERN_WARNING "falling back to iommu=soft.\n"); + "but GART IOMMU not available.\n"); + printk(KERN_WARNING "falling back to iommu=soft.\n"); } return; } @@ -868,7 +868,8 @@ void __init gart_parse_options(char *p) if (!strncmp(p, "leak", 4)) { leak_trace = 1; p += 4; - if (*p == '=') ++p; + if (*p == '=') + ++p; if (isdigit(*p) && get_option(&p, &arg)) iommu_leak_pages = arg; } -- cgit v1.2.3 From 3610f2116e961cdcbd3546a3828470f7aa636212 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Sep 2008 12:13:54 +0200 Subject: x86/iommu: convert GART need_flush to bool Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index aa569db73a2..aecea068f58 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -80,7 +80,7 @@ AGPEXTERN int agp_memory_reserved; AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ -static int need_flush; /* global flush state. set for each gart wrap */ +static bool need_flush; /* global flush state. set for each gart wrap */ static unsigned long alloc_iommu(struct device *dev, int size, unsigned long align_mask) @@ -98,7 +98,7 @@ static unsigned long alloc_iommu(struct device *dev, int size, offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, size, base_index, boundary_size, align_mask); if (offset == -1) { - need_flush = 1; + need_flush = true; offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, size, base_index, boundary_size, align_mask); @@ -107,11 +107,11 @@ static unsigned long alloc_iommu(struct device *dev, int size, next_bit = offset+size; if (next_bit >= iommu_pages) { next_bit = 0; - need_flush = 1; + need_flush = true; } } if (iommu_fullflush) - need_flush = 1; + need_flush = true; spin_unlock_irqrestore(&iommu_bitmap_lock, flags); return offset; @@ -136,7 +136,7 @@ static void flush_gart(void) spin_lock_irqsave(&iommu_bitmap_lock, flags); if (need_flush) { k8_flush_garts(); - need_flush = 0; + need_flush = false; } spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } -- cgit v1.2.3 From 0114267be1bebc2e9c913b19579900153583d617 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Sep 2008 12:42:12 +0200 Subject: x86/iommu: use __GFP_ZERO instead of memset for GART Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index aecea068f58..d077116fec1 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -674,13 +674,13 @@ static __init int init_k8_gatt(struct agp_kern_info *info) info->aper_size = aper_size >> 20; gatt_size = (aper_size >> PAGE_SHIFT) * sizeof(u32); - gatt = (void *)__get_free_pages(GFP_KERNEL, get_order(gatt_size)); + gatt = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(gatt_size)); if (!gatt) panic("Cannot allocate GATT table"); if (set_memory_uc((unsigned long)gatt, gatt_size >> PAGE_SHIFT)) panic("Could not set GART PTEs to uncacheable pages"); - memset(gatt, 0, gatt_size); agp_gatt_table = gatt; enable_gart_translations(); @@ -788,19 +788,16 @@ void __init gart_iommu_init(void) iommu_size = check_iommu_size(info.aper_base, aper_size); iommu_pages = iommu_size >> PAGE_SHIFT; - iommu_gart_bitmap = (void *) __get_free_pages(GFP_KERNEL, + iommu_gart_bitmap = (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(iommu_pages/8)); if (!iommu_gart_bitmap) panic("Cannot allocate iommu bitmap\n"); - memset(iommu_gart_bitmap, 0, iommu_pages/8); #ifdef CONFIG_IOMMU_LEAK if (leak_trace) { - iommu_leak_tab = (void *)__get_free_pages(GFP_KERNEL, + iommu_leak_tab = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, get_order(iommu_pages*sizeof(void *))); - if (iommu_leak_tab) - memset(iommu_leak_tab, 0, iommu_pages * 8); - else + if (!iommu_leak_tab) printk(KERN_DEBUG "PCI-DMA: Cannot allocate leak trace area\n"); } -- cgit v1.2.3 From 8f0afaa58e912bbe7d5b0bad9fb024337edf363e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 27 Sep 2008 20:26:06 -0700 Subject: x86: mtrr_cleanup hole size should be less than half of chunk_size, v2 v2: should check with half of range0 size instead of chunk_size So don't have silly big hole. in hpa's case we could auto detect instead of adding mtrr_chunk_size in command line. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 74 ++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index aff46b99ff0..bccf57f5b61 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -992,22 +992,17 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, /* only cut back, when it is not the last */ if (sizek) { while (range0_basek + range0_sizek > (basek + sizek)) { - range0_sizek -= chunk_sizek; + if (range0_sizek >= chunk_sizek) + range0_sizek -= chunk_sizek; + else + range0_sizek = 0; + if (!range0_sizek) break; } } - if (range0_sizek) { - if (debug_print) - printk(KERN_DEBUG "range0: %016lx - %016lx\n", - range0_basek<<10, - (range0_basek + range0_sizek)<<10); - state->reg = range_to_mtrr(state->reg, range0_basek, - range0_sizek, MTRR_TYPE_WRBACK); - - } - +second_try: range_basek = range0_basek + range0_sizek; /* one hole in the middle */ @@ -1015,33 +1010,50 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, second_sizek = range_basek - basek; if (range0_sizek > state->range_sizek) { - unsigned long hole_basek, hole_sizek; /* one hole in middle or at end */ hole_sizek = range0_sizek - state->range_sizek - second_sizek; - if (hole_sizek) { - hole_basek = range_basek - hole_sizek - second_sizek; - if (debug_print) - printk(KERN_DEBUG "hole: %016lx - %016lx\n", - hole_basek<<10, - (hole_basek + hole_sizek)<<10); - state->reg = range_to_mtrr(state->reg, hole_basek, - hole_sizek, - MTRR_TYPE_UNCACHABLE); + + /* hole size should be less than half of range0 size */ + if (hole_sizek > (range0_sizek >> 1) && + range0_sizek >= chunk_sizek) { + range0_sizek -= chunk_sizek; + second_sizek = 0; + hole_sizek = 0; + + goto second_try; } - } else { + } + + if (range0_sizek) { + if (debug_print) + printk(KERN_DEBUG "range0: %016lx - %016lx\n", + range0_basek<<10, + (range0_basek + range0_sizek)<<10); + state->reg = range_to_mtrr(state->reg, range0_basek, + range0_sizek, MTRR_TYPE_WRBACK); + } + + if (range0_sizek < state->range_sizek) { /* need to handle left over */ range_sizek = state->range_sizek - range0_sizek; - if (range_sizek) { - if (debug_print) - printk(KERN_DEBUG "range: %016lx - %016lx\n", - range_basek<<10, - (range_basek + range_sizek)<<10); - state->reg = range_to_mtrr(state->reg, range_basek, - range_sizek, - MTRR_TYPE_WRBACK); - } + if (debug_print) + printk(KERN_DEBUG "range: %016lx - %016lx\n", + range_basek<<10, + (range_basek + range_sizek)<<10); + state->reg = range_to_mtrr(state->reg, range_basek, + range_sizek, MTRR_TYPE_WRBACK); + } + + if (hole_sizek) { + hole_basek = range_basek - hole_sizek - second_sizek; + if (debug_print) + printk(KERN_DEBUG "hole: %016lx - %016lx\n", + hole_basek<<10, + (hole_basek + hole_sizek)<<10); + state->reg = range_to_mtrr(state->reg, hole_basek, + hole_sizek, MTRR_TYPE_UNCACHABLE); } return second_sizek; -- cgit v1.2.3 From 12544697f12e0ecdcf971075415c7678fae502af Mon Sep 17 00:00:00 2001 From: dcg Date: Sun, 28 Sep 2008 18:49:46 +0200 Subject: x86_64: be less annoying on boot, v2 Honour "quiet" boot parameter in early_printk() calls Signed-off-by: Diego Calleja Signed-off-by: Ingo Molnar --- arch/x86/kernel/head64.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 11aa501c9f4..d16084f9064 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -108,7 +108,8 @@ void __init x86_64_start_kernel(char * real_mode_data) } load_idt((const struct desc_ptr *)&idt_descr); - early_printk("Kernel alive\n"); + if (console_loglevel == 10) + early_printk("Kernel alive\n"); x86_64_init_pda(); -- cgit v1.2.3 From 73436a1d2501575f9c2e6ddb26889145e23cefd8 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 29 Sep 2008 13:39:17 -0700 Subject: x86: mtrr_cleanup safe to get more spare regs now Delay exit to make sure we can actually get the optimal result in as many cases as possible. Signed-off-by: Yinghai Lu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mtrr/main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index bccf57f5b61..ae0ca97e20b 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1353,10 +1353,8 @@ static int __init mtrr_cleanup(unsigned address_bits) nr_mtrr_spare_reg = num_var_ranges - 1; num_reg_good = -1; for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) { - if (!min_loss_pfn[i]) { + if (!min_loss_pfn[i]) num_reg_good = i; - break; - } } index_good = -1; -- cgit v1.2.3 From dd7e52224fd7438d701b4bb9834a9ddc06828210 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 29 Sep 2008 18:54:11 -0700 Subject: x86: mtrr_cleanup prepare to make gran_size to less 1M make the print out right with size < 1M Signed-off-by: Yinghai Lu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mtrr/main.c | 103 ++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index ae0ca97e20b..b1bd1038c91 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -905,6 +905,27 @@ set_var_mtrr_all(unsigned int address_bits) } } +static unsigned long to_size_factor(unsigned long sizek, char *factorp) +{ + char factor; + unsigned long base = sizek; + + if (base & ((1<<10) - 1)) { + /* not MB alignment */ + factor = 'K'; + } else if (base & ((1<<20) - 1)){ + factor = 'M'; + base >>= 10; + } else { + factor = 'G'; + base >>= 20; + } + + *factorp = factor; + + return base; +} + static unsigned int __init range_to_mtrr(unsigned int reg, unsigned long range_startk, unsigned long range_sizek, unsigned char type) @@ -926,13 +947,21 @@ range_to_mtrr(unsigned int reg, unsigned long range_startk, align = max_align; sizek = 1 << align; - if (debug_print) + if (debug_print) { + char start_factor = 'K', size_factor = 'K'; + unsigned long start_base, size_base; + + start_base = to_size_factor(range_startk, &start_factor), + size_base = to_size_factor(sizek, &size_factor), + printk(KERN_DEBUG "Setting variable MTRR %d, " - "base: %ldMB, range: %ldMB, type %s\n", - reg, range_startk >> 10, sizek >> 10, + "base: %ld%cB, range: %ld%cB, type %s\n", + reg, start_base, start_factor, + size_base, size_factor, (type == MTRR_TYPE_UNCACHABLE)?"UC": ((type == MTRR_TYPE_WRBACK)?"WB":"Other") ); + } save_var_mtrr(reg++, range_startk, sizek, type); range_startk += sizek; range_sizek -= sizek; @@ -1245,6 +1274,8 @@ static int __init mtrr_cleanup(unsigned address_bits) if (mtrr_chunk_size && mtrr_gran_size) { int num_reg; + char gran_factor, chunk_factor, lose_factor; + unsigned long gran_base, chunk_base, lose_base; debug_print++; /* convert ranges to var ranges state */ @@ -1270,12 +1301,15 @@ static int __init mtrr_cleanup(unsigned address_bits) result[i].lose_cover_sizek = (range_sums - range_sums_new) << PSHIFT; - printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", - result[i].bad?"*BAD*":" ", result[i].gran_sizek >> 10, - result[i].chunk_sizek >> 10); - printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ldM \n", + gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), + chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), + lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), + printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t", + result[i].bad?"*BAD*":" ", + gran_base, gran_factor, chunk_base, chunk_factor); + printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n", result[i].num_reg, result[i].bad?"-":"", - result[i].lose_cover_sizek >> 10); + lose_base, lose_factor); if (!result[i].bad) { set_var_mtrr_all(address_bits); return 1; @@ -1290,14 +1324,25 @@ static int __init mtrr_cleanup(unsigned address_bits) memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn)); memset(result, 0, sizeof(result)); for (gran_size = (1ULL<<20); gran_size < (1ULL<<32); gran_size <<= 1) { + char gran_factor; + unsigned long gran_base; + + if (debug_print) + gran_base = to_size_factor(gran_size >> 10, &gran_factor); + for (chunk_size = gran_size; chunk_size < (1ULL<<32); chunk_size <<= 1) { int num_reg; - if (debug_print) - printk(KERN_INFO - "\ngran_size: %lldM chunk_size_size: %lldM\n", - gran_size >> 20, chunk_size >> 20); + if (debug_print) { + char chunk_factor; + unsigned long chunk_base; + + chunk_base = to_size_factor(chunk_size>>10, &chunk_factor), + printk(KERN_INFO "\n"); + printk(KERN_INFO "gran_size: %ld%c chunk_size: %ld%c \n", + gran_base, gran_factor, chunk_base, chunk_factor); + } if (i >= NUM_RESULT) continue; @@ -1340,12 +1385,18 @@ static int __init mtrr_cleanup(unsigned address_bits) /* print out all */ for (i = 0; i < NUM_RESULT; i++) { - printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", - result[i].bad?"*BAD* ":" ", result[i].gran_sizek >> 10, - result[i].chunk_sizek >> 10); - printk(KERN_CONT "num_reg: %d \tlose RAM: %s%ldM\n", - result[i].num_reg, result[i].bad?"-":"", - result[i].lose_cover_sizek >> 10); + char gran_factor, chunk_factor, lose_factor; + unsigned long gran_base, chunk_base, lose_base; + + gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), + chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), + lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), + printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t", + result[i].bad?"*BAD*":" ", + gran_base, gran_factor, chunk_base, chunk_factor); + printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n", + result[i].num_reg, result[i].bad?"-":"", + lose_base, lose_factor); } /* try to find the optimal index */ @@ -1370,14 +1421,18 @@ static int __init mtrr_cleanup(unsigned address_bits) } if (index_good != -1) { + char gran_factor, chunk_factor, lose_factor; + unsigned long gran_base, chunk_base, lose_base; + printk(KERN_INFO "Found optimal setting for mtrr clean up\n"); i = index_good; - printk(KERN_INFO "gran_size: %ldM \tchunk_size: %ldM \t", - result[i].gran_sizek >> 10, - result[i].chunk_sizek >> 10); - printk(KERN_CONT "num_reg: %d \tlose RAM: %ldM\n", - result[i].num_reg, - result[i].lose_cover_sizek >> 10); + gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), + chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), + lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), + printk(KERN_INFO "gran_size: %ld%c \tchunk_size: %ld%c \t", + gran_base, gran_factor, chunk_base, chunk_factor); + printk(KERN_CONT "num_reg: %d \tlose RAM: %ld%c\n", + result[i].num_reg, lose_base, lose_factor); /* convert ranges to var ranges state */ chunk_size = result[i].chunk_sizek; chunk_size <<= 10; -- cgit v1.2.3 From 4624065731751a3ace88e5824d8e5654e2d7abd3 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 29 Sep 2008 18:54:12 -0700 Subject: x86: mtrr_cleanup try gran_size to less than 1M one have gran < 1M reg00: base=0xd8000000 (3456MB), size= 128MB: uncachable, count=1 reg01: base=0xe0000000 (3584MB), size= 512MB: uncachable, count=1 reg02: base=0x00000000 ( 0MB), size=4096MB: write-back, count=1 reg03: base=0x100000000 (4096MB), size= 512MB: write-back, count=1 reg04: base=0x120000000 (4608MB), size= 128MB: write-back, count=1 reg05: base=0xd7f80000 (3455MB), size= 512KB: uncachable, count=1 will get Found optimal setting for mtrr clean up gran_size: 512K chunk_size: 2M num_reg: 7 lose RAM: 0G range0: 0000000000000000 - 00000000d8000000 Setting variable MTRR 0, base: 0GB, range: 2GB, type WB Setting variable MTRR 1, base: 2GB, range: 1GB, type WB Setting variable MTRR 2, base: 3GB, range: 256MB, type WB Setting variable MTRR 3, base: 3328MB, range: 128MB, type WB hole: 00000000d7f00000 - 00000000d7f80000 Setting variable MTRR 4, base: 3455MB, range: 512KB, type UC rangeX: 0000000100000000 - 0000000128000000 Setting variable MTRR 5, base: 4GB, range: 512MB, type WB Setting variable MTRR 6, base: 4608MB, range: 128MB, type WB so start from 64k instead of 1M Signed-off-by: Yinghai Lu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mtrr/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index b1bd1038c91..8f1a342b16b 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1197,11 +1197,11 @@ struct mtrr_cleanup_result { }; /* - * gran_size: 1M, 2M, ..., 2G + * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G * chunk size: gran_size, ..., 2G - * so we need (1+12)*6 + * so we need (1+16)*8 */ -#define NUM_RESULT 78 +#define NUM_RESULT 136 #define PSHIFT (PAGE_SHIFT - 10) static struct mtrr_cleanup_result __initdata result[NUM_RESULT]; @@ -1323,7 +1323,7 @@ static int __init mtrr_cleanup(unsigned address_bits) i = 0; memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn)); memset(result, 0, sizeof(result)); - for (gran_size = (1ULL<<20); gran_size < (1ULL<<32); gran_size <<= 1) { + for (gran_size = (1ULL<<16); gran_size < (1ULL<<32); gran_size <<= 1) { char gran_factor; unsigned long gran_base; -- cgit v1.2.3 From a03352d2c1dcb00970801fb8b800a39acd3103d9 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Mon, 29 Sep 2008 20:19:22 -0700 Subject: x86: export set_memory_ro and set_memory_rw Export set_memory_ro() and set_memory_rw() calls for use by drivers that need to have more debug information about who might be writing to memory space. this was initially developed for use while debugging a memory corruption problem with e1000e. Signed-off-by: Bruce Allan Signed-off-by: Jesse Brandeburg Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 43e2f8483e4..62c1eefcce0 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -906,11 +906,13 @@ int set_memory_ro(unsigned long addr, int numpages) { return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); } +EXPORT_SYMBOL_GPL(set_memory_ro); int set_memory_rw(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); } +EXPORT_SYMBOL_GPL(set_memory_rw); int set_memory_np(unsigned long addr, int numpages) { -- cgit v1.2.3 From 08115ab4d98cb577a83971ebd57cdfbcc6f50b68 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 29 Sep 2008 18:24:23 -0400 Subject: xen: make CONFIG_XEN_SAVE_RESTORE depend on CONFIG_XEN Xen options need to depend on XEN. Also, add newline at end of file. Without this patch you need to disable CONFIG_PM in order to disable CPU hotplugging. Signed-off-by: Chuck Ebbert Acked-by Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index d3e68465ace..87b9ab16642 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig @@ -26,7 +26,7 @@ config XEN_MAX_DOMAIN_MEMORY config XEN_SAVE_RESTORE bool - depends on PM + depends on XEN && PM default y config XEN_DEBUG_FS @@ -35,4 +35,4 @@ config XEN_DEBUG_FS default n help Enable statistics output and various tuning options in debugfs. - Enabling this option may incur a significant performance overhead. \ No newline at end of file + Enabling this option may incur a significant performance overhead. -- cgit v1.2.3 From 9b1568458a3ef006361710dc12848aec891883b5 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 29 Sep 2008 14:52:03 -0400 Subject: x86, debug printouts: IOMMU setup failures should not be KERN_ERR The number of BIOSes that have an option to enable the IOMMU, or fix anything about its configuration, is vanishingly small. There's no good reason to punish quiet boot for this. Signed-off-by: Adam Jackson Signed-off-by: Ingo Molnar --- arch/x86/kernel/aperture_64.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 44e21826db1..9a32b37ee2e 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -455,11 +455,11 @@ out: force_iommu || valid_agp || fallback_aper_force) { - printk(KERN_ERR + printk(KERN_INFO "Your BIOS doesn't leave a aperture memory hole\n"); - printk(KERN_ERR + printk(KERN_INFO "Please enable the IOMMU option in the BIOS setup\n"); - printk(KERN_ERR + printk(KERN_INFO "This costs you %d MB of RAM\n", 32 << fallback_aper_order); -- cgit v1.2.3 From bff0aa4b8f8a1c8492e99c522d044bb98a6ec098 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 30 Sep 2008 20:28:20 -0700 Subject: x86: ia32_signal.c: remove unnecessary cast to u32 __put_user() looks type of the 2nd parameter, so casting the 1st parameter is not necessary. text data bss dec hex filename 6227 0 8 6235 185b ia32_signal.o.new 6227 0 8 6235 185b ia32_signal.o.old Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index e47bed2440e..690a480c68c 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -351,21 +351,21 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, savesegment(es, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->es); - err |= __put_user((u32)regs->di, &sc->di); - err |= __put_user((u32)regs->si, &sc->si); - err |= __put_user((u32)regs->bp, &sc->bp); - err |= __put_user((u32)regs->sp, &sc->sp); - err |= __put_user((u32)regs->bx, &sc->bx); - err |= __put_user((u32)regs->dx, &sc->dx); - err |= __put_user((u32)regs->cx, &sc->cx); - err |= __put_user((u32)regs->ax, &sc->ax); - err |= __put_user((u32)regs->cs, &sc->cs); - err |= __put_user((u32)regs->ss, &sc->ss); + err |= __put_user(regs->di, &sc->di); + err |= __put_user(regs->si, &sc->si); + err |= __put_user(regs->bp, &sc->bp); + err |= __put_user(regs->sp, &sc->sp); + err |= __put_user(regs->bx, &sc->bx); + err |= __put_user(regs->dx, &sc->dx); + err |= __put_user(regs->cx, &sc->cx); + err |= __put_user(regs->ax, &sc->ax); + err |= __put_user(regs->cs, &sc->cs); + err |= __put_user(regs->ss, &sc->ss); err |= __put_user(current->thread.trap_no, &sc->trapno); err |= __put_user(current->thread.error_code, &sc->err); - err |= __put_user((u32)regs->ip, &sc->ip); - err |= __put_user((u32)regs->flags, &sc->flags); - err |= __put_user((u32)regs->sp, &sc->sp_at_signal); + err |= __put_user(regs->ip, &sc->ip); + err |= __put_user(regs->flags, &sc->flags); + err |= __put_user(regs->sp, &sc->sp_at_signal); tmp = save_i387_xstate_ia32(fpstate); if (tmp < 0) -- cgit v1.2.3 From 7b9cee16ffb495558c1e3ada55cba906e520006e Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Tue, 30 Sep 2008 20:30:51 -0700 Subject: x86: ia32_signal.c remove unnecessary function calls the below 2 functions are called in save_i387_xstate_ia32() - clear_used_math(); - stts(); Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 690a480c68c..4bc02b23674 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -370,12 +370,9 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, tmp = save_i387_xstate_ia32(fpstate); if (tmp < 0) err = -EFAULT; - else { - clear_used_math(); - stts(); + else err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL), &sc->fpstate); - } /* non-iBCS2 extensions.. */ err |= __put_user(mask, &sc->oldmask); -- cgit v1.2.3 From 2ffb3501f6f356ff80e7149214bc64d3fa9021c4 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Sep 2008 16:29:40 -0700 Subject: x86: change MTRR_SANITIZER to def_bool y This option has been added in v2.6.26 as a default-disabled feature and went through several revisions since then. The feature fixes a wide range of MTRR setup problems that BIOSes leave us with: slow system, slow Xorg, slow system when adding lots of RAM, etc., so we want to enable it by default for v2.6.28. See: [Bug 10508] Upgrade to 4GB of RAM messes up MTRRs http://bugzilla.kernel.org/show_bug.cgi?id=10508 and the test results in: http://lkml.org/lkml/2008/9/29/273 1. hpa reg00: base=0xc0000000 (3072MB), size=1024MB: uncachable, count=1 reg01: base=0x13c000000 (5056MB), size= 64MB: uncachable, count=1 reg02: base=0x00000000 ( 0MB), size=4096MB: write-back, count=1 reg03: base=0x100000000 (4096MB), size=1024MB: write-back, count=1 reg04: base=0xbf700000 (3063MB), size= 1MB: uncachable, count=1 reg05: base=0xbf800000 (3064MB), size= 8MB: uncachable, count=1 will get Found optimal setting for mtrr clean up gran_size: 1M chunk_size: 128M num_reg: 6 lose RAM: 0M range0: 0000000000000000 - 00000000c0000000 Setting variable MTRR 0, base: 0MB, range: 2048MB, type WB Setting variable MTRR 1, base: 2048MB, range: 1024MB, type WB hole: 00000000bf700000 - 00000000c0000000 Setting variable MTRR 2, base: 3063MB, range: 1MB, type UC Setting variable MTRR 3, base: 3064MB, range: 8MB, type UC range0: 0000000100000000 - 0000000140000000 Setting variable MTRR 4, base: 4096MB, range: 1024MB, type WB hole: 000000013c000000 - 0000000140000000 Setting variable MTRR 5, base: 5056MB, range: 64MB, type UC 2. Dylan Taft reg00: base=0x00000000 ( 0MB), size=4096MB: write-back, count=1 reg01: base=0x100000000 (4096MB), size= 512MB: write-back, count=1 reg02: base=0x120000000 (4608MB), size= 256MB: write-back, count=1 reg03: base=0xd0000000 (3328MB), size= 256MB: uncachable, count=1 reg04: base=0xe0000000 (3584MB), size= 512MB: uncachable, count=1 reg05: base=0xc7e00000 (3198MB), size= 2MB: uncachable, count=1 reg06: base=0xc8000000 (3200MB), size= 128MB: uncachable, count=1 will get Found optimal setting for mtrr clean up gran_size: 1M chunk_size: 4M num_reg: 6 lose RAM: 0M range0: 0000000000000000 - 00000000c8000000 Setting variable MTRR 0, base: 0MB, range: 2048MB, type WB Setting variable MTRR 1, base: 2048MB, range: 1024MB, type WB Setting variable MTRR 2, base: 3072MB, range: 128MB, type WB hole: 00000000c7e00000 - 00000000c8000000 Setting variable MTRR 3, base: 3198MB, range: 2MB, type UC rangeX: 0000000100000000 - 0000000130000000 Setting variable MTRR 4, base: 4096MB, range: 512MB, type WB Setting variable MTRR 5, base: 4608MB, range: 256MB, type WB 3. Gabriel reg00: base=0xd0000000 (3328MB), size= 256MB: uncachable, count=1 reg01: base=0xe0000000 (3584MB), size= 512MB: uncachable, count=1 reg02: base=0x00000000 ( 0MB), size=4096MB: write-back, count=1 reg03: base=0x100000000 (4096MB), size= 512MB: write-back, count=1 reg04: base=0x120000000 (4608MB), size= 128MB: write-back, count=1 reg05: base=0x128000000 (4736MB), size= 64MB: write-back, count=1 reg06: base=0xcf600000 (3318MB), size= 2MB: uncachable, count=1 will get Found optimal setting for mtrr clean up gran_size: 1M chunk_size: 16M num_reg: 7 lose RAM: 0M range0: 0000000000000000 - 00000000d0000000 Setting variable MTRR 0, base: 0MB, range: 2048MB, type WB Setting variable MTRR 1, base: 2048MB, range: 1024MB, type WB Setting variable MTRR 2, base: 3072MB, range: 256MB, type WB hole: 00000000cf600000 - 00000000cf800000 Setting variable MTRR 3, base: 3318MB, range: 2MB, type UC rangeX: 0000000100000000 - 000000012c000000 Setting variable MTRR 4, base: 4096MB, range: 512MB, type WB Setting variable MTRR 5, base: 4608MB, range: 128MB, type WB Setting variable MTRR 6, base: 4736MB, range: 64MB, type WB 4. Mika Fischer reg00: base=0xc0000000 (3072MB), size=1024MB: uncachable, count=1 reg01: base=0x00000000 ( 0MB), size=4096MB: write-back, count=1 reg02: base=0x100000000 (4096MB), size=1024MB: write-back, count=1 reg03: base=0xbf700000 (3063MB), size= 1MB: uncachable, count=1 reg04: base=0xbf800000 (3064MB), size= 8MB: uncachable, count=1 will get Found optimal setting for mtrr clean up gran_size: 1M chunk_size: 16M num_reg: 5 lose RAM: 0M range0: 0000000000000000 - 00000000c0000000 Setting variable MTRR 0, base: 0MB, range: 2048MB, type WB Setting variable MTRR 1, base: 2048MB, range: 1024MB, type WB hole: 00000000bf700000 - 00000000c0000000 Setting variable MTRR 2, base: 3063MB, range: 1MB, type UC Setting variable MTRR 3, base: 3064MB, range: 8MB, type UC rangeX: 0000000100000000 - 0000000140000000 Setting variable MTRR 4, base: 4096MB, range: 1024MB, type WB Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed92864d132..09f6b7fa29a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1120,7 +1120,7 @@ config MTRR See for more information. config MTRR_SANITIZER - bool + def_bool y prompt "MTRR cleanup support" depends on MTRR help @@ -1131,7 +1131,7 @@ config MTRR_SANITIZER The largest mtrr entry size for a continous block can be set with mtrr_chunk_size. - If unsure, say N. + If unsure, say Y. config MTRR_SANITIZER_ENABLE_DEFAULT int "MTRR cleanup enable value (0-1)" -- cgit v1.2.3 From 40becd8d5af03ee7935e79c3fccd0d1f380d95b4 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 29 Sep 2008 00:06:36 +0900 Subject: AMD IOMMU: use iommu_device_max_index AMD IOMMU can use iommu_device_max_index() instead of the homegrown function. Signed-off-by: FUJITA Tomonori Acked-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index c19212191c9..3b346c6f551 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -470,10 +470,6 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom, * efficient allocator. * ****************************************************************************/ -static unsigned long dma_mask_to_pages(unsigned long mask) -{ - return PAGE_ALIGN(mask) >> PAGE_SHIFT; -} /* * The address allocator core function. @@ -486,14 +482,14 @@ static unsigned long dma_ops_alloc_addresses(struct device *dev, unsigned long align_mask, u64 dma_mask) { - unsigned long limit = dma_mask_to_pages(dma_mask); + unsigned long limit; unsigned long address; - unsigned long size = dom->aperture_size >> PAGE_SHIFT; unsigned long boundary_size; boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, PAGE_SIZE) >> PAGE_SHIFT; - limit = limit < size ? limit : size; + limit = iommu_device_max_index(dom->aperture_size >> PAGE_SHIFT, 0, + dma_mask >> PAGE_SHIFT); if (dom->next_bit >= limit) { dom->next_bit = 0; -- cgit v1.2.3 From fd1452ebf257317f24e0e285a17a2ec2ce3e6df7 Mon Sep 17 00:00:00 2001 From: Dmitry Adamushko Date: Thu, 2 Oct 2008 16:56:19 +0300 Subject: x86/microcode: fix sleeping function called from invalid context at kernel/mutex.c Fix the following "sleeping function called from invalid context" bug: ... __might_sleep mutex_lock_nested microcode_update_cpu mc_sysdev_resume __sysdev_resume sysdev_resume device_power_up ... Signed-off-by: Dmitry Adamushko Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_core.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 8db2eb55e9e..936d8d55f23 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -324,10 +324,6 @@ void microcode_update_cpu(int cpu) struct ucode_cpu_info *uci = ucode_cpu_info + cpu; int err = 0; - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu); - - mutex_lock(µcode_mutex); /* * Check if the system resume is in progress (uci->valid != NULL), * otherwise just request a firmware: @@ -340,11 +336,8 @@ void microcode_update_cpu(int cpu) err = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev); } - if (!err) microcode_ops->apply_microcode(cpu); - - mutex_unlock(µcode_mutex); } static void microcode_init_cpu(int cpu) @@ -352,7 +345,13 @@ static void microcode_init_cpu(int cpu) cpumask_t old = current->cpus_allowed; set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); + /* We should bind the task to the CPU */ + BUG_ON(raw_smp_processor_id() != cpu); + + mutex_lock(µcode_mutex); microcode_update_cpu(cpu); + mutex_unlock(µcode_mutex); + set_cpus_allowed_ptr(current, &old); } -- cgit v1.2.3 From 136c82c6f7f12c9bed8bf709f92123077966512c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2EA=2E=20Magall=C3=B3n?= Date: Fri, 3 Oct 2008 00:32:37 +0200 Subject: x86: mtrr_cleanup try gran_size to less than 1M, cleanup Patch below cleans up formatting, with space for big bases and sizes (64 Gb). Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/if.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index 84c480bb371..4c4214690dd 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c @@ -405,9 +405,9 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset) } /* RED-PEN: base can be > 32bit */ len += seq_printf(seq, - "reg%02i: base=0x%05lx000 (%4luMB), size=%4lu%cB: %s, count=%d\n", + "reg%02i: base=0x%06lx000 (%5luMB), size=%5lu%cB, count=%d: %s\n", i, base, base >> (20 - PAGE_SHIFT), size, factor, - mtrr_attrib_to_str(type), mtrr_usage_table[i]); + mtrr_usage_table[i], mtrr_attrib_to_str(type)); } } return 0; -- cgit v1.2.3 From 834836ee6a3a9deadff9394b23db965a08bcde35 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 2 Oct 2008 15:46:20 -0700 Subject: x86: mtrr_cleanup try gran_size to less than 1M, v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit J.A. Magallón reported: >> Also, on a 64 bit box with 4Gb, it gives this: >> >> cicely:~# cat /proc/mtrr >> reg00: base=0x00000000 ( 0MB), size=4096MB: write-back, count=1 >> reg01: base=0x100000000 (4096MB), size=1024MB: write-back, count=1 >> reg02: base=0x140000000 (5120MB), size= 512MB: write-back, count=1 >> reg03: base=0x160000000 (5632MB), size= 256MB: write-back, count=1 >> reg04: base=0x80000000 (2048MB), size=2048MB: uncachable, count=1 boundary handling has a problem ... fix it. Reported-by: J.A. Magallón Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 8f1a342b16b..b4a3f0c1a5e 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1044,7 +1044,7 @@ second_try: hole_sizek = range0_sizek - state->range_sizek - second_sizek; /* hole size should be less than half of range0 size */ - if (hole_sizek > (range0_sizek >> 1) && + if (hole_sizek >= (range0_sizek >> 1) && range0_sizek >= chunk_sizek) { range0_sizek -= chunk_sizek; second_sizek = 0; -- cgit v1.2.3 From 8bb39311bf461243f6cade3644764d848516dd23 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 2 Oct 2008 23:26:59 -0700 Subject: x86, debug: mtrr_cleanup print out var mtrr before change it Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index b4a3f0c1a5e..406074c46f1 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1211,13 +1211,14 @@ static unsigned long __initdata min_loss_pfn[RANGE_NUM]; static int __init mtrr_cleanup(unsigned address_bits) { unsigned long extra_remove_base, extra_remove_size; - unsigned long i, base, size, def, dummy; + unsigned long base, size, def, dummy; mtrr_type type; int nr_range, nr_range_new; u64 chunk_size, gran_size; unsigned long range_sums, range_sums_new; int index_good; int num_reg_good; + int i; /* extra one for all 0 */ int num[MTRR_NUM_TYPES + 1]; @@ -1259,6 +1260,28 @@ static int __init mtrr_cleanup(unsigned address_bits) num_var_ranges - num[MTRR_NUM_TYPES]) return 0; + /* print original var MTRRs at first, for debugging: */ + printk(KERN_DEBUG "original variable MTRRs\n"); + for (i = 0; i < num_var_ranges; i++) { + char start_factor = 'K', size_factor = 'K'; + unsigned long start_base, size_base; + + size_base = range_state[i].size_pfn << (PAGE_SHIFT - 10); + if (!size_base) + continue; + + size_base = to_size_factor(size_base, &size_factor), + start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10); + start_base = to_size_factor(start_base, &start_factor), + + printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n", + i, start_base, start_factor, + size_base, size_factor, + (type == MTRR_TYPE_UNCACHABLE) ? "UC" : + ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other") + ); + } + memset(range, 0, sizeof(range)); extra_remove_size = 0; if (mtrr_tom2) { -- cgit v1.2.3 From db053b86f4b1ec790da2dafe2acb93be76288bb9 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 2 Oct 2008 16:41:31 -0700 Subject: xen: clean up x86-64 warnings There are a couple of Xen features which rely on directly accessing per-cpu data via a segment register, which is not yet available on x86-64. In the meantime, just disable direct access to the vcpu info structure; this leaves some of the code as dead, but it will come to life in time, and the warnings are suppressed. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 61 ++++++++--------------------------------------- arch/x86/xen/xen-asm_64.S | 20 +++++++++++++--- 2 files changed, 27 insertions(+), 54 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 8ca2f88bde1..85692c9f649 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -112,7 +112,14 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; * * 0: not available, 1: available */ -static int have_vcpu_info_placement = 1; +static int have_vcpu_info_placement = +#ifdef CONFIG_X86_32 + 1 +#else + 0 +#endif + ; + static void xen_vcpu_setup(int cpu) { @@ -941,6 +948,7 @@ static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) } #endif +#ifdef CONFIG_X86_32 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) { /* If there's an existing pte, then don't allow _PAGE_RW to be set */ @@ -959,6 +967,7 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) xen_set_pte(ptep, pte); } +#endif static __init void xen_pagetable_setup_start(pgd_t *base) { @@ -1025,7 +1034,6 @@ void xen_setup_vcpu_info_placement(void) /* xen_vcpu_setup managed to place the vcpu_info within the percpu area for all cpus, so make use of it */ -#ifdef CONFIG_X86_32 if (have_vcpu_info_placement) { printk(KERN_INFO "Xen: using vcpu_info placement\n"); @@ -1035,7 +1043,6 @@ void xen_setup_vcpu_info_placement(void) pv_irq_ops.irq_enable = xen_irq_enable_direct; pv_mmu_ops.read_cr2 = xen_read_cr2_direct; } -#endif } static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, @@ -1056,12 +1063,10 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, goto patch_site switch (type) { -#ifdef CONFIG_X86_32 SITE(pv_irq_ops, irq_enable); SITE(pv_irq_ops, irq_disable); SITE(pv_irq_ops, save_fl); SITE(pv_irq_ops, restore_fl); -#endif /* CONFIG_X86_32 */ #undef SITE patch_site: @@ -1399,48 +1404,11 @@ static void *m2v(phys_addr_t maddr) return __ka(m2p(maddr)); } -#ifdef CONFIG_X86_64 -static void walk(pgd_t *pgd, unsigned long addr) -{ - unsigned l4idx = pgd_index(addr); - unsigned l3idx = pud_index(addr); - unsigned l2idx = pmd_index(addr); - unsigned l1idx = pte_index(addr); - pgd_t l4; - pud_t l3; - pmd_t l2; - pte_t l1; - - xen_raw_printk("walk %p, %lx -> %d %d %d %d\n", - pgd, addr, l4idx, l3idx, l2idx, l1idx); - - l4 = pgd[l4idx]; - xen_raw_printk(" l4: %016lx\n", l4.pgd); - xen_raw_printk(" %016lx\n", pgd_val(l4)); - - l3 = ((pud_t *)(m2v(l4.pgd)))[l3idx]; - xen_raw_printk(" l3: %016lx\n", l3.pud); - xen_raw_printk(" %016lx\n", pud_val(l3)); - - l2 = ((pmd_t *)(m2v(l3.pud)))[l2idx]; - xen_raw_printk(" l2: %016lx\n", l2.pmd); - xen_raw_printk(" %016lx\n", pmd_val(l2)); - - l1 = ((pte_t *)(m2v(l2.pmd)))[l1idx]; - xen_raw_printk(" l1: %016lx\n", l1.pte); - xen_raw_printk(" %016lx\n", pte_val(l1)); -} -#endif - static void set_page_prot(void *addr, pgprot_t prot) { unsigned long pfn = __pa(addr) >> PAGE_SHIFT; pte_t pte = pfn_pte(pfn, prot); - xen_raw_printk("addr=%p pfn=%lx mfn=%lx prot=%016llx pte=%016llx\n", - addr, pfn, get_phys_to_machine(pfn), - pgprot_val(prot), pte.pte); - if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) BUG(); } @@ -1698,15 +1666,6 @@ asmlinkage void __init xen_start_kernel(void) xen_raw_console_write("about to get started...\n"); -#if 0 - xen_raw_printk("&boot_params=%p __pa(&boot_params)=%lx __va(__pa(&boot_params))=%lx\n", - &boot_params, __pa_symbol(&boot_params), - __va(__pa_symbol(&boot_params))); - - walk(pgd, &boot_params); - walk(pgd, __va(__pa(&boot_params))); -#endif - /* Start the world */ #ifdef CONFIG_X86_32 i386_start_kernel(); diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 3b9bda46487..05794c566e8 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -26,8 +26,15 @@ /* Pseudo-flag used for virtual NMI, which we don't implement yet */ #define XEN_EFLAGS_NMI 0x80000000 -#if 0 -#include +#if 1 +/* + x86-64 does not yet support direct access to percpu variables + via a segment override, so we just need to make sure this code + never gets used + */ +#define BUG ud2a +#define PER_CPU_VAR(var, off) 0xdeadbeef +#endif /* Enable events. This clears the event mask and tests the pending @@ -35,6 +42,8 @@ events, then enter the hypervisor to get them handled. */ ENTRY(xen_irq_enable_direct) + BUG + /* Unmask events */ movb $0, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) @@ -58,6 +67,8 @@ ENDPATCH(xen_irq_enable_direct) non-zero. */ ENTRY(xen_irq_disable_direct) + BUG + movb $1, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) ENDPATCH(xen_irq_disable_direct) ret @@ -74,6 +85,8 @@ ENDPATCH(xen_irq_disable_direct) Xen and x86 use opposite senses (mask vs enable). */ ENTRY(xen_save_fl_direct) + BUG + testb $0xff, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) setz %ah addb %ah,%ah @@ -91,6 +104,8 @@ ENDPATCH(xen_save_fl_direct) if so. */ ENTRY(xen_restore_fl_direct) + BUG + testb $X86_EFLAGS_IF>>8, %ah setz PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) /* Preempt here doesn't matter because that will deal with @@ -133,7 +148,6 @@ check_events: pop %rcx pop %rax ret -#endif ENTRY(xen_adjust_exception_frame) mov 8+0(%rsp),%rcx -- cgit v1.2.3 From a2e8d3dcfd420177aaa0c53aca60a869bad75f4b Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Thu, 2 Oct 2008 22:09:20 -0700 Subject: x86: signal: move macros out from restore_sigcontext() move macros, COPY, COPY_SEG*, GET_SEG, out from restore_sigcontext(). x86_64: introduce COPY_SEG_STRICT for cs. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 38 +++++++++++++++++++++----------------- arch/x86/kernel/signal_64.c | 18 +++++++++++------- 2 files changed, 32 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 4337cd510f0..545448b7aeb 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -113,6 +113,27 @@ asmlinkage int sys_sigaltstack(unsigned long bx) return do_sigaltstack(uss, uoss, regs->sp); } +#define COPY(x) { \ + err |= __get_user(regs->x, &sc->x); \ +} + +#define COPY_SEG(seg) { \ + unsigned short tmp; \ + err |= __get_user(tmp, &sc->seg); \ + regs->seg = tmp; \ +} + +#define COPY_SEG_STRICT(seg) { \ + unsigned short tmp; \ + err |= __get_user(tmp, &sc->seg); \ + regs->seg = tmp | 3; \ +} + +#define GET_SEG(seg) { \ + unsigned short tmp; \ + err |= __get_user(tmp, &sc->seg); \ + loadsegment(seg, tmp); \ +} /* * Do a signal return; undo the signal stack. @@ -126,23 +147,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; -#define COPY(x) err |= __get_user(regs->x, &sc->x) - -#define COPY_SEG(seg) \ - { unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ - regs->seg = tmp; } - -#define COPY_SEG_STRICT(seg) \ - { unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ - regs->seg = tmp|3; } - -#define GET_SEG(seg) \ - { unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ - loadsegment(seg, tmp); } - GET_SEG(gs); COPY_SEG(fs); COPY_SEG(es); diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 53f86d95985..feff4a91d09 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -52,6 +52,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, return do_sigaltstack(uss, uoss, regs->sp); } +#define COPY(x) { \ + err |= __get_user(regs->x, &sc->x); \ +} + +#define COPY_SEG_STRICT(seg) { \ + unsigned short tmp; \ + err |= __get_user(tmp, &sc->seg); \ + regs->seg = tmp | 3; \ +} + /* * Do a signal return; undo the signal stack. */ @@ -64,8 +74,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; -#define COPY(x) (err |= __get_user(regs->x, &sc->x)) - COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(dx); COPY(cx); COPY(ip); COPY(r8); @@ -80,11 +88,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Kernel saves and restores only the CS segment register on signals, * which is the bare minimum needed to allow mixed 32/64-bit code. * App's signal handler can save/restore other segments if needed. */ - { - unsigned cs; - err |= __get_user(cs, &sc->cs); - regs->cs = cs | 3; /* Force into user mode */ - } + COPY_SEG_STRICT(cs); { unsigned int tmpflags; -- cgit v1.2.3 From 69e13ad56f9e2cd81c4f8bfd6267211c10c14c08 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Thu, 2 Oct 2008 22:18:47 -0700 Subject: x86: signal: remove indent in restore_sigcontext() remove braces and indent for flags and fpstate in restore_sigcontext(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_32.c | 21 +++++++-------------- arch/x86/kernel/signal_64.c | 19 +++++++------------ 2 files changed, 14 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 545448b7aeb..d6dd057d0f2 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -142,6 +142,8 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *pax) { + void __user *buf; + unsigned int tmpflags; unsigned int err = 0; /* Always make any pending restarted system calls return -EINTR */ @@ -156,21 +158,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, COPY_SEG_STRICT(cs); COPY_SEG_STRICT(ss); - { - unsigned int tmpflags; + err |= __get_user(tmpflags, &sc->flags); + regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); + regs->orig_ax = -1; /* disable syscall checks */ - err |= __get_user(tmpflags, &sc->flags); - regs->flags = (regs->flags & ~FIX_EFLAGS) | - (tmpflags & FIX_EFLAGS); - regs->orig_ax = -1; /* disable syscall checks */ - } - - { - void __user *buf; - - err |= __get_user(buf, &sc->fpstate); - err |= restore_i387_xstate(buf); - } + err |= __get_user(buf, &sc->fpstate); + err |= restore_i387_xstate(buf); err |= __get_user(*pax, &sc->ax); return err; diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index feff4a91d09..a5c9627f4db 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -69,6 +69,8 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *pax) { + void __user *buf; + unsigned int tmpflags; unsigned int err = 0; /* Always make any pending restarted system calls return -EINTR */ @@ -90,19 +92,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, * App's signal handler can save/restore other segments if needed. */ COPY_SEG_STRICT(cs); - { - unsigned int tmpflags; - err |= __get_user(tmpflags, &sc->flags); - regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); - regs->orig_ax = -1; /* disable syscall checks */ - } - - { - void __user *buf; + err |= __get_user(tmpflags, &sc->flags); + regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); + regs->orig_ax = -1; /* disable syscall checks */ - err |= __get_user(buf, &sc->fpstate); - err |= restore_i387_xstate(buf); - } + err |= __get_user(buf, &sc->fpstate); + err |= restore_i387_xstate(buf); err |= __get_user(*pax, &sc->ax); return err; -- cgit v1.2.3 From 175e438f7a2de9d94110046be48697969569736a Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Thu, 2 Oct 2008 17:32:06 -0500 Subject: x86: trivial printk fix in efi.c [patch] x86: Trivial printk fix in efi.c The following line is lacking a space between "memdesc" and "doesn't". "Kernel-defined memdescdoesn't match the one from EFI!" Fixed the printk by adding a space. Signed-off-by: Russ Anderson Cc: Russ Anderson Signed-off-by: Ingo Molnar --- arch/x86/kernel/efi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 06cc8d4254b..945a31cdd81 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -414,9 +414,11 @@ void __init efi_init(void) if (memmap.map == NULL) printk(KERN_ERR "Could not map the EFI memory map!\n"); memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); + if (memmap.desc_size != sizeof(efi_memory_desc_t)) - printk(KERN_WARNING "Kernel-defined memdesc" - "doesn't match the one from EFI!\n"); + printk(KERN_WARNING + "Kernel-defined memdesc doesn't match the one from EFI!\n"); + if (add_efi_memmap) do_add_efi_memmap(); -- cgit v1.2.3 From 6cdcdb99cf7c2e1835fc5b471864d21161c3e679 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Fri, 3 Oct 2008 21:08:49 +0400 Subject: x86 setup: fix ghost entries under /sys/firmware/edd take 3 Some BIOSes do not indicate error when trying to read from non- existing device. Zero buffer before reading and check that we possibly have valid MBR by looking for MBR magic. This was fixed in different way for edd.S in http://marc.info/?l=linux-kernel&m=114087765422490&w=2, but lost again when edd.S was rewritten in C. Signed-off-by: Andrey Borzenkov < arvidjaar@mail.ru> Signed-off-by: H. Peter Anvin --- arch/x86/boot/edd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c index bf4ae6ff518..067e28cd3c5 100644 --- a/arch/x86/boot/edd.c +++ b/arch/x86/boot/edd.c @@ -43,6 +43,7 @@ static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) char *mbrbuf_ptr, *mbrbuf_end; u32 buf_base, mbr_base; extern char _end[]; + u16 mbr_magic; sector_size = ei->params.bytes_per_sector; if (!sector_size) @@ -60,11 +61,15 @@ static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) if (mbrbuf_end > (char *)(size_t)boot_params.hdr.heap_end_ptr) return -1; + memset(mbrbuf_ptr, 0, sector_size); if (read_mbr(devno, mbrbuf_ptr)) return -1; *mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET]; - return 0; + mbr_magic = *(u16 *)&mbrbuf_ptr[510]; + + /* check for valid MBR magic */ + return mbr_magic == 0xAA55 ? 0 : -1; } static int get_edd_info(u8 devno, struct edd_info *ei) -- cgit v1.2.3 From 98920dc3d1113b883cbc73e3293446d3525c6042 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 3 Oct 2008 10:22:33 -0700 Subject: Revert "x86: fix ghost EDD devices in /sys again" This reverts commit 464f04c9e9b3b1c4f5ffb89c51d8ba2a2034c846. Obsoleted by commit 6cdcdb99cf7c2e1835fc5b471864d21161c3e679. Signed-off-by: H. Peter Anvin --- arch/x86/boot/edd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c index 067e28cd3c5..1aae8f3e5ca 100644 --- a/arch/x86/boot/edd.c +++ b/arch/x86/boot/edd.c @@ -32,9 +32,7 @@ static int read_mbr(u8 devno, void *buf) : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) : : "esi", "edi", "memory"); - /* Some BIOSes do not set carry flag on error but still return - * error in AH. The condition below is expected to catch both */ - return -!!ax; /* 0 or -1 */ + return -(u8)ax; /* 0 or -1 */ } static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) -- cgit v1.2.3 From d960c9ce47c5360b39e47c064818e91c89df0e21 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sat, 4 Oct 2008 21:18:51 +0200 Subject: x86 setup: remove IMAGE_OFFSET After commit 968de4f ("i386: Relocatable kernel support") IMAGE_OFFSET wasn't actually used anymore in the (current) X86 build system. Now remove its last traces. Signed-off-by: Paul Bolle Signed-off-by: H. Peter Anvin --- arch/x86/boot/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index cceba1f4636..cd48c721001 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -72,9 +72,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ KBUILD_CFLAGS += $(call cc-option,-m32) KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ -$(obj)/zImage: IMAGE_OFFSET := 0x1000 $(obj)/zImage: asflags-y := $(SVGA_MODE) $(RAMDISK) -$(obj)/bzImage: IMAGE_OFFSET := 0x100000 $(obj)/bzImage: ccflags-y := -D__BIG_KERNEL__ $(obj)/bzImage: asflags-y := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ $(obj)/bzImage: BUILDFLAGS := -b @@ -117,7 +115,7 @@ $(obj)/setup.bin: $(obj)/setup.elf FORCE $(call if_changed,objcopy) $(obj)/compressed/vmlinux: FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ + $(Q)$(MAKE) $(build)=$(obj)/compressed $@ # Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel FDARGS = -- cgit v1.2.3 From 42fde7a05c5d6dc76e518ae12091ea897b1c132b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 4 Oct 2008 19:34:18 -0700 Subject: x86: mtrr_cleanup: print out correct type v2 Print out the correct type when the Write Protected (WP) type is seen. Signed-off-by: Yinghai Lu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mtrr/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 406074c46f1..9086b38fbab 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1273,12 +1273,14 @@ static int __init mtrr_cleanup(unsigned address_bits) size_base = to_size_factor(size_base, &size_factor), start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10); start_base = to_size_factor(start_base, &start_factor), + type = range_state[i].type; printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n", i, start_base, start_factor, size_base, size_factor, (type == MTRR_TYPE_UNCACHABLE) ? "UC" : - ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other") + ((type == MTRR_TYPE_WRPROT) ? "WP" : + ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other")) ); } -- cgit v1.2.3 From 99e1aa17ce434010dd820b583628370cc15f10f3 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 4 Oct 2008 14:50:32 -0700 Subject: x86: mtrr_cleanup: first 1M may be covered in var mtrrs The first 1M is don't care when it comes to the variables MTRRs. Cover it as WB as a heuristic approximation; this is generally what we want to minimize the number of registers. Signed-off-by: Yinghai Lu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mtrr/main.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 9086b38fbab..663e530e08e 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1293,6 +1293,15 @@ static int __init mtrr_cleanup(unsigned address_bits) } nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base, extra_remove_size); + /* + * [0, 1M) should always be coverred by var mtrr with WB + * and fixed mtrrs should take effective before var mtrr for it + */ + nr_range = add_range_with_merge(range, nr_range, 0, + (1ULL<<(20 - PAGE_SHIFT)) - 1); + /* sort the ranges */ + sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); + range_sums = sum_ranges(range, nr_range); printk(KERN_INFO "total RAM coverred: %ldM\n", range_sums >> (20 - PAGE_SHIFT)); -- cgit v1.2.3 From dd5523552c2897e3fde16fc2fc8f6332addf66ab Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 4 Oct 2008 14:50:33 -0700 Subject: x86: mtrr_cleanup: treat WRPROT as UNCACHEABLE For the purpose of MTRR canonicalization, treat WRPROT as UNCACHEABLE. Signed-off-by: Yinghai Lu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mtrr/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 663e530e08e..5994a9f78f3 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -759,7 +759,8 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, /* take out UC ranges */ for (i = 0; i < num_var_ranges; i++) { type = range_state[i].type; - if (type != MTRR_TYPE_UNCACHABLE) + if (type != MTRR_TYPE_UNCACHABLE && + type != MTRR_TYPE_WRPROT) continue; size = range_state[i].size_pfn; if (!size) @@ -1248,6 +1249,8 @@ static int __init mtrr_cleanup(unsigned address_bits) continue; if (!size) type = MTRR_NUM_TYPES; + if (type == MTRR_TYPE_WRPROT) + type = MTRR_TYPE_UNCACHABLE; num[type]++; } -- cgit v1.2.3 From 2407390bd20de38740eef87eab4fe3d1deafdbdd Mon Sep 17 00:00:00 2001 From: Michal Januszewski Date: Sun, 5 Oct 2008 12:16:04 +0200 Subject: x86: replace a magic number with a named constant in the VESA boot code Replace a magic number with a named constant in the VESA boot code. Signed-off-by: Michal Januszewski Cc: linux-fbdev-devel@lists.sourceforge.net Signed-off-by: Ingo Molnar --- arch/x86/boot/video-vesa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 401ad998ad0..1e6fe0214c8 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -224,7 +224,7 @@ static void vesa_store_pm_info(void) static void vesa_store_mode_params_graphics(void) { /* Tell the kernel we're in VESA graphics mode */ - boot_params.screen_info.orig_video_isVGA = 0x23; + boot_params.screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB; /* Mode parameters */ boot_params.screen_info.vesa_attributes = vminfo.mode_attr; -- cgit v1.2.3 From 300bb762513f12068bf6166e0a1a02a4031a979c Mon Sep 17 00:00:00 2001 From: Alex Raimondi Date: Mon, 22 Sep 2008 21:40:55 +0200 Subject: avr32: Replace static clock list with dynamic linked list This replaces the at32_clock_list array with a linked list. Clocks can now be registered (added) to the list. Signed-off-by: Alex Raimondi Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/at32ap700x.c | 22 +++++++++------- arch/avr32/mach-at32ap/clock.c | 52 ++++++++++++++++++++++++++++--------- arch/avr32/mach-at32ap/clock.h | 8 +++--- 3 files changed, 58 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index c28dd172f62..fd306c49194 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -2028,7 +2028,7 @@ static struct clk gclk4 = { .index = 4, }; -struct clk *at32_clock_list[] = { +static __initdata struct clk *init_clocks[] = { &osc32k, &osc0, &osc1, @@ -2092,7 +2092,6 @@ struct clk *at32_clock_list[] = { &gclk3, &gclk4, }; -unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); void __init setup_platform(void) { @@ -2123,14 +2122,19 @@ void __init setup_platform(void) genclk_init_parent(&abdac0_sample_clk); /* - * Turn on all clocks that have at least one user already, and - * turn off everything else. We only do this for module - * clocks, and even though it isn't particularly pretty to - * check the address of the mode function, it should do the - * trick... + * Build initial dynamic clock list by registering all clocks + * from the array. + * At the same time, turn on all clocks that have at least one + * user already, and turn off everything else. We only do this + * for module clocks, and even though it isn't particularly + * pretty to check the address of the mode function, it should + * do the trick... */ - for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) { - struct clk *clk = at32_clock_list[i]; + for (i = 0; i < ARRAY_SIZE(init_clocks); i++) { + struct clk *clk = init_clocks[i]; + + /* first, register clock */ + at32_clk_register(clk); if (clk->users == 0) continue; diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c index 6c27ddac5ad..138a00a2a2d 100644 --- a/arch/avr32/mach-at32ap/clock.c +++ b/arch/avr32/mach-at32ap/clock.c @@ -15,24 +15,40 @@ #include #include #include +#include #include #include "clock.h" +/* at32 clock list */ +static LIST_HEAD(at32_clock_list); + static DEFINE_SPINLOCK(clk_lock); +static DEFINE_SPINLOCK(clk_list_lock); + +void at32_clk_register(struct clk *clk) +{ + spin_lock(&clk_list_lock); + /* add the new item to the end of the list */ + list_add_tail(&clk->list, &at32_clock_list); + spin_unlock(&clk_list_lock); +} struct clk *clk_get(struct device *dev, const char *id) { - int i; + struct clk *clk; - for (i = 0; i < at32_nr_clocks; i++) { - struct clk *clk = at32_clock_list[i]; + spin_lock(&clk_list_lock); - if (clk->dev == dev && strcmp(id, clk->name) == 0) + list_for_each_entry(clk, &at32_clock_list, list) { + if (clk->dev == dev && strcmp(id, clk->name) == 0) { + spin_unlock(&clk_list_lock); return clk; + } } + spin_unlock(&clk_list_lock); return ERR_PTR(-ENOENT); } EXPORT_SYMBOL(clk_get); @@ -203,8 +219,8 @@ dump_clock(struct clk *parent, struct clkinf *r) /* cost of this scan is small, but not linear... */ r->nest = nest + NEST_DELTA; - for (i = 3; i < at32_nr_clocks; i++) { - clk = at32_clock_list[i]; + + list_for_each_entry(clk, &at32_clock_list, list) { if (clk->parent == parent) dump_clock(clk, r); } @@ -215,6 +231,7 @@ static int clk_show(struct seq_file *s, void *unused) { struct clkinf r; int i; + struct clk *clk; /* show all the power manager registers */ seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL)); @@ -234,14 +251,25 @@ static int clk_show(struct seq_file *s, void *unused) seq_printf(s, "\n"); - /* show clock tree as derived from the three oscillators - * we "know" are at the head of the list - */ r.s = s; r.nest = 0; - dump_clock(at32_clock_list[0], &r); - dump_clock(at32_clock_list[1], &r); - dump_clock(at32_clock_list[2], &r); + /* protected from changes on the list while dumping */ + spin_lock(&clk_list_lock); + + /* show clock tree as derived from the three oscillators */ + clk = clk_get(NULL, "osc32k"); + dump_clock(clk, &r); + clk_put(clk); + + clk = clk_get(NULL, "osc0"); + dump_clock(clk, &r); + clk_put(clk); + + clk = clk_get(NULL, "osc1"); + dump_clock(clk, &r); + clk_put(clk); + + spin_unlock(&clk_list_lock); return 0; } diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h index bb8e1f29583..623bf0e9a1e 100644 --- a/arch/avr32/mach-at32ap/clock.h +++ b/arch/avr32/mach-at32ap/clock.h @@ -12,8 +12,13 @@ * published by the Free Software Foundation. */ #include +#include + + +void at32_clk_register(struct clk *clk); struct clk { + struct list_head list; /* linking element */ const char *name; /* Clock name/function */ struct device *dev; /* Device the clock is used by */ struct clk *parent; /* Parent clock, if any */ @@ -25,6 +30,3 @@ struct clk { u16 users; /* Enabled if non-zero */ u16 index; /* Sibling index */ }; - -extern struct clk *at32_clock_list[]; -extern unsigned int at32_nr_clocks; -- cgit v1.2.3 From 6b918657b7431e4c5c953b8222ae2f4fc1b2576a Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Thu, 7 Aug 2008 14:08:49 +0200 Subject: atmel-mci: Platform code for supporting multiple mmc slots Add the necessary platform infrastructure to support multiple mmc/sdcard slots all at once through a single controller. Currently, the driver will use the first valid slot it finds and stick with that, but later patches will add support for switching between several slots on the fly. Extend the platform data structure with per-slot information: MMC/SDcard bus width and card detect/write protect pins. This will affect the pin muxing as well as the capabilities announced to the mmc core. Note that board code is now required to supply a mci_platform_data struct to at32_add_device_mci(). Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atngw100/setup.c | 7 +++- arch/avr32/boards/atstk1000/atstk1002.c | 18 +++++---- arch/avr32/boards/atstk1000/atstk1003.c | 12 +++++- arch/avr32/boards/atstk1000/atstk1004.c | 12 +++++- arch/avr32/include/asm/atmel-mci.h | 22 +++++++++- arch/avr32/mach-at32ap/at32ap700x.c | 72 ++++++++++++++++++++++++--------- 6 files changed, 113 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index b8286f1ce85..f3085208959 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -53,8 +53,11 @@ static struct spi_board_info spi0_board_info[] __initdata = { }; static struct mci_platform_data __initdata mci0_data = { - .detect_pin = GPIO_PIN_PC(25), - .wp_pin = GPIO_PIN_PE(0), + .slot[0] = { + .bus_width = 4, + .detect_pin = GPIO_PIN_PC(25), + .wp_pin = GPIO_PIN_PE(0), + }, }; /* diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index dfc3443e23a..4fedbc4488d 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -264,16 +264,20 @@ void __init setup_board(void) #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + /* MMC card detect requires MACB0 *NOT* be used */ #ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM -static struct mci_platform_data __initdata mci0_data = { - .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ - .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ -}; -#define MCI_PDATA &mci0_data + .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ + .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ #else -#define MCI_PDATA NULL + .detect_pin = -ENODEV, + .wp_pin = -ENODEV, #endif /* SW6 for sd{cd,wp} routing */ + }, +}; #endif /* SW2 for MMC signal routing */ @@ -326,7 +330,7 @@ static int __init atstk1002_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, MCI_PDATA); + at32_add_device_mci(0, &mci0_pdata); #endif #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM set_hw_addr(at32_add_device_eth(1, ð_data[1])); diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c index 0cf664174c1..acc61235b89 100644 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ b/arch/avr32/boards/atstk1000/atstk1003.c @@ -66,6 +66,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { { } }; #endif +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + .detect_pin = -ENODEV, + .wp_pin = -ENODEV, + }, +}; +#endif + #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC static void __init atstk1003_setup_extdac(void) { @@ -154,7 +164,7 @@ static int __init atstk1003_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, NULL); + at32_add_device_mci(0, &mci0_data); #endif at32_add_device_usba(0, NULL); #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index 50a5273e591..d6a2d02f032 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -71,6 +71,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { { } }; #endif +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + .detect_pin = -ENODEV, + .wp_pin = -ENODEV, + }, +}; +#endif + #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC static void __init atstk1004_setup_extdac(void) { @@ -137,7 +147,7 @@ static int __init atstk1004_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, NULL); + at32_add_device_mci(0, &mci0_data); #endif at32_add_device_lcdc(0, &atstk1000_lcdc_data, fbmem_start, fbmem_size, 0); diff --git a/arch/avr32/include/asm/atmel-mci.h b/arch/avr32/include/asm/atmel-mci.h index c2ea6e1c9aa..d38c64ca41e 100644 --- a/arch/avr32/include/asm/atmel-mci.h +++ b/arch/avr32/include/asm/atmel-mci.h @@ -1,9 +1,29 @@ #ifndef __ASM_AVR32_ATMEL_MCI_H #define __ASM_AVR32_ATMEL_MCI_H -struct mci_platform_data { +/** + * struct mci_slot_pdata - board-specific per-slot configuration + * @bus_width: Number of data lines wired up the slot + * @detect_pin: GPIO pin wired to the card detect switch + * @wp_pin: GPIO pin wired to the write protect sensor + * + * If a given slot is not present on the board, @bus_width should be + * set to 0. The other fields are ignored in this case. + * + * Any pins that aren't available should be set to a negative value. + */ +struct mci_slot_pdata { + unsigned int bus_width; int detect_pin; int wp_pin; }; +/** + * struct mci_platform_data - board-specific MMC/SDcard configuration + * @slot: Per-slot configuration data. + */ +struct mci_platform_data { + struct mci_slot_pdata slot[2]; +}; + #endif /* __ASM_AVR32_ATMEL_MCI_H */ diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index e01dbe4ebb4..9967d5a3b6e 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1272,10 +1272,13 @@ static struct clk atmel_mci0_pclk = { struct platform_device *__init at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { - struct mci_platform_data _data; struct platform_device *pdev; - if (id != 0) + if (id != 0 || !data) + return NULL; + + /* Must have at least one usable slot */ + if (!data->slot[0].bus_width && !data->slot[1].bus_width) return NULL; pdev = platform_device_alloc("atmel_mci", id); @@ -1286,28 +1289,61 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) ARRAY_SIZE(atmel_mci0_resource))) goto fail; - if (!data) { - data = &_data; - memset(data, -1, sizeof(struct mci_platform_data)); - data->detect_pin = GPIO_PIN_NONE; - data->wp_pin = GPIO_PIN_NONE; - } if (platform_device_add_data(pdev, data, sizeof(struct mci_platform_data))) goto fail; - select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ - select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ - select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */ - select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ - select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ - select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ + /* CLK line is common to both slots */ + select_peripheral(PA(10), PERIPH_A, 0); - if (gpio_is_valid(data->detect_pin)) - at32_select_gpio(data->detect_pin, 0); - if (gpio_is_valid(data->wp_pin)) - at32_select_gpio(data->wp_pin, 0); + switch (data->slot[0].bus_width) { + case 4: + select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ + select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ + select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ + /* fall through */ + case 1: + select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ + select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */ + + if (gpio_is_valid(data->slot[0].detect_pin)) + at32_select_gpio(data->slot[0].detect_pin, 0); + if (gpio_is_valid(data->slot[0].wp_pin)) + at32_select_gpio(data->slot[0].wp_pin, 0); + break; + case 0: + /* Slot is unused */ + break; + default: + goto fail; + } + + switch (data->slot[1].bus_width) { + case 4: + select_peripheral(PB(8), PERIPH_B, 0); /* DATA1 */ + select_peripheral(PB(9), PERIPH_B, 0); /* DATA2 */ + select_peripheral(PB(10), PERIPH_B, 0); /* DATA3 */ + /* fall through */ + case 1: + select_peripheral(PB(6), PERIPH_B, 0); /* CMD */ + select_peripheral(PB(7), PERIPH_B, 0); /* DATA0 */ + + if (gpio_is_valid(data->slot[1].detect_pin)) + at32_select_gpio(data->slot[1].detect_pin, 0); + if (gpio_is_valid(data->slot[1].wp_pin)) + at32_select_gpio(data->slot[1].wp_pin, 0); + break; + case 0: + /* Slot is unused */ + break; + default: + if (!data->slot[0].bus_width) + goto fail; + + data->slot[1].bus_width = 0; + break; + } atmel_mci0_pclk.dev = &pdev->dev; -- cgit v1.2.3 From 965ebf33ea5afb6386f5b57cc71e6572253746b3 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 17 Sep 2008 20:53:55 +0200 Subject: atmel-mci: support multiple mmc slots The Atmel MCI controller can drive multiple cards through separate sets of pins, but only one at a time. This patch adds support for multiplexing access to the controller so that multiple card slots can be used as if they were hooked up to separate mmc controllers. The atmel-mci driver registers each slot as a separate mmc_host. Both access the same common controller state, but they also have some state on their own for card detection/write protect handling, and separate shadows of the MR and SDCR registers. When one of the slots receives a request from the mmc core, the common controller state is checked. If it's idle, the request is submitted immediately. If not, the request is added to a queue. When a request is done, the queue is checked and if there is a queued request, it is submitted before the completion callback is called. This patch also includes a few cleanups and fixes, including a locking overhaul. I had to change the locking extensively in any case, so I might as well try to get it right. The driver no longer takes any irq-safe locks, which may or may not improve the overall system performance. This patch also adds a bit of documentation of the internal data structures. Signed-off-by: Haavard Skinnemoen --- arch/avr32/include/asm/atmel-mci.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/avr32/include/asm/atmel-mci.h b/arch/avr32/include/asm/atmel-mci.h index d38c64ca41e..5d5ae1295cf 100644 --- a/arch/avr32/include/asm/atmel-mci.h +++ b/arch/avr32/include/asm/atmel-mci.h @@ -1,6 +1,8 @@ #ifndef __ASM_AVR32_ATMEL_MCI_H #define __ASM_AVR32_ATMEL_MCI_H +#define ATMEL_MCI_MAX_NR_SLOTS 2 + /** * struct mci_slot_pdata - board-specific per-slot configuration * @bus_width: Number of data lines wired up the slot @@ -11,6 +13,10 @@ * set to 0. The other fields are ignored in this case. * * Any pins that aren't available should be set to a negative value. + * + * Note that support for multiple slots is experimental -- some cards + * might get upset if we don't get the clock management exactly right. + * But in most cases, it should work just fine. */ struct mci_slot_pdata { unsigned int bus_width; @@ -23,7 +29,7 @@ struct mci_slot_pdata { * @slot: Per-slot configuration data. */ struct mci_platform_data { - struct mci_slot_pdata slot[2]; + struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; }; #endif /* __ASM_AVR32_ATMEL_MCI_H */ -- cgit v1.2.3 From 65e8b083fc8ec303499baa1924ae032d46d29990 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 30 Jul 2008 20:29:03 +0200 Subject: atmel-mci: Add experimental DMA support This adds support for DMA transfers through the generic DMA engine framework with the DMA slave extensions. The driver has been tested using mmc-block and ext3fs on several SD, SDHC and MMC+ cards. Reads and writes work fine, with read transfer rates up to 7.5 MiB/s on fast cards with debugging disabled. Unfortunately, the driver has been known to lock up from time to time with DMA enabled, so DMA support is currently optional and marked EXPERIMENTAL. However, I didn't see any problems while testing 13 different cards (MMC, SD and SDHC of different brands and sizes), so I suspect the "Initialize BLKR before sending data transfer command" fix that was posted earlier fixed this as well. Signed-off-by: Haavard Skinnemoen --- arch/avr32/include/asm/atmel-mci.h | 4 ++++ arch/avr32/mach-at32ap/at32ap700x.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'arch') diff --git a/arch/avr32/include/asm/atmel-mci.h b/arch/avr32/include/asm/atmel-mci.h index 5d5ae1295cf..59f3fadd0b6 100644 --- a/arch/avr32/include/asm/atmel-mci.h +++ b/arch/avr32/include/asm/atmel-mci.h @@ -3,6 +3,8 @@ #define ATMEL_MCI_MAX_NR_SLOTS 2 +struct dma_slave; + /** * struct mci_slot_pdata - board-specific per-slot configuration * @bus_width: Number of data lines wired up the slot @@ -26,9 +28,11 @@ struct mci_slot_pdata { /** * struct mci_platform_data - board-specific MMC/SDcard configuration + * @dma_slave: DMA slave interface to use in data transfers, or NULL. * @slot: Per-slot configuration data. */ struct mci_platform_data { + struct dma_slave *dma_slave; struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; }; diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 9967d5a3b6e..f1b9a3ac273 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1273,6 +1273,7 @@ struct platform_device *__init at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { struct platform_device *pdev; + struct dw_dma_slave *dws; if (id != 0 || !data) return NULL; @@ -1289,6 +1290,21 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) ARRAY_SIZE(atmel_mci0_resource))) goto fail; + if (data->dma_slave) + dws = kmemdup(to_dw_dma_slave(data->dma_slave), + sizeof(struct dw_dma_slave), GFP_KERNEL); + else + dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); + + dws->slave.dev = &pdev->dev; + dws->slave.dma_dev = &dw_dmac0_device.dev; + dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT; + dws->cfg_hi = (DWC_CFGH_SRC_PER(0) + | DWC_CFGH_DST_PER(1)); + dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL + | DWC_CFGL_HS_SRC_POL); + + data->dma_slave = &dws->slave; if (platform_device_add_data(pdev, data, sizeof(struct mci_platform_data))) -- cgit v1.2.3 From 33fb0e4eb53f16af312f9698f974e2e64af39c12 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 7 Oct 2008 00:11:22 +0200 Subject: x86: SB450: skip IRQ0 override if it is not routed to INT2 of IOAPIC On some HP nx6... laptops (e.g. nx6325) BIOS reports an IRQ0 override but the SB450 chipset is configured such that timer interrupts goe to INT0 of IOAPIC. Check IRQ0 routing and if it is routed to INT0 of IOAPIC skip the timer override. [ This more generic PCI ID based quirk should alleviate the need for dmi_ignore_irq0_timer_override DMI quirks. ] Signed-off-by: Andreas Herrmann Acked-by: "Maciej W. Rozycki" Tested-by: Dmitry Torokhov Cc: Signed-off-by: Ingo Molnar --- arch/x86/kernel/early-quirks.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 4353cf5e6fa..6b839b14764 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -95,6 +95,52 @@ static void __init nvidia_bugs(int num, int slot, int func) } +static u32 ati_ixp4x0_rev(int num, int slot, int func) +{ + u32 d; + u8 b; + + b = read_pci_config_byte(num, slot, func, 0xac); + b &= ~(1<<5); + write_pci_config_byte(num, slot, func, 0xac, b); + + d = read_pci_config(num, slot, func, 0x70); + d |= 1<<8; + write_pci_config(num, slot, func, 0x70, d); + + d = read_pci_config(num, slot, func, 0x8); + d &= 0xff; + return d; +} + +static void __init ati_bugs(int num, int slot, int func) +{ +#if defined(CONFIG_ACPI) && defined (CONFIG_X86_IO_APIC) + u32 d; + u8 b; + + if (acpi_use_timer_override) + return; + + d = ati_ixp4x0_rev(num, slot, func); + if (d < 0x82) + acpi_skip_timer_override = 1; + else { + /* check for IRQ0 interrupt swap */ + outb(0x72, 0xcd6); b = inb(0xcd7); + if (!(b & 0x2)) + acpi_skip_timer_override = 1; + } + + if (acpi_skip_timer_override) { + printk(KERN_INFO "SB4X0 revision 0x%x\n", d); + printk(KERN_INFO "Ignoring ACPI timer override.\n"); + printk(KERN_INFO "If you got timer trouble " + "try acpi_use_timer_override\n"); + } +#endif +} + #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -114,6 +160,8 @@ static struct chipset early_qrk[] __initdata = { PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, + PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, {} }; -- cgit v1.2.3 From 8d89adf44cf750e49691ba5b744b2ad77a05e997 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 7 Oct 2008 06:47:52 +0200 Subject: x86: SB450: deprioritize DMI quirks This PCI ID based quick should be a full solution for the IRQ0 override related slowdown problem on SB450 based systems: 33fb0e4: x86: SB450: skip IRQ0 override if it is not routed to INT2 of IOAPIC Emit a warning in those cases where the DMI quirk triggers but the PCI ID based quirk didnt. If this warning does not trigger then we can phase out the DMI quirks. Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index c102af85df9..096102d9b24 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1421,8 +1421,16 @@ static int __init force_acpi_ht(const struct dmi_system_id *d) */ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) { - pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", d->ident); - acpi_skip_timer_override = 1; + /* + * The ati_ixp4x0_rev() early PCI quirk should have set + * the acpi_skip_timer_override flag already: + */ + if (!acpi_skip_timer_override) { + WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n"); + pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", + d->ident); + acpi_skip_timer_override = 1; + } return 0; } -- cgit v1.2.3 From 8cc7117e7c4968b10fd7327b4a62d9c23082a7b3 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 13 Oct 2008 14:45:06 +0800 Subject: Blackfin arch: Add new board support for ADZS-BF526-EZ-BRD Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 13 +- arch/blackfin/configs/BF526-EZBRD_defconfig | 1427 +++++++++++++++++++++++++++ arch/blackfin/mach-bf527/boards/Kconfig | 5 + arch/blackfin/mach-bf527/boards/Makefile | 1 + arch/blackfin/mach-bf527/boards/ezbrd.c | 734 ++++++++++++++ 5 files changed, 2177 insertions(+), 3 deletions(-) create mode 100644 arch/blackfin/configs/BF526-EZBRD_defconfig create mode 100644 arch/blackfin/mach-bf527/boards/ezbrd.c (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 4154ff1101f..c507a92cb28 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -249,7 +249,7 @@ config MEM_MT48LC8M32B2B5_7 config MEM_MT48LC32M16A2TG_75 bool - depends on (BFIN527_EZKIT || BFIN532_IP0X || BLACKSTAMP) + depends on (BFIN527_EZKIT || BFIN532_IP0X || BLACKSTAMP || BFIN526_EZBRD) default y source "arch/blackfin/mach-bf527/Kconfig" @@ -286,13 +286,20 @@ config BOOT_LOAD memory region is used to capture NULL pointer references as well as some core kernel functions. +config ROM_BASE + hex "Kernel ROM Base" + default "0x20040000" + range 0x20000000 0x20400000 if !(BF54x || BF561) + range 0x20000000 0x30000000 if (BF54x || BF561) + help + comment "Clock/PLL Setup" config CLKIN_HZ int "Frequency of the crystal on the board in Hz" default "11059200" if BFIN533_STAMP default "27000000" if BFIN533_EZKIT - default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP) + default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD) default "30000000" if BFIN561_EZKIT default "24576000" if PNAV10 default "10000000" if BFIN532_IP0X @@ -332,7 +339,7 @@ config VCO_MULT default "22" if BFIN533_BLUETECHNIX_CM default "20" if (BFIN537_BLUETECHNIX_CM || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM) default "20" if BFIN561_EZKIT - default "16" if (H8606_HVSISTEMAS || BLACKSTAMP) + default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD) help This controls the frequency of the on-chip PLL. This can be between 1 and 64. PLL Frequency = (Crystal Frequency) * (this setting) diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig new file mode 100644 index 00000000000..c33bf6f8381 --- /dev/null +++ b/arch/blackfin/configs/BF526-EZBRD_defconfig @@ -0,0 +1,1427 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.26.3 +# Thu Aug 28 16:49:53 2008 +# +# CONFIG_MMU is not set +# CONFIG_FPU is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_BLACKFIN=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_GPIO=y +CONFIG_FORCE_MAX_ZONEORDER=14 +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +# CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set + +# +# Blackfin Processor Options +# + +# +# Processor and Board Settings +# +# CONFIG_BF522 is not set +# CONFIG_BF523 is not set +# CONFIG_BF524 is not set +# CONFIG_BF525 is not set +CONFIG_BF526=y +# CONFIG_BF527 is not set +# CONFIG_BF531 is not set +# CONFIG_BF532 is not set +# CONFIG_BF533 is not set +# CONFIG_BF534 is not set +# CONFIG_BF536 is not set +# CONFIG_BF537 is not set +# CONFIG_BF542 is not set +# CONFIG_BF544 is not set +# CONFIG_BF547 is not set +# CONFIG_BF548 is not set +# CONFIG_BF549 is not set +# CONFIG_BF561 is not set +CONFIG_BF_REV_0_0=y +# CONFIG_BF_REV_0_1 is not set +# CONFIG_BF_REV_0_2 is not set +# CONFIG_BF_REV_0_3 is not set +# CONFIG_BF_REV_0_4 is not set +# CONFIG_BF_REV_0_5 is not set +# CONFIG_BF_REV_ANY is not set +# CONFIG_BF_REV_NONE is not set +CONFIG_BF52x=y +CONFIG_MEM_MT48LC32M16A2TG_75=y +# CONFIG_BFIN527_EZKIT is not set +# CONFIG_BFIN527_BLUETECHNIX_CM is not set +CONFIG_BFIN526_EZBRD=y + +# +# BF527 Specific Configuration +# + +# +# Alternative Multiplexing Scheme +# +# CONFIG_BF527_SPORT0_PORTF is not set +CONFIG_BF527_SPORT0_PORTG=y +CONFIG_BF527_SPORT0_TSCLK_PG10=y +# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set +CONFIG_BF527_UART1_PORTF=y +# CONFIG_BF527_UART1_PORTG is not set +# CONFIG_BF527_NAND_D_PORTF is not set +CONFIG_BF527_NAND_D_PORTH=y + +# +# Interrupt Priority Assignment +# + +# +# Priority +# +CONFIG_IRQ_PLL_WAKEUP=7 +CONFIG_IRQ_DMA0_ERROR=7 +CONFIG_IRQ_DMAR0_BLK=7 +CONFIG_IRQ_DMAR1_BLK=7 +CONFIG_IRQ_DMAR0_OVR=7 +CONFIG_IRQ_DMAR1_OVR=7 +CONFIG_IRQ_PPI_ERROR=7 +CONFIG_IRQ_MAC_ERROR=7 +CONFIG_IRQ_SPORT0_ERROR=7 +CONFIG_IRQ_SPORT1_ERROR=7 +CONFIG_IRQ_UART0_ERROR=7 +CONFIG_IRQ_UART1_ERROR=7 +CONFIG_IRQ_RTC=8 +CONFIG_IRQ_PPI=8 +CONFIG_IRQ_SPORT0_RX=9 +CONFIG_IRQ_SPORT0_TX=9 +CONFIG_IRQ_SPORT1_RX=9 +CONFIG_IRQ_SPORT1_TX=9 +CONFIG_IRQ_TWI=10 +CONFIG_IRQ_SPI=10 +CONFIG_IRQ_UART0_RX=10 +CONFIG_IRQ_UART0_TX=10 +CONFIG_IRQ_UART1_RX=10 +CONFIG_IRQ_UART1_TX=10 +CONFIG_IRQ_OPTSEC=11 +CONFIG_IRQ_CNT=11 +CONFIG_IRQ_MAC_RX=11 +CONFIG_IRQ_PORTH_INTA=11 +CONFIG_IRQ_MAC_TX=11 +CONFIG_IRQ_PORTH_INTB=11 +CONFIG_IRQ_TMR0=12 +CONFIG_IRQ_TMR1=12 +CONFIG_IRQ_TMR2=12 +CONFIG_IRQ_TMR3=12 +CONFIG_IRQ_TMR4=12 +CONFIG_IRQ_TMR5=12 +CONFIG_IRQ_TMR6=12 +CONFIG_IRQ_TMR7=12 +CONFIG_IRQ_PORTG_INTA=12 +CONFIG_IRQ_PORTG_INTB=12 +CONFIG_IRQ_MEM_DMA0=13 +CONFIG_IRQ_MEM_DMA1=13 +CONFIG_IRQ_WATCH=13 +CONFIG_IRQ_PORTF_INTA=13 +CONFIG_IRQ_PORTF_INTB=13 +CONFIG_IRQ_SPI_ERROR=7 +CONFIG_IRQ_NFC_ERROR=7 +CONFIG_IRQ_HDMA_ERROR=7 +CONFIG_IRQ_HDMA=7 +CONFIG_IRQ_USB_EINT=10 +CONFIG_IRQ_USB_INT0=11 +CONFIG_IRQ_USB_INT1=11 +CONFIG_IRQ_USB_INT2=11 +CONFIG_IRQ_USB_DMA=11 + +# +# Board customizations +# +# CONFIG_CMDLINE_BOOL is not set +CONFIG_BOOT_LOAD=0x1000 + +# +# Clock/PLL Setup +# +CONFIG_CLKIN_HZ=25000000 +# CONFIG_BFIN_KERNEL_CLOCK is not set +CONFIG_MAX_MEM_SIZE=512 +CONFIG_MAX_VCO_HZ=400000000 +CONFIG_MIN_VCO_HZ=50000000 +CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MIN_SCLK_HZ=27000000 + +# +# Kernel Timer/Scheduler +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +# CONFIG_CYCLES_CLOCKSOURCE is not set +# CONFIG_TICK_ONESHOT is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Memory Setup +# + +# +# Misc +# +CONFIG_BFIN_SCRATCH_REG_RETN=y +# CONFIG_BFIN_SCRATCH_REG_RETE is not set +# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set + +# +# Blackfin Kernel Optimizations +# + +# +# Memory Optimizations +# +CONFIG_I_ENTRY_L1=y +CONFIG_EXCPT_IRQ_SYSC_L1=y +CONFIG_DO_IRQ_L1=y +CONFIG_CORE_TIMER_IRQ_L1=y +CONFIG_IDLE_L1=y +# CONFIG_SCHEDULE_L1 is not set +CONFIG_ARITHMETIC_OPS_L1=y +CONFIG_ACCESS_OK_L1=y +# CONFIG_MEMSET_L1 is not set +# CONFIG_MEMCPY_L1 is not set +# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set +# CONFIG_IP_CHECKSUM_L1 is not set +CONFIG_CACHELINE_ALIGNED_L1=y +# CONFIG_SYSCALL_TAB_L1 is not set +# CONFIG_CPLB_SWITCH_TAB_L1 is not set + +# +# Speed Optimizations +# +CONFIG_BFIN_INS_LOWOVERHEAD=y +CONFIG_RAMKERNEL=y +# CONFIG_ROMKERNEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_VIRT_TO_BUS=y +CONFIG_BFIN_GPTIMERS=y +CONFIG_BFIN_DMA_5XX=y +# CONFIG_DMA_UNCACHED_4M is not set +# CONFIG_DMA_UNCACHED_2M is not set +CONFIG_DMA_UNCACHED_1M=y +# CONFIG_DMA_UNCACHED_NONE is not set + +# +# Cache Support +# +CONFIG_BFIN_ICACHE=y +CONFIG_BFIN_DCACHE=y +# CONFIG_BFIN_DCACHE_BANKA is not set +# CONFIG_BFIN_ICACHE_LOCK is not set +CONFIG_BFIN_WB=y +# CONFIG_BFIN_WT is not set +# CONFIG_MPU is not set + +# +# Asynchonous Memory Configuration +# + +# +# EBIU_AMGCTL Global Control +# +CONFIG_C_AMCKEN=y +CONFIG_C_CDPRIO=y +# CONFIG_C_AMBEN is not set +# CONFIG_C_AMBEN_B0 is not set +# CONFIG_C_AMBEN_B0_B1 is not set +# CONFIG_C_AMBEN_B0_B1_B2 is not set +CONFIG_C_AMBEN_ALL=y + +# +# EBIU_AMBCTL Control +# +CONFIG_BANK_0=0x7BB0 +CONFIG_BANK_1=0x5554 +CONFIG_BANK_2=0x7BB0 +CONFIG_BANK_3=0xFFC0 + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF_FDPIC=y +CONFIG_BINFMT_FLAT=y +CONFIG_BINFMT_ZFLAT=y +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_PM_WAKEUP_BY_GPIO is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_RAM=y +CONFIG_MTD_ROM=m +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_UCLINUX is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_BFIN=m +CONFIG_BFIN_NAND_BASE=0x20212000 +CONFIG_BFIN_NAND_CLE=2 +CONFIG_BFIN_NAND_ALE=1 +CONFIG_BFIN_NAND_READY=3 +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_BF5XX is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_BFIN_MAC=y +CONFIG_BFIN_TX_DESC_NUM=10 +CONFIG_BFIN_RX_DESC_NUM=20 +CONFIG_BFIN_MAC_RMII=y +# CONFIG_SMC91X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +CONFIG_NETDEV_1000=y +# CONFIG_E1000E_ENABLED is not set +# CONFIG_AX88180 is not set +CONFIG_NETDEV_10000=y + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_TWI_KEYPAD is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_AD9960 is not set +# CONFIG_SPI_ADC_BF533 is not set +# CONFIG_BF5xx_PPIFCD is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set +# CONFIG_BF5xx_PPI is not set +# CONFIG_BFIN_SPORT is not set +# CONFIG_BFIN_TIMER_LATENCY is not set +# CONFIG_TWI_LCD is not set +CONFIG_SIMPLE_GPIO=m +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_BFIN=y +CONFIG_SERIAL_BFIN_CONSOLE=y +CONFIG_SERIAL_BFIN_DMA=y +# CONFIG_SERIAL_BFIN_PIO is not set +# CONFIG_SERIAL_BFIN_UART0 is not set +CONFIG_SERIAL_BFIN_UART1=y +# CONFIG_BFIN_UART1_CTSRTS is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_BFIN_SPORT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_BFIN_OTP=y +# CONFIG_BFIN_OTP_WRITE_ENABLE is not set + +# +# CAN, the car bus and industrial fieldbus +# +# CONFIG_CAN4LINUX is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# +CONFIG_I2C_BLACKFIN_TWI=y +CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50 +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_PCA_PLATFORM is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_AD5252 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BFIN=y +# CONFIG_SPI_BITBANG is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_BFIN_WDT=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# SPI devices +# + +# +# ALSA Blackfin devices +# +# CONFIG_SND_BLACKFIN_AD1836 is not set +# CONFIG_SND_BFIN_AD73311 is not set +# CONFIG_SND_BFIN_AD73322 is not set + +# +# USB devices +# +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set + +# +# System on Chip audio support +# +CONFIG_SND_SOC=m +CONFIG_SND_BF5XX_I2S=m +CONFIG_SND_BF5XX_SOC_SSM2602=m +# CONFIG_SND_BF5XX_AC97 is not set +CONFIG_SND_BF5XX_SOC_SPORT=m +CONFIG_SND_BF5XX_SOC_I2S=m +CONFIG_SND_BF5XX_SPORT_NUM=0 + +# +# ALSA SoC audio for Freescale SOCs +# + +# +# SoC Audio for the Texas Instruments OMAP +# +CONFIG_SND_SOC_SSM2602=m + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +CONFIG_USB_OTG_BLACKLIST_HUB=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# Blackfin high speed USB support +# +CONFIG_USB_MUSB_HOST=y +# CONFIG_USB_MUSB_PERIPHERAL is not set +# CONFIG_USB_MUSB_OTG is not set +CONFIG_USB_MUSB_HDRC_HCD=y +CONFIG_MUSB_PIO_ONLY=y +CONFIG_USB_MUSB_LOGLEVEL=0 + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_BFIN=y +# CONFIG_UIO is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_YAFFS_FS=m +CONFIG_YAFFS_YAFFS1=y +# CONFIG_YAFFS_9BYTE_TAGS is not set +# CONFIG_YAFFS_DOES_ECC is not set +CONFIG_YAFFS_YAFFS2=y +CONFIG_YAFFS_AUTO_YAFFS2=y +# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set +# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_SAMPLES is not set +CONFIG_DEBUG_MMRS=y +CONFIG_DEBUG_HUNT_FOR_ZERO=y +CONFIG_DEBUG_BFIN_HWTRACE_ON=y +CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y +# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set +# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set +CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0 +# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set +# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set +CONFIG_EARLY_PRINTK=y +CONFIG_CPLB_INFO=y +CONFIG_ACCESS_CHECK=y + +# +# Security options +# +# CONFIG_KEYS is not set +CONFIG_SECURITY=y +# CONFIG_SECURITY_NETWORK is not set +# CONFIG_SECURITY_CAPABILITIES is not set +# CONFIG_SECURITY_ROOTPLUG is not set +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/blackfin/mach-bf527/boards/Kconfig b/arch/blackfin/mach-bf527/boards/Kconfig index 8bf9e58f014..df224d04e16 100644 --- a/arch/blackfin/mach-bf527/boards/Kconfig +++ b/arch/blackfin/mach-bf527/boards/Kconfig @@ -14,4 +14,9 @@ config BFIN527_BLUETECHNIX_CM help CM-BF527 support for EVAL- and DEV-Board. +config BFIN526_EZBRD + bool "BF526-EZBRD" + help + BF526-EZBRD/EZKIT Lite board support. + endchoice diff --git a/arch/blackfin/mach-bf527/boards/Makefile b/arch/blackfin/mach-bf527/boards/Makefile index 7ba7d256bbb..eb6ed3362f9 100644 --- a/arch/blackfin/mach-bf527/boards/Makefile +++ b/arch/blackfin/mach-bf527/boards/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_BFIN527_EZKIT) += ezkit.o obj-$(CONFIG_BFIN527_BLUETECHNIX_CM) += cm_bf527.o +obj-$(CONFIG_BFIN526_EZBRD) += ezbrd.o diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c new file mode 100644 index 00000000000..36c87b6fbde --- /dev/null +++ b/arch/blackfin/mach-bf527/boards/ezbrd.c @@ -0,0 +1,734 @@ +/* + * File: arch/blackfin/mach-bf527/boards/ezbrd.c + * Based on: arch/blackfin/mach-bf537/boards/stamp.c + * Author: Aidan Williams + * + * Created: + * Description: + * + * Modified: + * Copyright 2005 National ICT Australia (NICTA) + * Copyright 2004-2008 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Name the Board for the /proc/cpuinfo + */ +const char bfin_board_name[] = "BF526-EZBRD"; + +/* + * Driver needs to know address, irq and flag pin. + */ + +#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) +static struct resource musb_resources[] = { + [0] = { + .start = 0xffc03800, + .end = 0xffc03cff, + .flags = IORESOURCE_MEM, + }, + [1] = { /* general IRQ */ + .start = IRQ_USB_INT0, + .end = IRQ_USB_INT0, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, + [2] = { /* DMA IRQ */ + .start = IRQ_USB_DMA, + .end = IRQ_USB_DMA, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; + +static struct musb_hdrc_config musb_config = { + .multipoint = 0, + .dyn_fifo = 0, + .soft_con = 1, + .dma = 1, + .num_eps = 7, + .dma_channels = 7, + .gpio_vrsel = GPIO_PG13, +}; + +static struct musb_hdrc_platform_data musb_plat = { +#if defined(CONFIG_USB_MUSB_OTG) + .mode = MUSB_OTG, +#elif defined(CONFIG_USB_MUSB_HDRC_HCD) + .mode = MUSB_HOST, +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) + .mode = MUSB_PERIPHERAL, +#endif + .config = &musb_config, +}; + +static u64 musb_dmamask = ~(u32)0; + +static struct platform_device musb_device = { + .name = "musb_hdrc", + .id = 0, + .dev = { + .dma_mask = &musb_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &musb_plat, + }, + .num_resources = ARRAY_SIZE(musb_resources), + .resource = musb_resources, +}; +#endif + +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) +static struct mtd_partition ezbrd_partitions[] = { + { + .name = "bootloader(nor)", + .size = 0x40000, + .offset = 0, + }, { + .name = "linux kernel(nor)", + .size = 0x1C0000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "file system(nor)", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; + +static struct physmap_flash_data ezbrd_flash_data = { + .width = 2, + .parts = ezbrd_partitions, + .nr_parts = ARRAY_SIZE(ezbrd_partitions), +}; + +static struct resource ezbrd_flash_resource = { + .start = 0x20000000, + .end = 0x203fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ezbrd_flash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ezbrd_flash_data, + }, + .num_resources = 1, + .resource = &ezbrd_flash_resource, +}; +#endif + +#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) +static struct mtd_partition partition_info[] = { + { + .name = "linux kernel(nand)", + .offset = 0, + .size = 4 * 1024 * 1024, + }, + { + .name = "file system(nand)", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct bf5xx_nand_platform bf5xx_nand_platform = { + .page_size = NFC_PG_SIZE_256, + .data_width = NFC_NWIDTH_8, + .partitions = partition_info, + .nr_partitions = ARRAY_SIZE(partition_info), + .rd_dly = 3, + .wr_dly = 3, +}; + +static struct resource bf5xx_nand_resources[] = { + { + .start = NFC_CTL, + .end = NFC_DATA_RD + 2, + .flags = IORESOURCE_MEM, + }, + { + .start = CH_NFC, + .end = CH_NFC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bf5xx_nand_device = { + .name = "bf5xx-nand", + .id = 0, + .num_resources = ARRAY_SIZE(bf5xx_nand_resources), + .resource = bf5xx_nand_resources, + .dev = { + .platform_data = &bf5xx_nand_platform, + }, +}; +#endif + +#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) +static struct platform_device rtc_device = { + .name = "rtc-bfin", + .id = -1, +}; +#endif + + +#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mac_device = { + .name = "bfin_mac", +}; +#endif + +#if defined(CONFIG_MTD_M25P80) \ + || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition bfin_spi_flash_partitions[] = { + { + .name = "bootloader(spi)", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_CAP_ROM + }, { + .name = "linux kernel(spi)", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; + +static struct flash_platform_data bfin_spi_flash_data = { + .name = "m25p80", + .parts = bfin_spi_flash_partitions, + .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions), + .type = "m25p16", +}; + +/* SPI flash chip (m25p64) */ +static struct bfin5xx_spi_chip spi_flash_chip_info = { + .enable_dma = 0, /* use dma transfer with this chip*/ + .bits_per_word = 8, +}; +#endif + +#if defined(CONFIG_SPI_ADC_BF533) \ + || defined(CONFIG_SPI_ADC_BF533_MODULE) +/* SPI ADC chip */ +static struct bfin5xx_spi_chip spi_adc_chip_info = { + .enable_dma = 1, /* use dma transfer with this chip*/ + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) +static struct bfin5xx_spi_chip spi_mmc_chip_info = { + .enable_dma = 1, + .bits_per_word = 8, +}; +#endif + +#if defined(CONFIG_PBX) +static struct bfin5xx_spi_chip spi_si3xxx_chip_info = { + .ctl_reg = 0x4, /* send zero */ + .enable_dma = 0, + .bits_per_word = 8, + .cs_change_per_word = 1, +}; +#endif + +#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE) +static struct bfin5xx_spi_chip spi_ad7877_chip_info = { + .enable_dma = 0, + .bits_per_word = 16, +}; + +static const struct ad7877_platform_data bfin_ad7877_ts_info = { + .model = 7877, + .vref_delay_usecs = 50, /* internal, no capacitor */ + .x_plate_ohms = 419, + .y_plate_ohms = 486, + .pressure_max = 1000, + .pressure_min = 0, + .stopacq_polarity = 1, + .first_conversion_delay = 3, + .acquisition_time = 1, + .averaging = 1, + .pen_down_acc_interval = 1, +}; +#endif + +#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \ + && defined(CONFIG_SND_SOC_WM8731_SPI) +static struct bfin5xx_spi_chip spi_wm8731_chip_info = { + .enable_dma = 0, + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) +static struct bfin5xx_spi_chip spidev_chip_info = { + .enable_dma = 0, + .bits_per_word = 8, +}; +#endif + +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) +static struct bfin5xx_spi_chip lq035q1_spi_chip_info = { + .enable_dma = 0, + .bits_per_word = 8, +}; +#endif + +static struct spi_board_info bfin_spi_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) \ + || defined(CONFIG_MTD_M25P80_MODULE) + { + /* the modalias must be the same as spi device driver name */ + .modalias = "m25p80", /* Name of spi_driver for this device */ + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, /* Framework bus number */ + .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/ + .platform_data = &bfin_spi_flash_data, + .controller_data = &spi_flash_chip_info, + .mode = SPI_MODE_3, + }, +#endif + +#if defined(CONFIG_SPI_ADC_BF533) \ + || defined(CONFIG_SPI_ADC_BF533_MODULE) + { + .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */ + .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, /* Framework bus number */ + .chip_select = 1, /* Framework chip select. */ + .platform_data = NULL, /* No spi_driver specific config */ + .controller_data = &spi_adc_chip_info, + }, +#endif + +#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) + { + .modalias = "spi_mmc_dummy", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 0, + .platform_data = NULL, + .controller_data = &spi_mmc_chip_info, + .mode = SPI_MODE_3, + }, + { + .modalias = "spi_mmc", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = CONFIG_SPI_MMC_CS_CHAN, + .platform_data = NULL, + .controller_data = &spi_mmc_chip_info, + .mode = SPI_MODE_3, + }, +#endif +#if defined(CONFIG_PBX) + { + .modalias = "fxs-spi", + .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 8 - CONFIG_J11_JUMPER, + .controller_data = &spi_si3xxx_chip_info, + .mode = SPI_MODE_3, + }, + { + .modalias = "fxo-spi", + .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 8 - CONFIG_J19_JUMPER, + .controller_data = &spi_si3xxx_chip_info, + .mode = SPI_MODE_3, + }, +#endif +#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE) + { + .modalias = "ad7877", + .platform_data = &bfin_ad7877_ts_info, + .irq = IRQ_PF8, + .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 2, + .controller_data = &spi_ad7877_chip_info, + }, +#endif +#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \ + && defined(CONFIG_SND_SOC_WM8731_SPI) + { + .modalias = "wm8731", + .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 5, + .controller_data = &spi_wm8731_chip_info, + .mode = SPI_MODE_0, + }, +#endif +#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) + { + .modalias = "spidev", + .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 1, + .controller_data = &spidev_chip_info, + }, +#endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) + { + .modalias = "bfin-lq035q1-spi", + .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 1, + .controller_data = &lq035q1_spi_chip_info, + .mode = SPI_CPHA | SPI_CPOL, + }, +#endif +}; + +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) +/* SPI controller data */ +static struct bfin5xx_spi_master bfin_spi0_info = { + .num_chipselect = 8, + .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, +}; + +/* SPI (0) */ +static struct resource bfin_spi0_resource[] = { + [0] = { + .start = SPI0_REGBASE, + .end = SPI0_REGBASE + 0xFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = CH_SPI, + .end = CH_SPI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_spi0_device = { + .name = "bfin-spi", + .id = 0, /* Bus number */ + .num_resources = ARRAY_SIZE(bfin_spi0_resource), + .resource = bfin_spi0_resource, + .dev = { + .platform_data = &bfin_spi0_info, /* Passed to driver */ + }, +}; +#endif /* spi master and devices */ + +#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) +static struct resource bfin_uart_resources[] = { +#ifdef CONFIG_SERIAL_BFIN_UART0 + { + .start = 0xFFC00400, + .end = 0xFFC004FF, + .flags = IORESOURCE_MEM, + }, +#endif +#ifdef CONFIG_SERIAL_BFIN_UART1 + { + .start = 0xFFC02000, + .end = 0xFFC020FF, + .flags = IORESOURCE_MEM, + }, +#endif +}; + +static struct platform_device bfin_uart_device = { + .name = "bfin-uart", + .id = 1, + .num_resources = ARRAY_SIZE(bfin_uart_resources), + .resource = bfin_uart_resources, +}; +#endif + +#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE) +static struct resource bfin_sir_resources[] = { +#ifdef CONFIG_BFIN_SIR0 + { + .start = 0xFFC00400, + .end = 0xFFC004FF, + .flags = IORESOURCE_MEM, + }, +#endif +#ifdef CONFIG_BFIN_SIR1 + { + .start = 0xFFC02000, + .end = 0xFFC020FF, + .flags = IORESOURCE_MEM, + }, +#endif +}; + +static struct platform_device bfin_sir_device = { + .name = "bfin_sir", + .id = 0, + .num_resources = ARRAY_SIZE(bfin_sir_resources), + .resource = bfin_sir_resources, +}; +#endif + +#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) +static struct resource bfin_twi0_resource[] = { + [0] = { + .start = TWI0_REGBASE, + .end = TWI0_REGBASE, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_TWI, + .end = IRQ_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device i2c_bfin_twi_device = { + .name = "i2c-bfin-twi", + .id = 0, + .num_resources = ARRAY_SIZE(bfin_twi0_resource), + .resource = bfin_twi0_resource, +}; +#endif + +#ifdef CONFIG_I2C_BOARDINFO +static struct i2c_board_info __initdata bfin_i2c_board_info[] = { +#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) + { + I2C_BOARD_INFO("pcf8574_lcd", 0x22), + }, +#endif +#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE) + { + I2C_BOARD_INFO("pcf8574_keypad", 0x27), + .irq = IRQ_PF8, + }, +#endif +}; +#endif + +#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) +static struct platform_device bfin_sport0_uart_device = { + .name = "bfin-sport-uart", + .id = 0, +}; + +static struct platform_device bfin_sport1_uart_device = { + .name = "bfin-sport-uart", + .id = 1, +}; +#endif + +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +#include +#include + +static struct gpio_keys_button bfin_gpio_keys_table[] = { + {BTN_0, GPIO_PG0, 1, "gpio-keys: BTN0"}, + {BTN_1, GPIO_PG13, 1, "gpio-keys: BTN1"}, +}; + +static struct gpio_keys_platform_data bfin_gpio_keys_data = { + .buttons = bfin_gpio_keys_table, + .nbuttons = ARRAY_SIZE(bfin_gpio_keys_table), +}; + +static struct platform_device bfin_device_gpiokeys = { + .name = "gpio-keys", + .dev = { + .platform_data = &bfin_gpio_keys_data, + }, +}; +#endif + +static struct resource bfin_gpios_resources = { + .start = 0, + .end = MAX_BLACKFIN_GPIOS - 1, + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device bfin_gpios_device = { + .name = "simple-gpio", + .id = -1, + .num_resources = 1, + .resource = &bfin_gpios_resources, +}; + +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_100, 400000000), + VRPAIR(VLEV_105, 426000000), + VRPAIR(VLEV_110, 500000000), + VRPAIR(VLEV_115, 533000000), + VRPAIR(VLEV_120, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) +#include + +static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = { + .mode = LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB, + .use_bl = 1, + .gpio_bl = GPIO_PG12, +}; + +static struct resource bfin_lq035q1_resources[] = { + { + .start = IRQ_PPI_ERROR, + .end = IRQ_PPI_ERROR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_lq035q1_device = { + .name = "bfin-lq035q1", + .id = -1, + .num_resources = ARRAY_SIZE(bfin_lq035q1_resources), + .resource = bfin_lq035q1_resources, + .dev = { + .platform_data = &bfin_lq035q1_data, + }, +}; +#endif + +static struct platform_device *stamp_devices[] __initdata = { + + &bfin_dpmc, + +#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) + &bf5xx_nand_device, +#endif + +#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) + &rtc_device, +#endif + +#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) + &musb_device, +#endif + +#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mac_device, +#endif + +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) + &bfin_spi0_device, +#endif + +#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) + &bfin_uart_device, +#endif + +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) + &bfin_lq035q1_device, +#endif + +#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE) + &bfin_sir_device, +#endif + +#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) + &i2c_bfin_twi_device, +#endif + +#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) + &bfin_sport0_uart_device, + &bfin_sport1_uart_device, +#endif + +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) + &bfin_device_gpiokeys, +#endif + +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) + &ezbrd_flash_device, +#endif + + &bfin_gpios_device, +}; + +static int __init stamp_init(void) +{ + printk(KERN_INFO "%s(): registering device resources\n", __func__); + +#ifdef CONFIG_I2C_BOARDINFO + i2c_register_board_info(0, bfin_i2c_board_info, + ARRAY_SIZE(bfin_i2c_board_info)); +#endif + + platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); + spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); + return 0; +} + +arch_initcall(stamp_init); + +void native_machine_restart(char *cmd) +{ + /* workaround reboot hang when booting from SPI */ + if ((bfin_read_SYSCR() & 0x7) == 0x3) + bfin_gpio_reset_spi0_ssel1(); +} + +void bfin_get_ether_addr(char *addr) +{ + /* the MAC is stored in OTP memory page 0xDF */ + u32 ret; + u64 otp_mac; + u32 (*otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)0xEF00001A; + + ret = otp_read(0xDF, 0x00, &otp_mac); + if (!(ret & 0x1)) { + char *otp_mac_p = (char *)&otp_mac; + for (ret = 0; ret < 6; ++ret) + addr[ret] = otp_mac_p[5 - ret]; + } +} +EXPORT_SYMBOL(bfin_get_ether_addr); -- cgit v1.2.3 From 1ffb9bef23d283e0e94c73e6683a6591ba3b0888 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 7 Oct 2008 16:06:27 +0800 Subject: Blackfin arch: add note about newer ezkits using PB4 for AD7877 instead of PJ11 Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/boards/ezkit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index d22515d080a..628f21889e2 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -559,7 +559,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { { .modalias = "ad7877", .platform_data = &bfin_ad7877_ts_info, - .irq = IRQ_PJ11, + .irq = IRQ_PJ11, /* newer boards (Rev 1.4+) use IRQ_PB4 */ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, .chip_select = 2, -- cgit v1.2.3 From f4585a08479a730fb809606b8ee327a5398c117c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 13 Oct 2008 14:45:21 +0800 Subject: Blackfin arch: only include asm/cplb.h when it is truly used Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/cacheflush.h | 2 -- arch/blackfin/kernel/traps.c | 1 + arch/blackfin/mach-bf527/boards/cm_bf527.c | 3 +-- arch/blackfin/mach-bf527/boards/ezkit.c | 3 +-- arch/blackfin/mach-bf548/boards/cm_bf548.c | 7 +++---- arch/blackfin/mach-bf548/boards/ezkit.c | 3 +-- 6 files changed, 7 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index d81a77545a0..5ef9e35e9c3 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h @@ -30,8 +30,6 @@ #ifndef _BLACKFIN_CACHEFLUSH_H #define _BLACKFIN_CACHEFLUSH_H -#include - extern void blackfin_icache_dcache_flush_range(unsigned int, unsigned int); extern void blackfin_icache_flush_range(unsigned int, unsigned int); extern void blackfin_dcache_flush_range(unsigned int, unsigned int); diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 9a9d5083acf..fd24e04fc19 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index 986483fb69f..9ea440bbb13 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -209,7 +208,7 @@ static struct mtd_partition partition_info[] = { { .name = "linux kernel(nand)", .offset = 0, - .size = 4 * SIZE_1M, + .size = 4 * 1024 * 1024, }, { .name = "file system(nand)", diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index a756934482c..04a8d6da905 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -226,7 +225,7 @@ static struct mtd_partition partition_info[] = { { .name = "linux kernel(nand)", .offset = 0, - .size = 4 * SIZE_1M, + .size = 4 * 1024 * 1024, }, { .name = "file system(nand)", diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c index 36f56f9ffd0..c5609ff805f 100644 --- a/arch/blackfin/mach-bf548/boards/cm_bf548.c +++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -329,12 +328,12 @@ static struct mtd_partition partition_info[] = { { .name = "linux kernel(nand)", .offset = 0, - .size = 4 * SIZE_1M, + .size = 4 * 1024 * 1024, }, { .name = "file system(nand)", - .offset = 4 * SIZE_1M, - .size = (256 - 4) * SIZE_1M, + .offset = 4 * 1024 * 1024, + .size = (256 - 4) * 1024 * 1024, }, }; diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 628f21889e2..397ddf6b810 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -375,7 +374,7 @@ static struct mtd_partition partition_info[] = { { .name = "linux kernel(nand)", .offset = 0, - .size = 4 * SIZE_1M, + .size = 4 * 1024 * 1024, }, { .name = "file system(nand)", -- cgit v1.2.3 From 0c7a6b2135c1bcb5139ca9ca87f292caafcb9410 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 8 Oct 2008 16:27:12 +0800 Subject: Blackfin arch: add supporting for double fault debug handling Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig.debug | 38 ++++++++ arch/blackfin/kernel/setup.c | 30 ++++-- arch/blackfin/kernel/traps.c | 34 ++++++- arch/blackfin/mach-common/entry.S | 189 ++++++++++++++++++++++++++------------ arch/blackfin/mach-common/head.S | 40 +++++++- 5 files changed, 255 insertions(+), 76 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index c468624d55f..0afa8981872 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -22,6 +22,44 @@ config DEBUG_HWERR hardware error interrupts and need to know where they are coming from. +config DEBUG_DOUBLEFAULT + bool "Debug Double Faults" + default n + help + If an exception is caused while executing code within the exception + handler, the NMI handler, the reset vector, or in emulator mode, + a double fault occurs. On the Blackfin, this is a unrecoverable + event. You have two options: + - RESET exactly when double fault occurs. The excepting + instruction address is stored in RETX, where the next kernel + boot will print it out. + - Print debug message. This is much more error prone, although + easier to handle. It is error prone since: + - The excepting instruction is not committed. + - All writebacks from the instruction are prevented. + - The generated exception is not taken. + - The EXCAUSE field is updated with an unrecoverable event + The only way to check this is to see if EXCAUSE contains the + unrecoverable event value at every exception return. By selecting + this option, you are skipping over the faulting instruction, and + hoping things stay together enough to print out a debug message. + + This does add a little kernel code, but is the only method to debug + double faults - if unsure say "Y" + +choice + prompt "Double Fault Failure Method" + default DEBUG_DOUBLEFAULT_PRINT + depends on DEBUG_DOUBLEFAULT + +config DEBUG_DOUBLEFAULT_PRINT + bool "Print" + +config DEBUG_DOUBLEFAULT_RESET + bool "Reset" + +endchoice + config DEBUG_ICACHE_CHECK bool "Check Instruction cache coherency" depends on DEBUG_KERNEL diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 7a82d10b4eb..8e639dc886a 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -52,7 +52,8 @@ EXPORT_SYMBOL(mtd_size); #endif char __initdata command_line[COMMAND_LINE_SIZE]; -unsigned int __initdata *__retx; +void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat, + *init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr; /* boot memmap, for parsing "memmap=" */ #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ @@ -782,16 +783,25 @@ void __init setup_arch(char **cmdline_p) _bfin_swrst = bfin_read_SWRST(); - /* If we double fault, reset the system - otherwise we hang forever */ - bfin_write_SWRST(DOUBLE_FAULT); +#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT + bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT); +#endif +#ifdef CONFIG_DEBUG_DOUBLEFAULT_RESET + bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT); +#endif - if (_bfin_swrst & RESET_DOUBLE) - /* - * don't decode the address, since you don't know if this - * kernel's symbol map is the same as the crashing kernel - */ - printk(KERN_INFO "Recovering from Double Fault event at %pF\n", __retx); - else if (_bfin_swrst & RESET_WDOG) + if (_bfin_swrst & RESET_DOUBLE) { + printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* We assume the crashing kernel, and the current symbol table match */ + printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n", + (int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx); + printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr); + printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr); +#endif + printk(KERN_NOTICE " The instruction at %pF caused a double exception\n", + init_retx); + } else if (_bfin_swrst & RESET_WDOG) printk(KERN_INFO "Recovering from Watchdog event\n"); else if (_bfin_swrst & RESET_SOFTWARE) printk(KERN_NOTICE "Reset caused by Software reset\n"); diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index fd24e04fc19..bd41fca315d 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -68,7 +68,15 @@ void __init trap_init(void) CSYNC(); } -unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr; +/* + * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR + * values across the transition from exception to IRQ5. + * We put these in L1, so they are going to be in a valid + * location during exception context + */ +__attribute__((l1_data)) +unsigned long saved_retx, saved_seqstat, + saved_icplb_fault_addr, saved_dcplb_fault_addr; static void decode_address(char *buf, unsigned long address) { @@ -186,9 +194,27 @@ asmlinkage void double_fault_c(struct pt_regs *fp) console_verbose(); oops_in_progress = 1; printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); - dump_bfin_process(fp); - dump_bfin_mem(fp); - show_regs(fp); +#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT + if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { + char buf[150]; + decode_address(buf, saved_retx); + printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", + (int)saved_seqstat & SEQSTAT_EXCAUSE, buf); + decode_address(buf, saved_dcplb_fault_addr); + printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); + decode_address(buf, saved_icplb_fault_addr); + printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); + + decode_address(buf, fp->retx); + printk(KERN_NOTICE "The instruction at %s caused a double exception\n", + buf); + } else +#endif + { + dump_bfin_process(fp); + dump_bfin_mem(fp); + show_regs(fp); + } panic("Double Fault - unrecoverable event\n"); } diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 847c172a99e..90c7397036e 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -129,6 +129,18 @@ ENTRY(_ex_icplb_miss) #else call __cplb_hdr; #endif + +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* While we were processing this, did we double fault? */ + r7 = SEQSTAT; /* reason code is in bit 5:0 */ + r6.l = lo(SEQSTAT_EXCAUSE); + r6.h = hi(SEQSTAT_EXCAUSE); + r7 = r7 & r6; + r6 = 0x25; + CC = R7 == R6; + if CC JUMP _double_fault; +#endif + DEBUG_HWTRACE_RESTORE(p5, r7) RESTORE_ALL_SYS SP = EX_SCRATCH_REG; @@ -136,11 +148,8 @@ ENTRY(_ex_icplb_miss) ENDPROC(_ex_icplb_miss) ENTRY(_ex_syscall) - (R7:6,P5:4) = [sp++]; - ASTAT = [sp++]; raise 15; /* invoked by TRAP #0, for sys call */ - sp = EX_SCRATCH_REG; - rtx + jump.s _bfin_return_from_exception; ENDPROC(_ex_syscall) ENTRY(_ex_soft_bp) @@ -250,6 +259,29 @@ ENTRY(_bfin_return_from_exception) R7=LC1; LC1=R7; #endif + +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* While we were processing the current exception, + * did we cause another, and double fault? + */ + r7 = SEQSTAT; /* reason code is in bit 5:0 */ + r6.l = lo(SEQSTAT_EXCAUSE); + r6.h = hi(SEQSTAT_EXCAUSE); + r7 = r7 & r6; + r6 = 0x25; + CC = R7 == R6; + if CC JUMP _double_fault; + + /* Did we cause a HW error? */ + p5.l = lo(ILAT); + p5.h = hi(ILAT); + r6 = [p5]; + r7 = 0x20; /* Did I just cause anther HW error? */ + r7 = r7 & r1; + CC = R7 == R6; + if CC JUMP _double_fault; +#endif + (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; sp = EX_SCRATCH_REG; @@ -292,6 +324,14 @@ ENTRY(_ex_trap_c) [p4] = p5; csync; +#ifndef CONFIG_DEBUG_DOUBLEFAULT + /* + * Save these registers, as they are only valid in exception context + * (where we are now - as soon as we defer to IRQ5, they can change) + * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3, + * but they are not very interesting, so don't save them + */ + p4.l = lo(DCPLB_FAULT_ADDR); p4.h = hi(DCPLB_FAULT_ADDR); r7 = [p4]; @@ -304,12 +344,11 @@ ENTRY(_ex_trap_c) p5.l = _saved_icplb_fault_addr; [p5] = r7; - p4.l = _excpt_saved_stuff; - p4.h = _excpt_saved_stuff; - r6 = retx; + p4.l = _saved_retx; + p4.h = _saved_retx; [p4] = r6; - +#endif r6 = SYSCFG; [p4 + 4] = r6; BITCLR(r6, 0); @@ -327,59 +366,56 @@ ENTRY(_ex_trap_c) r6 = 0x3f; sti r6; - (R7:6,P5:4) = [sp++]; - ASTAT = [sp++]; - SP = EX_SCRATCH_REG; raise 5; - rtx; + jump.s _bfin_return_from_exception; ENDPROC(_ex_trap_c) /* We just realized we got an exception, while we were processing a different * exception. This is a unrecoverable event, so crash */ ENTRY(_double_fault) - /* Turn caches & protection off, to ensure we don't get any more - * double exceptions - */ - - P4.L = LO(IMEM_CONTROL); - P4.H = HI(IMEM_CONTROL); - - R5 = [P4]; /* Control Register*/ - BITCLR(R5,ENICPLB_P); - SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ - .align 8; - [P4] = R5; - SSYNC; - - P4.L = LO(DMEM_CONTROL); - P4.H = HI(DMEM_CONTROL); - R5 = [P4]; - BITCLR(R5,ENDCPLB_P); - SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ - .align 8; - [P4] = R5; - SSYNC; - - /* Fix up the stack */ - (R7:6,P5:4) = [sp++]; - ASTAT = [sp++]; - SP = EX_SCRATCH_REG; - - /* We should be out of the exception stack, and back down into - * kernel or user space stack - */ - SAVE_ALL_SYS + /* Turn caches & protection off, to ensure we don't get any more + * double exceptions + */ + + P4.L = LO(IMEM_CONTROL); + P4.H = HI(IMEM_CONTROL); + + R5 = [P4]; /* Control Register*/ + BITCLR(R5,ENICPLB_P); + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + + P4.L = LO(DMEM_CONTROL); + P4.H = HI(DMEM_CONTROL); + R5 = [P4]; + BITCLR(R5,ENDCPLB_P); + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + + /* Fix up the stack */ + (R7:6,P5:4) = [sp++]; + ASTAT = [sp++]; + SP = EX_SCRATCH_REG; + + /* We should be out of the exception stack, and back down into + * kernel or user space stack + */ + SAVE_ALL_SYS /* The dumping functions expect the return address in the RETI * slot. */ r6 = retx; [sp + PT_PC] = r6; - r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ - SP += -12; - call _double_fault_c; - SP += 12; + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ + SP += -12; + call _double_fault_c; + SP += 12; .L_double_fault_panic: JUMP .L_double_fault_panic @@ -388,8 +424,8 @@ ENDPROC(_double_fault) ENTRY(_exception_to_level5) SAVE_ALL_SYS - p4.l = _excpt_saved_stuff; - p4.h = _excpt_saved_stuff; + p4.l = _saved_retx; + p4.h = _saved_retx; r6 = [p4]; [sp + PT_PC] = r6; @@ -420,6 +456,17 @@ ENTRY(_exception_to_level5) call _trap_c; SP += 12; +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* Grab ILAT */ + p2.l = lo(ILAT); + p2.h = hi(ILAT); + r0 = [p2]; + r1 = 0x20; /* Did I just cause anther HW error? */ + r0 = r0 & r1; + CC = R0 == R1; + if CC JUMP _double_fault; +#endif + call _ret_from_exception; RESTORE_ALL_SYS rti; @@ -436,7 +483,39 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ /* Try to deal with syscalls quickly. */ [--sp] = ASTAT; [--sp] = (R7:6,P5:4); + +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* + * Save these registers, as they are only valid in exception context + * (where we are now - as soon as we defer to IRQ5, they can change) + * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3, + * but they are not very interesting, so don't save them + */ + + p4.l = lo(DCPLB_FAULT_ADDR); + p4.h = hi(DCPLB_FAULT_ADDR); + r7 = [p4]; + p5.h = _saved_dcplb_fault_addr; + p5.l = _saved_dcplb_fault_addr; + [p5] = r7; + + r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; + p5.h = _saved_icplb_fault_addr; + p5.l = _saved_icplb_fault_addr; + [p5] = r7; + + p4.l = _saved_retx; + p4.h = _saved_retx; + r6 = retx; + [p4] = r6; + r7 = SEQSTAT; /* reason code is in bit 5:0 */ + p4.l = _saved_seqstat; + p4.h = _saved_seqstat; + [p4] = r7; +#else + r7 = SEQSTAT; /* reason code is in bit 5:0 */ +#endif r6.l = lo(SEQSTAT_EXCAUSE); r6.h = hi(SEQSTAT_EXCAUSE); r7 = r7 & r6; @@ -1432,15 +1511,7 @@ ENTRY(_sys_call_table) .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall .endr - - /* - * Used to save the real RETX, IMASK and SYSCFG when temporarily - * storing safe values across the transition from exception to IRQ5. - */ -_excpt_saved_stuff: - .long 0; - .long 0; - .long 0; +END(_sys_call_table) _exception_stack: .rept 1024 diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 191b4e974c4..7cb21cfcbf2 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -90,12 +90,46 @@ ENTRY(__start) [p0] = R0; SSYNC; - /* Save RETX, in case of doublefault */ - p0.l = ___retx; - p0.h = ___retx; + /* in case of double faults, save a few things */ + p0.l = _init_retx; + p0.h = _init_retx; R0 = RETX; [P0] = R0; +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* Only save these if we are storing them, + * This happens here, since L1 gets clobbered + * below + */ + p0.l = _saved_retx; + p0.h = _saved_retx; + p1.l = _init_saved_retx; + p1.h = _init_saved_retx; + r0 = [p0]; + [p1] = r0; + + p0.l = _saved_dcplb_fault_addr; + p0.h = _saved_dcplb_fault_addr; + p1.l = _init_saved_dcplb_fault_addr; + p1.h = _init_saved_dcplb_fault_addr; + r0 = [p0]; + [p1] = r0; + + p0.l = _saved_icplb_fault_addr; + p0.h = _saved_icplb_fault_addr; + p1.l = _init_saved_icplb_fault_addr; + p1.h = _init_saved_icplb_fault_addr; + r0 = [p0]; + [p1] = r0; + + p0.l = _saved_seqstat; + p0.h = _saved_seqstat; + p1.l = _init_saved_seqstat; + p1.h = _init_saved_seqstat; + r0 = [p0]; + [p1] = r0; +#endif + /* Initialize stack pointer */ sp.l = lo(INITIAL_STACK); sp.h = hi(INITIAL_STACK); -- cgit v1.2.3 From 5d2e321306f82550e6d354b3210a18b86bdb13c1 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Tue, 7 Oct 2008 16:27:01 +0800 Subject: Blackfin arch: fixing bug - under IRQ stress, running applications may wrongly trigger an ICPLB miss and be killed Disable IRQs while frobbing the CPLB registers, to avoid accessing the data in current_rwx_mask while it isn't covered by CPLBs. Signed-off-by: Bernd Schmidt Signed-off-by: Bryan Wu --- arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 99f2831e296..5094677fd09 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c @@ -322,9 +322,11 @@ int cplb_hdr(int seqstat, struct pt_regs *regs) void flush_switched_cplbs(void) { int i; + unsigned long flags; nr_cplb_flush++; + local_irq_save(flags); disable_icplb(); for (i = first_switched_icplb; i < MAX_CPLBS; i++) { icplb_tbl[i].data = 0; @@ -338,6 +340,8 @@ void flush_switched_cplbs(void) bfin_write32(DCPLB_DATA0 + i * 4, 0); } enable_dcplb(); + local_irq_restore(flags); + } void set_mask_dcplbs(unsigned long *masks) @@ -345,10 +349,15 @@ void set_mask_dcplbs(unsigned long *masks) int i; unsigned long addr = (unsigned long)masks; unsigned long d_data; - current_rwx_mask = masks; + unsigned long flags; - if (!masks) + if (!masks) { + current_rwx_mask = masks; return; + } + + local_irq_save(flags); + current_rwx_mask = masks; d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; #ifdef CONFIG_BFIN_DCACHE @@ -367,4 +376,5 @@ void set_mask_dcplbs(unsigned long *masks) addr += PAGE_SIZE; } enable_dcplb(); + local_irq_restore(flags); } -- cgit v1.2.3 From f364eadab59b316ea0bd9f9bc01af0ad89065569 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 7 Oct 2008 14:04:27 -0700 Subject: x86: xsave: fix error condition in save_i387_xstate() Actually return failure on error. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin --- arch/x86/kernel/xsave.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index ed5274a5bb0..448fde96963 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -121,6 +121,8 @@ int save_i387_xstate(void __user *buf) err |= __put_user(FP_XSTATE_MAGIC2, (__u32 __user *) (buf + sig_xstate_size - FP_XSTATE_MAGIC2_SIZE)); + if (err) + return err; } return 1; -- cgit v1.2.3 From 04944b793e18ece23f63c0252646b310c1845940 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 7 Oct 2008 14:04:28 -0700 Subject: x86: xsave: set FP, SSE bits in the xsave header in the user sigcontext If a processor implementation discern that a processor state component is in its initialized state, it may modify the corresponding bit in the xsave header.xstate_bv as '0'. State in the memory layout setup by 'xsave' will be consistent with the bit values in the header. During signal handling, legacy applications may change the FP/SSE bits in the sigcontext memory layout without touching the FP/SSE header bits in the xsave header. So always set FP/SSE bits in the xsave header while saving the sigcontext state to the user space. During signal return, this will enable the kernel to capture any changes to the FP/SSE bits by the legacy applications which don't touch xsave headers. xsave aware apps can change the xstate_bv in the xsave header aswell as change any contents in the memory layout. xrestor as part of sigreturn will capture all the changes. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin --- arch/x86/kernel/i387.c | 14 ++++++++++++++ arch/x86/kernel/xsave.c | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 45723f1fe19..1f20608d4ca 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -468,9 +468,23 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) static int save_i387_xsave(void __user *buf) { + struct task_struct *tsk = current; struct _fpstate_ia32 __user *fx = buf; int err = 0; + /* + * For legacy compatible, we always set FP/SSE bits in the bit + * vector while saving the state to the user context. + * This will enable us capturing any changes(during sigreturn) to + * the FP/SSE bits by the legacy applications which don't touch + * xstate_bv in the xsave header. + * + * xsave aware applications can change the xstate_bv in the xsave + * header as well as change any contents in the memory layout. + * xrestore as part of sigreturn will capture all the changes. + */ + tsk->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; + if (save_i387_fxsave(fx) < 0) return -1; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 448fde96963..2f98323716d 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -114,6 +114,8 @@ int save_i387_xstate(void __user *buf) if (task_thread_info(tsk)->status & TS_XSAVE) { struct _fpstate __user *fx = buf; + struct _xstate __user *x = buf; + u64 xstate_bv; err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, sizeof(struct _fpx_sw_bytes)); @@ -121,6 +123,29 @@ int save_i387_xstate(void __user *buf) err |= __put_user(FP_XSTATE_MAGIC2, (__u32 __user *) (buf + sig_xstate_size - FP_XSTATE_MAGIC2_SIZE)); + + /* + * Read the xstate_bv which we copied (directly from the cpu or + * from the state in task struct) to the user buffers and + * set the FP/SSE bits. + */ + err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv); + + /* + * For legacy compatible, we always set FP/SSE bits in the bit + * vector while saving the state to the user context. This will + * enable us capturing any changes(during sigreturn) to + * the FP/SSE bits by the legacy applications which don't touch + * xstate_bv in the xsave header. + * + * xsave aware apps can change the xstate_bv in the xsave + * header as well as change any contents in the memory layout. + * xrestore as part of sigreturn will capture all the changes. + */ + xstate_bv |= XSTATE_FPSSE; + + err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv); + if (err) return err; } -- cgit v1.2.3 From 6cf4a9243a7fea75e7fd6f2e1ba6fb01c805e056 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Tue, 7 Oct 2008 15:24:02 -0700 Subject: sparc32: sun4m interrupt mask cleanup Here is an updated version of a patch I wrote 6 years ago http://marc.info/?l=linux-sparc&m=103939103607617&w=2 that simplifies interrupt mask lookup. It's main purpose is to add VME bus support but it's really a cleanup of the mask code. Signed-off-by: Robert Reif Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4m_irq.c | 145 ++++++++++++++++++++++++++---------------- arch/sparc/kernel/traps.c | 17 ----- 2 files changed, 91 insertions(+), 71 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index ec66d4aab09..f10317179ee 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -71,8 +71,9 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ -#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ -#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ +#define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ +#define SUN4M_INT_ECC_ERR 0x10000000 /* ecc memory error */ +#define SUN4M_INT_VME_ERR 0x08000000 /* vme async error */ #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ @@ -83,10 +84,22 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ +#define SUN4M_INT_VMEBITS 0x0000007F /* vme int bits */ + +#define SUN4M_INT_ERROR (SUN4M_INT_MODULE_ERR | \ + SUN4M_INT_M2S_WRITE_ERR | \ + SUN4M_INT_ECC_ERR | \ + SUN4M_INT_VME_ERR) #define SUN4M_INT_SBUS(x) (1 << (x+7)) #define SUN4M_INT_VME(x) (1 << (x)) +/* Interrupt levels used by OBP */ +#define OBP_INT_LEVEL_SOFT 0x10 +#define OBP_INT_LEVEL_ONBOARD 0x20 +#define OBP_INT_LEVEL_SBUS 0x30 +#define OBP_INT_LEVEL_VME 0x40 + /* Interrupt level assignment on sun4m: * * level source @@ -140,59 +153,57 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; * power: 0x22 onboard power device (XXX unknown mask bit XXX) */ -/* These tables only apply for interrupts greater than 15.. - * - * any intr value below 0x10 is considered to be a soft-int - * this may be useful or it may not.. but that's how I've done it. - * and it won't clash with what OBP is telling us about devices. - * - * take an encoded intr value and lookup if it's valid - * then get the mask bits that match from irq_mask - * - * P3: Translation from irq 0x0d to mask 0x2000 is for MrCoffee. - */ -static unsigned char irq_xlate[32] = { - /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f */ - 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 5, 6, 14, 0, 7, - 0, 0, 8, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 0 -}; - -static unsigned long irq_mask[] = { - 0, /* illegal index */ - SUN4M_INT_SCSI, /* 1 irq 4 */ - SUN4M_INT_ETHERNET, /* 2 irq 6 */ - SUN4M_INT_VIDEO, /* 3 irq 8 */ - SUN4M_INT_REALTIME, /* 4 irq 10 */ - SUN4M_INT_FLOPPY, /* 5 irq 11 */ - (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), /* 6 irq 12 */ - SUN4M_INT_MODULE_ERR, /* 7 irq 15 */ - SUN4M_INT_SBUS(0), /* 8 irq 2 */ - SUN4M_INT_SBUS(1), /* 9 irq 3 */ - SUN4M_INT_SBUS(2), /* 10 irq 5 */ - SUN4M_INT_SBUS(3), /* 11 irq 7 */ - SUN4M_INT_SBUS(4), /* 12 irq 9 */ - SUN4M_INT_SBUS(5), /* 13 irq 11 */ - SUN4M_INT_SBUS(6) /* 14 irq 13 */ +static unsigned long irq_mask[0x50] = { + /* SMP */ + 0, SUN4M_SOFT_INT(1), + SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), + SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), + SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7), + SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9), + SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), + SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), + SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), + /* soft */ + 0, SUN4M_SOFT_INT(1), + SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), + SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), + SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7), + SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9), + SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), + SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), + SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), + /* onboard */ + 0, 0, 0, 0, + SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0, + SUN4M_INT_VIDEO, SUN4M_INT_MODULE, + SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, + (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), + SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, + /* sbus */ + 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), + 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), + 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5), + 0, SUN4M_INT_SBUS(6), 0, 0, + /* vme */ + 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1), + 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3), + 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5), + 0, SUN4M_INT_VME(6), 0, 0 }; static unsigned long sun4m_get_irqmask(unsigned int irq) { unsigned long mask; - if (irq > 0x20) { - /* OBIO/SBUS interrupts */ - irq &= 0x1f; - mask = irq_mask[irq_xlate[irq]]; - if (!mask) - printk("sun4m_get_irqmask: IRQ%d has no valid mask!\n",irq); - } else { - /* Soft Interrupts will come here. - * Currently there is no way to trigger them but I'm sure - * something could be cooked up. - */ - irq &= 0xf; - mask = SUN4M_SOFT_INT(irq); - } + if (irq < 0x50) + mask = irq_mask[irq]; + else + mask = 0; + + if (!mask) + printk(KERN_ERR "sun4m_get_irqmask: IRQ%d has no valid mask!\n", + irq); + return mask; } @@ -247,10 +258,10 @@ static unsigned long cpu_pil_to_imask[16] = { /*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR, /*10*/ SUN4M_INT_REALTIME, /*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY, -/*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, -/*13*/ SUN4M_INT_AUDIO, +/*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, +/*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, /*14*/ SUN4M_INT_E14, -/*15*/ 0x00000000 +/*15*/ SUN4M_INT_ERROR }; /* We assume the caller has disabled local interrupts when these are called, @@ -304,8 +315,7 @@ struct sun4m_timer_global { static struct sun4m_timer_global __iomem *timers_global; -#define OBIO_INTR 0x20 -#define TIMER_IRQ (OBIO_INTR | 10) +#define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); @@ -314,6 +324,33 @@ static void sun4m_clear_clock_irq(void) sbus_readl(&timers_global->l10_limit); } +void sun4m_nmi(struct pt_regs *regs) +{ + unsigned long afsr, afar, si; + + printk(KERN_ERR "Aieee: sun4m NMI received!\n"); + /* XXX HyperSparc hack XXX */ + __asm__ __volatile__("mov 0x500, %%g1\n\t" + "lda [%%g1] 0x4, %0\n\t" + "mov 0x600, %%g1\n\t" + "lda [%%g1] 0x4, %1\n\t" : + "=r" (afsr), "=r" (afar)); + printk(KERN_ERR "afsr=%08lx afar=%08lx\n", afsr, afar); + si = sbus_readl(&sun4m_irq_global->pending); + printk(KERN_ERR "si=%08lx\n", si); + if (si & SUN4M_INT_MODULE_ERR) + printk(KERN_ERR "Module async error\n"); + if (si & SUN4M_INT_M2S_WRITE_ERR) + printk(KERN_ERR "MBus/SBus async error\n"); + if (si & SUN4M_INT_ECC_ERR) + printk(KERN_ERR "ECC memory error\n"); + if (si & SUN4M_INT_VME_ERR) + printk(KERN_ERR "VME async error\n"); + printk(KERN_ERR "you lose buddy boy...\n"); + show_regs(regs); + prom_halt(); +} + /* Exported for sun4m_smp.c */ void sun4m_clear_profile_irq(int cpu) { diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index 5d45d5fd8c9..2b7d5065903 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c @@ -43,23 +43,6 @@ void syscall_trace_exit(struct pt_regs *regs) { } -void sun4m_nmi(struct pt_regs *regs) -{ - unsigned long afsr, afar; - - printk("Aieee: sun4m NMI received!\n"); - /* XXX HyperSparc hack XXX */ - __asm__ __volatile__("mov 0x500, %%g1\n\t" - "lda [%%g1] 0x4, %0\n\t" - "mov 0x600, %%g1\n\t" - "lda [%%g1] 0x4, %1\n\t" : - "=r" (afsr), "=r" (afar)); - printk("afsr=%08lx afar=%08lx\n", afsr, afar); - printk("you lose buddy boy...\n"); - show_regs(regs); - prom_halt(); -} - void sun4d_nmi(struct pt_regs *regs) { printk("Aieee: sun4d NMI received!\n"); -- cgit v1.2.3 From a5ac0129249611fc4a35e6d7cd9b8462d67e5798 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 13 Oct 2008 14:07:19 +0800 Subject: Blackfin arch: add supporting for kgdb Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig.debug | 3 + arch/blackfin/include/asm/kgdb.h | 21 +- arch/blackfin/kernel/kgdb.c | 711 ++++++++++++++++++------ arch/blackfin/kernel/traps.c | 35 +- arch/blackfin/mach-bf561/include/mach/mem_map.h | 18 +- arch/blackfin/mach-common/entry.S | 9 +- arch/blackfin/mach-common/ints-priority.c | 4 - 7 files changed, 606 insertions(+), 195 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index 0afa8981872..2cb0a3080d7 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -2,6 +2,9 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config HAVE_ARCH_KGDB + def_bool y + config DEBUG_MMRS bool "Generate Blackfin MMR tree" select DEBUG_FS diff --git a/arch/blackfin/include/asm/kgdb.h b/arch/blackfin/include/asm/kgdb.h index 0f73847fd6b..26ebac6646d 100644 --- a/arch/blackfin/include/asm/kgdb.h +++ b/arch/blackfin/include/asm/kgdb.h @@ -124,9 +124,16 @@ enum regnames { /* Number of bytes of registers. */ #define NUMREGBYTES BFIN_NUM_REGS*4 -#define BREAKPOINT() asm(" EXCPT 2;"); -#define BREAK_INSTR_SIZE 2 -#define HW_BREAKPOINT_NUM 6 +static inline void arch_kgdb_breakpoint(void) +{ + asm(" EXCPT 2;"); +} +#define BREAK_INSTR_SIZE 2 +#define CACHE_FLUSH_IS_SAFE 1 +#define HW_INST_WATCHPOINT_NUM 6 +#define HW_WATCHPOINT_NUM 8 +#define TYPE_INST_WATCHPOINT 0 +#define TYPE_DATA_WATCHPOINT 1 /* Instruction watchpoint address control register bits mask */ #define WPPWR 0x1 @@ -163,10 +170,11 @@ enum regnames { #define WPDAEN1 0x8 #define WPDCNTEN0 0x10 #define WPDCNTEN1 0x20 + #define WPDSRC0 0xc0 -#define WPDACC0 0x300 +#define WPDACC0_OFFSET 8 #define WPDSRC1 0xc00 -#define WPDACC1 0x3000 +#define WPDACC1_OFFSET 12 /* Watchpoint status register bits mask */ #define STATIA0 0x1 @@ -178,7 +186,4 @@ enum regnames { #define STATDA0 0x40 #define STATDA1 0x80 -extern void kgdb_print(const char *fmt, ...); -extern void init_kgdb_uart(void); - #endif diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index a1f9641a642..b795a207742 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -1,32 +1,9 @@ /* - * File: arch/blackfin/kernel/kgdb.c - * Based on: - * Author: Sonic Zhang + * arch/blackfin/kernel/kgdb.c - Blackfin kgdb pieces * - * Created: - * Description: + * Copyright 2005-2008 Analog Devices Inc. * - * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $ - * - * Modified: - * Copyright 2005-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Licensed under the GPL-2 or later. */ #include @@ -39,24 +16,29 @@ #include #include #include -#include #include #include +#include #include #include #include +#include /* Put the error code here just in case the user cares. */ -int gdb_bf533errcode; +int gdb_bfin_errcode; /* Likewise, the vector number here (since GDB only gets the signal number through the usual means, and that's not very specific). */ -int gdb_bf533vector = -1; +int gdb_bfin_vector = -1; #if KGDB_MAX_NO_CPUS != 8 #error change the definition of slavecpulocks #endif -void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) +#ifdef CONFIG_BFIN_WDT +# error "Please unselect blackfin watchdog driver before build KGDB." +#endif + +void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) { gdb_regs[BFIN_R0] = regs->r0; gdb_regs[BFIN_R1] = regs->r1; @@ -133,7 +115,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat; } -void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) +void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) { regs->r0 = gdb_regs[BFIN_R0]; regs->r1 = gdb_regs[BFIN_R1]; @@ -199,171 +181,208 @@ struct hw_breakpoint { unsigned int dataacc:2; unsigned short count; unsigned int addr; -} breakinfo[HW_BREAKPOINT_NUM]; +} breakinfo[HW_WATCHPOINT_NUM]; -int kgdb_arch_init(void) -{ - debugger_step = 0; - - kgdb_remove_all_hw_break(); - return 0; -} - -int kgdb_set_hw_break(unsigned long addr) +int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type) { int breakno; - for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) - if (!breakinfo[breakno].occupied) { + int bfin_type; + int dataacc = 0; + + switch (type) { + case BP_HARDWARE_BREAKPOINT: + bfin_type = TYPE_INST_WATCHPOINT; + break; + case BP_WRITE_WATCHPOINT: + dataacc = 1; + bfin_type = TYPE_DATA_WATCHPOINT; + break; + case BP_READ_WATCHPOINT: + dataacc = 2; + bfin_type = TYPE_DATA_WATCHPOINT; + break; + case BP_ACCESS_WATCHPOINT: + dataacc = 3; + bfin_type = TYPE_DATA_WATCHPOINT; + break; + default: + return -ENOSPC; + } + + /* Becasue hardware data watchpoint impelemented in current + * Blackfin can not trigger an exception event as the hardware + * instrction watchpoint does, we ignaore all data watch point here. + * They can be turned on easily after future blackfin design + * supports this feature. + */ + for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++) + if (bfin_type == breakinfo[breakno].type + && !breakinfo[breakno].occupied) { breakinfo[breakno].occupied = 1; breakinfo[breakno].enabled = 1; - breakinfo[breakno].type = 1; breakinfo[breakno].addr = addr; + breakinfo[breakno].dataacc = dataacc; + breakinfo[breakno].count = 0; return 0; } return -ENOSPC; } -int kgdb_remove_hw_break(unsigned long addr) +int bfin_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype type) { int breakno; - for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) - if (breakinfo[breakno].addr == addr) - memset(&(breakinfo[breakno]), 0, sizeof(struct hw_breakpoint)); + int bfin_type; + + switch (type) { + case BP_HARDWARE_BREAKPOINT: + bfin_type = TYPE_INST_WATCHPOINT; + break; + case BP_WRITE_WATCHPOINT: + case BP_READ_WATCHPOINT: + case BP_ACCESS_WATCHPOINT: + bfin_type = TYPE_DATA_WATCHPOINT; + break; + default: + return 0; + } + for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) + if (bfin_type == breakinfo[breakno].type + && breakinfo[breakno].occupied + && breakinfo[breakno].addr == addr) { + breakinfo[breakno].occupied = 0; + breakinfo[breakno].enabled = 0; + } return 0; } -void kgdb_remove_all_hw_break(void) +void bfin_remove_all_hw_break(void) { - memset(breakinfo, 0, sizeof(struct hw_breakpoint)*8); -} + int breakno; -/* -void kgdb_show_info(void) -{ - printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n", - bfin_read_WPIA0(), bfin_read_WPIACNT0(), - bfin_read_WPIACTL(), bfin_read_WPSTAT()); + memset(breakinfo, 0, sizeof(struct hw_breakpoint)*HW_WATCHPOINT_NUM); + + for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++) + breakinfo[breakno].type = TYPE_INST_WATCHPOINT; + for (; breakno < HW_WATCHPOINT_NUM; breakno++) + breakinfo[breakno].type = TYPE_DATA_WATCHPOINT; } -*/ -void kgdb_correct_hw_break(void) +void bfin_correct_hw_break(void) { int breakno; - int correctit; - uint32_t wpdactl = bfin_read_WPDACTL(); + unsigned int wpiactl = 0; + unsigned int wpdactl = 0; + int enable_wp = 0; + + for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) + if (breakinfo[breakno].enabled) { + enable_wp = 1; - correctit = 0; - for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) { - if (breakinfo[breakno].type == 1) { switch (breakno) { case 0: - if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) { - correctit = 1; - wpdactl &= ~(WPIREN01|EMUSW0); - wpdactl |= WPIAEN0|WPICNTEN0; - bfin_write_WPIA0(breakinfo[breakno].addr); - bfin_write_WPIACNT0(breakinfo[breakno].skip); - } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) { - correctit = 1; - wpdactl &= ~WPIAEN0; - } + wpiactl |= WPIAEN0|WPICNTEN0; + bfin_write_WPIA0(breakinfo[breakno].addr); + bfin_write_WPIACNT0(breakinfo[breakno].count + + breakinfo->skip); break; - case 1: - if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) { - correctit = 1; - wpdactl &= ~(WPIREN01|EMUSW1); - wpdactl |= WPIAEN1|WPICNTEN1; - bfin_write_WPIA1(breakinfo[breakno].addr); - bfin_write_WPIACNT1(breakinfo[breakno].skip); - } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) { - correctit = 1; - wpdactl &= ~WPIAEN1; - } + wpiactl |= WPIAEN1|WPICNTEN1; + bfin_write_WPIA1(breakinfo[breakno].addr); + bfin_write_WPIACNT1(breakinfo[breakno].count + + breakinfo->skip); break; - case 2: - if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) { - correctit = 1; - wpdactl &= ~(WPIREN23|EMUSW2); - wpdactl |= WPIAEN2|WPICNTEN2; - bfin_write_WPIA2(breakinfo[breakno].addr); - bfin_write_WPIACNT2(breakinfo[breakno].skip); - } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) { - correctit = 1; - wpdactl &= ~WPIAEN2; - } + wpiactl |= WPIAEN2|WPICNTEN2; + bfin_write_WPIA2(breakinfo[breakno].addr); + bfin_write_WPIACNT2(breakinfo[breakno].count + + breakinfo->skip); break; - case 3: - if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) { - correctit = 1; - wpdactl &= ~(WPIREN23|EMUSW3); - wpdactl |= WPIAEN3|WPICNTEN3; - bfin_write_WPIA3(breakinfo[breakno].addr); - bfin_write_WPIACNT3(breakinfo[breakno].skip); - } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) { - correctit = 1; - wpdactl &= ~WPIAEN3; - } + wpiactl |= WPIAEN3|WPICNTEN3; + bfin_write_WPIA3(breakinfo[breakno].addr); + bfin_write_WPIACNT3(breakinfo[breakno].count + + breakinfo->skip); break; case 4: - if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) { - correctit = 1; - wpdactl &= ~(WPIREN45|EMUSW4); - wpdactl |= WPIAEN4|WPICNTEN4; - bfin_write_WPIA4(breakinfo[breakno].addr); - bfin_write_WPIACNT4(breakinfo[breakno].skip); - } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) { - correctit = 1; - wpdactl &= ~WPIAEN4; - } + wpiactl |= WPIAEN4|WPICNTEN4; + bfin_write_WPIA4(breakinfo[breakno].addr); + bfin_write_WPIACNT4(breakinfo[breakno].count + + breakinfo->skip); break; case 5: - if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) { - correctit = 1; - wpdactl &= ~(WPIREN45|EMUSW5); - wpdactl |= WPIAEN5|WPICNTEN5; - bfin_write_WPIA5(breakinfo[breakno].addr); - bfin_write_WPIACNT5(breakinfo[breakno].skip); - } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) { - correctit = 1; - wpdactl &= ~WPIAEN5; - } + wpiactl |= WPIAEN5|WPICNTEN5; + bfin_write_WPIA5(breakinfo[breakno].addr); + bfin_write_WPIACNT5(breakinfo[breakno].count + + breakinfo->skip); + break; + case 6: + wpdactl |= WPDAEN0|WPDCNTEN0|WPDSRC0; + wpdactl |= breakinfo[breakno].dataacc + << WPDACC0_OFFSET; + bfin_write_WPDA0(breakinfo[breakno].addr); + bfin_write_WPDACNT0(breakinfo[breakno].count + + breakinfo->skip); + break; + case 7: + wpdactl |= WPDAEN1|WPDCNTEN1|WPDSRC1; + wpdactl |= breakinfo[breakno].dataacc + << WPDACC1_OFFSET; + bfin_write_WPDA1(breakinfo[breakno].addr); + bfin_write_WPDACNT1(breakinfo[breakno].count + + breakinfo->skip); break; } } - } - if (correctit) { - wpdactl &= ~WPAND; - wpdactl |= WPPWR; - /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/ + + /* Should enable WPPWR bit first before set any other + * WPIACTL and WPDACTL bits */ + if (enable_wp) { + bfin_write_WPIACTL(WPPWR); + CSYNC(); + bfin_write_WPIACTL(wpiactl|WPPWR); bfin_write_WPDACTL(wpdactl); CSYNC(); - /*kgdb_show_info();*/ } } void kgdb_disable_hw_debug(struct pt_regs *regs) { /* Disable hardware debugging while we are in kgdb */ - bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1); + bfin_write_WPIACTL(0); + bfin_write_WPDACTL(0); CSYNC(); } -void kgdb_post_master_code(struct pt_regs *regs, int eVector, int err_code) +#ifdef CONFIG_SMP +void kgdb_passive_cpu_callback(void *info) +{ + kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); +} + +void kgdb_roundup_cpus(unsigned long flags) +{ + smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0); +} + +void kgdb_roundup_cpu(int cpu, unsigned long flags) +{ + smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0); +} +#endif + +void kgdb_post_primary_code(struct pt_regs *regs, int eVector, int err_code) { /* Master processor is completely in the debugger */ - gdb_bf533vector = eVector; - gdb_bf533errcode = err_code; + gdb_bfin_vector = eVector; + gdb_bfin_errcode = err_code; } -int kgdb_arch_handle_exception(int exceptionVector, int signo, +int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, - struct pt_regs *linux_regs) + struct pt_regs *regs) { long addr; long breakno; @@ -385,44 +404,40 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo, /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) { - linux_regs->retx = addr; + regs->retx = addr; } - newPC = linux_regs->retx; + newPC = regs->retx; /* clear the trace bit */ - linux_regs->syscfg &= 0xfffffffe; + regs->syscfg &= 0xfffffffe; /* set the trace bit if we're stepping */ if (remcom_in_buffer[0] == 's') { - linux_regs->syscfg |= 0x1; - debugger_step = linux_regs->ipend; - debugger_step >>= 6; - for (i = 10; i > 0; i--, debugger_step >>= 1) - if (debugger_step & 1) + regs->syscfg |= 0x1; + kgdb_single_step = regs->ipend; + kgdb_single_step >>= 6; + for (i = 10; i > 0; i--, kgdb_single_step >>= 1) + if (kgdb_single_step & 1) break; /* i indicate event priority of current stopped instruction * user space instruction is 0, IVG15 is 1, IVTMR is 10. - * debugger_step > 0 means in single step mode + * kgdb_single_step > 0 means in single step mode */ - debugger_step = i + 1; - } else { - debugger_step = 0; + kgdb_single_step = i + 1; } - wp_status = bfin_read_WPSTAT(); - CSYNC(); - - if (exceptionVector == VEC_WATCH) { - for (breakno = 0; breakno < 6; ++breakno) { + if (vector == VEC_WATCH) { + wp_status = bfin_read_WPSTAT(); + for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) { if (wp_status & (1 << breakno)) { breakinfo->skip = 1; break; } } + bfin_write_WPSTAT(0); } - kgdb_correct_hw_break(); - bfin_write_WPSTAT(0); + bfin_correct_hw_break(); return 0; } /* switch */ @@ -431,5 +446,385 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo, struct kgdb_arch arch_kgdb_ops = { .gdb_bpt_instr = {0xa1}, +#ifdef CONFIG_SMP + .flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP, +#else .flags = KGDB_HW_BREAKPOINT, +#endif + .set_hw_breakpoint = bfin_set_hw_break, + .remove_hw_breakpoint = bfin_remove_hw_break, + .remove_all_hw_break = bfin_remove_all_hw_break, + .correct_hw_break = bfin_correct_hw_break, }; + +static int hex(char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return ch - 'a' + 10; + if ((ch >= '0') && (ch <= '9')) + return ch - '0'; + if ((ch >= 'A') && (ch <= 'F')) + return ch - 'A' + 10; + return -1; +} + +static int validate_memory_access_address(unsigned long addr, int size) +{ + int cpu = raw_smp_processor_id(); + + if (size < 0) + return EFAULT; + if (addr >= 0x1000 && (addr + size) <= physical_mem_end) + return 0; + if (addr >= SYSMMR_BASE) + return 0; + if (addr >= ASYNC_BANK0_BASE + && addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) + return 0; + if (cpu == 0) { + if (addr >= L1_SCRATCH_START + && (addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH)) + return 0; +#if L1_CODE_LENGTH != 0 + if (addr >= L1_CODE_START + && (addr + size <= L1_CODE_START + L1_CODE_LENGTH)) + return 0; +#endif +#if L1_DATA_A_LENGTH != 0 + if (addr >= L1_DATA_A_START + && (addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH)) + return 0; +#endif +#if L1_DATA_B_LENGTH != 0 + if (addr >= L1_DATA_B_START + && (addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)) + return 0; +#endif +#ifdef CONFIG_SMP + } else if (cpu == 1) { + if (addr >= COREB_L1_SCRATCH_START + && (addr + size <= COREB_L1_SCRATCH_START + + L1_SCRATCH_LENGTH)) + return 0; +# if L1_CODE_LENGTH != 0 + if (addr >= COREB_L1_CODE_START + && (addr + size <= COREB_L1_CODE_START + L1_CODE_LENGTH)) + return 0; +# endif +# if L1_DATA_A_LENGTH != 0 + if (addr >= COREB_L1_DATA_A_START + && (addr + size <= COREB_L1_DATA_A_START + L1_DATA_A_LENGTH)) + return 0; +# endif +# if L1_DATA_B_LENGTH != 0 + if (addr >= COREB_L1_DATA_B_START + && (addr + size <= COREB_L1_DATA_B_START + L1_DATA_B_LENGTH)) + return 0; +# endif +#endif + } + +#if L2_LENGTH != 0 + if (addr >= L2_START + && addr + size <= L2_START + L2_LENGTH) + return 0; +#endif + + return EFAULT; +} + +/* + * Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null). May return an error. + */ +int kgdb_mem2hex(char *mem, char *buf, int count) +{ + char *tmp; + int err = 0; + unsigned char *pch; + unsigned short mmr16; + unsigned long mmr32; + int cpu = raw_smp_processor_id(); + + if (validate_memory_access_address((unsigned long)mem, count)) + return EFAULT; + + /* + * We use the upper half of buf as an intermediate buffer for the + * raw memory copy. Hex conversion will work against this one. + */ + tmp = buf + count; + + if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ + switch (count) { + case 2: + if ((unsigned int)mem % 2 == 0) { + mmr16 = *(unsigned short *)mem; + pch = (unsigned char *)&mmr16; + *tmp++ = *pch++; + *tmp++ = *pch++; + tmp -= 2; + } else + err = EFAULT; + break; + case 4: + if ((unsigned int)mem % 4 == 0) { + mmr32 = *(unsigned long *)mem; + pch = (unsigned char *)&mmr32; + *tmp++ = *pch++; + *tmp++ = *pch++; + *tmp++ = *pch++; + *tmp++ = *pch++; + tmp -= 4; + } else + err = EFAULT; + break; + default: + err = EFAULT; + } + } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START && + (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH +#ifdef CONFIG_SMP + || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START && + (unsigned int)(mem + count) <= + COREB_L1_CODE_START + L1_CODE_LENGTH +#endif + ) { + /* access L1 instruction SRAM*/ + if (dma_memcpy(tmp, mem, count) == NULL) + err = EFAULT; + } else + err = probe_kernel_read(tmp, mem, count); + + if (!err) { + while (count > 0) { + buf = pack_hex_byte(buf, *tmp); + tmp++; + count--; + } + + *buf = 0; + } + + return err; +} + +/* + * Copy the binary array pointed to by buf into mem. Fix $, #, and + * 0x7d escaped with 0x7d. Return a pointer to the character after + * the last byte written. + */ +int kgdb_ebin2mem(char *buf, char *mem, int count) +{ + char *tmp_old; + char *tmp_new; + unsigned short *mmr16; + unsigned long *mmr32; + int err = 0; + int size = 0; + int cpu = raw_smp_processor_id(); + + tmp_old = tmp_new = buf; + + while (count-- > 0) { + if (*tmp_old == 0x7d) + *tmp_new = *(++tmp_old) ^ 0x20; + else + *tmp_new = *tmp_old; + tmp_new++; + tmp_old++; + size++; + } + + if (validate_memory_access_address((unsigned long)mem, size)) + return EFAULT; + + if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ + switch (size) { + case 2: + if ((unsigned int)mem % 2 == 0) { + mmr16 = (unsigned short *)buf; + *(unsigned short *)mem = *mmr16; + } else + return EFAULT; + break; + case 4: + if ((unsigned int)mem % 4 == 0) { + mmr32 = (unsigned long *)buf; + *(unsigned long *)mem = *mmr32; + } else + return EFAULT; + break; + default: + return EFAULT; + } + } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START && + (unsigned int)(mem + count) < L1_CODE_START + L1_CODE_LENGTH +#ifdef CONFIG_SMP + || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START && + (unsigned int)(mem + count) <= + COREB_L1_CODE_START + L1_CODE_LENGTH +#endif + ) { + /* access L1 instruction SRAM */ + if (dma_memcpy(mem, buf, size) == NULL) + err = EFAULT; + } else + err = probe_kernel_write(mem, buf, size); + + return err; +} + +/* + * Convert the hex array pointed to by buf into binary to be placed in mem. + * Return a pointer to the character AFTER the last byte written. + * May return an error. + */ +int kgdb_hex2mem(char *buf, char *mem, int count) +{ + char *tmp_raw; + char *tmp_hex; + unsigned short *mmr16; + unsigned long *mmr32; + int cpu = raw_smp_processor_id(); + + if (validate_memory_access_address((unsigned long)mem, count)) + return EFAULT; + + /* + * We use the upper half of buf as an intermediate buffer for the + * raw memory that is converted from hex. + */ + tmp_raw = buf + count * 2; + + tmp_hex = tmp_raw - 1; + while (tmp_hex >= buf) { + tmp_raw--; + *tmp_raw = hex(*tmp_hex--); + *tmp_raw |= hex(*tmp_hex--) << 4; + } + + if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ + switch (count) { + case 2: + if ((unsigned int)mem % 2 == 0) { + mmr16 = (unsigned short *)tmp_raw; + *(unsigned short *)mem = *mmr16; + } else + return EFAULT; + break; + case 4: + if ((unsigned int)mem % 4 == 0) { + mmr32 = (unsigned long *)tmp_raw; + *(unsigned long *)mem = *mmr32; + } else + return EFAULT; + break; + default: + return EFAULT; + } + } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START && + (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH +#ifdef CONFIG_SMP + || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START && + (unsigned int)(mem + count) <= + COREB_L1_CODE_START + L1_CODE_LENGTH +#endif + ) { + /* access L1 instruction SRAM */ + if (dma_memcpy(mem, tmp_raw, count) == NULL) + return EFAULT; + } else + return probe_kernel_write(mem, tmp_raw, count); + return 0; +} + +int kgdb_validate_break_address(unsigned long addr) +{ + int cpu = raw_smp_processor_id(); + + if (addr >= 0x1000 && (addr + BREAK_INSTR_SIZE) <= physical_mem_end) + return 0; + if (addr >= ASYNC_BANK0_BASE + && addr + BREAK_INSTR_SIZE <= ASYNC_BANK3_BASE + ASYNC_BANK3_BASE) + return 0; +#if L1_CODE_LENGTH != 0 + if (cpu == 0 && addr >= L1_CODE_START + && addr + BREAK_INSTR_SIZE <= L1_CODE_START + L1_CODE_LENGTH) + return 0; +# ifdef CONFIG_SMP + else if (cpu == 1 && addr >= COREB_L1_CODE_START + && addr + BREAK_INSTR_SIZE <= COREB_L1_CODE_START + L1_CODE_LENGTH) + return 0; +# endif +#endif +#if L2_LENGTH != 0 + if (addr >= L2_START + && addr + BREAK_INSTR_SIZE <= L2_START + L2_LENGTH) + return 0; +#endif + + return EFAULT; +} + +int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) +{ + int err; + int cpu = raw_smp_processor_id(); + + if ((cpu == 0 && (unsigned int)addr >= L1_CODE_START + && (unsigned int)(addr + BREAK_INSTR_SIZE) + < L1_CODE_START + L1_CODE_LENGTH) +#ifdef CONFIG_SMP + || (cpu == 1 && (unsigned int)addr >= COREB_L1_CODE_START + && (unsigned int)(addr + BREAK_INSTR_SIZE) + < COREB_L1_CODE_START + L1_CODE_LENGTH) +#endif + ) { + /* access L1 instruction SRAM */ + if (dma_memcpy(saved_instr, (void *)addr, BREAK_INSTR_SIZE) + == NULL) + return -EFAULT; + + if (dma_memcpy((void *)addr, arch_kgdb_ops.gdb_bpt_instr, + BREAK_INSTR_SIZE) == NULL) + return -EFAULT; + + return 0; + } else { + err = probe_kernel_read(saved_instr, (char *)addr, + BREAK_INSTR_SIZE); + if (err) + return err; + + return probe_kernel_write((char *)addr, + arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); + } +} + +int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) +{ + if ((unsigned int)addr >= L1_CODE_START && + (unsigned int)(addr + BREAK_INSTR_SIZE) < + L1_CODE_START + L1_CODE_LENGTH) { + /* access L1 instruction SRAM */ + if (dma_memcpy((void *)addr, bundle, BREAK_INSTR_SIZE) == NULL) + return -EFAULT; + + return 0; + } else + return probe_kernel_write((char *)addr, + (char *)bundle, BREAK_INSTR_SIZE); +} + +int kgdb_arch_init(void) +{ + kgdb_single_step = 0; + + bfin_remove_all_hw_break(); + return 0; +} + +void kgdb_arch_exit(void) +{ +} diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index bd41fca315d..8d561baef89 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -43,12 +43,11 @@ #include #ifdef CONFIG_KGDB -# include # include # define CHK_DEBUGGER_TRAP() \ do { \ - CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \ + kgdb_handle_exception(trapnr, sig, info.si_code, fp); \ } while (0) # define CHK_DEBUGGER_TRAP_MAYBE() \ do { \ @@ -300,7 +299,7 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = SEGV_STACKFLOW; sig = SIGSEGV; printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x04 - User Defined, Caught by default */ /* 0x05 - User Defined, Caught by default */ @@ -329,7 +328,7 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = TRAP_TRACEFLOW; sig = SIGTRAP; printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x12 - Reserved, Caught by default */ /* 0x13 - Reserved, Caught by default */ @@ -351,35 +350,35 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = ILL_ILLOPC; sig = SIGILL; printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x22 - Illegal Instruction Combination, handled here */ case VEC_ILGAL_I: info.si_code = ILL_ILLPARAOP; sig = SIGILL; printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x23 - Data CPLB protection violation, handled here */ case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x24 - Data access misaligned, handled here */ case VEC_MISALI_D: info.si_code = BUS_ADRALN; sig = SIGBUS; printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x25 - Unrecoverable Event, handled here */ case VEC_UNCOV: info.si_code = ILL_ILLEXCPT; sig = SIGILL; printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, error case is handled here */ @@ -387,7 +386,6 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = BUS_ADRALN; sig = SIGBUS; printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); break; /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ case VEC_CPLB_MHIT: @@ -399,7 +397,7 @@ asmlinkage void trap_c(struct pt_regs *fp) else #endif printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x28 - Emulation Watchpoint, handled here */ case VEC_WATCH: @@ -418,7 +416,7 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = BUS_OPFETCH; sig = SIGBUS; printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; #else /* 0x29 - Reserved, Caught by default */ @@ -428,21 +426,20 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = BUS_ADRALN; sig = SIGBUS; printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2B - Instruction CPLB protection violation, handled here */ case VEC_CPLB_I_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ case VEC_CPLB_I_M: info.si_code = ILL_CPLB_MISS; sig = SIGBUS; printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); break; /* 0x2D - Instruction CPLB Multiple Hits, handled here */ case VEC_CPLB_I_MHIT: @@ -454,14 +451,14 @@ asmlinkage void trap_c(struct pt_regs *fp) else #endif printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2E - Illegal use of Supervisor Resource, handled here */ case VEC_ILL_RES: info.si_code = ILL_PRVOPC; sig = SIGILL; printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2F - Reserved, Caught by default */ /* 0x30 - Reserved, Caught by default */ @@ -508,14 +505,14 @@ asmlinkage void trap_c(struct pt_regs *fp) printk(KERN_NOTICE HWC_default(KERN_NOTICE)); break; } - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; default: info.si_code = TRAP_ILLTRAP; sig = SIGTRAP; printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", (fp->seqstat & SEQSTAT_EXCAUSE)); - CHK_DEBUGGER_TRAP(); + CHK_DEBUGGER_TRAP_MAYBE(); break; } diff --git a/arch/blackfin/mach-bf561/include/mach/mem_map.h b/arch/blackfin/mach-bf561/include/mach/mem_map.h index c26d8486cc4..9d6674ad1e5 100644 --- a/arch/blackfin/mach-bf561/include/mach/mem_map.h +++ b/arch/blackfin/mach-bf561/include/mach/mem_map.h @@ -35,9 +35,16 @@ /* Memory Map for ADSP-BF561 processors */ #ifdef CONFIG_BF561 -#define L1_CODE_START 0xFFA00000 -#define L1_DATA_A_START 0xFF800000 -#define L1_DATA_B_START 0xFF900000 +#define COREA_L1_CODE_START 0xFFA00000 +#define COREA_L1_DATA_A_START 0xFF800000 +#define COREA_L1_DATA_B_START 0xFF900000 +#define COREB_L1_CODE_START 0xFF600000 +#define COREB_L1_DATA_A_START 0xFF500000 +#define COREB_L1_DATA_B_START 0xFF400000 + +#define L1_CODE_START COREA_L1_CODE_START +#define L1_DATA_A_START COREA_L1_DATA_A_START +#define L1_DATA_B_START COREA_L1_DATA_B_START #define L1_CODE_LENGTH 0x4000 @@ -72,7 +79,10 @@ /* Scratch Pad Memory */ -#define L1_SCRATCH_START 0xFFB00000 +#define COREA_L1_SCRATCH_START 0xFFB00000 +#define COREB_L1_SCRATCH_START 0xFF700000 + +#define L1_SCRATCH_START COREA_L1_SCRATCH_START #define L1_SCRATCH_LENGTH 0x1000 #endif /* _MEM_MAP_533_H_ */ diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 90c7397036e..5a219b228de 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -190,8 +190,8 @@ ENTRY(_ex_single_step) if cc jump .Lfind_priority_done; jump.s .Lfind_priority_start; .Lfind_priority_done: - p4.l = _debugger_step; - p4.h = _debugger_step; + p4.l = _kgdb_single_step; + p4.h = _kgdb_single_step; r6 = [p4]; cc = r6 == 0; if cc jump .Ldo_single_step; @@ -1071,7 +1071,12 @@ ENTRY(_ex_table) */ .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ +#ifdef CONFIG_KGDB + .long _ex_trap_c /* 0x02 - User Defined - KGDB initial connection + and break signal trap */ +#else .long _ex_replaceable /* 0x02 - User Defined */ +#endif .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */ .long _ex_replaceable /* 0x05 - User Defined */ diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 5fa536727c6..ff4d5c2879a 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1136,8 +1136,4 @@ void do_irq(int vec, struct pt_regs *fp) vec = ivg->irqno; } asm_do_IRQ(vec, fp); - -#ifdef CONFIG_KGDB - kgdb_process_breakpoint(); -#endif } -- cgit v1.2.3 From aca5e4aac88a0ee84e9dc63e3d4189adbaef24ca Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 8 Oct 2008 14:27:59 +0800 Subject: Blackfin arch: add BF54x / BF52x Rotary Input device driver platform resource to board file Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf527/boards/ezkit.c | 36 ++++++++++++++++++++++ .../mach-bf527/include/mach/defBF52x_base.h | 27 ++++++++++++++++ arch/blackfin/mach-bf527/include/mach/portmux.h | 4 +++ arch/blackfin/mach-bf548/boards/ezkit.c | 35 +++++++++++++++++++++ 4 files changed, 102 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 04a8d6da905..8ee2b744e23 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -853,6 +853,38 @@ static struct platform_device bfin_device_gpiokeys = { }; #endif +#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE) +#include +#include + +static struct bfin_rotary_platform_data bfin_rotary_data = { + /*.rotary_up_key = KEY_UP,*/ + /*.rotary_down_key = KEY_DOWN,*/ + .rotary_rel_code = REL_WHEEL, + .rotary_button_key = KEY_ENTER, + .debounce = 10, /* 0..17 */ + .mode = ROT_QUAD_ENC | ROT_DEBE, +}; + +static struct resource bfin_rotary_resources[] = { + { + .start = IRQ_CNT, + .end = IRQ_CNT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_rotary_device = { + .name = "bfin-rotary", + .id = -1, + .num_resources = ARRAY_SIZE(bfin_rotary_resources), + .resource = bfin_rotary_resources, + .dev = { + .platform_data = &bfin_rotary_data, + }, +}; +#endif + static struct resource bfin_gpios_resources = { .start = 0, .end = MAX_BLACKFIN_GPIOS - 1, @@ -969,6 +1001,10 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_device_gpiokeys, #endif +#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE) + &bfin_rotary_device, +#endif + #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) &ezkit_flash_device, #endif diff --git a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h index 6ac2ed7026e..68b55d03fed 100644 --- a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h +++ b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h @@ -1840,6 +1840,33 @@ #define DPRESCALE 0xf /* Load Counter Register */ +/* CNT_COMMAND bit field options */ + +#define W1LCNT_ZERO 0x0001 /* write 1 to load CNT_COUNTER with zero */ +#define W1LCNT_MIN 0x0004 /* write 1 to load CNT_COUNTER from CNT_MIN */ +#define W1LCNT_MAX 0x0008 /* write 1 to load CNT_COUNTER from CNT_MAX */ + +#define W1LMIN_ZERO 0x0010 /* write 1 to load CNT_MIN with zero */ +#define W1LMIN_CNT 0x0020 /* write 1 to load CNT_MIN from CNT_COUNTER */ +#define W1LMIN_MAX 0x0080 /* write 1 to load CNT_MIN from CNT_MAX */ + +#define W1LMAX_ZERO 0x0100 /* write 1 to load CNT_MAX with zero */ +#define W1LMAX_CNT 0x0200 /* write 1 to load CNT_MAX from CNT_COUNTER */ +#define W1LMAX_MIN 0x0400 /* write 1 to load CNT_MAX from CNT_MIN */ + +/* CNT_CONFIG bit field options */ + +#define CNTMODE_QUADENC 0x0000 /* quadrature encoder mode */ +#define CNTMODE_BINENC 0x0100 /* binary encoder mode */ +#define CNTMODE_UDCNT 0x0200 /* up/down counter mode */ +#define CNTMODE_DIRCNT 0x0400 /* direction counter mode */ +#define CNTMODE_DIRTMR 0x0500 /* direction timer mode */ + +#define BNDMODE_COMP 0x0000 /* boundary compare mode */ +#define BNDMODE_ZERO 0x1000 /* boundary compare and zero mode */ +#define BNDMODE_CAPT 0x2000 /* boundary capture mode */ +#define BNDMODE_AEXT 0x3000 /* boundary auto-extend mode */ + /* Bit masks for OTP_CONTROL */ #define FUSE_FADDR 0x1ff /* OTP/Fuse Address */ diff --git a/arch/blackfin/mach-bf527/include/mach/portmux.h b/arch/blackfin/mach-bf527/include/mach/portmux.h index ae4d205bfcf..7f6da2c386b 100644 --- a/arch/blackfin/mach-bf527/include/mach/portmux.h +++ b/arch/blackfin/mach-bf527/include/mach/portmux.h @@ -67,6 +67,10 @@ #define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1)) #endif +#define P_CNT_CZM (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(3)) +#define P_CNT_CDG (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(3)) +#define P_CNT_CUD (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(3)) + #define P_HWAIT (P_DONTCARE) #define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0)) diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 397ddf6b810..7c08b9f1838 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -183,6 +183,37 @@ static struct platform_device bf54x_kpad_device = { }; #endif +#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE) +#include + +static struct bfin_rotary_platform_data bfin_rotary_data = { + /*.rotary_up_key = KEY_UP,*/ + /*.rotary_down_key = KEY_DOWN,*/ + .rotary_rel_code = REL_WHEEL, + .rotary_button_key = KEY_ENTER, + .debounce = 10, /* 0..17 */ + .mode = ROT_QUAD_ENC | ROT_DEBE, +}; + +static struct resource bfin_rotary_resources[] = { + { + .start = IRQ_CNT, + .end = IRQ_CNT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_rotary_device = { + .name = "bfin-rotary", + .id = -1, + .num_resources = ARRAY_SIZE(bfin_rotary_resources), + .resource = bfin_rotary_resources, + .dev = { + .platform_data = &bfin_rotary_data, + }, +}; +#endif + #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) static struct platform_device rtc_device = { .name = "rtc-bfin", @@ -817,6 +848,10 @@ static struct platform_device *ezkit_devices[] __initdata = { &bf54x_kpad_device, #endif +#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE) + &bfin_rotary_device, +#endif + #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) &i2c_bfin_twi0_device, #if !defined(CONFIG_BF542) -- cgit v1.2.3 From 5c64e0d5109532f8184be29c1dc163059e3ded4b Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 8 Oct 2008 14:43:47 +0800 Subject: Blackfin arch: Better error handling of unknown exceptions Better error handling of unknown exceptions, allows userspace to do a EXCPT n instruction for a not installed exception handler, and the kernel doesn't crash (like it use to before this). Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/traps.h | 5 ++++- arch/blackfin/kernel/traps.c | 43 ++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/traps.h b/arch/blackfin/include/asm/traps.h index f0e5f940d9c..34f7295fb07 100644 --- a/arch/blackfin/include/asm/traps.h +++ b/arch/blackfin/include/asm/traps.h @@ -59,6 +59,9 @@ level " or a 16-bit register is accessed with a 32-bit instruction.\n" #define HWC_x3(level) \ "External Memory Addressing Error\n" +#define EXC_0x04(level) \ + "Unimplmented exception occured\n" \ + level " - Maybe you forgot to install a custom exception handler?\n" #define HWC_x12(level) \ "Performance Monitor Overflow\n" #define HWC_x18(level) \ @@ -84,7 +87,7 @@ level " a particular processor implementation.\n" #define EXC_0x22(level) \ "Illegal instruction combination\n" \ - level " - See section for multi-issue rules in the ADSP-BF53x Blackfin\n" \ + level " - See section for multi-issue rules in the Blackfin\n" \ level " Processor Instruction Set Reference.\n" #define EXC_0x23(level) \ "Data access CPLB protection violation\n" \ diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 8d561baef89..be5ae7fabc5 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -301,18 +301,28 @@ asmlinkage void trap_c(struct pt_regs *fp) printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; - /* 0x04 - User Defined, Caught by default */ - /* 0x05 - User Defined, Caught by default */ - /* 0x06 - User Defined, Caught by default */ - /* 0x07 - User Defined, Caught by default */ - /* 0x08 - User Defined, Caught by default */ - /* 0x09 - User Defined, Caught by default */ - /* 0x0A - User Defined, Caught by default */ - /* 0x0B - User Defined, Caught by default */ - /* 0x0C - User Defined, Caught by default */ - /* 0x0D - User Defined, Caught by default */ - /* 0x0E - User Defined, Caught by default */ - /* 0x0F - User Defined, Caught by default */ + /* 0x04 - User Defined */ + /* 0x05 - User Defined */ + /* 0x06 - User Defined */ + /* 0x07 - User Defined */ + /* 0x08 - User Defined */ + /* 0x09 - User Defined */ + /* 0x0A - User Defined */ + /* 0x0B - User Defined */ + /* 0x0C - User Defined */ + /* 0x0D - User Defined */ + /* 0x0E - User Defined */ + /* 0x0F - User Defined */ + /* + * If we got here, it is most likely that someone was trying to use a + * custom exception handler, and it is not actually installed properly + */ + case VEC_EXCPT04 ... VEC_EXCPT15: + info.si_code = ILL_ILLPARAOP; + sig = SIGILL; + printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); + CHK_DEBUGGER_TRAP_MAYBE(); + break; /* 0x10 HW Single step, handled here */ case VEC_STEP: info.si_code = TRAP_STEP; @@ -507,9 +517,14 @@ asmlinkage void trap_c(struct pt_regs *fp) } CHK_DEBUGGER_TRAP_MAYBE(); break; + /* + * We should be handling all known exception types above, + * if we get here we hit a reserved one, so panic + */ default: - info.si_code = TRAP_ILLTRAP; - sig = SIGTRAP; + oops_in_progress = 1; + info.si_code = ILL_ILLPARAOP; + sig = SIGILL; printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", (fp->seqstat & SEQSTAT_EXCAUSE)); CHK_DEBUGGER_TRAP_MAYBE(); -- cgit v1.2.3 From fffe53bee7d90ab2103d2520ab4d095aea9b7397 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 8 Oct 2008 14:46:09 +0800 Subject: Blackfin arch: fix bug - sometimes there is no response to the hitting key in uboot for bf561-ezkit when running with 50mhz SCLK use 10 delays rather than 7 Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/reboot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index 367e2dc0988..b0a8f89cc9b 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -34,15 +34,15 @@ void bfin_reset(void) bfin_write_SWRST(0x7); /* Due to the way reset is handled in the hardware, we need - * to delay for 7 SCLKS. The only reliable way to do this is - * to calculate the CCLK/SCLK ratio and multiply 7. For now, + * to delay for 10 SCLKS. The only reliable way to do this is + * to calculate the CCLK/SCLK ratio and multiply 10. For now, * we'll assume worse case which is a 1:15 ratio. */ asm( "LSETUP (1f, 1f) LC0 = %0\n" "1: nop;" : - : "a" (15 * 7) + : "a" (15 * 10) : "LC0", "LB0", "LT0" ); -- cgit v1.2.3 From 74c04503d777b5d1f8f2e38852df4f1a6c82fc7b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 8 Oct 2008 16:13:17 +0800 Subject: Blackfin arch: mark local gpio_error() as static Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index ecbd141e0ef..12710ed180b 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -231,7 +231,7 @@ inline int check_gpio(unsigned gpio) } #endif -void gpio_error(unsigned gpio) +static void gpio_error(unsigned gpio) { printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio); } -- cgit v1.2.3 From 7d98c881eed9e19767bc77ffd650d0041b4f41ec Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 8 Oct 2008 16:29:01 +0800 Subject: Blackfin arch: Make sure we protect except 2 properly, and print out memory properly Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/traps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index be5ae7fabc5..0112ba407f6 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -317,6 +317,7 @@ asmlinkage void trap_c(struct pt_regs *fp) * If we got here, it is most likely that someone was trying to use a * custom exception handler, and it is not actually installed properly */ + case VEC_EXCPT02: case VEC_EXCPT04 ... VEC_EXCPT15: info.si_code = ILL_ILLPARAOP; sig = SIGILL; @@ -968,7 +969,7 @@ void dump_bfin_mem(struct pt_regs *fp) if (!((unsigned long)addr & 0xF)) printk("\n" KERN_NOTICE "0x%p: ", addr); - if (get_instruction(&val, addr)) { + if (!get_instruction(&val, addr)) { val = 0; sprintf(buf, "????"); } else -- cgit v1.2.3 From ca87b7ad00a620f259048fdfb27dc2a5384c1e4e Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 8 Oct 2008 17:30:01 +0800 Subject: Blackfin arch: add CONFIG_APP_STACKS_L1 to enable or disable putting kernel stacks in L1 use CONFIG_APP_STACKS_L1 to enable or disable putting kernel stacks in L1, default is enabled, SMP kernel need turn it off Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 9 ++++ arch/blackfin/include/asm/mmu_context.h | 79 ++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 37 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index c507a92cb28..9d936a3986c 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -629,6 +629,15 @@ config CPLB_SWITCH_TAB_L1 If enabled, the CPLB Switch Tables are linked into L1 data memory. (less latency) +config APP_STACK_L1 + bool "Support locating application stack in L1 Scratch Memory" + default y + help + If enabled the application stack can be located in L1 + scratch memory (less latency). + + Currently only works with FLAT binaries. + comment "Speed Optimizations" config BFIN_INS_LOWOVERHEAD bool "ins[bwl] low overhead, higher interrupt latency" diff --git a/arch/blackfin/include/asm/mmu_context.h b/arch/blackfin/include/asm/mmu_context.h index 8529552a981..35593dda2a4 100644 --- a/arch/blackfin/include/asm/mmu_context.h +++ b/arch/blackfin/include/asm/mmu_context.h @@ -45,49 +45,12 @@ extern unsigned long l1_stack_len; extern int l1sram_free(const void*); extern void *l1sram_alloc_max(void*); -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} - -/* Called when creating a new context during fork() or execve(). */ -static inline int -init_new_context(struct task_struct *tsk, struct mm_struct *mm) -{ -#ifdef CONFIG_MPU - unsigned long p = __get_free_pages(GFP_KERNEL, page_mask_order); - mm->context.page_rwx_mask = (unsigned long *)p; - memset(mm->context.page_rwx_mask, 0, - page_mask_nelts * 3 * sizeof(long)); -#endif - return 0; -} - static inline void free_l1stack(void) { nr_l1stack_tasks--; if (nr_l1stack_tasks == 0) l1sram_free(l1_stack_base); } -static inline void destroy_context(struct mm_struct *mm) -{ - struct sram_list_struct *tmp; - - if (current_l1_stack_save == mm->context.l1_stack_save) - current_l1_stack_save = NULL; - if (mm->context.l1_stack_save) - free_l1stack(); - - while ((tmp = mm->context.sram_list)) { - mm->context.sram_list = tmp->next; - sram_free(tmp->addr); - kfree(tmp); - } -#ifdef CONFIG_MPU - if (current_rwx_mask == mm->context.page_rwx_mask) - current_rwx_mask = NULL; - free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order); -#endif -} static inline unsigned long alloc_l1stack(unsigned long length, unsigned long *stack_base) @@ -134,6 +97,7 @@ static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_m } #endif +#ifdef CONFIG_APP_STACK_L1 /* L1 stack switching. */ if (!next_mm->context.l1_stack_save) return; @@ -144,6 +108,7 @@ static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_m } current_l1_stack_save = next_mm->context.l1_stack_save; memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len); +#endif } #ifdef CONFIG_MPU @@ -180,4 +145,44 @@ static inline void update_protections(struct mm_struct *mm) } #endif +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ +} + +/* Called when creating a new context during fork() or execve(). */ +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ +#ifdef CONFIG_MPU + unsigned long p = __get_free_pages(GFP_KERNEL, page_mask_order); + mm->context.page_rwx_mask = (unsigned long *)p; + memset(mm->context.page_rwx_mask, 0, + page_mask_nelts * 3 * sizeof(long)); +#endif + return 0; +} + +static inline void destroy_context(struct mm_struct *mm) +{ + struct sram_list_struct *tmp; + +#ifdef CONFIG_APP_STACK_L1 + if (current_l1_stack_save == mm->context.l1_stack_save) + current_l1_stack_save = 0; + if (mm->context.l1_stack_save) + free_l1stack(); +#endif + + while ((tmp = mm->context.sram_list)) { + mm->context.sram_list = tmp->next; + sram_free(tmp->addr); + kfree(tmp); + } +#ifdef CONFIG_MPU + if (current_rwx_mask == mm->context.page_rwx_mask) + current_rwx_mask = NULL; + free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order); +#endif +} + #endif -- cgit v1.2.3 From 763e63c640ae799e3ce6495e71832744bffc661b Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 8 Oct 2008 17:08:15 +0800 Subject: Blackfin arch: add a meaningful name for each irqchip Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index ff4d5c2879a..f65b3a13a8c 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -243,12 +243,14 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state) #endif static struct irq_chip bfin_core_irqchip = { + .name = "CORE", .ack = bfin_ack_noop, .mask = bfin_core_mask_irq, .unmask = bfin_core_unmask_irq, }; static struct irq_chip bfin_internal_irqchip = { + .name = "INTN", .ack = bfin_ack_noop, .mask = bfin_internal_mask_irq, .unmask = bfin_internal_unmask_irq, @@ -278,6 +280,7 @@ static void bfin_generic_error_unmask_irq(unsigned int irq) } static struct irq_chip bfin_generic_error_irqchip = { + .name = "ERROR", .ack = bfin_ack_noop, .mask_ack = bfin_generic_error_mask_irq, .mask = bfin_generic_error_mask_irq, @@ -495,6 +498,7 @@ int bfin_gpio_set_wake(unsigned int irq, unsigned int state) #endif static struct irq_chip bfin_gpio_irqchip = { + .name = "GPIO", .ack = bfin_gpio_ack_irq, .mask = bfin_gpio_mask_irq, .mask_ack = bfin_gpio_mask_ack_irq, @@ -884,6 +888,7 @@ void bfin_pm_restore(void) #endif static struct irq_chip bfin_gpio_irqchip = { + .name = "GPIO", .ack = bfin_gpio_ack_irq, .mask = bfin_gpio_mask_irq, .mask_ack = bfin_gpio_mask_ack_irq, -- cgit v1.2.3 From 5e95320f9fb7a3171bb75eba15acb745c6e43805 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 8 Oct 2008 17:22:49 +0800 Subject: Blackfin arch: rename blackfin_sram.c to sram-alloc.c rename blackfin_sram.c to sram-alloc.c (we know it is a blackfin file, since it is in arch/blackfin) - and there is no "driver" code in there, it is just an allocator/deallocator for L1 and L2 sram. Also fix a problem that checkpatch pointed out Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/mm/Makefile | 2 +- arch/blackfin/mm/blackfin_sram.c | 806 -------------------------------------- arch/blackfin/mm/sram-alloc.c | 809 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 810 insertions(+), 807 deletions(-) delete mode 100644 arch/blackfin/mm/blackfin_sram.c create mode 100644 arch/blackfin/mm/sram-alloc.c (limited to 'arch') diff --git a/arch/blackfin/mm/Makefile b/arch/blackfin/mm/Makefile index 2a7202ce01f..81aacbc32d3 100644 --- a/arch/blackfin/mm/Makefile +++ b/arch/blackfin/mm/Makefile @@ -2,4 +2,4 @@ # arch/blackfin/mm/Makefile # -obj-y := blackfin_sram.o init.o +obj-y := sram-alloc.o init.o diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c deleted file mode 100644 index 4f5e887a0d9..00000000000 --- a/arch/blackfin/mm/blackfin_sram.c +++ /dev/null @@ -1,806 +0,0 @@ -/* - * File: arch/blackfin/mm/blackfin_sram.c - * Based on: - * Author: - * - * Created: - * Description: SRAM driver for Blackfin ADSP-BF5xx - * - * Modified: - * Copyright 2004-2007 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "blackfin_sram.h" - -static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock; -static spinlock_t l2_sram_lock; - -/* the data structure for L1 scratchpad and DATA SRAM */ -struct sram_piece { - void *paddr; - int size; - pid_t pid; - struct sram_piece *next; -}; - -static struct sram_piece free_l1_ssram_head, used_l1_ssram_head; - -#if L1_DATA_A_LENGTH != 0 -static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head; -#endif - -#if L1_DATA_B_LENGTH != 0 -static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head; -#endif - -#if L1_CODE_LENGTH != 0 -static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head; -#endif - -#if L2_LENGTH != 0 -static struct sram_piece free_l2_sram_head, used_l2_sram_head; -#endif - -static struct kmem_cache *sram_piece_cache; - -/* L1 Scratchpad SRAM initialization function */ -static void __init l1sram_init(void) -{ - free_l1_ssram_head.next = - kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); - if (!free_l1_ssram_head.next) { - printk(KERN_INFO"Fail to initialize Scratchpad data SRAM.\n"); - return; - } - - free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START; - free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH; - free_l1_ssram_head.next->pid = 0; - free_l1_ssram_head.next->next = NULL; - - used_l1_ssram_head.next = NULL; - - /* mutex initialize */ - spin_lock_init(&l1sram_lock); - - printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n", - L1_SCRATCH_LENGTH >> 10); -} - -static void __init l1_data_sram_init(void) -{ -#if L1_DATA_A_LENGTH != 0 - free_l1_data_A_sram_head.next = - kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); - if (!free_l1_data_A_sram_head.next) { - printk(KERN_INFO"Fail to initialize L1 Data A SRAM.\n"); - return; - } - - free_l1_data_A_sram_head.next->paddr = - (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1); - free_l1_data_A_sram_head.next->size = - L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1); - free_l1_data_A_sram_head.next->pid = 0; - free_l1_data_A_sram_head.next->next = NULL; - - used_l1_data_A_sram_head.next = NULL; - - printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n", - L1_DATA_A_LENGTH >> 10, - free_l1_data_A_sram_head.next->size >> 10); -#endif -#if L1_DATA_B_LENGTH != 0 - free_l1_data_B_sram_head.next = - kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); - if (!free_l1_data_B_sram_head.next) { - printk(KERN_INFO"Fail to initialize L1 Data B SRAM.\n"); - return; - } - - free_l1_data_B_sram_head.next->paddr = - (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1); - free_l1_data_B_sram_head.next->size = - L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1); - free_l1_data_B_sram_head.next->pid = 0; - free_l1_data_B_sram_head.next->next = NULL; - - used_l1_data_B_sram_head.next = NULL; - - printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n", - L1_DATA_B_LENGTH >> 10, - free_l1_data_B_sram_head.next->size >> 10); -#endif - - /* mutex initialize */ - spin_lock_init(&l1_data_sram_lock); -} - -static void __init l1_inst_sram_init(void) -{ -#if L1_CODE_LENGTH != 0 - free_l1_inst_sram_head.next = - kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); - if (!free_l1_inst_sram_head.next) { - printk(KERN_INFO"Fail to initialize L1 Instruction SRAM.\n"); - return; - } - - free_l1_inst_sram_head.next->paddr = - (void *)L1_CODE_START + (_etext_l1 - _stext_l1); - free_l1_inst_sram_head.next->size = - L1_CODE_LENGTH - (_etext_l1 - _stext_l1); - free_l1_inst_sram_head.next->pid = 0; - free_l1_inst_sram_head.next->next = NULL; - - used_l1_inst_sram_head.next = NULL; - - printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n", - L1_CODE_LENGTH >> 10, - free_l1_inst_sram_head.next->size >> 10); -#endif - - /* mutex initialize */ - spin_lock_init(&l1_inst_sram_lock); -} - -static void __init l2_sram_init(void) -{ -#if L2_LENGTH != 0 - free_l2_sram_head.next = - kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); - if (!free_l2_sram_head.next) { - printk(KERN_INFO"Fail to initialize L2 SRAM.\n"); - return; - } - - free_l2_sram_head.next->paddr = (void *)L2_START + - (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2); - free_l2_sram_head.next->size = L2_LENGTH - - (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2); - free_l2_sram_head.next->pid = 0; - free_l2_sram_head.next->next = NULL; - - used_l2_sram_head.next = NULL; - - printk(KERN_INFO "Blackfin L2 SRAM: %d KB (%d KB free)\n", - L2_LENGTH >> 10, - free_l2_sram_head.next->size >> 10); -#endif - - /* mutex initialize */ - spin_lock_init(&l2_sram_lock); -} -void __init bfin_sram_init(void) -{ - sram_piece_cache = kmem_cache_create("sram_piece_cache", - sizeof(struct sram_piece), - 0, SLAB_PANIC, NULL); - - l1sram_init(); - l1_data_sram_init(); - l1_inst_sram_init(); - l2_sram_init(); -} - -/* SRAM allocate function */ -static void *_sram_alloc(size_t size, struct sram_piece *pfree_head, - struct sram_piece *pused_head) -{ - struct sram_piece *pslot, *plast, *pavail; - - if (size <= 0 || !pfree_head || !pused_head) - return NULL; - - /* Align the size */ - size = (size + 3) & ~3; - - pslot = pfree_head->next; - plast = pfree_head; - - /* search an available piece slot */ - while (pslot != NULL && size > pslot->size) { - plast = pslot; - pslot = pslot->next; - } - - if (!pslot) - return NULL; - - if (pslot->size == size) { - plast->next = pslot->next; - pavail = pslot; - } else { - pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); - - if (!pavail) - return NULL; - - pavail->paddr = pslot->paddr; - pavail->size = size; - pslot->paddr += size; - pslot->size -= size; - } - - pavail->pid = current->pid; - - pslot = pused_head->next; - plast = pused_head; - - /* insert new piece into used piece list !!! */ - while (pslot != NULL && pavail->paddr < pslot->paddr) { - plast = pslot; - pslot = pslot->next; - } - - pavail->next = pslot; - plast->next = pavail; - - return pavail->paddr; -} - -/* Allocate the largest available block. */ -static void *_sram_alloc_max(struct sram_piece *pfree_head, - struct sram_piece *pused_head, - unsigned long *psize) -{ - struct sram_piece *pslot, *pmax; - - if (!pfree_head || !pused_head) - return NULL; - - pmax = pslot = pfree_head->next; - - /* search an available piece slot */ - while (pslot != NULL) { - if (pslot->size > pmax->size) - pmax = pslot; - pslot = pslot->next; - } - - if (!pmax) - return NULL; - - *psize = pmax->size; - - return _sram_alloc(*psize, pfree_head, pused_head); -} - -/* SRAM free function */ -static int _sram_free(const void *addr, - struct sram_piece *pfree_head, - struct sram_piece *pused_head) -{ - struct sram_piece *pslot, *plast, *pavail; - - if (!pfree_head || !pused_head) - return -1; - - /* search the relevant memory slot */ - pslot = pused_head->next; - plast = pused_head; - - /* search an available piece slot */ - while (pslot != NULL && pslot->paddr != addr) { - plast = pslot; - pslot = pslot->next; - } - - if (!pslot) - return -1; - - plast->next = pslot->next; - pavail = pslot; - pavail->pid = 0; - - /* insert free pieces back to the free list */ - pslot = pfree_head->next; - plast = pfree_head; - - while (pslot != NULL && addr > pslot->paddr) { - plast = pslot; - pslot = pslot->next; - } - - if (plast != pfree_head && plast->paddr + plast->size == pavail->paddr) { - plast->size += pavail->size; - kmem_cache_free(sram_piece_cache, pavail); - } else { - pavail->next = plast->next; - plast->next = pavail; - plast = pavail; - } - - if (pslot && plast->paddr + plast->size == pslot->paddr) { - plast->size += pslot->size; - plast->next = pslot->next; - kmem_cache_free(sram_piece_cache, pslot); - } - - return 0; -} - -int sram_free(const void *addr) -{ - if (0) {} -#if L1_CODE_LENGTH != 0 - else if (addr >= (void *)L1_CODE_START - && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH)) - return l1_inst_sram_free(addr); -#endif -#if L1_DATA_A_LENGTH != 0 - else if (addr >= (void *)L1_DATA_A_START - && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH)) - return l1_data_A_sram_free(addr); -#endif -#if L1_DATA_B_LENGTH != 0 - else if (addr >= (void *)L1_DATA_B_START - && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH)) - return l1_data_B_sram_free(addr); -#endif -#if L2_LENGTH != 0 - else if (addr >= (void *)L2_START - && addr < (void *)(L2_START + L2_LENGTH)) - return l2_sram_free(addr); -#endif - else - return -1; -} -EXPORT_SYMBOL(sram_free); - -void *l1_data_A_sram_alloc(size_t size) -{ - unsigned long flags; - void *addr = NULL; - - /* add mutex operation */ - spin_lock_irqsave(&l1_data_sram_lock, flags); - -#if L1_DATA_A_LENGTH != 0 - addr = _sram_alloc(size, &free_l1_data_A_sram_head, - &used_l1_data_A_sram_head); -#endif - - /* add mutex operation */ - spin_unlock_irqrestore(&l1_data_sram_lock, flags); - - pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n", - (long unsigned int)addr, size); - - return addr; -} -EXPORT_SYMBOL(l1_data_A_sram_alloc); - -int l1_data_A_sram_free(const void *addr) -{ - unsigned long flags; - int ret; - - /* add mutex operation */ - spin_lock_irqsave(&l1_data_sram_lock, flags); - -#if L1_DATA_A_LENGTH != 0 - ret = _sram_free(addr, &free_l1_data_A_sram_head, - &used_l1_data_A_sram_head); -#else - ret = -1; -#endif - - /* add mutex operation */ - spin_unlock_irqrestore(&l1_data_sram_lock, flags); - - return ret; -} -EXPORT_SYMBOL(l1_data_A_sram_free); - -void *l1_data_B_sram_alloc(size_t size) -{ -#if L1_DATA_B_LENGTH != 0 - unsigned long flags; - void *addr; - - /* add mutex operation */ - spin_lock_irqsave(&l1_data_sram_lock, flags); - - addr = _sram_alloc(size, &free_l1_data_B_sram_head, - &used_l1_data_B_sram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l1_data_sram_lock, flags); - - pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n", - (long unsigned int)addr, size); - - return addr; -#else - return NULL; -#endif -} -EXPORT_SYMBOL(l1_data_B_sram_alloc); - -int l1_data_B_sram_free(const void *addr) -{ -#if L1_DATA_B_LENGTH != 0 - unsigned long flags; - int ret; - - /* add mutex operation */ - spin_lock_irqsave(&l1_data_sram_lock, flags); - - ret = _sram_free(addr, &free_l1_data_B_sram_head, - &used_l1_data_B_sram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l1_data_sram_lock, flags); - - return ret; -#else - return -1; -#endif -} -EXPORT_SYMBOL(l1_data_B_sram_free); - -void *l1_data_sram_alloc(size_t size) -{ - void *addr = l1_data_A_sram_alloc(size); - - if (!addr) - addr = l1_data_B_sram_alloc(size); - - return addr; -} -EXPORT_SYMBOL(l1_data_sram_alloc); - -void *l1_data_sram_zalloc(size_t size) -{ - void *addr = l1_data_sram_alloc(size); - - if (addr) - memset(addr, 0x00, size); - - return addr; -} -EXPORT_SYMBOL(l1_data_sram_zalloc); - -int l1_data_sram_free(const void *addr) -{ - int ret; - ret = l1_data_A_sram_free(addr); - if (ret == -1) - ret = l1_data_B_sram_free(addr); - return ret; -} -EXPORT_SYMBOL(l1_data_sram_free); - -void *l1_inst_sram_alloc(size_t size) -{ -#if L1_CODE_LENGTH != 0 - unsigned long flags; - void *addr; - - /* add mutex operation */ - spin_lock_irqsave(&l1_inst_sram_lock, flags); - - addr = _sram_alloc(size, &free_l1_inst_sram_head, - &used_l1_inst_sram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l1_inst_sram_lock, flags); - - pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n", - (long unsigned int)addr, size); - - return addr; -#else - return NULL; -#endif -} -EXPORT_SYMBOL(l1_inst_sram_alloc); - -int l1_inst_sram_free(const void *addr) -{ -#if L1_CODE_LENGTH != 0 - unsigned long flags; - int ret; - - /* add mutex operation */ - spin_lock_irqsave(&l1_inst_sram_lock, flags); - - ret = _sram_free(addr, &free_l1_inst_sram_head, - &used_l1_inst_sram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l1_inst_sram_lock, flags); - - return ret; -#else - return -1; -#endif -} -EXPORT_SYMBOL(l1_inst_sram_free); - -/* L1 Scratchpad memory allocate function */ -void *l1sram_alloc(size_t size) -{ - unsigned long flags; - void *addr; - - /* add mutex operation */ - spin_lock_irqsave(&l1sram_lock, flags); - - addr = _sram_alloc(size, &free_l1_ssram_head, - &used_l1_ssram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l1sram_lock, flags); - - return addr; -} - -/* L1 Scratchpad memory allocate function */ -void *l1sram_alloc_max(size_t *psize) -{ - unsigned long flags; - void *addr; - - /* add mutex operation */ - spin_lock_irqsave(&l1sram_lock, flags); - - addr = _sram_alloc_max(&free_l1_ssram_head, - &used_l1_ssram_head, psize); - - /* add mutex operation */ - spin_unlock_irqrestore(&l1sram_lock, flags); - - return addr; -} - -/* L1 Scratchpad memory free function */ -int l1sram_free(const void *addr) -{ - unsigned long flags; - int ret; - - /* add mutex operation */ - spin_lock_irqsave(&l1sram_lock, flags); - - ret = _sram_free(addr, &free_l1_ssram_head, - &used_l1_ssram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l1sram_lock, flags); - - return ret; -} - -void *l2_sram_alloc(size_t size) -{ -#if L2_LENGTH != 0 - unsigned long flags; - void *addr; - - /* add mutex operation */ - spin_lock_irqsave(&l2_sram_lock, flags); - - addr = _sram_alloc(size, &free_l2_sram_head, - &used_l2_sram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l2_sram_lock, flags); - - pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n", - (long unsigned int)addr, size); - - return addr; -#else - return NULL; -#endif -} -EXPORT_SYMBOL(l2_sram_alloc); - -void *l2_sram_zalloc(size_t size) -{ - void *addr = l2_sram_alloc(size); - - if (addr) - memset(addr, 0x00, size); - - return addr; -} -EXPORT_SYMBOL(l2_sram_zalloc); - -int l2_sram_free(const void *addr) -{ -#if L2_LENGTH != 0 - unsigned long flags; - int ret; - - /* add mutex operation */ - spin_lock_irqsave(&l2_sram_lock, flags); - - ret = _sram_free(addr, &free_l2_sram_head, - &used_l2_sram_head); - - /* add mutex operation */ - spin_unlock_irqrestore(&l2_sram_lock, flags); - - return ret; -#else - return -1; -#endif -} -EXPORT_SYMBOL(l2_sram_free); - -int sram_free_with_lsl(const void *addr) -{ - struct sram_list_struct *lsl, **tmp; - struct mm_struct *mm = current->mm; - - for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next) - if ((*tmp)->addr == addr) - goto found; - return -1; -found: - lsl = *tmp; - sram_free(addr); - *tmp = lsl->next; - kfree(lsl); - - return 0; -} -EXPORT_SYMBOL(sram_free_with_lsl); - -void *sram_alloc_with_lsl(size_t size, unsigned long flags) -{ - void *addr = NULL; - struct sram_list_struct *lsl = NULL; - struct mm_struct *mm = current->mm; - - lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL); - if (!lsl) - return NULL; - - if (flags & L1_INST_SRAM) - addr = l1_inst_sram_alloc(size); - - if (addr == NULL && (flags & L1_DATA_A_SRAM)) - addr = l1_data_A_sram_alloc(size); - - if (addr == NULL && (flags & L1_DATA_B_SRAM)) - addr = l1_data_B_sram_alloc(size); - - if (addr == NULL && (flags & L2_SRAM)) - addr = l2_sram_alloc(size); - - if (addr == NULL) { - kfree(lsl); - return NULL; - } - lsl->addr = addr; - lsl->length = size; - lsl->next = mm->context.sram_list; - mm->context.sram_list = lsl; - return addr; -} -EXPORT_SYMBOL(sram_alloc_with_lsl); - -#ifdef CONFIG_PROC_FS -/* Once we get a real allocator, we'll throw all of this away. - * Until then, we need some sort of visibility into the L1 alloc. - */ -/* Need to keep line of output the same. Currently, that is 44 bytes - * (including newline). - */ -static int _sram_proc_read(char *buf, int *len, int count, const char *desc, - struct sram_piece *pfree_head, - struct sram_piece *pused_head) -{ - struct sram_piece *pslot; - - if (!pfree_head || !pused_head) - return -1; - - *len += sprintf(&buf[*len], "--- SRAM %-14s Size PID State \n", desc); - - /* search the relevant memory slot */ - pslot = pused_head->next; - - while (pslot != NULL) { - *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", - pslot->paddr, pslot->paddr + pslot->size, - pslot->size, pslot->pid, "ALLOCATED"); - - pslot = pslot->next; - } - - pslot = pfree_head->next; - - while (pslot != NULL) { - *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", - pslot->paddr, pslot->paddr + pslot->size, - pslot->size, pslot->pid, "FREE"); - - pslot = pslot->next; - } - - return 0; -} -static int sram_proc_read(char *buf, char **start, off_t offset, int count, - int *eof, void *data) -{ - int len = 0; - - if (_sram_proc_read(buf, &len, count, "Scratchpad", - &free_l1_ssram_head, &used_l1_ssram_head)) - goto not_done; -#if L1_DATA_A_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L1 Data A", - &free_l1_data_A_sram_head, - &used_l1_data_A_sram_head)) - goto not_done; -#endif -#if L1_DATA_B_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L1 Data B", - &free_l1_data_B_sram_head, - &used_l1_data_B_sram_head)) - goto not_done; -#endif -#if L1_CODE_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L1 Instruction", - &free_l1_inst_sram_head, &used_l1_inst_sram_head)) - goto not_done; -#endif -#if L2_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L2", - &free_l2_sram_head, &used_l2_sram_head)) - goto not_done; -#endif - - *eof = 1; - not_done: - return len; -} - -static int __init sram_proc_init(void) -{ - struct proc_dir_entry *ptr; - ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL); - if (!ptr) { - printk(KERN_WARNING "unable to create /proc/sram\n"); - return -1; - } - ptr->owner = THIS_MODULE; - ptr->read_proc = sram_proc_read; - return 0; -} -late_initcall(sram_proc_init); -#endif diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c new file mode 100644 index 00000000000..0f1ca6930c1 --- /dev/null +++ b/arch/blackfin/mm/sram-alloc.c @@ -0,0 +1,809 @@ +/* + * File: arch/blackfin/mm/sram-alloc.c + * Based on: + * Author: + * + * Created: + * Description: SRAM allocator for Blackfin L1 and L2 memory + * + * Modified: + * Copyright 2004-2008 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "blackfin_sram.h" + +static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock; +static spinlock_t l2_sram_lock; + +/* the data structure for L1 scratchpad and DATA SRAM */ +struct sram_piece { + void *paddr; + int size; + pid_t pid; + struct sram_piece *next; +}; + +static struct sram_piece free_l1_ssram_head, used_l1_ssram_head; + +#if L1_DATA_A_LENGTH != 0 +static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head; +#endif + +#if L1_DATA_B_LENGTH != 0 +static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head; +#endif + +#if L1_CODE_LENGTH != 0 +static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head; +#endif + +#if L2_LENGTH != 0 +static struct sram_piece free_l2_sram_head, used_l2_sram_head; +#endif + +static struct kmem_cache *sram_piece_cache; + +/* L1 Scratchpad SRAM initialization function */ +static void __init l1sram_init(void) +{ + free_l1_ssram_head.next = + kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); + if (!free_l1_ssram_head.next) { + printk(KERN_INFO "Failed to initialize Scratchpad data SRAM\n"); + return; + } + + free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START; + free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH; + free_l1_ssram_head.next->pid = 0; + free_l1_ssram_head.next->next = NULL; + + used_l1_ssram_head.next = NULL; + + /* mutex initialize */ + spin_lock_init(&l1sram_lock); + + printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n", + L1_SCRATCH_LENGTH >> 10); +} + +static void __init l1_data_sram_init(void) +{ +#if L1_DATA_A_LENGTH != 0 + free_l1_data_A_sram_head.next = + kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); + if (!free_l1_data_A_sram_head.next) { + printk(KERN_INFO "Failed to initialize L1 Data A SRAM\n"); + return; + } + + free_l1_data_A_sram_head.next->paddr = + (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1); + free_l1_data_A_sram_head.next->size = + L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1); + free_l1_data_A_sram_head.next->pid = 0; + free_l1_data_A_sram_head.next->next = NULL; + + used_l1_data_A_sram_head.next = NULL; + + printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n", + L1_DATA_A_LENGTH >> 10, + free_l1_data_A_sram_head.next->size >> 10); +#endif +#if L1_DATA_B_LENGTH != 0 + free_l1_data_B_sram_head.next = + kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); + if (!free_l1_data_B_sram_head.next) { + printk(KERN_INFO "Failed to initialize L1 Data B SRAM\n"); + return; + } + + free_l1_data_B_sram_head.next->paddr = + (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1); + free_l1_data_B_sram_head.next->size = + L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1); + free_l1_data_B_sram_head.next->pid = 0; + free_l1_data_B_sram_head.next->next = NULL; + + used_l1_data_B_sram_head.next = NULL; + + printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n", + L1_DATA_B_LENGTH >> 10, + free_l1_data_B_sram_head.next->size >> 10); +#endif + + /* mutex initialize */ + spin_lock_init(&l1_data_sram_lock); +} + +static void __init l1_inst_sram_init(void) +{ +#if L1_CODE_LENGTH != 0 + free_l1_inst_sram_head.next = + kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); + if (!free_l1_inst_sram_head.next) { + printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n"); + return; + } + + free_l1_inst_sram_head.next->paddr = + (void *)L1_CODE_START + (_etext_l1 - _stext_l1); + free_l1_inst_sram_head.next->size = + L1_CODE_LENGTH - (_etext_l1 - _stext_l1); + free_l1_inst_sram_head.next->pid = 0; + free_l1_inst_sram_head.next->next = NULL; + + used_l1_inst_sram_head.next = NULL; + + printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n", + L1_CODE_LENGTH >> 10, + free_l1_inst_sram_head.next->size >> 10); +#endif + + /* mutex initialize */ + spin_lock_init(&l1_inst_sram_lock); +} + +static void __init l2_sram_init(void) +{ +#if L2_LENGTH != 0 + free_l2_sram_head.next = + kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); + if (!free_l2_sram_head.next) { + printk(KERN_INFO "Failed to initialize L2 SRAM\n"); + return; + } + + free_l2_sram_head.next->paddr = (void *)L2_START + + (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2); + free_l2_sram_head.next->size = L2_LENGTH - + (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2); + free_l2_sram_head.next->pid = 0; + free_l2_sram_head.next->next = NULL; + + used_l2_sram_head.next = NULL; + + printk(KERN_INFO "Blackfin L2 SRAM: %d KB (%d KB free)\n", + L2_LENGTH >> 10, + free_l2_sram_head.next->size >> 10); +#endif + + /* mutex initialize */ + spin_lock_init(&l2_sram_lock); +} +void __init bfin_sram_init(void) +{ + sram_piece_cache = kmem_cache_create("sram_piece_cache", + sizeof(struct sram_piece), + 0, SLAB_PANIC, NULL); + + l1sram_init(); + l1_data_sram_init(); + l1_inst_sram_init(); + l2_sram_init(); +} + +/* SRAM allocate function */ +static void *_sram_alloc(size_t size, struct sram_piece *pfree_head, + struct sram_piece *pused_head) +{ + struct sram_piece *pslot, *plast, *pavail; + + if (size <= 0 || !pfree_head || !pused_head) + return NULL; + + /* Align the size */ + size = (size + 3) & ~3; + + pslot = pfree_head->next; + plast = pfree_head; + + /* search an available piece slot */ + while (pslot != NULL && size > pslot->size) { + plast = pslot; + pslot = pslot->next; + } + + if (!pslot) + return NULL; + + if (pslot->size == size) { + plast->next = pslot->next; + pavail = pslot; + } else { + pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); + + if (!pavail) + return NULL; + + pavail->paddr = pslot->paddr; + pavail->size = size; + pslot->paddr += size; + pslot->size -= size; + } + + pavail->pid = current->pid; + + pslot = pused_head->next; + plast = pused_head; + + /* insert new piece into used piece list !!! */ + while (pslot != NULL && pavail->paddr < pslot->paddr) { + plast = pslot; + pslot = pslot->next; + } + + pavail->next = pslot; + plast->next = pavail; + + return pavail->paddr; +} + +/* Allocate the largest available block. */ +static void *_sram_alloc_max(struct sram_piece *pfree_head, + struct sram_piece *pused_head, + unsigned long *psize) +{ + struct sram_piece *pslot, *pmax; + + if (!pfree_head || !pused_head) + return NULL; + + pmax = pslot = pfree_head->next; + + /* search an available piece slot */ + while (pslot != NULL) { + if (pslot->size > pmax->size) + pmax = pslot; + pslot = pslot->next; + } + + if (!pmax) + return NULL; + + *psize = pmax->size; + + return _sram_alloc(*psize, pfree_head, pused_head); +} + +/* SRAM free function */ +static int _sram_free(const void *addr, + struct sram_piece *pfree_head, + struct sram_piece *pused_head) +{ + struct sram_piece *pslot, *plast, *pavail; + + if (!pfree_head || !pused_head) + return -1; + + /* search the relevant memory slot */ + pslot = pused_head->next; + plast = pused_head; + + /* search an available piece slot */ + while (pslot != NULL && pslot->paddr != addr) { + plast = pslot; + pslot = pslot->next; + } + + if (!pslot) + return -1; + + plast->next = pslot->next; + pavail = pslot; + pavail->pid = 0; + + /* insert free pieces back to the free list */ + pslot = pfree_head->next; + plast = pfree_head; + + while (pslot != NULL && addr > pslot->paddr) { + plast = pslot; + pslot = pslot->next; + } + + if (plast != pfree_head && plast->paddr + plast->size == pavail->paddr) { + plast->size += pavail->size; + kmem_cache_free(sram_piece_cache, pavail); + } else { + pavail->next = plast->next; + plast->next = pavail; + plast = pavail; + } + + if (pslot && plast->paddr + plast->size == pslot->paddr) { + plast->size += pslot->size; + plast->next = pslot->next; + kmem_cache_free(sram_piece_cache, pslot); + } + + return 0; +} + +int sram_free(const void *addr) +{ + +#if L1_CODE_LENGTH != 0 + if (addr >= (void *)L1_CODE_START + && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH)) + return l1_inst_sram_free(addr); + else +#endif +#if L1_DATA_A_LENGTH != 0 + if (addr >= (void *)L1_DATA_A_START + && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH)) + return l1_data_A_sram_free(addr); + else +#endif +#if L1_DATA_B_LENGTH != 0 + if (addr >= (void *)L1_DATA_B_START + && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH)) + return l1_data_B_sram_free(addr); + else +#endif +#if L2_LENGTH != 0 + if (addr >= (void *)L2_START + && addr < (void *)(L2_START + L2_LENGTH)) + return l2_sram_free(addr); + else +#endif + return -1; +} +EXPORT_SYMBOL(sram_free); + +void *l1_data_A_sram_alloc(size_t size) +{ + unsigned long flags; + void *addr = NULL; + + /* add mutex operation */ + spin_lock_irqsave(&l1_data_sram_lock, flags); + +#if L1_DATA_A_LENGTH != 0 + addr = _sram_alloc(size, &free_l1_data_A_sram_head, + &used_l1_data_A_sram_head); +#endif + + /* add mutex operation */ + spin_unlock_irqrestore(&l1_data_sram_lock, flags); + + pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n", + (long unsigned int)addr, size); + + return addr; +} +EXPORT_SYMBOL(l1_data_A_sram_alloc); + +int l1_data_A_sram_free(const void *addr) +{ + unsigned long flags; + int ret; + + /* add mutex operation */ + spin_lock_irqsave(&l1_data_sram_lock, flags); + +#if L1_DATA_A_LENGTH != 0 + ret = _sram_free(addr, &free_l1_data_A_sram_head, + &used_l1_data_A_sram_head); +#else + ret = -1; +#endif + + /* add mutex operation */ + spin_unlock_irqrestore(&l1_data_sram_lock, flags); + + return ret; +} +EXPORT_SYMBOL(l1_data_A_sram_free); + +void *l1_data_B_sram_alloc(size_t size) +{ +#if L1_DATA_B_LENGTH != 0 + unsigned long flags; + void *addr; + + /* add mutex operation */ + spin_lock_irqsave(&l1_data_sram_lock, flags); + + addr = _sram_alloc(size, &free_l1_data_B_sram_head, + &used_l1_data_B_sram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l1_data_sram_lock, flags); + + pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n", + (long unsigned int)addr, size); + + return addr; +#else + return NULL; +#endif +} +EXPORT_SYMBOL(l1_data_B_sram_alloc); + +int l1_data_B_sram_free(const void *addr) +{ +#if L1_DATA_B_LENGTH != 0 + unsigned long flags; + int ret; + + /* add mutex operation */ + spin_lock_irqsave(&l1_data_sram_lock, flags); + + ret = _sram_free(addr, &free_l1_data_B_sram_head, + &used_l1_data_B_sram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l1_data_sram_lock, flags); + + return ret; +#else + return -1; +#endif +} +EXPORT_SYMBOL(l1_data_B_sram_free); + +void *l1_data_sram_alloc(size_t size) +{ + void *addr = l1_data_A_sram_alloc(size); + + if (!addr) + addr = l1_data_B_sram_alloc(size); + + return addr; +} +EXPORT_SYMBOL(l1_data_sram_alloc); + +void *l1_data_sram_zalloc(size_t size) +{ + void *addr = l1_data_sram_alloc(size); + + if (addr) + memset(addr, 0x00, size); + + return addr; +} +EXPORT_SYMBOL(l1_data_sram_zalloc); + +int l1_data_sram_free(const void *addr) +{ + int ret; + ret = l1_data_A_sram_free(addr); + if (ret == -1) + ret = l1_data_B_sram_free(addr); + return ret; +} +EXPORT_SYMBOL(l1_data_sram_free); + +void *l1_inst_sram_alloc(size_t size) +{ +#if L1_CODE_LENGTH != 0 + unsigned long flags; + void *addr; + + /* add mutex operation */ + spin_lock_irqsave(&l1_inst_sram_lock, flags); + + addr = _sram_alloc(size, &free_l1_inst_sram_head, + &used_l1_inst_sram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l1_inst_sram_lock, flags); + + pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n", + (long unsigned int)addr, size); + + return addr; +#else + return NULL; +#endif +} +EXPORT_SYMBOL(l1_inst_sram_alloc); + +int l1_inst_sram_free(const void *addr) +{ +#if L1_CODE_LENGTH != 0 + unsigned long flags; + int ret; + + /* add mutex operation */ + spin_lock_irqsave(&l1_inst_sram_lock, flags); + + ret = _sram_free(addr, &free_l1_inst_sram_head, + &used_l1_inst_sram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l1_inst_sram_lock, flags); + + return ret; +#else + return -1; +#endif +} +EXPORT_SYMBOL(l1_inst_sram_free); + +/* L1 Scratchpad memory allocate function */ +void *l1sram_alloc(size_t size) +{ + unsigned long flags; + void *addr; + + /* add mutex operation */ + spin_lock_irqsave(&l1sram_lock, flags); + + addr = _sram_alloc(size, &free_l1_ssram_head, + &used_l1_ssram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l1sram_lock, flags); + + return addr; +} + +/* L1 Scratchpad memory allocate function */ +void *l1sram_alloc_max(size_t *psize) +{ + unsigned long flags; + void *addr; + + /* add mutex operation */ + spin_lock_irqsave(&l1sram_lock, flags); + + addr = _sram_alloc_max(&free_l1_ssram_head, + &used_l1_ssram_head, psize); + + /* add mutex operation */ + spin_unlock_irqrestore(&l1sram_lock, flags); + + return addr; +} + +/* L1 Scratchpad memory free function */ +int l1sram_free(const void *addr) +{ + unsigned long flags; + int ret; + + /* add mutex operation */ + spin_lock_irqsave(&l1sram_lock, flags); + + ret = _sram_free(addr, &free_l1_ssram_head, + &used_l1_ssram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l1sram_lock, flags); + + return ret; +} + +void *l2_sram_alloc(size_t size) +{ +#if L2_LENGTH != 0 + unsigned long flags; + void *addr; + + /* add mutex operation */ + spin_lock_irqsave(&l2_sram_lock, flags); + + addr = _sram_alloc(size, &free_l2_sram_head, + &used_l2_sram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l2_sram_lock, flags); + + pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n", + (long unsigned int)addr, size); + + return addr; +#else + return NULL; +#endif +} +EXPORT_SYMBOL(l2_sram_alloc); + +void *l2_sram_zalloc(size_t size) +{ + void *addr = l2_sram_alloc(size); + + if (addr) + memset(addr, 0x00, size); + + return addr; +} +EXPORT_SYMBOL(l2_sram_zalloc); + +int l2_sram_free(const void *addr) +{ +#if L2_LENGTH != 0 + unsigned long flags; + int ret; + + /* add mutex operation */ + spin_lock_irqsave(&l2_sram_lock, flags); + + ret = _sram_free(addr, &free_l2_sram_head, + &used_l2_sram_head); + + /* add mutex operation */ + spin_unlock_irqrestore(&l2_sram_lock, flags); + + return ret; +#else + return -1; +#endif +} +EXPORT_SYMBOL(l2_sram_free); + +int sram_free_with_lsl(const void *addr) +{ + struct sram_list_struct *lsl, **tmp; + struct mm_struct *mm = current->mm; + + for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next) + if ((*tmp)->addr == addr) + goto found; + return -1; +found: + lsl = *tmp; + sram_free(addr); + *tmp = lsl->next; + kfree(lsl); + + return 0; +} +EXPORT_SYMBOL(sram_free_with_lsl); + +void *sram_alloc_with_lsl(size_t size, unsigned long flags) +{ + void *addr = NULL; + struct sram_list_struct *lsl = NULL; + struct mm_struct *mm = current->mm; + + lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL); + if (!lsl) + return NULL; + + if (flags & L1_INST_SRAM) + addr = l1_inst_sram_alloc(size); + + if (addr == NULL && (flags & L1_DATA_A_SRAM)) + addr = l1_data_A_sram_alloc(size); + + if (addr == NULL && (flags & L1_DATA_B_SRAM)) + addr = l1_data_B_sram_alloc(size); + + if (addr == NULL && (flags & L2_SRAM)) + addr = l2_sram_alloc(size); + + if (addr == NULL) { + kfree(lsl); + return NULL; + } + lsl->addr = addr; + lsl->length = size; + lsl->next = mm->context.sram_list; + mm->context.sram_list = lsl; + return addr; +} +EXPORT_SYMBOL(sram_alloc_with_lsl); + +#ifdef CONFIG_PROC_FS +/* Once we get a real allocator, we'll throw all of this away. + * Until then, we need some sort of visibility into the L1 alloc. + */ +/* Need to keep line of output the same. Currently, that is 44 bytes + * (including newline). + */ +static int _sram_proc_read(char *buf, int *len, int count, const char *desc, + struct sram_piece *pfree_head, + struct sram_piece *pused_head) +{ + struct sram_piece *pslot; + + if (!pfree_head || !pused_head) + return -1; + + *len += sprintf(&buf[*len], "--- SRAM %-14s Size PID State \n", desc); + + /* search the relevant memory slot */ + pslot = pused_head->next; + + while (pslot != NULL) { + *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", + pslot->paddr, pslot->paddr + pslot->size, + pslot->size, pslot->pid, "ALLOCATED"); + + pslot = pslot->next; + } + + pslot = pfree_head->next; + + while (pslot != NULL) { + *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", + pslot->paddr, pslot->paddr + pslot->size, + pslot->size, pslot->pid, "FREE"); + + pslot = pslot->next; + } + + return 0; +} +static int sram_proc_read(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + int len = 0; + + if (_sram_proc_read(buf, &len, count, "Scratchpad", + &free_l1_ssram_head, &used_l1_ssram_head)) + goto not_done; +#if L1_DATA_A_LENGTH != 0 + if (_sram_proc_read(buf, &len, count, "L1 Data A", + &free_l1_data_A_sram_head, + &used_l1_data_A_sram_head)) + goto not_done; +#endif +#if L1_DATA_B_LENGTH != 0 + if (_sram_proc_read(buf, &len, count, "L1 Data B", + &free_l1_data_B_sram_head, + &used_l1_data_B_sram_head)) + goto not_done; +#endif +#if L1_CODE_LENGTH != 0 + if (_sram_proc_read(buf, &len, count, "L1 Instruction", + &free_l1_inst_sram_head, &used_l1_inst_sram_head)) + goto not_done; +#endif +#if L2_LENGTH != 0 + if (_sram_proc_read(buf, &len, count, "L2", + &free_l2_sram_head, &used_l2_sram_head)) + goto not_done; +#endif + + *eof = 1; + not_done: + return len; +} + +static int __init sram_proc_init(void) +{ + struct proc_dir_entry *ptr; + ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL); + if (!ptr) { + printk(KERN_WARNING "unable to create /proc/sram\n"); + return -1; + } + ptr->owner = THIS_MODULE; + ptr->read_proc = sram_proc_read; + return 0; +} +late_initcall(sram_proc_init); +#endif -- cgit v1.2.3 From 5b04f271fe49bb7adb061de454d383c027a18de0 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 8 Oct 2008 17:32:57 +0800 Subject: Blackfin arch: Modify some funtion names to more genernal ones Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/cplbinit.h | 2 +- arch/blackfin/kernel/cplb-mpu/cplbinit.c | 2 +- arch/blackfin/kernel/cplb-nompu/cplbinit.c | 2 +- arch/blackfin/kernel/setup.c | 8 ++++---- arch/blackfin/mach-common/head.S | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/cplbinit.h b/arch/blackfin/include/asm/cplbinit.h index 0eb1c1b685a..9d23cd1ff7d 100644 --- a/arch/blackfin/include/asm/cplbinit.h +++ b/arch/blackfin/include/asm/cplbinit.h @@ -90,6 +90,6 @@ extern u_long dpdt_swapcount_table[]; extern unsigned long reserved_mem_dcache_on; extern unsigned long reserved_mem_icache_on; -extern void generate_cpl_tables(void); +extern void generate_cplb_tables(void); #endif diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index 48060105346..d4257d0ad6a 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -36,7 +36,7 @@ struct cplb_entry dcplb_tbl[MAX_CPLBS]; int first_switched_icplb, first_switched_dcplb; int first_mask_dcplb; -void __init generate_cpl_tables(void) +void __init generate_cplb_tables(void) { int i_d, i_i; unsigned long addr; diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c index 728f708d398..2c45c16c352 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c @@ -308,7 +308,7 @@ __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end) } } -void __init generate_cpl_tables(void) +void __init generate_cplb_tables(void) { u16 i, j, process; diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 8e639dc886a..ea4f60978c6 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -78,10 +78,10 @@ static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata; static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata; static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata; -void __init bf53x_cache_init(void) +void __init bfin_cache_init(void) { #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) - generate_cpl_tables(); + generate_cplb_tables(); #endif #ifdef CONFIG_BFIN_ICACHE @@ -101,7 +101,7 @@ void __init bf53x_cache_init(void) #endif } -void __init bf53x_relocate_l1_mem(void) +void __init bfin_relocate_l1_mem(void) { unsigned long l1_code_length; unsigned long l1_data_a_length; @@ -860,7 +860,7 @@ void __init setup_arch(char **cmdline_p) != SAFE_USER_INSTRUCTION - FIXED_CODE_START); init_exception_vectors(); - bf53x_cache_init(); + bfin_cache_init(); } static int __init topology_init(void) diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 7cb21cfcbf2..eb9eef0e23b 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -141,7 +141,7 @@ ENTRY(__start) #endif /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */ - call _bf53x_relocate_l1_mem; + call _bfin_relocate_l1_mem; #ifdef CONFIG_BFIN_KERNEL_CLOCK call _start_dma_code; #endif -- cgit v1.2.3 From 7eb2c23f602ab35c5f4227bc87945a3c78a14150 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 8 Oct 2008 17:39:02 +0800 Subject: Blackfin arch: fix merge errors during 2.6.26 upgrade Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 9d936a3986c..a837bb6e7bb 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -375,14 +375,6 @@ config SCLK_DIV This can be between 1 and 15 System Clock = (PLL frequency) / (this setting) -config MAX_MEM_SIZE - int "Max SDRAM Memory Size in MBytes" - depends on !MPU - default 512 - help - This is the max memory size that the kernel will create CPLB - tables for. Your system will not be able to handle any more. - choice prompt "DDR SDRAM Chip Type" depends on BFIN_KERNEL_CLOCK @@ -396,6 +388,14 @@ config MEM_MT46V32M16_5B bool "MT46V32M16_5B" endchoice +config MAX_MEM_SIZE + int "Max SDRAM Memory Size in MBytes" + depends on !MPU + default 512 + help + This is the max memory size that the kernel will create CPLB + tables for. Your system will not be able to handle any more. + # # Max & Min Speeds for various Chips # @@ -462,8 +462,6 @@ config CYCLES_CLOCKSOURCE source kernel/time/Kconfig -comment "Memory Setup" - comment "Misc" choice -- cgit v1.2.3 From 9df10281e1c03b1c04d17f387bc59eb932c0bb87 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 8 Oct 2008 18:03:33 +0800 Subject: Blackfin arch: Use DTEST rather than DMA to poke at L1 SRAM during exception context Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin-global.h | 2 + arch/blackfin/kernel/traps.c | 3 +- arch/blackfin/mach-common/head.S | 10 ++ arch/blackfin/mm/Makefile | 2 +- arch/blackfin/mm/isram-driver.c | 201 ++++++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 arch/blackfin/mm/isram-driver.c (limited to 'arch') diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index 7ba70de66f2..e1f9cbd00a0 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h @@ -92,6 +92,8 @@ extern int sram_free(const void*); extern void *sram_alloc_with_lsl(size_t, unsigned long); extern int sram_free_with_lsl(const void*); +extern void *isram_memcpy(void *dest, const void *src, size_t n); + extern const char bfin_board_name[]; extern unsigned long bfin_sic_iwr[]; diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 0112ba407f6..89cff2c7e8b 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -40,7 +40,6 @@ #include #include #include -#include #ifdef CONFIG_KGDB # include @@ -632,7 +631,7 @@ bool get_instruction(unsigned short *val, unsigned short *address) #if L1_CODE_LENGTH != 0 if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) { - dma_memcpy(val, address, 2); + isram_memcpy(val, address, 2); return true; } #endif diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index eb9eef0e23b..3069df58072 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -68,6 +68,16 @@ ENTRY(__start) M2 = r0; M3 = r0; + /* + * Clear ITEST_COMMAND and DTEST_COMMAND registers, + * Leaving these as non-zero can confuse the emulator + */ + p0.L = LO(DTEST_COMMAND); + p0.H = HI(DTEST_COMMAND); + [p0] = R0; + [p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0; + CSYNC; + trace_buffer_init(p0,r0); P0 = R1; R0 = R1; diff --git a/arch/blackfin/mm/Makefile b/arch/blackfin/mm/Makefile index 81aacbc32d3..d489f894f4b 100644 --- a/arch/blackfin/mm/Makefile +++ b/arch/blackfin/mm/Makefile @@ -2,4 +2,4 @@ # arch/blackfin/mm/Makefile # -obj-y := sram-alloc.o init.o +obj-y := sram-alloc.o isram-driver.o init.o diff --git a/arch/blackfin/mm/isram-driver.c b/arch/blackfin/mm/isram-driver.c new file mode 100644 index 00000000000..22913e7a181 --- /dev/null +++ b/arch/blackfin/mm/isram-driver.c @@ -0,0 +1,201 @@ +/* + * Description: Instruction SRAM accessor functions for the Blackfin + * + * Copyright 2008 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include + +/* + * IMPORTANT WARNING ABOUT THESE FUNCTIONS + * + * The emulator will not function correctly if a write command is left in + * ITEST_COMMAND or DTEST_COMMAND AND access to cache memory is needed by + * the emulator. To avoid such problems, ensure that both ITEST_COMMAND + * and DTEST_COMMAND are zero when exiting these functions. + */ + + +/* + * On the Blackfin, L1 instruction sram (which operates at core speeds) can not + * be accessed by a normal core load, so we need to go through a few hoops to + * read/write it. + * To try to make it easier - we export a memcpy interface, where either src or + * dest can be in this special L1 memory area. + * The low level read/write functions should not be exposed to the rest of the + * kernel, since they operate on 64-bit data, and need specific address alignment + */ + +static DEFINE_SPINLOCK(dtest_lock); + +/* Takes a void pointer */ +#define IADDR2DTEST(x) \ + ({ unsigned long __addr = (unsigned long)(x); \ + (__addr & 0x47F8) | /* address bits 14 & 10:3 */ \ + (__addr & 0x0800) << 15 | /* address bit 11 */ \ + (__addr & 0x3000) << 4 | /* address bits 13:12 */ \ + (__addr & 0x8000) << 8 | /* address bit 15 */ \ + (0x1000004); /* isram access */ \ + }) + +/* Takes a pointer, and returns the offset (in bits) which things should be shifted */ +#define ADDR2OFFSET(x) ((((unsigned long)(x)) & 0x7) * 8) + +/* Takes a pointer, determines if it is the last byte in the isram 64-bit data type */ +#define ADDR2LAST(x) ((((unsigned long)x) & 0x7) == 0x7) + +static void isram_write(const void *addr, uint64_t data) +{ + uint32_t cmd; + unsigned long flags; + + if (addr >= (void *)(L1_CODE_START + L1_CODE_LENGTH)) + return; + + cmd = IADDR2DTEST(addr) | 1; /* write */ + + /* + * Writes to DTEST_DATA[0:1] need to be atomic with write to DTEST_COMMAND + * While in exception context - atomicity is guaranteed or double fault + */ + spin_lock_irqsave(&dtest_lock, flags); + + bfin_write_DTEST_DATA0(data & 0xFFFFFFFF); + bfin_write_DTEST_DATA1(data >> 32); + + /* use the builtin, since interrupts are already turned off */ + __builtin_bfin_csync(); + bfin_write_DTEST_COMMAND(cmd); + __builtin_bfin_csync(); + + bfin_write_DTEST_COMMAND(0); + __builtin_bfin_csync(); + + spin_unlock_irqrestore(&dtest_lock, flags); +} + +static uint64_t isram_read(const void *addr) +{ + uint32_t cmd; + unsigned long flags; + uint64_t ret; + + if (addr > (void *)(L1_CODE_START + L1_CODE_LENGTH)) + return 0; + + cmd = IADDR2DTEST(addr) | 0; /* read */ + + /* + * Reads of DTEST_DATA[0:1] need to be atomic with write to DTEST_COMMAND + * While in exception context - atomicity is guaranteed or double fault + */ + spin_lock_irqsave(&dtest_lock, flags); + /* use the builtin, since interrupts are already turned off */ + __builtin_bfin_csync(); + bfin_write_DTEST_COMMAND(cmd); + __builtin_bfin_csync(); + ret = bfin_read_DTEST_DATA0() | ((uint64_t)bfin_read_DTEST_DATA1() << 32); + + bfin_write_DTEST_COMMAND(0); + __builtin_bfin_csync(); + spin_unlock_irqrestore(&dtest_lock, flags); + + return ret; +} + +static bool isram_check_addr(const void *addr, size_t n) +{ + if ((addr >= (void *)L1_CODE_START) && + (addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))) { + if ((addr + n) >= (void *)(L1_CODE_START + L1_CODE_LENGTH)) { + show_stack(NULL, NULL); + printk(KERN_ERR "isram_memcpy: copy involving %p length " + "(%zu) too long\n", addr, n); + } + return true; + } + return false; +} + +/* + * The isram_memcpy() function copies n bytes from memory area src to memory area dest. + * The isram_memcpy() function returns a pointer to dest. + * Either dest or src can be in L1 instruction sram. + */ +void *isram_memcpy(void *dest, const void *src, size_t n) +{ + uint64_t data_in = 0, data_out = 0; + size_t count; + bool dest_in_l1, src_in_l1, need_data, put_data; + unsigned char byte, *src_byte, *dest_byte; + + src_byte = (unsigned char *)src; + dest_byte = (unsigned char *)dest; + + dest_in_l1 = isram_check_addr(dest, n); + src_in_l1 = isram_check_addr(src, n); + + need_data = true; + put_data = true; + for (count = 0; count < n; count++) { + if (src_in_l1) { + if (need_data) { + data_in = isram_read(src + count); + need_data = false; + } + + if (ADDR2LAST(src + count)) + need_data = true; + + byte = (unsigned char)((data_in >> ADDR2OFFSET(src + count)) & 0xff); + + } else { + /* src is in L2 or L3 - so just dereference*/ + byte = src_byte[count]; + } + + if (dest_in_l1) { + if (put_data) { + data_out = isram_read(dest + count); + put_data = false; + } + + data_out &= ~((uint64_t)0xff << ADDR2OFFSET(dest + count)); + data_out |= ((uint64_t)byte << ADDR2OFFSET(dest + count)); + + if (ADDR2LAST(dest + count)) { + put_data = true; + isram_write(dest + count, data_out); + } + } else { + /* dest in L2 or L3 - so just dereference */ + dest_byte[count] = byte; + } + } + + /* make sure we dump the last byte if necessary */ + if (dest_in_l1 && !put_data) + isram_write(dest + count, data_out); + + return dest; +} +EXPORT_SYMBOL(isram_memcpy); + -- cgit v1.2.3 From bfd15117aeafcc42033cf5179cc15f4bd8bce957 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 8 Oct 2008 18:02:44 +0800 Subject: Blackfin arch: Not call generic set_irq_handler() in bfin_gpio_irq_type() due to spinlock recursion Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index f65b3a13a8c..34e8a726ffd 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -364,6 +364,14 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, } #endif /* BF537_GENERIC_ERROR_INT_DEMUX */ +static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) +{ + struct irq_desc *desc = irq_desc + irq; + /* May not call generic set_irq_handler() due to spinlock + recursion. */ + desc->handle_irq = handle; +} + #if !defined(CONFIG_BF54x) static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; @@ -476,9 +484,9 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) SSYNC(); if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - set_irq_handler(irq, handle_edge_irq); + bfin_set_irq_handler(irq, handle_edge_irq); else - set_irq_handler(irq, handle_level_irq); + bfin_set_irq_handler(irq, handle_level_irq); return 0; } @@ -808,10 +816,10 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { pint[bank]->edge_set = pintbit; - set_irq_handler(irq, handle_edge_irq); + bfin_set_irq_handler(irq, handle_edge_irq); } else { pint[bank]->edge_clear = pintbit; - set_irq_handler(irq, handle_level_irq); + bfin_set_irq_handler(irq, handle_level_irq); } SSYNC(); -- cgit v1.2.3 From 520bab804e3fe4868890980a55fe785f1b8a55e5 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 18 Jun 2008 15:36:32 +0200 Subject: avr32: Implement {read,write}[bwl]_be Signed-off-by: Haavard Skinnemoen --- arch/avr32/include/asm/io.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h index a520f77ead9..22c97ef9220 100644 --- a/arch/avr32/include/asm/io.h +++ b/arch/avr32/include/asm/io.h @@ -160,6 +160,14 @@ BUILDIO_IOPORT(l, u32) #define readw_relaxed readw #define readl_relaxed readl +#define readb_be __raw_readb +#define readw_be __raw_readw +#define readl_be __raw_readl + +#define writeb_be __raw_writeb +#define writew_be __raw_writew +#define writel_be __raw_writel + #define __BUILD_MEMORY_STRING(bwl, type) \ static inline void writes##bwl(volatile void __iomem *addr, \ const void *data, unsigned int count) \ -- cgit v1.2.3 From b3bc2c5562f06ca34b30f61c5714e96490946c81 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 28 Jul 2008 13:05:19 +0200 Subject: avr32: Minor pm_power_off cleanup Include to see the declaration of pm_power_off, and remove unneeded NULL initializer. Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/process.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 2c08ac992ac..134d5302b6d 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -20,7 +21,7 @@ #include -void (*pm_power_off)(void) = NULL; +void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); /* -- cgit v1.2.3 From 8806048878fce541afe1d72cd2320f092519f90a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 8 Oct 2008 19:14:33 +0100 Subject: [MIPS] Sibyte: Register PIO PATA device only for Swarm and Litte Sur Symbol name spaghetti which is too complicated to cleanup on this stage of the release cycle breaks the build on BCM1480 platforms. Signed-off-by: Ralf Baechle --- arch/mips/sibyte/swarm/platform.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/mips/sibyte/swarm/platform.c b/arch/mips/sibyte/swarm/platform.c index dd0e5b9b64e..54847fe1e56 100644 --- a/arch/mips/sibyte/swarm/platform.c +++ b/arch/mips/sibyte/swarm/platform.c @@ -9,6 +9,8 @@ #include #include +#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) + #define DRV_NAME "pata-swarm" #define SWARM_IDE_SHIFT 5 @@ -79,3 +81,5 @@ static int __init swarm_pata_init(void) } device_initcall(swarm_pata_init); + +#endif /* defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) */ -- cgit v1.2.3 From 6fbc779c03591ee536fef9efb7d7e20f281d0b5c Mon Sep 17 00:00:00 2001 From: Victor Gallardo Date: Thu, 18 Sep 2008 12:41:26 +0000 Subject: ibm_newemac: Fix EMAC soft reset on 460EX/GT This patch fixes EMAC soft reset on 460EX/GT when no external clock is available. Signed-off-by: Victor Gallardo Signed-off-by: David S. Miller --- arch/powerpc/include/asm/dcr-regs.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/include/asm/dcr-regs.h b/arch/powerpc/include/asm/dcr-regs.h index 29b0ecef980..f15296cf359 100644 --- a/arch/powerpc/include/asm/dcr-regs.h +++ b/arch/powerpc/include/asm/dcr-regs.h @@ -68,6 +68,10 @@ #define SDR0_UART3 0x0123 #define SDR0_CUST0 0x4000 +/* SDRs (460EX/460GT) */ +#define SDR0_ETH_CFG 0x4103 +#define SDR0_ETH_CFG_ECS 0x00000100 /* EMAC int clk source */ + /* * All those DCR register addresses are offsets from the base address * for the SRAM0 controller (e.g. 0x20 on 440GX). The base address is -- cgit v1.2.3 From 18ee49ddb0d242ed1d0e273038d5e4f6de7379d3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 1 Oct 2008 15:41:33 +0000 Subject: phylib: rename mii_bus::dev to mii_bus::parent In preparation of giving mii_bus objects a device tree presence of their own, rename struct mii_bus's ->dev argument to ->parent, since having a 'struct device *dev' that points to our parent device conflicts with introducing a 'struct device dev' representing our own device. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller Acked-by: Andy Fleming --- arch/powerpc/platforms/82xx/ep8248e.c | 2 +- arch/powerpc/platforms/pasemi/gpio_mdio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index d5770fdf7f0..0eb6d7f6224 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c @@ -137,7 +137,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev, bus->irq[i] = -1; bus->name = "ep8248e-mdio-bitbang"; - bus->dev = &ofdev->dev; + bus->parent = &ofdev->dev; snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start); return mdiobus_register(bus); diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index ab6955412ba..798c7abe160 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -272,7 +272,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, prop = of_get_property(np, "mdio-pin", NULL); priv->mdio_pin = *prop; - new_bus->dev = dev; + new_bus->parent = dev; dev_set_drvdata(dev, new_bus); err = mdiobus_register(new_bus); -- cgit v1.2.3 From 3343c1d4482b27a444e76bf53d16df4a6f30b873 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 9 Oct 2008 11:11:11 +0800 Subject: Blackfin arch: Fix BUG: anomaly_threshold is used with ANOMALY_05000363 Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h | 2 +- arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h index ebf592b59aa..993464ee93c 100644 --- a/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h +++ b/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h @@ -83,7 +83,7 @@ struct bfin_serial_port { unsigned int rx_dma_channel; struct work_struct tx_dma_workqueue; #else -# if ANOMALY_05000230 +# if ANOMALY_05000363 unsigned int anomaly_threshold; # endif #endif diff --git a/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h index 8aa02780e64..8552a67654c 100644 --- a/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h +++ b/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h @@ -83,7 +83,7 @@ struct bfin_serial_port { unsigned int rx_dma_channel; struct work_struct tx_dma_workqueue; #else -# if ANOMALY_05000230 +# if ANOMALY_05000363 unsigned int anomaly_threshold; # endif #endif -- cgit v1.2.3 From 202d7bd95cf5ca36199e5777c961eae62a74667c Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Thu, 9 Oct 2008 11:59:46 +0800 Subject: Blackfin arch: Make sure we program the correct values in only when necessary for MUSB driver Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf527/include/mach/anomaly.h | 2 ++ arch/blackfin/mach-bf548/include/mach/anomaly.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h index b7b166f4f06..dc26912430e 100644 --- a/arch/blackfin/mach-bf527/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h @@ -37,6 +37,8 @@ #define ANOMALY_05000342 (1) /* USB Calibration Value Is Not Initialized */ #define ANOMALY_05000346 (1) +/* USB Calibration Value to use */ +#define ANOMALY_05000346_value 0xE510 /* Preboot Routine Incorrectly Alters Reset Value of USB Register */ #define ANOMALY_05000347 (1) /* Security Features Are Not Functional */ diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h index 3ad59655881..d02cd803828 100644 --- a/arch/blackfin/mach-bf548/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h @@ -61,6 +61,8 @@ #define ANOMALY_05000344 (__SILICON_REVISION__ < 1) /* USB Calibration Value Is Not Intialized */ #define ANOMALY_05000346 (__SILICON_REVISION__ < 1) +/* USB Calibration Value to use */ +#define ANOMALY_05000346_value 0x5411 /* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */ #define ANOMALY_05000347 (__SILICON_REVISION__ < 1) /* Data Lost when Core Reads SDH Data FIFO */ -- cgit v1.2.3 From cd88b4dca85d0e46db3d0aadd748037a10ebbfc1 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 12:03:22 +0800 Subject: Blackfin arch: BF561 is supported, no longer a work in progress Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index a837bb6e7bb..423ecfb9e91 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -162,7 +162,7 @@ config BF549 config BF561 bool "BF561" help - Not Supported Yet - Work in progress - BF561 Processor Support. + BF561 Processor Support. endchoice -- cgit v1.2.3 From 46ce0d9a361b7b3de9a1c8dce1f2b636e395ab9e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 12:05:31 +0800 Subject: Blackfin arch: fix default silicon rev selection so it works for all supported parts Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 423ecfb9e91..b5027f575e0 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -168,10 +168,9 @@ endchoice choice prompt "Silicon Rev" - default BF_REV_0_1 if BF527 - default BF_REV_0_2 if BF537 - default BF_REV_0_3 if BF533 - default BF_REV_0_0 if BF549 + default BF_REV_0_1 if (BF52x || BF54x) + default BF_REV_0_2 if (BF534 || BF536 || BF537) + default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF561) config BF_REV_0_0 bool "0.0" -- cgit v1.2.3 From 49f7253cc9a5002c3f2aef4ab96df62204ac7052 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 12:06:27 +0800 Subject: Blackfin arch: add support for BF52x-0.2, BF533-0.6, and BF54x-0.2 Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 6 +++++- arch/blackfin/Makefile | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index b5027f575e0..554ac5827c1 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -182,7 +182,7 @@ config BF_REV_0_1 config BF_REV_0_2 bool "0.2" - depends on (BF537 || BF536 || BF534) + depends on (BF52x || BF537 || BF536 || BF534 || BF54x) config BF_REV_0_3 bool "0.3" @@ -196,6 +196,10 @@ config BF_REV_0_5 bool "0.5" depends on (BF561 || BF533 || BF532 || BF531) +config BF_REV_0_6 + bool "0.6" + depends on (BF533 || BF532 || BF531) + config BF_REV_ANY bool "any" diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index eac0533d6e4..6bf50977850 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -67,6 +67,7 @@ rev-$(CONFIG_BF_REV_0_2) := 0.2 rev-$(CONFIG_BF_REV_0_3) := 0.3 rev-$(CONFIG_BF_REV_0_4) := 0.4 rev-$(CONFIG_BF_REV_0_5) := 0.5 +rev-$(CONFIG_BF_REV_0_6) := 0.6 rev-$(CONFIG_BF_REV_NONE) := none rev-$(CONFIG_BF_REV_ANY) := any -- cgit v1.2.3 From 5e9e7687cbc016ac36b6825f79d78213319331d9 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 9 Oct 2008 12:31:03 +0800 Subject: Blackfin arch: Fix BUG -- BF533 + 0.5 silicon + MPU + UART PIO -> crash Apply ANOMALY_05000283 & ANOMALY_05000315 Workaround also to the EXCEPTION path. Cover evt_ivhw also with ANOMALY_05000315 The Workaround needs to be prior to accesses (either read or write) to any system MMR. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 18 ++++++++++++++++++ arch/blackfin/mach-common/interrupt.S | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 5a219b228de..76c42d3b5e8 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -484,6 +484,15 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ [--sp] = ASTAT; [--sp] = (R7:6,P5:4); +#if ANOMALY_05000283 || ANOMALY_05000315 + cc = r7 == r7; + p5.h = HI(CHIPID); + p5.l = LO(CHIPID); + if cc jump 1f; + r7.l = W[p5]; +1: +#endif + #ifdef CONFIG_DEBUG_DOUBLEFAULT /* * Save these registers, as they are only valid in exception context @@ -1020,6 +1029,15 @@ ENTRY(_early_trap) SAVE_ALL_SYS trace_buffer_stop(p0,r0); +#if ANOMALY_05000283 || ANOMALY_05000315 + cc = r5 == r5; + p4.h = HI(CHIPID); + p4.l = LO(CHIPID); + if cc jump 1f; + r5.l = W[p4]; +1: +#endif + /* Turn caches off, to ensure we don't get double exceptions */ P4.L = LO(IMEM_CONTROL); diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index b27e59d3240..647f0f52291 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -143,7 +143,7 @@ ENTRY(_evt_ivhw) fp = 0; #endif -#if ANOMALY_05000283 +#if ANOMALY_05000283 || ANOMALY_05000315 cc = r7 == r7; p5.h = HI(CHIPID); p5.l = LO(CHIPID); -- cgit v1.2.3 From 27707d3e43e3a9c53e75cd7769f3ef74b1d56625 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 9 Oct 2008 14:04:41 +0800 Subject: Blackfin arch: Fix bug - kernel build with config kernel debugging with remote gdb fails Add some comment and fix duplicated VEC_EXCPT02 Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/kernel/traps.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 89cff2c7e8b..1a3c4daf557 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -284,15 +284,6 @@ asmlinkage void trap_c(struct pt_regs *fp) return; else break; -#ifdef CONFIG_KGDB - case VEC_EXCPT02 : /* gdb connection */ - info.si_code = TRAP_ILLTRAP; - sig = SIGTRAP; - CHK_DEBUGGER_TRAP(); - return; -#else - /* 0x02 - User Defined, Caught by default */ -#endif /* 0x03 - User Defined, userspace stack overflow */ case VEC_EXCPT03: info.si_code = SEGV_STACKFLOW; @@ -300,6 +291,14 @@ asmlinkage void trap_c(struct pt_regs *fp) printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; + /* 0x02 - KGDB initial connection and break signal trap */ + case VEC_EXCPT02: +#ifdef CONFIG_KGDB + info.si_code = TRAP_ILLTRAP; + sig = SIGTRAP; + CHK_DEBUGGER_TRAP(); + return; +#endif /* 0x04 - User Defined */ /* 0x05 - User Defined */ /* 0x06 - User Defined */ @@ -312,11 +311,9 @@ asmlinkage void trap_c(struct pt_regs *fp) /* 0x0D - User Defined */ /* 0x0E - User Defined */ /* 0x0F - User Defined */ - /* - * If we got here, it is most likely that someone was trying to use a + /* If we got here, it is most likely that someone was trying to use a * custom exception handler, and it is not actually installed properly */ - case VEC_EXCPT02: case VEC_EXCPT04 ... VEC_EXCPT15: info.si_code = ILL_ILLPARAOP; sig = SIGILL; -- cgit v1.2.3 From 8606801b0361e0f8520892c9bf524df89c35e690 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 9 Oct 2008 13:55:33 +0800 Subject: Blackfin arch: flags of UART3 mem resource is missing Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/boards/cm_bf548.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c index c5609ff805f..24192aaa927 100644 --- a/arch/blackfin/mach-bf548/boards/cm_bf548.c +++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c @@ -172,6 +172,7 @@ static struct resource bfin_uart_resources[] = { { .start = 0xFFC03100, .end = 0xFFC031FF, + .flags = IORESOURCE_MEM, }, #endif }; -- cgit v1.2.3 From f099f39acf7575eff3dee3c562cec4e592876c33 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 9 Oct 2008 14:11:57 +0800 Subject: Blackfin arch: Make L2 SRAM cacheable Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 7 +++++++ arch/blackfin/include/asm/cplb.h | 8 +++++++- arch/blackfin/kernel/cplb-mpu/cplbinit.c | 10 ++++++++++ arch/blackfin/kernel/cplb-nompu/cplbinit.c | 4 ++-- 4 files changed, 26 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 554ac5827c1..10c97efbd91 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -772,6 +772,13 @@ config BFIN_WT endchoice +config BFIN_L2_CACHEABLE + bool "Cache L2 SRAM" + depends on (BFIN_DCACHE || BFIN_ICACHE) && (BF54x || BF561) + default n + help + Select to make L2 SRAM cacheable in L1 data and instruction cache. + config MPU bool "Enable the memory protection unit (EXPERIMENTAL)" default n diff --git a/arch/blackfin/include/asm/cplb.h b/arch/blackfin/include/asm/cplb.h index 05d6f05fb74..9e8b4035fce 100644 --- a/arch/blackfin/include/asm/cplb.h +++ b/arch/blackfin/include/asm/cplb.h @@ -55,7 +55,13 @@ #endif #define L1_DMEMORY (CPLB_LOCK | CPLB_COMMON) -#define L2_MEMORY (CPLB_COMMON) +#ifdef CONFIG_BFIN_L2_CACHEABLE +#define L2_IMEMORY (SDRAM_IGENERIC) +#define L2_DMEMORY (SDRAM_DGENERIC) +#else +#define L2_IMEMORY (CPLB_COMMON) +#define L2_DMEMORY (CPLB_COMMON) +#endif #define SDRAM_DNON_CHBL (CPLB_COMMON) #define SDRAM_EBIU (CPLB_COMMON) #define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY) diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index d4257d0ad6a..55af729f849 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -83,8 +83,18 @@ void __init generate_cplb_tables(void) dcplb_tbl[i_d].addr = L1_DATA_A_START; dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB; #endif +#if L1_CODE_LENGTH > 0 icplb_tbl[i_i].addr = L1_CODE_START; icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; +#endif + + /* Cover L2 memory */ +#if L2_LENGTH > 0 + dcplb_tbl[i_d].addr = L2_START; + dcplb_tbl[i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB; + icplb_tbl[i_i].addr = L2_START; + icplb_tbl[i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB; +#endif first_mask_dcplb = i_d; first_switched_dcplb = i_d + (1 << page_mask_order); diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c index 2c45c16c352..301252e8444 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c @@ -168,8 +168,8 @@ static struct cplb_desc cplb_data[] = { .end = L2_START + L2_LENGTH, .psize = SIZE_1M, .attr = SWITCH_T | I_CPLB | D_CPLB, - .i_conf = L2_MEMORY, - .d_conf = L2_MEMORY, + .i_conf = L2_IMEMORY, + .d_conf = L2_DMEMORY, .valid = (L2_LENGTH > 0), .name = "L2 Memory", }, -- cgit v1.2.3 From dd4354fa51f6379fb3ac98ba9377ca5895f50497 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Thu, 9 Oct 2008 14:17:47 +0800 Subject: Blackfin arch: fix define error in BF561 memory map macros Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf561/include/mach/mem_map.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf561/include/mach/mem_map.h b/arch/blackfin/mach-bf561/include/mach/mem_map.h index 9d6674ad1e5..f1d4c0637bd 100644 --- a/arch/blackfin/mach-bf561/include/mach/mem_map.h +++ b/arch/blackfin/mach-bf561/include/mach/mem_map.h @@ -35,14 +35,14 @@ /* Memory Map for ADSP-BF561 processors */ #ifdef CONFIG_BF561 -#define COREA_L1_CODE_START 0xFFA00000 +#define COREA_L1_CODE_START 0xFFA00000 #define COREA_L1_DATA_A_START 0xFF800000 #define COREA_L1_DATA_B_START 0xFF900000 -#define COREB_L1_CODE_START 0xFF600000 -#define COREB_L1_DATA_A_START 0xFF500000 -#define COREB_L1_DATA_B_START 0xFF400000 +#define COREB_L1_CODE_START 0xFF600000 +#define COREB_L1_DATA_A_START 0xFF400000 +#define COREB_L1_DATA_B_START 0xFF500000 -#define L1_CODE_START COREA_L1_CODE_START +#define L1_CODE_START COREA_L1_CODE_START #define L1_DATA_A_START COREA_L1_DATA_A_START #define L1_DATA_B_START COREA_L1_DATA_B_START -- cgit v1.2.3 From dabaad5b90dec6909c984d95330f6f41c325f9a8 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:17:36 +0800 Subject: Blackfin arch: fix bug -- PTRACE_PEEKDATA does not seem to work which breaks umoven() in strace Don't add arbitrary offset when peeking at data Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 66 ++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index bf1a51d8e60..9ce80d05e2c 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -46,7 +46,6 @@ #include #include -#define MAX_SHARED_LIBS 3 #define TEXT_OFFSET 0 /* * does not yet catch signals sent when the child dies. @@ -192,14 +191,12 @@ void ptrace_disable(struct task_struct *child) long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; - int add = 0; unsigned long __user *datap = (unsigned long __user *)data; switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKDATA: pr_debug("ptrace: PEEKDATA\n"); - add = MAX_SHARED_LIBS * 4; /* space between text and data */ /* fall through */ case PTRACE_PEEKTEXT: /* read word at location addr. */ { @@ -207,39 +204,38 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int copied; ret = -EIO; - pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + add %d %ld\n", addr, add, - sizeof(data)); - if (is_user_addr_valid(child, addr + add, sizeof(tmp)) < 0) + pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data)); + if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) break; pr_debug("ptrace: user address is valid\n"); #if L1_CODE_LENGTH != 0 - if (addr + add >= L1_CODE_START - && addr + add + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { - safe_dma_memcpy (&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= L1_CODE_START + && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { + safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else #endif #if L1_DATA_A_LENGTH != 0 - if (addr + add >= L1_DATA_A_START - && addr + add + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { - memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= L1_DATA_A_START + && addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { + memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else #endif #if L1_DATA_B_LENGTH != 0 - if (addr + add >= L1_DATA_B_START - && addr + add + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { - memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= L1_DATA_B_START + && addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { + memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else #endif - if (addr + add >= FIXED_CODE_START - && addr + add + sizeof(tmp) <= FIXED_CODE_END) { - memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= FIXED_CODE_START + && addr + sizeof(tmp) <= FIXED_CODE_END) { + memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else - copied = access_process_vm(child, addr + add, &tmp, + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); if (copied != sizeof(tmp)) @@ -291,39 +287,39 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int copied; ret = -EIO; - pr_debug("ptrace: POKETEXT at addr 0x%08lx + add %d %ld bytes %lx\n", - addr, add, sizeof(data), data); - if (is_user_addr_valid(child, addr + add, sizeof(data)) < 0) + pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n", + addr, sizeof(data), data); + if (is_user_addr_valid(child, addr, sizeof(data)) < 0) break; pr_debug("ptrace: user address is valid\n"); #if L1_CODE_LENGTH != 0 - if (addr + add >= L1_CODE_START - && addr + add + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { - safe_dma_memcpy ((void *)(addr + add), &data, sizeof(data)); + if (addr >= L1_CODE_START + && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { + safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else #endif #if L1_DATA_A_LENGTH != 0 - if (addr + add >= L1_DATA_A_START - && addr + add + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { - memcpy((void *)(addr + add), &data, sizeof(data)); + if (addr >= L1_DATA_A_START + && addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { + memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else #endif #if L1_DATA_B_LENGTH != 0 - if (addr + add >= L1_DATA_B_START - && addr + add + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { - memcpy((void *)(addr + add), &data, sizeof(data)); + if (addr >= L1_DATA_B_START + && addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { + memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else #endif - if (addr + add >= FIXED_CODE_START - && addr + add + sizeof(data) <= FIXED_CODE_END) { - memcpy((void *)(addr + add), &data, sizeof(data)); + if (addr >= FIXED_CODE_START + && addr + sizeof(data) <= FIXED_CODE_END) { + memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else - copied = access_process_vm(child, addr + add, &data, + copied = access_process_vm(child, addr, &data, sizeof(data), 1); pr_debug("ptrace: copied size %d\n", copied); if (copied != sizeof(data)) -- cgit v1.2.3 From d3ab3a62f57f3aaeed5a7e2ef136937ffd16448a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:19:50 +0800 Subject: Blackfin arch: ptrace - cleanup debug messages and style Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 9ce80d05e2c..b3f4ac792cf 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -280,7 +280,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* when I and D space are separate, this will have to be fixed. */ case PTRACE_POKEDATA: - printk(KERN_NOTICE "ptrace: PTRACE_PEEKDATA\n"); + pr_debug("ptrace: PTRACE_PEEKDATA\n"); /* fall through */ case PTRACE_POKETEXT: /* write the word at location addr. */ { @@ -351,7 +351,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) { /* restart after signal. */ long tmp; - pr_debug("ptrace_cont\n"); + pr_debug("ptrace: syscall/cont\n"); ret = -EIO; if (!valid_signal(data)) @@ -365,7 +365,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); put_reg(child, PT_SYSCFG, tmp); - pr_debug("before wake_up_process\n"); + pr_debug("ptrace: before wake_up_process\n"); wake_up_process(child); ret = 0; break; @@ -394,7 +394,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) { /* set the trap flag. */ long tmp; - pr_debug("single step\n"); + pr_debug("ptrace: single step\n"); ret = -EIO; if (!valid_signal(data)) break; @@ -411,21 +411,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } case PTRACE_GETREGS: - { - - /* Get all gp regs from the child. */ - ret = ptrace_getregs(child, datap); - break; - } + /* Get all gp regs from the child. */ + ret = ptrace_getregs(child, datap); + break; case PTRACE_SETREGS: - { - printk(KERN_NOTICE - "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n"); - /* Set all gp regs in the child. */ - ret = 0; - break; - } + printk(KERN_WARNING "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n"); + /* Set all gp regs in the child. */ + ret = 0; + break; + default: ret = ptrace_request(child, request, addr, data); break; @@ -436,7 +431,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) asmlinkage void syscall_trace(void) { - if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; -- cgit v1.2.3 From cb4c173d94e90f9d8c7b621d1a8dfc8b741874a2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:21:05 +0800 Subject: Blackfin arch: use existing ptrace_disable() func to clear TRACE_BITS and create the opposite ptrace_enable() Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 87 ++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 50 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index b3f4ac792cf..e8172eece04 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -175,6 +175,13 @@ static inline int is_user_addr_valid(struct task_struct *child, return -EIO; } +void ptrace_enable(struct task_struct *child) +{ + unsigned long tmp; + tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS); + put_reg(child, PT_SYSCFG, tmp); +} + /* * Called by kernel/ptrace.c when detaching.. * @@ -347,29 +354,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: - { /* restart after signal. */ - long tmp; - - pr_debug("ptrace: syscall/cont\n"); + case PTRACE_CONT: /* restart after signal. */ + pr_debug("ptrace: syscall/cont\n"); - ret = -EIO; - if (!valid_signal(data)) - break; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - - child->exit_code = data; - /* make sure the single step bit is not set. */ - tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); - put_reg(child, PT_SYSCFG, tmp); - pr_debug("ptrace: before wake_up_process\n"); - wake_up_process(child); - ret = 0; + ret = -EIO; + if (!valid_signal(data)) break; - } + if (request == PTRACE_SYSCALL) + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->exit_code = data; + ptrace_disable(child); + pr_debug("ptrace: before wake_up_process\n"); + wake_up_process(child); + ret = 0; + break; /* * make the child exit. Best I can do is send it a sigkill. @@ -377,38 +377,25 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * exit. */ case PTRACE_KILL: - { - long tmp; - ret = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - break; - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); - put_reg(child, PT_SYSCFG, tmp); - wake_up_process(child); + ret = 0; + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; - } - - case PTRACE_SINGLESTEP: - { /* set the trap flag. */ - long tmp; - - pr_debug("ptrace: single step\n"); - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - - tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS); - put_reg(child, PT_SYSCFG, tmp); + child->exit_code = SIGKILL; + ptrace_disable(child); + wake_up_process(child); + break; - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; + case PTRACE_SINGLESTEP: /* set the trap flag. */ + pr_debug("ptrace: single step\n"); + ret = -EIO; + if (!valid_signal(data)) break; - } + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + ptrace_enable(child); + child->exit_code = data; + wake_up_process(child); + ret = 0; + break; case PTRACE_GETREGS: /* Get all gp regs from the child. */ -- cgit v1.2.3 From f5a817e3f707759882e423060badd2f2e52b66a4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:22:56 +0800 Subject: Blackfin arch: ptrace - make sure PT_ORIG_R0 and PT_ORIG_P0 offsets are declared Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/ptrace.h | 2 ++ arch/blackfin/kernel/asm-offsets.c | 1 + 2 files changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h index a45a80e54ad..e3f086dc726 100644 --- a/arch/blackfin/include/asm/ptrace.h +++ b/arch/blackfin/include/asm/ptrace.h @@ -158,6 +158,8 @@ extern void show_regs(struct pt_regs *); #define PT_SEQSTAT 8 #define PT_IPEND 4 +#define PT_ORIG_R0 208 +#define PT_ORIG_P0 212 #define PT_SYSCFG 216 #define PT_TEXT_ADDR 220 #define PT_TEXT_END_ADDR 224 diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index 881afe9082c..9bb85dd5ccb 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c @@ -60,6 +60,7 @@ int main(void) DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); /* offsets into the pt_regs */ + DEFINE(PT_ORIG_R0, offsetof(struct pt_regs, orig_r0)); DEFINE(PT_ORIG_P0, offsetof(struct pt_regs, orig_p0)); DEFINE(PT_ORIG_PC, offsetof(struct pt_regs, orig_pc)); DEFINE(PT_R0, offsetof(struct pt_regs, r0)); -- cgit v1.2.3 From 47664c1f86c833c4b6398885fdb2b80fc4945c6a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:32:18 +0800 Subject: Blackfin arch: give sys_strace proper entry markings a global _sys_trace will cause the assembler to fail, it should be fixed in toolchain side firstly. Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 76c42d3b5e8..c13fa8da28c 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -704,6 +704,9 @@ ENTRY(_system_call) rts; ENDPROC(_system_call) +/* Do not mark as ENTRY() to avoid error in assembler ... + * this symbol need not be global anyways, so ... + */ _sys_trace: call _syscall_trace; -- cgit v1.2.3 From 55f2feae3a1e075d9b4b0e73a6024f3e25717878 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Thu, 9 Oct 2008 15:37:47 +0800 Subject: Blackfin arch: correct icache size in show_cpuinfo(), let c_start() return proper pointer Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index ea4f60978c6..e9054e0b455 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -1000,7 +1000,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "cpu family\t: 0x%x\n" "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" "stepping\t: %d\n", - 0, + *(unsigned int *)v, vendor, (bfin_read_CHIPID() & CHIPID_FAMILY), cpu, cclk/1000000, sclk/1000000, @@ -1048,7 +1048,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE)) dcache_size = 0; - if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) == (IMC | ENICPLB)) + if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) != (IMC | ENICPLB)) icache_size = 0; seq_printf(m, "cache size\t: %d KB(L1 icache) " @@ -1137,12 +1137,18 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { - return *pos < NR_CPUS ? ((void *)0x12345678) : NULL; + if (*pos == 0) + *pos = first_cpu(cpu_online_map); + if (*pos >= num_online_cpus()) + return NULL; + + return pos; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - ++*pos; + *pos = next_cpu(*pos, cpu_online_map); + return c_start(m, pos); } -- cgit v1.2.3 From 1d5ff7e27d2ca30cd3f61afd353b03dd67330818 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Thu, 9 Oct 2008 17:06:32 +0800 Subject: Blackfin arch: Fix bug - HW Errors never recover on BF548 The kernel does not properly clear the EBIU Error Master (EBIU_ERRMST) Register on BF548, which causes the kernel to panic. We need to make sure that we clear the EBIU_ERRMST (necessary on BF54x) Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/traps.c | 15 +++++++++++++-- arch/blackfin/mach-common/interrupt.S | 9 +++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 1a3c4daf557..709c247b701 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -1025,8 +1025,19 @@ void show_regs(struct pt_regs *fp) printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", (long)fp->seqstat, fp->ipend, fp->syscfg); - printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", - (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); + if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { + printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", + (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); +#ifdef EBIU_ERRMST + /* If the error was from the EBIU, print it out */ + if (bfin_read_EBIU_ERRMST() & CORE_ERROR) { + printk(KERN_NOTICE " EBIU Error Reason : 0x%04x\n", + bfin_read_EBIU_ERRMST()); + printk(KERN_NOTICE " EBIU Error Address : 0x%08x\n", + bfin_read_EBIU_ERRADD()); + } +#endif + } printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", fp->seqstat & SEQSTAT_EXCAUSE); for (i = 6; i <= 15 ; i++) { diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 647f0f52291..4a2ec7a9675 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -179,7 +179,16 @@ ENTRY(_evt_ivhw) call _trap_c; SP += 12; +#ifdef EBIU_ERRMST + /* make sure EBIU_ERRMST is clear */ + p0.l = LO(EBIU_ERRMST); + p0.h = HI(EBIU_ERRMST); + r0.l = (CORE_ERROR | CORE_MERROR); + w[p0] = r0.l; +#endif + call _ret_from_exception; + .Lcommon_restore_all_sys: RESTORE_ALL_SYS rti; -- cgit v1.2.3 From 6c3fc69a173868c0a3c20bc1bba5ede463b5029c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 17:13:39 +0800 Subject: Blackfin arch: avoid using actual config name in comment avoid using actual config name in comment as a text search is done to see what files need to be rebuilt Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin-global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index e1f9cbd00a0..f842ea3bfc1 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h @@ -106,7 +106,7 @@ extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[], _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[], _ebss_l2[], _l2_lma_start[]; -/* only used when CONFIG_MTD_UCLINUX */ +/* only used when MTD_UCLINUX */ extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size; #ifdef CONFIG_BFIN_ICACHE_LOCK -- cgit v1.2.3 From 664d0403f96ff5f4fb43a4b3a54b5642589c57d2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 17:28:36 +0800 Subject: Blackfin arch: fix end address for parallel flash and increase kernel partition size to 4meg Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/boards/ezkit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 7c08b9f1838..5288187a3ac 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -462,7 +462,7 @@ static struct mtd_partition ezkit_partitions[] = { .offset = 0, }, { .name = "linux kernel(nor)", - .size = 0x1C0000, + .size = 0x400000, .offset = MTDPART_OFS_APPEND, }, { .name = "file system(nor)", @@ -479,7 +479,7 @@ static struct physmap_flash_data ezkit_flash_data = { static struct resource ezkit_flash_resource = { .start = 0x20000000, - .end = 0x20ffffff, + .end = 0x21ffffff, .flags = IORESOURCE_MEM, }; -- cgit v1.2.3 From 0c0497c257c12c9ecb8825490a339bfce8a0532f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 17:32:28 +0800 Subject: Blackfin arch: Move all the silicon rev handling to one place Move all the silicon rev handling to one place (Kconfig) and make sure we warn if you are running on silicon that has not been tested on Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 13 +++++++++++++ arch/blackfin/kernel/setup.c | 3 ++- arch/blackfin/mach-bf527/include/mach/bf527.h | 2 -- arch/blackfin/mach-bf533/include/mach/bf533.h | 2 -- arch/blackfin/mach-bf537/include/mach/bf537.h | 2 -- arch/blackfin/mach-bf548/include/mach/bf548.h | 2 -- arch/blackfin/mach-bf561/include/mach/bf561.h | 2 -- 7 files changed, 15 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 10c97efbd91..8102c79aaa9 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -166,6 +166,19 @@ config BF561 endchoice +config BF_REV_MIN + int + default 0 if (BF52x || BF54x) + default 2 if (BF537 || BF536 || BF534) + default 3 if (BF561 ||BF533 || BF532 || BF531) + +config BF_REV_MAX + int + default 2 if (BF52x || BF54x) + default 3 if (BF537 || BF536 || BF534) + default 5 if (BF561) + default 6 if (BF533 || BF532 || BF531) + choice prompt "Silicon Rev" default BF_REV_0_1 if (BF52x || BF54x) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index e9054e0b455..4267523912b 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -821,9 +821,10 @@ void __init setup_arch(char **cmdline_p) printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", bfin_compiled_revid(), bfin_revid()); } - if (bfin_revid() < SUPPORTED_REVID) + if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", CPU, bfin_revid()); + printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", diff --git a/arch/blackfin/mach-bf527/include/mach/bf527.h b/arch/blackfin/mach-bf527/include/mach/bf527.h index 056eb4b9cd2..330041fde54 100644 --- a/arch/blackfin/mach-bf527/include/mach/bf527.h +++ b/arch/blackfin/mach-bf527/include/mach/bf527.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF527_H__ #define __MACH_BF527_H__ -#define SUPPORTED_REVID 2 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ diff --git a/arch/blackfin/mach-bf533/include/mach/bf533.h b/arch/blackfin/mach-bf533/include/mach/bf533.h index 12a41693199..94980111230 100644 --- a/arch/blackfin/mach-bf533/include/mach/bf533.h +++ b/arch/blackfin/mach-bf533/include/mach/bf533.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF533_H__ #define __MACH_BF533_H__ -#define SUPPORTED_REVID 2 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ diff --git a/arch/blackfin/mach-bf537/include/mach/bf537.h b/arch/blackfin/mach-bf537/include/mach/bf537.h index cfe2a221112..7a047e04e38 100644 --- a/arch/blackfin/mach-bf537/include/mach/bf537.h +++ b/arch/blackfin/mach-bf537/include/mach/bf537.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF537_H__ #define __MACH_BF537_H__ -#define SUPPORTED_REVID 2 - /* Masks for generic ERROR IRQ demultiplexing used in int-priority-sc.c */ #define SPI_ERR_MASK (TXCOL | RBSY | MODF | TXE) /* SPI_STAT */ diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h index e748588e893..14f8a7b8454 100644 --- a/arch/blackfin/mach-bf548/include/mach/bf548.h +++ b/arch/blackfin/mach-bf548/include/mach/bf548.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF548_H__ #define __MACH_BF548_H__ -#define SUPPORTED_REVID 0 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ diff --git a/arch/blackfin/mach-bf561/include/mach/bf561.h b/arch/blackfin/mach-bf561/include/mach/bf561.h index 3ef9e5f3613..7787caad355 100644 --- a/arch/blackfin/mach-bf561/include/mach/bf561.h +++ b/arch/blackfin/mach-bf561/include/mach/bf561.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF561_H__ #define __MACH_BF561_H__ -#define SUPPORTED_REVID 0x3 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ -- cgit v1.2.3 From 0cfbb3234c8b18fc2a4934bed418be47c8382b72 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 9 Oct 2008 17:39:37 +0800 Subject: Blackfin arch: early prink code still use uart core console functions to parse and set configure option string Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig.debug | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index 2cb0a3080d7..f08aea4fc5e 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -184,6 +184,7 @@ config DEBUG_BFIN_NO_KERN_HWTRACE config EARLY_PRINTK bool "Early printk" default n + select SERIAL_CORE_CONSOLE help This option enables special console drivers which allow the kernel to print messages very early in the bootup process. -- cgit v1.2.3 From 45138439e171111a93273e9c0008b41ac56d0731 Mon Sep 17 00:00:00 2001 From: Javier Herrero Date: Thu, 9 Oct 2008 18:06:47 +0800 Subject: Blackfin arch: flash memory map and dm9000 resources updating Signed-off-by: Javier Herrero Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf533/boards/H8606.c | 34 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c index c66a68f3023..72ac3ac8ef7 100644 --- a/arch/blackfin/mach-bf533/boards/H8606.c +++ b/arch/blackfin/mach-bf533/boards/H8606.c @@ -9,7 +9,7 @@ * Modified: * Copyright 2005 National ICT Australia (NICTA) * Copyright 2004-2006 Analog Devices Inc - * Copyright 2007 HV Sistemas S.L. + * Copyright 2007,2008 HV Sistemas S.L. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * @@ -64,18 +64,18 @@ static struct platform_device rtc_device = { static struct resource dm9000_resources[] = { [0] = { .start = 0x20300000, - .end = 0x20300000 + 1, + .end = 0x20300002, .flags = IORESOURCE_MEM, }, [1] = { - .start = 0x20300000 + 4, - .end = 0x20300000 + 5, + .start = 0x20300004, + .end = 0x20300006, .flags = IORESOURCE_MEM, }, [2] = { .start = IRQ_PF10, .end = IRQ_PF10, - .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), + .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IRQF_SHARED | IRQF_TRIGGER_HIGH), }, }; @@ -140,18 +140,22 @@ static struct platform_device net2272_bfin_device = { #if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) static struct mtd_partition bfin_spi_flash_partitions[] = { { - .name = "bootloader(spi)", - .size = 0x00060000, + .name = "bootloader (spi)", + .size = 0x40000, .offset = 0, .mask_flags = MTD_CAP_ROM }, { - .name = "linux kernel(spi)", - .size = 0x100000, - .offset = 0x60000 + .name = "fpga (spi)", + .size = 0x30000, + .offset = 0x40000 }, { - .name = "file system(spi)", - .size = 0x6a0000, - .offset = 0x00160000, + .name = "linux kernel (spi)", + .size = 0x150000, + .offset = 0x70000 + }, { + .name = "jffs2 root file system (spi)", + .size = 0x640000, + .offset = 0x1c0000, } }; @@ -340,7 +344,7 @@ static struct platform_device bfin_sir_device = { static struct plat_serial8250_port serial8250_platform_data [] = { { - .membase = 0x20200000, + .membase = (void *)0x20200000, .mapbase = 0x20200000, .irq = IRQ_PF8, .flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE, @@ -348,7 +352,7 @@ static struct plat_serial8250_port serial8250_platform_data [] = { .regshift = 1, .uartclk = 66666667, }, { - .membase = 0x20200010, + .membase = (void *)0x20200010, .mapbase = 0x20200010, .irq = IRQ_PF8, .flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE, -- cgit v1.2.3 From eefb47f6a1e855653d275cb90592a3587ea93a09 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 8 Oct 2008 13:01:39 -0700 Subject: xen: use spin_lock_nest_lock when pinning a pagetable When pinning/unpinning a pagetable with split pte locks, we can end up holding multiple pte locks at once (we need to hold the locks while there's a pending batched hypercall affecting the pte page). Because all the pte locks are in the same lock class, lockdep thinks that we're potentially taking a lock recursively. This warning is spurious because we always take the pte locks while holding mm->page_table_lock. lockdep now has spin_lock_nest_lock to express this kind of dominant lock use, so use it here so that lockdep knows what's going on. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/mmu.c | 74 +++++++++++++++++++++++++++++++++++------------------- arch/x86/xen/mmu.h | 3 --- 2 files changed, 48 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 64e58681767..ae173f6edd8 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -651,9 +651,12 @@ void xen_set_pgd(pgd_t *ptr, pgd_t val) * For 64-bit, we must skip the Xen hole in the middle of the address * space, just after the big x86-64 virtual hole. */ -static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), +static int xen_pgd_walk(struct mm_struct *mm, + int (*func)(struct mm_struct *mm, struct page *, + enum pt_level), unsigned long limit) { + pgd_t *pgd = mm->pgd; int flush = 0; unsigned hole_low, hole_high; unsigned pgdidx_limit, pudidx_limit, pmdidx_limit; @@ -698,7 +701,7 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), pud = pud_offset(&pgd[pgdidx], 0); if (PTRS_PER_PUD > 1) /* not folded */ - flush |= (*func)(virt_to_page(pud), PT_PUD); + flush |= (*func)(mm, virt_to_page(pud), PT_PUD); for (pudidx = 0; pudidx < PTRS_PER_PUD; pudidx++) { pmd_t *pmd; @@ -713,7 +716,7 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), pmd = pmd_offset(&pud[pudidx], 0); if (PTRS_PER_PMD > 1) /* not folded */ - flush |= (*func)(virt_to_page(pmd), PT_PMD); + flush |= (*func)(mm, virt_to_page(pmd), PT_PMD); for (pmdidx = 0; pmdidx < PTRS_PER_PMD; pmdidx++) { struct page *pte; @@ -727,7 +730,7 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), continue; pte = pmd_page(pmd[pmdidx]); - flush |= (*func)(pte, PT_PTE); + flush |= (*func)(mm, pte, PT_PTE); } } } @@ -735,20 +738,20 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), out: /* Do the top level last, so that the callbacks can use it as a cue to do final things like tlb flushes. */ - flush |= (*func)(virt_to_page(pgd), PT_PGD); + flush |= (*func)(mm, virt_to_page(pgd), PT_PGD); return flush; } /* If we're using split pte locks, then take the page's lock and return a pointer to it. Otherwise return NULL. */ -static spinlock_t *xen_pte_lock(struct page *page) +static spinlock_t *xen_pte_lock(struct page *page, struct mm_struct *mm) { spinlock_t *ptl = NULL; #if USE_SPLIT_PTLOCKS ptl = __pte_lockptr(page); - spin_lock(ptl); + spin_lock_nest_lock(ptl, &mm->page_table_lock); #endif return ptl; @@ -772,7 +775,8 @@ static void xen_do_pin(unsigned level, unsigned long pfn) MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); } -static int xen_pin_page(struct page *page, enum pt_level level) +static int xen_pin_page(struct mm_struct *mm, struct page *page, + enum pt_level level) { unsigned pgfl = TestSetPagePinned(page); int flush; @@ -813,7 +817,7 @@ static int xen_pin_page(struct page *page, enum pt_level level) */ ptl = NULL; if (level == PT_PTE) - ptl = xen_pte_lock(page); + ptl = xen_pte_lock(page, mm); MULTI_update_va_mapping(mcs.mc, (unsigned long)pt, pfn_pte(pfn, PAGE_KERNEL_RO), @@ -834,11 +838,11 @@ static int xen_pin_page(struct page *page, enum pt_level level) /* This is called just after a mm has been created, but it has not been used yet. We need to make sure that its pagetable is all read-only, and can be pinned. */ -void xen_pgd_pin(pgd_t *pgd) +static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd) { xen_mc_batch(); - if (xen_pgd_walk(pgd, xen_pin_page, USER_LIMIT)) { + if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) { /* re-enable interrupts for kmap_flush_unused */ xen_mc_issue(0); kmap_flush_unused(); @@ -852,25 +856,35 @@ void xen_pgd_pin(pgd_t *pgd) xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(pgd))); if (user_pgd) { - xen_pin_page(virt_to_page(user_pgd), PT_PGD); + xen_pin_page(mm, virt_to_page(user_pgd), PT_PGD); xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(user_pgd))); } } #else /* CONFIG_X86_32 */ #ifdef CONFIG_X86_PAE /* Need to make sure unshared kernel PMD is pinnable */ - xen_pin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); + xen_pin_page(mm, virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), + PT_PMD); #endif xen_do_pin(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(pgd))); #endif /* CONFIG_X86_64 */ xen_mc_issue(0); } +static void xen_pgd_pin(struct mm_struct *mm) +{ + __xen_pgd_pin(mm, mm->pgd); +} + /* * On save, we need to pin all pagetables to make sure they get their * mfns turned into pfns. Search the list for any unpinned pgds and pin * them (unpinned pgds are not currently in use, probably because the * process is under construction or destruction). + * + * Expected to be called in stop_machine() ("equivalent to taking + * every spinlock in the system"), so the locking doesn't really + * matter all that much. */ void xen_mm_pin_all(void) { @@ -881,7 +895,7 @@ void xen_mm_pin_all(void) list_for_each_entry(page, &pgd_list, lru) { if (!PagePinned(page)) { - xen_pgd_pin((pgd_t *)page_address(page)); + __xen_pgd_pin(&init_mm, (pgd_t *)page_address(page)); SetPageSavePinned(page); } } @@ -894,7 +908,8 @@ void xen_mm_pin_all(void) * that's before we have page structures to store the bits. So do all * the book-keeping now. */ -static __init int xen_mark_pinned(struct page *page, enum pt_level level) +static __init int xen_mark_pinned(struct mm_struct *mm, struct page *page, + enum pt_level level) { SetPagePinned(page); return 0; @@ -902,10 +917,11 @@ static __init int xen_mark_pinned(struct page *page, enum pt_level level) void __init xen_mark_init_mm_pinned(void) { - xen_pgd_walk(init_mm.pgd, xen_mark_pinned, FIXADDR_TOP); + xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP); } -static int xen_unpin_page(struct page *page, enum pt_level level) +static int xen_unpin_page(struct mm_struct *mm, struct page *page, + enum pt_level level) { unsigned pgfl = TestClearPagePinned(page); @@ -923,7 +939,7 @@ static int xen_unpin_page(struct page *page, enum pt_level level) * partially-pinned state. */ if (level == PT_PTE) { - ptl = xen_pte_lock(page); + ptl = xen_pte_lock(page, mm); if (ptl) xen_do_pin(MMUEXT_UNPIN_TABLE, pfn); @@ -945,7 +961,7 @@ static int xen_unpin_page(struct page *page, enum pt_level level) } /* Release a pagetables pages back as normal RW */ -static void xen_pgd_unpin(pgd_t *pgd) +static void __xen_pgd_unpin(struct mm_struct *mm, pgd_t *pgd) { xen_mc_batch(); @@ -957,21 +973,27 @@ static void xen_pgd_unpin(pgd_t *pgd) if (user_pgd) { xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(user_pgd))); - xen_unpin_page(virt_to_page(user_pgd), PT_PGD); + xen_unpin_page(mm, virt_to_page(user_pgd), PT_PGD); } } #endif #ifdef CONFIG_X86_PAE /* Need to make sure unshared kernel PMD is unpinned */ - xen_unpin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); + xen_unpin_page(mm, virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), + PT_PMD); #endif - xen_pgd_walk(pgd, xen_unpin_page, USER_LIMIT); + xen_pgd_walk(mm, xen_unpin_page, USER_LIMIT); xen_mc_issue(0); } +static void xen_pgd_unpin(struct mm_struct *mm) +{ + __xen_pgd_unpin(mm, mm->pgd); +} + /* * On resume, undo any pinning done at save, so that the rest of the * kernel doesn't see any unexpected pinned pagetables. @@ -986,7 +1008,7 @@ void xen_mm_unpin_all(void) list_for_each_entry(page, &pgd_list, lru) { if (PageSavePinned(page)) { BUG_ON(!PagePinned(page)); - xen_pgd_unpin((pgd_t *)page_address(page)); + __xen_pgd_unpin(&init_mm, (pgd_t *)page_address(page)); ClearPageSavePinned(page); } } @@ -997,14 +1019,14 @@ void xen_mm_unpin_all(void) void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) { spin_lock(&next->page_table_lock); - xen_pgd_pin(next->pgd); + xen_pgd_pin(next); spin_unlock(&next->page_table_lock); } void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) { spin_lock(&mm->page_table_lock); - xen_pgd_pin(mm->pgd); + xen_pgd_pin(mm); spin_unlock(&mm->page_table_lock); } @@ -1095,7 +1117,7 @@ void xen_exit_mmap(struct mm_struct *mm) /* pgd may not be pinned in the error exit path of execve */ if (xen_page_pinned(mm->pgd)) - xen_pgd_unpin(mm->pgd); + xen_pgd_unpin(mm); spin_unlock(&mm->page_table_lock); } diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index 0f59bd03f9e..98d71659da5 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -18,9 +18,6 @@ void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next); void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm); void xen_exit_mmap(struct mm_struct *mm); -void xen_pgd_pin(pgd_t *pgd); -//void xen_pgd_unpin(pgd_t *pgd); - pteval_t xen_pte_val(pte_t); pmdval_t xen_pmd_val(pmd_t); pgdval_t xen_pgd_val(pgd_t); -- cgit v1.2.3 From ec2a5652ea53c102306f08cdf516f98e32bd4b61 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 9 Oct 2008 09:45:04 -0700 Subject: phylib: two dynamic mii_bus allocation fallout fixes 1. arch/powerpc/platforms/pasemi/gpio_mdio.c also needs to be converted over to mdiobus_{alloc,free}(). 2. drivers/net/phy/fixed.c used to embed a struct mii_bus into its struct fixed_mdio_bus and then use container_of() to go from the former to the latter. Since mii bus structures are no longer embedded, we need to do something like use the mii bus private pointer to go from mii_bus to fixed_mdio_bus instead. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- arch/powerpc/platforms/pasemi/gpio_mdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index 798c7abe160..75cc165d5be 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -230,7 +230,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, if (!priv) goto out; - new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); + new_bus = mdiobus_alloc(); if (!new_bus) goto out_free_priv; @@ -306,7 +306,7 @@ static int gpio_mdio_remove(struct of_device *dev) kfree(bus->priv); bus->priv = NULL; - kfree(bus); + mdiobus_free(bus); return 0; } -- cgit v1.2.3 From 8d5922572038bae9f7b16fcb974eee806727b44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9meth=20M=C3=A1rton?= Date: Thu, 9 Oct 2008 14:59:17 +0200 Subject: [CPUFREQ] correct broken links and email addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the no longer working links and email address in the documentation and in source code. Signed-off-by: Márton Németh Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/p4-clockmod.c | 2 +- arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index f1685fb91fb..b8e05ee4f73 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c @@ -171,7 +171,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) } if (c->x86 != 0xF) { - printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); + printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); return 0; } diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 15e13c01cc3..3b5f06423e7 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c @@ -26,7 +26,7 @@ #include #define PFX "speedstep-centrino: " -#define MAINTAINER "cpufreq@lists.linux.org.uk" +#define MAINTAINER "cpufreq@vger.kernel.org" #define dprintk(msg...) \ cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) -- cgit v1.2.3 From 18c6faa9624bf5d9d7da3906a8a1b909dba5899b Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Mon, 28 Jul 2008 13:00:49 +0200 Subject: [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/elanfreq.c Before: total: 15 errors, 10 warnings, 308 lines checked After: total: 0 errors, 4 warnings, 308 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/elafreq.o.* add1d36c2f077c5aab7682e8642a9f34 /tmp/elafreq.o.after add1d36c2f077c5aab7682e8642a9f34 /tmp/elafreq.o.before paolo@paolo-desktop:~/linux.trees.git$ size /tmp/elafreq.o.* text data bss dec hex filename 934 270 4 1208 4b8 /tmp/elafreq.o.after 934 270 4 1208 4b8 /tmp/elafreq.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/elanfreq.c | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c index e4a4bf870e9..fe613c93b36 100644 --- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include #define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */ #define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */ @@ -82,7 +82,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) u8 clockspeed_reg; /* Clock Speed Register */ local_irq_disable(); - outb_p(0x80,REG_CSCIR); + outb_p(0x80, REG_CSCIR); clockspeed_reg = inb_p(REG_CSCDR); local_irq_enable(); @@ -98,10 +98,10 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) } /* 33 MHz is not 32 MHz... */ - if ((clockspeed_reg & 0xE0)==0xA0) + if ((clockspeed_reg & 0xE0) == 0xA0) return 33000; - return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000); + return (1<<((clockspeed_reg & 0xE0) >> 5)) * 1000; } @@ -117,7 +117,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) * There is no return value. */ -static void elanfreq_set_cpu_state (unsigned int state) +static void elanfreq_set_cpu_state(unsigned int state) { struct cpufreq_freqs freqs; @@ -144,20 +144,20 @@ static void elanfreq_set_cpu_state (unsigned int state) */ local_irq_disable(); - outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */ - outb_p(0x00,REG_CSCDR); + outb_p(0x40, REG_CSCIR); /* Disable hyperspeed mode */ + outb_p(0x00, REG_CSCDR); local_irq_enable(); /* wait till internal pipelines and */ udelay(1000); /* buffers have cleaned up */ local_irq_disable(); /* now, set the CPU clock speed register (0x80) */ - outb_p(0x80,REG_CSCIR); - outb_p(elan_multiplier[state].val80h,REG_CSCDR); + outb_p(0x80, REG_CSCIR); + outb_p(elan_multiplier[state].val80h, REG_CSCDR); /* now, the hyperspeed bit in PMU Force Mode Register (0x40) */ - outb_p(0x40,REG_CSCIR); - outb_p(elan_multiplier[state].val40h,REG_CSCDR); + outb_p(0x40, REG_CSCIR); + outb_p(elan_multiplier[state].val40h, REG_CSCDR); udelay(10000); local_irq_enable(); @@ -173,12 +173,12 @@ static void elanfreq_set_cpu_state (unsigned int state) * for the hardware supported by the driver. */ -static int elanfreq_verify (struct cpufreq_policy *policy) +static int elanfreq_verify(struct cpufreq_policy *policy) { return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]); } -static int elanfreq_target (struct cpufreq_policy *policy, +static int elanfreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -205,7 +205,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) /* capability check */ if ((c->x86_vendor != X86_VENDOR_AMD) || - (c->x86 != 4) || (c->x86_model!=10)) + (c->x86 != 4) || (c->x86_model != 10)) return -ENODEV; /* max freq */ @@ -213,7 +213,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) max_freq = elanfreq_get_cpu_frequency(0); /* table init */ - for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { if (elanfreq_table[i].frequency > max_freq) elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID; } @@ -224,7 +224,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table); if (result) - return (result); + return result; cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu); return 0; @@ -260,7 +260,7 @@ __setup("elanfreq=", elanfreq_setup); #endif -static struct freq_attr* elanfreq_attr[] = { +static struct freq_attr *elanfreq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, }; @@ -284,9 +284,9 @@ static int __init elanfreq_init(void) /* Test if we have the right hardware */ if ((c->x86_vendor != X86_VENDOR_AMD) || - (c->x86 != 4) || (c->x86_model!=10)) { + (c->x86 != 4) || (c->x86_model != 10)) { printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); - return -ENODEV; + return -ENODEV; } return cpufreq_register_driver(&elanfreq_driver); } @@ -298,7 +298,7 @@ static void __exit elanfreq_exit(void) } -module_param (max_freq, int, 0444); +module_param(max_freq, int, 0444); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Robert Schwebel , Sven Geggus "); -- cgit v1.2.3 From 8d2d2051e50c4ca0207a42b243369e22f7d90a5c Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Mon, 28 Jul 2008 21:08:16 +0200 Subject: [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/powernow-k6.c Before: total: 11 errors, 15 warnings, 255 lines checked After: total: 0 errors, 6 warnings, 254 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/powernow-k6.o.* 476932f5e1ffe365db9d1dfb3f860369 /tmp/powernow-k6.o.after 476932f5e1ffe365db9d1dfb3f860369 /tmp/powernow-k6.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/powernow-k6.c | 41 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c index eb9b62b0830..b5ced806a31 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c @@ -15,12 +15,11 @@ #include #include -#include -#include +#include +#include - -#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long - as it is unused */ +#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long + as it is unused */ static unsigned int busfreq; /* FSB, in 10 kHz */ static unsigned int max_multiplier; @@ -53,7 +52,7 @@ static int powernow_k6_get_cpu_multiplier(void) msrval = POWERNOW_IOPORT + 0x1; wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ - invalue=inl(POWERNOW_IOPORT + 0x8); + invalue = inl(POWERNOW_IOPORT + 0x8); msrval = POWERNOW_IOPORT + 0x0; wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ @@ -67,9 +66,9 @@ static int powernow_k6_get_cpu_multiplier(void) * * Tries to change the PowerNow! multiplier */ -static void powernow_k6_set_state (unsigned int best_i) +static void powernow_k6_set_state(unsigned int best_i) { - unsigned long outvalue=0, invalue=0; + unsigned long outvalue = 0, invalue = 0; unsigned long msrval; struct cpufreq_freqs freqs; @@ -90,10 +89,10 @@ static void powernow_k6_set_state (unsigned int best_i) msrval = POWERNOW_IOPORT + 0x1; wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ - invalue=inl(POWERNOW_IOPORT + 0x8); + invalue = inl(POWERNOW_IOPORT + 0x8); invalue = invalue & 0xf; outvalue = outvalue | invalue; - outl(outvalue ,(POWERNOW_IOPORT + 0x8)); + outl(outvalue , (POWERNOW_IOPORT + 0x8)); msrval = POWERNOW_IOPORT + 0x0; wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ @@ -124,7 +123,7 @@ static int powernow_k6_verify(struct cpufreq_policy *policy) * * sets a new CPUFreq policy */ -static int powernow_k6_target (struct cpufreq_policy *policy, +static int powernow_k6_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -152,7 +151,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) busfreq = cpu_khz / max_multiplier; /* table init */ - for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { if (clock_ratio[i].index > max_multiplier) clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID; else @@ -165,7 +164,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio); if (result) - return (result); + return result; cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu); @@ -176,8 +175,8 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) { unsigned int i; - for (i=0; i<8; i++) { - if (i==max_multiplier) + for (i = 0; i < 8; i++) { + if (i == max_multiplier) powernow_k6_set_state(i); } cpufreq_frequency_table_put_attr(policy->cpu); @@ -189,7 +188,7 @@ static unsigned int powernow_k6_get(unsigned int cpu) return busfreq * powernow_k6_get_cpu_multiplier(); } -static struct freq_attr* powernow_k6_attr[] = { +static struct freq_attr *powernow_k6_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, }; @@ -227,7 +226,7 @@ static int __init powernow_k6_init(void) } if (cpufreq_register_driver(&powernow_k6_driver)) { - release_region (POWERNOW_IOPORT, 16); + release_region(POWERNOW_IOPORT, 16); return -EINVAL; } @@ -243,13 +242,13 @@ static int __init powernow_k6_init(void) static void __exit powernow_k6_exit(void) { cpufreq_unregister_driver(&powernow_k6_driver); - release_region (POWERNOW_IOPORT, 16); + release_region(POWERNOW_IOPORT, 16); } -MODULE_AUTHOR ("Arjan van de Ven , Dave Jones , Dominik Brodowski "); -MODULE_DESCRIPTION ("PowerNow! driver for AMD K6-2+ / K6-3+ processors."); -MODULE_LICENSE ("GPL"); +MODULE_AUTHOR("Arjan van de Ven , Dave Jones , Dominik Brodowski "); +MODULE_DESCRIPTION("PowerNow! driver for AMD K6-2+ / K6-3+ processors."); +MODULE_LICENSE("GPL"); module_init(powernow_k6_init); module_exit(powernow_k6_exit); -- cgit v1.2.3 From 847aef6ffd85787b62395b64719f8f7c5975bf1b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 14 Jul 2008 11:59:44 +0900 Subject: [CPUFREQ] acpi-cpufreq: add error handling for cpufreq_register_driver() error add error handling for cpufreq_register_driver() error Signed-off-by: Akinobu Mita Cc: cpufreq@lists.linux.org.uk Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 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 dd097b83583..1def5b06fa4 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -785,7 +785,11 @@ static int __init acpi_cpufreq_init(void) if (ret) return ret; - return cpufreq_register_driver(&acpi_cpufreq_driver); + ret = cpufreq_register_driver(&acpi_cpufreq_driver); + if (ret) + free_percpu(acpi_perf_data); + + return ret; } static void __exit acpi_cpufreq_exit(void) @@ -795,8 +799,6 @@ static void __exit acpi_cpufreq_exit(void) cpufreq_unregister_driver(&acpi_cpufreq_driver); free_percpu(acpi_perf_data); - - return; } module_param(acpi_pstate_strict, uint, 0644); -- cgit v1.2.3 From bf0b90e357c883e8efd72954432efe652de74c76 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Mon, 4 Aug 2008 11:59:07 -0700 Subject: [CPUFREQ][1/6] cpufreq: Add cpu number parameter to __cpufreq_driver_getavg() Add a cpu parameter to __cpufreq_driver_getavg(). This is needed for software cpufreq coordination where policy->cpu may not be same as the CPU on which we want to getavg frequency. A follow-on patch will use this parameter to getavg freq from all cpus in policy->cpus. Change since last patch. Fix the offline/online and suspend/resume oops reported by Youquan Song Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 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 1def5b06fa4..c24c4a487b7 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -256,7 +256,8 @@ static u32 get_cur_val(const cpumask_t *mask) * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and * no meaning should be associated with absolute values of these MSRs. */ -static unsigned int get_measured_perf(unsigned int cpu) +static unsigned int get_measured_perf(struct cpufreq_policy *policy, + unsigned int cpu) { union { struct { @@ -326,7 +327,7 @@ static unsigned int get_measured_perf(unsigned int cpu) #endif - retval = per_cpu(drv_data, cpu)->max_freq * perf_percent / 100; + retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100; put_cpu(); set_cpus_allowed_ptr(current, &saved_mask); -- cgit v1.2.3 From a70973c2141f98e2046f7ce9a29774bf254cf70f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 3 Oct 2008 00:31:19 +0400 Subject: proc: remove unused get_dma_list() Signed-off-by: Alexey Dobriyan --- arch/arm/kernel/dma.c | 17 ----------------- arch/sparc/include/asm/dma_32.h | 1 - 2 files changed, 18 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index ba99a203552..d006085ed7e 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -25,23 +25,6 @@ EXPORT_SYMBOL(dma_spin_lock); static dma_t dma_chan[MAX_DMA_CHANNELS]; -/* - * Get dma list for /proc/dma - */ -int get_dma_list(char *buf) -{ - dma_t *dma; - char *p = buf; - int i; - - for (i = 0, dma = dma_chan; i < MAX_DMA_CHANNELS; i++, dma++) - if (dma->lock) - p += sprintf(p, "%2d: %14s %s\n", i, - dma->d_ops->type, dma->device_id); - - return p - buf; -} - /* * Request DMA channel * diff --git a/arch/sparc/include/asm/dma_32.h b/arch/sparc/include/asm/dma_32.h index cf7189c0079..7fa752959b9 100644 --- a/arch/sparc/include/asm/dma_32.h +++ b/arch/sparc/include/asm/dma_32.h @@ -231,7 +231,6 @@ static inline void sparc_dma_pause(struct sparc_dma_registers *regs, #define for_each_dvma(dma) \ for((dma) = dma_chain; (dma); (dma) = (dma)->next) -extern int get_dma_list(char *); extern int request_dma(unsigned int, __const__ char *); extern void free_dma(unsigned int); -- cgit v1.2.3 From 2043f3f7312cc7fbbc2acffb9d87265b0ad9a529 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 13 Oct 2008 14:46:30 +0800 Subject: Blackfin arch: Enable framebuffer support for the BF526-EZkit TFT LCD display Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf537/boards/stamp.c | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 8482d22321f..ccfa0880184 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -582,6 +582,13 @@ static struct bfin5xx_spi_chip spidev_chip_info = { }; #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) +static struct bfin5xx_spi_chip lq035q1_spi_chip_info = { + .enable_dma = 0, + .bits_per_word = 8, +}; +#endif + #if defined(CONFIG_MTD_DATAFLASH) \ || defined(CONFIG_MTD_DATAFLASH_MODULE) @@ -730,6 +737,16 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .controller_data = &spidev_chip_info, }, #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) + { + .modalias = "bfin-lq035q1-spi", + .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 1, + .controller_data = &lq035q1_spi_chip_info, + .mode = SPI_CPHA | SPI_CPOL, + }, +#endif }; #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) @@ -777,6 +794,34 @@ static struct platform_device bfin_fb_adv7393_device = { }; #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) +#include + +static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = { + .mode = LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB, + .use_bl = 1, + .gpio_bl = GPIO_PF7, +}; + +static struct resource bfin_lq035q1_resources[] = { + { + .start = IRQ_PPI_ERROR, + .end = IRQ_PPI_ERROR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_lq035q1_device = { + .name = "bfin-lq035q1", + .id = -1, + .num_resources = ARRAY_SIZE(bfin_lq035q1_resources), + .resource = bfin_lq035q1_resources, + .dev = { + .platform_data = &bfin_lq035q1_data, + }, +}; +#endif + #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) static struct resource bfin_uart_resources[] = { #ifdef CONFIG_SERIAL_BFIN_UART0 @@ -997,6 +1042,10 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_fb_device, #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) + &bfin_lq035q1_device, +#endif + #if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE) &bfin_fb_adv7393_device, #endif -- cgit v1.2.3 From d207a8c7681f14302e9e80ef5b8202abe39060b5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:26:57 +0800 Subject: Blackfin arch: ptrace - fix off-by-one check on end of memory regions Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 50 ++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index e8172eece04..7e1f762b670 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -161,15 +161,15 @@ static inline int is_user_addr_valid(struct task_struct *child, struct sram_list_struct *sraml; for (vml = child->mm->context.vmlist; vml; vml = vml->next) - if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end) + if (start >= vml->vma->vm_start && start + len < vml->vma->vm_end) return 0; for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next) if (start >= (unsigned long)sraml->addr - && start + len <= (unsigned long)sraml->addr + sraml->length) + && start + len < (unsigned long)sraml->addr + sraml->length) return 0; - if (start >= FIXED_CODE_START && start + len <= FIXED_CODE_END) + if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END) return 0; return -EIO; @@ -216,34 +216,30 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; pr_debug("ptrace: user address is valid\n"); -#if L1_CODE_LENGTH != 0 - if (addr >= L1_CODE_START + if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); - } else -#endif -#if L1_DATA_A_LENGTH != 0 - if (addr >= L1_DATA_A_START + + } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START && addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); - } else -#endif -#if L1_DATA_B_LENGTH != 0 - if (addr >= L1_DATA_B_START + + } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START && addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); - } else -#endif - if (addr >= FIXED_CODE_START + + } else if (addr >= FIXED_CODE_START && addr + sizeof(tmp) <= FIXED_CODE_END) { memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); + } else copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); if (copied != sizeof(tmp)) break; @@ -300,34 +296,30 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; pr_debug("ptrace: user address is valid\n"); -#if L1_CODE_LENGTH != 0 - if (addr >= L1_CODE_START + if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); copied = sizeof(data); - } else -#endif -#if L1_DATA_A_LENGTH != 0 - if (addr >= L1_DATA_A_START + + } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START && addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); - } else -#endif -#if L1_DATA_B_LENGTH != 0 - if (addr >= L1_DATA_B_START + + } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START && addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); - } else -#endif - if (addr >= FIXED_CODE_START + + } else if (addr >= FIXED_CODE_START && addr + sizeof(data) <= FIXED_CODE_END) { memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); + } else copied = access_process_vm(child, addr, &data, sizeof(data), 1); + pr_debug("ptrace: copied size %d\n", copied); if (copied != sizeof(data)) break; -- cgit v1.2.3 From 3c08f1d122627c9559fb03a11f52ea37f960b61e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:12:51 +0800 Subject: Blackfin arch: have is_user_addr_valid() check for overflows (like when address is -1) Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 7e1f762b670..140bf00e997 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -160,6 +160,10 @@ static inline int is_user_addr_valid(struct task_struct *child, struct vm_list_struct *vml; struct sram_list_struct *sraml; + /* overflow */ + if (start + len < start) + return -EIO; + for (vml = child->mm->context.vmlist; vml; vml = vml->next) if (start >= vml->vma->vm_start && start + len < vml->vma->vm_end) return 0; -- cgit v1.2.3 From a88c71e4367aada2065c5e247477c891d2ca952f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:37:52 +0800 Subject: Blackfin arch: emulate a TTY over the EMUDAT/JTAG interface Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/early_printk.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 60f67f90fe3..1f4e3d2e090 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c @@ -35,6 +35,9 @@ extern struct console *bfin_earlyserial_init(unsigned int port, unsigned int cflag); #endif +#ifdef CONFIG_BFIN_JTAG_COMM +extern struct console *bfin_jc_early_init(void); +#endif static struct console *early_console; @@ -142,6 +145,15 @@ int __init setup_early_printk(char *buf) early_console = earlyserial_init(buf); } #endif + +#ifdef CONFIG_BFIN_JTAG_COMM + /* Check for Blackfin JTAG */ + if (!strncmp(buf, "jtag", 4)) { + buf += 4; + early_console = bfin_jc_early_init(); + } +#endif + #ifdef CONFIG_FB /* TODO: add framebuffer console support */ #endif -- cgit v1.2.3 From 9f06c38fb230720371397a57faa24aa6e31b2c87 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Fri, 10 Oct 2008 18:13:21 +0800 Subject: Blackfin arch: Add optional verbose debug Add optional verbose debug - which when turned off, quiets down userspace errors. Saves ~8k of code/data for production systems Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig.debug | 13 +++ arch/blackfin/kernel/traps.c | 230 ++++++++++++++++++++++++------------------- 2 files changed, 143 insertions(+), 100 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index f08aea4fc5e..3ad25983ec9 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -5,6 +5,19 @@ source "lib/Kconfig.debug" config HAVE_ARCH_KGDB def_bool y +config DEBUG_VERBOSE + bool "Verbose fault messages" + default y + select PRINTK + help + When a program crashes due to an exception, or the kernel detects + an internal error, the kernel can print a not so brief message + explaining what the problem was. This debugging information is + useful to developers and kernel hackers when tracking down problems, + but mostly meaningless to other people. This is always helpful for + debugging but serves no purpose on a production system. + Most people should say N here. + config DEBUG_MMRS bool "Generate Blackfin MMR tree" select DEBUG_FS diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 709c247b701..1aa2c788e22 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -58,6 +58,15 @@ # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) #endif + +#ifdef CONFIG_VERBOSE_DEBUG +#define verbose_printk(fmt, arg...) \ + printk(fmt, ##arg) +#else +#define verbose_printk(fmt, arg...) \ + ({ if (0) printk(fmt, ##arg); 0; }) +#endif + /* Initiate the event table handler */ void __init trap_init(void) { @@ -78,6 +87,7 @@ unsigned long saved_retx, saved_seqstat, static void decode_address(char *buf, unsigned long address) { +#ifdef CONFIG_DEBUG_VERBOSE struct vm_list_struct *vml; struct task_struct *p; struct mm_struct *mm; @@ -185,12 +195,16 @@ static void decode_address(char *buf, unsigned long address) done: write_unlock_irqrestore(&tasklist_lock, flags); +#else + sprintf(buf, " "); +#endif } asmlinkage void double_fault_c(struct pt_regs *fp) { console_verbose(); oops_in_progress = 1; +#ifdef CONFIG_DEBUG_VERBOSE printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { @@ -213,6 +227,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp) dump_bfin_mem(fp); show_regs(fp); } +#endif panic("Double Fault - unrecoverable event\n"); } @@ -288,7 +303,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT03: info.si_code = SEGV_STACKFLOW; sig = SIGSEGV; - printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x02 - KGDB initial connection and break signal trap */ @@ -317,7 +332,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT04 ... VEC_EXCPT15: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x10 HW Single step, handled here */ @@ -334,7 +349,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_OVFLOW: info.si_code = TRAP_TRACEFLOW; sig = SIGTRAP; - printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x12 - Reserved, Caught by default */ @@ -356,35 +371,35 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_UNDEF_I: info.si_code = ILL_ILLOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x22 - Illegal Instruction Combination, handled here */ case VEC_ILGAL_I: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x23 - Data CPLB protection violation, handled here */ case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x24 - Data access misaligned, handled here */ case VEC_MISALI_D: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x25 - Unrecoverable Event, handled here */ case VEC_UNCOV: info.si_code = ILL_ILLEXCPT; sig = SIGILL; - printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, @@ -392,7 +407,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_M: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); break; /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ case VEC_CPLB_MHIT: @@ -400,10 +415,10 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGSEGV; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO if (saved_dcplb_fault_addr < FIXED_CODE_START) - printk(KERN_NOTICE "NULL pointer access\n"); + verbose_printk(KERN_NOTICE "NULL pointer access\n"); else #endif - printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x28 - Emulation Watchpoint, handled here */ @@ -422,7 +437,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ info.si_code = BUS_OPFETCH; sig = SIGBUS; - printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); + verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); CHK_DEBUGGER_TRAP_MAYBE(); break; #else @@ -432,21 +447,21 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_MISALI_I: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2B - Instruction CPLB protection violation, handled here */ case VEC_CPLB_I_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ case VEC_CPLB_I_M: info.si_code = ILL_CPLB_MISS; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); break; /* 0x2D - Instruction CPLB Multiple Hits, handled here */ case VEC_CPLB_I_MHIT: @@ -454,17 +469,17 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGSEGV; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO if (saved_icplb_fault_addr < FIXED_CODE_START) - printk(KERN_NOTICE "Jump to NULL address\n"); + verbose_printk(KERN_NOTICE "Jump to NULL address\n"); else #endif - printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2E - Illegal use of Supervisor Resource, handled here */ case VEC_ILL_RES: info.si_code = ILL_PRVOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2F - Reserved, Caught by default */ @@ -492,17 +507,17 @@ asmlinkage void trap_c(struct pt_regs *fp) case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); + verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); break; /* External Memory Addressing Error */ case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): info.si_code = BUS_ADRERR; sig = SIGBUS; - printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); + verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); break; /* Performance Monitor Overflow */ case (SEQSTAT_HWERRCAUSE_PERF_FLOW): - printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); + verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); break; /* RAISE 5 instruction */ case (SEQSTAT_HWERRCAUSE_RAISE_5): @@ -522,7 +537,7 @@ asmlinkage void trap_c(struct pt_regs *fp) oops_in_progress = 1; info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", + verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", (fp->seqstat & SEQSTAT_EXCAUSE)); CHK_DEBUGGER_TRAP_MAYBE(); break; @@ -531,7 +546,6 @@ asmlinkage void trap_c(struct pt_regs *fp) BUG_ON(sig == 0); if (sig != SIGTRAP) { - unsigned long *stack; dump_bfin_process(fp); dump_bfin_mem(fp); show_regs(fp); @@ -539,7 +553,7 @@ asmlinkage void trap_c(struct pt_regs *fp) /* Print out the trace buffer if it makes sense */ #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) - printk(KERN_NOTICE "No trace since you do not have " + verbose_printk(KERN_NOTICE "No trace since you do not have " "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" KERN_NOTICE "\n"); else @@ -548,20 +562,22 @@ asmlinkage void trap_c(struct pt_regs *fp) if (oops_in_progress) { /* Dump the current kernel stack */ - printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); show_stack(current, NULL); - print_modules(); #ifndef CONFIG_ACCESS_CHECK - printk(KERN_EMERG "Please turn on " + verbose_printk(KERN_EMERG "Please turn on " "CONFIG_ACCESS_CHECK\n"); #endif panic("Kernel exception"); } else { +#ifdef CONFIG_VERBOSE_DEBUG + unsigned long *stack; /* Dump the user space stack */ stack = (unsigned long *)rdusp(); - printk(KERN_NOTICE "Userspace Stack\n"); + verbose_printk(KERN_NOTICE "Userspace Stack\n"); show_stack(NULL, stack); +#endif } } @@ -582,7 +598,7 @@ asmlinkage void trap_c(struct pt_regs *fp) * Similar to get_user, do some address checking, then dereference * Return true on sucess, false on bad address */ -bool get_instruction(unsigned short *val, unsigned short *address) +static bool get_instruction(unsigned short *val, unsigned short *address) { unsigned long addr; @@ -643,45 +659,48 @@ bool get_instruction(unsigned short *val, unsigned short *address) * These are the normal instructions which cause change of flow, which * would be at the source of the trace buffer */ -void decode_instruction(unsigned short *address) +#ifdef CONFIG_DEBUG_VERBOSE +static void decode_instruction(unsigned short *address) { unsigned short opcode; if (get_instruction(&opcode, address)) { if (opcode == 0x0010) - printk("RTS"); + verbose_printk("RTS"); else if (opcode == 0x0011) - printk("RTI"); + verbose_printk("RTI"); else if (opcode == 0x0012) - printk("RTX"); + verbose_printk("RTX"); else if (opcode >= 0x0050 && opcode <= 0x0057) - printk("JUMP (P%i)", opcode & 7); + verbose_printk("JUMP (P%i)", opcode & 7); else if (opcode >= 0x0060 && opcode <= 0x0067) - printk("CALL (P%i)", opcode & 7); + verbose_printk("CALL (P%i)", opcode & 7); else if (opcode >= 0x0070 && opcode <= 0x0077) - printk("CALL (PC+P%i)", opcode & 7); + verbose_printk("CALL (PC+P%i)", opcode & 7); else if (opcode >= 0x0080 && opcode <= 0x0087) - printk("JUMP (PC+P%i)", opcode & 7); + verbose_printk("JUMP (PC+P%i)", opcode & 7); else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF)) - printk("IF !CC JUMP"); + verbose_printk("IF !CC JUMP"); else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff)) - printk("IF CC JUMP"); + verbose_printk("IF CC JUMP"); else if (opcode >= 0x2000 && opcode <= 0x2fff) - printk("JUMP.S"); + verbose_printk("JUMP.S"); else if (opcode >= 0xe080 && opcode <= 0xe0ff) - printk("LSETUP"); + verbose_printk("LSETUP"); else if (opcode >= 0xe200 && opcode <= 0xe2ff) - printk("JUMP.L"); + verbose_printk("JUMP.L"); else if (opcode >= 0xe300 && opcode <= 0xe3ff) - printk("CALL pcrel"); + verbose_printk("CALL pcrel"); else - printk("0x%04x", opcode); + verbose_printk("0x%04x", opcode); } } +#endif void dump_bfin_trace_buffer(void) { +#ifdef CONFIG_DEBUG_VERBOSE #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON int tflags, i = 0; char buf[150]; @@ -737,6 +756,7 @@ void dump_bfin_trace_buffer(void) trace_buffer_restore(tflags); #endif +#endif } EXPORT_SYMBOL(dump_bfin_trace_buffer); @@ -744,7 +764,7 @@ EXPORT_SYMBOL(dump_bfin_trace_buffer); * Checks to see if the address pointed to is either a * 16-bit CALL instruction, or a 32-bit CALL instruction */ -bool is_bfin_call(unsigned short *addr) +static bool is_bfin_call(unsigned short *addr) { unsigned short opcode = 0, *ins_addr; ins_addr = (unsigned short *)addr; @@ -766,8 +786,10 @@ bool is_bfin_call(unsigned short *addr) return false; } + void show_stack(struct task_struct *task, unsigned long *stack) { +#ifdef CONFIG_PRINTK unsigned int *addr, *endstack, *fp = 0, *frame; unsigned short *ins_addr; char buf[150]; @@ -792,8 +814,10 @@ void show_stack(struct task_struct *task, unsigned long *stack) } else endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack); + printk(KERN_NOTICE "Stack info:\n"); decode_address(buf, (unsigned int)stack); - printk(KERN_NOTICE "Stack info:\n" KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); + printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); + addr = (unsigned int *)((unsigned int)stack & ~0x3F); /* First thing is to look for a frame pointer */ @@ -884,7 +908,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) if (!j) printk("\n"); } - +#endif } void dump_stack(void) @@ -902,38 +926,39 @@ EXPORT_SYMBOL(dump_stack); void dump_bfin_process(struct pt_regs *fp) { +#ifdef CONFIG_DEBUG_VERBOSE /* We should be able to look at fp->ipend, but we don't push it on the * stack all the time, so do this until we fix that */ unsigned int context = bfin_read_IPEND(); if (oops_in_progress) - printk(KERN_EMERG "Kernel OOPS in progress\n"); + verbose_printk(KERN_EMERG "Kernel OOPS in progress\n"); if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) - printk(KERN_NOTICE "HW Error context\n"); + verbose_printk(KERN_NOTICE "HW Error context\n"); else if (context & 0x0020) - printk(KERN_NOTICE "Deferred Exception context\n"); + verbose_printk(KERN_NOTICE "Deferred Exception context\n"); else if (context & 0x3FC0) - printk(KERN_NOTICE "Interrupt context\n"); + verbose_printk(KERN_NOTICE "Interrupt context\n"); else if (context & 0x4000) - printk(KERN_NOTICE "Deferred Interrupt context\n"); + verbose_printk(KERN_NOTICE "Deferred Interrupt context\n"); else if (context & 0x8000) - printk(KERN_NOTICE "Kernel process context\n"); + verbose_printk(KERN_NOTICE "Kernel process context\n"); /* Because we are crashing, and pointers could be bad, we check things * pretty closely before we use them */ if ((unsigned long)current >= FIXED_CODE_START && !((unsigned long)current & 0x3) && current->pid) { - printk(KERN_NOTICE "CURRENT PROCESS:\n"); + verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n"); if (current->comm >= (char *)FIXED_CODE_START) - printk(KERN_NOTICE "COMM=%s PID=%d\n", + verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n", current->comm, current->pid); else - printk(KERN_NOTICE "COMM= invalid\n"); + verbose_printk(KERN_NOTICE "COMM= invalid\n"); if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) - printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" + verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" KERN_NOTICE "\n", (void *)current->mm->start_code, @@ -944,26 +969,28 @@ void dump_bfin_process(struct pt_regs *fp) (void *)current->mm->brk, (void *)current->mm->start_stack); else - printk(KERN_NOTICE "invalid mm\n"); + verbose_printk(KERN_NOTICE "invalid mm\n"); } else - printk(KERN_NOTICE "\n" KERN_NOTICE + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "No Valid process in current context\n"); +#endif } void dump_bfin_mem(struct pt_regs *fp) { +#ifdef CONFIG_DEBUG_VERBOSE unsigned short *addr, *erraddr, val = 0, err = 0; char sti = 0, buf[6]; erraddr = (void *)fp->pc; - printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); + verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10; addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; addr++) { if (!((unsigned long)addr & 0xF)) - printk("\n" KERN_NOTICE "0x%p: ", addr); + verbose_printk("\n" KERN_NOTICE "0x%p: ", addr); if (!get_instruction(&val, addr)) { val = 0; @@ -972,10 +999,10 @@ void dump_bfin_mem(struct pt_regs *fp) sprintf(buf, "%04x", val); if (addr == erraddr) { - printk("[%s]", buf); + verbose_printk("[%s]", buf); err = val; } else - printk(" %s ", buf); + verbose_printk(" %s ", buf); /* Do any previous instructions turn on interrupts? */ if (addr <= erraddr && /* in the past */ @@ -984,14 +1011,14 @@ void dump_bfin_mem(struct pt_regs *fp) sti = 1; } - printk("\n"); + verbose_printk("\n"); /* Hardware error interrupts can be deferred */ if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR && oops_in_progress)){ - printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); + verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); #ifndef CONFIG_DEBUG_HWERR - printk(KERN_NOTICE "The remaining message may be meaningless\n" + verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n" KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" " better idea where it came from\n"); #else @@ -1005,45 +1032,47 @@ void dump_bfin_mem(struct pt_regs *fp) /* And the last RETI points to the current userspace context */ if ((fp + 1)->pc >= current->mm->start_code && (fp + 1)->pc <= current->mm->end_code) { - printk(KERN_NOTICE "It might be better to look around here : \n"); - printk(KERN_NOTICE "-------------------------------------------\n"); + verbose_printk(KERN_NOTICE "It might be better to look around here : \n"); + verbose_printk(KERN_NOTICE "-------------------------------------------\n"); show_regs(fp + 1); - printk(KERN_NOTICE "-------------------------------------------\n"); + verbose_printk(KERN_NOTICE "-------------------------------------------\n"); } } #endif } +#endif } void show_regs(struct pt_regs *fp) { +#ifdef CONFIG_DEBUG_VERBOSE char buf [150]; struct irqaction *action; unsigned int i; unsigned long flags; - printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); - printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); + verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", (long)fp->seqstat, fp->ipend, fp->syscfg); if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { - printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", + verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); #ifdef EBIU_ERRMST /* If the error was from the EBIU, print it out */ if (bfin_read_EBIU_ERRMST() & CORE_ERROR) { - printk(KERN_NOTICE " EBIU Error Reason : 0x%04x\n", + verbose_printk(KERN_NOTICE " EBIU Error Reason : 0x%04x\n", bfin_read_EBIU_ERRMST()); - printk(KERN_NOTICE " EBIU Error Address : 0x%08x\n", + verbose_printk(KERN_NOTICE " EBIU Error Address : 0x%08x\n", bfin_read_EBIU_ERRADD()); } #endif } - printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", + verbose_printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", fp->seqstat & SEQSTAT_EXCAUSE); for (i = 6; i <= 15 ; i++) { if (fp->ipend & (1 << i)) { decode_address(buf, bfin_read32(EVT0 + 4*i)); - printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); + verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); } } @@ -1056,64 +1085,65 @@ void show_regs(struct pt_regs *fp) goto unlock; decode_address(buf, (unsigned int)action->handler); - printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf); + verbose_printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf); for (action = action->next; action; action = action->next) { decode_address(buf, (unsigned int)action->handler); - printk(", %s", buf); + verbose_printk(", %s", buf); } - printk("\n"); + verbose_printk("\n"); unlock: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } } decode_address(buf, fp->rete); - printk(KERN_NOTICE " RETE: %s\n", buf); + verbose_printk(KERN_NOTICE " RETE: %s\n", buf); decode_address(buf, fp->retn); - printk(KERN_NOTICE " RETN: %s\n", buf); + verbose_printk(KERN_NOTICE " RETN: %s\n", buf); decode_address(buf, fp->retx); - printk(KERN_NOTICE " RETX: %s\n", buf); + verbose_printk(KERN_NOTICE " RETX: %s\n", buf); decode_address(buf, fp->rets); - printk(KERN_NOTICE " RETS: %s\n", buf); + verbose_printk(KERN_NOTICE " RETS: %s\n", buf); decode_address(buf, fp->pc); - printk(KERN_NOTICE " PC : %s\n", buf); + verbose_printk(KERN_NOTICE " PC : %s\n", buf); if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { decode_address(buf, saved_dcplb_fault_addr); - printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); + verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); decode_address(buf, saved_icplb_fault_addr); - printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); + verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); } - printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); - printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); + verbose_printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", fp->r0, fp->r1, fp->r2, fp->r3); - printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", + verbose_printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", fp->r4, fp->r5, fp->r6, fp->r7); - printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", + verbose_printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", fp->p0, fp->p1, fp->p2, fp->p3); - printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", + verbose_printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", fp->p4, fp->p5, fp->fp, (long)fp); - printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", + verbose_printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", fp->lb0, fp->lt0, fp->lc0); - printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", + verbose_printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", fp->lb1, fp->lt1, fp->lc1); - printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", + verbose_printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", fp->b0, fp->l0, fp->m0, fp->i0); - printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", + verbose_printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", fp->b1, fp->l1, fp->m1, fp->i1); - printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", + verbose_printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", fp->b2, fp->l2, fp->m2, fp->i2); - printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", + verbose_printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", fp->b3, fp->l3, fp->m3, fp->i3); - printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", + verbose_printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", fp->a0w, fp->a0x, fp->a1w, fp->a1x); - printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", + verbose_printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", rdusp(), fp->astat); - printk(KERN_NOTICE "\n"); + verbose_printk(KERN_NOTICE "\n"); +#endif } #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1 -- cgit v1.2.3 From f5623a3cf27284f5121296dec847a8f75e5d0691 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:51:15 +0800 Subject: Blackfin arch: update board defconfigs Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/configs/H8606_defconfig | 36 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig index ba0bee90b7e..1fc31f1b762 100644 --- a/arch/blackfin/configs/H8606_defconfig +++ b/arch/blackfin/configs/H8606_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.12 +# Linux kernel version: 2.6.22.14 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -192,7 +192,7 @@ CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=400000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # @@ -516,7 +516,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y # # CONFIG_MTD_DATAFLASH is not set CONFIG_MTD_M25P80=y -CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_M25PXX_USE_FAST_READ is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set @@ -635,25 +635,25 @@ CONFIG_INPUT=y # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set -CONFIG_INPUT_MISC=y -# CONFIG_INPUT_ATI_REMOTE is not set -# CONFIG_INPUT_ATI_REMOTE2 is not set -# CONFIG_INPUT_KEYSPAN_REMOTE is not set -# CONFIG_INPUT_POWERMATE is not set -# CONFIG_INPUT_YEALINK is not set -# CONFIG_INPUT_UINPUT is not set -# CONFIG_BF53X_PFBUTTONS is not set +# CONFIG_INPUT_MISC is not set # # Hardware I/O ports @@ -681,7 +681,15 @@ CONFIG_BFIN_TIMER_LATENCY=y # # Serial drivers # -# CONFIG_SERIAL_8250 is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set # # Non-8250 serial port support -- cgit v1.2.3 From 6d0b8c993dc0a26fe7a9ee8b839d1964bd0debd4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 18:05:02 +0800 Subject: Blackfin arch: remove non-bf54x ifdef logic since this file is only compiled on bf54x parts Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/head.S | 49 ++++------------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S index 4d5cfeacb12..b0628164e5d 100644 --- a/arch/blackfin/mach-bf548/head.S +++ b/arch/blackfin/mach-bf548/head.S @@ -73,25 +73,19 @@ ENTRY(_start_dma_code) w[p0] = r0.l; ssync; -#if defined(CONFIG_BF54x) + /* enable self refresh via SRREQ */ P2.H = hi(EBIU_RSTCTL); P2.L = lo(EBIU_RSTCTL); R0 = [P2]; BITSET (R0, 3); -#else - P2.H = hi(EBIU_SDGCTL); - P2.L = lo(EBIU_SDGCTL); - R0 = [P2]; - BITSET (R0, 24); -#endif [P2] = R0; SSYNC; -#if defined(CONFIG_BF54x) + + /* wait for SRACK bit to be set */ .LSRR_MODE: R0 = [P2]; CC = BITTST(R0, 4); if !CC JUMP .LSRR_MODE; -#endif r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */ r0 = r0 << 9; /* Shift it over, */ @@ -123,7 +117,7 @@ ENTRY(_start_dma_code) w[p0] = r0.l; ssync; -#if defined(CONFIG_BF54x) + /* disable self refresh by clearing SRREQ */ P2.H = hi(EBIU_RSTCTL); P2.L = lo(EBIU_RSTCTL); R0 = [P2]; @@ -155,41 +149,6 @@ ENTRY(_start_dma_code) r0.h = hi(mem_DDRCTL2); [p0] = r0; ssync; -#else - p0.l = lo(EBIU_SDRRC); - p0.h = hi(EBIU_SDRRC); - r0 = mem_SDRRC; - w[p0] = r0.l; - ssync; - - p0.l = LO(EBIU_SDBCTL); - p0.h = HI(EBIU_SDBCTL); /* SDRAM Memory Bank Control Register */ - r0 = mem_SDBCTL; - w[p0] = r0.l; - ssync; - - P2.H = hi(EBIU_SDGCTL); - P2.L = lo(EBIU_SDGCTL); - R0 = [P2]; - BITCLR (R0, 24); - p0.h = hi(EBIU_SDSTAT); - p0.l = lo(EBIU_SDSTAT); - r2.l = w[p0]; - cc = bittst(r2,3); - if !cc jump .Lskip; - NOP; - BITSET (R0, 23); -.Lskip: - [P2] = R0; - SSYNC; - - R0.L = lo(mem_SDGCTL); - R0.H = hi(mem_SDGCTL); - R1 = [p2]; - R1 = R1 | R0; - [P2] = R1; - SSYNC; -#endif RTS; ENDPROC(_start_dma_code) -- cgit v1.2.3 From e482cad241c0b7108cbc94959307a73d19ba17d5 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Fri, 10 Oct 2008 18:21:45 +0800 Subject: Blackfin arch: print out error/warning if you are running on the incorrect CPU type Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/processor.h | 6 ++++ arch/blackfin/kernel/setup.c | 43 +++++++++++++++++---------- arch/blackfin/mach-bf527/include/mach/bf527.h | 19 ++++++++++-- arch/blackfin/mach-bf533/include/mach/bf533.h | 10 +++---- arch/blackfin/mach-bf537/include/mach/bf537.h | 10 +++---- arch/blackfin/mach-bf548/include/mach/bf548.h | 23 +++++++------- arch/blackfin/mach-bf561/include/mach/bf561.h | 6 ++-- 7 files changed, 76 insertions(+), 41 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index 6f3995b119d..e3e9b41fa8d 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h @@ -134,6 +134,12 @@ static inline uint32_t __pure bfin_revid(void) return revid; } +static inline uint16_t __pure bfin_cpuid(void) +{ + return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12; + +} + static inline uint32_t __pure bfin_compiled_revid(void) { #if defined(CONFIG_BF_REV_0_0) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 4267523912b..74370f3707b 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -813,17 +813,23 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU); else printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid()); - if (bfin_revid() != bfin_compiled_revid()) { - if (bfin_compiled_revid() == -1) - printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n", - bfin_revid()); - else if (bfin_compiled_revid() != 0xffff) - printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", - bfin_compiled_revid(), bfin_revid()); + + if (unlikely(CPUID != bfin_cpuid())) + printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", + CPU, bfin_cpuid(), bfin_revid()); + else { + if (bfin_revid() != bfin_compiled_revid()) { + if (bfin_compiled_revid() == -1) + printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n", + bfin_revid()); + else if (bfin_compiled_revid() != 0xffff) + printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", + bfin_compiled_revid(), bfin_revid()); + } + if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) + printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", + CPU, bfin_revid()); } - if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) - printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", - CPU, bfin_revid()); printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); @@ -997,13 +1003,18 @@ static int show_cpuinfo(struct seq_file *m, void *v) } seq_printf(m, "processor\t: %d\n" - "vendor_id\t: %s\n" - "cpu family\t: 0x%x\n" - "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" - "stepping\t: %d\n", + "vendor_id\t: %s\n", *(unsigned int *)v, - vendor, - (bfin_read_CHIPID() & CHIPID_FAMILY), + vendor); + + if (CPUID == bfin_cpuid()) + seq_printf(m, "cpu family\t: 0x%04x\n", CPUID); + else + seq_printf(m, "cpu family\t: Compiled for:0x%04x, running on:0x%04x\n", + CPUID, bfin_cpuid()); + + seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" + "stepping\t: %d\n", cpu, cclk/1000000, sclk/1000000, #ifdef CONFIG_MPU "mpu on", diff --git a/arch/blackfin/mach-bf527/include/mach/bf527.h b/arch/blackfin/mach-bf527/include/mach/bf527.h index 330041fde54..144f08d3f8e 100644 --- a/arch/blackfin/mach-bf527/include/mach/bf527.h +++ b/arch/blackfin/mach-bf527/include/mach/bf527.h @@ -110,16 +110,31 @@ #ifdef CONFIG_BF527 #define CPU "BF527" +#define CPUID 0x27e4 +#endif +#ifdef CONFIG_BF526 +#define CPU "BF526" +#define CPUID 0x27e4 #endif #ifdef CONFIG_BF525 #define CPU "BF525" +#define CPUID 0x27e4 +#endif +#ifdef CONFIG_BF524 +#define CPU "BF524" +#define CPUID 0x27e4 +#endif +#ifdef CONFIG_BF523 +#define CPU "BF523" +#define CPUID 0x27e4 #endif #ifdef CONFIG_BF522 #define CPU "BF522" +#define CPUID 0x27e4 #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF527_H__ */ diff --git a/arch/blackfin/mach-bf533/include/mach/bf533.h b/arch/blackfin/mach-bf533/include/mach/bf533.h index 94980111230..dfc8c1ad2d7 100644 --- a/arch/blackfin/mach-bf533/include/mach/bf533.h +++ b/arch/blackfin/mach-bf533/include/mach/bf533.h @@ -141,19 +141,19 @@ #ifdef CONFIG_BF533 #define CPU "BF533" -#define CPUID 0x027a5000 +#define CPUID 0x27a5 #endif #ifdef CONFIG_BF532 #define CPU "BF532" -#define CPUID 0x0275A000 +#define CPUID 0x275A #endif #ifdef CONFIG_BF531 #define CPU "BF531" -#define CPUID 0x027a5000 +#define CPUID 0x27a5 #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF533_H__ */ diff --git a/arch/blackfin/mach-bf537/include/mach/bf537.h b/arch/blackfin/mach-bf537/include/mach/bf537.h index 7a047e04e38..24d5c9d4232 100644 --- a/arch/blackfin/mach-bf537/include/mach/bf537.h +++ b/arch/blackfin/mach-bf537/include/mach/bf537.h @@ -121,19 +121,19 @@ #ifdef CONFIG_BF537 #define CPU "BF537" -#define CPUID 0x027c8000 +#define CPUID 0x27c8 #endif #ifdef CONFIG_BF536 #define CPU "BF536" -#define CPUID 0x027c8000 +#define CPUID 0x27c8 #endif #ifdef CONFIG_BF534 #define CPU "BF534" -#define CPUID 0x027c6000 +#define CPUID 0x27c6 #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF537_H__ */ diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h index 14f8a7b8454..49f9b403d45 100644 --- a/arch/blackfin/mach-bf548/include/mach/bf548.h +++ b/arch/blackfin/mach-bf548/include/mach/bf548.h @@ -106,20 +106,23 @@ #if defined(CONFIG_BF542) # define CPU "BF542" -# define CPUID 0x027c8000 +# define CPUID 0x27de #elif defined(CONFIG_BF544) -# define CPU "BF544" -# define CPUID 0x027c8000 +# define CPU "BF544" +# define CPUID 0x27de #elif defined(CONFIG_BF547) -# define CPU "BF547" +# define CPU "BF547" +# define CPUID 0x27de #elif defined(CONFIG_BF548) -# define CPU "BF548" -# define CPUID 0x027c6000 +# define CPU "BF548" +# define CPUID 0x27de #elif defined(CONFIG_BF549) -# define CPU "BF549" -#else -# define CPU "UNKNOWN" -# define CPUID 0x0 +# define CPU "BF549" +# define CPUID 0x27de +#endif + +#ifndef CPU +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF48_H__ */ diff --git a/arch/blackfin/mach-bf561/include/mach/bf561.h b/arch/blackfin/mach-bf561/include/mach/bf561.h index 7787caad355..18b1b3a223a 100644 --- a/arch/blackfin/mach-bf561/include/mach/bf561.h +++ b/arch/blackfin/mach-bf561/include/mach/bf561.h @@ -211,11 +211,11 @@ #ifdef CONFIG_BF561 #define CPU "BF561" -#define CPUID 0x027bb000 +#define CPUID 0x27bb #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF561_H__ */ -- cgit v1.2.3 From 9a6f5ae1f1f3c37aad938a1c82db248a3f95a629 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 18:57:21 +0800 Subject: Blackfin arch: bfin_reset() is an internal reboot function ... everyone should go through machine_restart() Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin-global.h | 1 - arch/blackfin/kernel/reboot.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index f842ea3bfc1..56dcb0a2d24 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h @@ -63,7 +63,6 @@ extern void bfin_dcache_init(void); extern void init_exception_vectors(void); extern void program_IAR(void); -extern void bfin_reset(void); extern asmlinkage void lower_to_irq14(void); extern asmlinkage void bfin_return_from_exception(void); extern asmlinkage void evt14_softirq(void); diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index b0a8f89cc9b..d0ead640d99 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -20,7 +20,7 @@ * the core reset. */ __attribute__((l1_text)) -void bfin_reset(void) +static void bfin_reset(void) { /* Wait for completion of "system" events such as cache line * line fills so that we avoid infinite stalls later on as -- cgit v1.2.3 From 5dc64a3442b98eaa0e3730c35fcf00cf962a93e7 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 10 Oct 2008 11:27:38 +0100 Subject: xen: do not reserve 2 pages of padding between hypervisor and fixmap. When reserving space for the hypervisor the Xen paravirt backend adds an extra two pages (this was carried forward from the 2.6.18-xen tree which had them "for safety"). Depending on various CONFIG options this can cause the boot time fixmaps to span multiple PMDs which is not supported and triggers a WARN in early_ioremap_init(). This was exposed by 2216d199b1430d1c0affb1498a9ebdbd9c0de439 which moved the dmi table parsing earlier. x86: fix CONFIG_X86_RESERVE_LOW_64K=y The bad_bios_dmi_table() quirk never triggered because we do DMI setup too late. Move it a bit earlier. There is no real reason to reserve these two extra pages and the fixmap already incorporates FIX_HOLE which serves the same purpose. None of the other callers of reserve_top_address do this. Signed-off-by: Ian Campbell Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 85692c9f649..977a54255fb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1370,7 +1370,7 @@ static void __init xen_reserve_top(void) if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) top = pp.virt_start; - reserve_top_address(-top + 2 * PAGE_SIZE); + reserve_top_address(-top); #endif /* CONFIG_X86_32 */ } -- cgit v1.2.3 From d6b52039c95556ade5c4f99592a0dc46473fbf93 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 29 Sep 2008 23:14:11 +0400 Subject: ALSA: Correct Vladimir Barinov's e-mail address Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- arch/arm/plat-omap/include/mach/mtd-xip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/mach/mtd-xip.h b/arch/arm/plat-omap/include/mach/mtd-xip.h index 5cee7e16a1b..39b591ff54b 100644 --- a/arch/arm/plat-omap/include/mach/mtd-xip.h +++ b/arch/arm/plat-omap/include/mach/mtd-xip.h @@ -3,7 +3,7 @@ * * Do not include this file directly. It's included from linux/mtd/xip.h * - * Author: Vladimir Barinov + * Author: Vladimir Barinov * * (c) 2005 MontaVista Software, Inc. This file is licensed under the * terms of the GNU General Public License version 2. This program is -- cgit v1.2.3 From 4e8086d65bd0a606434a4b16611653387f8c9698 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 21:07:55 +0800 Subject: Blackfin arch: update anomaly headers to match the latest sheet Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf527/include/mach/anomaly.h | 158 +++++++++++++++++------- arch/blackfin/mach-bf533/include/mach/anomaly.h | 49 ++++---- arch/blackfin/mach-bf537/include/mach/anomaly.h | 2 + arch/blackfin/mach-bf548/include/mach/anomaly.h | 91 ++++++++++++-- arch/blackfin/mach-bf561/include/mach/anomaly.h | 2 + 5 files changed, 227 insertions(+), 75 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h index dc26912430e..62373e61c58 100644 --- a/arch/blackfin/mach-bf527/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h @@ -7,12 +7,24 @@ */ /* This file shoule be up to date with: - * - Revision C, 01/25/2008; ADSP-BF527 Blackfin Processor Anomaly List + * - Revision B, 08/12/2008; ADSP-BF526 Blackfin Processor Anomaly List + * - Revision E, 08/18/2008; ADSP-BF527 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ #define _MACH_ANOMALY_H_ +#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) +# define ANOMALY_BF526 1 +#else +# define ANOMALY_BF526 0 +#endif +#if defined(__ADSPBF523__) || defined(__ADSPBF525__) || defined(__ADSPBF527__) +# define ANOMALY_BF527 1 +#else +# define ANOMALY_BF527 0 +#endif + /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */ #define ANOMALY_05000074 (1) /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */ @@ -23,70 +35,124 @@ #define ANOMALY_05000245 (1) /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */ #define ANOMALY_05000265 (1) -/* New Feature: EMAC TX DMA Word Alignment */ -#define ANOMALY_05000285 (1) +/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */ +#define ANOMALY_05000310 (1) /* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */ -#define ANOMALY_05000312 (1) +#define ANOMALY_05000312 (ANOMALY_BF527) +/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */ +#define ANOMALY_05000313 (__SILICON_REVISION__ < 2) /* Incorrect Access of OTP_STATUS During otp_write() Function */ -#define ANOMALY_05000328 (1) +#define ANOMALY_05000328 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */ -#define ANOMALY_05000337 (1) +#define ANOMALY_05000337 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */ -#define ANOMALY_05000341 (1) +#define ANOMALY_05000341 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* TWI May Not Operate Correctly Under Certain Signal Termination Conditions */ -#define ANOMALY_05000342 (1) +#define ANOMALY_05000342 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* USB Calibration Value Is Not Initialized */ -#define ANOMALY_05000346 (1) +#define ANOMALY_05000346 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* USB Calibration Value to use */ #define ANOMALY_05000346_value 0xE510 /* Preboot Routine Incorrectly Alters Reset Value of USB Register */ -#define ANOMALY_05000347 (1) +#define ANOMALY_05000347 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Security Features Are Not Functional */ -#define ANOMALY_05000348 (__SILICON_REVISION__ < 1) +#define ANOMALY_05000348 (ANOMALY_BF527 && __SILICON_REVISION__ < 1) +/* bfrom_SysControl() Firmware Function Performs Improper System Reset */ +#define ANOMALY_05000353 (ANOMALY_BF526) /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */ -#define ANOMALY_05000355 (1) +#define ANOMALY_05000355 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ -#define ANOMALY_05000357 (1) +#define ANOMALY_05000357 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Incorrect Revision Number in DSPID Register */ -#define ANOMALY_05000364 (__SILICON_REVISION__ > 0) +#define ANOMALY_05000364 (ANOMALY_BF527 && __SILICON_REVISION__ == 1) /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */ #define ANOMALY_05000366 (1) -/* New Feature: Higher Default CCLK Rate */ -#define ANOMALY_05000368 (1) +/* Incorrect Default CSEL Value in PLL_DIV */ +#define ANOMALY_05000368 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ -#define ANOMALY_05000371 (1) +#define ANOMALY_05000371 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Authentication Fails To Initiate */ -#define ANOMALY_05000376 (__SILICON_REVISION__ > 0) +#define ANOMALY_05000376 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Data Read From L3 Memory by USB DMA May be Corrupted */ -#define ANOMALY_05000380 (1) -/* USB Full-speed Mode not Fully Tested */ -#define ANOMALY_05000381 (1) -/* New Feature: Boot from OTP Memory */ -#define ANOMALY_05000385 (1) -/* New Feature: bfrom_SysControl() Routine */ -#define ANOMALY_05000386 (1) -/* New Feature: Programmable Preboot Settings */ -#define ANOMALY_05000387 (1) +#define ANOMALY_05000380 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* 8-Bit NAND Flash Boot Mode Not Functional */ +#define ANOMALY_05000382 (__SILICON_REVISION__ < 2) +/* Host Must Not Read Back During Host DMA Boot */ +#define ANOMALY_05000384 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Boot from OTP Memory Not Functional */ +#define ANOMALY_05000385 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* bfrom_SysControl() Firmware Routine Not Functional */ +#define ANOMALY_05000386 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Programmable Preboot Settings Not Functional */ +#define ANOMALY_05000387 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* CRC32 Checksum Support Not Functional */ +#define ANOMALY_05000388 (__SILICON_REVISION__ < 2) /* Reset Vector Must Not Be in SDRAM Memory Space */ -#define ANOMALY_05000389 (1) -/* New Feature: pTempCurrent Added to ADI_BOOT_DATA Structure */ -#define ANOMALY_05000392 (1) -/* New Feature: dTempByteCount Value Increased in ADI_BOOT_DATA Structure */ -#define ANOMALY_05000393 (1) -/* New Feature: Log Buffer Functionality */ -#define ANOMALY_05000394 (1) -/* New Feature: Hook Routine Functionality */ -#define ANOMALY_05000395 (1) -/* New Feature: Header Indirect Bit */ -#define ANOMALY_05000396 (1) -/* New Feature: BK_ONES, BK_ZEROS, and BK_DATECODE Constants */ -#define ANOMALY_05000397 (1) -/* New Feature: SWRESET, DFRESET and WDRESET Bits Added to SYSCR Register */ -#define ANOMALY_05000398 (1) -/* New Feature: BCODE_NOBOOT Added to BCODE Field of SYSCR Register */ -#define ANOMALY_05000399 (1) +#define ANOMALY_05000389 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000392 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000393 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Log Buffer Not Functional */ +#define ANOMALY_05000394 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Hook Routine Not Functional */ +#define ANOMALY_05000395 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Header Indirect Bit Not Functional */ +#define ANOMALY_05000396 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */ +#define ANOMALY_05000397 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* SWRESET, DFRESET and WDRESET Bits in the SYSCR Register Not Functional */ +#define ANOMALY_05000398 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* BCODE_NOBOOT in BCODE Field of SYSCR Register Not Functional */ +#define ANOMALY_05000399 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* PPI Data Signals D0 and D8 do not Tristate After Disabling PPI */ -#define ANOMALY_05000401 (1) +#define ANOMALY_05000401 (__SILICON_REVISION__ < 2) +/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */ +#define ANOMALY_05000403 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Disallows Certain User Interrupts */ +#define ANOMALY_05000404 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Firmware Does Not Save/Restore Full Context */ +#define ANOMALY_05000405 (1) +/* Lockbox SESR Firmware Arguments Are Not Retained After First Initialization */ +#define ANOMALY_05000407 (__SILICON_REVISION__ < 2) +/* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */ +#define ANOMALY_05000408 (1) +/* Lockbox firmware leaves MDMA0 channel enabled */ +#define ANOMALY_05000409 (__SILICON_REVISION__ < 2) +/* Incorrect Default Internal Voltage Regulator Setting */ +#define ANOMALY_05000410 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */ +#define ANOMALY_05000411 (__SILICON_REVISION__ < 2) +/* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */ +#define ANOMALY_05000414 (__SILICON_REVISION__ < 2) +/* DEB2_URGENT Bit Not Functional */ +#define ANOMALY_05000415 (__SILICON_REVISION__ < 2) +/* Speculative Fetches Can Cause Undesired External FIFO Operations */ +#define ANOMALY_05000416 (1) +/* SPORT0 Ignores External TSCLK0 on PG14 When TMR6 is an Output */ +#define ANOMALY_05000417 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* tSFSPE and tHFSPE Do Not Meet Data Sheet Specifications */ +#define ANOMALY_05000418 (__SILICON_REVISION__ < 2) +/* USB PLL_STABLE Bit May Not Accurately Reflect the USB PLL's Status */ +#define ANOMALY_05000420 (__SILICON_REVISION__ < 2) +/* TWI Fall Time (Tof) May Violate the Minimum I2C Specification */ +#define ANOMALY_05000421 (1) +/* TWI Input Capacitance (Ci) May Violate the Maximum I2C Specification */ +#define ANOMALY_05000422 (ANOMALY_BF527 && __SILICON_REVISION__ > 1) +/* Certain Ethernet Frames With Errors are Misclassified in RMII Mode */ +#define ANOMALY_05000423 (__SILICON_REVISION__ < 2) +/* Internal Voltage Regulator Not Trimmed */ +#define ANOMALY_05000424 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Multichannel SPORT Channel Misalignment Under Specific Configuration */ +#define ANOMALY_05000425 (__SILICON_REVISION__ < 2) +/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */ +#define ANOMALY_05000426 (1) +/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Reflects Buffer Status Instead of IRQ Status */ +#define ANOMALY_05000429 (__SILICON_REVISION__ < 2) +/* Software System Reset Corrupts PLL_LOCKCNT Register */ +#define ANOMALY_05000430 (ANOMALY_BF527 && __SILICON_REVISION__ > 1) +/* bfrom_SysControl() Does Not Clear SIC_IWR1 Before Executing PLL Programming Sequence */ +#define ANOMALY_05000432 (ANOMALY_BF526) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000125 (0) @@ -99,6 +165,8 @@ #define ANOMALY_05000263 (0) #define ANOMALY_05000266 (0) #define ANOMALY_05000273 (0) +#define ANOMALY_05000285 (0) +#define ANOMALY_05000307 (0) #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) #define ANOMALY_05000363 (0) diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h index 8f7ea112fd3..f544fc56959 100644 --- a/arch/blackfin/mach-bf533/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h @@ -7,7 +7,7 @@ */ /* This file shoule be up to date with: - * - Revision C, 02/08/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List + * - Revision D, 06/18/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -97,11 +97,11 @@ /* UART STB Bit Incorrectly Affects Receiver Setting */ #define ANOMALY_05000231 (__SILICON_REVISION__ < 5) /* PPI_FS3 Is Not Driven in 2 or 3 Internal Frame Sync Transmit Modes */ -#define ANOMALY_05000233 (__SILICON_REVISION__ < 4) +#define ANOMALY_05000233 (__SILICON_REVISION__ < 6) /* Incorrect Revision Number in DSPID Register */ #define ANOMALY_05000234 (__SILICON_REVISION__ == 4) /* DF Bit in PLL_CTL Register Does Not Respond to Hardware Reset */ -#define ANOMALY_05000242 (__SILICON_REVISION__ < 4) +#define ANOMALY_05000242 (__SILICON_REVISION__ < 5) /* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */ #define ANOMALY_05000244 (__SILICON_REVISION__ < 5) /* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */ @@ -131,7 +131,7 @@ /* CSYNC/SSYNC/IDLE Causes Infinite Stall in Penultimate Instruction in Hardware Loop */ #define ANOMALY_05000264 (__SILICON_REVISION__ < 5) /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */ -#define ANOMALY_05000265 (__SILICON_REVISION__ < 5) +#define ANOMALY_05000265 (1) /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Increase */ #define ANOMALY_05000269 (__SILICON_REVISION__ < 5) /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */ @@ -141,56 +141,59 @@ /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */ #define ANOMALY_05000272 (1) /* Writes to Synchronous SDRAM Memory May Be Lost */ -#define ANOMALY_05000273 (1) +#define ANOMALY_05000273 (__SILICON_REVISION__ < 6) /* Timing Requirements Change for External Frame Sync PPI Modes with Non-Zero PPI_DELAY */ #define ANOMALY_05000276 (1) /* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */ -#define ANOMALY_05000277 (1) +#define ANOMALY_05000277 (__SILICON_REVISION__ < 6) /* Disabling Peripherals with DMA Running May Cause DMA System Instability */ -#define ANOMALY_05000278 (1) +#define ANOMALY_05000278 (__SILICON_REVISION__ < 6) /* False Hardware Error Exception When ISR Context Is Not Restored */ -#define ANOMALY_05000281 (1) +#define ANOMALY_05000281 (__SILICON_REVISION__ < 6) /* Memory DMA Corruption with 32-Bit Data and Traffic Control */ -#define ANOMALY_05000282 (1) +#define ANOMALY_05000282 (__SILICON_REVISION__ < 6) /* System MMR Write Is Stalled Indefinitely When Killed in a Particular Stage */ -#define ANOMALY_05000283 (1) +#define ANOMALY_05000283 (__SILICON_REVISION__ < 6) /* SPORTs May Receive Bad Data If FIFOs Fill Up */ -#define ANOMALY_05000288 (1) +#define ANOMALY_05000288 (__SILICON_REVISION__ < 6) /* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */ -#define ANOMALY_05000301 (1) +#define ANOMALY_05000301 (__SILICON_REVISION__ < 6) /* SSYNCs After Writes To DMA MMR Registers May Not Be Handled Correctly */ #define ANOMALY_05000302 (__SILICON_REVISION__ < 5) /* New Feature: Additional Hysteresis on SPORT Input Pins (Not Available On Older Silicon) */ #define ANOMALY_05000305 (__SILICON_REVISION__ < 5) /* New Feature: Additional PPI Frame Sync Sampling Options (Not Available On Older Silicon) */ #define ANOMALY_05000306 (__SILICON_REVISION__ < 5) +/* SCKELOW Bit Does Not Maintain State Through Hibernate */ +#define ANOMALY_05000307 (1) /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */ #define ANOMALY_05000310 (1) /* Erroneous Flag (GPIO) Pin Operations under Specific Sequences */ -#define ANOMALY_05000311 (1) +#define ANOMALY_05000311 (__SILICON_REVISION__ < 6) /* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */ -#define ANOMALY_05000312 (1) +#define ANOMALY_05000312 (__SILICON_REVISION__ < 6) /* PPI Is Level-Sensitive on First Transfer */ -#define ANOMALY_05000313 (1) +#define ANOMALY_05000313 (__SILICON_REVISION__ < 6) /* Killed System MMR Write Completes Erroneously On Next System MMR Access */ -#define ANOMALY_05000315 (1) +#define ANOMALY_05000315 (__SILICON_REVISION__ < 6) /* Internal Voltage Regulator Values of 1.05V, 1.10V and 1.15V Not Allowed for LQFP Packages */ -#define ANOMALY_05000319 (ANOMALY_BF531 || ANOMALY_BF532) +#define ANOMALY_05000319 ((ANOMALY_BF531 || ANOMALY_BF532) && __SILICON_REVISION__ < 6) /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ -#define ANOMALY_05000357 (1) +#define ANOMALY_05000357 (__SILICON_REVISION__ < 6) /* UART Break Signal Issues */ #define ANOMALY_05000363 (__SILICON_REVISION__ < 5) /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */ #define ANOMALY_05000366 (1) /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ -#define ANOMALY_05000371 (1) +#define ANOMALY_05000371 (__SILICON_REVISION__ < 6) /* PPI Does Not Start Properly In Specific Mode */ -#define ANOMALY_05000400 (__SILICON_REVISION__ >= 5) +#define ANOMALY_05000400 (__SILICON_REVISION__ == 5) /* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */ -#define ANOMALY_05000402 (__SILICON_REVISION__ >= 5) +#define ANOMALY_05000402 (__SILICON_REVISION__ == 5) /* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */ #define ANOMALY_05000403 (1) - +/* Speculative Fetches Can Cause Undesired External FIFO Operations */ +#define ANOMALY_05000416 (1) /* These anomalies have been "phased" out of analog.com anomaly sheets and are * here to show running on older silicon just isn't feasible. @@ -268,5 +271,7 @@ /* Anomalies that don't exist on this proc */ #define ANOMALY_05000266 (0) #define ANOMALY_05000323 (0) +#define ANOMALY_05000353 (1) +#define ANOMALY_05000386 (1) #endif diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h index 8460ab9c324..c68992494f9 100644 --- a/arch/blackfin/mach-bf537/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h @@ -158,6 +158,8 @@ #define ANOMALY_05000266 (0) #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) +#define ANOMALY_05000353 (1) #define ANOMALY_05000363 (0) +#define ANOMALY_05000386 (1) #endif diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h index d02cd803828..816b09278f6 100644 --- a/arch/blackfin/mach-bf548/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h @@ -2,18 +2,18 @@ * File: include/asm-blackfin/mach-bf548/anomaly.h * Bugs: Enter bugs at http://blackfin.uclinux.org/ * - * Copyright (C) 2004-2007 Analog Devices Inc. + * Copyright (C) 2004-2008 Analog Devices Inc. * Licensed under the GPL-2 or later. */ /* This file shoule be up to date with: - * - Revision E, 11/28/2007; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List + * - Revision G, 08/07/2008; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ #define _MACH_ANOMALY_H_ -/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot 2 Not Supported */ +/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */ #define ANOMALY_05000074 (1) /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */ #define ANOMALY_05000119 (1) @@ -36,14 +36,14 @@ /* TWI Slave Boot Mode Is Not Functional */ #define ANOMALY_05000324 (__SILICON_REVISION__ < 1) /* External FIFO Boot Mode Is Not Functional */ -#define ANOMALY_05000325 (__SILICON_REVISION__ < 1) +#define ANOMALY_05000325 (__SILICON_REVISION__ < 2) /* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */ #define ANOMALY_05000327 (__SILICON_REVISION__ < 1) /* Incorrect Access of OTP_STATUS During otp_write() Function */ #define ANOMALY_05000328 (__SILICON_REVISION__ < 1) /* Synchronous Burst Flash Boot Mode Is Not Functional */ #define ANOMALY_05000329 (__SILICON_REVISION__ < 1) -/* Host DMA Boot Mode Is Not Functional */ +/* Host DMA Boot Modes Are Not Functional */ #define ANOMALY_05000330 (__SILICON_REVISION__ < 1) /* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */ #define ANOMALY_05000334 (__SILICON_REVISION__ < 1) @@ -63,26 +63,100 @@ #define ANOMALY_05000346 (__SILICON_REVISION__ < 1) /* USB Calibration Value to use */ #define ANOMALY_05000346_value 0x5411 -/* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */ +/* Preboot Routine Incorrectly Alters Reset Value of USB Register */ #define ANOMALY_05000347 (__SILICON_REVISION__ < 1) /* Data Lost when Core Reads SDH Data FIFO */ #define ANOMALY_05000349 (__SILICON_REVISION__ < 1) /* PLL Status Register Is Inaccurate */ #define ANOMALY_05000351 (__SILICON_REVISION__ < 1) +/* bfrom_SysControl() Firmware Function Performs Improper System Reset */ +#define ANOMALY_05000353 (__SILICON_REVISION__ < 2) +/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */ +#define ANOMALY_05000355 (__SILICON_REVISION__ < 1) +/* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */ +#define ANOMALY_05000356 (__SILICON_REVISION__ < 1) /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ #define ANOMALY_05000357 (1) /* External Memory Read Access Hangs Core With PLL Bypass */ #define ANOMALY_05000360 (1) /* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */ #define ANOMALY_05000365 (1) +/* WURESET Bit In SYSCR Register Does Not Properly Indicate Hibernate Wake-Up */ +#define ANOMALY_05000367 (__SILICON_REVISION__ < 1) /* Addressing Conflict between Boot ROM and Asynchronous Memory */ #define ANOMALY_05000369 (1) +/* Default PLL MSEL and SSEL Settings Can Cause 400MHz Product To Violate Specifications */ +#define ANOMALY_05000370 (__SILICON_REVISION__ < 1) /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ -#define ANOMALY_05000371 (1) +#define ANOMALY_05000371 (__SILICON_REVISION__ < 2) +/* USB DP/DM Data Pins May Lose State When Entering Hibernate */ +#define ANOMALY_05000372 (__SILICON_REVISION__ < 1) /* Mobile DDR Operation Not Functional */ #define ANOMALY_05000377 (1) /* Security/Authentication Speedpath Causes Authentication To Fail To Initiate */ -#define ANOMALY_05000378 (1) +#define ANOMALY_05000378 (__SILICON_REVISION__ < 2) +/* 16-Bit NAND FLASH Boot Mode Is Not Functional */ +#define ANOMALY_05000379 (1) +/* 8-Bit NAND Flash Boot Mode Not Functional */ +#define ANOMALY_05000382 (__SILICON_REVISION__ < 1) +/* Some ATAPI Modes Are Not Functional */ +#define ANOMALY_05000383 (1) +/* Boot from OTP Memory Not Functional */ +#define ANOMALY_05000385 (__SILICON_REVISION__ < 1) +/* bfrom_SysControl() Firmware Routine Not Functional */ +#define ANOMALY_05000386 (__SILICON_REVISION__ < 1) +/* Programmable Preboot Settings Not Functional */ +#define ANOMALY_05000387 (__SILICON_REVISION__ < 1) +/* CRC32 Checksum Support Not Functional */ +#define ANOMALY_05000388 (__SILICON_REVISION__ < 1) +/* Reset Vector Must Not Be in SDRAM Memory Space */ +#define ANOMALY_05000389 (__SILICON_REVISION__ < 1) +/* Changed Meaning of BCODE Field in SYSCR Register */ +#define ANOMALY_05000390 (__SILICON_REVISION__ < 1) +/* Repeated Boot from Page-Mode or Burst-Mode Flash Memory May Fail */ +#define ANOMALY_05000391 (__SILICON_REVISION__ < 1) +/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000392 (__SILICON_REVISION__ < 1) +/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000393 (__SILICON_REVISION__ < 1) +/* Log Buffer Not Functional */ +#define ANOMALY_05000394 (__SILICON_REVISION__ < 1) +/* Hook Routine Not Functional */ +#define ANOMALY_05000395 (__SILICON_REVISION__ < 1) +/* Header Indirect Bit Not Functional */ +#define ANOMALY_05000396 (__SILICON_REVISION__ < 1) +/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */ +#define ANOMALY_05000397 (__SILICON_REVISION__ < 1) +/* Lockbox SESR Disallows Certain User Interrupts */ +#define ANOMALY_05000404 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Firmware Does Not Save/Restore Full Context */ +#define ANOMALY_05000405 (1) +/* Lockbox SESR Argument Checking Does Not Check L2 Memory Protection Range */ +#define ANOMALY_05000406 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Firmware Arguments Are Not Retained After First Initialization */ +#define ANOMALY_05000407 (__SILICON_REVISION__ < 2) +/* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */ +#define ANOMALY_05000408 (1) +/* Lockbox firmware leaves MDMA0 channel enabled */ +#define ANOMALY_05000409 (__SILICON_REVISION__ < 2) +/* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */ +#define ANOMALY_05000411 (__SILICON_REVISION__ < 2) +/* NAND Boot Mode Not Compatible With Some NAND Flash Devices */ +#define ANOMALY_05000413 (__SILICON_REVISION__ < 2) +/* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */ +#define ANOMALY_05000414 (__SILICON_REVISION__ < 2) +/* Speculative Fetches Can Cause Undesired External FIFO Operations */ +#define ANOMALY_05000416 (1) +/* Multichannel SPORT Channel Misalignment Under Specific Configuration */ +#define ANOMALY_05000425 (1) +/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */ +#define ANOMALY_05000426 (1) +/* CORE_EPPI_PRIO bit and SYS_EPPI_PRIO bit in the HMDMA1_CONTROL register are not functional */ +#define ANOMALY_05000427 (__SILICON_REVISION__ < 2) +/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Behaves as a Buffer Status Bit Instead of an IRQ Status Bit */ +#define ANOMALY_05000429 (__SILICON_REVISION__ < 2) +/* Software System Reset Corrupts PLL_LOCKCNT Register */ +#define ANOMALY_05000430 (__SILICON_REVISION__ >= 2) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000125 (0) @@ -95,6 +169,7 @@ #define ANOMALY_05000263 (0) #define ANOMALY_05000266 (0) #define ANOMALY_05000273 (0) +#define ANOMALY_05000307 (0) #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) #define ANOMALY_05000363 (0) diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h index 5c5d7d7d695..22990df04ae 100644 --- a/arch/blackfin/mach-bf561/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h @@ -270,5 +270,7 @@ #define ANOMALY_05000183 (0) #define ANOMALY_05000273 (0) #define ANOMALY_05000311 (0) +#define ANOMALY_05000353 (1) +#define ANOMALY_05000386 (1) #endif -- cgit v1.2.3 From 2817142f31bfbf26c216bf4f9192540c81b2d071 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sat, 20 Sep 2008 04:14:01 +0300 Subject: [WATCHDOG] omap_wdt.c: sync linux-omap changes These are changes that have been sitting in linux-omap and were never sent upstream. Hopefully, it'll never happen again at least for this driver. Signed-off-by: Felipe Balbi Signed-off-by: Wim Van Sebroeck --- arch/arm/plat-omap/devices.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 01da719a745..cc62cec1b75 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -441,16 +441,8 @@ static inline void omap_init_uwire(void) {} #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) -#ifdef CONFIG_ARCH_OMAP24XX -#define OMAP_WDT_BASE 0x48022000 -#else -#define OMAP_WDT_BASE 0xfffeb000 -#endif - static struct resource wdt_resources[] = { { - .start = OMAP_WDT_BASE, - .end = OMAP_WDT_BASE + 0x4f, .flags = IORESOURCE_MEM, }, }; @@ -464,6 +456,19 @@ static struct platform_device omap_wdt_device = { static void omap_init_wdt(void) { + if (cpu_is_omap16xx()) + wdt_resources[0].start = 0xfffeb000; + else if (cpu_is_omap2420()) + wdt_resources[0].start = 0x48022000; /* WDT2 */ + else if (cpu_is_omap2430()) + wdt_resources[0].start = 0x49016000; /* WDT2 */ + else if (cpu_is_omap343x()) + wdt_resources[0].start = 0x48314000; /* WDT2 */ + else + return; + + wdt_resources[0].end = wdt_resources[0].start + 0x4f; + (void) platform_device_register(&omap_wdt_device); } #else -- cgit v1.2.3 From 22ac92322c83334b562024414b770e48927ae963 Mon Sep 17 00:00:00 2001 From: Sylver Bruneau Date: Thu, 26 Jun 2008 10:47:45 +0200 Subject: [WATCHDOG] Orion: add hardware watchdog support This patch allows the use of the hardware watchdog in the Marvell Orion series of ARM SoCs. Signed-off-by: Sylver Bruneau Signed-off-by: Lennert Buytenhek Signed-off-by: Wim Van Sebroeck --- arch/arm/mach-orion5x/include/mach/orion5x.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index 61eb74a8886..615cc1d0818 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -153,9 +153,11 @@ #define CPU_CONF ORION5X_BRIDGE_REG(0x100) #define CPU_CTRL ORION5X_BRIDGE_REG(0x104) #define CPU_RESET_MASK ORION5X_BRIDGE_REG(0x108) +#define WDT_RESET 0x0002 #define CPU_SOFT_RESET ORION5X_BRIDGE_REG(0x10c) #define POWER_MNG_CTRL_REG ORION5X_BRIDGE_REG(0x11C) #define BRIDGE_CAUSE ORION5X_BRIDGE_REG(0x110) +#define WDT_INT_REQ 0x0008 #define BRIDGE_MASK ORION5X_BRIDGE_REG(0x114) #define BRIDGE_INT_TIMER0 0x0002 #define BRIDGE_INT_TIMER1 0x0004 -- cgit v1.2.3 From cdbf4c3c5f4909767c21f47f68f2ee57a8b36b3b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 13 Oct 2008 11:33:43 +0800 Subject: Blackfin arch: use the Blackfin on-chip ROM to do software reset when possible Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfrom.h | 85 +++++++++++++++++++++++++++++++++++++++ arch/blackfin/kernel/reboot.c | 10 ++++- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 arch/blackfin/include/asm/bfrom.h (limited to 'arch') diff --git a/arch/blackfin/include/asm/bfrom.h b/arch/blackfin/include/asm/bfrom.h new file mode 100644 index 00000000000..cfe8024c3b2 --- /dev/null +++ b/arch/blackfin/include/asm/bfrom.h @@ -0,0 +1,85 @@ +/* Blackfin on-chip ROM API + * + * Copyright 2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFROM_H__ +#define __BFROM_H__ + +#include + +/* Possible syscontrol action flags */ +#define SYSCTRL_READ 0x00000000 /* read registers */ +#define SYSCTRL_WRITE 0x00000001 /* write registers */ +#define SYSCTRL_SYSRESET 0x00000002 /* perform system reset */ +#define SYSCTRL_CORERESET 0x00000004 /* perform core reset */ +#define SYSCTRL_SOFTRESET 0x00000006 /* perform core and system reset */ +#define SYSCTRL_VRCTL 0x00000010 /* read/write VR_CTL register */ +#define SYSCTRL_EXTVOLTAGE 0x00000020 /* VDDINT supplied externally */ +#define SYSCTRL_INTVOLTAGE 0x00000000 /* VDDINT generated by on-chip regulator */ +#define SYSCTRL_OTPVOLTAGE 0x00000040 /* For Factory Purposes Only */ +#define SYSCTRL_PLLCTL 0x00000100 /* read/write PLL_CTL register */ +#define SYSCTRL_PLLDIV 0x00000200 /* read/write PLL_DIV register */ +#define SYSCTRL_LOCKCNT 0x00000400 /* read/write PLL_LOCKCNT register */ +#define SYSCTRL_PLLSTAT 0x00000800 /* read/write PLL_STAT register */ + +typedef struct ADI_SYSCTRL_VALUES { + uint16_t uwVrCtl; + uint16_t uwPllCtl; + uint16_t uwPllDiv; + uint16_t uwPllLockCnt; + uint16_t uwPllStat; +} ADI_SYSCTRL_VALUES; + +static uint32_t (* const bfrom_SysControl)(uint32_t action_flags, ADI_SYSCTRL_VALUES *power_settings, void *reserved) = (void *)0xEF000038; + +/* We need a dedicated function since we need to screw with the stack pointer + * when resetting. The on-chip ROM will save/restore registers on the stack + * when doing a system reset, so the stack cannot be outside of the chip. + */ +__attribute__((__noreturn__)) +static inline void bfrom_SoftReset(void *new_stack) +{ + while (1) + __asm__ __volatile__( + "sp = %[stack];" + "jump (%[bfrom_syscontrol]);" + : : [bfrom_syscontrol] "p"(bfrom_SysControl), + "q0"(SYSCTRL_SOFTRESET), + "q1"(0), + "q2"(NULL), + [stack] "p"(new_stack) + ); +} + +/* OTP Functions */ +static uint32_t (* const bfrom_OtpCommand)(uint32_t command, uint32_t value) = (void *)0xEF000018; +static uint32_t (* const bfrom_OtpRead)(uint32_t page, uint32_t flags, uint64_t *page_content) = (void *)0xEF00001A; +static uint32_t (* const bfrom_OtpWrite)(uint32_t page, uint32_t flags, uint64_t *page_content) = (void *)0xEF00001C; + +/* otp command: defines for "command" */ +#define OTP_INIT 0x00000001 +#define OTP_CLOSE 0x00000002 + +/* otp read/write: defines for "flags" */ +#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */ +#define OTP_UPPER_HALF 0x00000001 +#define OTP_NO_ECC 0x00000010 /* do not use ECC */ +#define OTP_LOCK 0x00000020 /* sets page protection bit for page */ +#define OTP_CHECK_FOR_PREV_WRITE 0x00000080 + +/* Return values for all functions */ +#define OTP_SUCCESS 0x00000000 +#define OTP_MASTER_ERROR 0x001 +#define OTP_WRITE_ERROR 0x003 +#define OTP_READ_ERROR 0x005 +#define OTP_ACC_VIO_ERROR 0x009 +#define OTP_DATA_MULT_ERROR 0x011 +#define OTP_ECC_MULT_ERROR 0x021 +#define OTP_PREV_WR_ERROR 0x041 +#define OTP_DATA_SB_WARN 0x100 +#define OTP_ECC_SB_WARN 0x200 + +#endif diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index d0ead640d99..ae97ca407b0 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -10,6 +10,7 @@ #include #include #include +#include /* A system soft reset makes external memory unusable so force * this function into L1. We use the compiler ssync here rather @@ -74,7 +75,14 @@ void machine_restart(char *cmd) { native_machine_restart(cmd); local_irq_disable(); - bfin_reset(); + if (ANOMALY_05000353 || ANOMALY_05000386) + bfin_reset(); + else + /* the bootrom checks to see how it was reset and will + * automatically perform a software reset for us when + * it starts executing boot + */ + asm("raise 1;"); } __attribute__((weak)) -- cgit v1.2.3 From ad5dd977430216059d8344ccc516f11be4a37082 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 21:17:11 +0800 Subject: Blackfin arch: make sure L2 start and length are always defined (fixes building on BF542) Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/include/mach/mem_map.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/mach-bf548/include/mach/mem_map.h b/arch/blackfin/mach-bf548/include/mach/mem_map.h index f99f47bc3a0..a2228428dc0 100644 --- a/arch/blackfin/mach-bf548/include/mach/mem_map.h +++ b/arch/blackfin/mach-bf548/include/mach/mem_map.h @@ -94,13 +94,13 @@ #endif /*CONFIG_BFIN_DCACHE*/ /* Level 2 Memory */ -#if !defined(CONFIG_BF542) -# define L2_START 0xFEB00000 -# if defined(CONFIG_BF544) -# define L2_LENGTH 0x10000 -# else -# define L2_LENGTH 0x20000 -# endif +#define L2_START 0xFEB00000 +#if defined(CONFIG_BF542) +# define L2_LENGTH 0 +#elif defined(CONFIG_BF544) +# define L2_LENGTH 0x10000 +#else +# define L2_LENGTH 0x20000 #endif /* Scratch Pad Memory */ -- cgit v1.2.3 From fecc8d6d5611a6b1dce4a6cff4713f390056aa1c Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Fri, 10 Oct 2008 21:23:29 +0800 Subject: Blackfin arch: Remove useless head file Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/cpumask.h | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 arch/blackfin/include/asm/cpumask.h (limited to 'arch') diff --git a/arch/blackfin/include/asm/cpumask.h b/arch/blackfin/include/asm/cpumask.h deleted file mode 100644 index b20a8e9012c..00000000000 --- a/arch/blackfin/include/asm/cpumask.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_BLACKFIN_CPUMASK_H -#define _ASM_BLACKFIN_CPUMASK_H - -#include - -#endif /* _ASM_BLACKFIN_CPUMASK_H */ -- cgit v1.2.3 From 3094c981f2d567f0a442687ced24a5340aa10b6c Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Fri, 10 Oct 2008 21:22:01 +0800 Subject: Blackfin arch: fix a typo in comments Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 74370f3707b..7054594831c 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -411,7 +411,7 @@ static __init void parse_cmdline_early(char *cmdline_p) * [_rambase, _ramstart]: kernel image * [memory_start, memory_end]: dynamic memory managed by kernel * [memory_end, _ramend]: reserved memory - * [meory_mtd_start(memory_end), + * [memory_mtd_start(memory_end), * memory_mtd_start + mtd_size]: rootfs (if any) * [_ramend - DMA_UNCACHED_REGION, * _ramend]: uncached DMA region -- cgit v1.2.3 From 43603c8df97f246e8be7b9cc92a8f968a85108bd Mon Sep 17 00:00:00 2001 From: Hans Schou Date: Thu, 9 Oct 2008 20:47:24 +0200 Subject: x86, debug: print more information about unknown CPUs Write the name of the unknown vendor_id to output instead of just "unknown". Tag changed to 'vendor_id' as used in /proc/cpuinfo Signed-off-by: Hans Schou Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cef3519b3bb..84c4040efa8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -406,7 +406,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) if (!printed) { printed++; - printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n"); + printk(KERN_ERR "CPU: vendor_id '%s' unknown, using generic init.\n", v); printk(KERN_ERR "CPU: Your system may be unstable.\n"); } -- cgit v1.2.3 From b2bc27314664c4d1a2f02e6f4cd0c32e4681d61e Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:36 -0700 Subject: x86, cpa: rename PTE attribute macros for kernel direct mapping in early boot Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_32.S | 34 +++++++++++++++------------------- arch/x86/kernel/head_64.S | 4 ++-- 2 files changed, 17 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index a7010c3a377..e835b4eea70 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -172,10 +172,6 @@ num_subarch_entries = (. - subarch_entries) / 4 * * Note that the stack is not yet set up! */ -#define PTE_ATTR 0x007 /* PRESENT+RW+USER */ -#define PDE_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */ -#define PGD_ATTR 0x001 /* PRESENT (no other attributes) */ - default_entry: #ifdef CONFIG_X86_PAE @@ -196,9 +192,9 @@ default_entry: movl $pa(pg0), %edi movl %edi, pa(init_pg_tables_start) movl $pa(swapper_pg_pmd), %edx - movl $PTE_ATTR, %eax + movl $PTE_IDENT_ATTR, %eax 10: - leal PDE_ATTR(%edi),%ecx /* Create PMD entry */ + leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ movl %ecx,(%edx) /* Store PMD entry */ /* Upper half already zero */ addl $8,%edx @@ -215,7 +211,7 @@ default_entry: * End condition: we must map up to and including INIT_MAP_BEYOND_END * bytes beyond the end of our own page tables. */ - leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp + leal (INIT_MAP_BEYOND_END+PTE_IDENT_ATTR)(%edi),%ebp cmpl %ebp,%eax jb 10b 1: @@ -224,7 +220,7 @@ default_entry: movl %eax, pa(max_pfn_mapped) /* Do early initialization of the fixmap area */ - movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax + movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8) #else /* Not PAE */ @@ -233,9 +229,9 @@ page_pde_offset = (__PAGE_OFFSET >> 20); movl $pa(pg0), %edi movl %edi, pa(init_pg_tables_start) movl $pa(swapper_pg_dir), %edx - movl $PTE_ATTR, %eax + movl $PTE_IDENT_ATTR, %eax 10: - leal PDE_ATTR(%edi),%ecx /* Create PDE entry */ + leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ movl %ecx,(%edx) /* Store identity PDE entry */ movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ addl $4,%edx @@ -249,7 +245,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20); * bytes beyond the end of our own page tables; the +0x007 is * the attribute bits */ - leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp + leal (INIT_MAP_BEYOND_END+PTE_IDENT_ATTR)(%edi),%ebp cmpl %ebp,%eax jb 10b movl %edi,pa(init_pg_tables_end) @@ -257,7 +253,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20); movl %eax, pa(max_pfn_mapped) /* Do early initialization of the fixmap area */ - movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax + movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax movl %eax,pa(swapper_pg_dir+0xffc) #endif jmp 3f @@ -634,19 +630,19 @@ ENTRY(empty_zero_page) /* Page-aligned for the benefit of paravirt? */ .align PAGE_SIZE_asm ENTRY(swapper_pg_dir) - .long pa(swapper_pg_pmd+PGD_ATTR),0 /* low identity map */ + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ # if KPMDS == 3 - .long pa(swapper_pg_pmd+PGD_ATTR),0 - .long pa(swapper_pg_pmd+PGD_ATTR+0x1000),0 - .long pa(swapper_pg_pmd+PGD_ATTR+0x2000),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0 # elif KPMDS == 2 .long 0,0 - .long pa(swapper_pg_pmd+PGD_ATTR),0 - .long pa(swapper_pg_pmd+PGD_ATTR+0x1000),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 # elif KPMDS == 1 .long 0,0 .long 0,0 - .long pa(swapper_pg_pmd+PGD_ATTR),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 # else # error "Kernel PMDs should be 1, 2 or 3" # endif diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index db3280afe88..26cfdc1d7c7 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -110,7 +110,7 @@ startup_64: movq %rdi, %rax shrq $PMD_SHIFT, %rax andq $(PTRS_PER_PMD - 1), %rax - leaq __PAGE_KERNEL_LARGE_EXEC(%rdi), %rdx + leaq __PAGE_KERNEL_IDENT_LARGE_EXEC(%rdi), %rdx leaq level2_spare_pgt(%rip), %rbx movq %rdx, 0(%rbx, %rax, 8) ident_complete: @@ -374,7 +374,7 @@ NEXT_PAGE(level2_ident_pgt) /* Since I easily can, map the first 1G. * Don't set NX because code runs from these pages. */ - PMDS(0, __PAGE_KERNEL_LARGE_EXEC, PTRS_PER_PMD) + PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD) NEXT_PAGE(level2_kernel_pgt) /* -- cgit v1.2.3 From a2699e477b8e6b17d4da64916f766dd5a2576c9c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:38 -0700 Subject: x86, cpa: make the kernel physical mapping initialization a two pass sequence In the first pass, kernel physical mapping will be setup using large or small pages but uses the same PTE attributes as that of the early PTE attributes setup by early boot code in head_[32|64].S After flushing TLB's, we go through the second pass, which setups the direct mapped PTE's with the appropriate attributes (like NX, GLOBAL etc) which are runtime detectable. This two pass mechanism conforms to the TLB app note which says: "Software should not write to a paging-structure entry in a way that would change, for any linear address, both the page size and either the page frame or attributes." Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 65 ++++++++++++++++++++++++++++++--- arch/x86/mm/init_64.c | 99 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 144 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d37f29376b0..9b5f7d7049d 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -194,11 +194,30 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - unsigned pages_2m = 0, pages_4k = 0; + unsigned pages_2m, pages_4k; + int mapping_iter; + + /* + * First iteration will setup identity mapping using large/small pages + * based on use_pse, with other attributes same as set by + * the early code in head_32.S + * + * Second iteration will setup the appropriate attributes (NX, GLOBAL..) + * as desired for the kernel identity mapping. + * + * This two pass mechanism conforms to the TLB app note which says: + * + * "Software should not write to a paging-structure entry in a way + * that would change, for any linear address, both the page size + * and either the page frame or attributes." + */ + mapping_iter = 1; if (!cpu_has_pse) use_pse = 0; +repeat: + pages_2m = pages_4k = 0; pfn = start_pfn; pgd_idx = pgd_index((pfn<> PAGE_SHIFT, PAGE_KERNEL).pte); + pages++; +repeat_set_pte: set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL)); last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE; - pages++; } - update_page_count(PG_LEVEL_4K, pages); + + if (physical_mapping_iter == 1) + update_page_count(PG_LEVEL_4K, pages); return last_map_addr; } @@ -318,7 +323,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, { unsigned long pages = 0; unsigned long last_map_addr = end; - unsigned long start = address; int i = pmd_index(address); @@ -341,15 +345,14 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, last_map_addr = phys_pte_update(pmd, address, end); spin_unlock(&init_mm.page_table_lock); + continue; } - /* Count entries we're using from level2_ident_pgt */ - if (start == 0) - pages++; - continue; + goto repeat_set_pte; } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); @@ -366,7 +369,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, pmd_populate_kernel(&init_mm, pmd, __va(pte_phys)); spin_unlock(&init_mm.page_table_lock); } - update_page_count(PG_LEVEL_2M, pages); + if (physical_mapping_iter == 1) + update_page_count(PG_LEVEL_2M, pages); return last_map_addr; } @@ -405,14 +409,18 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, } if (pud_val(*pud)) { - if (!pud_large(*pud)) + if (!pud_large(*pud)) { last_map_addr = phys_pmd_update(pud, addr, end, page_size_mask); - continue; + continue; + } + + goto repeat_set_pte; } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); @@ -430,7 +438,9 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, spin_unlock(&init_mm.page_table_lock); } __flush_tlb_all(); - update_page_count(PG_LEVEL_1G, pages); + + if (physical_mapping_iter == 1) + update_page_count(PG_LEVEL_1G, pages); return last_map_addr; } @@ -494,15 +504,54 @@ static void __init init_gbpages(void) direct_gbpages = 0; } +static int is_kernel(unsigned long pfn) +{ + unsigned long pg_addresss = pfn << PAGE_SHIFT; + + if (pg_addresss >= (unsigned long) __pa(_text) && + pg_addresss <= (unsigned long) __pa(_end)) + return 1; + + return 0; +} + static unsigned long __init kernel_physical_mapping_init(unsigned long start, unsigned long end, unsigned long page_size_mask) { - unsigned long next, last_map_addr = end; + unsigned long next, last_map_addr; + u64 cached_supported_pte_mask = __supported_pte_mask; + unsigned long cache_start = start; + unsigned long cache_end = end; + + /* + * First iteration will setup identity mapping using large/small pages + * based on page_size_mask, with other attributes same as set by + * the early code in head_64.S + * + * Second iteration will setup the appropriate attributes + * as desired for the kernel identity mapping. + * + * This two pass mechanism conforms to the TLB app note which says: + * + * "Software should not write to a paging-structure entry in a way + * that would change, for any linear address, both the page size + * and either the page frame or attributes." + * + * For now, only difference between very early PTE attributes used in + * head_64.S and here is _PAGE_NX. + */ + BUILD_BUG_ON((__PAGE_KERNEL_LARGE & ~__PAGE_KERNEL_IDENT_LARGE_EXEC) + != _PAGE_NX); + __supported_pte_mask &= ~(_PAGE_NX); + physical_mapping_iter = 1; - start = (unsigned long)__va(start); - end = (unsigned long)__va(end); +repeat: + last_map_addr = cache_end; + + start = (unsigned long)__va(cache_start); + end = (unsigned long)__va(cache_end); for (; start < end; start = next) { pgd_t *pgd = pgd_offset_k(start); @@ -514,11 +563,21 @@ static unsigned long __init kernel_physical_mapping_init(unsigned long start, next = end; if (pgd_val(*pgd)) { + /* + * Static identity mappings will be overwritten + * with run-time mappings. For example, this allows + * the static 0-1GB identity mapping to be mapped + * non-executable with this. + */ + if (is_kernel(pte_pfn(*((pte_t *) pgd)))) + goto realloc; + last_map_addr = phys_pud_update(pgd, __pa(start), __pa(end), page_size_mask); continue; } +realloc: pud = alloc_low_page(&pud_phys); last_map_addr = phys_pud_init(pud, __pa(start), __pa(next), page_size_mask); @@ -528,6 +587,16 @@ static unsigned long __init kernel_physical_mapping_init(unsigned long start, pgd_populate(&init_mm, pgd, __va(pud_phys)); spin_unlock(&init_mm.page_table_lock); } + __flush_tlb_all(); + + if (physical_mapping_iter == 1) { + physical_mapping_iter = 2; + /* + * Second iteration will set the actual desired PTE attributes. + */ + __supported_pte_mask = cached_supported_pte_mask; + goto repeat; + } return last_map_addr; } -- cgit v1.2.3 From 0b8fdcbcd287a1fbe66817491e6149841ae25705 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:39 -0700 Subject: x86, cpa: dont use large pages for kernel identity mapping with DEBUG_PAGEALLOC Don't use large pages for kernel identity mapping with DEBUG_PAGEALLOC. This will remove the need to split the large page for the allocated kernel page in the interrupt context. This will simplify cpa code(as we don't do the split any more from the interrupt context). cpa code simplication in the subsequent patches. Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 18 ++++++++++++++---- arch/x86/mm/init_64.c | 26 ++++++++++++++++++++------ 2 files changed, 34 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 9b5f7d7049d..44ccb028c35 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -777,7 +777,7 @@ void __init setup_bootmem_allocator(void) after_init_bootmem = 1; } -static void __init find_early_table_space(unsigned long end) +static void __init find_early_table_space(unsigned long end, int use_pse) { unsigned long puds, pmds, ptes, tables, start; @@ -787,7 +787,7 @@ static void __init find_early_table_space(unsigned long end) pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; tables += PAGE_ALIGN(pmds * sizeof(pmd_t)); - if (cpu_has_pse) { + if (use_pse) { unsigned long extra; extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); @@ -827,12 +827,22 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, pgd_t *pgd_base = swapper_pg_dir; unsigned long start_pfn, end_pfn; unsigned long big_page_start; +#ifdef CONFIG_DEBUG_PAGEALLOC + /* + * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages. + * This will simplify cpa(), which otherwise needs to support splitting + * large pages into small in interrupt context, etc. + */ + int use_pse = 0; +#else + int use_pse = cpu_has_pse; +#endif /* * Find space for the kernel direct mapping tables. */ if (!after_init_bootmem) - find_early_table_space(end); + find_early_table_space(end, use_pse); #ifdef CONFIG_X86_PAE set_nx(); @@ -878,7 +888,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT); if (start_pfn < end_pfn) kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn, - cpu_has_pse); + use_pse); /* tail is not big page alignment ? */ start_pfn = end_pfn; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 1ba945eb628..9d7587ac1eb 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -456,13 +456,14 @@ phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end, return phys_pud_init(pud, addr, end, page_size_mask); } -static void __init find_early_table_space(unsigned long end) +static void __init find_early_table_space(unsigned long end, int use_pse, + int use_gbpages) { unsigned long puds, pmds, ptes, tables, start; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); - if (direct_gbpages) { + if (use_gbpages) { unsigned long extra; extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; @@ -470,7 +471,7 @@ static void __init find_early_table_space(unsigned long end) pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); - if (cpu_has_pse) { + if (use_pse) { unsigned long extra; extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; @@ -640,6 +641,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, struct map_range mr[NR_RANGE_MR]; int nr_range, i; + int use_pse, use_gbpages; printk(KERN_INFO "init_memory_mapping\n"); @@ -653,9 +655,21 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, if (!after_bootmem) init_gbpages(); - if (direct_gbpages) +#ifdef CONFIG_DEBUG_PAGEALLOC + /* + * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages. + * This will simplify cpa(), which otherwise needs to support splitting + * large pages into small in interrupt context, etc. + */ + use_pse = use_gbpages = 0; +#else + use_pse = cpu_has_pse; + use_gbpages = direct_gbpages; +#endif + + if (use_gbpages) page_size_mask |= 1 << PG_LEVEL_1G; - if (cpu_has_pse) + if (use_pse) page_size_mask |= 1 << PG_LEVEL_2M; memset(mr, 0, sizeof(mr)); @@ -716,7 +730,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, (mr[i].page_size_mask & (1< Date: Tue, 23 Sep 2008 14:00:40 -0700 Subject: x86, cpa: no need to check alias for __set_pages_p/__set_pages_np No alias checking needed for setting present/not-present mapping. Otherwise, we may need to break large pages for 64-bit kernel text mappings (this adds to complexity if we want to do this from atomic context especially, for ex: with CONFIG_DEBUG_PAGEALLOC). Let's keep it simple! Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 4b6968ba086..162812b05d2 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -1121,7 +1121,13 @@ static int __set_pages_p(struct page *page, int numpages) .mask_clr = __pgprot(0), .flags = 0}; - return __change_page_attr_set_clr(&cpa, 1); + /* + * No alias checking needed for setting present flag. otherwise, + * we may need to break large pages for 64-bit kernel text + * mappings (this adds to complexity if we want to do this from + * atomic context especially). Let's keep it simple! + */ + return __change_page_attr_set_clr(&cpa, 0); } static int __set_pages_np(struct page *page, int numpages) @@ -1133,7 +1139,13 @@ static int __set_pages_np(struct page *page, int numpages) .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), .flags = 0}; - return __change_page_attr_set_clr(&cpa, 1); + /* + * No alias checking needed for setting not present flag. otherwise, + * we may need to break large pages for 64-bit kernel text + * mappings (this adds to complexity if we want to do this from + * atomic context especially). Let's keep it simple! + */ + return __change_page_attr_set_clr(&cpa, 0); } void kernel_map_pages(struct page *page, int numpages, int enable) @@ -1153,11 +1165,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) /* * The return value is ignored as the calls cannot fail. - * Large pages are kept enabled at boot time, and are - * split up quickly with DEBUG_PAGEALLOC. If a splitup - * fails here (due to temporary memory shortage) no damage - * is done because we just keep the largepage intact up - * to the next attempt when it will likely be split up: + * Large pages for identity mappings are not used at boot time + * and hence no memory allocations during large page split. */ if (enable) __set_pages_p(page, numpages); -- cgit v1.2.3 From 8311eb84bf842d345f543f4c62ca2b6ea26f638c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:41 -0700 Subject: x86, cpa: remove cpa pool code Interrupt context no longer splits large page in cpa(). So we can do away with cpa memory pool code. Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 1 - arch/x86/mm/init_64.c | 2 - arch/x86/mm/pageattr.c | 157 ++----------------------------------------------- 3 files changed, 5 insertions(+), 155 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 44ccb028c35..74780800e7e 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -1051,7 +1051,6 @@ void __init mem_init(void) if (boot_cpu_data.wp_works_ok < 0) test_wp_bit(); - cpa_init(); save_pg_dir(); zap_low_mappings(); } diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 9d7587ac1eb..f54a4d97530 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -889,8 +889,6 @@ void __init mem_init(void) reservedpages << (PAGE_SHIFT-10), datasize >> 10, initsize >> 10); - - cpa_init(); } void free_init_pages(char *what, unsigned long begin, unsigned long end) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 162812b05d2..f5e8663c0f7 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -447,114 +447,17 @@ out_unlock: return do_split; } -static LIST_HEAD(page_pool); -static unsigned long pool_size, pool_pages, pool_low; -static unsigned long pool_used, pool_failed; - -static void cpa_fill_pool(struct page **ret) -{ - gfp_t gfp = GFP_KERNEL; - unsigned long flags; - struct page *p; - - /* - * Avoid recursion (on debug-pagealloc) and also signal - * our priority to get to these pagetables: - */ - if (current->flags & PF_MEMALLOC) - return; - current->flags |= PF_MEMALLOC; - - /* - * Allocate atomically from atomic contexts: - */ - if (in_atomic() || irqs_disabled() || debug_pagealloc) - gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN; - - while (pool_pages < pool_size || (ret && !*ret)) { - p = alloc_pages(gfp, 0); - if (!p) { - pool_failed++; - break; - } - /* - * If the call site needs a page right now, provide it: - */ - if (ret && !*ret) { - *ret = p; - continue; - } - spin_lock_irqsave(&pgd_lock, flags); - list_add(&p->lru, &page_pool); - pool_pages++; - spin_unlock_irqrestore(&pgd_lock, flags); - } - - current->flags &= ~PF_MEMALLOC; -} - -#define SHIFT_MB (20 - PAGE_SHIFT) -#define ROUND_MB_GB ((1 << 10) - 1) -#define SHIFT_MB_GB 10 -#define POOL_PAGES_PER_GB 16 - -void __init cpa_init(void) -{ - struct sysinfo si; - unsigned long gb; - - si_meminfo(&si); - /* - * Calculate the number of pool pages: - * - * Convert totalram (nr of pages) to MiB and round to the next - * GiB. Shift MiB to Gib and multiply the result by - * POOL_PAGES_PER_GB: - */ - if (debug_pagealloc) { - gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB; - pool_size = POOL_PAGES_PER_GB * gb; - } else { - pool_size = 1; - } - pool_low = pool_size; - - cpa_fill_pool(NULL); - printk(KERN_DEBUG - "CPA: page pool initialized %lu of %lu pages preallocated\n", - pool_pages, pool_size); -} - static int split_large_page(pte_t *kpte, unsigned long address) { unsigned long flags, pfn, pfninc = 1; unsigned int i, level; pte_t *pbase, *tmp; pgprot_t ref_prot; - struct page *base; + struct page *base = alloc_pages(GFP_KERNEL, 0); + if (!base) + return -ENOMEM; - /* - * Get a page from the pool. The pool list is protected by the - * pgd_lock, which we have to take anyway for the split - * operation: - */ spin_lock_irqsave(&pgd_lock, flags); - if (list_empty(&page_pool)) { - spin_unlock_irqrestore(&pgd_lock, flags); - base = NULL; - cpa_fill_pool(&base); - if (!base) - return -ENOMEM; - spin_lock_irqsave(&pgd_lock, flags); - } else { - base = list_first_entry(&page_pool, struct page, lru); - list_del(&base->lru); - pool_pages--; - - if (pool_pages < pool_low) - pool_low = pool_pages; - } - /* * Check for races, another CPU might have split this page * up for us already: @@ -611,11 +514,8 @@ out_unlock: * If we dropped out via the lookup_address check under * pgd_lock then stick the page back into the pool: */ - if (base) { - list_add(&base->lru, &page_pool); - pool_pages++; - } else - pool_used++; + if (base) + __free_page(base); spin_unlock_irqrestore(&pgd_lock, flags); return 0; @@ -899,8 +799,6 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, cpa_flush_all(cache); out: - cpa_fill_pool(NULL); - return ret; } @@ -1178,53 +1076,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) * but that can deadlock->flush only current cpu: */ __flush_tlb_all(); - - /* - * Try to refill the page pool here. We can do this only after - * the tlb flush. - */ - cpa_fill_pool(NULL); -} - -#ifdef CONFIG_DEBUG_FS -static int dpa_show(struct seq_file *m, void *v) -{ - seq_puts(m, "DEBUG_PAGEALLOC\n"); - seq_printf(m, "pool_size : %lu\n", pool_size); - seq_printf(m, "pool_pages : %lu\n", pool_pages); - seq_printf(m, "pool_low : %lu\n", pool_low); - seq_printf(m, "pool_used : %lu\n", pool_used); - seq_printf(m, "pool_failed : %lu\n", pool_failed); - - return 0; -} - -static int dpa_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, dpa_show, NULL); } -static const struct file_operations dpa_fops = { - .open = dpa_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init debug_pagealloc_proc_init(void) -{ - struct dentry *de; - - de = debugfs_create_file("debug_pagealloc", 0600, NULL, NULL, - &dpa_fops); - if (!de) - return -ENOMEM; - - return 0; -} -__initcall(debug_pagealloc_proc_init); -#endif - #ifdef CONFIG_HIBERNATION bool kernel_page_present(struct page *page) -- cgit v1.2.3 From ad5ca55f6bdb47c957b681c7358bb3719ba4ee82 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:42 -0700 Subject: x86, cpa: srlz cpa(), global flush tlb after splitting big page and before doing cpa Do a global flush tlb after splitting the large page and before we do the actual change page attribute in the PTE. With out this, we violate the TLB application note, which says "The TLBs may contain both ordinary and large-page translations for a 4-KByte range of linear addresses. This may occur if software modifies the paging structures so that the page size used for the address range changes. If the two translations differ with respect to page frame or attributes (e.g., permissions), processor behavior is undefined and may be implementation-specific." And also serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings) using cpa_lock. So that we don't allow any other cpu, with stale large tlb entries change the page attribute in parallel to some other cpu splitting a large page entry along with changing the attribute. Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index f5e8663c0f7..b6374d653d0 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -35,6 +35,14 @@ struct cpa_data { int curpage; }; +/* + * Serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings) + * using cpa_lock. So that we don't allow any other cpu, with stale large tlb + * entries change the page attribute in parallel to some other cpu + * splitting a large page entry along with changing the attribute. + */ +static DEFINE_SPINLOCK(cpa_lock); + #define CPA_FLUSHTLB 1 #define CPA_ARRAY 2 @@ -453,7 +461,13 @@ static int split_large_page(pte_t *kpte, unsigned long address) unsigned int i, level; pte_t *pbase, *tmp; pgprot_t ref_prot; - struct page *base = alloc_pages(GFP_KERNEL, 0); + struct page *base; + + if (!debug_pagealloc) + spin_unlock(&cpa_lock); + base = alloc_pages(GFP_KERNEL, 0); + if (!debug_pagealloc) + spin_lock(&cpa_lock); if (!base) return -ENOMEM; @@ -594,7 +608,25 @@ repeat: */ err = split_large_page(kpte, address); if (!err) { - cpa->flags |= CPA_FLUSHTLB; + /* + * Do a global flush tlb after splitting the large page + * and before we do the actual change page attribute in the PTE. + * + * With out this, we violate the TLB application note, that says + * "The TLBs may contain both ordinary and large-page + * translations for a 4-KByte range of linear addresses. This + * may occur if software modifies the paging structures so that + * the page size used for the address range changes. If the two + * translations differ with respect to page frame or attributes + * (e.g., permissions), processor behavior is undefined and may + * be implementation-specific." + * + * We do this global tlb flush inside the cpa_lock, so that we + * don't allow any other cpu, with stale tlb entries change the + * page attribute in parallel, that also falls into the + * just split large page entry. + */ + flush_tlb_all(); goto repeat; } @@ -686,7 +718,11 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) if (cpa->flags & CPA_ARRAY) cpa->numpages = 1; + if (!debug_pagealloc) + spin_lock(&cpa_lock); ret = __change_page_attr(cpa, checkalias); + if (!debug_pagealloc) + spin_unlock(&cpa_lock); if (ret) return ret; -- cgit v1.2.3 From 9542ada803198e6eba29d3289abb39ea82047b92 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 24 Sep 2008 08:53:33 -0700 Subject: x86: track memtype for RAM in page struct Track the memtype for RAM pages in page struct instead of using the memtype list. This avoids the explosion in the number of entries in memtype list (of the order of 20,000 with AGP) and makes the PAT tracking simpler. We are using PG_arch_1 bit in page->flags. We still use the memtype list for non RAM pages. Signed-off-by: Suresh Siddha Signed-off-by: Venkatesh Pallipadi Signed-off-by: Ingo Molnar --- arch/x86/mm/ioremap.c | 19 ++++++++++++ arch/x86/mm/pat.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) (limited to 'arch') diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index d4b6e6a29ae..d03c461e045 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -83,6 +83,25 @@ int page_is_ram(unsigned long pagenr) return 0; } +int pagerange_is_ram(unsigned long start, unsigned long end) +{ + int ram_page = 0, not_rampage = 0; + unsigned long page_nr; + + for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT); + ++page_nr) { + if (page_is_ram(page_nr)) + ram_page = 1; + else + not_rampage = 1; + + if (ram_page == not_rampage) + return -1; + } + + return ram_page; +} + /* * Fix up the linear direct mapping of the kernel to avoid cache attribute * conflicts. diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index f049b1d6ebd..aceb6c7c6db 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -210,6 +210,75 @@ static int chk_conflict(struct memtype *new, struct memtype *entry, static struct memtype *cached_entry; static u64 cached_start; +/* + * RED-PEN: TODO: Add PageReserved() check as well here, + * once we add SetPageReserved() to all the drivers using + * set_memory_* or set_pages_*. + * + * This will help prevent accidentally freeing pages + * before setting the attribute back to WB. + */ + +/* + * For RAM pages, mark the pages as non WB memory type using + * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or + * set_memory_wc() on a RAM page at a time before marking it as WB again. + * This is ok, because only one driver will be owning the page and + * doing set_memory_*() calls. + * + * For now, we use PageNonWB to track that the RAM page is being mapped + * as non WB. In future, we will have to use one more flag + * (or some other mechanism in page_struct) to distinguish between + * UC and WC mapping. + */ +static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type, + unsigned long *new_type) +{ + struct page *page; + u64 pfn, end_pfn; + + for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) { + page = pfn_to_page(pfn); + if (page_mapped(page) || PageNonWB(page)) + goto out; + + SetPageNonWB(page); + } + return 0; + +out: + end_pfn = pfn; + for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) { + page = pfn_to_page(pfn); + ClearPageNonWB(page); + } + + return -EINVAL; +} + +static int free_ram_pages_type(u64 start, u64 end) +{ + struct page *page; + u64 pfn, end_pfn; + + for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) { + page = pfn_to_page(pfn); + if (page_mapped(page) || !PageNonWB(page)) + goto out; + + ClearPageNonWB(page); + } + return 0; + +out: + end_pfn = pfn; + for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) { + page = pfn_to_page(pfn); + SetPageNonWB(page); + } + return -EINVAL; +} + /* * req_type typically has one of the: * - _PAGE_CACHE_WB @@ -232,6 +301,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, unsigned long actual_type; struct list_head *where; int err = 0; + int is_range_ram; BUG_ON(start >= end); /* end is exclusive */ @@ -270,6 +340,12 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, actual_type = pat_x_mtrr_type(start, end, req_type & _PAGE_CACHE_MASK); + is_range_ram = pagerange_is_ram(start, end); + if (is_range_ram == 1) + return reserve_ram_pages_type(start, end, req_type, new_type); + else if (is_range_ram < 0) + return -EINVAL; + new = kmalloc(sizeof(struct memtype), GFP_KERNEL); if (!new) return -ENOMEM; @@ -358,6 +434,7 @@ int free_memtype(u64 start, u64 end) { struct memtype *entry; int err = -EINVAL; + int is_range_ram; if (!pat_enabled) return 0; @@ -366,6 +443,12 @@ int free_memtype(u64 start, u64 end) if (is_ISA_range(start, end - 1)) return 0; + is_range_ram = pagerange_is_ram(start, end); + if (is_range_ram == 1) + return free_ram_pages_type(start, end); + else if (is_range_ram < 0) + return -EINVAL; + spin_lock(&memtype_lock); list_for_each_entry(entry, &memtype_list, nd) { if (entry->start == start && entry->end == end) { -- cgit v1.2.3 From 28dd033f43ca957cd751e02652b36c6fa364ca18 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 29 Sep 2008 12:13:26 -0700 Subject: x86: fix pagetable init 64-bit breakage Fix _end alignment check - can trigger a crash if _end happens to be on a page boundary. Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index f54a4d97530..6116ff0d741 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -510,7 +510,7 @@ static int is_kernel(unsigned long pfn) unsigned long pg_addresss = pfn << PAGE_SHIFT; if (pg_addresss >= (unsigned long) __pa(_text) && - pg_addresss <= (unsigned long) __pa(_end)) + pg_addresss < (unsigned long) __pa(_end)) return 1; return 0; -- cgit v1.2.3 From ad2cde16a21985cdc4302e4a4b0fc373d666fdf7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 30 Sep 2008 13:20:45 +0200 Subject: x86, pat: cleanups clean up recently added code to be more consistent with other x86 code. Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 67 ++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index aceb6c7c6db..738fd0f2495 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -7,24 +7,24 @@ * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen. */ -#include +#include +#include +#include #include #include +#include #include -#include -#include -#include -#include -#include +#include #include -#include +#include #include -#include -#include -#include #include +#include #include +#include +#include +#include #include #ifdef CONFIG_X86_PAT @@ -46,6 +46,7 @@ early_param("nopat", nopat); static int debug_enable; + static int __init pat_debug_setup(char *str) { debug_enable = 1; @@ -145,14 +146,14 @@ static char *cattr_name(unsigned long flags) */ struct memtype { - u64 start; - u64 end; - unsigned long type; - struct list_head nd; + u64 start; + u64 end; + unsigned long type; + struct list_head nd; }; static LIST_HEAD(memtype_list); -static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */ +static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */ /* * Does intersection of PAT memory type and MTRR memory type and returns @@ -180,8 +181,8 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type) return req_type; } -static int chk_conflict(struct memtype *new, struct memtype *entry, - unsigned long *type) +static int +chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type) { if (new->type != entry->type) { if (type) { @@ -210,15 +211,6 @@ static int chk_conflict(struct memtype *new, struct memtype *entry, static struct memtype *cached_entry; static u64 cached_start; -/* - * RED-PEN: TODO: Add PageReserved() check as well here, - * once we add SetPageReserved() to all the drivers using - * set_memory_* or set_pages_*. - * - * This will help prevent accidentally freeing pages - * before setting the attribute back to WB. - */ - /* * For RAM pages, mark the pages as non WB memory type using * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or @@ -232,7 +224,7 @@ static u64 cached_start; * UC and WC mapping. */ static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type, - unsigned long *new_type) + unsigned long *new_type) { struct page *page; u64 pfn, end_pfn; @@ -295,15 +287,15 @@ out: * it will return a negative return value. */ int reserve_memtype(u64 start, u64 end, unsigned long req_type, - unsigned long *new_type) + unsigned long *new_type) { struct memtype *new, *entry; unsigned long actual_type; struct list_head *where; - int err = 0; int is_range_ram; + int err = 0; - BUG_ON(start >= end); /* end is exclusive */ + BUG_ON(start >= end); /* end is exclusive */ if (!pat_enabled) { /* This is identical to page table setting without PAT */ @@ -336,9 +328,10 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, actual_type = _PAGE_CACHE_WB; else actual_type = _PAGE_CACHE_UC_MINUS; - } else + } else { actual_type = pat_x_mtrr_type(start, end, req_type & _PAGE_CACHE_MASK); + } is_range_ram = pagerange_is_ram(start, end); if (is_range_ram == 1) @@ -350,9 +343,9 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, if (!new) return -ENOMEM; - new->start = start; - new->end = end; - new->type = actual_type; + new->start = start; + new->end = end; + new->type = actual_type; if (new_type) *new_type = actual_type; @@ -411,6 +404,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, start, end, cattr_name(new->type), cattr_name(req_type)); kfree(new); spin_unlock(&memtype_lock); + return err; } @@ -469,6 +463,7 @@ int free_memtype(u64 start, u64 end) } dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end); + return err; } @@ -575,9 +570,9 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot) { + unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK); u64 addr = (u64)pfn << PAGE_SHIFT; unsigned long flags; - unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK); reserve_memtype(addr, addr + size, want_flags, &flags); if (flags != want_flags) { @@ -620,6 +615,7 @@ static struct memtype *memtype_get_idx(loff_t pos) } spin_unlock(&memtype_lock); kfree(print_entry); + return NULL; } @@ -650,6 +646,7 @@ static int memtype_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type), print_entry->start, print_entry->end); kfree(print_entry); + return 0; } -- cgit v1.2.3 From b27a43c1e90582facad44de67d02bc9e9f900289 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 7 Oct 2008 13:58:46 -0700 Subject: x86, cpa: make the kernel physical mapping initialization a two pass sequence, fix Jeremy Fitzhardinge wrote: > I'd noticed that current tip/master hasn't been booting under Xen, and I > just got around to bisecting it down to this change. > > commit 065ae73c5462d42e9761afb76f2b52965ff45bd6 > Author: Suresh Siddha > > x86, cpa: make the kernel physical mapping initialization a two pass sequence > > This patch is causing Xen to fail various pagetable updates because it > ends up remapping pagetables to RW, which Xen explicitly prohibits (as > that would allow guests to make arbitrary changes to pagetables, rather > than have them mediated by the hypervisor). Instead of making init a two pass sequence, to satisfy the Intel's TLB Application note (developer.intel.com/design/processor/applnots/317080.pdf Section 6 page 26), we preserve the original page permissions when fragmenting the large mappings and don't touch the existing memory mapping (which satisfies Xen's requirements). Only open issue is: on a native linux kernel, we will go back to mapping the first 0-1GB kernel identity mapping as executable (because of the static mapping setup in head_64.S). We can fix this in a different patch if needed. Signed-off-by: Suresh Siddha Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 149 +++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 88 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 6116ff0d741..8c7eae490a2 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -270,10 +270,9 @@ static __ref void unmap_low_page(void *adr) early_iounmap(adr, PAGE_SIZE); } -static int physical_mapping_iter; - static unsigned long __meminit -phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end) +phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, + pgprot_t prot) { unsigned pages = 0; unsigned long last_map_addr = end; @@ -291,35 +290,40 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end) break; } + /* + * We will re-use the existing mapping. + * Xen for example has some special requirements, like mapping + * pagetable pages as RO. So assume someone who pre-setup + * these mappings are more intelligent. + */ if (pte_val(*pte)) - goto repeat_set_pte; + continue; if (0) printk(" pte=%p addr=%lx pte=%016lx\n", pte, addr, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL).pte); pages++; -repeat_set_pte: - set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL)); + set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, prot)); last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE; } - if (physical_mapping_iter == 1) - update_page_count(PG_LEVEL_4K, pages); + update_page_count(PG_LEVEL_4K, pages); return last_map_addr; } static unsigned long __meminit -phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end) +phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end, + pgprot_t prot) { pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); - return phys_pte_init(pte, address, end); + return phys_pte_init(pte, address, end, prot); } static unsigned long __meminit phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, - unsigned long page_size_mask) + unsigned long page_size_mask, pgprot_t prot) { unsigned long pages = 0; unsigned long last_map_addr = end; @@ -330,6 +334,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, unsigned long pte_phys; pmd_t *pmd = pmd_page + pmd_index(address); pte_t *pte; + pgprot_t new_prot = prot; if (address >= end) { if (!after_bootmem) { @@ -343,45 +348,58 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, if (!pmd_large(*pmd)) { spin_lock(&init_mm.page_table_lock); last_map_addr = phys_pte_update(pmd, address, - end); + end, prot); spin_unlock(&init_mm.page_table_lock); continue; } - goto repeat_set_pte; + /* + * If we are ok with PG_LEVEL_2M mapping, then we will + * use the existing mapping, + * + * Otherwise, we will split the large page mapping but + * use the same existing protection bits except for + * large page, so that we don't violate Intel's TLB + * Application note (317080) which says, while changing + * the page sizes, new and old translations should + * not differ with respect to page frame and + * attributes. + */ + if (page_size_mask & (1 << PG_LEVEL_2M)) + continue; + new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd)); } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); + pfn_pte(address >> PAGE_SHIFT, + __pgprot(pgprot_val(prot) | _PAGE_PSE))); spin_unlock(&init_mm.page_table_lock); last_map_addr = (address & PMD_MASK) + PMD_SIZE; continue; } pte = alloc_low_page(&pte_phys); - last_map_addr = phys_pte_init(pte, address, end); + last_map_addr = phys_pte_init(pte, address, end, new_prot); unmap_low_page(pte); spin_lock(&init_mm.page_table_lock); pmd_populate_kernel(&init_mm, pmd, __va(pte_phys)); spin_unlock(&init_mm.page_table_lock); } - if (physical_mapping_iter == 1) - update_page_count(PG_LEVEL_2M, pages); + update_page_count(PG_LEVEL_2M, pages); return last_map_addr; } static unsigned long __meminit phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end, - unsigned long page_size_mask) + unsigned long page_size_mask, pgprot_t prot) { pmd_t *pmd = pmd_offset(pud, 0); unsigned long last_map_addr; - last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask); + last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot); __flush_tlb_all(); return last_map_addr; } @@ -398,6 +416,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, unsigned long pmd_phys; pud_t *pud = pud_page + pud_index(addr); pmd_t *pmd; + pgprot_t prot = PAGE_KERNEL; if (addr >= end) break; @@ -411,16 +430,28 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, if (pud_val(*pud)) { if (!pud_large(*pud)) { last_map_addr = phys_pmd_update(pud, addr, end, - page_size_mask); + page_size_mask, prot); continue; } - - goto repeat_set_pte; + /* + * If we are ok with PG_LEVEL_1G mapping, then we will + * use the existing mapping. + * + * Otherwise, we will split the gbpage mapping but use + * the same existing protection bits except for large + * page, so that we don't violate Intel's TLB + * Application note (317080) which says, while changing + * the page sizes, new and old translations should + * not differ with respect to page frame and + * attributes. + */ + if (page_size_mask & (1 << PG_LEVEL_1G)) + continue; + prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud)); } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); @@ -430,7 +461,8 @@ repeat_set_pte: } pmd = alloc_low_page(&pmd_phys); - last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask); + last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask, + prot); unmap_low_page(pmd); spin_lock(&init_mm.page_table_lock); @@ -439,8 +471,7 @@ repeat_set_pte: } __flush_tlb_all(); - if (physical_mapping_iter == 1) - update_page_count(PG_LEVEL_1G, pages); + update_page_count(PG_LEVEL_1G, pages); return last_map_addr; } @@ -505,54 +536,15 @@ static void __init init_gbpages(void) direct_gbpages = 0; } -static int is_kernel(unsigned long pfn) -{ - unsigned long pg_addresss = pfn << PAGE_SHIFT; - - if (pg_addresss >= (unsigned long) __pa(_text) && - pg_addresss < (unsigned long) __pa(_end)) - return 1; - - return 0; -} - static unsigned long __init kernel_physical_mapping_init(unsigned long start, unsigned long end, unsigned long page_size_mask) { - unsigned long next, last_map_addr; - u64 cached_supported_pte_mask = __supported_pte_mask; - unsigned long cache_start = start; - unsigned long cache_end = end; - - /* - * First iteration will setup identity mapping using large/small pages - * based on page_size_mask, with other attributes same as set by - * the early code in head_64.S - * - * Second iteration will setup the appropriate attributes - * as desired for the kernel identity mapping. - * - * This two pass mechanism conforms to the TLB app note which says: - * - * "Software should not write to a paging-structure entry in a way - * that would change, for any linear address, both the page size - * and either the page frame or attributes." - * - * For now, only difference between very early PTE attributes used in - * head_64.S and here is _PAGE_NX. - */ - BUILD_BUG_ON((__PAGE_KERNEL_LARGE & ~__PAGE_KERNEL_IDENT_LARGE_EXEC) - != _PAGE_NX); - __supported_pte_mask &= ~(_PAGE_NX); - physical_mapping_iter = 1; + unsigned long next, last_map_addr = end; -repeat: - last_map_addr = cache_end; - - start = (unsigned long)__va(cache_start); - end = (unsigned long)__va(cache_end); + start = (unsigned long)__va(start); + end = (unsigned long)__va(end); for (; start < end; start = next) { pgd_t *pgd = pgd_offset_k(start); @@ -564,21 +556,11 @@ repeat: next = end; if (pgd_val(*pgd)) { - /* - * Static identity mappings will be overwritten - * with run-time mappings. For example, this allows - * the static 0-1GB identity mapping to be mapped - * non-executable with this. - */ - if (is_kernel(pte_pfn(*((pte_t *) pgd)))) - goto realloc; - last_map_addr = phys_pud_update(pgd, __pa(start), __pa(end), page_size_mask); continue; } -realloc: pud = alloc_low_page(&pud_phys); last_map_addr = phys_pud_init(pud, __pa(start), __pa(next), page_size_mask); @@ -590,15 +572,6 @@ realloc: } __flush_tlb_all(); - if (physical_mapping_iter == 1) { - physical_mapping_iter = 2; - /* - * Second iteration will set the actual desired PTE attributes. - */ - __supported_pte_mask = cached_supported_pte_mask; - goto repeat; - } - return last_map_addr; } -- cgit v1.2.3 From 7a0f475513fa573bc8e072021960313da32f0ee3 Mon Sep 17 00:00:00 2001 From: Klaus-Dieter Wacker Date: Fri, 10 Oct 2008 21:33:18 +0200 Subject: [S390] qdio enhanced SIGA (iqdio) support. Add support for z10 HiperSockets multiwrite SBALs on output queues. This is used on LPAR with EDDP enabled devices. Signed-off-by: Klaus-Dieter Wacker Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/qdio.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 6813772171f..4734c3f0535 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -299,7 +299,13 @@ struct qdio_ssqd_desc { u8 mbccnt; u16 qdioac2; u64 sch_token; - u64:64; + u8 mro; + u8 mri; + u8:8; + u8 sbalic; + u16:16; + u8:8; + u8 mmwc; } __attribute__ ((packed)); /* params are: ccw_device, qdio_error, queue_number, -- cgit v1.2.3 From d86730bb9597b02bff59a3a5a01c0094d71a265f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 10 Oct 2008 21:33:19 +0200 Subject: [S390] s390: use sys_pause for 31bit pause entry point sys32_pause is a useless copy of the generic sys_pause. (and it's certainly not there for old sparc32 binaries..) Signed-off-by: Christoph Hellwig Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/compat_linux.c | 8 -------- arch/s390/kernel/compat_linux.h | 1 - arch/s390/kernel/compat_wrapper.S | 2 -- arch/s390/kernel/syscalls.S | 2 +- 4 files changed, 1 insertion(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index d7f22226fc4..98e246dc023 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -608,14 +608,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct time return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } -/* These are here just in case some old sparc32 binary calls it. */ -asmlinkage long sys32_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, u32 poshi, u32 poslo) { diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 20723a06201..05f8516366a 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h @@ -206,7 +206,6 @@ long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz); long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz); -long sys32_pause(void); long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, u32 poshi, u32 poslo); long sys32_pwrite64(unsigned int fd, const char __user *ubuf, diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 328a20e880b..ee51ca9e23b 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -128,8 +128,6 @@ sys32_alarm_wrapper: llgfr %r2,%r2 # unsigned int jg sys_alarm # branch to system call -#sys32_pause_wrapper # void - .globl compat_sys_utime_wrapper compat_sys_utime_wrapper: llgtr %r2,%r2 # char * diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index c66d35e5514..3ae303914b4 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -37,7 +37,7 @@ SYSCALL(sys_stime,sys_ni_syscall,sys32_stime_wrapper) /* 25 old stime syscall * SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper) SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper) NI_SYSCALL /* old fstat syscall */ -SYSCALL(sys_pause,sys_pause,sys32_pause) +SYSCALL(sys_pause,sys_pause,sys_pause) SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper) /* 30 */ NI_SYSCALL /* old stty syscall */ NI_SYSCALL /* old gtty syscall */ -- cgit v1.2.3 From 753c4dd6a2fa2af81f5d809d610d29f2d9dd9bc1 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 10 Oct 2008 21:33:20 +0200 Subject: [S390] ptrace changes * System call parameter and result access functions * Add tracehook calls * Split syscall_trace into two functions do_syscall_trace_enter and do_syscall_trace_exit Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + arch/s390/include/asm/ptrace.h | 1 + arch/s390/include/asm/syscall.h | 80 +++++++++++++++++++++++++++++++++++++ arch/s390/include/asm/thread_info.h | 2 + arch/s390/kernel/entry.S | 50 ++++++++++++++++++----- arch/s390/kernel/entry64.S | 42 ++++++++++++++----- arch/s390/kernel/ptrace.c | 61 +++++++++++++++------------- arch/s390/kernel/signal.c | 13 ++++++ 8 files changed, 202 insertions(+), 48 deletions(-) create mode 100644 arch/s390/include/asm/syscall.h (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8d41908e251..4c03049e7db 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -74,6 +74,7 @@ config S390 select HAVE_KPROBES select HAVE_KRETPROBES select HAVE_KVM if 64BIT + select HAVE_ARCH_TRACEHOOK source "init/Kconfig" diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index af2c9ac28a0..a7226f8143f 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -490,6 +490,7 @@ extern void user_disable_single_step(struct task_struct *); #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) +#define user_stack_pointer(regs)((regs)->gprs[15]) #define regs_return_value(regs)((regs)->gprs[2]) #define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs * regs); diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h new file mode 100644 index 00000000000..6e623971fbb --- /dev/null +++ b/arch/s390/include/asm/syscall.h @@ -0,0 +1,80 @@ +/* + * Access to user system call parameters and results + * + * Copyright IBM Corp. 2008 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + */ + +#ifndef _ASM_SYSCALL_H +#define _ASM_SYSCALL_H 1 + +#include + +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + if (regs->trap != __LC_SVC_OLD_PSW) + return -1; + return regs->gprs[2]; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->gprs[2] = regs->orig_gpr2; +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->gprs[2]; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->gprs[2] = error ? -error : val; +} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); +#ifdef CONFIG_COMPAT + if (test_tsk_thread_flag(task, TIF_31BIT)) { + if (i + n == 6) + args[--n] = (u32) regs->args[0]; + while (n-- > 0) + args[n] = (u32) regs->gprs[2 + i + n]; + } +#endif + if (i + n == 6) + args[--n] = regs->args[0]; + memcpy(args, ®s->gprs[2 + i], n * sizeof(args[0])); +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + BUG_ON(i + n > 6); + if (i + n == 6) + regs->args[0] = args[--n]; + memcpy(®s->gprs[2 + i], args, n * sizeof(args[0])); +} + +#endif /* _ASM_SYSCALL_H */ diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 91a8f93ad35..ea40a9d690f 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -86,6 +86,7 @@ static inline struct thread_info *current_thread_info(void) * thread information flags bit numbers */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ @@ -100,6 +101,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */ #define _TIF_SYSCALL_TRACE (1< #include #include +#include #include #include @@ -639,40 +640,44 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, } #endif -asmlinkage void -syscall_trace(struct pt_regs *regs, int entryexit) +asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) { - if (unlikely(current->audit_context) && entryexit) - audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]); - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - goto out; - if (!(current->ptrace & PT_PTRACED)) - goto out; - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); + long ret; /* - * If the debuffer has set an invalid system call number, - * we prepare to skip the system call restart handling. + * The sysc_tracesys code in entry.S stored the system + * call number to gprs[2]. */ - if (!entryexit && regs->gprs[2] >= NR_syscalls) + ret = regs->gprs[2]; + if (test_thread_flag(TIF_SYSCALL_TRACE) && + (tracehook_report_syscall_entry(regs) || + regs->gprs[2] >= NR_syscalls)) { + /* + * Tracing decided this syscall should not happen or the + * debugger stored an invalid system call number. Skip + * the system call and the system call restart handling. + */ regs->trap = -1; - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; + ret = -1; } - out: - if (unlikely(current->audit_context) && !entryexit) - audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X, - regs->gprs[2], regs->orig_gpr2, regs->gprs[3], - regs->gprs[4], regs->gprs[5]); + + if (unlikely(current->audit_context)) + audit_syscall_entry(test_thread_flag(TIF_31BIT) ? + AUDIT_ARCH_S390 : AUDIT_ARCH_S390X, + regs->gprs[2], regs->orig_gpr2, + regs->gprs[3], regs->gprs[4], + regs->gprs[5]); + return ret; +} + +asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) +{ + if (unlikely(current->audit_context)) + audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), + regs->gprs[2]); + + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, 0); } /* diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index b9768204021..4f7fc3059a8 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -507,6 +508,12 @@ void do_signal(struct pt_regs *regs) */ if (current->thread.per_info.single_step) set_thread_flag(TIF_SINGLE_STEP); + + /* + * Let tracing know that we've done the handler setup. + */ + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLE_STEP)); } return; } @@ -526,3 +533,9 @@ void do_signal(struct pt_regs *regs) set_thread_flag(TIF_RESTART_SVC); } } + +void do_notify_resume(struct pt_regs *regs) +{ + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); +} -- cgit v1.2.3 From b2300b9efe1b8174833e17f37e975c9da00c388a Mon Sep 17 00:00:00 2001 From: Hongjie Yang Date: Fri, 10 Oct 2008 21:33:21 +0200 Subject: [S390] dcssblk: add >2G DCSSs support and stacked contiguous DCSSs support. The DCSS block device driver is modified to add >2G DCSSs support and allow a DCSS block device to map to a set of contiguous DCSSs. The extmem code is also modified to use new Diagnose x'64' subcodes for >2G DCSSs. Signed-off-by: Hongjie Yang Signed-off-by: Martin Schwidefsky --- arch/s390/mm/extmem.c | 251 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 212 insertions(+), 39 deletions(-) (limited to 'arch') diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index f231f5ec74b..580fc64cc73 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -43,20 +43,40 @@ #define DCSS_FINDSEG 0x0c #define DCSS_LOADNOLY 0x10 #define DCSS_SEGEXT 0x18 +#define DCSS_LOADSHRX 0x20 +#define DCSS_LOADNSRX 0x24 +#define DCSS_FINDSEGX 0x2c +#define DCSS_SEGEXTX 0x38 #define DCSS_FINDSEGA 0x0c struct qrange { - unsigned int start; // 3byte start address, 1 byte type - unsigned int end; // 3byte end address, 1 byte reserved + unsigned long start; /* last byte type */ + unsigned long end; /* last byte reserved */ }; struct qout64 { + unsigned long segstart; + unsigned long segend; + int segcnt; + int segrcnt; + struct qrange range[6]; +}; + +#ifdef CONFIG_64BIT +struct qrange_old { + unsigned int start; /* last byte type */ + unsigned int end; /* last byte reserved */ +}; + +/* output area format for the Diag x'64' old subcode x'18' */ +struct qout64_old { int segstart; int segend; int segcnt; int segrcnt; - struct qrange range[6]; + struct qrange_old range[6]; }; +#endif struct qin64 { char qopcode; @@ -86,6 +106,55 @@ static DEFINE_MUTEX(dcss_lock); static LIST_HEAD(dcss_list); static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", "EW/EN-MIXED" }; +static int loadshr_scode, loadnsr_scode, findseg_scode; +static int segext_scode, purgeseg_scode; +static int scode_set; + +/* set correct Diag x'64' subcodes. */ +static int +dcss_set_subcodes(void) +{ +#ifdef CONFIG_64BIT + char *name = kmalloc(8 * sizeof(char), GFP_DMA); + unsigned long rx, ry; + int rc; + + if (name == NULL) + return -ENOMEM; + + rx = (unsigned long) name; + ry = DCSS_FINDSEGX; + + strcpy(name, "dummy"); + asm volatile( + " diag %0,%1,0x64\n" + "0: ipm %2\n" + " srl %2,28\n" + " j 2f\n" + "1: la %2,3\n" + "2:\n" + EX_TABLE(0b, 1b) + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); + + kfree(name); + /* Diag x'64' new subcodes are supported, set to new subcodes */ + if (rc != 3) { + loadshr_scode = DCSS_LOADSHRX; + loadnsr_scode = DCSS_LOADNSRX; + purgeseg_scode = DCSS_PURGESEG; + findseg_scode = DCSS_FINDSEGX; + segext_scode = DCSS_SEGEXTX; + return 0; + } +#endif + /* Diag x'64' new subcodes are not supported, set to old subcodes */ + loadshr_scode = DCSS_LOADNOLY; + loadnsr_scode = DCSS_LOADNSR; + purgeseg_scode = DCSS_PURGESEG; + findseg_scode = DCSS_FINDSEG; + segext_scode = DCSS_SEGEXT; + return 0; +} /* * Create the 8 bytes, ebcdic VM segment name from @@ -135,25 +204,45 @@ segment_by_name (char *name) * Perform a function on a dcss segment. */ static inline int -dcss_diag (__u8 func, void *parameter, +dcss_diag(int *func, void *parameter, unsigned long *ret1, unsigned long *ret2) { unsigned long rx, ry; int rc; + if (scode_set == 0) { + rc = dcss_set_subcodes(); + if (rc < 0) + return rc; + scode_set = 1; + } rx = (unsigned long) parameter; - ry = (unsigned long) func; - asm volatile( + ry = (unsigned long) *func; + #ifdef CONFIG_64BIT - " sam31\n" - " diag %0,%1,0x64\n" - " sam64\n" + /* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */ + if (*func > DCSS_SEGEXT) + asm volatile( + " diag %0,%1,0x64\n" + " ipm %2\n" + " srl %2,28\n" + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); + /* 31-bit Diag x'64' old subcode, switch to 31-bit addressing mode */ + else + asm volatile( + " sam31\n" + " diag %0,%1,0x64\n" + " sam64\n" + " ipm %2\n" + " srl %2,28\n" + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); #else + asm volatile( " diag %0,%1,0x64\n" -#endif " ipm %2\n" " srl %2,28\n" : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); +#endif *ret1 = rx; *ret2 = ry; return rc; @@ -190,14 +279,45 @@ query_segment_type (struct dcss_segment *seg) qin->qoutlen = sizeof(struct qout64); memcpy (qin->qname, seg->dcss_name, 8); - diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc); + diag_cc = dcss_diag(&segext_scode, qin, &dummy, &vmrc); + if (diag_cc < 0) { + rc = diag_cc; + goto out_free; + } if (diag_cc > 1) { PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc); rc = dcss_diag_translate_rc (vmrc); goto out_free; } +#ifdef CONFIG_64BIT + /* Only old format of output area of Diagnose x'64' is supported, + copy data for the new format. */ + if (segext_scode == DCSS_SEGEXT) { + struct qout64_old *qout_old; + qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA); + if (qout_old == NULL) { + rc = -ENOMEM; + goto out_free; + } + memcpy(qout_old, qout, sizeof(struct qout64_old)); + qout->segstart = (unsigned long) qout_old->segstart; + qout->segend = (unsigned long) qout_old->segend; + qout->segcnt = qout_old->segcnt; + qout->segrcnt = qout_old->segrcnt; + + if (qout->segcnt > 6) + qout->segrcnt = 6; + for (i = 0; i < qout->segrcnt; i++) { + qout->range[i].start = + (unsigned long) qout_old->range[i].start; + qout->range[i].end = + (unsigned long) qout_old->range[i].end; + } + kfree(qout_old); + } +#endif if (qout->segcnt > 6) { rc = -ENOTSUPP; goto out_free; @@ -268,6 +388,30 @@ segment_type (char* name) return seg.vm_segtype; } +/* + * check if segment collides with other segments that are currently loaded + * returns 1 if this is the case, 0 if no collision was found + */ +static int +segment_overlaps_others (struct dcss_segment *seg) +{ + struct list_head *l; + struct dcss_segment *tmp; + + BUG_ON(!mutex_is_locked(&dcss_lock)); + list_for_each(l, &dcss_list) { + tmp = list_entry(l, struct dcss_segment, list); + if ((tmp->start_addr >> 20) > (seg->end >> 20)) + continue; + if ((tmp->end >> 20) < (seg->start_addr >> 20)) + continue; + if (seg == tmp) + continue; + return 1; + } + return 0; +} + /* * real segment loading function, called from segment_load */ @@ -276,7 +420,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long { struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment), GFP_DMA); - int dcss_command, rc, diag_cc; + int rc, diag_cc; + unsigned long start_addr, end_addr, dummy; if (seg == NULL) { rc = -ENOMEM; @@ -287,6 +432,13 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long if (rc < 0) goto out_free; + if (loadshr_scode == DCSS_LOADSHRX) { + if (segment_overlaps_others(seg)) { + rc = -EBUSY; + goto out_free; + } + } + rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1); if (rc) @@ -316,20 +468,28 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long } if (do_nonshared) - dcss_command = DCSS_LOADNSR; + diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name, + &start_addr, &end_addr); else - dcss_command = DCSS_LOADNOLY; - - diag_cc = dcss_diag(dcss_command, seg->dcss_name, - &seg->start_addr, &seg->end); + diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name, + &start_addr, &end_addr); + if (diag_cc < 0) { + dcss_diag(&purgeseg_scode, seg->dcss_name, + &dummy, &dummy); + rc = diag_cc; + goto out_resource; + } if (diag_cc > 1) { PRINT_WARN ("segment_load: could not load segment %s - " - "diag returned error (%ld)\n",name,seg->end); - rc = dcss_diag_translate_rc (seg->end); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, - &seg->start_addr, &seg->end); + "diag returned error (%ld)\n", + name, end_addr); + rc = dcss_diag_translate_rc(end_addr); + dcss_diag(&purgeseg_scode, seg->dcss_name, + &dummy, &dummy); goto out_resource; } + seg->start_addr = start_addr; + seg->end = end_addr; seg->do_nonshared = do_nonshared; atomic_set(&seg->ref_count, 1); list_add(&seg->list, &dcss_list); @@ -423,8 +583,8 @@ int segment_modify_shared (char *name, int do_nonshared) { struct dcss_segment *seg; - unsigned long dummy; - int dcss_command, rc, diag_cc; + unsigned long start_addr, end_addr, dummy; + int rc, diag_cc; mutex_lock(&dcss_lock); seg = segment_by_name (name); @@ -445,38 +605,51 @@ segment_modify_shared (char *name, int do_nonshared) goto out_unlock; } release_resource(seg->res); - if (do_nonshared) { - dcss_command = DCSS_LOADNSR; + if (do_nonshared) seg->res->flags &= ~IORESOURCE_READONLY; - } else { - dcss_command = DCSS_LOADNOLY; + else if (seg->vm_segtype == SEG_TYPE_SR || seg->vm_segtype == SEG_TYPE_ER) seg->res->flags |= IORESOURCE_READONLY; - } + if (request_resource(&iomem_resource, seg->res)) { PRINT_WARN("segment_modify_shared: could not reload segment %s" " - overlapping resources\n", name); rc = -EBUSY; kfree(seg->res); - goto out_del; + goto out_del_mem; + } + + dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy); + if (do_nonshared) + diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name, + &start_addr, &end_addr); + else + diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name, + &start_addr, &end_addr); + if (diag_cc < 0) { + rc = diag_cc; + goto out_del_res; } - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); - diag_cc = dcss_diag(dcss_command, seg->dcss_name, - &seg->start_addr, &seg->end); if (diag_cc > 1) { PRINT_WARN ("segment_modify_shared: could not reload segment %s" - " - diag returned error (%ld)\n",name,seg->end); - rc = dcss_diag_translate_rc (seg->end); - goto out_del; + " - diag returned error (%ld)\n", + name, end_addr); + rc = dcss_diag_translate_rc(end_addr); + goto out_del_res; } + seg->start_addr = start_addr; + seg->end = end_addr; seg->do_nonshared = do_nonshared; rc = 0; goto out_unlock; - out_del: + out_del_res: + release_resource(seg->res); + kfree(seg->res); + out_del_mem: vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); list_del(&seg->list); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy); kfree(seg); out_unlock: mutex_unlock(&dcss_lock); @@ -510,7 +683,7 @@ segment_unload(char *name) kfree(seg->res); vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); list_del(&seg->list); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy); kfree(seg); out_unlock: mutex_unlock(&dcss_lock); @@ -545,7 +718,7 @@ segment_save(char *name) endpfn = (seg->end) >> PAGE_SHIFT; sprintf(cmd1, "DEFSEG %s", name); for (i=0; isegcnt; i++) { - sprintf(cmd1+strlen(cmd1), " %X-%X %s", + sprintf(cmd1+strlen(cmd1), " %lX-%lX %s", seg->range[i].start >> PAGE_SHIFT, seg->range[i].end >> PAGE_SHIFT, segtype_string[seg->range[i].start & 0xff]); -- cgit v1.2.3 From 5a0d0e65379256b4da2c9092e197a2c761f51c01 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 10 Oct 2008 21:33:22 +0200 Subject: [S390] Move private simple udelay function to arch/s390/lib/delay.c. Move cio's private simple udelay function to lib/delay.c and turn it into something much more readable. So we have all implementations at one place. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/delay.h | 1 + arch/s390/lib/delay.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h index 78357314c45..a356c958e26 100644 --- a/arch/s390/include/asm/delay.h +++ b/arch/s390/include/asm/delay.h @@ -15,6 +15,7 @@ #define _S390_DELAY_H extern void __udelay(unsigned long usecs); +extern void udelay_simple(unsigned long usecs); extern void __delay(unsigned long loops); #define udelay(n) __udelay(n) diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 0953cee05ef..6ccb9fab055 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -92,3 +92,16 @@ out: local_irq_restore(flags); preempt_enable(); } + +/* + * Simple udelay variant. To be used on startup and reboot + * when the interrupt handler isn't working. + */ +void udelay_simple(unsigned long usecs) +{ + u64 end; + + end = get_clock() + ((u64) usecs << 12); + while (get_clock() < end) + cpu_relax(); +} -- cgit v1.2.3 From ab1d848fd6a9151b02c6cbf4bddce6e24707b094 Mon Sep 17 00:00:00 2001 From: Nigel Hislop Date: Fri, 10 Oct 2008 21:33:25 +0200 Subject: [S390] Add ioctl support for EMC Symmetrix Subsystem Control I/O EMC Symmetrix Subsystem Control I/O through CKD dasd requires a specific parameter list sent to the array via a Perform Subsystem Function CCW. The Symmetrix response is retrieved from the array via a Read Subsystem Data CCW. Signed-off-by: Nigel Hislop Signed-off-by: Hannes Reinecke Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/dasd.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h index 3f002e13d02..55b2b80cdf6 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/asm/dasd.h @@ -3,6 +3,8 @@ * Author(s)......: Holger Smolinski * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + * EMC Symmetrix ioctl Copyright EMC Corporation, 2008 + * Author.........: Nigel Hislop * * This file is the interface of the DASD device driver, which is exported to user space * any future changes wrt the API will result in a change of the APIVERSION reported @@ -202,6 +204,16 @@ typedef struct attrib_data_t { #define DASD_SEQ_PRESTAGE 0x4 #define DASD_REC_ACCESS 0x5 +/* + * Perform EMC Symmetrix I/O + */ +typedef struct dasd_symmio_parms { + unsigned char reserved[8]; /* compat with older releases */ + unsigned long long psf_data; /* char * cast to u64 */ + unsigned long long rssd_result; /* char * cast to u64 */ + int psf_data_len; + int rssd_result_len; +} __attribute__ ((packed)) dasd_symmio_parms_t; /******************************************************************************** * SECTION: Definition of IOCTLs @@ -247,6 +259,7 @@ typedef struct attrib_data_t { /* Set Attributes (cache operations) */ #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) +#define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) #endif /* DASD_H */ -- cgit v1.2.3 From 15e86b0c752d50e910b2cca6e83ce74c4440d06c Mon Sep 17 00:00:00 2001 From: Florian Funke Date: Fri, 10 Oct 2008 21:33:26 +0200 Subject: [S390] introduce dirty bit for kvm live migration This patch defines a dirty bit in the PGSTE that can be used to implement dirty pages logging for KVM's live migration. The bit is set in the ptep_rcp_copy function, which is called to save dirty and referenced information from the storage key in the PGSTE. The bit can be tested and reset by KVM using the kvm_s390_test_and_clear_page_dirty function that is introduced by this patch. Acked-by: Carsten Otte Signed-off-by: Florian Funke Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/pgtable.h | 45 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 0bdb704ae05..1a928f84afd 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -281,6 +281,9 @@ extern char empty_zero_page[PAGE_SIZE]; #define RCP_GR_BIT 50 #define RCP_GC_BIT 49 +/* User dirty bit for KVM's migration feature */ +#define KVM_UD_BIT 47 + #ifndef __s390x__ /* Bits in the segment table address-space-control-element */ @@ -575,12 +578,16 @@ static inline void ptep_rcp_copy(pte_t *ptep) unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); skey = page_get_storage_key(page_to_phys(page)); - if (skey & _PAGE_CHANGED) + if (skey & _PAGE_CHANGED) { set_bit_simple(RCP_GC_BIT, pgste); + set_bit_simple(KVM_UD_BIT, pgste); + } if (skey & _PAGE_REFERENCED) set_bit_simple(RCP_GR_BIT, pgste); - if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) + if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { SetPageDirty(page); + set_bit_simple(KVM_UD_BIT, pgste); + } if (test_and_clear_bit_simple(RCP_HR_BIT, pgste)) SetPageReferenced(page); #endif @@ -744,6 +751,40 @@ static inline pte_t pte_mkspecial(pte_t pte) return pte; } +#ifdef CONFIG_PGSTE +/* + * Get (and clear) the user dirty bit for a PTE. + */ +static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm, + pte_t *ptep) +{ + int dirty; + unsigned long *pgste; + struct page *page; + unsigned int skey; + + if (!mm->context.pgstes) + return -EINVAL; + rcp_lock(ptep); + pgste = (unsigned long *) (ptep + PTRS_PER_PTE); + page = virt_to_page(pte_val(*ptep)); + skey = page_get_storage_key(page_to_phys(page)); + if (skey & _PAGE_CHANGED) { + set_bit_simple(RCP_GC_BIT, pgste); + set_bit_simple(KVM_UD_BIT, pgste); + } + if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { + SetPageDirty(page); + set_bit_simple(KVM_UD_BIT, pgste); + } + dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste); + if (skey & _PAGE_CHANGED) + page_clear_dirty(page); + rcp_unlock(ptep); + return dirty; +} +#endif + #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) -- cgit v1.2.3 From 4a672cfa3a7fcbc6f2adc558f34148be1096c561 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 10 Oct 2008 21:33:29 +0200 Subject: [S390] fix initialization of stp chsc_sstpc returns -EIO on error and 0 on success but stp_reset checks against 1 instead of 0. chsc_sstpc used to return 1 on success, one call location has not been updated .. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 06acb1a18bb..b94e9e3b694 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -1356,7 +1356,7 @@ static void __init stp_reset(void) stp_page = alloc_bootmem_pages(PAGE_SIZE); rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); - if (rc == 1) + if (rc == 0) set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags); else if (stp_online) { printk(KERN_WARNING "Running on non STP capable machine.\n"); -- cgit v1.2.3 From 69fc7eed5f56bce15b239e5110de2575a6970df4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 9 Oct 2008 16:58:13 +0100 Subject: [ARM] 5300/1: fixup spitz reset during boot Some machines don't have the pullup/down on their reset pin, so configuring the reset generating pin as input makes them reset immediately. Fix that by making reset pin direction configurable. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/include/mach/reset.h | 9 ++++++--- arch/arm/mach-pxa/reset.c | 9 ++++++--- arch/arm/mach-pxa/spitz.c | 2 +- arch/arm/mach-pxa/tosa.c | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/include/mach/reset.h b/arch/arm/mach-pxa/include/mach/reset.h index 9489a48871a..7b8842cfa5f 100644 --- a/arch/arm/mach-pxa/include/mach/reset.h +++ b/arch/arm/mach-pxa/include/mach/reset.h @@ -10,9 +10,12 @@ extern unsigned int reset_status; extern void clear_reset_status(unsigned int mask); -/* - * register GPIO as reset generator +/** + * init_gpio_reset() - register GPIO as reset generator + * + * @gpio - gpio nr + * @output - set gpio as out/low instead of input during normal work */ -extern int init_gpio_reset(int gpio); +extern int init_gpio_reset(int gpio, int output); #endif /* __ASM_ARCH_RESET_H */ diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c index 31d78855aac..1b2af575c40 100644 --- a/arch/arm/mach-pxa/reset.c +++ b/arch/arm/mach-pxa/reset.c @@ -20,7 +20,7 @@ static void do_hw_reset(void); static int reset_gpio = -1; -int init_gpio_reset(int gpio) +int init_gpio_reset(int gpio, int output) { int rc; @@ -30,9 +30,12 @@ int init_gpio_reset(int gpio) goto out; } - rc = gpio_direction_input(gpio); + if (output) + rc = gpio_direction_output(gpio, 0); + else + rc = gpio_direction_input(gpio); if (rc) { - printk(KERN_ERR "Can't configure reset_gpio for input\n"); + printk(KERN_ERR "Can't configure reset_gpio\n"); gpio_free(gpio); goto out; } diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 9b4f24c7c05..524f656dc56 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -618,7 +618,7 @@ static void spitz_restart(char mode) static void __init common_init(void) { - init_gpio_reset(SPITZ_GPIO_ON_RESET); + init_gpio_reset(SPITZ_GPIO_ON_RESET, 1); 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 9f3ef9eb32e..130e37e4ebd 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -781,7 +781,7 @@ 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); + init_gpio_reset(TOSA_GPIO_ON_RESET, 0); pm_power_off = tosa_poweroff; arm_pm_restart = tosa_restart; -- cgit v1.2.3 From 5d9a76cd0ed367d01b0b237253adb7607e86a277 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Sun, 17 Aug 2008 16:49:25 +0200 Subject: MIPS: Use compat_sys_ptrace This replaces mips's sys_ptrace32 with a compat_arch_ptrace and enables the new generic definition of compat_sys_ptrace instead. Signed-off-by: Thomas Bogendoerfer Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace32.c | 43 ++++++++---------------------------------- arch/mips/kernel/scall64-n32.S | 2 +- arch/mips/kernel/scall64-o32.S | 2 +- arch/mips/kernel/signal32.c | 12 ++++++++++++ 4 files changed, 22 insertions(+), 37 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 76818be6ba7..cac56a8c867 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -15,6 +15,7 @@ * binaries. */ #include +#include #include #include #include @@ -46,37 +47,13 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data); * Tracing a 32-bit process with a 64-bit strace and vice versa will not * work. I don't know how to fix this. */ -asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { - struct task_struct *child; + int addr = caddr; + int data = cdata; int ret; -#if 0 - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -214,7 +191,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } dregs = __get_dsp_regs(child); tmp = (unsigned long) (dregs[addr - DSP_BASE]); @@ -224,14 +201,14 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } tmp = child->thread.dsp.dspcontrol; break; default: tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } ret = put_user(tmp, (unsigned __user *) (unsigned long) data); break; @@ -414,10 +391,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = ptrace_request(child, request, addr, data); break; } - -out_tsk: - put_task_struct(child); out: - unlock_kernel(); return ret; } diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index da7f1b6ea0f..324c5499dec 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -219,7 +219,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_getrusage PTR compat_sys_sysinfo PTR compat_sys_times - PTR sys32_ptrace + PTR compat_sys_ptrace PTR sys_getuid /* 6100 */ PTR sys_syslog PTR sys_getgid diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d7cd1aac9ad..85fedac99a5 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -231,7 +231,7 @@ sys_call_table: PTR sys_setuid PTR sys_getuid PTR compat_sys_stime /* 4025 */ - PTR sys32_ptrace + PTR compat_sys_ptrace PTR sys_alarm PTR sys_ni_syscall /* was sys_fstat */ PTR sys_pause diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 572c610db1b..652709b353a 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -482,6 +482,18 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) return err; } +int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) +{ + memset(to, 0, sizeof *to); + + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) + return -EFAULT; + + return 0; +} + asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) { struct sigframe32 __user *frame; -- cgit v1.2.3 From 9fa32c6b0275ab1e8b19f74fbfa3ed8411345db6 Mon Sep 17 00:00:00 2001 From: Patrick Glass Date: Mon, 18 Aug 2008 14:41:30 -0700 Subject: MIPS: PMC MSP71XX gpio drivers This new gpio driver for PMC-Sierra's MSP71xx SoC allows standard api calls for access to the general and extended gpio's. Signed-off-by: Patrick Glass Signed-off-by: Ralf Baechle create mode 100755 arch/mips/pmc-sierra/msp71xx/gpio.c create mode 100755 arch/mips/pmc-sierra/msp71xx/gpio_extended.c create mode 100755 include/asm-mips/pmc-sierra/msp71xx/gpio.h --- arch/mips/pmc-sierra/msp71xx/Makefile | 1 + arch/mips/pmc-sierra/msp71xx/gpio.c | 218 +++++++++++++++++++++++++++ arch/mips/pmc-sierra/msp71xx/gpio_extended.c | 148 ++++++++++++++++++ 3 files changed, 367 insertions(+) create mode 100644 arch/mips/pmc-sierra/msp71xx/gpio.c create mode 100644 arch/mips/pmc-sierra/msp71xx/gpio_extended.c (limited to 'arch') diff --git a/arch/mips/pmc-sierra/msp71xx/Makefile b/arch/mips/pmc-sierra/msp71xx/Makefile index 4bba79c1cc7..e107f79b149 100644 --- a/arch/mips/pmc-sierra/msp71xx/Makefile +++ b/arch/mips/pmc-sierra/msp71xx/Makefile @@ -3,6 +3,7 @@ # obj-y += msp_prom.o msp_setup.o msp_irq.o \ msp_time.o msp_serial.o msp_elb.o +obj-$(CONFIG_HAVE_GPIO_LIB) += gpio.o gpio_extended.o obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o diff --git a/arch/mips/pmc-sierra/msp71xx/gpio.c b/arch/mips/pmc-sierra/msp71xx/gpio.c new file mode 100644 index 00000000000..69848c5813e --- /dev/null +++ b/arch/mips/pmc-sierra/msp71xx/gpio.c @@ -0,0 +1,218 @@ +/* + * @file /arch/mips/pmc-sierra/msp71xx/gpio.c + * + * Generic PMC MSP71xx GPIO handling. These base gpio are controlled by two + * types of registers. The data register sets the output level when in output + * mode and when in input mode will contain the value at the input. The config + * register sets the various modes for each gpio. + * + * 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. + * + * @author Patrick Glass + */ + +#include +#include +#include +#include +#include +#include + +#define MSP71XX_CFG_OFFSET(gpio) (4 * (gpio)) +#define CONF_MASK 0x0F +#define MSP71XX_GPIO_INPUT 0x01 +#define MSP71XX_GPIO_OUTPUT 0x08 + +#define MSP71XX_GPIO_BASE 0x0B8400000L + +#define to_msp71xx_gpio_chip(c) container_of(c, struct msp71xx_gpio_chip, chip) + +static spinlock_t gpio_lock; + +/* + * struct msp71xx_gpio_chip - container for gpio chip and registers + * @chip: chip structure for the specified gpio bank + * @data_reg: register for reading and writing the gpio pin value + * @config_reg: register to set the mode for the gpio pin bank + * @out_drive_reg: register to set the output drive mode for the gpio pin bank + */ +struct msp71xx_gpio_chip { + struct gpio_chip chip; + void __iomem *data_reg; + void __iomem *config_reg; + void __iomem *out_drive_reg; +}; + +/* + * msp71xx_gpio_get() - return the chip's gpio value + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be returned + * + * It will return 0 if gpio value is low and other if high. + */ +static int msp71xx_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); + + return __raw_readl(msp_chip->data_reg) & (1 << offset); +} + +/* + * msp71xx_gpio_set() - set the output value for the gpio + * @chip: chip structure who controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This will set the gpio bit specified to the desired value. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static void msp71xx_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&gpio_lock, flags); + + data = __raw_readl(msp_chip->data_reg); + if (value) + data |= (1 << offset); + else + data &= ~(1 << offset); + __raw_writel(data, msp_chip->data_reg); + + spin_unlock_irqrestore(&gpio_lock, flags); +} + +/* + * msp71xx_set_gpio_mode() - declare the mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be assigned + * @mode: desired configuration for the gpio (see datasheet) + * + * It will set the gpio pin config to the @mode value passed in. + */ +static int msp71xx_set_gpio_mode(struct gpio_chip *chip, + unsigned offset, int mode) +{ + struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); + const unsigned bit_offset = MSP71XX_CFG_OFFSET(offset); + unsigned long flags; + u32 cfg; + + spin_lock_irqsave(&gpio_lock, flags); + + cfg = __raw_readl(msp_chip->config_reg); + cfg &= ~(CONF_MASK << bit_offset); + cfg |= (mode << bit_offset); + __raw_writel(cfg, msp_chip->config_reg); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} + +/* + * msp71xx_direction_output() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This call will set the mode for the @gpio to output. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static int msp71xx_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + msp71xx_gpio_set(chip, offset, value); + + return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_OUTPUT); +} + +/* + * msp71xx_direction_input() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose to which the value will be assigned + * + * This call will set the mode for the @gpio to input. + */ +static int msp71xx_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_INPUT); +} + +/* + * msp71xx_set_output_drive() - declare the output drive for the gpio line + * @gpio: gpio pin whose output drive you wish to modify + * @value: zero for active drain 1 for open drain drive + * + * This call will set the output drive mode for the @gpio to output. + */ +int msp71xx_set_output_drive(unsigned gpio, int value) +{ + unsigned long flags; + u32 data; + + if (gpio > 15 || gpio < 0) + return -EINVAL; + + spin_lock_irqsave(&gpio_lock, flags); + + data = __raw_readl((void __iomem *)(MSP71XX_GPIO_BASE + 0x190)); + if (value) + data |= (1 << gpio); + else + data &= ~(1 << gpio); + __raw_writel(data, (void __iomem *)(MSP71XX_GPIO_BASE + 0x190)); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} +EXPORT_SYMBOL(msp71xx_set_output_drive); + +#define MSP71XX_GPIO_BANK(name, dr, cr, base_gpio, num_gpio) \ +{ \ + .chip = { \ + .label = name, \ + .direction_input = msp71xx_direction_input, \ + .direction_output = msp71xx_direction_output, \ + .get = msp71xx_gpio_get, \ + .set = msp71xx_gpio_set, \ + .base = base_gpio, \ + .ngpio = num_gpio \ + }, \ + .data_reg = (void __iomem *)(MSP71XX_GPIO_BASE + dr), \ + .config_reg = (void __iomem *)(MSP71XX_GPIO_BASE + cr), \ + .out_drive_reg = (void __iomem *)(MSP71XX_GPIO_BASE + 0x190), \ +} + +/* + * struct msp71xx_gpio_banks[] - container array of gpio banks + * @chip: chip structure for the specified gpio bank + * @data_reg: register for reading and writing the gpio pin value + * @config_reg: register to set the mode for the gpio pin bank + * + * This array structure defines the gpio banks for the PMC MIPS Processor. + * We specify the bank name, the data register, the config register, base + * starting gpio number, and the number of gpios exposed by the bank. + */ +static struct msp71xx_gpio_chip msp71xx_gpio_banks[] = { + + MSP71XX_GPIO_BANK("GPIO_1_0", 0x170, 0x180, 0, 2), + MSP71XX_GPIO_BANK("GPIO_5_2", 0x174, 0x184, 2, 4), + MSP71XX_GPIO_BANK("GPIO_9_6", 0x178, 0x188, 6, 4), + MSP71XX_GPIO_BANK("GPIO_15_10", 0x17C, 0x18C, 10, 6), +}; + +void __init msp71xx_init_gpio(void) +{ + int i; + + spin_lock_init(&gpio_lock); + + for (i = 0; i < ARRAY_SIZE(msp71xx_gpio_banks); i++) + gpiochip_add(&msp71xx_gpio_banks[i].chip); +} diff --git a/arch/mips/pmc-sierra/msp71xx/gpio_extended.c b/arch/mips/pmc-sierra/msp71xx/gpio_extended.c new file mode 100644 index 00000000000..fc6dbc6cf1c --- /dev/null +++ b/arch/mips/pmc-sierra/msp71xx/gpio_extended.c @@ -0,0 +1,148 @@ +/* + * @file /arch/mips/pmc-sierra/msp71xx/gpio_extended.c + * + * Generic PMC MSP71xx EXTENDED (EXD) GPIO handling. The extended gpio is + * a set of hardware registers that have no need for explicit locking as + * it is handled by unique method of writing individual set/clr bits. + * + * 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. + * + * @author Patrick Glass + */ + +#include +#include +#include +#include +#include + +#define MSP71XX_DATA_OFFSET(gpio) (2 * (gpio)) +#define MSP71XX_READ_OFFSET(gpio) (MSP71XX_DATA_OFFSET(gpio) + 1) +#define MSP71XX_CFG_OUT_OFFSET(gpio) (MSP71XX_DATA_OFFSET(gpio) + 16) +#define MSP71XX_CFG_IN_OFFSET(gpio) (MSP71XX_CFG_OUT_OFFSET(gpio) + 1) + +#define MSP71XX_EXD_GPIO_BASE 0x0BC000000L + +#define to_msp71xx_exd_gpio_chip(c) \ + container_of(c, struct msp71xx_exd_gpio_chip, chip) + +/* + * struct msp71xx_exd_gpio_chip - container for gpio chip and registers + * @chip: chip structure for the specified gpio bank + * @reg: register for control and data of gpio pin + */ +struct msp71xx_exd_gpio_chip { + struct gpio_chip chip; + void __iomem *reg; +}; + +/* + * msp71xx_exd_gpio_get() - return the chip's gpio value + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be returned + * + * It will return 0 if gpio value is low and other if high. + */ +static int msp71xx_exd_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + const unsigned bit = MSP71XX_READ_OFFSET(offset); + + return __raw_readl(msp71xx_chip->reg) & (1 << bit); +} + +/* + * msp71xx_exd_gpio_set() - set the output value for the gpio + * @chip: chip structure who controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This will set the gpio bit specified to the desired value. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static void msp71xx_exd_gpio_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + const unsigned bit = MSP71XX_DATA_OFFSET(offset); + + __raw_writel(1 << (bit + (value ? 1 : 0)), msp71xx_chip->reg); +} + +/* + * msp71xx_exd_direction_output() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This call will set the mode for the @gpio to output. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static int msp71xx_exd_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + + msp71xx_exd_gpio_set(chip, offset, value); + __raw_writel(1 << MSP71XX_CFG_OUT_OFFSET(offset), msp71xx_chip->reg); + return 0; +} + +/* + * msp71xx_exd_direction_input() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose to which the value will be assigned + * + * This call will set the mode for the @gpio to input. + */ +static int msp71xx_exd_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + + __raw_writel(1 << MSP71XX_CFG_IN_OFFSET(offset), msp71xx_chip->reg); + return 0; +} + +#define MSP71XX_EXD_GPIO_BANK(name, exd_reg, base_gpio, num_gpio) \ +{ \ + .chip = { \ + .label = name, \ + .direction_input = msp71xx_exd_direction_input, \ + .direction_output = msp71xx_exd_direction_output, \ + .get = msp71xx_exd_gpio_get, \ + .set = msp71xx_exd_gpio_set, \ + .base = base_gpio, \ + .ngpio = num_gpio, \ + }, \ + .reg = (void __iomem *)(MSP71XX_EXD_GPIO_BASE + exd_reg), \ +} + +/* + * struct msp71xx_exd_gpio_banks[] - container array of gpio banks + * @chip: chip structure for the specified gpio bank + * @reg: register for reading and writing the gpio pin value + * + * This array structure defines the extended gpio banks for the + * PMC MIPS Processor. We specify the bank name, the data/config + * register,the base starting gpio number, and the number of + * gpios exposed by the bank of gpios. + */ +static struct msp71xx_exd_gpio_chip msp71xx_exd_gpio_banks[] = { + + MSP71XX_EXD_GPIO_BANK("GPIO_23_16", 0x188, 16, 8), + MSP71XX_EXD_GPIO_BANK("GPIO_27_24", 0x18C, 24, 4), +}; + +void __init msp71xx_init_gpio_extended(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(msp71xx_exd_gpio_banks); i++) + gpiochip_add(&msp71xx_exd_gpio_banks[i].chip); +} -- cgit v1.2.3 From f96a3383cfede841cdf80a5927f14478981ed78c Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:05 +0900 Subject: MIPS: RBTX4927: More explicit initialization * Make sure all interrupts cleared on startup * Initialize some GPIOs Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/rbtx4927/irq.c | 5 +++++ arch/mips/txx9/rbtx4927/setup.c | 9 +++++++++ 2 files changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c index 00cd5231da3..22076e3f03a 100644 --- a/arch/mips/txx9/rbtx4927/irq.c +++ b/arch/mips/txx9/rbtx4927/irq.c @@ -142,6 +142,11 @@ static void __init toshiba_rbtx4927_irq_ioc_init(void) { int i; + /* mask all IOC interrupts */ + writeb(0, rbtx4927_imask_addr); + /* clear SoftInt interrupts */ + writeb(0, rbtx4927_softint_addr); + for (i = RBTX4927_IRQ_IOC; i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++) set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type, diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index 0d39bafea79..5985f330838 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -212,6 +213,14 @@ static void __init rbtx4927_mem_setup(void) set_io_port_base(KSEG1 + RBTX4927_ISA_IO_OFFSET); #endif + /* TX4927-SIO DTR on (PIO[15]) */ + gpio_request(15, "sio-dtr"); + gpio_direction_output(15, 1); + gpio_request(0, "led"); + gpio_direction_output(0, 1); + gpio_request(1, "led"); + gpio_direction_output(1, 1); + tx4927_sio_init(0, 0); #ifdef CONFIG_SERIAL_TXX9_CONSOLE argptr = prom_getcmdline(); -- cgit v1.2.3 From e0dfb20c2b77c6626a24578240266ace928cd2e7 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:06 +0900 Subject: MIPS: TXx9: Improve handling of built-in and command-line args * Make prom_init_cmdline() static and be called from prom_init. * Append built-in args if the first character was '+'. * Drop command-line args if the first character of built-in was '-'. * Enclose args include spaces by quotes. * TX4938_NAND_BOOT is no longer needed. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/Kconfig | 7 ------- arch/mips/txx9/generic/setup.c | 42 +++++++++++++++++++++++++++++++----------- arch/mips/txx9/jmr3927/prom.c | 1 - arch/mips/txx9/rbtx4927/prom.c | 1 - arch/mips/txx9/rbtx4938/prom.c | 3 --- 5 files changed, 31 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 840fe757c48..6fb2ef09d5d 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -97,13 +97,6 @@ config TOSHIBA_RBTX4938_MPLEX_ATA endchoice -config TX4938_NAND_BOOT - depends on EXPERIMENTAL && TOSHIBA_RBTX4938_MPLEX_NAND - bool "NAND Boot Support (EXPERIMENTAL)" - help - This is only for Toshiba RBTX4938 reference board, which has NAND IPL. - Select this option if you need to use NAND boot. - endif config PCI_TX4927 diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index fe6bee09cec..33d8c9e3223 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -127,31 +127,51 @@ extern struct txx9_board_vec rbtx4938_vec; struct txx9_board_vec *txx9_board_vec __initdata; static char txx9_system_type[32]; -void __init prom_init_cmdline(void) +static void __init prom_init_cmdline(void) { int argc = (int)fw_arg0; - char **argv = (char **)fw_arg1; + int *argv32 = (int *)fw_arg1; int i; /* Always ignore the "-c" at argv[0] */ -#ifdef CONFIG_64BIT - char *fixed_argv[32]; - for (i = 0; i < argc; i++) - fixed_argv[i] = (char *)(long)(*((__s32 *)argv + i)); - argv = fixed_argv; -#endif + char builtin[CL_SIZE]; /* ignore all built-in args if any f/w args given */ - if (argc > 1) - *arcs_cmdline = '\0'; + /* + * But if built-in strings was started with '+', append them + * to command line args. If built-in was started with '-', + * ignore all f/w args. + */ + builtin[0] = '\0'; + if (arcs_cmdline[0] == '+') + strcpy(builtin, arcs_cmdline + 1); + else if (arcs_cmdline[0] == '-') { + strcpy(builtin, arcs_cmdline + 1); + argc = 0; + } else if (argc <= 1) + strcpy(builtin, arcs_cmdline); + arcs_cmdline[0] = '\0'; for (i = 1; i < argc; i++) { + char *str = (char *)(long)argv32[i]; if (i != 1) strcat(arcs_cmdline, " "); - strcat(arcs_cmdline, argv[i]); + if (strchr(str, ' ')) { + strcat(arcs_cmdline, "\""); + strcat(arcs_cmdline, str); + strcat(arcs_cmdline, "\""); + } else + strcat(arcs_cmdline, str); + } + /* append saved builtin args */ + if (builtin[0]) { + if (arcs_cmdline[0]) + strcat(arcs_cmdline, " "); + strcat(arcs_cmdline, builtin); } } void __init prom_init(void) { + prom_init_cmdline(); #ifdef CONFIG_CPU_TX39XX txx9_board_vec = &jmr3927_vec; #endif diff --git a/arch/mips/txx9/jmr3927/prom.c b/arch/mips/txx9/jmr3927/prom.c index 70c4c8ec3e8..c899c0c087a 100644 --- a/arch/mips/txx9/jmr3927/prom.c +++ b/arch/mips/txx9/jmr3927/prom.c @@ -47,7 +47,6 @@ void __init jmr3927_prom_init(void) if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0) printk(KERN_ERR "TX3927 TLB off\n"); - prom_init_cmdline(); add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM); txx9_sio_putchar_init(TX3927_SIO_REG(1)); } diff --git a/arch/mips/txx9/rbtx4927/prom.c b/arch/mips/txx9/rbtx4927/prom.c index 1dc0a5b1956..cc97c6a6011 100644 --- a/arch/mips/txx9/rbtx4927/prom.c +++ b/arch/mips/txx9/rbtx4927/prom.c @@ -36,7 +36,6 @@ void __init rbtx4927_prom_init(void) { - prom_init_cmdline(); add_memory_region(0, tx4927_get_mem_size(), BOOT_MEM_RAM); txx9_sio_putchar_init(TX4927_SIO_REG(0) & 0xfffffffffULL); } diff --git a/arch/mips/txx9/rbtx4938/prom.c b/arch/mips/txx9/rbtx4938/prom.c index d73123cd2ab..bcb469247e8 100644 --- a/arch/mips/txx9/rbtx4938/prom.c +++ b/arch/mips/txx9/rbtx4938/prom.c @@ -18,9 +18,6 @@ void __init rbtx4938_prom_init(void) { -#ifndef CONFIG_TX4938_NAND_BOOT - prom_init_cmdline(); -#endif add_memory_region(0, tx4938_get_mem_size(), BOOT_MEM_RAM); txx9_sio_putchar_init(TX4938_SIO_REG(0) & 0xfffffffffULL); } -- cgit v1.2.3 From 265b89db1058124ddbf0091ba3f8c020e3a5ae9d Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:07 +0900 Subject: MIPS: TXx9: Add prom_getenv Add prom_getenv() which can be used for YAMON. This assumes other firmware should pass NULL for fw_arg2. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 33d8c9e3223..005179c2af2 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -212,6 +212,21 @@ char * __init prom_getcmdline(void) return &(arcs_cmdline[0]); } +const char *__init prom_getenv(const char *name) +{ + const s32 *str = (const s32 *)fw_arg2; + + if (!str) + return NULL; + /* YAMON style ("name", "value" pairs) */ + while (str[0] && str[1]) { + if (!strcmp((const char *)(unsigned long)str[0], name)) + return (const char *)(unsigned long)str[1]; + str += 2; + } + return NULL; +} + static void __noreturn txx9_machine_halt(void) { local_irq_disable(); -- cgit v1.2.3 From 860e546c19d88c21819c7f0861c505debd2d6eed Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:08 +0900 Subject: MIPS: TXx9: Early command-line preprocessing * Select board by command-line option or firmware environment variable. * Handle "masterclk=" option. * Add boards.h to centerize board_vec declaration. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 include/asm-mips/txx9/boards.h --- arch/mips/txx9/generic/setup.c | 74 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 005179c2af2..dc5dbcc53a9 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -119,14 +119,31 @@ int irq_to_gpio(unsigned irq) EXPORT_SYMBOL(irq_to_gpio); #endif -extern struct txx9_board_vec jmr3927_vec; -extern struct txx9_board_vec rbtx4927_vec; -extern struct txx9_board_vec rbtx4937_vec; -extern struct txx9_board_vec rbtx4938_vec; +#define BOARD_VEC(board) extern struct txx9_board_vec board; +#include +#undef BOARD_VEC struct txx9_board_vec *txx9_board_vec __initdata; static char txx9_system_type[32]; +static struct txx9_board_vec *board_vecs[] __initdata = { +#define BOARD_VEC(board) &board, +#include +#undef BOARD_VEC +}; + +static struct txx9_board_vec *__init find_board_byname(const char *name) +{ + int i; + + /* search board_vecs table */ + for (i = 0; i < ARRAY_SIZE(board_vecs); i++) { + if (strstr(board_vecs[i]->system, name)) + return board_vecs[i]; + } + return NULL; +} + static void __init prom_init_cmdline(void) { int argc = (int)fw_arg0; @@ -169,9 +186,47 @@ static void __init prom_init_cmdline(void) } } -void __init prom_init(void) +static void __init preprocess_cmdline(void) { - prom_init_cmdline(); + char cmdline[CL_SIZE]; + char *s; + + strcpy(cmdline, arcs_cmdline); + s = cmdline; + arcs_cmdline[0] = '\0'; + while (s && *s) { + char *str = strsep(&s, " "); + if (strncmp(str, "board=", 6) == 0) { + txx9_board_vec = find_board_byname(str + 6); + continue; + } else if (strncmp(str, "masterclk=", 10) == 0) { + unsigned long val; + if (strict_strtoul(str + 10, 10, &val) == 0) + txx9_master_clock = val; + continue; + } + if (arcs_cmdline[0]) + strcat(arcs_cmdline, " "); + strcat(arcs_cmdline, str); + } +} + +static void __init select_board(void) +{ + const char *envstr; + + /* first, determine by "board=" argument in preprocess_cmdline() */ + if (txx9_board_vec) + return; + /* next, determine by "board" envvar */ + envstr = prom_getenv("board"); + if (envstr) { + txx9_board_vec = find_board_byname(envstr); + if (txx9_board_vec) + return; + } + + /* select "default" board */ #ifdef CONFIG_CPU_TX39XX txx9_board_vec = &jmr3927_vec; #endif @@ -192,6 +247,13 @@ void __init prom_init(void) #endif } #endif +} + +void __init prom_init(void) +{ + prom_init_cmdline(); + preprocess_cmdline(); + select_board(); strcpy(txx9_system_type, txx9_board_vec->system); -- cgit v1.2.3 From d10e025f0e4ba4b96d7b5786d232ac5b0b232b11 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:09 +0900 Subject: MIPS: TXx9: Cache fixup TX39/TX49 can enable/disable I/D cache at runtime. Add kernel options to control them. This is useful to debug some cache-related issues, such as aliasing or I/D coherency. Also enable CWF bit for TX49 SoCs. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 113 ++++++++++++++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx3927.c | 18 +++--- arch/mips/txx9/generic/setup_tx4927.c | 1 + arch/mips/txx9/generic/setup_tx4938.c | 1 + arch/mips/txx9/jmr3927/setup.c | 11 +--- arch/mips/txx9/rbtx4927/setup.c | 6 -- 6 files changed, 124 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index dc5dbcc53a9..fa88aefea9e 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_CPU_TX49XX @@ -186,6 +187,110 @@ static void __init prom_init_cmdline(void) } } +static int txx9_ic_disable __initdata; +static int txx9_dc_disable __initdata; + +#if defined(CONFIG_CPU_TX49XX) +/* flush all cache on very early stage (before 4k_cache_init) */ +static void __init early_flush_dcache(void) +{ + unsigned int conf = read_c0_config(); + unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6)); + unsigned int linesz = 32; + unsigned long addr, end; + + end = INDEX_BASE + dc_size / 4; + /* 4way, waybit=0 */ + for (addr = INDEX_BASE; addr < end; addr += linesz) { + cache_op(Index_Writeback_Inv_D, addr | 0); + cache_op(Index_Writeback_Inv_D, addr | 1); + cache_op(Index_Writeback_Inv_D, addr | 2); + cache_op(Index_Writeback_Inv_D, addr | 3); + } +} + +static void __init txx9_cache_fixup(void) +{ + unsigned int conf; + + conf = read_c0_config(); + /* flush and disable */ + if (txx9_ic_disable) { + conf |= TX49_CONF_IC; + write_c0_config(conf); + } + if (txx9_dc_disable) { + early_flush_dcache(); + conf |= TX49_CONF_DC; + write_c0_config(conf); + } + + /* enable cache */ + conf = read_c0_config(); + if (!txx9_ic_disable) + conf &= ~TX49_CONF_IC; + if (!txx9_dc_disable) + conf &= ~TX49_CONF_DC; + write_c0_config(conf); + + if (conf & TX49_CONF_IC) + pr_info("TX49XX I-Cache disabled.\n"); + if (conf & TX49_CONF_DC) + pr_info("TX49XX D-Cache disabled.\n"); +} +#elif defined(CONFIG_CPU_TX39XX) +/* flush all cache on very early stage (before tx39_cache_init) */ +static void __init early_flush_dcache(void) +{ + unsigned int conf = read_c0_config(); + unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >> + TX39_CONF_DCS_SHIFT)); + unsigned int linesz = 16; + unsigned long addr, end; + + end = INDEX_BASE + dc_size / 2; + /* 2way, waybit=0 */ + for (addr = INDEX_BASE; addr < end; addr += linesz) { + cache_op(Index_Writeback_Inv_D, addr | 0); + cache_op(Index_Writeback_Inv_D, addr | 1); + } +} + +static void __init txx9_cache_fixup(void) +{ + unsigned int conf; + + conf = read_c0_config(); + /* flush and disable */ + if (txx9_ic_disable) { + conf &= ~TX39_CONF_ICE; + write_c0_config(conf); + } + if (txx9_dc_disable) { + early_flush_dcache(); + conf &= ~TX39_CONF_DCE; + write_c0_config(conf); + } + + /* enable cache */ + conf = read_c0_config(); + if (!txx9_ic_disable) + conf |= TX39_CONF_ICE; + if (!txx9_dc_disable) + conf |= TX39_CONF_DCE; + write_c0_config(conf); + + if (!(conf & TX39_CONF_ICE)) + pr_info("TX39XX I-Cache disabled.\n"); + if (!(conf & TX39_CONF_DCE)) + pr_info("TX39XX D-Cache disabled.\n"); +} +#else +static inline void txx9_cache_fixup(void) +{ +} +#endif + static void __init preprocess_cmdline(void) { char cmdline[CL_SIZE]; @@ -204,11 +309,19 @@ static void __init preprocess_cmdline(void) if (strict_strtoul(str + 10, 10, &val) == 0) txx9_master_clock = val; continue; + } else if (strcmp(str, "icdisable") == 0) { + txx9_ic_disable = 1; + continue; + } else if (strcmp(str, "dcdisable") == 0) { + txx9_dc_disable = 1; + continue; } if (arcs_cmdline[0]) strcat(arcs_cmdline, " "); strcat(arcs_cmdline, str); } + + txx9_cache_fixup(); } static void __init select_board(void) diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c index 7bd963d37fc..4bc2f859379 100644 --- a/arch/mips/txx9/generic/setup_tx3927.c +++ b/arch/mips/txx9/generic/setup_tx3927.c @@ -99,16 +99,14 @@ void __init tx3927_setup(void) txx9_gpio_init(TX3927_PIO_REG, 0, 16); conf = read_c0_conf(); - if (!(conf & TX39_CONF_ICE)) - printk(KERN_INFO "TX3927 I-Cache disabled.\n"); - if (!(conf & TX39_CONF_DCE)) - printk(KERN_INFO "TX3927 D-Cache disabled.\n"); - else if (!(conf & TX39_CONF_WBON)) - printk(KERN_INFO "TX3927 D-Cache WriteThrough.\n"); - else if (!(conf & TX39_CONF_CWFON)) - printk(KERN_INFO "TX3927 D-Cache WriteBack.\n"); - else - printk(KERN_INFO "TX3927 D-Cache WriteBack (CWF) .\n"); + if (conf & TX39_CONF_DCE) { + if (!(conf & TX39_CONF_WBON)) + pr_info("TX3927 D-Cache WriteThrough.\n"); + else if (!(conf & TX39_CONF_CWFON)) + pr_info("TX3927 D-Cache WriteBack.\n"); + else + pr_info("TX3927 D-Cache WriteBack (CWF) .\n"); + } } void __init tx3927_time_init(unsigned int evt_tmrnr, unsigned int src_tmrnr) diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index f80d4b7a694..e679c79a4b0 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -44,6 +44,7 @@ void __init tx4927_setup(void) txx9_reg_res_init(TX4927_REV_PCODE(), TX4927_REG_BASE, TX4927_REG_SIZE); + set_c0_config(TX49_CONF_CWFON); /* SDRAMC,EBUSC are configured by PROM */ for (i = 0; i < 8; i++) { diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index f3040b9ba05..95c058f0a96 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -47,6 +47,7 @@ void __init tx4938_setup(void) txx9_reg_res_init(TX4938_REV_PCODE(), TX4938_REG_BASE, TX4938_REG_SIZE); + set_c0_config(TX49_CONF_CWFON); /* SDRAMC,EBUSC are configured by PROM */ for (i = 0; i < 8; i++) { diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c index 87db41be8a5..2e40a926825 100644 --- a/arch/mips/txx9/jmr3927/setup.c +++ b/arch/mips/txx9/jmr3927/setup.c @@ -62,7 +62,6 @@ static void __init jmr3927_time_init(void) } #define DO_WRITE_THROUGH -#define DO_ENABLE_CACHE static void jmr3927_board_init(void); @@ -77,11 +76,6 @@ static void __init jmr3927_mem_setup(void) /* cache setup */ { unsigned int conf; -#ifdef DO_ENABLE_CACHE - int mips_ic_disable = 0, mips_dc_disable = 0; -#else - int mips_ic_disable = 1, mips_dc_disable = 1; -#endif #ifdef DO_WRITE_THROUGH int mips_config_cwfon = 0; int mips_config_wbon = 0; @@ -91,10 +85,7 @@ static void __init jmr3927_mem_setup(void) #endif conf = read_c0_conf(); - conf &= ~(TX39_CONF_ICE | TX39_CONF_DCE | - TX39_CONF_WBON | TX39_CONF_CWFON); - conf |= mips_ic_disable ? 0 : TX39_CONF_ICE; - conf |= mips_dc_disable ? 0 : TX39_CONF_DCE; + conf &= ~(TX39_CONF_WBON | TX39_CONF_CWFON); conf |= mips_config_wbon ? TX39_CONF_WBON : 0; conf |= mips_config_cwfon ? TX39_CONF_CWFON : 0; diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index 5985f330838..0464a39b39a 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -186,14 +186,8 @@ static void __init rbtx4937_clock_init(void); static void __init rbtx4927_mem_setup(void) { - u32 cp0_config; char *argptr; - /* enable caches -- HCP5 does this, pmon does not */ - cp0_config = read_c0_config(); - cp0_config = cp0_config & ~(TX49_CONF_IC | TX49_CONF_DC); - write_c0_config(cp0_config); - if (TX4927_REV_PCODE() == 0x4927) { rbtx4927_clock_init(); tx4927_setup(); -- cgit v1.2.3 From c7b95bcb38ea492fd025008ef99501a2b90aa237 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:10 +0900 Subject: MIPS: TXx9: Runtime configuration of timeout-error Add kernel options to control bus timeout error. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 11 +++++++++++ arch/mips/txx9/generic/setup_tx3927.c | 5 ----- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index fa88aefea9e..fa45f174b0e 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -68,7 +68,12 @@ unsigned int txx9_master_clock; unsigned int txx9_cpu_clock; unsigned int txx9_gbus_clock; +#ifdef CONFIG_CPU_TX39XX +/* don't enable by default - see errata */ +int txx9_ccfg_toeon __initdata; +#else int txx9_ccfg_toeon __initdata = 1; +#endif /* Minimum CLK support */ @@ -315,6 +320,12 @@ static void __init preprocess_cmdline(void) } else if (strcmp(str, "dcdisable") == 0) { txx9_dc_disable = 1; continue; + } else if (strcmp(str, "toeoff") == 0) { + txx9_ccfg_toeon = 0; + continue; + } else if (strcmp(str, "toeon") == 0) { + txx9_ccfg_toeon = 1; + continue; } if (arcs_cmdline[0]) strcat(arcs_cmdline, " "); diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c index 4bc2f859379..06c49257607 100644 --- a/arch/mips/txx9/generic/setup_tx3927.c +++ b/arch/mips/txx9/generic/setup_tx3927.c @@ -32,11 +32,6 @@ void __init tx3927_setup(void) int i; unsigned int conf; - /* don't enable - see errata */ - txx9_ccfg_toeon = 0; - if (strstr(prom_getcmdline(), "toeon") != NULL) - txx9_ccfg_toeon = 1; - txx9_reg_res_init(TX3927_REV_PCODE(), TX3927_REG_BASE, TX3927_REG_SIZE); -- cgit v1.2.3 From 51f607c76e1e7bd089dcad97b6b0a58649be06a3 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:11 +0900 Subject: MIPS: TXx9: Add mtd support Add helper routines to register physmap-flash platform devices for NOR flashes. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 41 +++++++++++++++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx3927.c | 14 ++++++++++++ arch/mips/txx9/generic/setup_tx4927.c | 14 ++++++++++++ arch/mips/txx9/generic/setup_tx4938.c | 14 ++++++++++++ arch/mips/txx9/jmr3927/setup.c | 9 ++++++++ arch/mips/txx9/rbtx4927/setup.c | 9 ++++++++ arch/mips/txx9/rbtx4938/setup.c | 38 ++++++++++++++++++++++++++++++++ 7 files changed, 139 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index fa45f174b0e..cfa3ccf493b 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -593,3 +594,43 @@ static unsigned long __swizzle_addr_none(unsigned long port) unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none; EXPORT_SYMBOL(__swizzle_addr_b); #endif + +void __init txx9_physmap_flash_init(int no, unsigned long addr, + unsigned long size, + const struct physmap_flash_data *pdata) +{ +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) + struct resource res = { + .start = addr, + .end = addr + size - 1, + .flags = IORESOURCE_MEM, + }; + struct platform_device *pdev; +#ifdef CONFIG_MTD_PARTITIONS + static struct mtd_partition parts[2]; + struct physmap_flash_data pdata_part; + + /* If this area contained boot area, make separate partition */ + if (pdata->nr_parts == 0 && !pdata->parts && + addr < 0x1fc00000 && addr + size > 0x1fc00000 && + !parts[0].name) { + parts[0].name = "boot"; + parts[0].offset = 0x1fc00000 - addr; + parts[0].size = addr + size - 0x1fc00000; + parts[1].name = "user"; + parts[1].offset = 0; + parts[1].size = 0x1fc00000 - addr; + pdata_part = *pdata; + pdata_part.nr_parts = ARRAY_SIZE(parts); + pdata_part.parts = parts; + pdata = &pdata_part; + } +#endif + pdev = platform_device_alloc("physmap-flash", no); + if (!pdev || + platform_device_add_resources(pdev, &res, 1) || + platform_device_add_data(pdev, pdata, sizeof(*pdata)) || + platform_device_add(pdev)) + platform_device_put(pdev); +#endif +} diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c index 06c49257607..9505d58454c 100644 --- a/arch/mips/txx9/generic/setup_tx3927.c +++ b/arch/mips/txx9/generic/setup_tx3927.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -121,3 +122,16 @@ void __init tx3927_sio_init(unsigned int sclk, unsigned int cts_mask) TXX9_IRQ_BASE + TX3927_IR_SIO(i), i, sclk, (1 << i) & cts_mask); } + +void __init tx3927_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX3927_ROMC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(tx3927_romcptr->cr[ch] & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index e679c79a4b0..0840ef930e4 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -187,3 +188,16 @@ void __init tx4927_sio_init(unsigned int sclk, unsigned int cts_mask) TXX9_IRQ_BASE + TX4927_IR_SIO(i), i, sclk, (1 << i) & cts_mask); } + +void __init tx4927_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX4927_EBUSC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(TX4927_EBUSC_CR(ch) & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 95c058f0a96..630a7aac61f 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -269,3 +270,16 @@ void __init tx4938_ethaddr_init(unsigned char *addr0, unsigned char *addr1) if (addr1 && (pcfg & TX4938_PCFG_ETH1_SEL)) txx9_ethaddr_init(TXX9_IRQ_BASE + TX4938_IR_ETH1, addr1); } + +void __init tx4938_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX4938_EBUSC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(TX4938_EBUSC_CR(ch) & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c index 2e40a926825..0f3843c92cf 100644 --- a/arch/mips/txx9/jmr3927/setup.c +++ b/arch/mips/txx9/jmr3927/setup.c @@ -190,11 +190,20 @@ static void __init jmr3927_rtc_init(void) platform_device_register_simple("rtc-ds1742", -1, &res, 1); } +static void __init jmr3927_mtd_init(void) +{ + int i; + + for (i = 0; i < 2; i++) + tx3927_mtd_init(i); +} + static void __init jmr3927_device_init(void) { __swizzle_addr_b = jmr3927_swizzle_addr_b; jmr3927_rtc_init(); tx3927_wdt_init(); + jmr3927_mtd_init(); } struct txx9_board_vec jmr3927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index 0464a39b39a..abe32c1a79d 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -307,11 +307,20 @@ static void __init rbtx4927_ne_init(void) platform_device_register_simple("ne", -1, res, ARRAY_SIZE(res)); } +static void __init rbtx4927_mtd_init(void) +{ + int i; + + for (i = 0; i < 2; i++) + tx4927_mtd_init(i); +} + static void __init rbtx4927_device_init(void) { toshiba_rbtx4927_rtc_init(); rbtx4927_ne_init(); tx4927_wdt_init(); + rbtx4927_mtd_init(); } struct txx9_board_vec rbtx4927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index 9ab48dec0fe..e7bc5b8c7db 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -294,6 +295,42 @@ static int __init rbtx4938_spi_init(void) return 0; } +static void __init rbtx4938_mtd_init(void) +{ + struct physmap_flash_data pdata = { + .width = 4, + }; + + switch (readb(rbtx4938_bdipsw_addr) & 7) { + case 0: + /* Boot */ + txx9_physmap_flash_init(0, 0x1fc00000, 0x400000, &pdata); + /* System */ + txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); + break; + case 1: + /* System */ + txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); + /* Boot */ + txx9_physmap_flash_init(1, 0x1ec00000, 0x400000, &pdata); + break; + case 2: + /* Ext */ + txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); + /* System */ + txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); + /* Boot */ + txx9_physmap_flash_init(2, 0x1dc00000, 0x400000, &pdata); + break; + case 3: + /* Boot */ + txx9_physmap_flash_init(1, 0x1bc00000, 0x400000, &pdata); + /* System */ + txx9_physmap_flash_init(2, 0x1a000000, 0x1000000, &pdata); + break; + } +} + static void __init rbtx4938_arch_init(void) { gpiochip_add(&rbtx4938_spi_gpio_chip); @@ -306,6 +343,7 @@ static void __init rbtx4938_device_init(void) rbtx4938_ethaddr_init(); rbtx4938_ne_init(); tx4938_wdt_init(); + rbtx4938_mtd_init(); } struct txx9_board_vec rbtx4938_vec __initdata = { -- cgit v1.2.3 From 74894363499942a76f2c20e41e8bfebc9fdc267a Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:12 +0900 Subject: MIPS: TXx9: Raise priority of interrupts for errors, timers, SIO Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/irq_tx4927.c | 11 +++++++++++ arch/mips/txx9/generic/irq_tx4938.c | 11 +++++++++++ 2 files changed, 22 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/irq_tx4927.c b/arch/mips/txx9/generic/irq_tx4927.c index cbea1fdde82..ad2870def8f 100644 --- a/arch/mips/txx9/generic/irq_tx4927.c +++ b/arch/mips/txx9/generic/irq_tx4927.c @@ -30,8 +30,19 @@ void __init tx4927_irq_init(void) { + int i; + mips_cpu_irq_init(); txx9_irq_init(TX4927_IRC_REG & 0xfffffffffULL); set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT, handle_simple_irq); + /* raise priority for errors, timers, SIO */ + txx9_irq_set_pri(TX4927_IR_ECCERR, 7); + txx9_irq_set_pri(TX4927_IR_WTOERR, 7); + txx9_irq_set_pri(TX4927_IR_PCIERR, 7); + txx9_irq_set_pri(TX4927_IR_PCIPME, 7); + for (i = 0; i < TX4927_NUM_IR_TMR; i++) + txx9_irq_set_pri(TX4927_IR_TMR(i), 6); + for (i = 0; i < TX4927_NUM_IR_SIO; i++) + txx9_irq_set_pri(TX4927_IR_SIO(i), 5); } diff --git a/arch/mips/txx9/generic/irq_tx4938.c b/arch/mips/txx9/generic/irq_tx4938.c index 6eac684bf19..025ae11359a 100644 --- a/arch/mips/txx9/generic/irq_tx4938.c +++ b/arch/mips/txx9/generic/irq_tx4938.c @@ -18,8 +18,19 @@ void __init tx4938_irq_init(void) { + int i; + mips_cpu_irq_init(); txx9_irq_init(TX4938_IRC_REG & 0xfffffffffULL); set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT, handle_simple_irq); + /* raise priority for errors, timers, SIO */ + txx9_irq_set_pri(TX4938_IR_ECCERR, 7); + txx9_irq_set_pri(TX4938_IR_WTOERR, 7); + txx9_irq_set_pri(TX4938_IR_PCIERR, 7); + txx9_irq_set_pri(TX4938_IR_PCIPME, 7); + for (i = 0; i < TX4938_NUM_IR_TMR; i++) + txx9_irq_set_pri(TX4938_IR_TMR(i), 6); + for (i = 0; i < TX4938_NUM_IR_SIO; i++) + txx9_irq_set_pri(TX4938_IR_SIO(i), 5); } -- cgit v1.2.3 From e6332374770ae5aa370af5792115261edbad05c1 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:13 +0900 Subject: MIPS: RBTX4938: Add TOSHIBA_RBTX4938_MPLEX_KEEP Add TOSHIBA_RBTX4938_MPLEX_KEEP to keep MPLEX settings by firmware. Also replace some printk with pr_info. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/Kconfig | 2 ++ arch/mips/txx9/rbtx4938/setup.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 6fb2ef09d5d..aade3348af2 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -94,6 +94,8 @@ config TOSHIBA_RBTX4938_MPLEX_NAND bool "NAND" config TOSHIBA_RBTX4938_MPLEX_ATA bool "ATA" +config TOSHIBA_RBTX4938_MPLEX_KEEP + bool "Keep firmware settings" endchoice diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index e7bc5b8c7db..7aba92a1239 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -174,23 +174,30 @@ static void __init rbtx4938_mem_setup(void) #endif #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61 - printk(KERN_INFO "PIOSEL: disabling both ata and nand selection\n"); + pr_info("PIOSEL: disabling both ATA and NAND selection\n"); txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL | TX4938_PCFG_ATA_SEL); #endif #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND - printk(KERN_INFO "PIOSEL: enabling nand selection\n"); + pr_info("PIOSEL: enabling NAND selection\n"); txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); #endif #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA - printk(KERN_INFO "PIOSEL: enabling ata selection\n"); + pr_info("PIOSEL: enabling ATA selection\n"); txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); #endif +#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_KEEP + pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); + pr_info("PIOSEL: NAND %s, ATA %s\n", + (pcfg & TX4938_PCFG_NDF_SEL) ? "enabled" : "disabled", + (pcfg & TX4938_PCFG_ATA_SEL) ? "enabled" : "disabled"); +#endif + rbtx4938_spi_setup(); pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); /* updated */ /* fixup piosel */ -- cgit v1.2.3 From d75a40e90e9eb08c2159e719a90a7922dab231d3 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:14 +0900 Subject: MIPS: TXx9: Make spi_eeprom.c more generic Helper routines in txx9/rbtx4938/spi_eeprom.c is not TX4938 specific. Move it to txx9/generic/ directory and make it works with SPI bus number other than 0. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 arch/mips/txx9/generic/spi_eeprom.c delete mode 100644 arch/mips/txx9/rbtx4938/spi_eeprom.c --- arch/mips/txx9/generic/Makefile | 1 + arch/mips/txx9/generic/spi_eeprom.c | 103 +++++++++++++++++++++++++++++++++++ arch/mips/txx9/rbtx4938/Makefile | 2 +- arch/mips/txx9/rbtx4938/setup.c | 11 ++-- arch/mips/txx9/rbtx4938/spi_eeprom.c | 99 --------------------------------- 5 files changed, 111 insertions(+), 105 deletions(-) create mode 100644 arch/mips/txx9/generic/spi_eeprom.c delete mode 100644 arch/mips/txx9/rbtx4938/spi_eeprom.c (limited to 'arch') diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile index 9bb34af26b7..986852cc774 100644 --- a/arch/mips/txx9/generic/Makefile +++ b/arch/mips/txx9/generic/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_SOC_TX3927) += setup_tx3927.o irq_tx3927.o obj-$(CONFIG_SOC_TX4927) += mem_tx4927.o setup_tx4927.o irq_tx4927.o obj-$(CONFIG_SOC_TX4938) += mem_tx4927.o setup_tx4938.o irq_tx4938.o obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o +obj-$(CONFIG_SPI) += spi_eeprom.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/generic/spi_eeprom.c b/arch/mips/txx9/generic/spi_eeprom.c new file mode 100644 index 00000000000..75c347238f4 --- /dev/null +++ b/arch/mips/txx9/generic/spi_eeprom.c @@ -0,0 +1,103 @@ +/* + * spi_eeprom.c + * Copyright (C) 2000-2001 Toshiba Corporation + * + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) + */ +#include +#include +#include +#include +#include + +#define AT250X0_PAGE_SIZE 8 + +/* register board information for at25 driver */ +int __init spi_eeprom_register(int busid, int chipid, int size) +{ + struct spi_board_info info = { + .modalias = "at25", + .max_speed_hz = 1500000, /* 1.5Mbps */ + .bus_num = busid, + .chip_select = chipid, + /* Mode 0: High-Active, Sample-Then-Shift */ + }; + struct spi_eeprom *eeprom; + eeprom = kzalloc(sizeof(*eeprom), GFP_KERNEL); + if (!eeprom) + return -ENOMEM; + strcpy(eeprom->name, "at250x0"); + eeprom->byte_len = size; + eeprom->page_size = AT250X0_PAGE_SIZE; + eeprom->flags = EE_ADDR1; + info.platform_data = eeprom; + return spi_register_board_info(&info, 1); +} + +/* simple temporary spi driver to provide early access to seeprom. */ + +static struct read_param { + int busid; + int chipid; + int address; + unsigned char *buf; + int len; +} *read_param; + +static int __init early_seeprom_probe(struct spi_device *spi) +{ + int stat = 0; + u8 cmd[2]; + int len = read_param->len; + char *buf = read_param->buf; + int address = read_param->address; + + dev_info(&spi->dev, "spiclk %u KHz.\n", + (spi->max_speed_hz + 500) / 1000); + if (read_param->busid != spi->master->bus_num || + read_param->chipid != spi->chip_select) + return -ENODEV; + while (len > 0) { + /* spi_write_then_read can only work with small chunk */ + int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE; + cmd[0] = 0x03; /* AT25_READ */ + cmd[1] = address; + stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c); + buf += c; + len -= c; + address += c; + } + return stat; +} + +static struct spi_driver early_seeprom_driver __initdata = { + .driver = { + .name = "at25", + .owner = THIS_MODULE, + }, + .probe = early_seeprom_probe, +}; + +int __init spi_eeprom_read(int busid, int chipid, int address, + unsigned char *buf, int len) +{ + int ret; + struct read_param param = { + .busid = busid, + .chipid = chipid, + .address = address, + .buf = buf, + .len = len + }; + + read_param = ¶m; + ret = spi_register_driver(&early_seeprom_driver); + if (!ret) + spi_unregister_driver(&early_seeprom_driver); + return ret; +} diff --git a/arch/mips/txx9/rbtx4938/Makefile b/arch/mips/txx9/rbtx4938/Makefile index 9dcc52ae5b9..f3e1f597b4f 100644 --- a/arch/mips/txx9/rbtx4938/Makefile +++ b/arch/mips/txx9/rbtx4938/Makefile @@ -1,3 +1,3 @@ -obj-y += prom.o setup.o irq.o spi_eeprom.o +obj-y += prom.o setup.o irq.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index 7aba92a1239..ec6e81258f7 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -111,6 +111,7 @@ static void __init rbtx4938_pci_setup(void) #define SEEPROM2_CS 0 /* IOC */ #define SEEPROM3_CS 1 /* IOC */ #define SRTC_CS 2 /* IOC */ +#define SPI_BUSNO 0 static int __init rbtx4938_ethaddr_init(void) { @@ -120,7 +121,7 @@ static int __init rbtx4938_ethaddr_init(void) int i; /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ - if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) { + if (spi_eeprom_read(SPI_BUSNO, SEEPROM1_CS, 0, dat, sizeof(dat))) { printk(KERN_ERR "seeprom: read error.\n"); return -ENODEV; } else { @@ -287,9 +288,9 @@ static int __init rbtx4938_spi_init(void) .mode = SPI_MODE_1 | SPI_CS_HIGH, }; spi_register_board_info(&srtc_info, 1); - spi_eeprom_register(SEEPROM1_CS); - spi_eeprom_register(16 + SEEPROM2_CS); - spi_eeprom_register(16 + SEEPROM3_CS); + spi_eeprom_register(SPI_BUSNO, SEEPROM1_CS, 128); + spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM2_CS, 128); + spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM3_CS, 128); gpio_request(16 + SRTC_CS, "rtc-rs5c348"); gpio_direction_output(16 + SRTC_CS, 0); gpio_request(SEEPROM1_CS, "seeprom1"); @@ -298,7 +299,7 @@ static int __init rbtx4938_spi_init(void) gpio_direction_output(16 + SEEPROM2_CS, 1); gpio_request(16 + SEEPROM3_CS, "seeprom3"); gpio_direction_output(16 + SEEPROM3_CS, 1); - tx4938_spi_init(0); + tx4938_spi_init(SPI_BUSNO); return 0; } diff --git a/arch/mips/txx9/rbtx4938/spi_eeprom.c b/arch/mips/txx9/rbtx4938/spi_eeprom.c deleted file mode 100644 index a7ea8b041c1..00000000000 --- a/arch/mips/txx9/rbtx4938/spi_eeprom.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * spi_eeprom.c - * Copyright (C) 2000-2001 Toshiba Corporation - * - * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is - * licensed "as is" without any warranty of any kind, whether express - * or implied. - * - * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) - */ -#include -#include -#include -#include -#include - -#define AT250X0_PAGE_SIZE 8 - -/* register board information for at25 driver */ -int __init spi_eeprom_register(int chipid) -{ - static struct spi_eeprom eeprom = { - .name = "at250x0", - .byte_len = 128, - .page_size = AT250X0_PAGE_SIZE, - .flags = EE_ADDR1, - }; - struct spi_board_info info = { - .modalias = "at25", - .max_speed_hz = 1500000, /* 1.5Mbps */ - .bus_num = 0, - .chip_select = chipid, - .platform_data = &eeprom, - /* Mode 0: High-Active, Sample-Then-Shift */ - }; - - return spi_register_board_info(&info, 1); -} - -/* simple temporary spi driver to provide early access to seeprom. */ - -static struct read_param { - int chipid; - int address; - unsigned char *buf; - int len; -} *read_param; - -static int __init early_seeprom_probe(struct spi_device *spi) -{ - int stat = 0; - u8 cmd[2]; - int len = read_param->len; - char *buf = read_param->buf; - int address = read_param->address; - - dev_info(&spi->dev, "spiclk %u KHz.\n", - (spi->max_speed_hz + 500) / 1000); - if (read_param->chipid != spi->chip_select) - return -ENODEV; - while (len > 0) { - /* spi_write_then_read can only work with small chunk */ - int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE; - cmd[0] = 0x03; /* AT25_READ */ - cmd[1] = address; - stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c); - buf += c; - len -= c; - address += c; - } - return stat; -} - -static struct spi_driver early_seeprom_driver __initdata = { - .driver = { - .name = "at25", - .owner = THIS_MODULE, - }, - .probe = early_seeprom_probe, -}; - -int __init spi_eeprom_read(int chipid, int address, - unsigned char *buf, int len) -{ - int ret; - struct read_param param = { - .chipid = chipid, - .address = address, - .buf = buf, - .len = len - }; - - read_param = ¶m; - ret = spi_register_driver(&early_seeprom_driver); - if (!ret) - spi_unregister_driver(&early_seeprom_driver); - return ret; -} -- cgit v1.2.3 From 496a3b5c2c188e8af07261792b3d4e6cf1c1dab9 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:15 +0900 Subject: MIPS: TXx9: Default machine_restart using watchdog reset Add default machine_restart routine using watchdog reset of TX4927 and TX4938. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 15 +++++++++++++++ arch/mips/txx9/generic/setup_tx4927.c | 28 ++++++++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx4938.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index cfa3ccf493b..118d716f783 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_CPU_TX49XX #include #endif @@ -444,6 +445,20 @@ void __init txx9_wdt_init(unsigned long base) platform_device_register_simple("txx9wdt", -1, &res, 1); } +void txx9_wdt_now(unsigned long base) +{ + struct txx9_tmr_reg __iomem *tmrptr = + ioremap(base, sizeof(struct txx9_tmr_reg)); + /* disable watch dog timer */ + __raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr); + __raw_writel(0, &tmrptr->tcr); + /* kick watchdog */ + __raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr); + __raw_writel(1, &tmrptr->cpra); /* immediate */ + __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, + &tmrptr->tcr); +} + /* SPI support */ void __init txx9_spi_init(int busid, unsigned long base, int irq) { diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index 0840ef930e4..7189675f6a2 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,10 @@ static void __init tx4927_wdr_init(void) { + /* report watchdog reset status */ + if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST) + pr_warning("Watchdog reset detected at 0x%lx\n", + read_c0_errorepc()); /* clear WatchDogReset (W1C) */ tx4927_ccfg_set(TX4927_CCFG_WDRST); /* do reset on watchdog */ @@ -34,6 +39,27 @@ void __init tx4927_wdt_init(void) txx9_wdt_init(TX4927_TMR_REG(2) & 0xfffffffffULL); } +static void tx4927_machine_restart(char *command) +{ + local_irq_disable(); + pr_emerg("Rebooting (with %s watchdog reset)...\n", + (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) ? + "external" : "internal"); + /* clear watchdog status */ + tx4927_ccfg_set(TX4927_CCFG_WDRST); /* W1C */ + txx9_wdt_now(TX4927_TMR_REG(2) & 0xfffffffffULL); + while (!(____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST)) + ; + mdelay(10); + if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) { + pr_emerg("Rebooting (with internal watchdog reset)...\n"); + /* External WDRST failed. Do internal watchdog reset */ + tx4927_ccfg_clear(TX4927_CCFG_WDREXEN); + } + /* fallback */ + (*_machine_halt)(); +} + static struct resource tx4927_sdram_resource[4]; void __init tx4927_setup(void) @@ -169,6 +195,8 @@ void __init tx4927_setup(void) txx9_gpio_init(TX4927_PIO_REG & 0xfffffffffULL, 0, TX4927_NUM_PIO); __raw_writel(0, &tx4927_pioptr->maskcpu); __raw_writel(0, &tx4927_pioptr->maskext); + + _machine_restart = tx4927_machine_restart; } void __init tx4927_time_init(unsigned int tmrnr) diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 630a7aac61f..4fbc85a8597 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,10 @@ static void __init tx4938_wdr_init(void) { + /* report watchdog reset status */ + if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST) + pr_warning("Watchdog reset detected at 0x%lx\n", + read_c0_errorepc()); /* clear WatchDogReset (W1C) */ tx4938_ccfg_set(TX4938_CCFG_WDRST); /* do reset on watchdog */ @@ -34,6 +39,27 @@ void __init tx4938_wdt_init(void) txx9_wdt_init(TX4938_TMR_REG(2) & 0xfffffffffULL); } +static void tx4938_machine_restart(char *command) +{ + local_irq_disable(); + pr_emerg("Rebooting (with %s watchdog reset)...\n", + (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) ? + "external" : "internal"); + /* clear watchdog status */ + tx4938_ccfg_set(TX4938_CCFG_WDRST); /* W1C */ + txx9_wdt_now(TX4938_TMR_REG(2) & 0xfffffffffULL); + while (!(____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST)) + ; + mdelay(10); + if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) { + pr_emerg("Rebooting (with internal watchdog reset)...\n"); + /* External WDRST failed. Do internal watchdog reset */ + tx4938_ccfg_clear(TX4938_CCFG_WDREXEN); + } + /* fallback */ + (*_machine_halt)(); +} + static struct resource tx4938_sdram_resource[4]; static struct resource tx4938_sram_resource; @@ -229,6 +255,8 @@ void __init tx4938_setup(void) TX4938_CLKCTR_ETH1CKD); } } + + _machine_restart = tx4938_machine_restart; } void __init tx4938_time_init(unsigned int tmrnr) -- cgit v1.2.3 From ce8e74112b1b1215aa5bbe261ed751498ce65434 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:16 +0900 Subject: MIPS: TXx9: Add board_be_init for TX4927/TX4938 Setup default board_be_handler for TX4927/TX4938. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup_tx4927.c | 23 +++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx4938.c | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index 7189675f6a2..c4248cbbd84 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -60,6 +62,26 @@ static void tx4927_machine_restart(char *command) (*_machine_halt)(); } +void show_registers(struct pt_regs *regs); +static int tx4927_be_handler(struct pt_regs *regs, int is_fixup) +{ + int data = regs->cp0_cause & 4; + console_verbose(); + pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc); + pr_err("ccfg:%llx, toea:%llx\n", + (unsigned long long)____raw_readq(&tx4927_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4927_ccfgptr->toea)); +#ifdef CONFIG_PCI + tx4927_report_pcic_status(); +#endif + show_registers(regs); + panic("BusError!"); +} +static void __init tx4927_be_init(void) +{ + board_be_handler = tx4927_be_handler; +} + static struct resource tx4927_sdram_resource[4]; void __init tx4927_setup(void) @@ -197,6 +219,7 @@ void __init tx4927_setup(void) __raw_writel(0, &tx4927_pioptr->maskext); _machine_restart = tx4927_machine_restart; + board_be_init = tx4927_be_init; } void __init tx4927_time_init(unsigned int tmrnr) diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 4fbc85a8597..0d8517ad3ad 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -60,6 +62,26 @@ static void tx4938_machine_restart(char *command) (*_machine_halt)(); } +void show_registers(struct pt_regs *regs); +static int tx4938_be_handler(struct pt_regs *regs, int is_fixup) +{ + int data = regs->cp0_cause & 4; + console_verbose(); + pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc); + pr_err("ccfg:%llx, toea:%llx\n", + (unsigned long long)____raw_readq(&tx4938_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4938_ccfgptr->toea)); +#ifdef CONFIG_PCI + tx4927_report_pcic_status(); +#endif + show_registers(regs); + panic("BusError!"); +} +static void __init tx4938_be_init(void) +{ + board_be_handler = tx4938_be_handler; +} + static struct resource tx4938_sdram_resource[4]; static struct resource tx4938_sram_resource; @@ -257,6 +279,7 @@ void __init tx4938_setup(void) } _machine_restart = tx4938_machine_restart; + board_be_init = tx4938_be_init; } void __init tx4938_time_init(unsigned int tmrnr) -- cgit v1.2.3 From ee25d33f87348fd9e0ea148c4a25a3e7415fb5ba Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:17 +0900 Subject: MIPS: TXx9: Add __init tag for tx4938_pcic1_map_irq. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-tx4938.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/pci/pci-tx4938.c b/arch/mips/pci/pci-tx4938.c index 60e2c52c2c5..1ea257bc3b8 100644 --- a/arch/mips/pci/pci-tx4938.c +++ b/arch/mips/pci/pci-tx4938.c @@ -114,7 +114,7 @@ int __init tx4938_pciclk66_setup(void) return pciclk; } -int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) +int __init tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) { if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) { switch (slot) { -- cgit v1.2.3 From 3cd4e067a3e548a56a8b5e202552dcd18a2783a9 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:00:22 +0200 Subject: MIPS: RB532: Cleanup and group definitions to their right places This patch moves GPIO related definitions to gpio.h and IRQ related to irq.h Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/devices.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 82ab395efa3..7090dc97606 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -34,21 +34,11 @@ #include #include #include - -#define ETH0_DMA_RX_IRQ (GROUP1_IRQ_BASE + 0) -#define ETH0_DMA_TX_IRQ (GROUP1_IRQ_BASE + 1) -#define ETH0_RX_OVR_IRQ (GROUP3_IRQ_BASE + 9) -#define ETH0_TX_UND_IRQ (GROUP3_IRQ_BASE + 10) +#include #define ETH0_RX_DMA_ADDR (DMA0_BASE_ADDR + 0 * DMA_CHAN_OFFSET) #define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET) -/* NAND definitions */ -#define GPIO_RDY (1 << 0x08) -#define GPIO_WPX (1 << 0x09) -#define GPIO_ALE (1 << 0x0a) -#define GPIO_CLE (1 << 0x0b) - static struct resource korina_dev0_res[] = { { .name = "korina_regs", @@ -101,8 +91,6 @@ static struct platform_device korina_dev0 = { .num_resources = ARRAY_SIZE(korina_dev0_res), }; -#define CF_GPIO_NUM 13 - static struct resource cf_slot0_res[] = { { .name = "cf_membase", @@ -116,7 +104,7 @@ static struct resource cf_slot0_res[] = { }; static struct cf_device cf_slot0_data = { - .gpio_pin = 13 + .gpio_pin = CF_GPIO_NUM }; static struct platform_device cf_slot0 = { -- cgit v1.2.3 From 3c8cf8caa5b217fbb17d0dce7f6bbec1d7da7249 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:01:03 +0200 Subject: MIPS: RB532: Use physical addresses for gpio and device controller registers This patch fixes the misuse of virtual addresses for the GPIO and third device controller which would lead to problems while accessing ioremap'd registers. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/gpio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 00a1c7877bf..11d7127655e 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -47,8 +47,8 @@ struct mpmc_device dev3; static struct resource rb532_gpio_reg0_res[] = { { .name = "gpio_reg0", - .start = (u32)(IDT434_REG_BASE + GPIOBASE), - .end = (u32)(IDT434_REG_BASE + GPIOBASE + sizeof(struct rb532_gpio_reg)), + .start = REGBASE + GPIOBASE, + .end = REGBASE + GPIOBASE + sizeof(struct rb532_gpio_reg) - 1, .flags = IORESOURCE_MEM, } }; @@ -56,8 +56,8 @@ static struct resource rb532_gpio_reg0_res[] = { static struct resource rb532_dev3_ctl_res[] = { { .name = "dev3_ctl", - .start = (u32)(IDT434_REG_BASE + DEV3BASE), - .end = (u32)(IDT434_REG_BASE + DEV3BASE + sizeof(struct dev_reg)), + .start = REGBASE + DEV3BASE, + .end = REGBASE + DEV3BASE + sizeof(struct dev_reg) - 1, .flags = IORESOURCE_MEM, } }; -- cgit v1.2.3 From 49afa0a15180c22c8836ef36edd6aa48ab7b2915 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:01:31 +0200 Subject: MIPS: RB532: Remove gpio bootup state We are no longer using gpio bootup state, so do not export it and do not parse the kernel command line tag for it. Instead we provide gpio-keys for the button the gpio bootup state was checking. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/prom.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch') diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c index 1bc0af8febf..c5d8868e1b1 100644 --- a/arch/mips/rb532/prom.c +++ b/arch/mips/rb532/prom.c @@ -41,8 +41,6 @@ extern void __init setup_serial_port(void); unsigned int idt_cpu_freq = 132000000; EXPORT_SYMBOL(idt_cpu_freq); -unsigned int gpio_bootup_state; -EXPORT_SYMBOL(gpio_bootup_state); static struct resource ddr_reg[] = { { @@ -108,9 +106,6 @@ void __init prom_setup_cmdline(void) mips_machtype = MACH_MIKROTIK_RB532; } - if (match_tag(prom_argv[i], GPIO_TAG)) - gpio_bootup_state = tag2ul(prom_argv[i], GPIO_TAG); - strcpy(cp, prom_argv[i]); cp += strlen(prom_argv[i]); } @@ -122,11 +117,6 @@ void __init prom_setup_cmdline(void) strcpy(cp, arcs_cmdline); cp += strlen(arcs_cmdline); } - if (gpio_bootup_state & 0x02) - strcpy(cp, GPIO_INIT_NOBUTTON); - else - strcpy(cp, GPIO_INIT_BUTTON); - cmd_line[CL_SIZE-1] = '\0'; strcpy(arcs_cmdline, cmd_line); -- cgit v1.2.3 From c76befc3429354909d3242d11b8d3bcb3bea4b03 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:02:03 +0200 Subject: MIPS: RB532: replace raw volatile read with a readl This patch replaces a raw read using volatiles with a readl. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 11d7127655e..b028779fedd 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -70,7 +70,7 @@ void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val) spin_lock_irqsave(&dev3.lock, flags); - data = *(volatile unsigned *) (IDT434_REG_BASE + reg_offs); + data = readl(IDT434_REG_BASE + reg_offs); for (i = 0; i != len; ++i) { if (val & (1 << i)) data |= (1 << (i + bit)); -- cgit v1.2.3 From b6e2f58a503b56e154f90dc516647c93c5fe873d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:03:03 +0200 Subject: MIPS: RB532: Fix id usage in platform devices When there is only platform device of the same type, id = -1 should be used, fix this. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/devices.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 7090dc97606..31619c601b1 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -84,7 +84,7 @@ static struct korina_device korina_dev0_data = { }; static struct platform_device korina_dev0 = { - .id = 0, + .id = -1, .name = "korina", .dev.platform_data = &korina_dev0_data, .resource = korina_dev0_res, @@ -108,7 +108,7 @@ static struct cf_device cf_slot0_data = { }; static struct platform_device cf_slot0 = { - .id = 0, + .id = -1, .name = "pata-rb532-cf", .dev.platform_data = &cf_slot0_data, .resource = cf_slot0_res, @@ -173,7 +173,7 @@ static struct mtd_partition rb532_partition_info[] = { static struct platform_device rb532_led = { .name = "rb532-led", - .id = 0, + .id = -1, }; static struct gpio_keys_button rb532_gpio_btn[] = { -- cgit v1.2.3 From deeb45ac4a32c8271b022ecba73913bc1112e8e6 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:53:24 +0200 Subject: MIPS: RB532: Remove obsolute reference to setup_serial_port We are no longer using setup_serial_port. So just remove it from the prom code. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/prom.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c index c5d8868e1b1..46ca24dbcc2 100644 --- a/arch/mips/rb532/prom.c +++ b/arch/mips/rb532/prom.c @@ -37,8 +37,6 @@ #include #include -extern void __init setup_serial_port(void); - unsigned int idt_cpu_freq = 132000000; EXPORT_SYMBOL(idt_cpu_freq); -- cgit v1.2.3 From 606a083b1e1a357cb66454e4581b80f1a67d8368 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:53:50 +0200 Subject: MIPS: RB532: Cleanup the headers again This patch cleans up headers and regroups informations to where they should reside. While moving, try to have a consistant naming for defines. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/irq.c | 2 +- arch/mips/rb532/serial.c | 6 +++--- arch/mips/rb532/setup.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/rb532/irq.c b/arch/mips/rb532/irq.c index c0d0f950caf..549b46d2fce 100644 --- a/arch/mips/rb532/irq.c +++ b/arch/mips/rb532/irq.c @@ -45,7 +45,7 @@ #include #include -#include +#include struct intr_group { u32 mask; /* mask of valid bits in pending/mask registers */ diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c index 1a05b5ddee0..3e0d7ec3a57 100644 --- a/arch/mips/rb532/serial.c +++ b/arch/mips/rb532/serial.c @@ -31,16 +31,16 @@ #include #include -#include +#include extern unsigned int idt_cpu_freq; static struct uart_port rb532_uart = { .type = PORT_16550A, .line = 0, - .irq = RC32434_UART0_IRQ, + .irq = UART0_IRQ, .iotype = UPIO_MEM, - .membase = (char *)KSEG1ADDR(RC32434_UART0_BASE), + .membase = (char *)KSEG1ADDR(REGBASE + UART0BASE), .regshift = 2 }; diff --git a/arch/mips/rb532/setup.c b/arch/mips/rb532/setup.c index 7aafa95ac20..50f530f5b60 100644 --- a/arch/mips/rb532/setup.c +++ b/arch/mips/rb532/setup.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include struct pci_reg __iomem *pci_reg; @@ -27,7 +27,7 @@ static struct resource pci0_res[] = { static void rb_machine_restart(char *command) { /* just jump to the reset vector */ - writel(0x80000001, (void *)KSEG1ADDR(RC32434_REG_BASE + RC32434_RST)); + writel(0x80000001, IDT434_REG_BASE + RST); ((void (*)(void)) KSEG1ADDR(0x1FC00000u))(); } -- cgit v1.2.3 From d888e25b8dd1b501ac75b0c6587c043a394319c3 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:54:34 +0200 Subject: MIPS: RB532: Convert to GPIO lib This patch converts the rb532 code to use gpio library and register its gpio chip. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/rb532/gpio.c | 228 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 162 insertions(+), 68 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1e06d233fa8..00a23a11849 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -568,7 +568,7 @@ config MIKROTIK_RB532 select SYS_SUPPORTS_LITTLE_ENDIAN select SWAP_IO_SPACE select BOOT_RAW - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Support the Mikrotik(tm) RouterBoard 532 series, based on the IDT RC32434 SoC. diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index b028779fedd..76a7fd96d56 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -27,20 +27,23 @@ */ #include -#include #include #include -#include #include -#include #include - -#include +#include #include - -struct rb532_gpio_reg __iomem *rb532_gpio_reg0; -EXPORT_SYMBOL(rb532_gpio_reg0); +#include + +struct rb532_gpio_chip { + struct gpio_chip chip; + void __iomem *regbase; + void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value); + int (*get_int_level)(struct gpio_chip *chip, unsigned offset); + void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value); + int (*get_int_status)(struct gpio_chip *chip, unsigned offset); +}; struct mpmc_device dev3; @@ -108,108 +111,199 @@ unsigned char get_latch_u5(void) } EXPORT_SYMBOL(get_latch_u5); -int rb532_gpio_get_value(unsigned gpio) +/* + * Return GPIO level */ +static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset) { - return readl(&rb532_gpio_reg0->gpiod) & (1 << gpio); + u32 mask = 1 << offset; + struct rb532_gpio_chip *gpch; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + return readl(gpch->regbase + GPIOD) & mask; } -EXPORT_SYMBOL(rb532_gpio_get_value); -void rb532_gpio_set_value(unsigned gpio, int value) +/* + * Set output GPIO level + */ +static void rb532_gpio_set(struct gpio_chip *chip, + unsigned offset, int value) { - unsigned tmp; + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpvr; - tmp = readl(&rb532_gpio_reg0->gpiod) & ~(1 << gpio); - if (value) - tmp |= 1 << gpio; + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpvr = gpch->regbase + GPIOD; - writel(tmp, (void *)&rb532_gpio_reg0->gpiod); + local_irq_save(flags); + tmp = readl(gpvr); + if (value) + tmp |= mask; + else + tmp &= ~mask; + writel(tmp, gpvr); + local_irq_restore(flags); } -EXPORT_SYMBOL(rb532_gpio_set_value); -int rb532_gpio_direction_input(unsigned gpio) +/* + * Set GPIO direction to input + */ +static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - writel(readl(&rb532_gpio_reg0->gpiocfg) & ~(1 << gpio), - (void *)&rb532_gpio_reg0->gpiocfg); + unsigned long flags; + u32 mask = 1 << offset; + u32 value; + struct rb532_gpio_chip *gpch; + void __iomem *gpdr; - return 0; -} -EXPORT_SYMBOL(rb532_gpio_direction_input); + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpdr = gpch->regbase + GPIOCFG; -int rb532_gpio_direction_output(unsigned gpio, int value) -{ - gpio_set_value(gpio, value); - writel(readl(&rb532_gpio_reg0->gpiocfg) | (1 << gpio), - (void *)&rb532_gpio_reg0->gpiocfg); + local_irq_save(flags); + value = readl(gpdr); + value &= ~mask; + writel(value, gpdr); + local_irq_restore(flags); return 0; } -EXPORT_SYMBOL(rb532_gpio_direction_output); -void rb532_gpio_set_int_level(unsigned gpio, int value) +/* + * Set GPIO direction to output + */ +static int rb532_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) { - unsigned tmp; + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpdr; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + writel(mask, gpch->regbase + GPIOD); + gpdr = gpch->regbase + GPIOCFG; + + local_irq_save(flags); + tmp = readl(gpdr); + tmp |= mask; + writel(tmp, gpdr); + local_irq_restore(flags); - tmp = readl(&rb532_gpio_reg0->gpioilevel) & ~(1 << gpio); - if (value) - tmp |= 1 << gpio; - writel(tmp, (void *)&rb532_gpio_reg0->gpioilevel); + return 0; } -EXPORT_SYMBOL(rb532_gpio_set_int_level); -int rb532_gpio_get_int_level(unsigned gpio) +/* + * Set the GPIO interrupt level + */ +static void rb532_gpio_set_int_level(struct gpio_chip *chip, + unsigned offset, int value) { - return readl(&rb532_gpio_reg0->gpioilevel) & (1 << gpio); -} -EXPORT_SYMBOL(rb532_gpio_get_int_level); + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpil; -void rb532_gpio_set_int_status(unsigned gpio, int value) -{ - unsigned tmp; + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpil = gpch->regbase + GPIOILEVEL; - tmp = readl(&rb532_gpio_reg0->gpioistat); + local_irq_save(flags); + tmp = readl(gpil); if (value) - tmp |= 1 << gpio; - writel(tmp, (void *)&rb532_gpio_reg0->gpioistat); + tmp |= mask; + else + tmp &= ~mask; + writel(tmp, gpil); + local_irq_restore(flags); } -EXPORT_SYMBOL(rb532_gpio_set_int_status); -int rb532_gpio_get_int_status(unsigned gpio) +/* + * Get the GPIO interrupt level + */ +static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset) { - return readl(&rb532_gpio_reg0->gpioistat) & (1 << gpio); + u32 mask = 1 << offset; + struct rb532_gpio_chip *gpch; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + return readl(gpch->regbase + GPIOILEVEL) & mask; } -EXPORT_SYMBOL(rb532_gpio_get_int_status); -void rb532_gpio_set_func(unsigned gpio, int value) +/* + * Set the GPIO interrupt status + */ +static void rb532_gpio_set_int_status(struct gpio_chip *chip, + unsigned offset, int value) { - unsigned tmp; + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpis; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpis = gpch->regbase + GPIOISTAT; - tmp = readl(&rb532_gpio_reg0->gpiofunc); + local_irq_save(flags); + tmp = readl(gpis); if (value) - tmp |= 1 << gpio; - writel(tmp, (void *)&rb532_gpio_reg0->gpiofunc); + tmp |= mask; + else + tmp &= ~mask; + writel(tmp, gpis); + local_irq_restore(flags); } -EXPORT_SYMBOL(rb532_gpio_set_func); -int rb532_gpio_get_func(unsigned gpio) +/* + * Get the GPIO interrupt status + */ +static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset) { - return readl(&rb532_gpio_reg0->gpiofunc) & (1 << gpio); + u32 mask = 1 << offset; + struct rb532_gpio_chip *gpch; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + return readl(gpch->regbase + GPIOISTAT) & mask; } -EXPORT_SYMBOL(rb532_gpio_get_func); + +static struct rb532_gpio_chip rb532_gpio_chip[] = { + [0] = { + .chip = { + .label = "gpio0", + .direction_input = rb532_gpio_direction_input, + .direction_output = rb532_gpio_direction_output, + .get = rb532_gpio_get, + .set = rb532_gpio_set, + .base = 0, + .ngpio = 32, + }, + .get_int_level = rb532_gpio_get_int_level, + .set_int_level = rb532_gpio_set_int_level, + .get_int_status = rb532_gpio_get_int_status, + .set_int_status = rb532_gpio_set_int_status, + }, +}; int __init rb532_gpio_init(void) { - rb532_gpio_reg0 = ioremap_nocache(rb532_gpio_reg0_res[0].start, - rb532_gpio_reg0_res[0].end - - rb532_gpio_reg0_res[0].start); + struct resource *r; - if (!rb532_gpio_reg0) { + r = rb532_gpio_reg0_res; + rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start); + + if (!rb532_gpio_chip->regbase) { printk(KERN_ERR "rb532: cannot remap GPIO register 0\n"); return -ENXIO; } - dev3.base = ioremap_nocache(rb532_dev3_ctl_res[0].start, - rb532_dev3_ctl_res[0].end - - rb532_dev3_ctl_res[0].start); + /* Register our GPIO chip */ + gpiochip_add(&rb532_gpio_chip->chip); + + r = rb532_dev3_ctl_res; + dev3.base = ioremap_nocache(r->start, r->end - r->start); if (!dev3.base) { printk(KERN_ERR "rb532: cannot remap device controller 3\n"); -- cgit v1.2.3 From f6d9831bb11eb465f95fb1736b866d405d9c7cbf Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:36 +0900 Subject: MIPS: TXx9: stop_unused_modules TXx9 SoCs have pin multiplex. Stop some controller modules which can not be used due to pin configurations. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup_tx4927.c | 31 +++++++++++++++++++ arch/mips/txx9/generic/setup_tx4938.c | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index c4248cbbd84..914e93c6263 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -252,3 +252,34 @@ void __init tx4927_mtd_init(int ch) return; /* disabled */ txx9_physmap_flash_init(ch, start, size, &pdata); } + +static void __init tx4927_stop_unused_modules(void) +{ + __u64 pcfg, rst = 0, ckd = 0; + char buf[128]; + + buf[0] = '\0'; + local_irq_disable(); + pcfg = ____raw_readq(&tx4927_ccfgptr->pcfg); + if (!(pcfg & TX4927_PCFG_SEL2)) { + rst |= TX4927_CLKCTR_ACLRST; + ckd |= TX4927_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + if (rst | ckd) { + txx9_set64(&tx4927_ccfgptr->clkctr, rst); + txx9_set64(&tx4927_ccfgptr->clkctr, ckd); + } + local_irq_enable(); + if (buf[0]) + pr_info("%s: stop%s\n", txx9_pcode_str, buf); +} + +static int __init tx4927_late_init(void) +{ + if (txx9_pcode != 0x4927) + return -ENODEV; + tx4927_stop_unused_modules(); + return 0; +} +late_initcall(tx4927_late_init); diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 0d8517ad3ad..af724e53ef9 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -334,3 +334,59 @@ void __init tx4938_mtd_init(int ch) return; /* disabled */ txx9_physmap_flash_init(ch, start, size, &pdata); } + +static void __init tx4938_stop_unused_modules(void) +{ + __u64 pcfg, rst = 0, ckd = 0; + char buf[128]; + + buf[0] = '\0'; + local_irq_disable(); + pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); + switch (txx9_pcode) { + case 0x4937: + if (!(pcfg & TX4938_PCFG_SEL2)) { + rst |= TX4938_CLKCTR_ACLRST; + ckd |= TX4938_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + break; + case 0x4938: + if (!(pcfg & TX4938_PCFG_SEL2) || + (pcfg & TX4938_PCFG_ETH0_SEL)) { + rst |= TX4938_CLKCTR_ACLRST; + ckd |= TX4938_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + if ((pcfg & + (TX4938_PCFG_ATA_SEL | TX4938_PCFG_ISA_SEL | + TX4938_PCFG_NDF_SEL)) + != TX4938_PCFG_NDF_SEL) { + rst |= TX4938_CLKCTR_NDFRST; + ckd |= TX4938_CLKCTR_NDFCKD; + strcat(buf, " NDFMC"); + } + if (!(pcfg & TX4938_PCFG_SPI_SEL)) { + rst |= TX4938_CLKCTR_SPIRST; + ckd |= TX4938_CLKCTR_SPICKD; + strcat(buf, " SPI"); + } + break; + } + if (rst | ckd) { + txx9_set64(&tx4938_ccfgptr->clkctr, rst); + txx9_set64(&tx4938_ccfgptr->clkctr, ckd); + } + local_irq_enable(); + if (buf[0]) + pr_info("%s: stop%s\n", txx9_pcode_str, buf); +} + +static int __init tx4938_late_init(void) +{ + if (txx9_pcode != 0x4937 && txx9_pcode != 0x4938) + return -ENODEV; + tx4938_stop_unused_modules(); + return 0; +} +late_initcall(tx4938_late_init); -- cgit v1.2.3 From 21e77df215e58523a755b5dd006cb17610616f20 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:37 +0900 Subject: MIPS: TXx9: Microoptimize interrupt handlers The IOC interrupt status register on RBTX49XX only have 8 bits. Use 8-bit version of __fls() to optimize interrupt handlers. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/rbtx4927/irq.c | 6 +++--- arch/mips/txx9/rbtx4938/irq.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c index 22076e3f03a..9c14ebb26cb 100644 --- a/arch/mips/txx9/rbtx4927/irq.c +++ b/arch/mips/txx9/rbtx4927/irq.c @@ -133,9 +133,9 @@ static int toshiba_rbtx4927_irq_nested(int sw_irq) u8 level3; level3 = readb(rbtx4927_imstat_addr) & 0x1f; - if (level3) - sw_irq = RBTX4927_IRQ_IOC + fls(level3) - 1; - return sw_irq; + if (unlikely(!level3)) + return -1; + return RBTX4927_IRQ_IOC + __fls8(level3); } static void __init toshiba_rbtx4927_irq_ioc_init(void) diff --git a/arch/mips/txx9/rbtx4938/irq.c b/arch/mips/txx9/rbtx4938/irq.c index ca2f8306ce9..7d21befb893 100644 --- a/arch/mips/txx9/rbtx4938/irq.c +++ b/arch/mips/txx9/rbtx4938/irq.c @@ -85,10 +85,10 @@ static int toshiba_rbtx4938_irq_nested(int sw_irq) u8 level3; level3 = readb(rbtx4938_imstat_addr); - if (level3) - /* must use fls so onboard ATA has priority */ - sw_irq = RBTX4938_IRQ_IOC + fls(level3) - 1; - return sw_irq; + if (unlikely(!level3)) + return -1; + /* must use fls so onboard ATA has priority */ + return RBTX4938_IRQ_IOC + __fls8(level3); } static void __init -- cgit v1.2.3 From ae027ead87b13cff99b4f48da7696aa4fe75393b Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:38 +0900 Subject: MIPS: TXx9: IOC LED support Add leds-gpio platform device for controlling LEDs connected to IOC on RBTX49XX and JMR3927 board. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 111 ++++++++++++++++++++++++++++++++++++++++ arch/mips/txx9/jmr3927/setup.c | 5 ++ arch/mips/txx9/rbtx4927/setup.c | 1 + arch/mips/txx9/rbtx4938/setup.c | 1 + 4 files changed, 118 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 118d716f783..1ea06553a1e 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -649,3 +650,113 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr, platform_device_put(pdev); #endif } + +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +static DEFINE_SPINLOCK(txx9_iocled_lock); + +#define TXX9_IOCLED_MAXLEDS 8 + +struct txx9_iocled_data { + struct gpio_chip chip; + u8 cur_val; + void __iomem *mmioaddr; + struct gpio_led_platform_data pdata; + struct gpio_led leds[TXX9_IOCLED_MAXLEDS]; + char names[TXX9_IOCLED_MAXLEDS][32]; +}; + +static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset) +{ + struct txx9_iocled_data *data = + container_of(chip, struct txx9_iocled_data, chip); + return data->cur_val & (1 << offset); +} + +static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct txx9_iocled_data *data = + container_of(chip, struct txx9_iocled_data, chip); + unsigned long flags; + spin_lock_irqsave(&txx9_iocled_lock, flags); + if (value) + data->cur_val |= 1 << offset; + else + data->cur_val &= ~(1 << offset); + writeb(data->cur_val, data->mmioaddr); + mmiowb(); + spin_unlock_irqrestore(&txx9_iocled_lock, flags); +} + +static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset) +{ + return 0; +} + +static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset, + int value) +{ + txx9_iocled_set(chip, offset, value); + return 0; +} + +void __init txx9_iocled_init(unsigned long baseaddr, + int basenum, unsigned int num, int lowactive, + const char *color, char **deftriggers) +{ + struct txx9_iocled_data *iocled; + struct platform_device *pdev; + int i; + static char *default_triggers[] __initdata = { + "heartbeat", + "ide-disk", + "nand-disk", + NULL, + }; + + if (!deftriggers) + deftriggers = default_triggers; + iocled = kzalloc(sizeof(*iocled), GFP_KERNEL); + if (!iocled) + return; + iocled->mmioaddr = ioremap(baseaddr, 1); + if (!iocled->mmioaddr) + return; + iocled->chip.get = txx9_iocled_get; + iocled->chip.set = txx9_iocled_set; + iocled->chip.direction_input = txx9_iocled_dir_in; + iocled->chip.direction_output = txx9_iocled_dir_out; + iocled->chip.label = "iocled"; + iocled->chip.base = basenum; + iocled->chip.ngpio = num; + if (gpiochip_add(&iocled->chip)) + return; + if (basenum < 0) + basenum = iocled->chip.base; + + pdev = platform_device_alloc("leds-gpio", basenum); + if (!pdev) + return; + iocled->pdata.num_leds = num; + iocled->pdata.leds = iocled->leds; + for (i = 0; i < num; i++) { + struct gpio_led *led = &iocled->leds[i]; + snprintf(iocled->names[i], sizeof(iocled->names[i]), + "iocled:%s:%u", color, i); + led->name = iocled->names[i]; + led->gpio = basenum + i; + led->active_low = lowactive; + if (deftriggers && *deftriggers) + led->default_trigger = *deftriggers++; + } + pdev->dev.platform_data = &iocled->pdata; + if (platform_device_add(pdev)) + platform_device_put(pdev); +} +#else /* CONFIG_LEDS_GPIO */ +void __init txx9_iocled_init(unsigned long baseaddr, + int basenum, unsigned int num, int lowactive, + const char *color, char **deftriggers) +{ +} +#endif /* CONFIG_LEDS_GPIO */ diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c index 0f3843c92cf..25e50a7be38 100644 --- a/arch/mips/txx9/jmr3927/setup.c +++ b/arch/mips/txx9/jmr3927/setup.c @@ -200,10 +200,15 @@ static void __init jmr3927_mtd_init(void) static void __init jmr3927_device_init(void) { + unsigned long iocled_base = JMR3927_IOC_LED_ADDR - IO_BASE; +#ifdef __LITTLE_ENDIAN + iocled_base |= 1; +#endif __swizzle_addr_b = jmr3927_swizzle_addr_b; jmr3927_rtc_init(); tx3927_wdt_init(); jmr3927_mtd_init(); + txx9_iocled_init(iocled_base, -1, 8, 1, "green", NULL); } struct txx9_board_vec jmr3927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index abe32c1a79d..4a74423b2ba 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -321,6 +321,7 @@ static void __init rbtx4927_device_init(void) rbtx4927_ne_init(); tx4927_wdt_init(); rbtx4927_mtd_init(); + txx9_iocled_init(RBTX4927_LED_ADDR - IO_BASE, -1, 3, 1, "green", NULL); } struct txx9_board_vec rbtx4927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index ec6e81258f7..e077cc4d3a5 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -352,6 +352,7 @@ static void __init rbtx4938_device_init(void) rbtx4938_ne_init(); tx4938_wdt_init(); rbtx4938_mtd_init(); + txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL); } struct txx9_board_vec rbtx4938_vec __initdata = { -- cgit v1.2.3 From 0dcdbe6add26719e956299eb519542f7d2f7d0a8 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:39 +0900 Subject: MIPS: TXx9: Add TX4939 SoC support Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 arch/mips/pci/pci-tx4939.c create mode 100644 arch/mips/txx9/generic/irq_tx4939.c create mode 100644 arch/mips/txx9/generic/setup_tx4939.c create mode 100644 include/asm-mips/txx9/tx4939.h --- arch/mips/pci/Makefile | 1 + arch/mips/pci/pci-tx4939.c | 109 ++++++++ arch/mips/txx9/Kconfig | 7 + arch/mips/txx9/generic/Makefile | 1 + arch/mips/txx9/generic/irq_tx4939.c | 215 ++++++++++++++++ arch/mips/txx9/generic/setup_tx4939.c | 460 ++++++++++++++++++++++++++++++++++ 6 files changed, 793 insertions(+) create mode 100644 arch/mips/pci/pci-tx4939.c create mode 100644 arch/mips/txx9/generic/irq_tx4939.c create mode 100644 arch/mips/txx9/generic/setup_tx4939.c (limited to 'arch') diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c8c32f417b6..b1886244ced 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o obj-$(CONFIG_SOC_TX4927) += pci-tx4927.o obj-$(CONFIG_SOC_TX4938) += pci-tx4938.o +obj-$(CONFIG_SOC_TX4939) += pci-tx4939.o obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-rbtx4938.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o diff --git a/arch/mips/pci/pci-tx4939.c b/arch/mips/pci/pci-tx4939.c new file mode 100644 index 00000000000..5fecf1cdc32 --- /dev/null +++ b/arch/mips/pci/pci-tx4939.c @@ -0,0 +1,109 @@ +/* + * linux/arch/mips/pci/pci-tx4939.c + * + * Based on linux/arch/mips/txx9/rbtx4939/setup.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright 2001, 2003-2005 MontaVista Software Inc. + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +int __init tx4939_report_pciclk(void) +{ + int pciclk = 0; + + pr_info("PCIC --%s PCICLK:", + (__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCI66) ? + " PCI66" : ""); + if (__raw_readq(&tx4939_ccfgptr->pcfg) & TX4939_PCFG_PCICLKEN_ALL) { + pciclk = txx9_master_clock * 20 / 6; + if (!(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCI66)) + pciclk /= 2; + printk(KERN_CONT "Internal(%u.%uMHz)", + (pciclk + 50000) / 1000000, + ((pciclk + 50000) / 100000) % 10); + } else { + printk(KERN_CONT "External"); + pciclk = -1; + } + printk(KERN_CONT "\n"); + return pciclk; +} + +void __init tx4939_report_pci1clk(void) +{ + unsigned int pciclk = txx9_master_clock * 20 / 6; + + pr_info("PCIC1 -- PCICLK:%u.%uMHz\n", + (pciclk + 50000) / 1000000, + ((pciclk + 50000) / 100000) % 10); +} + +int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot) +{ + if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4939_pcic1ptr) { + switch (slot) { + case TX4927_PCIC_IDSEL_AD_TO_SLOT(31): + if (__raw_readq(&tx4939_ccfgptr->pcfg) & + TX4939_PCFG_ET0MODE) + return TXX9_IRQ_BASE + TX4939_IR_ETH(0); + break; + case TX4927_PCIC_IDSEL_AD_TO_SLOT(30): + if (__raw_readq(&tx4939_ccfgptr->pcfg) & + TX4939_PCFG_ET1MODE) + return TXX9_IRQ_BASE + TX4939_IR_ETH(1); + break; + } + return 0; + } + return -1; +} + +int __init tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq = tx4939_pcic1_map_irq(dev, slot); + + if (irq >= 0) + return irq; + irq = pin; + /* IRQ rotation */ + irq--; /* 0-3 */ + irq = (irq + 33 - slot) % 4; + irq++; /* 1-4 */ + + switch (irq) { + case 1: + irq = TXX9_IRQ_BASE + TX4939_IR_INTA; + break; + case 2: + irq = TXX9_IRQ_BASE + TX4939_IR_INTB; + break; + case 3: + irq = TXX9_IRQ_BASE + TX4939_IR_INTC; + break; + case 4: + irq = TXX9_IRQ_BASE + TX4939_IR_INTD; + break; + } + return irq; +} + +void __init tx4939_setup_pcierr_irq(void) +{ + if (request_irq(TXX9_IRQ_BASE + TX4939_IR_PCIERR, + tx4927_pcierr_interrupt, + IRQF_DISABLED, "PCI error", + (void *)TX4939_PCIC_REG)) + pr_warning("Failed to request irq for PCIERR\n"); +} diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index aade3348af2..58691a1fe77 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -71,6 +71,13 @@ config SOC_TX4938 select PCI_TX4927 select GPIO_TXX9 +config SOC_TX4939 + bool + select CEVT_TXX9 + select HAS_TXX9_SERIAL + select HW_HAS_PCI + select PCI_TX4927 + config TOSHIBA_FPCIB0 bool "FPCIB0 Backplane Support" depends on PCI && MACH_TXX9 diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile index 986852cc774..0030d23bef5 100644 --- a/arch/mips/txx9/generic/Makefile +++ b/arch/mips/txx9/generic/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_SOC_TX3927) += setup_tx3927.o irq_tx3927.o obj-$(CONFIG_SOC_TX4927) += mem_tx4927.o setup_tx4927.o irq_tx4927.o obj-$(CONFIG_SOC_TX4938) += mem_tx4927.o setup_tx4938.o irq_tx4938.o +obj-$(CONFIG_SOC_TX4939) += setup_tx4939.o irq_tx4939.o obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o obj-$(CONFIG_SPI) += spi_eeprom.o diff --git a/arch/mips/txx9/generic/irq_tx4939.c b/arch/mips/txx9/generic/irq_tx4939.c new file mode 100644 index 00000000000..013213a8706 --- /dev/null +++ b/arch/mips/txx9/generic/irq_tx4939.c @@ -0,0 +1,215 @@ +/* + * TX4939 irq routines + * Based on linux/arch/mips/kernel/irq_txx9.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright 2001, 2003-2005 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * source@mvista.com + * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +/* + * TX4939 defines 64 IRQs. + * Similer to irq_txx9.c but different register layouts. + */ +#include +#include +#include +#include +#include +#include + +/* IRCER : Int. Control Enable */ +#define TXx9_IRCER_ICE 0x00000001 + +/* IRCR : Int. Control */ +#define TXx9_IRCR_LOW 0x00000000 +#define TXx9_IRCR_HIGH 0x00000001 +#define TXx9_IRCR_DOWN 0x00000002 +#define TXx9_IRCR_UP 0x00000003 +#define TXx9_IRCR_EDGE(cr) ((cr) & 0x00000002) + +/* IRSCR : Int. Status Control */ +#define TXx9_IRSCR_EIClrE 0x00000100 +#define TXx9_IRSCR_EIClr_MASK 0x0000000f + +/* IRCSR : Int. Current Status */ +#define TXx9_IRCSR_IF 0x00010000 + +#define irc_dlevel 0 +#define irc_elevel 1 + +static struct { + unsigned char level; + unsigned char mode; +} tx4939irq[TX4939_NUM_IR] __read_mostly; + +static void tx4939_irq_unmask(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 __iomem *lvlp; + int ofs; + if (irq_nr < 32) { + irq_nr--; + lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; + } else { + irq_nr -= 32; + lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; + } + ofs = (irq_nr & 16) + (irq_nr & 1) * 8; + __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) + | (tx4939irq[irq_nr].level << ofs), + lvlp); +} + +static inline void tx4939_irq_mask(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 __iomem *lvlp; + int ofs; + if (irq_nr < 32) { + irq_nr--; + lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; + } else { + irq_nr -= 32; + lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; + } + ofs = (irq_nr & 16) + (irq_nr & 1) * 8; + __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) + | (irc_dlevel << ofs), + lvlp); + mmiowb(); +} + +static void tx4939_irq_mask_ack(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + + tx4939_irq_mask(irq); + if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) { + irq_nr--; + /* clear edge detection */ + __raw_writel((TXx9_IRSCR_EIClrE | (irq_nr & 0xf)) + << (irq_nr & 0x10), + &tx4939_ircptr->edc.r); + } +} + +static int tx4939_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 cr; + u32 __iomem *crp; + int ofs; + int mode; + + if (flow_type & IRQF_TRIGGER_PROBE) + return 0; + switch (flow_type & IRQF_TRIGGER_MASK) { + case IRQF_TRIGGER_RISING: + mode = TXx9_IRCR_UP; + break; + case IRQF_TRIGGER_FALLING: + mode = TXx9_IRCR_DOWN; + break; + case IRQF_TRIGGER_HIGH: + mode = TXx9_IRCR_HIGH; + break; + case IRQF_TRIGGER_LOW: + mode = TXx9_IRCR_LOW; + break; + default: + return -EINVAL; + } + if (irq_nr < 32) { + irq_nr--; + crp = &tx4939_ircptr->dm[(irq_nr & 8) >> 3].r; + } else { + irq_nr -= 32; + crp = &tx4939_ircptr->dm2[((irq_nr & 8) >> 3)].r; + } + ofs = (((irq_nr & 16) >> 1) | (irq_nr & (8 - 1))) * 2; + cr = __raw_readl(crp); + cr &= ~(0x3 << ofs); + cr |= (mode & 0x3) << ofs; + __raw_writel(cr, crp); + tx4939irq[irq_nr].mode = mode; + return 0; +} + +static struct irq_chip tx4939_irq_chip = { + .name = "TX4939", + .ack = tx4939_irq_mask_ack, + .mask = tx4939_irq_mask, + .mask_ack = tx4939_irq_mask_ack, + .unmask = tx4939_irq_unmask, + .set_type = tx4939_irq_set_type, +}; + +static int tx4939_irq_set_pri(int irc_irq, int new_pri) +{ + int old_pri; + + if ((unsigned int)irc_irq >= TX4939_NUM_IR) + return 0; + old_pri = tx4939irq[irc_irq].level; + tx4939irq[irc_irq].level = new_pri; + return old_pri; +} + +void __init tx4939_irq_init(void) +{ + int i; + + mips_cpu_irq_init(); + /* disable interrupt control */ + __raw_writel(0, &tx4939_ircptr->den.r); + __raw_writel(0, &tx4939_ircptr->maskint.r); + __raw_writel(0, &tx4939_ircptr->maskext.r); + /* irq_base + 0 is not used */ + for (i = 1; i < TX4939_NUM_IR; i++) { + tx4939irq[i].level = 4; /* middle level */ + tx4939irq[i].mode = TXx9_IRCR_LOW; + set_irq_chip_and_handler(TXX9_IRQ_BASE + i, + &tx4939_irq_chip, handle_level_irq); + } + + /* mask all IRC interrupts */ + __raw_writel(0, &tx4939_ircptr->msk.r); + for (i = 0; i < 16; i++) + __raw_writel(0, &tx4939_ircptr->lvl[i].r); + /* setup IRC interrupt mode (Low Active) */ + for (i = 0; i < 2; i++) + __raw_writel(0, &tx4939_ircptr->dm[i].r); + for (i = 0; i < 2; i++) + __raw_writel(0, &tx4939_ircptr->dm2[i].r); + /* enable interrupt control */ + __raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r); + __raw_writel(irc_elevel, &tx4939_ircptr->msk.r); + + set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT, + handle_simple_irq); + + /* raise priority for errors, timers, sio */ + tx4939_irq_set_pri(TX4939_IR_WTOERR, 7); + tx4939_irq_set_pri(TX4939_IR_PCIERR, 7); + tx4939_irq_set_pri(TX4939_IR_PCIPME, 7); + for (i = 0; i < TX4939_NUM_IR_TMR; i++) + tx4939_irq_set_pri(TX4939_IR_TMR(i), 6); + for (i = 0; i < TX4939_NUM_IR_SIO; i++) + tx4939_irq_set_pri(TX4939_IR_SIO(i), 5); +} + +int tx4939_irq(void) +{ + u32 csr = __raw_readl(&tx4939_ircptr->cs.r); + + if (likely(!(csr & TXx9_IRCSR_IF))) + return TXX9_IRQ_BASE + (csr & (TX4939_NUM_IR - 1)); + return -1; +} diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c new file mode 100644 index 00000000000..f14a497077d --- /dev/null +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -0,0 +1,460 @@ +/* + * TX4939 setup routines + * Based on linux/arch/mips/txx9/generic/setup_tx4938.c, + * and RBTX49xx patch from CELF patch archive. + * + * 2003-2005 (c) MontaVista Software, Inc. + * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __init tx4939_wdr_init(void) +{ + /* report watchdog reset status */ + if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST) + pr_warning("Watchdog reset detected at 0x%lx\n", + read_c0_errorepc()); + /* clear WatchDogReset (W1C) */ + tx4939_ccfg_set(TX4939_CCFG_WDRST); + /* do reset on watchdog */ + tx4939_ccfg_set(TX4939_CCFG_WR); +} + +void __init tx4939_wdt_init(void) +{ + txx9_wdt_init(TX4939_TMR_REG(2) & 0xfffffffffULL); +} + +static void tx4939_machine_restart(char *command) +{ + local_irq_disable(); + pr_emerg("Rebooting (with %s watchdog reset)...\n", + (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) ? + "external" : "internal"); + /* clear watchdog status */ + tx4939_ccfg_set(TX4939_CCFG_WDRST); /* W1C */ + txx9_wdt_now(TX4939_TMR_REG(2) & 0xfffffffffULL); + while (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST)) + ; + mdelay(10); + if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) { + pr_emerg("Rebooting (with internal watchdog reset)...\n"); + /* External WDRST failed. Do internal watchdog reset */ + tx4939_ccfg_clear(TX4939_CCFG_WDREXEN); + } + /* fallback */ + (*_machine_halt)(); +} + +void show_registers(struct pt_regs *regs); +static int tx4939_be_handler(struct pt_regs *regs, int is_fixup) +{ + int data = regs->cp0_cause & 4; + console_verbose(); + pr_err("%cBE exception at %#lx\n", + data ? 'D' : 'I', regs->cp0_epc); + pr_err("ccfg:%llx, toea:%llx\n", + (unsigned long long)____raw_readq(&tx4939_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4939_ccfgptr->toea)); +#ifdef CONFIG_PCI + tx4927_report_pcic_status(); +#endif + show_registers(regs); + panic("BusError!"); +} +static void __init tx4939_be_init(void) +{ + board_be_handler = tx4939_be_handler; +} + +static struct resource tx4939_sdram_resource[4]; +static struct resource tx4939_sram_resource; +#define TX4939_SRAM_SIZE 0x800 + +void __init tx4939_add_memory_regions(void) +{ + int i; + unsigned long start, size; + u64 win; + + for (i = 0; i < 4; i++) { + if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i))) + continue; + win = ____raw_readq(&tx4939_ddrcptr->win[i]); + start = (unsigned long)(win >> 48); + size = (((unsigned long)(win >> 32) & 0xffff) + 1) - start; + add_memory_region(start << 20, size << 20, BOOT_MEM_RAM); + } +} + +void __init tx4939_setup(void) +{ + int i; + __u32 divmode; + __u64 pcfg; + int cpuclk = 0; + + txx9_reg_res_init(TX4939_REV_PCODE(), TX4939_REG_BASE, + TX4939_REG_SIZE); + set_c0_config(TX49_CONF_CWFON); + + /* SDRAMC,EBUSC are configured by PROM */ + for (i = 0; i < 4; i++) { + if (!(TX4939_EBUSC_CR(i) & 0x8)) + continue; /* disabled */ + txx9_ce_res[i].start = (unsigned long)TX4939_EBUSC_BA(i); + txx9_ce_res[i].end = + txx9_ce_res[i].start + TX4939_EBUSC_SIZE(i) - 1; + request_resource(&iomem_resource, &txx9_ce_res[i]); + } + + /* clocks */ + if (txx9_master_clock) { + /* calculate cpu_clock from master_clock */ + divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & + TX4939_CCFG_MULCLK_MASK; + cpuclk = txx9_master_clock * 20 / 2; + switch (divmode) { + case TX4939_CCFG_MULCLK_8: + cpuclk = cpuclk / 3 * 4 /* / 6 * 8 */; break; + case TX4939_CCFG_MULCLK_9: + cpuclk = cpuclk / 2 * 3 /* / 6 * 9 */; break; + case TX4939_CCFG_MULCLK_10: + cpuclk = cpuclk / 3 * 5 /* / 6 * 10 */; break; + case TX4939_CCFG_MULCLK_11: + cpuclk = cpuclk / 6 * 11; break; + case TX4939_CCFG_MULCLK_12: + cpuclk = cpuclk * 2 /* / 6 * 12 */; break; + case TX4939_CCFG_MULCLK_13: + cpuclk = cpuclk / 6 * 13; break; + case TX4939_CCFG_MULCLK_14: + cpuclk = cpuclk / 3 * 7 /* / 6 * 14 */; break; + case TX4939_CCFG_MULCLK_15: + cpuclk = cpuclk / 2 * 5 /* / 6 * 15 */; break; + } + txx9_cpu_clock = cpuclk; + } else { + if (txx9_cpu_clock == 0) + txx9_cpu_clock = 400000000; /* 400MHz */ + /* calculate master_clock from cpu_clock */ + cpuclk = txx9_cpu_clock; + divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & + TX4939_CCFG_MULCLK_MASK; + switch (divmode) { + case TX4939_CCFG_MULCLK_8: + txx9_master_clock = cpuclk * 6 / 8; break; + case TX4939_CCFG_MULCLK_9: + txx9_master_clock = cpuclk * 6 / 9; break; + case TX4939_CCFG_MULCLK_10: + txx9_master_clock = cpuclk * 6 / 10; break; + case TX4939_CCFG_MULCLK_11: + txx9_master_clock = cpuclk * 6 / 11; break; + case TX4939_CCFG_MULCLK_12: + txx9_master_clock = cpuclk * 6 / 12; break; + case TX4939_CCFG_MULCLK_13: + txx9_master_clock = cpuclk * 6 / 13; break; + case TX4939_CCFG_MULCLK_14: + txx9_master_clock = cpuclk * 6 / 14; break; + case TX4939_CCFG_MULCLK_15: + txx9_master_clock = cpuclk * 6 / 15; break; + } + txx9_master_clock /= 10; /* * 2 / 20 */ + } + /* calculate gbus_clock from cpu_clock */ + divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & + TX4939_CCFG_YDIVMODE_MASK; + txx9_gbus_clock = txx9_cpu_clock; + switch (divmode) { + case TX4939_CCFG_YDIVMODE_2: + txx9_gbus_clock /= 2; break; + case TX4939_CCFG_YDIVMODE_3: + txx9_gbus_clock /= 3; break; + case TX4939_CCFG_YDIVMODE_5: + txx9_gbus_clock /= 5; break; + case TX4939_CCFG_YDIVMODE_6: + txx9_gbus_clock /= 6; break; + } + /* change default value to udelay/mdelay take reasonable time */ + loops_per_jiffy = txx9_cpu_clock / HZ / 2; + + /* CCFG */ + tx4939_wdr_init(); + /* clear BusErrorOnWrite flag (W1C) */ + tx4939_ccfg_set(TX4939_CCFG_WDRST | TX4939_CCFG_BEOW); + /* enable Timeout BusError */ + if (txx9_ccfg_toeon) + tx4939_ccfg_set(TX4939_CCFG_TOE); + + /* DMA selection */ + txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_DMASEL_ALL); + + /* Use external clock for external arbiter */ + if (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB)) + txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_PCICLKEN_ALL); + + pr_info("%s -- %dMHz(M%dMHz,G%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n", + txx9_pcode_str, + (cpuclk + 500000) / 1000000, + (txx9_master_clock + 500000) / 1000000, + (txx9_gbus_clock + 500000) / 1000000, + (__u32)____raw_readq(&tx4939_ccfgptr->crir), + (unsigned long long)____raw_readq(&tx4939_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4939_ccfgptr->pcfg)); + + pr_info("%s DDRC -- EN:%08x", txx9_pcode_str, + (__u32)____raw_readq(&tx4939_ddrcptr->winen)); + for (i = 0; i < 4; i++) { + __u64 win = ____raw_readq(&tx4939_ddrcptr->win[i]); + if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i))) + continue; /* disabled */ + printk(KERN_CONT " #%d:%016llx", i, (unsigned long long)win); + tx4939_sdram_resource[i].name = "DDR SDRAM"; + tx4939_sdram_resource[i].start = + (unsigned long)(win >> 48) << 20; + tx4939_sdram_resource[i].end = + ((((unsigned long)(win >> 32) & 0xffff) + 1) << + 20) - 1; + tx4939_sdram_resource[i].flags = IORESOURCE_MEM; + request_resource(&iomem_resource, &tx4939_sdram_resource[i]); + } + printk(KERN_CONT "\n"); + + /* SRAM */ + if (____raw_readq(&tx4939_sramcptr->cr) & 1) { + unsigned int size = TX4939_SRAM_SIZE; + tx4939_sram_resource.name = "SRAM"; + tx4939_sram_resource.start = + (____raw_readq(&tx4939_sramcptr->cr) >> (39-11)) + & ~(size - 1); + tx4939_sram_resource.end = + tx4939_sram_resource.start + TX4939_SRAM_SIZE - 1; + tx4939_sram_resource.flags = IORESOURCE_MEM; + request_resource(&iomem_resource, &tx4939_sram_resource); + } + + /* TMR */ + /* disable all timers */ + for (i = 0; i < TX4939_NR_TMR; i++) + txx9_tmr_init(TX4939_TMR_REG(i) & 0xfffffffffULL); + + /* DMA */ + for (i = 0; i < 2; i++) + ____raw_writeq(TX4938_DMA_MCR_MSTEN, + (void __iomem *)(TX4939_DMA_REG(i) + 0x50)); + + /* set PCIC1 reset (required to prevent hangup on BIST) */ + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST); + pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); + if (pcfg & (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE)) { + mdelay(1); /* at least 128 cpu clock */ + /* clear PCIC1 reset */ + txx9_clear64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST); + } else { + pr_info("%s: stop PCIC1\n", txx9_pcode_str); + /* stop PCIC1 */ + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1CKD); + } + if (!(pcfg & TX4939_PCFG_ET0MODE)) { + pr_info("%s: stop ETH0\n", txx9_pcode_str); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0RST); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0CKD); + } + if (!(pcfg & TX4939_PCFG_ET1MODE)) { + pr_info("%s: stop ETH1\n", txx9_pcode_str); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1RST); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1CKD); + } + + _machine_restart = tx4939_machine_restart; + board_be_init = tx4939_be_init; +} + +void __init tx4939_time_init(unsigned int tmrnr) +{ + if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_TINTDIS) + txx9_clockevent_init(TX4939_TMR_REG(tmrnr) & 0xfffffffffULL, + TXX9_IRQ_BASE + TX4939_IR_TMR(tmrnr), + TXX9_IMCLK); +} + +void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) +{ + int i; + unsigned int ch_mask = 0; + __u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); + + cts_mask |= ~1; /* only SIO0 have RTS/CTS */ + if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO0) + cts_mask |= 1 << 0; /* disable SIO0 RTS/CTS by PCFG setting */ + if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2) + ch_mask |= 1 << 2; /* disable SIO2 by PCFG setting */ + if (pcfg & TX4939_PCFG_SIO3MODE) + ch_mask |= 1 << 3; /* disable SIO3 by PCFG setting */ + for (i = 0; i < 4; i++) { + if ((1 << i) & ch_mask) + continue; + txx9_sio_init(TX4939_SIO_REG(i) & 0xfffffffffULL, + TXX9_IRQ_BASE + TX4939_IR_SIO(i), + i, sclk, (1 << i) & cts_mask); + } +} + +#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) +static int tx4939_get_eth_speed(struct net_device *dev) +{ + struct ethtool_cmd cmd = { ETHTOOL_GSET }; + int speed = 100; /* default 100Mbps */ + int err; + if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) + return speed; + err = dev->ethtool_ops->get_settings(dev, &cmd); + if (err < 0) + return speed; + speed = cmd.speed == SPEED_100 ? 100 : 10; + return speed; +} +static int tx4939_netdev_event(struct notifier_block *this, + unsigned long event, + void *ptr) +{ + struct net_device *dev = ptr; + if (event == NETDEV_CHANGE && netif_carrier_ok(dev)) { + __u64 bit = 0; + if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(0)) + bit = TX4939_PCFG_SPEED0; + else if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(1)) + bit = TX4939_PCFG_SPEED1; + if (bit) { + int speed = tx4939_get_eth_speed(dev); + if (speed == 100) + txx9_set64(&tx4939_ccfgptr->pcfg, bit); + else + txx9_clear64(&tx4939_ccfgptr->pcfg, bit); + } + } + return NOTIFY_DONE; +} + +static struct notifier_block tx4939_netdev_notifier = { + .notifier_call = tx4939_netdev_event, + .priority = 1, +}; + +void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1) +{ + u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); + + if (addr0 && (pcfg & TX4939_PCFG_ET0MODE)) + txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(0), addr0); + if (addr1 && (pcfg & TX4939_PCFG_ET1MODE)) + txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(1), addr1); + register_netdevice_notifier(&tx4939_netdev_notifier); +} +#else +void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1) +{ +} +#endif + +void __init tx4939_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX4939_EBUSC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(TX4939_EBUSC_CR(ch) & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} + +static void __init tx4939_stop_unused_modules(void) +{ + __u64 pcfg, rst = 0, ckd = 0; + char buf[128]; + + buf[0] = '\0'; + local_irq_disable(); + pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); + if ((pcfg & TX4939_PCFG_I2SMODE_MASK) != + TX4939_PCFG_I2SMODE_ACLC) { + rst |= TX4939_CLKCTR_ACLRST; + ckd |= TX4939_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + if ((pcfg & TX4939_PCFG_I2SMODE_MASK) != + TX4939_PCFG_I2SMODE_I2S && + (pcfg & TX4939_PCFG_I2SMODE_MASK) != + TX4939_PCFG_I2SMODE_I2S_ALT) { + rst |= TX4939_CLKCTR_I2SRST; + ckd |= TX4939_CLKCTR_I2SCKD; + strcat(buf, " I2S"); + } + if (!(pcfg & TX4939_PCFG_ATA0MODE)) { + rst |= TX4939_CLKCTR_ATA0RST; + ckd |= TX4939_CLKCTR_ATA0CKD; + strcat(buf, " ATA0"); + } + if (!(pcfg & TX4939_PCFG_ATA1MODE)) { + rst |= TX4939_CLKCTR_ATA1RST; + ckd |= TX4939_CLKCTR_ATA1CKD; + strcat(buf, " ATA1"); + } + if (pcfg & TX4939_PCFG_SPIMODE) { + rst |= TX4939_CLKCTR_SPIRST; + ckd |= TX4939_CLKCTR_SPICKD; + strcat(buf, " SPI"); + } + if (!(pcfg & (TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE))) { + rst |= TX4939_CLKCTR_VPCRST; + ckd |= TX4939_CLKCTR_VPCCKD; + strcat(buf, " VPC"); + } + if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2) { + rst |= TX4939_CLKCTR_SIO2RST; + ckd |= TX4939_CLKCTR_SIO2CKD; + strcat(buf, " SIO2"); + } + if (pcfg & TX4939_PCFG_SIO3MODE) { + rst |= TX4939_CLKCTR_SIO3RST; + ckd |= TX4939_CLKCTR_SIO3CKD; + strcat(buf, " SIO3"); + } + if (rst | ckd) { + txx9_set64(&tx4939_ccfgptr->clkctr, rst); + txx9_set64(&tx4939_ccfgptr->clkctr, ckd); + } + local_irq_enable(); + if (buf[0]) + pr_info("%s: stop%s\n", txx9_pcode_str, buf); +} + +static int __init tx4939_late_init(void) +{ + if (txx9_pcode != 0x4939) + return -ENODEV; + tx4939_stop_unused_modules(); + return 0; +} +late_initcall(tx4939_late_init); -- cgit v1.2.3 From b27311e1cace4e296ace786c886d22f7a8ec78d6 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:40 +0900 Subject: MIPS: TXx9: Add RBTX4939 board support Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 arch/mips/txx9/rbtx4939/Makefile create mode 100644 arch/mips/txx9/rbtx4939/irq.c create mode 100644 arch/mips/txx9/rbtx4939/prom.c create mode 100644 arch/mips/txx9/rbtx4939/setup.c create mode 100644 include/asm-mips/txx9/rbtx4939.h --- arch/mips/Makefile | 8 +- arch/mips/txx9/Kconfig | 8 + arch/mips/txx9/generic/setup.c | 5 + arch/mips/txx9/rbtx4939/Makefile | 3 + arch/mips/txx9/rbtx4939/irq.c | 96 ++++++++++++ arch/mips/txx9/rbtx4939/prom.c | 17 +++ arch/mips/txx9/rbtx4939/setup.c | 306 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 437 insertions(+), 6 deletions(-) create mode 100644 arch/mips/txx9/rbtx4939/Makefile create mode 100644 arch/mips/txx9/rbtx4939/irq.c create mode 100644 arch/mips/txx9/rbtx4939/prom.c create mode 100644 arch/mips/txx9/rbtx4939/setup.c (limited to 'arch') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 9aab51caf16..87f67228e30 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -567,15 +567,11 @@ cflags-$(CONFIG_MIKROTIK_RB532) += -Iinclude/asm-mips/mach-rc32434 load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 # -# Toshiba RBTX4927 board or -# Toshiba RBTX4937 board +# Toshiba RBTX49XX boards # core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ - -# -# Toshiba RBTX4938 board -# core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ +core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ cflags-y += -Iinclude/asm-mips/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 58691a1fe77..17052db4161 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -45,6 +45,14 @@ config TOSHIBA_RBTX4938 This Toshiba board is based on the TX4938 processor. Say Y here to support this machine type +config TOSHIBA_RBTX4939 + bool "Toshiba RBTX4939 bobard" + depends on MACH_TX49XX + select SOC_TX4939 + help + This Toshiba board is based on the TX4939 processor. Say Y here to + support this machine type + config SOC_TX3927 bool select CEVT_TXX9 diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 1ea06553a1e..7a05c34c1de 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -371,6 +371,11 @@ static void __init select_board(void) case 0x4938: txx9_board_vec = &rbtx4938_vec; break; +#endif +#ifdef CONFIG_TOSHIBA_RBTX4939 + case 0x4939: + txx9_board_vec = &rbtx4939_vec; + break; #endif } #endif diff --git a/arch/mips/txx9/rbtx4939/Makefile b/arch/mips/txx9/rbtx4939/Makefile new file mode 100644 index 00000000000..3232cd03a7d --- /dev/null +++ b/arch/mips/txx9/rbtx4939/Makefile @@ -0,0 +1,3 @@ +obj-y += irq.o setup.o prom.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4939/irq.c b/arch/mips/txx9/rbtx4939/irq.c new file mode 100644 index 00000000000..500cc0a908e --- /dev/null +++ b/arch/mips/txx9/rbtx4939/irq.c @@ -0,0 +1,96 @@ +/* + * Toshiba RBTX4939 interrupt routines + * Based on linux/arch/mips/txx9/rbtx4938/irq.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include +#include + +/* + * RBTX4939 IOC controller definition + */ + +static void rbtx4939_ioc_irq_unmask(unsigned int irq) +{ + int ioc_nr = irq - RBTX4939_IRQ_IOC; + + writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr); +} + +static void rbtx4939_ioc_irq_mask(unsigned int irq) +{ + int ioc_nr = irq - RBTX4939_IRQ_IOC; + + writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr); + mmiowb(); +} + +static struct irq_chip rbtx4939_ioc_irq_chip = { + .name = "IOC", + .ack = rbtx4939_ioc_irq_mask, + .mask = rbtx4939_ioc_irq_mask, + .mask_ack = rbtx4939_ioc_irq_mask, + .unmask = rbtx4939_ioc_irq_unmask, +}; + + +static inline int rbtx4939_ioc_irqroute(void) +{ + unsigned char istat = readb(rbtx4939_ifac2_addr); + + if (unlikely(istat == 0)) + return -1; + return RBTX4939_IRQ_IOC + __fls8(istat); +} + +static int rbtx4939_irq_dispatch(int pending) +{ + int irq; + + if (pending & CAUSEF_IP7) + return MIPS_CPU_IRQ_BASE + 7; + irq = tx4939_irq(); + if (likely(irq >= 0)) { + /* redirect IOC interrupts */ + switch (irq) { + case RBTX4939_IRQ_IOCINT: + irq = rbtx4939_ioc_irqroute(); + break; + } + } else if (pending & CAUSEF_IP0) + irq = MIPS_CPU_IRQ_BASE + 0; + else if (pending & CAUSEF_IP1) + irq = MIPS_CPU_IRQ_BASE + 1; + else + irq = -1; + return irq; +} + +void __init rbtx4939_irq_setup(void) +{ + int i; + + /* mask all IOC interrupts */ + writeb(0, rbtx4939_ien_addr); + + /* clear SoftInt interrupts */ + writeb(0, rbtx4939_softint_addr); + + txx9_irq_dispatch = rbtx4939_irq_dispatch; + + tx4939_irq_init(); + for (i = RBTX4939_IRQ_IOC; + i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++) + set_irq_chip_and_handler(i, &rbtx4939_ioc_irq_chip, + handle_level_irq); + + set_irq_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq); +} diff --git a/arch/mips/txx9/rbtx4939/prom.c b/arch/mips/txx9/rbtx4939/prom.c new file mode 100644 index 00000000000..bd277ecb4ad --- /dev/null +++ b/arch/mips/txx9/rbtx4939/prom.c @@ -0,0 +1,17 @@ +/* + * rbtx4939 specific prom routines + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +void __init rbtx4939_prom_init(void) +{ + tx4939_add_memory_regions(); + txx9_sio_putchar_init(TX4939_SIO_REG(0) & 0xfffffffffULL); +} diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c new file mode 100644 index 00000000000..277864d5e77 --- /dev/null +++ b/arch/mips/txx9/rbtx4939/setup.c @@ -0,0 +1,306 @@ +/* + * Toshiba RBTX4939 setup routines. + * Based on linux/arch/mips/txx9/rbtx4938/setup.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void rbtx4939_machine_restart(char *command) +{ + local_irq_disable(); + writeb(1, rbtx4939_reseten_addr); + writeb(1, rbtx4939_softreset_addr); + while (1) + ; +} + +static void __init rbtx4939_time_init(void) +{ + tx4939_time_init(0); +} + +static void __init rbtx4939_pci_setup(void) +{ +#ifdef CONFIG_PCI + int extarb = !(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB); + struct pci_controller *c = &txx9_primary_pcic; + + register_pci_controller(c); + + tx4939_report_pciclk(); + tx4927_pcic_setup(tx4939_pcicptr, c, extarb); + if (!(__raw_readq(&tx4939_ccfgptr->pcfg) & TX4939_PCFG_ATA1MODE) && + (__raw_readq(&tx4939_ccfgptr->pcfg) & + (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE))) { + tx4939_report_pci1clk(); + + /* mem:64K(max), io:64K(max) (enough for ETH0,ETH1) */ + c = txx9_alloc_pci_controller(NULL, 0, 0x10000, 0, 0x10000); + register_pci_controller(c); + tx4927_pcic_setup(tx4939_pcic1ptr, c, 0); + } + + tx4939_setup_pcierr_irq(); +#endif /* CONFIG_PCI */ +} + +static unsigned long long default_ebccr[] __initdata = { + 0x01c0000000007608ULL, /* 64M ROM */ + 0x017f000000007049ULL, /* 1M IOC */ + 0x0180000000408608ULL, /* ISA */ + 0, +}; + +static void __init rbtx4939_ebusc_setup(void) +{ + int i; + unsigned int sp; + + /* use user-configured speed */ + sp = TX4939_EBUSC_CR(0) & 0x30; + default_ebccr[0] |= sp; + default_ebccr[1] |= sp; + default_ebccr[2] |= sp; + /* initialise by myself */ + for (i = 0; i < ARRAY_SIZE(default_ebccr); i++) { + if (default_ebccr[i]) + ____raw_writeq(default_ebccr[i], + &tx4939_ebuscptr->cr[i]); + else + ____raw_writeq(____raw_readq(&tx4939_ebuscptr->cr[i]) + & ~8, + &tx4939_ebuscptr->cr[i]); + } +} + +static void __init rbtx4939_update_ioc_pen(void) +{ + __u64 pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); + __u64 ccfg = ____raw_readq(&tx4939_ccfgptr->ccfg); + __u8 pe1 = readb(rbtx4939_pe1_addr); + __u8 pe2 = readb(rbtx4939_pe2_addr); + __u8 pe3 = readb(rbtx4939_pe3_addr); + if (pcfg & TX4939_PCFG_ATA0MODE) + pe1 |= RBTX4939_PE1_ATA(0); + else + pe1 &= ~RBTX4939_PE1_ATA(0); + if (pcfg & TX4939_PCFG_ATA1MODE) { + pe1 |= RBTX4939_PE1_ATA(1); + pe1 &= ~(RBTX4939_PE1_RMII(0) | RBTX4939_PE1_RMII(1)); + } else { + pe1 &= ~RBTX4939_PE1_ATA(1); + if (pcfg & TX4939_PCFG_ET0MODE) + pe1 |= RBTX4939_PE1_RMII(0); + else + pe1 &= ~RBTX4939_PE1_RMII(0); + if (pcfg & TX4939_PCFG_ET1MODE) + pe1 |= RBTX4939_PE1_RMII(1); + else + pe1 &= ~RBTX4939_PE1_RMII(1); + } + if (ccfg & TX4939_CCFG_PTSEL) + pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P | + RBTX4939_PE3_VP_S); + else { + __u64 vmode = pcfg & + (TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE); + if (vmode == 0) + pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P | + RBTX4939_PE3_VP_S); + else if (vmode == TX4939_PCFG_VPSMODE) { + pe3 |= RBTX4939_PE3_VP_P; + pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_S); + } else if (vmode == TX4939_PCFG_VSSMODE) { + pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_S; + pe3 &= ~RBTX4939_PE3_VP_P; + } else { + pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_P; + pe3 &= ~RBTX4939_PE3_VP_S; + } + } + if (pcfg & TX4939_PCFG_SPIMODE) { + if (pcfg & TX4939_PCFG_SIO2MODE_GPIO) + pe2 &= ~(RBTX4939_PE2_SIO2 | RBTX4939_PE2_SIO0); + else { + if (pcfg & TX4939_PCFG_SIO2MODE_SIO2) { + pe2 |= RBTX4939_PE2_SIO2; + pe2 &= ~RBTX4939_PE2_SIO0; + } else { + pe2 |= RBTX4939_PE2_SIO0; + pe2 &= ~RBTX4939_PE2_SIO2; + } + } + if (pcfg & TX4939_PCFG_SIO3MODE) + pe2 |= RBTX4939_PE2_SIO3; + else + pe2 &= ~RBTX4939_PE2_SIO3; + pe2 &= ~RBTX4939_PE2_SPI; + } else { + pe2 |= RBTX4939_PE2_SPI; + pe2 &= ~(RBTX4939_PE2_SIO3 | RBTX4939_PE2_SIO2 | + RBTX4939_PE2_SIO0); + } + if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_GPIO) + pe2 |= RBTX4939_PE2_GPIO; + else + pe2 &= ~RBTX4939_PE2_GPIO; + writeb(pe1, rbtx4939_pe1_addr); + writeb(pe2, rbtx4939_pe2_addr); + writeb(pe3, rbtx4939_pe3_addr); +} + +#define RBTX4939_MAX_7SEGLEDS 8 + +#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +static u8 led_val[RBTX4939_MAX_7SEGLEDS]; +struct rbtx4939_led_data { + struct led_classdev cdev; + char name[32]; + unsigned int num; +}; + +/* Use "dot" in 7seg LEDs */ +static void rbtx4939_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct rbtx4939_led_data *led_dat = + container_of(led_cdev, struct rbtx4939_led_data, cdev); + unsigned int num = led_dat->num; + unsigned long flags; + + local_irq_save(flags); + led_val[num] = (led_val[num] & 0x7f) | (value ? 0x80 : 0); + writeb(led_val[num], rbtx4939_7seg_addr(num / 4, num % 4)); + local_irq_restore(flags); +} + +static int __init rbtx4939_led_probe(struct platform_device *pdev) +{ + struct rbtx4939_led_data *leds_data; + int i; + static char *default_triggers[] __initdata = { + "heartbeat", + "ide-disk", + "nand-disk", + }; + + leds_data = kzalloc(sizeof(*leds_data) * RBTX4939_MAX_7SEGLEDS, + GFP_KERNEL); + if (!leds_data) + return -ENOMEM; + for (i = 0; i < RBTX4939_MAX_7SEGLEDS; i++) { + int rc; + struct rbtx4939_led_data *led_dat = &leds_data[i]; + + led_dat->num = i; + led_dat->cdev.brightness_set = rbtx4939_led_brightness_set; + sprintf(led_dat->name, "rbtx4939:amber:%u", i); + led_dat->cdev.name = led_dat->name; + if (i < ARRAY_SIZE(default_triggers)) + led_dat->cdev.default_trigger = default_triggers[i]; + rc = led_classdev_register(&pdev->dev, &led_dat->cdev); + if (rc < 0) + return rc; + led_dat->cdev.brightness_set(&led_dat->cdev, 0); + } + return 0; + +} + +static struct platform_driver rbtx4939_led_driver = { + .driver = { + .name = "rbtx4939-led", + .owner = THIS_MODULE, + }, +}; + +static void __init rbtx4939_led_setup(void) +{ + platform_device_register_simple("rbtx4939-led", -1, NULL, 0); + platform_driver_probe(&rbtx4939_led_driver, rbtx4939_led_probe); +} +#else +static inline void rbtx4939_led_setup(void) +{ +} +#endif + +static void __init rbtx4939_arch_init(void) +{ + rbtx4939_pci_setup(); +} + +static void __init rbtx4939_device_init(void) +{ +#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) + int i, j; + unsigned char ethaddr[2][6]; + for (i = 0; i < 2; i++) { + unsigned long area = CKSEG1 + 0x1fff0000 + (i * 0x10); + if (readb(rbtx4939_bdipsw_addr) & 8) { + u16 buf[3]; + area -= 0x03000000; + for (j = 0; j < 3; j++) + buf[j] = le16_to_cpup((u16 *)(area + j * 2)); + memcpy(ethaddr[i], buf, 6); + } else + memcpy(ethaddr[i], (void *)area, 6); + } + tx4939_ethaddr_init(ethaddr[0], ethaddr[1]); +#endif + rbtx4939_led_setup(); + tx4939_wdt_init(); +} + +static void __init rbtx4939_setup(void) +{ + rbtx4939_ebusc_setup(); + /* always enable ATA0 */ + txx9_set64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_ATA0MODE); + rbtx4939_update_ioc_pen(); + if (txx9_master_clock == 0) + txx9_master_clock = 20000000; + tx4939_setup(); + + _machine_restart = rbtx4939_machine_restart; + + pr_info("RBTX4939 (Rev %02x) --- FPGA(Rev %02x) DIPSW:%02x,%02x\n", + readb(rbtx4939_board_rev_addr), readb(rbtx4939_ioc_rev_addr), + readb(rbtx4939_udipsw_addr), readb(rbtx4939_bdipsw_addr)); + +#ifdef CONFIG_PCI + txx9_alloc_pci_controller(&txx9_primary_pcic, 0, 0, 0, 0); + txx9_board_pcibios_setup = tx4927_pcibios_setup; +#else + set_io_port_base(RBTX4939_ETHER_BASE); +#endif + + tx4939_sio_init(TX4939_SCLK0(txx9_master_clock), 0); +} + +struct txx9_board_vec rbtx4939_vec __initdata = { + .system = "Tothiba RBTX4939", + .prom_init = rbtx4939_prom_init, + .mem_setup = rbtx4939_setup, + .irq_setup = rbtx4939_irq_setup, + .time_init = rbtx4939_time_init, + .device_init = rbtx4939_device_init, + .arch_init = rbtx4939_arch_init, +#ifdef CONFIG_PCI + .pci_map_irq = tx4939_pci_map_irq, +#endif +}; -- cgit v1.2.3 From b6263ff2d6e58cc2fe615219ab2a06778b5e6cef Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:41 +0900 Subject: MIPS: TXx9: Implement prom_free_prom_memory Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 7a05c34c1de..5526375010f 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -394,6 +395,11 @@ void __init prom_init(void) void __init prom_free_prom_memory(void) { + unsigned long saddr = PAGE_SIZE; + unsigned long eaddr = __pa_symbol(&_text); + + if (saddr < eaddr) + free_init_pages("prom memory", saddr, eaddr); } const char *get_system_type(void) -- cgit v1.2.3 From e8c7c482347574ecdd45c43e32c332d5fc2ece61 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 16 Sep 2008 19:12:16 +0200 Subject: MIPS: Alchemy: rename directory It's more than the au1000 these days. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/Makefile | 30 +- arch/mips/alchemy/Kconfig | 136 +++++ arch/mips/alchemy/common/Makefile | 14 + arch/mips/alchemy/common/au1xxx_irqmap.c | 205 +++++++ arch/mips/alchemy/common/clocks.c | 93 +++ arch/mips/alchemy/common/cputable.c | 52 ++ arch/mips/alchemy/common/dbdma.c | 978 +++++++++++++++++++++++++++++++ arch/mips/alchemy/common/dma.c | 238 ++++++++ arch/mips/alchemy/common/gpio.c | 148 +++++ arch/mips/alchemy/common/irq.c | 596 +++++++++++++++++++ arch/mips/alchemy/common/pci.c | 104 ++++ arch/mips/alchemy/common/platform.c | 319 ++++++++++ arch/mips/alchemy/common/power.c | 465 +++++++++++++++ arch/mips/alchemy/common/prom.c | 146 +++++ arch/mips/alchemy/common/puts.c | 68 +++ arch/mips/alchemy/common/reset.c | 189 ++++++ arch/mips/alchemy/common/setup.c | 160 +++++ arch/mips/alchemy/common/sleeper.S | 154 +++++ arch/mips/alchemy/common/time.c | 266 +++++++++ arch/mips/alchemy/db1x00/Makefile | 8 + arch/mips/alchemy/db1x00/board_setup.c | 108 ++++ arch/mips/alchemy/db1x00/init.c | 62 ++ arch/mips/alchemy/db1x00/irqmap.c | 86 +++ arch/mips/alchemy/mtx-1/Makefile | 12 + arch/mips/alchemy/mtx-1/board_setup.c | 98 ++++ arch/mips/alchemy/mtx-1/init.c | 60 ++ arch/mips/alchemy/mtx-1/irqmap.c | 52 ++ arch/mips/alchemy/mtx-1/platform.c | 149 +++++ arch/mips/alchemy/pb1000/Makefile | 8 + arch/mips/alchemy/pb1000/board_setup.c | 165 ++++++ arch/mips/alchemy/pb1000/init.c | 57 ++ arch/mips/alchemy/pb1000/irqmap.c | 38 ++ arch/mips/alchemy/pb1100/Makefile | 8 + arch/mips/alchemy/pb1100/board_setup.c | 109 ++++ arch/mips/alchemy/pb1100/init.c | 60 ++ arch/mips/alchemy/pb1100/irqmap.c | 40 ++ arch/mips/alchemy/pb1200/Makefile | 8 + arch/mips/alchemy/pb1200/board_setup.c | 162 +++++ arch/mips/alchemy/pb1200/init.c | 58 ++ arch/mips/alchemy/pb1200/irqmap.c | 160 +++++ arch/mips/alchemy/pb1200/platform.c | 85 +++ arch/mips/alchemy/pb1500/Makefile | 8 + arch/mips/alchemy/pb1500/board_setup.c | 119 ++++ arch/mips/alchemy/pb1500/init.c | 58 ++ arch/mips/alchemy/pb1500/irqmap.c | 46 ++ arch/mips/alchemy/pb1550/Makefile | 8 + arch/mips/alchemy/pb1550/board_setup.c | 58 ++ arch/mips/alchemy/pb1550/init.c | 58 ++ arch/mips/alchemy/pb1550/irqmap.c | 43 ++ arch/mips/alchemy/xxs1500/Makefile | 8 + arch/mips/alchemy/xxs1500/board_setup.c | 79 +++ arch/mips/alchemy/xxs1500/init.c | 58 ++ arch/mips/alchemy/xxs1500/irqmap.c | 49 ++ arch/mips/au1000/Kconfig | 136 ----- arch/mips/au1000/common/Makefile | 14 - arch/mips/au1000/common/au1xxx_irqmap.c | 205 ------- arch/mips/au1000/common/clocks.c | 93 --- arch/mips/au1000/common/cputable.c | 52 -- arch/mips/au1000/common/dbdma.c | 978 ------------------------------- arch/mips/au1000/common/dma.c | 238 -------- arch/mips/au1000/common/gpio.c | 148 ----- arch/mips/au1000/common/irq.c | 596 ------------------- arch/mips/au1000/common/pci.c | 104 ---- arch/mips/au1000/common/platform.c | 319 ---------- arch/mips/au1000/common/power.c | 465 --------------- arch/mips/au1000/common/prom.c | 146 ----- arch/mips/au1000/common/puts.c | 68 --- arch/mips/au1000/common/reset.c | 189 ------ arch/mips/au1000/common/setup.c | 160 ----- arch/mips/au1000/common/sleeper.S | 154 ----- arch/mips/au1000/common/time.c | 266 --------- arch/mips/au1000/db1x00/Makefile | 8 - arch/mips/au1000/db1x00/board_setup.c | 108 ---- arch/mips/au1000/db1x00/init.c | 62 -- arch/mips/au1000/db1x00/irqmap.c | 86 --- arch/mips/au1000/mtx-1/Makefile | 12 - arch/mips/au1000/mtx-1/board_setup.c | 98 ---- arch/mips/au1000/mtx-1/init.c | 60 -- arch/mips/au1000/mtx-1/irqmap.c | 52 -- arch/mips/au1000/mtx-1/platform.c | 149 ----- arch/mips/au1000/pb1000/Makefile | 8 - arch/mips/au1000/pb1000/board_setup.c | 165 ------ arch/mips/au1000/pb1000/init.c | 57 -- arch/mips/au1000/pb1000/irqmap.c | 38 -- arch/mips/au1000/pb1100/Makefile | 8 - arch/mips/au1000/pb1100/board_setup.c | 109 ---- arch/mips/au1000/pb1100/init.c | 60 -- arch/mips/au1000/pb1100/irqmap.c | 40 -- arch/mips/au1000/pb1200/Makefile | 8 - arch/mips/au1000/pb1200/board_setup.c | 162 ----- arch/mips/au1000/pb1200/init.c | 58 -- arch/mips/au1000/pb1200/irqmap.c | 160 ----- arch/mips/au1000/pb1200/platform.c | 85 --- arch/mips/au1000/pb1500/Makefile | 8 - arch/mips/au1000/pb1500/board_setup.c | 119 ---- arch/mips/au1000/pb1500/init.c | 58 -- arch/mips/au1000/pb1500/irqmap.c | 46 -- arch/mips/au1000/pb1550/Makefile | 8 - arch/mips/au1000/pb1550/board_setup.c | 58 -- arch/mips/au1000/pb1550/init.c | 58 -- arch/mips/au1000/pb1550/irqmap.c | 43 -- arch/mips/au1000/xxs1500/Makefile | 8 - arch/mips/au1000/xxs1500/board_setup.c | 79 --- arch/mips/au1000/xxs1500/init.c | 58 -- arch/mips/au1000/xxs1500/irqmap.c | 49 -- 106 files changed, 6532 insertions(+), 6532 deletions(-) create mode 100644 arch/mips/alchemy/Kconfig create mode 100644 arch/mips/alchemy/common/Makefile create mode 100644 arch/mips/alchemy/common/au1xxx_irqmap.c create mode 100644 arch/mips/alchemy/common/clocks.c create mode 100644 arch/mips/alchemy/common/cputable.c create mode 100644 arch/mips/alchemy/common/dbdma.c create mode 100644 arch/mips/alchemy/common/dma.c create mode 100644 arch/mips/alchemy/common/gpio.c create mode 100644 arch/mips/alchemy/common/irq.c create mode 100644 arch/mips/alchemy/common/pci.c create mode 100644 arch/mips/alchemy/common/platform.c create mode 100644 arch/mips/alchemy/common/power.c create mode 100644 arch/mips/alchemy/common/prom.c create mode 100644 arch/mips/alchemy/common/puts.c create mode 100644 arch/mips/alchemy/common/reset.c create mode 100644 arch/mips/alchemy/common/setup.c create mode 100644 arch/mips/alchemy/common/sleeper.S create mode 100644 arch/mips/alchemy/common/time.c create mode 100644 arch/mips/alchemy/db1x00/Makefile create mode 100644 arch/mips/alchemy/db1x00/board_setup.c create mode 100644 arch/mips/alchemy/db1x00/init.c create mode 100644 arch/mips/alchemy/db1x00/irqmap.c create mode 100644 arch/mips/alchemy/mtx-1/Makefile create mode 100644 arch/mips/alchemy/mtx-1/board_setup.c create mode 100644 arch/mips/alchemy/mtx-1/init.c create mode 100644 arch/mips/alchemy/mtx-1/irqmap.c create mode 100644 arch/mips/alchemy/mtx-1/platform.c create mode 100644 arch/mips/alchemy/pb1000/Makefile create mode 100644 arch/mips/alchemy/pb1000/board_setup.c create mode 100644 arch/mips/alchemy/pb1000/init.c create mode 100644 arch/mips/alchemy/pb1000/irqmap.c create mode 100644 arch/mips/alchemy/pb1100/Makefile create mode 100644 arch/mips/alchemy/pb1100/board_setup.c create mode 100644 arch/mips/alchemy/pb1100/init.c create mode 100644 arch/mips/alchemy/pb1100/irqmap.c create mode 100644 arch/mips/alchemy/pb1200/Makefile create mode 100644 arch/mips/alchemy/pb1200/board_setup.c create mode 100644 arch/mips/alchemy/pb1200/init.c create mode 100644 arch/mips/alchemy/pb1200/irqmap.c create mode 100644 arch/mips/alchemy/pb1200/platform.c create mode 100644 arch/mips/alchemy/pb1500/Makefile create mode 100644 arch/mips/alchemy/pb1500/board_setup.c create mode 100644 arch/mips/alchemy/pb1500/init.c create mode 100644 arch/mips/alchemy/pb1500/irqmap.c create mode 100644 arch/mips/alchemy/pb1550/Makefile create mode 100644 arch/mips/alchemy/pb1550/board_setup.c create mode 100644 arch/mips/alchemy/pb1550/init.c create mode 100644 arch/mips/alchemy/pb1550/irqmap.c create mode 100644 arch/mips/alchemy/xxs1500/Makefile create mode 100644 arch/mips/alchemy/xxs1500/board_setup.c create mode 100644 arch/mips/alchemy/xxs1500/init.c create mode 100644 arch/mips/alchemy/xxs1500/irqmap.c delete mode 100644 arch/mips/au1000/Kconfig delete mode 100644 arch/mips/au1000/common/Makefile delete mode 100644 arch/mips/au1000/common/au1xxx_irqmap.c delete mode 100644 arch/mips/au1000/common/clocks.c delete mode 100644 arch/mips/au1000/common/cputable.c delete mode 100644 arch/mips/au1000/common/dbdma.c delete mode 100644 arch/mips/au1000/common/dma.c delete mode 100644 arch/mips/au1000/common/gpio.c delete mode 100644 arch/mips/au1000/common/irq.c delete mode 100644 arch/mips/au1000/common/pci.c delete mode 100644 arch/mips/au1000/common/platform.c delete mode 100644 arch/mips/au1000/common/power.c delete mode 100644 arch/mips/au1000/common/prom.c delete mode 100644 arch/mips/au1000/common/puts.c delete mode 100644 arch/mips/au1000/common/reset.c delete mode 100644 arch/mips/au1000/common/setup.c delete mode 100644 arch/mips/au1000/common/sleeper.S delete mode 100644 arch/mips/au1000/common/time.c delete mode 100644 arch/mips/au1000/db1x00/Makefile delete mode 100644 arch/mips/au1000/db1x00/board_setup.c delete mode 100644 arch/mips/au1000/db1x00/init.c delete mode 100644 arch/mips/au1000/db1x00/irqmap.c delete mode 100644 arch/mips/au1000/mtx-1/Makefile delete mode 100644 arch/mips/au1000/mtx-1/board_setup.c delete mode 100644 arch/mips/au1000/mtx-1/init.c delete mode 100644 arch/mips/au1000/mtx-1/irqmap.c delete mode 100644 arch/mips/au1000/mtx-1/platform.c delete mode 100644 arch/mips/au1000/pb1000/Makefile delete mode 100644 arch/mips/au1000/pb1000/board_setup.c delete mode 100644 arch/mips/au1000/pb1000/init.c delete mode 100644 arch/mips/au1000/pb1000/irqmap.c delete mode 100644 arch/mips/au1000/pb1100/Makefile delete mode 100644 arch/mips/au1000/pb1100/board_setup.c delete mode 100644 arch/mips/au1000/pb1100/init.c delete mode 100644 arch/mips/au1000/pb1100/irqmap.c delete mode 100644 arch/mips/au1000/pb1200/Makefile delete mode 100644 arch/mips/au1000/pb1200/board_setup.c delete mode 100644 arch/mips/au1000/pb1200/init.c delete mode 100644 arch/mips/au1000/pb1200/irqmap.c delete mode 100644 arch/mips/au1000/pb1200/platform.c delete mode 100644 arch/mips/au1000/pb1500/Makefile delete mode 100644 arch/mips/au1000/pb1500/board_setup.c delete mode 100644 arch/mips/au1000/pb1500/init.c delete mode 100644 arch/mips/au1000/pb1500/irqmap.c delete mode 100644 arch/mips/au1000/pb1550/Makefile delete mode 100644 arch/mips/au1000/pb1550/board_setup.c delete mode 100644 arch/mips/au1000/pb1550/init.c delete mode 100644 arch/mips/au1000/pb1550/irqmap.c delete mode 100644 arch/mips/au1000/xxs1500/Makefile delete mode 100644 arch/mips/au1000/xxs1500/board_setup.c delete mode 100644 arch/mips/au1000/xxs1500/init.c delete mode 100644 arch/mips/au1000/xxs1500/irqmap.c (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 00a23a11849..c15416c2e89 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -598,7 +598,7 @@ config WR_PPMC endchoice -source "arch/mips/au1000/Kconfig" +source "arch/mips/alchemy/Kconfig" source "arch/mips/basler/excite/Kconfig" source "arch/mips/jazz/Kconfig" source "arch/mips/lasat/Kconfig" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 87f67228e30..4401a0c1278 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -176,103 +176,103 @@ load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # # Common Alchemy Au1x00 stuff # -core-$(CONFIG_SOC_AU1X00) += arch/mips/au1000/common/ +core-$(CONFIG_SOC_AU1X00) += arch/mips/alchemy/common/ cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00 # # AMD Alchemy Pb1000 eval board # -libs-$(CONFIG_MIPS_PB1000) += arch/mips/au1000/pb1000/ +libs-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/pb1000/ cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 # # AMD Alchemy Pb1100 eval board # -libs-$(CONFIG_MIPS_PB1100) += arch/mips/au1000/pb1100/ +libs-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/pb1100/ cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 # # AMD Alchemy Pb1500 eval board # -libs-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/pb1500/ +libs-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/pb1500/ cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 # # AMD Alchemy Pb1550 eval board # -libs-$(CONFIG_MIPS_PB1550) += arch/mips/au1000/pb1550/ +libs-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/pb1550/ cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 # # AMD Alchemy Pb1200 eval board # -libs-$(CONFIG_MIPS_PB1200) += arch/mips/au1000/pb1200/ +libs-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/pb1200/ cflags-$(CONFIG_MIPS_PB1200) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 # # AMD Alchemy Db1000 eval board # -libs-$(CONFIG_MIPS_DB1000) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 # # AMD Alchemy Db1100 eval board # -libs-$(CONFIG_MIPS_DB1100) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 # # AMD Alchemy Db1500 eval board # -libs-$(CONFIG_MIPS_DB1500) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 # # AMD Alchemy Db1550 eval board # -libs-$(CONFIG_MIPS_DB1550) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # # AMD Alchemy Db1200 eval board # -libs-$(CONFIG_MIPS_DB1200) += arch/mips/au1000/pb1200/ +libs-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/pb1200/ cflags-$(CONFIG_MIPS_DB1200) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 # # AMD Alchemy Bosporus eval board # -libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 # # AMD Alchemy Mirage eval board # -libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 # # 4G-Systems eval board # -libs-$(CONFIG_MIPS_MTX1) += arch/mips/au1000/mtx-1/ +libs-$(CONFIG_MIPS_MTX1) += arch/mips/alchemy/mtx-1/ load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 # # MyCable eval board # -libs-$(CONFIG_MIPS_XXS1500) += arch/mips/au1000/xxs1500/ +libs-$(CONFIG_MIPS_XXS1500) += arch/mips/alchemy/xxs1500/ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig new file mode 100644 index 00000000000..e4a057d80ab --- /dev/null +++ b/arch/mips/alchemy/Kconfig @@ -0,0 +1,136 @@ +choice + prompt "Machine type" + depends on MACH_ALCHEMY + default MIPS_DB1000 + +config MIPS_MTX1 + bool "4G Systems MTX-1 board" + select DMA_NONCOHERENT + select HW_HAS_PCI + select SOC_AU1500 + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_BOSPORUS + bool "Alchemy Bosporus board" + select SOC_AU1500 + select DMA_NONCOHERENT + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1000 + bool "Alchemy DB1000 board" + select SOC_AU1000 + select DMA_NONCOHERENT + select HW_HAS_PCI + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1100 + bool "Alchemy DB1100 board" + select SOC_AU1100 + select DMA_NONCOHERENT + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1200 + bool "Alchemy DB1200 board" + select SOC_AU1200 + select DMA_COHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1500 + bool "Alchemy DB1500 board" + select SOC_AU1500 + select DMA_NONCOHERENT + select HW_HAS_PCI + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1550 + bool "Alchemy DB1550 board" + select SOC_AU1550 + select HW_HAS_PCI + select DMA_NONCOHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_MIRAGE + bool "Alchemy Mirage board" + select DMA_NONCOHERENT + select SOC_AU1500 + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1000 + bool "Alchemy PB1000 board" + select SOC_AU1000 + select DMA_NONCOHERENT + select HW_HAS_PCI + select SWAP_IO_SPACE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1100 + bool "Alchemy PB1100 board" + select SOC_AU1100 + select DMA_NONCOHERENT + select HW_HAS_PCI + select SWAP_IO_SPACE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1200 + bool "Alchemy PB1200 board" + select SOC_AU1200 + select DMA_NONCOHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1500 + bool "Alchemy PB1500 board" + select SOC_AU1500 + select DMA_NONCOHERENT + select HW_HAS_PCI + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1550 + bool "Alchemy PB1550 board" + select SOC_AU1550 + select DMA_NONCOHERENT + select HW_HAS_PCI + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_XXS1500 + bool "MyCable XXS1500 board" + select DMA_NONCOHERENT + select SOC_AU1500 + select SYS_SUPPORTS_LITTLE_ENDIAN + +endchoice + +config SOC_AU1000 + bool + select SOC_AU1X00 + +config SOC_AU1100 + bool + select SOC_AU1X00 + +config SOC_AU1500 + bool + select SOC_AU1X00 + +config SOC_AU1550 + bool + select SOC_AU1X00 + +config SOC_AU1200 + bool + select SOC_AU1X00 + +config SOC_AU1X00 + bool + select 64BIT_PHYS_ADDR + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_APM_EMULATION diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile new file mode 100644 index 00000000000..df48fd65bbf --- /dev/null +++ b/arch/mips/alchemy/common/Makefile @@ -0,0 +1,14 @@ +# +# Copyright 2000, 2008 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for the Alchemy Au1xx0 CPUs, generic files. +# + +obj-y += prom.o irq.o puts.o time.o reset.o \ + au1xxx_irqmap.o clocks.o platform.o power.o setup.o \ + sleeper.o cputable.o dma.o dbdma.o gpio.o + +obj-$(CONFIG_PCI) += pci.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/common/au1xxx_irqmap.c b/arch/mips/alchemy/common/au1xxx_irqmap.c new file mode 100644 index 00000000000..c7ca1596394 --- /dev/null +++ b/arch/mips/alchemy/common/au1xxx_irqmap.c @@ -0,0 +1,205 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx processor specific IRQ tables + * + * Copyright 2004 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include + +#include + +/* The IC0 interrupt table. This is processor, rather than + * board dependent, so no reason to keep this info in the board + * dependent files. + * + * Careful if you change match 2 request! + * The interrupt handler is called directly from the low level dispatch code. + */ +struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = { + +#if defined(CONFIG_SOC_AU1000) + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + +#elif defined(CONFIG_SOC_AU1500) + + { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + +#elif defined(CONFIG_SOC_AU1100) + + { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + /* { AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0 }, */ + { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + +#elif defined(CONFIG_SOC_AU1550) + + { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + +#elif defined(CONFIG_SOC_AU1200) + + { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0 }, + +#else +#error "Error: Unknown Alchemy SOC" +#endif + +}; + +int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map); diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c new file mode 100644 index 00000000000..043429d17c5 --- /dev/null +++ b/arch/mips/alchemy/common/clocks.c @@ -0,0 +1,93 @@ +/* + * BRIEF MODULE DESCRIPTION + * Simple Au1xx0 clocks routines. + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +static unsigned int au1x00_clock; /* Hz */ +static unsigned int lcd_clock; /* KHz */ +static unsigned long uart_baud_base; + +/* + * Set the au1000_clock + */ +void set_au1x00_speed(unsigned int new_freq) +{ + au1x00_clock = new_freq; +} + +unsigned int get_au1x00_speed(void) +{ + return au1x00_clock; +} +EXPORT_SYMBOL(get_au1x00_speed); + +/* + * The UART baud base is not known at compile time ... if + * we want to be able to use the same code on different + * speed CPUs. + */ +unsigned long get_au1x00_uart_baud_base(void) +{ + return uart_baud_base; +} + +void set_au1x00_uart_baud_base(unsigned long new_baud_base) +{ + uart_baud_base = new_baud_base; +} + +/* + * Calculate the Au1x00's LCD clock based on the current + * cpu clock and the system bus clock, and try to keep it + * below 40 MHz (the Pb1000 board can lock-up if the LCD + * clock is over 40 MHz). + */ +void set_au1x00_lcd_clock(void) +{ + unsigned int static_cfg0; + unsigned int sys_busclk = (get_au1x00_speed() / 1000) / + ((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2); + + static_cfg0 = au_readl(MEM_STCFG0); + + if (static_cfg0 & (1 << 11)) + lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */ + else + lcd_clock = sys_busclk / 4; + + if (lcd_clock > 50000) /* Epson MAX */ + printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n", + lcd_clock); +} + +unsigned int get_au1x00_lcd_clock(void) +{ + return lcd_clock; +} +EXPORT_SYMBOL(get_au1x00_lcd_clock); diff --git a/arch/mips/alchemy/common/cputable.c b/arch/mips/alchemy/common/cputable.c new file mode 100644 index 00000000000..ba6430bc2d0 --- /dev/null +++ b/arch/mips/alchemy/common/cputable.c @@ -0,0 +1,52 @@ +/* + * arch/mips/au1000/common/cputable.c + * + * Copyright (C) 2004 Dan Malek (dan@embeddededge.com) + * Copied from PowerPC and updated for Alchemy Au1xxx processors. + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include + +struct cpu_spec *cur_cpu_spec[NR_CPUS]; + +/* With some thought, we can probably use the mask to reduce the + * size of the table. + */ +struct cpu_spec cpu_specs[] = { + { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 }, + { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 }, + { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 }, + { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 }, + { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 }, + { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 }, + { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 }, + { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 }, + { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 }, + { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 }, + { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 }, + { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 }, + { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 }, + { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 }, + { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 }, + { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 }, + { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 } +}; + +void set_cpuspec(void) +{ + struct cpu_spec *sp; + u32 prid; + + prid = read_c0_prid(); + sp = cpu_specs; + while ((prid & sp->prid_mask) != sp->prid_value) + sp++; + cur_cpu_spec[0] = sp; +} diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c new file mode 100644 index 00000000000..601ee9180ee --- /dev/null +++ b/arch/mips/alchemy/common/dbdma.c @@ -0,0 +1,978 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * The Descriptor Based DMA channel manager that first appeared + * on the Au1550. I started with dma.c, but I think all that is + * left is this initial comment :-) + * + * Copyright 2004 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) + +/* + * The Descriptor Based DMA supports up to 16 channels. + * + * There are 32 devices defined. We keep an internal structure + * of devices using these channels, along with additional + * information. + * + * We allocate the descriptors and allow access to them through various + * functions. The drivers allocate the data buffers and assign them + * to the descriptors. + */ +static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock); + +/* I couldn't find a macro that did this... */ +#define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) + +static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; +static int dbdma_initialized; +static void au1xxx_dbdma_init(void); + +static dbdev_tab_t dbdev_tab[] = { +#ifdef CONFIG_SOC_AU1550 + /* UARTS */ + { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 }, + { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 }, + { DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 }, + { DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 }, + + /* EXT DMA */ + { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 }, + + /* USB DEV */ + { DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 }, + { DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 }, + { DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 }, + { DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 }, + { DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 }, + { DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 }, + + /* PSC 0 */ + { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, + { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, + + /* PSC 1 */ + { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 }, + { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, + + /* PSC 2 */ + { DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 }, + { DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 }, + + /* PSC 3 */ + { DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 }, + { DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 }, + + { DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */ + { DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */ + + /* MAC 0 */ + { DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + + /* MAC 1 */ + { DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + +#endif /* CONFIG_SOC_AU1550 */ + +#ifdef CONFIG_SOC_AU1200 + { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 }, + { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 }, + { DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 }, + { DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 }, + + { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 }, + { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 }, + { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 }, + { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 }, + + { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 }, + { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 }, + + { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 }, + { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 16, 0x11a0001c, 0, 0 }, + { DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 }, + { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 16, 0x11b0001c, 0, 0 }, + { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 }, + { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 }, + { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 }, + { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + +#endif /* CONFIG_SOC_AU1200 */ + + { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + /* Provide 16 user definable device types */ + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, + { ~0, 0, 0, 0, 0, 0, 0 }, +}; + +#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab) + +static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS]; + +static dbdev_tab_t *find_dbdev_id(u32 id) +{ + int i; + dbdev_tab_t *p; + for (i = 0; i < DBDEV_TAB_SIZE; ++i) { + p = &dbdev_tab[i]; + if (p->dev_id == id) + return p; + } + return NULL; +} + +void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp) +{ + return phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); +} +EXPORT_SYMBOL(au1xxx_ddma_get_nextptr_virt); + +u32 au1xxx_ddma_add_device(dbdev_tab_t *dev) +{ + u32 ret = 0; + dbdev_tab_t *p; + static u16 new_id = 0x1000; + + p = find_dbdev_id(~0); + if (NULL != p) { + memcpy(p, dev, sizeof(dbdev_tab_t)); + p->dev_id = DSCR_DEV2CUSTOM_ID(new_id, dev->dev_id); + ret = p->dev_id; + new_id++; +#if 0 + printk(KERN_DEBUG "add_device: id:%x flags:%x padd:%x\n", + p->dev_id, p->dev_flags, p->dev_physaddr); +#endif + } + + return ret; +} +EXPORT_SYMBOL(au1xxx_ddma_add_device); + +void au1xxx_ddma_del_device(u32 devid) +{ + dbdev_tab_t *p = find_dbdev_id(devid); + + if (p != NULL) { + memset(p, 0, sizeof(dbdev_tab_t)); + p->dev_id = ~0; + } +} +EXPORT_SYMBOL(au1xxx_ddma_del_device); + +/* Allocate a channel and return a non-zero descriptor if successful. */ +u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, + void (*callback)(int, void *), void *callparam) +{ + unsigned long flags; + u32 used, chan, rv; + u32 dcp; + int i; + dbdev_tab_t *stp, *dtp; + chan_tab_t *ctp; + au1x_dma_chan_t *cp; + + /* + * We do the intialization on the first channel allocation. + * We have to wait because of the interrupt handler initialization + * which can't be done successfully during board set up. + */ + if (!dbdma_initialized) + au1xxx_dbdma_init(); + dbdma_initialized = 1; + + stp = find_dbdev_id(srcid); + if (stp == NULL) + return 0; + dtp = find_dbdev_id(destid); + if (dtp == NULL) + return 0; + + used = 0; + rv = 0; + + /* Check to see if we can get both channels. */ + spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); + if (!(stp->dev_flags & DEV_FLAGS_INUSE) || + (stp->dev_flags & DEV_FLAGS_ANYUSE)) { + /* Got source */ + stp->dev_flags |= DEV_FLAGS_INUSE; + if (!(dtp->dev_flags & DEV_FLAGS_INUSE) || + (dtp->dev_flags & DEV_FLAGS_ANYUSE)) { + /* Got destination */ + dtp->dev_flags |= DEV_FLAGS_INUSE; + } else { + /* Can't get dest. Release src. */ + stp->dev_flags &= ~DEV_FLAGS_INUSE; + used++; + } + } else + used++; + spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); + + if (!used) { + /* Let's see if we can allocate a channel for it. */ + ctp = NULL; + chan = 0; + spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); + for (i = 0; i < NUM_DBDMA_CHANS; i++) + if (chan_tab_ptr[i] == NULL) { + /* + * If kmalloc fails, it is caught below same + * as a channel not available. + */ + ctp = kmalloc(sizeof(chan_tab_t), GFP_ATOMIC); + chan_tab_ptr[i] = ctp; + break; + } + spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); + + if (ctp != NULL) { + memset(ctp, 0, sizeof(chan_tab_t)); + ctp->chan_index = chan = i; + dcp = DDMA_CHANNEL_BASE; + dcp += (0x0100 * chan); + ctp->chan_ptr = (au1x_dma_chan_t *)dcp; + cp = (au1x_dma_chan_t *)dcp; + ctp->chan_src = stp; + ctp->chan_dest = dtp; + ctp->chan_callback = callback; + ctp->chan_callparam = callparam; + + /* Initialize channel configuration. */ + i = 0; + if (stp->dev_intlevel) + i |= DDMA_CFG_SED; + if (stp->dev_intpolarity) + i |= DDMA_CFG_SP; + if (dtp->dev_intlevel) + i |= DDMA_CFG_DED; + if (dtp->dev_intpolarity) + i |= DDMA_CFG_DP; + if ((stp->dev_flags & DEV_FLAGS_SYNC) || + (dtp->dev_flags & DEV_FLAGS_SYNC)) + i |= DDMA_CFG_SYNC; + cp->ddma_cfg = i; + au_sync(); + + /* Return a non-zero value that can be used to + * find the channel information in subsequent + * operations. + */ + rv = (u32)(&chan_tab_ptr[chan]); + } else { + /* Release devices */ + stp->dev_flags &= ~DEV_FLAGS_INUSE; + dtp->dev_flags &= ~DEV_FLAGS_INUSE; + } + } + return rv; +} +EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); + +/* + * Set the device width if source or destination is a FIFO. + * Should be 8, 16, or 32 bits. + */ +u32 au1xxx_dbdma_set_devwidth(u32 chanid, int bits) +{ + u32 rv; + chan_tab_t *ctp; + dbdev_tab_t *stp, *dtp; + + ctp = *((chan_tab_t **)chanid); + stp = ctp->chan_src; + dtp = ctp->chan_dest; + rv = 0; + + if (stp->dev_flags & DEV_FLAGS_IN) { /* Source in fifo */ + rv = stp->dev_devwidth; + stp->dev_devwidth = bits; + } + if (dtp->dev_flags & DEV_FLAGS_OUT) { /* Destination out fifo */ + rv = dtp->dev_devwidth; + dtp->dev_devwidth = bits; + } + + return rv; +} +EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth); + +/* Allocate a descriptor ring, initializing as much as possible. */ +u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries) +{ + int i; + u32 desc_base, srcid, destid; + u32 cmd0, cmd1, src1, dest1; + u32 src0, dest0; + chan_tab_t *ctp; + dbdev_tab_t *stp, *dtp; + au1x_ddma_desc_t *dp; + + /* + * I guess we could check this to be within the + * range of the table...... + */ + ctp = *((chan_tab_t **)chanid); + stp = ctp->chan_src; + dtp = ctp->chan_dest; + + /* + * The descriptors must be 32-byte aligned. There is a + * possibility the allocation will give us such an address, + * and if we try that first we are likely to not waste larger + * slabs of memory. + */ + desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), + GFP_KERNEL|GFP_DMA); + if (desc_base == 0) + return 0; + + if (desc_base & 0x1f) { + /* + * Lost....do it again, allocate extra, and round + * the address base. + */ + kfree((const void *)desc_base); + i = entries * sizeof(au1x_ddma_desc_t); + i += (sizeof(au1x_ddma_desc_t) - 1); + desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA); + if (desc_base == 0) + return 0; + + desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); + } + dp = (au1x_ddma_desc_t *)desc_base; + + /* Keep track of the base descriptor. */ + ctp->chan_desc_base = dp; + + /* Initialize the rings with as much information as we know. */ + srcid = stp->dev_id; + destid = dtp->dev_id; + + cmd0 = cmd1 = src1 = dest1 = 0; + src0 = dest0 = 0; + + cmd0 |= DSCR_CMD0_SID(srcid); + cmd0 |= DSCR_CMD0_DID(destid); + cmd0 |= DSCR_CMD0_IE | DSCR_CMD0_CV; + cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_NOCHANGE); + + /* Is it mem to mem transfer? */ + if (((DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_THROTTLE) || + (DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_ALWAYS)) && + ((DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_THROTTLE) || + (DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_ALWAYS))) + cmd0 |= DSCR_CMD0_MEM; + + switch (stp->dev_devwidth) { + case 8: + cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_BYTE); + break; + case 16: + cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_HALFWORD); + break; + case 32: + default: + cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_WORD); + break; + } + + switch (dtp->dev_devwidth) { + case 8: + cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_BYTE); + break; + case 16: + cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_HALFWORD); + break; + case 32: + default: + cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_WORD); + break; + } + + /* + * If the device is marked as an in/out FIFO, ensure it is + * set non-coherent. + */ + if (stp->dev_flags & DEV_FLAGS_IN) + cmd0 |= DSCR_CMD0_SN; /* Source in FIFO */ + if (dtp->dev_flags & DEV_FLAGS_OUT) + cmd0 |= DSCR_CMD0_DN; /* Destination out FIFO */ + + /* + * Set up source1. For now, assume no stride and increment. + * A channel attribute update can change this later. + */ + switch (stp->dev_tsize) { + case 1: + src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE1); + break; + case 2: + src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE2); + break; + case 4: + src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE4); + break; + case 8: + default: + src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE8); + break; + } + + /* If source input is FIFO, set static address. */ + if (stp->dev_flags & DEV_FLAGS_IN) { + if (stp->dev_flags & DEV_FLAGS_BURSTABLE) + src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST); + else + src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); + } + + if (stp->dev_physaddr) + src0 = stp->dev_physaddr; + + /* + * Set up dest1. For now, assume no stride and increment. + * A channel attribute update can change this later. + */ + switch (dtp->dev_tsize) { + case 1: + dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE1); + break; + case 2: + dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE2); + break; + case 4: + dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE4); + break; + case 8: + default: + dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE8); + break; + } + + /* If destination output is FIFO, set static address. */ + if (dtp->dev_flags & DEV_FLAGS_OUT) { + if (dtp->dev_flags & DEV_FLAGS_BURSTABLE) + dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST); + else + dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); + } + + if (dtp->dev_physaddr) + dest0 = dtp->dev_physaddr; + +#if 0 + printk(KERN_DEBUG "did:%x sid:%x cmd0:%x cmd1:%x source0:%x " + "source1:%x dest0:%x dest1:%x\n", + dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, + src1, dest0, dest1); +#endif + for (i = 0; i < entries; i++) { + dp->dscr_cmd0 = cmd0; + dp->dscr_cmd1 = cmd1; + dp->dscr_source0 = src0; + dp->dscr_source1 = src1; + dp->dscr_dest0 = dest0; + dp->dscr_dest1 = dest1; + dp->dscr_stat = 0; + dp->sw_context = 0; + dp->sw_status = 0; + dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); + dp++; + } + + /* Make last descrptor point to the first. */ + dp--; + dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(ctp->chan_desc_base)); + ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base; + + return (u32)ctp->chan_desc_base; +} +EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc); + +/* + * Put a source buffer into the DMA ring. + * This updates the source pointer and byte count. Normally used + * for memory to fifo transfers. + */ +u32 _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags) +{ + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + + /* + * I guess we could check this to be within the + * range of the table...... + */ + ctp = *(chan_tab_t **)chanid; + + /* + * We should have multiple callers for a particular channel, + * an interrupt doesn't affect this pointer nor the descriptor, + * so no locking should be needed. + */ + dp = ctp->put_ptr; + + /* + * If the descriptor is valid, we are way ahead of the DMA + * engine, so just return an error condition. + */ + if (dp->dscr_cmd0 & DSCR_CMD0_V) + return 0; + + /* Load up buffer address and byte count. */ + dp->dscr_source0 = virt_to_phys(buf); + dp->dscr_cmd1 = nbytes; + /* Check flags */ + if (flags & DDMA_FLAGS_IE) + dp->dscr_cmd0 |= DSCR_CMD0_IE; + if (flags & DDMA_FLAGS_NOIE) + dp->dscr_cmd0 &= ~DSCR_CMD0_IE; + + /* + * There is an errata on the Au1200/Au1550 parts that could result + * in "stale" data being DMA'ed. It has to do with the snoop logic on + * the cache eviction buffer. DMA_NONCOHERENT is on by default for + * these parts. If it is fixed in the future, these dma_cache_inv will + * just be nothing more than empty macros. See io.h. + */ + dma_cache_wback_inv((unsigned long)buf, nbytes); + dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ + au_sync(); + dma_cache_wback_inv((unsigned long)dp, sizeof(dp)); + ctp->chan_ptr->ddma_dbell = 0; + + /* Get next descriptor pointer. */ + ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + + /* Return something non-zero. */ + return nbytes; +} +EXPORT_SYMBOL(_au1xxx_dbdma_put_source); + +/* Put a destination buffer into the DMA ring. + * This updates the destination pointer and byte count. Normally used + * to place an empty buffer into the ring for fifo to memory transfers. + */ +u32 +_au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags) +{ + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + + /* I guess we could check this to be within the + * range of the table...... + */ + ctp = *((chan_tab_t **)chanid); + + /* We should have multiple callers for a particular channel, + * an interrupt doesn't affect this pointer nor the descriptor, + * so no locking should be needed. + */ + dp = ctp->put_ptr; + + /* If the descriptor is valid, we are way ahead of the DMA + * engine, so just return an error condition. + */ + if (dp->dscr_cmd0 & DSCR_CMD0_V) + return 0; + + /* Load up buffer address and byte count */ + + /* Check flags */ + if (flags & DDMA_FLAGS_IE) + dp->dscr_cmd0 |= DSCR_CMD0_IE; + if (flags & DDMA_FLAGS_NOIE) + dp->dscr_cmd0 &= ~DSCR_CMD0_IE; + + dp->dscr_dest0 = virt_to_phys(buf); + dp->dscr_cmd1 = nbytes; +#if 0 + printk(KERN_DEBUG "cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", + dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0, + dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); +#endif + /* + * There is an errata on the Au1200/Au1550 parts that could result in + * "stale" data being DMA'ed. It has to do with the snoop logic on the + * cache eviction buffer. DMA_NONCOHERENT is on by default for these + * parts. If it is fixed in the future, these dma_cache_inv will just + * be nothing more than empty macros. See io.h. + */ + dma_cache_inv((unsigned long)buf, nbytes); + dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ + au_sync(); + dma_cache_wback_inv((unsigned long)dp, sizeof(dp)); + ctp->chan_ptr->ddma_dbell = 0; + + /* Get next descriptor pointer. */ + ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + + /* Return something non-zero. */ + return nbytes; +} +EXPORT_SYMBOL(_au1xxx_dbdma_put_dest); + +/* + * Get a destination buffer into the DMA ring. + * Normally used to get a full buffer from the ring during fifo + * to memory transfers. This does not set the valid bit, you will + * have to put another destination buffer to keep the DMA going. + */ +u32 au1xxx_dbdma_get_dest(u32 chanid, void **buf, int *nbytes) +{ + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + u32 rv; + + /* + * I guess we could check this to be within the + * range of the table...... + */ + ctp = *((chan_tab_t **)chanid); + + /* + * We should have multiple callers for a particular channel, + * an interrupt doesn't affect this pointer nor the descriptor, + * so no locking should be needed. + */ + dp = ctp->get_ptr; + + /* + * If the descriptor is valid, we are way ahead of the DMA + * engine, so just return an error condition. + */ + if (dp->dscr_cmd0 & DSCR_CMD0_V) + return 0; + + /* Return buffer address and byte count. */ + *buf = (void *)(phys_to_virt(dp->dscr_dest0)); + *nbytes = dp->dscr_cmd1; + rv = dp->dscr_stat; + + /* Get next descriptor pointer. */ + ctp->get_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + + /* Return something non-zero. */ + return rv; +} +EXPORT_SYMBOL_GPL(au1xxx_dbdma_get_dest); + +void au1xxx_dbdma_stop(u32 chanid) +{ + chan_tab_t *ctp; + au1x_dma_chan_t *cp; + int halt_timeout = 0; + + ctp = *((chan_tab_t **)chanid); + + cp = ctp->chan_ptr; + cp->ddma_cfg &= ~DDMA_CFG_EN; /* Disable channel */ + au_sync(); + while (!(cp->ddma_stat & DDMA_STAT_H)) { + udelay(1); + halt_timeout++; + if (halt_timeout > 100) { + printk(KERN_WARNING "warning: DMA channel won't halt\n"); + break; + } + } + /* clear current desc valid and doorbell */ + cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); + au_sync(); +} +EXPORT_SYMBOL(au1xxx_dbdma_stop); + +/* + * Start using the current descriptor pointer. If the DBDMA encounters + * a non-valid descriptor, it will stop. In this case, we can just + * continue by adding a buffer to the list and starting again. + */ +void au1xxx_dbdma_start(u32 chanid) +{ + chan_tab_t *ctp; + au1x_dma_chan_t *cp; + + ctp = *((chan_tab_t **)chanid); + cp = ctp->chan_ptr; + cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); + cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ + au_sync(); + cp->ddma_dbell = 0; + au_sync(); +} +EXPORT_SYMBOL(au1xxx_dbdma_start); + +void au1xxx_dbdma_reset(u32 chanid) +{ + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + + au1xxx_dbdma_stop(chanid); + + ctp = *((chan_tab_t **)chanid); + ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base; + + /* Run through the descriptors and reset the valid indicator. */ + dp = ctp->chan_desc_base; + + do { + dp->dscr_cmd0 &= ~DSCR_CMD0_V; + /* + * Reset our software status -- this is used to determine + * if a descriptor is in use by upper level software. Since + * posting can reset 'V' bit. + */ + dp->sw_status = 0; + dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + } while (dp != ctp->chan_desc_base); +} +EXPORT_SYMBOL(au1xxx_dbdma_reset); + +u32 au1xxx_get_dma_residue(u32 chanid) +{ + chan_tab_t *ctp; + au1x_dma_chan_t *cp; + u32 rv; + + ctp = *((chan_tab_t **)chanid); + cp = ctp->chan_ptr; + + /* This is only valid if the channel is stopped. */ + rv = cp->ddma_bytecnt; + au_sync(); + + return rv; +} +EXPORT_SYMBOL_GPL(au1xxx_get_dma_residue); + +void au1xxx_dbdma_chan_free(u32 chanid) +{ + chan_tab_t *ctp; + dbdev_tab_t *stp, *dtp; + + ctp = *((chan_tab_t **)chanid); + stp = ctp->chan_src; + dtp = ctp->chan_dest; + + au1xxx_dbdma_stop(chanid); + + kfree((void *)ctp->chan_desc_base); + + stp->dev_flags &= ~DEV_FLAGS_INUSE; + dtp->dev_flags &= ~DEV_FLAGS_INUSE; + chan_tab_ptr[ctp->chan_index] = NULL; + + kfree(ctp); +} +EXPORT_SYMBOL(au1xxx_dbdma_chan_free); + +static irqreturn_t dbdma_interrupt(int irq, void *dev_id) +{ + u32 intstat; + u32 chan_index; + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + au1x_dma_chan_t *cp; + + intstat = dbdma_gptr->ddma_intstat; + au_sync(); + chan_index = __ffs(intstat); + + ctp = chan_tab_ptr[chan_index]; + cp = ctp->chan_ptr; + dp = ctp->cur_ptr; + + /* Reset interrupt. */ + cp->ddma_irq = 0; + au_sync(); + + if (ctp->chan_callback) + ctp->chan_callback(irq, ctp->chan_callparam); + + ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + return IRQ_RETVAL(1); +} + +static void au1xxx_dbdma_init(void) +{ + int irq_nr; + + dbdma_gptr->ddma_config = 0; + dbdma_gptr->ddma_throttle = 0; + dbdma_gptr->ddma_inten = 0xffff; + au_sync(); + +#if defined(CONFIG_SOC_AU1550) + irq_nr = AU1550_DDMA_INT; +#elif defined(CONFIG_SOC_AU1200) + irq_nr = AU1200_DDMA_INT; +#else + #error Unknown Au1x00 SOC +#endif + + if (request_irq(irq_nr, dbdma_interrupt, IRQF_DISABLED, + "Au1xxx dbdma", (void *)dbdma_gptr)) + printk(KERN_ERR "Can't get 1550 dbdma irq"); +} + +void au1xxx_dbdma_dump(u32 chanid) +{ + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + dbdev_tab_t *stp, *dtp; + au1x_dma_chan_t *cp; + u32 i = 0; + + ctp = *((chan_tab_t **)chanid); + stp = ctp->chan_src; + dtp = ctp->chan_dest; + cp = ctp->chan_ptr; + + printk(KERN_DEBUG "Chan %x, stp %x (dev %d) dtp %x (dev %d) \n", + (u32)ctp, (u32)stp, stp - dbdev_tab, (u32)dtp, + dtp - dbdev_tab); + printk(KERN_DEBUG "desc base %x, get %x, put %x, cur %x\n", + (u32)(ctp->chan_desc_base), (u32)(ctp->get_ptr), + (u32)(ctp->put_ptr), (u32)(ctp->cur_ptr)); + + printk(KERN_DEBUG "dbdma chan %x\n", (u32)cp); + printk(KERN_DEBUG "cfg %08x, desptr %08x, statptr %08x\n", + cp->ddma_cfg, cp->ddma_desptr, cp->ddma_statptr); + printk(KERN_DEBUG "dbell %08x, irq %08x, stat %08x, bytecnt %08x\n", + cp->ddma_dbell, cp->ddma_irq, cp->ddma_stat, + cp->ddma_bytecnt); + + /* Run through the descriptors */ + dp = ctp->chan_desc_base; + + do { + printk(KERN_DEBUG "Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n", + i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); + printk(KERN_DEBUG "src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n", + dp->dscr_source0, dp->dscr_source1, + dp->dscr_dest0, dp->dscr_dest1); + printk(KERN_DEBUG "stat %08x, nxtptr %08x\n", + dp->dscr_stat, dp->dscr_nxtptr); + dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + } while (dp != ctp->chan_desc_base); +} + +/* Put a descriptor into the DMA ring. + * This updates the source/destination pointers and byte count. + */ +u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr) +{ + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + u32 nbytes = 0; + + /* + * I guess we could check this to be within the + * range of the table...... + */ + ctp = *((chan_tab_t **)chanid); + + /* + * We should have multiple callers for a particular channel, + * an interrupt doesn't affect this pointer nor the descriptor, + * so no locking should be needed. + */ + dp = ctp->put_ptr; + + /* + * If the descriptor is valid, we are way ahead of the DMA + * engine, so just return an error condition. + */ + if (dp->dscr_cmd0 & DSCR_CMD0_V) + return 0; + + /* Load up buffer addresses and byte count. */ + dp->dscr_dest0 = dscr->dscr_dest0; + dp->dscr_source0 = dscr->dscr_source0; + dp->dscr_dest1 = dscr->dscr_dest1; + dp->dscr_source1 = dscr->dscr_source1; + dp->dscr_cmd1 = dscr->dscr_cmd1; + nbytes = dscr->dscr_cmd1; + /* Allow the caller to specifiy if an interrupt is generated */ + dp->dscr_cmd0 &= ~DSCR_CMD0_IE; + dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V; + ctp->chan_ptr->ddma_dbell = 0; + + /* Get next descriptor pointer. */ + ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + + /* Return something non-zero. */ + return nbytes; +} + +#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ diff --git a/arch/mips/alchemy/common/dma.c b/arch/mips/alchemy/common/dma.c new file mode 100644 index 00000000000..d6fbda232e6 --- /dev/null +++ b/arch/mips/alchemy/common/dma.c @@ -0,0 +1,238 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * A DMA channel allocator for Au1x00. API is modeled loosely off of + * linux/kernel/dma.c. + * + * Copyright 2000, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include + +#include +#include + +#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \ + defined(CONFIG_SOC_AU1100) +/* + * A note on resource allocation: + * + * All drivers needing DMA channels, should allocate and release them + * through the public routines `request_dma()' and `free_dma()'. + * + * In order to avoid problems, all processes should allocate resources in + * the same sequence and release them in the reverse order. + * + * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. + * When releasing them, first release the IRQ, then release the DMA. The + * main reason for this order is that, if you are requesting the DMA buffer + * done interrupt, you won't know the irq number until the DMA channel is + * returned from request_dma. + */ + +DEFINE_SPINLOCK(au1000_dma_spin_lock); + +struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = { + {.dev_id = -1,}, + {.dev_id = -1,}, + {.dev_id = -1,}, + {.dev_id = -1,}, + {.dev_id = -1,}, + {.dev_id = -1,}, + {.dev_id = -1,}, + {.dev_id = -1,} +}; +EXPORT_SYMBOL(au1000_dma_table); + +/* Device FIFO addresses and default DMA modes */ +static const struct dma_dev { + unsigned int fifo_addr; + unsigned int dma_mode; +} dma_dev_table[DMA_NUM_DEV] = { + {UART0_ADDR + UART_TX, 0}, + {UART0_ADDR + UART_RX, 0}, + {0, 0}, + {0, 0}, + {AC97C_DATA, DMA_DW16 }, /* coherent */ + {AC97C_DATA, DMA_DR | DMA_DW16 }, /* coherent */ + {UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC}, + {UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC}, + {USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC}, + {USBD_EP0WR, DMA_DW8 | DMA_NC}, + {USBD_EP2WR, DMA_DW8 | DMA_NC}, + {USBD_EP3WR, DMA_DW8 | DMA_NC}, + {USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC}, + {USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC}, + {I2S_DATA, DMA_DW32 | DMA_NC}, + {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC} +}; + +int au1000_dma_read_proc(char *buf, char **start, off_t fpos, + int length, int *eof, void *data) +{ + int i, len = 0; + struct dma_chan *chan; + + for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) { + chan = get_dma_chan(i); + if (chan != NULL) + len += sprintf(buf + len, "%2d: %s\n", + i, chan->dev_str); + } + + if (fpos >= len) { + *start = buf; + *eof = 1; + return 0; + } + *start = buf + fpos; + len -= fpos; + if (len > length) + return length; + *eof = 1; + return len; +} + +/* Device FIFO addresses and default DMA modes - 2nd bank */ +static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = { + { SD0_XMIT_FIFO, DMA_DS | DMA_DW8 }, /* coherent */ + { SD0_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8 }, /* coherent */ + { SD1_XMIT_FIFO, DMA_DS | DMA_DW8 }, /* coherent */ + { SD1_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8 } /* coherent */ +}; + +void dump_au1000_dma_channel(unsigned int dmanr) +{ + struct dma_chan *chan; + + if (dmanr >= NUM_AU1000_DMA_CHANNELS) + return; + chan = &au1000_dma_table[dmanr]; + + printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr); + printk(KERN_INFO " mode = 0x%08x\n", + au_readl(chan->io + DMA_MODE_SET)); + printk(KERN_INFO " addr = 0x%08x\n", + au_readl(chan->io + DMA_PERIPHERAL_ADDR)); + printk(KERN_INFO " start0 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER0_START)); + printk(KERN_INFO " start1 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER1_START)); + printk(KERN_INFO " count0 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER0_COUNT)); + printk(KERN_INFO " count1 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER1_COUNT)); +} + +/* + * Finds a free channel, and binds the requested device to it. + * Returns the allocated channel number, or negative on error. + * Requests the DMA done IRQ if irqhandler != NULL. + */ +int request_au1000_dma(int dev_id, const char *dev_str, + irq_handler_t irqhandler, + unsigned long irqflags, + void *irq_dev_id) +{ + struct dma_chan *chan; + const struct dma_dev *dev; + int i, ret; + +#if defined(CONFIG_SOC_AU1100) + if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2)) + return -EINVAL; +#else + if (dev_id < 0 || dev_id >= DMA_NUM_DEV) + return -EINVAL; +#endif + + for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) + if (au1000_dma_table[i].dev_id < 0) + break; + + if (i == NUM_AU1000_DMA_CHANNELS) + return -ENODEV; + + chan = &au1000_dma_table[i]; + + if (dev_id >= DMA_NUM_DEV) { + dev_id -= DMA_NUM_DEV; + dev = &dma_dev_table_bank2[dev_id]; + } else + dev = &dma_dev_table[dev_id]; + + if (irqhandler) { + chan->irq = AU1000_DMA_INT_BASE + i; + chan->irq_dev = irq_dev_id; + ret = request_irq(chan->irq, irqhandler, irqflags, dev_str, + chan->irq_dev); + if (ret) { + chan->irq = 0; + chan->irq_dev = NULL; + return ret; + } + } else { + chan->irq = 0; + chan->irq_dev = NULL; + } + + /* fill it in */ + chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN; + chan->dev_id = dev_id; + chan->dev_str = dev_str; + chan->fifo_addr = dev->fifo_addr; + chan->mode = dev->dma_mode; + + /* initialize the channel before returning */ + init_dma(i); + + return i; +} +EXPORT_SYMBOL(request_au1000_dma); + +void free_au1000_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) { + printk(KERN_ERR "Error trying to free DMA%d\n", dmanr); + return; + } + + disable_dma(dmanr); + if (chan->irq) + free_irq(chan->irq, chan->irq_dev); + + chan->irq = 0; + chan->irq_dev = NULL; + chan->dev_id = -1; +} +EXPORT_SYMBOL(free_au1000_dma); + +#endif /* AU1000 AU1500 AU1100 */ diff --git a/arch/mips/alchemy/common/gpio.c b/arch/mips/alchemy/common/gpio.c new file mode 100644 index 00000000000..e660ddd611c --- /dev/null +++ b/arch/mips/alchemy/common/gpio.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2007, OpenWrt.org, Florian Fainelli + * Architecture specific GPIO support + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Notes : + * au1000 SoC have only one GPIO line : GPIO1 + * others have a second one : GPIO2 + */ + +#include + +#include +#include + +#define gpio1 sys +#if !defined(CONFIG_SOC_AU1000) + +static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE; +#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000 + +static int au1xxx_gpio2_read(unsigned gpio) +{ + gpio -= AU1XXX_GPIO_BASE; + return ((gpio2->pinstate >> gpio) & 0x01); +} + +static void au1xxx_gpio2_write(unsigned gpio, int value) +{ + gpio -= AU1XXX_GPIO_BASE; + + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); +} + +static int au1xxx_gpio2_direction_input(unsigned gpio) +{ + gpio -= AU1XXX_GPIO_BASE; + gpio2->dir &= ~(0x01 << gpio); + return 0; +} + +static int au1xxx_gpio2_direction_output(unsigned gpio, int value) +{ + gpio -= AU1XXX_GPIO_BASE; + gpio2->dir |= 0x01 << gpio; + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); + return 0; +} + +#endif /* !defined(CONFIG_SOC_AU1000) */ + +static int au1xxx_gpio1_read(unsigned gpio) +{ + return (gpio1->pinstaterd >> gpio) & 0x01; +} + +static void au1xxx_gpio1_write(unsigned gpio, int value) +{ + if (value) + gpio1->outputset = (0x01 << gpio); + else + /* Output a zero */ + gpio1->outputclr = (0x01 << gpio); +} + +static int au1xxx_gpio1_direction_input(unsigned gpio) +{ + gpio1->pininputen = (0x01 << gpio); + return 0; +} + +static int au1xxx_gpio1_direction_output(unsigned gpio, int value) +{ + gpio1->trioutclr = (0x01 & gpio); + au1xxx_gpio1_write(gpio, value); + return 0; +} + +int au1xxx_gpio_get_value(unsigned gpio) +{ + if (gpio >= AU1XXX_GPIO_BASE) +#if defined(CONFIG_SOC_AU1000) + return 0; +#else + return au1xxx_gpio2_read(gpio); +#endif + else + return au1xxx_gpio1_read(gpio); +} +EXPORT_SYMBOL(au1xxx_gpio_get_value); + +void au1xxx_gpio_set_value(unsigned gpio, int value) +{ + if (gpio >= AU1XXX_GPIO_BASE) +#if defined(CONFIG_SOC_AU1000) + ; +#else + au1xxx_gpio2_write(gpio, value); +#endif + else + au1xxx_gpio1_write(gpio, value); +} +EXPORT_SYMBOL(au1xxx_gpio_set_value); + +int au1xxx_gpio_direction_input(unsigned gpio) +{ + if (gpio >= AU1XXX_GPIO_BASE) +#if defined(CONFIG_SOC_AU1000) + return -ENODEV; +#else + return au1xxx_gpio2_direction_input(gpio); +#endif + + return au1xxx_gpio1_direction_input(gpio); +} +EXPORT_SYMBOL(au1xxx_gpio_direction_input); + +int au1xxx_gpio_direction_output(unsigned gpio, int value) +{ + if (gpio >= AU1XXX_GPIO_BASE) +#if defined(CONFIG_SOC_AU1000) + return -ENODEV; +#else + return au1xxx_gpio2_direction_output(gpio, value); +#endif + + return au1xxx_gpio1_direction_output(gpio, value); +} +EXPORT_SYMBOL(au1xxx_gpio_direction_output); diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c new file mode 100644 index 00000000000..40c6ceceb5f --- /dev/null +++ b/arch/mips/alchemy/common/irq.c @@ -0,0 +1,596 @@ +/* + * Copyright 2001, 2007-2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_MIPS_PB1000 +#include +#endif + +#define EXT_INTC0_REQ0 2 /* IP 2 */ +#define EXT_INTC0_REQ1 3 /* IP 3 */ +#define EXT_INTC1_REQ0 4 /* IP 4 */ +#define EXT_INTC1_REQ1 5 /* IP 5 */ +#define MIPS_TIMER_IP 7 /* IP 7 */ + +void (*board_init_irq)(void) __initdata = NULL; + +static DEFINE_SPINLOCK(irq_lock); + +#ifdef CONFIG_PM + +/* + * Save/restore the interrupt controller state. + * Called from the save/restore core registers as part of the + * au_sleep function in power.c.....maybe I should just pm_register() + * them instead? + */ +static unsigned int sleep_intctl_config0[2]; +static unsigned int sleep_intctl_config1[2]; +static unsigned int sleep_intctl_config2[2]; +static unsigned int sleep_intctl_src[2]; +static unsigned int sleep_intctl_assign[2]; +static unsigned int sleep_intctl_wake[2]; +static unsigned int sleep_intctl_mask[2]; + +void save_au1xxx_intctl(void) +{ + sleep_intctl_config0[0] = au_readl(IC0_CFG0RD); + sleep_intctl_config1[0] = au_readl(IC0_CFG1RD); + sleep_intctl_config2[0] = au_readl(IC0_CFG2RD); + sleep_intctl_src[0] = au_readl(IC0_SRCRD); + sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD); + sleep_intctl_wake[0] = au_readl(IC0_WAKERD); + sleep_intctl_mask[0] = au_readl(IC0_MASKRD); + + sleep_intctl_config0[1] = au_readl(IC1_CFG0RD); + sleep_intctl_config1[1] = au_readl(IC1_CFG1RD); + sleep_intctl_config2[1] = au_readl(IC1_CFG2RD); + sleep_intctl_src[1] = au_readl(IC1_SRCRD); + sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD); + sleep_intctl_wake[1] = au_readl(IC1_WAKERD); + sleep_intctl_mask[1] = au_readl(IC1_MASKRD); +} + +/* + * For most restore operations, we clear the entire register and + * then set the bits we found during the save. + */ +void restore_au1xxx_intctl(void) +{ + au_writel(0xffffffff, IC0_MASKCLR); au_sync(); + + au_writel(0xffffffff, IC0_CFG0CLR); au_sync(); + au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync(); + au_writel(0xffffffff, IC0_CFG1CLR); au_sync(); + au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync(); + au_writel(0xffffffff, IC0_CFG2CLR); au_sync(); + au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync(); + au_writel(0xffffffff, IC0_SRCCLR); au_sync(); + au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync(); + au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync(); + au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync(); + au_writel(0xffffffff, IC0_WAKECLR); au_sync(); + au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync(); + au_writel(0xffffffff, IC0_RISINGCLR); au_sync(); + au_writel(0xffffffff, IC0_FALLINGCLR); au_sync(); + au_writel(0x00000000, IC0_TESTBIT); au_sync(); + + au_writel(0xffffffff, IC1_MASKCLR); au_sync(); + + au_writel(0xffffffff, IC1_CFG0CLR); au_sync(); + au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync(); + au_writel(0xffffffff, IC1_CFG1CLR); au_sync(); + au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync(); + au_writel(0xffffffff, IC1_CFG2CLR); au_sync(); + au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync(); + au_writel(0xffffffff, IC1_SRCCLR); au_sync(); + au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync(); + au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync(); + au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync(); + au_writel(0xffffffff, IC1_WAKECLR); au_sync(); + au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync(); + au_writel(0xffffffff, IC1_RISINGCLR); au_sync(); + au_writel(0xffffffff, IC1_FALLINGCLR); au_sync(); + au_writel(0x00000000, IC1_TESTBIT); au_sync(); + + au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync(); + + au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync(); +} +#endif /* CONFIG_PM */ + + +inline void local_enable_irq(unsigned int irq_nr) +{ + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; + + if (bit >= 32) { + au_writel(1 << (bit - 32), IC1_MASKSET); + au_writel(1 << (bit - 32), IC1_WAKESET); + } else { + au_writel(1 << bit, IC0_MASKSET); + au_writel(1 << bit, IC0_WAKESET); + } + au_sync(); +} + + +inline void local_disable_irq(unsigned int irq_nr) +{ + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; + + if (bit >= 32) { + au_writel(1 << (bit - 32), IC1_MASKCLR); + au_writel(1 << (bit - 32), IC1_WAKECLR); + } else { + au_writel(1 << bit, IC0_MASKCLR); + au_writel(1 << bit, IC0_WAKECLR); + } + au_sync(); +} + + +static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr) +{ + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; + + if (bit >= 32) { + au_writel(1 << (bit - 32), IC1_RISINGCLR); + au_writel(1 << (bit - 32), IC1_MASKCLR); + } else { + au_writel(1 << bit, IC0_RISINGCLR); + au_writel(1 << bit, IC0_MASKCLR); + } + au_sync(); +} + + +static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr) +{ + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; + + if (bit >= 32) { + au_writel(1 << (bit - 32), IC1_FALLINGCLR); + au_writel(1 << (bit - 32), IC1_MASKCLR); + } else { + au_writel(1 << bit, IC0_FALLINGCLR); + au_writel(1 << bit, IC0_MASKCLR); + } + au_sync(); +} + + +static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr) +{ + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; + + /* + * This may assume that we don't get interrupts from + * both edges at once, or if we do, that we don't care. + */ + if (bit >= 32) { + au_writel(1 << (bit - 32), IC1_FALLINGCLR); + au_writel(1 << (bit - 32), IC1_RISINGCLR); + au_writel(1 << (bit - 32), IC1_MASKCLR); + } else { + au_writel(1 << bit, IC0_FALLINGCLR); + au_writel(1 << bit, IC0_RISINGCLR); + au_writel(1 << bit, IC0_MASKCLR); + } + au_sync(); +} + +static inline void mask_and_ack_level_irq(unsigned int irq_nr) +{ + local_disable_irq(irq_nr); + au_sync(); +#if defined(CONFIG_MIPS_PB1000) + if (irq_nr == AU1000_GPIO_15) { + au_writel(0x8000, PB1000_MDR); /* ack int */ + au_sync(); + } +#endif +} + +static void end_irq(unsigned int irq_nr) +{ + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + local_enable_irq(irq_nr); + +#if defined(CONFIG_MIPS_PB1000) + if (irq_nr == AU1000_GPIO_15) { + au_writel(0x4000, PB1000_MDR); /* enable int */ + au_sync(); + } +#endif +} + +unsigned long save_local_and_disable(int controller) +{ + int i; + unsigned long flags, mask; + + spin_lock_irqsave(&irq_lock, flags); + if (controller) { + mask = au_readl(IC1_MASKSET); + for (i = 32; i < 64; i++) + local_disable_irq(i); + } else { + mask = au_readl(IC0_MASKSET); + for (i = 0; i < 32; i++) + local_disable_irq(i); + } + spin_unlock_irqrestore(&irq_lock, flags); + + return mask; +} + +void restore_local_and_enable(int controller, unsigned long mask) +{ + int i; + unsigned long flags, new_mask; + + spin_lock_irqsave(&irq_lock, flags); + for (i = 0; i < 32; i++) + if (mask & (1 << i)) { + if (controller) + local_enable_irq(i + 32); + else + local_enable_irq(i); + } + + if (controller) + new_mask = au_readl(IC1_MASKSET); + else + new_mask = au_readl(IC0_MASKSET); + + spin_unlock_irqrestore(&irq_lock, flags); +} + + +static struct irq_chip rise_edge_irq_type = { + .name = "Au1000 Rise Edge", + .ack = mask_and_ack_rise_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_rise_edge_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +static struct irq_chip fall_edge_irq_type = { + .name = "Au1000 Fall Edge", + .ack = mask_and_ack_fall_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_fall_edge_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +static struct irq_chip either_edge_irq_type = { + .name = "Au1000 Rise or Fall Edge", + .ack = mask_and_ack_either_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_either_edge_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +static struct irq_chip level_irq_type = { + .name = "Au1000 Level", + .ack = mask_and_ack_level_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_level_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req) +{ + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; + + if (irq_nr > AU1000_MAX_INTR) + return; + + /* Config2[n], Config1[n], Config0[n] */ + if (bit >= 32) { + switch (type) { + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1 << (bit - 32), IC1_CFG2CLR); + au_writel(1 << (bit - 32), IC1_CFG1CLR); + au_writel(1 << (bit - 32), IC1_CFG0SET); + set_irq_chip(irq_nr, &rise_edge_irq_type); + break; + case INTC_INT_FALL_EDGE: /* 0:1:0 */ + au_writel(1 << (bit - 32), IC1_CFG2CLR); + au_writel(1 << (bit - 32), IC1_CFG1SET); + au_writel(1 << (bit - 32), IC1_CFG0CLR); + set_irq_chip(irq_nr, &fall_edge_irq_type); + break; + case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ + au_writel(1 << (bit - 32), IC1_CFG2CLR); + au_writel(1 << (bit - 32), IC1_CFG1SET); + au_writel(1 << (bit - 32), IC1_CFG0SET); + set_irq_chip(irq_nr, &either_edge_irq_type); + break; + case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ + au_writel(1 << (bit - 32), IC1_CFG2SET); + au_writel(1 << (bit - 32), IC1_CFG1CLR); + au_writel(1 << (bit - 32), IC1_CFG0SET); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_LOW_LEVEL: /* 1:1:0 */ + au_writel(1 << (bit - 32), IC1_CFG2SET); + au_writel(1 << (bit - 32), IC1_CFG1SET); + au_writel(1 << (bit - 32), IC1_CFG0CLR); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_DISABLED: /* 0:0:0 */ + au_writel(1 << (bit - 32), IC1_CFG0CLR); + au_writel(1 << (bit - 32), IC1_CFG1CLR); + au_writel(1 << (bit - 32), IC1_CFG2CLR); + break; + default: /* disable the interrupt */ + printk(KERN_WARNING "unexpected int type %d (irq %d)\n", + type, irq_nr); + au_writel(1 << (bit - 32), IC1_CFG0CLR); + au_writel(1 << (bit - 32), IC1_CFG1CLR); + au_writel(1 << (bit - 32), IC1_CFG2CLR); + return; + } + if (int_req) /* assign to interrupt request 1 */ + au_writel(1 << (bit - 32), IC1_ASSIGNCLR); + else /* assign to interrupt request 0 */ + au_writel(1 << (bit - 32), IC1_ASSIGNSET); + au_writel(1 << (bit - 32), IC1_SRCSET); + au_writel(1 << (bit - 32), IC1_MASKCLR); + au_writel(1 << (bit - 32), IC1_WAKECLR); + } else { + switch (type) { + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1 << bit, IC0_CFG2CLR); + au_writel(1 << bit, IC0_CFG1CLR); + au_writel(1 << bit, IC0_CFG0SET); + set_irq_chip(irq_nr, &rise_edge_irq_type); + break; + case INTC_INT_FALL_EDGE: /* 0:1:0 */ + au_writel(1 << bit, IC0_CFG2CLR); + au_writel(1 << bit, IC0_CFG1SET); + au_writel(1 << bit, IC0_CFG0CLR); + set_irq_chip(irq_nr, &fall_edge_irq_type); + break; + case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ + au_writel(1 << bit, IC0_CFG2CLR); + au_writel(1 << bit, IC0_CFG1SET); + au_writel(1 << bit, IC0_CFG0SET); + set_irq_chip(irq_nr, &either_edge_irq_type); + break; + case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ + au_writel(1 << bit, IC0_CFG2SET); + au_writel(1 << bit, IC0_CFG1CLR); + au_writel(1 << bit, IC0_CFG0SET); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_LOW_LEVEL: /* 1:1:0 */ + au_writel(1 << bit, IC0_CFG2SET); + au_writel(1 << bit, IC0_CFG1SET); + au_writel(1 << bit, IC0_CFG0CLR); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_DISABLED: /* 0:0:0 */ + au_writel(1 << bit, IC0_CFG0CLR); + au_writel(1 << bit, IC0_CFG1CLR); + au_writel(1 << bit, IC0_CFG2CLR); + break; + default: /* disable the interrupt */ + printk(KERN_WARNING "unexpected int type %d (irq %d)\n", + type, irq_nr); + au_writel(1 << bit, IC0_CFG0CLR); + au_writel(1 << bit, IC0_CFG1CLR); + au_writel(1 << bit, IC0_CFG2CLR); + return; + } + if (int_req) /* assign to interrupt request 1 */ + au_writel(1 << bit, IC0_ASSIGNCLR); + else /* assign to interrupt request 0 */ + au_writel(1 << bit, IC0_ASSIGNSET); + au_writel(1 << bit, IC0_SRCSET); + au_writel(1 << bit, IC0_MASKCLR); + au_writel(1 << bit, IC0_WAKECLR); + } + au_sync(); +} + +/* + * Interrupts are nested. Even if an interrupt handler is registered + * as "fast", we might get another interrupt before we return from + * intcX_reqX_irqdispatch(). + */ + +static void intc0_req0_irqdispatch(void) +{ + static unsigned long intc0_req0; + unsigned int bit; + + intc0_req0 |= au_readl(IC0_REQ0INT); + + if (!intc0_req0) + return; + +#ifdef AU1000_USB_DEV_REQ_INT + /* + * Because of the tight timing of SETUP token to reply + * transactions, the USB devices-side packet complete + * interrupt needs the highest priority. + */ + if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) { + intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT); + do_IRQ(AU1000_USB_DEV_REQ_INT); + return; + } +#endif + bit = __ffs(intc0_req0); + intc0_req0 &= ~(1 << bit); + do_IRQ(AU1000_INTC0_INT_BASE + bit); +} + + +static void intc0_req1_irqdispatch(void) +{ + static unsigned long intc0_req1; + unsigned int bit; + + intc0_req1 |= au_readl(IC0_REQ1INT); + + if (!intc0_req1) + return; + + bit = __ffs(intc0_req1); + intc0_req1 &= ~(1 << bit); + do_IRQ(AU1000_INTC0_INT_BASE + bit); +} + + +/* + * Interrupt Controller 1: + * interrupts 32 - 63 + */ +static void intc1_req0_irqdispatch(void) +{ + static unsigned long intc1_req0; + unsigned int bit; + + intc1_req0 |= au_readl(IC1_REQ0INT); + + if (!intc1_req0) + return; + + bit = __ffs(intc1_req0); + intc1_req0 &= ~(1 << bit); + do_IRQ(AU1000_INTC1_INT_BASE + bit); +} + + +static void intc1_req1_irqdispatch(void) +{ + static unsigned long intc1_req1; + unsigned int bit; + + intc1_req1 |= au_readl(IC1_REQ1INT); + + if (!intc1_req1) + return; + + bit = __ffs(intc1_req1); + intc1_req1 &= ~(1 << bit); + do_IRQ(AU1000_INTC1_INT_BASE + bit); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause(); + + if (pending & CAUSEF_IP7) + do_IRQ(MIPS_CPU_IRQ_BASE + 7); + else if (pending & CAUSEF_IP2) + intc0_req0_irqdispatch(); + else if (pending & CAUSEF_IP3) + intc0_req1_irqdispatch(); + else if (pending & CAUSEF_IP4) + intc1_req0_irqdispatch(); + else if (pending & CAUSEF_IP5) + intc1_req1_irqdispatch(); + else + spurious_interrupt(); +} + +void __init arch_init_irq(void) +{ + int i; + struct au1xxx_irqmap *imp; + extern struct au1xxx_irqmap au1xxx_irq_map[]; + extern struct au1xxx_irqmap au1xxx_ic0_map[]; + extern int au1xxx_nr_irqs; + extern int au1xxx_ic0_nr_irqs; + + /* + * Initialize interrupt controllers to a safe state. + */ + au_writel(0xffffffff, IC0_CFG0CLR); + au_writel(0xffffffff, IC0_CFG1CLR); + au_writel(0xffffffff, IC0_CFG2CLR); + au_writel(0xffffffff, IC0_MASKCLR); + au_writel(0xffffffff, IC0_ASSIGNSET); + au_writel(0xffffffff, IC0_WAKECLR); + au_writel(0xffffffff, IC0_SRCSET); + au_writel(0xffffffff, IC0_FALLINGCLR); + au_writel(0xffffffff, IC0_RISINGCLR); + au_writel(0x00000000, IC0_TESTBIT); + + au_writel(0xffffffff, IC1_CFG0CLR); + au_writel(0xffffffff, IC1_CFG1CLR); + au_writel(0xffffffff, IC1_CFG2CLR); + au_writel(0xffffffff, IC1_MASKCLR); + au_writel(0xffffffff, IC1_ASSIGNSET); + au_writel(0xffffffff, IC1_WAKECLR); + au_writel(0xffffffff, IC1_SRCSET); + au_writel(0xffffffff, IC1_FALLINGCLR); + au_writel(0xffffffff, IC1_RISINGCLR); + au_writel(0x00000000, IC1_TESTBIT); + + mips_cpu_irq_init(); + + /* + * Initialize IC0, which is fixed per processor. + */ + imp = au1xxx_ic0_map; + for (i = 0; i < au1xxx_ic0_nr_irqs; i++) { + setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); + imp++; + } + + /* + * Now set up the irq mapping for the board. + */ + imp = au1xxx_irq_map; + for (i = 0; i < au1xxx_nr_irqs; i++) { + setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); + imp++; + } + + set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); + + /* Board specific IRQ initialization. + */ + if (board_init_irq) + board_init_irq(); +} diff --git a/arch/mips/alchemy/common/pci.c b/arch/mips/alchemy/common/pci.c new file mode 100644 index 00000000000..7866cf50cf9 --- /dev/null +++ b/arch/mips/alchemy/common/pci.c @@ -0,0 +1,104 @@ +/* + * BRIEF MODULE DESCRIPTION + * Alchemy/AMD Au1x00 PCI support. + * + * Copyright 2001-2003, 2007-2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * + * Support for all devices (greater than 16) added by David Gathright. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include + +/* TBD */ +static struct resource pci_io_resource = { + .start = PCI_IO_START, + .end = PCI_IO_END, + .name = "PCI IO space", + .flags = IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + .start = PCI_MEM_START, + .end = PCI_MEM_END, + .name = "PCI memory space", + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops au1x_pci_ops; + +static struct pci_controller au1x_controller = { + .pci_ops = &au1x_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, +}; + +#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550) +static unsigned long virt_io_addr; +#endif + +static int __init au1x_pci_setup(void) +{ + extern void au1x_pci_cfg_init(void); + +#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550) + virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START, + Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1); + + if (!virt_io_addr) { + printk(KERN_ERR "Unable to ioremap pci space\n"); + return 1; + } + au1x_controller.io_map_base = virt_io_addr; + +#ifdef CONFIG_DMA_NONCOHERENT + { + /* + * Set the NC bit in controller for Au1500 pre-AC silicon + */ + u32 prid = read_c0_prid(); + + if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) { + au_writel((1 << 16) | au_readl(Au1500_PCI_CFG), + Au1500_PCI_CFG); + printk(KERN_INFO "Non-coherent PCI accesses enabled\n"); + } + } +#endif + + set_io_port_base(virt_io_addr); +#endif + + au1x_pci_cfg_init(); + + register_pci_controller(&au1x_controller); + return 0; +} + +arch_initcall(au1x_pci_setup); diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c new file mode 100644 index 00000000000..dc8a67efac2 --- /dev/null +++ b/arch/mips/alchemy/common/platform.c @@ -0,0 +1,319 @@ +/* + * Platform device support for Au1x00 SoCs. + * + * Copyright 2004, Matt Porter + * + * (C) Copyright Embedded Alley Solutions, Inc 2005 + * Author: Pantelis Antoniou + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +#include + +#define PORT(_base, _irq) \ + { \ + .iobase = _base, \ + .membase = (void __iomem *)_base,\ + .mapbase = CPHYSADDR(_base), \ + .irq = _irq, \ + .regshift = 2, \ + .iotype = UPIO_AU, \ + .flags = UPF_SKIP_TEST \ + } + +static struct plat_serial8250_port au1x00_uart_data[] = { +#if defined(CONFIG_SERIAL_8250_AU1X00) +#if defined(CONFIG_SOC_AU1000) + PORT(UART0_ADDR, AU1000_UART0_INT), + PORT(UART1_ADDR, AU1000_UART1_INT), + PORT(UART2_ADDR, AU1000_UART2_INT), + PORT(UART3_ADDR, AU1000_UART3_INT), +#elif defined(CONFIG_SOC_AU1500) + PORT(UART0_ADDR, AU1500_UART0_INT), + PORT(UART3_ADDR, AU1500_UART3_INT), +#elif defined(CONFIG_SOC_AU1100) + PORT(UART0_ADDR, AU1100_UART0_INT), + PORT(UART1_ADDR, AU1100_UART1_INT), + PORT(UART3_ADDR, AU1100_UART3_INT), +#elif defined(CONFIG_SOC_AU1550) + PORT(UART0_ADDR, AU1550_UART0_INT), + PORT(UART1_ADDR, AU1550_UART1_INT), + PORT(UART3_ADDR, AU1550_UART3_INT), +#elif defined(CONFIG_SOC_AU1200) + PORT(UART0_ADDR, AU1200_UART0_INT), + PORT(UART1_ADDR, AU1200_UART1_INT), +#endif +#endif /* CONFIG_SERIAL_8250_AU1X00 */ + { }, +}; + +static struct platform_device au1xx0_uart_device = { + .name = "serial8250", + .id = PLAT8250_DEV_AU1X00, + .dev = { + .platform_data = au1x00_uart_data, + }, +}; + +/* OHCI (USB full speed host controller) */ +static struct resource au1xxx_usb_ohci_resources[] = { + [0] = { + .start = USB_OHCI_BASE, + .end = USB_OHCI_BASE + USB_OHCI_LEN - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AU1000_USB_HOST_INT, + .end = AU1000_USB_HOST_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +/* The dmamask must be set for OHCI to work */ +static u64 ohci_dmamask = DMA_32BIT_MASK; + +static struct platform_device au1xxx_usb_ohci_device = { + .name = "au1xxx-ohci", + .id = 0, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(au1xxx_usb_ohci_resources), + .resource = au1xxx_usb_ohci_resources, +}; + +/*** AU1100 LCD controller ***/ + +#ifdef CONFIG_FB_AU1100 +static struct resource au1100_lcd_resources[] = { + [0] = { + .start = LCD_PHYS_ADDR, + .end = LCD_PHYS_ADDR + 0x800 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AU1100_LCD_INT, + .end = AU1100_LCD_INT, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 au1100_lcd_dmamask = DMA_32BIT_MASK; + +static struct platform_device au1100_lcd_device = { + .name = "au1100-lcd", + .id = 0, + .dev = { + .dma_mask = &au1100_lcd_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(au1100_lcd_resources), + .resource = au1100_lcd_resources, +}; +#endif + +#ifdef CONFIG_SOC_AU1200 +/* EHCI (USB high speed host controller) */ +static struct resource au1xxx_usb_ehci_resources[] = { + [0] = { + .start = USB_EHCI_BASE, + .end = USB_EHCI_BASE + USB_EHCI_LEN - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AU1000_USB_HOST_INT, + .end = AU1000_USB_HOST_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ehci_dmamask = DMA_32BIT_MASK; + +static struct platform_device au1xxx_usb_ehci_device = { + .name = "au1xxx-ehci", + .id = 0, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(au1xxx_usb_ehci_resources), + .resource = au1xxx_usb_ehci_resources, +}; + +/* Au1200 UDC (USB gadget controller) */ +static struct resource au1xxx_usb_gdt_resources[] = { + [0] = { + .start = USB_UDC_BASE, + .end = USB_UDC_BASE + USB_UDC_LEN - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AU1200_USB_INT, + .end = AU1200_USB_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource au1xxx_mmc_resources[] = { + [0] = { + .start = SD0_PHYS_ADDR, + .end = SD0_PHYS_ADDR + 0x7ffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = SD1_PHYS_ADDR, + .end = SD1_PHYS_ADDR + 0x7ffff, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = AU1200_SD_INT, + .end = AU1200_SD_INT, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 udc_dmamask = DMA_32BIT_MASK; + +static struct platform_device au1xxx_usb_gdt_device = { + .name = "au1xxx-udc", + .id = 0, + .dev = { + .dma_mask = &udc_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(au1xxx_usb_gdt_resources), + .resource = au1xxx_usb_gdt_resources, +}; + +/* Au1200 UOC (USB OTG controller) */ +static struct resource au1xxx_usb_otg_resources[] = { + [0] = { + .start = USB_UOC_BASE, + .end = USB_UOC_BASE + USB_UOC_LEN - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AU1200_USB_INT, + .end = AU1200_USB_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 uoc_dmamask = DMA_32BIT_MASK; + +static struct platform_device au1xxx_usb_otg_device = { + .name = "au1xxx-uoc", + .id = 0, + .dev = { + .dma_mask = &uoc_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(au1xxx_usb_otg_resources), + .resource = au1xxx_usb_otg_resources, +}; + +static struct resource au1200_lcd_resources[] = { + [0] = { + .start = LCD_PHYS_ADDR, + .end = LCD_PHYS_ADDR + 0x800 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AU1200_LCD_INT, + .end = AU1200_LCD_INT, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 au1200_lcd_dmamask = DMA_32BIT_MASK; + +static struct platform_device au1200_lcd_device = { + .name = "au1200-lcd", + .id = 0, + .dev = { + .dma_mask = &au1200_lcd_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(au1200_lcd_resources), + .resource = au1200_lcd_resources, +}; + +static u64 au1xxx_mmc_dmamask = DMA_32BIT_MASK; + +static struct platform_device au1xxx_mmc_device = { + .name = "au1xxx-mmc", + .id = 0, + .dev = { + .dma_mask = &au1xxx_mmc_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(au1xxx_mmc_resources), + .resource = au1xxx_mmc_resources, +}; +#endif /* #ifdef CONFIG_SOC_AU1200 */ + +static struct platform_device au1x00_pcmcia_device = { + .name = "au1x00-pcmcia", + .id = 0, +}; + +/* All Alchemy demoboards with I2C have this #define in their headers */ +#ifdef SMBUS_PSC_BASE +static struct resource pbdb_smbus_resources[] = { + { + .start = CPHYSADDR(SMBUS_PSC_BASE), + .end = CPHYSADDR(SMBUS_PSC_BASE + 0xfffff), + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device pbdb_smbus_device = { + .name = "au1xpsc_smbus", + .id = 0, /* bus number */ + .num_resources = ARRAY_SIZE(pbdb_smbus_resources), + .resource = pbdb_smbus_resources, +}; +#endif + +static struct platform_device *au1xxx_platform_devices[] __initdata = { + &au1xx0_uart_device, + &au1xxx_usb_ohci_device, + &au1x00_pcmcia_device, +#ifdef CONFIG_FB_AU1100 + &au1100_lcd_device, +#endif +#ifdef CONFIG_SOC_AU1200 + &au1xxx_usb_ehci_device, + &au1xxx_usb_gdt_device, + &au1xxx_usb_otg_device, + &au1200_lcd_device, + &au1xxx_mmc_device, +#endif +#ifdef SMBUS_PSC_BASE + &pbdb_smbus_device, +#endif +}; + +static int __init au1xxx_platform_init(void) +{ + unsigned int uartclk = get_au1x00_uart_baud_base() * 16; + int i; + + /* Fill up uartclk. */ + for (i = 0; au1x00_uart_data[i].flags; i++) + au1x00_uart_data[i].uartclk = uartclk; + + return platform_add_devices(au1xxx_platform_devices, + ARRAY_SIZE(au1xxx_platform_devices)); +} + +arch_initcall(au1xxx_platform_init); diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c new file mode 100644 index 00000000000..bd854a6d1d8 --- /dev/null +++ b/arch/mips/alchemy/common/power.c @@ -0,0 +1,465 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xx0 Power Management routines. + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * Some of the routines are right out of init/main.c, whose + * copyrights apply here. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_PM + +#define DEBUG 1 +#ifdef DEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +static void au1000_calibrate_delay(void); + +extern unsigned long save_local_and_disable(int controller); +extern void restore_local_and_enable(int controller, unsigned long mask); +extern void local_enable_irq(unsigned int irq_nr); + +static DEFINE_SPINLOCK(pm_lock); + +/* + * We need to save/restore a bunch of core registers that are + * either volatile or reset to some state across a processor sleep. + * If reading a register doesn't provide a proper result for a + * later restore, we have to provide a function for loading that + * register and save a copy. + * + * We only have to save/restore registers that aren't otherwise + * done as part of a driver pm_* function. + */ +static unsigned int sleep_aux_pll_cntrl; +static unsigned int sleep_cpu_pll_cntrl; +static unsigned int sleep_pin_function; +static unsigned int sleep_uart0_inten; +static unsigned int sleep_uart0_fifoctl; +static unsigned int sleep_uart0_linectl; +static unsigned int sleep_uart0_clkdiv; +static unsigned int sleep_uart0_enable; +static unsigned int sleep_usbhost_enable; +static unsigned int sleep_usbdev_enable; +static unsigned int sleep_static_memctlr[4][3]; + +/* + * Define this to cause the value you write to /proc/sys/pm/sleep to + * set the TOY timer for the amount of time you want to sleep. + * This is done mainly for testing, but may be useful in other cases. + * The value is number of 32KHz ticks to sleep. + */ +#define SLEEP_TEST_TIMEOUT 1 +#ifdef SLEEP_TEST_TIMEOUT +static int sleep_ticks; +void wakeup_counter0_set(int ticks); +#endif + +static void save_core_regs(void) +{ + extern void save_au1xxx_intctl(void); + extern void pm_eth0_shutdown(void); + + /* + * Do the serial ports.....these really should be a pm_* + * registered function by the driver......but of course the + * standard serial driver doesn't understand our Au1xxx + * unique registers. + */ + sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER); + sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR); + sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR); + sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK); + sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL); + + /* Shutdown USB host/device. */ + sleep_usbhost_enable = au_readl(USB_HOST_CONFIG); + + /* There appears to be some undocumented reset register.... */ + au_writel(0, 0xb0100004); au_sync(); + au_writel(0, USB_HOST_CONFIG); au_sync(); + + sleep_usbdev_enable = au_readl(USBD_ENABLE); + au_writel(0, USBD_ENABLE); au_sync(); + + /* Save interrupt controller state. */ + save_au1xxx_intctl(); + + /* Clocks and PLLs. */ + sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL); + + /* + * We don't really need to do this one, but unless we + * write it again it won't have a valid value if we + * happen to read it. + */ + sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL); + + sleep_pin_function = au_readl(SYS_PINFUNC); + + /* Save the static memory controller configuration. */ + sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0); + sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0); + sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0); + sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1); + sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1); + sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1); + sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2); + sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2); + sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2); + sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3); + sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3); + sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3); +} + +static void restore_core_regs(void) +{ + extern void restore_au1xxx_intctl(void); + extern void wakeup_counter0_adjust(void); + + au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync(); + au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync(); + au_writel(sleep_pin_function, SYS_PINFUNC); au_sync(); + + /* Restore the static memory controller configuration. */ + au_writel(sleep_static_memctlr[0][0], MEM_STCFG0); + au_writel(sleep_static_memctlr[0][1], MEM_STTIME0); + au_writel(sleep_static_memctlr[0][2], MEM_STADDR0); + au_writel(sleep_static_memctlr[1][0], MEM_STCFG1); + au_writel(sleep_static_memctlr[1][1], MEM_STTIME1); + au_writel(sleep_static_memctlr[1][2], MEM_STADDR1); + au_writel(sleep_static_memctlr[2][0], MEM_STCFG2); + au_writel(sleep_static_memctlr[2][1], MEM_STTIME2); + au_writel(sleep_static_memctlr[2][2], MEM_STADDR2); + au_writel(sleep_static_memctlr[3][0], MEM_STCFG3); + au_writel(sleep_static_memctlr[3][1], MEM_STTIME3); + au_writel(sleep_static_memctlr[3][2], MEM_STADDR3); + + /* + * Enable the UART if it was enabled before sleep. + * I guess I should define module control bits........ + */ + if (sleep_uart0_enable & 0x02) { + au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync(); + au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync(); + au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync(); + au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync(); + au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync(); + au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync(); + au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync(); + } + + restore_au1xxx_intctl(); + wakeup_counter0_adjust(); +} + +unsigned long suspend_mode; + +void wakeup_from_suspend(void) +{ + suspend_mode = 0; +} + +int au_sleep(void) +{ + unsigned long wakeup, flags; + extern void save_and_sleep(void); + + spin_lock_irqsave(&pm_lock, flags); + + save_core_regs(); + + flush_cache_all(); + + /** + ** The code below is all system dependent and we should probably + ** have a function call out of here to set this up. You need + ** to configure the GPIO or timer interrupts that will bring + ** you out of sleep. + ** For testing, the TOY counter wakeup is useful. + **/ +#if 0 + au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD); + + /* GPIO 6 can cause a wake up event */ + wakeup = au_readl(SYS_WAKEMSK); + wakeup &= ~(1 << 8); /* turn off match20 wakeup */ + wakeup |= 1 << 6; /* turn on GPIO 6 wakeup */ +#else + /* For testing, allow match20 to wake us up. */ +#ifdef SLEEP_TEST_TIMEOUT + wakeup_counter0_set(sleep_ticks); +#endif + wakeup = 1 << 8; /* turn on match20 wakeup */ + wakeup = 0; +#endif + au_writel(1, SYS_WAKESRC); /* clear cause */ + au_sync(); + au_writel(wakeup, SYS_WAKEMSK); + au_sync(); + + save_and_sleep(); + + /* + * After a wakeup, the cpu vectors back to 0x1fc00000, so + * it's up to the boot code to get us back here. + */ + restore_core_regs(); + spin_unlock_irqrestore(&pm_lock, flags); + return 0; +} + +static int pm_do_sleep(ctl_table *ctl, int write, struct file *file, + void __user *buffer, size_t *len, loff_t *ppos) +{ +#ifdef SLEEP_TEST_TIMEOUT +#define TMPBUFLEN2 16 + char buf[TMPBUFLEN2], *p; +#endif + + if (!write) + *len = 0; + else { +#ifdef SLEEP_TEST_TIMEOUT + if (*len > TMPBUFLEN2 - 1) + return -EFAULT; + if (copy_from_user(buf, buffer, *len)) + return -EFAULT; + buf[*len] = 0; + p = buf; + sleep_ticks = simple_strtoul(p, &p, 0); +#endif + + au_sleep(); + } + return 0; +} + +static int pm_do_freq(ctl_table *ctl, int write, struct file *file, + void __user *buffer, size_t *len, loff_t *ppos) +{ + int retval = 0, i; + unsigned long val, pll; +#define TMPBUFLEN 64 +#define MAX_CPU_FREQ 396 + char buf[TMPBUFLEN], *p; + unsigned long flags, intc0_mask, intc1_mask; + unsigned long old_baud_base, old_cpu_freq, old_clk, old_refresh; + unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh; + unsigned long baud_rate; + + spin_lock_irqsave(&pm_lock, flags); + if (!write) + *len = 0; + else { + /* Parse the new frequency */ + if (*len > TMPBUFLEN - 1) { + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + if (copy_from_user(buf, buffer, *len)) { + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + buf[*len] = 0; + p = buf; + val = simple_strtoul(p, &p, 0); + if (val > MAX_CPU_FREQ) { + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + + pll = val / 12; + if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */ + /* Revisit this for higher speed CPUs */ + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + + old_baud_base = get_au1x00_uart_baud_base(); + old_cpu_freq = get_au1x00_speed(); + + new_cpu_freq = pll * 12 * 1000000; + new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL) + & 0x03) + 2) * 16)); + set_au1x00_speed(new_cpu_freq); + set_au1x00_uart_baud_base(new_baud_base); + + old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff; + new_refresh = ((old_refresh * new_cpu_freq) / old_cpu_freq) | + (au_readl(MEM_SDREFCFG) & ~0x1ffffff); + + au_writel(pll, SYS_CPUPLL); + au_sync_delay(1); + au_writel(new_refresh, MEM_SDREFCFG); + au_sync_delay(1); + + for (i = 0; i < 4; i++) + if (au_readl(UART_BASE + UART_MOD_CNTRL + + i * 0x00100000) == 3) { + old_clk = au_readl(UART_BASE + UART_CLK + + i * 0x00100000); + baud_rate = old_baud_base / old_clk; + /* + * We won't get an exact baud rate and the error + * could be significant enough that our new + * calculation will result in a clock that will + * give us a baud rate that's too far off from + * what we really want. + */ + if (baud_rate > 100000) + baud_rate = 115200; + else if (baud_rate > 50000) + baud_rate = 57600; + else if (baud_rate > 30000) + baud_rate = 38400; + else if (baud_rate > 17000) + baud_rate = 19200; + else + baud_rate = 9600; + new_clk = new_baud_base / baud_rate; + au_writel(new_clk, UART_BASE + UART_CLK + + i * 0x00100000); + au_sync_delay(10); + } + } + + /* + * We don't want _any_ interrupts other than match20. Otherwise our + * au1000_calibrate_delay() calculation will be off, potentially a lot. + */ + intc0_mask = save_local_and_disable(0); + intc1_mask = save_local_and_disable(1); + local_enable_irq(AU1000_TOY_MATCH2_INT); + spin_unlock_irqrestore(&pm_lock, flags); + au1000_calibrate_delay(); + restore_local_and_enable(0, intc0_mask); + restore_local_and_enable(1, intc1_mask); + + return retval; +} + + +static struct ctl_table pm_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "sleep", + .data = NULL, + .maxlen = 0, + .mode = 0600, + .proc_handler = &pm_do_sleep + }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "freq", + .data = NULL, + .maxlen = 0, + .mode = 0600, + .proc_handler = &pm_do_freq + }, + {} +}; + +static struct ctl_table pm_dir_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "pm", + .mode = 0555, + .child = pm_table + }, + {} +}; + +/* + * Initialize power interface + */ +static int __init pm_init(void) +{ + register_sysctl_table(pm_dir_table); + return 0; +} + +__initcall(pm_init); + +/* + * This is right out of init/main.c + */ + +/* + * This is the number of bits of precision for the loops_per_jiffy. + * Each bit takes on average 1.5/HZ seconds. This (like the original) + * is a little better than 1%. + */ +#define LPS_PREC 8 + +static void au1000_calibrate_delay(void) +{ + unsigned long ticks, loopbit; + int lps_precision = LPS_PREC; + + loops_per_jiffy = 1 << 12; + + while (loops_per_jiffy <<= 1) { + /* Wait for "start of" clock tick */ + ticks = jiffies; + while (ticks == jiffies) + /* nothing */ ; + /* Go ... */ + ticks = jiffies; + __delay(loops_per_jiffy); + ticks = jiffies - ticks; + if (ticks) + break; + } + + /* + * Do a binary approximation to get loops_per_jiffy set to be equal + * one clock (up to lps_precision bits) + */ + loops_per_jiffy >>= 1; + loopbit = loops_per_jiffy; + while (lps_precision-- && (loopbit >>= 1)) { + loops_per_jiffy |= loopbit; + ticks = jiffies; + while (ticks == jiffies); + ticks = jiffies; + __delay(loops_per_jiffy); + if (jiffies != ticks) /* longer than 1 tick */ + loops_per_jiffy &= ~loopbit; + } +} +#endif /* CONFIG_PM */ diff --git a/arch/mips/alchemy/common/prom.c b/arch/mips/alchemy/common/prom.c new file mode 100644 index 00000000000..18b310b475c --- /dev/null +++ b/arch/mips/alchemy/common/prom.c @@ -0,0 +1,146 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PROM library initialisation code, supports YAMON and U-Boot. + * + * Copyright 2000-2001, 2006, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/xx files. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include + +int prom_argc; +char **prom_argv; +char **prom_envp; + +char * __init_or_module prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while (actr < prom_argc) { + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + if (prom_argc > 1) + *cp = '\0'; +} + +char *prom_getenv(char *envname) +{ + /* + * Return a pointer to the given environment variable. + * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". + */ + + char **env = prom_envp; + int i = strlen(envname); + int yamon = (*env && strchr(*env, '=') == NULL); + + while (*env) { + if (yamon) { + if (strcmp(envname, *env++) == 0) + return *env; + } else if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') + return *env + i + 1; + env++; + } + + return NULL; +} + +static inline unsigned char str2hexnum(unsigned char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return 0; /* foo */ +} + +static inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for (i = 0; i < 6; i++) { + unsigned char num; + + if ((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= str2hexnum(*str++); + ea[i] = num; + } +} + +int prom_get_ethernet_addr(char *ethernet_addr) +{ + char *ethaddr_str; + char *argptr; + + /* Check the environment variables first */ + ethaddr_str = prom_getenv("ethaddr"); + if (!ethaddr_str) { + /* Check command line */ + argptr = prom_getcmdline(); + ethaddr_str = strstr(argptr, "ethaddr="); + if (!ethaddr_str) + return -1; + + ethaddr_str += strlen("ethaddr="); + } + + str2eaddr(ethernet_addr, ethaddr_str); + + return 0; +} +EXPORT_SYMBOL(prom_get_ethernet_addr); + +void __init prom_free_prom_memory(void) +{ +} diff --git a/arch/mips/alchemy/common/puts.c b/arch/mips/alchemy/common/puts.c new file mode 100644 index 00000000000..55bbe24d45b --- /dev/null +++ b/arch/mips/alchemy/common/puts.c @@ -0,0 +1,68 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Low level UART routines to directly access Alchemy UART. + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#define SERIAL_BASE UART_BASE +#define SER_CMD 0x7 +#define SER_DATA 0x1 +#define TX_BUSY 0x20 + +#define TIMEOUT 0xffffff +#define SLOW_DOWN + +static volatile unsigned long * const com1 = (unsigned long *)SERIAL_BASE; + +#ifdef SLOW_DOWN +static inline void slow_down(void) +{ + int k; + + for (k = 0; k < 10000; k++); +} +#else +#define slow_down() +#endif + +void +prom_putchar(const unsigned char c) +{ + unsigned char ch; + int i = 0; + + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) + break; + } while (0 == (ch & TX_BUSY)); + + com1[SER_DATA] = c; +} diff --git a/arch/mips/alchemy/common/reset.c b/arch/mips/alchemy/common/reset.c new file mode 100644 index 00000000000..d555429c8d6 --- /dev/null +++ b/arch/mips/alchemy/common/reset.c @@ -0,0 +1,189 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Au1xx0 reset routines. + * + * Copyright 2001, 2006, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +extern int au_sleep(void); + +void au1000_restart(char *command) +{ + /* Set all integrated peripherals to disabled states */ + extern void board_reset(void); + u32 prid = read_c0_prid(); + + printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n"); + + switch (prid & 0xFF000000) { + case 0x00000000: /* Au1000 */ + au_writel(0x02, 0xb0000010); /* ac97_enable */ + au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ + asm("sync"); + au_writel(0x00, 0xb017fffc); /* usbh_enable */ + au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb0300040); /* ir_enable */ + au_writel(0x00, 0xb4004104); /* mac dma */ + au_writel(0x00, 0xb4004114); /* mac dma */ + au_writel(0x00, 0xb4004124); /* mac dma */ + au_writel(0x00, 0xb4004134); /* mac dma */ + au_writel(0x00, 0xb0520000); /* macen0 */ + au_writel(0x00, 0xb0520004); /* macen1 */ + au_writel(0x00, 0xb1000008); /* i2s_enable */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1200100); /* uart1_enable */ + au_writel(0x00, 0xb1300100); /* uart2_enable */ + au_writel(0x00, 0xb1400100); /* uart3_enable */ + au_writel(0x02, 0xb1600100); /* ssi0_enable */ + au_writel(0x02, 0xb1680100); /* ssi1_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; + case 0x01000000: /* Au1500 */ + au_writel(0x02, 0xb0000010); /* ac97_enable */ + au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ + asm("sync"); + au_writel(0x00, 0xb017fffc); /* usbh_enable */ + au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb4004104); /* mac dma */ + au_writel(0x00, 0xb4004114); /* mac dma */ + au_writel(0x00, 0xb4004124); /* mac dma */ + au_writel(0x00, 0xb4004134); /* mac dma */ + au_writel(0x00, 0xb1520000); /* macen0 */ + au_writel(0x00, 0xb1520004); /* macen1 */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1400100); /* uart3_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; + case 0x02000000: /* Au1100 */ + au_writel(0x02, 0xb0000010); /* ac97_enable */ + au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ + asm("sync"); + au_writel(0x00, 0xb017fffc); /* usbh_enable */ + au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb0300040); /* ir_enable */ + au_writel(0x00, 0xb4004104); /* mac dma */ + au_writel(0x00, 0xb4004114); /* mac dma */ + au_writel(0x00, 0xb4004124); /* mac dma */ + au_writel(0x00, 0xb4004134); /* mac dma */ + au_writel(0x00, 0xb0520000); /* macen0 */ + au_writel(0x00, 0xb1000008); /* i2s_enable */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1200100); /* uart1_enable */ + au_writel(0x00, 0xb1400100); /* uart3_enable */ + au_writel(0x02, 0xb1600100); /* ssi0_enable */ + au_writel(0x02, 0xb1680100); /* ssi1_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; + case 0x03000000: /* Au1550 */ + au_writel(0x00, 0xb1a00004); /* psc 0 */ + au_writel(0x00, 0xb1b00004); /* psc 1 */ + au_writel(0x00, 0xb0a00004); /* psc 2 */ + au_writel(0x00, 0xb0b00004); /* psc 3 */ + au_writel(0x00, 0xb017fffc); /* usbh_enable */ + au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb4004104); /* mac dma */ + au_writel(0x00, 0xb4004114); /* mac dma */ + au_writel(0x00, 0xb4004124); /* mac dma */ + au_writel(0x00, 0xb4004134); /* mac dma */ + au_writel(0x00, 0xb1520000); /* macen0 */ + au_writel(0x00, 0xb1520004); /* macen1 */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1200100); /* uart1_enable */ + au_writel(0x00, 0xb1400100); /* uart3_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; + } + + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + + /* Give board a chance to do a hardware reset */ + board_reset(); + + /* Jump to the beggining in case board_reset() is empty */ + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void au1000_halt(void) +{ +#if defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) + /* Power off system */ + printk(KERN_NOTICE "\n** Powering off...\n"); + au_writew(au_readw(0xAF00001C) | (3 << 14), 0xAF00001C); + au_sync(); + while (1); /* should not get here */ +#else + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); +#ifdef CONFIG_MIPS_MIRAGE + au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT); +#endif +#ifdef CONFIG_MIPS_DB1200 + au_writew(au_readw(0xB980001C) | (1 << 14), 0xB980001C); +#endif +#ifdef CONFIG_PM + au_sleep(); + + /* Should not get here */ + printk(KERN_ERR "Unable to put CPU in sleep mode\n"); + while (1); +#else + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +#endif +#endif /* defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) */ +} + +void au1000_power_off(void) +{ + au1000_halt(); +} diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c new file mode 100644 index 00000000000..1ac6b06f42a --- /dev/null +++ b/arch/mips/alchemy/common/setup.c @@ -0,0 +1,160 @@ +/* + * Copyright 2000, 2007-2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. +#include +#include +#include + +#include +#include +#include + +#include +#include + +extern void __init board_setup(void); +extern void au1000_restart(char *); +extern void au1000_halt(void); +extern void au1000_power_off(void); +extern void set_cpuspec(void); + +void __init plat_mem_setup(void) +{ + struct cpu_spec *sp; + char *argptr; + unsigned long prid, cpufreq, bclk; + + set_cpuspec(); + sp = cur_cpu_spec[0]; + + board_setup(); /* board specific setup */ + + prid = read_c0_prid(); + if (sp->cpu_pll_wo) +#ifdef CONFIG_SOC_AU1000_FREQUENCY + cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000; +#else + cpufreq = 396; +#endif + else + cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12; + printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq); + + if (sp->cpu_bclk) { + /* Enable BCLK switching */ + bclk = au_readl(SYS_POWERCTRL); + au_writel(bclk | 0x60, SYS_POWERCTRL); + printk(KERN_INFO "BCLK switching enabled!\n"); + } + + if (sp->cpu_od) + /* Various early Au1xx0 errata corrected by this */ + set_c0_config(1 << 19); /* Set Config[OD] */ + else + /* Clear to obtain best system bus performance */ + clear_c0_config(1 << 19); /* Clear Config[OD] */ + + argptr = prom_getcmdline(); + +#ifdef CONFIG_SERIAL_8250_CONSOLE + argptr = strstr(argptr, "console="); + if (argptr == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + +#ifdef CONFIG_FB_AU1100 + argptr = strstr(argptr, "video="); + if (argptr == NULL) { + argptr = prom_getcmdline(); + /* default panel */ + /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/ + } +#endif + +#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000) + /* au1000 does not support vra, au1500 and au1100 do */ + strcat(argptr, " au1000_audio=vra"); + argptr = prom_getcmdline(); +#endif + _machine_restart = au1000_restart; + _machine_halt = au1000_halt; + pm_power_off = au1000_power_off; + + /* IO/MEM resources. */ + set_io_port_base(0); + ioport_resource.start = IOPORT_RESOURCE_START; + ioport_resource.end = IOPORT_RESOURCE_END; + iomem_resource.start = IOMEM_RESOURCE_START; + iomem_resource.end = IOMEM_RESOURCE_END; + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); + au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); + au_writel(0, SYS_TOYTRIM); +} + +#if defined(CONFIG_64BIT_PHYS_ADDR) +/* This routine should be valid for all Au1x based boards */ +phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + /* Don't fixup 36-bit addresses */ + if ((phys_addr >> 32) != 0) + return phys_addr; + +#ifdef CONFIG_PCI + { + u32 start = (u32)Au1500_PCI_MEM_START; + u32 end = (u32)Au1500_PCI_MEM_END; + + /* Check for PCI memory window */ + if (phys_addr >= start && (phys_addr + size - 1) <= end) + return (phys_t) + ((phys_addr - start) + Au1500_PCI_MEM_START); + } +#endif + + /* + * All Au1xx0 SOCs have a PCMCIA controller. + * We setup our 32-bit pseudo addresses to be equal to the + * 36-bit addr >> 4, to make it easier to check the address + * and fix it. + * The PCMCIA socket 0 physical attribute address is 0xF 4000 0000. + * The pseudo address we use is 0xF400 0000. Any address over + * 0xF400 0000 is a PCMCIA pseudo address. + */ + if ((phys_addr >= 0xF4000000) && (phys_addr < 0xFFFFFFFF)) + return (phys_t)(phys_addr << 4); + + /* default nop */ + return phys_addr; +} +EXPORT_SYMBOL(__fixup_bigphys_addr); +#endif diff --git a/arch/mips/alchemy/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S new file mode 100644 index 00000000000..3006e270c8b --- /dev/null +++ b/arch/mips/alchemy/common/sleeper.S @@ -0,0 +1,154 @@ +/* + * Copyright 2002 Embedded Edge, LLC + * Author: dan@embeddededge.com + * + * Sleep helper for Au1xxx sleep mode. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + + .text + .set macro + .set noat + .align 5 + +/* Save all of the processor general registers and go to sleep. + * A wakeup condition will get us back here to restore the registers. + */ +LEAF(save_and_sleep) + + subu sp, PT_SIZE + sw $1, PT_R1(sp) + sw $2, PT_R2(sp) + sw $3, PT_R3(sp) + sw $4, PT_R4(sp) + sw $5, PT_R5(sp) + sw $6, PT_R6(sp) + sw $7, PT_R7(sp) + sw $8, PT_R8(sp) + sw $9, PT_R9(sp) + sw $10, PT_R10(sp) + sw $11, PT_R11(sp) + sw $12, PT_R12(sp) + sw $13, PT_R13(sp) + sw $14, PT_R14(sp) + sw $15, PT_R15(sp) + sw $16, PT_R16(sp) + sw $17, PT_R17(sp) + sw $18, PT_R18(sp) + sw $19, PT_R19(sp) + sw $20, PT_R20(sp) + sw $21, PT_R21(sp) + sw $22, PT_R22(sp) + sw $23, PT_R23(sp) + sw $24, PT_R24(sp) + sw $25, PT_R25(sp) + sw $26, PT_R26(sp) + sw $27, PT_R27(sp) + sw $28, PT_R28(sp) + sw $29, PT_R29(sp) + sw $30, PT_R30(sp) + sw $31, PT_R31(sp) + mfc0 k0, CP0_STATUS + sw k0, 0x20(sp) + mfc0 k0, CP0_CONTEXT + sw k0, 0x1c(sp) + mfc0 k0, CP0_PAGEMASK + sw k0, 0x18(sp) + mfc0 k0, CP0_CONFIG + sw k0, 0x14(sp) + + /* Now set up the scratch registers so the boot rom will + * return to this point upon wakeup. + */ + la k0, 1f + lui k1, 0xb190 + ori k1, 0x18 + sw sp, 0(k1) + ori k1, 0x1c + sw k0, 0(k1) + +/* Put SDRAM into self refresh. Preload instructions into cache, + * issue a precharge, then auto refresh, then sleep commands to it. + */ + la t0, sdsleep + .set mips3 + cache 0x14, 0(t0) + cache 0x14, 32(t0) + cache 0x14, 64(t0) + cache 0x14, 96(t0) + .set mips0 + +sdsleep: + lui k0, 0xb400 + sw zero, 0x001c(k0) /* Precharge */ + sw zero, 0x0020(k0) /* Auto refresh */ + sw zero, 0x0030(k0) /* SDRAM sleep */ + sync + + lui k1, 0xb190 + sw zero, 0x0078(k1) /* get ready to sleep */ + sync + sw zero, 0x007c(k1) /* Put processor to sleep */ + sync + + /* This is where we return upon wakeup. + * Reload all of the registers and return. + */ +1: nop + lw k0, 0x20(sp) + mtc0 k0, CP0_STATUS + lw k0, 0x1c(sp) + mtc0 k0, CP0_CONTEXT + lw k0, 0x18(sp) + mtc0 k0, CP0_PAGEMASK + lw k0, 0x14(sp) + mtc0 k0, CP0_CONFIG + + /* We need to catch the ealry Alchemy SOCs with + * the write-only Config[OD] bit and set it back to one... + */ + jal au1x00_fixup_config_od + lw $1, PT_R1(sp) + lw $2, PT_R2(sp) + lw $3, PT_R3(sp) + lw $4, PT_R4(sp) + lw $5, PT_R5(sp) + lw $6, PT_R6(sp) + lw $7, PT_R7(sp) + lw $8, PT_R8(sp) + lw $9, PT_R9(sp) + lw $10, PT_R10(sp) + lw $11, PT_R11(sp) + lw $12, PT_R12(sp) + lw $13, PT_R13(sp) + lw $14, PT_R14(sp) + lw $15, PT_R15(sp) + lw $16, PT_R16(sp) + lw $17, PT_R17(sp) + lw $18, PT_R18(sp) + lw $19, PT_R19(sp) + lw $20, PT_R20(sp) + lw $21, PT_R21(sp) + lw $22, PT_R22(sp) + lw $23, PT_R23(sp) + lw $24, PT_R24(sp) + lw $25, PT_R25(sp) + lw $26, PT_R26(sp) + lw $27, PT_R27(sp) + lw $28, PT_R28(sp) + lw $29, PT_R29(sp) + lw $30, PT_R30(sp) + lw $31, PT_R31(sp) + addiu sp, PT_SIZE + + jr ra +END(save_and_sleep) diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c new file mode 100644 index 00000000000..563d9390a87 --- /dev/null +++ b/arch/mips/alchemy/common/time.c @@ -0,0 +1,266 @@ +/* + * + * Copyright (C) 2001, 2006, 2008 MontaVista Software, + * Copied and modified Carsten Langgaard's time.c + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * ######################################################################## + * + * Setting up the clock on the MIPS boards. + * + * We provide the clock interrupt processing and the timer offset compute + * functions. If CONFIG_PM is selected, we also ensure the 32KHz timer is + * available. -- Dan + */ + +#include +#include +#include + +#include +#include +#include + +static int no_au1xxx_32khz; +extern int allow_au1k_wait; /* default off for CP0 Counter */ + +#ifdef CONFIG_PM +#if HZ < 100 || HZ > 1000 +#error "unsupported HZ value! Must be in [100,1000]" +#endif +#define MATCH20_INC (328 * 100 / HZ) /* magic number 328 is for HZ=100... */ +static unsigned long last_pc0, last_match20; +#endif + +static DEFINE_SPINLOCK(time_lock); + +unsigned long wtimer; + +#ifdef CONFIG_PM +static irqreturn_t counter0_irq(int irq, void *dev_id) +{ + unsigned long pc0; + int time_elapsed; + static int jiffie_drift; + + if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { + /* should never happen! */ + printk(KERN_WARNING "counter 0 w status error\n"); + return IRQ_NONE; + } + + pc0 = au_readl(SYS_TOYREAD); + if (pc0 < last_match20) + /* counter overflowed */ + time_elapsed = (0xffffffff - last_match20) + pc0; + else + time_elapsed = pc0 - last_match20; + + while (time_elapsed > 0) { + do_timer(1); +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif + time_elapsed -= MATCH20_INC; + last_match20 += MATCH20_INC; + jiffie_drift++; + } + + last_pc0 = pc0; + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); + + /* + * Our counter ticks at 10.009765625 ms/tick, we we're running + * almost 10 uS too slow per tick. + */ + + if (jiffie_drift >= 999) { + jiffie_drift -= 999; + do_timer(1); /* increment jiffies by one */ +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif + } + + return IRQ_HANDLED; +} + +struct irqaction counter0_action = { + .handler = counter0_irq, + .flags = IRQF_DISABLED, + .name = "alchemy-toy", + .dev_id = NULL, +}; + +/* When we wakeup from sleep, we have to "catch up" on all of the + * timer ticks we have missed. + */ +void wakeup_counter0_adjust(void) +{ + unsigned long pc0; + int time_elapsed; + + pc0 = au_readl(SYS_TOYREAD); + if (pc0 < last_match20) + /* counter overflowed */ + time_elapsed = (0xffffffff - last_match20) + pc0; + else + time_elapsed = pc0 - last_match20; + + while (time_elapsed > 0) { + time_elapsed -= MATCH20_INC; + last_match20 += MATCH20_INC; + } + + last_pc0 = pc0; + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); + +} + +/* This is just for debugging to set the timer for a sleep delay. */ +void wakeup_counter0_set(int ticks) +{ + unsigned long pc0; + + pc0 = au_readl(SYS_TOYREAD); + last_pc0 = pc0; + au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2); + au_sync(); +} +#endif + +/* + * I haven't found anyone that doesn't use a 12 MHz source clock, + * but just in case..... + */ +#define AU1000_SRC_CLK 12000000 + +/* + * We read the real processor speed from the PLL. This is important + * because it is more accurate than computing it from the 32 KHz + * counter, if it exists. If we don't have an accurate processor + * speed, all of the peripherals that derive their clocks based on + * this advertised speed will introduce error and sometimes not work + * properly. This function is futher convoluted to still allow configurations + * to do that in case they have really, really old silicon with a + * write-only PLL register, that we need the 32 KHz when power management + * "wait" is enabled, and we need to detect if the 32 KHz isn't present + * but requested......got it? :-) -- Dan + */ +unsigned long calc_clock(void) +{ + unsigned long cpu_speed; + unsigned long flags; + unsigned long counter; + + spin_lock_irqsave(&time_lock, flags); + + /* Power management cares if we don't have a 32 KHz counter. */ + no_au1xxx_32khz = 0; + counter = au_readl(SYS_COUNTER_CNTRL); + if (counter & SYS_CNTRL_E0) { + int trim_divide = 16; + + au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL); + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); + /* RTC now ticks at 32.768/16 kHz */ + au_writel(trim_divide - 1, SYS_RTCTRIM); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); + au_writel(0, SYS_TOYWRITE); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); + } else + no_au1xxx_32khz = 1; + + /* + * On early Au1000, sys_cpupll was write-only. Since these + * silicon versions of Au1000 are not sold by AMD, we don't bend + * over backwards trying to determine the frequency. + */ + if (cur_cpu_spec[0]->cpu_pll_wo) +#ifdef CONFIG_SOC_AU1000_FREQUENCY + cpu_speed = CONFIG_SOC_AU1000_FREQUENCY; +#else + cpu_speed = 396000000; +#endif + else + cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; + /* On Alchemy CPU:counter ratio is 1:1 */ + mips_hpt_frequency = cpu_speed; + /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */ + set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL) + & 0x03) + 2) * 16)); + spin_unlock_irqrestore(&time_lock, flags); + return cpu_speed; +} + +void __init plat_time_init(void) +{ + unsigned int est_freq = calc_clock(); + + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk(KERN_INFO "CPU frequency %u.%02u MHz\n", + est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000); + set_au1x00_speed(est_freq); + set_au1x00_lcd_clock(); /* program the LCD clock */ + +#ifdef CONFIG_PM + /* + * setup counter 0, since it keeps ticking after a + * 'wait' instruction has been executed. The CP0 timer and + * counter 1 do NOT continue running after 'wait' + * + * It's too early to call request_irq() here, so we handle + * counter 0 interrupt as a special irq and it doesn't show + * up under /proc/interrupts. + * + * Check to ensure we really have a 32 KHz oscillator before + * we do this. + */ + if (no_au1xxx_32khz) + printk(KERN_WARNING "WARNING: no 32KHz clock found.\n"); + else { + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); + au_writel(0, SYS_TOYWRITE); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); + + au_writel(au_readl(SYS_WAKEMSK) | (1 << 8), SYS_WAKEMSK); + au_writel(~0, SYS_WAKESRC); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); + + /* Setup match20 to interrupt once every HZ */ + last_pc0 = last_match20 = au_readl(SYS_TOYREAD); + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); + setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action); + + /* We can use the real 'wait' instruction. */ + allow_au1k_wait = 1; + } + +#endif +} diff --git a/arch/mips/alchemy/db1x00/Makefile b/arch/mips/alchemy/db1x00/Makefile new file mode 100644 index 00000000000..274db3b55d8 --- /dev/null +++ b/arch/mips/alchemy/db1x00/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2000, 2008 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for the Alchemy Semiconductor DBAu1xx0 boards. +# + +lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/alchemy/db1x00/board_setup.c b/arch/mips/alchemy/db1x00/board_setup.c new file mode 100644 index 00000000000..9e5ccbbfced --- /dev/null +++ b/arch/mips/alchemy/db1x00/board_setup.c @@ -0,0 +1,108 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Db1x00 board setup. + * + * Copyright 2000, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include + +static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; + +void board_reset(void) +{ + /* Hit BCSR.SW_RESET[RESET] */ + bcsr->swreset = 0x0000; +} + +void __init board_setup(void) +{ + u32 pin_func = 0; + + /* Not valid for Au1550 */ +#if defined(CONFIG_IRDA) && \ + (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100)) + /* Set IRFIRSEL instead of GPIO15 */ + pin_func = au_readl(SYS_PINFUNC) | SYS_PF_IRF; + au_writel(pin_func, SYS_PINFUNC); + /* Power off until the driver is in use */ + bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK; + bcsr->resets |= BCSR_RESETS_IRDA_MODE_OFF; + au_sync(); +#endif + bcsr->pcmcia = 0x0000; /* turn off PCMCIA power */ + +#ifdef CONFIG_MIPS_MIRAGE + /* Enable GPIO[31:0] inputs */ + au_writel(0, SYS_PININPUTEN); + + /* GPIO[20] is output, tristate the other input primary GPIOs */ + au_writel(~(1 << 20), SYS_TRIOUTCLR); + + /* Set GPIO[210:208] instead of SSI_0 */ + pin_func = au_readl(SYS_PINFUNC) | SYS_PF_S0; + + /* Set GPIO[215:211] for LEDs */ + pin_func |= 5 << 2; + + /* Set GPIO[214:213] for more LEDs */ + pin_func |= 5 << 12; + + /* Set GPIO[207:200] instead of PCMCIA/LCD */ + pin_func |= SYS_PF_LCD | SYS_PF_PC; + au_writel(pin_func, SYS_PINFUNC); + + /* + * Enable speaker amplifier. This should + * be part of the audio driver. + */ + au_writel(au_readl(GPIO2_DIR) | 0x200, GPIO2_DIR); + au_writel(0x02000200, GPIO2_OUTPUT); +#endif + + au_sync(); + +#ifdef CONFIG_MIPS_DB1000 + printk(KERN_INFO "AMD Alchemy Au1000/Db1000 Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1500 + printk(KERN_INFO "AMD Alchemy Au1500/Db1500 Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1100 + printk(KERN_INFO "AMD Alchemy Au1100/Db1100 Board\n"); +#endif +#ifdef CONFIG_MIPS_BOSPORUS + printk(KERN_INFO "AMD Alchemy Bosporus Board\n"); +#endif +#ifdef CONFIG_MIPS_MIRAGE + printk(KERN_INFO "AMD Alchemy Mirage Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1550 + printk(KERN_INFO "AMD Alchemy Au1550/Db1550 Board\n"); +#endif +} diff --git a/arch/mips/alchemy/db1x00/init.c b/arch/mips/alchemy/db1x00/init.c new file mode 100644 index 00000000000..84741351496 --- /dev/null +++ b/arch/mips/alchemy/db1x00/init.c @@ -0,0 +1,62 @@ +/* + * BRIEF MODULE DESCRIPTION + * PB1000 board setup + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ +#ifdef CONFIG_MIPS_BOSPORUS + return "Alchemy Bosporus Gateway Reference"; +#else + return "Alchemy Db1x00"; +#endif +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtol(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/db1x00/irqmap.c b/arch/mips/alchemy/db1x00/irqmap.c new file mode 100644 index 00000000000..94c090e8bf7 --- /dev/null +++ b/arch/mips/alchemy/db1x00/irqmap.c @@ -0,0 +1,86 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +#ifdef CONFIG_MIPS_DB1500 +char irq_tab_alchemy[][5] __initdata = { + [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT371 */ + [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */ +}; +#endif + +#ifdef CONFIG_MIPS_BOSPORUS +char irq_tab_alchemy[][5] __initdata = { + [11] = { -1, INTA, INTB, INTX, INTX }, /* IDSEL 11 - miniPCI */ + [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - SN1741 */ + [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */ +}; +#endif + +#ifdef CONFIG_MIPS_MIRAGE +char irq_tab_alchemy[][5] __initdata = { + [11] = { -1, INTD, INTX, INTX, INTX }, /* IDSEL 11 - SMI VGX */ + [12] = { -1, INTX, INTX, INTC, INTX }, /* IDSEL 12 - PNX1300 */ + [13] = { -1, INTA, INTB, INTX, INTX }, /* IDSEL 13 - miniPCI */ +}; +#endif + +#ifdef CONFIG_MIPS_DB1550 +char irq_tab_alchemy[][5] __initdata = { + [11] = { -1, INTC, INTX, INTX, INTX }, /* IDSEL 11 - on-board HPT371 */ + [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */ + [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */ +}; +#endif + + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + +#ifndef CONFIG_MIPS_MIRAGE +#ifdef CONFIG_MIPS_DB1550 + { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ + { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ +#else + { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */ + { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */ + { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ + + { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */ + { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */ + { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ +#endif +#else + { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */ +#endif + +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile new file mode 100644 index 00000000000..7c67b3d33be --- /dev/null +++ b/arch/mips/alchemy/mtx-1/Makefile @@ -0,0 +1,12 @@ +# +# Copyright 2003 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# Bruno Randolf +# +# Makefile for 4G Systems MTX-1 board. +# + +lib-y := init.o board_setup.o irqmap.o +obj-y := platform.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c new file mode 100644 index 00000000000..3f8079186cf --- /dev/null +++ b/arch/mips/alchemy/mtx-1/board_setup.c @@ -0,0 +1,98 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * 4G Systems MTX-1 board setup. + * + * Copyright 2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * Bruno Randolf + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +extern int (*board_pci_idsel)(unsigned int devsel, int assert); +int mtx1_pci_idsel(unsigned int devsel, int assert); + +void board_reset(void) +{ + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); +} + +void __init board_setup(void) +{ +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + /* Enable USB power switch */ + au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR); + au_writel(0x100000, GPIO2_OUTPUT); +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ + +#ifdef CONFIG_PCI +#if defined(__MIPSEB__) + au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif +#endif + + /* Initialize sys_pinfunc */ + au_writel(SYS_PF_NI2, SYS_PINFUNC); + + /* Initialize GPIO */ + au_writel(0xFFFFFFFF, SYS_TRIOUTCLR); + au_writel(0x00000001, SYS_OUTPUTCLR); /* set M66EN (PCI 66MHz) to OFF */ + au_writel(0x00000008, SYS_OUTPUTSET); /* set PCI CLKRUN# to OFF */ + au_writel(0x00000002, SYS_OUTPUTSET); /* set EXT_IO3 ON */ + au_writel(0x00000020, SYS_OUTPUTCLR); /* set eth PHY TX_ER to OFF */ + + /* Enable LED and set it to green */ + au_writel(au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR); + au_writel(0x18000800, GPIO2_OUTPUT); + + board_pci_idsel = mtx1_pci_idsel; + + printk(KERN_INFO "4G Systems MTX-1 Board\n"); +} + +int +mtx1_pci_idsel(unsigned int devsel, int assert) +{ +#define MTX_IDSEL_ONLY_0_AND_3 0 +#if MTX_IDSEL_ONLY_0_AND_3 + if (devsel != 0 && devsel != 3) { + printk(KERN_ERR "*** not 0 or 3\n"); + return 0; + } +#endif + + if (assert && devsel != 0) + /* Suppress signal to Cardbus */ + au_writel(0x00000002, SYS_OUTPUTCLR); /* set EXT_IO3 OFF */ + else + au_writel(0x00000002, SYS_OUTPUTSET); /* set EXT_IO3 ON */ + au_sync_udelay(1); + return 1; +} + diff --git a/arch/mips/alchemy/mtx-1/init.c b/arch/mips/alchemy/mtx-1/init.c new file mode 100644 index 00000000000..3bae13c2895 --- /dev/null +++ b/arch/mips/alchemy/mtx-1/init.c @@ -0,0 +1,60 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * 4G Systems MTX-1 board setup + * + * Copyright 2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * Bruno Randolf + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ + return "MTX-1"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtol(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/mtx-1/irqmap.c b/arch/mips/alchemy/mtx-1/irqmap.c new file mode 100644 index 00000000000..f2bf02951e9 --- /dev/null +++ b/arch/mips/alchemy/mtx-1/irqmap.c @@ -0,0 +1,52 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +char irq_tab_alchemy[][5] __initdata = { + [0] = { -1, INTA, INTA, INTX, INTX }, /* IDSEL 00 - AdapterA-Slot0 (top) */ + [1] = { -1, INTB, INTA, INTX, INTX }, /* IDSEL 01 - AdapterA-Slot1 (bottom) */ + [2] = { -1, INTC, INTD, INTX, INTX }, /* IDSEL 02 - AdapterB-Slot0 (top) */ + [3] = { -1, INTD, INTC, INTX, INTX }, /* IDSEL 03 - AdapterB-Slot1 (bottom) */ + [4] = { -1, INTA, INTB, INTX, INTX }, /* IDSEL 04 - AdapterC-Slot0 (top) */ + [5] = { -1, INTB, INTA, INTX, INTX }, /* IDSEL 05 - AdapterC-Slot1 (bottom) */ + [6] = { -1, INTC, INTD, INTX, INTX }, /* IDSEL 06 - AdapterD-Slot0 (top) */ + [7] = { -1, INTD, INTC, INTX, INTX }, /* IDSEL 07 - AdapterD-Slot1 (bottom) */ +}; + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, + { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/alchemy/mtx-1/platform.c b/arch/mips/alchemy/mtx-1/platform.c new file mode 100644 index 00000000000..8b5914d1241 --- /dev/null +++ b/arch/mips/alchemy/mtx-1/platform.c @@ -0,0 +1,149 @@ +/* + * MTX-1 platform devices registration + * + * Copyright (C) 2007, Florian Fainelli + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gpio_keys_button mtx1_gpio_button[] = { + { + .gpio = 207, + .code = BTN_0, + .desc = "System button", + } +}; + +static struct gpio_keys_platform_data mtx1_buttons_data = { + .buttons = mtx1_gpio_button, + .nbuttons = ARRAY_SIZE(mtx1_gpio_button), +}; + +static struct platform_device mtx1_button = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &mtx1_buttons_data, + } +}; + +static struct resource mtx1_wdt_res[] = { + [0] = { + .start = 15, + .end = 15, + .name = "mtx1-wdt-gpio", + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device mtx1_wdt = { + .name = "mtx1-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(mtx1_wdt_res), + .resource = mtx1_wdt_res, +}; + +static struct gpio_led default_leds[] = { + { + .name = "mtx1:green", + .gpio = 211, + }, { + .name = "mtx1:red", + .gpio = 212, + }, +}; + +static struct gpio_led_platform_data mtx1_led_data = { + .num_leds = ARRAY_SIZE(default_leds), + .leds = default_leds, +}; + +static struct platform_device mtx1_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &mtx1_led_data, + } +}; + +static struct mtd_partition mtx1_mtd_partitions[] = { + { + .name = "filesystem", + .size = 0x01C00000, + .offset = 0, + }, + { + .name = "yamon", + .size = 0x00100000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "kernel", + .size = 0x002c0000, + .offset = MTDPART_OFS_APPEND, + }, + { + .name = "yamon env", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + }, +}; + +static struct physmap_flash_data mtx1_flash_data = { + .width = 4, + .nr_parts = 4, + .parts = mtx1_mtd_partitions, +}; + +static struct resource mtx1_mtd_resource = { + .start = 0x1e000000, + .end = 0x1fffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device mtx1_mtd = { + .name = "physmap-flash", + .dev = { + .platform_data = &mtx1_flash_data, + }, + .num_resources = 1, + .resource = &mtx1_mtd_resource, +}; + +static struct __initdata platform_device * mtx1_devs[] = { + &mtx1_gpio_leds, + &mtx1_wdt, + &mtx1_button, + &mtx1_mtd, +}; + +static int __init mtx1_register_devices(void) +{ + gpio_direction_input(207); + return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs)); +} + +arch_initcall(mtx1_register_devices); diff --git a/arch/mips/alchemy/pb1000/Makefile b/arch/mips/alchemy/pb1000/Makefile new file mode 100644 index 00000000000..99bbec0ca41 --- /dev/null +++ b/arch/mips/alchemy/pb1000/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2000, 2008 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for the Alchemy Semiconductor Pb1000 board. +# + +lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/alchemy/pb1000/board_setup.c b/arch/mips/alchemy/pb1000/board_setup.c new file mode 100644 index 00000000000..25df167a95b --- /dev/null +++ b/arch/mips/alchemy/pb1000/board_setup.c @@ -0,0 +1,165 @@ +/* + * Copyright 2000, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +void board_reset(void) +{ +} + +void __init board_setup(void) +{ + u32 pin_func, static_cfg0; + u32 sys_freqctrl, sys_clksrc; + u32 prid = read_c0_prid(); + + /* Set AUX clock to 12 MHz * 8 = 96 MHz */ + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PINSTATERD); + udelay(100); + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + /* Zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* Zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | + SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | + SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); + + switch (prid & 0x000000FF) { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + /* CPU core freq to 48 MHz to slow it way down... */ + au_writel(4, SYS_CPUPLL); + + /* + * Setup 48 MHz FREQ2 from CPUPLL for USB Host + * FRDIV2 = 3 -> div by 8 of 384 MHz -> 48 MHz + */ + sys_freqctrl |= (3 << SYS_FC_FRDIV2_BIT) | SYS_FC_FE2; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* CPU core freq to 384 MHz */ + au_writel(0x20, SYS_CPUPLL); + + printk(KERN_INFO "Au1000: 48 MHz OHCI workaround enabled\n"); + break; + + default: /* HC and newer */ + /* FREQ2 = aux / 2 = 48 MHz */ + sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) | + SYS_FC_FE2 | SYS_FC_FS2; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + break; + } + + /* + * Route 48 MHz FREQ2 into USB Host and/or Device + */ + sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MUH_BIT; + au_writel(sys_clksrc, SYS_CLKSRC); + + /* Configure pins GPIO[14:9] as GPIO */ + pin_func = au_readl(SYS_PINFUNC) & ~(SYS_PF_UR3 | SYS_PF_USB); + + /* 2nd USB port is USB host */ + pin_func |= SYS_PF_USB; + + au_writel(pin_func, SYS_PINFUNC); + au_writel(0x2800, SYS_TRIOUTCLR); + au_writel(0x0030, SYS_OUTPUTCLR); +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ + + /* Make GPIO 15 an input (for interrupt line) */ + pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_IRF; + /* We don't need I2S, so make it available for GPIO[31:29] */ + pin_func |= SYS_PF_I2S; + au_writel(pin_func, SYS_PINFUNC); + + au_writel(0x8000, SYS_TRIOUTCLR); + + static_cfg0 = au_readl(MEM_STCFG0) & ~0xc00; + au_writel(static_cfg0, MEM_STCFG0); + + /* configure RCE2* for LCD */ + au_writel(0x00000004, MEM_STCFG2); + + /* MEM_STTIME2 */ + au_writel(0x09000000, MEM_STTIME2); + + /* Set 32-bit base address decoding for RCE2* */ + au_writel(0x10003ff0, MEM_STADDR2); + + /* + * PCI CPLD setup + * Expand CE0 to cover PCI + */ + au_writel(0x11803e40, MEM_STADDR1); + + /* Burst visibility on */ + au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0); + + au_writel(0x83, MEM_STCFG1); /* ewait enabled, flash timing */ + au_writel(0x33030a10, MEM_STTIME1); /* slower timing for FPGA */ + + /* Setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + + /* + * Enable Au1000 BCLK switching - note: sed1356 must not use + * its BCLK (Au1000 LCLK) for any timings + */ + switch (prid & 0x000000FF) { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + break; + default: /* HC and newer */ + /* + * Enable sys bus clock divider when IDLE state or no bus + * activity. + */ + au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); + break; + } +} diff --git a/arch/mips/alchemy/pb1000/init.c b/arch/mips/alchemy/pb1000/init.c new file mode 100644 index 00000000000..8a9c7d57208 --- /dev/null +++ b/arch/mips/alchemy/pb1000/init.c @@ -0,0 +1,57 @@ +/* + * BRIEF MODULE DESCRIPTION + * Pb1000 board setup + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ + return "Alchemy Pb1000"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = (int)fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtol(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/pb1000/irqmap.c b/arch/mips/alchemy/pb1000/irqmap.c new file mode 100644 index 00000000000..b3d56b0af32 --- /dev/null +++ b/arch/mips/alchemy/pb1000/irqmap.c @@ -0,0 +1,38 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 }, +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/alchemy/pb1100/Makefile b/arch/mips/alchemy/pb1100/Makefile new file mode 100644 index 00000000000..793e97c49e4 --- /dev/null +++ b/arch/mips/alchemy/pb1100/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2000, 2001, 2008 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for the Alchemy Semiconductor Pb1100 board. +# + +lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/alchemy/pb1100/board_setup.c b/arch/mips/alchemy/pb1100/board_setup.c new file mode 100644 index 00000000000..c0bfd59a7a3 --- /dev/null +++ b/arch/mips/alchemy/pb1100/board_setup.c @@ -0,0 +1,109 @@ +/* + * Copyright 2002, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +void board_reset(void) +{ + /* Hit BCSR.RST_VDDI[SOFT_RESET] */ + au_writel(0x00000000, PB1100_RST_VDDI); +} + +void __init board_setup(void) +{ + volatile void __iomem *base = (volatile void __iomem *)0xac000000UL; + + /* Set AUX clock to 12 MHz * 8 = 96 MHz */ + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PININPUTEN); + udelay(100); + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + { + u32 pin_func, sys_freqctrl, sys_clksrc; + + /* Configure pins GPIO[14:9] as GPIO */ + pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3; + + /* Zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* Zero and disable USBH/USBD/IrDA clock */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~(SYS_CS_CIR | SYS_CS_DIR | SYS_CS_MIR_MASK); + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~(SYS_CS_CIR | SYS_CS_DIR | SYS_CS_MIR_MASK); + + /* FREQ2 = aux / 2 = 48 MHz */ + sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) | + SYS_FC_FE2 | SYS_FC_FS2; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48 MHz FREQ2 into USBH/USBD/IrDA + */ + sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MIR_BIT; + au_writel(sys_clksrc, SYS_CLKSRC); + + /* Setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + + /* + * Get USB Functionality pin state (device vs host drive pins). + */ + pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_USB; + /* 2nd USB port is USB host. */ + pin_func |= SYS_PF_USB; + au_writel(pin_func, SYS_PINFUNC); + } +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ + + /* Enable sys bus clock divider when IDLE state or no bus activity. */ + au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); + + /* Enable the RTC if not already enabled. */ + if (!(readb(base + 0x28) & 0x20)) { + writeb(readb(base + 0x28) | 0x20, base + 0x28); + au_sync(); + } + /* Put the clock in BCD mode. */ + if (readb(base + 0x2C) & 0x4) { /* reg B */ + writeb(readb(base + 0x2c) & ~0x4, base + 0x2c); + au_sync(); + } +} diff --git a/arch/mips/alchemy/pb1100/init.c b/arch/mips/alchemy/pb1100/init.c new file mode 100644 index 00000000000..7c6792308bc --- /dev/null +++ b/arch/mips/alchemy/pb1100/init.c @@ -0,0 +1,60 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Pb1100 board setup + * + * Copyright 2002, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ + return "Alchemy Pb1100"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg3; + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtol(memsize_str, 0, &memsize); + + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/pb1100/irqmap.c b/arch/mips/alchemy/pb1100/irqmap.c new file mode 100644 index 00000000000..9b7dd8b4128 --- /dev/null +++ b/arch/mips/alchemy/pb1100/irqmap.c @@ -0,0 +1,40 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xx0 IRQ map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card Fully_Inserted# */ + { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card STSCHG# */ + { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card IRQ# */ + { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, /* DC_IRQ# */ +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/alchemy/pb1200/Makefile b/arch/mips/alchemy/pb1200/Makefile new file mode 100644 index 00000000000..d678adf7ce8 --- /dev/null +++ b/arch/mips/alchemy/pb1200/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards. +# + +lib-y := init.o board_setup.o irqmap.o +obj-y += platform.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/pb1200/board_setup.c b/arch/mips/alchemy/pb1200/board_setup.c new file mode 100644 index 00000000000..6cb2115059a --- /dev/null +++ b/arch/mips/alchemy/pb1200/board_setup.c @@ -0,0 +1,162 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Pb1200/Db1200 board setup. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +extern void _board_init_irq(void); +extern void (*board_init_irq)(void); + +void board_reset(void) +{ + bcsr->resets = 0; + bcsr->system = 0; +} + +void __init board_setup(void) +{ + char *argptr = NULL; + +#if 0 + { + u32 pin_func; + + /* + * Enable PSC1 SYNC for AC97. Normaly done in audio driver, + * but it is board specific code, so put it here. + */ + pin_func = au_readl(SYS_PINFUNC); + au_sync(); + pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1; + au_writel(pin_func, SYS_PINFUNC); + + au_writel(0, (u32)bcsr | 0x10); /* turn off PCMCIA power */ + au_sync(); + } +#endif + +#if defined(CONFIG_I2C_AU1550) + { + u32 freq0, clksrc; + u32 pin_func; + + /* Select SMBus in CPLD */ + bcsr->resets &= ~BCSR_RESETS_PCS0MUX; + + pin_func = au_readl(SYS_PINFUNC); + au_sync(); + pin_func &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B); + /* Set GPIOs correctly */ + pin_func |= 2 << 17; + au_writel(pin_func, SYS_PINFUNC); + au_sync(); + + /* The I2C driver depends on 50 MHz clock */ + freq0 = au_readl(SYS_FREQCTRL0); + au_sync(); + freq0 &= ~(SYS_FC_FRDIV1_MASK | SYS_FC_FS1 | SYS_FC_FE1); + freq0 |= 3 << SYS_FC_FRDIV1_BIT; + /* 396 MHz / (3 + 1) * 2 == 49.5 MHz */ + au_writel(freq0, SYS_FREQCTRL0); + au_sync(); + freq0 |= SYS_FC_FE1; + au_writel(freq0, SYS_FREQCTRL0); + au_sync(); + + clksrc = au_readl(SYS_CLKSRC); + au_sync(); + clksrc &= ~(SYS_CS_CE0 | SYS_CS_DE0 | SYS_CS_ME0_MASK); + /* Bit 22 is EXTCLK0 for PSC0 */ + clksrc |= SYS_CS_MUX_FQ1 << SYS_CS_ME0_BIT; + au_writel(clksrc, SYS_CLKSRC); + au_sync(); + } +#endif + +#ifdef CONFIG_FB_AU1200 + argptr = prom_getcmdline(); +#ifdef CONFIG_MIPS_PB1200 + strcat(argptr, " video=au1200fb:panel:bs"); +#endif +#ifdef CONFIG_MIPS_DB1200 + strcat(argptr, " video=au1200fb:panel:bs"); +#endif +#endif + + /* + * The Pb1200 development board uses external MUX for PSC0 to + * support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI + */ +#ifdef CONFIG_I2C_AU1550 + bcsr->resets &= ~BCSR_RESETS_PCS0MUX; +#endif + au_sync(); + +#ifdef CONFIG_MIPS_PB1200 + printk(KERN_INFO "AMD Alchemy Pb1200 Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1200 + printk(KERN_INFO "AMD Alchemy Db1200 Board\n"); +#endif + + /* Setup Pb1200 External Interrupt Controller */ + board_init_irq = _board_init_irq; +} + +int board_au1200fb_panel(void) +{ + BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; + int p; + + p = bcsr->switches; + p >>= 8; + p &= 0x0F; + return p; +} + +int board_au1200fb_panel_init(void) +{ + /* Apply power */ + BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; + + bcsr->board |= BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL; + /* printk(KERN_DEBUG "board_au1200fb_panel_init()\n"); */ + return 0; +} + +int board_au1200fb_panel_shutdown(void) +{ + /* Remove power */ + BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; + + bcsr->board &= ~(BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | + BCSR_BOARD_LCDBL); + /* printk(KERN_DEBUG "board_au1200fb_panel_shutdown()\n"); */ + return 0; +} diff --git a/arch/mips/alchemy/pb1200/init.c b/arch/mips/alchemy/pb1200/init.c new file mode 100644 index 00000000000..e9b2a0fd48a --- /dev/null +++ b/arch/mips/alchemy/pb1200/init.c @@ -0,0 +1,58 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PB1200 board setup + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ + return "Alchemy Pb1200"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = (int)fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x08000000; + else + strict_strtol(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/pb1200/irqmap.c b/arch/mips/alchemy/pb1200/irqmap.c new file mode 100644 index 00000000000..2a505ad8715 --- /dev/null +++ b/arch/mips/alchemy/pb1200/irqmap.c @@ -0,0 +1,160 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#ifdef CONFIG_MIPS_PB1200 +#include +#endif + +#ifdef CONFIG_MIPS_DB1200 +#include +#define PB1200_INT_BEGIN DB1200_INT_BEGIN +#define PB1200_INT_END DB1200_INT_END +#endif + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + /* This is external interrupt cascade */ + { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); + +/* + * Support for External interrupts on the Pb1200 Development platform. + */ +static volatile int pb1200_cascade_en; + +irqreturn_t pb1200_cascade_handler(int irq, void *dev_id) +{ + unsigned short bisr = bcsr->int_status; + int extirq_nr = 0; + + /* Clear all the edge interrupts. This has no effect on level. */ + bcsr->int_status = bisr; + for ( ; bisr; bisr &= bisr - 1) { + extirq_nr = PB1200_INT_BEGIN + __ffs(bisr); + /* Ack and dispatch IRQ */ + do_IRQ(extirq_nr); + } + + return IRQ_RETVAL(1); +} + +inline void pb1200_enable_irq(unsigned int irq_nr) +{ + bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN); + bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN); +} + +inline void pb1200_disable_irq(unsigned int irq_nr) +{ + bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN); + bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN); +} + +static unsigned int pb1200_setup_cascade(void) +{ + return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler, + 0, "Pb1200 Cascade", &pb1200_cascade_handler); +} + +static unsigned int pb1200_startup_irq(unsigned int irq) +{ + if (++pb1200_cascade_en == 1) { + int res; + + res = pb1200_setup_cascade(); + if (res) + return res; + } + + pb1200_enable_irq(irq); + + return 0; +} + +static void pb1200_shutdown_irq(unsigned int irq) +{ + pb1200_disable_irq(irq); + if (--pb1200_cascade_en == 0) + free_irq(AU1000_GPIO_7, &pb1200_cascade_handler); +} + +static struct irq_chip external_irq_type = { +#ifdef CONFIG_MIPS_PB1200 + .name = "Pb1200 Ext", +#endif +#ifdef CONFIG_MIPS_DB1200 + .name = "Db1200 Ext", +#endif + .startup = pb1200_startup_irq, + .shutdown = pb1200_shutdown_irq, + .ack = pb1200_disable_irq, + .mask = pb1200_disable_irq, + .mask_ack = pb1200_disable_irq, + .unmask = pb1200_enable_irq, +}; + +void _board_init_irq(void) +{ + unsigned int irq; + +#ifdef CONFIG_MIPS_PB1200 + /* We have a problem with CPLD rev 3. */ + if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) { + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "Pb1200 must be at CPLD rev 4. Please have Pb1200\n"); + printk(KERN_ERR "updated to latest revision. This software will\n"); + printk(KERN_ERR "not work on anything less than CPLD rev 4.\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + printk(KERN_ERR "WARNING!!!\n"); + panic("Game over. Your score is 0."); + } +#endif + + for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) { + set_irq_chip_and_handler(irq, &external_irq_type, + handle_level_irq); + pb1200_disable_irq(irq); + } + + /* + * GPIO_7 can not be hooked here, so it is hooked upon first + * request of any source attached to the cascade. + */ +} diff --git a/arch/mips/alchemy/pb1200/platform.c b/arch/mips/alchemy/pb1200/platform.c new file mode 100644 index 00000000000..f8fb0aeac57 --- /dev/null +++ b/arch/mips/alchemy/pb1200/platform.c @@ -0,0 +1,85 @@ +/* + * Pb1200/DBAu1200 board platform device registration + * + * Copyright (C) 2008 MontaVista Software Inc. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include + +static struct resource ide_resources[] = { + [0] = { + .start = IDE_PHYS_ADDR, + .end = IDE_PHYS_ADDR + IDE_PHYS_LEN - 1, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = IDE_INT, + .end = IDE_INT, + .flags = IORESOURCE_IRQ + } +}; + +static u64 ide_dmamask = DMA_32BIT_MASK; + +static struct platform_device ide_device = { + .name = "au1200-ide", + .id = 0, + .dev = { + .dma_mask = &ide_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .num_resources = ARRAY_SIZE(ide_resources), + .resource = ide_resources +}; + +static struct resource smc91c111_resources[] = { + [0] = { + .name = "smc91x-regs", + .start = SMC91C111_PHYS_ADDR, + .end = SMC91C111_PHYS_ADDR + 0xf, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = SMC91C111_INT, + .end = SMC91C111_INT, + .flags = IORESOURCE_IRQ + }, +}; + +static struct platform_device smc91c111_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(smc91c111_resources), + .resource = smc91c111_resources +}; + +static struct platform_device *board_platform_devices[] __initdata = { + &ide_device, + &smc91c111_device +}; + +static int __init board_register_devices(void) +{ + return platform_add_devices(board_platform_devices, + ARRAY_SIZE(board_platform_devices)); +} + +arch_initcall(board_register_devices); diff --git a/arch/mips/alchemy/pb1500/Makefile b/arch/mips/alchemy/pb1500/Makefile new file mode 100644 index 00000000000..602f38df20b --- /dev/null +++ b/arch/mips/alchemy/pb1500/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2000, 2001, 2008 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for the Alchemy Semiconductor Pb1500 board. +# + +lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/alchemy/pb1500/board_setup.c b/arch/mips/alchemy/pb1500/board_setup.c new file mode 100644 index 00000000000..035771c6e5b --- /dev/null +++ b/arch/mips/alchemy/pb1500/board_setup.c @@ -0,0 +1,119 @@ +/* + * Copyright 2000, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +void board_reset(void) +{ + /* Hit BCSR.RST_VDDI[SOFT_RESET] */ + au_writel(0x00000000, PB1500_RST_VDDI); +} + +void __init board_setup(void) +{ + u32 pin_func; + u32 sys_freqctrl, sys_clksrc; + + sys_clksrc = sys_freqctrl = pin_func = 0; + /* Set AUX clock to 12 MHz * 8 = 96 MHz */ + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PINSTATERD); + udelay(100); + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + + /* GPIO201 is input for PCMCIA card detect */ + /* GPIO203 is input for PCMCIA interrupt request */ + au_writel(au_readl(GPIO2_DIR) & ~((1 << 1) | (1 << 3)), GPIO2_DIR); + + /* Zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | + SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | + SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); + + /* FREQ2 = aux/2 = 48 MHz */ + sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) | SYS_FC_FE2 | SYS_FC_FS2; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USB Host and/or Device + */ + sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MUH_BIT; + au_writel(sys_clksrc, SYS_CLKSRC); + + pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_USB; + /* 2nd USB port is USB host */ + pin_func |= SYS_PF_USB; + au_writel(pin_func, SYS_PINFUNC); +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ + +#ifdef CONFIG_PCI + /* Setup PCI bus controller */ + au_writel(0, Au1500_PCI_CMEM); + au_writel(0x00003fff, Au1500_CFG_BASE); +#if defined(__MIPSEB__) + au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif + au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV); + au_writel(0, Au1500_PCI_MWBASE_REV_CCL); + au_writel(0x02a00356, Au1500_PCI_STATCMD); + au_writel(0x00003c04, Au1500_PCI_HDRTYPE); + au_writel(0x00000008, Au1500_PCI_MBAR); + au_sync(); +#endif + + /* Enable sys bus clock divider when IDLE state or no bus activity. */ + au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); + + /* Enable the RTC if not already enabled */ + if (!(au_readl(0xac000028) & 0x20)) { + printk(KERN_INFO "enabling clock ...\n"); + au_writel((au_readl(0xac000028) | 0x20), 0xac000028); + } + /* Put the clock in BCD mode */ + if (au_readl(0xac00002c) & 0x4) { /* reg B */ + au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c); + au_sync(); + } +} diff --git a/arch/mips/alchemy/pb1500/init.c b/arch/mips/alchemy/pb1500/init.c new file mode 100644 index 00000000000..3b6e395cf95 --- /dev/null +++ b/arch/mips/alchemy/pb1500/init.c @@ -0,0 +1,58 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Pb1500 board setup + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ + return "Alchemy Pb1500"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = (int)fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtol(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/pb1500/irqmap.c b/arch/mips/alchemy/pb1500/irqmap.c new file mode 100644 index 00000000000..39c4682766a --- /dev/null +++ b/arch/mips/alchemy/pb1500/irqmap.c @@ -0,0 +1,46 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +char irq_tab_alchemy[][5] __initdata = { + [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT370 */ + [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */ +}; + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, + { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/alchemy/pb1550/Makefile b/arch/mips/alchemy/pb1550/Makefile new file mode 100644 index 00000000000..7d8beca87fa --- /dev/null +++ b/arch/mips/alchemy/pb1550/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2000, 2008 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for the Alchemy Semiconductor Pb1550 board. +# + +lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/alchemy/pb1550/board_setup.c b/arch/mips/alchemy/pb1550/board_setup.c new file mode 100644 index 00000000000..0ed76b64b6a --- /dev/null +++ b/arch/mips/alchemy/pb1550/board_setup.c @@ -0,0 +1,58 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Pb1550 board setup. + * + * Copyright 2000, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include + +void board_reset(void) +{ + /* Hit BCSR.SYSTEM[RESET] */ + au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C); +} + +void __init board_setup(void) +{ + u32 pin_func; + + /* + * Enable PSC1 SYNC for AC'97. Normaly done in audio driver, + * but it is board specific code, so put it here. + */ + pin_func = au_readl(SYS_PINFUNC); + au_sync(); + pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1; + au_writel(pin_func, SYS_PINFUNC); + + au_writel(0, (u32)bcsr | 0x10); /* turn off PCMCIA power */ + au_sync(); + + printk(KERN_INFO "AMD Alchemy Pb1550 Board\n"); +} diff --git a/arch/mips/alchemy/pb1550/init.c b/arch/mips/alchemy/pb1550/init.c new file mode 100644 index 00000000000..e1055a13a1a --- /dev/null +++ b/arch/mips/alchemy/pb1550/init.c @@ -0,0 +1,58 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Pb1550 board setup + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ + return "Alchemy Pb1550"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = (int)fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x08000000; + else + strict_strtol(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/pb1550/irqmap.c b/arch/mips/alchemy/pb1550/irqmap.c new file mode 100644 index 00000000000..a02a4d1fa89 --- /dev/null +++ b/arch/mips/alchemy/pb1550/irqmap.c @@ -0,0 +1,43 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xx0 IRQ map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +char irq_tab_alchemy[][5] __initdata = { + [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */ + [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */ +}; + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/alchemy/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile new file mode 100644 index 00000000000..db3c526f64d --- /dev/null +++ b/arch/mips/alchemy/xxs1500/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2003 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for MyCable XXS1500 board. +# + +lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/alchemy/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c new file mode 100644 index 00000000000..4c587acac5c --- /dev/null +++ b/arch/mips/alchemy/xxs1500/board_setup.c @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +void board_reset(void) +{ + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); +} + +void __init board_setup(void) +{ + u32 pin_func; + + /* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */ + pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3; + pin_func |= SYS_PF_UR3; + au_writel(pin_func, SYS_PINFUNC); + + /* Enable UART */ + au_writel(0x01, UART3_ADDR + UART_MOD_CNTRL); /* clock enable (CE) */ + mdelay(10); + au_writel(0x03, UART3_ADDR + UART_MOD_CNTRL); /* CE and "enable" */ + mdelay(10); + + /* Enable DTR = USB power up */ + au_writel(0x01, UART3_ADDR + UART_MCR); /* UART_MCR_DTR is 0x01??? */ + +#ifdef CONFIG_PCMCIA_XXS1500 + /* Setup PCMCIA signals */ + au_writel(0, SYS_PININPUTEN); + + /* GPIO 0, 1, and 4 are inputs */ + au_writel(1 | (1 << 1) | (1 << 4), SYS_TRIOUTCLR); + + /* Enable GPIO2 if not already enabled */ + au_writel(1, GPIO2_ENABLE); + /* GPIO2 208/9/10/11 are inputs */ + au_writel((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11), GPIO2_DIR); + + /* Turn off power */ + au_writel((au_readl(GPIO2_PINSTATE) & ~(1 << 14)) | (1 << 30), + GPIO2_OUTPUT); +#endif + +#ifdef CONFIG_PCI +#if defined(__MIPSEB__) + au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif +#endif +} diff --git a/arch/mips/alchemy/xxs1500/init.c b/arch/mips/alchemy/xxs1500/init.c new file mode 100644 index 00000000000..7516434760a --- /dev/null +++ b/arch/mips/alchemy/xxs1500/init.c @@ -0,0 +1,58 @@ +/* + * BRIEF MODULE DESCRIPTION + * XXS1500 board setup + * + * Copyright 2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include + +const char *get_system_type(void) +{ + return "XXS1500"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtol(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/alchemy/xxs1500/irqmap.c b/arch/mips/alchemy/xxs1500/irqmap.c new file mode 100644 index 00000000000..edf06ed1187 --- /dev/null +++ b/arch/mips/alchemy/xxs1500/irqmap.c @@ -0,0 +1,49 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, + { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */ + { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, +}; + +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig deleted file mode 100644 index e4a057d80ab..00000000000 --- a/arch/mips/au1000/Kconfig +++ /dev/null @@ -1,136 +0,0 @@ -choice - prompt "Machine type" - depends on MACH_ALCHEMY - default MIPS_DB1000 - -config MIPS_MTX1 - bool "4G Systems MTX-1 board" - select DMA_NONCOHERENT - select HW_HAS_PCI - select SOC_AU1500 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_BOSPORUS - bool "Alchemy Bosporus board" - select SOC_AU1500 - select DMA_NONCOHERENT - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1000 - bool "Alchemy DB1000 board" - select SOC_AU1000 - select DMA_NONCOHERENT - select HW_HAS_PCI - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1100 - bool "Alchemy DB1100 board" - select SOC_AU1100 - select DMA_NONCOHERENT - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1200 - bool "Alchemy DB1200 board" - select SOC_AU1200 - select DMA_COHERENT - select MIPS_DISABLE_OBSOLETE_IDE - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1500 - bool "Alchemy DB1500 board" - select SOC_AU1500 - select DMA_NONCOHERENT - select HW_HAS_PCI - select MIPS_DISABLE_OBSOLETE_IDE - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1550 - bool "Alchemy DB1550 board" - select SOC_AU1550 - select HW_HAS_PCI - select DMA_NONCOHERENT - select MIPS_DISABLE_OBSOLETE_IDE - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_MIRAGE - bool "Alchemy Mirage board" - select DMA_NONCOHERENT - select SOC_AU1500 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1000 - bool "Alchemy PB1000 board" - select SOC_AU1000 - select DMA_NONCOHERENT - select HW_HAS_PCI - select SWAP_IO_SPACE - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1100 - bool "Alchemy PB1100 board" - select SOC_AU1100 - select DMA_NONCOHERENT - select HW_HAS_PCI - select SWAP_IO_SPACE - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1200 - bool "Alchemy PB1200 board" - select SOC_AU1200 - select DMA_NONCOHERENT - select MIPS_DISABLE_OBSOLETE_IDE - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1500 - bool "Alchemy PB1500 board" - select SOC_AU1500 - select DMA_NONCOHERENT - select HW_HAS_PCI - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1550 - bool "Alchemy PB1550 board" - select SOC_AU1550 - select DMA_NONCOHERENT - select HW_HAS_PCI - select MIPS_DISABLE_OBSOLETE_IDE - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_XXS1500 - bool "MyCable XXS1500 board" - select DMA_NONCOHERENT - select SOC_AU1500 - select SYS_SUPPORTS_LITTLE_ENDIAN - -endchoice - -config SOC_AU1000 - bool - select SOC_AU1X00 - -config SOC_AU1100 - bool - select SOC_AU1X00 - -config SOC_AU1500 - bool - select SOC_AU1X00 - -config SOC_AU1550 - bool - select SOC_AU1X00 - -config SOC_AU1200 - bool - select SOC_AU1X00 - -config SOC_AU1X00 - bool - select 64BIT_PHYS_ADDR - select CEVT_R4K - select CSRC_R4K - select IRQ_CPU - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_APM_EMULATION diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile deleted file mode 100644 index df48fd65bbf..00000000000 --- a/arch/mips/au1000/common/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright 2000, 2008 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# -# Makefile for the Alchemy Au1xx0 CPUs, generic files. -# - -obj-y += prom.o irq.o puts.o time.o reset.o \ - au1xxx_irqmap.o clocks.o platform.o power.o setup.o \ - sleeper.o cputable.o dma.o dbdma.o gpio.o - -obj-$(CONFIG_PCI) += pci.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c deleted file mode 100644 index c7ca1596394..00000000000 --- a/arch/mips/au1000/common/au1xxx_irqmap.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xxx processor specific IRQ tables - * - * Copyright 2004 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include - -#include - -/* The IC0 interrupt table. This is processor, rather than - * board dependent, so no reason to keep this info in the board - * dependent files. - * - * Careful if you change match 2 request! - * The interrupt handler is called directly from the low level dispatch code. - */ -struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = { - -#if defined(CONFIG_SOC_AU1000) - { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, - { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, - -#elif defined(CONFIG_SOC_AU1500) - - { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, - { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, - -#elif defined(CONFIG_SOC_AU1100) - - { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, - { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - /* { AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0 }, */ - { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, - -#elif defined(CONFIG_SOC_AU1550) - - { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, - { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, - { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, - { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, - { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 }, - { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, - { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, - { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - -#elif defined(CONFIG_SOC_AU1200) - - { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, - { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0 }, - { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0 }, - -#else -#error "Error: Unknown Alchemy SOC" -#endif - -}; - -int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map); diff --git a/arch/mips/au1000/common/clocks.c b/arch/mips/au1000/common/clocks.c deleted file mode 100644 index 043429d17c5..00000000000 --- a/arch/mips/au1000/common/clocks.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Simple Au1xx0 clocks routines. - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -static unsigned int au1x00_clock; /* Hz */ -static unsigned int lcd_clock; /* KHz */ -static unsigned long uart_baud_base; - -/* - * Set the au1000_clock - */ -void set_au1x00_speed(unsigned int new_freq) -{ - au1x00_clock = new_freq; -} - -unsigned int get_au1x00_speed(void) -{ - return au1x00_clock; -} -EXPORT_SYMBOL(get_au1x00_speed); - -/* - * The UART baud base is not known at compile time ... if - * we want to be able to use the same code on different - * speed CPUs. - */ -unsigned long get_au1x00_uart_baud_base(void) -{ - return uart_baud_base; -} - -void set_au1x00_uart_baud_base(unsigned long new_baud_base) -{ - uart_baud_base = new_baud_base; -} - -/* - * Calculate the Au1x00's LCD clock based on the current - * cpu clock and the system bus clock, and try to keep it - * below 40 MHz (the Pb1000 board can lock-up if the LCD - * clock is over 40 MHz). - */ -void set_au1x00_lcd_clock(void) -{ - unsigned int static_cfg0; - unsigned int sys_busclk = (get_au1x00_speed() / 1000) / - ((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2); - - static_cfg0 = au_readl(MEM_STCFG0); - - if (static_cfg0 & (1 << 11)) - lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */ - else - lcd_clock = sys_busclk / 4; - - if (lcd_clock > 50000) /* Epson MAX */ - printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n", - lcd_clock); -} - -unsigned int get_au1x00_lcd_clock(void) -{ - return lcd_clock; -} -EXPORT_SYMBOL(get_au1x00_lcd_clock); diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c deleted file mode 100644 index ba6430bc2d0..00000000000 --- a/arch/mips/au1000/common/cputable.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * arch/mips/au1000/common/cputable.c - * - * Copyright (C) 2004 Dan Malek (dan@embeddededge.com) - * Copied from PowerPC and updated for Alchemy Au1xxx processors. - * - * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include - -struct cpu_spec *cur_cpu_spec[NR_CPUS]; - -/* With some thought, we can probably use the mask to reduce the - * size of the table. - */ -struct cpu_spec cpu_specs[] = { - { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 }, - { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 }, - { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 }, - { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 }, - { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 }, - { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 }, - { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 }, - { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 }, - { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 }, - { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 }, - { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 }, - { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 }, - { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 }, - { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 }, - { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 }, - { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 }, - { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 } -}; - -void set_cpuspec(void) -{ - struct cpu_spec *sp; - u32 prid; - - prid = read_c0_prid(); - sp = cpu_specs; - while ((prid & sp->prid_mask) != sp->prid_value) - sp++; - cur_cpu_spec[0] = sp; -} diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c deleted file mode 100644 index 601ee9180ee..00000000000 --- a/arch/mips/au1000/common/dbdma.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * The Descriptor Based DMA channel manager that first appeared - * on the Au1550. I started with dma.c, but I think all that is - * left is this initial comment :-) - * - * Copyright 2004 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) - -/* - * The Descriptor Based DMA supports up to 16 channels. - * - * There are 32 devices defined. We keep an internal structure - * of devices using these channels, along with additional - * information. - * - * We allocate the descriptors and allow access to them through various - * functions. The drivers allocate the data buffers and assign them - * to the descriptors. - */ -static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock); - -/* I couldn't find a macro that did this... */ -#define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) - -static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; -static int dbdma_initialized; -static void au1xxx_dbdma_init(void); - -static dbdev_tab_t dbdev_tab[] = { -#ifdef CONFIG_SOC_AU1550 - /* UARTS */ - { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 }, - { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 }, - { DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 }, - { DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 }, - - /* EXT DMA */ - { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 }, - - /* USB DEV */ - { DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 }, - { DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 }, - { DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 }, - { DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 }, - { DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 }, - { DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 }, - - /* PSC 0 */ - { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, - { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, - - /* PSC 1 */ - { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 }, - { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, - - /* PSC 2 */ - { DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 }, - { DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 }, - - /* PSC 3 */ - { DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 }, - { DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 }, - - { DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */ - { DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */ - - /* MAC 0 */ - { DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, - - /* MAC 1 */ - { DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, - -#endif /* CONFIG_SOC_AU1550 */ - -#ifdef CONFIG_SOC_AU1200 - { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 }, - { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 }, - { DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 }, - { DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 }, - - { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 }, - - { DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - - { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 }, - { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 }, - { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 }, - { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 }, - - { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 }, - { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 }, - - { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 }, - { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 16, 0x11a0001c, 0, 0 }, - { DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - - { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 }, - { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 16, 0x11b0001c, 0, 0 }, - { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - - { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 }, - { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 }, - { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 }, - { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - - { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, - -#endif /* CONFIG_SOC_AU1200 */ - - { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - - /* Provide 16 user definable device types */ - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, - { ~0, 0, 0, 0, 0, 0, 0 }, -}; - -#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab) - -static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS]; - -static dbdev_tab_t *find_dbdev_id(u32 id) -{ - int i; - dbdev_tab_t *p; - for (i = 0; i < DBDEV_TAB_SIZE; ++i) { - p = &dbdev_tab[i]; - if (p->dev_id == id) - return p; - } - return NULL; -} - -void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp) -{ - return phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); -} -EXPORT_SYMBOL(au1xxx_ddma_get_nextptr_virt); - -u32 au1xxx_ddma_add_device(dbdev_tab_t *dev) -{ - u32 ret = 0; - dbdev_tab_t *p; - static u16 new_id = 0x1000; - - p = find_dbdev_id(~0); - if (NULL != p) { - memcpy(p, dev, sizeof(dbdev_tab_t)); - p->dev_id = DSCR_DEV2CUSTOM_ID(new_id, dev->dev_id); - ret = p->dev_id; - new_id++; -#if 0 - printk(KERN_DEBUG "add_device: id:%x flags:%x padd:%x\n", - p->dev_id, p->dev_flags, p->dev_physaddr); -#endif - } - - return ret; -} -EXPORT_SYMBOL(au1xxx_ddma_add_device); - -void au1xxx_ddma_del_device(u32 devid) -{ - dbdev_tab_t *p = find_dbdev_id(devid); - - if (p != NULL) { - memset(p, 0, sizeof(dbdev_tab_t)); - p->dev_id = ~0; - } -} -EXPORT_SYMBOL(au1xxx_ddma_del_device); - -/* Allocate a channel and return a non-zero descriptor if successful. */ -u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, - void (*callback)(int, void *), void *callparam) -{ - unsigned long flags; - u32 used, chan, rv; - u32 dcp; - int i; - dbdev_tab_t *stp, *dtp; - chan_tab_t *ctp; - au1x_dma_chan_t *cp; - - /* - * We do the intialization on the first channel allocation. - * We have to wait because of the interrupt handler initialization - * which can't be done successfully during board set up. - */ - if (!dbdma_initialized) - au1xxx_dbdma_init(); - dbdma_initialized = 1; - - stp = find_dbdev_id(srcid); - if (stp == NULL) - return 0; - dtp = find_dbdev_id(destid); - if (dtp == NULL) - return 0; - - used = 0; - rv = 0; - - /* Check to see if we can get both channels. */ - spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); - if (!(stp->dev_flags & DEV_FLAGS_INUSE) || - (stp->dev_flags & DEV_FLAGS_ANYUSE)) { - /* Got source */ - stp->dev_flags |= DEV_FLAGS_INUSE; - if (!(dtp->dev_flags & DEV_FLAGS_INUSE) || - (dtp->dev_flags & DEV_FLAGS_ANYUSE)) { - /* Got destination */ - dtp->dev_flags |= DEV_FLAGS_INUSE; - } else { - /* Can't get dest. Release src. */ - stp->dev_flags &= ~DEV_FLAGS_INUSE; - used++; - } - } else - used++; - spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); - - if (!used) { - /* Let's see if we can allocate a channel for it. */ - ctp = NULL; - chan = 0; - spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); - for (i = 0; i < NUM_DBDMA_CHANS; i++) - if (chan_tab_ptr[i] == NULL) { - /* - * If kmalloc fails, it is caught below same - * as a channel not available. - */ - ctp = kmalloc(sizeof(chan_tab_t), GFP_ATOMIC); - chan_tab_ptr[i] = ctp; - break; - } - spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); - - if (ctp != NULL) { - memset(ctp, 0, sizeof(chan_tab_t)); - ctp->chan_index = chan = i; - dcp = DDMA_CHANNEL_BASE; - dcp += (0x0100 * chan); - ctp->chan_ptr = (au1x_dma_chan_t *)dcp; - cp = (au1x_dma_chan_t *)dcp; - ctp->chan_src = stp; - ctp->chan_dest = dtp; - ctp->chan_callback = callback; - ctp->chan_callparam = callparam; - - /* Initialize channel configuration. */ - i = 0; - if (stp->dev_intlevel) - i |= DDMA_CFG_SED; - if (stp->dev_intpolarity) - i |= DDMA_CFG_SP; - if (dtp->dev_intlevel) - i |= DDMA_CFG_DED; - if (dtp->dev_intpolarity) - i |= DDMA_CFG_DP; - if ((stp->dev_flags & DEV_FLAGS_SYNC) || - (dtp->dev_flags & DEV_FLAGS_SYNC)) - i |= DDMA_CFG_SYNC; - cp->ddma_cfg = i; - au_sync(); - - /* Return a non-zero value that can be used to - * find the channel information in subsequent - * operations. - */ - rv = (u32)(&chan_tab_ptr[chan]); - } else { - /* Release devices */ - stp->dev_flags &= ~DEV_FLAGS_INUSE; - dtp->dev_flags &= ~DEV_FLAGS_INUSE; - } - } - return rv; -} -EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); - -/* - * Set the device width if source or destination is a FIFO. - * Should be 8, 16, or 32 bits. - */ -u32 au1xxx_dbdma_set_devwidth(u32 chanid, int bits) -{ - u32 rv; - chan_tab_t *ctp; - dbdev_tab_t *stp, *dtp; - - ctp = *((chan_tab_t **)chanid); - stp = ctp->chan_src; - dtp = ctp->chan_dest; - rv = 0; - - if (stp->dev_flags & DEV_FLAGS_IN) { /* Source in fifo */ - rv = stp->dev_devwidth; - stp->dev_devwidth = bits; - } - if (dtp->dev_flags & DEV_FLAGS_OUT) { /* Destination out fifo */ - rv = dtp->dev_devwidth; - dtp->dev_devwidth = bits; - } - - return rv; -} -EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth); - -/* Allocate a descriptor ring, initializing as much as possible. */ -u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries) -{ - int i; - u32 desc_base, srcid, destid; - u32 cmd0, cmd1, src1, dest1; - u32 src0, dest0; - chan_tab_t *ctp; - dbdev_tab_t *stp, *dtp; - au1x_ddma_desc_t *dp; - - /* - * I guess we could check this to be within the - * range of the table...... - */ - ctp = *((chan_tab_t **)chanid); - stp = ctp->chan_src; - dtp = ctp->chan_dest; - - /* - * The descriptors must be 32-byte aligned. There is a - * possibility the allocation will give us such an address, - * and if we try that first we are likely to not waste larger - * slabs of memory. - */ - desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), - GFP_KERNEL|GFP_DMA); - if (desc_base == 0) - return 0; - - if (desc_base & 0x1f) { - /* - * Lost....do it again, allocate extra, and round - * the address base. - */ - kfree((const void *)desc_base); - i = entries * sizeof(au1x_ddma_desc_t); - i += (sizeof(au1x_ddma_desc_t) - 1); - desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA); - if (desc_base == 0) - return 0; - - desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); - } - dp = (au1x_ddma_desc_t *)desc_base; - - /* Keep track of the base descriptor. */ - ctp->chan_desc_base = dp; - - /* Initialize the rings with as much information as we know. */ - srcid = stp->dev_id; - destid = dtp->dev_id; - - cmd0 = cmd1 = src1 = dest1 = 0; - src0 = dest0 = 0; - - cmd0 |= DSCR_CMD0_SID(srcid); - cmd0 |= DSCR_CMD0_DID(destid); - cmd0 |= DSCR_CMD0_IE | DSCR_CMD0_CV; - cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_NOCHANGE); - - /* Is it mem to mem transfer? */ - if (((DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_THROTTLE) || - (DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_ALWAYS)) && - ((DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_THROTTLE) || - (DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_ALWAYS))) - cmd0 |= DSCR_CMD0_MEM; - - switch (stp->dev_devwidth) { - case 8: - cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_BYTE); - break; - case 16: - cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_HALFWORD); - break; - case 32: - default: - cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_WORD); - break; - } - - switch (dtp->dev_devwidth) { - case 8: - cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_BYTE); - break; - case 16: - cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_HALFWORD); - break; - case 32: - default: - cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_WORD); - break; - } - - /* - * If the device is marked as an in/out FIFO, ensure it is - * set non-coherent. - */ - if (stp->dev_flags & DEV_FLAGS_IN) - cmd0 |= DSCR_CMD0_SN; /* Source in FIFO */ - if (dtp->dev_flags & DEV_FLAGS_OUT) - cmd0 |= DSCR_CMD0_DN; /* Destination out FIFO */ - - /* - * Set up source1. For now, assume no stride and increment. - * A channel attribute update can change this later. - */ - switch (stp->dev_tsize) { - case 1: - src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE1); - break; - case 2: - src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE2); - break; - case 4: - src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE4); - break; - case 8: - default: - src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE8); - break; - } - - /* If source input is FIFO, set static address. */ - if (stp->dev_flags & DEV_FLAGS_IN) { - if (stp->dev_flags & DEV_FLAGS_BURSTABLE) - src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST); - else - src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); - } - - if (stp->dev_physaddr) - src0 = stp->dev_physaddr; - - /* - * Set up dest1. For now, assume no stride and increment. - * A channel attribute update can change this later. - */ - switch (dtp->dev_tsize) { - case 1: - dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE1); - break; - case 2: - dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE2); - break; - case 4: - dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE4); - break; - case 8: - default: - dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE8); - break; - } - - /* If destination output is FIFO, set static address. */ - if (dtp->dev_flags & DEV_FLAGS_OUT) { - if (dtp->dev_flags & DEV_FLAGS_BURSTABLE) - dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST); - else - dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); - } - - if (dtp->dev_physaddr) - dest0 = dtp->dev_physaddr; - -#if 0 - printk(KERN_DEBUG "did:%x sid:%x cmd0:%x cmd1:%x source0:%x " - "source1:%x dest0:%x dest1:%x\n", - dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, - src1, dest0, dest1); -#endif - for (i = 0; i < entries; i++) { - dp->dscr_cmd0 = cmd0; - dp->dscr_cmd1 = cmd1; - dp->dscr_source0 = src0; - dp->dscr_source1 = src1; - dp->dscr_dest0 = dest0; - dp->dscr_dest1 = dest1; - dp->dscr_stat = 0; - dp->sw_context = 0; - dp->sw_status = 0; - dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); - dp++; - } - - /* Make last descrptor point to the first. */ - dp--; - dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(ctp->chan_desc_base)); - ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base; - - return (u32)ctp->chan_desc_base; -} -EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc); - -/* - * Put a source buffer into the DMA ring. - * This updates the source pointer and byte count. Normally used - * for memory to fifo transfers. - */ -u32 _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags) -{ - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - /* - * I guess we could check this to be within the - * range of the table...... - */ - ctp = *(chan_tab_t **)chanid; - - /* - * We should have multiple callers for a particular channel, - * an interrupt doesn't affect this pointer nor the descriptor, - * so no locking should be needed. - */ - dp = ctp->put_ptr; - - /* - * If the descriptor is valid, we are way ahead of the DMA - * engine, so just return an error condition. - */ - if (dp->dscr_cmd0 & DSCR_CMD0_V) - return 0; - - /* Load up buffer address and byte count. */ - dp->dscr_source0 = virt_to_phys(buf); - dp->dscr_cmd1 = nbytes; - /* Check flags */ - if (flags & DDMA_FLAGS_IE) - dp->dscr_cmd0 |= DSCR_CMD0_IE; - if (flags & DDMA_FLAGS_NOIE) - dp->dscr_cmd0 &= ~DSCR_CMD0_IE; - - /* - * There is an errata on the Au1200/Au1550 parts that could result - * in "stale" data being DMA'ed. It has to do with the snoop logic on - * the cache eviction buffer. DMA_NONCOHERENT is on by default for - * these parts. If it is fixed in the future, these dma_cache_inv will - * just be nothing more than empty macros. See io.h. - */ - dma_cache_wback_inv((unsigned long)buf, nbytes); - dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ - au_sync(); - dma_cache_wback_inv((unsigned long)dp, sizeof(dp)); - ctp->chan_ptr->ddma_dbell = 0; - - /* Get next descriptor pointer. */ - ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - - /* Return something non-zero. */ - return nbytes; -} -EXPORT_SYMBOL(_au1xxx_dbdma_put_source); - -/* Put a destination buffer into the DMA ring. - * This updates the destination pointer and byte count. Normally used - * to place an empty buffer into the ring for fifo to memory transfers. - */ -u32 -_au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags) -{ - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - /* I guess we could check this to be within the - * range of the table...... - */ - ctp = *((chan_tab_t **)chanid); - - /* We should have multiple callers for a particular channel, - * an interrupt doesn't affect this pointer nor the descriptor, - * so no locking should be needed. - */ - dp = ctp->put_ptr; - - /* If the descriptor is valid, we are way ahead of the DMA - * engine, so just return an error condition. - */ - if (dp->dscr_cmd0 & DSCR_CMD0_V) - return 0; - - /* Load up buffer address and byte count */ - - /* Check flags */ - if (flags & DDMA_FLAGS_IE) - dp->dscr_cmd0 |= DSCR_CMD0_IE; - if (flags & DDMA_FLAGS_NOIE) - dp->dscr_cmd0 &= ~DSCR_CMD0_IE; - - dp->dscr_dest0 = virt_to_phys(buf); - dp->dscr_cmd1 = nbytes; -#if 0 - printk(KERN_DEBUG "cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", - dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0, - dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); -#endif - /* - * There is an errata on the Au1200/Au1550 parts that could result in - * "stale" data being DMA'ed. It has to do with the snoop logic on the - * cache eviction buffer. DMA_NONCOHERENT is on by default for these - * parts. If it is fixed in the future, these dma_cache_inv will just - * be nothing more than empty macros. See io.h. - */ - dma_cache_inv((unsigned long)buf, nbytes); - dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ - au_sync(); - dma_cache_wback_inv((unsigned long)dp, sizeof(dp)); - ctp->chan_ptr->ddma_dbell = 0; - - /* Get next descriptor pointer. */ - ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - - /* Return something non-zero. */ - return nbytes; -} -EXPORT_SYMBOL(_au1xxx_dbdma_put_dest); - -/* - * Get a destination buffer into the DMA ring. - * Normally used to get a full buffer from the ring during fifo - * to memory transfers. This does not set the valid bit, you will - * have to put another destination buffer to keep the DMA going. - */ -u32 au1xxx_dbdma_get_dest(u32 chanid, void **buf, int *nbytes) -{ - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - u32 rv; - - /* - * I guess we could check this to be within the - * range of the table...... - */ - ctp = *((chan_tab_t **)chanid); - - /* - * We should have multiple callers for a particular channel, - * an interrupt doesn't affect this pointer nor the descriptor, - * so no locking should be needed. - */ - dp = ctp->get_ptr; - - /* - * If the descriptor is valid, we are way ahead of the DMA - * engine, so just return an error condition. - */ - if (dp->dscr_cmd0 & DSCR_CMD0_V) - return 0; - - /* Return buffer address and byte count. */ - *buf = (void *)(phys_to_virt(dp->dscr_dest0)); - *nbytes = dp->dscr_cmd1; - rv = dp->dscr_stat; - - /* Get next descriptor pointer. */ - ctp->get_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - - /* Return something non-zero. */ - return rv; -} -EXPORT_SYMBOL_GPL(au1xxx_dbdma_get_dest); - -void au1xxx_dbdma_stop(u32 chanid) -{ - chan_tab_t *ctp; - au1x_dma_chan_t *cp; - int halt_timeout = 0; - - ctp = *((chan_tab_t **)chanid); - - cp = ctp->chan_ptr; - cp->ddma_cfg &= ~DDMA_CFG_EN; /* Disable channel */ - au_sync(); - while (!(cp->ddma_stat & DDMA_STAT_H)) { - udelay(1); - halt_timeout++; - if (halt_timeout > 100) { - printk(KERN_WARNING "warning: DMA channel won't halt\n"); - break; - } - } - /* clear current desc valid and doorbell */ - cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); - au_sync(); -} -EXPORT_SYMBOL(au1xxx_dbdma_stop); - -/* - * Start using the current descriptor pointer. If the DBDMA encounters - * a non-valid descriptor, it will stop. In this case, we can just - * continue by adding a buffer to the list and starting again. - */ -void au1xxx_dbdma_start(u32 chanid) -{ - chan_tab_t *ctp; - au1x_dma_chan_t *cp; - - ctp = *((chan_tab_t **)chanid); - cp = ctp->chan_ptr; - cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); - cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ - au_sync(); - cp->ddma_dbell = 0; - au_sync(); -} -EXPORT_SYMBOL(au1xxx_dbdma_start); - -void au1xxx_dbdma_reset(u32 chanid) -{ - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - au1xxx_dbdma_stop(chanid); - - ctp = *((chan_tab_t **)chanid); - ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base; - - /* Run through the descriptors and reset the valid indicator. */ - dp = ctp->chan_desc_base; - - do { - dp->dscr_cmd0 &= ~DSCR_CMD0_V; - /* - * Reset our software status -- this is used to determine - * if a descriptor is in use by upper level software. Since - * posting can reset 'V' bit. - */ - dp->sw_status = 0; - dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - } while (dp != ctp->chan_desc_base); -} -EXPORT_SYMBOL(au1xxx_dbdma_reset); - -u32 au1xxx_get_dma_residue(u32 chanid) -{ - chan_tab_t *ctp; - au1x_dma_chan_t *cp; - u32 rv; - - ctp = *((chan_tab_t **)chanid); - cp = ctp->chan_ptr; - - /* This is only valid if the channel is stopped. */ - rv = cp->ddma_bytecnt; - au_sync(); - - return rv; -} -EXPORT_SYMBOL_GPL(au1xxx_get_dma_residue); - -void au1xxx_dbdma_chan_free(u32 chanid) -{ - chan_tab_t *ctp; - dbdev_tab_t *stp, *dtp; - - ctp = *((chan_tab_t **)chanid); - stp = ctp->chan_src; - dtp = ctp->chan_dest; - - au1xxx_dbdma_stop(chanid); - - kfree((void *)ctp->chan_desc_base); - - stp->dev_flags &= ~DEV_FLAGS_INUSE; - dtp->dev_flags &= ~DEV_FLAGS_INUSE; - chan_tab_ptr[ctp->chan_index] = NULL; - - kfree(ctp); -} -EXPORT_SYMBOL(au1xxx_dbdma_chan_free); - -static irqreturn_t dbdma_interrupt(int irq, void *dev_id) -{ - u32 intstat; - u32 chan_index; - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - au1x_dma_chan_t *cp; - - intstat = dbdma_gptr->ddma_intstat; - au_sync(); - chan_index = __ffs(intstat); - - ctp = chan_tab_ptr[chan_index]; - cp = ctp->chan_ptr; - dp = ctp->cur_ptr; - - /* Reset interrupt. */ - cp->ddma_irq = 0; - au_sync(); - - if (ctp->chan_callback) - ctp->chan_callback(irq, ctp->chan_callparam); - - ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - return IRQ_RETVAL(1); -} - -static void au1xxx_dbdma_init(void) -{ - int irq_nr; - - dbdma_gptr->ddma_config = 0; - dbdma_gptr->ddma_throttle = 0; - dbdma_gptr->ddma_inten = 0xffff; - au_sync(); - -#if defined(CONFIG_SOC_AU1550) - irq_nr = AU1550_DDMA_INT; -#elif defined(CONFIG_SOC_AU1200) - irq_nr = AU1200_DDMA_INT; -#else - #error Unknown Au1x00 SOC -#endif - - if (request_irq(irq_nr, dbdma_interrupt, IRQF_DISABLED, - "Au1xxx dbdma", (void *)dbdma_gptr)) - printk(KERN_ERR "Can't get 1550 dbdma irq"); -} - -void au1xxx_dbdma_dump(u32 chanid) -{ - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - dbdev_tab_t *stp, *dtp; - au1x_dma_chan_t *cp; - u32 i = 0; - - ctp = *((chan_tab_t **)chanid); - stp = ctp->chan_src; - dtp = ctp->chan_dest; - cp = ctp->chan_ptr; - - printk(KERN_DEBUG "Chan %x, stp %x (dev %d) dtp %x (dev %d) \n", - (u32)ctp, (u32)stp, stp - dbdev_tab, (u32)dtp, - dtp - dbdev_tab); - printk(KERN_DEBUG "desc base %x, get %x, put %x, cur %x\n", - (u32)(ctp->chan_desc_base), (u32)(ctp->get_ptr), - (u32)(ctp->put_ptr), (u32)(ctp->cur_ptr)); - - printk(KERN_DEBUG "dbdma chan %x\n", (u32)cp); - printk(KERN_DEBUG "cfg %08x, desptr %08x, statptr %08x\n", - cp->ddma_cfg, cp->ddma_desptr, cp->ddma_statptr); - printk(KERN_DEBUG "dbell %08x, irq %08x, stat %08x, bytecnt %08x\n", - cp->ddma_dbell, cp->ddma_irq, cp->ddma_stat, - cp->ddma_bytecnt); - - /* Run through the descriptors */ - dp = ctp->chan_desc_base; - - do { - printk(KERN_DEBUG "Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n", - i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); - printk(KERN_DEBUG "src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n", - dp->dscr_source0, dp->dscr_source1, - dp->dscr_dest0, dp->dscr_dest1); - printk(KERN_DEBUG "stat %08x, nxtptr %08x\n", - dp->dscr_stat, dp->dscr_nxtptr); - dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - } while (dp != ctp->chan_desc_base); -} - -/* Put a descriptor into the DMA ring. - * This updates the source/destination pointers and byte count. - */ -u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr) -{ - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - u32 nbytes = 0; - - /* - * I guess we could check this to be within the - * range of the table...... - */ - ctp = *((chan_tab_t **)chanid); - - /* - * We should have multiple callers for a particular channel, - * an interrupt doesn't affect this pointer nor the descriptor, - * so no locking should be needed. - */ - dp = ctp->put_ptr; - - /* - * If the descriptor is valid, we are way ahead of the DMA - * engine, so just return an error condition. - */ - if (dp->dscr_cmd0 & DSCR_CMD0_V) - return 0; - - /* Load up buffer addresses and byte count. */ - dp->dscr_dest0 = dscr->dscr_dest0; - dp->dscr_source0 = dscr->dscr_source0; - dp->dscr_dest1 = dscr->dscr_dest1; - dp->dscr_source1 = dscr->dscr_source1; - dp->dscr_cmd1 = dscr->dscr_cmd1; - nbytes = dscr->dscr_cmd1; - /* Allow the caller to specifiy if an interrupt is generated */ - dp->dscr_cmd0 &= ~DSCR_CMD0_IE; - dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V; - ctp->chan_ptr->ddma_dbell = 0; - - /* Get next descriptor pointer. */ - ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - - /* Return something non-zero. */ - return nbytes; -} - -#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c deleted file mode 100644 index d6fbda232e6..00000000000 --- a/arch/mips/au1000/common/dma.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * A DMA channel allocator for Au1x00. API is modeled loosely off of - * linux/kernel/dma.c. - * - * Copyright 2000, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include -#include -#include -#include -#include - -#include -#include - -#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \ - defined(CONFIG_SOC_AU1100) -/* - * A note on resource allocation: - * - * All drivers needing DMA channels, should allocate and release them - * through the public routines `request_dma()' and `free_dma()'. - * - * In order to avoid problems, all processes should allocate resources in - * the same sequence and release them in the reverse order. - * - * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. - * When releasing them, first release the IRQ, then release the DMA. The - * main reason for this order is that, if you are requesting the DMA buffer - * done interrupt, you won't know the irq number until the DMA channel is - * returned from request_dma. - */ - -DEFINE_SPINLOCK(au1000_dma_spin_lock); - -struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = { - {.dev_id = -1,}, - {.dev_id = -1,}, - {.dev_id = -1,}, - {.dev_id = -1,}, - {.dev_id = -1,}, - {.dev_id = -1,}, - {.dev_id = -1,}, - {.dev_id = -1,} -}; -EXPORT_SYMBOL(au1000_dma_table); - -/* Device FIFO addresses and default DMA modes */ -static const struct dma_dev { - unsigned int fifo_addr; - unsigned int dma_mode; -} dma_dev_table[DMA_NUM_DEV] = { - {UART0_ADDR + UART_TX, 0}, - {UART0_ADDR + UART_RX, 0}, - {0, 0}, - {0, 0}, - {AC97C_DATA, DMA_DW16 }, /* coherent */ - {AC97C_DATA, DMA_DR | DMA_DW16 }, /* coherent */ - {UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC}, - {UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC}, - {USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC}, - {USBD_EP0WR, DMA_DW8 | DMA_NC}, - {USBD_EP2WR, DMA_DW8 | DMA_NC}, - {USBD_EP3WR, DMA_DW8 | DMA_NC}, - {USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC}, - {USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC}, - {I2S_DATA, DMA_DW32 | DMA_NC}, - {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC} -}; - -int au1000_dma_read_proc(char *buf, char **start, off_t fpos, - int length, int *eof, void *data) -{ - int i, len = 0; - struct dma_chan *chan; - - for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) { - chan = get_dma_chan(i); - if (chan != NULL) - len += sprintf(buf + len, "%2d: %s\n", - i, chan->dev_str); - } - - if (fpos >= len) { - *start = buf; - *eof = 1; - return 0; - } - *start = buf + fpos; - len -= fpos; - if (len > length) - return length; - *eof = 1; - return len; -} - -/* Device FIFO addresses and default DMA modes - 2nd bank */ -static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = { - { SD0_XMIT_FIFO, DMA_DS | DMA_DW8 }, /* coherent */ - { SD0_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8 }, /* coherent */ - { SD1_XMIT_FIFO, DMA_DS | DMA_DW8 }, /* coherent */ - { SD1_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8 } /* coherent */ -}; - -void dump_au1000_dma_channel(unsigned int dmanr) -{ - struct dma_chan *chan; - - if (dmanr >= NUM_AU1000_DMA_CHANNELS) - return; - chan = &au1000_dma_table[dmanr]; - - printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr); - printk(KERN_INFO " mode = 0x%08x\n", - au_readl(chan->io + DMA_MODE_SET)); - printk(KERN_INFO " addr = 0x%08x\n", - au_readl(chan->io + DMA_PERIPHERAL_ADDR)); - printk(KERN_INFO " start0 = 0x%08x\n", - au_readl(chan->io + DMA_BUFFER0_START)); - printk(KERN_INFO " start1 = 0x%08x\n", - au_readl(chan->io + DMA_BUFFER1_START)); - printk(KERN_INFO " count0 = 0x%08x\n", - au_readl(chan->io + DMA_BUFFER0_COUNT)); - printk(KERN_INFO " count1 = 0x%08x\n", - au_readl(chan->io + DMA_BUFFER1_COUNT)); -} - -/* - * Finds a free channel, and binds the requested device to it. - * Returns the allocated channel number, or negative on error. - * Requests the DMA done IRQ if irqhandler != NULL. - */ -int request_au1000_dma(int dev_id, const char *dev_str, - irq_handler_t irqhandler, - unsigned long irqflags, - void *irq_dev_id) -{ - struct dma_chan *chan; - const struct dma_dev *dev; - int i, ret; - -#if defined(CONFIG_SOC_AU1100) - if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2)) - return -EINVAL; -#else - if (dev_id < 0 || dev_id >= DMA_NUM_DEV) - return -EINVAL; -#endif - - for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) - if (au1000_dma_table[i].dev_id < 0) - break; - - if (i == NUM_AU1000_DMA_CHANNELS) - return -ENODEV; - - chan = &au1000_dma_table[i]; - - if (dev_id >= DMA_NUM_DEV) { - dev_id -= DMA_NUM_DEV; - dev = &dma_dev_table_bank2[dev_id]; - } else - dev = &dma_dev_table[dev_id]; - - if (irqhandler) { - chan->irq = AU1000_DMA_INT_BASE + i; - chan->irq_dev = irq_dev_id; - ret = request_irq(chan->irq, irqhandler, irqflags, dev_str, - chan->irq_dev); - if (ret) { - chan->irq = 0; - chan->irq_dev = NULL; - return ret; - } - } else { - chan->irq = 0; - chan->irq_dev = NULL; - } - - /* fill it in */ - chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN; - chan->dev_id = dev_id; - chan->dev_str = dev_str; - chan->fifo_addr = dev->fifo_addr; - chan->mode = dev->dma_mode; - - /* initialize the channel before returning */ - init_dma(i); - - return i; -} -EXPORT_SYMBOL(request_au1000_dma); - -void free_au1000_dma(unsigned int dmanr) -{ - struct dma_chan *chan = get_dma_chan(dmanr); - - if (!chan) { - printk(KERN_ERR "Error trying to free DMA%d\n", dmanr); - return; - } - - disable_dma(dmanr); - if (chan->irq) - free_irq(chan->irq, chan->irq_dev); - - chan->irq = 0; - chan->irq_dev = NULL; - chan->dev_id = -1; -} -EXPORT_SYMBOL(free_au1000_dma); - -#endif /* AU1000 AU1500 AU1100 */ diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c deleted file mode 100644 index e660ddd611c..00000000000 --- a/arch/mips/au1000/common/gpio.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2007, OpenWrt.org, Florian Fainelli - * Architecture specific GPIO support - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Notes : - * au1000 SoC have only one GPIO line : GPIO1 - * others have a second one : GPIO2 - */ - -#include - -#include -#include - -#define gpio1 sys -#if !defined(CONFIG_SOC_AU1000) - -static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE; -#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000 - -static int au1xxx_gpio2_read(unsigned gpio) -{ - gpio -= AU1XXX_GPIO_BASE; - return ((gpio2->pinstate >> gpio) & 0x01); -} - -static void au1xxx_gpio2_write(unsigned gpio, int value) -{ - gpio -= AU1XXX_GPIO_BASE; - - gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); -} - -static int au1xxx_gpio2_direction_input(unsigned gpio) -{ - gpio -= AU1XXX_GPIO_BASE; - gpio2->dir &= ~(0x01 << gpio); - return 0; -} - -static int au1xxx_gpio2_direction_output(unsigned gpio, int value) -{ - gpio -= AU1XXX_GPIO_BASE; - gpio2->dir |= 0x01 << gpio; - gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); - return 0; -} - -#endif /* !defined(CONFIG_SOC_AU1000) */ - -static int au1xxx_gpio1_read(unsigned gpio) -{ - return (gpio1->pinstaterd >> gpio) & 0x01; -} - -static void au1xxx_gpio1_write(unsigned gpio, int value) -{ - if (value) - gpio1->outputset = (0x01 << gpio); - else - /* Output a zero */ - gpio1->outputclr = (0x01 << gpio); -} - -static int au1xxx_gpio1_direction_input(unsigned gpio) -{ - gpio1->pininputen = (0x01 << gpio); - return 0; -} - -static int au1xxx_gpio1_direction_output(unsigned gpio, int value) -{ - gpio1->trioutclr = (0x01 & gpio); - au1xxx_gpio1_write(gpio, value); - return 0; -} - -int au1xxx_gpio_get_value(unsigned gpio) -{ - if (gpio >= AU1XXX_GPIO_BASE) -#if defined(CONFIG_SOC_AU1000) - return 0; -#else - return au1xxx_gpio2_read(gpio); -#endif - else - return au1xxx_gpio1_read(gpio); -} -EXPORT_SYMBOL(au1xxx_gpio_get_value); - -void au1xxx_gpio_set_value(unsigned gpio, int value) -{ - if (gpio >= AU1XXX_GPIO_BASE) -#if defined(CONFIG_SOC_AU1000) - ; -#else - au1xxx_gpio2_write(gpio, value); -#endif - else - au1xxx_gpio1_write(gpio, value); -} -EXPORT_SYMBOL(au1xxx_gpio_set_value); - -int au1xxx_gpio_direction_input(unsigned gpio) -{ - if (gpio >= AU1XXX_GPIO_BASE) -#if defined(CONFIG_SOC_AU1000) - return -ENODEV; -#else - return au1xxx_gpio2_direction_input(gpio); -#endif - - return au1xxx_gpio1_direction_input(gpio); -} -EXPORT_SYMBOL(au1xxx_gpio_direction_input); - -int au1xxx_gpio_direction_output(unsigned gpio, int value) -{ - if (gpio >= AU1XXX_GPIO_BASE) -#if defined(CONFIG_SOC_AU1000) - return -ENODEV; -#else - return au1xxx_gpio2_direction_output(gpio, value); -#endif - - return au1xxx_gpio1_direction_output(gpio, value); -} -EXPORT_SYMBOL(au1xxx_gpio_direction_output); diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c deleted file mode 100644 index 40c6ceceb5f..00000000000 --- a/arch/mips/au1000/common/irq.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Copyright 2001, 2007-2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include - -#include -#include -#include -#ifdef CONFIG_MIPS_PB1000 -#include -#endif - -#define EXT_INTC0_REQ0 2 /* IP 2 */ -#define EXT_INTC0_REQ1 3 /* IP 3 */ -#define EXT_INTC1_REQ0 4 /* IP 4 */ -#define EXT_INTC1_REQ1 5 /* IP 5 */ -#define MIPS_TIMER_IP 7 /* IP 7 */ - -void (*board_init_irq)(void) __initdata = NULL; - -static DEFINE_SPINLOCK(irq_lock); - -#ifdef CONFIG_PM - -/* - * Save/restore the interrupt controller state. - * Called from the save/restore core registers as part of the - * au_sleep function in power.c.....maybe I should just pm_register() - * them instead? - */ -static unsigned int sleep_intctl_config0[2]; -static unsigned int sleep_intctl_config1[2]; -static unsigned int sleep_intctl_config2[2]; -static unsigned int sleep_intctl_src[2]; -static unsigned int sleep_intctl_assign[2]; -static unsigned int sleep_intctl_wake[2]; -static unsigned int sleep_intctl_mask[2]; - -void save_au1xxx_intctl(void) -{ - sleep_intctl_config0[0] = au_readl(IC0_CFG0RD); - sleep_intctl_config1[0] = au_readl(IC0_CFG1RD); - sleep_intctl_config2[0] = au_readl(IC0_CFG2RD); - sleep_intctl_src[0] = au_readl(IC0_SRCRD); - sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD); - sleep_intctl_wake[0] = au_readl(IC0_WAKERD); - sleep_intctl_mask[0] = au_readl(IC0_MASKRD); - - sleep_intctl_config0[1] = au_readl(IC1_CFG0RD); - sleep_intctl_config1[1] = au_readl(IC1_CFG1RD); - sleep_intctl_config2[1] = au_readl(IC1_CFG2RD); - sleep_intctl_src[1] = au_readl(IC1_SRCRD); - sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD); - sleep_intctl_wake[1] = au_readl(IC1_WAKERD); - sleep_intctl_mask[1] = au_readl(IC1_MASKRD); -} - -/* - * For most restore operations, we clear the entire register and - * then set the bits we found during the save. - */ -void restore_au1xxx_intctl(void) -{ - au_writel(0xffffffff, IC0_MASKCLR); au_sync(); - - au_writel(0xffffffff, IC0_CFG0CLR); au_sync(); - au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync(); - au_writel(0xffffffff, IC0_CFG1CLR); au_sync(); - au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync(); - au_writel(0xffffffff, IC0_CFG2CLR); au_sync(); - au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync(); - au_writel(0xffffffff, IC0_SRCCLR); au_sync(); - au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync(); - au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync(); - au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync(); - au_writel(0xffffffff, IC0_WAKECLR); au_sync(); - au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync(); - au_writel(0xffffffff, IC0_RISINGCLR); au_sync(); - au_writel(0xffffffff, IC0_FALLINGCLR); au_sync(); - au_writel(0x00000000, IC0_TESTBIT); au_sync(); - - au_writel(0xffffffff, IC1_MASKCLR); au_sync(); - - au_writel(0xffffffff, IC1_CFG0CLR); au_sync(); - au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync(); - au_writel(0xffffffff, IC1_CFG1CLR); au_sync(); - au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync(); - au_writel(0xffffffff, IC1_CFG2CLR); au_sync(); - au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync(); - au_writel(0xffffffff, IC1_SRCCLR); au_sync(); - au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync(); - au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync(); - au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync(); - au_writel(0xffffffff, IC1_WAKECLR); au_sync(); - au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync(); - au_writel(0xffffffff, IC1_RISINGCLR); au_sync(); - au_writel(0xffffffff, IC1_FALLINGCLR); au_sync(); - au_writel(0x00000000, IC1_TESTBIT); au_sync(); - - au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync(); - - au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync(); -} -#endif /* CONFIG_PM */ - - -inline void local_enable_irq(unsigned int irq_nr) -{ - unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; - - if (bit >= 32) { - au_writel(1 << (bit - 32), IC1_MASKSET); - au_writel(1 << (bit - 32), IC1_WAKESET); - } else { - au_writel(1 << bit, IC0_MASKSET); - au_writel(1 << bit, IC0_WAKESET); - } - au_sync(); -} - - -inline void local_disable_irq(unsigned int irq_nr) -{ - unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; - - if (bit >= 32) { - au_writel(1 << (bit - 32), IC1_MASKCLR); - au_writel(1 << (bit - 32), IC1_WAKECLR); - } else { - au_writel(1 << bit, IC0_MASKCLR); - au_writel(1 << bit, IC0_WAKECLR); - } - au_sync(); -} - - -static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr) -{ - unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; - - if (bit >= 32) { - au_writel(1 << (bit - 32), IC1_RISINGCLR); - au_writel(1 << (bit - 32), IC1_MASKCLR); - } else { - au_writel(1 << bit, IC0_RISINGCLR); - au_writel(1 << bit, IC0_MASKCLR); - } - au_sync(); -} - - -static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr) -{ - unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; - - if (bit >= 32) { - au_writel(1 << (bit - 32), IC1_FALLINGCLR); - au_writel(1 << (bit - 32), IC1_MASKCLR); - } else { - au_writel(1 << bit, IC0_FALLINGCLR); - au_writel(1 << bit, IC0_MASKCLR); - } - au_sync(); -} - - -static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr) -{ - unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; - - /* - * This may assume that we don't get interrupts from - * both edges at once, or if we do, that we don't care. - */ - if (bit >= 32) { - au_writel(1 << (bit - 32), IC1_FALLINGCLR); - au_writel(1 << (bit - 32), IC1_RISINGCLR); - au_writel(1 << (bit - 32), IC1_MASKCLR); - } else { - au_writel(1 << bit, IC0_FALLINGCLR); - au_writel(1 << bit, IC0_RISINGCLR); - au_writel(1 << bit, IC0_MASKCLR); - } - au_sync(); -} - -static inline void mask_and_ack_level_irq(unsigned int irq_nr) -{ - local_disable_irq(irq_nr); - au_sync(); -#if defined(CONFIG_MIPS_PB1000) - if (irq_nr == AU1000_GPIO_15) { - au_writel(0x8000, PB1000_MDR); /* ack int */ - au_sync(); - } -#endif -} - -static void end_irq(unsigned int irq_nr) -{ - if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - local_enable_irq(irq_nr); - -#if defined(CONFIG_MIPS_PB1000) - if (irq_nr == AU1000_GPIO_15) { - au_writel(0x4000, PB1000_MDR); /* enable int */ - au_sync(); - } -#endif -} - -unsigned long save_local_and_disable(int controller) -{ - int i; - unsigned long flags, mask; - - spin_lock_irqsave(&irq_lock, flags); - if (controller) { - mask = au_readl(IC1_MASKSET); - for (i = 32; i < 64; i++) - local_disable_irq(i); - } else { - mask = au_readl(IC0_MASKSET); - for (i = 0; i < 32; i++) - local_disable_irq(i); - } - spin_unlock_irqrestore(&irq_lock, flags); - - return mask; -} - -void restore_local_and_enable(int controller, unsigned long mask) -{ - int i; - unsigned long flags, new_mask; - - spin_lock_irqsave(&irq_lock, flags); - for (i = 0; i < 32; i++) - if (mask & (1 << i)) { - if (controller) - local_enable_irq(i + 32); - else - local_enable_irq(i); - } - - if (controller) - new_mask = au_readl(IC1_MASKSET); - else - new_mask = au_readl(IC0_MASKSET); - - spin_unlock_irqrestore(&irq_lock, flags); -} - - -static struct irq_chip rise_edge_irq_type = { - .name = "Au1000 Rise Edge", - .ack = mask_and_ack_rise_edge_irq, - .mask = local_disable_irq, - .mask_ack = mask_and_ack_rise_edge_irq, - .unmask = local_enable_irq, - .end = end_irq, -}; - -static struct irq_chip fall_edge_irq_type = { - .name = "Au1000 Fall Edge", - .ack = mask_and_ack_fall_edge_irq, - .mask = local_disable_irq, - .mask_ack = mask_and_ack_fall_edge_irq, - .unmask = local_enable_irq, - .end = end_irq, -}; - -static struct irq_chip either_edge_irq_type = { - .name = "Au1000 Rise or Fall Edge", - .ack = mask_and_ack_either_edge_irq, - .mask = local_disable_irq, - .mask_ack = mask_and_ack_either_edge_irq, - .unmask = local_enable_irq, - .end = end_irq, -}; - -static struct irq_chip level_irq_type = { - .name = "Au1000 Level", - .ack = mask_and_ack_level_irq, - .mask = local_disable_irq, - .mask_ack = mask_and_ack_level_irq, - .unmask = local_enable_irq, - .end = end_irq, -}; - -static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req) -{ - unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; - - if (irq_nr > AU1000_MAX_INTR) - return; - - /* Config2[n], Config1[n], Config0[n] */ - if (bit >= 32) { - switch (type) { - case INTC_INT_RISE_EDGE: /* 0:0:1 */ - au_writel(1 << (bit - 32), IC1_CFG2CLR); - au_writel(1 << (bit - 32), IC1_CFG1CLR); - au_writel(1 << (bit - 32), IC1_CFG0SET); - set_irq_chip(irq_nr, &rise_edge_irq_type); - break; - case INTC_INT_FALL_EDGE: /* 0:1:0 */ - au_writel(1 << (bit - 32), IC1_CFG2CLR); - au_writel(1 << (bit - 32), IC1_CFG1SET); - au_writel(1 << (bit - 32), IC1_CFG0CLR); - set_irq_chip(irq_nr, &fall_edge_irq_type); - break; - case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ - au_writel(1 << (bit - 32), IC1_CFG2CLR); - au_writel(1 << (bit - 32), IC1_CFG1SET); - au_writel(1 << (bit - 32), IC1_CFG0SET); - set_irq_chip(irq_nr, &either_edge_irq_type); - break; - case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ - au_writel(1 << (bit - 32), IC1_CFG2SET); - au_writel(1 << (bit - 32), IC1_CFG1CLR); - au_writel(1 << (bit - 32), IC1_CFG0SET); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_LOW_LEVEL: /* 1:1:0 */ - au_writel(1 << (bit - 32), IC1_CFG2SET); - au_writel(1 << (bit - 32), IC1_CFG1SET); - au_writel(1 << (bit - 32), IC1_CFG0CLR); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_DISABLED: /* 0:0:0 */ - au_writel(1 << (bit - 32), IC1_CFG0CLR); - au_writel(1 << (bit - 32), IC1_CFG1CLR); - au_writel(1 << (bit - 32), IC1_CFG2CLR); - break; - default: /* disable the interrupt */ - printk(KERN_WARNING "unexpected int type %d (irq %d)\n", - type, irq_nr); - au_writel(1 << (bit - 32), IC1_CFG0CLR); - au_writel(1 << (bit - 32), IC1_CFG1CLR); - au_writel(1 << (bit - 32), IC1_CFG2CLR); - return; - } - if (int_req) /* assign to interrupt request 1 */ - au_writel(1 << (bit - 32), IC1_ASSIGNCLR); - else /* assign to interrupt request 0 */ - au_writel(1 << (bit - 32), IC1_ASSIGNSET); - au_writel(1 << (bit - 32), IC1_SRCSET); - au_writel(1 << (bit - 32), IC1_MASKCLR); - au_writel(1 << (bit - 32), IC1_WAKECLR); - } else { - switch (type) { - case INTC_INT_RISE_EDGE: /* 0:0:1 */ - au_writel(1 << bit, IC0_CFG2CLR); - au_writel(1 << bit, IC0_CFG1CLR); - au_writel(1 << bit, IC0_CFG0SET); - set_irq_chip(irq_nr, &rise_edge_irq_type); - break; - case INTC_INT_FALL_EDGE: /* 0:1:0 */ - au_writel(1 << bit, IC0_CFG2CLR); - au_writel(1 << bit, IC0_CFG1SET); - au_writel(1 << bit, IC0_CFG0CLR); - set_irq_chip(irq_nr, &fall_edge_irq_type); - break; - case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ - au_writel(1 << bit, IC0_CFG2CLR); - au_writel(1 << bit, IC0_CFG1SET); - au_writel(1 << bit, IC0_CFG0SET); - set_irq_chip(irq_nr, &either_edge_irq_type); - break; - case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ - au_writel(1 << bit, IC0_CFG2SET); - au_writel(1 << bit, IC0_CFG1CLR); - au_writel(1 << bit, IC0_CFG0SET); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_LOW_LEVEL: /* 1:1:0 */ - au_writel(1 << bit, IC0_CFG2SET); - au_writel(1 << bit, IC0_CFG1SET); - au_writel(1 << bit, IC0_CFG0CLR); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_DISABLED: /* 0:0:0 */ - au_writel(1 << bit, IC0_CFG0CLR); - au_writel(1 << bit, IC0_CFG1CLR); - au_writel(1 << bit, IC0_CFG2CLR); - break; - default: /* disable the interrupt */ - printk(KERN_WARNING "unexpected int type %d (irq %d)\n", - type, irq_nr); - au_writel(1 << bit, IC0_CFG0CLR); - au_writel(1 << bit, IC0_CFG1CLR); - au_writel(1 << bit, IC0_CFG2CLR); - return; - } - if (int_req) /* assign to interrupt request 1 */ - au_writel(1 << bit, IC0_ASSIGNCLR); - else /* assign to interrupt request 0 */ - au_writel(1 << bit, IC0_ASSIGNSET); - au_writel(1 << bit, IC0_SRCSET); - au_writel(1 << bit, IC0_MASKCLR); - au_writel(1 << bit, IC0_WAKECLR); - } - au_sync(); -} - -/* - * Interrupts are nested. Even if an interrupt handler is registered - * as "fast", we might get another interrupt before we return from - * intcX_reqX_irqdispatch(). - */ - -static void intc0_req0_irqdispatch(void) -{ - static unsigned long intc0_req0; - unsigned int bit; - - intc0_req0 |= au_readl(IC0_REQ0INT); - - if (!intc0_req0) - return; - -#ifdef AU1000_USB_DEV_REQ_INT - /* - * Because of the tight timing of SETUP token to reply - * transactions, the USB devices-side packet complete - * interrupt needs the highest priority. - */ - if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) { - intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT); - do_IRQ(AU1000_USB_DEV_REQ_INT); - return; - } -#endif - bit = __ffs(intc0_req0); - intc0_req0 &= ~(1 << bit); - do_IRQ(AU1000_INTC0_INT_BASE + bit); -} - - -static void intc0_req1_irqdispatch(void) -{ - static unsigned long intc0_req1; - unsigned int bit; - - intc0_req1 |= au_readl(IC0_REQ1INT); - - if (!intc0_req1) - return; - - bit = __ffs(intc0_req1); - intc0_req1 &= ~(1 << bit); - do_IRQ(AU1000_INTC0_INT_BASE + bit); -} - - -/* - * Interrupt Controller 1: - * interrupts 32 - 63 - */ -static void intc1_req0_irqdispatch(void) -{ - static unsigned long intc1_req0; - unsigned int bit; - - intc1_req0 |= au_readl(IC1_REQ0INT); - - if (!intc1_req0) - return; - - bit = __ffs(intc1_req0); - intc1_req0 &= ~(1 << bit); - do_IRQ(AU1000_INTC1_INT_BASE + bit); -} - - -static void intc1_req1_irqdispatch(void) -{ - static unsigned long intc1_req1; - unsigned int bit; - - intc1_req1 |= au_readl(IC1_REQ1INT); - - if (!intc1_req1) - return; - - bit = __ffs(intc1_req1); - intc1_req1 &= ~(1 << bit); - do_IRQ(AU1000_INTC1_INT_BASE + bit); -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause(); - - if (pending & CAUSEF_IP7) - do_IRQ(MIPS_CPU_IRQ_BASE + 7); - else if (pending & CAUSEF_IP2) - intc0_req0_irqdispatch(); - else if (pending & CAUSEF_IP3) - intc0_req1_irqdispatch(); - else if (pending & CAUSEF_IP4) - intc1_req0_irqdispatch(); - else if (pending & CAUSEF_IP5) - intc1_req1_irqdispatch(); - else - spurious_interrupt(); -} - -void __init arch_init_irq(void) -{ - int i; - struct au1xxx_irqmap *imp; - extern struct au1xxx_irqmap au1xxx_irq_map[]; - extern struct au1xxx_irqmap au1xxx_ic0_map[]; - extern int au1xxx_nr_irqs; - extern int au1xxx_ic0_nr_irqs; - - /* - * Initialize interrupt controllers to a safe state. - */ - au_writel(0xffffffff, IC0_CFG0CLR); - au_writel(0xffffffff, IC0_CFG1CLR); - au_writel(0xffffffff, IC0_CFG2CLR); - au_writel(0xffffffff, IC0_MASKCLR); - au_writel(0xffffffff, IC0_ASSIGNSET); - au_writel(0xffffffff, IC0_WAKECLR); - au_writel(0xffffffff, IC0_SRCSET); - au_writel(0xffffffff, IC0_FALLINGCLR); - au_writel(0xffffffff, IC0_RISINGCLR); - au_writel(0x00000000, IC0_TESTBIT); - - au_writel(0xffffffff, IC1_CFG0CLR); - au_writel(0xffffffff, IC1_CFG1CLR); - au_writel(0xffffffff, IC1_CFG2CLR); - au_writel(0xffffffff, IC1_MASKCLR); - au_writel(0xffffffff, IC1_ASSIGNSET); - au_writel(0xffffffff, IC1_WAKECLR); - au_writel(0xffffffff, IC1_SRCSET); - au_writel(0xffffffff, IC1_FALLINGCLR); - au_writel(0xffffffff, IC1_RISINGCLR); - au_writel(0x00000000, IC1_TESTBIT); - - mips_cpu_irq_init(); - - /* - * Initialize IC0, which is fixed per processor. - */ - imp = au1xxx_ic0_map; - for (i = 0; i < au1xxx_ic0_nr_irqs; i++) { - setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); - imp++; - } - - /* - * Now set up the irq mapping for the board. - */ - imp = au1xxx_irq_map; - for (i = 0; i < au1xxx_nr_irqs; i++) { - setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); - imp++; - } - - set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); - - /* Board specific IRQ initialization. - */ - if (board_init_irq) - board_init_irq(); -} diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c deleted file mode 100644 index 7866cf50cf9..00000000000 --- a/arch/mips/au1000/common/pci.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Alchemy/AMD Au1x00 PCI support. - * - * Copyright 2001-2003, 2007-2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) - * - * Support for all devices (greater than 16) added by David Gathright. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -#include - -/* TBD */ -static struct resource pci_io_resource = { - .start = PCI_IO_START, - .end = PCI_IO_END, - .name = "PCI IO space", - .flags = IORESOURCE_IO -}; - -static struct resource pci_mem_resource = { - .start = PCI_MEM_START, - .end = PCI_MEM_END, - .name = "PCI memory space", - .flags = IORESOURCE_MEM -}; - -extern struct pci_ops au1x_pci_ops; - -static struct pci_controller au1x_controller = { - .pci_ops = &au1x_pci_ops, - .io_resource = &pci_io_resource, - .mem_resource = &pci_mem_resource, -}; - -#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550) -static unsigned long virt_io_addr; -#endif - -static int __init au1x_pci_setup(void) -{ - extern void au1x_pci_cfg_init(void); - -#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550) - virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START, - Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1); - - if (!virt_io_addr) { - printk(KERN_ERR "Unable to ioremap pci space\n"); - return 1; - } - au1x_controller.io_map_base = virt_io_addr; - -#ifdef CONFIG_DMA_NONCOHERENT - { - /* - * Set the NC bit in controller for Au1500 pre-AC silicon - */ - u32 prid = read_c0_prid(); - - if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) { - au_writel((1 << 16) | au_readl(Au1500_PCI_CFG), - Au1500_PCI_CFG); - printk(KERN_INFO "Non-coherent PCI accesses enabled\n"); - } - } -#endif - - set_io_port_base(virt_io_addr); -#endif - - au1x_pci_cfg_init(); - - register_pci_controller(&au1x_controller); - return 0; -} - -arch_initcall(au1x_pci_setup); diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c deleted file mode 100644 index dc8a67efac2..00000000000 --- a/arch/mips/au1000/common/platform.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Platform device support for Au1x00 SoCs. - * - * Copyright 2004, Matt Porter - * - * (C) Copyright Embedded Alley Solutions, Inc 2005 - * Author: Pantelis Antoniou - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include - -#include - -#define PORT(_base, _irq) \ - { \ - .iobase = _base, \ - .membase = (void __iomem *)_base,\ - .mapbase = CPHYSADDR(_base), \ - .irq = _irq, \ - .regshift = 2, \ - .iotype = UPIO_AU, \ - .flags = UPF_SKIP_TEST \ - } - -static struct plat_serial8250_port au1x00_uart_data[] = { -#if defined(CONFIG_SERIAL_8250_AU1X00) -#if defined(CONFIG_SOC_AU1000) - PORT(UART0_ADDR, AU1000_UART0_INT), - PORT(UART1_ADDR, AU1000_UART1_INT), - PORT(UART2_ADDR, AU1000_UART2_INT), - PORT(UART3_ADDR, AU1000_UART3_INT), -#elif defined(CONFIG_SOC_AU1500) - PORT(UART0_ADDR, AU1500_UART0_INT), - PORT(UART3_ADDR, AU1500_UART3_INT), -#elif defined(CONFIG_SOC_AU1100) - PORT(UART0_ADDR, AU1100_UART0_INT), - PORT(UART1_ADDR, AU1100_UART1_INT), - PORT(UART3_ADDR, AU1100_UART3_INT), -#elif defined(CONFIG_SOC_AU1550) - PORT(UART0_ADDR, AU1550_UART0_INT), - PORT(UART1_ADDR, AU1550_UART1_INT), - PORT(UART3_ADDR, AU1550_UART3_INT), -#elif defined(CONFIG_SOC_AU1200) - PORT(UART0_ADDR, AU1200_UART0_INT), - PORT(UART1_ADDR, AU1200_UART1_INT), -#endif -#endif /* CONFIG_SERIAL_8250_AU1X00 */ - { }, -}; - -static struct platform_device au1xx0_uart_device = { - .name = "serial8250", - .id = PLAT8250_DEV_AU1X00, - .dev = { - .platform_data = au1x00_uart_data, - }, -}; - -/* OHCI (USB full speed host controller) */ -static struct resource au1xxx_usb_ohci_resources[] = { - [0] = { - .start = USB_OHCI_BASE, - .end = USB_OHCI_BASE + USB_OHCI_LEN - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AU1000_USB_HOST_INT, - .end = AU1000_USB_HOST_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -/* The dmamask must be set for OHCI to work */ -static u64 ohci_dmamask = DMA_32BIT_MASK; - -static struct platform_device au1xxx_usb_ohci_device = { - .name = "au1xxx-ohci", - .id = 0, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(au1xxx_usb_ohci_resources), - .resource = au1xxx_usb_ohci_resources, -}; - -/*** AU1100 LCD controller ***/ - -#ifdef CONFIG_FB_AU1100 -static struct resource au1100_lcd_resources[] = { - [0] = { - .start = LCD_PHYS_ADDR, - .end = LCD_PHYS_ADDR + 0x800 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AU1100_LCD_INT, - .end = AU1100_LCD_INT, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 au1100_lcd_dmamask = DMA_32BIT_MASK; - -static struct platform_device au1100_lcd_device = { - .name = "au1100-lcd", - .id = 0, - .dev = { - .dma_mask = &au1100_lcd_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(au1100_lcd_resources), - .resource = au1100_lcd_resources, -}; -#endif - -#ifdef CONFIG_SOC_AU1200 -/* EHCI (USB high speed host controller) */ -static struct resource au1xxx_usb_ehci_resources[] = { - [0] = { - .start = USB_EHCI_BASE, - .end = USB_EHCI_BASE + USB_EHCI_LEN - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AU1000_USB_HOST_INT, - .end = AU1000_USB_HOST_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ehci_dmamask = DMA_32BIT_MASK; - -static struct platform_device au1xxx_usb_ehci_device = { - .name = "au1xxx-ehci", - .id = 0, - .dev = { - .dma_mask = &ehci_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(au1xxx_usb_ehci_resources), - .resource = au1xxx_usb_ehci_resources, -}; - -/* Au1200 UDC (USB gadget controller) */ -static struct resource au1xxx_usb_gdt_resources[] = { - [0] = { - .start = USB_UDC_BASE, - .end = USB_UDC_BASE + USB_UDC_LEN - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AU1200_USB_INT, - .end = AU1200_USB_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource au1xxx_mmc_resources[] = { - [0] = { - .start = SD0_PHYS_ADDR, - .end = SD0_PHYS_ADDR + 0x7ffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = SD1_PHYS_ADDR, - .end = SD1_PHYS_ADDR + 0x7ffff, - .flags = IORESOURCE_MEM, - }, - [2] = { - .start = AU1200_SD_INT, - .end = AU1200_SD_INT, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 udc_dmamask = DMA_32BIT_MASK; - -static struct platform_device au1xxx_usb_gdt_device = { - .name = "au1xxx-udc", - .id = 0, - .dev = { - .dma_mask = &udc_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(au1xxx_usb_gdt_resources), - .resource = au1xxx_usb_gdt_resources, -}; - -/* Au1200 UOC (USB OTG controller) */ -static struct resource au1xxx_usb_otg_resources[] = { - [0] = { - .start = USB_UOC_BASE, - .end = USB_UOC_BASE + USB_UOC_LEN - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AU1200_USB_INT, - .end = AU1200_USB_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 uoc_dmamask = DMA_32BIT_MASK; - -static struct platform_device au1xxx_usb_otg_device = { - .name = "au1xxx-uoc", - .id = 0, - .dev = { - .dma_mask = &uoc_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(au1xxx_usb_otg_resources), - .resource = au1xxx_usb_otg_resources, -}; - -static struct resource au1200_lcd_resources[] = { - [0] = { - .start = LCD_PHYS_ADDR, - .end = LCD_PHYS_ADDR + 0x800 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AU1200_LCD_INT, - .end = AU1200_LCD_INT, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 au1200_lcd_dmamask = DMA_32BIT_MASK; - -static struct platform_device au1200_lcd_device = { - .name = "au1200-lcd", - .id = 0, - .dev = { - .dma_mask = &au1200_lcd_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(au1200_lcd_resources), - .resource = au1200_lcd_resources, -}; - -static u64 au1xxx_mmc_dmamask = DMA_32BIT_MASK; - -static struct platform_device au1xxx_mmc_device = { - .name = "au1xxx-mmc", - .id = 0, - .dev = { - .dma_mask = &au1xxx_mmc_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(au1xxx_mmc_resources), - .resource = au1xxx_mmc_resources, -}; -#endif /* #ifdef CONFIG_SOC_AU1200 */ - -static struct platform_device au1x00_pcmcia_device = { - .name = "au1x00-pcmcia", - .id = 0, -}; - -/* All Alchemy demoboards with I2C have this #define in their headers */ -#ifdef SMBUS_PSC_BASE -static struct resource pbdb_smbus_resources[] = { - { - .start = CPHYSADDR(SMBUS_PSC_BASE), - .end = CPHYSADDR(SMBUS_PSC_BASE + 0xfffff), - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device pbdb_smbus_device = { - .name = "au1xpsc_smbus", - .id = 0, /* bus number */ - .num_resources = ARRAY_SIZE(pbdb_smbus_resources), - .resource = pbdb_smbus_resources, -}; -#endif - -static struct platform_device *au1xxx_platform_devices[] __initdata = { - &au1xx0_uart_device, - &au1xxx_usb_ohci_device, - &au1x00_pcmcia_device, -#ifdef CONFIG_FB_AU1100 - &au1100_lcd_device, -#endif -#ifdef CONFIG_SOC_AU1200 - &au1xxx_usb_ehci_device, - &au1xxx_usb_gdt_device, - &au1xxx_usb_otg_device, - &au1200_lcd_device, - &au1xxx_mmc_device, -#endif -#ifdef SMBUS_PSC_BASE - &pbdb_smbus_device, -#endif -}; - -static int __init au1xxx_platform_init(void) -{ - unsigned int uartclk = get_au1x00_uart_baud_base() * 16; - int i; - - /* Fill up uartclk. */ - for (i = 0; au1x00_uart_data[i].flags; i++) - au1x00_uart_data[i].uartclk = uartclk; - - return platform_add_devices(au1xxx_platform_devices, - ARRAY_SIZE(au1xxx_platform_devices)); -} - -arch_initcall(au1xxx_platform_init); diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c deleted file mode 100644 index bd854a6d1d8..00000000000 --- a/arch/mips/au1000/common/power.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xx0 Power Management routines. - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * Some of the routines are right out of init/main.c, whose - * copyrights apply here. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#ifdef CONFIG_PM - -#define DEBUG 1 -#ifdef DEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args) -#else -#define DPRINTK(fmt, args...) -#endif - -static void au1000_calibrate_delay(void); - -extern unsigned long save_local_and_disable(int controller); -extern void restore_local_and_enable(int controller, unsigned long mask); -extern void local_enable_irq(unsigned int irq_nr); - -static DEFINE_SPINLOCK(pm_lock); - -/* - * We need to save/restore a bunch of core registers that are - * either volatile or reset to some state across a processor sleep. - * If reading a register doesn't provide a proper result for a - * later restore, we have to provide a function for loading that - * register and save a copy. - * - * We only have to save/restore registers that aren't otherwise - * done as part of a driver pm_* function. - */ -static unsigned int sleep_aux_pll_cntrl; -static unsigned int sleep_cpu_pll_cntrl; -static unsigned int sleep_pin_function; -static unsigned int sleep_uart0_inten; -static unsigned int sleep_uart0_fifoctl; -static unsigned int sleep_uart0_linectl; -static unsigned int sleep_uart0_clkdiv; -static unsigned int sleep_uart0_enable; -static unsigned int sleep_usbhost_enable; -static unsigned int sleep_usbdev_enable; -static unsigned int sleep_static_memctlr[4][3]; - -/* - * Define this to cause the value you write to /proc/sys/pm/sleep to - * set the TOY timer for the amount of time you want to sleep. - * This is done mainly for testing, but may be useful in other cases. - * The value is number of 32KHz ticks to sleep. - */ -#define SLEEP_TEST_TIMEOUT 1 -#ifdef SLEEP_TEST_TIMEOUT -static int sleep_ticks; -void wakeup_counter0_set(int ticks); -#endif - -static void save_core_regs(void) -{ - extern void save_au1xxx_intctl(void); - extern void pm_eth0_shutdown(void); - - /* - * Do the serial ports.....these really should be a pm_* - * registered function by the driver......but of course the - * standard serial driver doesn't understand our Au1xxx - * unique registers. - */ - sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER); - sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR); - sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR); - sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK); - sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL); - - /* Shutdown USB host/device. */ - sleep_usbhost_enable = au_readl(USB_HOST_CONFIG); - - /* There appears to be some undocumented reset register.... */ - au_writel(0, 0xb0100004); au_sync(); - au_writel(0, USB_HOST_CONFIG); au_sync(); - - sleep_usbdev_enable = au_readl(USBD_ENABLE); - au_writel(0, USBD_ENABLE); au_sync(); - - /* Save interrupt controller state. */ - save_au1xxx_intctl(); - - /* Clocks and PLLs. */ - sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL); - - /* - * We don't really need to do this one, but unless we - * write it again it won't have a valid value if we - * happen to read it. - */ - sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL); - - sleep_pin_function = au_readl(SYS_PINFUNC); - - /* Save the static memory controller configuration. */ - sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0); - sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0); - sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0); - sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1); - sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1); - sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1); - sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2); - sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2); - sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2); - sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3); - sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3); - sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3); -} - -static void restore_core_regs(void) -{ - extern void restore_au1xxx_intctl(void); - extern void wakeup_counter0_adjust(void); - - au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync(); - au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync(); - au_writel(sleep_pin_function, SYS_PINFUNC); au_sync(); - - /* Restore the static memory controller configuration. */ - au_writel(sleep_static_memctlr[0][0], MEM_STCFG0); - au_writel(sleep_static_memctlr[0][1], MEM_STTIME0); - au_writel(sleep_static_memctlr[0][2], MEM_STADDR0); - au_writel(sleep_static_memctlr[1][0], MEM_STCFG1); - au_writel(sleep_static_memctlr[1][1], MEM_STTIME1); - au_writel(sleep_static_memctlr[1][2], MEM_STADDR1); - au_writel(sleep_static_memctlr[2][0], MEM_STCFG2); - au_writel(sleep_static_memctlr[2][1], MEM_STTIME2); - au_writel(sleep_static_memctlr[2][2], MEM_STADDR2); - au_writel(sleep_static_memctlr[3][0], MEM_STCFG3); - au_writel(sleep_static_memctlr[3][1], MEM_STTIME3); - au_writel(sleep_static_memctlr[3][2], MEM_STADDR3); - - /* - * Enable the UART if it was enabled before sleep. - * I guess I should define module control bits........ - */ - if (sleep_uart0_enable & 0x02) { - au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync(); - au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync(); - au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync(); - au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync(); - au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync(); - au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync(); - au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync(); - } - - restore_au1xxx_intctl(); - wakeup_counter0_adjust(); -} - -unsigned long suspend_mode; - -void wakeup_from_suspend(void) -{ - suspend_mode = 0; -} - -int au_sleep(void) -{ - unsigned long wakeup, flags; - extern void save_and_sleep(void); - - spin_lock_irqsave(&pm_lock, flags); - - save_core_regs(); - - flush_cache_all(); - - /** - ** The code below is all system dependent and we should probably - ** have a function call out of here to set this up. You need - ** to configure the GPIO or timer interrupts that will bring - ** you out of sleep. - ** For testing, the TOY counter wakeup is useful. - **/ -#if 0 - au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD); - - /* GPIO 6 can cause a wake up event */ - wakeup = au_readl(SYS_WAKEMSK); - wakeup &= ~(1 << 8); /* turn off match20 wakeup */ - wakeup |= 1 << 6; /* turn on GPIO 6 wakeup */ -#else - /* For testing, allow match20 to wake us up. */ -#ifdef SLEEP_TEST_TIMEOUT - wakeup_counter0_set(sleep_ticks); -#endif - wakeup = 1 << 8; /* turn on match20 wakeup */ - wakeup = 0; -#endif - au_writel(1, SYS_WAKESRC); /* clear cause */ - au_sync(); - au_writel(wakeup, SYS_WAKEMSK); - au_sync(); - - save_and_sleep(); - - /* - * After a wakeup, the cpu vectors back to 0x1fc00000, so - * it's up to the boot code to get us back here. - */ - restore_core_regs(); - spin_unlock_irqrestore(&pm_lock, flags); - return 0; -} - -static int pm_do_sleep(ctl_table *ctl, int write, struct file *file, - void __user *buffer, size_t *len, loff_t *ppos) -{ -#ifdef SLEEP_TEST_TIMEOUT -#define TMPBUFLEN2 16 - char buf[TMPBUFLEN2], *p; -#endif - - if (!write) - *len = 0; - else { -#ifdef SLEEP_TEST_TIMEOUT - if (*len > TMPBUFLEN2 - 1) - return -EFAULT; - if (copy_from_user(buf, buffer, *len)) - return -EFAULT; - buf[*len] = 0; - p = buf; - sleep_ticks = simple_strtoul(p, &p, 0); -#endif - - au_sleep(); - } - return 0; -} - -static int pm_do_freq(ctl_table *ctl, int write, struct file *file, - void __user *buffer, size_t *len, loff_t *ppos) -{ - int retval = 0, i; - unsigned long val, pll; -#define TMPBUFLEN 64 -#define MAX_CPU_FREQ 396 - char buf[TMPBUFLEN], *p; - unsigned long flags, intc0_mask, intc1_mask; - unsigned long old_baud_base, old_cpu_freq, old_clk, old_refresh; - unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh; - unsigned long baud_rate; - - spin_lock_irqsave(&pm_lock, flags); - if (!write) - *len = 0; - else { - /* Parse the new frequency */ - if (*len > TMPBUFLEN - 1) { - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - if (copy_from_user(buf, buffer, *len)) { - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - buf[*len] = 0; - p = buf; - val = simple_strtoul(p, &p, 0); - if (val > MAX_CPU_FREQ) { - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - - pll = val / 12; - if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */ - /* Revisit this for higher speed CPUs */ - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - - old_baud_base = get_au1x00_uart_baud_base(); - old_cpu_freq = get_au1x00_speed(); - - new_cpu_freq = pll * 12 * 1000000; - new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL) - & 0x03) + 2) * 16)); - set_au1x00_speed(new_cpu_freq); - set_au1x00_uart_baud_base(new_baud_base); - - old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff; - new_refresh = ((old_refresh * new_cpu_freq) / old_cpu_freq) | - (au_readl(MEM_SDREFCFG) & ~0x1ffffff); - - au_writel(pll, SYS_CPUPLL); - au_sync_delay(1); - au_writel(new_refresh, MEM_SDREFCFG); - au_sync_delay(1); - - for (i = 0; i < 4; i++) - if (au_readl(UART_BASE + UART_MOD_CNTRL + - i * 0x00100000) == 3) { - old_clk = au_readl(UART_BASE + UART_CLK + - i * 0x00100000); - baud_rate = old_baud_base / old_clk; - /* - * We won't get an exact baud rate and the error - * could be significant enough that our new - * calculation will result in a clock that will - * give us a baud rate that's too far off from - * what we really want. - */ - if (baud_rate > 100000) - baud_rate = 115200; - else if (baud_rate > 50000) - baud_rate = 57600; - else if (baud_rate > 30000) - baud_rate = 38400; - else if (baud_rate > 17000) - baud_rate = 19200; - else - baud_rate = 9600; - new_clk = new_baud_base / baud_rate; - au_writel(new_clk, UART_BASE + UART_CLK + - i * 0x00100000); - au_sync_delay(10); - } - } - - /* - * We don't want _any_ interrupts other than match20. Otherwise our - * au1000_calibrate_delay() calculation will be off, potentially a lot. - */ - intc0_mask = save_local_and_disable(0); - intc1_mask = save_local_and_disable(1); - local_enable_irq(AU1000_TOY_MATCH2_INT); - spin_unlock_irqrestore(&pm_lock, flags); - au1000_calibrate_delay(); - restore_local_and_enable(0, intc0_mask); - restore_local_and_enable(1, intc1_mask); - - return retval; -} - - -static struct ctl_table pm_table[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "sleep", - .data = NULL, - .maxlen = 0, - .mode = 0600, - .proc_handler = &pm_do_sleep - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "freq", - .data = NULL, - .maxlen = 0, - .mode = 0600, - .proc_handler = &pm_do_freq - }, - {} -}; - -static struct ctl_table pm_dir_table[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "pm", - .mode = 0555, - .child = pm_table - }, - {} -}; - -/* - * Initialize power interface - */ -static int __init pm_init(void) -{ - register_sysctl_table(pm_dir_table); - return 0; -} - -__initcall(pm_init); - -/* - * This is right out of init/main.c - */ - -/* - * This is the number of bits of precision for the loops_per_jiffy. - * Each bit takes on average 1.5/HZ seconds. This (like the original) - * is a little better than 1%. - */ -#define LPS_PREC 8 - -static void au1000_calibrate_delay(void) -{ - unsigned long ticks, loopbit; - int lps_precision = LPS_PREC; - - loops_per_jiffy = 1 << 12; - - while (loops_per_jiffy <<= 1) { - /* Wait for "start of" clock tick */ - ticks = jiffies; - while (ticks == jiffies) - /* nothing */ ; - /* Go ... */ - ticks = jiffies; - __delay(loops_per_jiffy); - ticks = jiffies - ticks; - if (ticks) - break; - } - - /* - * Do a binary approximation to get loops_per_jiffy set to be equal - * one clock (up to lps_precision bits) - */ - loops_per_jiffy >>= 1; - loopbit = loops_per_jiffy; - while (lps_precision-- && (loopbit >>= 1)) { - loops_per_jiffy |= loopbit; - ticks = jiffies; - while (ticks == jiffies); - ticks = jiffies; - __delay(loops_per_jiffy); - if (jiffies != ticks) /* longer than 1 tick */ - loops_per_jiffy &= ~loopbit; - } -} -#endif /* CONFIG_PM */ diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c deleted file mode 100644 index 18b310b475c..00000000000 --- a/arch/mips/au1000/common/prom.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * PROM library initialisation code, supports YAMON and U-Boot. - * - * Copyright 2000-2001, 2006, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * This file was derived from Carsten Langgaard's - * arch/mips/mips-boards/xx files. - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -#include - -int prom_argc; -char **prom_argv; -char **prom_envp; - -char * __init_or_module prom_getcmdline(void) -{ - return &(arcs_cmdline[0]); -} - -void prom_init_cmdline(void) -{ - char *cp; - int actr; - - actr = 1; /* Always ignore argv[0] */ - - cp = &(arcs_cmdline[0]); - while (actr < prom_argc) { - strcpy(cp, prom_argv[actr]); - cp += strlen(prom_argv[actr]); - *cp++ = ' '; - actr++; - } - if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ - --cp; - if (prom_argc > 1) - *cp = '\0'; -} - -char *prom_getenv(char *envname) -{ - /* - * Return a pointer to the given environment variable. - * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". - */ - - char **env = prom_envp; - int i = strlen(envname); - int yamon = (*env && strchr(*env, '=') == NULL); - - while (*env) { - if (yamon) { - if (strcmp(envname, *env++) == 0) - return *env; - } else if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') - return *env + i + 1; - env++; - } - - return NULL; -} - -static inline unsigned char str2hexnum(unsigned char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - - return 0; /* foo */ -} - -static inline void str2eaddr(unsigned char *ea, unsigned char *str) -{ - int i; - - for (i = 0; i < 6; i++) { - unsigned char num; - - if ((*str == '.') || (*str == ':')) - str++; - num = str2hexnum(*str++) << 4; - num |= str2hexnum(*str++); - ea[i] = num; - } -} - -int prom_get_ethernet_addr(char *ethernet_addr) -{ - char *ethaddr_str; - char *argptr; - - /* Check the environment variables first */ - ethaddr_str = prom_getenv("ethaddr"); - if (!ethaddr_str) { - /* Check command line */ - argptr = prom_getcmdline(); - ethaddr_str = strstr(argptr, "ethaddr="); - if (!ethaddr_str) - return -1; - - ethaddr_str += strlen("ethaddr="); - } - - str2eaddr(ethernet_addr, ethaddr_str); - - return 0; -} -EXPORT_SYMBOL(prom_get_ethernet_addr); - -void __init prom_free_prom_memory(void) -{ -} diff --git a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c deleted file mode 100644 index 55bbe24d45b..00000000000 --- a/arch/mips/au1000/common/puts.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Low level UART routines to directly access Alchemy UART. - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#define SERIAL_BASE UART_BASE -#define SER_CMD 0x7 -#define SER_DATA 0x1 -#define TX_BUSY 0x20 - -#define TIMEOUT 0xffffff -#define SLOW_DOWN - -static volatile unsigned long * const com1 = (unsigned long *)SERIAL_BASE; - -#ifdef SLOW_DOWN -static inline void slow_down(void) -{ - int k; - - for (k = 0; k < 10000; k++); -} -#else -#define slow_down() -#endif - -void -prom_putchar(const unsigned char c) -{ - unsigned char ch; - int i = 0; - - do { - ch = com1[SER_CMD]; - slow_down(); - i++; - if (i > TIMEOUT) - break; - } while (0 == (ch & TX_BUSY)); - - com1[SER_DATA] = c; -} diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c deleted file mode 100644 index d555429c8d6..00000000000 --- a/arch/mips/au1000/common/reset.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Au1xx0 reset routines. - * - * Copyright 2001, 2006, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -extern int au_sleep(void); - -void au1000_restart(char *command) -{ - /* Set all integrated peripherals to disabled states */ - extern void board_reset(void); - u32 prid = read_c0_prid(); - - printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n"); - - switch (prid & 0xFF000000) { - case 0x00000000: /* Au1000 */ - au_writel(0x02, 0xb0000010); /* ac97_enable */ - au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ - asm("sync"); - au_writel(0x00, 0xb017fffc); /* usbh_enable */ - au_writel(0x00, 0xb0200058); /* usbd_enable */ - au_writel(0x00, 0xb0300040); /* ir_enable */ - au_writel(0x00, 0xb4004104); /* mac dma */ - au_writel(0x00, 0xb4004114); /* mac dma */ - au_writel(0x00, 0xb4004124); /* mac dma */ - au_writel(0x00, 0xb4004134); /* mac dma */ - au_writel(0x00, 0xb0520000); /* macen0 */ - au_writel(0x00, 0xb0520004); /* macen1 */ - au_writel(0x00, 0xb1000008); /* i2s_enable */ - au_writel(0x00, 0xb1100100); /* uart0_enable */ - au_writel(0x00, 0xb1200100); /* uart1_enable */ - au_writel(0x00, 0xb1300100); /* uart2_enable */ - au_writel(0x00, 0xb1400100); /* uart3_enable */ - au_writel(0x02, 0xb1600100); /* ssi0_enable */ - au_writel(0x02, 0xb1680100); /* ssi1_enable */ - au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ - au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ - au_writel(0x00, 0xb1900028); /* sys_clksrc */ - au_writel(0x10, 0xb1900060); /* sys_cpupll */ - au_writel(0x00, 0xb1900064); /* sys_auxpll */ - au_writel(0x00, 0xb1900100); /* sys_pininputen */ - break; - case 0x01000000: /* Au1500 */ - au_writel(0x02, 0xb0000010); /* ac97_enable */ - au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ - asm("sync"); - au_writel(0x00, 0xb017fffc); /* usbh_enable */ - au_writel(0x00, 0xb0200058); /* usbd_enable */ - au_writel(0x00, 0xb4004104); /* mac dma */ - au_writel(0x00, 0xb4004114); /* mac dma */ - au_writel(0x00, 0xb4004124); /* mac dma */ - au_writel(0x00, 0xb4004134); /* mac dma */ - au_writel(0x00, 0xb1520000); /* macen0 */ - au_writel(0x00, 0xb1520004); /* macen1 */ - au_writel(0x00, 0xb1100100); /* uart0_enable */ - au_writel(0x00, 0xb1400100); /* uart3_enable */ - au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ - au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ - au_writel(0x00, 0xb1900028); /* sys_clksrc */ - au_writel(0x10, 0xb1900060); /* sys_cpupll */ - au_writel(0x00, 0xb1900064); /* sys_auxpll */ - au_writel(0x00, 0xb1900100); /* sys_pininputen */ - break; - case 0x02000000: /* Au1100 */ - au_writel(0x02, 0xb0000010); /* ac97_enable */ - au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ - asm("sync"); - au_writel(0x00, 0xb017fffc); /* usbh_enable */ - au_writel(0x00, 0xb0200058); /* usbd_enable */ - au_writel(0x00, 0xb0300040); /* ir_enable */ - au_writel(0x00, 0xb4004104); /* mac dma */ - au_writel(0x00, 0xb4004114); /* mac dma */ - au_writel(0x00, 0xb4004124); /* mac dma */ - au_writel(0x00, 0xb4004134); /* mac dma */ - au_writel(0x00, 0xb0520000); /* macen0 */ - au_writel(0x00, 0xb1000008); /* i2s_enable */ - au_writel(0x00, 0xb1100100); /* uart0_enable */ - au_writel(0x00, 0xb1200100); /* uart1_enable */ - au_writel(0x00, 0xb1400100); /* uart3_enable */ - au_writel(0x02, 0xb1600100); /* ssi0_enable */ - au_writel(0x02, 0xb1680100); /* ssi1_enable */ - au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ - au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ - au_writel(0x00, 0xb1900028); /* sys_clksrc */ - au_writel(0x10, 0xb1900060); /* sys_cpupll */ - au_writel(0x00, 0xb1900064); /* sys_auxpll */ - au_writel(0x00, 0xb1900100); /* sys_pininputen */ - break; - case 0x03000000: /* Au1550 */ - au_writel(0x00, 0xb1a00004); /* psc 0 */ - au_writel(0x00, 0xb1b00004); /* psc 1 */ - au_writel(0x00, 0xb0a00004); /* psc 2 */ - au_writel(0x00, 0xb0b00004); /* psc 3 */ - au_writel(0x00, 0xb017fffc); /* usbh_enable */ - au_writel(0x00, 0xb0200058); /* usbd_enable */ - au_writel(0x00, 0xb4004104); /* mac dma */ - au_writel(0x00, 0xb4004114); /* mac dma */ - au_writel(0x00, 0xb4004124); /* mac dma */ - au_writel(0x00, 0xb4004134); /* mac dma */ - au_writel(0x00, 0xb1520000); /* macen0 */ - au_writel(0x00, 0xb1520004); /* macen1 */ - au_writel(0x00, 0xb1100100); /* uart0_enable */ - au_writel(0x00, 0xb1200100); /* uart1_enable */ - au_writel(0x00, 0xb1400100); /* uart3_enable */ - au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ - au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ - au_writel(0x00, 0xb1900028); /* sys_clksrc */ - au_writel(0x10, 0xb1900060); /* sys_cpupll */ - au_writel(0x00, 0xb1900064); /* sys_auxpll */ - au_writel(0x00, 0xb1900100); /* sys_pininputen */ - break; - } - - set_c0_status(ST0_BEV | ST0_ERL); - change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); - write_c0_wired(0); - - /* Give board a chance to do a hardware reset */ - board_reset(); - - /* Jump to the beggining in case board_reset() is empty */ - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); -} - -void au1000_halt(void) -{ -#if defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) - /* Power off system */ - printk(KERN_NOTICE "\n** Powering off...\n"); - au_writew(au_readw(0xAF00001C) | (3 << 14), 0xAF00001C); - au_sync(); - while (1); /* should not get here */ -#else - printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -#ifdef CONFIG_MIPS_MIRAGE - au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT); -#endif -#ifdef CONFIG_MIPS_DB1200 - au_writew(au_readw(0xB980001C) | (1 << 14), 0xB980001C); -#endif -#ifdef CONFIG_PM - au_sleep(); - - /* Should not get here */ - printk(KERN_ERR "Unable to put CPU in sleep mode\n"); - while (1); -#else - while (1) - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); -#endif -#endif /* defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) */ -} - -void au1000_power_off(void) -{ - au1000_halt(); -} diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c deleted file mode 100644 index 1ac6b06f42a..00000000000 --- a/arch/mips/au1000/common/setup.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2000, 2007-2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. -#include -#include -#include - -#include -#include -#include - -#include -#include - -extern void __init board_setup(void); -extern void au1000_restart(char *); -extern void au1000_halt(void); -extern void au1000_power_off(void); -extern void set_cpuspec(void); - -void __init plat_mem_setup(void) -{ - struct cpu_spec *sp; - char *argptr; - unsigned long prid, cpufreq, bclk; - - set_cpuspec(); - sp = cur_cpu_spec[0]; - - board_setup(); /* board specific setup */ - - prid = read_c0_prid(); - if (sp->cpu_pll_wo) -#ifdef CONFIG_SOC_AU1000_FREQUENCY - cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000; -#else - cpufreq = 396; -#endif - else - cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12; - printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq); - - if (sp->cpu_bclk) { - /* Enable BCLK switching */ - bclk = au_readl(SYS_POWERCTRL); - au_writel(bclk | 0x60, SYS_POWERCTRL); - printk(KERN_INFO "BCLK switching enabled!\n"); - } - - if (sp->cpu_od) - /* Various early Au1xx0 errata corrected by this */ - set_c0_config(1 << 19); /* Set Config[OD] */ - else - /* Clear to obtain best system bus performance */ - clear_c0_config(1 << 19); /* Clear Config[OD] */ - - argptr = prom_getcmdline(); - -#ifdef CONFIG_SERIAL_8250_CONSOLE - argptr = strstr(argptr, "console="); - if (argptr == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " console=ttyS0,115200"); - } -#endif - -#ifdef CONFIG_FB_AU1100 - argptr = strstr(argptr, "video="); - if (argptr == NULL) { - argptr = prom_getcmdline(); - /* default panel */ - /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/ - } -#endif - -#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000) - /* au1000 does not support vra, au1500 and au1100 do */ - strcat(argptr, " au1000_audio=vra"); - argptr = prom_getcmdline(); -#endif - _machine_restart = au1000_restart; - _machine_halt = au1000_halt; - pm_power_off = au1000_power_off; - - /* IO/MEM resources. */ - set_io_port_base(0); - ioport_resource.start = IOPORT_RESOURCE_START; - ioport_resource.end = IOPORT_RESOURCE_END; - iomem_resource.start = IOMEM_RESOURCE_START; - iomem_resource.end = IOMEM_RESOURCE_END; - - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); - au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); - au_writel(0, SYS_TOYTRIM); -} - -#if defined(CONFIG_64BIT_PHYS_ADDR) -/* This routine should be valid for all Au1x based boards */ -phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) -{ - /* Don't fixup 36-bit addresses */ - if ((phys_addr >> 32) != 0) - return phys_addr; - -#ifdef CONFIG_PCI - { - u32 start = (u32)Au1500_PCI_MEM_START; - u32 end = (u32)Au1500_PCI_MEM_END; - - /* Check for PCI memory window */ - if (phys_addr >= start && (phys_addr + size - 1) <= end) - return (phys_t) - ((phys_addr - start) + Au1500_PCI_MEM_START); - } -#endif - - /* - * All Au1xx0 SOCs have a PCMCIA controller. - * We setup our 32-bit pseudo addresses to be equal to the - * 36-bit addr >> 4, to make it easier to check the address - * and fix it. - * The PCMCIA socket 0 physical attribute address is 0xF 4000 0000. - * The pseudo address we use is 0xF400 0000. Any address over - * 0xF400 0000 is a PCMCIA pseudo address. - */ - if ((phys_addr >= 0xF4000000) && (phys_addr < 0xFFFFFFFF)) - return (phys_t)(phys_addr << 4); - - /* default nop */ - return phys_addr; -} -EXPORT_SYMBOL(__fixup_bigphys_addr); -#endif diff --git a/arch/mips/au1000/common/sleeper.S b/arch/mips/au1000/common/sleeper.S deleted file mode 100644 index 4b3cf021a45..00000000000 --- a/arch/mips/au1000/common/sleeper.S +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2002 Embedded Edge, LLC - * Author: dan@embeddededge.com - * - * Sleep helper for Au1xxx sleep mode. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include - - .text - .set macro - .set noat - .align 5 - -/* Save all of the processor general registers and go to sleep. - * A wakeup condition will get us back here to restore the registers. - */ -LEAF(save_and_sleep) - - subu sp, PT_SIZE - sw $1, PT_R1(sp) - sw $2, PT_R2(sp) - sw $3, PT_R3(sp) - sw $4, PT_R4(sp) - sw $5, PT_R5(sp) - sw $6, PT_R6(sp) - sw $7, PT_R7(sp) - sw $8, PT_R8(sp) - sw $9, PT_R9(sp) - sw $10, PT_R10(sp) - sw $11, PT_R11(sp) - sw $12, PT_R12(sp) - sw $13, PT_R13(sp) - sw $14, PT_R14(sp) - sw $15, PT_R15(sp) - sw $16, PT_R16(sp) - sw $17, PT_R17(sp) - sw $18, PT_R18(sp) - sw $19, PT_R19(sp) - sw $20, PT_R20(sp) - sw $21, PT_R21(sp) - sw $22, PT_R22(sp) - sw $23, PT_R23(sp) - sw $24, PT_R24(sp) - sw $25, PT_R25(sp) - sw $26, PT_R26(sp) - sw $27, PT_R27(sp) - sw $28, PT_R28(sp) - sw $29, PT_R29(sp) - sw $30, PT_R30(sp) - sw $31, PT_R31(sp) - mfc0 k0, CP0_STATUS - sw k0, 0x20(sp) - mfc0 k0, CP0_CONTEXT - sw k0, 0x1c(sp) - mfc0 k0, CP0_PAGEMASK - sw k0, 0x18(sp) - mfc0 k0, CP0_CONFIG - sw k0, 0x14(sp) - - /* Now set up the scratch registers so the boot rom will - * return to this point upon wakeup. - */ - la k0, 1f - lui k1, 0xb190 - ori k1, 0x18 - sw sp, 0(k1) - ori k1, 0x1c - sw k0, 0(k1) - -/* Put SDRAM into self refresh. Preload instructions into cache, - * issue a precharge, then auto refresh, then sleep commands to it. - */ - la t0, sdsleep - .set mips3 - cache 0x14, 0(t0) - cache 0x14, 32(t0) - cache 0x14, 64(t0) - cache 0x14, 96(t0) - .set mips0 - -sdsleep: - lui k0, 0xb400 - sw zero, 0x001c(k0) /* Precharge */ - sw zero, 0x0020(k0) /* Auto refresh */ - sw zero, 0x0030(k0) /* SDRAM sleep */ - sync - - lui k1, 0xb190 - sw zero, 0x0078(k1) /* get ready to sleep */ - sync - sw zero, 0x007c(k1) /* Put processor to sleep */ - sync - - /* This is where we return upon wakeup. - * Reload all of the registers and return. - */ -1: nop - lw k0, 0x20(sp) - mtc0 k0, CP0_STATUS - lw k0, 0x1c(sp) - mtc0 k0, CP0_CONTEXT - lw k0, 0x18(sp) - mtc0 k0, CP0_PAGEMASK - lw k0, 0x14(sp) - mtc0 k0, CP0_CONFIG - - /* We need to catch the ealry Alchemy SOCs with - * the write-only Config[OD] bit and set it back to one... - */ - jal au1x00_fixup_config_od - lw $1, PT_R1(sp) - lw $2, PT_R2(sp) - lw $3, PT_R3(sp) - lw $4, PT_R4(sp) - lw $5, PT_R5(sp) - lw $6, PT_R6(sp) - lw $7, PT_R7(sp) - lw $8, PT_R8(sp) - lw $9, PT_R9(sp) - lw $10, PT_R10(sp) - lw $11, PT_R11(sp) - lw $12, PT_R12(sp) - lw $13, PT_R13(sp) - lw $14, PT_R14(sp) - lw $15, PT_R15(sp) - lw $16, PT_R16(sp) - lw $17, PT_R17(sp) - lw $18, PT_R18(sp) - lw $19, PT_R19(sp) - lw $20, PT_R20(sp) - lw $21, PT_R21(sp) - lw $22, PT_R22(sp) - lw $23, PT_R23(sp) - lw $24, PT_R24(sp) - lw $25, PT_R25(sp) - lw $26, PT_R26(sp) - lw $27, PT_R27(sp) - lw $28, PT_R28(sp) - lw $29, PT_R29(sp) - lw $30, PT_R30(sp) - lw $31, PT_R31(sp) - addiu sp, PT_SIZE - - jr ra -END(save_and_sleep) diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c deleted file mode 100644 index 563d9390a87..00000000000 --- a/arch/mips/au1000/common/time.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * - * Copyright (C) 2001, 2006, 2008 MontaVista Software, - * Copied and modified Carsten Langgaard's time.c - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * ######################################################################## - * - * Setting up the clock on the MIPS boards. - * - * We provide the clock interrupt processing and the timer offset compute - * functions. If CONFIG_PM is selected, we also ensure the 32KHz timer is - * available. -- Dan - */ - -#include -#include -#include - -#include -#include -#include - -static int no_au1xxx_32khz; -extern int allow_au1k_wait; /* default off for CP0 Counter */ - -#ifdef CONFIG_PM -#if HZ < 100 || HZ > 1000 -#error "unsupported HZ value! Must be in [100,1000]" -#endif -#define MATCH20_INC (328 * 100 / HZ) /* magic number 328 is for HZ=100... */ -static unsigned long last_pc0, last_match20; -#endif - -static DEFINE_SPINLOCK(time_lock); - -unsigned long wtimer; - -#ifdef CONFIG_PM -static irqreturn_t counter0_irq(int irq, void *dev_id) -{ - unsigned long pc0; - int time_elapsed; - static int jiffie_drift; - - if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { - /* should never happen! */ - printk(KERN_WARNING "counter 0 w status error\n"); - return IRQ_NONE; - } - - pc0 = au_readl(SYS_TOYREAD); - if (pc0 < last_match20) - /* counter overflowed */ - time_elapsed = (0xffffffff - last_match20) + pc0; - else - time_elapsed = pc0 - last_match20; - - while (time_elapsed > 0) { - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - time_elapsed -= MATCH20_INC; - last_match20 += MATCH20_INC; - jiffie_drift++; - } - - last_pc0 = pc0; - au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); - au_sync(); - - /* - * Our counter ticks at 10.009765625 ms/tick, we we're running - * almost 10 uS too slow per tick. - */ - - if (jiffie_drift >= 999) { - jiffie_drift -= 999; - do_timer(1); /* increment jiffies by one */ -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - } - - return IRQ_HANDLED; -} - -struct irqaction counter0_action = { - .handler = counter0_irq, - .flags = IRQF_DISABLED, - .name = "alchemy-toy", - .dev_id = NULL, -}; - -/* When we wakeup from sleep, we have to "catch up" on all of the - * timer ticks we have missed. - */ -void wakeup_counter0_adjust(void) -{ - unsigned long pc0; - int time_elapsed; - - pc0 = au_readl(SYS_TOYREAD); - if (pc0 < last_match20) - /* counter overflowed */ - time_elapsed = (0xffffffff - last_match20) + pc0; - else - time_elapsed = pc0 - last_match20; - - while (time_elapsed > 0) { - time_elapsed -= MATCH20_INC; - last_match20 += MATCH20_INC; - } - - last_pc0 = pc0; - au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); - au_sync(); - -} - -/* This is just for debugging to set the timer for a sleep delay. */ -void wakeup_counter0_set(int ticks) -{ - unsigned long pc0; - - pc0 = au_readl(SYS_TOYREAD); - last_pc0 = pc0; - au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2); - au_sync(); -} -#endif - -/* - * I haven't found anyone that doesn't use a 12 MHz source clock, - * but just in case..... - */ -#define AU1000_SRC_CLK 12000000 - -/* - * We read the real processor speed from the PLL. This is important - * because it is more accurate than computing it from the 32 KHz - * counter, if it exists. If we don't have an accurate processor - * speed, all of the peripherals that derive their clocks based on - * this advertised speed will introduce error and sometimes not work - * properly. This function is futher convoluted to still allow configurations - * to do that in case they have really, really old silicon with a - * write-only PLL register, that we need the 32 KHz when power management - * "wait" is enabled, and we need to detect if the 32 KHz isn't present - * but requested......got it? :-) -- Dan - */ -unsigned long calc_clock(void) -{ - unsigned long cpu_speed; - unsigned long flags; - unsigned long counter; - - spin_lock_irqsave(&time_lock, flags); - - /* Power management cares if we don't have a 32 KHz counter. */ - no_au1xxx_32khz = 0; - counter = au_readl(SYS_COUNTER_CNTRL); - if (counter & SYS_CNTRL_E0) { - int trim_divide = 16; - - au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL); - - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); - /* RTC now ticks at 32.768/16 kHz */ - au_writel(trim_divide - 1, SYS_RTCTRIM); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); - - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); - au_writel(0, SYS_TOYWRITE); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); - } else - no_au1xxx_32khz = 1; - - /* - * On early Au1000, sys_cpupll was write-only. Since these - * silicon versions of Au1000 are not sold by AMD, we don't bend - * over backwards trying to determine the frequency. - */ - if (cur_cpu_spec[0]->cpu_pll_wo) -#ifdef CONFIG_SOC_AU1000_FREQUENCY - cpu_speed = CONFIG_SOC_AU1000_FREQUENCY; -#else - cpu_speed = 396000000; -#endif - else - cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - /* On Alchemy CPU:counter ratio is 1:1 */ - mips_hpt_frequency = cpu_speed; - /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */ - set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL) - & 0x03) + 2) * 16)); - spin_unlock_irqrestore(&time_lock, flags); - return cpu_speed; -} - -void __init plat_time_init(void) -{ - unsigned int est_freq = calc_clock(); - - est_freq += 5000; /* round */ - est_freq -= est_freq%10000; - printk(KERN_INFO "CPU frequency %u.%02u MHz\n", - est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000); - set_au1x00_speed(est_freq); - set_au1x00_lcd_clock(); /* program the LCD clock */ - -#ifdef CONFIG_PM - /* - * setup counter 0, since it keeps ticking after a - * 'wait' instruction has been executed. The CP0 timer and - * counter 1 do NOT continue running after 'wait' - * - * It's too early to call request_irq() here, so we handle - * counter 0 interrupt as a special irq and it doesn't show - * up under /proc/interrupts. - * - * Check to ensure we really have a 32 KHz oscillator before - * we do this. - */ - if (no_au1xxx_32khz) - printk(KERN_WARNING "WARNING: no 32KHz clock found.\n"); - else { - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); - au_writel(0, SYS_TOYWRITE); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); - - au_writel(au_readl(SYS_WAKEMSK) | (1 << 8), SYS_WAKEMSK); - au_writel(~0, SYS_WAKESRC); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - - /* Setup match20 to interrupt once every HZ */ - last_pc0 = last_match20 = au_readl(SYS_TOYREAD); - au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action); - - /* We can use the real 'wait' instruction. */ - allow_au1k_wait = 1; - } - -#endif -} diff --git a/arch/mips/au1000/db1x00/Makefile b/arch/mips/au1000/db1x00/Makefile deleted file mode 100644 index 274db3b55d8..00000000000 --- a/arch/mips/au1000/db1x00/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2000, 2008 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# -# Makefile for the Alchemy Semiconductor DBAu1xx0 boards. -# - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c deleted file mode 100644 index 9e5ccbbfced..00000000000 --- a/arch/mips/au1000/db1x00/board_setup.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Alchemy Db1x00 board setup. - * - * Copyright 2000, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include -#include - -static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; - -void board_reset(void) -{ - /* Hit BCSR.SW_RESET[RESET] */ - bcsr->swreset = 0x0000; -} - -void __init board_setup(void) -{ - u32 pin_func = 0; - - /* Not valid for Au1550 */ -#if defined(CONFIG_IRDA) && \ - (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100)) - /* Set IRFIRSEL instead of GPIO15 */ - pin_func = au_readl(SYS_PINFUNC) | SYS_PF_IRF; - au_writel(pin_func, SYS_PINFUNC); - /* Power off until the driver is in use */ - bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK; - bcsr->resets |= BCSR_RESETS_IRDA_MODE_OFF; - au_sync(); -#endif - bcsr->pcmcia = 0x0000; /* turn off PCMCIA power */ - -#ifdef CONFIG_MIPS_MIRAGE - /* Enable GPIO[31:0] inputs */ - au_writel(0, SYS_PININPUTEN); - - /* GPIO[20] is output, tristate the other input primary GPIOs */ - au_writel(~(1 << 20), SYS_TRIOUTCLR); - - /* Set GPIO[210:208] instead of SSI_0 */ - pin_func = au_readl(SYS_PINFUNC) | SYS_PF_S0; - - /* Set GPIO[215:211] for LEDs */ - pin_func |= 5 << 2; - - /* Set GPIO[214:213] for more LEDs */ - pin_func |= 5 << 12; - - /* Set GPIO[207:200] instead of PCMCIA/LCD */ - pin_func |= SYS_PF_LCD | SYS_PF_PC; - au_writel(pin_func, SYS_PINFUNC); - - /* - * Enable speaker amplifier. This should - * be part of the audio driver. - */ - au_writel(au_readl(GPIO2_DIR) | 0x200, GPIO2_DIR); - au_writel(0x02000200, GPIO2_OUTPUT); -#endif - - au_sync(); - -#ifdef CONFIG_MIPS_DB1000 - printk(KERN_INFO "AMD Alchemy Au1000/Db1000 Board\n"); -#endif -#ifdef CONFIG_MIPS_DB1500 - printk(KERN_INFO "AMD Alchemy Au1500/Db1500 Board\n"); -#endif -#ifdef CONFIG_MIPS_DB1100 - printk(KERN_INFO "AMD Alchemy Au1100/Db1100 Board\n"); -#endif -#ifdef CONFIG_MIPS_BOSPORUS - printk(KERN_INFO "AMD Alchemy Bosporus Board\n"); -#endif -#ifdef CONFIG_MIPS_MIRAGE - printk(KERN_INFO "AMD Alchemy Mirage Board\n"); -#endif -#ifdef CONFIG_MIPS_DB1550 - printk(KERN_INFO "AMD Alchemy Au1550/Db1550 Board\n"); -#endif -} diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c deleted file mode 100644 index 84741351496..00000000000 --- a/arch/mips/au1000/db1x00/init.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * PB1000 board setup - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ -#ifdef CONFIG_MIPS_BOSPORUS - return "Alchemy Bosporus Gateway Reference"; -#else - return "Alchemy Db1x00"; -#endif -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x04000000; - else - strict_strtol(memsize_str, 0, &memsize); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c deleted file mode 100644 index 94c090e8bf7..00000000000 --- a/arch/mips/au1000/db1x00/irqmap.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xxx irq map table - * - * Copyright 2003 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -#ifdef CONFIG_MIPS_DB1500 -char irq_tab_alchemy[][5] __initdata = { - [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT371 */ - [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */ -}; -#endif - -#ifdef CONFIG_MIPS_BOSPORUS -char irq_tab_alchemy[][5] __initdata = { - [11] = { -1, INTA, INTB, INTX, INTX }, /* IDSEL 11 - miniPCI */ - [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - SN1741 */ - [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */ -}; -#endif - -#ifdef CONFIG_MIPS_MIRAGE -char irq_tab_alchemy[][5] __initdata = { - [11] = { -1, INTD, INTX, INTX, INTX }, /* IDSEL 11 - SMI VGX */ - [12] = { -1, INTX, INTX, INTC, INTX }, /* IDSEL 12 - PNX1300 */ - [13] = { -1, INTA, INTB, INTX, INTX }, /* IDSEL 13 - miniPCI */ -}; -#endif - -#ifdef CONFIG_MIPS_DB1550 -char irq_tab_alchemy[][5] __initdata = { - [11] = { -1, INTC, INTX, INTX, INTX }, /* IDSEL 11 - on-board HPT371 */ - [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */ - [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */ -}; -#endif - - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - -#ifndef CONFIG_MIPS_MIRAGE -#ifdef CONFIG_MIPS_DB1550 - { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ - { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ -#else - { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */ - { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */ - { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ - - { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */ - { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */ - { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ -#endif -#else - { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */ -#endif - -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile deleted file mode 100644 index 7c67b3d33be..00000000000 --- a/arch/mips/au1000/mtx-1/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Copyright 2003 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# Bruno Randolf -# -# Makefile for 4G Systems MTX-1 board. -# - -lib-y := init.o board_setup.o irqmap.o -obj-y := platform.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c deleted file mode 100644 index 3f8079186cf..00000000000 --- a/arch/mips/au1000/mtx-1/board_setup.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * 4G Systems MTX-1 board setup. - * - * Copyright 2003, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * Bruno Randolf - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -extern int (*board_pci_idsel)(unsigned int devsel, int assert); -int mtx1_pci_idsel(unsigned int devsel, int assert); - -void board_reset(void) -{ - /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ - au_writel(0x00000000, 0xAE00001C); -} - -void __init board_setup(void) -{ -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - /* Enable USB power switch */ - au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR); - au_writel(0x100000, GPIO2_OUTPUT); -#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ - -#ifdef CONFIG_PCI -#if defined(__MIPSEB__) - au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); -#else - au_writel(0xf, Au1500_PCI_CFG); -#endif -#endif - - /* Initialize sys_pinfunc */ - au_writel(SYS_PF_NI2, SYS_PINFUNC); - - /* Initialize GPIO */ - au_writel(0xFFFFFFFF, SYS_TRIOUTCLR); - au_writel(0x00000001, SYS_OUTPUTCLR); /* set M66EN (PCI 66MHz) to OFF */ - au_writel(0x00000008, SYS_OUTPUTSET); /* set PCI CLKRUN# to OFF */ - au_writel(0x00000002, SYS_OUTPUTSET); /* set EXT_IO3 ON */ - au_writel(0x00000020, SYS_OUTPUTCLR); /* set eth PHY TX_ER to OFF */ - - /* Enable LED and set it to green */ - au_writel(au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR); - au_writel(0x18000800, GPIO2_OUTPUT); - - board_pci_idsel = mtx1_pci_idsel; - - printk(KERN_INFO "4G Systems MTX-1 Board\n"); -} - -int -mtx1_pci_idsel(unsigned int devsel, int assert) -{ -#define MTX_IDSEL_ONLY_0_AND_3 0 -#if MTX_IDSEL_ONLY_0_AND_3 - if (devsel != 0 && devsel != 3) { - printk(KERN_ERR "*** not 0 or 3\n"); - return 0; - } -#endif - - if (assert && devsel != 0) - /* Suppress signal to Cardbus */ - au_writel(0x00000002, SYS_OUTPUTCLR); /* set EXT_IO3 OFF */ - else - au_writel(0x00000002, SYS_OUTPUTSET); /* set EXT_IO3 ON */ - au_sync_udelay(1); - return 1; -} - diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c deleted file mode 100644 index 3bae13c2895..00000000000 --- a/arch/mips/au1000/mtx-1/init.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * 4G Systems MTX-1 board setup - * - * Copyright 2003, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * Bruno Randolf - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ - return "MTX-1"; -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x04000000; - else - strict_strtol(memsize_str, 0, &memsize); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c deleted file mode 100644 index f2bf02951e9..00000000000 --- a/arch/mips/au1000/mtx-1/irqmap.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xxx irq map table - * - * Copyright 2003 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -char irq_tab_alchemy[][5] __initdata = { - [0] = { -1, INTA, INTA, INTX, INTX }, /* IDSEL 00 - AdapterA-Slot0 (top) */ - [1] = { -1, INTB, INTA, INTX, INTX }, /* IDSEL 01 - AdapterA-Slot1 (bottom) */ - [2] = { -1, INTC, INTD, INTX, INTX }, /* IDSEL 02 - AdapterB-Slot0 (top) */ - [3] = { -1, INTD, INTC, INTX, INTX }, /* IDSEL 03 - AdapterB-Slot1 (bottom) */ - [4] = { -1, INTA, INTB, INTX, INTX }, /* IDSEL 04 - AdapterC-Slot0 (top) */ - [5] = { -1, INTB, INTA, INTX, INTX }, /* IDSEL 05 - AdapterC-Slot1 (bottom) */ - [6] = { -1, INTC, INTD, INTX, INTX }, /* IDSEL 06 - AdapterD-Slot0 (top) */ - [7] = { -1, INTD, INTC, INTX, INTX }, /* IDSEL 07 - AdapterD-Slot1 (bottom) */ -}; - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, - { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c deleted file mode 100644 index 8b5914d1241..00000000000 --- a/arch/mips/au1000/mtx-1/platform.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * MTX-1 platform devices registration - * - * Copyright (C) 2007, Florian Fainelli - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct gpio_keys_button mtx1_gpio_button[] = { - { - .gpio = 207, - .code = BTN_0, - .desc = "System button", - } -}; - -static struct gpio_keys_platform_data mtx1_buttons_data = { - .buttons = mtx1_gpio_button, - .nbuttons = ARRAY_SIZE(mtx1_gpio_button), -}; - -static struct platform_device mtx1_button = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &mtx1_buttons_data, - } -}; - -static struct resource mtx1_wdt_res[] = { - [0] = { - .start = 15, - .end = 15, - .name = "mtx1-wdt-gpio", - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device mtx1_wdt = { - .name = "mtx1-wdt", - .id = 0, - .num_resources = ARRAY_SIZE(mtx1_wdt_res), - .resource = mtx1_wdt_res, -}; - -static struct gpio_led default_leds[] = { - { - .name = "mtx1:green", - .gpio = 211, - }, { - .name = "mtx1:red", - .gpio = 212, - }, -}; - -static struct gpio_led_platform_data mtx1_led_data = { - .num_leds = ARRAY_SIZE(default_leds), - .leds = default_leds, -}; - -static struct platform_device mtx1_gpio_leds = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &mtx1_led_data, - } -}; - -static struct mtd_partition mtx1_mtd_partitions[] = { - { - .name = "filesystem", - .size = 0x01C00000, - .offset = 0, - }, - { - .name = "yamon", - .size = 0x00100000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, - { - .name = "kernel", - .size = 0x002c0000, - .offset = MTDPART_OFS_APPEND, - }, - { - .name = "yamon env", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - }, -}; - -static struct physmap_flash_data mtx1_flash_data = { - .width = 4, - .nr_parts = 4, - .parts = mtx1_mtd_partitions, -}; - -static struct resource mtx1_mtd_resource = { - .start = 0x1e000000, - .end = 0x1fffffff, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device mtx1_mtd = { - .name = "physmap-flash", - .dev = { - .platform_data = &mtx1_flash_data, - }, - .num_resources = 1, - .resource = &mtx1_mtd_resource, -}; - -static struct __initdata platform_device * mtx1_devs[] = { - &mtx1_gpio_leds, - &mtx1_wdt, - &mtx1_button, - &mtx1_mtd, -}; - -static int __init mtx1_register_devices(void) -{ - gpio_direction_input(207); - return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs)); -} - -arch_initcall(mtx1_register_devices); diff --git a/arch/mips/au1000/pb1000/Makefile b/arch/mips/au1000/pb1000/Makefile deleted file mode 100644 index 99bbec0ca41..00000000000 --- a/arch/mips/au1000/pb1000/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2000, 2008 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# -# Makefile for the Alchemy Semiconductor Pb1000 board. -# - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c deleted file mode 100644 index 25df167a95b..00000000000 --- a/arch/mips/au1000/pb1000/board_setup.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2000, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include -#include - -void board_reset(void) -{ -} - -void __init board_setup(void) -{ - u32 pin_func, static_cfg0; - u32 sys_freqctrl, sys_clksrc; - u32 prid = read_c0_prid(); - - /* Set AUX clock to 12 MHz * 8 = 96 MHz */ - au_writel(8, SYS_AUXPLL); - au_writel(0, SYS_PINSTATERD); - udelay(100); - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - /* Zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* Zero and disable USBH/USBD clocks */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | - SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | - SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); - - switch (prid & 0x000000FF) { - case 0x00: /* DA */ - case 0x01: /* HA */ - case 0x02: /* HB */ - /* CPU core freq to 48 MHz to slow it way down... */ - au_writel(4, SYS_CPUPLL); - - /* - * Setup 48 MHz FREQ2 from CPUPLL for USB Host - * FRDIV2 = 3 -> div by 8 of 384 MHz -> 48 MHz - */ - sys_freqctrl |= (3 << SYS_FC_FRDIV2_BIT) | SYS_FC_FE2; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* CPU core freq to 384 MHz */ - au_writel(0x20, SYS_CPUPLL); - - printk(KERN_INFO "Au1000: 48 MHz OHCI workaround enabled\n"); - break; - - default: /* HC and newer */ - /* FREQ2 = aux / 2 = 48 MHz */ - sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) | - SYS_FC_FE2 | SYS_FC_FS2; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - break; - } - - /* - * Route 48 MHz FREQ2 into USB Host and/or Device - */ - sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MUH_BIT; - au_writel(sys_clksrc, SYS_CLKSRC); - - /* Configure pins GPIO[14:9] as GPIO */ - pin_func = au_readl(SYS_PINFUNC) & ~(SYS_PF_UR3 | SYS_PF_USB); - - /* 2nd USB port is USB host */ - pin_func |= SYS_PF_USB; - - au_writel(pin_func, SYS_PINFUNC); - au_writel(0x2800, SYS_TRIOUTCLR); - au_writel(0x0030, SYS_OUTPUTCLR); -#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ - - /* Make GPIO 15 an input (for interrupt line) */ - pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_IRF; - /* We don't need I2S, so make it available for GPIO[31:29] */ - pin_func |= SYS_PF_I2S; - au_writel(pin_func, SYS_PINFUNC); - - au_writel(0x8000, SYS_TRIOUTCLR); - - static_cfg0 = au_readl(MEM_STCFG0) & ~0xc00; - au_writel(static_cfg0, MEM_STCFG0); - - /* configure RCE2* for LCD */ - au_writel(0x00000004, MEM_STCFG2); - - /* MEM_STTIME2 */ - au_writel(0x09000000, MEM_STTIME2); - - /* Set 32-bit base address decoding for RCE2* */ - au_writel(0x10003ff0, MEM_STADDR2); - - /* - * PCI CPLD setup - * Expand CE0 to cover PCI - */ - au_writel(0x11803e40, MEM_STADDR1); - - /* Burst visibility on */ - au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0); - - au_writel(0x83, MEM_STCFG1); /* ewait enabled, flash timing */ - au_writel(0x33030a10, MEM_STTIME1); /* slower timing for FPGA */ - - /* Setup the static bus controller */ - au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ - au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ - au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ - - /* - * Enable Au1000 BCLK switching - note: sed1356 must not use - * its BCLK (Au1000 LCLK) for any timings - */ - switch (prid & 0x000000FF) { - case 0x00: /* DA */ - case 0x01: /* HA */ - case 0x02: /* HB */ - break; - default: /* HC and newer */ - /* - * Enable sys bus clock divider when IDLE state or no bus - * activity. - */ - au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); - break; - } -} diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c deleted file mode 100644 index 8a9c7d57208..00000000000 --- a/arch/mips/au1000/pb1000/init.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Pb1000 board setup - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ - return "Alchemy Pb1000"; -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = (int)fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x04000000; - else - strict_strtol(memsize_str, 0, &memsize); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c deleted file mode 100644 index b3d56b0af32..00000000000 --- a/arch/mips/au1000/pb1000/irqmap.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xxx irq map table - * - * Copyright 2003 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 }, -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/pb1100/Makefile b/arch/mips/au1000/pb1100/Makefile deleted file mode 100644 index 793e97c49e4..00000000000 --- a/arch/mips/au1000/pb1100/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2000, 2001, 2008 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# -# Makefile for the Alchemy Semiconductor Pb1100 board. -# - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c deleted file mode 100644 index c0bfd59a7a3..00000000000 --- a/arch/mips/au1000/pb1100/board_setup.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2002, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include -#include - -void board_reset(void) -{ - /* Hit BCSR.RST_VDDI[SOFT_RESET] */ - au_writel(0x00000000, PB1100_RST_VDDI); -} - -void __init board_setup(void) -{ - volatile void __iomem *base = (volatile void __iomem *)0xac000000UL; - - /* Set AUX clock to 12 MHz * 8 = 96 MHz */ - au_writel(8, SYS_AUXPLL); - au_writel(0, SYS_PININPUTEN); - udelay(100); - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - { - u32 pin_func, sys_freqctrl, sys_clksrc; - - /* Configure pins GPIO[14:9] as GPIO */ - pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3; - - /* Zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* Zero and disable USBH/USBD/IrDA clock */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~(SYS_CS_CIR | SYS_CS_DIR | SYS_CS_MIR_MASK); - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~(SYS_CS_CIR | SYS_CS_DIR | SYS_CS_MIR_MASK); - - /* FREQ2 = aux / 2 = 48 MHz */ - sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) | - SYS_FC_FE2 | SYS_FC_FS2; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* - * Route 48 MHz FREQ2 into USBH/USBD/IrDA - */ - sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MIR_BIT; - au_writel(sys_clksrc, SYS_CLKSRC); - - /* Setup the static bus controller */ - au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ - au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ - au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ - - /* - * Get USB Functionality pin state (device vs host drive pins). - */ - pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_USB; - /* 2nd USB port is USB host. */ - pin_func |= SYS_PF_USB; - au_writel(pin_func, SYS_PINFUNC); - } -#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ - - /* Enable sys bus clock divider when IDLE state or no bus activity. */ - au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); - - /* Enable the RTC if not already enabled. */ - if (!(readb(base + 0x28) & 0x20)) { - writeb(readb(base + 0x28) | 0x20, base + 0x28); - au_sync(); - } - /* Put the clock in BCD mode. */ - if (readb(base + 0x2C) & 0x4) { /* reg B */ - writeb(readb(base + 0x2c) & ~0x4, base + 0x2c); - au_sync(); - } -} diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c deleted file mode 100644 index 7c6792308bc..00000000000 --- a/arch/mips/au1000/pb1100/init.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Pb1100 board setup - * - * Copyright 2002, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ - return "Alchemy Pb1100"; -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg3; - - prom_init_cmdline(); - - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x04000000; - else - strict_strtol(memsize_str, 0, &memsize); - - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c deleted file mode 100644 index 9b7dd8b4128..00000000000 --- a/arch/mips/au1000/pb1100/irqmap.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xx0 IRQ map table - * - * Copyright 2003 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card Fully_Inserted# */ - { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card STSCHG# */ - { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card IRQ# */ - { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, /* DC_IRQ# */ -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/pb1200/Makefile b/arch/mips/au1000/pb1200/Makefile deleted file mode 100644 index d678adf7ce8..00000000000 --- a/arch/mips/au1000/pb1200/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards. -# - -lib-y := init.o board_setup.o irqmap.o -obj-y += platform.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c deleted file mode 100644 index 6cb2115059a..00000000000 --- a/arch/mips/au1000/pb1200/board_setup.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Alchemy Pb1200/Db1200 board setup. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include -#include - -extern void _board_init_irq(void); -extern void (*board_init_irq)(void); - -void board_reset(void) -{ - bcsr->resets = 0; - bcsr->system = 0; -} - -void __init board_setup(void) -{ - char *argptr = NULL; - -#if 0 - { - u32 pin_func; - - /* - * Enable PSC1 SYNC for AC97. Normaly done in audio driver, - * but it is board specific code, so put it here. - */ - pin_func = au_readl(SYS_PINFUNC); - au_sync(); - pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1; - au_writel(pin_func, SYS_PINFUNC); - - au_writel(0, (u32)bcsr | 0x10); /* turn off PCMCIA power */ - au_sync(); - } -#endif - -#if defined(CONFIG_I2C_AU1550) - { - u32 freq0, clksrc; - u32 pin_func; - - /* Select SMBus in CPLD */ - bcsr->resets &= ~BCSR_RESETS_PCS0MUX; - - pin_func = au_readl(SYS_PINFUNC); - au_sync(); - pin_func &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B); - /* Set GPIOs correctly */ - pin_func |= 2 << 17; - au_writel(pin_func, SYS_PINFUNC); - au_sync(); - - /* The I2C driver depends on 50 MHz clock */ - freq0 = au_readl(SYS_FREQCTRL0); - au_sync(); - freq0 &= ~(SYS_FC_FRDIV1_MASK | SYS_FC_FS1 | SYS_FC_FE1); - freq0 |= 3 << SYS_FC_FRDIV1_BIT; - /* 396 MHz / (3 + 1) * 2 == 49.5 MHz */ - au_writel(freq0, SYS_FREQCTRL0); - au_sync(); - freq0 |= SYS_FC_FE1; - au_writel(freq0, SYS_FREQCTRL0); - au_sync(); - - clksrc = au_readl(SYS_CLKSRC); - au_sync(); - clksrc &= ~(SYS_CS_CE0 | SYS_CS_DE0 | SYS_CS_ME0_MASK); - /* Bit 22 is EXTCLK0 for PSC0 */ - clksrc |= SYS_CS_MUX_FQ1 << SYS_CS_ME0_BIT; - au_writel(clksrc, SYS_CLKSRC); - au_sync(); - } -#endif - -#ifdef CONFIG_FB_AU1200 - argptr = prom_getcmdline(); -#ifdef CONFIG_MIPS_PB1200 - strcat(argptr, " video=au1200fb:panel:bs"); -#endif -#ifdef CONFIG_MIPS_DB1200 - strcat(argptr, " video=au1200fb:panel:bs"); -#endif -#endif - - /* - * The Pb1200 development board uses external MUX for PSC0 to - * support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI - */ -#ifdef CONFIG_I2C_AU1550 - bcsr->resets &= ~BCSR_RESETS_PCS0MUX; -#endif - au_sync(); - -#ifdef CONFIG_MIPS_PB1200 - printk(KERN_INFO "AMD Alchemy Pb1200 Board\n"); -#endif -#ifdef CONFIG_MIPS_DB1200 - printk(KERN_INFO "AMD Alchemy Db1200 Board\n"); -#endif - - /* Setup Pb1200 External Interrupt Controller */ - board_init_irq = _board_init_irq; -} - -int board_au1200fb_panel(void) -{ - BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; - int p; - - p = bcsr->switches; - p >>= 8; - p &= 0x0F; - return p; -} - -int board_au1200fb_panel_init(void) -{ - /* Apply power */ - BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; - - bcsr->board |= BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL; - /* printk(KERN_DEBUG "board_au1200fb_panel_init()\n"); */ - return 0; -} - -int board_au1200fb_panel_shutdown(void) -{ - /* Remove power */ - BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; - - bcsr->board &= ~(BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | - BCSR_BOARD_LCDBL); - /* printk(KERN_DEBUG "board_au1200fb_panel_shutdown()\n"); */ - return 0; -} diff --git a/arch/mips/au1000/pb1200/init.c b/arch/mips/au1000/pb1200/init.c deleted file mode 100644 index e9b2a0fd48a..00000000000 --- a/arch/mips/au1000/pb1200/init.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * PB1200 board setup - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ - return "Alchemy Pb1200"; -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = (int)fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x08000000; - else - strict_strtol(memsize_str, 0, &memsize); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c deleted file mode 100644 index 2a505ad8715..00000000000 --- a/arch/mips/au1000/pb1200/irqmap.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xxx irq map table - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#ifdef CONFIG_MIPS_PB1200 -#include -#endif - -#ifdef CONFIG_MIPS_DB1200 -#include -#define PB1200_INT_BEGIN DB1200_INT_BEGIN -#define PB1200_INT_END DB1200_INT_END -#endif - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - /* This is external interrupt cascade */ - { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); - -/* - * Support for External interrupts on the Pb1200 Development platform. - */ -static volatile int pb1200_cascade_en; - -irqreturn_t pb1200_cascade_handler(int irq, void *dev_id) -{ - unsigned short bisr = bcsr->int_status; - int extirq_nr = 0; - - /* Clear all the edge interrupts. This has no effect on level. */ - bcsr->int_status = bisr; - for ( ; bisr; bisr &= bisr - 1) { - extirq_nr = PB1200_INT_BEGIN + __ffs(bisr); - /* Ack and dispatch IRQ */ - do_IRQ(extirq_nr); - } - - return IRQ_RETVAL(1); -} - -inline void pb1200_enable_irq(unsigned int irq_nr) -{ - bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN); - bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN); -} - -inline void pb1200_disable_irq(unsigned int irq_nr) -{ - bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN); - bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN); -} - -static unsigned int pb1200_setup_cascade(void) -{ - return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler, - 0, "Pb1200 Cascade", &pb1200_cascade_handler); -} - -static unsigned int pb1200_startup_irq(unsigned int irq) -{ - if (++pb1200_cascade_en == 1) { - int res; - - res = pb1200_setup_cascade(); - if (res) - return res; - } - - pb1200_enable_irq(irq); - - return 0; -} - -static void pb1200_shutdown_irq(unsigned int irq) -{ - pb1200_disable_irq(irq); - if (--pb1200_cascade_en == 0) - free_irq(AU1000_GPIO_7, &pb1200_cascade_handler); -} - -static struct irq_chip external_irq_type = { -#ifdef CONFIG_MIPS_PB1200 - .name = "Pb1200 Ext", -#endif -#ifdef CONFIG_MIPS_DB1200 - .name = "Db1200 Ext", -#endif - .startup = pb1200_startup_irq, - .shutdown = pb1200_shutdown_irq, - .ack = pb1200_disable_irq, - .mask = pb1200_disable_irq, - .mask_ack = pb1200_disable_irq, - .unmask = pb1200_enable_irq, -}; - -void _board_init_irq(void) -{ - unsigned int irq; - -#ifdef CONFIG_MIPS_PB1200 - /* We have a problem with CPLD rev 3. */ - if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) { - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "Pb1200 must be at CPLD rev 4. Please have Pb1200\n"); - printk(KERN_ERR "updated to latest revision. This software will\n"); - printk(KERN_ERR "not work on anything less than CPLD rev 4.\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - printk(KERN_ERR "WARNING!!!\n"); - panic("Game over. Your score is 0."); - } -#endif - - for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) { - set_irq_chip_and_handler(irq, &external_irq_type, - handle_level_irq); - pb1200_disable_irq(irq); - } - - /* - * GPIO_7 can not be hooked here, so it is hooked upon first - * request of any source attached to the cascade. - */ -} diff --git a/arch/mips/au1000/pb1200/platform.c b/arch/mips/au1000/pb1200/platform.c deleted file mode 100644 index f8fb0aeac57..00000000000 --- a/arch/mips/au1000/pb1200/platform.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Pb1200/DBAu1200 board platform device registration - * - * Copyright (C) 2008 MontaVista Software Inc. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -#include - -static struct resource ide_resources[] = { - [0] = { - .start = IDE_PHYS_ADDR, - .end = IDE_PHYS_ADDR + IDE_PHYS_LEN - 1, - .flags = IORESOURCE_MEM - }, - [1] = { - .start = IDE_INT, - .end = IDE_INT, - .flags = IORESOURCE_IRQ - } -}; - -static u64 ide_dmamask = DMA_32BIT_MASK; - -static struct platform_device ide_device = { - .name = "au1200-ide", - .id = 0, - .dev = { - .dma_mask = &ide_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, - }, - .num_resources = ARRAY_SIZE(ide_resources), - .resource = ide_resources -}; - -static struct resource smc91c111_resources[] = { - [0] = { - .name = "smc91x-regs", - .start = SMC91C111_PHYS_ADDR, - .end = SMC91C111_PHYS_ADDR + 0xf, - .flags = IORESOURCE_MEM - }, - [1] = { - .start = SMC91C111_INT, - .end = SMC91C111_INT, - .flags = IORESOURCE_IRQ - }, -}; - -static struct platform_device smc91c111_device = { - .name = "smc91x", - .id = -1, - .num_resources = ARRAY_SIZE(smc91c111_resources), - .resource = smc91c111_resources -}; - -static struct platform_device *board_platform_devices[] __initdata = { - &ide_device, - &smc91c111_device -}; - -static int __init board_register_devices(void) -{ - return platform_add_devices(board_platform_devices, - ARRAY_SIZE(board_platform_devices)); -} - -arch_initcall(board_register_devices); diff --git a/arch/mips/au1000/pb1500/Makefile b/arch/mips/au1000/pb1500/Makefile deleted file mode 100644 index 602f38df20b..00000000000 --- a/arch/mips/au1000/pb1500/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2000, 2001, 2008 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# -# Makefile for the Alchemy Semiconductor Pb1500 board. -# - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c deleted file mode 100644 index 035771c6e5b..00000000000 --- a/arch/mips/au1000/pb1500/board_setup.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2000, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include -#include - -void board_reset(void) -{ - /* Hit BCSR.RST_VDDI[SOFT_RESET] */ - au_writel(0x00000000, PB1500_RST_VDDI); -} - -void __init board_setup(void) -{ - u32 pin_func; - u32 sys_freqctrl, sys_clksrc; - - sys_clksrc = sys_freqctrl = pin_func = 0; - /* Set AUX clock to 12 MHz * 8 = 96 MHz */ - au_writel(8, SYS_AUXPLL); - au_writel(0, SYS_PINSTATERD); - udelay(100); - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - - /* GPIO201 is input for PCMCIA card detect */ - /* GPIO203 is input for PCMCIA interrupt request */ - au_writel(au_readl(GPIO2_DIR) & ~((1 << 1) | (1 << 3)), GPIO2_DIR); - - /* Zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* zero and disable USBH/USBD clocks */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | - SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK | - SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK); - - /* FREQ2 = aux/2 = 48 MHz */ - sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) | SYS_FC_FE2 | SYS_FC_FS2; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* - * Route 48MHz FREQ2 into USB Host and/or Device - */ - sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MUH_BIT; - au_writel(sys_clksrc, SYS_CLKSRC); - - pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_USB; - /* 2nd USB port is USB host */ - pin_func |= SYS_PF_USB; - au_writel(pin_func, SYS_PINFUNC); -#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ - -#ifdef CONFIG_PCI - /* Setup PCI bus controller */ - au_writel(0, Au1500_PCI_CMEM); - au_writel(0x00003fff, Au1500_CFG_BASE); -#if defined(__MIPSEB__) - au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); -#else - au_writel(0xf, Au1500_PCI_CFG); -#endif - au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV); - au_writel(0, Au1500_PCI_MWBASE_REV_CCL); - au_writel(0x02a00356, Au1500_PCI_STATCMD); - au_writel(0x00003c04, Au1500_PCI_HDRTYPE); - au_writel(0x00000008, Au1500_PCI_MBAR); - au_sync(); -#endif - - /* Enable sys bus clock divider when IDLE state or no bus activity. */ - au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); - - /* Enable the RTC if not already enabled */ - if (!(au_readl(0xac000028) & 0x20)) { - printk(KERN_INFO "enabling clock ...\n"); - au_writel((au_readl(0xac000028) | 0x20), 0xac000028); - } - /* Put the clock in BCD mode */ - if (au_readl(0xac00002c) & 0x4) { /* reg B */ - au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c); - au_sync(); - } -} diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c deleted file mode 100644 index 3b6e395cf95..00000000000 --- a/arch/mips/au1000/pb1500/init.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Pb1500 board setup - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ - return "Alchemy Pb1500"; -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = (int)fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x04000000; - else - strict_strtol(memsize_str, 0, &memsize); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c deleted file mode 100644 index 39c4682766a..00000000000 --- a/arch/mips/au1000/pb1500/irqmap.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xxx irq map table - * - * Copyright 2003 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -char irq_tab_alchemy[][5] __initdata = { - [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT370 */ - [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */ -}; - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, - { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/pb1550/Makefile b/arch/mips/au1000/pb1550/Makefile deleted file mode 100644 index 7d8beca87fa..00000000000 --- a/arch/mips/au1000/pb1550/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2000, 2008 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# -# Makefile for the Alchemy Semiconductor Pb1550 board. -# - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/au1000/pb1550/board_setup.c b/arch/mips/au1000/pb1550/board_setup.c deleted file mode 100644 index 0ed76b64b6a..00000000000 --- a/arch/mips/au1000/pb1550/board_setup.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Alchemy Pb1550 board setup. - * - * Copyright 2000, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include -#include - -void board_reset(void) -{ - /* Hit BCSR.SYSTEM[RESET] */ - au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C); -} - -void __init board_setup(void) -{ - u32 pin_func; - - /* - * Enable PSC1 SYNC for AC'97. Normaly done in audio driver, - * but it is board specific code, so put it here. - */ - pin_func = au_readl(SYS_PINFUNC); - au_sync(); - pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1; - au_writel(pin_func, SYS_PINFUNC); - - au_writel(0, (u32)bcsr | 0x10); /* turn off PCMCIA power */ - au_sync(); - - printk(KERN_INFO "AMD Alchemy Pb1550 Board\n"); -} diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c deleted file mode 100644 index e1055a13a1a..00000000000 --- a/arch/mips/au1000/pb1550/init.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Pb1550 board setup - * - * Copyright 2001, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ - return "Alchemy Pb1550"; -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = (int)fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x08000000; - else - strict_strtol(memsize_str, 0, &memsize); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c deleted file mode 100644 index a02a4d1fa89..00000000000 --- a/arch/mips/au1000/pb1550/irqmap.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xx0 IRQ map table - * - * Copyright 2003 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -char irq_tab_alchemy[][5] __initdata = { - [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */ - [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */ -}; - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/xxs1500/Makefile b/arch/mips/au1000/xxs1500/Makefile deleted file mode 100644 index db3c526f64d..00000000000 --- a/arch/mips/au1000/xxs1500/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2003 MontaVista Software Inc. -# Author: MontaVista Software, Inc. -# -# Makefile for MyCable XXS1500 board. -# - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/au1000/xxs1500/board_setup.c deleted file mode 100644 index 4c587acac5c..00000000000 --- a/arch/mips/au1000/xxs1500/board_setup.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2000-2003, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -void board_reset(void) -{ - /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ - au_writel(0x00000000, 0xAE00001C); -} - -void __init board_setup(void) -{ - u32 pin_func; - - /* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */ - pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3; - pin_func |= SYS_PF_UR3; - au_writel(pin_func, SYS_PINFUNC); - - /* Enable UART */ - au_writel(0x01, UART3_ADDR + UART_MOD_CNTRL); /* clock enable (CE) */ - mdelay(10); - au_writel(0x03, UART3_ADDR + UART_MOD_CNTRL); /* CE and "enable" */ - mdelay(10); - - /* Enable DTR = USB power up */ - au_writel(0x01, UART3_ADDR + UART_MCR); /* UART_MCR_DTR is 0x01??? */ - -#ifdef CONFIG_PCMCIA_XXS1500 - /* Setup PCMCIA signals */ - au_writel(0, SYS_PININPUTEN); - - /* GPIO 0, 1, and 4 are inputs */ - au_writel(1 | (1 << 1) | (1 << 4), SYS_TRIOUTCLR); - - /* Enable GPIO2 if not already enabled */ - au_writel(1, GPIO2_ENABLE); - /* GPIO2 208/9/10/11 are inputs */ - au_writel((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11), GPIO2_DIR); - - /* Turn off power */ - au_writel((au_readl(GPIO2_PINSTATE) & ~(1 << 14)) | (1 << 30), - GPIO2_OUTPUT); -#endif - -#ifdef CONFIG_PCI -#if defined(__MIPSEB__) - au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); -#else - au_writel(0xf, Au1500_PCI_CFG); -#endif -#endif -} diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c deleted file mode 100644 index 7516434760a..00000000000 --- a/arch/mips/au1000/xxs1500/init.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * XXS1500 board setup - * - * Copyright 2003, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include - -#include - -const char *get_system_type(void) -{ - return "XXS1500"; -} - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - - memsize_str = prom_getenv("memsize"); - if (!memsize_str) - memsize = 0x04000000; - else - strict_strtol(memsize_str, 0, &memsize); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c deleted file mode 100644 index edf06ed1187..00000000000 --- a/arch/mips/au1000/xxs1500/irqmap.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Au1xxx irq map table - * - * Copyright 2003 Embedded Edge, LLC - * dan@embeddededge.com - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include - -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { - { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, - { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, - { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, - - { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */ - { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, -}; - -int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); -- cgit v1.2.3 From 384740dc49ea651ba350704d13ff6be9976e37fe Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 16 Sep 2008 19:48:51 +0200 Subject: MIPS: Move headfiles to new location below arch/mips/include Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 84 +- arch/mips/include/asm/Kbuild | 3 + arch/mips/include/asm/a.out.h | 35 + arch/mips/include/asm/abi.h | 25 + arch/mips/include/asm/addrspace.h | 154 ++ arch/mips/include/asm/asm.h | 409 +++++ arch/mips/include/asm/asmmacro-32.h | 158 ++ arch/mips/include/asm/asmmacro-64.h | 139 ++ arch/mips/include/asm/asmmacro.h | 82 + arch/mips/include/asm/atomic.h | 801 +++++++++ arch/mips/include/asm/auxvec.h | 4 + arch/mips/include/asm/barrier.h | 155 ++ arch/mips/include/asm/bcache.h | 60 + arch/mips/include/asm/bitops.h | 672 ++++++++ arch/mips/include/asm/bootinfo.h | 110 ++ arch/mips/include/asm/branch.h | 38 + arch/mips/include/asm/break.h | 34 + arch/mips/include/asm/bug.h | 33 + arch/mips/include/asm/bugs.h | 53 + arch/mips/include/asm/byteorder.h | 76 + arch/mips/include/asm/cache.h | 20 + arch/mips/include/asm/cachectl.h | 26 + arch/mips/include/asm/cacheflush.h | 116 ++ arch/mips/include/asm/cacheops.h | 85 + arch/mips/include/asm/checksum.h | 260 +++ arch/mips/include/asm/cmp.h | 18 + arch/mips/include/asm/cmpxchg.h | 124 ++ arch/mips/include/asm/compat-signal.h | 119 ++ arch/mips/include/asm/compat.h | 221 +++ arch/mips/include/asm/compiler.h | 19 + arch/mips/include/asm/cpu-features.h | 219 +++ arch/mips/include/asm/cpu-info.h | 84 + arch/mips/include/asm/cpu.h | 267 +++ arch/mips/include/asm/cputime.h | 6 + arch/mips/include/asm/current.h | 23 + arch/mips/include/asm/debug.h | 48 + arch/mips/include/asm/dec/ecc.h | 55 + arch/mips/include/asm/dec/interrupts.h | 126 ++ arch/mips/include/asm/dec/ioasic.h | 38 + arch/mips/include/asm/dec/ioasic_addrs.h | 152 ++ arch/mips/include/asm/dec/ioasic_ints.h | 74 + arch/mips/include/asm/dec/kn01.h | 90 + arch/mips/include/asm/dec/kn02.h | 91 + arch/mips/include/asm/dec/kn02ba.h | 67 + arch/mips/include/asm/dec/kn02ca.h | 79 + arch/mips/include/asm/dec/kn02xa.h | 84 + arch/mips/include/asm/dec/kn03.h | 74 + arch/mips/include/asm/dec/kn05.h | 76 + arch/mips/include/asm/dec/kn230.h | 26 + arch/mips/include/asm/dec/machtype.h | 27 + arch/mips/include/asm/dec/prom.h | 174 ++ arch/mips/include/asm/dec/system.h | 19 + arch/mips/include/asm/delay.h | 112 ++ arch/mips/include/asm/device.h | 7 + arch/mips/include/asm/div64.h | 110 ++ arch/mips/include/asm/dma-mapping.h | 81 + arch/mips/include/asm/dma.h | 315 ++++ arch/mips/include/asm/ds1286.h | 15 + arch/mips/include/asm/ds1287.h | 27 + arch/mips/include/asm/dsp.h | 85 + arch/mips/include/asm/edac.h | 34 + arch/mips/include/asm/elf.h | 371 ++++ arch/mips/include/asm/emergency-restart.h | 6 + arch/mips/include/asm/emma2rh/emma2rh.h | 333 ++++ arch/mips/include/asm/emma2rh/markeins.h | 75 + arch/mips/include/asm/errno.h | 131 ++ arch/mips/include/asm/fb.h | 19 + arch/mips/include/asm/fcntl.h | 61 + arch/mips/include/asm/fixmap.h | 118 ++ arch/mips/include/asm/floppy.h | 56 + arch/mips/include/asm/fpregdef.h | 99 ++ arch/mips/include/asm/fpu.h | 153 ++ arch/mips/include/asm/fpu_emulator.h | 37 + arch/mips/include/asm/futex.h | 203 +++ arch/mips/include/asm/fw/arc/hinv.h | 175 ++ arch/mips/include/asm/fw/arc/types.h | 86 + arch/mips/include/asm/fw/cfe/cfe_api.h | 122 ++ arch/mips/include/asm/fw/cfe/cfe_error.h | 80 + arch/mips/include/asm/gcmpregs.h | 117 ++ arch/mips/include/asm/gic.h | 487 ++++++ arch/mips/include/asm/gpio.h | 6 + arch/mips/include/asm/gt64120.h | 580 +++++++ arch/mips/include/asm/hardirq.h | 24 + arch/mips/include/asm/hazards.h | 271 +++ arch/mips/include/asm/highmem.h | 67 + arch/mips/include/asm/hw_irq.h | 20 + arch/mips/include/asm/i8253.h | 21 + arch/mips/include/asm/i8259.h | 86 + arch/mips/include/asm/ide.h | 13 + arch/mips/include/asm/inst.h | 394 +++++ arch/mips/include/asm/io.h | 589 +++++++ arch/mips/include/asm/ioctl.h | 94 ++ arch/mips/include/asm/ioctls.h | 109 ++ arch/mips/include/asm/ip32/crime.h | 158 ++ arch/mips/include/asm/ip32/ip32_ints.h | 114 ++ arch/mips/include/asm/ip32/mace.h | 365 ++++ arch/mips/include/asm/ipcbuf.h | 28 + arch/mips/include/asm/irq.h | 163 ++ arch/mips/include/asm/irq_cpu.h | 20 + arch/mips/include/asm/irq_gt641xx.h | 60 + arch/mips/include/asm/irq_regs.h | 21 + arch/mips/include/asm/irqflags.h | 283 ++++ arch/mips/include/asm/isadep.h | 34 + arch/mips/include/asm/jazz.h | 310 ++++ arch/mips/include/asm/jazzdma.h | 95 ++ arch/mips/include/asm/kdebug.h | 13 + arch/mips/include/asm/kexec.h | 30 + arch/mips/include/asm/kgdb.h | 44 + arch/mips/include/asm/kmap_types.h | 30 + arch/mips/include/asm/kspd.h | 36 + arch/mips/include/asm/lasat/ds1603.h | 18 + arch/mips/include/asm/lasat/eeprom.h | 17 + arch/mips/include/asm/lasat/head.h | 22 + arch/mips/include/asm/lasat/lasat.h | 258 +++ arch/mips/include/asm/lasat/lasatint.h | 14 + arch/mips/include/asm/lasat/picvue.h | 15 + arch/mips/include/asm/lasat/serial.h | 13 + arch/mips/include/asm/linkage.h | 10 + arch/mips/include/asm/local.h | 221 +++ arch/mips/include/asm/m48t35.h | 27 + arch/mips/include/asm/m48t37.h | 35 + arch/mips/include/asm/mach-au1x00/au1000.h | 1772 ++++++++++++++++++++ arch/mips/include/asm/mach-au1x00/au1000_dma.h | 458 +++++ arch/mips/include/asm/mach-au1x00/au1000_gpio.h | 56 + arch/mips/include/asm/mach-au1x00/au1100_mmc.h | 208 +++ arch/mips/include/asm/mach-au1x00/au1550_spi.h | 15 + arch/mips/include/asm/mach-au1x00/au1xxx.h | 43 + arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h | 386 +++++ arch/mips/include/asm/mach-au1x00/au1xxx_ide.h | 194 +++ arch/mips/include/asm/mach-au1x00/au1xxx_psc.h | 505 ++++++ arch/mips/include/asm/mach-au1x00/gpio.h | 69 + arch/mips/include/asm/mach-au1x00/ioremap.h | 42 + arch/mips/include/asm/mach-au1x00/prom.h | 13 + arch/mips/include/asm/mach-au1x00/war.h | 25 + arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 25 + arch/mips/include/asm/mach-bcm47xx/gpio.h | 59 + arch/mips/include/asm/mach-bcm47xx/war.h | 25 + arch/mips/include/asm/mach-cobalt/cobalt.h | 22 + .../asm/mach-cobalt/cpu-feature-overrides.h | 56 + arch/mips/include/asm/mach-cobalt/irq.h | 57 + arch/mips/include/asm/mach-cobalt/mach-gt64120.h | 27 + arch/mips/include/asm/mach-cobalt/war.h | 25 + arch/mips/include/asm/mach-db1x00/db1200.h | 230 +++ arch/mips/include/asm/mach-db1x00/db1x00.h | 179 ++ arch/mips/include/asm/mach-dec/mc146818rtc.h | 43 + arch/mips/include/asm/mach-dec/war.h | 25 + arch/mips/include/asm/mach-emma2rh/irq.h | 15 + arch/mips/include/asm/mach-emma2rh/war.h | 25 + .../asm/mach-excite/cpu-feature-overrides.h | 48 + arch/mips/include/asm/mach-excite/excite.h | 154 ++ arch/mips/include/asm/mach-excite/excite_fpga.h | 80 + .../include/asm/mach-excite/excite_nandflash.h | 7 + arch/mips/include/asm/mach-excite/rm9k_eth.h | 23 + arch/mips/include/asm/mach-excite/rm9k_wdt.h | 12 + arch/mips/include/asm/mach-excite/rm9k_xicap.h | 16 + arch/mips/include/asm/mach-excite/war.h | 25 + .../asm/mach-generic/cpu-feature-overrides.h | 13 + arch/mips/include/asm/mach-generic/dma-coherence.h | 45 + arch/mips/include/asm/mach-generic/floppy.h | 139 ++ arch/mips/include/asm/mach-generic/gpio.h | 21 + arch/mips/include/asm/mach-generic/ide.h | 167 ++ arch/mips/include/asm/mach-generic/ioremap.h | 34 + arch/mips/include/asm/mach-generic/irq.h | 45 + .../include/asm/mach-generic/kernel-entry-init.h | 25 + arch/mips/include/asm/mach-generic/kmalloc.h | 13 + arch/mips/include/asm/mach-generic/mangle-port.h | 52 + arch/mips/include/asm/mach-generic/mc146818rtc.h | 36 + arch/mips/include/asm/mach-generic/spaces.h | 85 + arch/mips/include/asm/mach-generic/topology.h | 1 + .../include/asm/mach-ip22/cpu-feature-overrides.h | 44 + arch/mips/include/asm/mach-ip22/ds1286.h | 18 + arch/mips/include/asm/mach-ip22/spaces.h | 27 + arch/mips/include/asm/mach-ip22/war.h | 29 + .../include/asm/mach-ip27/cpu-feature-overrides.h | 54 + arch/mips/include/asm/mach-ip27/dma-coherence.h | 50 + arch/mips/include/asm/mach-ip27/irq.h | 22 + .../mips/include/asm/mach-ip27/kernel-entry-init.h | 59 + arch/mips/include/asm/mach-ip27/kmalloc.h | 8 + arch/mips/include/asm/mach-ip27/mangle-port.h | 25 + arch/mips/include/asm/mach-ip27/mmzone.h | 36 + arch/mips/include/asm/mach-ip27/spaces.h | 30 + arch/mips/include/asm/mach-ip27/topology.h | 59 + arch/mips/include/asm/mach-ip27/war.h | 25 + .../include/asm/mach-ip28/cpu-feature-overrides.h | 50 + arch/mips/include/asm/mach-ip28/ds1286.h | 4 + arch/mips/include/asm/mach-ip28/spaces.h | 22 + arch/mips/include/asm/mach-ip28/war.h | 25 + .../include/asm/mach-ip32/cpu-feature-overrides.h | 50 + arch/mips/include/asm/mach-ip32/dma-coherence.h | 72 + arch/mips/include/asm/mach-ip32/kmalloc.h | 11 + arch/mips/include/asm/mach-ip32/mangle-port.h | 26 + arch/mips/include/asm/mach-ip32/mc146818rtc.h | 36 + arch/mips/include/asm/mach-ip32/war.h | 25 + arch/mips/include/asm/mach-jazz/dma-coherence.h | 40 + arch/mips/include/asm/mach-jazz/floppy.h | 135 ++ arch/mips/include/asm/mach-jazz/mc146818rtc.h | 38 + arch/mips/include/asm/mach-jazz/war.h | 25 + arch/mips/include/asm/mach-lasat/irq.h | 13 + arch/mips/include/asm/mach-lasat/mach-gt64120.h | 27 + arch/mips/include/asm/mach-lasat/war.h | 25 + arch/mips/include/asm/mach-lemote/dma-coherence.h | 42 + arch/mips/include/asm/mach-lemote/mc146818rtc.h | 36 + arch/mips/include/asm/mach-lemote/war.h | 25 + .../include/asm/mach-malta/cpu-feature-overrides.h | 72 + arch/mips/include/asm/mach-malta/irq.h | 9 + .../include/asm/mach-malta/kernel-entry-init.h | 52 + arch/mips/include/asm/mach-malta/mach-gt64120.h | 19 + arch/mips/include/asm/mach-malta/mc146818rtc.h | 48 + arch/mips/include/asm/mach-malta/war.h | 25 + .../asm/mach-mipssim/cpu-feature-overrides.h | 65 + arch/mips/include/asm/mach-mipssim/war.h | 25 + arch/mips/include/asm/mach-pb1x00/mc146818rtc.h | 34 + arch/mips/include/asm/mach-pb1x00/pb1000.h | 87 + arch/mips/include/asm/mach-pb1x00/pb1100.h | 85 + arch/mips/include/asm/mach-pb1x00/pb1200.h | 259 +++ arch/mips/include/asm/mach-pb1x00/pb1500.h | 49 + arch/mips/include/asm/mach-pb1x00/pb1550.h | 177 ++ arch/mips/include/asm/mach-pnx8550/cm.h | 43 + arch/mips/include/asm/mach-pnx8550/glb.h | 86 + arch/mips/include/asm/mach-pnx8550/int.h | 140 ++ .../include/asm/mach-pnx8550/kernel-entry-init.h | 262 +++ arch/mips/include/asm/mach-pnx8550/nand.h | 121 ++ arch/mips/include/asm/mach-pnx8550/pci.h | 185 ++ arch/mips/include/asm/mach-pnx8550/uart.h | 30 + arch/mips/include/asm/mach-pnx8550/usb.h | 32 + arch/mips/include/asm/mach-pnx8550/war.h | 25 + .../asm/mach-rc32434/cpu-feature-overrides.h | 81 + arch/mips/include/asm/mach-rc32434/ddr.h | 141 ++ arch/mips/include/asm/mach-rc32434/dma.h | 103 ++ arch/mips/include/asm/mach-rc32434/dma_v.h | 52 + arch/mips/include/asm/mach-rc32434/eth.h | 220 +++ arch/mips/include/asm/mach-rc32434/gpio.h | 88 + arch/mips/include/asm/mach-rc32434/integ.h | 59 + arch/mips/include/asm/mach-rc32434/irq.h | 33 + arch/mips/include/asm/mach-rc32434/pci.h | 481 ++++++ arch/mips/include/asm/mach-rc32434/prom.h | 40 + arch/mips/include/asm/mach-rc32434/rb.h | 84 + arch/mips/include/asm/mach-rc32434/rc32434.h | 19 + arch/mips/include/asm/mach-rc32434/timer.h | 65 + arch/mips/include/asm/mach-rc32434/war.h | 25 + .../include/asm/mach-rm/cpu-feature-overrides.h | 43 + arch/mips/include/asm/mach-rm/mc146818rtc.h | 21 + arch/mips/include/asm/mach-rm/war.h | 29 + .../asm/mach-sibyte/cpu-feature-overrides.h | 47 + arch/mips/include/asm/mach-sibyte/war.h | 37 + arch/mips/include/asm/mach-tx39xx/ioremap.h | 38 + arch/mips/include/asm/mach-tx39xx/mangle-port.h | 23 + arch/mips/include/asm/mach-tx39xx/war.h | 25 + .../asm/mach-tx49xx/cpu-feature-overrides.h | 23 + arch/mips/include/asm/mach-tx49xx/ioremap.h | 43 + arch/mips/include/asm/mach-tx49xx/kmalloc.h | 8 + arch/mips/include/asm/mach-tx49xx/war.h | 25 + arch/mips/include/asm/mach-vr41xx/irq.h | 8 + arch/mips/include/asm/mach-vr41xx/war.h | 25 + arch/mips/include/asm/mach-wrppmc/mach-gt64120.h | 83 + arch/mips/include/asm/mach-wrppmc/war.h | 25 + .../asm/mach-yosemite/cpu-feature-overrides.h | 47 + arch/mips/include/asm/mach-yosemite/war.h | 25 + arch/mips/include/asm/mc146818-time.h | 119 ++ arch/mips/include/asm/mc146818rtc.h | 16 + arch/mips/include/asm/mips-boards/bonito64.h | 436 +++++ arch/mips/include/asm/mips-boards/generic.h | 104 ++ arch/mips/include/asm/mips-boards/launch.h | 35 + arch/mips/include/asm/mips-boards/malta.h | 102 ++ arch/mips/include/asm/mips-boards/maltaint.h | 110 ++ arch/mips/include/asm/mips-boards/msc01_pci.h | 258 +++ arch/mips/include/asm/mips-boards/piix4.h | 80 + arch/mips/include/asm/mips-boards/prom.h | 47 + arch/mips/include/asm/mips-boards/sim.h | 40 + arch/mips/include/asm/mips-boards/simint.h | 31 + arch/mips/include/asm/mips_mt.h | 26 + arch/mips/include/asm/mipsmtregs.h | 395 +++++ arch/mips/include/asm/mipsprom.h | 76 + arch/mips/include/asm/mipsregs.h | 1526 +++++++++++++++++ arch/mips/include/asm/mman.h | 77 + arch/mips/include/asm/mmu.h | 6 + arch/mips/include/asm/mmu_context.h | 297 ++++ arch/mips/include/asm/mmzone.h | 17 + arch/mips/include/asm/module.h | 136 ++ arch/mips/include/asm/msc01_ic.h | 148 ++ arch/mips/include/asm/msgbuf.h | 47 + arch/mips/include/asm/mutex.h | 9 + arch/mips/include/asm/nile4.h | 310 ++++ arch/mips/include/asm/paccess.h | 112 ++ arch/mips/include/asm/page.h | 191 +++ arch/mips/include/asm/param.h | 31 + arch/mips/include/asm/parport.h | 15 + arch/mips/include/asm/pci.h | 179 ++ arch/mips/include/asm/pci/bridge.h | 854 ++++++++++ arch/mips/include/asm/percpu.h | 6 + arch/mips/include/asm/pgalloc.h | 143 ++ arch/mips/include/asm/pgtable-32.h | 234 +++ arch/mips/include/asm/pgtable-64.h | 253 +++ arch/mips/include/asm/pgtable-bits.h | 137 ++ arch/mips/include/asm/pgtable.h | 383 +++++ arch/mips/include/asm/pmc-sierra/msp71xx/gpio.h | 46 + .../include/asm/pmc-sierra/msp71xx/msp_cic_int.h | 151 ++ arch/mips/include/asm/pmc-sierra/msp71xx/msp_int.h | 43 + arch/mips/include/asm/pmc-sierra/msp71xx/msp_pci.h | 205 +++ .../mips/include/asm/pmc-sierra/msp71xx/msp_prom.h | 176 ++ .../include/asm/pmc-sierra/msp71xx/msp_regops.h | 236 +++ .../mips/include/asm/pmc-sierra/msp71xx/msp_regs.h | 663 ++++++++ .../include/asm/pmc-sierra/msp71xx/msp_slp_int.h | 141 ++ arch/mips/include/asm/pmc-sierra/msp71xx/war.h | 28 + arch/mips/include/asm/pmon.h | 46 + arch/mips/include/asm/poll.h | 9 + arch/mips/include/asm/posix_types.h | 144 ++ arch/mips/include/asm/prefetch.h | 87 + arch/mips/include/asm/processor.h | 263 +++ arch/mips/include/asm/ptrace.h | 102 ++ arch/mips/include/asm/r4k-timer.h | 30 + arch/mips/include/asm/r4kcache.h | 443 +++++ arch/mips/include/asm/reboot.h | 15 + arch/mips/include/asm/reg.h | 128 ++ arch/mips/include/asm/regdef.h | 100 ++ arch/mips/include/asm/resource.h | 35 + arch/mips/include/asm/rm9k-ocd.h | 56 + arch/mips/include/asm/rtlx.h | 65 + arch/mips/include/asm/scatterlist.h | 28 + arch/mips/include/asm/seccomp.h | 37 + arch/mips/include/asm/sections.h | 6 + arch/mips/include/asm/segment.h | 6 + arch/mips/include/asm/sembuf.h | 22 + arch/mips/include/asm/serial.h | 22 + arch/mips/include/asm/setup.h | 10 + arch/mips/include/asm/sgi/gio.h | 86 + arch/mips/include/asm/sgi/hpc3.h | 317 ++++ arch/mips/include/asm/sgi/ioc.h | 200 +++ arch/mips/include/asm/sgi/ip22.h | 78 + arch/mips/include/asm/sgi/mc.h | 231 +++ arch/mips/include/asm/sgi/pi1.h | 71 + arch/mips/include/asm/sgi/seeq.h | 21 + arch/mips/include/asm/sgi/sgi.h | 47 + arch/mips/include/asm/sgi/wd.h | 20 + arch/mips/include/asm/sgialib.h | 124 ++ arch/mips/include/asm/sgiarcs.h | 548 ++++++ arch/mips/include/asm/sgidefs.h | 44 + arch/mips/include/asm/shmbuf.h | 38 + arch/mips/include/asm/shmparam.h | 13 + arch/mips/include/asm/sibyte/bcm1480_int.h | 312 ++++ arch/mips/include/asm/sibyte/bcm1480_l2c.h | 176 ++ arch/mips/include/asm/sibyte/bcm1480_mc.h | 984 +++++++++++ arch/mips/include/asm/sibyte/bcm1480_regs.h | 902 ++++++++++ arch/mips/include/asm/sibyte/bcm1480_scd.h | 406 +++++ arch/mips/include/asm/sibyte/bigsur.h | 49 + arch/mips/include/asm/sibyte/board.h | 68 + arch/mips/include/asm/sibyte/carmel.h | 58 + arch/mips/include/asm/sibyte/sb1250.h | 68 + arch/mips/include/asm/sibyte/sb1250_defs.h | 259 +++ arch/mips/include/asm/sibyte/sb1250_dma.h | 594 +++++++ arch/mips/include/asm/sibyte/sb1250_genbus.h | 474 ++++++ arch/mips/include/asm/sibyte/sb1250_int.h | 248 +++ arch/mips/include/asm/sibyte/sb1250_l2c.h | 131 ++ arch/mips/include/asm/sibyte/sb1250_ldt.h | 423 +++++ arch/mips/include/asm/sibyte/sb1250_mac.h | 656 ++++++++ arch/mips/include/asm/sibyte/sb1250_mc.h | 550 ++++++ arch/mips/include/asm/sibyte/sb1250_regs.h | 893 ++++++++++ arch/mips/include/asm/sibyte/sb1250_scd.h | 654 ++++++++ arch/mips/include/asm/sibyte/sb1250_smbus.h | 204 +++ arch/mips/include/asm/sibyte/sb1250_syncser.h | 146 ++ arch/mips/include/asm/sibyte/sb1250_uart.h | 362 ++++ arch/mips/include/asm/sibyte/sentosa.h | 40 + arch/mips/include/asm/sibyte/swarm.h | 64 + arch/mips/include/asm/sigcontext.h | 100 ++ arch/mips/include/asm/siginfo.h | 130 ++ arch/mips/include/asm/signal.h | 139 ++ arch/mips/include/asm/sim.h | 82 + arch/mips/include/asm/smp-ops.h | 57 + arch/mips/include/asm/smp.h | 63 + arch/mips/include/asm/smtc.h | 71 + arch/mips/include/asm/smtc_ipi.h | 128 ++ arch/mips/include/asm/smtc_proc.h | 23 + arch/mips/include/asm/smvp.h | 19 + arch/mips/include/asm/sn/addrs.h | 430 +++++ arch/mips/include/asm/sn/agent.h | 46 + arch/mips/include/asm/sn/arch.h | 64 + arch/mips/include/asm/sn/fru.h | 44 + arch/mips/include/asm/sn/gda.h | 107 ++ arch/mips/include/asm/sn/hub.h | 16 + arch/mips/include/asm/sn/intr.h | 129 ++ arch/mips/include/asm/sn/io.h | 59 + arch/mips/include/asm/sn/ioc3.h | 663 ++++++++ arch/mips/include/asm/sn/klconfig.h | 898 ++++++++++ arch/mips/include/asm/sn/kldir.h | 217 +++ arch/mips/include/asm/sn/klkernvars.h | 29 + arch/mips/include/asm/sn/launch.h | 106 ++ arch/mips/include/asm/sn/mapped_kernel.h | 54 + arch/mips/include/asm/sn/nmi.h | 125 ++ arch/mips/include/asm/sn/sn0/addrs.h | 288 ++++ arch/mips/include/asm/sn/sn0/arch.h | 72 + arch/mips/include/asm/sn/sn0/hub.h | 40 + arch/mips/include/asm/sn/sn0/hubio.h | 972 +++++++++++ arch/mips/include/asm/sn/sn0/hubmd.h | 789 +++++++++ arch/mips/include/asm/sn/sn0/hubni.h | 255 +++ arch/mips/include/asm/sn/sn0/hubpi.h | 409 +++++ arch/mips/include/asm/sn/sn0/ip27.h | 85 + arch/mips/include/asm/sn/sn_private.h | 19 + arch/mips/include/asm/sn/types.h | 26 + arch/mips/include/asm/sni.h | 244 +++ arch/mips/include/asm/socket.h | 117 ++ arch/mips/include/asm/sockios.h | 26 + arch/mips/include/asm/sparsemem.h | 14 + arch/mips/include/asm/spinlock.h | 376 +++++ arch/mips/include/asm/spinlock_types.h | 20 + arch/mips/include/asm/stackframe.h | 574 +++++++ arch/mips/include/asm/stacktrace.h | 48 + arch/mips/include/asm/stat.h | 132 ++ arch/mips/include/asm/statfs.h | 96 ++ arch/mips/include/asm/string.h | 143 ++ arch/mips/include/asm/suspend.h | 6 + arch/mips/include/asm/sysmips.h | 25 + arch/mips/include/asm/system.h | 220 +++ arch/mips/include/asm/termbits.h | 226 +++ arch/mips/include/asm/termios.h | 132 ++ arch/mips/include/asm/thread_info.h | 151 ++ arch/mips/include/asm/time.h | 79 + arch/mips/include/asm/timex.h | 43 + arch/mips/include/asm/titan_dep.h | 231 +++ arch/mips/include/asm/tlb.h | 23 + arch/mips/include/asm/tlbdebug.h | 16 + arch/mips/include/asm/tlbflush.h | 47 + arch/mips/include/asm/topology.h | 17 + arch/mips/include/asm/traps.h | 28 + arch/mips/include/asm/txx9/boards.h | 13 + arch/mips/include/asm/txx9/generic.h | 89 + arch/mips/include/asm/txx9/jmr3927.h | 180 ++ arch/mips/include/asm/txx9/pci.h | 39 + arch/mips/include/asm/txx9/rbtx4927.h | 92 + arch/mips/include/asm/txx9/rbtx4938.h | 145 ++ arch/mips/include/asm/txx9/rbtx4939.h | 133 ++ arch/mips/include/asm/txx9/smsc_fdc37m81x.h | 68 + arch/mips/include/asm/txx9/spi.h | 34 + arch/mips/include/asm/txx9/tx3927.h | 341 ++++ arch/mips/include/asm/txx9/tx4927.h | 269 +++ arch/mips/include/asm/txx9/tx4927pcic.h | 203 +++ arch/mips/include/asm/txx9/tx4938.h | 295 ++++ arch/mips/include/asm/txx9/tx4939.h | 544 ++++++ arch/mips/include/asm/txx9irq.h | 34 + arch/mips/include/asm/txx9pio.h | 29 + arch/mips/include/asm/txx9tmr.h | 67 + arch/mips/include/asm/types.h | 54 + arch/mips/include/asm/uaccess.h | 852 ++++++++++ arch/mips/include/asm/ucontext.h | 21 + arch/mips/include/asm/unaligned.h | 28 + arch/mips/include/asm/unistd.h | 1037 ++++++++++++ arch/mips/include/asm/user.h | 58 + arch/mips/include/asm/vga.h | 47 + arch/mips/include/asm/vpe.h | 37 + arch/mips/include/asm/vr41xx/capcella.h | 43 + arch/mips/include/asm/vr41xx/giu.h | 78 + arch/mips/include/asm/vr41xx/irq.h | 101 ++ arch/mips/include/asm/vr41xx/mpc30x.h | 37 + arch/mips/include/asm/vr41xx/pci.h | 90 + arch/mips/include/asm/vr41xx/siu.h | 58 + arch/mips/include/asm/vr41xx/tb0219.h | 42 + arch/mips/include/asm/vr41xx/tb0226.h | 43 + arch/mips/include/asm/vr41xx/tb0287.h | 43 + arch/mips/include/asm/vr41xx/vr41xx.h | 152 ++ arch/mips/include/asm/war.h | 244 +++ arch/mips/include/asm/wbflush.h | 34 + arch/mips/include/asm/xor.h | 1 + arch/mips/include/asm/xtalk/xtalk.h | 52 + arch/mips/include/asm/xtalk/xwidget.h | 167 ++ 463 files changed, 61652 insertions(+), 42 deletions(-) create mode 100644 arch/mips/include/asm/Kbuild create mode 100644 arch/mips/include/asm/a.out.h create mode 100644 arch/mips/include/asm/abi.h create mode 100644 arch/mips/include/asm/addrspace.h create mode 100644 arch/mips/include/asm/asm.h create mode 100644 arch/mips/include/asm/asmmacro-32.h create mode 100644 arch/mips/include/asm/asmmacro-64.h create mode 100644 arch/mips/include/asm/asmmacro.h create mode 100644 arch/mips/include/asm/atomic.h create mode 100644 arch/mips/include/asm/auxvec.h create mode 100644 arch/mips/include/asm/barrier.h create mode 100644 arch/mips/include/asm/bcache.h create mode 100644 arch/mips/include/asm/bitops.h create mode 100644 arch/mips/include/asm/bootinfo.h create mode 100644 arch/mips/include/asm/branch.h create mode 100644 arch/mips/include/asm/break.h create mode 100644 arch/mips/include/asm/bug.h create mode 100644 arch/mips/include/asm/bugs.h create mode 100644 arch/mips/include/asm/byteorder.h create mode 100644 arch/mips/include/asm/cache.h create mode 100644 arch/mips/include/asm/cachectl.h create mode 100644 arch/mips/include/asm/cacheflush.h create mode 100644 arch/mips/include/asm/cacheops.h create mode 100644 arch/mips/include/asm/checksum.h create mode 100644 arch/mips/include/asm/cmp.h create mode 100644 arch/mips/include/asm/cmpxchg.h create mode 100644 arch/mips/include/asm/compat-signal.h create mode 100644 arch/mips/include/asm/compat.h create mode 100644 arch/mips/include/asm/compiler.h create mode 100644 arch/mips/include/asm/cpu-features.h create mode 100644 arch/mips/include/asm/cpu-info.h create mode 100644 arch/mips/include/asm/cpu.h create mode 100644 arch/mips/include/asm/cputime.h create mode 100644 arch/mips/include/asm/current.h create mode 100644 arch/mips/include/asm/debug.h create mode 100644 arch/mips/include/asm/dec/ecc.h create mode 100644 arch/mips/include/asm/dec/interrupts.h create mode 100644 arch/mips/include/asm/dec/ioasic.h create mode 100644 arch/mips/include/asm/dec/ioasic_addrs.h create mode 100644 arch/mips/include/asm/dec/ioasic_ints.h create mode 100644 arch/mips/include/asm/dec/kn01.h create mode 100644 arch/mips/include/asm/dec/kn02.h create mode 100644 arch/mips/include/asm/dec/kn02ba.h create mode 100644 arch/mips/include/asm/dec/kn02ca.h create mode 100644 arch/mips/include/asm/dec/kn02xa.h create mode 100644 arch/mips/include/asm/dec/kn03.h create mode 100644 arch/mips/include/asm/dec/kn05.h create mode 100644 arch/mips/include/asm/dec/kn230.h create mode 100644 arch/mips/include/asm/dec/machtype.h create mode 100644 arch/mips/include/asm/dec/prom.h create mode 100644 arch/mips/include/asm/dec/system.h create mode 100644 arch/mips/include/asm/delay.h create mode 100644 arch/mips/include/asm/device.h create mode 100644 arch/mips/include/asm/div64.h create mode 100644 arch/mips/include/asm/dma-mapping.h create mode 100644 arch/mips/include/asm/dma.h create mode 100644 arch/mips/include/asm/ds1286.h create mode 100644 arch/mips/include/asm/ds1287.h create mode 100644 arch/mips/include/asm/dsp.h create mode 100644 arch/mips/include/asm/edac.h create mode 100644 arch/mips/include/asm/elf.h create mode 100644 arch/mips/include/asm/emergency-restart.h create mode 100644 arch/mips/include/asm/emma2rh/emma2rh.h create mode 100644 arch/mips/include/asm/emma2rh/markeins.h create mode 100644 arch/mips/include/asm/errno.h create mode 100644 arch/mips/include/asm/fb.h create mode 100644 arch/mips/include/asm/fcntl.h create mode 100644 arch/mips/include/asm/fixmap.h create mode 100644 arch/mips/include/asm/floppy.h create mode 100644 arch/mips/include/asm/fpregdef.h create mode 100644 arch/mips/include/asm/fpu.h create mode 100644 arch/mips/include/asm/fpu_emulator.h create mode 100644 arch/mips/include/asm/futex.h create mode 100644 arch/mips/include/asm/fw/arc/hinv.h create mode 100644 arch/mips/include/asm/fw/arc/types.h create mode 100644 arch/mips/include/asm/fw/cfe/cfe_api.h create mode 100644 arch/mips/include/asm/fw/cfe/cfe_error.h create mode 100644 arch/mips/include/asm/gcmpregs.h create mode 100644 arch/mips/include/asm/gic.h create mode 100644 arch/mips/include/asm/gpio.h create mode 100644 arch/mips/include/asm/gt64120.h create mode 100644 arch/mips/include/asm/hardirq.h create mode 100644 arch/mips/include/asm/hazards.h create mode 100644 arch/mips/include/asm/highmem.h create mode 100644 arch/mips/include/asm/hw_irq.h create mode 100644 arch/mips/include/asm/i8253.h create mode 100644 arch/mips/include/asm/i8259.h create mode 100644 arch/mips/include/asm/ide.h create mode 100644 arch/mips/include/asm/inst.h create mode 100644 arch/mips/include/asm/io.h create mode 100644 arch/mips/include/asm/ioctl.h create mode 100644 arch/mips/include/asm/ioctls.h create mode 100644 arch/mips/include/asm/ip32/crime.h create mode 100644 arch/mips/include/asm/ip32/ip32_ints.h create mode 100644 arch/mips/include/asm/ip32/mace.h create mode 100644 arch/mips/include/asm/ipcbuf.h create mode 100644 arch/mips/include/asm/irq.h create mode 100644 arch/mips/include/asm/irq_cpu.h create mode 100644 arch/mips/include/asm/irq_gt641xx.h create mode 100644 arch/mips/include/asm/irq_regs.h create mode 100644 arch/mips/include/asm/irqflags.h create mode 100644 arch/mips/include/asm/isadep.h create mode 100644 arch/mips/include/asm/jazz.h create mode 100644 arch/mips/include/asm/jazzdma.h create mode 100644 arch/mips/include/asm/kdebug.h create mode 100644 arch/mips/include/asm/kexec.h create mode 100644 arch/mips/include/asm/kgdb.h create mode 100644 arch/mips/include/asm/kmap_types.h create mode 100644 arch/mips/include/asm/kspd.h create mode 100644 arch/mips/include/asm/lasat/ds1603.h create mode 100644 arch/mips/include/asm/lasat/eeprom.h create mode 100644 arch/mips/include/asm/lasat/head.h create mode 100644 arch/mips/include/asm/lasat/lasat.h create mode 100644 arch/mips/include/asm/lasat/lasatint.h create mode 100644 arch/mips/include/asm/lasat/picvue.h create mode 100644 arch/mips/include/asm/lasat/serial.h create mode 100644 arch/mips/include/asm/linkage.h create mode 100644 arch/mips/include/asm/local.h create mode 100644 arch/mips/include/asm/m48t35.h create mode 100644 arch/mips/include/asm/m48t37.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1000.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1000_dma.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1000_gpio.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1100_mmc.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1550_spi.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1xxx.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1xxx_ide.h create mode 100644 arch/mips/include/asm/mach-au1x00/au1xxx_psc.h create mode 100644 arch/mips/include/asm/mach-au1x00/gpio.h create mode 100644 arch/mips/include/asm/mach-au1x00/ioremap.h create mode 100644 arch/mips/include/asm/mach-au1x00/prom.h create mode 100644 arch/mips/include/asm/mach-au1x00/war.h create mode 100644 arch/mips/include/asm/mach-bcm47xx/bcm47xx.h create mode 100644 arch/mips/include/asm/mach-bcm47xx/gpio.h create mode 100644 arch/mips/include/asm/mach-bcm47xx/war.h create mode 100644 arch/mips/include/asm/mach-cobalt/cobalt.h create mode 100644 arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-cobalt/irq.h create mode 100644 arch/mips/include/asm/mach-cobalt/mach-gt64120.h create mode 100644 arch/mips/include/asm/mach-cobalt/war.h create mode 100644 arch/mips/include/asm/mach-db1x00/db1200.h create mode 100644 arch/mips/include/asm/mach-db1x00/db1x00.h create mode 100644 arch/mips/include/asm/mach-dec/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-dec/war.h create mode 100644 arch/mips/include/asm/mach-emma2rh/irq.h create mode 100644 arch/mips/include/asm/mach-emma2rh/war.h create mode 100644 arch/mips/include/asm/mach-excite/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-excite/excite.h create mode 100644 arch/mips/include/asm/mach-excite/excite_fpga.h create mode 100644 arch/mips/include/asm/mach-excite/excite_nandflash.h create mode 100644 arch/mips/include/asm/mach-excite/rm9k_eth.h create mode 100644 arch/mips/include/asm/mach-excite/rm9k_wdt.h create mode 100644 arch/mips/include/asm/mach-excite/rm9k_xicap.h create mode 100644 arch/mips/include/asm/mach-excite/war.h create mode 100644 arch/mips/include/asm/mach-generic/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-generic/dma-coherence.h create mode 100644 arch/mips/include/asm/mach-generic/floppy.h create mode 100644 arch/mips/include/asm/mach-generic/gpio.h create mode 100644 arch/mips/include/asm/mach-generic/ide.h create mode 100644 arch/mips/include/asm/mach-generic/ioremap.h create mode 100644 arch/mips/include/asm/mach-generic/irq.h create mode 100644 arch/mips/include/asm/mach-generic/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-generic/kmalloc.h create mode 100644 arch/mips/include/asm/mach-generic/mangle-port.h create mode 100644 arch/mips/include/asm/mach-generic/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-generic/spaces.h create mode 100644 arch/mips/include/asm/mach-generic/topology.h create mode 100644 arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-ip22/ds1286.h create mode 100644 arch/mips/include/asm/mach-ip22/spaces.h create mode 100644 arch/mips/include/asm/mach-ip22/war.h create mode 100644 arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-ip27/dma-coherence.h create mode 100644 arch/mips/include/asm/mach-ip27/irq.h create mode 100644 arch/mips/include/asm/mach-ip27/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-ip27/kmalloc.h create mode 100644 arch/mips/include/asm/mach-ip27/mangle-port.h create mode 100644 arch/mips/include/asm/mach-ip27/mmzone.h create mode 100644 arch/mips/include/asm/mach-ip27/spaces.h create mode 100644 arch/mips/include/asm/mach-ip27/topology.h create mode 100644 arch/mips/include/asm/mach-ip27/war.h create mode 100644 arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-ip28/ds1286.h create mode 100644 arch/mips/include/asm/mach-ip28/spaces.h create mode 100644 arch/mips/include/asm/mach-ip28/war.h create mode 100644 arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-ip32/dma-coherence.h create mode 100644 arch/mips/include/asm/mach-ip32/kmalloc.h create mode 100644 arch/mips/include/asm/mach-ip32/mangle-port.h create mode 100644 arch/mips/include/asm/mach-ip32/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-ip32/war.h create mode 100644 arch/mips/include/asm/mach-jazz/dma-coherence.h create mode 100644 arch/mips/include/asm/mach-jazz/floppy.h create mode 100644 arch/mips/include/asm/mach-jazz/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-jazz/war.h create mode 100644 arch/mips/include/asm/mach-lasat/irq.h create mode 100644 arch/mips/include/asm/mach-lasat/mach-gt64120.h create mode 100644 arch/mips/include/asm/mach-lasat/war.h create mode 100644 arch/mips/include/asm/mach-lemote/dma-coherence.h create mode 100644 arch/mips/include/asm/mach-lemote/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-lemote/war.h create mode 100644 arch/mips/include/asm/mach-malta/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-malta/irq.h create mode 100644 arch/mips/include/asm/mach-malta/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-malta/mach-gt64120.h create mode 100644 arch/mips/include/asm/mach-malta/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-malta/war.h create mode 100644 arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-mipssim/war.h create mode 100644 arch/mips/include/asm/mach-pb1x00/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-pb1x00/pb1000.h create mode 100644 arch/mips/include/asm/mach-pb1x00/pb1100.h create mode 100644 arch/mips/include/asm/mach-pb1x00/pb1200.h create mode 100644 arch/mips/include/asm/mach-pb1x00/pb1500.h create mode 100644 arch/mips/include/asm/mach-pb1x00/pb1550.h create mode 100644 arch/mips/include/asm/mach-pnx8550/cm.h create mode 100644 arch/mips/include/asm/mach-pnx8550/glb.h create mode 100644 arch/mips/include/asm/mach-pnx8550/int.h create mode 100644 arch/mips/include/asm/mach-pnx8550/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-pnx8550/nand.h create mode 100644 arch/mips/include/asm/mach-pnx8550/pci.h create mode 100644 arch/mips/include/asm/mach-pnx8550/uart.h create mode 100644 arch/mips/include/asm/mach-pnx8550/usb.h create mode 100644 arch/mips/include/asm/mach-pnx8550/war.h create mode 100644 arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-rc32434/ddr.h create mode 100644 arch/mips/include/asm/mach-rc32434/dma.h create mode 100644 arch/mips/include/asm/mach-rc32434/dma_v.h create mode 100644 arch/mips/include/asm/mach-rc32434/eth.h create mode 100644 arch/mips/include/asm/mach-rc32434/gpio.h create mode 100644 arch/mips/include/asm/mach-rc32434/integ.h create mode 100644 arch/mips/include/asm/mach-rc32434/irq.h create mode 100644 arch/mips/include/asm/mach-rc32434/pci.h create mode 100644 arch/mips/include/asm/mach-rc32434/prom.h create mode 100644 arch/mips/include/asm/mach-rc32434/rb.h create mode 100644 arch/mips/include/asm/mach-rc32434/rc32434.h create mode 100644 arch/mips/include/asm/mach-rc32434/timer.h create mode 100644 arch/mips/include/asm/mach-rc32434/war.h create mode 100644 arch/mips/include/asm/mach-rm/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-rm/mc146818rtc.h create mode 100644 arch/mips/include/asm/mach-rm/war.h create mode 100644 arch/mips/include/asm/mach-sibyte/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-sibyte/war.h create mode 100644 arch/mips/include/asm/mach-tx39xx/ioremap.h create mode 100644 arch/mips/include/asm/mach-tx39xx/mangle-port.h create mode 100644 arch/mips/include/asm/mach-tx39xx/war.h create mode 100644 arch/mips/include/asm/mach-tx49xx/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-tx49xx/ioremap.h create mode 100644 arch/mips/include/asm/mach-tx49xx/kmalloc.h create mode 100644 arch/mips/include/asm/mach-tx49xx/war.h create mode 100644 arch/mips/include/asm/mach-vr41xx/irq.h create mode 100644 arch/mips/include/asm/mach-vr41xx/war.h create mode 100644 arch/mips/include/asm/mach-wrppmc/mach-gt64120.h create mode 100644 arch/mips/include/asm/mach-wrppmc/war.h create mode 100644 arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-yosemite/war.h create mode 100644 arch/mips/include/asm/mc146818-time.h create mode 100644 arch/mips/include/asm/mc146818rtc.h create mode 100644 arch/mips/include/asm/mips-boards/bonito64.h create mode 100644 arch/mips/include/asm/mips-boards/generic.h create mode 100644 arch/mips/include/asm/mips-boards/launch.h create mode 100644 arch/mips/include/asm/mips-boards/malta.h create mode 100644 arch/mips/include/asm/mips-boards/maltaint.h create mode 100644 arch/mips/include/asm/mips-boards/msc01_pci.h create mode 100644 arch/mips/include/asm/mips-boards/piix4.h create mode 100644 arch/mips/include/asm/mips-boards/prom.h create mode 100644 arch/mips/include/asm/mips-boards/sim.h create mode 100644 arch/mips/include/asm/mips-boards/simint.h create mode 100644 arch/mips/include/asm/mips_mt.h create mode 100644 arch/mips/include/asm/mipsmtregs.h create mode 100644 arch/mips/include/asm/mipsprom.h create mode 100644 arch/mips/include/asm/mipsregs.h create mode 100644 arch/mips/include/asm/mman.h create mode 100644 arch/mips/include/asm/mmu.h create mode 100644 arch/mips/include/asm/mmu_context.h create mode 100644 arch/mips/include/asm/mmzone.h create mode 100644 arch/mips/include/asm/module.h create mode 100644 arch/mips/include/asm/msc01_ic.h create mode 100644 arch/mips/include/asm/msgbuf.h create mode 100644 arch/mips/include/asm/mutex.h create mode 100644 arch/mips/include/asm/nile4.h create mode 100644 arch/mips/include/asm/paccess.h create mode 100644 arch/mips/include/asm/page.h create mode 100644 arch/mips/include/asm/param.h create mode 100644 arch/mips/include/asm/parport.h create mode 100644 arch/mips/include/asm/pci.h create mode 100644 arch/mips/include/asm/pci/bridge.h create mode 100644 arch/mips/include/asm/percpu.h create mode 100644 arch/mips/include/asm/pgalloc.h create mode 100644 arch/mips/include/asm/pgtable-32.h create mode 100644 arch/mips/include/asm/pgtable-64.h create mode 100644 arch/mips/include/asm/pgtable-bits.h create mode 100644 arch/mips/include/asm/pgtable.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/gpio.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/msp_cic_int.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/msp_int.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/msp_pci.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/msp_slp_int.h create mode 100644 arch/mips/include/asm/pmc-sierra/msp71xx/war.h create mode 100644 arch/mips/include/asm/pmon.h create mode 100644 arch/mips/include/asm/poll.h create mode 100644 arch/mips/include/asm/posix_types.h create mode 100644 arch/mips/include/asm/prefetch.h create mode 100644 arch/mips/include/asm/processor.h create mode 100644 arch/mips/include/asm/ptrace.h create mode 100644 arch/mips/include/asm/r4k-timer.h create mode 100644 arch/mips/include/asm/r4kcache.h create mode 100644 arch/mips/include/asm/reboot.h create mode 100644 arch/mips/include/asm/reg.h create mode 100644 arch/mips/include/asm/regdef.h create mode 100644 arch/mips/include/asm/resource.h create mode 100644 arch/mips/include/asm/rm9k-ocd.h create mode 100644 arch/mips/include/asm/rtlx.h create mode 100644 arch/mips/include/asm/scatterlist.h create mode 100644 arch/mips/include/asm/seccomp.h create mode 100644 arch/mips/include/asm/sections.h create mode 100644 arch/mips/include/asm/segment.h create mode 100644 arch/mips/include/asm/sembuf.h create mode 100644 arch/mips/include/asm/serial.h create mode 100644 arch/mips/include/asm/setup.h create mode 100644 arch/mips/include/asm/sgi/gio.h create mode 100644 arch/mips/include/asm/sgi/hpc3.h create mode 100644 arch/mips/include/asm/sgi/ioc.h create mode 100644 arch/mips/include/asm/sgi/ip22.h create mode 100644 arch/mips/include/asm/sgi/mc.h create mode 100644 arch/mips/include/asm/sgi/pi1.h create mode 100644 arch/mips/include/asm/sgi/seeq.h create mode 100644 arch/mips/include/asm/sgi/sgi.h create mode 100644 arch/mips/include/asm/sgi/wd.h create mode 100644 arch/mips/include/asm/sgialib.h create mode 100644 arch/mips/include/asm/sgiarcs.h create mode 100644 arch/mips/include/asm/sgidefs.h create mode 100644 arch/mips/include/asm/shmbuf.h create mode 100644 arch/mips/include/asm/shmparam.h create mode 100644 arch/mips/include/asm/sibyte/bcm1480_int.h create mode 100644 arch/mips/include/asm/sibyte/bcm1480_l2c.h create mode 100644 arch/mips/include/asm/sibyte/bcm1480_mc.h create mode 100644 arch/mips/include/asm/sibyte/bcm1480_regs.h create mode 100644 arch/mips/include/asm/sibyte/bcm1480_scd.h create mode 100644 arch/mips/include/asm/sibyte/bigsur.h create mode 100644 arch/mips/include/asm/sibyte/board.h create mode 100644 arch/mips/include/asm/sibyte/carmel.h create mode 100644 arch/mips/include/asm/sibyte/sb1250.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_defs.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_dma.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_genbus.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_int.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_l2c.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_ldt.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_mac.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_mc.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_regs.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_scd.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_smbus.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_syncser.h create mode 100644 arch/mips/include/asm/sibyte/sb1250_uart.h create mode 100644 arch/mips/include/asm/sibyte/sentosa.h create mode 100644 arch/mips/include/asm/sibyte/swarm.h create mode 100644 arch/mips/include/asm/sigcontext.h create mode 100644 arch/mips/include/asm/siginfo.h create mode 100644 arch/mips/include/asm/signal.h create mode 100644 arch/mips/include/asm/sim.h create mode 100644 arch/mips/include/asm/smp-ops.h create mode 100644 arch/mips/include/asm/smp.h create mode 100644 arch/mips/include/asm/smtc.h create mode 100644 arch/mips/include/asm/smtc_ipi.h create mode 100644 arch/mips/include/asm/smtc_proc.h create mode 100644 arch/mips/include/asm/smvp.h create mode 100644 arch/mips/include/asm/sn/addrs.h create mode 100644 arch/mips/include/asm/sn/agent.h create mode 100644 arch/mips/include/asm/sn/arch.h create mode 100644 arch/mips/include/asm/sn/fru.h create mode 100644 arch/mips/include/asm/sn/gda.h create mode 100644 arch/mips/include/asm/sn/hub.h create mode 100644 arch/mips/include/asm/sn/intr.h create mode 100644 arch/mips/include/asm/sn/io.h create mode 100644 arch/mips/include/asm/sn/ioc3.h create mode 100644 arch/mips/include/asm/sn/klconfig.h create mode 100644 arch/mips/include/asm/sn/kldir.h create mode 100644 arch/mips/include/asm/sn/klkernvars.h create mode 100644 arch/mips/include/asm/sn/launch.h create mode 100644 arch/mips/include/asm/sn/mapped_kernel.h create mode 100644 arch/mips/include/asm/sn/nmi.h create mode 100644 arch/mips/include/asm/sn/sn0/addrs.h create mode 100644 arch/mips/include/asm/sn/sn0/arch.h create mode 100644 arch/mips/include/asm/sn/sn0/hub.h create mode 100644 arch/mips/include/asm/sn/sn0/hubio.h create mode 100644 arch/mips/include/asm/sn/sn0/hubmd.h create mode 100644 arch/mips/include/asm/sn/sn0/hubni.h create mode 100644 arch/mips/include/asm/sn/sn0/hubpi.h create mode 100644 arch/mips/include/asm/sn/sn0/ip27.h create mode 100644 arch/mips/include/asm/sn/sn_private.h create mode 100644 arch/mips/include/asm/sn/types.h create mode 100644 arch/mips/include/asm/sni.h create mode 100644 arch/mips/include/asm/socket.h create mode 100644 arch/mips/include/asm/sockios.h create mode 100644 arch/mips/include/asm/sparsemem.h create mode 100644 arch/mips/include/asm/spinlock.h create mode 100644 arch/mips/include/asm/spinlock_types.h create mode 100644 arch/mips/include/asm/stackframe.h create mode 100644 arch/mips/include/asm/stacktrace.h create mode 100644 arch/mips/include/asm/stat.h create mode 100644 arch/mips/include/asm/statfs.h create mode 100644 arch/mips/include/asm/string.h create mode 100644 arch/mips/include/asm/suspend.h create mode 100644 arch/mips/include/asm/sysmips.h create mode 100644 arch/mips/include/asm/system.h create mode 100644 arch/mips/include/asm/termbits.h create mode 100644 arch/mips/include/asm/termios.h create mode 100644 arch/mips/include/asm/thread_info.h create mode 100644 arch/mips/include/asm/time.h create mode 100644 arch/mips/include/asm/timex.h create mode 100644 arch/mips/include/asm/titan_dep.h create mode 100644 arch/mips/include/asm/tlb.h create mode 100644 arch/mips/include/asm/tlbdebug.h create mode 100644 arch/mips/include/asm/tlbflush.h create mode 100644 arch/mips/include/asm/topology.h create mode 100644 arch/mips/include/asm/traps.h create mode 100644 arch/mips/include/asm/txx9/boards.h create mode 100644 arch/mips/include/asm/txx9/generic.h create mode 100644 arch/mips/include/asm/txx9/jmr3927.h create mode 100644 arch/mips/include/asm/txx9/pci.h create mode 100644 arch/mips/include/asm/txx9/rbtx4927.h create mode 100644 arch/mips/include/asm/txx9/rbtx4938.h create mode 100644 arch/mips/include/asm/txx9/rbtx4939.h create mode 100644 arch/mips/include/asm/txx9/smsc_fdc37m81x.h create mode 100644 arch/mips/include/asm/txx9/spi.h create mode 100644 arch/mips/include/asm/txx9/tx3927.h create mode 100644 arch/mips/include/asm/txx9/tx4927.h create mode 100644 arch/mips/include/asm/txx9/tx4927pcic.h create mode 100644 arch/mips/include/asm/txx9/tx4938.h create mode 100644 arch/mips/include/asm/txx9/tx4939.h create mode 100644 arch/mips/include/asm/txx9irq.h create mode 100644 arch/mips/include/asm/txx9pio.h create mode 100644 arch/mips/include/asm/txx9tmr.h create mode 100644 arch/mips/include/asm/types.h create mode 100644 arch/mips/include/asm/uaccess.h create mode 100644 arch/mips/include/asm/ucontext.h create mode 100644 arch/mips/include/asm/unaligned.h create mode 100644 arch/mips/include/asm/unistd.h create mode 100644 arch/mips/include/asm/user.h create mode 100644 arch/mips/include/asm/vga.h create mode 100644 arch/mips/include/asm/vpe.h create mode 100644 arch/mips/include/asm/vr41xx/capcella.h create mode 100644 arch/mips/include/asm/vr41xx/giu.h create mode 100644 arch/mips/include/asm/vr41xx/irq.h create mode 100644 arch/mips/include/asm/vr41xx/mpc30x.h create mode 100644 arch/mips/include/asm/vr41xx/pci.h create mode 100644 arch/mips/include/asm/vr41xx/siu.h create mode 100644 arch/mips/include/asm/vr41xx/tb0219.h create mode 100644 arch/mips/include/asm/vr41xx/tb0226.h create mode 100644 arch/mips/include/asm/vr41xx/tb0287.h create mode 100644 arch/mips/include/asm/vr41xx/vr41xx.h create mode 100644 arch/mips/include/asm/war.h create mode 100644 arch/mips/include/asm/wbflush.h create mode 100644 arch/mips/include/asm/xor.h create mode 100644 arch/mips/include/asm/xtalk/xtalk.h create mode 100644 arch/mips/include/asm/xtalk/xwidget.h (limited to 'arch') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4401a0c1278..7f39fd8a91f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -170,97 +170,97 @@ libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ -cflags-$(CONFIG_MACH_JAZZ) += -Iinclude/asm-mips/mach-jazz +cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # # Common Alchemy Au1x00 stuff # core-$(CONFIG_SOC_AU1X00) += arch/mips/alchemy/common/ -cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00 +cflags-$(CONFIG_SOC_AU1X00) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 # # AMD Alchemy Pb1000 eval board # libs-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/pb1000/ -cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 # # AMD Alchemy Pb1100 eval board # libs-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/pb1100/ -cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 # # AMD Alchemy Pb1500 eval board # libs-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/pb1500/ -cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 # # AMD Alchemy Pb1550 eval board # libs-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/pb1550/ -cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 # # AMD Alchemy Pb1200 eval board # libs-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/pb1200/ -cflags-$(CONFIG_MIPS_PB1200) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 # # AMD Alchemy Db1000 eval board # libs-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 # # AMD Alchemy Db1100 eval board # libs-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 # # AMD Alchemy Db1500 eval board # libs-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 # # AMD Alchemy Db1550 eval board # libs-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # # AMD Alchemy Db1200 eval board # libs-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/pb1200/ -cflags-$(CONFIG_MIPS_DB1200) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 # # AMD Alchemy Bosporus eval board # libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 # # AMD Alchemy Mirage eval board # libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 # @@ -279,14 +279,14 @@ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # Cobalt Server # core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ -cflags-$(CONFIG_MIPS_COBALT) += -Iinclude/asm-mips/mach-cobalt +cflags-$(CONFIG_MIPS_COBALT) += -I$(srctree)/arch/mips/include/asm/mach-cobalt load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 # # DECstation family # core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ -cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec +cflags-$(CONFIG_MACH_DECSTATION)+= -I$(srctree)/arch/mips/include/asm/mach-dec libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 @@ -294,7 +294,7 @@ load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 # Wind River PPMC Board (4KC + GT64120) # core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ -cflags-$(CONFIG_WR_PPMC) += -Iinclude/asm-mips/mach-wrppmc +cflags-$(CONFIG_WR_PPMC) += -I$(srctree)/arch/mips/include/asm/mach-wrppmc load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 # @@ -302,13 +302,13 @@ load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 # core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/ load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000 -cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote +cflags-$(CONFIG_LEMOTE_FULONG) += -I$(srctree)/arch/mips/include/asm/mach-lemote # # MIPS Malta board # core-$(CONFIG_MIPS_MALTA) += arch/mips/mti-malta/ -cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-malta +cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 all-$(CONFIG_MIPS_MALTA) := vmlinux.bin @@ -316,14 +316,14 @@ all-$(CONFIG_MIPS_MALTA) := vmlinux.bin # MIPS SIM # core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ -cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-mipssim +cflags-$(CONFIG_MIPS_SIM) += -I$(srctree)/arch/mips/include/asm/mach-mipssim load-$(CONFIG_MIPS_SIM) += 0x80100000 # # PMC-Sierra MSP SOCs # core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/ -cflags-$(CONFIG_PMC_MSP) += -Iinclude/asm-mips/pmc-sierra/msp71xx \ +cflags-$(CONFIG_PMC_MSP) += -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \ -mno-branch-likely load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 @@ -331,28 +331,28 @@ load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 # PMC-Sierra Yosemite # core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/ -cflags-$(CONFIG_PMC_YOSEMITE) += -Iinclude/asm-mips/mach-yosemite +cflags-$(CONFIG_PMC_YOSEMITE) += -I$(srctree)/arch/mips/include/asm/mach-yosemite load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 # # Basler eXcite # core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/ -cflags-$(CONFIG_BASLER_EXCITE) += -Iinclude/asm-mips/mach-excite +cflags-$(CONFIG_BASLER_EXCITE) += -I$(srctree)/arch/mips/include/asm/mach-excite load-$(CONFIG_BASLER_EXCITE) += 0x80100000 # # LASAT platforms # core-$(CONFIG_LASAT) += arch/mips/lasat/ -cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat +cflags-$(CONFIG_LASAT) += -I$(srctree)/arch/mips/include/asm/mach-lasat load-$(CONFIG_LASAT) += 0xffffffff80000000 # # Common VR41xx # core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/ -cflags-$(CONFIG_MACH_VR41XX) += -Iinclude/asm-mips/mach-vr41xx +cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx # # ZAO Networks Capcella (VR4131) @@ -385,13 +385,13 @@ load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 # Common NXP PNX8550 # core-$(CONFIG_SOC_PNX8550) += arch/mips/nxp/pnx8550/common/ -cflags-$(CONFIG_SOC_PNX8550) += -Iinclude/asm-mips/mach-pnx8550 +cflags-$(CONFIG_SOC_PNX8550) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 # # NXP PNX8550 JBS board # libs-$(CONFIG_PNX8550_JBS) += arch/mips/nxp/pnx8550/jbs/ -#cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550 +#cflags-$(CONFIG_PNX8550_JBS) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 # NXP PNX8550 STB810 board @@ -402,7 +402,7 @@ load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 # NEC EMMA2RH boards # core-$(CONFIG_EMMA2RH) += arch/mips/emma2rh/common/ -cflags-$(CONFIG_EMMA2RH) += -Iinclude/asm-mips/mach-emma2rh +cflags-$(CONFIG_EMMA2RH) += -I$(srctree)/arch/mips/include/asm/mach-emma2rh # NEC EMMA2RH Mark-eins core-$(CONFIG_MARKEINS) += arch/mips/emma2rh/markeins/ @@ -418,7 +418,7 @@ load-$(CONFIG_MARKEINS) += 0xffffffff88100000 # address by 8kb. # core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP22) += -Iinclude/asm-mips/mach-ip22 +cflags-$(CONFIG_SGI_IP22) += -I$(srctree)/arch/mips/include/asm/mach-ip22 ifdef CONFIG_32BIT load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 endif @@ -435,7 +435,7 @@ endif # ifdef CONFIG_SGI_IP27 core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ -cflags-$(CONFIG_SGI_IP27) += -Iinclude/asm-mips/mach-ip27 +cflags-$(CONFIG_SGI_IP27) += -I$(srctree)/arch/mips/include/asm/mach-ip27 ifdef CONFIG_MAPPED_KERNEL load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 @@ -460,7 +460,7 @@ ifdef CONFIG_SGI_IP28 endif endif core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=1 -Iinclude/asm-mips/mach-ip28 +cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=1 -I$(srctree)/arch/mips/include/asm/mach-ip28 load-$(CONFIG_SGI_IP28) += 0xa800000020004000 # @@ -472,7 +472,7 @@ load-$(CONFIG_SGI_IP28) += 0xa800000020004000 # will break. # core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ -cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32 +cflags-$(CONFIG_SGI_IP32) += -I$(srctree)/arch/mips/include/asm/mach-ip32 load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 # @@ -484,22 +484,22 @@ load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 # core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_BCM112X) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_SB1250) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/bcm1480/ core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x55) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_BCM1x55) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/bcm1480/ core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x80) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_BCM1x80) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL # @@ -529,14 +529,14 @@ load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 # Broadcom BCM47XX boards # core-$(CONFIG_BCM47XX) += arch/mips/bcm47xx/ -cflags-$(CONFIG_BCM47XX) += -Iinclude/asm-mips/mach-bcm47xx +cflags-$(CONFIG_BCM47XX) += -I$(srctree)/arch/mips/include/asm/mach-bcm47xx load-$(CONFIG_BCM47XX) := 0xffffffff80001000 # # SNI RM # core-$(CONFIG_SNI_RM) += arch/mips/sni/ -cflags-$(CONFIG_SNI_RM) += -Iinclude/asm-mips/mach-rm +cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm ifdef CONFIG_CPU_LITTLE_ENDIAN load-$(CONFIG_SNI_RM) += 0xffffffff80600000 else @@ -548,10 +548,10 @@ all-$(CONFIG_SNI_RM) := vmlinux.ecoff # Common TXx9 # core-$(CONFIG_MACH_TX39XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX39XX) += -Iinclude/asm-mips/mach-tx39xx +cflags-$(CONFIG_MACH_TX39XX) += -I$(srctree)/arch/mips/include/asm/mach-tx39xx load-$(CONFIG_MACH_TX39XX) += 0xffffffff80050000 core-$(CONFIG_MACH_TX49XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX49XX) += -Iinclude/asm-mips/mach-tx49xx +cflags-$(CONFIG_MACH_TX49XX) += -I$(srctree)/arch/mips/include/asm/mach-tx49xx load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 # @@ -563,7 +563,7 @@ core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/txx9/jmr3927/ # Routerboard 532 board # core-$(CONFIG_MIKROTIK_RB532) += arch/mips/rb532/ -cflags-$(CONFIG_MIKROTIK_RB532) += -Iinclude/asm-mips/mach-rc32434 +cflags-$(CONFIG_MIKROTIK_RB532) += -I$(srctree)/arch/mips/include/asm/mach-rc32434 load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 # @@ -573,7 +573,7 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ -cflags-y += -Iinclude/asm-mips/mach-generic +cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ ifdef CONFIG_32BIT diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild new file mode 100644 index 00000000000..7897f05e316 --- /dev/null +++ b/arch/mips/include/asm/Kbuild @@ -0,0 +1,3 @@ +include include/asm-generic/Kbuild.asm + +header-y += cachectl.h sgidefs.h sysmips.h diff --git a/arch/mips/include/asm/a.out.h b/arch/mips/include/asm/a.out.h new file mode 100644 index 00000000000..cad8371422a --- /dev/null +++ b/arch/mips/include/asm/a.out.h @@ -0,0 +1,35 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2003 by Ralf Baechle + */ +#ifndef _ASM_A_OUT_H +#define _ASM_A_OUT_H + +#ifdef __KERNEL__ + + +#endif + +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for + file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, + in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in + bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +#endif /* _ASM_A_OUT_H */ diff --git a/arch/mips/include/asm/abi.h b/arch/mips/include/asm/abi.h new file mode 100644 index 00000000000..1dd74fbdc09 --- /dev/null +++ b/arch/mips/include/asm/abi.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005, 06 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2005 MIPS Technologies, Inc. + */ +#ifndef _ASM_ABI_H +#define _ASM_ABI_H + +#include +#include + +struct mips_abi { + int (* const setup_frame)(struct k_sigaction * ka, + struct pt_regs *regs, int signr, + sigset_t *set); + int (* const setup_rt_frame)(struct k_sigaction * ka, + struct pt_regs *regs, int signr, + sigset_t *set, siginfo_t *info); + const unsigned long restart; +}; + +#endif /* _ASM_ABI_H */ diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h new file mode 100644 index 00000000000..569f80aacbd --- /dev/null +++ b/arch/mips/include/asm/addrspace.h @@ -0,0 +1,154 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 99 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999 by Silicon Graphics, Inc. + */ +#ifndef _ASM_ADDRSPACE_H +#define _ASM_ADDRSPACE_H + +#include + +/* + * Configure language + */ +#ifdef __ASSEMBLY__ +#define _ATYPE_ +#define _ATYPE32_ +#define _ATYPE64_ +#define _CONST64_(x) x +#else +#define _ATYPE_ __PTRDIFF_TYPE__ +#define _ATYPE32_ int +#define _ATYPE64_ __s64 +#ifdef CONFIG_64BIT +#define _CONST64_(x) x ## L +#else +#define _CONST64_(x) x ## LL +#endif +#endif + +/* + * 32-bit MIPS address spaces + */ +#ifdef __ASSEMBLY__ +#define _ACAST32_ +#define _ACAST64_ +#else +#define _ACAST32_ (_ATYPE_)(_ATYPE32_) /* widen if necessary */ +#define _ACAST64_ (_ATYPE64_) /* do _not_ narrow */ +#endif + +/* + * Returns the kernel segment base of a given address + */ +#define KSEGX(a) ((_ACAST32_ (a)) & 0xe0000000) + +/* + * Returns the physical address of a CKSEGx / XKPHYS address + */ +#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) +#define XPHYSADDR(a) ((_ACAST64_(a)) & \ + _CONST64_(0x000000ffffffffff)) + +#ifdef CONFIG_64BIT + +/* + * Memory segments (64bit kernel mode addresses) + * The compatibility segments use the full 64-bit sign extended value. Note + * the R8000 doesn't have them so don't reference these in generic MIPS code. + */ +#define XKUSEG _CONST64_(0x0000000000000000) +#define XKSSEG _CONST64_(0x4000000000000000) +#define XKPHYS _CONST64_(0x8000000000000000) +#define XKSEG _CONST64_(0xc000000000000000) +#define CKSEG0 _CONST64_(0xffffffff80000000) +#define CKSEG1 _CONST64_(0xffffffffa0000000) +#define CKSSEG _CONST64_(0xffffffffc0000000) +#define CKSEG3 _CONST64_(0xffffffffe0000000) + +#define CKSEG0ADDR(a) (CPHYSADDR(a) | CKSEG0) +#define CKSEG1ADDR(a) (CPHYSADDR(a) | CKSEG1) +#define CKSEG2ADDR(a) (CPHYSADDR(a) | CKSEG2) +#define CKSEG3ADDR(a) (CPHYSADDR(a) | CKSEG3) + +#else + +#define CKSEG0ADDR(a) (CPHYSADDR(a) | KSEG0) +#define CKSEG1ADDR(a) (CPHYSADDR(a) | KSEG1) +#define CKSEG2ADDR(a) (CPHYSADDR(a) | KSEG2) +#define CKSEG3ADDR(a) (CPHYSADDR(a) | KSEG3) + +/* + * Map an address to a certain kernel segment + */ +#define KSEG0ADDR(a) (CPHYSADDR(a) | KSEG0) +#define KSEG1ADDR(a) (CPHYSADDR(a) | KSEG1) +#define KSEG2ADDR(a) (CPHYSADDR(a) | KSEG2) +#define KSEG3ADDR(a) (CPHYSADDR(a) | KSEG3) + +/* + * Memory segments (32bit kernel mode addresses) + * These are the traditional names used in the 32-bit universe. + */ +#define KUSEG 0x00000000 +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 +#define KSEG2 0xc0000000 +#define KSEG3 0xe0000000 + +#define CKUSEG 0x00000000 +#define CKSEG0 0x80000000 +#define CKSEG1 0xa0000000 +#define CKSEG2 0xc0000000 +#define CKSEG3 0xe0000000 + +#endif + +/* + * Cache modes for XKPHYS address conversion macros + */ +#define K_CALG_COH_EXCL1_NOL2 0 +#define K_CALG_COH_SHRL1_NOL2 1 +#define K_CALG_UNCACHED 2 +#define K_CALG_NONCOHERENT 3 +#define K_CALG_COH_EXCL 4 +#define K_CALG_COH_SHAREABLE 5 +#define K_CALG_NOTUSED 6 +#define K_CALG_UNCACHED_ACCEL 7 + +/* + * 64-bit address conversions + */ +#define PHYS_TO_XKSEG_UNCACHED(p) PHYS_TO_XKPHYS(K_CALG_UNCACHED, (p)) +#define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE, (p)) +#define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK) +#define PHYS_TO_XKPHYS(cm, a) (_CONST64_(0x8000000000000000) | \ + (_CONST64_(cm) << 59) | (a)) + +/* + * The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting + * the region, 3 bits for the CCA mode. This leaves 59 bits of which the + * R8000 implements most with its 48-bit physical address space. + */ +#define TO_PHYS_MASK _CONST64_(0x07ffffffffffffff) /* 2^^59 - 1 */ + +#ifndef CONFIG_CPU_R8000 + +/* + * The R8000 doesn't have the 32-bit compat spaces so we don't define them + * in order to catch bugs in the source code. + */ + +#define COMPAT_K1BASE32 _CONST64_(0xffffffffa0000000) +#define PHYS_TO_COMPATK1(x) ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */ + +#endif + +#define KDM_TO_PHYS(x) (_ACAST64_ (x) & TO_PHYS_MASK) +#define PHYS_TO_K0(x) (_ACAST64_ (x) | CAC_BASE) + +#endif /* _ASM_ADDRSPACE_H */ diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h new file mode 100644 index 00000000000..608cfcfbb3e --- /dev/null +++ b/arch/mips/include/asm/asm.h @@ -0,0 +1,409 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle + * Copyright (C) 1999 by Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + * Copyright (C) 2002 Maciej W. Rozycki + * + * Some useful macros for MIPS assembler code + * + * Some of the routines below contain useless nops that will be optimized + * away by gas in -O mode. These nops are however required to fill delay + * slots in noreorder mode. + */ +#ifndef __ASM_ASM_H +#define __ASM_ASM_H + +#include + +#ifndef CAT +#ifdef __STDC__ +#define __CAT(str1, str2) str1##str2 +#else +#define __CAT(str1, str2) str1/**/str2 +#endif +#define CAT(str1, str2) __CAT(str1, str2) +#endif + +/* + * PIC specific declarations + * Not used for the kernel but here seems to be the right place. + */ +#ifdef __PIC__ +#define CPRESTORE(register) \ + .cprestore register +#define CPADD(register) \ + .cpadd register +#define CPLOAD(register) \ + .cpload register +#else +#define CPRESTORE(register) +#define CPADD(register) +#define CPLOAD(register) +#endif + +/* + * LEAF - declare leaf routine + */ +#define LEAF(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol, 0; \ +symbol: .frame sp, 0, ra + +/* + * NESTED - declare nested routine entry point + */ +#define NESTED(symbol, framesize, rpc) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol, 0; \ +symbol: .frame sp, framesize, rpc + +/* + * END - mark end of function + */ +#define END(function) \ + .end function; \ + .size function, .-function + +/* + * EXPORT - export definition of symbol + */ +#define EXPORT(symbol) \ + .globl symbol; \ +symbol: + +/* + * FEXPORT - export definition of a function symbol + */ +#define FEXPORT(symbol) \ + .globl symbol; \ + .type symbol, @function; \ +symbol: + +/* + * ABS - export absolute symbol + */ +#define ABS(symbol,value) \ + .globl symbol; \ +symbol = value + +#define PANIC(msg) \ + .set push; \ + .set reorder; \ + PTR_LA a0, 8f; \ + jal panic; \ +9: b 9b; \ + .set pop; \ + TEXT(msg) + +/* + * Print formatted string + */ +#ifdef CONFIG_PRINTK +#define PRINT(string) \ + .set push; \ + .set reorder; \ + PTR_LA a0, 8f; \ + jal printk; \ + .set pop; \ + TEXT(string) +#else +#define PRINT(string) +#endif + +#define TEXT(msg) \ + .pushsection .data; \ +8: .asciiz msg; \ + .popsection; + +/* + * Build text tables + */ +#define TTABLE(string) \ + .pushsection .text; \ + .word 1f; \ + .popsection \ + .pushsection .data; \ +1: .asciiz string; \ + .popsection + +/* + * MIPS IV pref instruction. + * Use with .set noreorder only! + * + * MIPS IV implementations are free to treat this as a nop. The R5000 + * is one of them. So we should have an option not to use this instruction. + */ +#ifdef CONFIG_CPU_HAS_PREFETCH + +#define PREF(hint,addr) \ + .set push; \ + .set mips4; \ + pref hint, addr; \ + .set pop + +#define PREFX(hint,addr) \ + .set push; \ + .set mips4; \ + prefx hint, addr; \ + .set pop + +#else /* !CONFIG_CPU_HAS_PREFETCH */ + +#define PREF(hint, addr) +#define PREFX(hint, addr) + +#endif /* !CONFIG_CPU_HAS_PREFETCH */ + +/* + * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) +#define MOVN(rd, rs, rt) \ + .set push; \ + .set reorder; \ + beqz rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#define MOVZ(rd, rs, rt) \ + .set push; \ + .set reorder; \ + bnez rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) +#define MOVN(rd, rs, rt) \ + .set push; \ + .set noreorder; \ + bnezl rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#define MOVZ(rd, rs, rt) \ + .set push; \ + .set noreorder; \ + beqzl rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +#define MOVN(rd, rs, rt) \ + movn rd, rs, rt +#define MOVZ(rd, rs, rt) \ + movz rd, rs, rt +#endif /* MIPS IV, MIPS V, MIPS32 or MIPS64 */ + +/* + * Stack alignment + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define ALSZ 7 +#define ALMASK ~7 +#endif +#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) +#define ALSZ 15 +#define ALMASK ~15 +#endif + +/* + * Macros to handle different pointer/register sizes for 32/64-bit code + */ + +/* + * Size of a register + */ +#ifdef __mips64 +#define SZREG 8 +#else +#define SZREG 4 +#endif + +/* + * Use the following macros in assemblercode to load/store registers, + * pointers etc. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define REG_S sw +#define REG_L lw +#define REG_SUBU subu +#define REG_ADDU addu +#endif +#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) +#define REG_S sd +#define REG_L ld +#define REG_SUBU dsubu +#define REG_ADDU daddu +#endif + +/* + * How to add/sub/load/store/shift C int variables. + */ +#if (_MIPS_SZINT == 32) +#define INT_ADD add +#define INT_ADDU addu +#define INT_ADDI addi +#define INT_ADDIU addiu +#define INT_SUB sub +#define INT_SUBU subu +#define INT_L lw +#define INT_S sw +#define INT_SLL sll +#define INT_SLLV sllv +#define INT_SRL srl +#define INT_SRLV srlv +#define INT_SRA sra +#define INT_SRAV srav +#endif + +#if (_MIPS_SZINT == 64) +#define INT_ADD dadd +#define INT_ADDU daddu +#define INT_ADDI daddi +#define INT_ADDIU daddiu +#define INT_SUB dsub +#define INT_SUBU dsubu +#define INT_L ld +#define INT_S sd +#define INT_SLL dsll +#define INT_SLLV dsllv +#define INT_SRL dsrl +#define INT_SRLV dsrlv +#define INT_SRA dsra +#define INT_SRAV dsrav +#endif + +/* + * How to add/sub/load/store/shift C long variables. + */ +#if (_MIPS_SZLONG == 32) +#define LONG_ADD add +#define LONG_ADDU addu +#define LONG_ADDI addi +#define LONG_ADDIU addiu +#define LONG_SUB sub +#define LONG_SUBU subu +#define LONG_L lw +#define LONG_S sw +#define LONG_SLL sll +#define LONG_SLLV sllv +#define LONG_SRL srl +#define LONG_SRLV srlv +#define LONG_SRA sra +#define LONG_SRAV srav + +#define LONG .word +#define LONGSIZE 4 +#define LONGMASK 3 +#define LONGLOG 2 +#endif + +#if (_MIPS_SZLONG == 64) +#define LONG_ADD dadd +#define LONG_ADDU daddu +#define LONG_ADDI daddi +#define LONG_ADDIU daddiu +#define LONG_SUB dsub +#define LONG_SUBU dsubu +#define LONG_L ld +#define LONG_S sd +#define LONG_SLL dsll +#define LONG_SLLV dsllv +#define LONG_SRL dsrl +#define LONG_SRLV dsrlv +#define LONG_SRA dsra +#define LONG_SRAV dsrav + +#define LONG .dword +#define LONGSIZE 8 +#define LONGMASK 7 +#define LONGLOG 3 +#endif + +/* + * How to add/sub/load/store/shift pointers. + */ +#if (_MIPS_SZPTR == 32) +#define PTR_ADD add +#define PTR_ADDU addu +#define PTR_ADDI addi +#define PTR_ADDIU addiu +#define PTR_SUB sub +#define PTR_SUBU subu +#define PTR_L lw +#define PTR_S sw +#define PTR_LA la +#define PTR_LI li +#define PTR_SLL sll +#define PTR_SLLV sllv +#define PTR_SRL srl +#define PTR_SRLV srlv +#define PTR_SRA sra +#define PTR_SRAV srav + +#define PTR_SCALESHIFT 2 + +#define PTR .word +#define PTRSIZE 4 +#define PTRLOG 2 +#endif + +#if (_MIPS_SZPTR == 64) +#define PTR_ADD dadd +#define PTR_ADDU daddu +#define PTR_ADDI daddi +#define PTR_ADDIU daddiu +#define PTR_SUB dsub +#define PTR_SUBU dsubu +#define PTR_L ld +#define PTR_S sd +#define PTR_LA dla +#define PTR_LI dli +#define PTR_SLL dsll +#define PTR_SLLV dsllv +#define PTR_SRL dsrl +#define PTR_SRLV dsrlv +#define PTR_SRA dsra +#define PTR_SRAV dsrav + +#define PTR_SCALESHIFT 3 + +#define PTR .dword +#define PTRSIZE 8 +#define PTRLOG 3 +#endif + +/* + * Some cp0 registers were extended to 64bit for MIPS III. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define MFC0 mfc0 +#define MTC0 mtc0 +#endif +#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) +#define MFC0 dmfc0 +#define MTC0 dmtc0 +#endif + +#define SSNOP sll zero, zero, 1 + +#ifdef CONFIG_SGI_IP28 +/* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ +#include +#define R10KCBARRIER(addr) cache Cache_Barrier, addr; +#else +#define R10KCBARRIER(addr) +#endif + +#endif /* __ASM_ASM_H */ diff --git a/arch/mips/include/asm/asmmacro-32.h b/arch/mips/include/asm/asmmacro-32.h new file mode 100644 index 00000000000..5de3963f511 --- /dev/null +++ b/arch/mips/include/asm/asmmacro-32.h @@ -0,0 +1,158 @@ +/* + * asmmacro.h: Assembler macros to make things easier to read. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1998, 1999, 2003 Ralf Baechle + */ +#ifndef _ASM_ASMMACRO_32_H +#define _ASM_ASMMACRO_32_H + +#include +#include +#include +#include + + .macro fpu_save_double thread status tmp1=t0 + cfc1 \tmp1, fcr31 + sdc1 $f0, THREAD_FPR0(\thread) + sdc1 $f2, THREAD_FPR2(\thread) + sdc1 $f4, THREAD_FPR4(\thread) + sdc1 $f6, THREAD_FPR6(\thread) + sdc1 $f8, THREAD_FPR8(\thread) + sdc1 $f10, THREAD_FPR10(\thread) + sdc1 $f12, THREAD_FPR12(\thread) + sdc1 $f14, THREAD_FPR14(\thread) + sdc1 $f16, THREAD_FPR16(\thread) + sdc1 $f18, THREAD_FPR18(\thread) + sdc1 $f20, THREAD_FPR20(\thread) + sdc1 $f22, THREAD_FPR22(\thread) + sdc1 $f24, THREAD_FPR24(\thread) + sdc1 $f26, THREAD_FPR26(\thread) + sdc1 $f28, THREAD_FPR28(\thread) + sdc1 $f30, THREAD_FPR30(\thread) + sw \tmp1, THREAD_FCR31(\thread) + .endm + + .macro fpu_save_single thread tmp=t0 + cfc1 \tmp, fcr31 + swc1 $f0, THREAD_FPR0(\thread) + swc1 $f1, THREAD_FPR1(\thread) + swc1 $f2, THREAD_FPR2(\thread) + swc1 $f3, THREAD_FPR3(\thread) + swc1 $f4, THREAD_FPR4(\thread) + swc1 $f5, THREAD_FPR5(\thread) + swc1 $f6, THREAD_FPR6(\thread) + swc1 $f7, THREAD_FPR7(\thread) + swc1 $f8, THREAD_FPR8(\thread) + swc1 $f9, THREAD_FPR9(\thread) + swc1 $f10, THREAD_FPR10(\thread) + swc1 $f11, THREAD_FPR11(\thread) + swc1 $f12, THREAD_FPR12(\thread) + swc1 $f13, THREAD_FPR13(\thread) + swc1 $f14, THREAD_FPR14(\thread) + swc1 $f15, THREAD_FPR15(\thread) + swc1 $f16, THREAD_FPR16(\thread) + swc1 $f17, THREAD_FPR17(\thread) + swc1 $f18, THREAD_FPR18(\thread) + swc1 $f19, THREAD_FPR19(\thread) + swc1 $f20, THREAD_FPR20(\thread) + swc1 $f21, THREAD_FPR21(\thread) + swc1 $f22, THREAD_FPR22(\thread) + swc1 $f23, THREAD_FPR23(\thread) + swc1 $f24, THREAD_FPR24(\thread) + swc1 $f25, THREAD_FPR25(\thread) + swc1 $f26, THREAD_FPR26(\thread) + swc1 $f27, THREAD_FPR27(\thread) + swc1 $f28, THREAD_FPR28(\thread) + swc1 $f29, THREAD_FPR29(\thread) + swc1 $f30, THREAD_FPR30(\thread) + swc1 $f31, THREAD_FPR31(\thread) + sw \tmp, THREAD_FCR31(\thread) + .endm + + .macro fpu_restore_double thread status tmp=t0 + lw \tmp, THREAD_FCR31(\thread) + ldc1 $f0, THREAD_FPR0(\thread) + ldc1 $f2, THREAD_FPR2(\thread) + ldc1 $f4, THREAD_FPR4(\thread) + ldc1 $f6, THREAD_FPR6(\thread) + ldc1 $f8, THREAD_FPR8(\thread) + ldc1 $f10, THREAD_FPR10(\thread) + ldc1 $f12, THREAD_FPR12(\thread) + ldc1 $f14, THREAD_FPR14(\thread) + ldc1 $f16, THREAD_FPR16(\thread) + ldc1 $f18, THREAD_FPR18(\thread) + ldc1 $f20, THREAD_FPR20(\thread) + ldc1 $f22, THREAD_FPR22(\thread) + ldc1 $f24, THREAD_FPR24(\thread) + ldc1 $f26, THREAD_FPR26(\thread) + ldc1 $f28, THREAD_FPR28(\thread) + ldc1 $f30, THREAD_FPR30(\thread) + ctc1 \tmp, fcr31 + .endm + + .macro fpu_restore_single thread tmp=t0 + lw \tmp, THREAD_FCR31(\thread) + lwc1 $f0, THREAD_FPR0(\thread) + lwc1 $f1, THREAD_FPR1(\thread) + lwc1 $f2, THREAD_FPR2(\thread) + lwc1 $f3, THREAD_FPR3(\thread) + lwc1 $f4, THREAD_FPR4(\thread) + lwc1 $f5, THREAD_FPR5(\thread) + lwc1 $f6, THREAD_FPR6(\thread) + lwc1 $f7, THREAD_FPR7(\thread) + lwc1 $f8, THREAD_FPR8(\thread) + lwc1 $f9, THREAD_FPR9(\thread) + lwc1 $f10, THREAD_FPR10(\thread) + lwc1 $f11, THREAD_FPR11(\thread) + lwc1 $f12, THREAD_FPR12(\thread) + lwc1 $f13, THREAD_FPR13(\thread) + lwc1 $f14, THREAD_FPR14(\thread) + lwc1 $f15, THREAD_FPR15(\thread) + lwc1 $f16, THREAD_FPR16(\thread) + lwc1 $f17, THREAD_FPR17(\thread) + lwc1 $f18, THREAD_FPR18(\thread) + lwc1 $f19, THREAD_FPR19(\thread) + lwc1 $f20, THREAD_FPR20(\thread) + lwc1 $f21, THREAD_FPR21(\thread) + lwc1 $f22, THREAD_FPR22(\thread) + lwc1 $f23, THREAD_FPR23(\thread) + lwc1 $f24, THREAD_FPR24(\thread) + lwc1 $f25, THREAD_FPR25(\thread) + lwc1 $f26, THREAD_FPR26(\thread) + lwc1 $f27, THREAD_FPR27(\thread) + lwc1 $f28, THREAD_FPR28(\thread) + lwc1 $f29, THREAD_FPR29(\thread) + lwc1 $f30, THREAD_FPR30(\thread) + lwc1 $f31, THREAD_FPR31(\thread) + ctc1 \tmp, fcr31 + .endm + + .macro cpu_save_nonscratch thread + LONG_S s0, THREAD_REG16(\thread) + LONG_S s1, THREAD_REG17(\thread) + LONG_S s2, THREAD_REG18(\thread) + LONG_S s3, THREAD_REG19(\thread) + LONG_S s4, THREAD_REG20(\thread) + LONG_S s5, THREAD_REG21(\thread) + LONG_S s6, THREAD_REG22(\thread) + LONG_S s7, THREAD_REG23(\thread) + LONG_S sp, THREAD_REG29(\thread) + LONG_S fp, THREAD_REG30(\thread) + .endm + + .macro cpu_restore_nonscratch thread + LONG_L s0, THREAD_REG16(\thread) + LONG_L s1, THREAD_REG17(\thread) + LONG_L s2, THREAD_REG18(\thread) + LONG_L s3, THREAD_REG19(\thread) + LONG_L s4, THREAD_REG20(\thread) + LONG_L s5, THREAD_REG21(\thread) + LONG_L s6, THREAD_REG22(\thread) + LONG_L s7, THREAD_REG23(\thread) + LONG_L sp, THREAD_REG29(\thread) + LONG_L fp, THREAD_REG30(\thread) + LONG_L ra, THREAD_REG31(\thread) + .endm + +#endif /* _ASM_ASMMACRO_32_H */ diff --git a/arch/mips/include/asm/asmmacro-64.h b/arch/mips/include/asm/asmmacro-64.h new file mode 100644 index 00000000000..225feefcb25 --- /dev/null +++ b/arch/mips/include/asm/asmmacro-64.h @@ -0,0 +1,139 @@ +/* + * asmmacro.h: Assembler macros to make things easier to read. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1998, 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_ASMMACRO_64_H +#define _ASM_ASMMACRO_64_H + +#include +#include +#include +#include + + .macro fpu_save_16even thread tmp=t0 + cfc1 \tmp, fcr31 + sdc1 $f0, THREAD_FPR0(\thread) + sdc1 $f2, THREAD_FPR2(\thread) + sdc1 $f4, THREAD_FPR4(\thread) + sdc1 $f6, THREAD_FPR6(\thread) + sdc1 $f8, THREAD_FPR8(\thread) + sdc1 $f10, THREAD_FPR10(\thread) + sdc1 $f12, THREAD_FPR12(\thread) + sdc1 $f14, THREAD_FPR14(\thread) + sdc1 $f16, THREAD_FPR16(\thread) + sdc1 $f18, THREAD_FPR18(\thread) + sdc1 $f20, THREAD_FPR20(\thread) + sdc1 $f22, THREAD_FPR22(\thread) + sdc1 $f24, THREAD_FPR24(\thread) + sdc1 $f26, THREAD_FPR26(\thread) + sdc1 $f28, THREAD_FPR28(\thread) + sdc1 $f30, THREAD_FPR30(\thread) + sw \tmp, THREAD_FCR31(\thread) + .endm + + .macro fpu_save_16odd thread + sdc1 $f1, THREAD_FPR1(\thread) + sdc1 $f3, THREAD_FPR3(\thread) + sdc1 $f5, THREAD_FPR5(\thread) + sdc1 $f7, THREAD_FPR7(\thread) + sdc1 $f9, THREAD_FPR9(\thread) + sdc1 $f11, THREAD_FPR11(\thread) + sdc1 $f13, THREAD_FPR13(\thread) + sdc1 $f15, THREAD_FPR15(\thread) + sdc1 $f17, THREAD_FPR17(\thread) + sdc1 $f19, THREAD_FPR19(\thread) + sdc1 $f21, THREAD_FPR21(\thread) + sdc1 $f23, THREAD_FPR23(\thread) + sdc1 $f25, THREAD_FPR25(\thread) + sdc1 $f27, THREAD_FPR27(\thread) + sdc1 $f29, THREAD_FPR29(\thread) + sdc1 $f31, THREAD_FPR31(\thread) + .endm + + .macro fpu_save_double thread status tmp + sll \tmp, \status, 5 + bgez \tmp, 2f + fpu_save_16odd \thread +2: + fpu_save_16even \thread \tmp + .endm + + .macro fpu_restore_16even thread tmp=t0 + lw \tmp, THREAD_FCR31(\thread) + ldc1 $f0, THREAD_FPR0(\thread) + ldc1 $f2, THREAD_FPR2(\thread) + ldc1 $f4, THREAD_FPR4(\thread) + ldc1 $f6, THREAD_FPR6(\thread) + ldc1 $f8, THREAD_FPR8(\thread) + ldc1 $f10, THREAD_FPR10(\thread) + ldc1 $f12, THREAD_FPR12(\thread) + ldc1 $f14, THREAD_FPR14(\thread) + ldc1 $f16, THREAD_FPR16(\thread) + ldc1 $f18, THREAD_FPR18(\thread) + ldc1 $f20, THREAD_FPR20(\thread) + ldc1 $f22, THREAD_FPR22(\thread) + ldc1 $f24, THREAD_FPR24(\thread) + ldc1 $f26, THREAD_FPR26(\thread) + ldc1 $f28, THREAD_FPR28(\thread) + ldc1 $f30, THREAD_FPR30(\thread) + ctc1 \tmp, fcr31 + .endm + + .macro fpu_restore_16odd thread + ldc1 $f1, THREAD_FPR1(\thread) + ldc1 $f3, THREAD_FPR3(\thread) + ldc1 $f5, THREAD_FPR5(\thread) + ldc1 $f7, THREAD_FPR7(\thread) + ldc1 $f9, THREAD_FPR9(\thread) + ldc1 $f11, THREAD_FPR11(\thread) + ldc1 $f13, THREAD_FPR13(\thread) + ldc1 $f15, THREAD_FPR15(\thread) + ldc1 $f17, THREAD_FPR17(\thread) + ldc1 $f19, THREAD_FPR19(\thread) + ldc1 $f21, THREAD_FPR21(\thread) + ldc1 $f23, THREAD_FPR23(\thread) + ldc1 $f25, THREAD_FPR25(\thread) + ldc1 $f27, THREAD_FPR27(\thread) + ldc1 $f29, THREAD_FPR29(\thread) + ldc1 $f31, THREAD_FPR31(\thread) + .endm + + .macro fpu_restore_double thread status tmp + sll \tmp, \status, 5 + bgez \tmp, 1f # 16 register mode? + + fpu_restore_16odd \thread +1: fpu_restore_16even \thread \tmp + .endm + + .macro cpu_save_nonscratch thread + LONG_S s0, THREAD_REG16(\thread) + LONG_S s1, THREAD_REG17(\thread) + LONG_S s2, THREAD_REG18(\thread) + LONG_S s3, THREAD_REG19(\thread) + LONG_S s4, THREAD_REG20(\thread) + LONG_S s5, THREAD_REG21(\thread) + LONG_S s6, THREAD_REG22(\thread) + LONG_S s7, THREAD_REG23(\thread) + LONG_S sp, THREAD_REG29(\thread) + LONG_S fp, THREAD_REG30(\thread) + .endm + + .macro cpu_restore_nonscratch thread + LONG_L s0, THREAD_REG16(\thread) + LONG_L s1, THREAD_REG17(\thread) + LONG_L s2, THREAD_REG18(\thread) + LONG_L s3, THREAD_REG19(\thread) + LONG_L s4, THREAD_REG20(\thread) + LONG_L s5, THREAD_REG21(\thread) + LONG_L s6, THREAD_REG22(\thread) + LONG_L s7, THREAD_REG23(\thread) + LONG_L sp, THREAD_REG29(\thread) + LONG_L fp, THREAD_REG30(\thread) + LONG_L ra, THREAD_REG31(\thread) + .endm + +#endif /* _ASM_ASMMACRO_64_H */ diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h new file mode 100644 index 00000000000..7a881755800 --- /dev/null +++ b/arch/mips/include/asm/asmmacro.h @@ -0,0 +1,82 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 Ralf Baechle + */ +#ifndef _ASM_ASMMACRO_H +#define _ASM_ASMMACRO_H + +#include + +#ifdef CONFIG_32BIT +#include +#endif +#ifdef CONFIG_64BIT +#include +#endif +#ifdef CONFIG_MIPS_MT_SMTC +#include +#endif + +#ifdef CONFIG_MIPS_MT_SMTC + .macro local_irq_enable reg=t0 + mfc0 \reg, CP0_TCSTATUS + ori \reg, \reg, TCSTATUS_IXMT + xori \reg, \reg, TCSTATUS_IXMT + mtc0 \reg, CP0_TCSTATUS + _ehb + .endm + + .macro local_irq_disable reg=t0 + mfc0 \reg, CP0_TCSTATUS + ori \reg, \reg, TCSTATUS_IXMT + mtc0 \reg, CP0_TCSTATUS + _ehb + .endm +#else + .macro local_irq_enable reg=t0 + mfc0 \reg, CP0_STATUS + ori \reg, \reg, 1 + mtc0 \reg, CP0_STATUS + irq_enable_hazard + .endm + + .macro local_irq_disable reg=t0 + mfc0 \reg, CP0_STATUS + ori \reg, \reg, 1 + xori \reg, \reg, 1 + mtc0 \reg, CP0_STATUS + irq_disable_hazard + .endm +#endif /* CONFIG_MIPS_MT_SMTC */ + +/* + * Temporary until all gas have MT ASE support + */ + .macro DMT reg=0 + .word 0x41600bc1 | (\reg << 16) + .endm + + .macro EMT reg=0 + .word 0x41600be1 | (\reg << 16) + .endm + + .macro DVPE reg=0 + .word 0x41600001 | (\reg << 16) + .endm + + .macro EVPE reg=0 + .word 0x41600021 | (\reg << 16) + .endm + + .macro MFTR rt=0, rd=0, u=0, sel=0 + .word 0x41000000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel) + .endm + + .macro MTTR rt=0, rd=0, u=0, sel=0 + .word 0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel) + .endm + +#endif /* _ASM_ASMMACRO_H */ diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h new file mode 100644 index 00000000000..1232be3885b --- /dev/null +++ b/arch/mips/include/asm/atomic.h @@ -0,0 +1,801 @@ +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + * + * But use these as seldom as possible since they are much more slower + * than regular operations. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 97, 99, 2000, 03, 04, 06 by Ralf Baechle + */ +#ifndef _ASM_ATOMIC_H +#define _ASM_ATOMIC_H + +#include +#include +#include +#include +#include + +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +/* + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. + */ +#define atomic_read(v) ((v)->counter) + +/* + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. + */ +#define atomic_set(v, i) ((v)->counter = (i)) + +/* + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. + */ +static __inline__ void atomic_add(int i, atomic_t * v) +{ + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic_add \n" + " addu %0, %2 \n" + " sc %0, %1 \n" + " beqzl %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic_add \n" + " addu %0, %2 \n" + " sc %0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + v->counter += i; + raw_local_irq_restore(flags); + } +} + +/* + * atomic_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. + */ +static __inline__ void atomic_sub(int i, atomic_t * v) +{ + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic_sub \n" + " subu %0, %2 \n" + " sc %0, %1 \n" + " beqzl %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic_sub \n" + " subu %0, %2 \n" + " sc %0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + v->counter -= i; + raw_local_irq_restore(flags); + } +} + +/* + * Same as above, but return the result value + */ +static __inline__ int atomic_add_return(int i, atomic_t * v) +{ + unsigned long result; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_add_return \n" + " addu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqzl %0, 1b \n" + " addu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_add_return \n" + " addu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqz %0, 2f \n" + " addu %0, %1, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + result = v->counter; + result += i; + v->counter = result; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +static __inline__ int atomic_sub_return(int i, atomic_t * v) +{ + unsigned long result; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_sub_return \n" + " subu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqzl %0, 1b \n" + " subu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_sub_return \n" + " subu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqz %0, 2f \n" + " subu %0, %1, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + result = v->counter; + result -= i; + v->counter = result; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +/* + * atomic_sub_if_positive - conditionally subtract integer from atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically test @v and subtract @i if @v is greater or equal than @i. + * The function returns the old value of @v minus @i. + */ +static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) +{ + unsigned long result; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_sub_if_positive\n" + " subu %0, %1, %3 \n" + " bltz %0, 1f \n" + " sc %0, %2 \n" + " .set noreorder \n" + " beqzl %0, 1b \n" + " subu %0, %1, %3 \n" + " .set reorder \n" + "1: \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_sub_if_positive\n" + " subu %0, %1, %3 \n" + " bltz %0, 1f \n" + " sc %0, %2 \n" + " .set noreorder \n" + " beqz %0, 2f \n" + " subu %0, %1, %3 \n" + " .set reorder \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + "1: \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + result = v->counter; + result -= i; + if (result >= 0) + v->counter = result; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), (new))) + +/** + * atomic_add_unless - add unless the number is a given value + * @v: pointer of type atomic_t + * @a: the amount to add to v... + * @u: ...unless v is equal to u. + * + * Atomically adds @a to @v, so long as it was not @u. + * Returns non-zero if @v was not @u, and zero otherwise. + */ +static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) +{ + int c, old; + c = atomic_read(v); + for (;;) { + if (unlikely(c == (u))) + break; + old = atomic_cmpxchg((v), c, c + (a)); + if (likely(old == c)) + break; + c = old; + } + return c != (u); +} +#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) + +#define atomic_dec_return(v) atomic_sub_return(1, (v)) +#define atomic_inc_return(v) atomic_add_return(1, (v)) + +/* + * atomic_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v and returns + * true if the result is zero, or false for all + * other cases. + */ +#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) + +/* + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) + +/* + * atomic_dec_and_test - decrement by 1 and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. + */ +#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) + +/* + * atomic_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic_t + */ +#define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v) + +/* + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. + */ +#define atomic_inc(v) atomic_add(1, (v)) + +/* + * atomic_dec - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. + */ +#define atomic_dec(v) atomic_sub(1, (v)) + +/* + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. + */ +#define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0) + +#ifdef CONFIG_64BIT + +typedef struct { volatile long counter; } atomic64_t; + +#define ATOMIC64_INIT(i) { (i) } + +/* + * atomic64_read - read atomic variable + * @v: pointer of type atomic64_t + * + */ +#define atomic64_read(v) ((v)->counter) + +/* + * atomic64_set - set atomic variable + * @v: pointer of type atomic64_t + * @i: required value + */ +#define atomic64_set(v, i) ((v)->counter = (i)) + +/* + * atomic64_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic64_t + * + * Atomically adds @i to @v. + */ +static __inline__ void atomic64_add(long i, atomic64_t * v) +{ + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_add \n" + " addu %0, %2 \n" + " scd %0, %1 \n" + " beqzl %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_add \n" + " addu %0, %2 \n" + " scd %0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + v->counter += i; + raw_local_irq_restore(flags); + } +} + +/* + * atomic64_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic64_t + * + * Atomically subtracts @i from @v. + */ +static __inline__ void atomic64_sub(long i, atomic64_t * v) +{ + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_sub \n" + " subu %0, %2 \n" + " scd %0, %1 \n" + " beqzl %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_sub \n" + " subu %0, %2 \n" + " scd %0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + v->counter -= i; + raw_local_irq_restore(flags); + } +} + +/* + * Same as above, but return the result value + */ +static __inline__ long atomic64_add_return(long i, atomic64_t * v) +{ + unsigned long result; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_add_return \n" + " addu %0, %1, %3 \n" + " scd %0, %2 \n" + " beqzl %0, 1b \n" + " addu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_add_return \n" + " addu %0, %1, %3 \n" + " scd %0, %2 \n" + " beqz %0, 2f \n" + " addu %0, %1, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + result = v->counter; + result += i; + v->counter = result; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +static __inline__ long atomic64_sub_return(long i, atomic64_t * v) +{ + unsigned long result; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_sub_return \n" + " subu %0, %1, %3 \n" + " scd %0, %2 \n" + " beqzl %0, 1b \n" + " subu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_sub_return \n" + " subu %0, %1, %3 \n" + " scd %0, %2 \n" + " beqz %0, 2f \n" + " subu %0, %1, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + result = v->counter; + result -= i; + v->counter = result; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +/* + * atomic64_sub_if_positive - conditionally subtract integer from atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic64_t + * + * Atomically test @v and subtract @i if @v is greater or equal than @i. + * The function returns the old value of @v minus @i. + */ +static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) +{ + unsigned long result; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_sub_if_positive\n" + " dsubu %0, %1, %3 \n" + " bltz %0, 1f \n" + " scd %0, %2 \n" + " .set noreorder \n" + " beqzl %0, 1b \n" + " dsubu %0, %1, %3 \n" + " .set reorder \n" + "1: \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_sub_if_positive\n" + " dsubu %0, %1, %3 \n" + " bltz %0, 1f \n" + " scd %0, %2 \n" + " .set noreorder \n" + " beqz %0, 2f \n" + " dsubu %0, %1, %3 \n" + " .set reorder \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + "1: \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + result = v->counter; + result -= i; + if (result >= 0) + v->counter = result; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +#define atomic64_cmpxchg(v, o, n) \ + ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) +#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new))) + +/** + * atomic64_add_unless - add unless the number is a given value + * @v: pointer of type atomic64_t + * @a: the amount to add to v... + * @u: ...unless v is equal to u. + * + * Atomically adds @a to @v, so long as it was not @u. + * Returns non-zero if @v was not @u, and zero otherwise. + */ +static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) +{ + long c, old; + c = atomic64_read(v); + for (;;) { + if (unlikely(c == (u))) + break; + old = atomic64_cmpxchg((v), c, c + (a)); + if (likely(old == c)) + break; + c = old; + } + return c != (u); +} + +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) + +#define atomic64_dec_return(v) atomic64_sub_return(1, (v)) +#define atomic64_inc_return(v) atomic64_add_return(1, (v)) + +/* + * atomic64_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic64_t + * + * Atomically subtracts @i from @v and returns + * true if the result is zero, or false for all + * other cases. + */ +#define atomic64_sub_and_test(i, v) (atomic64_sub_return((i), (v)) == 0) + +/* + * atomic64_inc_and_test - increment and test + * @v: pointer of type atomic64_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) + +/* + * atomic64_dec_and_test - decrement by 1 and test + * @v: pointer of type atomic64_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. + */ +#define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0) + +/* + * atomic64_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic64_t + */ +#define atomic64_dec_if_positive(v) atomic64_sub_if_positive(1, v) + +/* + * atomic64_inc - increment atomic variable + * @v: pointer of type atomic64_t + * + * Atomically increments @v by 1. + */ +#define atomic64_inc(v) atomic64_add(1, (v)) + +/* + * atomic64_dec - decrement and test + * @v: pointer of type atomic64_t + * + * Atomically decrements @v by 1. + */ +#define atomic64_dec(v) atomic64_sub(1, (v)) + +/* + * atomic64_add_negative - add and test if negative + * @v: pointer of type atomic64_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. + */ +#define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0) + +#endif /* CONFIG_64BIT */ + +/* + * atomic*_return operations are serializing but not the non-*_return + * versions. + */ +#define smp_mb__before_atomic_dec() smp_llsc_mb() +#define smp_mb__after_atomic_dec() smp_llsc_mb() +#define smp_mb__before_atomic_inc() smp_llsc_mb() +#define smp_mb__after_atomic_inc() smp_llsc_mb() + +#include + +#endif /* _ASM_ATOMIC_H */ diff --git a/arch/mips/include/asm/auxvec.h b/arch/mips/include/asm/auxvec.h new file mode 100644 index 00000000000..7cf7f2d2194 --- /dev/null +++ b/arch/mips/include/asm/auxvec.h @@ -0,0 +1,4 @@ +#ifndef _ASM_AUXVEC_H +#define _ASM_AUXVEC_H + +#endif /* _ASM_AUXVEC_H */ diff --git a/arch/mips/include/asm/barrier.h b/arch/mips/include/asm/barrier.h new file mode 100644 index 00000000000..8e9ac313ca3 --- /dev/null +++ b/arch/mips/include/asm/barrier.h @@ -0,0 +1,155 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_BARRIER_H +#define __ASM_BARRIER_H + +/* + * read_barrier_depends - Flush all pending reads that subsequents reads + * depend on. + * + * No data-dependent reads from memory-like regions are ever reordered + * over this barrier. All reads preceding this primitive are guaranteed + * to access memory (but not necessarily other CPUs' caches) before any + * reads following this primitive that depend on the data return by + * any of the preceding reads. This primitive is much lighter weight than + * rmb() on most CPUs, and is never heavier weight than is + * rmb(). + * + * These ordering constraints are respected by both the local CPU + * and the compiler. + * + * Ordering is not guaranteed by anything other than these primitives, + * not even by data dependencies. See the documentation for + * memory_barrier() for examples and URLs to more information. + * + * For example, the following code would force ordering (the initial + * value of "a" is zero, "b" is one, and "p" is "&a"): + * + * + * CPU 0 CPU 1 + * + * b = 2; + * memory_barrier(); + * p = &b; q = p; + * read_barrier_depends(); + * d = *q; + * + * + * because the read of "*q" depends on the read of "p" and these + * two reads are separated by a read_barrier_depends(). However, + * the following code, with the same initial values for "a" and "b": + * + * + * CPU 0 CPU 1 + * + * a = 2; + * memory_barrier(); + * b = 3; y = b; + * read_barrier_depends(); + * x = a; + * + * + * does not enforce ordering, since there is no data dependency between + * the read of "a" and the read of "b". Therefore, on some CPUs, such + * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() + * in cases like this where there are no data dependencies. + */ + +#define read_barrier_depends() do { } while(0) +#define smp_read_barrier_depends() do { } while(0) + +#ifdef CONFIG_CPU_HAS_SYNC +#define __sync() \ + __asm__ __volatile__( \ + ".set push\n\t" \ + ".set noreorder\n\t" \ + ".set mips2\n\t" \ + "sync\n\t" \ + ".set pop" \ + : /* no output */ \ + : /* no input */ \ + : "memory") +#else +#define __sync() do { } while(0) +#endif + +#define __fast_iob() \ + __asm__ __volatile__( \ + ".set push\n\t" \ + ".set noreorder\n\t" \ + "lw $0,%0\n\t" \ + "nop\n\t" \ + ".set pop" \ + : /* no output */ \ + : "m" (*(int *)CKSEG1) \ + : "memory") + +#define fast_wmb() __sync() +#define fast_rmb() __sync() +#define fast_mb() __sync() +#ifdef CONFIG_SGI_IP28 +#define fast_iob() \ + __asm__ __volatile__( \ + ".set push\n\t" \ + ".set noreorder\n\t" \ + "lw $0,%0\n\t" \ + "sync\n\t" \ + "lw $0,%0\n\t" \ + ".set pop" \ + : /* no output */ \ + : "m" (*(int *)CKSEG1ADDR(0x1fa00004)) \ + : "memory") +#else +#define fast_iob() \ + do { \ + __sync(); \ + __fast_iob(); \ + } while (0) +#endif + +#ifdef CONFIG_CPU_HAS_WB + +#include + +#define wmb() fast_wmb() +#define rmb() fast_rmb() +#define mb() wbflush() +#define iob() wbflush() + +#else /* !CONFIG_CPU_HAS_WB */ + +#define wmb() fast_wmb() +#define rmb() fast_rmb() +#define mb() fast_mb() +#define iob() fast_iob() + +#endif /* !CONFIG_CPU_HAS_WB */ + +#if defined(CONFIG_WEAK_ORDERING) && defined(CONFIG_SMP) +#define __WEAK_ORDERING_MB " sync \n" +#else +#define __WEAK_ORDERING_MB " \n" +#endif +#if defined(CONFIG_WEAK_REORDERING_BEYOND_LLSC) && defined(CONFIG_SMP) +#define __WEAK_LLSC_MB " sync \n" +#else +#define __WEAK_LLSC_MB " \n" +#endif + +#define smp_mb() __asm__ __volatile__(__WEAK_ORDERING_MB : : :"memory") +#define smp_rmb() __asm__ __volatile__(__WEAK_ORDERING_MB : : :"memory") +#define smp_wmb() __asm__ __volatile__(__WEAK_ORDERING_MB : : :"memory") + +#define set_mb(var, value) \ + do { var = value; smp_mb(); } while (0) + +#define smp_llsc_mb() __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory") +#define smp_llsc_rmb() __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory") +#define smp_llsc_wmb() __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory") + +#endif /* __ASM_BARRIER_H */ diff --git a/arch/mips/include/asm/bcache.h b/arch/mips/include/asm/bcache.h new file mode 100644 index 00000000000..0ba9d6ef76a --- /dev/null +++ b/arch/mips/include/asm/bcache.h @@ -0,0 +1,60 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1997, 1999 by Ralf Baechle + * Copyright (c) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_BCACHE_H +#define _ASM_BCACHE_H + + +/* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent, + chipset implemented caches. On machines with other CPUs the CPU does the + cache thing itself. */ +struct bcache_ops { + void (*bc_enable)(void); + void (*bc_disable)(void); + void (*bc_wback_inv)(unsigned long page, unsigned long size); + void (*bc_inv)(unsigned long page, unsigned long size); +}; + +extern void indy_sc_init(void); + +#ifdef CONFIG_BOARD_SCACHE + +extern struct bcache_ops *bcops; + +static inline void bc_enable(void) +{ + bcops->bc_enable(); +} + +static inline void bc_disable(void) +{ + bcops->bc_disable(); +} + +static inline void bc_wback_inv(unsigned long page, unsigned long size) +{ + bcops->bc_wback_inv(page, size); +} + +static inline void bc_inv(unsigned long page, unsigned long size) +{ + bcops->bc_inv(page, size); +} + +#else /* !defined(CONFIG_BOARD_SCACHE) */ + +/* Not R4000 / R4400 / R4600 / R5000. */ + +#define bc_enable() do { } while (0) +#define bc_disable() do { } while (0) +#define bc_wback_inv(page, size) do { } while (0) +#define bc_inv(page, size) do { } while (0) + +#endif /* !defined(CONFIG_BOARD_SCACHE) */ + +#endif /* _ASM_BCACHE_H */ diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h new file mode 100644 index 00000000000..49df8c4c9d2 --- /dev/null +++ b/arch/mips/include/asm/bitops.h @@ -0,0 +1,672 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1994 - 1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org) + * Copyright (c) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_BITOPS_H +#define _ASM_BITOPS_H + +#ifndef _LINUX_BITOPS_H +#error only can be included directly +#endif + +#include +#include +#include +#include +#include +#include /* sigh ... */ +#include +#include +#include + +#if _MIPS_SZLONG == 32 +#define SZLONG_LOG 5 +#define SZLONG_MASK 31UL +#define __LL "ll " +#define __SC "sc " +#define __INS "ins " +#define __EXT "ext " +#elif _MIPS_SZLONG == 64 +#define SZLONG_LOG 6 +#define SZLONG_MASK 63UL +#define __LL "lld " +#define __SC "scd " +#define __INS "dins " +#define __EXT "dext " +#endif + +/* + * clear_bit() doesn't provide any barrier for the compiler. + */ +#define smp_mb__before_clear_bit() smp_llsc_mb() +#define smp_mb__after_clear_bit() smp_llsc_mb() + +/* + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void set_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned short bit = nr & SZLONG_MASK; + unsigned long temp; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # set_bit \n" + " or %0, %2 \n" + " " __SC "%0, %1 \n" + " beqzl %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << bit), "m" (*m)); +#ifdef CONFIG_CPU_MIPSR2 + } else if (__builtin_constant_p(bit)) { + __asm__ __volatile__( + "1: " __LL "%0, %1 # set_bit \n" + " " __INS "%0, %4, %2, 1 \n" + " " __SC "%0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + : "=&r" (temp), "=m" (*m) + : "ir" (bit), "m" (*m), "r" (~0)); +#endif /* CONFIG_CPU_MIPSR2 */ + } else if (cpu_has_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # set_bit \n" + " or %0, %2 \n" + " " __SC "%0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << bit), "m" (*m)); + } else { + volatile unsigned long *a = addr; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + *a |= mask; + raw_local_irq_restore(flags); + } +} + +/* + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned short bit = nr & SZLONG_MASK; + unsigned long temp; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # clear_bit \n" + " and %0, %2 \n" + " " __SC "%0, %1 \n" + " beqzl %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m) + : "ir" (~(1UL << bit)), "m" (*m)); +#ifdef CONFIG_CPU_MIPSR2 + } else if (__builtin_constant_p(bit)) { + __asm__ __volatile__( + "1: " __LL "%0, %1 # clear_bit \n" + " " __INS "%0, $0, %2, 1 \n" + " " __SC "%0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + : "=&r" (temp), "=m" (*m) + : "ir" (bit), "m" (*m)); +#endif /* CONFIG_CPU_MIPSR2 */ + } else if (cpu_has_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # clear_bit \n" + " and %0, %2 \n" + " " __SC "%0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m) + : "ir" (~(1UL << bit)), "m" (*m)); + } else { + volatile unsigned long *a = addr; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + *a &= ~mask; + raw_local_irq_restore(flags); + } +} + +/* + * clear_bit_unlock - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and implies release semantics before the memory + * operation. It can be used for an unlock. + */ +static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *addr) +{ + smp_mb__before_clear_bit(); + clear_bit(nr, addr); +} + +/* + * change_bit - Toggle a bit in memory + * @nr: Bit to change + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void change_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned short bit = nr & SZLONG_MASK; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # change_bit \n" + " xor %0, %2 \n" + " " __SC "%0, %1 \n" + " beqzl %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << bit), "m" (*m)); + } else if (cpu_has_llsc) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # change_bit \n" + " xor %0, %2 \n" + " " __SC "%0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << bit), "m" (*m)); + } else { + volatile unsigned long *a = addr; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + *a ^= mask; + raw_local_irq_restore(flags); + } +} + +/* + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned short bit = nr & SZLONG_MASK; + unsigned long res; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_set_bit \n" + " or %2, %0, %3 \n" + " " __SC "%2, %1 \n" + " beqzl %2, 1b \n" + " and %2, %0, %3 \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_set_bit \n" + " or %2, %0, %3 \n" + " " __SC "%2, %1 \n" + " beqz %2, 2f \n" + " and %2, %0, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " nop \n" + " .previous \n" + " .set pop \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); + } else { + volatile unsigned long *a = addr; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a |= mask; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return res != 0; +} + +/* + * test_and_set_bit_lock - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and implies acquire ordering semantics + * after the memory operation. + */ +static inline int test_and_set_bit_lock(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned short bit = nr & SZLONG_MASK; + unsigned long res; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_set_bit \n" + " or %2, %0, %3 \n" + " " __SC "%2, %1 \n" + " beqzl %2, 1b \n" + " and %2, %0, %3 \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_set_bit \n" + " or %2, %0, %3 \n" + " " __SC "%2, %1 \n" + " beqz %2, 2f \n" + " and %2, %0, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " nop \n" + " .previous \n" + " .set pop \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); + } else { + volatile unsigned long *a = addr; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a |= mask; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return res != 0; +} +/* + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_clear_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned short bit = nr & SZLONG_MASK; + unsigned long res; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_clear_bit \n" + " or %2, %0, %3 \n" + " xor %2, %3 \n" + " " __SC "%2, %1 \n" + " beqzl %2, 1b \n" + " and %2, %0, %3 \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); +#ifdef CONFIG_CPU_MIPSR2 + } else if (__builtin_constant_p(nr)) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + "1: " __LL "%0, %1 # test_and_clear_bit \n" + " " __EXT "%2, %0, %3, 1 \n" + " " __INS "%0, $0, %3, 1 \n" + " " __SC "%0, %1 \n" + " beqz %0, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "ir" (bit), "m" (*m) + : "memory"); +#endif + } else if (cpu_has_llsc) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_clear_bit \n" + " or %2, %0, %3 \n" + " xor %2, %3 \n" + " " __SC "%2, %1 \n" + " beqz %2, 2f \n" + " and %2, %0, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " nop \n" + " .previous \n" + " .set pop \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); + } else { + volatile unsigned long *a = addr; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a &= ~mask; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return res != 0; +} + +/* + * test_and_change_bit - Change a bit and return its old value + * @nr: Bit to change + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_change_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned short bit = nr & SZLONG_MASK; + unsigned long res; + + smp_llsc_mb(); + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_change_bit \n" + " xor %2, %0, %3 \n" + " " __SC "%2, %1 \n" + " beqzl %2, 1b \n" + " and %2, %0, %3 \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); + unsigned long temp; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set mips3 \n" + "1: " __LL "%0, %1 # test_and_change_bit \n" + " xor %2, %0, %3 \n" + " " __SC "\t%2, %1 \n" + " beqz %2, 2f \n" + " and %2, %0, %3 \n" + " .subsection 2 \n" + "2: b 1b \n" + " nop \n" + " .previous \n" + " .set pop \n" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << bit), "m" (*m) + : "memory"); + } else { + volatile unsigned long *a = addr; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a ^= mask; + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return res != 0; +} + +#include + +/* + * __clear_bit_unlock - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * __clear_bit() is non-atomic and implies release semantics before the memory + * operation. It can be used for an unlock if no other CPUs can concurrently + * modify other bits in the word. + */ +static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *addr) +{ + smp_mb(); + __clear_bit(nr, addr); +} + +#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) + +/* + * Return the bit position (0..63) of the most significant 1 bit in a word + * Returns -1 if no 1 bit exists + */ +static inline unsigned long __fls(unsigned long x) +{ + int lz; + + if (sizeof(x) == 4) { + __asm__( + " .set push \n" + " .set mips32 \n" + " clz %0, %1 \n" + " .set pop \n" + : "=r" (lz) + : "r" (x)); + + return 31 - lz; + } + + BUG_ON(sizeof(x) != 8); + + __asm__( + " .set push \n" + " .set mips64 \n" + " dclz %0, %1 \n" + " .set pop \n" + : "=r" (lz) + : "r" (x)); + + return 63 - lz; +} + +/* + * __ffs - find first bit in word. + * @word: The word to search + * + * Returns 0..SZLONG-1 + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ + return __fls(word & -word); +} + +/* + * fls - find last bit set. + * @word: The word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +static inline int fls(int word) +{ + __asm__("clz %0, %1" : "=r" (word) : "r" (word)); + + return 32 - word; +} + +#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPS64) +static inline int fls64(__u64 word) +{ + __asm__("dclz %0, %1" : "=r" (word) : "r" (word)); + + return 64 - word; +} +#else +#include +#endif + +/* + * ffs - find first bit set. + * @word: The word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static inline int ffs(int word) +{ + if (!word) + return 0; + + return fls(word & -word); +} + +#else + +#include +#include +#include +#include +#include + +#endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */ + +#include +#include + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +#endif /* __KERNEL__ */ + +#endif /* _ASM_BITOPS_H */ diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h new file mode 100644 index 00000000000..610fe3af7a0 --- /dev/null +++ b/arch/mips/include/asm/bootinfo.h @@ -0,0 +1,110 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 2003 by Ralf Baechle + * Copyright (C) 1995, 1996 Andreas Busse + * Copyright (C) 1995, 1996 Stoned Elipot + * Copyright (C) 1995, 1996 Paul M. Antoine. + */ +#ifndef _ASM_BOOTINFO_H +#define _ASM_BOOTINFO_H + +#include +#include + +/* + * The MACH_ IDs are sort of equivalent to PCI product IDs. As such the + * numbers do not necessarily reflect technical relations or similarities + * between systems. + */ + +/* + * Valid machtype values for group unknown + */ +#define MACH_UNKNOWN 0 /* whatever... */ + +/* + * Valid machtype for group DEC + */ +#define MACH_DSUNKNOWN 0 +#define MACH_DS23100 1 /* DECstation 2100 or 3100 */ +#define MACH_DS5100 2 /* DECsystem 5100 */ +#define MACH_DS5000_200 3 /* DECstation 5000/200 */ +#define MACH_DS5000_1XX 4 /* DECstation 5000/120, 125, 133, 150 */ +#define MACH_DS5000_XX 5 /* DECstation 5000/20, 25, 33, 50 */ +#define MACH_DS5000_2X0 6 /* DECstation 5000/240, 260 */ +#define MACH_DS5400 7 /* DECsystem 5400 */ +#define MACH_DS5500 8 /* DECsystem 5500 */ +#define MACH_DS5800 9 /* DECsystem 5800 */ +#define MACH_DS5900 10 /* DECsystem 5900 */ + +/* + * Valid machtype for group PMC-MSP + */ +#define MACH_MSP4200_EVAL 0 /* PMC-Sierra MSP4200 Evaluation */ +#define MACH_MSP4200_GW 1 /* PMC-Sierra MSP4200 Gateway demo */ +#define MACH_MSP4200_FPGA 2 /* PMC-Sierra MSP4200 Emulation */ +#define MACH_MSP7120_EVAL 3 /* PMC-Sierra MSP7120 Evaluation */ +#define MACH_MSP7120_GW 4 /* PMC-Sierra MSP7120 Residential GW */ +#define MACH_MSP7120_FPGA 5 /* PMC-Sierra MSP7120 Emulation */ +#define MACH_MSP_OTHER 255 /* PMC-Sierra unknown board type */ + +/* + * Valid machtype for group Mikrotik + */ +#define MACH_MIKROTIK_RB532 0 /* Mikrotik RouterBoard 532 */ +#define MACH_MIKROTIK_RB532A 1 /* Mikrotik RouterBoard 532A */ + +#define CL_SIZE COMMAND_LINE_SIZE + +extern char *system_type; +const char *get_system_type(void); + +extern unsigned long mips_machtype; + +#define BOOT_MEM_MAP_MAX 32 +#define BOOT_MEM_RAM 1 +#define BOOT_MEM_ROM_DATA 2 +#define BOOT_MEM_RESERVED 3 + +/* + * A memory map that's built upon what was determined + * or specified on the command line. + */ +struct boot_mem_map { + int nr_map; + struct boot_mem_map_entry { + phys_t addr; /* start of memory segment */ + phys_t size; /* size of memory segment */ + long type; /* type of memory segment */ + } map[BOOT_MEM_MAP_MAX]; +}; + +extern struct boot_mem_map boot_mem_map; + +extern void add_memory_region(phys_t start, phys_t size, long type); + +extern void prom_init(void); +extern void prom_free_prom_memory(void); + +extern void free_init_pages(const char *what, + unsigned long begin, unsigned long end); + +/* + * Initial kernel command line, usually setup by prom_init() + */ +extern char arcs_cmdline[CL_SIZE]; + +/* + * Registers a0, a1, a3 and a4 as passed to the kernel entry by firmware + */ +extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; + +/* + * Platform memory detection hook called by setup_arch + */ +extern void plat_mem_setup(void); + +#endif /* _ASM_BOOTINFO_H */ diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h new file mode 100644 index 00000000000..37c6857c8d4 --- /dev/null +++ b/arch/mips/include/asm/branch.h @@ -0,0 +1,38 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1998, 2001 by Ralf Baechle + */ +#ifndef _ASM_BRANCH_H +#define _ASM_BRANCH_H + +#include + +static inline int delay_slot(struct pt_regs *regs) +{ + return regs->cp0_cause & CAUSEF_BD; +} + +static inline unsigned long exception_epc(struct pt_regs *regs) +{ + if (!delay_slot(regs)) + return regs->cp0_epc; + + return regs->cp0_epc + 4; +} + +extern int __compute_return_epc(struct pt_regs *regs); + +static inline int compute_return_epc(struct pt_regs *regs) +{ + if (!delay_slot(regs)) { + regs->cp0_epc += 4; + return 0; + } + + return __compute_return_epc(regs); +} + +#endif /* _ASM_BRANCH_H */ diff --git a/arch/mips/include/asm/break.h b/arch/mips/include/asm/break.h new file mode 100644 index 00000000000..25b980c91e7 --- /dev/null +++ b/arch/mips/include/asm/break.h @@ -0,0 +1,34 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 2003 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef __ASM_BREAK_H +#define __ASM_BREAK_H + +/* + * The following break codes are or were in use for specific purposes in + * other MIPS operating systems. Linux/MIPS doesn't use all of them. The + * unused ones are here as placeholders; we might encounter them in + * non-Linux/MIPS object files or make use of them in the future. + */ +#define BRK_USERBP 0 /* User bp (used by debuggers) */ +#define BRK_KERNELBP 1 /* Break in the kernel */ +#define BRK_ABORT 2 /* Sometimes used by abort(3) to SIGIOT */ +#define BRK_BD_TAKEN 3 /* For bd slot emulation - not implemented */ +#define BRK_BD_NOTTAKEN 4 /* For bd slot emulation - not implemented */ +#define BRK_SSTEPBP 5 /* User bp (used by debuggers) */ +#define BRK_OVERFLOW 6 /* Overflow check */ +#define BRK_DIVZERO 7 /* Divide by zero check */ +#define BRK_RANGE 8 /* Range error check */ +#define BRK_STACKOVERFLOW 9 /* For Ada stackchecking */ +#define BRK_NORLD 10 /* No rld found - not used by Linux/MIPS */ +#define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */ +#define BRK_BUG 512 /* Used by BUG() */ +#define BRK_KDB 513 /* Used in KDB_ENTER() */ +#define BRK_MULOVF 1023 /* Multiply overflow */ + +#endif /* __ASM_BREAK_H */ diff --git a/arch/mips/include/asm/bug.h b/arch/mips/include/asm/bug.h new file mode 100644 index 00000000000..7eb63de808b --- /dev/null +++ b/arch/mips/include/asm/bug.h @@ -0,0 +1,33 @@ +#ifndef __ASM_BUG_H +#define __ASM_BUG_H + +#include + +#ifdef CONFIG_BUG + +#include + +#define BUG() \ +do { \ + __asm__ __volatile__("break %0" : : "i" (BRK_BUG)); \ +} while (0) + +#define HAVE_ARCH_BUG + +#if (_MIPS_ISA > _MIPS_ISA_MIPS1) + +#define BUG_ON(condition) \ +do { \ + __asm__ __volatile__("tne $0, %0, %1" \ + : : "r" (condition), "i" (BRK_BUG)); \ +} while (0) + +#define HAVE_ARCH_BUG_ON + +#endif /* _MIPS_ISA > _MIPS_ISA_MIPS1 */ + +#endif + +#include + +#endif /* __ASM_BUG_H */ diff --git a/arch/mips/include/asm/bugs.h b/arch/mips/include/asm/bugs.h new file mode 100644 index 00000000000..9dc10df3207 --- /dev/null +++ b/arch/mips/include/asm/bugs.h @@ -0,0 +1,53 @@ +/* + * This is included by init/main.c to check for architecture-dependent bugs. + * + * Copyright (C) 2007 Maciej W. Rozycki + * + * Needs: + * void check_bugs(void); + */ +#ifndef _ASM_BUGS_H +#define _ASM_BUGS_H + +#include +#include + +#include +#include + +extern int daddiu_bug; + +extern void check_bugs64_early(void); + +extern void check_bugs32(void); +extern void check_bugs64(void); + +static inline void check_bugs_early(void) +{ +#ifdef CONFIG_64BIT + check_bugs64_early(); +#endif +} + +static inline void check_bugs(void) +{ + unsigned int cpu = smp_processor_id(); + + cpu_data[cpu].udelay_val = loops_per_jiffy; + check_bugs32(); +#ifdef CONFIG_64BIT + check_bugs64(); +#endif +} + +static inline int r4k_daddiu_bug(void) +{ +#ifdef CONFIG_64BIT + WARN_ON(daddiu_bug < 0); + return daddiu_bug != 0; +#else + return 0; +#endif +} + +#endif /* _ASM_BUGS_H */ diff --git a/arch/mips/include/asm/byteorder.h b/arch/mips/include/asm/byteorder.h new file mode 100644 index 00000000000..fe7dc2d59b6 --- /dev/null +++ b/arch/mips/include/asm/byteorder.h @@ -0,0 +1,76 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 99, 2003 by Ralf Baechle + */ +#ifndef _ASM_BYTEORDER_H +#define _ASM_BYTEORDER_H + +#include +#include + +#ifdef __GNUC__ + +#ifdef CONFIG_CPU_MIPSR2 + +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__( + " wsbh %0, %1 \n" + : "=r" (x) + : "r" (x)); + + return x; +} +#define __arch__swab16(x) ___arch__swab16(x) + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +{ + __asm__( + " wsbh %0, %1 \n" + " rotr %0, %0, 16 \n" + : "=r" (x) + : "r" (x)); + + return x; +} +#define __arch__swab32(x) ___arch__swab32(x) + +#ifdef CONFIG_CPU_MIPS64_R2 + +static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x) +{ + __asm__( + " dsbh %0, %1 \n" + " dshd %0, %0 \n" + " drotr %0, %0, 32 \n" + : "=r" (x) + : "r" (x)); + + return x; +} + +#define __arch__swab64(x) ___arch__swab64(x) + +#endif /* CONFIG_CPU_MIPS64_R2 */ + +#endif /* CONFIG_CPU_MIPSR2 */ + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +# define __BYTEORDER_HAS_U64__ +# define __SWAB_64_THRU_32__ +#endif + +#endif /* __GNUC__ */ + +#if defined(__MIPSEB__) +# include +#elif defined(__MIPSEL__) +# include +#else +# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" +#endif + +#endif /* _ASM_BYTEORDER_H */ diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h new file mode 100644 index 00000000000..37f175c42bb --- /dev/null +++ b/arch/mips/include/asm/cache.h @@ -0,0 +1,20 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 98, 99, 2000, 2003 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_CACHE_H +#define _ASM_CACHE_H + +#include + +#define L1_CACHE_SHIFT CONFIG_MIPS_L1_CACHE_SHIFT +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#define SMP_CACHE_SHIFT L1_CACHE_SHIFT +#define SMP_CACHE_BYTES L1_CACHE_BYTES + +#endif /* _ASM_CACHE_H */ diff --git a/arch/mips/include/asm/cachectl.h b/arch/mips/include/asm/cachectl.h new file mode 100644 index 00000000000..f3ce721861d --- /dev/null +++ b/arch/mips/include/asm/cachectl.h @@ -0,0 +1,26 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle + */ +#ifndef _ASM_CACHECTL +#define _ASM_CACHECTL + +/* + * Options for cacheflush system call + */ +#define ICACHE (1<<0) /* flush instruction cache */ +#define DCACHE (1<<1) /* writeback and flush data cache */ +#define BCACHE (ICACHE|DCACHE) /* flush both caches */ + +/* + * Caching modes for the cachectl(2) call + * + * cachectl(2) is currently not supported and returns ENOSYS. + */ +#define CACHEABLE 0 /* make pages cacheable */ +#define UNCACHEABLE 1 /* make pages uncacheable */ + +#endif /* _ASM_CACHECTL */ diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h new file mode 100644 index 00000000000..03b1d69b142 --- /dev/null +++ b/arch/mips/include/asm/cacheflush.h @@ -0,0 +1,116 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 by Ralf Baechle + * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. + */ +#ifndef _ASM_CACHEFLUSH_H +#define _ASM_CACHEFLUSH_H + +/* Keep includes the same across arches. */ +#include +#include + +/* Cache flushing: + * + * - flush_cache_all() flushes entire cache + * - flush_cache_mm(mm) flushes the specified mm context's cache lines + * - flush_cache_dup mm(mm) handles cache flushing when forking + * - flush_cache_page(mm, vmaddr, pfn) flushes a single page + * - flush_cache_range(vma, start, end) flushes a range of pages + * - flush_icache_range(start, end) flush a range of instructions + * - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache + * + * MIPS specific flush operations: + * + * - flush_cache_sigtramp() flush signal trampoline + * - flush_icache_all() flush the entire instruction cache + * - flush_data_cache_page() flushes a page from the data cache + */ +extern void (*flush_cache_all)(void); +extern void (*__flush_cache_all)(void); +extern void (*flush_cache_mm)(struct mm_struct *mm); +#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0) +extern void (*flush_cache_range)(struct vm_area_struct *vma, + unsigned long start, unsigned long end); +extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); +extern void __flush_dcache_page(struct page *page); + +static inline void flush_dcache_page(struct page *page) +{ + if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) + __flush_dcache_page(page); + +} + +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) + +#define ARCH_HAS_FLUSH_ANON_PAGE +extern void __flush_anon_page(struct page *, unsigned long); +static inline void flush_anon_page(struct vm_area_struct *vma, + struct page *page, unsigned long vmaddr) +{ + if (cpu_has_dc_aliases && PageAnon(page)) + __flush_anon_page(page, vmaddr); +} + +static inline void flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ +} + +extern void (*flush_icache_range)(unsigned long start, unsigned long end); +extern void (*local_flush_icache_range)(unsigned long start, unsigned long end); + +extern void (*__flush_cache_vmap)(void); + +static inline void flush_cache_vmap(unsigned long start, unsigned long end) +{ + if (cpu_has_dc_aliases) + __flush_cache_vmap(); +} + +extern void (*__flush_cache_vunmap)(void); + +static inline void flush_cache_vunmap(unsigned long start, unsigned long end) +{ + if (cpu_has_dc_aliases) + __flush_cache_vunmap(); +} + +extern void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len); + +extern void copy_from_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len); + +extern void (*flush_cache_sigtramp)(unsigned long addr); +extern void (*flush_icache_all)(void); +extern void (*local_flush_data_cache_page)(void * addr); +extern void (*flush_data_cache_page)(unsigned long addr); + +/* + * This flag is used to indicate that the page pointed to by a pte + * is dirty and requires cleaning before returning it to the user. + */ +#define PG_dcache_dirty PG_arch_1 + +#define Page_dcache_dirty(page) \ + test_bit(PG_dcache_dirty, &(page)->flags) +#define SetPageDcacheDirty(page) \ + set_bit(PG_dcache_dirty, &(page)->flags) +#define ClearPageDcacheDirty(page) \ + clear_bit(PG_dcache_dirty, &(page)->flags) + +/* Run kernel code uncached, useful for cache probing functions. */ +unsigned long run_uncached(void *func); + +extern void *kmap_coherent(struct page *page, unsigned long addr); +extern void kunmap_coherent(void); + +#endif /* _ASM_CACHEFLUSH_H */ diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h new file mode 100644 index 00000000000..256ad2cc6eb --- /dev/null +++ b/arch/mips/include/asm/cacheops.h @@ -0,0 +1,85 @@ +/* + * Cache operations for the cache instruction. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * (C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle + * (C) Copyright 1999 Silicon Graphics, Inc. + */ +#ifndef __ASM_CACHEOPS_H +#define __ASM_CACHEOPS_H + +/* + * Cache Operations available on all MIPS processors with R4000-style caches + */ +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 +#define Index_Load_Tag_I 0x04 +#define Index_Load_Tag_D 0x05 +#define Index_Store_Tag_I 0x08 +#define Index_Store_Tag_D 0x09 +#if defined(CONFIG_CPU_LOONGSON2) +#define Hit_Invalidate_I 0x00 +#else +#define Hit_Invalidate_I 0x10 +#endif +#define Hit_Invalidate_D 0x11 +#define Hit_Writeback_Inv_D 0x15 + +/* + * R4000-specific cacheops + */ +#define Create_Dirty_Excl_D 0x0d +#define Fill 0x14 +#define Hit_Writeback_I 0x18 +#define Hit_Writeback_D 0x19 + +/* + * R4000SC and R4400SC-specific cacheops + */ +#define Index_Invalidate_SI 0x02 +#define Index_Writeback_Inv_SD 0x03 +#define Index_Load_Tag_SI 0x06 +#define Index_Load_Tag_SD 0x07 +#define Index_Store_Tag_SI 0x0A +#define Index_Store_Tag_SD 0x0B +#define Create_Dirty_Excl_SD 0x0f +#define Hit_Invalidate_SI 0x12 +#define Hit_Invalidate_SD 0x13 +#define Hit_Writeback_Inv_SD 0x17 +#define Hit_Writeback_SD 0x1b +#define Hit_Set_Virtual_SI 0x1e +#define Hit_Set_Virtual_SD 0x1f + +/* + * R5000-specific cacheops + */ +#define R5K_Page_Invalidate_S 0x17 + +/* + * RM7000-specific cacheops + */ +#define Page_Invalidate_T 0x16 + +/* + * R10000-specific cacheops + * + * Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused. + * Most of the _S cacheops are identical to the R4000SC _SD cacheops. + */ +#define Index_Writeback_Inv_S 0x03 +#define Index_Load_Tag_S 0x07 +#define Index_Store_Tag_S 0x0B +#define Hit_Invalidate_S 0x13 +#define Cache_Barrier 0x14 +#define Hit_Writeback_Inv_S 0x17 +#define Index_Load_Data_I 0x18 +#define Index_Load_Data_D 0x19 +#define Index_Load_Data_S 0x1b +#define Index_Store_Data_I 0x1c +#define Index_Store_Data_D 0x1d +#define Index_Store_Data_S 0x1f + +#endif /* __ASM_CACHEOPS_H */ diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h new file mode 100644 index 00000000000..290485ac540 --- /dev/null +++ b/arch/mips/include/asm/checksum.h @@ -0,0 +1,260 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2001 Thiemo Seufer. + * Copyright (C) 2002 Maciej W. Rozycki + */ +#ifndef _ASM_CHECKSUM_H +#define _ASM_CHECKSUM_H + +#include + +#include + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +__wsum csum_partial(const void *buff, int len, __wsum sum); + +__wsum __csum_partial_copy_user(const void *src, void *dst, + int len, __wsum sum, int *err_ptr); + +/* + * this is a new version of the above that records errors it finds in *errp, + * but continues and zeros the rest of the buffer. + */ +static inline +__wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len, + __wsum sum, int *err_ptr) +{ + might_sleep(); + return __csum_partial_copy_user((__force void *)src, dst, + len, sum, err_ptr); +} + +/* + * Copy and checksum to user + */ +#define HAVE_CSUM_COPY_USER +static inline +__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, + __wsum sum, int *err_ptr) +{ + might_sleep(); + if (access_ok(VERIFY_WRITE, dst, len)) + return __csum_partial_copy_user(src, (__force void *)dst, + len, sum, err_ptr); + if (len) + *err_ptr = -EFAULT; + + return (__force __wsum)-1; /* invalid checksum */ +} + +/* + * the same as csum_partial, but copies from user space (but on MIPS + * we have just one address space, so this is identical to the above) + */ +__wsum csum_partial_copy_nocheck(const void *src, void *dst, + int len, __wsum sum); + +/* + * Fold a partial checksum without adding pseudo headers + */ +static inline __sum16 csum_fold(__wsum sum) +{ + __asm__( + " .set push # csum_fold\n" + " .set noat \n" + " sll $1, %0, 16 \n" + " addu %0, $1 \n" + " sltu $1, %0, $1 \n" + " srl %0, %0, 16 \n" + " addu %0, $1 \n" + " xori %0, 0xffff \n" + " .set pop" + : "=r" (sum) + : "0" (sum)); + + return (__force __sum16)sum; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + * + * By Jorge Cwik , adapted for linux by + * Arnt Gulbrandsen. + */ +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + const unsigned int *word = iph; + const unsigned int *stop = word + ihl; + unsigned int csum; + int carry; + + csum = word[0]; + csum += word[1]; + carry = (csum < word[1]); + csum += carry; + + csum += word[2]; + carry = (csum < word[2]); + csum += carry; + + csum += word[3]; + carry = (csum < word[3]); + csum += carry; + + word += 4; + do { + csum += *word; + carry = (csum < *word); + csum += carry; + word++; + } while (word != stop); + + return csum_fold(csum); +} + +static inline __wsum csum_tcpudp_nofold(__be32 saddr, + __be32 daddr, unsigned short len, unsigned short proto, + __wsum sum) +{ + __asm__( + " .set push # csum_tcpudp_nofold\n" + " .set noat \n" +#ifdef CONFIG_32BIT + " addu %0, %2 \n" + " sltu $1, %0, %2 \n" + " addu %0, $1 \n" + + " addu %0, %3 \n" + " sltu $1, %0, %3 \n" + " addu %0, $1 \n" + + " addu %0, %4 \n" + " sltu $1, %0, %4 \n" + " addu %0, $1 \n" +#endif +#ifdef CONFIG_64BIT + " daddu %0, %2 \n" + " daddu %0, %3 \n" + " daddu %0, %4 \n" + " dsll32 $1, %0, 0 \n" + " daddu %0, $1 \n" + " dsra32 %0, %0, 0 \n" +#endif + " .set pop" + : "=r" (sum) + : "0" ((__force unsigned long)daddr), + "r" ((__force unsigned long)saddr), +#ifdef __MIPSEL__ + "r" ((proto + len) << 8), +#else + "r" (proto + len), +#endif + "r" ((__force unsigned long)sum)); + + return sum; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, + __wsum sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +static inline __sum16 ip_compute_csum(const void *buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +#define _HAVE_ARCH_IPV6_CSUM +static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + const struct in6_addr *daddr, + __u32 len, unsigned short proto, + __wsum sum) +{ + __asm__( + " .set push # csum_ipv6_magic\n" + " .set noreorder \n" + " .set noat \n" + " addu %0, %5 # proto (long in network byte order)\n" + " sltu $1, %0, %5 \n" + " addu %0, $1 \n" + + " addu %0, %6 # csum\n" + " sltu $1, %0, %6 \n" + " lw %1, 0(%2) # four words source address\n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " lw %1, 4(%2) \n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " lw %1, 8(%2) \n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " lw %1, 12(%2) \n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " lw %1, 0(%3) \n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " lw %1, 4(%3) \n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " lw %1, 8(%3) \n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " lw %1, 12(%3) \n" + " addu %0, $1 \n" + " addu %0, %1 \n" + " sltu $1, %0, %1 \n" + + " addu %0, $1 # Add final carry\n" + " .set pop" + : "=r" (sum), "=r" (proto) + : "r" (saddr), "r" (daddr), + "0" (htonl(len)), "1" (htonl(proto)), "r" (sum)); + + return csum_fold(sum); +} + +#endif /* _ASM_CHECKSUM_H */ diff --git a/arch/mips/include/asm/cmp.h b/arch/mips/include/asm/cmp.h new file mode 100644 index 00000000000..89a73fb93ae --- /dev/null +++ b/arch/mips/include/asm/cmp.h @@ -0,0 +1,18 @@ +#ifndef _ASM_CMP_H +#define _ASM_CMP_H + +/* + * Definitions for CMP multitasking on MIPS cores + */ +struct task_struct; + +extern void cmp_smp_setup(void); +extern void cmp_smp_finish(void); +extern void cmp_boot_secondary(int cpu, struct task_struct *t); +extern void cmp_init_secondary(void); +extern void cmp_cpus_done(void); +extern void cmp_prepare_cpus(unsigned int max_cpus); + +/* This is platform specific */ +extern void cmp_send_ipi(int cpu, unsigned int action); +#endif /* _ASM_CMP_H */ diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h new file mode 100644 index 00000000000..4a812c3ceb9 --- /dev/null +++ b/arch/mips/include/asm/cmpxchg.h @@ -0,0 +1,124 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 06, 07 by Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_CMPXCHG_H +#define __ASM_CMPXCHG_H + +#include + +#define __HAVE_ARCH_CMPXCHG 1 + +#define __cmpxchg_asm(ld, st, m, old, new) \ +({ \ + __typeof(*(m)) __ret; \ + \ + if (cpu_has_llsc && R10000_LLSC_WAR) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: " ld " %0, %2 # __cmpxchg_asm \n" \ + " bne %0, %z3, 2f \n" \ + " .set mips0 \n" \ + " move $1, %z4 \n" \ + " .set mips3 \n" \ + " " st " $1, %1 \n" \ + " beqzl $1, 1b \n" \ + "2: \n" \ + " .set pop \n" \ + : "=&r" (__ret), "=R" (*m) \ + : "R" (*m), "Jr" (old), "Jr" (new) \ + : "memory"); \ + } else if (cpu_has_llsc) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: " ld " %0, %2 # __cmpxchg_asm \n" \ + " bne %0, %z3, 2f \n" \ + " .set mips0 \n" \ + " move $1, %z4 \n" \ + " .set mips3 \n" \ + " " st " $1, %1 \n" \ + " beqz $1, 3f \n" \ + "2: \n" \ + " .subsection 2 \n" \ + "3: b 1b \n" \ + " .previous \n" \ + " .set pop \n" \ + : "=&r" (__ret), "=R" (*m) \ + : "R" (*m), "Jr" (old), "Jr" (new) \ + : "memory"); \ + } else { \ + unsigned long __flags; \ + \ + raw_local_irq_save(__flags); \ + __ret = *m; \ + if (__ret == old) \ + *m = new; \ + raw_local_irq_restore(__flags); \ + } \ + \ + __ret; \ +}) + +/* + * This function doesn't exist, so you'll get a linker error + * if something tries to do an invalid cmpxchg(). + */ +extern void __cmpxchg_called_with_bad_pointer(void); + +#define __cmpxchg(ptr, old, new, barrier) \ +({ \ + __typeof__(ptr) __ptr = (ptr); \ + __typeof__(*(ptr)) __old = (old); \ + __typeof__(*(ptr)) __new = (new); \ + __typeof__(*(ptr)) __res = 0; \ + \ + barrier; \ + \ + switch (sizeof(*(__ptr))) { \ + case 4: \ + __res = __cmpxchg_asm("ll", "sc", __ptr, __old, __new); \ + break; \ + case 8: \ + if (sizeof(long) == 8) { \ + __res = __cmpxchg_asm("lld", "scd", __ptr, \ + __old, __new); \ + break; \ + } \ + default: \ + __cmpxchg_called_with_bad_pointer(); \ + break; \ + } \ + \ + barrier; \ + \ + __res; \ +}) + +#define cmpxchg(ptr, old, new) __cmpxchg(ptr, old, new, smp_llsc_mb()) +#define cmpxchg_local(ptr, old, new) __cmpxchg(ptr, old, new, ) + +#define cmpxchg64(ptr, o, n) \ + ({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg((ptr), (o), (n)); \ + }) + +#ifdef CONFIG_64BIT +#define cmpxchg64_local(ptr, o, n) \ + ({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg_local((ptr), (o), (n)); \ + }) +#else +#include +#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#endif + +#endif /* __ASM_CMPXCHG_H */ diff --git a/arch/mips/include/asm/compat-signal.h b/arch/mips/include/asm/compat-signal.h new file mode 100644 index 00000000000..368a99e5c3e --- /dev/null +++ b/arch/mips/include/asm/compat-signal.h @@ -0,0 +1,119 @@ +#ifndef __ASM_COMPAT_SIGNAL_H +#define __ASM_COMPAT_SIGNAL_H + +#include +#include +#include + +#include +#include + +#include + +#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) + +typedef struct compat_siginfo { + int si_signo; + int si_code; + int si_errno; + + union { + int _pad[SI_PAD_SIZE32]; + + /* kill() */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + } _kill; + + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_uid_t _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* IRIX SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_clock_t _utime; + int _status; /* exit code */ + compat_clock_t _stime; + } _irix_sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + s32 _addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL, SIGXFSZ (To do ...) */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + + /* POSIX.1b timers */ + struct { + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + compat_sigval_t _sigval;/* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + compat_sigval_t _sigval; + } _rt; + + } _sifields; +} compat_siginfo_t; + +static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d, + const sigset_t *s) +{ + int err; + + BUG_ON(sizeof(*d) != sizeof(*s)); + BUG_ON(_NSIG_WORDS != 2); + + err = __put_user(s->sig[0], &d->sig[0]); + err |= __put_user(s->sig[0] >> 32, &d->sig[1]); + err |= __put_user(s->sig[1], &d->sig[2]); + err |= __put_user(s->sig[1] >> 32, &d->sig[3]); + + return err; +} + +static inline int __copy_conv_sigset_from_user(sigset_t *d, + const compat_sigset_t __user *s) +{ + int err; + union sigset_u { + sigset_t s; + compat_sigset_t c; + } *u = (union sigset_u *) d; + + BUG_ON(sizeof(*d) != sizeof(*s)); + BUG_ON(_NSIG_WORDS != 2); + +#ifdef CONFIG_CPU_BIG_ENDIAN + err = __get_user(u->c.sig[1], &s->sig[0]); + err |= __get_user(u->c.sig[0], &s->sig[1]); + err |= __get_user(u->c.sig[3], &s->sig[2]); + err |= __get_user(u->c.sig[2], &s->sig[3]); +#endif +#ifdef CONFIG_CPU_LITTLE_ENDIAN + err = __get_user(u->c.sig[0], &s->sig[0]); + err |= __get_user(u->c.sig[1], &s->sig[1]); + err |= __get_user(u->c.sig[2], &s->sig[2]); + err |= __get_user(u->c.sig[3], &s->sig[3]); +#endif + + return err; +} + +#endif /* __ASM_COMPAT_SIGNAL_H */ diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h new file mode 100644 index 00000000000..ac5d541368e --- /dev/null +++ b/arch/mips/include/asm/compat.h @@ -0,0 +1,221 @@ +#ifndef _ASM_COMPAT_H +#define _ASM_COMPAT_H +/* + * Architecture specific compatibility types + */ +#include +#include +#include + +#define COMPAT_USER_HZ 100 + +typedef u32 compat_size_t; +typedef s32 compat_ssize_t; +typedef s32 compat_time_t; +typedef s32 compat_clock_t; +typedef s32 compat_suseconds_t; + +typedef s32 compat_pid_t; +typedef s32 __compat_uid_t; +typedef s32 __compat_gid_t; +typedef __compat_uid_t __compat_uid32_t; +typedef __compat_gid_t __compat_gid32_t; +typedef u32 compat_mode_t; +typedef u32 compat_ino_t; +typedef u32 compat_dev_t; +typedef s32 compat_off_t; +typedef s64 compat_loff_t; +typedef u32 compat_nlink_t; +typedef s32 compat_ipc_pid_t; +typedef s32 compat_daddr_t; +typedef s32 compat_caddr_t; +typedef struct { + s32 val[2]; +} compat_fsid_t; +typedef s32 compat_timer_t; +typedef s32 compat_key_t; + +typedef s32 compat_int_t; +typedef s32 compat_long_t; +typedef s64 compat_s64; +typedef u32 compat_uint_t; +typedef u32 compat_ulong_t; +typedef u64 compat_u64; + +struct compat_timespec { + compat_time_t tv_sec; + s32 tv_nsec; +}; + +struct compat_timeval { + compat_time_t tv_sec; + s32 tv_usec; +}; + +struct compat_stat { + compat_dev_t st_dev; + s32 st_pad1[3]; + compat_ino_t st_ino; + compat_mode_t st_mode; + compat_nlink_t st_nlink; + __compat_uid_t st_uid; + __compat_gid_t st_gid; + compat_dev_t st_rdev; + s32 st_pad2[2]; + compat_off_t st_size; + s32 st_pad3; + compat_time_t st_atime; + s32 st_atime_nsec; + compat_time_t st_mtime; + s32 st_mtime_nsec; + compat_time_t st_ctime; + s32 st_ctime_nsec; + s32 st_blksize; + s32 st_blocks; + s32 st_pad4[14]; +}; + +struct compat_flock { + short l_type; + short l_whence; + compat_off_t l_start; + compat_off_t l_len; + s32 l_sysid; + compat_pid_t l_pid; + short __unused; + s32 pad[4]; +}; + +#define F_GETLK64 33 +#define F_SETLK64 34 +#define F_SETLKW64 35 + +struct compat_flock64 { + short l_type; + short l_whence; + compat_loff_t l_start; + compat_loff_t l_len; + compat_pid_t l_pid; +}; + +struct compat_statfs { + int f_type; + int f_bsize; + int f_frsize; + int f_blocks; + int f_bfree; + int f_files; + int f_ffree; + int f_bavail; + compat_fsid_t f_fsid; + int f_namelen; + int f_spare[6]; +}; + +#define COMPAT_RLIM_INFINITY 0x7fffffffUL + +typedef u32 compat_old_sigset_t; /* at least 32 bits */ + +#define _COMPAT_NSIG 128 /* Don't ask !$@#% ... */ +#define _COMPAT_NSIG_BPW 32 + +typedef u32 compat_sigset_word; + +#define COMPAT_OFF_T_MAX 0x7fffffff +#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL + +/* + * A pointer passed in from user mode. This should not + * be used for syscall parameters, just declare them + * as pointers because the syscall entry code will have + * appropriately converted them already. + */ +typedef u32 compat_uptr_t; + +static inline void __user *compat_ptr(compat_uptr_t uptr) +{ + /* cast to a __user pointer via "unsigned long" makes sparse happy */ + return (void __user *)(unsigned long)(long)uptr; +} + +static inline compat_uptr_t ptr_to_compat(void __user *uptr) +{ + return (u32)(unsigned long)uptr; +} + +static inline void __user *compat_alloc_user_space(long len) +{ + struct pt_regs *regs = (struct pt_regs *) + ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; + + return (void __user *) (regs->regs[29] - len); +} + +struct compat_ipc64_perm { + compat_key_t key; + __compat_uid32_t uid; + __compat_gid32_t gid; + __compat_uid32_t cuid; + __compat_gid32_t cgid; + compat_mode_t mode; + unsigned short seq; + unsigned short __pad2; + compat_ulong_t __unused1; + compat_ulong_t __unused2; +}; + +struct compat_semid64_ds { + struct compat_ipc64_perm sem_perm; + compat_time_t sem_otime; + compat_time_t sem_ctime; + compat_ulong_t sem_nsems; + compat_ulong_t __unused1; + compat_ulong_t __unused2; +}; + +struct compat_msqid64_ds { + struct compat_ipc64_perm msg_perm; +#ifndef CONFIG_CPU_LITTLE_ENDIAN + compat_ulong_t __unused1; +#endif + compat_time_t msg_stime; +#ifdef CONFIG_CPU_LITTLE_ENDIAN + compat_ulong_t __unused1; +#endif +#ifndef CONFIG_CPU_LITTLE_ENDIAN + compat_ulong_t __unused2; +#endif + compat_time_t msg_rtime; +#ifdef CONFIG_CPU_LITTLE_ENDIAN + compat_ulong_t __unused2; +#endif +#ifndef CONFIG_CPU_LITTLE_ENDIAN + compat_ulong_t __unused3; +#endif + compat_time_t msg_ctime; +#ifdef CONFIG_CPU_LITTLE_ENDIAN + compat_ulong_t __unused3; +#endif + compat_ulong_t msg_cbytes; + compat_ulong_t msg_qnum; + compat_ulong_t msg_qbytes; + compat_pid_t msg_lspid; + compat_pid_t msg_lrpid; + compat_ulong_t __unused4; + compat_ulong_t __unused5; +}; + +struct compat_shmid64_ds { + struct compat_ipc64_perm shm_perm; + compat_size_t shm_segsz; + compat_time_t shm_atime; + compat_time_t shm_dtime; + compat_time_t shm_ctime; + compat_pid_t shm_cpid; + compat_pid_t shm_lpid; + compat_ulong_t shm_nattch; + compat_ulong_t __unused1; + compat_ulong_t __unused2; +}; + +#endif /* _ASM_COMPAT_H */ diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h new file mode 100644 index 00000000000..71f5c5cfc58 --- /dev/null +++ b/arch/mips/include/asm/compiler.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2004, 2007 Maciej W. Rozycki + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef _ASM_COMPILER_H +#define _ASM_COMPILER_H + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define GCC_IMM_ASM() "n" +#define GCC_REG_ACCUM "$0" +#else +#define GCC_IMM_ASM() "rn" +#define GCC_REG_ACCUM "accum" +#endif + +#endif /* _ASM_COMPILER_H */ diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h new file mode 100644 index 00000000000..5ea701fc342 --- /dev/null +++ b/arch/mips/include/asm/cpu-features.h @@ -0,0 +1,219 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + */ +#ifndef __ASM_CPU_FEATURES_H +#define __ASM_CPU_FEATURES_H + +#include +#include +#include + +#ifndef current_cpu_type +#define current_cpu_type() current_cpu_data.cputype +#endif + +/* + * SMP assumption: Options of CPU 0 are a superset of all processors. + * This is true for all known MIPS systems. + */ +#ifndef cpu_has_tlb +#define cpu_has_tlb (cpu_data[0].options & MIPS_CPU_TLB) +#endif +#ifndef cpu_has_4kex +#define cpu_has_4kex (cpu_data[0].options & MIPS_CPU_4KEX) +#endif +#ifndef cpu_has_3k_cache +#define cpu_has_3k_cache (cpu_data[0].options & MIPS_CPU_3K_CACHE) +#endif +#define cpu_has_6k_cache 0 +#define cpu_has_8k_cache 0 +#ifndef cpu_has_4k_cache +#define cpu_has_4k_cache (cpu_data[0].options & MIPS_CPU_4K_CACHE) +#endif +#ifndef cpu_has_tx39_cache +#define cpu_has_tx39_cache (cpu_data[0].options & MIPS_CPU_TX39_CACHE) +#endif +#ifndef cpu_has_fpu +#define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU) +#define raw_cpu_has_fpu (raw_current_cpu_data.options & MIPS_CPU_FPU) +#else +#define raw_cpu_has_fpu cpu_has_fpu +#endif +#ifndef cpu_has_32fpr +#define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR) +#endif +#ifndef cpu_has_counter +#define cpu_has_counter (cpu_data[0].options & MIPS_CPU_COUNTER) +#endif +#ifndef cpu_has_watch +#define cpu_has_watch (cpu_data[0].options & MIPS_CPU_WATCH) +#endif +#ifndef cpu_has_divec +#define cpu_has_divec (cpu_data[0].options & MIPS_CPU_DIVEC) +#endif +#ifndef cpu_has_vce +#define cpu_has_vce (cpu_data[0].options & MIPS_CPU_VCE) +#endif +#ifndef cpu_has_cache_cdex_p +#define cpu_has_cache_cdex_p (cpu_data[0].options & MIPS_CPU_CACHE_CDEX_P) +#endif +#ifndef cpu_has_cache_cdex_s +#define cpu_has_cache_cdex_s (cpu_data[0].options & MIPS_CPU_CACHE_CDEX_S) +#endif +#ifndef cpu_has_prefetch +#define cpu_has_prefetch (cpu_data[0].options & MIPS_CPU_PREFETCH) +#endif +#ifndef cpu_has_mcheck +#define cpu_has_mcheck (cpu_data[0].options & MIPS_CPU_MCHECK) +#endif +#ifndef cpu_has_ejtag +#define cpu_has_ejtag (cpu_data[0].options & MIPS_CPU_EJTAG) +#endif +#ifndef cpu_has_llsc +#define cpu_has_llsc (cpu_data[0].options & MIPS_CPU_LLSC) +#endif +#ifndef cpu_has_mips16 +#define cpu_has_mips16 (cpu_data[0].ases & MIPS_ASE_MIPS16) +#endif +#ifndef cpu_has_mdmx +#define cpu_has_mdmx (cpu_data[0].ases & MIPS_ASE_MDMX) +#endif +#ifndef cpu_has_mips3d +#define cpu_has_mips3d (cpu_data[0].ases & MIPS_ASE_MIPS3D) +#endif +#ifndef cpu_has_smartmips +#define cpu_has_smartmips (cpu_data[0].ases & MIPS_ASE_SMARTMIPS) +#endif +#ifndef cpu_has_vtag_icache +#define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) +#endif +#ifndef cpu_has_dc_aliases +#define cpu_has_dc_aliases (cpu_data[0].dcache.flags & MIPS_CACHE_ALIASES) +#endif +#ifndef cpu_has_ic_fills_f_dc +#define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC) +#endif +#ifndef cpu_has_pindexed_dcache +#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX) +#endif + +/* + * I-Cache snoops remote store. This only matters on SMP. Some multiprocessors + * such as the R10000 have I-Caches that snoop local stores; the embedded ones + * don't. For maintaining I-cache coherency this means we need to flush the + * D-cache all the way back to whever the I-cache does refills from, so the + * I-cache has a chance to see the new data at all. Then we have to flush the + * I-cache also. + * Note we may have been rescheduled and may no longer be running on the CPU + * that did the store so we can't optimize this into only doing the flush on + * the local CPU. + */ +#ifndef cpu_icache_snoops_remote_store +#ifdef CONFIG_SMP +#define cpu_icache_snoops_remote_store (cpu_data[0].icache.flags & MIPS_IC_SNOOPS_REMOTE) +#else +#define cpu_icache_snoops_remote_store 1 +#endif +#endif + +# ifndef cpu_has_mips32r1 +# define cpu_has_mips32r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R1) +# endif +# ifndef cpu_has_mips32r2 +# define cpu_has_mips32r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2) +# endif +# ifndef cpu_has_mips64r1 +# define cpu_has_mips64r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1) +# endif +# ifndef cpu_has_mips64r2 +# define cpu_has_mips64r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2) +# endif + +/* + * Shortcuts ... + */ +#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2) +#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2) +#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1) +#define cpu_has_mips_r2 (cpu_has_mips32r2 | cpu_has_mips64r2) + +#ifndef cpu_has_dsp +#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP) +#endif + +#ifndef cpu_has_mipsmt +#define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT) +#endif + +#ifndef cpu_has_userlocal +#define cpu_has_userlocal (cpu_data[0].options & MIPS_CPU_ULRI) +#endif + +#ifdef CONFIG_32BIT +# ifndef cpu_has_nofpuex +# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX) +# endif +# ifndef cpu_has_64bits +# define cpu_has_64bits (cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT) +# endif +# ifndef cpu_has_64bit_zero_reg +# define cpu_has_64bit_zero_reg (cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT) +# endif +# ifndef cpu_has_64bit_gp_regs +# define cpu_has_64bit_gp_regs 0 +# endif +# ifndef cpu_has_64bit_addresses +# define cpu_has_64bit_addresses 0 +# endif +#endif + +#ifdef CONFIG_64BIT +# ifndef cpu_has_nofpuex +# define cpu_has_nofpuex 0 +# endif +# ifndef cpu_has_64bits +# define cpu_has_64bits 1 +# endif +# ifndef cpu_has_64bit_zero_reg +# define cpu_has_64bit_zero_reg 1 +# endif +# ifndef cpu_has_64bit_gp_regs +# define cpu_has_64bit_gp_regs 1 +# endif +# ifndef cpu_has_64bit_addresses +# define cpu_has_64bit_addresses 1 +# endif +#endif + +#if defined(CONFIG_CPU_MIPSR2_IRQ_VI) && !defined(cpu_has_vint) +# define cpu_has_vint (cpu_data[0].options & MIPS_CPU_VINT) +#elif !defined(cpu_has_vint) +# define cpu_has_vint 0 +#endif + +#if defined(CONFIG_CPU_MIPSR2_IRQ_EI) && !defined(cpu_has_veic) +# define cpu_has_veic (cpu_data[0].options & MIPS_CPU_VEIC) +#elif !defined(cpu_has_veic) +# define cpu_has_veic 0 +#endif + +#ifndef cpu_has_inclusive_pcaches +#define cpu_has_inclusive_pcaches (cpu_data[0].options & MIPS_CPU_INCLUSIVE_CACHES) +#endif + +#ifndef cpu_dcache_line_size +#define cpu_dcache_line_size() cpu_data[0].dcache.linesz +#endif +#ifndef cpu_icache_line_size +#define cpu_icache_line_size() cpu_data[0].icache.linesz +#endif +#ifndef cpu_scache_line_size +#define cpu_scache_line_size() cpu_data[0].scache.linesz +#endif + +#endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h new file mode 100644 index 00000000000..2de73dbb2e9 --- /dev/null +++ b/arch/mips/include/asm/cpu-info.h @@ -0,0 +1,84 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 Waldorf GMBH + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003 Ralf Baechle + * Copyright (C) 1996 Paul M. Antoine + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2004 Maciej W. Rozycki + */ +#ifndef __ASM_CPU_INFO_H +#define __ASM_CPU_INFO_H + +#include + +/* + * Descriptor for a cache + */ +struct cache_desc { + unsigned int waysize; /* Bytes per way */ + unsigned short sets; /* Number of lines per set */ + unsigned char ways; /* Number of ways */ + unsigned char linesz; /* Size of line in bytes */ + unsigned char waybit; /* Bits to select in a cache set */ + unsigned char flags; /* Flags describing cache properties */ +}; + +/* + * Flag definitions + */ +#define MIPS_CACHE_NOT_PRESENT 0x00000001 +#define MIPS_CACHE_VTAG 0x00000002 /* Virtually tagged cache */ +#define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */ +#define MIPS_CACHE_IC_F_DC 0x00000008 /* Ic can refill from D-cache */ +#define MIPS_IC_SNOOPS_REMOTE 0x00000010 /* Ic snoops remote stores */ +#define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */ + +struct cpuinfo_mips { + unsigned long udelay_val; + unsigned long asid_cache; + + /* + * Capability and feature descriptor structure for MIPS CPU + */ + unsigned long options; + unsigned long ases; + unsigned int processor_id; + unsigned int fpu_id; + unsigned int cputype; + int isa_level; + int tlbsize; + struct cache_desc icache; /* Primary I-cache */ + struct cache_desc dcache; /* Primary D or combined I/D cache */ + struct cache_desc scache; /* Secondary cache */ + struct cache_desc tcache; /* Tertiary/split secondary cache */ + int srsets; /* Shadow register sets */ + int core; /* physical core number */ +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) + /* + * In the MIPS MT "SMTC" model, each TC is considered + * to be a "CPU" for the purposes of scheduling, but + * exception resources, ASID spaces, etc, are common + * to all TCs within the same VPE. + */ + int vpe_id; /* Virtual Processor number */ +#endif +#ifdef CONFIG_MIPS_MT_SMTC + int tc_id; /* Thread Context number */ +#endif + void *data; /* Additional data */ +} __attribute__((aligned(SMP_CACHE_BYTES))); + +extern struct cpuinfo_mips cpu_data[]; +#define current_cpu_data cpu_data[smp_processor_id()] +#define raw_current_cpu_data cpu_data[raw_smp_processor_id()] + +extern void cpu_probe(void); +extern void cpu_report(void); + +extern const char *__cpu_name[]; +#define cpu_name_string() __cpu_name[smp_processor_id()] + +#endif /* __ASM_CPU_INFO_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h new file mode 100644 index 00000000000..229a786101d --- /dev/null +++ b/arch/mips/include/asm/cpu.h @@ -0,0 +1,267 @@ +/* + * cpu.h: Values of the PRId register used to match up + * various MIPS cpu types. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 2004 Maciej W. Rozycki + */ +#ifndef _ASM_CPU_H +#define _ASM_CPU_H + +/* Assigned Company values for bits 23:16 of the PRId Register + (CP0 register 15, select 0). As of the MIPS32 and MIPS64 specs from + MTI, the PRId register is defined in this (backwards compatible) + way: + + +----------------+----------------+----------------+----------------+ + | Company Options| Company ID | Processor ID | Revision | + +----------------+----------------+----------------+----------------+ + 31 24 23 16 15 8 7 + + I don't have docs for all the previous processors, but my impression is + that bits 16-23 have been 0 for all MIPS processors before the MIPS32/64 + spec. +*/ + +#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_MIPS 0x010000 +#define PRID_COMP_BROADCOM 0x020000 +#define PRID_COMP_ALCHEMY 0x030000 +#define PRID_COMP_SIBYTE 0x040000 +#define PRID_COMP_SANDCRAFT 0x050000 +#define PRID_COMP_NXP 0x060000 +#define PRID_COMP_TOSHIBA 0x070000 +#define PRID_COMP_LSI 0x080000 +#define PRID_COMP_LEXRA 0x0b0000 + + +/* + * Assigned values for the product ID register. In order to detect a + * certain CPU type exactly eventually additional registers may need to + * be examined. These are valid when 23:16 == PRID_COMP_LEGACY + */ +#define PRID_IMP_R2000 0x0100 +#define PRID_IMP_AU1_REV1 0x0100 +#define PRID_IMP_AU1_REV2 0x0200 +#define PRID_IMP_R3000 0x0200 /* Same as R2000A */ +#define PRID_IMP_R6000 0x0300 /* Same as R3000A */ +#define PRID_IMP_R4000 0x0400 +#define PRID_IMP_R6000A 0x0600 +#define PRID_IMP_R10000 0x0900 +#define PRID_IMP_R4300 0x0b00 +#define PRID_IMP_VR41XX 0x0c00 +#define PRID_IMP_R12000 0x0e00 +#define PRID_IMP_R14000 0x0f00 +#define PRID_IMP_R8000 0x1000 +#define PRID_IMP_PR4450 0x1200 +#define PRID_IMP_R4600 0x2000 +#define PRID_IMP_R4700 0x2100 +#define PRID_IMP_TX39 0x2200 +#define PRID_IMP_R4640 0x2200 +#define PRID_IMP_R4650 0x2200 /* Same as R4640 */ +#define PRID_IMP_R5000 0x2300 +#define PRID_IMP_TX49 0x2d00 +#define PRID_IMP_SONIC 0x2400 +#define PRID_IMP_MAGIC 0x2500 +#define PRID_IMP_RM7000 0x2700 +#define PRID_IMP_NEVADA 0x2800 /* RM5260 ??? */ +#define PRID_IMP_RM9000 0x3400 +#define PRID_IMP_LOONGSON1 0x4200 +#define PRID_IMP_R5432 0x5400 +#define PRID_IMP_R5500 0x5500 +#define PRID_IMP_LOONGSON2 0x6300 + +#define PRID_IMP_UNKNOWN 0xff00 + +/* + * These are the PRID's for when 23:16 == PRID_COMP_MIPS + */ + +#define PRID_IMP_4KC 0x8000 +#define PRID_IMP_5KC 0x8100 +#define PRID_IMP_20KC 0x8200 +#define PRID_IMP_4KEC 0x8400 +#define PRID_IMP_4KSC 0x8600 +#define PRID_IMP_25KF 0x8800 +#define PRID_IMP_5KE 0x8900 +#define PRID_IMP_4KECR2 0x9000 +#define PRID_IMP_4KEMPR2 0x9100 +#define PRID_IMP_4KSD 0x9200 +#define PRID_IMP_24K 0x9300 +#define PRID_IMP_34K 0x9500 +#define PRID_IMP_24KE 0x9600 +#define PRID_IMP_74K 0x9700 +#define PRID_IMP_1004K 0x9900 + +/* + * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE + */ + +#define PRID_IMP_SB1 0x0100 +#define PRID_IMP_SB1A 0x1100 + +/* + * These are the PRID's for when 23:16 == PRID_COMP_SANDCRAFT + */ + +#define PRID_IMP_SR71000 0x0400 + +/* + * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM + */ + +#define PRID_IMP_BCM4710 0x4000 +#define PRID_IMP_BCM3302 0x9000 + +/* + * Definitions for 7:0 on legacy processors + */ + +#define PRID_REV_MASK 0x00ff + +#define PRID_REV_TX4927 0x0022 +#define PRID_REV_TX4937 0x0030 +#define PRID_REV_R4400 0x0040 +#define PRID_REV_R3000A 0x0030 +#define PRID_REV_R3000 0x0020 +#define PRID_REV_R2000A 0x0010 +#define PRID_REV_TX3912 0x0010 +#define PRID_REV_TX3922 0x0030 +#define PRID_REV_TX3927 0x0040 +#define PRID_REV_VR4111 0x0050 +#define PRID_REV_VR4181 0x0050 /* Same as VR4111 */ +#define PRID_REV_VR4121 0x0060 +#define PRID_REV_VR4122 0x0070 +#define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */ +#define PRID_REV_VR4130 0x0080 +#define PRID_REV_34K_V1_0_2 0x0022 + +/* + * Older processors used to encode processor version and revision in two + * 4-bit bitfields, the 4K seems to simply count up and even newer MTI cores + * have switched to use the 8-bits as 3:3:2 bitfield with the last field as + * the patch number. *ARGH* + */ +#define PRID_REV_ENCODE_44(ver, rev) \ + ((ver) << 4 | (rev)) +#define PRID_REV_ENCODE_332(ver, rev, patch) \ + ((ver) << 5 | (rev) << 2 | (patch)) + +/* + * FPU implementation/revision register (CP1 control register 0). + * + * +---------------------------------+----------------+----------------+ + * | 0 | Implementation | Revision | + * +---------------------------------+----------------+----------------+ + * 31 16 15 8 7 0 + */ + +#define FPIR_IMP_NONE 0x0000 + +enum cpu_type_enum { + CPU_UNKNOWN, + + /* + * R2000 class processors + */ + CPU_R2000, CPU_R3000, CPU_R3000A, CPU_R3041, CPU_R3051, CPU_R3052, + CPU_R3081, CPU_R3081E, + + /* + * R6000 class processors + */ + CPU_R6000, CPU_R6000A, + + /* + * R4000 class processors + */ + CPU_R4000PC, CPU_R4000SC, CPU_R4000MC, CPU_R4200, CPU_R4300, CPU_R4310, + CPU_R4400PC, CPU_R4400SC, CPU_R4400MC, CPU_R4600, CPU_R4640, CPU_R4650, + CPU_R4700, CPU_R5000, CPU_R5000A, CPU_R5500, CPU_NEVADA, CPU_R5432, + CPU_R10000, CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, + CPU_VR4122, CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000, + CPU_SR71000, CPU_RM9000, CPU_TX49XX, + + /* + * R8000 class processors + */ + CPU_R8000, + + /* + * TX3900 class processors + */ + CPU_TX3912, CPU_TX3922, CPU_TX3927, + + /* + * MIPS32 class processors + */ + CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, + CPU_AU1000, CPU_AU1100, CPU_AU1200, CPU_AU1210, CPU_AU1250, CPU_AU1500, + CPU_AU1550, CPU_PR4450, CPU_BCM3302, CPU_BCM4710, + + /* + * MIPS64 class processors + */ + CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2, + + CPU_LAST +}; + + +/* + * ISA Level encodings + * + */ +#define MIPS_CPU_ISA_I 0x00000001 +#define MIPS_CPU_ISA_II 0x00000002 +#define MIPS_CPU_ISA_III 0x00000004 +#define MIPS_CPU_ISA_IV 0x00000008 +#define MIPS_CPU_ISA_V 0x00000010 +#define MIPS_CPU_ISA_M32R1 0x00000020 +#define MIPS_CPU_ISA_M32R2 0x00000040 +#define MIPS_CPU_ISA_M64R1 0x00000080 +#define MIPS_CPU_ISA_M64R2 0x00000100 + +#define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_I | MIPS_CPU_ISA_II | \ + MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 ) +#define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \ + MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2) + +/* + * CPU Option encodings + */ +#define MIPS_CPU_TLB 0x00000001 /* CPU has TLB */ +#define MIPS_CPU_4KEX 0x00000002 /* "R4K" exception model */ +#define MIPS_CPU_3K_CACHE 0x00000004 /* R3000-style caches */ +#define MIPS_CPU_4K_CACHE 0x00000008 /* R4000-style caches */ +#define MIPS_CPU_TX39_CACHE 0x00000010 /* TX3900-style caches */ +#define MIPS_CPU_FPU 0x00000020 /* CPU has FPU */ +#define MIPS_CPU_32FPR 0x00000040 /* 32 dbl. prec. FP registers */ +#define MIPS_CPU_COUNTER 0x00000080 /* Cycle count/compare */ +#define MIPS_CPU_WATCH 0x00000100 /* watchpoint registers */ +#define MIPS_CPU_DIVEC 0x00000200 /* dedicated interrupt vector */ +#define MIPS_CPU_VCE 0x00000400 /* virt. coherence conflict possible */ +#define MIPS_CPU_CACHE_CDEX_P 0x00000800 /* Create_Dirty_Exclusive CACHE op */ +#define MIPS_CPU_CACHE_CDEX_S 0x00001000 /* ... same for seconary cache ... */ +#define MIPS_CPU_MCHECK 0x00002000 /* Machine check exception */ +#define MIPS_CPU_EJTAG 0x00004000 /* EJTAG exception */ +#define MIPS_CPU_NOFPUEX 0x00008000 /* no FPU exception */ +#define MIPS_CPU_LLSC 0x00010000 /* CPU has ll/sc instructions */ +#define MIPS_CPU_INCLUSIVE_CACHES 0x00020000 /* P-cache subset enforced */ +#define MIPS_CPU_PREFETCH 0x00040000 /* CPU has usable prefetch */ +#define MIPS_CPU_VINT 0x00080000 /* CPU supports MIPSR2 vectored interrupts */ +#define MIPS_CPU_VEIC 0x00100000 /* CPU supports MIPSR2 external interrupt controller mode */ +#define MIPS_CPU_ULRI 0x00200000 /* CPU has ULRI feature */ + +/* + * CPU ASE encodings + */ +#define MIPS_ASE_MIPS16 0x00000001 /* code compression */ +#define MIPS_ASE_MDMX 0x00000002 /* MIPS digital media extension */ +#define MIPS_ASE_MIPS3D 0x00000004 /* MIPS-3D */ +#define MIPS_ASE_SMARTMIPS 0x00000008 /* SmartMIPS */ +#define MIPS_ASE_DSP 0x00000010 /* Signal Processing ASE */ +#define MIPS_ASE_MIPSMT 0x00000020 /* CPU supports MIPS MT */ + + +#endif /* _ASM_CPU_H */ diff --git a/arch/mips/include/asm/cputime.h b/arch/mips/include/asm/cputime.h new file mode 100644 index 00000000000..c00eacbdd97 --- /dev/null +++ b/arch/mips/include/asm/cputime.h @@ -0,0 +1,6 @@ +#ifndef __MIPS_CPUTIME_H +#define __MIPS_CPUTIME_H + +#include + +#endif /* __MIPS_CPUTIME_H */ diff --git a/arch/mips/include/asm/current.h b/arch/mips/include/asm/current.h new file mode 100644 index 00000000000..559db66b979 --- /dev/null +++ b/arch/mips/include/asm/current.h @@ -0,0 +1,23 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2002 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_CURRENT_H +#define _ASM_CURRENT_H + +#include + +struct task_struct; + +static inline struct task_struct * get_current(void) +{ + return current_thread_info()->task; +} + +#define current get_current() + +#endif /* _ASM_CURRENT_H */ diff --git a/arch/mips/include/asm/debug.h b/arch/mips/include/asm/debug.h new file mode 100644 index 00000000000..1fd5a2b3944 --- /dev/null +++ b/arch/mips/include/asm/debug.h @@ -0,0 +1,48 @@ +/* + * Debug macros for run-time debugging. + * Turned on/off with CONFIG_RUNTIME_DEBUG option. + * + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * 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. + * + */ + +#ifndef _ASM_DEBUG_H +#define _ASM_DEBUG_H + + +/* + * run-time macros for catching spurious errors. Eable CONFIG_RUNTIME_DEBUG in + * kernel hacking config menu to use them. + * + * Use them as run-time debugging aid. NEVER USE THEM AS ERROR HANDLING CODE!!! + */ + +#ifdef CONFIG_RUNTIME_DEBUG + +#include + +#define db_assert(x) if (!(x)) { \ + panic("assertion failed at %s:%d: %s", __FILE__, __LINE__, #x); } +#define db_warn(x) if (!(x)) { \ + printk(KERN_WARNING "warning at %s:%d: %s", __FILE__, __LINE__, #x); } +#define db_verify(x, y) db_assert(x y) +#define db_verify_warn(x, y) db_warn(x y) +#define db_run(x) do { x; } while (0) + +#else + +#define db_assert(x) +#define db_warn(x) +#define db_verify(x, y) x +#define db_verify_warn(x, y) x +#define db_run(x) + +#endif + +#endif /* _ASM_DEBUG_H */ diff --git a/arch/mips/include/asm/dec/ecc.h b/arch/mips/include/asm/dec/ecc.h new file mode 100644 index 00000000000..707ffdbc9ad --- /dev/null +++ b/arch/mips/include/asm/dec/ecc.h @@ -0,0 +1,55 @@ +/* + * include/asm-mips/dec/ecc.h + * + * ECC handling logic definitions common to DECstation/DECsystem + * 5000/200 (KN02), 5000/240 (KN03), 5000/260 (KN05) and + * DECsystem 5900 (KN03), 5900/260 (KN05) systems. + * + * Copyright (C) 2003 Maciej W. Rozycki + * + * 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. + */ +#ifndef __ASM_MIPS_DEC_ECC_H +#define __ASM_MIPS_DEC_ECC_H + +/* + * Error Address Register bits. + * The register is r/wc -- any write clears it. + */ +#define KN0X_EAR_VALID (1<<31) /* error data valid, bus IRQ */ +#define KN0X_EAR_CPU (1<<30) /* CPU/DMA transaction */ +#define KN0X_EAR_WRITE (1<<29) /* write/read transaction */ +#define KN0X_EAR_ECCERR (1<<28) /* ECC/timeout or overrun */ +#define KN0X_EAR_RES_27 (1<<27) /* unused */ +#define KN0X_EAR_ADDRESS (0x7ffffff<<0) /* address involved */ + +/* + * Error Syndrome Register bits. + * The register is frozen when EAR.VALID is set, otherwise it records bits + * from the last memory read. The register is r/wc -- any write clears it. + */ +#define KN0X_ESR_VLDHI (1<<31) /* error data valid hi word */ +#define KN0X_ESR_CHKHI (0x7f<<24) /* check bits read from mem */ +#define KN0X_ESR_SNGHI (1<<23) /* single/double bit error */ +#define KN0X_ESR_SYNHI (0x7f<<16) /* syndrome from ECC logic */ +#define KN0X_ESR_VLDLO (1<<15) /* error data valid lo word */ +#define KN0X_ESR_CHKLO (0x7f<<8) /* check bits read from mem */ +#define KN0X_ESR_SNGLO (1<<7) /* single/double bit error */ +#define KN0X_ESR_SYNLO (0x7f<<0) /* syndrome from ECC logic */ + + +#ifndef __ASSEMBLY__ + +#include + +struct pt_regs; + +extern void dec_ecc_be_init(void); +extern int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup); +extern irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id); +#endif + +#endif /* __ASM_MIPS_DEC_ECC_H */ diff --git a/arch/mips/include/asm/dec/interrupts.h b/arch/mips/include/asm/dec/interrupts.h new file mode 100644 index 00000000000..e10d341067c --- /dev/null +++ b/arch/mips/include/asm/dec/interrupts.h @@ -0,0 +1,126 @@ +/* + * Miscellaneous definitions used to initialise the interrupt vector table + * with the machine-specific interrupt routines. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997 by Paul M. Antoine. + * reworked 1998 by Harald Koerfgen. + * Copyright (C) 2001, 2002, 2003 Maciej W. Rozycki + */ + +#ifndef __ASM_DEC_INTERRUPTS_H +#define __ASM_DEC_INTERRUPTS_H + +#include +#include + + +/* + * The list of possible system devices which provide an + * interrupt. Not all devices exist on a given system. + */ +#define DEC_IRQ_CASCADE 0 /* cascade from CSR or I/O ASIC */ + +/* Ordinary interrupts */ +#define DEC_IRQ_AB_RECV 1 /* ACCESS.bus receive */ +#define DEC_IRQ_AB_XMIT 2 /* ACCESS.bus transmit */ +#define DEC_IRQ_DZ11 3 /* DZ11 (DC7085) serial */ +#define DEC_IRQ_ASC 4 /* ASC (NCR53C94) SCSI */ +#define DEC_IRQ_FLOPPY 5 /* 82077 FDC */ +#define DEC_IRQ_FPU 6 /* R3k FPU */ +#define DEC_IRQ_HALT 7 /* HALT button or from ACCESS.Bus */ +#define DEC_IRQ_ISDN 8 /* Am79C30A ISDN */ +#define DEC_IRQ_LANCE 9 /* LANCE (Am7990) Ethernet */ +#define DEC_IRQ_BUS 10 /* memory, I/O bus read/write errors */ +#define DEC_IRQ_PSU 11 /* power supply unit warning */ +#define DEC_IRQ_RTC 12 /* DS1287 RTC */ +#define DEC_IRQ_SCC0 13 /* SCC (Z85C30) serial #0 */ +#define DEC_IRQ_SCC1 14 /* SCC (Z85C30) serial #1 */ +#define DEC_IRQ_SII 15 /* SII (DC7061) SCSI */ +#define DEC_IRQ_TC0 16 /* TURBOchannel slot #0 */ +#define DEC_IRQ_TC1 17 /* TURBOchannel slot #1 */ +#define DEC_IRQ_TC2 18 /* TURBOchannel slot #2 */ +#define DEC_IRQ_TIMER 19 /* ARC periodic timer */ +#define DEC_IRQ_VIDEO 20 /* framebuffer */ + +/* I/O ASIC DMA interrupts */ +#define DEC_IRQ_ASC_MERR 21 /* ASC memory read error */ +#define DEC_IRQ_ASC_ERR 22 /* ASC page overrun */ +#define DEC_IRQ_ASC_DMA 23 /* ASC buffer pointer loaded */ +#define DEC_IRQ_FLOPPY_ERR 24 /* FDC error */ +#define DEC_IRQ_ISDN_ERR 25 /* ISDN memory read/overrun error */ +#define DEC_IRQ_ISDN_RXDMA 26 /* ISDN recv buffer pointer loaded */ +#define DEC_IRQ_ISDN_TXDMA 27 /* ISDN xmit buffer pointer loaded */ +#define DEC_IRQ_LANCE_MERR 28 /* LANCE memory read error */ +#define DEC_IRQ_SCC0A_RXERR 29 /* SCC0A (printer) receive overrun */ +#define DEC_IRQ_SCC0A_RXDMA 30 /* SCC0A receive half page */ +#define DEC_IRQ_SCC0A_TXERR 31 /* SCC0A xmit memory read/overrun */ +#define DEC_IRQ_SCC0A_TXDMA 32 /* SCC0A transmit page end */ +#define DEC_IRQ_AB_RXERR 33 /* ACCESS.bus receive overrun */ +#define DEC_IRQ_AB_RXDMA 34 /* ACCESS.bus receive half page */ +#define DEC_IRQ_AB_TXERR 35 /* ACCESS.bus xmit memory read/ovrn */ +#define DEC_IRQ_AB_TXDMA 36 /* ACCESS.bus transmit page end */ +#define DEC_IRQ_SCC1A_RXERR 37 /* SCC1A (modem) receive overrun */ +#define DEC_IRQ_SCC1A_RXDMA 38 /* SCC1A receive half page */ +#define DEC_IRQ_SCC1A_TXERR 39 /* SCC1A xmit memory read/overrun */ +#define DEC_IRQ_SCC1A_TXDMA 40 /* SCC1A transmit page end */ + +/* TC5 & TC6 are virtual slots for KN02's onboard devices */ +#define DEC_IRQ_TC5 DEC_IRQ_ASC /* virtual PMAZ-AA */ +#define DEC_IRQ_TC6 DEC_IRQ_LANCE /* virtual PMAD-AA */ + +#define DEC_NR_INTS 41 + + +/* Largest of cpu mask_nr tables. */ +#define DEC_MAX_CPU_INTS 6 +/* Largest of asic mask_nr tables. */ +#define DEC_MAX_ASIC_INTS 9 + + +/* + * CPU interrupt bits common to all systems. + */ +#define DEC_CPU_INR_FPU 7 /* R3k FPU */ +#define DEC_CPU_INR_SW1 1 /* software #1 */ +#define DEC_CPU_INR_SW0 0 /* software #0 */ + +#define DEC_CPU_IRQ_BASE MIPS_CPU_IRQ_BASE /* first IRQ assigned to CPU */ + +#define DEC_CPU_IRQ_NR(n) ((n) + DEC_CPU_IRQ_BASE) +#define DEC_CPU_IRQ_MASK(n) (1 << ((n) + CAUSEB_IP)) +#define DEC_CPU_IRQ_ALL (0xff << CAUSEB_IP) + + +#ifndef __ASSEMBLY__ + +/* + * Interrupt table structures to hide differences between systems. + */ +typedef union { int i; void *p; } int_ptr; +extern int dec_interrupt[DEC_NR_INTS]; +extern int_ptr cpu_mask_nr_tbl[DEC_MAX_CPU_INTS][2]; +extern int_ptr asic_mask_nr_tbl[DEC_MAX_ASIC_INTS][2]; +extern int cpu_fpu_mask; + + +/* + * Common interrupt routine prototypes for all DECStations + */ +extern void kn02_io_int(void); +extern void kn02xa_io_int(void); +extern void kn03_io_int(void); +extern void asic_dma_int(void); +extern void asic_all_int(void); +extern void kn02_all_int(void); +extern void cpu_all_int(void); + +extern void dec_intr_unimplemented(void); +extern void asic_intr_unimplemented(void); + +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/arch/mips/include/asm/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h new file mode 100644 index 00000000000..98badd6bf22 --- /dev/null +++ b/arch/mips/include/asm/dec/ioasic.h @@ -0,0 +1,38 @@ +/* + * include/asm-mips/dec/ioasic.h + * + * DEC I/O ASIC access operations. + * + * Copyright (C) 2000, 2002, 2003 Maciej W. Rozycki + * + * 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. + */ + +#ifndef __ASM_DEC_IOASIC_H +#define __ASM_DEC_IOASIC_H + +#include +#include + +extern spinlock_t ioasic_ssr_lock; + +extern volatile u32 *ioasic_base; + +static inline void ioasic_write(unsigned int reg, u32 v) +{ + ioasic_base[reg / 4] = v; +} + +static inline u32 ioasic_read(unsigned int reg) +{ + return ioasic_base[reg / 4]; +} + +extern void init_ioasic_irqs(int base); + +extern void dec_ioasic_clocksource_init(void); + +#endif /* __ASM_DEC_IOASIC_H */ diff --git a/arch/mips/include/asm/dec/ioasic_addrs.h b/arch/mips/include/asm/dec/ioasic_addrs.h new file mode 100644 index 00000000000..4cbc1f8a112 --- /dev/null +++ b/arch/mips/include/asm/dec/ioasic_addrs.h @@ -0,0 +1,152 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Definitions for the address map in the JUNKIO Asic + * + * Created with Information from: + * + * "DEC 3000 300/400/500/600/700/800/900 AXP Models System Programmer's Manual" + * + * and the Mach Sources + * + * Copyright (C) 199x the Anonymous + * Copyright (C) 2002, 2003 Maciej W. Rozycki + */ + +#ifndef __ASM_MIPS_DEC_IOASIC_ADDRS_H +#define __ASM_MIPS_DEC_IOASIC_ADDRS_H + +#define IOASIC_SLOT_SIZE 0x00040000 + +/* + * Address ranges decoded by the I/O ASIC for onboard devices. + */ +#define IOASIC_SYS_ROM (0*IOASIC_SLOT_SIZE) /* system board ROM */ +#define IOASIC_IOCTL (1*IOASIC_SLOT_SIZE) /* I/O ASIC */ +#define IOASIC_ESAR (2*IOASIC_SLOT_SIZE) /* LANCE MAC address chip */ +#define IOASIC_LANCE (3*IOASIC_SLOT_SIZE) /* LANCE Ethernet */ +#define IOASIC_SCC0 (4*IOASIC_SLOT_SIZE) /* SCC #0 */ +#define IOASIC_VDAC_HI (5*IOASIC_SLOT_SIZE) /* VDAC (maxine) */ +#define IOASIC_SCC1 (6*IOASIC_SLOT_SIZE) /* SCC #1 (3min, 3max+) */ +#define IOASIC_VDAC_LO (7*IOASIC_SLOT_SIZE) /* VDAC (maxine) */ +#define IOASIC_TOY (8*IOASIC_SLOT_SIZE) /* RTC */ +#define IOASIC_ISDN (9*IOASIC_SLOT_SIZE) /* ISDN (maxine) */ +#define IOASIC_ERRADDR (9*IOASIC_SLOT_SIZE) /* bus error address (3max+) */ +#define IOASIC_CHKSYN (10*IOASIC_SLOT_SIZE) /* ECC syndrome (3max+) */ +#define IOASIC_ACC_BUS (10*IOASIC_SLOT_SIZE) /* ACCESS.bus (maxine) */ +#define IOASIC_MCR (11*IOASIC_SLOT_SIZE) /* memory control (3max+) */ +#define IOASIC_FLOPPY (11*IOASIC_SLOT_SIZE) /* FDC (maxine) */ +#define IOASIC_SCSI (12*IOASIC_SLOT_SIZE) /* ASC SCSI */ +#define IOASIC_FDC_DMA (13*IOASIC_SLOT_SIZE) /* FDC DMA (maxine) */ +#define IOASIC_SCSI_DMA (14*IOASIC_SLOT_SIZE) /* ??? */ +#define IOASIC_RES_15 (15*IOASIC_SLOT_SIZE) /* unused? */ + + +/* + * Offsets for I/O ASIC registers + * (relative to (dec_kn_slot_base + IOASIC_IOCTL)). + */ + /* all systems */ +#define IO_REG_SCSI_DMA_P 0x00 /* SCSI DMA Pointer */ +#define IO_REG_SCSI_DMA_BP 0x10 /* SCSI DMA Buffer Pointer */ +#define IO_REG_LANCE_DMA_P 0x20 /* LANCE DMA Pointer */ +#define IO_REG_SCC0A_T_DMA_P 0x30 /* SCC0A Transmit DMA Pointer */ +#define IO_REG_SCC0A_R_DMA_P 0x40 /* SCC0A Receive DMA Pointer */ + + /* except Maxine */ +#define IO_REG_SCC1A_T_DMA_P 0x50 /* SCC1A Transmit DMA Pointer */ +#define IO_REG_SCC1A_R_DMA_P 0x60 /* SCC1A Receive DMA Pointer */ + + /* Maxine */ +#define IO_REG_AB_T_DMA_P 0x50 /* ACCESS.bus Transmit DMA Pointer */ +#define IO_REG_AB_R_DMA_P 0x60 /* ACCESS.bus Receive DMA Pointer */ +#define IO_REG_FLOPPY_DMA_P 0x70 /* Floppy DMA Pointer */ +#define IO_REG_ISDN_T_DMA_P 0x80 /* ISDN Transmit DMA Pointer */ +#define IO_REG_ISDN_T_DMA_BP 0x90 /* ISDN Transmit DMA Buffer Pointer */ +#define IO_REG_ISDN_R_DMA_P 0xa0 /* ISDN Receive DMA Pointer */ +#define IO_REG_ISDN_R_DMA_BP 0xb0 /* ISDN Receive DMA Buffer Pointer */ + + /* all systems */ +#define IO_REG_DATA_0 0xc0 /* System Data Buffer 0 */ +#define IO_REG_DATA_1 0xd0 /* System Data Buffer 1 */ +#define IO_REG_DATA_2 0xe0 /* System Data Buffer 2 */ +#define IO_REG_DATA_3 0xf0 /* System Data Buffer 3 */ + + /* all systems */ +#define IO_REG_SSR 0x100 /* System Support Register */ +#define IO_REG_SIR 0x110 /* System Interrupt Register */ +#define IO_REG_SIMR 0x120 /* System Interrupt Mask Reg. */ +#define IO_REG_SAR 0x130 /* System Address Register */ + + /* Maxine */ +#define IO_REG_ISDN_T_DATA 0x140 /* ISDN Xmit Data Register */ +#define IO_REG_ISDN_R_DATA 0x150 /* ISDN Receive Data Register */ + + /* all systems */ +#define IO_REG_LANCE_SLOT 0x160 /* LANCE I/O Slot Register */ +#define IO_REG_SCSI_SLOT 0x170 /* SCSI Slot Register */ +#define IO_REG_SCC0A_SLOT 0x180 /* SCC0A DMA Slot Register */ + + /* except Maxine */ +#define IO_REG_SCC1A_SLOT 0x190 /* SCC1A DMA Slot Register */ + + /* Maxine */ +#define IO_REG_AB_SLOT 0x190 /* ACCESS.bus DMA Slot Register */ +#define IO_REG_FLOPPY_SLOT 0x1a0 /* Floppy Slot Register */ + + /* all systems */ +#define IO_REG_SCSI_SCR 0x1b0 /* SCSI Partial-Word DMA Control */ +#define IO_REG_SCSI_SDR0 0x1c0 /* SCSI DMA Partial Word 0 */ +#define IO_REG_SCSI_SDR1 0x1d0 /* SCSI DMA Partial Word 1 */ +#define IO_REG_FCTR 0x1e0 /* Free-Running Counter */ +#define IO_REG_RES_31 0x1f0 /* unused */ + + +/* + * The upper 16 bits of the System Support Register are a part of the + * I/O ASIC's internal DMA engine and thus are common to all I/O ASIC + * machines. The exception is the Maxine, which makes use of the + * FLOPPY and ISDN bits (otherwise unused) and has a different SCC + * wiring. + */ + /* all systems */ +#define IO_SSR_SCC0A_TX_DMA_EN (1<<31) /* SCC0A transmit DMA enable */ +#define IO_SSR_SCC0A_RX_DMA_EN (1<<30) /* SCC0A receive DMA enable */ +#define IO_SSR_RES_27 (1<<27) /* unused */ +#define IO_SSR_RES_26 (1<<26) /* unused */ +#define IO_SSR_RES_25 (1<<25) /* unused */ +#define IO_SSR_RES_24 (1<<24) /* unused */ +#define IO_SSR_RES_23 (1<<23) /* unused */ +#define IO_SSR_SCSI_DMA_DIR (1<<18) /* SCSI DMA direction */ +#define IO_SSR_SCSI_DMA_EN (1<<17) /* SCSI DMA enable */ +#define IO_SSR_LANCE_DMA_EN (1<<16) /* LANCE DMA enable */ + + /* except Maxine */ +#define IO_SSR_SCC1A_TX_DMA_EN (1<<29) /* SCC1A transmit DMA enable */ +#define IO_SSR_SCC1A_RX_DMA_EN (1<<28) /* SCC1A receive DMA enable */ +#define IO_SSR_RES_22 (1<<22) /* unused */ +#define IO_SSR_RES_21 (1<<21) /* unused */ +#define IO_SSR_RES_20 (1<<20) /* unused */ +#define IO_SSR_RES_19 (1<<19) /* unused */ + + /* Maxine */ +#define IO_SSR_AB_TX_DMA_EN (1<<29) /* ACCESS.bus xmit DMA enable */ +#define IO_SSR_AB_RX_DMA_EN (1<<28) /* ACCESS.bus recv DMA enable */ +#define IO_SSR_FLOPPY_DMA_DIR (1<<22) /* Floppy DMA direction */ +#define IO_SSR_FLOPPY_DMA_EN (1<<21) /* Floppy DMA enable */ +#define IO_SSR_ISDN_TX_DMA_EN (1<<20) /* ISDN transmit DMA enable */ +#define IO_SSR_ISDN_RX_DMA_EN (1<<19) /* ISDN receive DMA enable */ + +/* + * The lower 16 bits are system-specific. Bits 15,11:8 are common and + * defined here. The rest is defined in system-specific headers. + */ +#define KN0X_IO_SSR_DIAGDN (1<<15) /* diagnostic jumper */ +#define KN0X_IO_SSR_SCC_RST (1<<11) /* ~SCC0,1 (Z85C30) reset */ +#define KN0X_IO_SSR_RTC_RST (1<<10) /* ~RTC (DS1287) reset */ +#define KN0X_IO_SSR_ASC_RST (1<<9) /* ~ASC (NCR53C94) reset */ +#define KN0X_IO_SSR_LANCE_RST (1<<8) /* ~LANCE (Am7990) reset */ + +#endif /* __ASM_MIPS_DEC_IOASIC_ADDRS_H */ diff --git a/arch/mips/include/asm/dec/ioasic_ints.h b/arch/mips/include/asm/dec/ioasic_ints.h new file mode 100644 index 00000000000..9aaa9869615 --- /dev/null +++ b/arch/mips/include/asm/dec/ioasic_ints.h @@ -0,0 +1,74 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Definitions for the interrupt related bits in the I/O ASIC + * interrupt status register (and the interrupt mask register, of course) + * + * Created with Information from: + * + * "DEC 3000 300/400/500/600/700/800/900 AXP Models System Programmer's Manual" + * + * and the Mach Sources + * + * Copyright (C) 199x the Anonymous + * Copyright (C) 2002 Maciej W. Rozycki + */ + +#ifndef __ASM_DEC_IOASIC_INTS_H +#define __ASM_DEC_IOASIC_INTS_H + +/* + * The upper 16 bits are a part of the I/O ASIC's internal DMA engine + * and thus are common to all I/O ASIC machines. The exception is + * the Maxine, which makes use of the FLOPPY and ISDN bits (otherwise + * unused) and has a different SCC wiring. + */ + /* all systems */ +#define IO_INR_SCC0A_TXDMA 31 /* SCC0A transmit page end */ +#define IO_INR_SCC0A_TXERR 30 /* SCC0A transmit memory read error */ +#define IO_INR_SCC0A_RXDMA 29 /* SCC0A receive half page */ +#define IO_INR_SCC0A_RXERR 28 /* SCC0A receive overrun */ +#define IO_INR_ASC_DMA 19 /* ASC buffer pointer loaded */ +#define IO_INR_ASC_ERR 18 /* ASC page overrun */ +#define IO_INR_ASC_MERR 17 /* ASC memory read error */ +#define IO_INR_LANCE_MERR 16 /* LANCE memory read error */ + + /* except Maxine */ +#define IO_INR_SCC1A_TXDMA 27 /* SCC1A transmit page end */ +#define IO_INR_SCC1A_TXERR 26 /* SCC1A transmit memory read error */ +#define IO_INR_SCC1A_RXDMA 25 /* SCC1A receive half page */ +#define IO_INR_SCC1A_RXERR 24 /* SCC1A receive overrun */ +#define IO_INR_RES_23 23 /* unused */ +#define IO_INR_RES_22 22 /* unused */ +#define IO_INR_RES_21 21 /* unused */ +#define IO_INR_RES_20 20 /* unused */ + + /* Maxine */ +#define IO_INR_AB_TXDMA 27 /* ACCESS.bus transmit page end */ +#define IO_INR_AB_TXERR 26 /* ACCESS.bus xmit memory read error */ +#define IO_INR_AB_RXDMA 25 /* ACCESS.bus receive half page */ +#define IO_INR_AB_RXERR 24 /* ACCESS.bus receive overrun */ +#define IO_INR_FLOPPY_ERR 23 /* FDC error */ +#define IO_INR_ISDN_TXDMA 22 /* ISDN xmit buffer pointer loaded */ +#define IO_INR_ISDN_RXDMA 21 /* ISDN recv buffer pointer loaded */ +#define IO_INR_ISDN_ERR 20 /* ISDN memory read/overrun error */ + +#define IO_INR_DMA 16 /* first DMA IRQ */ + +/* + * The lower 16 bits are system-specific and thus defined in + * system-specific headers. + */ + + +#define IO_IRQ_BASE 8 /* first IRQ assigned to I/O ASIC */ +#define IO_IRQ_LINES 32 /* number of I/O ASIC interrupts */ + +#define IO_IRQ_NR(n) ((n) + IO_IRQ_BASE) +#define IO_IRQ_MASK(n) (1 << (n)) +#define IO_IRQ_ALL 0x0000ffff +#define IO_IRQ_DMA 0xffff0000 + +#endif /* __ASM_DEC_IOASIC_INTS_H */ diff --git a/arch/mips/include/asm/dec/kn01.h b/arch/mips/include/asm/dec/kn01.h new file mode 100644 index 00000000000..28fa717ac42 --- /dev/null +++ b/arch/mips/include/asm/dec/kn01.h @@ -0,0 +1,90 @@ +/* + * Hardware info about DECstation DS2100/3100 systems (otherwise known as + * pmin/pmax or KN01). + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions + * are by courtesy of Chris Fraser. + * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki + */ +#ifndef __ASM_MIPS_DEC_KN01_H +#define __ASM_MIPS_DEC_KN01_H + +#define KN01_SLOT_BASE 0x10000000 +#define KN01_SLOT_SIZE 0x01000000 + +/* + * Address ranges for devices. + */ +#define KN01_PMASK (0*KN01_SLOT_SIZE) /* color plane mask */ +#define KN01_PCC (1*KN01_SLOT_SIZE) /* PCC (DC503) cursor */ +#define KN01_VDAC (2*KN01_SLOT_SIZE) /* color map */ +#define KN01_RES_3 (3*KN01_SLOT_SIZE) /* unused */ +#define KN01_RES_4 (4*KN01_SLOT_SIZE) /* unused */ +#define KN01_RES_5 (5*KN01_SLOT_SIZE) /* unused */ +#define KN01_RES_6 (6*KN01_SLOT_SIZE) /* unused */ +#define KN01_ERRADDR (7*KN01_SLOT_SIZE) /* write error address */ +#define KN01_LANCE (8*KN01_SLOT_SIZE) /* LANCE (Am7990) Ethernet */ +#define KN01_LANCE_MEM (9*KN01_SLOT_SIZE) /* LANCE buffer memory */ +#define KN01_SII (10*KN01_SLOT_SIZE) /* SII (DC7061) SCSI */ +#define KN01_SII_MEM (11*KN01_SLOT_SIZE) /* SII buffer memory */ +#define KN01_DZ11 (12*KN01_SLOT_SIZE) /* DZ11 (DC7085) serial */ +#define KN01_RTC (13*KN01_SLOT_SIZE) /* DS1287 RTC (bytes #0) */ +#define KN01_ESAR (13*KN01_SLOT_SIZE) /* MAC address (bytes #1) */ +#define KN01_CSR (14*KN01_SLOT_SIZE) /* system ctrl & status reg */ +#define KN01_SYS_ROM (15*KN01_SLOT_SIZE) /* system board ROM */ + + +/* + * Frame buffer memory address. + */ +#define KN01_VFB_MEM 0x0fc00000 + +/* + * CPU interrupt bits. + */ +#define KN01_CPU_INR_BUS 6 /* memory, I/O bus read/write errors */ +#define KN01_CPU_INR_VIDEO 6 /* PCC area detect #2 */ +#define KN01_CPU_INR_RTC 5 /* DS1287 RTC */ +#define KN01_CPU_INR_DZ11 4 /* DZ11 (DC7085) serial */ +#define KN01_CPU_INR_LANCE 3 /* LANCE (Am7990) Ethernet */ +#define KN01_CPU_INR_SII 2 /* SII (DC7061) SCSI */ + + +/* + * System Control & Status Register bits. + */ +#define KN01_CSR_MNFMOD (1<<15) /* MNFMOD manufacturing jumper */ +#define KN01_CSR_STATUS (1<<14) /* self-test result status output */ +#define KN01_CSR_PARDIS (1<<13) /* parity error disable */ +#define KN01_CSR_CRSRTST (1<<12) /* PCC test output */ +#define KN01_CSR_MONO (1<<11) /* mono/color fb SIMM installed */ +#define KN01_CSR_MEMERR (1<<10) /* write timeout error status & ack*/ +#define KN01_CSR_VINT (1<<9) /* PCC area detect #2 status & ack */ +#define KN01_CSR_TXDIS (1<<8) /* DZ11 transmit disable */ +#define KN01_CSR_VBGTRG (1<<2) /* blue DAC voltage over green (r/o) */ +#define KN01_CSR_VRGTRG (1<<1) /* red DAC voltage over green (r/o) */ +#define KN01_CSR_VRGTRB (1<<0) /* red DAC voltage over blue (r/o) */ +#define KN01_CSR_LEDS (0xff<<0) /* ~diagnostic LEDs (w/o) */ + + +#ifndef __ASSEMBLY__ + +#include +#include +#include + +struct pt_regs; + +extern u16 cached_kn01_csr; +extern spinlock_t kn01_lock; + +extern void dec_kn01_be_init(void); +extern int dec_kn01_be_handler(struct pt_regs *regs, int is_fixup); +extern irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id); +#endif + +#endif /* __ASM_MIPS_DEC_KN01_H */ diff --git a/arch/mips/include/asm/dec/kn02.h b/arch/mips/include/asm/dec/kn02.h new file mode 100644 index 00000000000..93430b5f472 --- /dev/null +++ b/arch/mips/include/asm/dec/kn02.h @@ -0,0 +1,91 @@ +/* + * Hardware info about DECstation 5000/200 systems (otherwise known as + * 3max or KN02). + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions + * are by courtesy of Chris Fraser. + * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki + */ +#ifndef __ASM_MIPS_DEC_KN02_H +#define __ASM_MIPS_DEC_KN02_H + +#define KN02_SLOT_BASE 0x1fc00000 +#define KN02_SLOT_SIZE 0x00080000 + +/* + * Address ranges decoded by the "system slot" logic for onboard devices. + */ +#define KN02_SYS_ROM (0*KN02_SLOT_SIZE) /* system board ROM */ +#define KN02_RES_1 (1*KN02_SLOT_SIZE) /* unused */ +#define KN02_CHKSYN (2*KN02_SLOT_SIZE) /* ECC syndrome */ +#define KN02_ERRADDR (3*KN02_SLOT_SIZE) /* bus error address */ +#define KN02_DZ11 (4*KN02_SLOT_SIZE) /* DZ11 (DC7085) serial */ +#define KN02_RTC (5*KN02_SLOT_SIZE) /* DS1287 RTC */ +#define KN02_CSR (6*KN02_SLOT_SIZE) /* system ctrl & status reg */ +#define KN02_SYS_ROM_7 (7*KN02_SLOT_SIZE) /* system board ROM (alias) */ + + +/* + * System Control & Status Register bits. + */ +#define KN02_CSR_RES_28 (0xf<<28) /* unused */ +#define KN02_CSR_PSU (1<<27) /* power supply unit warning */ +#define KN02_CSR_NVRAM (1<<26) /* ~NVRAM clear jumper */ +#define KN02_CSR_REFEVEN (1<<25) /* mem refresh bank toggle */ +#define KN02_CSR_NRMOD (1<<24) /* ~NRMOD manufact. jumper */ +#define KN02_CSR_IOINTEN (0xff<<16) /* IRQ mask bits */ +#define KN02_CSR_DIAGCHK (1<<15) /* diagn/norml ECC reads */ +#define KN02_CSR_DIAGGEN (1<<14) /* diagn/norml ECC writes */ +#define KN02_CSR_CORRECT (1<<13) /* ECC correct/check */ +#define KN02_CSR_LEDIAG (1<<12) /* ECC diagn. latch strobe */ +#define KN02_CSR_TXDIS (1<<11) /* DZ11 transmit disable */ +#define KN02_CSR_BNK32M (1<<10) /* 32M/8M stride */ +#define KN02_CSR_DIAGDN (1<<9) /* DIAGDN manufact. jumper */ +#define KN02_CSR_BAUD38 (1<<8) /* DZ11 38/19kbps ext. rate */ +#define KN02_CSR_IOINT (0xff<<0) /* IRQ status bits (r/o) */ +#define KN02_CSR_LEDS (0xff<<0) /* ~diagnostic LEDs (w/o) */ + + +/* + * CPU interrupt bits. + */ +#define KN02_CPU_INR_RES_6 6 /* unused */ +#define KN02_CPU_INR_BUS 5 /* memory, I/O bus read/write errors */ +#define KN02_CPU_INR_RES_4 4 /* unused */ +#define KN02_CPU_INR_RTC 3 /* DS1287 RTC */ +#define KN02_CPU_INR_CASCADE 2 /* CSR cascade */ + +/* + * CSR interrupt bits. + */ +#define KN02_CSR_INR_DZ11 7 /* DZ11 (DC7085) serial */ +#define KN02_CSR_INR_LANCE 6 /* LANCE (Am7990) Ethernet */ +#define KN02_CSR_INR_ASC 5 /* ASC (NCR53C94) SCSI */ +#define KN02_CSR_INR_RES_4 4 /* unused */ +#define KN02_CSR_INR_RES_3 3 /* unused */ +#define KN02_CSR_INR_TC2 2 /* TURBOchannel slot #2 */ +#define KN02_CSR_INR_TC1 1 /* TURBOchannel slot #1 */ +#define KN02_CSR_INR_TC0 0 /* TURBOchannel slot #0 */ + + +#define KN02_IRQ_BASE 8 /* first IRQ assigned to CSR */ +#define KN02_IRQ_LINES 8 /* number of CSR interrupts */ + +#define KN02_IRQ_NR(n) ((n) + KN02_IRQ_BASE) +#define KN02_IRQ_MASK(n) (1 << (n)) +#define KN02_IRQ_ALL 0xff + + +#ifndef __ASSEMBLY__ + +#include + +extern u32 cached_kn02_csr; +extern void init_kn02_irqs(int base); +#endif + +#endif /* __ASM_MIPS_DEC_KN02_H */ diff --git a/arch/mips/include/asm/dec/kn02ba.h b/arch/mips/include/asm/dec/kn02ba.h new file mode 100644 index 00000000000..c957a4f1b32 --- /dev/null +++ b/arch/mips/include/asm/dec/kn02ba.h @@ -0,0 +1,67 @@ +/* + * include/asm-mips/dec/kn02ba.h + * + * DECstation 5000/1xx (3min or KN02-BA) definitions. + * + * Copyright (C) 2002, 2003 Maciej W. Rozycki + * + * 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. + */ +#ifndef __ASM_MIPS_DEC_KN02BA_H +#define __ASM_MIPS_DEC_KN02BA_H + +#include /* For common definitions. */ + +/* + * CPU interrupt bits. + */ +#define KN02BA_CPU_INR_HALT 6 /* HALT button */ +#define KN02BA_CPU_INR_CASCADE 5 /* I/O ASIC cascade */ +#define KN02BA_CPU_INR_TC2 4 /* TURBOchannel slot #2 */ +#define KN02BA_CPU_INR_TC1 3 /* TURBOchannel slot #1 */ +#define KN02BA_CPU_INR_TC0 2 /* TURBOchannel slot #0 */ + +/* + * I/O ASIC interrupt bits. Star marks denote non-IRQ status bits. + */ +#define KN02BA_IO_INR_RES_15 15 /* unused */ +#define KN02BA_IO_INR_NVRAM 14 /* (*) NVRAM clear jumper */ +#define KN02BA_IO_INR_RES_13 13 /* unused */ +#define KN02BA_IO_INR_BUS 12 /* memory, I/O bus read/write errors */ +#define KN02BA_IO_INR_RES_11 11 /* unused */ +#define KN02BA_IO_INR_NRMOD 10 /* (*) NRMOD manufacturing jumper */ +#define KN02BA_IO_INR_ASC 9 /* ASC (NCR53C94) SCSI */ +#define KN02BA_IO_INR_LANCE 8 /* LANCE (Am7990) Ethernet */ +#define KN02BA_IO_INR_SCC1 7 /* SCC (Z85C30) serial #1 */ +#define KN02BA_IO_INR_SCC0 6 /* SCC (Z85C30) serial #0 */ +#define KN02BA_IO_INR_RTC 5 /* DS1287 RTC */ +#define KN02BA_IO_INR_PSU 4 /* power supply unit warning */ +#define KN02BA_IO_INR_RES_3 3 /* unused */ +#define KN02BA_IO_INR_ASC_DATA 2 /* SCSI data ready (for PIO) */ +#define KN02BA_IO_INR_PBNC 1 /* ~HALT button debouncer */ +#define KN02BA_IO_INR_PBNO 0 /* HALT button debouncer */ + + +/* + * Memory Error Register bits. + */ +#define KN02BA_MER_RES_27 (1<<27) /* unused */ + +/* + * Memory Size Register bits. + */ +#define KN02BA_MSR_RES_17 (0x3ff<<17) /* unused */ + +/* + * I/O ASIC System Support Register bits. + */ +#define KN02BA_IO_SSR_TXDIS1 (1<<14) /* SCC1 transmit disable */ +#define KN02BA_IO_SSR_TXDIS0 (1<<13) /* SCC0 transmit disable */ +#define KN02BA_IO_SSR_RES_12 (1<<12) /* unused */ + +#define KN02BA_IO_SSR_LEDS (0xff<<0) /* ~diagnostic LEDs */ + +#endif /* __ASM_MIPS_DEC_KN02BA_H */ diff --git a/arch/mips/include/asm/dec/kn02ca.h b/arch/mips/include/asm/dec/kn02ca.h new file mode 100644 index 00000000000..92c0fe25609 --- /dev/null +++ b/arch/mips/include/asm/dec/kn02ca.h @@ -0,0 +1,79 @@ +/* + * include/asm-mips/dec/kn02ca.h + * + * Personal DECstation 5000/xx (Maxine or KN02-CA) definitions. + * + * Copyright (C) 2002, 2003 Maciej W. Rozycki + * + * 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. + */ +#ifndef __ASM_MIPS_DEC_KN02CA_H +#define __ASM_MIPS_DEC_KN02CA_H + +#include /* For common definitions. */ + +/* + * CPU interrupt bits. + */ +#define KN02CA_CPU_INR_HALT 6 /* HALT from ACCESS.Bus */ +#define KN02CA_CPU_INR_CASCADE 5 /* I/O ASIC cascade */ +#define KN02CA_CPU_INR_BUS 4 /* memory, I/O bus read/write errors */ +#define KN02CA_CPU_INR_RTC 3 /* DS1287 RTC */ +#define KN02CA_CPU_INR_TIMER 2 /* ARC periodic timer */ + +/* + * I/O ASIC interrupt bits. Star marks denote non-IRQ status bits. + */ +#define KN02CA_IO_INR_FLOPPY 15 /* 82077 FDC */ +#define KN02CA_IO_INR_NVRAM 14 /* (*) NVRAM clear jumper */ +#define KN02CA_IO_INR_POWERON 13 /* (*) ACCESS.Bus/power-on reset */ +#define KN02CA_IO_INR_TC0 12 /* TURBOchannel slot #0 */ +#define KN02CA_IO_INR_TIMER 12 /* ARC periodic timer (?) */ +#define KN02CA_IO_INR_ISDN 11 /* Am79C30A ISDN */ +#define KN02CA_IO_INR_NRMOD 10 /* (*) NRMOD manufacturing jumper */ +#define KN02CA_IO_INR_ASC 9 /* ASC (NCR53C94) SCSI */ +#define KN02CA_IO_INR_LANCE 8 /* LANCE (Am7990) Ethernet */ +#define KN02CA_IO_INR_HDFLOPPY 7 /* (*) HD (1.44MB) floppy status */ +#define KN02CA_IO_INR_SCC0 6 /* SCC (Z85C30) serial #0 */ +#define KN02CA_IO_INR_TC1 5 /* TURBOchannel slot #1 */ +#define KN02CA_IO_INR_XDFLOPPY 4 /* (*) XD (2.88MB) floppy status */ +#define KN02CA_IO_INR_VIDEO 3 /* framebuffer */ +#define KN02CA_IO_INR_XVIDEO 2 /* ~framebuffer */ +#define KN02CA_IO_INR_AB_XMIT 1 /* ACCESS.bus transmit */ +#define KN02CA_IO_INR_AB_RECV 0 /* ACCESS.bus receive */ + + +/* + * Memory Error Register bits. + */ +#define KN02CA_MER_INTR (1<<27) /* ARC IRQ status & ack */ + +/* + * Memory Size Register bits. + */ +#define KN02CA_MSR_INTREN (1<<26) /* ARC periodic IRQ enable */ +#define KN02CA_MSR_MS10EN (1<<25) /* 10/1ms IRQ period select */ +#define KN02CA_MSR_PFORCE (0xf<<21) /* byte lane error force */ +#define KN02CA_MSR_MABEN (1<<20) /* A side VFB address enable */ +#define KN02CA_MSR_LASTBANK (0x7<<17) /* onboard RAM bank # */ + +/* + * I/O ASIC System Support Register bits. + */ +#define KN03CA_IO_SSR_RES_14 (1<<14) /* unused */ +#define KN03CA_IO_SSR_RES_13 (1<<13) /* unused */ +#define KN03CA_IO_SSR_ISDN_RST (1<<12) /* ~ISDN (Am79C30A) reset */ + +#define KN03CA_IO_SSR_FLOPPY_RST (1<<7) /* ~FDC (82077) reset */ +#define KN03CA_IO_SSR_VIDEO_RST (1<<6) /* ~framebuffer reset */ +#define KN03CA_IO_SSR_AB_RST (1<<5) /* ACCESS.bus reset */ +#define KN03CA_IO_SSR_RES_4 (1<<4) /* unused */ +#define KN03CA_IO_SSR_RES_3 (1<<4) /* unused */ +#define KN03CA_IO_SSR_RES_2 (1<<2) /* unused */ +#define KN03CA_IO_SSR_RES_1 (1<<1) /* unused */ +#define KN03CA_IO_SSR_LED (1<<0) /* power LED */ + +#endif /* __ASM_MIPS_DEC_KN02CA_H */ diff --git a/arch/mips/include/asm/dec/kn02xa.h b/arch/mips/include/asm/dec/kn02xa.h new file mode 100644 index 00000000000..b56b4577f6e --- /dev/null +++ b/arch/mips/include/asm/dec/kn02xa.h @@ -0,0 +1,84 @@ +/* + * Hardware info common to DECstation 5000/1xx systems (otherwise + * known as 3min or kn02ba) and Personal DECstations 5000/xx ones + * (otherwise known as maxine or kn02ca). + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions + * are by courtesy of Chris Fraser. + * Copyright (C) 2000, 2002, 2003, 2005 Maciej W. Rozycki + * + * These are addresses which have to be known early in the boot process. + * For other addresses refer to tc.h, ioasic_addrs.h and friends. + */ +#ifndef __ASM_MIPS_DEC_KN02XA_H +#define __ASM_MIPS_DEC_KN02XA_H + +#include + +#define KN02XA_SLOT_BASE 0x1c000000 + +/* + * Memory control ASIC registers. + */ +#define KN02XA_MER 0x0c400000 /* memory error register */ +#define KN02XA_MSR 0x0c800000 /* memory size register */ + +/* + * CPU control ASIC registers. + */ +#define KN02XA_MEM_CONF 0x0e000000 /* write timeout config */ +#define KN02XA_EAR 0x0e000004 /* error address register */ +#define KN02XA_BOOT0 0x0e000008 /* boot 0 register */ +#define KN02XA_MEM_INTR 0x0e00000c /* write err IRQ stat & ack */ + +/* + * Memory Error Register bits, common definitions. + * The rest is defined in system-specific headers. + */ +#define KN02XA_MER_RES_28 (0xf<<28) /* unused */ +#define KN02XA_MER_RES_17 (0x3ff<<17) /* unused */ +#define KN02XA_MER_PAGERR (1<<16) /* 2k page boundary error */ +#define KN02XA_MER_TRANSERR (1<<15) /* transfer length error */ +#define KN02XA_MER_PARDIS (1<<14) /* parity error disable */ +#define KN02XA_MER_SIZE (1<<13) /* r/o mirror of MSR_SIZE */ +#define KN02XA_MER_RES_12 (1<<12) /* unused */ +#define KN02XA_MER_BYTERR (0xf<<8) /* byte lane error bitmask: */ +#define KN02XA_MER_BYTERR_3 (0x8<<8) /* byte lane #3 */ +#define KN02XA_MER_BYTERR_2 (0x4<<8) /* byte lane #2 */ +#define KN02XA_MER_BYTERR_1 (0x2<<8) /* byte lane #1 */ +#define KN02XA_MER_BYTERR_0 (0x1<<8) /* byte lane #0 */ +#define KN02XA_MER_RES_0 (0xff<<0) /* unused */ + +/* + * Memory Size Register bits, common definitions. + * The rest is defined in system-specific headers. + */ +#define KN02XA_MSR_RES_27 (0x1f<<27) /* unused */ +#define KN02XA_MSR_RES_14 (0x7<<14) /* unused */ +#define KN02XA_MSR_SIZE (1<<13) /* 16M/4M stride */ +#define KN02XA_MSR_RES_0 (0x1fff<<0) /* unused */ + +/* + * Error Address Register bits. + */ +#define KN02XA_EAR_RES_29 (0x7<<29) /* unused */ +#define KN02XA_EAR_ADDRESS (0x7ffffff<<2) /* address involved */ +#define KN02XA_EAR_RES_0 (0x3<<0) /* unused */ + + +#ifndef __ASSEMBLY__ + +#include + +struct pt_regs; + +extern void dec_kn02xa_be_init(void); +extern int dec_kn02xa_be_handler(struct pt_regs *regs, int is_fixup); +extern irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id); +#endif + +#endif /* __ASM_MIPS_DEC_KN02XA_H */ diff --git a/arch/mips/include/asm/dec/kn03.h b/arch/mips/include/asm/dec/kn03.h new file mode 100644 index 00000000000..edede923ffb --- /dev/null +++ b/arch/mips/include/asm/dec/kn03.h @@ -0,0 +1,74 @@ +/* + * Hardware info about DECstation 5000/2x0 systems (otherwise known as + * 3max+) and DECsystem 5900 systems (otherwise known as bigmax) which + * differ mechanically but are otherwise identical (both are known as + * KN03). + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions + * are by courtesy of Chris Fraser. + * Copyright (C) 2000, 2002, 2003, 2005 Maciej W. Rozycki + */ +#ifndef __ASM_MIPS_DEC_KN03_H +#define __ASM_MIPS_DEC_KN03_H + +#include +#include + +#define KN03_SLOT_BASE 0x1f800000 + +/* + * CPU interrupt bits. + */ +#define KN03_CPU_INR_HALT 6 /* HALT button */ +#define KN03_CPU_INR_BUS 5 /* memory, I/O bus read/write errors */ +#define KN03_CPU_INR_RES_4 4 /* unused */ +#define KN03_CPU_INR_RTC 3 /* DS1287 RTC */ +#define KN03_CPU_INR_CASCADE 2 /* I/O ASIC cascade */ + +/* + * I/O ASIC interrupt bits. Star marks denote non-IRQ status bits. + */ +#define KN03_IO_INR_3MAXP 15 /* (*) 3max+/bigmax ID */ +#define KN03_IO_INR_NVRAM 14 /* (*) NVRAM clear jumper */ +#define KN03_IO_INR_TC2 13 /* TURBOchannel slot #2 */ +#define KN03_IO_INR_TC1 12 /* TURBOchannel slot #1 */ +#define KN03_IO_INR_TC0 11 /* TURBOchannel slot #0 */ +#define KN03_IO_INR_NRMOD 10 /* (*) NRMOD manufacturing jumper */ +#define KN03_IO_INR_ASC 9 /* ASC (NCR53C94) SCSI */ +#define KN03_IO_INR_LANCE 8 /* LANCE (Am7990) Ethernet */ +#define KN03_IO_INR_SCC1 7 /* SCC (Z85C30) serial #1 */ +#define KN03_IO_INR_SCC0 6 /* SCC (Z85C30) serial #0 */ +#define KN03_IO_INR_RTC 5 /* DS1287 RTC */ +#define KN03_IO_INR_PSU 4 /* power supply unit warning */ +#define KN03_IO_INR_RES_3 3 /* unused */ +#define KN03_IO_INR_ASC_DATA 2 /* SCSI data ready (for PIO) */ +#define KN03_IO_INR_PBNC 1 /* ~HALT button debouncer */ +#define KN03_IO_INR_PBNO 0 /* HALT button debouncer */ + + +/* + * Memory Control Register bits. + */ +#define KN03_MCR_RES_16 (0xffff<<16) /* unused */ +#define KN03_MCR_DIAGCHK (1<<15) /* diagn/norml ECC reads */ +#define KN03_MCR_DIAGGEN (1<<14) /* diagn/norml ECC writes */ +#define KN03_MCR_CORRECT (1<<13) /* ECC correct/check */ +#define KN03_MCR_RES_11 (0x3<<12) /* unused */ +#define KN03_MCR_BNK32M (1<<10) /* 32M/8M stride */ +#define KN03_MCR_RES_7 (0x7<<7) /* unused */ +#define KN03_MCR_CHECK (0x7f<<0) /* diagnostic check bits */ + +/* + * I/O ASIC System Support Register bits. + */ +#define KN03_IO_SSR_TXDIS1 (1<<14) /* SCC1 transmit disable */ +#define KN03_IO_SSR_TXDIS0 (1<<13) /* SCC0 transmit disable */ +#define KN03_IO_SSR_RES_12 (1<<12) /* unused */ + +#define KN03_IO_SSR_LEDS (0xff<<0) /* ~diagnostic LEDs */ + +#endif /* __ASM_MIPS_DEC_KN03_H */ diff --git a/arch/mips/include/asm/dec/kn05.h b/arch/mips/include/asm/dec/kn05.h new file mode 100644 index 00000000000..56d22dc8803 --- /dev/null +++ b/arch/mips/include/asm/dec/kn05.h @@ -0,0 +1,76 @@ +/* + * include/asm-mips/dec/kn05.h + * + * DECstation/DECsystem 5000/260 (4max+ or KN05), 5000/150 (4min + * or KN04-BA), Personal DECstation/DECsystem 5000/50 (4maxine or + * KN04-CA) and DECsystem 5900/260 (KN05) R4k CPU card MB ASIC + * definitions. + * + * Copyright (C) 2002, 2003, 2005, 2008 Maciej W. Rozycki + * + * 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. + * + * WARNING! All this information is pure guesswork based on the + * ROM. It is provided here in hope it will give someone some + * food for thought. No documentation for the KN05 nor the KN04 + * module has been located so far. + */ +#ifndef __ASM_MIPS_DEC_KN05_H +#define __ASM_MIPS_DEC_KN05_H + +#include + +/* + * The oncard MB (Memory Buffer) ASIC provides an additional address + * decoder. Certain address ranges within the "high" 16 slots are + * passed to the I/O ASIC's decoder like with the KN03 or KN02-BA/CA. + * Others are handled locally. "Low" slots are always passed. + */ +#define KN4K_SLOT_BASE 0x1fc00000 + +#define KN4K_MB_ROM (0*IOASIC_SLOT_SIZE) /* KN05/KN04 card ROM */ +#define KN4K_IOCTL (1*IOASIC_SLOT_SIZE) /* I/O ASIC */ +#define KN4K_ESAR (2*IOASIC_SLOT_SIZE) /* LANCE MAC address chip */ +#define KN4K_LANCE (3*IOASIC_SLOT_SIZE) /* LANCE Ethernet */ +#define KN4K_MB_INT (4*IOASIC_SLOT_SIZE) /* MB interrupt register */ +#define KN4K_MB_EA (5*IOASIC_SLOT_SIZE) /* MB error address? */ +#define KN4K_MB_EC (6*IOASIC_SLOT_SIZE) /* MB error ??? */ +#define KN4K_MB_CSR (7*IOASIC_SLOT_SIZE) /* MB control & status */ +#define KN4K_RES_08 (8*IOASIC_SLOT_SIZE) /* unused? */ +#define KN4K_RES_09 (9*IOASIC_SLOT_SIZE) /* unused? */ +#define KN4K_RES_10 (10*IOASIC_SLOT_SIZE) /* unused? */ +#define KN4K_RES_11 (11*IOASIC_SLOT_SIZE) /* unused? */ +#define KN4K_SCSI (12*IOASIC_SLOT_SIZE) /* ASC SCSI */ +#define KN4K_RES_13 (13*IOASIC_SLOT_SIZE) /* unused? */ +#define KN4K_RES_14 (14*IOASIC_SLOT_SIZE) /* unused? */ +#define KN4K_RES_15 (15*IOASIC_SLOT_SIZE) /* unused? */ + +/* + * Bits for the MB interrupt register. + * The register appears read-only. + */ +#define KN4K_MB_INT_TC (1<<0) /* TURBOchannel? */ +#define KN4K_MB_INT_RTC (1<<1) /* RTC? */ +#define KN4K_MB_INT_MT (1<<3) /* I/O ASIC cascade */ + +/* + * Bits for the MB control & status register. + * Set to 0x00bf8001 for KN05 and to 0x003f8000 for KN04 by the firmware. + */ +#define KN4K_MB_CSR_PF (1<<0) /* PreFetching enable? */ +#define KN4K_MB_CSR_F (1<<1) /* ??? */ +#define KN4K_MB_CSR_ECC (0xff<<2) /* ??? */ +#define KN4K_MB_CSR_OD (1<<10) /* ??? */ +#define KN4K_MB_CSR_CP (1<<11) /* ??? */ +#define KN4K_MB_CSR_UNC (1<<12) /* ??? */ +#define KN4K_MB_CSR_IM (1<<13) /* ??? */ +#define KN4K_MB_CSR_NC (1<<14) /* ??? */ +#define KN4K_MB_CSR_EE (1<<15) /* (bus) Exception Enable? */ +#define KN4K_MB_CSR_MSK (0x1f<<16) /* CPU Int[4:0] mask */ +#define KN4K_MB_CSR_FW (1<<21) /* ??? */ +#define KN4K_MB_CSR_W (1<<31) /* ??? */ + +#endif /* __ASM_MIPS_DEC_KN05_H */ diff --git a/arch/mips/include/asm/dec/kn230.h b/arch/mips/include/asm/dec/kn230.h new file mode 100644 index 00000000000..ff1bf17de8d --- /dev/null +++ b/arch/mips/include/asm/dec/kn230.h @@ -0,0 +1,26 @@ +/* + * include/asm-mips/dec/kn230.h + * + * DECsystem 5100 (MIPSmate or KN230) definitions. + * + * Copyright (C) 2002, 2003 Maciej W. Rozycki + * + * 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. + */ +#ifndef __ASM_MIPS_DEC_KN230_H +#define __ASM_MIPS_DEC_KN230_H + +/* + * CPU interrupt bits. + */ +#define KN230_CPU_INR_HALT 6 /* HALT button */ +#define KN230_CPU_INR_BUS 5 /* memory, I/O bus read/write errors */ +#define KN230_CPU_INR_RTC 4 /* DS1287 RTC */ +#define KN230_CPU_INR_SII 3 /* SII (DC7061) SCSI */ +#define KN230_CPU_INR_LANCE 3 /* LANCE (Am7990) Ethernet */ +#define KN230_CPU_INR_DZ11 2 /* DZ11 (DC7085) serial */ + +#endif /* __ASM_MIPS_DEC_KN230_H */ diff --git a/arch/mips/include/asm/dec/machtype.h b/arch/mips/include/asm/dec/machtype.h new file mode 100644 index 00000000000..a6ecdebc430 --- /dev/null +++ b/arch/mips/include/asm/dec/machtype.h @@ -0,0 +1,27 @@ +/* + * Various machine type macros + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1998, 2000 Harald Koerfgen + */ + +#ifndef __ASM_DEC_MACHTYPE_H +#define __ASM_DEC_MACHTYPE_H + +#include + +#define TURBOCHANNEL (mips_machtype == MACH_DS5000_200 || \ + mips_machtype == MACH_DS5000_1XX || \ + mips_machtype == MACH_DS5000_XX || \ + mips_machtype == MACH_DS5000_2X0 || \ + mips_machtype == MACH_DS5900) + +#define IOASIC (mips_machtype == MACH_DS5000_1XX || \ + mips_machtype == MACH_DS5000_XX || \ + mips_machtype == MACH_DS5000_2X0 || \ + mips_machtype == MACH_DS5900) + +#endif diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h new file mode 100644 index 00000000000..b9c8203688d --- /dev/null +++ b/arch/mips/include/asm/dec/prom.h @@ -0,0 +1,174 @@ +/* + * include/asm-mips/dec/prom.h + * + * DECstation PROM interface. + * + * Copyright (C) 2002 Maciej W. Rozycki + * + * 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. + * + * Based on arch/mips/dec/prom/prom.h by the Anonymous. + */ +#ifndef _ASM_DEC_PROM_H +#define _ASM_DEC_PROM_H + +#include + +#include + +/* + * PMAX/3MAX PROM entry points for DS2100/3100's and DS5000/2xx's. + * Many of these will work for MIPSen as well! + */ +#define VEC_RESET (u64 *)CKSEG1ADDR(0x1fc00000) + /* Prom base address */ + +#define PMAX_PROM_ENTRY(x) (VEC_RESET + (x)) /* Prom jump table */ + +#define PMAX_PROM_HALT PMAX_PROM_ENTRY(2) /* valid on MIPSen */ +#define PMAX_PROM_AUTOBOOT PMAX_PROM_ENTRY(5) /* valid on MIPSen */ +#define PMAX_PROM_OPEN PMAX_PROM_ENTRY(6) +#define PMAX_PROM_READ PMAX_PROM_ENTRY(7) +#define PMAX_PROM_CLOSE PMAX_PROM_ENTRY(10) +#define PMAX_PROM_LSEEK PMAX_PROM_ENTRY(11) +#define PMAX_PROM_GETCHAR PMAX_PROM_ENTRY(12) +#define PMAX_PROM_PUTCHAR PMAX_PROM_ENTRY(13) /* 12 on MIPSen */ +#define PMAX_PROM_GETS PMAX_PROM_ENTRY(15) +#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17) +#define PMAX_PROM_GETENV PMAX_PROM_ENTRY(33) /* valid on MIPSen */ + + +/* + * Magic number indicating REX PROM available on DECstation. Found in + * register a2 on transfer of control to program from PROM. + */ +#define REX_PROM_MAGIC 0x30464354 + +#ifdef CONFIG_64BIT + +#define prom_is_rex(magic) 1 /* KN04 and KN05 are REX PROMs. */ + +#else /* !CONFIG_64BIT */ + +#define prom_is_rex(magic) ((magic) == REX_PROM_MAGIC) + +#endif /* !CONFIG_64BIT */ + + +/* + * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's and + * DS5000/2x0. + */ +#define REX_PROM_GETBITMAP 0x84/4 /* get mem bitmap */ +#define REX_PROM_GETCHAR 0x24/4 /* getch() */ +#define REX_PROM_GETENV 0x64/4 /* get env. variable */ +#define REX_PROM_GETSYSID 0x80/4 /* get system id */ +#define REX_PROM_GETTCINFO 0xa4/4 +#define REX_PROM_PRINTF 0x30/4 /* printf() */ +#define REX_PROM_SLOTADDR 0x6c/4 /* slotaddr */ +#define REX_PROM_BOOTINIT 0x54/4 /* open() */ +#define REX_PROM_BOOTREAD 0x58/4 /* read() */ +#define REX_PROM_CLEARCACHE 0x7c/4 + + +/* + * Used by rex_getbitmap(). + */ +typedef struct { + int pagesize; + unsigned char bitmap[0]; +} memmap; + + +/* + * Function pointers as read from a PROM's callback vector. + */ +extern int (*__rex_bootinit)(void); +extern int (*__rex_bootread)(void); +extern int (*__rex_getbitmap)(memmap *); +extern unsigned long *(*__rex_slot_address)(int); +extern void *(*__rex_gettcinfo)(void); +extern int (*__rex_getsysid)(void); +extern void (*__rex_clear_cache)(void); + +extern int (*__prom_getchar)(void); +extern char *(*__prom_getenv)(char *); +extern int (*__prom_printf)(char *, ...); + +extern int (*__pmax_open)(char*, int); +extern int (*__pmax_lseek)(int, long, int); +extern int (*__pmax_read)(int, void *, int); +extern int (*__pmax_close)(int); + + +#ifdef CONFIG_64BIT + +/* + * On MIPS64 we have to call PROM functions via a helper + * dispatcher to accomodate ABI incompatibilities. + */ +#define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \ + __asm__(#fun " = call_o32") + +int __DEC_PROM_O32(_rex_bootinit, (int (*)(void))); +int __DEC_PROM_O32(_rex_bootread, (int (*)(void))); +int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), memmap *)); +unsigned long *__DEC_PROM_O32(_rex_slot_address, + (unsigned long *(*)(int), int)); +void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void))); +int __DEC_PROM_O32(_rex_getsysid, (int (*)(void))); +void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void))); + +int __DEC_PROM_O32(_prom_getchar, (int (*)(void))); +char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), char *)); +int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), char *, ...)); + + +#define rex_bootinit() _rex_bootinit(__rex_bootinit) +#define rex_bootread() _rex_bootread(__rex_bootread) +#define rex_getbitmap(x) _rex_getbitmap(__rex_getbitmap, x) +#define rex_slot_address(x) _rex_slot_address(__rex_slot_address, x) +#define rex_gettcinfo() _rex_gettcinfo(__rex_gettcinfo) +#define rex_getsysid() _rex_getsysid(__rex_getsysid) +#define rex_clear_cache() _rex_clear_cache(__rex_clear_cache) + +#define prom_getchar() _prom_getchar(__prom_getchar) +#define prom_getenv(x) _prom_getenv(__prom_getenv, x) +#define prom_printf(x...) _prom_printf(__prom_printf, x) + +#else /* !CONFIG_64BIT */ + +/* + * On plain MIPS we just call PROM functions directly. + */ +#define rex_bootinit __rex_bootinit +#define rex_bootread __rex_bootread +#define rex_getbitmap __rex_getbitmap +#define rex_slot_address __rex_slot_address +#define rex_gettcinfo __rex_gettcinfo +#define rex_getsysid __rex_getsysid +#define rex_clear_cache __rex_clear_cache + +#define prom_getchar __prom_getchar +#define prom_getenv __prom_getenv +#define prom_printf __prom_printf + +#define pmax_open __pmax_open +#define pmax_lseek __pmax_lseek +#define pmax_read __pmax_read +#define pmax_close __pmax_close + +#endif /* !CONFIG_64BIT */ + + +extern void prom_meminit(u32); +extern void prom_identify_arch(u32); +extern void prom_init_cmdline(s32, s32 *, u32); + +extern void register_prom_console(void); +extern void unregister_prom_console(void); + +#endif /* _ASM_DEC_PROM_H */ diff --git a/arch/mips/include/asm/dec/system.h b/arch/mips/include/asm/dec/system.h new file mode 100644 index 00000000000..b2afaccd683 --- /dev/null +++ b/arch/mips/include/asm/dec/system.h @@ -0,0 +1,19 @@ +/* + * include/asm-mips/dec/system.h + * + * Generic DECstation/DECsystem bits. + * + * Copyright (C) 2005, 2006 Maciej W. Rozycki + * + * 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. + */ +#ifndef __ASM_DEC_SYSTEM_H +#define __ASM_DEC_SYSTEM_H + +extern unsigned long dec_kn_slot_base, dec_kn_slot_size; +extern int dec_tc_bus; + +#endif /* __ASM_DEC_SYSTEM_H */ diff --git a/arch/mips/include/asm/delay.h b/arch/mips/include/asm/delay.h new file mode 100644 index 00000000000..b0bccd2c4ed --- /dev/null +++ b/arch/mips/include/asm/delay.h @@ -0,0 +1,112 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 by Waldorf Electronics + * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2007 Maciej W. Rozycki + */ +#ifndef _ASM_DELAY_H +#define _ASM_DELAY_H + +#include +#include + +#include +#include + +static inline void __delay(unsigned long loops) +{ + if (sizeof(long) == 4) + __asm__ __volatile__ ( + " .set noreorder \n" + " .align 3 \n" + "1: bnez %0, 1b \n" + " subu %0, 1 \n" + " .set reorder \n" + : "=r" (loops) + : "0" (loops)); + else if (sizeof(long) == 8 && !DADDI_WAR) + __asm__ __volatile__ ( + " .set noreorder \n" + " .align 3 \n" + "1: bnez %0, 1b \n" + " dsubu %0, 1 \n" + " .set reorder \n" + : "=r" (loops) + : "0" (loops)); + else if (sizeof(long) == 8 && DADDI_WAR) + __asm__ __volatile__ ( + " .set noreorder \n" + " .align 3 \n" + "1: bnez %0, 1b \n" + " dsubu %0, %2 \n" + " .set reorder \n" + : "=r" (loops) + : "0" (loops), "r" (1)); +} + + +/* + * Division by multiplication: you don't have to worry about + * loss of precision. + * + * Use only for very small delays ( < 1 msec). Should probably use a + * lookup table, really, as the multiplications take much too long with + * short delays. This is a "reasonable" implementation, though (and the + * first constant multiplications gets optimized away if the delay is + * a constant) + */ + +static inline void __udelay(unsigned long usecs, unsigned long lpj) +{ + unsigned long hi, lo; + + /* + * The rates of 128 is rounded wrongly by the catchall case + * for 64-bit. Excessive precission? Probably ... + */ +#if defined(CONFIG_64BIT) && (HZ == 128) + usecs *= 0x0008637bd05af6c7UL; /* 2**64 / (1000000 / HZ) */ +#elif defined(CONFIG_64BIT) + usecs *= (0x8000000000000000UL / (500000 / HZ)); +#else /* 32-bit junk follows here */ + usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) + + 0x80000000ULL) >> 32); +#endif + + if (sizeof(long) == 4) + __asm__("multu\t%2, %3" + : "=h" (usecs), "=l" (lo) + : "r" (usecs), "r" (lpj) + : GCC_REG_ACCUM); + else if (sizeof(long) == 8 && !R4000_WAR) + __asm__("dmultu\t%2, %3" + : "=h" (usecs), "=l" (lo) + : "r" (usecs), "r" (lpj) + : GCC_REG_ACCUM); + else if (sizeof(long) == 8 && R4000_WAR) + __asm__("dmultu\t%3, %4\n\tmfhi\t%0" + : "=r" (usecs), "=h" (hi), "=l" (lo) + : "r" (usecs), "r" (lpj) + : GCC_REG_ACCUM); + + __delay(usecs); +} + +#define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val + +#define udelay(usecs) __udelay((usecs), __udelay_val) + +/* make sure "usecs *= ..." in udelay do not overflow. */ +#if HZ >= 1000 +#define MAX_UDELAY_MS 1 +#elif HZ <= 200 +#define MAX_UDELAY_MS 5 +#else +#define MAX_UDELAY_MS (1000 / HZ) +#endif + +#endif /* _ASM_DELAY_H */ diff --git a/arch/mips/include/asm/device.h b/arch/mips/include/asm/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/arch/mips/include/asm/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/arch/mips/include/asm/div64.h b/arch/mips/include/asm/div64.h new file mode 100644 index 00000000000..d1d699105c1 --- /dev/null +++ b/arch/mips/include/asm/div64.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2000, 2004 Maciej W. Rozycki + * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef _ASM_DIV64_H +#define _ASM_DIV64_H + +#include + +#if (_MIPS_SZLONG == 32) + +#include + +/* + * No traps on overflows for any of these... + */ + +#define do_div64_32(res, high, low, base) ({ \ + unsigned long __quot32, __mod32; \ + unsigned long __cf, __tmp, __tmp2, __i; \ + \ + __asm__(".set push\n\t" \ + ".set noat\n\t" \ + ".set noreorder\n\t" \ + "move %2, $0\n\t" \ + "move %3, $0\n\t" \ + "b 1f\n\t" \ + " li %4, 0x21\n" \ + "0:\n\t" \ + "sll $1, %0, 0x1\n\t" \ + "srl %3, %0, 0x1f\n\t" \ + "or %0, $1, %5\n\t" \ + "sll %1, %1, 0x1\n\t" \ + "sll %2, %2, 0x1\n" \ + "1:\n\t" \ + "bnez %3, 2f\n\t" \ + " sltu %5, %0, %z6\n\t" \ + "bnez %5, 3f\n" \ + "2:\n\t" \ + " addiu %4, %4, -1\n\t" \ + "subu %0, %0, %z6\n\t" \ + "addiu %2, %2, 1\n" \ + "3:\n\t" \ + "bnez %4, 0b\n\t" \ + " srl %5, %1, 0x1f\n\t" \ + ".set pop" \ + : "=&r" (__mod32), "=&r" (__tmp), \ + "=&r" (__quot32), "=&r" (__cf), \ + "=&r" (__i), "=&r" (__tmp2) \ + : "Jr" (base), "0" (high), "1" (low)); \ + \ + (res) = __quot32; \ + __mod32; }) + +#define do_div(n, base) ({ \ + unsigned long long __quot; \ + unsigned long __mod; \ + unsigned long long __div; \ + unsigned long __upper, __low, __high, __base; \ + \ + __div = (n); \ + __base = (base); \ + \ + __high = __div >> 32; \ + __low = __div; \ + __upper = __high; \ + \ + if (__high) \ + __asm__("divu $0, %z2, %z3" \ + : "=h" (__upper), "=l" (__high) \ + : "Jr" (__high), "Jr" (__base) \ + : GCC_REG_ACCUM); \ + \ + __mod = do_div64_32(__low, __upper, __low, __base); \ + \ + __quot = __high; \ + __quot = __quot << 32 | __low; \ + (n) = __quot; \ + __mod; }) + +#endif /* (_MIPS_SZLONG == 32) */ + +#if (_MIPS_SZLONG == 64) + +/* + * Hey, we're already 64-bit, no + * need to play games.. + */ +#define do_div(n, base) ({ \ + unsigned long __quot; \ + unsigned int __mod; \ + unsigned long __div; \ + unsigned int __base; \ + \ + __div = (n); \ + __base = (base); \ + \ + __mod = __div % __base; \ + __quot = __div / __base; \ + \ + (n) = __quot; \ + __mod; }) + +#endif /* (_MIPS_SZLONG == 64) */ + +#endif /* _ASM_DIV64_H */ diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h new file mode 100644 index 00000000000..c64afb40cd0 --- /dev/null +++ b/arch/mips/include/asm/dma-mapping.h @@ -0,0 +1,81 @@ +#ifndef _ASM_DMA_MAPPING_H +#define _ASM_DMA_MAPPING_H + +#include +#include + +void *dma_alloc_noncoherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); + +void dma_free_noncoherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); + +void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + +extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction); +extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction); +extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction); +extern dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction direction); +extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, enum dma_data_direction direction); +extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nhwentries, enum dma_data_direction direction); +extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction); +extern void dma_sync_single_for_device(struct device *dev, + dma_addr_t dma_handle, size_t size, enum dma_data_direction direction); +extern void dma_sync_single_range_for_cpu(struct device *dev, + dma_addr_t dma_handle, unsigned long offset, size_t size, + enum dma_data_direction direction); +extern void dma_sync_single_range_for_device(struct device *dev, + dma_addr_t dma_handle, unsigned long offset, size_t size, + enum dma_data_direction direction); +extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction direction); +extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction direction); +extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); +extern int dma_supported(struct device *dev, u64 mask); + +static inline int +dma_set_mask(struct device *dev, u64 mask) +{ + if(!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + + *dev->dma_mask = mask; + + return 0; +} + +static inline int +dma_get_cache_alignment(void) +{ + /* XXX Largest on any MIPS */ + return 128; +} + +extern int dma_is_consistent(struct device *dev, dma_addr_t dma_addr); + +extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction); + +#if 0 +#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY + +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 + +#endif /* _ASM_DMA_MAPPING_H */ diff --git a/arch/mips/include/asm/dma.h b/arch/mips/include/asm/dma.h new file mode 100644 index 00000000000..1353c81065d --- /dev/null +++ b/arch/mips/include/asm/dma.h @@ -0,0 +1,315 @@ +/* + * linux/include/asm/dma.h: Defines for using and allocating dma channels. + * Written by Hennus Bergman, 1992. + * High DMA channel support & info by Hannu Savolainen + * and John Boyd, Nov. 1992. + * + * NOTE: all this is true *only* for ISA/EISA expansions on Mips boards + * and can only be used for expansion cards. Onboard DMA controllers, such + * as the R4030 on Jazz boards behave totally different! + */ + +#ifndef _ASM_DMA_H +#define _ASM_DMA_H + +#include /* need byte IO */ +#include /* And spinlocks */ +#include +#include + + +#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER +#define dma_outb outb_p +#else +#define dma_outb outb +#endif + +#define dma_inb inb + +/* + * NOTES about DMA transfers: + * + * controller 1: channels 0-3, byte operations, ports 00-1F + * controller 2: channels 4-7, word operations, ports C0-DF + * + * - ALL registers are 8 bits only, regardless of transfer size + * - channel 4 is not used - cascades 1 into 2. + * - channels 0-3 are byte - addresses/counts are for physical bytes + * - channels 5-7 are word - addresses/counts are for physical words + * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries + * - transfer count loaded to registers is 1 less than actual count + * - controller 2 offsets are all even (2x offsets for controller 1) + * - page registers for 5-7 don't use data bit 0, represent 128K pages + * - page registers for 0-3 use bit 0, represent 64K pages + * + * DMA transfers are limited to the lower 16MB of _physical_ memory. + * Note that addresses loaded into registers must be _physical_ addresses, + * not logical addresses (which may differ if paging is active). + * + * Address mapping for channels 0-3: + * + * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * P7 ... P0 A7 ... A0 A7 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Address mapping for channels 5-7: + * + * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) + * | ... | \ \ ... \ \ \ ... \ \ + * | ... | \ \ ... \ \ \ ... \ (not used) + * | ... | \ \ ... \ \ \ ... \ + * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses + * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at + * the hardware level, so odd-byte transfers aren't possible). + * + * Transfer count (_not # bytes_) is limited to 64K, represented as actual + * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, + * and up to 128K bytes may be transferred on channels 5-7 in one operation. + * + */ + +#ifndef CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN +#define MAX_DMA_CHANNELS 8 +#endif + +/* + * The maximum address in KSEG0 that we can perform a DMA transfer to on this + * platform. This describes only the PC style part of the DMA logic like on + * Deskstations or Acer PICA but not the much more versatile DMA logic used + * for the local devices on Acer PICA or Magnums. + */ +#if defined(CONFIG_SGI_IP22) || defined(CONFIG_SGI_IP28) +/* don't care; ISA bus master won't work, ISA slave DMA supports 32bit addr */ +#define MAX_DMA_ADDRESS PAGE_OFFSET +#else +#define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000) +#endif +#define MAX_DMA_PFN PFN_DOWN(virt_to_phys((void *)MAX_DMA_ADDRESS)) +#define MAX_DMA32_PFN (1UL << (32 - PAGE_SHIFT)) + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* DMA controller registers */ +#define DMA1_CMD_REG 0x08 /* command register (w) */ +#define DMA1_STAT_REG 0x08 /* status register (r) */ +#define DMA1_REQ_REG 0x09 /* request register (w) */ +#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ +#define DMA1_MODE_REG 0x0B /* mode register (w) */ +#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ +#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ +#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ + +#define DMA2_CMD_REG 0xD0 /* command register (w) */ +#define DMA2_STAT_REG 0xD0 /* status register (r) */ +#define DMA2_REQ_REG 0xD2 /* request register (w) */ +#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ +#define DMA2_MODE_REG 0xD6 /* mode register (w) */ +#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ +#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ +#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ + +#define DMA_ADDR_0 0x00 /* DMA address registers */ +#define DMA_ADDR_1 0x02 +#define DMA_ADDR_2 0x04 +#define DMA_ADDR_3 0x06 +#define DMA_ADDR_4 0xC0 +#define DMA_ADDR_5 0xC4 +#define DMA_ADDR_6 0xC8 +#define DMA_ADDR_7 0xCC + +#define DMA_CNT_0 0x01 /* DMA count registers */ +#define DMA_CNT_1 0x03 +#define DMA_CNT_2 0x05 +#define DMA_CNT_3 0x07 +#define DMA_CNT_4 0xC2 +#define DMA_CNT_5 0xC6 +#define DMA_CNT_6 0xCA +#define DMA_CNT_7 0xCE + +#define DMA_PAGE_0 0x87 /* DMA page registers */ +#define DMA_PAGE_1 0x83 +#define DMA_PAGE_2 0x81 +#define DMA_PAGE_3 0x82 +#define DMA_PAGE_5 0x8B +#define DMA_PAGE_6 0x89 +#define DMA_PAGE_7 0x8A + +#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ +#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ +#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ + +#define DMA_AUTOINIT 0x10 + +extern spinlock_t dma_spin_lock; + +static __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +static __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +/* enable/disable a specific DMA channel */ +static __inline__ void enable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr, DMA1_MASK_REG); + else + dma_outb(dmanr & 3, DMA2_MASK_REG); +} + +static __inline__ void disable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr | 4, DMA1_MASK_REG); + else + dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while holding the DMA lock ! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(0, DMA1_CLEAR_FF_REG); + else + dma_outb(0, DMA2_CLEAR_FF_REG); +} + +/* set mode (above) for a specific DMA channel */ +static __inline__ void set_dma_mode(unsigned int dmanr, char mode) +{ + if (dmanr<=3) + dma_outb(mode | dmanr, DMA1_MODE_REG); + else + dma_outb(mode | (dmanr&3), DMA2_MODE_REG); +} + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + switch(dmanr) { + case 0: + dma_outb(pagenr, DMA_PAGE_0); + break; + case 1: + dma_outb(pagenr, DMA_PAGE_1); + break; + case 2: + dma_outb(pagenr, DMA_PAGE_2); + break; + case 3: + dma_outb(pagenr, DMA_PAGE_3); + break; + case 5: + dma_outb(pagenr & 0xfe, DMA_PAGE_5); + break; + case 6: + dma_outb(pagenr & 0xfe, DMA_PAGE_6); + break; + case 7: + dma_outb(pagenr & 0xfe, DMA_PAGE_7); + break; + } +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) +{ + set_dma_page(dmanr, a>>16); + if (dmanr <= 3) { + dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + } else { + dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } +} + + +/* Set transfer size (max 64k for DMA0..3, 128k for DMA5..7) for + * a specific DMA channel. + * You must ensure the parameters are valid. + * NOTE: from a manual: "the number of transfers is one more + * than the initial word count"! This is taken into account. + * Assumes dma flip-flop is clear. + * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. + */ +static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) +{ + count--; + if (dmanr <= 3) { + dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + } else { + dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } +} + + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +static __inline__ int get_dma_residue(unsigned int dmanr) +{ + unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE + : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; + + /* using short to get 16-bit wrap around */ + unsigned short count; + + count = 1 + dma_inb(io_port); + count += dma_inb(io_port) << 8; + + return (dmanr<=3)? count : (count<<1); +} + + +/* These are in kernel/dma.c: */ +extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ +extern void free_dma(unsigned int dmanr); /* release it again */ + +/* From PCI */ + +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy (0) +#endif + +#endif /* _ASM_DMA_H */ diff --git a/arch/mips/include/asm/ds1286.h b/arch/mips/include/asm/ds1286.h new file mode 100644 index 00000000000..6983b6ff0af --- /dev/null +++ b/arch/mips/include/asm/ds1286.h @@ -0,0 +1,15 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Machine dependent access functions for RTC registers. + * + * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef _ASM_DS1286_H +#define _ASM_DS1286_H + +#include + +#endif /* _ASM_DS1286_H */ diff --git a/arch/mips/include/asm/ds1287.h b/arch/mips/include/asm/ds1287.h new file mode 100644 index 00000000000..ba1702e8693 --- /dev/null +++ b/arch/mips/include/asm/ds1287.h @@ -0,0 +1,27 @@ +/* + * DS1287 timer functions. + * + * Copyright (C) 2008 Yoichi Yuasa + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __ASM_DS1287_H +#define __ASM_DS1287_H + +extern int ds1287_timer_state(void); +extern void ds1287_set_base_clock(unsigned int clock); +extern int ds1287_clockevent_init(int irq); + +#endif diff --git a/arch/mips/include/asm/dsp.h b/arch/mips/include/asm/dsp.h new file mode 100644 index 00000000000..e9bfc0813c7 --- /dev/null +++ b/arch/mips/include/asm/dsp.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005 Mips Technologies + * Author: Chris Dearman, chris@mips.com derived from fpu.h + * + * 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. + */ +#ifndef _ASM_DSP_H +#define _ASM_DSP_H + +#include +#include +#include +#include + +#define DSP_DEFAULT 0x00000000 +#define DSP_MASK 0x3ff + +#define __enable_dsp_hazard() \ +do { \ + asm("_ehb"); \ +} while (0) + +static inline void __init_dsp(void) +{ + mthi1(0); + mtlo1(0); + mthi2(0); + mtlo2(0); + mthi3(0); + mtlo3(0); + wrdsp(DSP_DEFAULT, DSP_MASK); +} + +static inline void init_dsp(void) +{ + if (cpu_has_dsp) + __init_dsp(); +} + +#define __save_dsp(tsk) \ +do { \ + tsk->thread.dsp.dspr[0] = mfhi1(); \ + tsk->thread.dsp.dspr[1] = mflo1(); \ + tsk->thread.dsp.dspr[2] = mfhi2(); \ + tsk->thread.dsp.dspr[3] = mflo2(); \ + tsk->thread.dsp.dspr[4] = mfhi3(); \ + tsk->thread.dsp.dspr[5] = mflo3(); \ + tsk->thread.dsp.dspcontrol = rddsp(DSP_MASK); \ +} while (0) + +#define save_dsp(tsk) \ +do { \ + if (cpu_has_dsp) \ + __save_dsp(tsk); \ +} while (0) + +#define __restore_dsp(tsk) \ +do { \ + mthi1(tsk->thread.dsp.dspr[0]); \ + mtlo1(tsk->thread.dsp.dspr[1]); \ + mthi2(tsk->thread.dsp.dspr[2]); \ + mtlo2(tsk->thread.dsp.dspr[3]); \ + mthi3(tsk->thread.dsp.dspr[4]); \ + mtlo3(tsk->thread.dsp.dspr[5]); \ + wrdsp(tsk->thread.dsp.dspcontrol, DSP_MASK); \ +} while (0) + +#define restore_dsp(tsk) \ +do { \ + if (cpu_has_dsp) \ + __restore_dsp(tsk); \ +} while (0) + +#define __get_dsp_regs(tsk) \ +({ \ + if (tsk == current) \ + __save_dsp(current); \ + \ + tsk->thread.dsp.dspr; \ +}) + +#endif /* _ASM_DSP_H */ diff --git a/arch/mips/include/asm/edac.h b/arch/mips/include/asm/edac.h new file mode 100644 index 00000000000..4da0c1fe30d --- /dev/null +++ b/arch/mips/include/asm/edac.h @@ -0,0 +1,34 @@ +#ifndef ASM_EDAC_H +#define ASM_EDAC_H + +/* ECC atomic, DMA, SMP and interrupt safe scrub function */ + +static inline void atomic_scrub(void *va, u32 size) +{ + unsigned long *virt_addr = va; + unsigned long temp; + u32 i; + + for (i = 0; i < size / sizeof(unsigned long); i++) { + /* + * Very carefully read and write to memory atomically + * so we are interrupt, DMA and SMP safe. + * + * Intel: asm("lock; addl $0, %0"::"m"(*virt_addr)); + */ + + __asm__ __volatile__ ( + " .set mips2 \n" + "1: ll %0, %1 # atomic_scrub \n" + " addu %0, $0 \n" + " sc %0, %1 \n" + " beqz %0, 1b \n" + " .set mips0 \n" + : "=&r" (temp), "=m" (*virt_addr) + : "m" (*virt_addr)); + + virt_addr++; + } +} + +#endif diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h new file mode 100644 index 00000000000..f69f7acba63 --- /dev/null +++ b/arch/mips/include/asm/elf.h @@ -0,0 +1,371 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Much of this is taken from binutils and GNU libc ... + */ +#ifndef _ASM_ELF_H +#define _ASM_ELF_H + + +/* ELF header e_flags defines. */ +/* MIPS architecture level. */ +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x50000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x60000000 /* MIPS64 code. */ +#define EF_MIPS_ARCH_32R2 0x70000000 /* MIPS32 R2 code. */ +#define EF_MIPS_ARCH_64R2 0x80000000 /* MIPS64 R2 code. */ + +/* The ABI of a file. */ +#define EF_MIPS_ABI_O32 0x00001000 /* O32 ABI. */ +#define EF_MIPS_ABI_O64 0x00002000 /* O32 extended for 64 bit. */ + +#define PT_MIPS_REGINFO 0x70000000 +#define PT_MIPS_RTPROC 0x70000001 +#define PT_MIPS_OPTIONS 0x70000002 + +/* Flags in the e_flags field of the header */ +#define EF_MIPS_NOREORDER 0x00000001 +#define EF_MIPS_PIC 0x00000002 +#define EF_MIPS_CPIC 0x00000004 +#define EF_MIPS_ABI2 0x00000020 +#define EF_MIPS_OPTIONS_FIRST 0x00000080 +#define EF_MIPS_32BITMODE 0x00000100 +#define EF_MIPS_ABI 0x0000f000 +#define EF_MIPS_ARCH 0xf0000000 + +#define DT_MIPS_RLD_VERSION 0x70000001 +#define DT_MIPS_TIME_STAMP 0x70000002 +#define DT_MIPS_ICHECKSUM 0x70000003 +#define DT_MIPS_IVERSION 0x70000004 +#define DT_MIPS_FLAGS 0x70000005 + #define RHF_NONE 0x00000000 + #define RHF_HARDWAY 0x00000001 + #define RHF_NOTPOT 0x00000002 + #define RHF_SGI_ONLY 0x00000010 +#define DT_MIPS_BASE_ADDRESS 0x70000006 +#define DT_MIPS_CONFLICT 0x70000008 +#define DT_MIPS_LIBLIST 0x70000009 +#define DT_MIPS_LOCAL_GOTNO 0x7000000a +#define DT_MIPS_CONFLICTNO 0x7000000b +#define DT_MIPS_LIBLISTNO 0x70000010 +#define DT_MIPS_SYMTABNO 0x70000011 +#define DT_MIPS_UNREFEXTNO 0x70000012 +#define DT_MIPS_GOTSYM 0x70000013 +#define DT_MIPS_HIPAGENO 0x70000014 +#define DT_MIPS_RLD_MAP 0x70000016 + +#define R_MIPS_NONE 0 +#define R_MIPS_16 1 +#define R_MIPS_32 2 +#define R_MIPS_REL32 3 +#define R_MIPS_26 4 +#define R_MIPS_HI16 5 +#define R_MIPS_LO16 6 +#define R_MIPS_GPREL16 7 +#define R_MIPS_LITERAL 8 +#define R_MIPS_GOT16 9 +#define R_MIPS_PC16 10 +#define R_MIPS_CALL16 11 +#define R_MIPS_GPREL32 12 +/* The remaining relocs are defined on Irix, although they are not + in the MIPS ELF ABI. */ +#define R_MIPS_UNUSED1 13 +#define R_MIPS_UNUSED2 14 +#define R_MIPS_UNUSED3 15 +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +/* + * The following two relocation types are specified in the MIPS ABI + * conformance guide version 1.2 but not yet in the psABI. + */ +#define R_MIPS_GOTHI16 22 +#define R_MIPS_GOTLO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +/* + * The following two relocation types are specified in the MIPS ABI + * conformance guide version 1.2 but not yet in the psABI. + */ +#define R_MIPS_CALLHI16 30 +#define R_MIPS_CALLLO16 31 +/* + * This range is reserved for vendor specific relocations. + */ +#define R_MIPS_LOVENDOR 100 +#define R_MIPS_HIVENDOR 127 + +#define SHN_MIPS_ACCOMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +#define SHT_MIPS_LIST 0x70000000 +#define SHT_MIPS_CONFLICT 0x70000002 +#define SHT_MIPS_GPTAB 0x70000003 +#define SHT_MIPS_UCODE 0x70000004 +#define SHT_MIPS_DEBUG 0x70000005 +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + +#define SHF_MIPS_GPREL 0x10000000 +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRING 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPES 0x01000000 + +#ifndef ELF_ARCH +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +#ifdef CONFIG_32BIT + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (__h->e_machine != EM_MIPS) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ + __res = 0; \ + if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ + ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ + __res = 0; \ + \ + __res; \ +}) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 + +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (__h->e_machine != EM_MIPS) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS64) \ + __res = 0; \ + \ + __res; \ +}) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 + +#endif /* CONFIG_64BIT */ + +/* + * These are used to set parameters in the core dumps. + */ +#ifdef __MIPSEB__ +#define ELF_DATA ELFDATA2MSB +#elif __MIPSEL__ +#define ELF_DATA ELFDATA2LSB +#endif +#define ELF_ARCH EM_MIPS + +#endif /* !defined(ELF_ARCH) */ + +struct mips_abi; + +extern struct mips_abi mips_abi; +extern struct mips_abi mips_abi_32; +extern struct mips_abi mips_abi_n32; + +#ifdef CONFIG_32BIT + +#define SET_PERSONALITY(ex, ibcs2) \ +do { \ + if (ibcs2) \ + set_personality(PER_SVR4); \ + set_personality(PER_LINUX); \ + \ + current->thread.abi = &mips_abi; \ +} while (0) + +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT + +#ifdef CONFIG_MIPS32_N32 +#define __SET_PERSONALITY32_N32() \ + do { \ + set_thread_flag(TIF_32BIT_ADDR); \ + current->thread.abi = &mips_abi_n32; \ + } while (0) +#else +#define __SET_PERSONALITY32_N32() \ + do { } while (0) +#endif + +#ifdef CONFIG_MIPS32_O32 +#define __SET_PERSONALITY32_O32() \ + do { \ + set_thread_flag(TIF_32BIT_REGS); \ + set_thread_flag(TIF_32BIT_ADDR); \ + current->thread.abi = &mips_abi_32; \ + } while (0) +#else +#define __SET_PERSONALITY32_O32() \ + do { } while (0) +#endif + +#ifdef CONFIG_MIPS32_COMPAT +#define __SET_PERSONALITY32(ex) \ +do { \ + if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \ + ((ex).e_flags & EF_MIPS_ABI) == 0) \ + __SET_PERSONALITY32_N32(); \ + else \ + __SET_PERSONALITY32_O32(); \ +} while (0) +#else +#define __SET_PERSONALITY32(ex) do { } while (0) +#endif + +#define SET_PERSONALITY(ex, ibcs2) \ +do { \ + clear_thread_flag(TIF_32BIT_REGS); \ + clear_thread_flag(TIF_32BIT_ADDR); \ + \ + if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + __SET_PERSONALITY32(ex); \ + else \ + current->thread.abi = &mips_abi; \ + \ + if (ibcs2) \ + set_personality(PER_SVR4); \ + else if (current->personality != PER_LINUX32) \ + set_personality(PER_LINUX); \ +} while (0) + +#endif /* CONFIG_64BIT */ + +struct task_struct; + +extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs); +extern int dump_task_regs(struct task_struct *, elf_gregset_t *); +extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); + +#define ELF_CORE_COPY_REGS(elf_regs, regs) \ + elf_dump_regs((elf_greg_t *)&(elf_regs), regs); +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) +#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) \ + dump_task_fpu(tsk, elf_fpregs) + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE PAGE_SIZE + +/* This yields a mask that user programs can use to figure out what + instruction set this cpu supports. This could be done in userspace, + but it's not easy, and we've already done it here. */ + +#define ELF_HWCAP (0) + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. + + For the moment, we have only optimizations for the Intel generations, + but that could change... */ + +#define ELF_PLATFORM (NULL) + +/* + * See comments in asm-alpha/elf.h, this is the same thing + * on the MIPS. + */ +#define ELF_PLAT_INIT(_r, load_addr) do { \ + _r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0; \ + _r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \ + _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \ + _r->regs[13] = _r->regs[14] = _r->regs[15] = _r->regs[16] = 0; \ + _r->regs[17] = _r->regs[18] = _r->regs[19] = _r->regs[20] = 0; \ + _r->regs[21] = _r->regs[22] = _r->regs[23] = _r->regs[24] = 0; \ + _r->regs[25] = _r->regs[26] = _r->regs[27] = _r->regs[28] = 0; \ + _r->regs[30] = _r->regs[31] = 0; \ +} while (0) + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#ifndef ELF_ET_DYN_BASE +#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) +#endif + +#endif /* _ASM_ELF_H */ diff --git a/arch/mips/include/asm/emergency-restart.h b/arch/mips/include/asm/emergency-restart.h new file mode 100644 index 00000000000..108d8c48e42 --- /dev/null +++ b/arch/mips/include/asm/emergency-restart.h @@ -0,0 +1,6 @@ +#ifndef _ASM_EMERGENCY_RESTART_H +#define _ASM_EMERGENCY_RESTART_H + +#include + +#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/mips/include/asm/emma2rh/emma2rh.h b/arch/mips/include/asm/emma2rh/emma2rh.h new file mode 100644 index 00000000000..6a1af0af51e --- /dev/null +++ b/arch/mips/include/asm/emma2rh/emma2rh.h @@ -0,0 +1,333 @@ +/* + * include/asm-mips/emma2rh/emma2rh.h + * This file is EMMA2RH common header. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file based on include/asm-mips/ddb5xxx/ddb5xxx.h + * Copyright 2001 MontaVista Software Inc. + * + * 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_EMMA2RH_EMMA2RH_H +#define __ASM_EMMA2RH_EMMA2RH_H + +#include + +/* + * EMMA2RH registers + */ +#define REGBASE 0x10000000 + +#define EMMA2RH_BHIF_STRAP_0 (0x000010+REGBASE) +#define EMMA2RH_BHIF_INT_ST_0 (0x000030+REGBASE) +#define EMMA2RH_BHIF_INT_ST_1 (0x000034+REGBASE) +#define EMMA2RH_BHIF_INT_ST_2 (0x000038+REGBASE) +#define EMMA2RH_BHIF_INT_EN_0 (0x000040+REGBASE) +#define EMMA2RH_BHIF_INT_EN_1 (0x000044+REGBASE) +#define EMMA2RH_BHIF_INT_EN_2 (0x000048+REGBASE) +#define EMMA2RH_BHIF_INT1_EN_0 (0x000050+REGBASE) +#define EMMA2RH_BHIF_INT1_EN_1 (0x000054+REGBASE) +#define EMMA2RH_BHIF_INT1_EN_2 (0x000058+REGBASE) +#define EMMA2RH_BHIF_SW_INT (0x000070+REGBASE) +#define EMMA2RH_BHIF_SW_INT_EN (0x000080+REGBASE) +#define EMMA2RH_BHIF_SW_INT_CLR (0x000090+REGBASE) +#define EMMA2RH_BHIF_MAIN_CTRL (0x0000b4+REGBASE) +#define EMMA2RH_BHIF_EXCEPT_VECT_BASE_ADDRESS (0x0000c0+REGBASE) +#define EMMA2RH_GPIO_DIR (0x110d20+REGBASE) +#define EMMA2RH_GPIO_INT_ST (0x110d30+REGBASE) +#define EMMA2RH_GPIO_INT_MASK (0x110d3c+REGBASE) +#define EMMA2RH_GPIO_INT_MODE (0x110d48+REGBASE) +#define EMMA2RH_GPIO_INT_CND_A (0x110d54+REGBASE) +#define EMMA2RH_GPIO_INT_CND_B (0x110d60+REGBASE) +#define EMMA2RH_PBRD_INT_EN (0x100010+REGBASE) +#define EMMA2RH_PBRD_CLKSEL (0x100028+REGBASE) +#define EMMA2RH_PFUR0_BASE (0x101000+REGBASE) +#define EMMA2RH_PFUR1_BASE (0x102000+REGBASE) +#define EMMA2RH_PFUR2_BASE (0x103000+REGBASE) +#define EMMA2RH_PIIC0_BASE (0x107000+REGBASE) +#define EMMA2RH_PIIC1_BASE (0x108000+REGBASE) +#define EMMA2RH_PIIC2_BASE (0x109000+REGBASE) +#define EMMA2RH_PCI_CONTROL (0x200000+REGBASE) +#define EMMA2RH_PCI_ARBIT_CTR (0x200004+REGBASE) +#define EMMA2RH_PCI_IWIN0_CTR (0x200010+REGBASE) +#define EMMA2RH_PCI_IWIN1_CTR (0x200014+REGBASE) +#define EMMA2RH_PCI_INIT_ESWP (0x200018+REGBASE) +#define EMMA2RH_PCI_INT (0x200020+REGBASE) +#define EMMA2RH_PCI_INT_EN (0x200024+REGBASE) +#define EMMA2RH_PCI_TWIN_CTR (0x200030+REGBASE) +#define EMMA2RH_PCI_TWIN_BADR (0x200034+REGBASE) +#define EMMA2RH_PCI_TWIN0_DADR (0x200038+REGBASE) +#define EMMA2RH_PCI_TWIN1_DADR (0x20003c+REGBASE) + +/* + * Memory map (physical address) + * + * Note most of the following address must be properly aligned by the + * corresponding size. For example, if PCI_IO_SIZE is 16MB, then + * PCI_IO_BASE must be aligned along 16MB boundary. + */ + +/* the actual ram size is detected at run-time */ +#define EMMA2RH_RAM_BASE 0x00000000 +#define EMMA2RH_RAM_SIZE 0x10000000 /* less than 256MB */ + +#define EMMA2RH_IO_BASE 0x10000000 +#define EMMA2RH_IO_SIZE 0x01000000 /* 16 MB */ + +#define EMMA2RH_GENERALIO_BASE 0x11000000 +#define EMMA2RH_GENERALIO_SIZE 0x01000000 /* 16 MB */ + +#define EMMA2RH_PCI_IO_BASE 0x12000000 +#define EMMA2RH_PCI_IO_SIZE 0x02000000 /* 32 MB */ + +#define EMMA2RH_PCI_MEM_BASE 0x14000000 +#define EMMA2RH_PCI_MEM_SIZE 0x08000000 /* 128 MB */ + +#define EMMA2RH_ROM_BASE 0x1c000000 +#define EMMA2RH_ROM_SIZE 0x04000000 /* 64 MB */ + +#define EMMA2RH_PCI_CONFIG_BASE EMMA2RH_PCI_IO_BASE +#define EMMA2RH_PCI_CONFIG_SIZE EMMA2RH_PCI_IO_SIZE + +#define NUM_CPU_IRQ 8 +#define NUM_EMMA2RH_IRQ 96 + +#define CPU_EMMA2RH_CASCADE 2 +#define CPU_IRQ_BASE MIPS_CPU_IRQ_BASE +#define EMMA2RH_IRQ_BASE (CPU_IRQ_BASE + NUM_CPU_IRQ) + +/* + * emma2rh irq defs + */ + +#define EMMA2RH_IRQ_INT0 (0 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT1 (1 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT2 (2 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT3 (3 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT4 (4 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT5 (5 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT6 (6 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT7 (7 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT8 (8 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT9 (9 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT10 (10 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT11 (11 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT12 (12 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT13 (13 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT14 (14 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT15 (15 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT16 (16 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT17 (17 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT18 (18 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT19 (19 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT20 (20 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT21 (21 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT22 (22 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT23 (23 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT24 (24 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT25 (25 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT26 (26 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT27 (27 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT28 (28 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT29 (29 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT30 (30 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT31 (31 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT32 (32 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT33 (33 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT34 (34 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT35 (35 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT36 (36 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT37 (37 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT38 (38 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT39 (39 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT40 (40 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT41 (41 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT42 (42 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT43 (43 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT44 (44 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT45 (45 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT46 (46 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT47 (47 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT48 (48 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT49 (49 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT50 (50 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT51 (51 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT52 (52 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT53 (53 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT54 (54 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT55 (55 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT56 (56 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT57 (57 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT58 (58 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT59 (59 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT60 (60 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT61 (61 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT62 (62 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT63 (63 + EMMA2RH_IRQ_BASE) + +#define EMMA2RH_IRQ_PFUR0 EMMA2RH_IRQ_INT49 +#define EMMA2RH_IRQ_PFUR1 EMMA2RH_IRQ_INT50 +#define EMMA2RH_IRQ_PFUR2 EMMA2RH_IRQ_INT51 +#define EMMA2RH_IRQ_PIIC0 EMMA2RH_IRQ_INT56 +#define EMMA2RH_IRQ_PIIC1 EMMA2RH_IRQ_INT57 +#define EMMA2RH_IRQ_PIIC2 EMMA2RH_IRQ_INT58 + +/* + * EMMA2RH Register Access + */ + +#define EMMA2RH_BASE (0xa0000000) + +static inline void emma2rh_sync(void) +{ + volatile u32 *p = (volatile u32 *)0xbfc00000; + (void)(*p); +} + +static inline void emma2rh_out32(u32 offset, u32 val) +{ + *(volatile u32 *)(EMMA2RH_BASE | offset) = val; + emma2rh_sync(); +} + +static inline u32 emma2rh_in32(u32 offset) +{ + u32 val = *(volatile u32 *)(EMMA2RH_BASE | offset); + emma2rh_sync(); + return val; +} + +static inline void emma2rh_out16(u32 offset, u16 val) +{ + *(volatile u16 *)(EMMA2RH_BASE | offset) = val; + emma2rh_sync(); +} + +static inline u16 emma2rh_in16(u32 offset) +{ + u16 val = *(volatile u16 *)(EMMA2RH_BASE | offset); + emma2rh_sync(); + return val; +} + +static inline void emma2rh_out8(u32 offset, u8 val) +{ + *(volatile u8 *)(EMMA2RH_BASE | offset) = val; + emma2rh_sync(); +} + +static inline u8 emma2rh_in8(u32 offset) +{ + u8 val = *(volatile u8 *)(EMMA2RH_BASE | offset); + emma2rh_sync(); + return val; +} + +/** + * IIC registers map + **/ + +/*---------------------------------------------------------------------------*/ +/* CNT - Control register (00H R/W) */ +/*---------------------------------------------------------------------------*/ +#define SPT 0x00000001 +#define STT 0x00000002 +#define ACKE 0x00000004 +#define WTIM 0x00000008 +#define SPIE 0x00000010 +#define WREL 0x00000020 +#define LREL 0x00000040 +#define IICE 0x00000080 +#define CNT_RESERVED 0x000000ff /* reserved bit 0 */ + +#define I2C_EMMA_START (IICE | STT) +#define I2C_EMMA_STOP (IICE | SPT) +#define I2C_EMMA_REPSTART I2C_EMMA_START + +/*---------------------------------------------------------------------------*/ +/* STA - Status register (10H Read) */ +/*---------------------------------------------------------------------------*/ +#define MSTS 0x00000080 +#define ALD 0x00000040 +#define EXC 0x00000020 +#define COI 0x00000010 +#define TRC 0x00000008 +#define ACKD 0x00000004 +#define STD 0x00000002 +#define SPD 0x00000001 + +/*---------------------------------------------------------------------------*/ +/* CSEL - Clock select register (20H R/W) */ +/*---------------------------------------------------------------------------*/ +#define FCL 0x00000080 +#define ND50 0x00000040 +#define CLD 0x00000020 +#define DAD 0x00000010 +#define SMC 0x00000008 +#define DFC 0x00000004 +#define CL 0x00000003 +#define CSEL_RESERVED 0x000000ff /* reserved bit 0 */ + +#define FAST397 0x0000008b +#define FAST297 0x0000008a +#define FAST347 0x0000000b +#define FAST260 0x0000000a +#define FAST130 0x00000008 +#define STANDARD108 0x00000083 +#define STANDARD83 0x00000082 +#define STANDARD95 0x00000003 +#define STANDARD73 0x00000002 +#define STANDARD36 0x00000001 +#define STANDARD71 0x00000000 + +/*---------------------------------------------------------------------------*/ +/* SVA - Slave address register (30H R/W) */ +/*---------------------------------------------------------------------------*/ +#define SVA 0x000000fe + +/*---------------------------------------------------------------------------*/ +/* SHR - Shift register (40H R/W) */ +/*---------------------------------------------------------------------------*/ +#define SR 0x000000ff + +/*---------------------------------------------------------------------------*/ +/* INT - Interrupt register (50H R/W) */ +/* INTM - Interrupt mask register (60H R/W) */ +/*---------------------------------------------------------------------------*/ +#define INTE0 0x00000001 + +/*********************************************************************** + * I2C registers + *********************************************************************** + */ +#define I2C_EMMA_CNT 0x00 +#define I2C_EMMA_STA 0x10 +#define I2C_EMMA_CSEL 0x20 +#define I2C_EMMA_SVA 0x30 +#define I2C_EMMA_SHR 0x40 +#define I2C_EMMA_INT 0x50 +#define I2C_EMMA_INTM 0x60 + +/* + * include the board dependent part + */ +#if defined(CONFIG_MARKEINS) +#include +#else +#error "Unknown EMMA2RH board!" +#endif + +#endif /* __ASM_EMMA2RH_EMMA2RH_H */ diff --git a/arch/mips/include/asm/emma2rh/markeins.h b/arch/mips/include/asm/emma2rh/markeins.h new file mode 100644 index 00000000000..973b0628490 --- /dev/null +++ b/arch/mips/include/asm/emma2rh/markeins.h @@ -0,0 +1,75 @@ +/* + * include/asm-mips/emma2rh/markeins.h + * This file is EMMA2RH board depended header. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file based on include/asm-mips/ddb5xxx/ddb5xxx.h + * Copyright 2001 MontaVista Software Inc. + * + * 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 MARKEINS_H +#define MARKEINS_H + +#define NUM_EMMA2RH_IRQ_SW 32 +#define NUM_EMMA2RH_IRQ_GPIO 32 + +#define EMMA2RH_SW_CASCADE (EMMA2RH_IRQ_INT7 - EMMA2RH_IRQ_INT0) +#define EMMA2RH_GPIO_CASCADE (EMMA2RH_IRQ_INT46 - EMMA2RH_IRQ_INT0) + +#define EMMA2RH_SW_IRQ_BASE (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ) +#define EMMA2RH_GPIO_IRQ_BASE (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW) + +#define EMMA2RH_SW_IRQ_INT0 (0+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT1 (1+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT2 (2+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT3 (3+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT4 (4+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT5 (5+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT6 (6+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT7 (7+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT8 (8+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT9 (9+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT10 (10+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT11 (11+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT12 (12+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT13 (13+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT14 (14+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT15 (15+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT16 (16+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT17 (17+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT18 (18+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT19 (19+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT20 (20+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT21 (21+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT22 (22+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT23 (23+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT24 (24+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT25 (25+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT26 (26+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT27 (27+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT28 (28+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT29 (29+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT30 (30+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT31 (31+EMMA2RH_SW_IRQ_BASE) + +#define MARKEINS_PCI_IRQ_INTA EMMA2RH_GPIO_IRQ_BASE+15 +#define MARKEINS_PCI_IRQ_INTB EMMA2RH_GPIO_IRQ_BASE+16 +#define MARKEINS_PCI_IRQ_INTC EMMA2RH_GPIO_IRQ_BASE+17 +#define MARKEINS_PCI_IRQ_INTD EMMA2RH_GPIO_IRQ_BASE+18 + +#endif /* CONFIG_MARKEINS */ diff --git a/arch/mips/include/asm/errno.h b/arch/mips/include/asm/errno.h new file mode 100644 index 00000000000..3c0d840e457 --- /dev/null +++ b/arch/mips/include/asm/errno.h @@ -0,0 +1,131 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999, 2001, 2002 by Ralf Baechle + */ +#ifndef _ASM_ERRNO_H +#define _ASM_ERRNO_H + +/* + * These error numbers are intended to be MIPS ABI compatible + */ + +#include + +#define ENOMSG 35 /* No message of desired type */ +#define EIDRM 36 /* Identifier removed */ +#define ECHRNG 37 /* Channel number out of range */ +#define EL2NSYNC 38 /* Level 2 not synchronized */ +#define EL3HLT 39 /* Level 3 halted */ +#define EL3RST 40 /* Level 3 reset */ +#define ELNRNG 41 /* Link number out of range */ +#define EUNATCH 42 /* Protocol driver not attached */ +#define ENOCSI 43 /* No CSI structure available */ +#define EL2HLT 44 /* Level 2 halted */ +#define EDEADLK 45 /* Resource deadlock would occur */ +#define ENOLCK 46 /* No record locks available */ +#define EBADE 50 /* Invalid exchange */ +#define EBADR 51 /* Invalid request descriptor */ +#define EXFULL 52 /* Exchange full */ +#define ENOANO 53 /* No anode */ +#define EBADRQC 54 /* Invalid request code */ +#define EBADSLT 55 /* Invalid slot */ +#define EDEADLOCK 56 /* File locking deadlock error */ +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EDOTDOT 73 /* RFS specific error */ +#define EMULTIHOP 74 /* Multihop attempted */ +#define EBADMSG 77 /* Not a data message */ +#define ENAMETOOLONG 78 /* File name too long */ +#define EOVERFLOW 79 /* Value too large for defined data type */ +#define ENOTUNIQ 80 /* Name not unique on network */ +#define EBADFD 81 /* File descriptor in bad state */ +#define EREMCHG 82 /* Remote address changed */ +#define ELIBACC 83 /* Can not access a needed shared library */ +#define ELIBBAD 84 /* Accessing a corrupted shared library */ +#define ELIBSCN 85 /* .lib section in a.out corrupted */ +#define ELIBMAX 86 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 87 /* Cannot exec a shared library directly */ +#define EILSEQ 88 /* Illegal byte sequence */ +#define ENOSYS 89 /* Function not implemented */ +#define ELOOP 90 /* Too many symbolic links encountered */ +#define ERESTART 91 /* Interrupted system call should be restarted */ +#define ESTRPIPE 92 /* Streams pipe error */ +#define ENOTEMPTY 93 /* Directory not empty */ +#define EUSERS 94 /* Too many users */ +#define ENOTSOCK 95 /* Socket operation on non-socket */ +#define EDESTADDRREQ 96 /* Destination address required */ +#define EMSGSIZE 97 /* Message too long */ +#define EPROTOTYPE 98 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 99 /* Protocol not available */ +#define EPROTONOSUPPORT 120 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 121 /* Socket type not supported */ +#define EOPNOTSUPP 122 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 123 /* Protocol family not supported */ +#define EAFNOSUPPORT 124 /* Address family not supported by protocol */ +#define EADDRINUSE 125 /* Address already in use */ +#define EADDRNOTAVAIL 126 /* Cannot assign requested address */ +#define ENETDOWN 127 /* Network is down */ +#define ENETUNREACH 128 /* Network is unreachable */ +#define ENETRESET 129 /* Network dropped connection because of reset */ +#define ECONNABORTED 130 /* Software caused connection abort */ +#define ECONNRESET 131 /* Connection reset by peer */ +#define ENOBUFS 132 /* No buffer space available */ +#define EISCONN 133 /* Transport endpoint is already connected */ +#define ENOTCONN 134 /* Transport endpoint is not connected */ +#define EUCLEAN 135 /* Structure needs cleaning */ +#define ENOTNAM 137 /* Not a XENIX named type file */ +#define ENAVAIL 138 /* No XENIX semaphores available */ +#define EISNAM 139 /* Is a named type file */ +#define EREMOTEIO 140 /* Remote I/O error */ +#define EINIT 141 /* Reserved */ +#define EREMDEV 142 /* Error 142 */ +#define ESHUTDOWN 143 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 144 /* Too many references: cannot splice */ +#define ETIMEDOUT 145 /* Connection timed out */ +#define ECONNREFUSED 146 /* Connection refused */ +#define EHOSTDOWN 147 /* Host is down */ +#define EHOSTUNREACH 148 /* No route to host */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EALREADY 149 /* Operation already in progress */ +#define EINPROGRESS 150 /* Operation now in progress */ +#define ESTALE 151 /* Stale NFS file handle */ +#define ECANCELED 158 /* AIO operation canceled */ + +/* + * These error are Linux extensions. + */ +#define ENOMEDIUM 159 /* No medium found */ +#define EMEDIUMTYPE 160 /* Wrong medium type */ +#define ENOKEY 161 /* Required key not available */ +#define EKEYEXPIRED 162 /* Key has expired */ +#define EKEYREVOKED 163 /* Key has been revoked */ +#define EKEYREJECTED 164 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 165 /* Owner died */ +#define ENOTRECOVERABLE 166 /* State not recoverable */ + +#define EDQUOT 1133 /* Quota exceeded */ + +#ifdef __KERNEL__ + +/* The biggest error number defined here or in . */ +#define EMAXERRNO 1133 + +#endif /* __KERNEL__ */ + +#endif /* _ASM_ERRNO_H */ diff --git a/arch/mips/include/asm/fb.h b/arch/mips/include/asm/fb.h new file mode 100644 index 00000000000..bd3f68c9ddf --- /dev/null +++ b/arch/mips/include/asm/fb.h @@ -0,0 +1,19 @@ +#ifndef _ASM_FB_H_ +#define _ASM_FB_H_ + +#include +#include +#include + +static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, + unsigned long off) +{ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +} + +static inline int fb_is_primary_device(struct fb_info *info) +{ + return 0; +} + +#endif /* _ASM_FB_H_ */ diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h new file mode 100644 index 00000000000..2a52333a062 --- /dev/null +++ b/arch/mips/include/asm/fcntl.h @@ -0,0 +1,61 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 97, 98, 99, 2003, 05 Ralf Baechle + */ +#ifndef _ASM_FCNTL_H +#define _ASM_FCNTL_H + + +#define O_APPEND 0x0008 +#define O_SYNC 0x0010 +#define O_NONBLOCK 0x0080 +#define O_CREAT 0x0100 /* not fcntl */ +#define O_TRUNC 0x0200 /* not fcntl */ +#define O_EXCL 0x0400 /* not fcntl */ +#define O_NOCTTY 0x0800 /* not fcntl */ +#define FASYNC 0x1000 /* fcntl, for BSD compatibility */ +#define O_LARGEFILE 0x2000 /* allow large file opens */ +#define O_DIRECT 0x8000 /* direct disk access hint */ + +#define F_GETLK 14 +#define F_SETLK 6 +#define F_SETLKW 7 + +#define F_SETOWN 24 /* for sockets. */ +#define F_GETOWN 23 /* for sockets. */ + +#ifndef __mips64 +#define F_GETLK64 33 /* using 'struct flock64' */ +#define F_SETLK64 34 +#define F_SETLKW64 35 +#endif + +/* + * The flavours of struct flock. "struct flock" is the ABI compliant + * variant. Finally struct flock64 is the LFS variant of struct flock. As + * a historic accident and inconsistence with the ABI definition it doesn't + * contain all the same fields as struct flock. + */ + +#ifdef CONFIG_32BIT + +struct flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + long l_sysid; + __kernel_pid_t l_pid; + long pad[4]; +}; + +#define HAVE_ARCH_STRUCT_FLOCK + +#endif /* CONFIG_32BIT */ + +#include + +#endif /* _ASM_FCNTL_H */ diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h new file mode 100644 index 00000000000..9cc8522a394 --- /dev/null +++ b/arch/mips/include/asm/fixmap.h @@ -0,0 +1,118 @@ +/* + * fixmap.h: compile-time virtual memory allocation + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998 Ingo Molnar + * + * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 + */ + +#ifndef _ASM_FIXMAP_H +#define _ASM_FIXMAP_H + +#include +#ifdef CONFIG_HIGHMEM +#include +#include +#endif + +/* + * Here we define all the compile-time 'special' virtual + * addresses. The point is to have a constant address at + * compile time, but to set the physical address only + * in the boot process. We allocate these special addresses + * from the end of virtual memory (0xfffff000) backwards. + * Also this lets us do fail-safe vmalloc(), we + * can guarantee that these special addresses and + * vmalloc()-ed addresses never overlap. + * + * these 'compile-time allocated' memory buffers are + * fixed-size 4k pages. (or larger if used with an increment + * highger than 1) use fixmap_set(idx,phys) to associate + * physical memory with fixmap indices. + * + * TLB entries of such buffers will not be flushed across + * task switches. + */ + +/* + * on UP currently we will have no trace of the fixmap mechanizm, + * no page table allocations, etc. This might change in the + * future, say framebuffers for the console driver(s) could be + * fix-mapped? + */ +enum fixed_addresses { +#define FIX_N_COLOURS 8 + FIX_CMAP_BEGIN, +#ifdef CONFIG_MIPS_MT_SMTC + FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS), +#else + FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS, +#endif +#ifdef CONFIG_HIGHMEM + /* reserved pte's for temporary kernel mappings */ + FIX_KMAP_BEGIN = FIX_CMAP_END + 1, + FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, +#endif + __end_of_fixed_addresses +}; + +/* + * used by vmalloc.c. + * + * Leave one empty page between vmalloc'ed areas and + * the start of the fixmap, and leave one page empty + * at the top of mem.. + */ +#if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX) +#define FIXADDR_TOP ((unsigned long)(long)(int)(0xff000000 - 0x20000)) +#else +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) +#endif +#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) +#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) + +#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) +#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) + +extern void __this_fixmap_does_not_exist(void); + +/* + * 'index to address' translation. If anyone tries to use the idx + * directly without tranlation, we catch the bug with a NULL-deference + * kernel oops. Illegal ranges of incoming indices are caught too. + */ +static inline unsigned long fix_to_virt(const unsigned int idx) +{ + /* + * this branch gets completely eliminated after inlining, + * except when someone tries to use fixaddr indices in an + * illegal way. (such as mixing up address types or using + * out-of-range indices). + * + * If it doesn't get removed, the linker will complain + * loudly with a reasonably clear error message.. + */ + if (idx >= __end_of_fixed_addresses) + __this_fixmap_does_not_exist(); + + return __fix_to_virt(idx); +} + +static inline unsigned long virt_to_fix(const unsigned long vaddr) +{ + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); + return __virt_to_fix(vaddr); +} + +/* + * Called from pgtable_init() + */ +extern void fixrange_init(unsigned long start, unsigned long end, + pgd_t *pgd_base); + + +#endif diff --git a/arch/mips/include/asm/floppy.h b/arch/mips/include/asm/floppy.h new file mode 100644 index 00000000000..992d232adc8 --- /dev/null +++ b/arch/mips/include/asm/floppy.h @@ -0,0 +1,56 @@ +/* + * Architecture specific parts of the Floppy driver + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995 - 2000 Ralf Baechle + */ +#ifndef _ASM_FLOPPY_H +#define _ASM_FLOPPY_H + +#include + +static inline void fd_cacheflush(char * addr, long size) +{ + dma_cache_sync(NULL, addr, size, DMA_BIDIRECTIONAL); +} + +#define MAX_BUFFER_SECTORS 24 + + +/* + * And on Mips's the CMOS info fails also ... + * + * FIXME: This information should come from the ARC configuration tree + * or whereever a particular machine has stored this ... + */ +#define FLOPPY0_TYPE fd_drive_type(0) +#define FLOPPY1_TYPE fd_drive_type(1) + +#define FDC1 fd_getfdaddr1(); + +#define N_FDC 1 /* do you *really* want a second controller? */ +#define N_DRIVE 8 + +/* + * The DMA channel used by the floppy controller cannot access data at + * addresses >= 16MB + * + * Went back to the 1MB limit, as some people had problems with the floppy + * driver otherwise. It doesn't matter much for performance anyway, as most + * floppy accesses go through the track buffer. + * + * On MIPSes using vdma, this actually means that *all* transfers go thru + * the * track buffer since 0x1000000 is always smaller than KSEG0/1. + * Actually this needs to be a bit more complicated since the so much different + * hardware available with MIPS CPUs ... + */ +#define CROSS_64KB(a, s) ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64) + +#define EXTRA_FLOPPY_PARAMS + +#include + +#endif /* _ASM_FLOPPY_H */ diff --git a/arch/mips/include/asm/fpregdef.h b/arch/mips/include/asm/fpregdef.h new file mode 100644 index 00000000000..2b5fddc8f48 --- /dev/null +++ b/arch/mips/include/asm/fpregdef.h @@ -0,0 +1,99 @@ +/* + * Definitions for the FPU register names + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 Ralf Baechle + * Copyright (C) 1985 MIPS Computer Systems, Inc. + * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_FPREGDEF_H +#define _ASM_FPREGDEF_H + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + +/* + * These definitions only cover the R3000-ish 16/32 register model. + * But we're trying to be R3000 friendly anyway ... + */ +#define fv0 $f0 /* return value */ +#define fv0f $f1 +#define fv1 $f2 +#define fv1f $f3 +#define fa0 $f12 /* argument registers */ +#define fa0f $f13 +#define fa1 $f14 +#define fa1f $f15 +#define ft0 $f4 /* caller saved */ +#define ft0f $f5 +#define ft1 $f6 +#define ft1f $f7 +#define ft2 $f8 +#define ft2f $f9 +#define ft3 $f10 +#define ft3f $f11 +#define ft4 $f16 +#define ft4f $f17 +#define ft5 $f18 +#define ft5f $f19 +#define fs0 $f20 /* callee saved */ +#define fs0f $f21 +#define fs1 $f22 +#define fs1f $f23 +#define fs2 $f24 +#define fs2f $f25 +#define fs3 $f26 +#define fs3f $f27 +#define fs4 $f28 +#define fs4f $f29 +#define fs5 $f30 +#define fs5f $f31 + +#define fcr31 $31 /* FPU status register */ + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ + +#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 + +#define fv0 $f0 /* return value */ +#define fv1 $f2 +#define fa0 $f12 /* argument registers */ +#define fa1 $f13 +#define fa2 $f14 +#define fa3 $f15 +#define fa4 $f16 +#define fa5 $f17 +#define fa6 $f18 +#define fa7 $f19 +#define ft0 $f4 /* caller saved */ +#define ft1 $f5 +#define ft2 $f6 +#define ft3 $f7 +#define ft4 $f8 +#define ft5 $f9 +#define ft6 $f10 +#define ft7 $f11 +#define ft8 $f20 +#define ft9 $f21 +#define ft10 $f22 +#define ft11 $f23 +#define ft12 $f1 +#define ft13 $f3 +#define fs0 $f24 /* callee saved */ +#define fs1 $f25 +#define fs2 $f26 +#define fs3 $f27 +#define fs4 $f28 +#define fs5 $f29 +#define fs6 $f30 +#define fs7 $f31 + +#define fcr31 $31 + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */ + +#endif /* _ASM_FPREGDEF_H */ diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h new file mode 100644 index 00000000000..8a3ef247659 --- /dev/null +++ b/arch/mips/include/asm/fpu.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2002 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * 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. + */ +#ifndef _ASM_FPU_H +#define _ASM_FPU_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MIPS_MT_FPAFF +#include +#endif + +struct sigcontext; +struct sigcontext32; + +extern asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); +extern asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); + +extern asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); +extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); + +extern void fpu_emulator_init_fpu(void); +extern int fpu_emulator_save_context(struct sigcontext __user *sc); +extern int fpu_emulator_restore_context(struct sigcontext __user *sc); +extern void _init_fpu(void); +extern void _save_fp(struct task_struct *); +extern void _restore_fp(struct task_struct *); + +#define __enable_fpu() \ +do { \ + set_c0_status(ST0_CU1); \ + enable_fpu_hazard(); \ +} while (0) + +#define __disable_fpu() \ +do { \ + clear_c0_status(ST0_CU1); \ + disable_fpu_hazard(); \ +} while (0) + +#define enable_fpu() \ +do { \ + if (cpu_has_fpu) \ + __enable_fpu(); \ +} while (0) + +#define disable_fpu() \ +do { \ + if (cpu_has_fpu) \ + __disable_fpu(); \ +} while (0) + + +#define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) + +static inline int __is_fpu_owner(void) +{ + return test_thread_flag(TIF_USEDFPU); +} + +static inline int is_fpu_owner(void) +{ + return cpu_has_fpu && __is_fpu_owner(); +} + +static inline void __own_fpu(void) +{ + __enable_fpu(); + KSTK_STATUS(current) |= ST0_CU1; + set_thread_flag(TIF_USEDFPU); +} + +static inline void own_fpu_inatomic(int restore) +{ + if (cpu_has_fpu && !__is_fpu_owner()) { + __own_fpu(); + if (restore) + _restore_fp(current); + } +} + +static inline void own_fpu(int restore) +{ + preempt_disable(); + own_fpu_inatomic(restore); + preempt_enable(); +} + +static inline void lose_fpu(int save) +{ + preempt_disable(); + if (is_fpu_owner()) { + if (save) + _save_fp(current); + KSTK_STATUS(current) &= ~ST0_CU1; + clear_thread_flag(TIF_USEDFPU); + __disable_fpu(); + } + preempt_enable(); +} + +static inline void init_fpu(void) +{ + preempt_disable(); + if (cpu_has_fpu) { + __own_fpu(); + _init_fpu(); + } else { + fpu_emulator_init_fpu(); + } + preempt_enable(); +} + +static inline void save_fp(struct task_struct *tsk) +{ + if (cpu_has_fpu) + _save_fp(tsk); +} + +static inline void restore_fp(struct task_struct *tsk) +{ + if (cpu_has_fpu) + _restore_fp(tsk); +} + +static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) +{ + if (tsk == current) { + preempt_disable(); + if (is_fpu_owner()) + _save_fp(current); + preempt_enable(); + } + + return tsk->thread.fpu.fpr; +} + +#endif /* _ASM_FPU_H */ diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h new file mode 100644 index 00000000000..2731c38bd7a --- /dev/null +++ b/arch/mips/include/asm/fpu_emulator.h @@ -0,0 +1,37 @@ +/* + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Further private data for which no space exists in mips_fpu_struct. + * This should be subsumed into the mips_fpu_struct structure as + * defined in processor.h as soon as the absurd wired absolute assembler + * offsets become dynamic at compile time. + * + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + */ +#ifndef _ASM_FPU_EMULATOR_H +#define _ASM_FPU_EMULATOR_H + +struct mips_fpu_emulator_stats { + unsigned int emulated; + unsigned int loads; + unsigned int stores; + unsigned int cp1ops; + unsigned int cp1xops; + unsigned int errors; +}; + +extern struct mips_fpu_emulator_stats fpuemustats; + +#endif /* _ASM_FPU_EMULATOR_H */ diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h new file mode 100644 index 00000000000..b9cce90346c --- /dev/null +++ b/arch/mips/include/asm/futex.h @@ -0,0 +1,203 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2006 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef _ASM_FUTEX_H +#define _ASM_FUTEX_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ +{ \ + if (cpu_has_llsc && R10000_LLSC_WAR) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: ll %1, %4 # __futex_atomic_op \n" \ + " .set mips0 \n" \ + " " insn " \n" \ + " .set mips3 \n" \ + "2: sc $1, %2 \n" \ + " beqzl $1, 1b \n" \ + __WEAK_LLSC_MB \ + "3: \n" \ + " .set pop \n" \ + " .set mips0 \n" \ + " .section .fixup,\"ax\" \n" \ + "4: li %0, %6 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " "__UA_ADDR "\t1b, 4b \n" \ + " "__UA_ADDR "\t2b, 4b \n" \ + " .previous \n" \ + : "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \ + : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \ + : "memory"); \ + } else if (cpu_has_llsc) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: ll %1, %4 # __futex_atomic_op \n" \ + " .set mips0 \n" \ + " " insn " \n" \ + " .set mips3 \n" \ + "2: sc $1, %2 \n" \ + " beqz $1, 1b \n" \ + __WEAK_LLSC_MB \ + "3: \n" \ + " .set pop \n" \ + " .set mips0 \n" \ + " .section .fixup,\"ax\" \n" \ + "4: li %0, %6 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " "__UA_ADDR "\t1b, 4b \n" \ + " "__UA_ADDR "\t2b, 4b \n" \ + " .previous \n" \ + : "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \ + : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \ + : "memory"); \ + } else \ + ret = -ENOSYS; \ +} + +static inline int +futex_atomic_op_inuser(int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + pagefault_disable(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("move $1, %z5", ret, oldval, uaddr, oparg); + break; + + case FUTEX_OP_ADD: + __futex_atomic_op("addu $1, %1, %z5", + ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or $1, %1, %z5", + ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("and $1, %1, %z5", + ret, oldval, uaddr, ~oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor $1, %1, %z5", + ret, oldval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + pagefault_enable(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; + case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; + case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; + case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; + case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; + case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; + default: ret = -ENOSYS; + } + } + return ret; +} + +static inline int +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) +{ + int retval; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + "# futex_atomic_cmpxchg_inatomic \n" + " .set push \n" + " .set noat \n" + " .set mips3 \n" + "1: ll %0, %2 \n" + " bne %0, %z3, 3f \n" + " .set mips0 \n" + " move $1, %z4 \n" + " .set mips3 \n" + "2: sc $1, %1 \n" + " beqzl $1, 1b \n" + __WEAK_LLSC_MB + "3: \n" + " .set pop \n" + " .section .fixup,\"ax\" \n" + "4: li %0, %5 \n" + " j 3b \n" + " .previous \n" + " .section __ex_table,\"a\" \n" + " "__UA_ADDR "\t1b, 4b \n" + " "__UA_ADDR "\t2b, 4b \n" + " .previous \n" + : "=&r" (retval), "=R" (*uaddr) + : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) + : "memory"); + } else if (cpu_has_llsc) { + __asm__ __volatile__( + "# futex_atomic_cmpxchg_inatomic \n" + " .set push \n" + " .set noat \n" + " .set mips3 \n" + "1: ll %0, %2 \n" + " bne %0, %z3, 3f \n" + " .set mips0 \n" + " move $1, %z4 \n" + " .set mips3 \n" + "2: sc $1, %1 \n" + " beqz $1, 1b \n" + __WEAK_LLSC_MB + "3: \n" + " .set pop \n" + " .section .fixup,\"ax\" \n" + "4: li %0, %5 \n" + " j 3b \n" + " .previous \n" + " .section __ex_table,\"a\" \n" + " "__UA_ADDR "\t1b, 4b \n" + " "__UA_ADDR "\t2b, 4b \n" + " .previous \n" + : "=&r" (retval), "=R" (*uaddr) + : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) + : "memory"); + } else + return -ENOSYS; + + return retval; +} + +#endif +#endif /* _ASM_FUTEX_H */ diff --git a/arch/mips/include/asm/fw/arc/hinv.h b/arch/mips/include/asm/fw/arc/hinv.h new file mode 100644 index 00000000000..e6ff4add04e --- /dev/null +++ b/arch/mips/include/asm/fw/arc/hinv.h @@ -0,0 +1,175 @@ +/* + * ARCS hardware/memory inventory/configuration and system ID definitions. + */ +#ifndef _ASM_ARC_HINV_H +#define _ASM_ARC_HINV_H + +#include +#include + +/* configuration query defines */ +typedef enum configclass { + SystemClass, + ProcessorClass, + CacheClass, +#ifndef _NT_PROM + MemoryClass, + AdapterClass, + ControllerClass, + PeripheralClass +#else /* _NT_PROM */ + AdapterClass, + ControllerClass, + PeripheralClass, + MemoryClass +#endif /* _NT_PROM */ +} CONFIGCLASS; + +typedef enum configtype { + ARC, + CPU, + FPU, + PrimaryICache, + PrimaryDCache, + SecondaryICache, + SecondaryDCache, + SecondaryCache, +#ifndef _NT_PROM + Memory, +#endif + EISAAdapter, + TCAdapter, + SCSIAdapter, + DTIAdapter, + MultiFunctionAdapter, + DiskController, + TapeController, + CDROMController, + WORMController, + SerialController, + NetworkController, + DisplayController, + ParallelController, + PointerController, + KeyboardController, + AudioController, + OtherController, + DiskPeripheral, + FloppyDiskPeripheral, + TapePeripheral, + ModemPeripheral, + MonitorPeripheral, + PrinterPeripheral, + PointerPeripheral, + KeyboardPeripheral, + TerminalPeripheral, + LinePeripheral, + NetworkPeripheral, +#ifdef _NT_PROM + Memory, +#endif + OtherPeripheral, + + /* new stuff for IP30 */ + /* added without moving anything */ + /* except ANONYMOUS. */ + + XTalkAdapter, + PCIAdapter, + GIOAdapter, + TPUAdapter, + + Anonymous +} CONFIGTYPE; + +typedef enum { + Failed = 1, + ReadOnly = 2, + Removable = 4, + ConsoleIn = 8, + ConsoleOut = 16, + Input = 32, + Output = 64 +} IDENTIFIERFLAG; + +#ifndef NULL /* for GetChild(NULL); */ +#define NULL 0 +#endif + +union key_u { + struct { +#ifdef _MIPSEB + unsigned char c_bsize; /* block size in lines */ + unsigned char c_lsize; /* line size in bytes/tag */ + unsigned short c_size; /* cache size in 4K pages */ +#else /* _MIPSEL */ + unsigned short c_size; /* cache size in 4K pages */ + unsigned char c_lsize; /* line size in bytes/tag */ + unsigned char c_bsize; /* block size in lines */ +#endif /* _MIPSEL */ + } cache; + ULONG FullKey; +}; + +#if _MIPS_SIM == _MIPS_SIM_ABI64 +#define SGI_ARCS_VERS 64 /* sgi 64-bit version */ +#define SGI_ARCS_REV 0 /* rev .00 */ +#else +#define SGI_ARCS_VERS 1 /* first version */ +#define SGI_ARCS_REV 10 /* rev .10, 3/04/92 */ +#endif + +typedef struct component { + CONFIGCLASS Class; + CONFIGTYPE Type; + IDENTIFIERFLAG Flags; + USHORT Version; + USHORT Revision; + ULONG Key; + ULONG AffinityMask; + ULONG ConfigurationDataSize; + ULONG IdentifierLength; + char *Identifier; +} COMPONENT; + +/* internal structure that holds pathname parsing data */ +struct cfgdata { + char *name; /* full name */ + int minlen; /* minimum length to match */ + CONFIGTYPE type; /* type of token */ +}; + +/* System ID */ +typedef struct systemid { + CHAR VendorId[8]; + CHAR ProductId[8]; +} SYSTEMID; + +/* memory query functions */ +typedef enum memorytype { + ExceptionBlock, + SPBPage, /* ARCS == SystemParameterBlock */ +#ifndef _NT_PROM + FreeContiguous, + FreeMemory, + BadMemory, + LoadedProgram, + FirmwareTemporary, + FirmwarePermanent +#else /* _NT_PROM */ + FreeMemory, + BadMemory, + LoadedProgram, + FirmwareTemporary, + FirmwarePermanent, + FreeContiguous +#endif /* _NT_PROM */ +} MEMORYTYPE; + +typedef struct memorydescriptor { + MEMORYTYPE Type; + LONG BasePage; + LONG PageCount; +} MEMORYDESCRIPTOR; + +#endif /* _ASM_ARC_HINV_H */ diff --git a/arch/mips/include/asm/fw/arc/types.h b/arch/mips/include/asm/fw/arc/types.h new file mode 100644 index 00000000000..b9adcd6f086 --- /dev/null +++ b/arch/mips/include/asm/fw/arc/types.h @@ -0,0 +1,86 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright 1999 Ralf Baechle (ralf@gnu.org) + * Copyright 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_ARC_TYPES_H +#define _ASM_ARC_TYPES_H + + +#ifdef CONFIG_ARC32 + +typedef char CHAR; +typedef short SHORT; +typedef long LARGE_INTEGER __attribute__ ((__mode__ (__DI__))); +typedef long LONG __attribute__ ((__mode__ (__SI__))); +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG __attribute__ ((__mode__ (__SI__))); +typedef void VOID; + +/* The pointer types. Note that we're using a 64-bit compiler but all + pointer in the ARC structures are only 32-bit, so we need some disgusting + workarounds. Keep your vomit bag handy. */ +typedef LONG _PCHAR; +typedef LONG _PSHORT; +typedef LONG _PLARGE_INTEGER; +typedef LONG _PLONG; +typedef LONG _PUCHAR; +typedef LONG _PUSHORT; +typedef LONG _PULONG; +typedef LONG _PVOID; + +#endif /* CONFIG_ARC32 */ + +#ifdef CONFIG_ARC64 + +typedef char CHAR; +typedef short SHORT; +typedef long LARGE_INTEGER __attribute__ ((__mode__ (__DI__))); +typedef long LONG __attribute__ ((__mode__ (__DI__))); +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG __attribute__ ((__mode__ (__DI__))); +typedef void VOID; + +/* The pointer types. We're 64-bit and the firmware is also 64-bit, so + live is sane ... */ +typedef CHAR *_PCHAR; +typedef SHORT *_PSHORT; +typedef LARGE_INTEGER *_PLARGE_INTEGER; +typedef LONG *_PLONG; +typedef UCHAR *_PUCHAR; +typedef USHORT *_PUSHORT; +typedef ULONG *_PULONG; +typedef VOID *_PVOID; + +#endif /* CONFIG_ARC64 */ + +typedef CHAR *PCHAR; +typedef SHORT *PSHORT; +typedef LARGE_INTEGER *PLARGE_INTEGER; +typedef LONG *PLONG; +typedef UCHAR *PUCHAR; +typedef USHORT *PUSHORT; +typedef ULONG *PULONG; +typedef VOID *PVOID; + +/* + * Return type of ArcGetDisplayStatus() + */ +typedef struct { + USHORT CursorXPosition; + USHORT CursorYPosition; + USHORT CursorMaxXPosition; + USHORT CursorMaxYPosition; + USHORT ForegroundColor; + USHORT BackgroundColor; + UCHAR HighIntensity; + UCHAR Underscored; + UCHAR ReverseVideo; +} DISPLAY_STATUS; + +#endif /* _ASM_ARC_TYPES_H */ diff --git a/arch/mips/include/asm/fw/cfe/cfe_api.h b/arch/mips/include/asm/fw/cfe/cfe_api.h new file mode 100644 index 00000000000..0995575db32 --- /dev/null +++ b/arch/mips/include/asm/fw/cfe/cfe_api.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2000, 2001, 2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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. + */ +/* + * Broadcom Common Firmware Environment (CFE) + * + * This file contains declarations for doing callbacks to + * cfe from an application. It should be the only header + * needed by the application to use this library + * + * Authors: Mitch Lichtenberg, Chris Demetriou + */ +#ifndef CFE_API_H +#define CFE_API_H + +#include +#include + +typedef long intptr_t; + + +/* + * Constants + */ + +/* Seal indicating CFE's presence, passed to user program. */ +#define CFE_EPTSEAL 0x43464531 + +#define CFE_MI_RESERVED 0 /* memory is reserved, do not use */ +#define CFE_MI_AVAILABLE 1 /* memory is available */ + +#define CFE_FLG_WARMSTART 0x00000001 +#define CFE_FLG_FULL_ARENA 0x00000001 +#define CFE_FLG_ENV_PERMANENT 0x00000001 + +#define CFE_CPU_CMD_START 1 +#define CFE_CPU_CMD_STOP 0 + +#define CFE_STDHANDLE_CONSOLE 0 + +#define CFE_DEV_NETWORK 1 +#define CFE_DEV_DISK 2 +#define CFE_DEV_FLASH 3 +#define CFE_DEV_SERIAL 4 +#define CFE_DEV_CPU 5 +#define CFE_DEV_NVRAM 6 +#define CFE_DEV_CLOCK 7 +#define CFE_DEV_OTHER 8 +#define CFE_DEV_MASK 0x0F + +#define CFE_CACHE_FLUSH_D 1 +#define CFE_CACHE_INVAL_I 2 +#define CFE_CACHE_INVAL_D 4 +#define CFE_CACHE_INVAL_L2 8 + +#define CFE_FWI_64BIT 0x00000001 +#define CFE_FWI_32BIT 0x00000002 +#define CFE_FWI_RELOC 0x00000004 +#define CFE_FWI_UNCACHED 0x00000008 +#define CFE_FWI_MULTICPU 0x00000010 +#define CFE_FWI_FUNCSIM 0x00000020 +#define CFE_FWI_RTLSIM 0x00000040 + +typedef struct { + int64_t fwi_version; /* major, minor, eco version */ + int64_t fwi_totalmem; /* total installed mem */ + int64_t fwi_flags; /* various flags */ + int64_t fwi_boardid; /* board ID */ + int64_t fwi_bootarea_va; /* VA of boot area */ + int64_t fwi_bootarea_pa; /* PA of boot area */ + int64_t fwi_bootarea_size; /* size of boot area */ +} cfe_fwinfo_t; + + +/* + * Defines and prototypes for functions which take no arguments. + */ +int64_t cfe_getticks(void); + +/* + * Defines and prototypes for the rest of the functions. + */ +int cfe_close(int handle); +int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1); +int cfe_cpu_stop(int cpu); +int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen); +int cfe_enummem(int idx, int flags, uint64_t * start, uint64_t * length, + uint64_t * type); +int cfe_exit(int warm, int status); +int cfe_flushcache(int flg); +int cfe_getdevinfo(char *name); +int cfe_getenv(char *name, char *dest, int destlen); +int cfe_getfwinfo(cfe_fwinfo_t * info); +int cfe_getstdhandle(int flg); +int cfe_init(uint64_t handle, uint64_t ept); +int cfe_inpstat(int handle); +int cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, + int length, int *retlen, uint64_t offset); +int cfe_open(char *name); +int cfe_read(int handle, unsigned char *buffer, int length); +int cfe_readblk(int handle, int64_t offset, unsigned char *buffer, + int length); +int cfe_setenv(char *name, char *val); +int cfe_write(int handle, unsigned char *buffer, int length); +int cfe_writeblk(int handle, int64_t offset, unsigned char *buffer, + int length); + +#endif /* CFE_API_H */ diff --git a/arch/mips/include/asm/fw/cfe/cfe_error.h b/arch/mips/include/asm/fw/cfe/cfe_error.h new file mode 100644 index 00000000000..b8037463627 --- /dev/null +++ b/arch/mips/include/asm/fw/cfe/cfe_error.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2000, 2001, 2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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. + */ + +/* + * Broadcom Common Firmware Environment (CFE) + * + * CFE's global error code list is here. + * + * Author: Mitch Lichtenberg + */ + +#define CFE_OK 0 +#define CFE_ERR -1 /* generic error */ +#define CFE_ERR_INV_COMMAND -2 +#define CFE_ERR_EOF -3 +#define CFE_ERR_IOERR -4 +#define CFE_ERR_NOMEM -5 +#define CFE_ERR_DEVNOTFOUND -6 +#define CFE_ERR_DEVOPEN -7 +#define CFE_ERR_INV_PARAM -8 +#define CFE_ERR_ENVNOTFOUND -9 +#define CFE_ERR_ENVREADONLY -10 + +#define CFE_ERR_NOTELF -11 +#define CFE_ERR_NOT32BIT -12 +#define CFE_ERR_WRONGENDIAN -13 +#define CFE_ERR_BADELFVERS -14 +#define CFE_ERR_NOTMIPS -15 +#define CFE_ERR_BADELFFMT -16 +#define CFE_ERR_BADADDR -17 + +#define CFE_ERR_FILENOTFOUND -18 +#define CFE_ERR_UNSUPPORTED -19 + +#define CFE_ERR_HOSTUNKNOWN -20 + +#define CFE_ERR_TIMEOUT -21 + +#define CFE_ERR_PROTOCOLERR -22 + +#define CFE_ERR_NETDOWN -23 +#define CFE_ERR_NONAMESERVER -24 + +#define CFE_ERR_NOHANDLES -25 +#define CFE_ERR_ALREADYBOUND -26 + +#define CFE_ERR_CANNOTSET -27 +#define CFE_ERR_NOMORE -28 +#define CFE_ERR_BADFILESYS -29 +#define CFE_ERR_FSNOTAVAIL -30 + +#define CFE_ERR_INVBOOTBLOCK -31 +#define CFE_ERR_WRONGDEVTYPE -32 +#define CFE_ERR_BBCHECKSUM -33 +#define CFE_ERR_BOOTPROGCHKSUM -34 + +#define CFE_ERR_LDRNOTAVAIL -35 + +#define CFE_ERR_NOTREADY -36 + +#define CFE_ERR_GETMEM -37 +#define CFE_ERR_SETMEM -38 + +#define CFE_ERR_NOTCONN -39 +#define CFE_ERR_ADDRINUSE -40 diff --git a/arch/mips/include/asm/gcmpregs.h b/arch/mips/include/asm/gcmpregs.h new file mode 100644 index 00000000000..d74a8a4ca86 --- /dev/null +++ b/arch/mips/include/asm/gcmpregs.h @@ -0,0 +1,117 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000, 07 MIPS Technologies, Inc. + * + * Multiprocessor Subsystem Register Definitions + * + */ +#ifndef _ASM_GCMPREGS_H +#define _ASM_GCMPREGS_H + + +/* Offsets to major blocks within GCMP from GCMP base */ +#define GCMP_GCB_OFS 0x0000 /* Global Control Block */ +#define GCMP_CLCB_OFS 0x2000 /* Core Local Control Block */ +#define GCMP_COCB_OFS 0x4000 /* Core Other Control Block */ +#define GCMP_GDB_OFS 0x8000 /* Global Debug Block */ + +/* Offsets to individual GCMP registers from GCMP base */ +#define GCMPOFS(block, tag, reg) (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS) + +#define GCMPGCBOFS(reg) GCMPOFS(GCB, GCB, reg) +#define GCMPCLCBOFS(reg) GCMPOFS(CLCB, CCB, reg) +#define GCMPCOCBOFS(reg) GCMPOFS(COCB, CCB, reg) +#define GCMPGDBOFS(reg) GCMPOFS(GDB, GDB, reg) + +/* GCMP register access */ +#define GCMPGCB(reg) REGP(_gcmp_base, GCMPGCBOFS(reg)) +#define GCMPCLCB(reg) REGP(_gcmp_base, GCMPCLCBOFS(reg)) +#define GCMPCOCB(reg) REGP(_gcmp_base, GCMPCOCBOFS(reg)) +#define GCMPGDB(reg) REGP(_gcmp_base, GCMPGDBOFS(reg)) + +/* Mask generation */ +#define GCMPMSK(block, reg, bits) (MSK(bits)< + +#endif /* __ASM_MIPS_GPIO_H */ diff --git a/arch/mips/include/asm/gt64120.h b/arch/mips/include/asm/gt64120.h new file mode 100644 index 00000000000..e64b41093c4 --- /dev/null +++ b/arch/mips/include/asm/gt64120.h @@ -0,0 +1,580 @@ +/* + * Copyright (C) 2000, 2004, 2005 MIPS Technologies, Inc. + * All rights reserved. + * Authors: Carsten Langgaard + * Maciej W. Rozycki + * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_GT64120_H +#define _ASM_GT64120_H + +#include + +#include +#include + +#define MSK(n) ((1 << (n)) - 1) + +/* + * Register offset addresses + */ +/* CPU Configuration. */ +#define GT_CPU_OFS 0x000 + +#define GT_MULTI_OFS 0x120 + +/* CPU Address Decode. */ +#define GT_SCS10LD_OFS 0x008 +#define GT_SCS10HD_OFS 0x010 +#define GT_SCS32LD_OFS 0x018 +#define GT_SCS32HD_OFS 0x020 +#define GT_CS20LD_OFS 0x028 +#define GT_CS20HD_OFS 0x030 +#define GT_CS3BOOTLD_OFS 0x038 +#define GT_CS3BOOTHD_OFS 0x040 +#define GT_PCI0IOLD_OFS 0x048 +#define GT_PCI0IOHD_OFS 0x050 +#define GT_PCI0M0LD_OFS 0x058 +#define GT_PCI0M0HD_OFS 0x060 +#define GT_ISD_OFS 0x068 + +#define GT_PCI0M1LD_OFS 0x080 +#define GT_PCI0M1HD_OFS 0x088 +#define GT_PCI1IOLD_OFS 0x090 +#define GT_PCI1IOHD_OFS 0x098 +#define GT_PCI1M0LD_OFS 0x0a0 +#define GT_PCI1M0HD_OFS 0x0a8 +#define GT_PCI1M1LD_OFS 0x0b0 +#define GT_PCI1M1HD_OFS 0x0b8 +#define GT_PCI1M1LD_OFS 0x0b0 +#define GT_PCI1M1HD_OFS 0x0b8 + +#define GT_SCS10AR_OFS 0x0d0 +#define GT_SCS32AR_OFS 0x0d8 +#define GT_CS20R_OFS 0x0e0 +#define GT_CS3BOOTR_OFS 0x0e8 + +#define GT_PCI0IOREMAP_OFS 0x0f0 +#define GT_PCI0M0REMAP_OFS 0x0f8 +#define GT_PCI0M1REMAP_OFS 0x100 +#define GT_PCI1IOREMAP_OFS 0x108 +#define GT_PCI1M0REMAP_OFS 0x110 +#define GT_PCI1M1REMAP_OFS 0x118 + +/* CPU Error Report. */ +#define GT_CPUERR_ADDRLO_OFS 0x070 +#define GT_CPUERR_ADDRHI_OFS 0x078 + +#define GT_CPUERR_DATALO_OFS 0x128 /* GT-64120A only */ +#define GT_CPUERR_DATAHI_OFS 0x130 /* GT-64120A only */ +#define GT_CPUERR_PARITY_OFS 0x138 /* GT-64120A only */ + +/* CPU Sync Barrier. */ +#define GT_PCI0SYNC_OFS 0x0c0 +#define GT_PCI1SYNC_OFS 0x0c8 + +/* SDRAM and Device Address Decode. */ +#define GT_SCS0LD_OFS 0x400 +#define GT_SCS0HD_OFS 0x404 +#define GT_SCS1LD_OFS 0x408 +#define GT_SCS1HD_OFS 0x40c +#define GT_SCS2LD_OFS 0x410 +#define GT_SCS2HD_OFS 0x414 +#define GT_SCS3LD_OFS 0x418 +#define GT_SCS3HD_OFS 0x41c +#define GT_CS0LD_OFS 0x420 +#define GT_CS0HD_OFS 0x424 +#define GT_CS1LD_OFS 0x428 +#define GT_CS1HD_OFS 0x42c +#define GT_CS2LD_OFS 0x430 +#define GT_CS2HD_OFS 0x434 +#define GT_CS3LD_OFS 0x438 +#define GT_CS3HD_OFS 0x43c +#define GT_BOOTLD_OFS 0x440 +#define GT_BOOTHD_OFS 0x444 + +#define GT_ADERR_OFS 0x470 + +/* SDRAM Configuration. */ +#define GT_SDRAM_CFG_OFS 0x448 + +#define GT_SDRAM_OPMODE_OFS 0x474 +#define GT_SDRAM_BM_OFS 0x478 +#define GT_SDRAM_ADDRDECODE_OFS 0x47c + +/* SDRAM Parameters. */ +#define GT_SDRAM_B0_OFS 0x44c +#define GT_SDRAM_B1_OFS 0x450 +#define GT_SDRAM_B2_OFS 0x454 +#define GT_SDRAM_B3_OFS 0x458 + +/* Device Parameters. */ +#define GT_DEV_B0_OFS 0x45c +#define GT_DEV_B1_OFS 0x460 +#define GT_DEV_B2_OFS 0x464 +#define GT_DEV_B3_OFS 0x468 +#define GT_DEV_BOOT_OFS 0x46c + +/* ECC. */ +#define GT_ECC_ERRDATALO 0x480 /* GT-64120A only */ +#define GT_ECC_ERRDATAHI 0x484 /* GT-64120A only */ +#define GT_ECC_MEM 0x488 /* GT-64120A only */ +#define GT_ECC_CALC 0x48c /* GT-64120A only */ +#define GT_ECC_ERRADDR 0x490 /* GT-64120A only */ + +/* DMA Record. */ +#define GT_DMA0_CNT_OFS 0x800 +#define GT_DMA1_CNT_OFS 0x804 +#define GT_DMA2_CNT_OFS 0x808 +#define GT_DMA3_CNT_OFS 0x80c +#define GT_DMA0_SA_OFS 0x810 +#define GT_DMA1_SA_OFS 0x814 +#define GT_DMA2_SA_OFS 0x818 +#define GT_DMA3_SA_OFS 0x81c +#define GT_DMA0_DA_OFS 0x820 +#define GT_DMA1_DA_OFS 0x824 +#define GT_DMA2_DA_OFS 0x828 +#define GT_DMA3_DA_OFS 0x82c +#define GT_DMA0_NEXT_OFS 0x830 +#define GT_DMA1_NEXT_OFS 0x834 +#define GT_DMA2_NEXT_OFS 0x838 +#define GT_DMA3_NEXT_OFS 0x83c + +#define GT_DMA0_CUR_OFS 0x870 +#define GT_DMA1_CUR_OFS 0x874 +#define GT_DMA2_CUR_OFS 0x878 +#define GT_DMA3_CUR_OFS 0x87c + +/* DMA Channel Control. */ +#define GT_DMA0_CTRL_OFS 0x840 +#define GT_DMA1_CTRL_OFS 0x844 +#define GT_DMA2_CTRL_OFS 0x848 +#define GT_DMA3_CTRL_OFS 0x84c + +/* DMA Arbiter. */ +#define GT_DMA_ARB_OFS 0x860 + +/* Timer/Counter. */ +#define GT_TC0_OFS 0x850 +#define GT_TC1_OFS 0x854 +#define GT_TC2_OFS 0x858 +#define GT_TC3_OFS 0x85c + +#define GT_TC_CONTROL_OFS 0x864 + +/* PCI Internal. */ +#define GT_PCI0_CMD_OFS 0xc00 +#define GT_PCI0_TOR_OFS 0xc04 +#define GT_PCI0_BS_SCS10_OFS 0xc08 +#define GT_PCI0_BS_SCS32_OFS 0xc0c +#define GT_PCI0_BS_CS20_OFS 0xc10 +#define GT_PCI0_BS_CS3BT_OFS 0xc14 + +#define GT_PCI1_IACK_OFS 0xc30 +#define GT_PCI0_IACK_OFS 0xc34 + +#define GT_PCI0_BARE_OFS 0xc3c +#define GT_PCI0_PREFMBR_OFS 0xc40 + +#define GT_PCI0_SCS10_BAR_OFS 0xc48 +#define GT_PCI0_SCS32_BAR_OFS 0xc4c +#define GT_PCI0_CS20_BAR_OFS 0xc50 +#define GT_PCI0_CS3BT_BAR_OFS 0xc54 +#define GT_PCI0_SSCS10_BAR_OFS 0xc58 +#define GT_PCI0_SSCS32_BAR_OFS 0xc5c + +#define GT_PCI0_SCS3BT_BAR_OFS 0xc64 + +#define GT_PCI1_CMD_OFS 0xc80 +#define GT_PCI1_TOR_OFS 0xc84 +#define GT_PCI1_BS_SCS10_OFS 0xc88 +#define GT_PCI1_BS_SCS32_OFS 0xc8c +#define GT_PCI1_BS_CS20_OFS 0xc90 +#define GT_PCI1_BS_CS3BT_OFS 0xc94 + +#define GT_PCI1_BARE_OFS 0xcbc +#define GT_PCI1_PREFMBR_OFS 0xcc0 + +#define GT_PCI1_SCS10_BAR_OFS 0xcc8 +#define GT_PCI1_SCS32_BAR_OFS 0xccc +#define GT_PCI1_CS20_BAR_OFS 0xcd0 +#define GT_PCI1_CS3BT_BAR_OFS 0xcd4 +#define GT_PCI1_SSCS10_BAR_OFS 0xcd8 +#define GT_PCI1_SSCS32_BAR_OFS 0xcdc + +#define GT_PCI1_SCS3BT_BAR_OFS 0xce4 + +#define GT_PCI1_CFGADDR_OFS 0xcf0 +#define GT_PCI1_CFGDATA_OFS 0xcf4 +#define GT_PCI0_CFGADDR_OFS 0xcf8 +#define GT_PCI0_CFGDATA_OFS 0xcfc + +/* Interrupts. */ +#define GT_INTRCAUSE_OFS 0xc18 +#define GT_INTRMASK_OFS 0xc1c + +#define GT_PCI0_ICMASK_OFS 0xc24 +#define GT_PCI0_SERR0MASK_OFS 0xc28 + +#define GT_CPU_INTSEL_OFS 0xc70 +#define GT_PCI0_INTSEL_OFS 0xc74 + +#define GT_HINTRCAUSE_OFS 0xc98 +#define GT_HINTRMASK_OFS 0xc9c + +#define GT_PCI0_HICMASK_OFS 0xca4 +#define GT_PCI1_SERR1MASK_OFS 0xca8 + + +/* + * I2O Support Registers + */ +#define INBOUND_MESSAGE_REGISTER0_PCI_SIDE 0x010 +#define INBOUND_MESSAGE_REGISTER1_PCI_SIDE 0x014 +#define OUTBOUND_MESSAGE_REGISTER0_PCI_SIDE 0x018 +#define OUTBOUND_MESSAGE_REGISTER1_PCI_SIDE 0x01c +#define INBOUND_DOORBELL_REGISTER_PCI_SIDE 0x020 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_PCI_SIDE 0x024 +#define INBOUND_INTERRUPT_MASK_REGISTER_PCI_SIDE 0x028 +#define OUTBOUND_DOORBELL_REGISTER_PCI_SIDE 0x02c +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_PCI_SIDE 0x030 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_PCI_SIDE 0x034 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI_SIDE 0x040 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI_SIDE 0x044 +#define QUEUE_CONTROL_REGISTER_PCI_SIDE 0x050 +#define QUEUE_BASE_ADDRESS_REGISTER_PCI_SIDE 0x054 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_PCI_SIDE 0x060 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_PCI_SIDE 0x064 +#define INBOUND_POST_HEAD_POINTER_REGISTER_PCI_SIDE 0x068 +#define INBOUND_POST_TAIL_POINTER_REGISTER_PCI_SIDE 0x06c +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_PCI_SIDE 0x070 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_PCI_SIDE 0x074 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_PCI_SIDE 0x078 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_PCI_SIDE 0x07c + +#define INBOUND_MESSAGE_REGISTER0_CPU_SIDE 0x1c10 +#define INBOUND_MESSAGE_REGISTER1_CPU_SIDE 0x1c14 +#define OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE 0x1c18 +#define OUTBOUND_MESSAGE_REGISTER1_CPU_SIDE 0x1c1c +#define INBOUND_DOORBELL_REGISTER_CPU_SIDE 0x1c20 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE 0x1c24 +#define INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE 0x1c28 +#define OUTBOUND_DOORBELL_REGISTER_CPU_SIDE 0x1c2c +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE 0x1c30 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE 0x1c34 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU_SIDE 0x1c40 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU_SIDE 0x1c44 +#define QUEUE_CONTROL_REGISTER_CPU_SIDE 0x1c50 +#define QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE 0x1c54 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE 0x1c60 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE 0x1c64 +#define INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE 0x1c68 +#define INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE 0x1c6c +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE 0x1c70 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE 0x1c74 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE 0x1c78 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE 0x1c7c + +/* + * Register encodings + */ +#define GT_CPU_ENDIAN_SHF 12 +#define GT_CPU_ENDIAN_MSK (MSK(1) << GT_CPU_ENDIAN_SHF) +#define GT_CPU_ENDIAN_BIT GT_CPU_ENDIAN_MSK +#define GT_CPU_WR_SHF 16 +#define GT_CPU_WR_MSK (MSK(1) << GT_CPU_WR_SHF) +#define GT_CPU_WR_BIT GT_CPU_WR_MSK +#define GT_CPU_WR_DXDXDXDX 0 +#define GT_CPU_WR_DDDD 1 + + +#define GT_PCI_DCRM_SHF 21 +#define GT_PCI_LD_SHF 0 +#define GT_PCI_LD_MSK (MSK(15) << GT_PCI_LD_SHF) +#define GT_PCI_HD_SHF 0 +#define GT_PCI_HD_MSK (MSK(7) << GT_PCI_HD_SHF) +#define GT_PCI_REMAP_SHF 0 +#define GT_PCI_REMAP_MSK (MSK(11) << GT_PCI_REMAP_SHF) + + +#define GT_CFGADDR_CFGEN_SHF 31 +#define GT_CFGADDR_CFGEN_MSK (MSK(1) << GT_CFGADDR_CFGEN_SHF) +#define GT_CFGADDR_CFGEN_BIT GT_CFGADDR_CFGEN_MSK + +#define GT_CFGADDR_BUSNUM_SHF 16 +#define GT_CFGADDR_BUSNUM_MSK (MSK(8) << GT_CFGADDR_BUSNUM_SHF) + +#define GT_CFGADDR_DEVNUM_SHF 11 +#define GT_CFGADDR_DEVNUM_MSK (MSK(5) << GT_CFGADDR_DEVNUM_SHF) + +#define GT_CFGADDR_FUNCNUM_SHF 8 +#define GT_CFGADDR_FUNCNUM_MSK (MSK(3) << GT_CFGADDR_FUNCNUM_SHF) + +#define GT_CFGADDR_REGNUM_SHF 2 +#define GT_CFGADDR_REGNUM_MSK (MSK(6) << GT_CFGADDR_REGNUM_SHF) + + +#define GT_SDRAM_BM_ORDER_SHF 2 +#define GT_SDRAM_BM_ORDER_MSK (MSK(1) << GT_SDRAM_BM_ORDER_SHF) +#define GT_SDRAM_BM_ORDER_BIT GT_SDRAM_BM_ORDER_MSK +#define GT_SDRAM_BM_ORDER_SUB 1 +#define GT_SDRAM_BM_ORDER_LIN 0 + +#define GT_SDRAM_BM_RSVD_ALL1 0xffb + + +#define GT_SDRAM_ADDRDECODE_ADDR_SHF 0 +#define GT_SDRAM_ADDRDECODE_ADDR_MSK (MSK(3) << GT_SDRAM_ADDRDECODE_ADDR_SHF) +#define GT_SDRAM_ADDRDECODE_ADDR_0 0 +#define GT_SDRAM_ADDRDECODE_ADDR_1 1 +#define GT_SDRAM_ADDRDECODE_ADDR_2 2 +#define GT_SDRAM_ADDRDECODE_ADDR_3 3 +#define GT_SDRAM_ADDRDECODE_ADDR_4 4 +#define GT_SDRAM_ADDRDECODE_ADDR_5 5 +#define GT_SDRAM_ADDRDECODE_ADDR_6 6 +#define GT_SDRAM_ADDRDECODE_ADDR_7 7 + + +#define GT_SDRAM_B0_CASLAT_SHF 0 +#define GT_SDRAM_B0_CASLAT_MSK (MSK(2) << GT_SDRAM_B0__SHF) +#define GT_SDRAM_B0_CASLAT_2 1 +#define GT_SDRAM_B0_CASLAT_3 2 + +#define GT_SDRAM_B0_FTDIS_SHF 2 +#define GT_SDRAM_B0_FTDIS_MSK (MSK(1) << GT_SDRAM_B0_FTDIS_SHF) +#define GT_SDRAM_B0_FTDIS_BIT GT_SDRAM_B0_FTDIS_MSK + +#define GT_SDRAM_B0_SRASPRCHG_SHF 3 +#define GT_SDRAM_B0_SRASPRCHG_MSK (MSK(1) << GT_SDRAM_B0_SRASPRCHG_SHF) +#define GT_SDRAM_B0_SRASPRCHG_BIT GT_SDRAM_B0_SRASPRCHG_MSK +#define GT_SDRAM_B0_SRASPRCHG_2 0 +#define GT_SDRAM_B0_SRASPRCHG_3 1 + +#define GT_SDRAM_B0_B0COMPAB_SHF 4 +#define GT_SDRAM_B0_B0COMPAB_MSK (MSK(1) << GT_SDRAM_B0_B0COMPAB_SHF) +#define GT_SDRAM_B0_B0COMPAB_BIT GT_SDRAM_B0_B0COMPAB_MSK + +#define GT_SDRAM_B0_64BITINT_SHF 5 +#define GT_SDRAM_B0_64BITINT_MSK (MSK(1) << GT_SDRAM_B0_64BITINT_SHF) +#define GT_SDRAM_B0_64BITINT_BIT GT_SDRAM_B0_64BITINT_MSK +#define GT_SDRAM_B0_64BITINT_2 0 +#define GT_SDRAM_B0_64BITINT_4 1 + +#define GT_SDRAM_B0_BW_SHF 6 +#define GT_SDRAM_B0_BW_MSK (MSK(1) << GT_SDRAM_B0_BW_SHF) +#define GT_SDRAM_B0_BW_BIT GT_SDRAM_B0_BW_MSK +#define GT_SDRAM_B0_BW_32 0 +#define GT_SDRAM_B0_BW_64 1 + +#define GT_SDRAM_B0_BLODD_SHF 7 +#define GT_SDRAM_B0_BLODD_MSK (MSK(1) << GT_SDRAM_B0_BLODD_SHF) +#define GT_SDRAM_B0_BLODD_BIT GT_SDRAM_B0_BLODD_MSK + +#define GT_SDRAM_B0_PAR_SHF 8 +#define GT_SDRAM_B0_PAR_MSK (MSK(1) << GT_SDRAM_B0_PAR_SHF) +#define GT_SDRAM_B0_PAR_BIT GT_SDRAM_B0_PAR_MSK + +#define GT_SDRAM_B0_BYPASS_SHF 9 +#define GT_SDRAM_B0_BYPASS_MSK (MSK(1) << GT_SDRAM_B0_BYPASS_SHF) +#define GT_SDRAM_B0_BYPASS_BIT GT_SDRAM_B0_BYPASS_MSK + +#define GT_SDRAM_B0_SRAS2SCAS_SHF 10 +#define GT_SDRAM_B0_SRAS2SCAS_MSK (MSK(1) << GT_SDRAM_B0_SRAS2SCAS_SHF) +#define GT_SDRAM_B0_SRAS2SCAS_BIT GT_SDRAM_B0_SRAS2SCAS_MSK +#define GT_SDRAM_B0_SRAS2SCAS_2 0 +#define GT_SDRAM_B0_SRAS2SCAS_3 1 + +#define GT_SDRAM_B0_SIZE_SHF 11 +#define GT_SDRAM_B0_SIZE_MSK (MSK(1) << GT_SDRAM_B0_SIZE_SHF) +#define GT_SDRAM_B0_SIZE_BIT GT_SDRAM_B0_SIZE_MSK +#define GT_SDRAM_B0_SIZE_16M 0 +#define GT_SDRAM_B0_SIZE_64M 1 + +#define GT_SDRAM_B0_EXTPAR_SHF 12 +#define GT_SDRAM_B0_EXTPAR_MSK (MSK(1) << GT_SDRAM_B0_EXTPAR_SHF) +#define GT_SDRAM_B0_EXTPAR_BIT GT_SDRAM_B0_EXTPAR_MSK + +#define GT_SDRAM_B0_BLEN_SHF 13 +#define GT_SDRAM_B0_BLEN_MSK (MSK(1) << GT_SDRAM_B0_BLEN_SHF) +#define GT_SDRAM_B0_BLEN_BIT GT_SDRAM_B0_BLEN_MSK +#define GT_SDRAM_B0_BLEN_8 0 +#define GT_SDRAM_B0_BLEN_4 1 + + +#define GT_SDRAM_CFG_REFINT_SHF 0 +#define GT_SDRAM_CFG_REFINT_MSK (MSK(14) << GT_SDRAM_CFG_REFINT_SHF) + +#define GT_SDRAM_CFG_NINTERLEAVE_SHF 14 +#define GT_SDRAM_CFG_NINTERLEAVE_MSK (MSK(1) << GT_SDRAM_CFG_NINTERLEAVE_SHF) +#define GT_SDRAM_CFG_NINTERLEAVE_BIT GT_SDRAM_CFG_NINTERLEAVE_MSK + +#define GT_SDRAM_CFG_RMW_SHF 15 +#define GT_SDRAM_CFG_RMW_MSK (MSK(1) << GT_SDRAM_CFG_RMW_SHF) +#define GT_SDRAM_CFG_RMW_BIT GT_SDRAM_CFG_RMW_MSK + +#define GT_SDRAM_CFG_NONSTAGREF_SHF 16 +#define GT_SDRAM_CFG_NONSTAGREF_MSK (MSK(1) << GT_SDRAM_CFG_NONSTAGREF_SHF) +#define GT_SDRAM_CFG_NONSTAGREF_BIT GT_SDRAM_CFG_NONSTAGREF_MSK + +#define GT_SDRAM_CFG_DUPCNTL_SHF 19 +#define GT_SDRAM_CFG_DUPCNTL_MSK (MSK(1) << GT_SDRAM_CFG_DUPCNTL_SHF) +#define GT_SDRAM_CFG_DUPCNTL_BIT GT_SDRAM_CFG_DUPCNTL_MSK + +#define GT_SDRAM_CFG_DUPBA_SHF 20 +#define GT_SDRAM_CFG_DUPBA_MSK (MSK(1) << GT_SDRAM_CFG_DUPBA_SHF) +#define GT_SDRAM_CFG_DUPBA_BIT GT_SDRAM_CFG_DUPBA_MSK + +#define GT_SDRAM_CFG_DUPEOT0_SHF 21 +#define GT_SDRAM_CFG_DUPEOT0_MSK (MSK(1) << GT_SDRAM_CFG_DUPEOT0_SHF) +#define GT_SDRAM_CFG_DUPEOT0_BIT GT_SDRAM_CFG_DUPEOT0_MSK + +#define GT_SDRAM_CFG_DUPEOT1_SHF 22 +#define GT_SDRAM_CFG_DUPEOT1_MSK (MSK(1) << GT_SDRAM_CFG_DUPEOT1_SHF) +#define GT_SDRAM_CFG_DUPEOT1_BIT GT_SDRAM_CFG_DUPEOT1_MSK + +#define GT_SDRAM_OPMODE_OP_SHF 0 +#define GT_SDRAM_OPMODE_OP_MSK (MSK(3) << GT_SDRAM_OPMODE_OP_SHF) +#define GT_SDRAM_OPMODE_OP_NORMAL 0 +#define GT_SDRAM_OPMODE_OP_NOP 1 +#define GT_SDRAM_OPMODE_OP_PRCHG 2 +#define GT_SDRAM_OPMODE_OP_MODE 3 +#define GT_SDRAM_OPMODE_OP_CBR 4 + +#define GT_TC_CONTROL_ENTC0_SHF 0 +#define GT_TC_CONTROL_ENTC0_MSK (MSK(1) << GT_TC_CONTROL_ENTC0_SHF) +#define GT_TC_CONTROL_ENTC0_BIT GT_TC_CONTROL_ENTC0_MSK +#define GT_TC_CONTROL_SELTC0_SHF 1 +#define GT_TC_CONTROL_SELTC0_MSK (MSK(1) << GT_TC_CONTROL_SELTC0_SHF) +#define GT_TC_CONTROL_SELTC0_BIT GT_TC_CONTROL_SELTC0_MSK + + +#define GT_PCI0_BARE_SWSCS3BOOTDIS_SHF 0 +#define GT_PCI0_BARE_SWSCS3BOOTDIS_MSK (MSK(1) << GT_PCI0_BARE_SWSCS3BOOTDIS_SHF) +#define GT_PCI0_BARE_SWSCS3BOOTDIS_BIT GT_PCI0_BARE_SWSCS3BOOTDIS_MSK + +#define GT_PCI0_BARE_SWSCS32DIS_SHF 1 +#define GT_PCI0_BARE_SWSCS32DIS_MSK (MSK(1) << GT_PCI0_BARE_SWSCS32DIS_SHF) +#define GT_PCI0_BARE_SWSCS32DIS_BIT GT_PCI0_BARE_SWSCS32DIS_MSK + +#define GT_PCI0_BARE_SWSCS10DIS_SHF 2 +#define GT_PCI0_BARE_SWSCS10DIS_MSK (MSK(1) << GT_PCI0_BARE_SWSCS10DIS_SHF) +#define GT_PCI0_BARE_SWSCS10DIS_BIT GT_PCI0_BARE_SWSCS10DIS_MSK + +#define GT_PCI0_BARE_INTIODIS_SHF 3 +#define GT_PCI0_BARE_INTIODIS_MSK (MSK(1) << GT_PCI0_BARE_INTIODIS_SHF) +#define GT_PCI0_BARE_INTIODIS_BIT GT_PCI0_BARE_INTIODIS_MSK + +#define GT_PCI0_BARE_INTMEMDIS_SHF 4 +#define GT_PCI0_BARE_INTMEMDIS_MSK (MSK(1) << GT_PCI0_BARE_INTMEMDIS_SHF) +#define GT_PCI0_BARE_INTMEMDIS_BIT GT_PCI0_BARE_INTMEMDIS_MSK + +#define GT_PCI0_BARE_CS3BOOTDIS_SHF 5 +#define GT_PCI0_BARE_CS3BOOTDIS_MSK (MSK(1) << GT_PCI0_BARE_CS3BOOTDIS_SHF) +#define GT_PCI0_BARE_CS3BOOTDIS_BIT GT_PCI0_BARE_CS3BOOTDIS_MSK + +#define GT_PCI0_BARE_CS20DIS_SHF 6 +#define GT_PCI0_BARE_CS20DIS_MSK (MSK(1) << GT_PCI0_BARE_CS20DIS_SHF) +#define GT_PCI0_BARE_CS20DIS_BIT GT_PCI0_BARE_CS20DIS_MSK + +#define GT_PCI0_BARE_SCS32DIS_SHF 7 +#define GT_PCI0_BARE_SCS32DIS_MSK (MSK(1) << GT_PCI0_BARE_SCS32DIS_SHF) +#define GT_PCI0_BARE_SCS32DIS_BIT GT_PCI0_BARE_SCS32DIS_MSK + +#define GT_PCI0_BARE_SCS10DIS_SHF 8 +#define GT_PCI0_BARE_SCS10DIS_MSK (MSK(1) << GT_PCI0_BARE_SCS10DIS_SHF) +#define GT_PCI0_BARE_SCS10DIS_BIT GT_PCI0_BARE_SCS10DIS_MSK + + +#define GT_INTRCAUSE_MASABORT0_SHF 18 +#define GT_INTRCAUSE_MASABORT0_MSK (MSK(1) << GT_INTRCAUSE_MASABORT0_SHF) +#define GT_INTRCAUSE_MASABORT0_BIT GT_INTRCAUSE_MASABORT0_MSK + +#define GT_INTRCAUSE_TARABORT0_SHF 19 +#define GT_INTRCAUSE_TARABORT0_MSK (MSK(1) << GT_INTRCAUSE_TARABORT0_SHF) +#define GT_INTRCAUSE_TARABORT0_BIT GT_INTRCAUSE_TARABORT0_MSK + + +#define GT_PCI0_CFGADDR_REGNUM_SHF 2 +#define GT_PCI0_CFGADDR_REGNUM_MSK (MSK(6) << GT_PCI0_CFGADDR_REGNUM_SHF) +#define GT_PCI0_CFGADDR_FUNCTNUM_SHF 8 +#define GT_PCI0_CFGADDR_FUNCTNUM_MSK (MSK(3) << GT_PCI0_CFGADDR_FUNCTNUM_SHF) +#define GT_PCI0_CFGADDR_DEVNUM_SHF 11 +#define GT_PCI0_CFGADDR_DEVNUM_MSK (MSK(5) << GT_PCI0_CFGADDR_DEVNUM_SHF) +#define GT_PCI0_CFGADDR_BUSNUM_SHF 16 +#define GT_PCI0_CFGADDR_BUSNUM_MSK (MSK(8) << GT_PCI0_CFGADDR_BUSNUM_SHF) +#define GT_PCI0_CFGADDR_CONFIGEN_SHF 31 +#define GT_PCI0_CFGADDR_CONFIGEN_MSK (MSK(1) << GT_PCI0_CFGADDR_CONFIGEN_SHF) +#define GT_PCI0_CFGADDR_CONFIGEN_BIT GT_PCI0_CFGADDR_CONFIGEN_MSK + +#define GT_PCI0_CMD_MBYTESWAP_SHF 0 +#define GT_PCI0_CMD_MBYTESWAP_MSK (MSK(1) << GT_PCI0_CMD_MBYTESWAP_SHF) +#define GT_PCI0_CMD_MBYTESWAP_BIT GT_PCI0_CMD_MBYTESWAP_MSK +#define GT_PCI0_CMD_MWORDSWAP_SHF 10 +#define GT_PCI0_CMD_MWORDSWAP_MSK (MSK(1) << GT_PCI0_CMD_MWORDSWAP_SHF) +#define GT_PCI0_CMD_MWORDSWAP_BIT GT_PCI0_CMD_MWORDSWAP_MSK +#define GT_PCI0_CMD_SBYTESWAP_SHF 16 +#define GT_PCI0_CMD_SBYTESWAP_MSK (MSK(1) << GT_PCI0_CMD_SBYTESWAP_SHF) +#define GT_PCI0_CMD_SBYTESWAP_BIT GT_PCI0_CMD_SBYTESWAP_MSK +#define GT_PCI0_CMD_SWORDSWAP_SHF 11 +#define GT_PCI0_CMD_SWORDSWAP_MSK (MSK(1) << GT_PCI0_CMD_SWORDSWAP_SHF) +#define GT_PCI0_CMD_SWORDSWAP_BIT GT_PCI0_CMD_SWORDSWAP_MSK + +#define GT_INTR_T0EXP_SHF 8 +#define GT_INTR_T0EXP_MSK (MSK(1) << GT_INTR_T0EXP_SHF) +#define GT_INTR_T0EXP_BIT GT_INTR_T0EXP_MSK +#define GT_INTR_RETRYCTR0_SHF 20 +#define GT_INTR_RETRYCTR0_MSK (MSK(1) << GT_INTR_RETRYCTR0_SHF) +#define GT_INTR_RETRYCTR0_BIT GT_INTR_RETRYCTR0_MSK + +/* + * Misc + */ +#define GT_DEF_PCI0_IO_BASE 0x10000000UL +#define GT_DEF_PCI0_IO_SIZE 0x02000000UL +#define GT_DEF_PCI0_MEM0_BASE 0x12000000UL +#define GT_DEF_PCI0_MEM0_SIZE 0x02000000UL +#define GT_DEF_BASE 0x14000000UL + +#define GT_MAX_BANKSIZE (256 * 1024 * 1024) /* Max 256MB bank */ +#define GT_LATTIM_MIN 6 /* Minimum lat */ + +/* + * The gt64120_dep.h file must define the following macros + * + * GT_READ(ofs, data_pointer) + * GT_WRITE(ofs, data) - read/write GT64120 registers in 32bit + * + * TIMER - gt64120 timer irq, temporary solution until + * full gt64120 cascade interrupt support is in place + */ + +#include + +/* + * Because of an error/peculiarity in the Galileo chip, we need to swap the + * bytes when running bigendian. We also provide non-swapping versions. + */ +#define __GT_READ(ofs) \ + (*(volatile u32 *)(GT64120_BASE+(ofs))) +#define __GT_WRITE(ofs, data) \ + do { *(volatile u32 *)(GT64120_BASE+(ofs)) = (data); } while (0) +#define GT_READ(ofs) le32_to_cpu(__GT_READ(ofs)) +#define GT_WRITE(ofs, data) __GT_WRITE(ofs, cpu_to_le32(data)) + +extern void gt641xx_set_base_clock(unsigned int clock); +extern int gt641xx_timer0_state(void); + +#endif /* _ASM_GT64120_H */ diff --git a/arch/mips/include/asm/hardirq.h b/arch/mips/include/asm/hardirq.h new file mode 100644 index 00000000000..90bf399e6dd --- /dev/null +++ b/arch/mips/include/asm/hardirq.h @@ -0,0 +1,24 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 98, 99, 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef _ASM_HARDIRQ_H +#define _ASM_HARDIRQ_H + +#include +#include + +typedef struct { + unsigned int __softirq_pending; +} ____cacheline_aligned irq_cpustat_t; + +#include /* Standard mappings for irq_cpustat_t above */ + +extern void ack_bad_irq(unsigned int irq); + +#endif /* _ASM_HARDIRQ_H */ diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h new file mode 100644 index 00000000000..2de638f84c8 --- /dev/null +++ b/arch/mips/include/asm/hazards.h @@ -0,0 +1,271 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 04, 07 Ralf Baechle + * Copyright (C) MIPS Technologies, Inc. + * written by Ralf Baechle + */ +#ifndef _ASM_HAZARDS_H +#define _ASM_HAZARDS_H + +#ifdef __ASSEMBLY__ +#define ASMMACRO(name, code...) .macro name; code; .endm +#else + +#include + +#define ASMMACRO(name, code...) \ +__asm__(".macro " #name "; " #code "; .endm"); \ + \ +static inline void name(void) \ +{ \ + __asm__ __volatile__ (#name); \ +} + +/* + * MIPS R2 instruction hazard barrier. Needs to be called as a subroutine. + */ +extern void mips_ihb(void); + +#endif + +ASMMACRO(_ssnop, + sll $0, $0, 1 + ) + +ASMMACRO(_ehb, + sll $0, $0, 3 + ) + +/* + * TLB hazards + */ +#if defined(CONFIG_CPU_MIPSR2) + +/* + * MIPSR2 defines ehb for hazard avoidance + */ + +ASMMACRO(mtc0_tlbw_hazard, + _ehb + ) +ASMMACRO(tlbw_use_hazard, + _ehb + ) +ASMMACRO(tlb_probe_hazard, + _ehb + ) +ASMMACRO(irq_enable_hazard, + _ehb + ) +ASMMACRO(irq_disable_hazard, + _ehb + ) +ASMMACRO(back_to_back_c0_hazard, + _ehb + ) +/* + * gcc has a tradition of misscompiling the previous construct using the + * address of a label as argument to inline assembler. Gas otoh has the + * annoying difference between la and dla which are only usable for 32-bit + * rsp. 64-bit code, so can't be used without conditional compilation. + * The alterantive is switching the assembler to 64-bit code which happens + * to work right even for 32-bit code ... + */ +#define instruction_hazard() \ +do { \ + unsigned long tmp; \ + \ + __asm__ __volatile__( \ + " .set mips64r2 \n" \ + " dla %0, 1f \n" \ + " jr.hb %0 \n" \ + " .set mips0 \n" \ + "1: \n" \ + : "=r" (tmp)); \ +} while (0) + +#elif defined(CONFIG_CPU_MIPSR1) + +/* + * These are slightly complicated by the fact that we guarantee R1 kernels to + * run fine on R2 processors. + */ +ASMMACRO(mtc0_tlbw_hazard, + _ssnop; _ssnop; _ehb + ) +ASMMACRO(tlbw_use_hazard, + _ssnop; _ssnop; _ssnop; _ehb + ) +ASMMACRO(tlb_probe_hazard, + _ssnop; _ssnop; _ssnop; _ehb + ) +ASMMACRO(irq_enable_hazard, + _ssnop; _ssnop; _ssnop; _ehb + ) +ASMMACRO(irq_disable_hazard, + _ssnop; _ssnop; _ssnop; _ehb + ) +ASMMACRO(back_to_back_c0_hazard, + _ssnop; _ssnop; _ssnop; _ehb + ) +/* + * gcc has a tradition of misscompiling the previous construct using the + * address of a label as argument to inline assembler. Gas otoh has the + * annoying difference between la and dla which are only usable for 32-bit + * rsp. 64-bit code, so can't be used without conditional compilation. + * The alterantive is switching the assembler to 64-bit code which happens + * to work right even for 32-bit code ... + */ +#define __instruction_hazard() \ +do { \ + unsigned long tmp; \ + \ + __asm__ __volatile__( \ + " .set mips64r2 \n" \ + " dla %0, 1f \n" \ + " jr.hb %0 \n" \ + " .set mips0 \n" \ + "1: \n" \ + : "=r" (tmp)); \ +} while (0) + +#define instruction_hazard() \ +do { \ + if (cpu_has_mips_r2) \ + __instruction_hazard(); \ +} while (0) + +#elif defined(CONFIG_CPU_R10000) + +/* + * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. + */ + +ASMMACRO(mtc0_tlbw_hazard, + ) +ASMMACRO(tlbw_use_hazard, + ) +ASMMACRO(tlb_probe_hazard, + ) +ASMMACRO(irq_enable_hazard, + ) +ASMMACRO(irq_disable_hazard, + ) +ASMMACRO(back_to_back_c0_hazard, + ) +#define instruction_hazard() do { } while (0) + +#elif defined(CONFIG_CPU_RM9000) + +/* + * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent + * use of the JTLB for instructions should not occur for 4 cpu cycles and use + * for data translations should not occur for 3 cpu cycles. + */ + +ASMMACRO(mtc0_tlbw_hazard, + _ssnop; _ssnop; _ssnop; _ssnop + ) +ASMMACRO(tlbw_use_hazard, + _ssnop; _ssnop; _ssnop; _ssnop + ) +ASMMACRO(tlb_probe_hazard, + _ssnop; _ssnop; _ssnop; _ssnop + ) +ASMMACRO(irq_enable_hazard, + ) +ASMMACRO(irq_disable_hazard, + ) +ASMMACRO(back_to_back_c0_hazard, + ) +#define instruction_hazard() do { } while (0) + +#elif defined(CONFIG_CPU_SB1) + +/* + * Mostly like R4000 for historic reasons + */ +ASMMACRO(mtc0_tlbw_hazard, + ) +ASMMACRO(tlbw_use_hazard, + ) +ASMMACRO(tlb_probe_hazard, + ) +ASMMACRO(irq_enable_hazard, + ) +ASMMACRO(irq_disable_hazard, + _ssnop; _ssnop; _ssnop + ) +ASMMACRO(back_to_back_c0_hazard, + ) +#define instruction_hazard() do { } while (0) + +#else + +/* + * Finally the catchall case for all other processors including R4000, R4400, + * R4600, R4700, R5000, RM7000, NEC VR41xx etc. + * + * The taken branch will result in a two cycle penalty for the two killed + * instructions on R4000 / R4400. Other processors only have a single cycle + * hazard so this is nice trick to have an optimal code for a range of + * processors. + */ +ASMMACRO(mtc0_tlbw_hazard, + nop; nop + ) +ASMMACRO(tlbw_use_hazard, + nop; nop; nop + ) +ASMMACRO(tlb_probe_hazard, + nop; nop; nop + ) +ASMMACRO(irq_enable_hazard, + _ssnop; _ssnop; _ssnop; + ) +ASMMACRO(irq_disable_hazard, + nop; nop; nop + ) +ASMMACRO(back_to_back_c0_hazard, + _ssnop; _ssnop; _ssnop; + ) +#define instruction_hazard() do { } while (0) + +#endif + + +/* FPU hazards */ + +#if defined(CONFIG_CPU_SB1) +ASMMACRO(enable_fpu_hazard, + .set push; + .set mips64; + .set noreorder; + _ssnop; + bnezl $0, .+4; + _ssnop; + .set pop +) +ASMMACRO(disable_fpu_hazard, +) + +#elif defined(CONFIG_CPU_MIPSR2) +ASMMACRO(enable_fpu_hazard, + _ehb +) +ASMMACRO(disable_fpu_hazard, + _ehb +) +#else +ASMMACRO(enable_fpu_hazard, + nop; nop; nop; nop +) +ASMMACRO(disable_fpu_hazard, + _ehb +) +#endif + +#endif /* _ASM_HAZARDS_H */ diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h new file mode 100644 index 00000000000..4374ab2adc7 --- /dev/null +++ b/arch/mips/include/asm/highmem.h @@ -0,0 +1,67 @@ +/* + * highmem.h: virtual kernel memory mappings for high memory + * + * Used in CONFIG_HIGHMEM systems for memory pages which + * are not addressable by direct kernel virtual addresses. + * + * Copyright (C) 1999 Gerhard Wichert, Siemens AG + * Gerhard.Wichert@pdb.siemens.de + * + * + * Redesigned the x86 32-bit VM architecture to deal with + * up to 16 Terabyte physical memory. With current x86 CPUs + * we now support up to 64 Gigabytes physical RAM. + * + * Copyright (C) 1999 Ingo Molnar + */ +#ifndef _ASM_HIGHMEM_H +#define _ASM_HIGHMEM_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +/* undef for production */ +#define HIGHMEM_DEBUG 1 + +/* declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +extern pte_t *kmap_pte; +extern pgprot_t kmap_prot; +extern pte_t *pkmap_page_table; + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +#define LAST_PKMAP 1024 +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +extern void * kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +extern void *__kmap(struct page *page); +extern void __kunmap(struct page *page); +extern void *__kmap_atomic(struct page *page, enum km_type type); +extern void __kunmap_atomic(void *kvaddr, enum km_type type); +extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); +extern struct page *__kmap_atomic_to_page(void *ptr); + +#define kmap __kmap +#define kunmap __kunmap +#define kmap_atomic __kmap_atomic +#define kunmap_atomic __kunmap_atomic +#define kmap_atomic_to_page __kmap_atomic_to_page + +#define flush_cache_kmaps() flush_cache_all() + +#endif /* __KERNEL__ */ + +#endif /* _ASM_HIGHMEM_H */ diff --git a/arch/mips/include/asm/hw_irq.h b/arch/mips/include/asm/hw_irq.h new file mode 100644 index 00000000000..aca05a43a97 --- /dev/null +++ b/arch/mips/include/asm/hw_irq.h @@ -0,0 +1,20 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000, 2001, 2002 by Ralf Baechle + */ +#ifndef __ASM_HW_IRQ_H +#define __ASM_HW_IRQ_H + +#include + +extern atomic_t irq_err_count; + +/* + * interrupt-retrigger: NOP for now. This may not be apropriate for all + * machines, we'll see ... + */ + +#endif /* __ASM_HW_IRQ_H */ diff --git a/arch/mips/include/asm/i8253.h b/arch/mips/include/asm/i8253.h new file mode 100644 index 00000000000..5dabc870b32 --- /dev/null +++ b/arch/mips/include/asm/i8253.h @@ -0,0 +1,21 @@ +/* + * Machine specific IO port address definition for generic. + * Written by Osamu Tomita + */ +#ifndef __ASM_I8253_H +#define __ASM_I8253_H + +#include + +/* i8253A PIT registers */ +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 +#define PIT_CH2 0x42 + +#define PIT_TICK_RATE 1193182UL + +extern spinlock_t i8253_lock; + +extern void setup_pit_timer(void); + +#endif /* __ASM_I8253_H */ diff --git a/arch/mips/include/asm/i8259.h b/arch/mips/include/asm/i8259.h new file mode 100644 index 00000000000..8572a2d9048 --- /dev/null +++ b/arch/mips/include/asm/i8259.h @@ -0,0 +1,86 @@ +/* + * include/asm-mips/i8259.h + * + * i8259A interrupt definitions. + * + * Copyright (C) 2003 Maciej W. Rozycki + * Copyright (C) 2003 Ralf Baechle + * + * 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. + */ +#ifndef _ASM_I8259_H +#define _ASM_I8259_H + +#include +#include + +#include +#include + +/* i8259A PIC registers */ +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_IMR 0x21 +#define PIC_MASTER_ISR PIC_MASTER_CMD +#define PIC_MASTER_POLL PIC_MASTER_ISR +#define PIC_MASTER_OCW3 PIC_MASTER_ISR +#define PIC_SLAVE_CMD 0xa0 +#define PIC_SLAVE_IMR 0xa1 + +/* i8259A PIC related value */ +#define PIC_CASCADE_IR 2 +#define MASTER_ICW4_DEFAULT 0x01 +#define SLAVE_ICW4_DEFAULT 0x01 +#define PIC_ICW4_AEOI 2 + +extern spinlock_t i8259A_lock; + +extern int i8259A_irq_pending(unsigned int irq); +extern void make_8259A_irq(unsigned int irq); + +extern void init_i8259_irqs(void); + +/* + * Do the traditional i8259 interrupt polling thing. This is for the few + * cases where no better interrupt acknowledge method is available and we + * absolutely must touch the i8259. + */ +static inline int i8259_irq(void) +{ + int irq; + + spin_lock(&i8259A_lock); + + /* Perform an interrupt acknowledge cycle on controller 1. */ + outb(0x0C, PIC_MASTER_CMD); /* prepare for poll */ + irq = inb(PIC_MASTER_CMD) & 7; + if (irq == PIC_CASCADE_IR) { + /* + * Interrupt is cascaded so perform interrupt + * acknowledge on controller 2. + */ + outb(0x0C, PIC_SLAVE_CMD); /* prepare for poll */ + irq = (inb(PIC_SLAVE_CMD) & 7) + 8; + } + + if (unlikely(irq == 7)) { + /* + * This may be a spurious interrupt. + * + * Read the interrupt status register (ISR). If the most + * significant bit is not set then there is no valid + * interrupt. + */ + outb(0x0B, PIC_MASTER_ISR); /* ISR register */ + if(~inb(PIC_MASTER_ISR) & 0x80) + irq = -1; + } + + spin_unlock(&i8259A_lock); + + return likely(irq >= 0) ? irq + I8259A_IRQ_BASE : irq; +} + +#endif /* _ASM_I8259_H */ diff --git a/arch/mips/include/asm/ide.h b/arch/mips/include/asm/ide.h new file mode 100644 index 00000000000..bb674c3b030 --- /dev/null +++ b/arch/mips/include/asm/ide.h @@ -0,0 +1,13 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * This file contains the MIPS architecture specific IDE code. + */ +#ifndef __ASM_IDE_H +#define __ASM_IDE_H + +#include + +#endif /* __ASM_IDE_H */ diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h new file mode 100644 index 00000000000..6489f00731c --- /dev/null +++ b/arch/mips/include/asm/inst.h @@ -0,0 +1,394 @@ +/* + * Format of an instruction in memory. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 2000 by Ralf Baechle + * Copyright (C) 2006 by Thiemo Seufer + */ +#ifndef _ASM_INST_H +#define _ASM_INST_H + +/* + * Major opcodes; before MIPS IV cop1x was called cop3. + */ +enum major_op { + spec_op, bcond_op, j_op, jal_op, + beq_op, bne_op, blez_op, bgtz_op, + addi_op, addiu_op, slti_op, sltiu_op, + andi_op, ori_op, xori_op, lui_op, + cop0_op, cop1_op, cop2_op, cop1x_op, + beql_op, bnel_op, blezl_op, bgtzl_op, + daddi_op, daddiu_op, ldl_op, ldr_op, + spec2_op, jalx_op, mdmx_op, spec3_op, + lb_op, lh_op, lwl_op, lw_op, + lbu_op, lhu_op, lwr_op, lwu_op, + sb_op, sh_op, swl_op, sw_op, + sdl_op, sdr_op, swr_op, cache_op, + ll_op, lwc1_op, lwc2_op, pref_op, + lld_op, ldc1_op, ldc2_op, ld_op, + sc_op, swc1_op, swc2_op, major_3b_op, + scd_op, sdc1_op, sdc2_op, sd_op +}; + +/* + * func field of spec opcode. + */ +enum spec_op { + sll_op, movc_op, srl_op, sra_op, + sllv_op, pmon_op, srlv_op, srav_op, + jr_op, jalr_op, movz_op, movn_op, + syscall_op, break_op, spim_op, sync_op, + mfhi_op, mthi_op, mflo_op, mtlo_op, + dsllv_op, spec2_unused_op, dsrlv_op, dsrav_op, + mult_op, multu_op, div_op, divu_op, + dmult_op, dmultu_op, ddiv_op, ddivu_op, + add_op, addu_op, sub_op, subu_op, + and_op, or_op, xor_op, nor_op, + spec3_unused_op, spec4_unused_op, slt_op, sltu_op, + dadd_op, daddu_op, dsub_op, dsubu_op, + tge_op, tgeu_op, tlt_op, tltu_op, + teq_op, spec5_unused_op, tne_op, spec6_unused_op, + dsll_op, spec7_unused_op, dsrl_op, dsra_op, + dsll32_op, spec8_unused_op, dsrl32_op, dsra32_op +}; + +/* + * func field of spec2 opcode. + */ +enum spec2_op { + madd_op, maddu_op, mul_op, spec2_3_unused_op, + msub_op, msubu_op, /* more unused ops */ + clz_op = 0x20, clo_op, + dclz_op = 0x24, dclo_op, + sdbpp_op = 0x3f +}; + +/* + * func field of spec3 opcode. + */ +enum spec3_op { + ext_op, dextm_op, dextu_op, dext_op, + ins_op, dinsm_op, dinsu_op, dins_op, + bshfl_op = 0x20, + dbshfl_op = 0x24, + rdhwr_op = 0x3b +}; + +/* + * rt field of bcond opcodes. + */ +enum rt_op { + bltz_op, bgez_op, bltzl_op, bgezl_op, + spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07, + tgei_op, tgeiu_op, tlti_op, tltiu_op, + teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op, + bltzal_op, bgezal_op, bltzall_op, bgezall_op, + rt_op_0x14, rt_op_0x15, rt_op_0x16, rt_op_0x17, + rt_op_0x18, rt_op_0x19, rt_op_0x1a, rt_op_0x1b, + bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f +}; + +/* + * rs field of cop opcodes. + */ +enum cop_op { + mfc_op = 0x00, dmfc_op = 0x01, + cfc_op = 0x02, mtc_op = 0x04, + dmtc_op = 0x05, ctc_op = 0x06, + bc_op = 0x08, cop_op = 0x10, + copm_op = 0x18 +}; + +/* + * rt field of cop.bc_op opcodes + */ +enum bcop_op { + bcf_op, bct_op, bcfl_op, bctl_op +}; + +/* + * func field of cop0 coi opcodes. + */ +enum cop0_coi_func { + tlbr_op = 0x01, tlbwi_op = 0x02, + tlbwr_op = 0x06, tlbp_op = 0x08, + rfe_op = 0x10, eret_op = 0x18 +}; + +/* + * func field of cop0 com opcodes. + */ +enum cop0_com_func { + tlbr1_op = 0x01, tlbw_op = 0x02, + tlbp1_op = 0x08, dctr_op = 0x09, + dctw_op = 0x0a +}; + +/* + * fmt field of cop1 opcodes. + */ +enum cop1_fmt { + s_fmt, d_fmt, e_fmt, q_fmt, + w_fmt, l_fmt +}; + +/* + * func field of cop1 instructions using d, s or w format. + */ +enum cop1_sdw_func { + fadd_op = 0x00, fsub_op = 0x01, + fmul_op = 0x02, fdiv_op = 0x03, + fsqrt_op = 0x04, fabs_op = 0x05, + fmov_op = 0x06, fneg_op = 0x07, + froundl_op = 0x08, ftruncl_op = 0x09, + fceill_op = 0x0a, ffloorl_op = 0x0b, + fround_op = 0x0c, ftrunc_op = 0x0d, + fceil_op = 0x0e, ffloor_op = 0x0f, + fmovc_op = 0x11, fmovz_op = 0x12, + fmovn_op = 0x13, frecip_op = 0x15, + frsqrt_op = 0x16, fcvts_op = 0x20, + fcvtd_op = 0x21, fcvte_op = 0x22, + fcvtw_op = 0x24, fcvtl_op = 0x25, + fcmp_op = 0x30 +}; + +/* + * func field of cop1x opcodes (MIPS IV). + */ +enum cop1x_func { + lwxc1_op = 0x00, ldxc1_op = 0x01, + pfetch_op = 0x07, swxc1_op = 0x08, + sdxc1_op = 0x09, madd_s_op = 0x20, + madd_d_op = 0x21, madd_e_op = 0x22, + msub_s_op = 0x28, msub_d_op = 0x29, + msub_e_op = 0x2a, nmadd_s_op = 0x30, + nmadd_d_op = 0x31, nmadd_e_op = 0x32, + nmsub_s_op = 0x38, nmsub_d_op = 0x39, + nmsub_e_op = 0x3a +}; + +/* + * func field for mad opcodes (MIPS IV). + */ +enum mad_func { + madd_fp_op = 0x08, msub_fp_op = 0x0a, + nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e +}; + +/* + * Damn ... bitfields depend from byteorder :-( + */ +#ifdef __MIPSEB__ +struct j_format { /* Jump format */ + unsigned int opcode : 6; + unsigned int target : 26; +}; + +struct i_format { /* Immediate format (addi, lw, ...) */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + signed int simmediate : 16; +}; + +struct u_format { /* Unsigned immediate format (ori, xori, ...) */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + unsigned int uimmediate : 16; +}; + +struct c_format { /* Cache (>= R6000) format */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int c_op : 3; + unsigned int cache : 2; + unsigned int simmediate : 16; +}; + +struct r_format { /* Register format */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + unsigned int rd : 5; + unsigned int re : 5; + unsigned int func : 6; +}; + +struct p_format { /* Performance counter format (R10000) */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + unsigned int rd : 5; + unsigned int re : 5; + unsigned int func : 6; +}; + +struct f_format { /* FPU register format */ + unsigned int opcode : 6; + unsigned int : 1; + unsigned int fmt : 4; + unsigned int rt : 5; + unsigned int rd : 5; + unsigned int re : 5; + unsigned int func : 6; +}; + +struct ma_format { /* FPU multipy and add format (MIPS IV) */ + unsigned int opcode : 6; + unsigned int fr : 5; + unsigned int ft : 5; + unsigned int fs : 5; + unsigned int fd : 5; + unsigned int func : 4; + unsigned int fmt : 2; +}; + +#elif defined(__MIPSEL__) + +struct j_format { /* Jump format */ + unsigned int target : 26; + unsigned int opcode : 6; +}; + +struct i_format { /* Immediate format */ + signed int simmediate : 16; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct u_format { /* Unsigned immediate format */ + unsigned int uimmediate : 16; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct c_format { /* Cache (>= R6000) format */ + unsigned int simmediate : 16; + unsigned int cache : 2; + unsigned int c_op : 3; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct r_format { /* Register format */ + unsigned int func : 6; + unsigned int re : 5; + unsigned int rd : 5; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct p_format { /* Performance counter format (R10000) */ + unsigned int func : 6; + unsigned int re : 5; + unsigned int rd : 5; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct f_format { /* FPU register format */ + unsigned int func : 6; + unsigned int re : 5; + unsigned int rd : 5; + unsigned int rt : 5; + unsigned int fmt : 4; + unsigned int : 1; + unsigned int opcode : 6; +}; + +struct ma_format { /* FPU multipy and add format (MIPS IV) */ + unsigned int fmt : 2; + unsigned int func : 4; + unsigned int fd : 5; + unsigned int fs : 5; + unsigned int ft : 5; + unsigned int fr : 5; + unsigned int opcode : 6; +}; + +#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ +#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" +#endif + +union mips_instruction { + unsigned int word; + unsigned short halfword[2]; + unsigned char byte[4]; + struct j_format j_format; + struct i_format i_format; + struct u_format u_format; + struct c_format c_format; + struct r_format r_format; + struct f_format f_format; + struct ma_format ma_format; +}; + +/* HACHACHAHCAHC ... */ + +/* In case some other massaging is needed, keep MIPSInst as wrapper */ + +#define MIPSInst(x) x + +#define I_OPCODE_SFT 26 +#define MIPSInst_OPCODE(x) (MIPSInst(x) >> I_OPCODE_SFT) + +#define I_JTARGET_SFT 0 +#define MIPSInst_JTARGET(x) (MIPSInst(x) & 0x03ffffff) + +#define I_RS_SFT 21 +#define MIPSInst_RS(x) ((MIPSInst(x) & 0x03e00000) >> I_RS_SFT) + +#define I_RT_SFT 16 +#define MIPSInst_RT(x) ((MIPSInst(x) & 0x001f0000) >> I_RT_SFT) + +#define I_IMM_SFT 0 +#define MIPSInst_SIMM(x) ((int)((short)(MIPSInst(x) & 0xffff))) +#define MIPSInst_UIMM(x) (MIPSInst(x) & 0xffff) + +#define I_CACHEOP_SFT 18 +#define MIPSInst_CACHEOP(x) ((MIPSInst(x) & 0x001c0000) >> I_CACHEOP_SFT) + +#define I_CACHESEL_SFT 16 +#define MIPSInst_CACHESEL(x) ((MIPSInst(x) & 0x00030000) >> I_CACHESEL_SFT) + +#define I_RD_SFT 11 +#define MIPSInst_RD(x) ((MIPSInst(x) & 0x0000f800) >> I_RD_SFT) + +#define I_RE_SFT 6 +#define MIPSInst_RE(x) ((MIPSInst(x) & 0x000007c0) >> I_RE_SFT) + +#define I_FUNC_SFT 0 +#define MIPSInst_FUNC(x) (MIPSInst(x) & 0x0000003f) + +#define I_FFMT_SFT 21 +#define MIPSInst_FFMT(x) ((MIPSInst(x) & 0x01e00000) >> I_FFMT_SFT) + +#define I_FT_SFT 16 +#define MIPSInst_FT(x) ((MIPSInst(x) & 0x001f0000) >> I_FT_SFT) + +#define I_FS_SFT 11 +#define MIPSInst_FS(x) ((MIPSInst(x) & 0x0000f800) >> I_FS_SFT) + +#define I_FD_SFT 6 +#define MIPSInst_FD(x) ((MIPSInst(x) & 0x000007c0) >> I_FD_SFT) + +#define I_FR_SFT 21 +#define MIPSInst_FR(x) ((MIPSInst(x) & 0x03e00000) >> I_FR_SFT) + +#define I_FMA_FUNC_SFT 2 +#define MIPSInst_FMA_FUNC(x) ((MIPSInst(x) & 0x0000003c) >> I_FMA_FUNC_SFT) + +#define I_FMA_FFMT_SFT 0 +#define MIPSInst_FMA_FFMT(x) (MIPSInst(x) & 0x00000003) + +typedef unsigned int mips_instruction; + +#endif /* _ASM_INST_H */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h new file mode 100644 index 00000000000..501a40b9f18 --- /dev/null +++ b/arch/mips/include/asm/io.h @@ -0,0 +1,589 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995 Waldorf GmbH + * Copyright (C) 1994 - 2000, 06 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * Author: Maciej W. Rozycki + */ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Slowdown I/O port space accesses for antique hardware. + */ +#undef CONF_SLOWDOWN_IO + +/* + * Raw operations are never swapped in software. OTOH values that raw + * operations are working on may or may not have been swapped by the bus + * hardware. An example use would be for flash memory that's used for + * execute in place. + */ +# define __raw_ioswabb(a, x) (x) +# define __raw_ioswabw(a, x) (x) +# define __raw_ioswabl(a, x) (x) +# define __raw_ioswabq(a, x) (x) +# define ____raw_ioswabq(a, x) (x) + +/* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */ + +#define IO_SPACE_LIMIT 0xffff + +/* + * On MIPS I/O ports are memory mapped, so we access them using normal + * load/store instructions. mips_io_port_base is the virtual address to + * which all ports are being mapped. For sake of efficiency some code + * assumes that this is an address that can be loaded with a single lui + * instruction, so the lower 16 bits must be zero. Should be true on + * on any sane architecture; generic code does not use this assumption. + */ +extern const unsigned long mips_io_port_base; + +/* + * Gcc will generate code to load the value of mips_io_port_base after each + * function call which may be fairly wasteful in some cases. So we don't + * play quite by the book. We tell gcc mips_io_port_base is a long variable + * which solves the code generation issue. Now we need to violate the + * aliasing rules a little to make initialization possible and finally we + * will need the barrier() to fight side effects of the aliasing chat. + * This trickery will eventually collapse under gcc's optimizer. Oh well. + */ +static inline void set_io_port_base(unsigned long base) +{ + * (unsigned long *) &mips_io_port_base = base; + barrier(); +} + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + * Linus + * + */ + +#define __SLOW_DOWN_IO \ + __asm__ __volatile__( \ + "sb\t$0,0x80(%0)" \ + : : "r" (mips_io_port_base)); + +#ifdef CONF_SLOWDOWN_IO +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif +#else +#define SLOW_DOWN_IO +#endif + +/* + * virt_to_phys - map virtual addresses to physical + * @address: address to remap + * + * The returned physical address is the physical (CPU) mapping for + * the memory address given. It is only valid to use this function on + * addresses directly mapped or allocated via kmalloc. + * + * This function does not give bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ +static inline unsigned long virt_to_phys(volatile const void *address) +{ + return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET; +} + +/* + * phys_to_virt - map physical address to virtual + * @address: address to remap + * + * The returned virtual address is a current CPU mapping for + * the memory address given. It is only valid to use this function on + * addresses that have a kernel mapping + * + * This function does not handle bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ +static inline void * phys_to_virt(unsigned long address) +{ + return (void *)(address + PAGE_OFFSET - PHYS_OFFSET); +} + +/* + * ISA I/O bus memory addresses are 1:1 with the physical address. + */ +static inline unsigned long isa_virt_to_bus(volatile void * address) +{ + return (unsigned long)address - PAGE_OFFSET; +} + +static inline void * isa_bus_to_virt(unsigned long address) +{ + return (void *)(address + PAGE_OFFSET); +} + +#define isa_page_to_bus page_to_phys + +/* + * However PCI ones are not necessarily 1:1 and therefore these interfaces + * are forbidden in portable PCI drivers. + * + * Allow them for x86 for legacy drivers, though. + */ +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt + +/* + * Change "struct page" to physical address. + */ +#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) + +extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags); +extern void __iounmap(const volatile void __iomem *addr); + +static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, + unsigned long flags) +{ + void __iomem *addr = plat_ioremap(offset, size, flags); + + if (addr) + return addr; + +#define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL)) + + if (cpu_has_64bit_addresses) { + u64 base = UNCAC_BASE; + + /* + * R10000 supports a 2 bit uncached attribute therefore + * UNCAC_BASE may not equal IO_BASE. + */ + if (flags == _CACHE_UNCACHED) + base = (u64) IO_BASE; + return (void __iomem *) (unsigned long) (base + offset); + } else if (__builtin_constant_p(offset) && + __builtin_constant_p(size) && __builtin_constant_p(flags)) { + phys_t phys_addr, last_addr; + + phys_addr = fixup_bigphys_addr(offset, size); + + /* Don't allow wraparound or zero size. */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + /* + * Map uncached objects in the low 512MB of address + * space using KSEG1. + */ + if (__IS_LOW512(phys_addr) && __IS_LOW512(last_addr) && + flags == _CACHE_UNCACHED) + return (void __iomem *) + (unsigned long)CKSEG1ADDR(phys_addr); + } + + return __ioremap(offset, size, flags); + +#undef __IS_LOW512 +} + +/* + * ioremap - map bus memory into CPU space + * @offset: bus address of the memory + * @size: size of the resource to map + * + * ioremap performs a platform specific sequence of operations to + * make bus memory CPU accessible via the readb/readw/readl/writeb/ + * writew/writel functions and the other mmio helpers. The returned + * address is not guaranteed to be usable directly as a virtual + * address. + */ +#define ioremap(offset, size) \ + __ioremap_mode((offset), (size), _CACHE_UNCACHED) + +/* + * ioremap_nocache - map bus memory into CPU space + * @offset: bus address of the memory + * @size: size of the resource to map + * + * ioremap_nocache performs a platform specific sequence of operations to + * make bus memory CPU accessible via the readb/readw/readl/writeb/ + * writew/writel functions and the other mmio helpers. The returned + * address is not guaranteed to be usable directly as a virtual + * address. + * + * This version of ioremap ensures that the memory is marked uncachable + * on the CPU as well as honouring existing caching rules from things like + * the PCI bus. Note that there are other caches and buffers on many + * busses. In paticular driver authors should read up on PCI writes + * + * It's useful if some control registers are in such an area and + * write combining or read caching is not desirable: + */ +#define ioremap_nocache(offset, size) \ + __ioremap_mode((offset), (size), _CACHE_UNCACHED) + +/* + * ioremap_cachable - map bus memory into CPU space + * @offset: bus address of the memory + * @size: size of the resource to map + * + * ioremap_nocache performs a platform specific sequence of operations to + * make bus memory CPU accessible via the readb/readw/readl/writeb/ + * writew/writel functions and the other mmio helpers. The returned + * address is not guaranteed to be usable directly as a virtual + * address. + * + * This version of ioremap ensures that the memory is marked cachable by + * the CPU. Also enables full write-combining. Useful for some + * memory-like regions on I/O busses. + */ +#define ioremap_cachable(offset, size) \ + __ioremap_mode((offset), (size), _page_cachable_default) + +/* + * These two are MIPS specific ioremap variant. ioremap_cacheable_cow + * requests a cachable mapping, ioremap_uncached_accelerated requests a + * mapping using the uncached accelerated mode which isn't supported on + * all processors. + */ +#define ioremap_cacheable_cow(offset, size) \ + __ioremap_mode((offset), (size), _CACHE_CACHABLE_COW) +#define ioremap_uncached_accelerated(offset, size) \ + __ioremap_mode((offset), (size), _CACHE_UNCACHED_ACCELERATED) + +static inline void iounmap(const volatile void __iomem *addr) +{ + if (plat_iounmap(addr)) + return; + +#define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1) + + if (cpu_has_64bit_addresses || + (__builtin_constant_p(addr) && __IS_KSEG1(addr))) + return; + + __iounmap(addr); + +#undef __IS_KSEG1 +} + +#define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \ + \ +static inline void pfx##write##bwlq(type val, \ + volatile void __iomem *mem) \ +{ \ + volatile type *__mem; \ + type __val; \ + \ + __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ + \ + __val = pfx##ioswab##bwlq(__mem, val); \ + \ + if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \ + *__mem = __val; \ + else if (cpu_has_64bits) { \ + unsigned long __flags; \ + type __tmp; \ + \ + if (irq) \ + local_irq_save(__flags); \ + __asm__ __volatile__( \ + ".set mips3" "\t\t# __writeq""\n\t" \ + "dsll32 %L0, %L0, 0" "\n\t" \ + "dsrl32 %L0, %L0, 0" "\n\t" \ + "dsll32 %M0, %M0, 0" "\n\t" \ + "or %L0, %L0, %M0" "\n\t" \ + "sd %L0, %2" "\n\t" \ + ".set mips0" "\n" \ + : "=r" (__tmp) \ + : "0" (__val), "m" (*__mem)); \ + if (irq) \ + local_irq_restore(__flags); \ + } else \ + BUG(); \ +} \ + \ +static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ +{ \ + volatile type *__mem; \ + type __val; \ + \ + __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ + \ + if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \ + __val = *__mem; \ + else if (cpu_has_64bits) { \ + unsigned long __flags; \ + \ + if (irq) \ + local_irq_save(__flags); \ + __asm__ __volatile__( \ + ".set mips3" "\t\t# __readq" "\n\t" \ + "ld %L0, %1" "\n\t" \ + "dsra32 %M0, %L0, 0" "\n\t" \ + "sll %L0, %L0, 0" "\n\t" \ + ".set mips0" "\n" \ + : "=r" (__val) \ + : "m" (*__mem)); \ + if (irq) \ + local_irq_restore(__flags); \ + } else { \ + __val = 0; \ + BUG(); \ + } \ + \ + return pfx##ioswab##bwlq(__mem, __val); \ +} + +#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) \ + \ +static inline void pfx##out##bwlq##p(type val, unsigned long port) \ +{ \ + volatile type *__addr; \ + type __val; \ + \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ + \ + __val = pfx##ioswab##bwlq(__addr, val); \ + \ + /* Really, we want this to be atomic */ \ + BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ + \ + *__addr = __val; \ + slow; \ +} \ + \ +static inline type pfx##in##bwlq##p(unsigned long port) \ +{ \ + volatile type *__addr; \ + type __val; \ + \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ + \ + BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ + \ + __val = *__addr; \ + slow; \ + \ + return pfx##ioswab##bwlq(__addr, __val); \ +} + +#define __BUILD_MEMORY_PFX(bus, bwlq, type) \ + \ +__BUILD_MEMORY_SINGLE(bus, bwlq, type, 1) + +#define BUILDIO_MEM(bwlq, type) \ + \ +__BUILD_MEMORY_PFX(__raw_, bwlq, type) \ +__BUILD_MEMORY_PFX(, bwlq, type) \ +__BUILD_MEMORY_PFX(__mem_, bwlq, type) \ + +BUILDIO_MEM(b, u8) +BUILDIO_MEM(w, u16) +BUILDIO_MEM(l, u32) +BUILDIO_MEM(q, u64) + +#define __BUILD_IOPORT_PFX(bus, bwlq, type) \ + __BUILD_IOPORT_SINGLE(bus, bwlq, type, ,) \ + __BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO) + +#define BUILDIO_IOPORT(bwlq, type) \ + __BUILD_IOPORT_PFX(, bwlq, type) \ + __BUILD_IOPORT_PFX(__mem_, bwlq, type) + +BUILDIO_IOPORT(b, u8) +BUILDIO_IOPORT(w, u16) +BUILDIO_IOPORT(l, u32) +#ifdef CONFIG_64BIT +BUILDIO_IOPORT(q, u64) +#endif + +#define __BUILDIO(bwlq, type) \ + \ +__BUILD_MEMORY_SINGLE(____raw_, bwlq, type, 0) + +__BUILDIO(q, u64) + +#define readb_relaxed readb +#define readw_relaxed readw +#define readl_relaxed readl +#define readq_relaxed readq + +/* + * Some code tests for these symbols + */ +#define readq readq +#define writeq writeq + +#define __BUILD_MEMORY_STRING(bwlq, type) \ + \ +static inline void writes##bwlq(volatile void __iomem *mem, \ + const void *addr, unsigned int count) \ +{ \ + const volatile type *__addr = addr; \ + \ + while (count--) { \ + __mem_write##bwlq(*__addr, mem); \ + __addr++; \ + } \ +} \ + \ +static inline void reads##bwlq(volatile void __iomem *mem, void *addr, \ + unsigned int count) \ +{ \ + volatile type *__addr = addr; \ + \ + while (count--) { \ + *__addr = __mem_read##bwlq(mem); \ + __addr++; \ + } \ +} + +#define __BUILD_IOPORT_STRING(bwlq, type) \ + \ +static inline void outs##bwlq(unsigned long port, const void *addr, \ + unsigned int count) \ +{ \ + const volatile type *__addr = addr; \ + \ + while (count--) { \ + __mem_out##bwlq(*__addr, port); \ + __addr++; \ + } \ +} \ + \ +static inline void ins##bwlq(unsigned long port, void *addr, \ + unsigned int count) \ +{ \ + volatile type *__addr = addr; \ + \ + while (count--) { \ + *__addr = __mem_in##bwlq(port); \ + __addr++; \ + } \ +} + +#define BUILDSTRING(bwlq, type) \ + \ +__BUILD_MEMORY_STRING(bwlq, type) \ +__BUILD_IOPORT_STRING(bwlq, type) + +BUILDSTRING(b, u8) +BUILDSTRING(w, u16) +BUILDSTRING(l, u32) +#ifdef CONFIG_64BIT +BUILDSTRING(q, u64) +#endif + + +/* Depends on MIPS II instruction set */ +#define mmiowb() asm volatile ("sync" ::: "memory") + +static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count) +{ + memset((void __force *) addr, val, count); +} +static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count) +{ + memcpy(dst, (void __force *) src, count); +} +static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count) +{ + memcpy((void __force *) dst, src, count); +} + +/* + * The caches on some architectures aren't dma-coherent and have need to + * handle this in software. There are three types of operations that + * can be applied to dma buffers. + * + * - dma_cache_wback_inv(start, size) makes caches and coherent by + * writing the content of the caches back to memory, if necessary. + * The function also invalidates the affected part of the caches as + * necessary before DMA transfers from outside to memory. + * - dma_cache_wback(start, size) makes caches and coherent by + * writing the content of the caches back to memory, if necessary. + * The function also invalidates the affected part of the caches as + * necessary before DMA transfers from outside to memory. + * - dma_cache_inv(start, size) invalidates the affected parts of the + * caches. Dirty lines of the caches may be written back or simply + * be discarded. This operation is necessary before dma operations + * to the memory. + * + * This API used to be exported; it now is for arch code internal use only. + */ +#ifdef CONFIG_DMA_NONCOHERENT + +extern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); +extern void (*_dma_cache_wback)(unsigned long start, unsigned long size); +extern void (*_dma_cache_inv)(unsigned long start, unsigned long size); + +#define dma_cache_wback_inv(start, size) _dma_cache_wback_inv(start, size) +#define dma_cache_wback(start, size) _dma_cache_wback(start, size) +#define dma_cache_inv(start, size) _dma_cache_inv(start, size) + +#else /* Sane hardware */ + +#define dma_cache_wback_inv(start,size) \ + do { (void) (start); (void) (size); } while (0) +#define dma_cache_wback(start,size) \ + do { (void) (start); (void) (size); } while (0) +#define dma_cache_inv(start,size) \ + do { (void) (start); (void) (size); } while (0) + +#endif /* CONFIG_DMA_NONCOHERENT */ + +/* + * Read a 32-bit register that requires a 64-bit read cycle on the bus. + * Avoid interrupt mucking, just adjust the address for 4-byte access. + * Assume the addresses are 8-byte aligned. + */ +#ifdef __MIPSEB__ +#define __CSR_32_ADJUST 4 +#else +#define __CSR_32_ADJUST 0 +#endif + +#define csr_out32(v, a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST) = (v)) +#define csr_in32(a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST)) + +/* + * Convert a physical pointer to a virtual kernel pointer for /dev/mem + * access + */ +#define xlate_dev_mem_ptr(p) __va(p) + +/* + * Convert a virtual cached pointer to an uncached pointer + */ +#define xlate_dev_kmem_ptr(p) p + +#endif /* _ASM_IO_H */ diff --git a/arch/mips/include/asm/ioctl.h b/arch/mips/include/asm/ioctl.h new file mode 100644 index 00000000000..85067e248a8 --- /dev/null +++ b/arch/mips/include/asm/ioctl.h @@ -0,0 +1,94 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 99, 2001 Ralf Baechle + */ +#ifndef _ASM_IOCTL_H +#define _ASM_IOCTL_H + +/* + * The original linux ioctl numbering scheme was just a general + * "anything goes" setup, where more or less random numbers were + * assigned. Sorry, I was clueless when I started out on this. + * + * On the alpha, we'll try to clean it up a bit, using a more sane + * ioctl numbering, and also trying to be compatible with OSF/1 in + * the process. I'd like to clean it up for the i386 as well, but + * it's so painful recognizing both the new and the old numbers.. + * + * The same applies for for the MIPS ABI; in fact even the macros + * from Linux/Alpha fit almost perfectly. + */ + +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 13 +#define _IOC_DIRBITS 3 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit. + * And this turns out useful to catch old ioctl numbers in header + * files for us. + */ +#define _IOC_NONE 1U +#define _IOC_READ 2U +#define _IOC_WRITE 4U + +/* + * The following are included for compatibility + */ +#define _IOC_VOID 0x20000000 +#define _IOC_OUT 0x40000000 +#define _IOC_IN 0x80000000 +#define _IOC_INOUT (IOC_IN|IOC_OUT) + +#define _IOC(dir, type, nr, size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* provoke compile error for invalid uses of size argument */ +extern unsigned int __invalid_size_argument_for_IOC; +#define _IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ + sizeof(t) : __invalid_size_argument_for_IOC) + +/* used to create numbers */ +#define _IO(type, nr) _IOC(_IOC_NONE, (type), (nr), 0) +#define _IOR(type, nr, size) _IOC(_IOC_READ, (type), (nr), (_IOC_TYPECHECK(size))) +#define _IOW(type, nr, size) _IOC(_IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size))) +#define _IOWR(type, nr, size) _IOC(_IOC_READ|_IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size))) +#define _IOR_BAD(type, nr, size) _IOC(_IOC_READ, (type), (nr), sizeof(size)) +#define _IOW_BAD(type, nr, size) _IOC(_IOC_WRITE, (type), (nr), sizeof(size)) +#define _IOWR_BAD(type, nr, size) _IOC(_IOC_READ|_IOC_WRITE, (type), (nr), sizeof(size)) + + +/* used to decode them.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +#endif /* _ASM_IOCTL_H */ diff --git a/arch/mips/include/asm/ioctls.h b/arch/mips/include/asm/ioctls.h new file mode 100644 index 00000000000..3f04a995ec5 --- /dev/null +++ b/arch/mips/include/asm/ioctls.h @@ -0,0 +1,109 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 2001 Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef __ASM_IOCTLS_H +#define __ASM_IOCTLS_H + +#include + +#define TCGETA 0x5401 +#define TCSETA 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */ +#define TCSETAW 0x5403 +#define TCSETAF 0x5404 + +#define TCSBRK 0x5405 +#define TCXONC 0x5406 +#define TCFLSH 0x5407 + +#define TCGETS 0x540d +#define TCSETS 0x540e +#define TCSETSW 0x540f +#define TCSETSF 0x5410 + +#define TIOCEXCL 0x740d /* set exclusive use of tty */ +#define TIOCNXCL 0x740e /* reset exclusive use of tty */ +#define TIOCOUTQ 0x7472 /* output queue size */ +#define TIOCSTI 0x5472 /* simulate terminal input */ +#define TIOCMGET 0x741d /* get all modem bits */ +#define TIOCMBIS 0x741b /* bis modem bits */ +#define TIOCMBIC 0x741c /* bic modem bits */ +#define TIOCMSET 0x741a /* set all modem bits */ +#define TIOCPKT 0x5470 /* pty: set/clear packet mode */ +#define TIOCPKT_DATA 0x00 /* data packet */ +#define TIOCPKT_FLUSHREAD 0x01 /* flush packet */ +#define TIOCPKT_FLUSHWRITE 0x02 /* flush packet */ +#define TIOCPKT_STOP 0x04 /* stop output */ +#define TIOCPKT_START 0x08 /* start output */ +#define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */ +#define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */ +/* #define TIOCPKT_IOCTL 0x40 state change of pty driver */ +#define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */ +#define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */ +#define TIOCNOTTY 0x5471 /* void tty association */ +#define TIOCSETD 0x7401 +#define TIOCGETD 0x7400 + +#define FIOCLEX 0x6601 +#define FIONCLEX 0x6602 +#define FIOASYNC 0x667d +#define FIONBIO 0x667e +#define FIOQSIZE 0x667f + +#define TIOCGLTC 0x7474 /* get special local chars */ +#define TIOCSLTC 0x7475 /* set special local chars */ +#define TIOCSPGRP _IOW('t', 118, int) /* set pgrp of tty */ +#define TIOCGPGRP _IOR('t', 119, int) /* get pgrp of tty */ +#define TIOCCONS _IOW('t', 120, int) /* become virtual console */ + +#define FIONREAD 0x467f +#define TIOCINQ FIONREAD + +#define TIOCGETP 0x7408 +#define TIOCSETP 0x7409 +#define TIOCSETN 0x740a /* TIOCSETP wo flush */ + +/* #define TIOCSETA _IOW('t', 20, struct termios) set termios struct */ +/* #define TIOCSETAW _IOW('t', 21, struct termios) drain output, set */ +/* #define TIOCSETAF _IOW('t', 22, struct termios) drn out, fls in, set */ +/* #define TIOCGETD _IOR('t', 26, int) get line discipline */ +/* #define TIOCSETD _IOW('t', 27, int) set line discipline */ + /* 127-124 compat */ + +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x7416 /* Return the session ID of FD */ +#define TCGETS2 _IOR('T', 0x2A, struct termios2) +#define TCSETS2 _IOW('T', 0x2B, struct termios2) +#define TCSETSW2 _IOW('T', 0x2C, struct termios2) +#define TCSETSF2 _IOW('T', 0x2D, struct termios2) +#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ + +/* I hope the range from 0x5480 on is free ... */ +#define TIOCSCTTY 0x5480 /* become controlling tty */ +#define TIOCGSOFTCAR 0x5481 +#define TIOCSSOFTCAR 0x5482 +#define TIOCLINUX 0x5483 +#define TIOCGSERIAL 0x5484 +#define TIOCSSERIAL 0x5485 +#define TCSBRKP 0x5486 /* Needed for POSIX tcsendbreak() */ +#define TIOCSERCONFIG 0x5488 +#define TIOCSERGWILD 0x5489 +#define TIOCSERSWILD 0x548a +#define TIOCGLCKTRMIOS 0x548b +#define TIOCSLCKTRMIOS 0x548c +#define TIOCSERGSTRUCT 0x548d /* For debugging only */ +#define TIOCSERGETLSR 0x548e /* Get line status register */ +#define TIOCSERGETMULTI 0x548f /* Get multiport config */ +#define TIOCSERSETMULTI 0x5490 /* Set multiport config */ +#define TIOCMIWAIT 0x5491 /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x5492 /* read serial port inline interrupt counts */ +#define TIOCGHAYESESP 0x5493 /* Get Hayes ESP configuration */ +#define TIOCSHAYESESP 0x5494 /* Set Hayes ESP configuration */ + +#endif /* __ASM_IOCTLS_H */ diff --git a/arch/mips/include/asm/ip32/crime.h b/arch/mips/include/asm/ip32/crime.h new file mode 100644 index 00000000000..7c36b0e5b1c --- /dev/null +++ b/arch/mips/include/asm/ip32/crime.h @@ -0,0 +1,158 @@ +/* + * Definitions for the SGI CRIME (CPU, Rendering, Interconnect and Memory + * Engine) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Harald Koerfgen + */ + +#ifndef __ASM_CRIME_H__ +#define __ASM_CRIME_H__ + +/* + * Address map + */ +#define CRIME_BASE 0x14000000 /* physical */ + +struct sgi_crime { + volatile unsigned long id; +#define CRIME_ID_MASK 0xff +#define CRIME_ID_IDBITS 0xf0 +#define CRIME_ID_IDVALUE 0xa0 +#define CRIME_ID_REV 0x0f +#define CRIME_REV_PETTY 0x00 +#define CRIME_REV_11 0x11 +#define CRIME_REV_13 0x13 +#define CRIME_REV_14 0x14 + + volatile unsigned long control; +#define CRIME_CONTROL_MASK 0x3fff +#define CRIME_CONTROL_TRITON_SYSADC 0x2000 +#define CRIME_CONTROL_CRIME_SYSADC 0x1000 +#define CRIME_CONTROL_HARD_RESET 0x0800 +#define CRIME_CONTROL_SOFT_RESET 0x0400 +#define CRIME_CONTROL_DOG_ENA 0x0200 +#define CRIME_CONTROL_ENDIANESS 0x0100 +#define CRIME_CONTROL_ENDIAN_BIG 0x0100 +#define CRIME_CONTROL_ENDIAN_LITTLE 0x0000 +#define CRIME_CONTROL_CQUEUE_HWM 0x000f +#define CRIME_CONTROL_CQUEUE_SHFT 0 +#define CRIME_CONTROL_WBUF_HWM 0x00f0 +#define CRIME_CONTROL_WBUF_SHFT 8 + + volatile unsigned long istat; + volatile unsigned long imask; + volatile unsigned long soft_int; + volatile unsigned long hard_int; +#define MACE_VID_IN1_INT BIT(0) +#define MACE_VID_IN2_INT BIT(1) +#define MACE_VID_OUT_INT BIT(2) +#define MACE_ETHERNET_INT BIT(3) +#define MACE_SUPERIO_INT BIT(4) +#define MACE_MISC_INT BIT(5) +#define MACE_AUDIO_INT BIT(6) +#define MACE_PCI_BRIDGE_INT BIT(7) +#define MACEPCI_SCSI0_INT BIT(8) +#define MACEPCI_SCSI1_INT BIT(9) +#define MACEPCI_SLOT0_INT BIT(10) +#define MACEPCI_SLOT1_INT BIT(11) +#define MACEPCI_SLOT2_INT BIT(12) +#define MACEPCI_SHARED0_INT BIT(13) +#define MACEPCI_SHARED1_INT BIT(14) +#define MACEPCI_SHARED2_INT BIT(15) +#define CRIME_GBE0_INT BIT(16) +#define CRIME_GBE1_INT BIT(17) +#define CRIME_GBE2_INT BIT(18) +#define CRIME_GBE3_INT BIT(19) +#define CRIME_CPUERR_INT BIT(20) +#define CRIME_MEMERR_INT BIT(21) +#define CRIME_RE_EMPTY_E_INT BIT(22) +#define CRIME_RE_FULL_E_INT BIT(23) +#define CRIME_RE_IDLE_E_INT BIT(24) +#define CRIME_RE_EMPTY_L_INT BIT(25) +#define CRIME_RE_FULL_L_INT BIT(26) +#define CRIME_RE_IDLE_L_INT BIT(27) +#define CRIME_SOFT0_INT BIT(28) +#define CRIME_SOFT1_INT BIT(29) +#define CRIME_SOFT2_INT BIT(30) +#define CRIME_SYSCORERR_INT CRIME_SOFT2_INT +#define CRIME_VICE_INT BIT(31) +/* Masks for deciding who handles the interrupt */ +#define CRIME_MACE_INT_MASK 0x8f +#define CRIME_MACEISA_INT_MASK 0x70 +#define CRIME_MACEPCI_INT_MASK 0xff00 +#define CRIME_CRIME_INT_MASK 0xffff0000 + + volatile unsigned long watchdog; +#define CRIME_DOG_POWER_ON_RESET 0x00010000 +#define CRIME_DOG_WARM_RESET 0x00080000 +#define CRIME_DOG_TIMEOUT (CRIME_DOG_POWER_ON_RESET|CRIME_DOG_WARM_RESET) +#define CRIME_DOG_VALUE 0x00007fff + + volatile unsigned long timer; +#define CRIME_MASTER_FREQ 66666500 /* Crime upcounter frequency */ +#define CRIME_NS_PER_TICK 15 /* for delay_calibrate */ + + volatile unsigned long cpu_error_addr; +#define CRIME_CPU_ERROR_ADDR_MASK 0x3ffffffff + + volatile unsigned long cpu_error_stat; +#define CRIME_CPU_ERROR_MASK 0x7 /* cpu error stat is 3 bits */ +#define CRIME_CPU_ERROR_CPU_ILL_ADDR 0x4 +#define CRIME_CPU_ERROR_VICE_WRT_PRTY 0x2 +#define CRIME_CPU_ERROR_CPU_WRT_PRTY 0x1 + + unsigned long _pad0[54]; + + volatile unsigned long mc_ctrl; + volatile unsigned long bank_ctrl[8]; +#define CRIME_MEM_BANK_CONTROL_MASK 0x11f /* 9 bits 7:5 reserved */ +#define CRIME_MEM_BANK_CONTROL_ADDR 0x01f +#define CRIME_MEM_BANK_CONTROL_SDRAM_SIZE 0x100 +#define CRIME_MAXBANKS 8 + + volatile unsigned long mem_ref_counter; +#define CRIME_MEM_REF_COUNTER_MASK 0x3ff /* 10bit */ + + volatile unsigned long mem_error_stat; +#define CRIME_MEM_ERROR_STAT_MASK 0x0ff7ffff /* 28-bit register */ +#define CRIME_MEM_ERROR_MACE_ID 0x0000007f +#define CRIME_MEM_ERROR_MACE_ACCESS 0x00000080 +#define CRIME_MEM_ERROR_RE_ID 0x00007f00 +#define CRIME_MEM_ERROR_RE_ACCESS 0x00008000 +#define CRIME_MEM_ERROR_GBE_ACCESS 0x00010000 +#define CRIME_MEM_ERROR_VICE_ACCESS 0x00020000 +#define CRIME_MEM_ERROR_CPU_ACCESS 0x00040000 +#define CRIME_MEM_ERROR_RESERVED 0x00080000 +#define CRIME_MEM_ERROR_SOFT_ERR 0x00100000 +#define CRIME_MEM_ERROR_HARD_ERR 0x00200000 +#define CRIME_MEM_ERROR_MULTIPLE 0x00400000 +#define CRIME_MEM_ERROR_ECC 0x01800000 +#define CRIME_MEM_ERROR_MEM_ECC_RD 0x00800000 +#define CRIME_MEM_ERROR_MEM_ECC_RMW 0x01000000 +#define CRIME_MEM_ERROR_INV 0x0e000000 +#define CRIME_MEM_ERROR_INV_MEM_ADDR_RD 0x02000000 +#define CRIME_MEM_ERROR_INV_MEM_ADDR_WR 0x04000000 +#define CRIME_MEM_ERROR_INV_MEM_ADDR_RMW 0x08000000 + + volatile unsigned long mem_error_addr; +#define CRIME_MEM_ERROR_ADDR_MASK 0x3fffffff + + volatile unsigned long mem_ecc_syn; +#define CRIME_MEM_ERROR_ECC_SYN_MASK 0xffffffff + + volatile unsigned long mem_ecc_chk; +#define CRIME_MEM_ERROR_ECC_CHK_MASK 0xffffffff + + volatile unsigned long mem_ecc_repl; +#define CRIME_MEM_ERROR_ECC_REPL_MASK 0xffffffff +}; + +extern struct sgi_crime __iomem *crime; + +#define CRIME_HI_MEM_BASE 0x40000000 /* this is where whole 1G of RAM is mapped */ + +#endif /* __ASM_CRIME_H__ */ diff --git a/arch/mips/include/asm/ip32/ip32_ints.h b/arch/mips/include/asm/ip32/ip32_ints.h new file mode 100644 index 00000000000..85bc5302bce --- /dev/null +++ b/arch/mips/include/asm/ip32/ip32_ints.h @@ -0,0 +1,114 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Harald Koerfgen + */ + +#ifndef __ASM_IP32_INTS_H +#define __ASM_IP32_INTS_H + +#include + +/* + * This list reflects the assignment of interrupt numbers to + * interrupting events. Order is fairly irrelevant to handling + * priority. This differs from irix. + */ + +enum ip32_irq_no { + /* + * CPU interrupts are 0 ... 7 + */ + + CRIME_IRQ_BASE = MIPS_CPU_IRQ_BASE + 8, + + /* + * MACE + */ + MACE_VID_IN1_IRQ = CRIME_IRQ_BASE, + MACE_VID_IN2_IRQ, + MACE_VID_OUT_IRQ, + MACE_ETHERNET_IRQ, + /* SUPERIO, MISC, and AUDIO are MACEISA */ + __MACE_SUPERIO, + __MACE_MISC, + __MACE_AUDIO, + MACE_PCI_BRIDGE_IRQ, + + /* + * MACEPCI + */ + MACEPCI_SCSI0_IRQ, + MACEPCI_SCSI1_IRQ, + MACEPCI_SLOT0_IRQ, + MACEPCI_SLOT1_IRQ, + MACEPCI_SLOT2_IRQ, + MACEPCI_SHARED0_IRQ, + MACEPCI_SHARED1_IRQ, + MACEPCI_SHARED2_IRQ, + + /* + * CRIME + */ + CRIME_GBE0_IRQ, + CRIME_GBE1_IRQ, + CRIME_GBE2_IRQ, + CRIME_GBE3_IRQ, + CRIME_CPUERR_IRQ, + CRIME_MEMERR_IRQ, + CRIME_RE_EMPTY_E_IRQ, + CRIME_RE_FULL_E_IRQ, + CRIME_RE_IDLE_E_IRQ, + CRIME_RE_EMPTY_L_IRQ, + CRIME_RE_FULL_L_IRQ, + CRIME_RE_IDLE_L_IRQ, + CRIME_SOFT0_IRQ, + CRIME_SOFT1_IRQ, + CRIME_SOFT2_IRQ, + CRIME_SYSCORERR_IRQ = CRIME_SOFT2_IRQ, + CRIME_VICE_IRQ, + + /* + * MACEISA + */ + MACEISA_AUDIO_SW_IRQ, + MACEISA_AUDIO_SC_IRQ, + MACEISA_AUDIO1_DMAT_IRQ, + MACEISA_AUDIO1_OF_IRQ, + MACEISA_AUDIO2_DMAT_IRQ, + MACEISA_AUDIO2_MERR_IRQ, + MACEISA_AUDIO3_DMAT_IRQ, + MACEISA_AUDIO3_MERR_IRQ, + MACEISA_RTC_IRQ, + MACEISA_KEYB_IRQ, + /* MACEISA_KEYB_POLL is not an IRQ */ + __MACEISA_KEYB_POLL, + MACEISA_MOUSE_IRQ, + /* MACEISA_MOUSE_POLL is not an IRQ */ + __MACEISA_MOUSE_POLL, + MACEISA_TIMER0_IRQ, + MACEISA_TIMER1_IRQ, + MACEISA_TIMER2_IRQ, + MACEISA_PARALLEL_IRQ, + MACEISA_PAR_CTXA_IRQ, + MACEISA_PAR_CTXB_IRQ, + MACEISA_PAR_MERR_IRQ, + MACEISA_SERIAL1_IRQ, + MACEISA_SERIAL1_TDMAT_IRQ, + MACEISA_SERIAL1_TDMAPR_IRQ, + MACEISA_SERIAL1_TDMAME_IRQ, + MACEISA_SERIAL1_RDMAT_IRQ, + MACEISA_SERIAL1_RDMAOR_IRQ, + MACEISA_SERIAL2_IRQ, + MACEISA_SERIAL2_TDMAT_IRQ, + MACEISA_SERIAL2_TDMAPR_IRQ, + MACEISA_SERIAL2_TDMAME_IRQ, + MACEISA_SERIAL2_RDMAT_IRQ, + MACEISA_SERIAL2_RDMAOR_IRQ, + + IP32_IRQ_MAX = MACEISA_SERIAL2_RDMAOR_IRQ +}; + +#endif /* __ASM_IP32_INTS_H */ diff --git a/arch/mips/include/asm/ip32/mace.h b/arch/mips/include/asm/ip32/mace.h new file mode 100644 index 00000000000..d08d7c67213 --- /dev/null +++ b/arch/mips/include/asm/ip32/mace.h @@ -0,0 +1,365 @@ +/* + * Definitions for the SGI MACE (Multimedia, Audio and Communications Engine) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Harald Koerfgen + * Copyright (C) 2004 Ladislav Michl + */ + +#ifndef __ASM_MACE_H__ +#define __ASM_MACE_H__ + +/* + * Address map + */ +#define MACE_BASE 0x1f000000 /* physical */ + +/* + * PCI interface + */ +struct mace_pci { + volatile unsigned int error_addr; + volatile unsigned int error; +#define MACEPCI_ERROR_MASTER_ABORT BIT(31) +#define MACEPCI_ERROR_TARGET_ABORT BIT(30) +#define MACEPCI_ERROR_DATA_PARITY_ERR BIT(29) +#define MACEPCI_ERROR_RETRY_ERR BIT(28) +#define MACEPCI_ERROR_ILLEGAL_CMD BIT(27) +#define MACEPCI_ERROR_SYSTEM_ERR BIT(26) +#define MACEPCI_ERROR_INTERRUPT_TEST BIT(25) +#define MACEPCI_ERROR_PARITY_ERR BIT(24) +#define MACEPCI_ERROR_OVERRUN BIT(23) +#define MACEPCI_ERROR_RSVD BIT(22) +#define MACEPCI_ERROR_MEMORY_ADDR BIT(21) +#define MACEPCI_ERROR_CONFIG_ADDR BIT(20) +#define MACEPCI_ERROR_MASTER_ABORT_ADDR_VALID BIT(19) +#define MACEPCI_ERROR_TARGET_ABORT_ADDR_VALID BIT(18) +#define MACEPCI_ERROR_DATA_PARITY_ADDR_VALID BIT(17) +#define MACEPCI_ERROR_RETRY_ADDR_VALID BIT(16) +#define MACEPCI_ERROR_SIG_TABORT BIT(4) +#define MACEPCI_ERROR_DEVSEL_MASK 0xc0 +#define MACEPCI_ERROR_DEVSEL_FAST 0 +#define MACEPCI_ERROR_DEVSEL_MED 0x40 +#define MACEPCI_ERROR_DEVSEL_SLOW 0x80 +#define MACEPCI_ERROR_FBB BIT(1) +#define MACEPCI_ERROR_66MHZ BIT(0) + volatile unsigned int control; +#define MACEPCI_CONTROL_INT(x) BIT(x) +#define MACEPCI_CONTROL_INT_MASK 0xff +#define MACEPCI_CONTROL_SERR_ENA BIT(8) +#define MACEPCI_CONTROL_ARB_N6 BIT(9) +#define MACEPCI_CONTROL_PARITY_ERR BIT(10) +#define MACEPCI_CONTROL_MRMRA_ENA BIT(11) +#define MACEPCI_CONTROL_ARB_N3 BIT(12) +#define MACEPCI_CONTROL_ARB_N4 BIT(13) +#define MACEPCI_CONTROL_ARB_N5 BIT(14) +#define MACEPCI_CONTROL_PARK_LIU BIT(15) +#define MACEPCI_CONTROL_INV_INT(x) BIT(16+x) +#define MACEPCI_CONTROL_INV_INT_MASK 0x00ff0000 +#define MACEPCI_CONTROL_OVERRUN_INT BIT(24) +#define MACEPCI_CONTROL_PARITY_INT BIT(25) +#define MACEPCI_CONTROL_SERR_INT BIT(26) +#define MACEPCI_CONTROL_IT_INT BIT(27) +#define MACEPCI_CONTROL_RE_INT BIT(28) +#define MACEPCI_CONTROL_DPED_INT BIT(29) +#define MACEPCI_CONTROL_TAR_INT BIT(30) +#define MACEPCI_CONTROL_MAR_INT BIT(31) + volatile unsigned int rev; + unsigned int _pad[0xcf8/4 - 4]; + volatile unsigned int config_addr; + union { + volatile unsigned char b[4]; + volatile unsigned short w[2]; + volatile unsigned int l; + } config_data; +}; +#define MACEPCI_LOW_MEMORY 0x1a000000 +#define MACEPCI_LOW_IO 0x18000000 +#define MACEPCI_SWAPPED_VIEW 0 +#define MACEPCI_NATIVE_VIEW 0x40000000 +#define MACEPCI_IO 0x80000000 +#define MACEPCI_HI_MEMORY 0x280000000 +#define MACEPCI_HI_IO 0x100000000 + +/* + * Video interface + */ +struct mace_video { + unsigned long xxx; /* later... */ +}; + +/* + * Ethernet interface + */ +struct mace_ethernet { + volatile unsigned long mac_ctrl; + volatile unsigned long int_stat; + volatile unsigned long dma_ctrl; + volatile unsigned long timer; + volatile unsigned long tx_int_al; + volatile unsigned long rx_int_al; + volatile unsigned long tx_info; + volatile unsigned long tx_info_al; + volatile unsigned long rx_buff; + volatile unsigned long rx_buff_al1; + volatile unsigned long rx_buff_al2; + volatile unsigned long diag; + volatile unsigned long phy_data; + volatile unsigned long phy_regs; + volatile unsigned long phy_trans_go; + volatile unsigned long backoff_seed; + /*===================================*/ + volatile unsigned long imq_reserved[4]; + volatile unsigned long mac_addr; + volatile unsigned long mac_addr2; + volatile unsigned long mcast_filter; + volatile unsigned long tx_ring_base; + /* Following are read-only registers for debugging */ + volatile unsigned long tx_pkt1_hdr; + volatile unsigned long tx_pkt1_ptr[3]; + volatile unsigned long tx_pkt2_hdr; + volatile unsigned long tx_pkt2_ptr[3]; + /*===================================*/ + volatile unsigned long rx_fifo; +}; + +/* + * Peripherals + */ + +/* Audio registers */ +struct mace_audio { + volatile unsigned long control; + volatile unsigned long codec_control; /* codec status control */ + volatile unsigned long codec_mask; /* codec status input mask */ + volatile unsigned long codec_read; /* codec status read data */ + struct { + volatile unsigned long control; /* channel control */ + volatile unsigned long read_ptr; /* channel read pointer */ + volatile unsigned long write_ptr; /* channel write pointer */ + volatile unsigned long depth; /* channel depth */ + } chan[3]; +}; + + +/* register definitions for parallel port DMA */ +struct mace_parport { + /* 0 - do nothing, + * 1 - pulse terminal count to the device after buffer is drained */ +#define MACEPAR_CONTEXT_LASTFLAG BIT(63) + /* Should not cross 4K page boundary */ +#define MACEPAR_CONTEXT_DATA_BOUND 0x0000000000001000UL +#define MACEPAR_CONTEXT_DATALEN_MASK 0x00000fff00000000UL +#define MACEPAR_CONTEXT_DATALEN_SHIFT 32 + /* Can be arbitrarily aligned on any byte boundary on output, + * 64 byte aligned on input */ +#define MACEPAR_CONTEXT_BASEADDR_MASK 0x00000000ffffffffUL + volatile u64 context_a; + volatile u64 context_b; + /* 0 - mem->device, 1 - device->mem */ +#define MACEPAR_CTLSTAT_DIRECTION BIT(0) + /* 0 - channel frozen, 1 - channel enabled */ +#define MACEPAR_CTLSTAT_ENABLE BIT(1) + /* 0 - channel active, 1 - complete channel reset */ +#define MACEPAR_CTLSTAT_RESET BIT(2) +#define MACEPAR_CTLSTAT_CTXB_VALID BIT(3) +#define MACEPAR_CTLSTAT_CTXA_VALID BIT(4) + volatile u64 cntlstat; /* Control/Status register */ +#define MACEPAR_DIAG_CTXINUSE BIT(0) + /* 1 - Dma engine is enabled and processing something */ +#define MACEPAR_DIAG_DMACTIVE BIT(1) + /* Counter of bytes left */ +#define MACEPAR_DIAG_CTRMASK 0x0000000000003ffcUL +#define MACEPAR_DIAG_CTRSHIFT 2 + volatile u64 diagnostic; /* RO: diagnostic register */ +}; + +/* ISA Control and DMA registers */ +struct mace_isactrl { + volatile unsigned long ringbase; +#define MACEISA_RINGBUFFERS_SIZE (8 * 4096) + + volatile unsigned long misc; +#define MACEISA_FLASH_WE BIT(0) /* 1=> Enable FLASH writes */ +#define MACEISA_PWD_CLEAR BIT(1) /* 1=> PWD CLEAR jumper detected */ +#define MACEISA_NIC_DEASSERT BIT(2) +#define MACEISA_NIC_DATA BIT(3) +#define MACEISA_LED_RED BIT(4) /* 0=> Illuminate red LED */ +#define MACEISA_LED_GREEN BIT(5) /* 0=> Illuminate green LED */ +#define MACEISA_DP_RAM_ENABLE BIT(6) + + volatile unsigned long istat; + volatile unsigned long imask; +#define MACEISA_AUDIO_SW_INT BIT(0) +#define MACEISA_AUDIO_SC_INT BIT(1) +#define MACEISA_AUDIO1_DMAT_INT BIT(2) +#define MACEISA_AUDIO1_OF_INT BIT(3) +#define MACEISA_AUDIO2_DMAT_INT BIT(4) +#define MACEISA_AUDIO2_MERR_INT BIT(5) +#define MACEISA_AUDIO3_DMAT_INT BIT(6) +#define MACEISA_AUDIO3_MERR_INT BIT(7) +#define MACEISA_RTC_INT BIT(8) +#define MACEISA_KEYB_INT BIT(9) +#define MACEISA_KEYB_POLL_INT BIT(10) +#define MACEISA_MOUSE_INT BIT(11) +#define MACEISA_MOUSE_POLL_INT BIT(12) +#define MACEISA_TIMER0_INT BIT(13) +#define MACEISA_TIMER1_INT BIT(14) +#define MACEISA_TIMER2_INT BIT(15) +#define MACEISA_PARALLEL_INT BIT(16) +#define MACEISA_PAR_CTXA_INT BIT(17) +#define MACEISA_PAR_CTXB_INT BIT(18) +#define MACEISA_PAR_MERR_INT BIT(19) +#define MACEISA_SERIAL1_INT BIT(20) +#define MACEISA_SERIAL1_TDMAT_INT BIT(21) +#define MACEISA_SERIAL1_TDMAPR_INT BIT(22) +#define MACEISA_SERIAL1_TDMAME_INT BIT(23) +#define MACEISA_SERIAL1_RDMAT_INT BIT(24) +#define MACEISA_SERIAL1_RDMAOR_INT BIT(25) +#define MACEISA_SERIAL2_INT BIT(26) +#define MACEISA_SERIAL2_TDMAT_INT BIT(27) +#define MACEISA_SERIAL2_TDMAPR_INT BIT(28) +#define MACEISA_SERIAL2_TDMAME_INT BIT(29) +#define MACEISA_SERIAL2_RDMAT_INT BIT(30) +#define MACEISA_SERIAL2_RDMAOR_INT BIT(31) + + volatile unsigned long _pad[0x2000/8 - 4]; + + volatile unsigned long dp_ram[0x400]; + struct mace_parport parport; +}; + +/* Keyboard & Mouse registers + * -> drivers/input/serio/maceps2.c */ +struct mace_ps2port { + volatile unsigned long tx; + volatile unsigned long rx; + volatile unsigned long control; + volatile unsigned long status; +}; + +struct mace_ps2 { + struct mace_ps2port keyb; + struct mace_ps2port mouse; +}; + +/* I2C registers + * -> drivers/i2c/algos/i2c-algo-sgi.c */ +struct mace_i2c { + volatile unsigned long config; +#define MACEI2C_RESET BIT(0) +#define MACEI2C_FAST BIT(1) +#define MACEI2C_DATA_OVERRIDE BIT(2) +#define MACEI2C_CLOCK_OVERRIDE BIT(3) +#define MACEI2C_DATA_STATUS BIT(4) +#define MACEI2C_CLOCK_STATUS BIT(5) + volatile unsigned long control; + volatile unsigned long data; +}; + +/* Timer registers */ +typedef union { + volatile unsigned long ust_msc; + struct reg { + volatile unsigned int ust; + volatile unsigned int msc; + } reg; +} timer_reg; + +struct mace_timers { + volatile unsigned long ust; +#define MACE_UST_PERIOD_NS 960 + + volatile unsigned long compare1; + volatile unsigned long compare2; + volatile unsigned long compare3; + + timer_reg audio_in; + timer_reg audio_out1; + timer_reg audio_out2; + timer_reg video_in1; + timer_reg video_in2; + timer_reg video_out; +}; + +struct mace_perif { + struct mace_audio audio; + char _pad0[0x10000 - sizeof(struct mace_audio)]; + + struct mace_isactrl ctrl; + char _pad1[0x10000 - sizeof(struct mace_isactrl)]; + + struct mace_ps2 ps2; + char _pad2[0x10000 - sizeof(struct mace_ps2)]; + + struct mace_i2c i2c; + char _pad3[0x10000 - sizeof(struct mace_i2c)]; + + struct mace_timers timers; + char _pad4[0x10000 - sizeof(struct mace_timers)]; +}; + + +/* + * ISA peripherals + */ + +/* Parallel port */ +struct mace_parallel { +}; + +struct mace_ecp1284 { /* later... */ +}; + +/* Serial port */ +struct mace_serial { + volatile unsigned long xxx; /* later... */ +}; + +struct mace_isa { + struct mace_parallel parallel; + char _pad1[0x8000 - sizeof(struct mace_parallel)]; + + struct mace_ecp1284 ecp1284; + char _pad2[0x8000 - sizeof(struct mace_ecp1284)]; + + struct mace_serial serial1; + char _pad3[0x8000 - sizeof(struct mace_serial)]; + + struct mace_serial serial2; + char _pad4[0x8000 - sizeof(struct mace_serial)]; + + volatile unsigned char rtc[0x10000]; +}; + +struct sgi_mace { + char _reserved[0x80000]; + + struct mace_pci pci; + char _pad0[0x80000 - sizeof(struct mace_pci)]; + + struct mace_video video_in1; + char _pad1[0x80000 - sizeof(struct mace_video)]; + + struct mace_video video_in2; + char _pad2[0x80000 - sizeof(struct mace_video)]; + + struct mace_video video_out; + char _pad3[0x80000 - sizeof(struct mace_video)]; + + struct mace_ethernet eth; + char _pad4[0x80000 - sizeof(struct mace_ethernet)]; + + struct mace_perif perif; + char _pad5[0x80000 - sizeof(struct mace_perif)]; + + struct mace_isa isa; + char _pad6[0x80000 - sizeof(struct mace_isa)]; +}; + +extern struct sgi_mace __iomem *mace; + +#endif /* __ASM_MACE_H__ */ diff --git a/arch/mips/include/asm/ipcbuf.h b/arch/mips/include/asm/ipcbuf.h new file mode 100644 index 00000000000..d47d08f264e --- /dev/null +++ b/arch/mips/include/asm/ipcbuf.h @@ -0,0 +1,28 @@ +#ifndef _ASM_IPCBUF_H +#define _ASM_IPCBUF_H + +/* + * The ipc64_perm structure for alpha architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 32-bit seq + * - 2 miscellaneous 64-bit values + */ + +struct ipc64_perm +{ + __kernel_key_t key; + __kernel_uid_t uid; + __kernel_gid_t gid; + __kernel_uid_t cuid; + __kernel_gid_t cgid; + __kernel_mode_t mode; + unsigned short seq; + unsigned short __pad1; + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _ASM_IPCBUF_H */ diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h new file mode 100644 index 00000000000..a58f0eecc68 --- /dev/null +++ b/arch/mips/include/asm/irq.h @@ -0,0 +1,163 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 by Waldorf GMBH, written by Ralf Baechle + * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02, 03 by Ralf Baechle + */ +#ifndef _ASM_IRQ_H +#define _ASM_IRQ_H + +#include + +#include + +#include + +#ifdef CONFIG_I8259 +static inline int irq_canonicalize(int irq) +{ + return ((irq == I8259A_IRQ_BASE + 2) ? I8259A_IRQ_BASE + 9 : irq); +} +#else +#define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ +#endif + +#ifdef CONFIG_MIPS_MT_SMTC + +struct irqaction; + +extern unsigned long irq_hwmask[]; +extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, + unsigned long hwmask); + +static inline void smtc_im_ack_irq(unsigned int irq) +{ + if (irq_hwmask[irq] & ST0_IM) + set_c0_status(irq_hwmask[irq] & ST0_IM); +} + +#else + +static inline void smtc_im_ack_irq(unsigned int irq) +{ +} + +#endif /* CONFIG_MIPS_MT_SMTC */ + +#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF +#include + +extern void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity); +extern void smtc_forward_irq(unsigned int irq); + +/* + * IRQ affinity hook invoked at the beginning of interrupt dispatch + * if option is enabled. + * + * Up through Linux 2.6.22 (at least) cpumask operations are very + * inefficient on MIPS. Initial prototypes of SMTC IRQ affinity + * used a "fast path" per-IRQ-descriptor cache of affinity information + * to reduce latency. As there is a project afoot to optimize the + * cpumask implementations, this version is optimistically assuming + * that cpumask.h macro overhead is reasonable during interrupt dispatch. + */ +#define IRQ_AFFINITY_HOOK(irq) \ +do { \ + if (!cpu_isset(smp_processor_id(), irq_desc[irq].affinity)) { \ + smtc_forward_irq(irq); \ + irq_exit(); \ + return; \ + } \ +} while (0) + +#else /* Not doing SMTC affinity */ + +#define IRQ_AFFINITY_HOOK(irq) do { } while (0) + +#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ + +#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP + +/* + * Clear interrupt mask handling "backstop" if irq_hwmask + * entry so indicates. This implies that the ack() or end() + * functions will take over re-enabling the low-level mask. + * Otherwise it will be done on return from exception. + */ +#define __DO_IRQ_SMTC_HOOK(irq) \ +do { \ + IRQ_AFFINITY_HOOK(irq); \ + if (irq_hwmask[irq] & 0x0000ff00) \ + write_c0_tccontext(read_c0_tccontext() & \ + ~(irq_hwmask[irq] & 0x0000ff00)); \ +} while (0) + +#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) \ +do { \ + if (irq_hwmask[irq] & 0x0000ff00) \ + write_c0_tccontext(read_c0_tccontext() & \ + ~(irq_hwmask[irq] & 0x0000ff00)); \ +} while (0) + +#else + +#define __DO_IRQ_SMTC_HOOK(irq) \ +do { \ + IRQ_AFFINITY_HOOK(irq); \ +} while (0) +#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) do { } while (0) + +#endif + +/* + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + * + * Ideally there should be away to get this into kernel/irq/handle.c to + * avoid the overhead of a call for just a tiny function ... + */ +#define do_IRQ(irq) \ +do { \ + irq_enter(); \ + __DO_IRQ_SMTC_HOOK(irq); \ + generic_handle_irq(irq); \ + irq_exit(); \ +} while (0) + +#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF +/* + * To avoid inefficient and in some cases pathological re-checking of + * IRQ affinity, we have this variant that skips the affinity check. + */ + + +#define do_IRQ_no_affinity(irq) \ +do { \ + irq_enter(); \ + __NO_AFFINITY_IRQ_SMTC_HOOK(irq); \ + generic_handle_irq(irq); \ + irq_exit(); \ +} while (0) + +#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ + +extern void arch_init_irq(void); +extern void spurious_interrupt(void); + +extern int allocate_irqno(void); +extern void alloc_legacy_irqno(void); +extern void free_irqno(unsigned int irq); + +/* + * Before R2 the timer and performance counter interrupts were both fixed to + * IE7. Since R2 their number has to be read from the c0_intctl register. + */ +#define CP0_LEGACY_COMPARE_IRQ 7 + +extern int cp0_compare_irq; +extern int cp0_perfcount_irq; + +#endif /* _ASM_IRQ_H */ diff --git a/arch/mips/include/asm/irq_cpu.h b/arch/mips/include/asm/irq_cpu.h new file mode 100644 index 00000000000..ef6a07cddb2 --- /dev/null +++ b/arch/mips/include/asm/irq_cpu.h @@ -0,0 +1,20 @@ +/* + * include/asm-mips/irq_cpu.h + * + * MIPS CPU interrupt definitions. + * + * Copyright (C) 2002 Maciej W. Rozycki + * + * 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. + */ +#ifndef _ASM_IRQ_CPU_H +#define _ASM_IRQ_CPU_H + +extern void mips_cpu_irq_init(void); +extern void rm7k_cpu_irq_init(void); +extern void rm9k_cpu_irq_init(void); + +#endif /* _ASM_IRQ_CPU_H */ diff --git a/arch/mips/include/asm/irq_gt641xx.h b/arch/mips/include/asm/irq_gt641xx.h new file mode 100644 index 00000000000..f9a7c3ac2e6 --- /dev/null +++ b/arch/mips/include/asm/irq_gt641xx.h @@ -0,0 +1,60 @@ +/* + * Galileo/Marvell GT641xx IRQ definitions. + * + * Copyright (C) 2007 Yoichi Yuasa + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _ASM_IRQ_GT641XX_H +#define _ASM_IRQ_GT641XX_H + +#ifndef GT641XX_IRQ_BASE +#define GT641XX_IRQ_BASE 8 +#endif + +#define GT641XX_MEMORY_OUT_OF_RANGE_IRQ (GT641XX_IRQ_BASE + 1) +#define GT641XX_DMA_OUT_OF_RANGE_IRQ (GT641XX_IRQ_BASE + 2) +#define GT641XX_CPU_ACCESS_OUT_OF_RANGE_IRQ (GT641XX_IRQ_BASE + 3) +#define GT641XX_DMA0_IRQ (GT641XX_IRQ_BASE + 4) +#define GT641XX_DMA1_IRQ (GT641XX_IRQ_BASE + 5) +#define GT641XX_DMA2_IRQ (GT641XX_IRQ_BASE + 6) +#define GT641XX_DMA3_IRQ (GT641XX_IRQ_BASE + 7) +#define GT641XX_TIMER0_IRQ (GT641XX_IRQ_BASE + 8) +#define GT641XX_TIMER1_IRQ (GT641XX_IRQ_BASE + 9) +#define GT641XX_TIMER2_IRQ (GT641XX_IRQ_BASE + 10) +#define GT641XX_TIMER3_IRQ (GT641XX_IRQ_BASE + 11) +#define GT641XX_PCI_0_MASTER_READ_ERROR_IRQ (GT641XX_IRQ_BASE + 12) +#define GT641XX_PCI_0_SLAVE_WRITE_ERROR_IRQ (GT641XX_IRQ_BASE + 13) +#define GT641XX_PCI_0_MASTER_WRITE_ERROR_IRQ (GT641XX_IRQ_BASE + 14) +#define GT641XX_PCI_0_SLAVE_READ_ERROR_IRQ (GT641XX_IRQ_BASE + 15) +#define GT641XX_PCI_0_ADDRESS_ERROR_IRQ (GT641XX_IRQ_BASE + 16) +#define GT641XX_MEMORY_ERROR_IRQ (GT641XX_IRQ_BASE + 17) +#define GT641XX_PCI_0_MASTER_ABORT_IRQ (GT641XX_IRQ_BASE + 18) +#define GT641XX_PCI_0_TARGET_ABORT_IRQ (GT641XX_IRQ_BASE + 19) +#define GT641XX_PCI_0_RETRY_TIMEOUT_IRQ (GT641XX_IRQ_BASE + 20) +#define GT641XX_CPU_INT0_IRQ (GT641XX_IRQ_BASE + 21) +#define GT641XX_CPU_INT1_IRQ (GT641XX_IRQ_BASE + 22) +#define GT641XX_CPU_INT2_IRQ (GT641XX_IRQ_BASE + 23) +#define GT641XX_CPU_INT3_IRQ (GT641XX_IRQ_BASE + 24) +#define GT641XX_CPU_INT4_IRQ (GT641XX_IRQ_BASE + 25) +#define GT641XX_PCI_INT0_IRQ (GT641XX_IRQ_BASE + 26) +#define GT641XX_PCI_INT1_IRQ (GT641XX_IRQ_BASE + 27) +#define GT641XX_PCI_INT2_IRQ (GT641XX_IRQ_BASE + 28) +#define GT641XX_PCI_INT3_IRQ (GT641XX_IRQ_BASE + 29) + +extern void gt641xx_irq_dispatch(void); +extern void gt641xx_irq_init(void); + +#endif /* _ASM_IRQ_GT641XX_H */ diff --git a/arch/mips/include/asm/irq_regs.h b/arch/mips/include/asm/irq_regs.h new file mode 100644 index 00000000000..33bd2a06de5 --- /dev/null +++ b/arch/mips/include/asm/irq_regs.h @@ -0,0 +1,21 @@ +/* + * 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. + * + * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_IRQ_REGS_H +#define __ASM_IRQ_REGS_H + +#define ARCH_HAS_OWN_IRQ_REGS + +#include + +static inline struct pt_regs *get_irq_regs(void) +{ + return current_thread_info()->regs; +} + +#endif /* __ASM_IRQ_REGS_H */ diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h new file mode 100644 index 00000000000..701ec0ba8fa --- /dev/null +++ b/arch/mips/include/asm/irqflags.h @@ -0,0 +1,283 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle + * Copyright (C) 1996 by Paul M. Antoine + * Copyright (C) 1999 Silicon Graphics + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +#ifndef __ASSEMBLY__ + +#include +#include + +__asm__( + " .macro raw_local_irq_enable \n" + " .set push \n" + " .set reorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n" + " ori $1, 0x400 \n" + " xori $1, 0x400 \n" + " mtc0 $1, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) + " ei \n" +#else + " mfc0 $1,$12 \n" + " ori $1,0x1f \n" + " xori $1,0x1e \n" + " mtc0 $1,$12 \n" +#endif + " irq_enable_hazard \n" + " .set pop \n" + " .endm"); + +extern void smtc_ipi_replay(void); + +static inline void raw_local_irq_enable(void) +{ +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC kernel needs to do a software replay of queued + * IPIs, at the cost of call overhead on each local_irq_enable() + */ + smtc_ipi_replay(); +#endif + __asm__ __volatile__( + "raw_local_irq_enable" + : /* no outputs */ + : /* no inputs */ + : "memory"); +} + + +/* + * For cli() we have to insert nops to make sure that the new value + * has actually arrived in the status register before the end of this + * macro. + * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs + * no nops at all. + */ +/* + * For TX49, operating only IE bit is not enough. + * + * If mfc0 $12 follows store and the mfc0 is last instruction of a + * page and fetching the next instruction causes TLB miss, the result + * of the mfc0 might wrongly contain EXL bit. + * + * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008 + * + * Workaround: mask EXL bit of the result or place a nop before mfc0. + */ +__asm__( + " .macro raw_local_irq_disable\n" + " .set push \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 $1, $2, 1 \n" + " ori $1, 0x400 \n" + " .set noreorder \n" + " mtc0 $1, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) + " di \n" +#else + " mfc0 $1,$12 \n" + " ori $1,0x1f \n" + " xori $1,0x1f \n" + " .set noreorder \n" + " mtc0 $1,$12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +static inline void raw_local_irq_disable(void) +{ + __asm__ __volatile__( + "raw_local_irq_disable" + : /* no outputs */ + : /* no inputs */ + : "memory"); +} + +__asm__( + " .macro raw_local_save_flags flags \n" + " .set push \n" + " .set reorder \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 \\flags, $2, 1 \n" +#else + " mfc0 \\flags, $12 \n" +#endif + " .set pop \n" + " .endm \n"); + +#define raw_local_save_flags(x) \ +__asm__ __volatile__( \ + "raw_local_save_flags %0" \ + : "=r" (x)) + +__asm__( + " .macro raw_local_irq_save result \n" + " .set push \n" + " .set reorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 \\result, $2, 1 \n" + " ori $1, \\result, 0x400 \n" + " .set noreorder \n" + " mtc0 $1, $2, 1 \n" + " andi \\result, \\result, 0x400 \n" +#elif defined(CONFIG_CPU_MIPSR2) + " di \\result \n" + " andi \\result, 1 \n" +#else + " mfc0 \\result, $12 \n" + " ori $1, \\result, 0x1f \n" + " xori $1, 0x1f \n" + " .set noreorder \n" + " mtc0 $1, $12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +#define raw_local_irq_save(x) \ +__asm__ __volatile__( \ + "raw_local_irq_save\t%0" \ + : "=r" (x) \ + : /* no inputs */ \ + : "memory") + +__asm__( + " .macro raw_local_irq_restore flags \n" + " .set push \n" + " .set noreorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + "mfc0 $1, $2, 1 \n" + "andi \\flags, 0x400 \n" + "ori $1, 0x400 \n" + "xori $1, 0x400 \n" + "or \\flags, $1 \n" + "mtc0 \\flags, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) + /* + * Slow, but doesn't suffer from a relativly unlikely race + * condition we're having since days 1. + */ + " beqz \\flags, 1f \n" + " di \n" + " ei \n" + "1: \n" +#elif defined(CONFIG_CPU_MIPSR2) + /* + * Fast, dangerous. Life is fun, life is good. + */ + " mfc0 $1, $12 \n" + " ins $1, \\flags, 0, 1 \n" + " mtc0 $1, $12 \n" +#else + " mfc0 $1, $12 \n" + " andi \\flags, 1 \n" + " ori $1, 0x1f \n" + " xori $1, 0x1f \n" + " or \\flags, $1 \n" + " mtc0 \\flags, $12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + + +static inline void raw_local_irq_restore(unsigned long flags) +{ + unsigned long __tmp1; + +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC kernel needs to do a software replay of queued + * IPIs, at the cost of branch and call overhead on each + * local_irq_restore() + */ + if (unlikely(!(flags & 0x0400))) + smtc_ipi_replay(); +#endif + + __asm__ __volatile__( + "raw_local_irq_restore\t%0" + : "=r" (__tmp1) + : "0" (flags) + : "memory"); +} + +static inline void __raw_local_irq_restore(unsigned long flags) +{ + unsigned long __tmp1; + + __asm__ __volatile__( + "raw_local_irq_restore\t%0" + : "=r" (__tmp1) + : "0" (flags) + : "memory"); +} + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU + */ + return flags & 0x400; +#else + return !(flags & 1); +#endif +} + +#endif + +/* + * Do the CPU's IRQ-state tracing from assembly code. + */ +#ifdef CONFIG_TRACE_IRQFLAGS +/* Reload some registers clobbered by trace_hardirqs_on */ +#ifdef CONFIG_64BIT +# define TRACE_IRQS_RELOAD_REGS \ + LONG_L $11, PT_R11(sp); \ + LONG_L $10, PT_R10(sp); \ + LONG_L $9, PT_R9(sp); \ + LONG_L $8, PT_R8(sp); \ + LONG_L $7, PT_R7(sp); \ + LONG_L $6, PT_R6(sp); \ + LONG_L $5, PT_R5(sp); \ + LONG_L $4, PT_R4(sp); \ + LONG_L $2, PT_R2(sp) +#else +# define TRACE_IRQS_RELOAD_REGS \ + LONG_L $7, PT_R7(sp); \ + LONG_L $6, PT_R6(sp); \ + LONG_L $5, PT_R5(sp); \ + LONG_L $4, PT_R4(sp); \ + LONG_L $2, PT_R2(sp) +#endif +# define TRACE_IRQS_ON \ + CLI; /* make sure trace_hardirqs_on() is called in kernel level */ \ + jal trace_hardirqs_on +# define TRACE_IRQS_ON_RELOAD \ + TRACE_IRQS_ON; \ + TRACE_IRQS_RELOAD_REGS +# define TRACE_IRQS_OFF \ + jal trace_hardirqs_off +#else +# define TRACE_IRQS_ON +# define TRACE_IRQS_ON_RELOAD +# define TRACE_IRQS_OFF +#endif + +#endif /* _ASM_IRQFLAGS_H */ diff --git a/arch/mips/include/asm/isadep.h b/arch/mips/include/asm/isadep.h new file mode 100644 index 00000000000..24c6cda7937 --- /dev/null +++ b/arch/mips/include/asm/isadep.h @@ -0,0 +1,34 @@ +/* + * Various ISA level dependent constants. + * Most of the following constants reflect the different layout + * of Coprocessor 0 registers. + * + * Copyright (c) 1998 Harald Koerfgen + */ + +#ifndef __ASM_ISADEP_H +#define __ASM_ISADEP_H + +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) +/* + * R2000 or R3000 + */ + +/* + * kernel or user mode? (CP0_STATUS) + */ +#define KU_MASK 0x08 +#define KU_USER 0x08 +#define KU_KERN 0x00 + +#else +/* + * kernel or user mode? + */ +#define KU_MASK 0x18 +#define KU_USER 0x10 +#define KU_KERN 0x00 + +#endif + +#endif /* __ASM_ISADEP_H */ diff --git a/arch/mips/include/asm/jazz.h b/arch/mips/include/asm/jazz.h new file mode 100644 index 00000000000..83f449dec95 --- /dev/null +++ b/arch/mips/include/asm/jazz.h @@ -0,0 +1,310 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995 - 1998 by Andreas Busse and Ralf Baechle + */ +#ifndef __ASM_JAZZ_H +#define __ASM_JAZZ_H + +/* + * The addresses below are virtual address. The mappings are + * created on startup via wired entries in the tlb. The Mips + * Magnum R3000 and R4000 machines are similar in many aspects, + * but many hardware register are accessible at 0xb9000000 in + * instead of 0xe0000000. + */ + +#define JAZZ_LOCAL_IO_SPACE 0xe0000000 + +/* + * Revision numbers in PICA_ASIC_REVISION + * + * 0xf0000000 - Rev1 + * 0xf0000001 - Rev2 + * 0xf0000002 - Rev3 + */ +#define PICA_ASIC_REVISION 0xe0000008 + +/* + * The segments of the seven segment LED are mapped + * to the control bits as follows: + * + * (7) + * --------- + * | | + * (2) | | (6) + * | (1) | + * --------- + * | | + * (3) | | (5) + * | (4) | + * --------- . (0) + */ +#define PICA_LED 0xe000f000 + +/* + * Some characters for the LED control registers + * The original Mips machines seem to have a LED display + * with integrated decoder while the Acer machines can + * control each of the seven segments and the dot independently. + * It's only a toy, anyway... + */ +#define LED_DOT 0x01 +#define LED_SPACE 0x00 +#define LED_0 0xfc +#define LED_1 0x60 +#define LED_2 0xda +#define LED_3 0xf2 +#define LED_4 0x66 +#define LED_5 0xb6 +#define LED_6 0xbe +#define LED_7 0xe0 +#define LED_8 0xfe +#define LED_9 0xf6 +#define LED_A 0xee +#define LED_b 0x3e +#define LED_C 0x9c +#define LED_d 0x7a +#define LED_E 0x9e +#define LED_F 0x8e + +#ifndef __ASSEMBLY__ + +static __inline__ void pica_set_led(unsigned int bits) +{ + volatile unsigned int *led_register = (unsigned int *) PICA_LED; + + *led_register = bits; +} + +#endif /* !__ASSEMBLY__ */ + +/* + * Base address of the Sonic Ethernet adapter in Jazz machines. + */ +#define JAZZ_ETHERNET_BASE 0xe0001000 + +/* + * Base address of the 53C94 SCSI hostadapter in Jazz machines. + */ +#define JAZZ_SCSI_BASE 0xe0002000 + +/* + * i8042 keyboard controller for JAZZ and PICA chipsets. + * This address is just a guess and seems to differ from + * other mips machines such as RC3xxx... + */ +#define JAZZ_KEYBOARD_ADDRESS 0xe0005000 +#define JAZZ_KEYBOARD_DATA 0xe0005000 +#define JAZZ_KEYBOARD_COMMAND 0xe0005001 + +#ifndef __ASSEMBLY__ + +typedef struct { + unsigned char data; + unsigned char command; +} jazz_keyboard_hardware; + +#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS) + +typedef struct { + unsigned char pad0[3]; + unsigned char data; + unsigned char pad1[3]; + unsigned char command; +} mips_keyboard_hardware; + +/* + * For now. Needs to be changed for RC3xxx support. See below. + */ +#define keyboard_hardware jazz_keyboard_hardware + +#endif /* !__ASSEMBLY__ */ + +/* + * i8042 keyboard controller for most other Mips machines. + */ +#define MIPS_KEYBOARD_ADDRESS 0xb9005000 +#define MIPS_KEYBOARD_DATA 0xb9005003 +#define MIPS_KEYBOARD_COMMAND 0xb9005007 + +/* + * Serial and parallel ports (WD 16C552) on the Mips JAZZ + */ +#define JAZZ_SERIAL1_BASE (unsigned int)0xe0006000 +#define JAZZ_SERIAL2_BASE (unsigned int)0xe0007000 +#define JAZZ_PARALLEL_BASE (unsigned int)0xe0008000 + +/* + * Dummy Device Address. Used in jazzdma.c + */ +#define JAZZ_DUMMY_DEVICE 0xe000d000 + +/* + * JAZZ timer registers and interrupt no. + * Note that the hardware timer interrupt is actually on + * cpu level 6, but to keep compatibility with PC stuff + * it is remapped to vector 0. See arch/mips/kernel/entry.S. + */ +#define JAZZ_TIMER_INTERVAL 0xe0000228 +#define JAZZ_TIMER_REGISTER 0xe0000230 + +/* + * DRAM configuration register + */ +#ifndef __ASSEMBLY__ +#ifdef __MIPSEL__ +typedef struct { + unsigned int bank2 : 3; + unsigned int bank1 : 3; + unsigned int mem_bus_width : 1; + unsigned int reserved2 : 1; + unsigned int page_mode : 1; + unsigned int reserved1 : 23; +} dram_configuration; +#else /* defined (__MIPSEB__) */ +typedef struct { + unsigned int reserved1 : 23; + unsigned int page_mode : 1; + unsigned int reserved2 : 1; + unsigned int mem_bus_width : 1; + unsigned int bank1 : 3; + unsigned int bank2 : 3; +} dram_configuration; +#endif +#endif /* !__ASSEMBLY__ */ + +#define PICA_DRAM_CONFIG 0xe00fffe0 + +/* + * JAZZ interrupt control registers + */ +#define JAZZ_IO_IRQ_SOURCE 0xe0010000 +#define JAZZ_IO_IRQ_ENABLE 0xe0010002 + +/* + * JAZZ Interrupt Level definitions + * + * This is somewhat broken. For reasons which nobody can remember anymore + * we remap the Jazz interrupts to the usual ISA style interrupt numbers. + */ +#define JAZZ_IRQ_START 24 +#define JAZZ_IRQ_END (24 + 9) +#define JAZZ_PARALLEL_IRQ (JAZZ_IRQ_START + 0) +#define JAZZ_FLOPPY_IRQ (JAZZ_IRQ_START + 1) +#define JAZZ_SOUND_IRQ (JAZZ_IRQ_START + 2) +#define JAZZ_VIDEO_IRQ (JAZZ_IRQ_START + 3) +#define JAZZ_ETHERNET_IRQ (JAZZ_IRQ_START + 4) +#define JAZZ_SCSI_IRQ (JAZZ_IRQ_START + 5) +#define JAZZ_KEYBOARD_IRQ (JAZZ_IRQ_START + 6) +#define JAZZ_MOUSE_IRQ (JAZZ_IRQ_START + 7) +#define JAZZ_SERIAL1_IRQ (JAZZ_IRQ_START + 8) +#define JAZZ_SERIAL2_IRQ (JAZZ_IRQ_START + 9) + +#define JAZZ_TIMER_IRQ (MIPS_CPU_IRQ_BASE+6) + + +/* + * JAZZ DMA Channels + * Note: Channels 4...7 are not used with respect to the Acer PICA-61 + * chipset which does not provide these DMA channels. + */ +#define JAZZ_SCSI_DMA 0 /* SCSI */ +#define JAZZ_FLOPPY_DMA 1 /* FLOPPY */ +#define JAZZ_AUDIOL_DMA 2 /* AUDIO L */ +#define JAZZ_AUDIOR_DMA 3 /* AUDIO R */ + +/* + * JAZZ R4030 MCT_ADR chip (DMA controller) + * Note: Virtual Addresses ! + */ +#define JAZZ_R4030_CONFIG 0xE0000000 /* R4030 config register */ +#define JAZZ_R4030_REVISION 0xE0000008 /* same as PICA_ASIC_REVISION */ +#define JAZZ_R4030_INV_ADDR 0xE0000010 /* Invalid Address register */ + +#define JAZZ_R4030_TRSTBL_BASE 0xE0000018 /* Translation Table Base */ +#define JAZZ_R4030_TRSTBL_LIM 0xE0000020 /* Translation Table Limit */ +#define JAZZ_R4030_TRSTBL_INV 0xE0000028 /* Translation Table Invalidate */ + +#define JAZZ_R4030_CACHE_MTNC 0xE0000030 /* Cache Maintenance */ +#define JAZZ_R4030_R_FAIL_ADDR 0xE0000038 /* Remote Failed Address */ +#define JAZZ_R4030_M_FAIL_ADDR 0xE0000040 /* Memory Failed Address */ + +#define JAZZ_R4030_CACHE_PTAG 0xE0000048 /* I/O Cache Physical Tag */ +#define JAZZ_R4030_CACHE_LTAG 0xE0000050 /* I/O Cache Logical Tag */ +#define JAZZ_R4030_CACHE_BMASK 0xE0000058 /* I/O Cache Byte Mask */ +#define JAZZ_R4030_CACHE_BWIN 0xE0000060 /* I/O Cache Buffer Window */ + +/* + * Remote Speed Registers. + * + * 0: free, 1: Ethernet, 2: SCSI, 3: Floppy, + * 4: RTC, 5: Kb./Mouse 6: serial 1, 7: serial 2, + * 8: parallel, 9: NVRAM, 10: CPU, 11: PROM, + * 12: reserved, 13: free, 14: 7seg LED, 15: ??? + */ +#define JAZZ_R4030_REM_SPEED 0xE0000070 /* 16 Remote Speed Registers */ + /* 0xE0000070,78,80... 0xE00000E8 */ +#define JAZZ_R4030_IRQ_ENABLE 0xE00000E8 /* Internal Interrupt Enable */ +#define JAZZ_R4030_INVAL_ADDR 0xE0000010 /* Invalid address Register */ +#define JAZZ_R4030_IRQ_SOURCE 0xE0000200 /* Interrupt Source Register */ +#define JAZZ_R4030_I386_ERROR 0xE0000208 /* i386/EISA Bus Error */ + +/* + * Virtual (E)ISA controller address + */ +#define JAZZ_EISA_IRQ_ACK 0xE0000238 /* EISA interrupt acknowledge */ + +/* + * Access the R4030 DMA and I/O Controller + */ +#ifndef __ASSEMBLY__ + +static inline void r4030_delay(void) +{ +__asm__ __volatile__( + ".set\tnoreorder\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\treorder"); +} + +static inline unsigned short r4030_read_reg16(unsigned long addr) +{ + unsigned short ret = *((volatile unsigned short *)addr); + r4030_delay(); + return ret; +} + +static inline unsigned int r4030_read_reg32(unsigned long addr) +{ + unsigned int ret = *((volatile unsigned int *)addr); + r4030_delay(); + return ret; +} + +static inline void r4030_write_reg16(unsigned long addr, unsigned val) +{ + *((volatile unsigned short *)addr) = val; + r4030_delay(); +} + +static inline void r4030_write_reg32(unsigned long addr, unsigned val) +{ + *((volatile unsigned int *)addr) = val; + r4030_delay(); +} + +#endif /* !__ASSEMBLY__ */ + +#define JAZZ_FDC_BASE 0xe0003000 +#define JAZZ_RTC_BASE 0xe0004000 +#define JAZZ_PORT_BASE 0xe2000000 + +#define JAZZ_EISA_BASE 0xe3000000 + +#endif /* __ASM_JAZZ_H */ diff --git a/arch/mips/include/asm/jazzdma.h b/arch/mips/include/asm/jazzdma.h new file mode 100644 index 00000000000..8bb37bba68f --- /dev/null +++ b/arch/mips/include/asm/jazzdma.h @@ -0,0 +1,95 @@ +/* + * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support + */ +#ifndef _ASM_JAZZDMA_H +#define _ASM_JAZZDMA_H + +/* + * Prototypes and macros + */ +extern unsigned long vdma_alloc(unsigned long paddr, unsigned long size); +extern int vdma_free(unsigned long laddr); +extern int vdma_remap(unsigned long laddr, unsigned long paddr, + unsigned long size); +extern unsigned long vdma_phys2log(unsigned long paddr); +extern unsigned long vdma_log2phys(unsigned long laddr); +extern void vdma_stats(void); /* for debugging only */ + +extern void vdma_enable(int channel); +extern void vdma_disable(int channel); +extern void vdma_set_mode(int channel, int mode); +extern void vdma_set_addr(int channel, long addr); +extern void vdma_set_count(int channel, int count); +extern int vdma_get_residue(int channel); +extern int vdma_get_enable(int channel); + +/* + * some definitions used by the driver functions + */ +#define VDMA_PAGESIZE 4096 +#define VDMA_PGTBL_ENTRIES 4096 +#define VDMA_PGTBL_SIZE (sizeof(VDMA_PGTBL_ENTRY) * VDMA_PGTBL_ENTRIES) +#define VDMA_PAGE_EMPTY 0xff000000 + +/* + * Macros to get page no. and offset of a given address + * Note that VDMA_PAGE() works for physical addresses only + */ +#define VDMA_PAGE(a) ((unsigned int)(a) >> 12) +#define VDMA_OFFSET(a) ((unsigned int)(a) & (VDMA_PAGESIZE-1)) + +/* + * error code returned by vdma_alloc() + * (See also arch/mips/kernel/jazzdma.c) + */ +#define VDMA_ERROR 0xffffffff + +/* + * VDMA pagetable entry description + */ +typedef volatile struct VDMA_PGTBL_ENTRY { + unsigned int frame; /* physical frame no. */ + unsigned int owner; /* owner of this entry (0=free) */ +} VDMA_PGTBL_ENTRY; + + +/* + * DMA channel control registers + * in the R4030 MCT_ADR chip + */ +#define JAZZ_R4030_CHNL_MODE 0xE0000100 /* 8 DMA Channel Mode Registers, */ + /* 0xE0000100,120,140... */ +#define JAZZ_R4030_CHNL_ENABLE 0xE0000108 /* 8 DMA Channel Enable Regs, */ + /* 0xE0000108,128,148... */ +#define JAZZ_R4030_CHNL_COUNT 0xE0000110 /* 8 DMA Channel Byte Cnt Regs, */ + /* 0xE0000110,130,150... */ +#define JAZZ_R4030_CHNL_ADDR 0xE0000118 /* 8 DMA Channel Address Regs, */ + /* 0xE0000118,138,158... */ + +/* channel enable register bits */ + +#define R4030_CHNL_ENABLE (1<<0) +#define R4030_CHNL_WRITE (1<<1) +#define R4030_TC_INTR (1<<8) +#define R4030_MEM_INTR (1<<9) +#define R4030_ADDR_INTR (1<<10) + +/* + * Channel mode register bits + */ +#define R4030_MODE_ATIME_40 (0) /* device access time on remote bus */ +#define R4030_MODE_ATIME_80 (1) +#define R4030_MODE_ATIME_120 (2) +#define R4030_MODE_ATIME_160 (3) +#define R4030_MODE_ATIME_200 (4) +#define R4030_MODE_ATIME_240 (5) +#define R4030_MODE_ATIME_280 (6) +#define R4030_MODE_ATIME_320 (7) +#define R4030_MODE_WIDTH_8 (1<<3) /* device data bus width */ +#define R4030_MODE_WIDTH_16 (2<<3) +#define R4030_MODE_WIDTH_32 (3<<3) +#define R4030_MODE_INTR_EN (1<<5) +#define R4030_MODE_BURST (1<<6) /* Rev. 2 only */ +#define R4030_MODE_FAST_ACK (1<<7) /* Rev. 2 only */ + +#endif /* _ASM_JAZZDMA_H */ diff --git a/arch/mips/include/asm/kdebug.h b/arch/mips/include/asm/kdebug.h new file mode 100644 index 00000000000..5bf62aafc89 --- /dev/null +++ b/arch/mips/include/asm/kdebug.h @@ -0,0 +1,13 @@ +#ifndef _ASM_MIPS_KDEBUG_H +#define _ASM_MIPS_KDEBUG_H + +#include + +enum die_val { + DIE_OOPS = 1, + DIE_FP, + DIE_TRAP, + DIE_RI, +}; + +#endif /* _ASM_MIPS_KDEBUG_H */ diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h new file mode 100644 index 00000000000..4314892aaeb --- /dev/null +++ b/arch/mips/include/asm/kexec.h @@ -0,0 +1,30 @@ +/* + * kexec.h for kexec + * Created by on Thu Oct 12 14:59:34 2006 + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#ifndef _MIPS_KEXEC +# define _MIPS_KEXEC + +/* Maximum physical address we can use pages from */ +#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000) +/* Maximum address we can reach in physical address mode */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000) + /* Maximum address we can use for the control code buffer */ +#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000) + +#define KEXEC_CONTROL_PAGE_SIZE 4096 + +/* The native architecture */ +#define KEXEC_ARCH KEXEC_ARCH_MIPS + +static inline void crash_setup_regs(struct pt_regs *newregs, + struct pt_regs *oldregs) +{ + /* Dummy implementation for now */ +} + +#endif /* !_MIPS_KEXEC */ diff --git a/arch/mips/include/asm/kgdb.h b/arch/mips/include/asm/kgdb.h new file mode 100644 index 00000000000..48223b09396 --- /dev/null +++ b/arch/mips/include/asm/kgdb.h @@ -0,0 +1,44 @@ +#ifndef __ASM_KGDB_H_ +#define __ASM_KGDB_H_ + +#ifdef __KERNEL__ + +#include + +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) + +#define KGDB_GDB_REG_SIZE 32 + +#elif (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS64) + +#ifdef CONFIG_32BIT +#define KGDB_GDB_REG_SIZE 32 +#else /* CONFIG_CPU_32BIT */ +#define KGDB_GDB_REG_SIZE 64 +#endif +#else +#error "Need to set KGDB_GDB_REG_SIZE for MIPS ISA" +#endif /* _MIPS_ISA */ + +#define BUFMAX 2048 +#if (KGDB_GDB_REG_SIZE == 32) +#define NUMREGBYTES (90*sizeof(u32)) +#define NUMCRITREGBYTES (12*sizeof(u32)) +#else +#define NUMREGBYTES (90*sizeof(u64)) +#define NUMCRITREGBYTES (12*sizeof(u64)) +#endif +#define BREAK_INSTR_SIZE 4 +#define CACHE_FLUSH_IS_SAFE 0 + +extern void arch_kgdb_breakpoint(void); +extern int kgdb_early_setup; +extern void *saved_vectors[32]; +extern void handle_exception(struct pt_regs *regs); +extern void breakinst(void); + +#endif /* __KERNEL__ */ + +#endif /* __ASM_KGDB_H_ */ diff --git a/arch/mips/include/asm/kmap_types.h b/arch/mips/include/asm/kmap_types.h new file mode 100644 index 00000000000..806aae3c533 --- /dev/null +++ b/arch/mips/include/asm/kmap_types.h @@ -0,0 +1,30 @@ +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + + +#ifdef CONFIG_DEBUG_HIGHMEM +# define D(n) __KM_FENCE_##n , +#else +# define D(n) +#endif + +enum km_type { +D(0) KM_BOUNCE_READ, +D(1) KM_SKB_SUNRPC_DATA, +D(2) KM_SKB_DATA_SOFTIRQ, +D(3) KM_USER0, +D(4) KM_USER1, +D(5) KM_BIO_SRC_IRQ, +D(6) KM_BIO_DST_IRQ, +D(7) KM_PTE0, +D(8) KM_PTE1, +D(9) KM_IRQ0, +D(10) KM_IRQ1, +D(11) KM_SOFTIRQ0, +D(12) KM_SOFTIRQ1, +D(13) KM_TYPE_NR +}; + +#undef D + +#endif diff --git a/arch/mips/include/asm/kspd.h b/arch/mips/include/asm/kspd.h new file mode 100644 index 00000000000..4e9e724c893 --- /dev/null +++ b/arch/mips/include/asm/kspd.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_KSPD_H +#define _ASM_KSPD_H + +struct kspd_notifications { + void (*kspd_sp_exit)(int sp_id); + + struct list_head list; +}; + +#ifdef CONFIG_MIPS_APSP_KSPD +extern void kspd_notify(struct kspd_notifications *notify); +#else +static inline void kspd_notify(struct kspd_notifications *notify) +{ +} +#endif + +#endif diff --git a/arch/mips/include/asm/lasat/ds1603.h b/arch/mips/include/asm/lasat/ds1603.h new file mode 100644 index 00000000000..edcd7544b35 --- /dev/null +++ b/arch/mips/include/asm/lasat/ds1603.h @@ -0,0 +1,18 @@ +#include + +/* Lasat 100 */ +#define DS1603_REG_100 (KSEG1ADDR(0x1c810000)) +#define DS1603_RST_100 (1 << 2) +#define DS1603_CLK_100 (1 << 0) +#define DS1603_DATA_SHIFT_100 1 +#define DS1603_DATA_100 (1 << DS1603_DATA_SHIFT_100) + +/* Lasat 200 */ +#define DS1603_REG_200 (KSEG1ADDR(0x11000000)) +#define DS1603_RST_200 (1 << 3) +#define DS1603_CLK_200 (1 << 4) +#define DS1603_DATA_200 (1 << 5) + +#define DS1603_DATA_REG_200 (DS1603_REG_200 + 0x10000) +#define DS1603_DATA_READ_SHIFT_200 9 +#define DS1603_DATA_READ_200 (1 << DS1603_DATA_READ_SHIFT_200) diff --git a/arch/mips/include/asm/lasat/eeprom.h b/arch/mips/include/asm/lasat/eeprom.h new file mode 100644 index 00000000000..3dac203697f --- /dev/null +++ b/arch/mips/include/asm/lasat/eeprom.h @@ -0,0 +1,17 @@ +#include + +/* lasat 100 */ +#define AT93C_REG_100 KSEG1ADDR(0x1c810000) +#define AT93C_RDATA_REG_100 AT93C_REG_100 +#define AT93C_RDATA_SHIFT_100 4 +#define AT93C_WDATA_SHIFT_100 4 +#define AT93C_CS_M_100 (1 << 5) +#define AT93C_CLK_M_100 (1 << 3) + +/* lasat 200 */ +#define AT93C_REG_200 KSEG1ADDR(0x11000000) +#define AT93C_RDATA_REG_200 (AT93C_REG_200+0x10000) +#define AT93C_RDATA_SHIFT_200 8 +#define AT93C_WDATA_SHIFT_200 2 +#define AT93C_CS_M_200 (1 << 0) +#define AT93C_CLK_M_200 (1 << 1) diff --git a/arch/mips/include/asm/lasat/head.h b/arch/mips/include/asm/lasat/head.h new file mode 100644 index 00000000000..f5589f31a19 --- /dev/null +++ b/arch/mips/include/asm/lasat/head.h @@ -0,0 +1,22 @@ +/* + * Image header stuff + */ +#ifndef _HEAD_H +#define _HEAD_H + +#define LASAT_K_MAGIC0_VAL 0xfedeabba +#define LASAT_K_MAGIC1_VAL 0x00bedead + +#ifndef _LANGUAGE_ASSEMBLY +#include +struct bootloader_header { + u32 magic[2]; + u32 version; + u32 image_start; + u32 image_size; + u32 kernel_start; + u32 kernel_entry; +}; +#endif + +#endif /* _HEAD_H */ diff --git a/arch/mips/include/asm/lasat/lasat.h b/arch/mips/include/asm/lasat/lasat.h new file mode 100644 index 00000000000..caeba1e302a --- /dev/null +++ b/arch/mips/include/asm/lasat/lasat.h @@ -0,0 +1,258 @@ +/* + * lasat.h + * + * Thomas Horsten + * Copyright (C) 2000 LASAT Networks A/S. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Configuration for LASAT boards, loads the appropriate include files. + */ +#ifndef _LASAT_H +#define _LASAT_H + +#ifndef _LANGUAGE_ASSEMBLY + +extern struct lasat_misc { + volatile u32 *reset_reg; + volatile u32 *flash_wp_reg; + u32 flash_wp_bit; +} *lasat_misc; + +enum lasat_mtdparts { + LASAT_MTD_BOOTLOADER, + LASAT_MTD_SERVICE, + LASAT_MTD_NORMAL, + LASAT_MTD_CONFIG, + LASAT_MTD_FS, + LASAT_MTD_LAST +}; + +/* + * The format of the data record in the EEPROM. + * See Documentation/LASAT/eeprom.txt for a detailed description + * of the fields in this struct, and the LASAT Hardware Configuration + * field specification for a detailed description of the config + * field. + */ +#include + +#define LASAT_EEPROM_VERSION 7 +struct lasat_eeprom_struct { + unsigned int version; + unsigned int cfg[3]; + unsigned char hwaddr[6]; + unsigned char print_partno[12]; + unsigned char term0; + unsigned char print_serial[14]; + unsigned char term1; + unsigned char prod_partno[12]; + unsigned char term2; + unsigned char prod_serial[14]; + unsigned char term3; + unsigned char passwd_hash[16]; + unsigned char pwdnull; + unsigned char vendid; + unsigned char ts_ref; + unsigned char ts_signoff; + unsigned char reserved[11]; + unsigned char debugaccess; + unsigned short prid; + unsigned int serviceflag; + unsigned int ipaddr; + unsigned int netmask; + unsigned int crc32; +}; + +struct lasat_eeprom_struct_pre7 { + unsigned int version; + unsigned int flags[3]; + unsigned char hwaddr0[6]; + unsigned char hwaddr1[6]; + unsigned char print_partno[9]; + unsigned char term0; + unsigned char print_serial[14]; + unsigned char term1; + unsigned char prod_partno[9]; + unsigned char term2; + unsigned char prod_serial[14]; + unsigned char term3; + unsigned char passwd_hash[24]; + unsigned char pwdnull; + unsigned char vendor; + unsigned char ts_ref; + unsigned char ts_signoff; + unsigned char reserved[6]; + unsigned int writecount; + unsigned int ipaddr; + unsigned int netmask; + unsigned int crc32; +}; + +/* Configuration descriptor encoding - see the doc for details */ + +#define LASAT_W0_DSCTYPE(v) (((v)) & 0xf) +#define LASAT_W0_BMID(v) (((v) >> 0x04) & 0xf) +#define LASAT_W0_CPUTYPE(v) (((v) >> 0x08) & 0xf) +#define LASAT_W0_BUSSPEED(v) (((v) >> 0x0c) & 0xf) +#define LASAT_W0_CPUCLK(v) (((v) >> 0x10) & 0xf) +#define LASAT_W0_SDRAMBANKSZ(v) (((v) >> 0x14) & 0xf) +#define LASAT_W0_SDRAMBANKS(v) (((v) >> 0x18) & 0xf) +#define LASAT_W0_L2CACHE(v) (((v) >> 0x1c) & 0xf) + +#define LASAT_W1_EDHAC(v) (((v)) & 0xf) +#define LASAT_W1_HIFN(v) (((v) >> 0x04) & 0x1) +#define LASAT_W1_ISDN(v) (((v) >> 0x05) & 0x1) +#define LASAT_W1_IDE(v) (((v) >> 0x06) & 0x1) +#define LASAT_W1_HDLC(v) (((v) >> 0x07) & 0x1) +#define LASAT_W1_USVERSION(v) (((v) >> 0x08) & 0x1) +#define LASAT_W1_4MACS(v) (((v) >> 0x09) & 0x1) +#define LASAT_W1_EXTSERIAL(v) (((v) >> 0x0a) & 0x1) +#define LASAT_W1_FLASHSIZE(v) (((v) >> 0x0c) & 0xf) +#define LASAT_W1_PCISLOTS(v) (((v) >> 0x10) & 0xf) +#define LASAT_W1_PCI1OPT(v) (((v) >> 0x14) & 0xf) +#define LASAT_W1_PCI2OPT(v) (((v) >> 0x18) & 0xf) +#define LASAT_W1_PCI3OPT(v) (((v) >> 0x1c) & 0xf) + +/* Routines specific to LASAT boards */ + +#define LASAT_BMID_MASQUERADE2 0 +#define LASAT_BMID_MASQUERADEPRO 1 +#define LASAT_BMID_SAFEPIPE25 2 +#define LASAT_BMID_SAFEPIPE50 3 +#define LASAT_BMID_SAFEPIPE100 4 +#define LASAT_BMID_SAFEPIPE5000 5 +#define LASAT_BMID_SAFEPIPE7000 6 +#define LASAT_BMID_SAFEPIPE1000 7 +#if 0 +#define LASAT_BMID_SAFEPIPE30 7 +#define LASAT_BMID_SAFEPIPE5100 8 +#define LASAT_BMID_SAFEPIPE7100 9 +#endif +#define LASAT_BMID_UNKNOWN 0xf +#define LASAT_MAX_BMID_NAMES 9 /* no larger than 15! */ + +#define LASAT_HAS_EDHAC (1 << 0) +#define LASAT_EDHAC_FAST (1 << 1) +#define LASAT_HAS_EADI (1 << 2) +#define LASAT_HAS_HIFN (1 << 3) +#define LASAT_HAS_ISDN (1 << 4) +#define LASAT_HAS_LEASEDLINE_IF (1 << 5) +#define LASAT_HAS_HDC (1 << 6) + +#define LASAT_PRID_MASQUERADE2 0 +#define LASAT_PRID_MASQUERADEPRO 1 +#define LASAT_PRID_SAFEPIPE25 2 +#define LASAT_PRID_SAFEPIPE50 3 +#define LASAT_PRID_SAFEPIPE100 4 +#define LASAT_PRID_SAFEPIPE5000 5 +#define LASAT_PRID_SAFEPIPE7000 6 +#define LASAT_PRID_SAFEPIPE30 7 +#define LASAT_PRID_SAFEPIPE5100 8 +#define LASAT_PRID_SAFEPIPE7100 9 + +#define LASAT_PRID_SAFEPIPE1110 10 +#define LASAT_PRID_SAFEPIPE3020 11 +#define LASAT_PRID_SAFEPIPE3030 12 +#define LASAT_PRID_SAFEPIPE5020 13 +#define LASAT_PRID_SAFEPIPE5030 14 +#define LASAT_PRID_SAFEPIPE1120 15 +#define LASAT_PRID_SAFEPIPE1130 16 +#define LASAT_PRID_SAFEPIPE6010 17 +#define LASAT_PRID_SAFEPIPE6110 18 +#define LASAT_PRID_SAFEPIPE6210 19 +#define LASAT_PRID_SAFEPIPE1020 20 +#define LASAT_PRID_SAFEPIPE1040 21 +#define LASAT_PRID_SAFEPIPE1060 22 + +struct lasat_info { + unsigned int li_cpu_hz; + unsigned int li_bus_hz; + unsigned int li_bmid; + unsigned int li_memsize; + unsigned int li_flash_size; + unsigned int li_prid; + unsigned char li_bmstr[16]; + unsigned char li_namestr[32]; + unsigned char li_typestr[16]; + /* Info on the Flash layout */ + unsigned int li_flash_base; + unsigned long li_flashpart_base[LASAT_MTD_LAST]; + unsigned long li_flashpart_size[LASAT_MTD_LAST]; + struct lasat_eeprom_struct li_eeprom_info; + unsigned int li_eeprom_upgrade_version; + unsigned int li_debugaccess; +}; + +extern struct lasat_info lasat_board_info; + +static inline unsigned long lasat_flash_partition_start(int partno) +{ + if (partno < 0 || partno >= LASAT_MTD_LAST) + return 0; + + return lasat_board_info.li_flashpart_base[partno]; +} + +static inline unsigned long lasat_flash_partition_size(int partno) +{ + if (partno < 0 || partno >= LASAT_MTD_LAST) + return 0; + + return lasat_board_info.li_flashpart_size[partno]; +} + +/* Called from setup() to initialize the global board_info struct */ +extern int lasat_init_board_info(void); + +/* Write the modified EEPROM info struct */ +extern void lasat_write_eeprom_info(void); + +#define N_MACHTYPES 2 +/* for calibration of delays */ + +/* the lasat_ndelay function is necessary because it is used at an + * early stage of the boot process where ndelay is not calibrated. + * It is used for the bit-banging rtc and eeprom drivers */ + +#include + +/* calculating with the slowest board with 100 MHz clock */ +#define LASAT_100_DIVIDER 20 +/* All 200's run at 250 MHz clock */ +#define LASAT_200_DIVIDER 8 + +extern unsigned int lasat_ndelay_divider; + +static inline void lasat_ndelay(unsigned int ns) +{ + __delay(ns / lasat_ndelay_divider); +} + +#define IS_LASAT_200() (current_cpu_data.cputype == CPU_R5000) + +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ + +#define LASAT_SERVICEMODE_MAGIC_1 0xdeadbeef +#define LASAT_SERVICEMODE_MAGIC_2 0xfedeabba + +/* Lasat 100 boards */ +#define LASAT_GT_BASE (KSEG1ADDR(0x14000000)) + +/* Lasat 200 boards */ +#define Vrc5074_PHYS_BASE 0x1fa00000 +#define Vrc5074_BASE (KSEG1ADDR(Vrc5074_PHYS_BASE)) +#define PCI_WINDOW1 0x1a000000 + +#endif /* _LASAT_H */ diff --git a/arch/mips/include/asm/lasat/lasatint.h b/arch/mips/include/asm/lasat/lasatint.h new file mode 100644 index 00000000000..e0d2458b43d --- /dev/null +++ b/arch/mips/include/asm/lasat/lasatint.h @@ -0,0 +1,14 @@ +#ifndef __ASM_LASAT_LASATINT_H +#define __ASM_LASAT_LASATINT_H + +/* lasat 100 */ +#define LASAT_INT_STATUS_REG_100 (KSEG1ADDR(0x1c880000)) +#define LASAT_INT_MASK_REG_100 (KSEG1ADDR(0x1c890000)) +#define LASATINT_MASK_SHIFT_100 0 + +/* lasat 200 */ +#define LASAT_INT_STATUS_REG_200 (KSEG1ADDR(0x1104003c)) +#define LASAT_INT_MASK_REG_200 (KSEG1ADDR(0x1104003c)) +#define LASATINT_MASK_SHIFT_200 16 + +#endif /* __ASM_LASAT_LASATINT_H */ diff --git a/arch/mips/include/asm/lasat/picvue.h b/arch/mips/include/asm/lasat/picvue.h new file mode 100644 index 00000000000..42a492edc40 --- /dev/null +++ b/arch/mips/include/asm/lasat/picvue.h @@ -0,0 +1,15 @@ +/* Lasat 100 */ +#define PVC_REG_100 KSEG1ADDR(0x1c820000) +#define PVC_DATA_SHIFT_100 0 +#define PVC_DATA_M_100 0xFF +#define PVC_E_100 (1 << 8) +#define PVC_RW_100 (1 << 9) +#define PVC_RS_100 (1 << 10) + +/* Lasat 200 */ +#define PVC_REG_200 KSEG1ADDR(0x11000000) +#define PVC_DATA_SHIFT_200 24 +#define PVC_DATA_M_200 (0xFF << PVC_DATA_SHIFT_200) +#define PVC_E_200 (1 << 16) +#define PVC_RW_200 (1 << 17) +#define PVC_RS_200 (1 << 18) diff --git a/arch/mips/include/asm/lasat/serial.h b/arch/mips/include/asm/lasat/serial.h new file mode 100644 index 00000000000..1c37d70579b --- /dev/null +++ b/arch/mips/include/asm/lasat/serial.h @@ -0,0 +1,13 @@ +#include + +/* Lasat 100 boards serial configuration */ +#define LASAT_BASE_BAUD_100 (7372800 / 16) +#define LASAT_UART_REGS_BASE_100 0x1c8b0000 +#define LASAT_UART_REGS_SHIFT_100 2 +#define LASATINT_UART_100 16 + +/* * LASAT 200 boards serial configuration */ +#define LASAT_BASE_BAUD_200 (100000000 / 16 / 12) +#define LASAT_UART_REGS_BASE_200 (Vrc5074_PHYS_BASE + 0x0300) +#define LASAT_UART_REGS_SHIFT_200 3 +#define LASATINT_UART_200 21 diff --git a/arch/mips/include/asm/linkage.h b/arch/mips/include/asm/linkage.h new file mode 100644 index 00000000000..e9a940d1b0c --- /dev/null +++ b/arch/mips/include/asm/linkage.h @@ -0,0 +1,10 @@ +#ifndef __ASM_LINKAGE_H +#define __ASM_LINKAGE_H + +#ifdef __ASSEMBLY__ +#include +#endif + +#define __weak __attribute__((weak)) + +#endif diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h new file mode 100644 index 00000000000..f96fd59e084 --- /dev/null +++ b/arch/mips/include/asm/local.h @@ -0,0 +1,221 @@ +#ifndef _ARCH_MIPS_LOCAL_H +#define _ARCH_MIPS_LOCAL_H + +#include +#include +#include +#include +#include + +typedef struct +{ + atomic_long_t a; +} local_t; + +#define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } + +#define local_read(l) atomic_long_read(&(l)->a) +#define local_set(l, i) atomic_long_set(&(l)->a, (i)) + +#define local_add(i, l) atomic_long_add((i), (&(l)->a)) +#define local_sub(i, l) atomic_long_sub((i), (&(l)->a)) +#define local_inc(l) atomic_long_inc(&(l)->a) +#define local_dec(l) atomic_long_dec(&(l)->a) + +/* + * Same as above, but return the result value + */ +static __inline__ long local_add_return(long i, local_t * l) +{ + unsigned long result; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1:" __LL "%1, %2 # local_add_return \n" + " addu %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqzl %0, 1b \n" + " addu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) + : "Ir" (i), "m" (l->a.counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1:" __LL "%1, %2 # local_add_return \n" + " addu %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqz %0, 1b \n" + " addu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) + : "Ir" (i), "m" (l->a.counter) + : "memory"); + } else { + unsigned long flags; + + local_irq_save(flags); + result = l->a.counter; + result += i; + l->a.counter = result; + local_irq_restore(flags); + } + + return result; +} + +static __inline__ long local_sub_return(long i, local_t * l) +{ + unsigned long result; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1:" __LL "%1, %2 # local_sub_return \n" + " subu %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqzl %0, 1b \n" + " subu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) + : "Ir" (i), "m" (l->a.counter) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1:" __LL "%1, %2 # local_sub_return \n" + " subu %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqz %0, 1b \n" + " subu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) + : "Ir" (i), "m" (l->a.counter) + : "memory"); + } else { + unsigned long flags; + + local_irq_save(flags); + result = l->a.counter; + result -= i; + l->a.counter = result; + local_irq_restore(flags); + } + + return result; +} + +#define local_cmpxchg(l, o, n) \ + ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) +#define local_xchg(l, n) (xchg_local(&((l)->a.counter), (n))) + +/** + * local_add_unless - add unless the number is a given value + * @l: pointer of type local_t + * @a: the amount to add to l... + * @u: ...unless l is equal to u. + * + * Atomically adds @a to @l, so long as it was not @u. + * Returns non-zero if @l was not @u, and zero otherwise. + */ +#define local_add_unless(l, a, u) \ +({ \ + long c, old; \ + c = local_read(l); \ + while (c != (u) && (old = local_cmpxchg((l), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define local_inc_not_zero(l) local_add_unless((l), 1, 0) + +#define local_dec_return(l) local_sub_return(1, (l)) +#define local_inc_return(l) local_add_return(1, (l)) + +/* + * local_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @l: pointer of type local_t + * + * Atomically subtracts @i from @l and returns + * true if the result is zero, or false for all + * other cases. + */ +#define local_sub_and_test(i, l) (local_sub_return((i), (l)) == 0) + +/* + * local_inc_and_test - increment and test + * @l: pointer of type local_t + * + * Atomically increments @l by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +#define local_inc_and_test(l) (local_inc_return(l) == 0) + +/* + * local_dec_and_test - decrement by 1 and test + * @l: pointer of type local_t + * + * Atomically decrements @l by 1 and + * returns true if the result is 0, or false for all other + * cases. + */ +#define local_dec_and_test(l) (local_sub_return(1, (l)) == 0) + +/* + * local_add_negative - add and test if negative + * @l: pointer of type local_t + * @i: integer value to add + * + * Atomically adds @i to @l and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. + */ +#define local_add_negative(i, l) (local_add_return(i, (l)) < 0) + +/* Use these for per-cpu local_t variables: on some archs they are + * much more efficient than these naive implementations. Note they take + * a variable, not an address. + */ + +#define __local_inc(l) ((l)->a.counter++) +#define __local_dec(l) ((l)->a.counter++) +#define __local_add(i, l) ((l)->a.counter+=(i)) +#define __local_sub(i, l) ((l)->a.counter-=(i)) + +/* Need to disable preemption for the cpu local counters otherwise we could + still access a variable of a previous CPU in a non atomic way. */ +#define cpu_local_wrap_v(l) \ + ({ local_t res__; \ + preempt_disable(); \ + res__ = (l); \ + preempt_enable(); \ + res__; }) +#define cpu_local_wrap(l) \ + ({ preempt_disable(); \ + l; \ + preempt_enable(); }) \ + +#define cpu_local_read(l) cpu_local_wrap_v(local_read(&__get_cpu_var(l))) +#define cpu_local_set(l, i) cpu_local_wrap(local_set(&__get_cpu_var(l), (i))) +#define cpu_local_inc(l) cpu_local_wrap(local_inc(&__get_cpu_var(l))) +#define cpu_local_dec(l) cpu_local_wrap(local_dec(&__get_cpu_var(l))) +#define cpu_local_add(i, l) cpu_local_wrap(local_add((i), &__get_cpu_var(l))) +#define cpu_local_sub(i, l) cpu_local_wrap(local_sub((i), &__get_cpu_var(l))) + +#define __cpu_local_inc(l) cpu_local_inc(l) +#define __cpu_local_dec(l) cpu_local_dec(l) +#define __cpu_local_add(i, l) cpu_local_add((i), (l)) +#define __cpu_local_sub(i, l) cpu_local_sub((i), (l)) + +#endif /* _ARCH_MIPS_LOCAL_H */ diff --git a/arch/mips/include/asm/m48t35.h b/arch/mips/include/asm/m48t35.h new file mode 100644 index 00000000000..f44852e9a96 --- /dev/null +++ b/arch/mips/include/asm/m48t35.h @@ -0,0 +1,27 @@ +/* + * Registers for the SGS-Thomson M48T35 Timekeeper RAM chip + */ +#ifndef _ASM_M48T35_H +#define _ASM_M48T35_H + +#include + +extern spinlock_t rtc_lock; + +struct m48t35_rtc { + volatile u8 pad[0x7ff8]; /* starts at 0x7ff8 */ + volatile u8 control; + volatile u8 sec; + volatile u8 min; + volatile u8 hour; + volatile u8 day; + volatile u8 date; + volatile u8 month; + volatile u8 year; +}; + +#define M48T35_RTC_SET 0x80 +#define M48T35_RTC_STOPPED 0x80 +#define M48T35_RTC_READ 0x40 + +#endif /* _ASM_M48T35_H */ diff --git a/arch/mips/include/asm/m48t37.h b/arch/mips/include/asm/m48t37.h new file mode 100644 index 00000000000..cabf86264f3 --- /dev/null +++ b/arch/mips/include/asm/m48t37.h @@ -0,0 +1,35 @@ +/* + * Registers for the SGS-Thomson M48T37 Timekeeper RAM chip + */ +#ifndef _ASM_M48T37_H +#define _ASM_M48T37_H + +#include + +extern spinlock_t rtc_lock; + +struct m48t37_rtc { + volatile u8 pad[0x7ff0]; /* NVRAM */ + volatile u8 flags; + volatile u8 century; + volatile u8 alarm_sec; + volatile u8 alarm_min; + volatile u8 alarm_hour; + volatile u8 alarm_data; + volatile u8 interrupts; + volatile u8 watchdog; + volatile u8 control; + volatile u8 sec; + volatile u8 min; + volatile u8 hour; + volatile u8 day; + volatile u8 date; + volatile u8 month; + volatile u8 year; +}; + +#define M48T37_RTC_SET 0x80 +#define M48T37_RTC_STOPPED 0x80 +#define M48T37_RTC_READ 0x40 + +#endif /* _ASM_M48T37_H */ diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h new file mode 100644 index 00000000000..0d302bad449 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1000.h @@ -0,0 +1,1772 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Include file for Alchemy Semiconductor's Au1k CPU. + * + * Copyright 2000-2001, 2006-2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /* + * some definitions add by takuzo@sm.sony.co.jp and sato@sm.sony.co.jp + */ + +#ifndef _AU1000_H_ +#define _AU1000_H_ + + +#ifndef _LANGUAGE_ASSEMBLY + +#include +#include + +#include +#include + +/* cpu pipeline flush */ +void static inline au_sync(void) +{ + __asm__ volatile ("sync"); +} + +void static inline au_sync_udelay(int us) +{ + __asm__ volatile ("sync"); + udelay(us); +} + +void static inline au_sync_delay(int ms) +{ + __asm__ volatile ("sync"); + mdelay(ms); +} + +void static inline au_writeb(u8 val, unsigned long reg) +{ + *(volatile u8 *)reg = val; +} + +void static inline au_writew(u16 val, unsigned long reg) +{ + *(volatile u16 *)reg = val; +} + +void static inline au_writel(u32 val, unsigned long reg) +{ + *(volatile u32 *)reg = val; +} + +static inline u8 au_readb(unsigned long reg) +{ + return *(volatile u8 *)reg; +} + +static inline u16 au_readw(unsigned long reg) +{ + return *(volatile u16 *)reg; +} + +static inline u32 au_readl(unsigned long reg) +{ + return *(volatile u32 *)reg; +} + + +/* arch/mips/au1000/common/clocks.c */ +extern void set_au1x00_speed(unsigned int new_freq); +extern unsigned int get_au1x00_speed(void); +extern void set_au1x00_uart_baud_base(unsigned long new_baud_base); +extern unsigned long get_au1x00_uart_baud_base(void); +extern void set_au1x00_lcd_clock(void); +extern unsigned int get_au1x00_lcd_clock(void); + +/* + * Every board describes its IRQ mapping with this table. + */ +struct au1xxx_irqmap { + int im_irq; + int im_type; + int im_request; +}; + +/* + * init_IRQ looks for a table with this name. + */ +extern struct au1xxx_irqmap au1xxx_irq_map[]; + +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ + +/* + * SDRAM register offsets + */ +#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \ + defined(CONFIG_SOC_AU1100) +#define MEM_SDMODE0 0x0000 +#define MEM_SDMODE1 0x0004 +#define MEM_SDMODE2 0x0008 +#define MEM_SDADDR0 0x000C +#define MEM_SDADDR1 0x0010 +#define MEM_SDADDR2 0x0014 +#define MEM_SDREFCFG 0x0018 +#define MEM_SDPRECMD 0x001C +#define MEM_SDAUTOREF 0x0020 +#define MEM_SDWRMD0 0x0024 +#define MEM_SDWRMD1 0x0028 +#define MEM_SDWRMD2 0x002C +#define MEM_SDSLEEP 0x0030 +#define MEM_SDSMCKE 0x0034 + +/* + * MEM_SDMODE register content definitions + */ +#define MEM_SDMODE_F (1 << 22) +#define MEM_SDMODE_SR (1 << 21) +#define MEM_SDMODE_BS (1 << 20) +#define MEM_SDMODE_RS (3 << 18) +#define MEM_SDMODE_CS (7 << 15) +#define MEM_SDMODE_TRAS (15 << 11) +#define MEM_SDMODE_TMRD (3 << 9) +#define MEM_SDMODE_TWR (3 << 7) +#define MEM_SDMODE_TRP (3 << 5) +#define MEM_SDMODE_TRCD (3 << 3) +#define MEM_SDMODE_TCL (7 << 0) + +#define MEM_SDMODE_BS_2Bank (0 << 20) +#define MEM_SDMODE_BS_4Bank (1 << 20) +#define MEM_SDMODE_RS_11Row (0 << 18) +#define MEM_SDMODE_RS_12Row (1 << 18) +#define MEM_SDMODE_RS_13Row (2 << 18) +#define MEM_SDMODE_RS_N(N) ((N) << 18) +#define MEM_SDMODE_CS_7Col (0 << 15) +#define MEM_SDMODE_CS_8Col (1 << 15) +#define MEM_SDMODE_CS_9Col (2 << 15) +#define MEM_SDMODE_CS_10Col (3 << 15) +#define MEM_SDMODE_CS_11Col (4 << 15) +#define MEM_SDMODE_CS_N(N) ((N) << 15) +#define MEM_SDMODE_TRAS_N(N) ((N) << 11) +#define MEM_SDMODE_TMRD_N(N) ((N) << 9) +#define MEM_SDMODE_TWR_N(N) ((N) << 7) +#define MEM_SDMODE_TRP_N(N) ((N) << 5) +#define MEM_SDMODE_TRCD_N(N) ((N) << 3) +#define MEM_SDMODE_TCL_N(N) ((N) << 0) + +/* + * MEM_SDADDR register contents definitions + */ +#define MEM_SDADDR_E (1 << 20) +#define MEM_SDADDR_CSBA (0x03FF << 10) +#define MEM_SDADDR_CSMASK (0x03FF << 0) +#define MEM_SDADDR_CSBA_N(N) ((N) & (0x03FF << 22) >> 12) +#define MEM_SDADDR_CSMASK_N(N) ((N)&(0x03FF << 22) >> 22) + +/* + * MEM_SDREFCFG register content definitions + */ +#define MEM_SDREFCFG_TRC (15 << 28) +#define MEM_SDREFCFG_TRPM (3 << 26) +#define MEM_SDREFCFG_E (1 << 25) +#define MEM_SDREFCFG_RE (0x1ffffff << 0) +#define MEM_SDREFCFG_TRC_N(N) ((N) << MEM_SDREFCFG_TRC) +#define MEM_SDREFCFG_TRPM_N(N) ((N) << MEM_SDREFCFG_TRPM) +#define MEM_SDREFCFG_REF_N(N) (N) +#endif + +/***********************************************************************/ + +/* + * Au1550 SDRAM Register Offsets + */ + +/***********************************************************************/ + +#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) +#define MEM_SDMODE0 0x0800 +#define MEM_SDMODE1 0x0808 +#define MEM_SDMODE2 0x0810 +#define MEM_SDADDR0 0x0820 +#define MEM_SDADDR1 0x0828 +#define MEM_SDADDR2 0x0830 +#define MEM_SDCONFIGA 0x0840 +#define MEM_SDCONFIGB 0x0848 +#define MEM_SDSTAT 0x0850 +#define MEM_SDERRADDR 0x0858 +#define MEM_SDSTRIDE0 0x0860 +#define MEM_SDSTRIDE1 0x0868 +#define MEM_SDSTRIDE2 0x0870 +#define MEM_SDWRMD0 0x0880 +#define MEM_SDWRMD1 0x0888 +#define MEM_SDWRMD2 0x0890 +#define MEM_SDPRECMD 0x08C0 +#define MEM_SDAUTOREF 0x08C8 +#define MEM_SDSREF 0x08D0 +#define MEM_SDSLEEP MEM_SDSREF + +#endif + +/* + * Physical base addresses for integrated peripherals + */ + +#ifdef CONFIG_SOC_AU1000 +#define MEM_PHYS_ADDR 0x14000000 +#define STATIC_MEM_PHYS_ADDR 0x14001000 +#define DMA0_PHYS_ADDR 0x14002000 +#define DMA1_PHYS_ADDR 0x14002100 +#define DMA2_PHYS_ADDR 0x14002200 +#define DMA3_PHYS_ADDR 0x14002300 +#define DMA4_PHYS_ADDR 0x14002400 +#define DMA5_PHYS_ADDR 0x14002500 +#define DMA6_PHYS_ADDR 0x14002600 +#define DMA7_PHYS_ADDR 0x14002700 +#define IC0_PHYS_ADDR 0x10400000 +#define IC1_PHYS_ADDR 0x11800000 +#define AC97_PHYS_ADDR 0x10000000 +#define USBH_PHYS_ADDR 0x10100000 +#define USBD_PHYS_ADDR 0x10200000 +#define IRDA_PHYS_ADDR 0x10300000 +#define MAC0_PHYS_ADDR 0x10500000 +#define MAC1_PHYS_ADDR 0x10510000 +#define MACEN_PHYS_ADDR 0x10520000 +#define MACDMA0_PHYS_ADDR 0x14004000 +#define MACDMA1_PHYS_ADDR 0x14004200 +#define I2S_PHYS_ADDR 0x11000000 +#define UART0_PHYS_ADDR 0x11100000 +#define UART1_PHYS_ADDR 0x11200000 +#define UART2_PHYS_ADDR 0x11300000 +#define UART3_PHYS_ADDR 0x11400000 +#define SSI0_PHYS_ADDR 0x11600000 +#define SSI1_PHYS_ADDR 0x11680000 +#define SYS_PHYS_ADDR 0x11900000 +#define PCMCIA_IO_PHYS_ADDR 0xF00000000ULL +#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL +#define PCMCIA_MEM_PHYS_ADDR 0xF80000000ULL +#endif + +/********************************************************************/ + +#ifdef CONFIG_SOC_AU1500 +#define MEM_PHYS_ADDR 0x14000000 +#define STATIC_MEM_PHYS_ADDR 0x14001000 +#define DMA0_PHYS_ADDR 0x14002000 +#define DMA1_PHYS_ADDR 0x14002100 +#define DMA2_PHYS_ADDR 0x14002200 +#define DMA3_PHYS_ADDR 0x14002300 +#define DMA4_PHYS_ADDR 0x14002400 +#define DMA5_PHYS_ADDR 0x14002500 +#define DMA6_PHYS_ADDR 0x14002600 +#define DMA7_PHYS_ADDR 0x14002700 +#define IC0_PHYS_ADDR 0x10400000 +#define IC1_PHYS_ADDR 0x11800000 +#define AC97_PHYS_ADDR 0x10000000 +#define USBH_PHYS_ADDR 0x10100000 +#define USBD_PHYS_ADDR 0x10200000 +#define PCI_PHYS_ADDR 0x14005000 +#define MAC0_PHYS_ADDR 0x11500000 +#define MAC1_PHYS_ADDR 0x11510000 +#define MACEN_PHYS_ADDR 0x11520000 +#define MACDMA0_PHYS_ADDR 0x14004000 +#define MACDMA1_PHYS_ADDR 0x14004200 +#define I2S_PHYS_ADDR 0x11000000 +#define UART0_PHYS_ADDR 0x11100000 +#define UART3_PHYS_ADDR 0x11400000 +#define GPIO2_PHYS_ADDR 0x11700000 +#define SYS_PHYS_ADDR 0x11900000 +#define PCI_MEM_PHYS_ADDR 0x400000000ULL +#define PCI_IO_PHYS_ADDR 0x500000000ULL +#define PCI_CONFIG0_PHYS_ADDR 0x600000000ULL +#define PCI_CONFIG1_PHYS_ADDR 0x680000000ULL +#define PCMCIA_IO_PHYS_ADDR 0xF00000000ULL +#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL +#define PCMCIA_MEM_PHYS_ADDR 0xF80000000ULL +#endif + +/********************************************************************/ + +#ifdef CONFIG_SOC_AU1100 +#define MEM_PHYS_ADDR 0x14000000 +#define STATIC_MEM_PHYS_ADDR 0x14001000 +#define DMA0_PHYS_ADDR 0x14002000 +#define DMA1_PHYS_ADDR 0x14002100 +#define DMA2_PHYS_ADDR 0x14002200 +#define DMA3_PHYS_ADDR 0x14002300 +#define DMA4_PHYS_ADDR 0x14002400 +#define DMA5_PHYS_ADDR 0x14002500 +#define DMA6_PHYS_ADDR 0x14002600 +#define DMA7_PHYS_ADDR 0x14002700 +#define IC0_PHYS_ADDR 0x10400000 +#define SD0_PHYS_ADDR 0x10600000 +#define SD1_PHYS_ADDR 0x10680000 +#define IC1_PHYS_ADDR 0x11800000 +#define AC97_PHYS_ADDR 0x10000000 +#define USBH_PHYS_ADDR 0x10100000 +#define USBD_PHYS_ADDR 0x10200000 +#define IRDA_PHYS_ADDR 0x10300000 +#define MAC0_PHYS_ADDR 0x10500000 +#define MACEN_PHYS_ADDR 0x10520000 +#define MACDMA0_PHYS_ADDR 0x14004000 +#define MACDMA1_PHYS_ADDR 0x14004200 +#define I2S_PHYS_ADDR 0x11000000 +#define UART0_PHYS_ADDR 0x11100000 +#define UART1_PHYS_ADDR 0x11200000 +#define UART3_PHYS_ADDR 0x11400000 +#define SSI0_PHYS_ADDR 0x11600000 +#define SSI1_PHYS_ADDR 0x11680000 +#define GPIO2_PHYS_ADDR 0x11700000 +#define SYS_PHYS_ADDR 0x11900000 +#define LCD_PHYS_ADDR 0x15000000 +#define PCMCIA_IO_PHYS_ADDR 0xF00000000ULL +#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL +#define PCMCIA_MEM_PHYS_ADDR 0xF80000000ULL +#endif + +/***********************************************************************/ + +#ifdef CONFIG_SOC_AU1550 +#define MEM_PHYS_ADDR 0x14000000 +#define STATIC_MEM_PHYS_ADDR 0x14001000 +#define IC0_PHYS_ADDR 0x10400000 +#define IC1_PHYS_ADDR 0x11800000 +#define USBH_PHYS_ADDR 0x14020000 +#define USBD_PHYS_ADDR 0x10200000 +#define PCI_PHYS_ADDR 0x14005000 +#define MAC0_PHYS_ADDR 0x10500000 +#define MAC1_PHYS_ADDR 0x10510000 +#define MACEN_PHYS_ADDR 0x10520000 +#define MACDMA0_PHYS_ADDR 0x14004000 +#define MACDMA1_PHYS_ADDR 0x14004200 +#define UART0_PHYS_ADDR 0x11100000 +#define UART1_PHYS_ADDR 0x11200000 +#define UART3_PHYS_ADDR 0x11400000 +#define GPIO2_PHYS_ADDR 0x11700000 +#define SYS_PHYS_ADDR 0x11900000 +#define DDMA_PHYS_ADDR 0x14002000 +#define PE_PHYS_ADDR 0x14008000 +#define PSC0_PHYS_ADDR 0x11A00000 +#define PSC1_PHYS_ADDR 0x11B00000 +#define PSC2_PHYS_ADDR 0x10A00000 +#define PSC3_PHYS_ADDR 0x10B00000 +#define PCI_MEM_PHYS_ADDR 0x400000000ULL +#define PCI_IO_PHYS_ADDR 0x500000000ULL +#define PCI_CONFIG0_PHYS_ADDR 0x600000000ULL +#define PCI_CONFIG1_PHYS_ADDR 0x680000000ULL +#define PCMCIA_IO_PHYS_ADDR 0xF00000000ULL +#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL +#define PCMCIA_MEM_PHYS_ADDR 0xF80000000ULL +#endif + +/***********************************************************************/ + +#ifdef CONFIG_SOC_AU1200 +#define MEM_PHYS_ADDR 0x14000000 +#define STATIC_MEM_PHYS_ADDR 0x14001000 +#define AES_PHYS_ADDR 0x10300000 +#define CIM_PHYS_ADDR 0x14004000 +#define IC0_PHYS_ADDR 0x10400000 +#define IC1_PHYS_ADDR 0x11800000 +#define USBM_PHYS_ADDR 0x14020000 +#define USBH_PHYS_ADDR 0x14020100 +#define UART0_PHYS_ADDR 0x11100000 +#define UART1_PHYS_ADDR 0x11200000 +#define GPIO2_PHYS_ADDR 0x11700000 +#define SYS_PHYS_ADDR 0x11900000 +#define DDMA_PHYS_ADDR 0x14002000 +#define PSC0_PHYS_ADDR 0x11A00000 +#define PSC1_PHYS_ADDR 0x11B00000 +#define SD0_PHYS_ADDR 0x10600000 +#define SD1_PHYS_ADDR 0x10680000 +#define LCD_PHYS_ADDR 0x15000000 +#define SWCNT_PHYS_ADDR 0x1110010C +#define MAEFE_PHYS_ADDR 0x14012000 +#define MAEBE_PHYS_ADDR 0x14010000 +#define PCMCIA_IO_PHYS_ADDR 0xF00000000ULL +#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL +#define PCMCIA_MEM_PHYS_ADDR 0xF80000000ULL +#endif + +/* Static Bus Controller */ +#define MEM_STCFG0 0xB4001000 +#define MEM_STTIME0 0xB4001004 +#define MEM_STADDR0 0xB4001008 + +#define MEM_STCFG1 0xB4001010 +#define MEM_STTIME1 0xB4001014 +#define MEM_STADDR1 0xB4001018 + +#define MEM_STCFG2 0xB4001020 +#define MEM_STTIME2 0xB4001024 +#define MEM_STADDR2 0xB4001028 + +#define MEM_STCFG3 0xB4001030 +#define MEM_STTIME3 0xB4001034 +#define MEM_STADDR3 0xB4001038 + +#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) +#define MEM_STNDCTL 0xB4001100 +#define MEM_STSTAT 0xB4001104 + +#define MEM_STNAND_CMD 0x0 +#define MEM_STNAND_ADDR 0x4 +#define MEM_STNAND_DATA 0x20 +#endif + +/* Interrupt Controller 0 */ +#define IC0_CFG0RD 0xB0400040 +#define IC0_CFG0SET 0xB0400040 +#define IC0_CFG0CLR 0xB0400044 + +#define IC0_CFG1RD 0xB0400048 +#define IC0_CFG1SET 0xB0400048 +#define IC0_CFG1CLR 0xB040004C + +#define IC0_CFG2RD 0xB0400050 +#define IC0_CFG2SET 0xB0400050 +#define IC0_CFG2CLR 0xB0400054 + +#define IC0_REQ0INT 0xB0400054 +#define IC0_SRCRD 0xB0400058 +#define IC0_SRCSET 0xB0400058 +#define IC0_SRCCLR 0xB040005C +#define IC0_REQ1INT 0xB040005C + +#define IC0_ASSIGNRD 0xB0400060 +#define IC0_ASSIGNSET 0xB0400060 +#define IC0_ASSIGNCLR 0xB0400064 + +#define IC0_WAKERD 0xB0400068 +#define IC0_WAKESET 0xB0400068 +#define IC0_WAKECLR 0xB040006C + +#define IC0_MASKRD 0xB0400070 +#define IC0_MASKSET 0xB0400070 +#define IC0_MASKCLR 0xB0400074 + +#define IC0_RISINGRD 0xB0400078 +#define IC0_RISINGCLR 0xB0400078 +#define IC0_FALLINGRD 0xB040007C +#define IC0_FALLINGCLR 0xB040007C + +#define IC0_TESTBIT 0xB0400080 + +/* Interrupt Controller 1 */ +#define IC1_CFG0RD 0xB1800040 +#define IC1_CFG0SET 0xB1800040 +#define IC1_CFG0CLR 0xB1800044 + +#define IC1_CFG1RD 0xB1800048 +#define IC1_CFG1SET 0xB1800048 +#define IC1_CFG1CLR 0xB180004C + +#define IC1_CFG2RD 0xB1800050 +#define IC1_CFG2SET 0xB1800050 +#define IC1_CFG2CLR 0xB1800054 + +#define IC1_REQ0INT 0xB1800054 +#define IC1_SRCRD 0xB1800058 +#define IC1_SRCSET 0xB1800058 +#define IC1_SRCCLR 0xB180005C +#define IC1_REQ1INT 0xB180005C + +#define IC1_ASSIGNRD 0xB1800060 +#define IC1_ASSIGNSET 0xB1800060 +#define IC1_ASSIGNCLR 0xB1800064 + +#define IC1_WAKERD 0xB1800068 +#define IC1_WAKESET 0xB1800068 +#define IC1_WAKECLR 0xB180006C + +#define IC1_MASKRD 0xB1800070 +#define IC1_MASKSET 0xB1800070 +#define IC1_MASKCLR 0xB1800074 + +#define IC1_RISINGRD 0xB1800078 +#define IC1_RISINGCLR 0xB1800078 +#define IC1_FALLINGRD 0xB180007C +#define IC1_FALLINGCLR 0xB180007C + +#define IC1_TESTBIT 0xB1800080 + +/* Interrupt Configuration Modes */ +#define INTC_INT_DISABLED 0x0 +#define INTC_INT_RISE_EDGE 0x1 +#define INTC_INT_FALL_EDGE 0x2 +#define INTC_INT_RISE_AND_FALL_EDGE 0x3 +#define INTC_INT_HIGH_LEVEL 0x5 +#define INTC_INT_LOW_LEVEL 0x6 +#define INTC_INT_HIGH_AND_LOW_LEVEL 0x7 + +/* Interrupt Numbers */ +/* Au1000 */ +#ifdef CONFIG_SOC_AU1000 +enum soc_au1000_ints { + AU1000_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1000_UART0_INT = AU1000_FIRST_INT, + AU1000_UART1_INT, /* au1000 */ + AU1000_UART2_INT, /* au1000 */ + AU1000_UART3_INT, + AU1000_SSI0_INT, /* au1000 */ + AU1000_SSI1_INT, /* au1000 */ + AU1000_DMA_INT_BASE, + + AU1000_TOY_INT = AU1000_FIRST_INT + 14, + AU1000_TOY_MATCH0_INT, + AU1000_TOY_MATCH1_INT, + AU1000_TOY_MATCH2_INT, + AU1000_RTC_INT, + AU1000_RTC_MATCH0_INT, + AU1000_RTC_MATCH1_INT, + AU1000_RTC_MATCH2_INT, + AU1000_IRDA_TX_INT, /* au1000 */ + AU1000_IRDA_RX_INT, /* au1000 */ + AU1000_USB_DEV_REQ_INT, + AU1000_USB_DEV_SUS_INT, + AU1000_USB_HOST_INT, + AU1000_ACSYNC_INT, + AU1000_MAC0_DMA_INT, + AU1000_MAC1_DMA_INT, + AU1000_I2S_UO_INT, /* au1000 */ + AU1000_AC97C_INT, + AU1000_GPIO_0, + AU1000_GPIO_1, + AU1000_GPIO_2, + AU1000_GPIO_3, + AU1000_GPIO_4, + AU1000_GPIO_5, + AU1000_GPIO_6, + AU1000_GPIO_7, + AU1000_GPIO_8, + AU1000_GPIO_9, + AU1000_GPIO_10, + AU1000_GPIO_11, + AU1000_GPIO_12, + AU1000_GPIO_13, + AU1000_GPIO_14, + AU1000_GPIO_15, + AU1000_GPIO_16, + AU1000_GPIO_17, + AU1000_GPIO_18, + AU1000_GPIO_19, + AU1000_GPIO_20, + AU1000_GPIO_21, + AU1000_GPIO_22, + AU1000_GPIO_23, + AU1000_GPIO_24, + AU1000_GPIO_25, + AU1000_GPIO_26, + AU1000_GPIO_27, + AU1000_GPIO_28, + AU1000_GPIO_29, + AU1000_GPIO_30, + AU1000_GPIO_31, +}; + +#define UART0_ADDR 0xB1100000 +#define UART1_ADDR 0xB1200000 +#define UART2_ADDR 0xB1300000 +#define UART3_ADDR 0xB1400000 + +#define USB_OHCI_BASE 0x10100000 /* phys addr for ioremap */ +#define USB_HOST_CONFIG 0xB017FFFC + +#define AU1000_ETH0_BASE 0xB0500000 +#define AU1000_ETH1_BASE 0xB0510000 +#define AU1000_MAC0_ENABLE 0xB0520000 +#define AU1000_MAC1_ENABLE 0xB0520004 +#define NUM_ETH_INTERFACES 2 +#endif /* CONFIG_SOC_AU1000 */ + +/* Au1500 */ +#ifdef CONFIG_SOC_AU1500 +enum soc_au1500_ints { + AU1500_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1500_UART0_INT = AU1500_FIRST_INT, + AU1000_PCI_INTA, /* au1500 */ + AU1000_PCI_INTB, /* au1500 */ + AU1500_UART3_INT, + AU1000_PCI_INTC, /* au1500 */ + AU1000_PCI_INTD, /* au1500 */ + AU1000_DMA_INT_BASE, + + AU1000_TOY_INT = AU1500_FIRST_INT + 14, + AU1000_TOY_MATCH0_INT, + AU1000_TOY_MATCH1_INT, + AU1000_TOY_MATCH2_INT, + AU1000_RTC_INT, + AU1000_RTC_MATCH0_INT, + AU1000_RTC_MATCH1_INT, + AU1000_RTC_MATCH2_INT, + AU1500_PCI_ERR_INT, + AU1500_RESERVED_INT, + AU1000_USB_DEV_REQ_INT, + AU1000_USB_DEV_SUS_INT, + AU1000_USB_HOST_INT, + AU1000_ACSYNC_INT, + AU1500_MAC0_DMA_INT, + AU1500_MAC1_DMA_INT, + AU1000_AC97C_INT = AU1500_FIRST_INT + 31, + AU1000_GPIO_0, + AU1000_GPIO_1, + AU1000_GPIO_2, + AU1000_GPIO_3, + AU1000_GPIO_4, + AU1000_GPIO_5, + AU1000_GPIO_6, + AU1000_GPIO_7, + AU1000_GPIO_8, + AU1000_GPIO_9, + AU1000_GPIO_10, + AU1000_GPIO_11, + AU1000_GPIO_12, + AU1000_GPIO_13, + AU1000_GPIO_14, + AU1000_GPIO_15, + AU1500_GPIO_200, + AU1500_GPIO_201, + AU1500_GPIO_202, + AU1500_GPIO_203, + AU1500_GPIO_20, + AU1500_GPIO_204, + AU1500_GPIO_205, + AU1500_GPIO_23, + AU1500_GPIO_24, + AU1500_GPIO_25, + AU1500_GPIO_26, + AU1500_GPIO_27, + AU1500_GPIO_28, + AU1500_GPIO_206, + AU1500_GPIO_207, + AU1500_GPIO_208_215, +}; + +/* shortcuts */ +#define INTA AU1000_PCI_INTA +#define INTB AU1000_PCI_INTB +#define INTC AU1000_PCI_INTC +#define INTD AU1000_PCI_INTD + +#define UART0_ADDR 0xB1100000 +#define UART3_ADDR 0xB1400000 + +#define USB_OHCI_BASE 0x10100000 /* phys addr for ioremap */ +#define USB_HOST_CONFIG 0xB017fffc + +#define AU1500_ETH0_BASE 0xB1500000 +#define AU1500_ETH1_BASE 0xB1510000 +#define AU1500_MAC0_ENABLE 0xB1520000 +#define AU1500_MAC1_ENABLE 0xB1520004 +#define NUM_ETH_INTERFACES 2 +#endif /* CONFIG_SOC_AU1500 */ + +/* Au1100 */ +#ifdef CONFIG_SOC_AU1100 +enum soc_au1100_ints { + AU1100_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1100_UART0_INT, + AU1100_UART1_INT, + AU1100_SD_INT, + AU1100_UART3_INT, + AU1000_SSI0_INT, + AU1000_SSI1_INT, + AU1000_DMA_INT_BASE, + + AU1000_TOY_INT = AU1100_FIRST_INT + 14, + AU1000_TOY_MATCH0_INT, + AU1000_TOY_MATCH1_INT, + AU1000_TOY_MATCH2_INT, + AU1000_RTC_INT, + AU1000_RTC_MATCH0_INT, + AU1000_RTC_MATCH1_INT, + AU1000_RTC_MATCH2_INT, + AU1000_IRDA_TX_INT, + AU1000_IRDA_RX_INT, + AU1000_USB_DEV_REQ_INT, + AU1000_USB_DEV_SUS_INT, + AU1000_USB_HOST_INT, + AU1000_ACSYNC_INT, + AU1100_MAC0_DMA_INT, + AU1100_GPIO_208_215, + AU1100_LCD_INT, + AU1000_AC97C_INT, + AU1000_GPIO_0, + AU1000_GPIO_1, + AU1000_GPIO_2, + AU1000_GPIO_3, + AU1000_GPIO_4, + AU1000_GPIO_5, + AU1000_GPIO_6, + AU1000_GPIO_7, + AU1000_GPIO_8, + AU1000_GPIO_9, + AU1000_GPIO_10, + AU1000_GPIO_11, + AU1000_GPIO_12, + AU1000_GPIO_13, + AU1000_GPIO_14, + AU1000_GPIO_15, + AU1000_GPIO_16, + AU1000_GPIO_17, + AU1000_GPIO_18, + AU1000_GPIO_19, + AU1000_GPIO_20, + AU1000_GPIO_21, + AU1000_GPIO_22, + AU1000_GPIO_23, + AU1000_GPIO_24, + AU1000_GPIO_25, + AU1000_GPIO_26, + AU1000_GPIO_27, + AU1000_GPIO_28, + AU1000_GPIO_29, + AU1000_GPIO_30, + AU1000_GPIO_31, +}; + +#define UART0_ADDR 0xB1100000 +#define UART1_ADDR 0xB1200000 +#define UART3_ADDR 0xB1400000 + +#define USB_OHCI_BASE 0x10100000 /* phys addr for ioremap */ +#define USB_HOST_CONFIG 0xB017FFFC + +#define AU1100_ETH0_BASE 0xB0500000 +#define AU1100_MAC0_ENABLE 0xB0520000 +#define NUM_ETH_INTERFACES 1 +#endif /* CONFIG_SOC_AU1100 */ + +#ifdef CONFIG_SOC_AU1550 +enum soc_au1550_ints { + AU1550_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1550_UART0_INT = AU1550_FIRST_INT, + AU1550_PCI_INTA, + AU1550_PCI_INTB, + AU1550_DDMA_INT, + AU1550_CRYPTO_INT, + AU1550_PCI_INTC, + AU1550_PCI_INTD, + AU1550_PCI_RST_INT, + AU1550_UART1_INT, + AU1550_UART3_INT, + AU1550_PSC0_INT, + AU1550_PSC1_INT, + AU1550_PSC2_INT, + AU1550_PSC3_INT, + AU1000_TOY_INT, + AU1000_TOY_MATCH0_INT, + AU1000_TOY_MATCH1_INT, + AU1000_TOY_MATCH2_INT, + AU1000_RTC_INT, + AU1000_RTC_MATCH0_INT, + AU1000_RTC_MATCH1_INT, + AU1000_RTC_MATCH2_INT, + + AU1550_NAND_INT = AU1550_FIRST_INT + 23, + AU1550_USB_DEV_REQ_INT, + AU1000_USB_DEV_REQ_INT = AU1550_USB_DEV_REQ_INT, + AU1550_USB_DEV_SUS_INT, + AU1000_USB_DEV_SUS_INT = AU1550_USB_DEV_SUS_INT, + AU1550_USB_HOST_INT, + AU1000_USB_HOST_INT = AU1550_USB_HOST_INT, + AU1550_MAC0_DMA_INT, + AU1550_MAC1_DMA_INT, + AU1000_GPIO_0 = AU1550_FIRST_INT + 32, + AU1000_GPIO_1, + AU1000_GPIO_2, + AU1000_GPIO_3, + AU1000_GPIO_4, + AU1000_GPIO_5, + AU1000_GPIO_6, + AU1000_GPIO_7, + AU1000_GPIO_8, + AU1000_GPIO_9, + AU1000_GPIO_10, + AU1000_GPIO_11, + AU1000_GPIO_12, + AU1000_GPIO_13, + AU1000_GPIO_14, + AU1000_GPIO_15, + AU1550_GPIO_200, + AU1500_GPIO_201_205, /* Logical or of GPIO201:205 */ + AU1500_GPIO_16, + AU1500_GPIO_17, + AU1500_GPIO_20, + AU1500_GPIO_21, + AU1500_GPIO_22, + AU1500_GPIO_23, + AU1500_GPIO_24, + AU1500_GPIO_25, + AU1500_GPIO_26, + AU1500_GPIO_27, + AU1500_GPIO_28, + AU1500_GPIO_206, + AU1500_GPIO_207, + AU1500_GPIO_208_218, /* Logical or of GPIO208:218 */ +}; + +/* shortcuts */ +#define INTA AU1550_PCI_INTA +#define INTB AU1550_PCI_INTB +#define INTC AU1550_PCI_INTC +#define INTD AU1550_PCI_INTD + +#define UART0_ADDR 0xB1100000 +#define UART1_ADDR 0xB1200000 +#define UART3_ADDR 0xB1400000 + +#define USB_OHCI_BASE 0x14020000 /* phys addr for ioremap */ +#define USB_OHCI_LEN 0x00060000 +#define USB_HOST_CONFIG 0xB4027ffc + +#define AU1550_ETH0_BASE 0xB0500000 +#define AU1550_ETH1_BASE 0xB0510000 +#define AU1550_MAC0_ENABLE 0xB0520000 +#define AU1550_MAC1_ENABLE 0xB0520004 +#define NUM_ETH_INTERFACES 2 +#endif /* CONFIG_SOC_AU1550 */ + +#ifdef CONFIG_SOC_AU1200 +enum soc_au1200_ints { + AU1200_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1200_UART0_INT = AU1200_FIRST_INT, + AU1200_SWT_INT, + AU1200_SD_INT, + AU1200_DDMA_INT, + AU1200_MAE_BE_INT, + AU1200_GPIO_200, + AU1200_GPIO_201, + AU1200_GPIO_202, + AU1200_UART1_INT, + AU1200_MAE_FE_INT, + AU1200_PSC0_INT, + AU1200_PSC1_INT, + AU1200_AES_INT, + AU1200_CAMERA_INT, + AU1000_TOY_INT, + AU1000_TOY_MATCH0_INT, + AU1000_TOY_MATCH1_INT, + AU1000_TOY_MATCH2_INT, + AU1000_RTC_INT, + AU1000_RTC_MATCH0_INT, + AU1000_RTC_MATCH1_INT, + AU1000_RTC_MATCH2_INT, + + AU1200_NAND_INT = AU1200_FIRST_INT + 23, + AU1200_GPIO_204, + AU1200_GPIO_205, + AU1200_GPIO_206, + AU1200_GPIO_207, + AU1200_GPIO_208_215, /* Logical OR of 208:215 */ + AU1200_USB_INT, + AU1000_USB_HOST_INT = AU1200_USB_INT, + AU1200_LCD_INT, + AU1200_MAE_BOTH_INT, + AU1000_GPIO_0, + AU1000_GPIO_1, + AU1000_GPIO_2, + AU1000_GPIO_3, + AU1000_GPIO_4, + AU1000_GPIO_5, + AU1000_GPIO_6, + AU1000_GPIO_7, + AU1000_GPIO_8, + AU1000_GPIO_9, + AU1000_GPIO_10, + AU1000_GPIO_11, + AU1000_GPIO_12, + AU1000_GPIO_13, + AU1000_GPIO_14, + AU1000_GPIO_15, + AU1000_GPIO_16, + AU1000_GPIO_17, + AU1000_GPIO_18, + AU1000_GPIO_19, + AU1000_GPIO_20, + AU1000_GPIO_21, + AU1000_GPIO_22, + AU1000_GPIO_23, + AU1000_GPIO_24, + AU1000_GPIO_25, + AU1000_GPIO_26, + AU1000_GPIO_27, + AU1000_GPIO_28, + AU1000_GPIO_29, + AU1000_GPIO_30, + AU1000_GPIO_31, +}; + +#define UART0_ADDR 0xB1100000 +#define UART1_ADDR 0xB1200000 + +#define USB_UOC_BASE 0x14020020 +#define USB_UOC_LEN 0x20 +#define USB_OHCI_BASE 0x14020100 +#define USB_OHCI_LEN 0x100 +#define USB_EHCI_BASE 0x14020200 +#define USB_EHCI_LEN 0x100 +#define USB_UDC_BASE 0x14022000 +#define USB_UDC_LEN 0x2000 +#define USB_MSR_BASE 0xB4020000 +#define USB_MSR_MCFG 4 +#define USBMSRMCFG_OMEMEN 0 +#define USBMSRMCFG_OBMEN 1 +#define USBMSRMCFG_EMEMEN 2 +#define USBMSRMCFG_EBMEN 3 +#define USBMSRMCFG_DMEMEN 4 +#define USBMSRMCFG_DBMEN 5 +#define USBMSRMCFG_GMEMEN 6 +#define USBMSRMCFG_OHCCLKEN 16 +#define USBMSRMCFG_EHCCLKEN 17 +#define USBMSRMCFG_UDCCLKEN 18 +#define USBMSRMCFG_PHYPLLEN 19 +#define USBMSRMCFG_RDCOMB 30 +#define USBMSRMCFG_PFEN 31 + +#endif /* CONFIG_SOC_AU1200 */ + +#define AU1000_INTC0_INT_BASE (MIPS_CPU_IRQ_BASE + 8) +#define AU1000_INTC0_INT_LAST (AU1000_INTC0_INT_BASE + 31) +#define AU1000_INTC1_INT_BASE (AU1000_INTC0_INT_BASE + 32) +#define AU1000_INTC1_INT_LAST (AU1000_INTC1_INT_BASE + 31) + +#define AU1000_MAX_INTR AU1000_INTC1_INT_LAST +#define INTX 0xFF /* not valid */ + +/* Programmable Counters 0 and 1 */ +#define SYS_BASE 0xB1900000 +#define SYS_COUNTER_CNTRL (SYS_BASE + 0x14) +# define SYS_CNTRL_E1S (1 << 23) +# define SYS_CNTRL_T1S (1 << 20) +# define SYS_CNTRL_M21 (1 << 19) +# define SYS_CNTRL_M11 (1 << 18) +# define SYS_CNTRL_M01 (1 << 17) +# define SYS_CNTRL_C1S (1 << 16) +# define SYS_CNTRL_BP (1 << 14) +# define SYS_CNTRL_EN1 (1 << 13) +# define SYS_CNTRL_BT1 (1 << 12) +# define SYS_CNTRL_EN0 (1 << 11) +# define SYS_CNTRL_BT0 (1 << 10) +# define SYS_CNTRL_E0 (1 << 8) +# define SYS_CNTRL_E0S (1 << 7) +# define SYS_CNTRL_32S (1 << 5) +# define SYS_CNTRL_T0S (1 << 4) +# define SYS_CNTRL_M20 (1 << 3) +# define SYS_CNTRL_M10 (1 << 2) +# define SYS_CNTRL_M00 (1 << 1) +# define SYS_CNTRL_C0S (1 << 0) + +/* Programmable Counter 0 Registers */ +#define SYS_TOYTRIM (SYS_BASE + 0) +#define SYS_TOYWRITE (SYS_BASE + 4) +#define SYS_TOYMATCH0 (SYS_BASE + 8) +#define SYS_TOYMATCH1 (SYS_BASE + 0xC) +#define SYS_TOYMATCH2 (SYS_BASE + 0x10) +#define SYS_TOYREAD (SYS_BASE + 0x40) + +/* Programmable Counter 1 Registers */ +#define SYS_RTCTRIM (SYS_BASE + 0x44) +#define SYS_RTCWRITE (SYS_BASE + 0x48) +#define SYS_RTCMATCH0 (SYS_BASE + 0x4C) +#define SYS_RTCMATCH1 (SYS_BASE + 0x50) +#define SYS_RTCMATCH2 (SYS_BASE + 0x54) +#define SYS_RTCREAD (SYS_BASE + 0x58) + +/* I2S Controller */ +#define I2S_DATA 0xB1000000 +# define I2S_DATA_MASK 0xffffff +#define I2S_CONFIG 0xB1000004 +# define I2S_CONFIG_XU (1 << 25) +# define I2S_CONFIG_XO (1 << 24) +# define I2S_CONFIG_RU (1 << 23) +# define I2S_CONFIG_RO (1 << 22) +# define I2S_CONFIG_TR (1 << 21) +# define I2S_CONFIG_TE (1 << 20) +# define I2S_CONFIG_TF (1 << 19) +# define I2S_CONFIG_RR (1 << 18) +# define I2S_CONFIG_RE (1 << 17) +# define I2S_CONFIG_RF (1 << 16) +# define I2S_CONFIG_PD (1 << 11) +# define I2S_CONFIG_LB (1 << 10) +# define I2S_CONFIG_IC (1 << 9) +# define I2S_CONFIG_FM_BIT 7 +# define I2S_CONFIG_FM_MASK (0x3 << I2S_CONFIG_FM_BIT) +# define I2S_CONFIG_FM_I2S (0x0 << I2S_CONFIG_FM_BIT) +# define I2S_CONFIG_FM_LJ (0x1 << I2S_CONFIG_FM_BIT) +# define I2S_CONFIG_FM_RJ (0x2 << I2S_CONFIG_FM_BIT) +# define I2S_CONFIG_TN (1 << 6) +# define I2S_CONFIG_RN (1 << 5) +# define I2S_CONFIG_SZ_BIT 0 +# define I2S_CONFIG_SZ_MASK (0x1F << I2S_CONFIG_SZ_BIT) + +#define I2S_CONTROL 0xB1000008 +# define I2S_CONTROL_D (1 << 1) +# define I2S_CONTROL_CE (1 << 0) + +/* USB Host Controller */ +#ifndef USB_OHCI_LEN +#define USB_OHCI_LEN 0x00100000 +#endif + +#ifndef CONFIG_SOC_AU1200 + +/* USB Device Controller */ +#define USBD_EP0RD 0xB0200000 +#define USBD_EP0WR 0xB0200004 +#define USBD_EP2WR 0xB0200008 +#define USBD_EP3WR 0xB020000C +#define USBD_EP4RD 0xB0200010 +#define USBD_EP5RD 0xB0200014 +#define USBD_INTEN 0xB0200018 +#define USBD_INTSTAT 0xB020001C +# define USBDEV_INT_SOF (1 << 12) +# define USBDEV_INT_HF_BIT 6 +# define USBDEV_INT_HF_MASK (0x3f << USBDEV_INT_HF_BIT) +# define USBDEV_INT_CMPLT_BIT 0 +# define USBDEV_INT_CMPLT_MASK (0x3f << USBDEV_INT_CMPLT_BIT) +#define USBD_CONFIG 0xB0200020 +#define USBD_EP0CS 0xB0200024 +#define USBD_EP2CS 0xB0200028 +#define USBD_EP3CS 0xB020002C +#define USBD_EP4CS 0xB0200030 +#define USBD_EP5CS 0xB0200034 +# define USBDEV_CS_SU (1 << 14) +# define USBDEV_CS_NAK (1 << 13) +# define USBDEV_CS_ACK (1 << 12) +# define USBDEV_CS_BUSY (1 << 11) +# define USBDEV_CS_TSIZE_BIT 1 +# define USBDEV_CS_TSIZE_MASK (0x3ff << USBDEV_CS_TSIZE_BIT) +# define USBDEV_CS_STALL (1 << 0) +#define USBD_EP0RDSTAT 0xB0200040 +#define USBD_EP0WRSTAT 0xB0200044 +#define USBD_EP2WRSTAT 0xB0200048 +#define USBD_EP3WRSTAT 0xB020004C +#define USBD_EP4RDSTAT 0xB0200050 +#define USBD_EP5RDSTAT 0xB0200054 +# define USBDEV_FSTAT_FLUSH (1 << 6) +# define USBDEV_FSTAT_UF (1 << 5) +# define USBDEV_FSTAT_OF (1 << 4) +# define USBDEV_FSTAT_FCNT_BIT 0 +# define USBDEV_FSTAT_FCNT_MASK (0x0f << USBDEV_FSTAT_FCNT_BIT) +#define USBD_ENABLE 0xB0200058 +# define USBDEV_ENABLE (1 << 1) +# define USBDEV_CE (1 << 0) + +#endif /* !CONFIG_SOC_AU1200 */ + +/* Ethernet Controllers */ + +/* 4 byte offsets from AU1000_ETH_BASE */ +#define MAC_CONTROL 0x0 +# define MAC_RX_ENABLE (1 << 2) +# define MAC_TX_ENABLE (1 << 3) +# define MAC_DEF_CHECK (1 << 5) +# define MAC_SET_BL(X) (((X) & 0x3) << 6) +# define MAC_AUTO_PAD (1 << 8) +# define MAC_DISABLE_RETRY (1 << 10) +# define MAC_DISABLE_BCAST (1 << 11) +# define MAC_LATE_COL (1 << 12) +# define MAC_HASH_MODE (1 << 13) +# define MAC_HASH_ONLY (1 << 15) +# define MAC_PASS_ALL (1 << 16) +# define MAC_INVERSE_FILTER (1 << 17) +# define MAC_PROMISCUOUS (1 << 18) +# define MAC_PASS_ALL_MULTI (1 << 19) +# define MAC_FULL_DUPLEX (1 << 20) +# define MAC_NORMAL_MODE 0 +# define MAC_INT_LOOPBACK (1 << 21) +# define MAC_EXT_LOOPBACK (1 << 22) +# define MAC_DISABLE_RX_OWN (1 << 23) +# define MAC_BIG_ENDIAN (1 << 30) +# define MAC_RX_ALL (1 << 31) +#define MAC_ADDRESS_HIGH 0x4 +#define MAC_ADDRESS_LOW 0x8 +#define MAC_MCAST_HIGH 0xC +#define MAC_MCAST_LOW 0x10 +#define MAC_MII_CNTRL 0x14 +# define MAC_MII_BUSY (1 << 0) +# define MAC_MII_READ 0 +# define MAC_MII_WRITE (1 << 1) +# define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6) +# define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11) +#define MAC_MII_DATA 0x18 +#define MAC_FLOW_CNTRL 0x1C +# define MAC_FLOW_CNTRL_BUSY (1 << 0) +# define MAC_FLOW_CNTRL_ENABLE (1 << 1) +# define MAC_PASS_CONTROL (1 << 2) +# define MAC_SET_PAUSE(X) (((X) & 0xffff) << 16) +#define MAC_VLAN1_TAG 0x20 +#define MAC_VLAN2_TAG 0x24 + +/* Ethernet Controller Enable */ + +# define MAC_EN_CLOCK_ENABLE (1 << 0) +# define MAC_EN_RESET0 (1 << 1) +# define MAC_EN_TOSS (0 << 2) +# define MAC_EN_CACHEABLE (1 << 3) +# define MAC_EN_RESET1 (1 << 4) +# define MAC_EN_RESET2 (1 << 5) +# define MAC_DMA_RESET (1 << 6) + +/* Ethernet Controller DMA Channels */ + +#define MAC0_TX_DMA_ADDR 0xB4004000 +#define MAC1_TX_DMA_ADDR 0xB4004200 +/* offsets from MAC_TX_RING_ADDR address */ +#define MAC_TX_BUFF0_STATUS 0x0 +# define TX_FRAME_ABORTED (1 << 0) +# define TX_JAB_TIMEOUT (1 << 1) +# define TX_NO_CARRIER (1 << 2) +# define TX_LOSS_CARRIER (1 << 3) +# define TX_EXC_DEF (1 << 4) +# define TX_LATE_COLL_ABORT (1 << 5) +# define TX_EXC_COLL (1 << 6) +# define TX_UNDERRUN (1 << 7) +# define TX_DEFERRED (1 << 8) +# define TX_LATE_COLL (1 << 9) +# define TX_COLL_CNT_MASK (0xF << 10) +# define TX_PKT_RETRY (1 << 31) +#define MAC_TX_BUFF0_ADDR 0x4 +# define TX_DMA_ENABLE (1 << 0) +# define TX_T_DONE (1 << 1) +# define TX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3) +#define MAC_TX_BUFF0_LEN 0x8 +#define MAC_TX_BUFF1_STATUS 0x10 +#define MAC_TX_BUFF1_ADDR 0x14 +#define MAC_TX_BUFF1_LEN 0x18 +#define MAC_TX_BUFF2_STATUS 0x20 +#define MAC_TX_BUFF2_ADDR 0x24 +#define MAC_TX_BUFF2_LEN 0x28 +#define MAC_TX_BUFF3_STATUS 0x30 +#define MAC_TX_BUFF3_ADDR 0x34 +#define MAC_TX_BUFF3_LEN 0x38 + +#define MAC0_RX_DMA_ADDR 0xB4004100 +#define MAC1_RX_DMA_ADDR 0xB4004300 +/* offsets from MAC_RX_RING_ADDR */ +#define MAC_RX_BUFF0_STATUS 0x0 +# define RX_FRAME_LEN_MASK 0x3fff +# define RX_WDOG_TIMER (1 << 14) +# define RX_RUNT (1 << 15) +# define RX_OVERLEN (1 << 16) +# define RX_COLL (1 << 17) +# define RX_ETHER (1 << 18) +# define RX_MII_ERROR (1 << 19) +# define RX_DRIBBLING (1 << 20) +# define RX_CRC_ERROR (1 << 21) +# define RX_VLAN1 (1 << 22) +# define RX_VLAN2 (1 << 23) +# define RX_LEN_ERROR (1 << 24) +# define RX_CNTRL_FRAME (1 << 25) +# define RX_U_CNTRL_FRAME (1 << 26) +# define RX_MCAST_FRAME (1 << 27) +# define RX_BCAST_FRAME (1 << 28) +# define RX_FILTER_FAIL (1 << 29) +# define RX_PACKET_FILTER (1 << 30) +# define RX_MISSED_FRAME (1 << 31) + +# define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN | \ + RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \ + RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME) +#define MAC_RX_BUFF0_ADDR 0x4 +# define RX_DMA_ENABLE (1 << 0) +# define RX_T_DONE (1 << 1) +# define RX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3) +# define RX_SET_BUFF_ADDR(X) ((X) & 0xffffffc0) +#define MAC_RX_BUFF1_STATUS 0x10 +#define MAC_RX_BUFF1_ADDR 0x14 +#define MAC_RX_BUFF2_STATUS 0x20 +#define MAC_RX_BUFF2_ADDR 0x24 +#define MAC_RX_BUFF3_STATUS 0x30 +#define MAC_RX_BUFF3_ADDR 0x34 + +/* UARTS 0-3 */ +#define UART_BASE UART0_ADDR +#ifdef CONFIG_SOC_AU1200 +#define UART_DEBUG_BASE UART1_ADDR +#else +#define UART_DEBUG_BASE UART3_ADDR +#endif + +#define UART_RX 0 /* Receive buffer */ +#define UART_TX 4 /* Transmit buffer */ +#define UART_IER 8 /* Interrupt Enable Register */ +#define UART_IIR 0xC /* Interrupt ID Register */ +#define UART_FCR 0x10 /* FIFO Control Register */ +#define UART_LCR 0x14 /* Line Control Register */ +#define UART_MCR 0x18 /* Modem Control Register */ +#define UART_LSR 0x1C /* Line Status Register */ +#define UART_MSR 0x20 /* Modem Status Register */ +#define UART_CLK 0x28 /* Baud Rate Clock Divider */ +#define UART_MOD_CNTRL 0x100 /* Module Control */ + +#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ +#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ +#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ +#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ +#define UART_FCR_TRIGGER_MASK 0xF0 /* Mask for the FIFO trigger range */ +#define UART_FCR_R_TRIGGER_1 0x00 /* Mask for receive trigger set at 1 */ +#define UART_FCR_R_TRIGGER_4 0x40 /* Mask for receive trigger set at 4 */ +#define UART_FCR_R_TRIGGER_8 0x80 /* Mask for receive trigger set at 8 */ +#define UART_FCR_R_TRIGGER_14 0xA0 /* Mask for receive trigger set at 14 */ +#define UART_FCR_T_TRIGGER_0 0x00 /* Mask for transmit trigger set at 0 */ +#define UART_FCR_T_TRIGGER_4 0x10 /* Mask for transmit trigger set at 4 */ +#define UART_FCR_T_TRIGGER_8 0x20 /* Mask for transmit trigger set at 8 */ +#define UART_FCR_T_TRIGGER_12 0x30 /* Mask for transmit trigger set at 12 */ + +/* + * These are the definitions for the Line Control Register + */ +#define UART_LCR_SBC 0x40 /* Set break control */ +#define UART_LCR_SPAR 0x20 /* Stick parity (?) */ +#define UART_LCR_EPAR 0x10 /* Even parity select */ +#define UART_LCR_PARITY 0x08 /* Parity Enable */ +#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */ +#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ +#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ +#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ +#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ + +/* + * These are the definitions for the Line Status Register + */ +#define UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break interrupt indicator */ +#define UART_LSR_FE 0x08 /* Frame error indicator */ +#define UART_LSR_PE 0x04 /* Parity error indicator */ +#define UART_LSR_OE 0x02 /* Overrun error indicator */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ + +/* + * These are the definitions for the Interrupt Identification Register + */ +#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ +#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ +#define UART_IIR_MSI 0x00 /* Modem status interrupt */ +#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ +#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ + +/* + * These are the definitions for the Interrupt Enable Register + */ +#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ +#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ +#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ +#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ + +/* + * These are the definitions for the Modem Control Register + */ +#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ +#define UART_MCR_OUT2 0x08 /* Out2 complement */ +#define UART_MCR_OUT1 0x04 /* Out1 complement */ +#define UART_MCR_RTS 0x02 /* RTS complement */ +#define UART_MCR_DTR 0x01 /* DTR complement */ + +/* + * These are the definitions for the Modem Status Register + */ +#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ +#define UART_MSR_RI 0x40 /* Ring Indicator */ +#define UART_MSR_DSR 0x20 /* Data Set Ready */ +#define UART_MSR_CTS 0x10 /* Clear to Send */ +#define UART_MSR_DDCD 0x08 /* Delta DCD */ +#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ +#define UART_MSR_DDSR 0x02 /* Delta DSR */ +#define UART_MSR_DCTS 0x01 /* Delta CTS */ +#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + +/* SSIO */ +#define SSI0_STATUS 0xB1600000 +# define SSI_STATUS_BF (1 << 4) +# define SSI_STATUS_OF (1 << 3) +# define SSI_STATUS_UF (1 << 2) +# define SSI_STATUS_D (1 << 1) +# define SSI_STATUS_B (1 << 0) +#define SSI0_INT 0xB1600004 +# define SSI_INT_OI (1 << 3) +# define SSI_INT_UI (1 << 2) +# define SSI_INT_DI (1 << 1) +#define SSI0_INT_ENABLE 0xB1600008 +# define SSI_INTE_OIE (1 << 3) +# define SSI_INTE_UIE (1 << 2) +# define SSI_INTE_DIE (1 << 1) +#define SSI0_CONFIG 0xB1600020 +# define SSI_CONFIG_AO (1 << 24) +# define SSI_CONFIG_DO (1 << 23) +# define SSI_CONFIG_ALEN_BIT 20 +# define SSI_CONFIG_ALEN_MASK (0x7 << 20) +# define SSI_CONFIG_DLEN_BIT 16 +# define SSI_CONFIG_DLEN_MASK (0x7 << 16) +# define SSI_CONFIG_DD (1 << 11) +# define SSI_CONFIG_AD (1 << 10) +# define SSI_CONFIG_BM_BIT 8 +# define SSI_CONFIG_BM_MASK (0x3 << 8) +# define SSI_CONFIG_CE (1 << 7) +# define SSI_CONFIG_DP (1 << 6) +# define SSI_CONFIG_DL (1 << 5) +# define SSI_CONFIG_EP (1 << 4) +#define SSI0_ADATA 0xB1600024 +# define SSI_AD_D (1 << 24) +# define SSI_AD_ADDR_BIT 16 +# define SSI_AD_ADDR_MASK (0xff << 16) +# define SSI_AD_DATA_BIT 0 +# define SSI_AD_DATA_MASK (0xfff << 0) +#define SSI0_CLKDIV 0xB1600028 +#define SSI0_CONTROL 0xB1600100 +# define SSI_CONTROL_CD (1 << 1) +# define SSI_CONTROL_E (1 << 0) + +/* SSI1 */ +#define SSI1_STATUS 0xB1680000 +#define SSI1_INT 0xB1680004 +#define SSI1_INT_ENABLE 0xB1680008 +#define SSI1_CONFIG 0xB1680020 +#define SSI1_ADATA 0xB1680024 +#define SSI1_CLKDIV 0xB1680028 +#define SSI1_ENABLE 0xB1680100 + +/* + * Register content definitions + */ +#define SSI_STATUS_BF (1 << 4) +#define SSI_STATUS_OF (1 << 3) +#define SSI_STATUS_UF (1 << 2) +#define SSI_STATUS_D (1 << 1) +#define SSI_STATUS_B (1 << 0) + +/* SSI_INT */ +#define SSI_INT_OI (1 << 3) +#define SSI_INT_UI (1 << 2) +#define SSI_INT_DI (1 << 1) + +/* SSI_INTEN */ +#define SSI_INTEN_OIE (1 << 3) +#define SSI_INTEN_UIE (1 << 2) +#define SSI_INTEN_DIE (1 << 1) + +#define SSI_CONFIG_AO (1 << 24) +#define SSI_CONFIG_DO (1 << 23) +#define SSI_CONFIG_ALEN (7 << 20) +#define SSI_CONFIG_DLEN (15 << 16) +#define SSI_CONFIG_DD (1 << 11) +#define SSI_CONFIG_AD (1 << 10) +#define SSI_CONFIG_BM (3 << 8) +#define SSI_CONFIG_CE (1 << 7) +#define SSI_CONFIG_DP (1 << 6) +#define SSI_CONFIG_DL (1 << 5) +#define SSI_CONFIG_EP (1 << 4) +#define SSI_CONFIG_ALEN_N(N) ((N-1) << 20) +#define SSI_CONFIG_DLEN_N(N) ((N-1) << 16) +#define SSI_CONFIG_BM_HI (0 << 8) +#define SSI_CONFIG_BM_LO (1 << 8) +#define SSI_CONFIG_BM_CY (2 << 8) + +#define SSI_ADATA_D (1 << 24) +#define SSI_ADATA_ADDR (0xFF << 16) +#define SSI_ADATA_DATA 0x0FFF +#define SSI_ADATA_ADDR_N(N) (N << 16) + +#define SSI_ENABLE_CD (1 << 1) +#define SSI_ENABLE_E (1 << 0) + +/* IrDA Controller */ +#define IRDA_BASE 0xB0300000 +#define IR_RING_PTR_STATUS (IRDA_BASE + 0x00) +#define IR_RING_BASE_ADDR_H (IRDA_BASE + 0x04) +#define IR_RING_BASE_ADDR_L (IRDA_BASE + 0x08) +#define IR_RING_SIZE (IRDA_BASE + 0x0C) +#define IR_RING_PROMPT (IRDA_BASE + 0x10) +#define IR_RING_ADDR_CMPR (IRDA_BASE + 0x14) +#define IR_INT_CLEAR (IRDA_BASE + 0x18) +#define IR_CONFIG_1 (IRDA_BASE + 0x20) +# define IR_RX_INVERT_LED (1 << 0) +# define IR_TX_INVERT_LED (1 << 1) +# define IR_ST (1 << 2) +# define IR_SF (1 << 3) +# define IR_SIR (1 << 4) +# define IR_MIR (1 << 5) +# define IR_FIR (1 << 6) +# define IR_16CRC (1 << 7) +# define IR_TD (1 << 8) +# define IR_RX_ALL (1 << 9) +# define IR_DMA_ENABLE (1 << 10) +# define IR_RX_ENABLE (1 << 11) +# define IR_TX_ENABLE (1 << 12) +# define IR_LOOPBACK (1 << 14) +# define IR_SIR_MODE (IR_SIR | IR_DMA_ENABLE | \ + IR_RX_ALL | IR_RX_ENABLE | IR_SF | IR_16CRC) +#define IR_SIR_FLAGS (IRDA_BASE + 0x24) +#define IR_ENABLE (IRDA_BASE + 0x28) +# define IR_RX_STATUS (1 << 9) +# define IR_TX_STATUS (1 << 10) +#define IR_READ_PHY_CONFIG (IRDA_BASE + 0x2C) +#define IR_WRITE_PHY_CONFIG (IRDA_BASE + 0x30) +#define IR_MAX_PKT_LEN (IRDA_BASE + 0x34) +#define IR_RX_BYTE_CNT (IRDA_BASE + 0x38) +#define IR_CONFIG_2 (IRDA_BASE + 0x3C) +# define IR_MODE_INV (1 << 0) +# define IR_ONE_PIN (1 << 1) +#define IR_INTERFACE_CONFIG (IRDA_BASE + 0x40) + +/* GPIO */ +#define SYS_PINFUNC 0xB190002C +# define SYS_PF_USB (1 << 15) /* 2nd USB device/host */ +# define SYS_PF_U3 (1 << 14) /* GPIO23/U3TXD */ +# define SYS_PF_U2 (1 << 13) /* GPIO22/U2TXD */ +# define SYS_PF_U1 (1 << 12) /* GPIO21/U1TXD */ +# define SYS_PF_SRC (1 << 11) /* GPIO6/SROMCKE */ +# define SYS_PF_CK5 (1 << 10) /* GPIO3/CLK5 */ +# define SYS_PF_CK4 (1 << 9) /* GPIO2/CLK4 */ +# define SYS_PF_IRF (1 << 8) /* GPIO15/IRFIRSEL */ +# define SYS_PF_UR3 (1 << 7) /* GPIO[14:9]/UART3 */ +# define SYS_PF_I2D (1 << 6) /* GPIO8/I2SDI */ +# define SYS_PF_I2S (1 << 5) /* I2S/GPIO[29:31] */ +# define SYS_PF_NI2 (1 << 4) /* NI2/GPIO[24:28] */ +# define SYS_PF_U0 (1 << 3) /* U0TXD/GPIO20 */ +# define SYS_PF_RD (1 << 2) /* IRTXD/GPIO19 */ +# define SYS_PF_A97 (1 << 1) /* AC97/SSL1 */ +# define SYS_PF_S0 (1 << 0) /* SSI_0/GPIO[16:18] */ + +/* Au1100 only */ +# define SYS_PF_PC (1 << 18) /* PCMCIA/GPIO[207:204] */ +# define SYS_PF_LCD (1 << 17) /* extern lcd/GPIO[203:200] */ +# define SYS_PF_CS (1 << 16) /* EXTCLK0/32KHz to gpio2 */ +# define SYS_PF_EX0 (1 << 9) /* GPIO2/clock */ + +/* Au1550 only. Redefines lots of pins */ +# define SYS_PF_PSC2_MASK (7 << 17) +# define SYS_PF_PSC2_AC97 0 +# define SYS_PF_PSC2_SPI 0 +# define SYS_PF_PSC2_I2S (1 << 17) +# define SYS_PF_PSC2_SMBUS (3 << 17) +# define SYS_PF_PSC2_GPIO (7 << 17) +# define SYS_PF_PSC3_MASK (7 << 20) +# define SYS_PF_PSC3_AC97 0 +# define SYS_PF_PSC3_SPI 0 +# define SYS_PF_PSC3_I2S (1 << 20) +# define SYS_PF_PSC3_SMBUS (3 << 20) +# define SYS_PF_PSC3_GPIO (7 << 20) +# define SYS_PF_PSC1_S1 (1 << 1) +# define SYS_PF_MUST_BE_SET ((1 << 5) | (1 << 2)) + +/* Au1200 only */ +#ifdef CONFIG_SOC_AU1200 +#define SYS_PINFUNC_DMA (1 << 31) +#define SYS_PINFUNC_S0A (1 << 30) +#define SYS_PINFUNC_S1A (1 << 29) +#define SYS_PINFUNC_LP0 (1 << 28) +#define SYS_PINFUNC_LP1 (1 << 27) +#define SYS_PINFUNC_LD16 (1 << 26) +#define SYS_PINFUNC_LD8 (1 << 25) +#define SYS_PINFUNC_LD1 (1 << 24) +#define SYS_PINFUNC_LD0 (1 << 23) +#define SYS_PINFUNC_P1A (3 << 21) +#define SYS_PINFUNC_P1B (1 << 20) +#define SYS_PINFUNC_FS3 (1 << 19) +#define SYS_PINFUNC_P0A (3 << 17) +#define SYS_PINFUNC_CS (1 << 16) +#define SYS_PINFUNC_CIM (1 << 15) +#define SYS_PINFUNC_P1C (1 << 14) +#define SYS_PINFUNC_U1T (1 << 12) +#define SYS_PINFUNC_U1R (1 << 11) +#define SYS_PINFUNC_EX1 (1 << 10) +#define SYS_PINFUNC_EX0 (1 << 9) +#define SYS_PINFUNC_U0R (1 << 8) +#define SYS_PINFUNC_MC (1 << 7) +#define SYS_PINFUNC_S0B (1 << 6) +#define SYS_PINFUNC_S0C (1 << 5) +#define SYS_PINFUNC_P0B (1 << 4) +#define SYS_PINFUNC_U0T (1 << 3) +#define SYS_PINFUNC_S1B (1 << 2) +#endif + +#define SYS_TRIOUTRD 0xB1900100 +#define SYS_TRIOUTCLR 0xB1900100 +#define SYS_OUTPUTRD 0xB1900108 +#define SYS_OUTPUTSET 0xB1900108 +#define SYS_OUTPUTCLR 0xB190010C +#define SYS_PINSTATERD 0xB1900110 +#define SYS_PININPUTEN 0xB1900110 + +/* GPIO2, Au1500, Au1550 only */ +#define GPIO2_BASE 0xB1700000 +#define GPIO2_DIR (GPIO2_BASE + 0) +#define GPIO2_OUTPUT (GPIO2_BASE + 8) +#define GPIO2_PINSTATE (GPIO2_BASE + 0xC) +#define GPIO2_INTENABLE (GPIO2_BASE + 0x10) +#define GPIO2_ENABLE (GPIO2_BASE + 0x14) + +/* Power Management */ +#define SYS_SCRATCH0 0xB1900018 +#define SYS_SCRATCH1 0xB190001C +#define SYS_WAKEMSK 0xB1900034 +#define SYS_ENDIAN 0xB1900038 +#define SYS_POWERCTRL 0xB190003C +#define SYS_WAKESRC 0xB190005C +#define SYS_SLPPWR 0xB1900078 +#define SYS_SLEEP 0xB190007C + +/* Clock Controller */ +#define SYS_FREQCTRL0 0xB1900020 +# define SYS_FC_FRDIV2_BIT 22 +# define SYS_FC_FRDIV2_MASK (0xff << SYS_FC_FRDIV2_BIT) +# define SYS_FC_FE2 (1 << 21) +# define SYS_FC_FS2 (1 << 20) +# define SYS_FC_FRDIV1_BIT 12 +# define SYS_FC_FRDIV1_MASK (0xff << SYS_FC_FRDIV1_BIT) +# define SYS_FC_FE1 (1 << 11) +# define SYS_FC_FS1 (1 << 10) +# define SYS_FC_FRDIV0_BIT 2 +# define SYS_FC_FRDIV0_MASK (0xff << SYS_FC_FRDIV0_BIT) +# define SYS_FC_FE0 (1 << 1) +# define SYS_FC_FS0 (1 << 0) +#define SYS_FREQCTRL1 0xB1900024 +# define SYS_FC_FRDIV5_BIT 22 +# define SYS_FC_FRDIV5_MASK (0xff << SYS_FC_FRDIV5_BIT) +# define SYS_FC_FE5 (1 << 21) +# define SYS_FC_FS5 (1 << 20) +# define SYS_FC_FRDIV4_BIT 12 +# define SYS_FC_FRDIV4_MASK (0xff << SYS_FC_FRDIV4_BIT) +# define SYS_FC_FE4 (1 << 11) +# define SYS_FC_FS4 (1 << 10) +# define SYS_FC_FRDIV3_BIT 2 +# define SYS_FC_FRDIV3_MASK (0xff << SYS_FC_FRDIV3_BIT) +# define SYS_FC_FE3 (1 << 1) +# define SYS_FC_FS3 (1 << 0) +#define SYS_CLKSRC 0xB1900028 +# define SYS_CS_ME1_BIT 27 +# define SYS_CS_ME1_MASK (0x7 << SYS_CS_ME1_BIT) +# define SYS_CS_DE1 (1 << 26) +# define SYS_CS_CE1 (1 << 25) +# define SYS_CS_ME0_BIT 22 +# define SYS_CS_ME0_MASK (0x7 << SYS_CS_ME0_BIT) +# define SYS_CS_DE0 (1 << 21) +# define SYS_CS_CE0 (1 << 20) +# define SYS_CS_MI2_BIT 17 +# define SYS_CS_MI2_MASK (0x7 << SYS_CS_MI2_BIT) +# define SYS_CS_DI2 (1 << 16) +# define SYS_CS_CI2 (1 << 15) +#ifdef CONFIG_SOC_AU1100 +# define SYS_CS_ML_BIT 7 +# define SYS_CS_ML_MASK (0x7 << SYS_CS_ML_BIT) +# define SYS_CS_DL (1 << 6) +# define SYS_CS_CL (1 << 5) +#else +# define SYS_CS_MUH_BIT 12 +# define SYS_CS_MUH_MASK (0x7 << SYS_CS_MUH_BIT) +# define SYS_CS_DUH (1 << 11) +# define SYS_CS_CUH (1 << 10) +# define SYS_CS_MUD_BIT 7 +# define SYS_CS_MUD_MASK (0x7 << SYS_CS_MUD_BIT) +# define SYS_CS_DUD (1 << 6) +# define SYS_CS_CUD (1 << 5) +#endif +# define SYS_CS_MIR_BIT 2 +# define SYS_CS_MIR_MASK (0x7 << SYS_CS_MIR_BIT) +# define SYS_CS_DIR (1 << 1) +# define SYS_CS_CIR (1 << 0) + +# define SYS_CS_MUX_AUX 0x1 +# define SYS_CS_MUX_FQ0 0x2 +# define SYS_CS_MUX_FQ1 0x3 +# define SYS_CS_MUX_FQ2 0x4 +# define SYS_CS_MUX_FQ3 0x5 +# define SYS_CS_MUX_FQ4 0x6 +# define SYS_CS_MUX_FQ5 0x7 +#define SYS_CPUPLL 0xB1900060 +#define SYS_AUXPLL 0xB1900064 + +/* AC97 Controller */ +#define AC97C_CONFIG 0xB0000000 +# define AC97C_RECV_SLOTS_BIT 13 +# define AC97C_RECV_SLOTS_MASK (0x3ff << AC97C_RECV_SLOTS_BIT) +# define AC97C_XMIT_SLOTS_BIT 3 +# define AC97C_XMIT_SLOTS_MASK (0x3ff << AC97C_XMIT_SLOTS_BIT) +# define AC97C_SG (1 << 2) +# define AC97C_SYNC (1 << 1) +# define AC97C_RESET (1 << 0) +#define AC97C_STATUS 0xB0000004 +# define AC97C_XU (1 << 11) +# define AC97C_XO (1 << 10) +# define AC97C_RU (1 << 9) +# define AC97C_RO (1 << 8) +# define AC97C_READY (1 << 7) +# define AC97C_CP (1 << 6) +# define AC97C_TR (1 << 5) +# define AC97C_TE (1 << 4) +# define AC97C_TF (1 << 3) +# define AC97C_RR (1 << 2) +# define AC97C_RE (1 << 1) +# define AC97C_RF (1 << 0) +#define AC97C_DATA 0xB0000008 +#define AC97C_CMD 0xB000000C +# define AC97C_WD_BIT 16 +# define AC97C_READ (1 << 7) +# define AC97C_INDEX_MASK 0x7f +#define AC97C_CNTRL 0xB0000010 +# define AC97C_RS (1 << 1) +# define AC97C_CE (1 << 0) + +/* Secure Digital (SD) Controller */ +#define SD0_XMIT_FIFO 0xB0600000 +#define SD0_RECV_FIFO 0xB0600004 +#define SD1_XMIT_FIFO 0xB0680000 +#define SD1_RECV_FIFO 0xB0680004 + +#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550) +/* Au1500 PCI Controller */ +#define Au1500_CFG_BASE 0xB4005000 /* virtual, KSEG1 addr */ +#define Au1500_PCI_CMEM (Au1500_CFG_BASE + 0) +#define Au1500_PCI_CFG (Au1500_CFG_BASE + 4) +# define PCI_ERROR ((1 << 22) | (1 << 23) | (1 << 24) | \ + (1 << 25) | (1 << 26) | (1 << 27)) +#define Au1500_PCI_B2BMASK_CCH (Au1500_CFG_BASE + 8) +#define Au1500_PCI_B2B0_VID (Au1500_CFG_BASE + 0xC) +#define Au1500_PCI_B2B1_ID (Au1500_CFG_BASE + 0x10) +#define Au1500_PCI_MWMASK_DEV (Au1500_CFG_BASE + 0x14) +#define Au1500_PCI_MWBASE_REV_CCL (Au1500_CFG_BASE + 0x18) +#define Au1500_PCI_ERR_ADDR (Au1500_CFG_BASE + 0x1C) +#define Au1500_PCI_SPEC_INTACK (Au1500_CFG_BASE + 0x20) +#define Au1500_PCI_ID (Au1500_CFG_BASE + 0x100) +#define Au1500_PCI_STATCMD (Au1500_CFG_BASE + 0x104) +#define Au1500_PCI_CLASSREV (Au1500_CFG_BASE + 0x108) +#define Au1500_PCI_HDRTYPE (Au1500_CFG_BASE + 0x10C) +#define Au1500_PCI_MBAR (Au1500_CFG_BASE + 0x110) + +#define Au1500_PCI_HDR 0xB4005100 /* virtual, KSEG1 addr */ + +/* + * All of our structures, like PCI resource, have 32-bit members. + * Drivers are expected to do an ioremap on the PCI MEM resource, but it's + * hard to store 0x4 0000 0000 in a 32-bit type. We require a small patch + * to __ioremap to check for addresses between (u32)Au1500_PCI_MEM_START and + * (u32)Au1500_PCI_MEM_END and change those to the full 36-bit PCI MEM + * addresses. For PCI I/O, it's simpler because we get to do the ioremap + * ourselves and then adjust the device's resources. + */ +#define Au1500_EXT_CFG 0x600000000ULL +#define Au1500_EXT_CFG_TYPE1 0x680000000ULL +#define Au1500_PCI_IO_START 0x500000000ULL +#define Au1500_PCI_IO_END 0x5000FFFFFULL +#define Au1500_PCI_MEM_START 0x440000000ULL +#define Au1500_PCI_MEM_END 0x44FFFFFFFULL + +#define PCI_IO_START 0x00001000 +#define PCI_IO_END 0x000FFFFF +#define PCI_MEM_START 0x40000000 +#define PCI_MEM_END 0x4FFFFFFF + +#define PCI_FIRST_DEVFN (0 << 3) +#define PCI_LAST_DEVFN (19 << 3) + +#define IOPORT_RESOURCE_START 0x00001000 /* skip legacy probing */ +#define IOPORT_RESOURCE_END 0xffffffff +#define IOMEM_RESOURCE_START 0x10000000 +#define IOMEM_RESOURCE_END 0xffffffff + +#else /* Au1000 and Au1100 and Au1200 */ + +/* Don't allow any legacy ports probing */ +#define IOPORT_RESOURCE_START 0x10000000 +#define IOPORT_RESOURCE_END 0xffffffff +#define IOMEM_RESOURCE_START 0x10000000 +#define IOMEM_RESOURCE_END 0xffffffff + +#define PCI_IO_START 0 +#define PCI_IO_END 0 +#define PCI_MEM_START 0 +#define PCI_MEM_END 0 +#define PCI_FIRST_DEVFN 0 +#define PCI_LAST_DEVFN 0 + +#endif + +#ifndef _LANGUAGE_ASSEMBLY +typedef volatile struct { + /* 0x0000 */ u32 toytrim; + /* 0x0004 */ u32 toywrite; + /* 0x0008 */ u32 toymatch0; + /* 0x000C */ u32 toymatch1; + /* 0x0010 */ u32 toymatch2; + /* 0x0014 */ u32 cntrctrl; + /* 0x0018 */ u32 scratch0; + /* 0x001C */ u32 scratch1; + /* 0x0020 */ u32 freqctrl0; + /* 0x0024 */ u32 freqctrl1; + /* 0x0028 */ u32 clksrc; + /* 0x002C */ u32 pinfunc; + /* 0x0030 */ u32 reserved0; + /* 0x0034 */ u32 wakemsk; + /* 0x0038 */ u32 endian; + /* 0x003C */ u32 powerctrl; + /* 0x0040 */ u32 toyread; + /* 0x0044 */ u32 rtctrim; + /* 0x0048 */ u32 rtcwrite; + /* 0x004C */ u32 rtcmatch0; + /* 0x0050 */ u32 rtcmatch1; + /* 0x0054 */ u32 rtcmatch2; + /* 0x0058 */ u32 rtcread; + /* 0x005C */ u32 wakesrc; + /* 0x0060 */ u32 cpupll; + /* 0x0064 */ u32 auxpll; + /* 0x0068 */ u32 reserved1; + /* 0x006C */ u32 reserved2; + /* 0x0070 */ u32 reserved3; + /* 0x0074 */ u32 reserved4; + /* 0x0078 */ u32 slppwr; + /* 0x007C */ u32 sleep; + /* 0x0080 */ u32 reserved5[32]; + /* 0x0100 */ u32 trioutrd; +#define trioutclr trioutrd + /* 0x0104 */ u32 reserved6; + /* 0x0108 */ u32 outputrd; +#define outputset outputrd + /* 0x010C */ u32 outputclr; + /* 0x0110 */ u32 pinstaterd; +#define pininputen pinstaterd +} AU1X00_SYS; + +static AU1X00_SYS * const sys = (AU1X00_SYS *)SYS_BASE; + +#endif + +/* + * Processor information based on PRID. + * Copied from PowerPC. + */ +#ifndef _LANGUAGE_ASSEMBLY +struct cpu_spec { + /* CPU is matched via (PRID & prid_mask) == prid_value */ + unsigned int prid_mask; + unsigned int prid_value; + + char *cpu_name; + unsigned char cpu_od; /* Set Config[OD] */ + unsigned char cpu_bclk; /* Enable BCLK switching */ + unsigned char cpu_pll_wo; /* sys_cpupll reg. write-only */ +}; + +extern struct cpu_spec cpu_specs[]; +extern struct cpu_spec *cur_cpu_spec[]; +#endif + +#endif diff --git a/arch/mips/include/asm/mach-au1x00/au1000_dma.h b/arch/mips/include/asm/mach-au1x00/au1000_dma.h new file mode 100644 index 00000000000..c333b4e1cd4 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1000_dma.h @@ -0,0 +1,458 @@ +/* + * BRIEF MODULE DESCRIPTION + * Defines for using and allocating DMA channels on the Alchemy + * Au1x00 MIPS processors. + * + * Copyright 2000, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef __ASM_AU1000_DMA_H +#define __ASM_AU1000_DMA_H + +#include /* need byte IO */ +#include /* And spinlocks */ +#include +#include + +#define NUM_AU1000_DMA_CHANNELS 8 + +/* DMA Channel Base Addresses */ +#define DMA_CHANNEL_BASE 0xB4002000 +#define DMA_CHANNEL_LEN 0x00000100 + +/* DMA Channel Register Offsets */ +#define DMA_MODE_SET 0x00000000 +#define DMA_MODE_READ DMA_MODE_SET +#define DMA_MODE_CLEAR 0x00000004 +/* DMA Mode register bits follow */ +#define DMA_DAH_MASK (0x0f << 20) +#define DMA_DID_BIT 16 +#define DMA_DID_MASK (0x0f << DMA_DID_BIT) +#define DMA_DS (1 << 15) +#define DMA_BE (1 << 13) +#define DMA_DR (1 << 12) +#define DMA_TS8 (1 << 11) +#define DMA_DW_BIT 9 +#define DMA_DW_MASK (0x03 << DMA_DW_BIT) +#define DMA_DW8 (0 << DMA_DW_BIT) +#define DMA_DW16 (1 << DMA_DW_BIT) +#define DMA_DW32 (2 << DMA_DW_BIT) +#define DMA_NC (1 << 8) +#define DMA_IE (1 << 7) +#define DMA_HALT (1 << 6) +#define DMA_GO (1 << 5) +#define DMA_AB (1 << 4) +#define DMA_D1 (1 << 3) +#define DMA_BE1 (1 << 2) +#define DMA_D0 (1 << 1) +#define DMA_BE0 (1 << 0) + +#define DMA_PERIPHERAL_ADDR 0x00000008 +#define DMA_BUFFER0_START 0x0000000C +#define DMA_BUFFER1_START 0x00000014 +#define DMA_BUFFER0_COUNT 0x00000010 +#define DMA_BUFFER1_COUNT 0x00000018 +#define DMA_BAH_BIT 16 +#define DMA_BAH_MASK (0x0f << DMA_BAH_BIT) +#define DMA_COUNT_BIT 0 +#define DMA_COUNT_MASK (0xffff << DMA_COUNT_BIT) + +/* DMA Device IDs follow */ +enum { + DMA_ID_UART0_TX = 0, + DMA_ID_UART0_RX, + DMA_ID_GP04, + DMA_ID_GP05, + DMA_ID_AC97C_TX, + DMA_ID_AC97C_RX, + DMA_ID_UART3_TX, + DMA_ID_UART3_RX, + DMA_ID_USBDEV_EP0_RX, + DMA_ID_USBDEV_EP0_TX, + DMA_ID_USBDEV_EP2_TX, + DMA_ID_USBDEV_EP3_TX, + DMA_ID_USBDEV_EP4_RX, + DMA_ID_USBDEV_EP5_RX, + DMA_ID_I2S_TX, + DMA_ID_I2S_RX, + DMA_NUM_DEV +}; + +/* DMA Device ID's for 2nd bank (AU1100) follow */ +enum { + DMA_ID_SD0_TX = 0, + DMA_ID_SD0_RX, + DMA_ID_SD1_TX, + DMA_ID_SD1_RX, + DMA_NUM_DEV_BANK2 +}; + +struct dma_chan { + int dev_id; /* this channel is allocated if >= 0, */ + /* free otherwise */ + unsigned int io; + const char *dev_str; + int irq; + void *irq_dev; + unsigned int fifo_addr; + unsigned int mode; +}; + +/* These are in arch/mips/au1000/common/dma.c */ +extern struct dma_chan au1000_dma_table[]; +extern int request_au1000_dma(int dev_id, + const char *dev_str, + irq_handler_t irqhandler, + unsigned long irqflags, + void *irq_dev_id); +extern void free_au1000_dma(unsigned int dmanr); +extern int au1000_dma_read_proc(char *buf, char **start, off_t fpos, + int length, int *eof, void *data); +extern void dump_au1000_dma_channel(unsigned int dmanr); +extern spinlock_t au1000_dma_spin_lock; + +static inline struct dma_chan *get_dma_chan(unsigned int dmanr) +{ + if (dmanr >= NUM_AU1000_DMA_CHANNELS || + au1000_dma_table[dmanr].dev_id < 0) + return NULL; + return &au1000_dma_table[dmanr]; +} + +static inline unsigned long claim_dma_lock(void) +{ + unsigned long flags; + + spin_lock_irqsave(&au1000_dma_spin_lock, flags); + return flags; +} + +static inline void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&au1000_dma_spin_lock, flags); +} + +/* + * Set the DMA buffer enable bits in the mode register. + */ +static inline void enable_dma_buffer0(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(DMA_BE0, chan->io + DMA_MODE_SET); +} + +static inline void enable_dma_buffer1(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(DMA_BE1, chan->io + DMA_MODE_SET); +} +static inline void enable_dma_buffers(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET); +} + +static inline void start_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(DMA_GO, chan->io + DMA_MODE_SET); +} + +#define DMA_HALT_POLL 0x5000 + +static inline void halt_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + int i; + + if (!chan) + return; + au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR); + + /* Poll the halt bit */ + for (i = 0; i < DMA_HALT_POLL; i++) + if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) + break; + if (i == DMA_HALT_POLL) + printk(KERN_INFO "halt_dma: HALT poll expired!\n"); +} + +static inline void disable_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + halt_dma(dmanr); + + /* Now we can disable the buffers */ + au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR); +} + +static inline int dma_halted(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return 1; + return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0; +} + +/* Initialize a DMA channel. */ +static inline void init_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + u32 mode; + + if (!chan) + return; + + disable_dma(dmanr); + + /* Set device FIFO address */ + au_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR); + + mode = chan->mode | (chan->dev_id << DMA_DID_BIT); + if (chan->irq) + mode |= DMA_IE; + + au_writel(~mode, chan->io + DMA_MODE_CLEAR); + au_writel(mode, chan->io + DMA_MODE_SET); +} + +/* + * Set mode for a specific DMA channel + */ +static inline void set_dma_mode(unsigned int dmanr, unsigned int mode) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + /* + * set_dma_mode is only allowed to change endianess, direction, + * transfer size, device FIFO width, and coherency settings. + * Make sure anything else is masked off. + */ + mode &= (DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC); + chan->mode &= ~(DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC); + chan->mode |= mode; +} + +static inline unsigned int get_dma_mode(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return 0; + return chan->mode; +} + +static inline int get_dma_active_buffer(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return -1; + return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0; +} + +/* + * Set the device FIFO address for a specific DMA channel - only + * applicable to GPO4 and GPO5. All the other devices have fixed + * FIFO addresses. + */ +static inline void set_dma_fifo_addr(unsigned int dmanr, unsigned int a) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + if (chan->mode & DMA_DS) /* second bank of device IDs */ + return; + + if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05) + return; + + au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR); +} + +/* + * Clear the DMA buffer done bits in the mode register. + */ +static inline void clear_dma_done0(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR); +} + +static inline void clear_dma_done1(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR); +} + +/* + * This does nothing - not applicable to Au1000 DMA. + */ +static inline void set_dma_page(unsigned int dmanr, char pagenr) +{ +} + +/* + * Set Buffer 0 transfer address for specific DMA channel. + */ +static inline void set_dma_addr0(unsigned int dmanr, unsigned int a) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(a, chan->io + DMA_BUFFER0_START); +} + +/* + * Set Buffer 1 transfer address for specific DMA channel. + */ +static inline void set_dma_addr1(unsigned int dmanr, unsigned int a) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + au_writel(a, chan->io + DMA_BUFFER1_START); +} + + +/* + * Set Buffer 0 transfer size (max 64k) for a specific DMA channel. + */ +static inline void set_dma_count0(unsigned int dmanr, unsigned int count) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + count &= DMA_COUNT_MASK; + au_writel(count, chan->io + DMA_BUFFER0_COUNT); +} + +/* + * Set Buffer 1 transfer size (max 64k) for a specific DMA channel. + */ +static inline void set_dma_count1(unsigned int dmanr, unsigned int count) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + count &= DMA_COUNT_MASK; + au_writel(count, chan->io + DMA_BUFFER1_COUNT); +} + +/* + * Set both buffer transfer sizes (max 64k) for a specific DMA channel. + */ +static inline void set_dma_count(unsigned int dmanr, unsigned int count) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + count &= DMA_COUNT_MASK; + au_writel(count, chan->io + DMA_BUFFER0_COUNT); + au_writel(count, chan->io + DMA_BUFFER1_COUNT); +} + +/* + * Returns which buffer has its done bit set in the mode register. + * Returns -1 if neither or both done bits set. + */ +static inline unsigned int get_dma_buffer_done(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return 0; + return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1); +} + + +/* + * Returns the DMA channel's Buffer Done IRQ number. + */ +static inline int get_dma_done_irq(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return -1; + return chan->irq; +} + +/* + * Get DMA residue count. Returns the number of _bytes_ left to transfer. + */ +static inline int get_dma_residue(unsigned int dmanr) +{ + int curBufCntReg, count; + struct dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return 0; + + curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? + DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT; + + count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK; + + if ((chan->mode & DMA_DW_MASK) == DMA_DW16) + count <<= 1; + else if ((chan->mode & DMA_DW_MASK) == DMA_DW32) + count <<= 2; + + return count; +} + +#endif /* __ASM_AU1000_DMA_H */ diff --git a/arch/mips/include/asm/mach-au1x00/au1000_gpio.h b/arch/mips/include/asm/mach-au1x00/au1000_gpio.h new file mode 100644 index 00000000000..d8c96fda554 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1000_gpio.h @@ -0,0 +1,56 @@ +/* + * FILE NAME au1000_gpio.h + * + * BRIEF MODULE DESCRIPTION + * API to Alchemy Au1xx0 GPIO device. + * + * Author: MontaVista Software, Inc. + * Steve Longerbeam + * + * Copyright 2001, 2008 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __AU1000_GPIO_H +#define __AU1000_GPIO_H + +#include + +#define AU1000GPIO_IOC_MAGIC 'A' + +#define AU1000GPIO_IN _IOR(AU1000GPIO_IOC_MAGIC, 0, int) +#define AU1000GPIO_SET _IOW(AU1000GPIO_IOC_MAGIC, 1, int) +#define AU1000GPIO_CLEAR _IOW(AU1000GPIO_IOC_MAGIC, 2, int) +#define AU1000GPIO_OUT _IOW(AU1000GPIO_IOC_MAGIC, 3, int) +#define AU1000GPIO_TRISTATE _IOW(AU1000GPIO_IOC_MAGIC, 4, int) +#define AU1000GPIO_AVAIL_MASK _IOR(AU1000GPIO_IOC_MAGIC, 5, int) + +#ifdef __KERNEL__ +extern u32 get_au1000_avail_gpio_mask(void); +extern int au1000gpio_tristate(u32 data); +extern int au1000gpio_in(u32 *data); +extern int au1000gpio_set(u32 data); +extern int au1000gpio_clear(u32 data); +extern int au1000gpio_out(u32 data); +#endif + +#endif diff --git a/arch/mips/include/asm/mach-au1x00/au1100_mmc.h b/arch/mips/include/asm/mach-au1x00/au1100_mmc.h new file mode 100644 index 00000000000..c35e2091849 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1100_mmc.h @@ -0,0 +1,208 @@ +/* + * BRIEF MODULE DESCRIPTION + * Defines for using the MMC/SD controllers on the + * Alchemy Au1100 mips processor. + * + * Copyright (c) 2003 Embedded Edge, LLC. + * Author: Embedded Edge, LLC. + * dan@embeddededge.com or tim@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +/* + * AU1100 MMC/SD definitions. + * + * From "AMD Alchemy Solutions Au1100 Processor Data Book - Preliminary" + * June, 2003 + */ + +#ifndef __ASM_AU1100_MMC_H +#define __ASM_AU1100_MMC_H + +#include + +struct au1xmmc_platform_data { + int(*cd_setup)(void *mmc_host, int on); + int(*card_inserted)(void *mmc_host); + int(*card_readonly)(void *mmc_host); + void(*set_power)(void *mmc_host, int state); + struct led_classdev *led; +}; + +#define SD0_BASE 0xB0600000 +#define SD1_BASE 0xB0680000 + + +/* + * Register offsets. + */ +#define SD_TXPORT (0x0000) +#define SD_RXPORT (0x0004) +#define SD_CONFIG (0x0008) +#define SD_ENABLE (0x000C) +#define SD_CONFIG2 (0x0010) +#define SD_BLKSIZE (0x0014) +#define SD_STATUS (0x0018) +#define SD_DEBUG (0x001C) +#define SD_CMD (0x0020) +#define SD_CMDARG (0x0024) +#define SD_RESP3 (0x0028) +#define SD_RESP2 (0x002C) +#define SD_RESP1 (0x0030) +#define SD_RESP0 (0x0034) +#define SD_TIMEOUT (0x0038) + + +/* + * SD_TXPORT bit definitions. + */ +#define SD_TXPORT_TXD (0x000000ff) + + +/* + * SD_RXPORT bit definitions. + */ +#define SD_RXPORT_RXD (0x000000ff) + + +/* + * SD_CONFIG bit definitions. + */ +#define SD_CONFIG_DIV (0x000001ff) +#define SD_CONFIG_DE (0x00000200) +#define SD_CONFIG_NE (0x00000400) +#define SD_CONFIG_TU (0x00000800) +#define SD_CONFIG_TO (0x00001000) +#define SD_CONFIG_RU (0x00002000) +#define SD_CONFIG_RO (0x00004000) +#define SD_CONFIG_I (0x00008000) +#define SD_CONFIG_CR (0x00010000) +#define SD_CONFIG_RAT (0x00020000) +#define SD_CONFIG_DD (0x00040000) +#define SD_CONFIG_DT (0x00080000) +#define SD_CONFIG_SC (0x00100000) +#define SD_CONFIG_RC (0x00200000) +#define SD_CONFIG_WC (0x00400000) +#define SD_CONFIG_xxx (0x00800000) +#define SD_CONFIG_TH (0x01000000) +#define SD_CONFIG_TE (0x02000000) +#define SD_CONFIG_TA (0x04000000) +#define SD_CONFIG_RH (0x08000000) +#define SD_CONFIG_RA (0x10000000) +#define SD_CONFIG_RF (0x20000000) +#define SD_CONFIG_CD (0x40000000) +#define SD_CONFIG_SI (0x80000000) + + +/* + * SD_ENABLE bit definitions. + */ +#define SD_ENABLE_CE (0x00000001) +#define SD_ENABLE_R (0x00000002) + + +/* + * SD_CONFIG2 bit definitions. + */ +#define SD_CONFIG2_EN (0x00000001) +#define SD_CONFIG2_FF (0x00000002) +#define SD_CONFIG2_xx1 (0x00000004) +#define SD_CONFIG2_DF (0x00000008) +#define SD_CONFIG2_DC (0x00000010) +#define SD_CONFIG2_xx2 (0x000000e0) +#define SD_CONFIG2_WB (0x00000100) +#define SD_CONFIG2_RW (0x00000200) + + +/* + * SD_BLKSIZE bit definitions. + */ +#define SD_BLKSIZE_BS (0x000007ff) +#define SD_BLKSIZE_BS_SHIFT (0) +#define SD_BLKSIZE_BC (0x01ff0000) +#define SD_BLKSIZE_BC_SHIFT (16) + + +/* + * SD_STATUS bit definitions. + */ +#define SD_STATUS_DCRCW (0x00000007) +#define SD_STATUS_xx1 (0x00000008) +#define SD_STATUS_CB (0x00000010) +#define SD_STATUS_DB (0x00000020) +#define SD_STATUS_CF (0x00000040) +#define SD_STATUS_D3 (0x00000080) +#define SD_STATUS_xx2 (0x00000300) +#define SD_STATUS_NE (0x00000400) +#define SD_STATUS_TU (0x00000800) +#define SD_STATUS_TO (0x00001000) +#define SD_STATUS_RU (0x00002000) +#define SD_STATUS_RO (0x00004000) +#define SD_STATUS_I (0x00008000) +#define SD_STATUS_CR (0x00010000) +#define SD_STATUS_RAT (0x00020000) +#define SD_STATUS_DD (0x00040000) +#define SD_STATUS_DT (0x00080000) +#define SD_STATUS_SC (0x00100000) +#define SD_STATUS_RC (0x00200000) +#define SD_STATUS_WC (0x00400000) +#define SD_STATUS_xx3 (0x00800000) +#define SD_STATUS_TH (0x01000000) +#define SD_STATUS_TE (0x02000000) +#define SD_STATUS_TA (0x04000000) +#define SD_STATUS_RH (0x08000000) +#define SD_STATUS_RA (0x10000000) +#define SD_STATUS_RF (0x20000000) +#define SD_STATUS_CD (0x40000000) +#define SD_STATUS_SI (0x80000000) + + +/* + * SD_CMD bit definitions. + */ +#define SD_CMD_GO (0x00000001) +#define SD_CMD_RY (0x00000002) +#define SD_CMD_xx1 (0x0000000c) +#define SD_CMD_CT_MASK (0x000000f0) +#define SD_CMD_CT_0 (0x00000000) +#define SD_CMD_CT_1 (0x00000010) +#define SD_CMD_CT_2 (0x00000020) +#define SD_CMD_CT_3 (0x00000030) +#define SD_CMD_CT_4 (0x00000040) +#define SD_CMD_CT_5 (0x00000050) +#define SD_CMD_CT_6 (0x00000060) +#define SD_CMD_CT_7 (0x00000070) +#define SD_CMD_CI (0x0000ff00) +#define SD_CMD_CI_SHIFT (8) +#define SD_CMD_RT_MASK (0x00ff0000) +#define SD_CMD_RT_0 (0x00000000) +#define SD_CMD_RT_1 (0x00010000) +#define SD_CMD_RT_2 (0x00020000) +#define SD_CMD_RT_3 (0x00030000) +#define SD_CMD_RT_4 (0x00040000) +#define SD_CMD_RT_5 (0x00050000) +#define SD_CMD_RT_6 (0x00060000) +#define SD_CMD_RT_1B (0x00810000) + + +#endif /* __ASM_AU1100_MMC_H */ + diff --git a/arch/mips/include/asm/mach-au1x00/au1550_spi.h b/arch/mips/include/asm/mach-au1x00/au1550_spi.h new file mode 100644 index 00000000000..08e1958e941 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1550_spi.h @@ -0,0 +1,15 @@ +/* + * au1550_spi.h - Au1550 PSC SPI controller driver - platform data structure + */ + +#ifndef _AU1550_SPI_H_ +#define _AU1550_SPI_H_ + +struct au1550_spi_info { + u32 mainclk_hz; /* main input clock frequency of PSC */ + u16 num_chipselect; /* number of chipselects supported */ + void (*activate_cs)(struct au1550_spi_info *spi, int cs, int polarity); + void (*deactivate_cs)(struct au1550_spi_info *spi, int cs, int polarity); +}; + +#endif diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx.h b/arch/mips/include/asm/mach-au1x00/au1xxx.h new file mode 100644 index 00000000000..1b3655090ed --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1xxx.h @@ -0,0 +1,43 @@ +/* + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _AU1XXX_H_ +#define _AU1XXX_H_ + +#include + +#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || \ + defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) +#include + +#elif defined(CONFIG_MIPS_PB1550) +#include + +#elif defined(CONFIG_MIPS_PB1200) +#include + +#elif defined(CONFIG_MIPS_DB1200) +#include + +#endif + +#endif /* _AU1XXX_H_ */ diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h new file mode 100644 index 00000000000..44a67bf05dc --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h @@ -0,0 +1,386 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Include file for Alchemy Semiconductor's Au1550 Descriptor + * Based DMA Controller. + * + * Copyright 2004 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Specifics for the Au1xxx Descriptor-Based DMA Controller, + * first seen in the AU1550 part. + */ +#ifndef _AU1000_DBDMA_H_ +#define _AU1000_DBDMA_H_ + +#ifndef _LANGUAGE_ASSEMBLY + +/* + * The DMA base addresses. + * The channels are every 256 bytes (0x0100) from the channel 0 base. + * Interrupt status/enable is bits 15:0 for channels 15 to zero. + */ +#define DDMA_GLOBAL_BASE 0xb4003000 +#define DDMA_CHANNEL_BASE 0xb4002000 + +typedef volatile struct dbdma_global { + u32 ddma_config; + u32 ddma_intstat; + u32 ddma_throttle; + u32 ddma_inten; +} dbdma_global_t; + +/* General Configuration. */ +#define DDMA_CONFIG_AF (1 << 2) +#define DDMA_CONFIG_AH (1 << 1) +#define DDMA_CONFIG_AL (1 << 0) + +#define DDMA_THROTTLE_EN (1 << 31) + +/* The structure of a DMA Channel. */ +typedef volatile struct au1xxx_dma_channel { + u32 ddma_cfg; /* See below */ + u32 ddma_desptr; /* 32-byte aligned pointer to descriptor */ + u32 ddma_statptr; /* word aligned pointer to status word */ + u32 ddma_dbell; /* A write activates channel operation */ + u32 ddma_irq; /* If bit 0 set, interrupt pending */ + u32 ddma_stat; /* See below */ + u32 ddma_bytecnt; /* Byte count, valid only when chan idle */ + /* Remainder, up to the 256 byte boundary, is reserved. */ +} au1x_dma_chan_t; + +#define DDMA_CFG_SED (1 << 9) /* source DMA level/edge detect */ +#define DDMA_CFG_SP (1 << 8) /* source DMA polarity */ +#define DDMA_CFG_DED (1 << 7) /* destination DMA level/edge detect */ +#define DDMA_CFG_DP (1 << 6) /* destination DMA polarity */ +#define DDMA_CFG_SYNC (1 << 5) /* Sync static bus controller */ +#define DDMA_CFG_PPR (1 << 4) /* PCI posted read/write control */ +#define DDMA_CFG_DFN (1 << 3) /* Descriptor fetch non-coherent */ +#define DDMA_CFG_SBE (1 << 2) /* Source big endian */ +#define DDMA_CFG_DBE (1 << 1) /* Destination big endian */ +#define DDMA_CFG_EN (1 << 0) /* Channel enable */ + +/* + * Always set when descriptor processing done, regardless of + * interrupt enable state. Reflected in global intstat, don't + * clear this until global intstat is read/used. + */ +#define DDMA_IRQ_IN (1 << 0) + +#define DDMA_STAT_DB (1 << 2) /* Doorbell pushed */ +#define DDMA_STAT_V (1 << 1) /* Descriptor valid */ +#define DDMA_STAT_H (1 << 0) /* Channel Halted */ + +/* + * "Standard" DDMA Descriptor. + * Must be 32-byte aligned. + */ +typedef volatile struct au1xxx_ddma_desc { + u32 dscr_cmd0; /* See below */ + u32 dscr_cmd1; /* See below */ + u32 dscr_source0; /* source phys address */ + u32 dscr_source1; /* See below */ + u32 dscr_dest0; /* Destination address */ + u32 dscr_dest1; /* See below */ + u32 dscr_stat; /* completion status */ + u32 dscr_nxtptr; /* Next descriptor pointer (mostly) */ + /* + * First 32 bytes are HW specific!!! + * Lets have some SW data following -- make sure it's 32 bytes. + */ + u32 sw_status; + u32 sw_context; + u32 sw_reserved[6]; +} au1x_ddma_desc_t; + +#define DSCR_CMD0_V (1 << 31) /* Descriptor valid */ +#define DSCR_CMD0_MEM (1 << 30) /* mem-mem transfer */ +#define DSCR_CMD0_SID_MASK (0x1f << 25) /* Source ID */ +#define DSCR_CMD0_DID_MASK (0x1f << 20) /* Destination ID */ +#define DSCR_CMD0_SW_MASK (0x3 << 18) /* Source Width */ +#define DSCR_CMD0_DW_MASK (0x3 << 16) /* Destination Width */ +#define DSCR_CMD0_ARB (0x1 << 15) /* Set for Hi Pri */ +#define DSCR_CMD0_DT_MASK (0x3 << 13) /* Descriptor Type */ +#define DSCR_CMD0_SN (0x1 << 12) /* Source non-coherent */ +#define DSCR_CMD0_DN (0x1 << 11) /* Destination non-coherent */ +#define DSCR_CMD0_SM (0x1 << 10) /* Stride mode */ +#define DSCR_CMD0_IE (0x1 << 8) /* Interrupt Enable */ +#define DSCR_CMD0_SP (0x1 << 4) /* Status pointer select */ +#define DSCR_CMD0_CV (0x1 << 2) /* Clear Valid when done */ +#define DSCR_CMD0_ST_MASK (0x3 << 0) /* Status instruction */ + +#define SW_STATUS_INUSE (1 << 0) + +/* Command 0 device IDs. */ +#ifdef CONFIG_SOC_AU1550 +#define DSCR_CMD0_UART0_TX 0 +#define DSCR_CMD0_UART0_RX 1 +#define DSCR_CMD0_UART3_TX 2 +#define DSCR_CMD0_UART3_RX 3 +#define DSCR_CMD0_DMA_REQ0 4 +#define DSCR_CMD0_DMA_REQ1 5 +#define DSCR_CMD0_DMA_REQ2 6 +#define DSCR_CMD0_DMA_REQ3 7 +#define DSCR_CMD0_USBDEV_RX0 8 +#define DSCR_CMD0_USBDEV_TX0 9 +#define DSCR_CMD0_USBDEV_TX1 10 +#define DSCR_CMD0_USBDEV_TX2 11 +#define DSCR_CMD0_USBDEV_RX3 12 +#define DSCR_CMD0_USBDEV_RX4 13 +#define DSCR_CMD0_PSC0_TX 14 +#define DSCR_CMD0_PSC0_RX 15 +#define DSCR_CMD0_PSC1_TX 16 +#define DSCR_CMD0_PSC1_RX 17 +#define DSCR_CMD0_PSC2_TX 18 +#define DSCR_CMD0_PSC2_RX 19 +#define DSCR_CMD0_PSC3_TX 20 +#define DSCR_CMD0_PSC3_RX 21 +#define DSCR_CMD0_PCI_WRITE 22 +#define DSCR_CMD0_NAND_FLASH 23 +#define DSCR_CMD0_MAC0_RX 24 +#define DSCR_CMD0_MAC0_TX 25 +#define DSCR_CMD0_MAC1_RX 26 +#define DSCR_CMD0_MAC1_TX 27 +#endif /* CONFIG_SOC_AU1550 */ + +#ifdef CONFIG_SOC_AU1200 +#define DSCR_CMD0_UART0_TX 0 +#define DSCR_CMD0_UART0_RX 1 +#define DSCR_CMD0_UART1_TX 2 +#define DSCR_CMD0_UART1_RX 3 +#define DSCR_CMD0_DMA_REQ0 4 +#define DSCR_CMD0_DMA_REQ1 5 +#define DSCR_CMD0_MAE_BE 6 +#define DSCR_CMD0_MAE_FE 7 +#define DSCR_CMD0_SDMS_TX0 8 +#define DSCR_CMD0_SDMS_RX0 9 +#define DSCR_CMD0_SDMS_TX1 10 +#define DSCR_CMD0_SDMS_RX1 11 +#define DSCR_CMD0_AES_TX 13 +#define DSCR_CMD0_AES_RX 12 +#define DSCR_CMD0_PSC0_TX 14 +#define DSCR_CMD0_PSC0_RX 15 +#define DSCR_CMD0_PSC1_TX 16 +#define DSCR_CMD0_PSC1_RX 17 +#define DSCR_CMD0_CIM_RXA 18 +#define DSCR_CMD0_CIM_RXB 19 +#define DSCR_CMD0_CIM_RXC 20 +#define DSCR_CMD0_MAE_BOTH 21 +#define DSCR_CMD0_LCD 22 +#define DSCR_CMD0_NAND_FLASH 23 +#define DSCR_CMD0_PSC0_SYNC 24 +#define DSCR_CMD0_PSC1_SYNC 25 +#define DSCR_CMD0_CIM_SYNC 26 +#endif /* CONFIG_SOC_AU1200 */ + +#define DSCR_CMD0_THROTTLE 30 +#define DSCR_CMD0_ALWAYS 31 +#define DSCR_NDEV_IDS 32 +/* This macro is used to find/create custom device types */ +#define DSCR_DEV2CUSTOM_ID(x, d) (((((x) & 0xFFFF) << 8) | 0x32000000) | \ + ((d) & 0xFF)) +#define DSCR_CUSTOM2DEV_ID(x) ((x) & 0xFF) + +#define DSCR_CMD0_SID(x) (((x) & 0x1f) << 25) +#define DSCR_CMD0_DID(x) (((x) & 0x1f) << 20) + +/* Source/Destination transfer width. */ +#define DSCR_CMD0_BYTE 0 +#define DSCR_CMD0_HALFWORD 1 +#define DSCR_CMD0_WORD 2 + +#define DSCR_CMD0_SW(x) (((x) & 0x3) << 18) +#define DSCR_CMD0_DW(x) (((x) & 0x3) << 16) + +/* DDMA Descriptor Type. */ +#define DSCR_CMD0_STANDARD 0 +#define DSCR_CMD0_LITERAL 1 +#define DSCR_CMD0_CMP_BRANCH 2 + +#define DSCR_CMD0_DT(x) (((x) & 0x3) << 13) + +/* Status Instruction. */ +#define DSCR_CMD0_ST_NOCHANGE 0 /* Don't change */ +#define DSCR_CMD0_ST_CURRENT 1 /* Write current status */ +#define DSCR_CMD0_ST_CMD0 2 /* Write cmd0 with V cleared */ +#define DSCR_CMD0_ST_BYTECNT 3 /* Write remaining byte count */ + +#define DSCR_CMD0_ST(x) (((x) & 0x3) << 0) + +/* Descriptor Command 1. */ +#define DSCR_CMD1_SUPTR_MASK (0xf << 28) /* upper 4 bits of src addr */ +#define DSCR_CMD1_DUPTR_MASK (0xf << 24) /* upper 4 bits of dest addr */ +#define DSCR_CMD1_FL_MASK (0x3 << 22) /* Flag bits */ +#define DSCR_CMD1_BC_MASK (0x3fffff) /* Byte count */ + +/* Flag description. */ +#define DSCR_CMD1_FL_MEM_STRIDE0 0 +#define DSCR_CMD1_FL_MEM_STRIDE1 1 +#define DSCR_CMD1_FL_MEM_STRIDE2 2 + +#define DSCR_CMD1_FL(x) (((x) & 0x3) << 22) + +/* Source1, 1-dimensional stride. */ +#define DSCR_SRC1_STS_MASK (3 << 30) /* Src xfer size */ +#define DSCR_SRC1_SAM_MASK (3 << 28) /* Src xfer movement */ +#define DSCR_SRC1_SB_MASK (0x3fff << 14) /* Block size */ +#define DSCR_SRC1_SB(x) (((x) & 0x3fff) << 14) +#define DSCR_SRC1_SS_MASK (0x3fff << 0) /* Stride */ +#define DSCR_SRC1_SS(x) (((x) & 0x3fff) << 0) + +/* Dest1, 1-dimensional stride. */ +#define DSCR_DEST1_DTS_MASK (3 << 30) /* Dest xfer size */ +#define DSCR_DEST1_DAM_MASK (3 << 28) /* Dest xfer movement */ +#define DSCR_DEST1_DB_MASK (0x3fff << 14) /* Block size */ +#define DSCR_DEST1_DB(x) (((x) & 0x3fff) << 14) +#define DSCR_DEST1_DS_MASK (0x3fff << 0) /* Stride */ +#define DSCR_DEST1_DS(x) (((x) & 0x3fff) << 0) + +#define DSCR_xTS_SIZE1 0 +#define DSCR_xTS_SIZE2 1 +#define DSCR_xTS_SIZE4 2 +#define DSCR_xTS_SIZE8 3 +#define DSCR_SRC1_STS(x) (((x) & 3) << 30) +#define DSCR_DEST1_DTS(x) (((x) & 3) << 30) + +#define DSCR_xAM_INCREMENT 0 +#define DSCR_xAM_DECREMENT 1 +#define DSCR_xAM_STATIC 2 +#define DSCR_xAM_BURST 3 +#define DSCR_SRC1_SAM(x) (((x) & 3) << 28) +#define DSCR_DEST1_DAM(x) (((x) & 3) << 28) + +/* The next descriptor pointer. */ +#define DSCR_NXTPTR_MASK (0x07ffffff) +#define DSCR_NXTPTR(x) ((x) >> 5) +#define DSCR_GET_NXTPTR(x) ((x) << 5) +#define DSCR_NXTPTR_MS (1 << 27) + +/* The number of DBDMA channels. */ +#define NUM_DBDMA_CHANS 16 + +/* + * DDMA API definitions + * FIXME: may not fit to this header file + */ +typedef struct dbdma_device_table { + u32 dev_id; + u32 dev_flags; + u32 dev_tsize; + u32 dev_devwidth; + u32 dev_physaddr; /* If FIFO */ + u32 dev_intlevel; + u32 dev_intpolarity; +} dbdev_tab_t; + + +typedef struct dbdma_chan_config { + spinlock_t lock; + + u32 chan_flags; + u32 chan_index; + dbdev_tab_t *chan_src; + dbdev_tab_t *chan_dest; + au1x_dma_chan_t *chan_ptr; + au1x_ddma_desc_t *chan_desc_base; + au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr; + void *chan_callparam; + void (*chan_callback)(int, void *); +} chan_tab_t; + +#define DEV_FLAGS_INUSE (1 << 0) +#define DEV_FLAGS_ANYUSE (1 << 1) +#define DEV_FLAGS_OUT (1 << 2) +#define DEV_FLAGS_IN (1 << 3) +#define DEV_FLAGS_BURSTABLE (1 << 4) +#define DEV_FLAGS_SYNC (1 << 5) +/* end DDMA API definitions */ + +/* + * External functions for drivers to use. + * Use this to allocate a DBDMA channel. The device IDs are one of + * the DSCR_CMD0 devices IDs, which is usually redefined to a more + * meaningful name. The 'callback' is called during DMA completion + * interrupt. + */ +extern u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, + void (*callback)(int, void *), + void *callparam); + +#define DBDMA_MEM_CHAN DSCR_CMD0_ALWAYS + +/* Set the device width of an in/out FIFO. */ +u32 au1xxx_dbdma_set_devwidth(u32 chanid, int bits); + +/* Allocate a ring of descriptors for DBDMA. */ +u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries); + +/* Put buffers on source/destination descriptors. */ +u32 _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags); +u32 _au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags); + +/* Get a buffer from the destination descriptor. */ +u32 au1xxx_dbdma_get_dest(u32 chanid, void **buf, int *nbytes); + +void au1xxx_dbdma_stop(u32 chanid); +void au1xxx_dbdma_start(u32 chanid); +void au1xxx_dbdma_reset(u32 chanid); +u32 au1xxx_get_dma_residue(u32 chanid); + +void au1xxx_dbdma_chan_free(u32 chanid); +void au1xxx_dbdma_dump(u32 chanid); + +u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr); + +u32 au1xxx_ddma_add_device(dbdev_tab_t *dev); +extern void au1xxx_ddma_del_device(u32 devid); +void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp); + +/* + * Some compatibilty macros -- needed to make changes to API + * without breaking existing drivers. + */ +#define au1xxx_dbdma_put_source(chanid, buf, nbytes) \ + _au1xxx_dbdma_put_source(chanid, buf, nbytes, DDMA_FLAGS_IE) +#define au1xxx_dbdma_put_source_flags(chanid, buf, nbytes, flags) \ + _au1xxx_dbdma_put_source(chanid, buf, nbytes, flags) +#define put_source_flags(chanid, buf, nbytes, flags) \ + au1xxx_dbdma_put_source_flags(chanid, buf, nbytes, flags) + +#define au1xxx_dbdma_put_dest(chanid, buf, nbytes) \ + _au1xxx_dbdma_put_dest(chanid, buf, nbytes, DDMA_FLAGS_IE) +#define au1xxx_dbdma_put_dest_flags(chanid, buf, nbytes, flags) \ + _au1xxx_dbdma_put_dest(chanid, buf, nbytes, flags) +#define put_dest_flags(chanid, buf, nbytes, flags) \ + au1xxx_dbdma_put_dest_flags(chanid, buf, nbytes, flags) + +/* + * Flags for the put_source/put_dest functions. + */ +#define DDMA_FLAGS_IE (1 << 0) +#define DDMA_FLAGS_NOIE (1 << 1) + +#endif /* _LANGUAGE_ASSEMBLY */ +#endif /* _AU1000_DBDMA_H_ */ diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h b/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h new file mode 100644 index 00000000000..60638b8969b --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h @@ -0,0 +1,194 @@ +/* + * include/asm-mips/mach-au1x00/au1xxx_ide.h version 01.30.00 Aug. 02 2005 + * + * BRIEF MODULE DESCRIPTION + * AMD Alchemy Au1xxx IDE interface routines over the Static Bus + * + * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE + * Interface and Linux Device Driver" Application Note. + */ + +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA +#define DMA_WAIT_TIMEOUT 100 +#define NUM_DESCRIPTORS PRD_ENTRIES +#else /* CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA */ +#define NUM_DESCRIPTORS 2 +#endif + +#ifndef AU1XXX_ATA_RQSIZE +#define AU1XXX_ATA_RQSIZE 128 +#endif + +/* Disable Burstable-Support for DBDMA */ +#ifndef CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON +#define CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON 0 +#endif + +#ifdef CONFIG_PM +/* + * This will enable the device to be powered up when write() or read() + * is called. If this is not defined, the driver will return -EBUSY. + */ +#define WAKE_ON_ACCESS 1 + +typedef struct { + spinlock_t lock; /* Used to block on state transitions */ + au1xxx_power_dev_t *dev; /* Power Managers device structure */ + unsigned stopped; /* Used to signal device is stopped */ +} pm_state; +#endif + +typedef struct { + u32 tx_dev_id, rx_dev_id, target_dev_id; + u32 tx_chan, rx_chan; + void *tx_desc_head, *rx_desc_head; + ide_hwif_t *hwif; +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + ide_drive_t *drive; + struct dbdma_cmd *dma_table_cpu; + dma_addr_t dma_table_dma; +#endif + int irq; + u32 regbase; +#ifdef CONFIG_PM + pm_state pm; +#endif +} _auide_hwif; + +/******************************************************************************/ +/* PIO Mode timing calculation : */ +/* */ +/* Static Bus Spec ATA Spec */ +/* Tcsoe = t1 */ +/* Toecs = t9 */ +/* Twcs = t9 */ +/* Tcsh = t2i | t2 */ +/* Tcsoff = t2i | t2 */ +/* Twp = t2 */ +/* Tcsw = t1 */ +/* Tpm = 0 */ +/* Ta = t1+t2 */ +/******************************************************************************/ + +#define TCSOE_MASK (0x07 << 29) +#define TOECS_MASK (0x07 << 26) +#define TWCS_MASK (0x07 << 28) +#define TCSH_MASK (0x0F << 24) +#define TCSOFF_MASK (0x07 << 20) +#define TWP_MASK (0x3F << 14) +#define TCSW_MASK (0x0F << 10) +#define TPM_MASK (0x0F << 6) +#define TA_MASK (0x3F << 0) +#define TS_MASK (1 << 8) + +/* Timing parameters PIO mode 0 */ +#define SBC_IDE_PIO0_TCSOE (0x04 << 29) +#define SBC_IDE_PIO0_TOECS (0x01 << 26) +#define SBC_IDE_PIO0_TWCS (0x02 << 28) +#define SBC_IDE_PIO0_TCSH (0x08 << 24) +#define SBC_IDE_PIO0_TCSOFF (0x07 << 20) +#define SBC_IDE_PIO0_TWP (0x10 << 14) +#define SBC_IDE_PIO0_TCSW (0x04 << 10) +#define SBC_IDE_PIO0_TPM (0x00 << 6) +#define SBC_IDE_PIO0_TA (0x15 << 0) +/* Timing parameters PIO mode 1 */ +#define SBC_IDE_PIO1_TCSOE (0x03 << 29) +#define SBC_IDE_PIO1_TOECS (0x01 << 26) +#define SBC_IDE_PIO1_TWCS (0x01 << 28) +#define SBC_IDE_PIO1_TCSH (0x06 << 24) +#define SBC_IDE_PIO1_TCSOFF (0x06 << 20) +#define SBC_IDE_PIO1_TWP (0x08 << 14) +#define SBC_IDE_PIO1_TCSW (0x03 << 10) +#define SBC_IDE_PIO1_TPM (0x00 << 6) +#define SBC_IDE_PIO1_TA (0x0B << 0) +/* Timing parameters PIO mode 2 */ +#define SBC_IDE_PIO2_TCSOE (0x05 << 29) +#define SBC_IDE_PIO2_TOECS (0x01 << 26) +#define SBC_IDE_PIO2_TWCS (0x01 << 28) +#define SBC_IDE_PIO2_TCSH (0x07 << 24) +#define SBC_IDE_PIO2_TCSOFF (0x07 << 20) +#define SBC_IDE_PIO2_TWP (0x1F << 14) +#define SBC_IDE_PIO2_TCSW (0x05 << 10) +#define SBC_IDE_PIO2_TPM (0x00 << 6) +#define SBC_IDE_PIO2_TA (0x22 << 0) +/* Timing parameters PIO mode 3 */ +#define SBC_IDE_PIO3_TCSOE (0x05 << 29) +#define SBC_IDE_PIO3_TOECS (0x01 << 26) +#define SBC_IDE_PIO3_TWCS (0x01 << 28) +#define SBC_IDE_PIO3_TCSH (0x0D << 24) +#define SBC_IDE_PIO3_TCSOFF (0x0D << 20) +#define SBC_IDE_PIO3_TWP (0x15 << 14) +#define SBC_IDE_PIO3_TCSW (0x05 << 10) +#define SBC_IDE_PIO3_TPM (0x00 << 6) +#define SBC_IDE_PIO3_TA (0x1A << 0) +/* Timing parameters PIO mode 4 */ +#define SBC_IDE_PIO4_TCSOE (0x04 << 29) +#define SBC_IDE_PIO4_TOECS (0x01 << 26) +#define SBC_IDE_PIO4_TWCS (0x01 << 28) +#define SBC_IDE_PIO4_TCSH (0x04 << 24) +#define SBC_IDE_PIO4_TCSOFF (0x04 << 20) +#define SBC_IDE_PIO4_TWP (0x0D << 14) +#define SBC_IDE_PIO4_TCSW (0x03 << 10) +#define SBC_IDE_PIO4_TPM (0x00 << 6) +#define SBC_IDE_PIO4_TA (0x12 << 0) +/* Timing parameters MDMA mode 0 */ +#define SBC_IDE_MDMA0_TCSOE (0x03 << 29) +#define SBC_IDE_MDMA0_TOECS (0x01 << 26) +#define SBC_IDE_MDMA0_TWCS (0x01 << 28) +#define SBC_IDE_MDMA0_TCSH (0x07 << 24) +#define SBC_IDE_MDMA0_TCSOFF (0x07 << 20) +#define SBC_IDE_MDMA0_TWP (0x0C << 14) +#define SBC_IDE_MDMA0_TCSW (0x03 << 10) +#define SBC_IDE_MDMA0_TPM (0x00 << 6) +#define SBC_IDE_MDMA0_TA (0x0F << 0) +/* Timing parameters MDMA mode 1 */ +#define SBC_IDE_MDMA1_TCSOE (0x05 << 29) +#define SBC_IDE_MDMA1_TOECS (0x01 << 26) +#define SBC_IDE_MDMA1_TWCS (0x01 << 28) +#define SBC_IDE_MDMA1_TCSH (0x05 << 24) +#define SBC_IDE_MDMA1_TCSOFF (0x05 << 20) +#define SBC_IDE_MDMA1_TWP (0x0F << 14) +#define SBC_IDE_MDMA1_TCSW (0x05 << 10) +#define SBC_IDE_MDMA1_TPM (0x00 << 6) +#define SBC_IDE_MDMA1_TA (0x15 << 0) +/* Timing parameters MDMA mode 2 */ +#define SBC_IDE_MDMA2_TCSOE (0x04 << 29) +#define SBC_IDE_MDMA2_TOECS (0x01 << 26) +#define SBC_IDE_MDMA2_TWCS (0x01 << 28) +#define SBC_IDE_MDMA2_TCSH (0x04 << 24) +#define SBC_IDE_MDMA2_TCSOFF (0x04 << 20) +#define SBC_IDE_MDMA2_TWP (0x0D << 14) +#define SBC_IDE_MDMA2_TCSW (0x04 << 10) +#define SBC_IDE_MDMA2_TPM (0x00 << 6) +#define SBC_IDE_MDMA2_TA (0x12 << 0) + +#define SBC_IDE_TIMING(mode) \ + (SBC_IDE_##mode##_TWCS | \ + SBC_IDE_##mode##_TCSH | \ + SBC_IDE_##mode##_TCSOFF | \ + SBC_IDE_##mode##_TWP | \ + SBC_IDE_##mode##_TCSW | \ + SBC_IDE_##mode##_TPM | \ + SBC_IDE_##mode##_TA) diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h b/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h new file mode 100644 index 00000000000..892b7f168eb --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h @@ -0,0 +1,505 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Include file for Alchemy Semiconductor's Au1k CPU. + * + * Copyright 2004 Embedded Edge, LLC + * dan@embeddededge.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Specifics for the Au1xxx Programmable Serial Controllers, first + * seen in the AU1550 part. + */ +#ifndef _AU1000_PSC_H_ +#define _AU1000_PSC_H_ + +/* The PSC base addresses. */ +#ifdef CONFIG_SOC_AU1550 +#define PSC0_BASE_ADDR 0xb1a00000 +#define PSC1_BASE_ADDR 0xb1b00000 +#define PSC2_BASE_ADDR 0xb0a00000 +#define PSC3_BASE_ADDR 0xb0b00000 +#endif + +#ifdef CONFIG_SOC_AU1200 +#define PSC0_BASE_ADDR 0xb1a00000 +#define PSC1_BASE_ADDR 0xb1b00000 +#endif + +/* + * The PSC select and control registers are common to all protocols. + */ +#define PSC_SEL_OFFSET 0x00000000 +#define PSC_CTRL_OFFSET 0x00000004 + +#define PSC_SEL_CLK_MASK (3 << 4) +#define PSC_SEL_CLK_INTCLK (0 << 4) +#define PSC_SEL_CLK_EXTCLK (1 << 4) +#define PSC_SEL_CLK_SERCLK (2 << 4) + +#define PSC_SEL_PS_MASK 0x00000007 +#define PSC_SEL_PS_DISABLED 0 +#define PSC_SEL_PS_SPIMODE 2 +#define PSC_SEL_PS_I2SMODE 3 +#define PSC_SEL_PS_AC97MODE 4 +#define PSC_SEL_PS_SMBUSMODE 5 + +#define PSC_CTRL_DISABLE 0 +#define PSC_CTRL_SUSPEND 2 +#define PSC_CTRL_ENABLE 3 + +/* AC97 Registers. */ +#define PSC_AC97CFG_OFFSET 0x00000008 +#define PSC_AC97MSK_OFFSET 0x0000000c +#define PSC_AC97PCR_OFFSET 0x00000010 +#define PSC_AC97STAT_OFFSET 0x00000014 +#define PSC_AC97EVNT_OFFSET 0x00000018 +#define PSC_AC97TXRX_OFFSET 0x0000001c +#define PSC_AC97CDC_OFFSET 0x00000020 +#define PSC_AC97RST_OFFSET 0x00000024 +#define PSC_AC97GPO_OFFSET 0x00000028 +#define PSC_AC97GPI_OFFSET 0x0000002c + +#define AC97_PSC_SEL (AC97_PSC_BASE + PSC_SEL_OFFSET) +#define AC97_PSC_CTRL (AC97_PSC_BASE + PSC_CTRL_OFFSET) +#define PSC_AC97CFG (AC97_PSC_BASE + PSC_AC97CFG_OFFSET) +#define PSC_AC97MSK (AC97_PSC_BASE + PSC_AC97MSK_OFFSET) +#define PSC_AC97PCR (AC97_PSC_BASE + PSC_AC97PCR_OFFSET) +#define PSC_AC97STAT (AC97_PSC_BASE + PSC_AC97STAT_OFFSET) +#define PSC_AC97EVNT (AC97_PSC_BASE + PSC_AC97EVNT_OFFSET) +#define PSC_AC97TXRX (AC97_PSC_BASE + PSC_AC97TXRX_OFFSET) +#define PSC_AC97CDC (AC97_PSC_BASE + PSC_AC97CDC_OFFSET) +#define PSC_AC97RST (AC97_PSC_BASE + PSC_AC97RST_OFFSET) +#define PSC_AC97GPO (AC97_PSC_BASE + PSC_AC97GPO_OFFSET) +#define PSC_AC97GPI (AC97_PSC_BASE + PSC_AC97GPI_OFFSET) + +/* AC97 Config Register. */ +#define PSC_AC97CFG_RT_MASK (3 << 30) +#define PSC_AC97CFG_RT_FIFO1 (0 << 30) +#define PSC_AC97CFG_RT_FIFO2 (1 << 30) +#define PSC_AC97CFG_RT_FIFO4 (2 << 30) +#define PSC_AC97CFG_RT_FIFO8 (3 << 30) + +#define PSC_AC97CFG_TT_MASK (3 << 28) +#define PSC_AC97CFG_TT_FIFO1 (0 << 28) +#define PSC_AC97CFG_TT_FIFO2 (1 << 28) +#define PSC_AC97CFG_TT_FIFO4 (2 << 28) +#define PSC_AC97CFG_TT_FIFO8 (3 << 28) + +#define PSC_AC97CFG_DD_DISABLE (1 << 27) +#define PSC_AC97CFG_DE_ENABLE (1 << 26) +#define PSC_AC97CFG_SE_ENABLE (1 << 25) + +#define PSC_AC97CFG_LEN_MASK (0xf << 21) +#define PSC_AC97CFG_TXSLOT_MASK (0x3ff << 11) +#define PSC_AC97CFG_RXSLOT_MASK (0x3ff << 1) +#define PSC_AC97CFG_GE_ENABLE (1) + +/* Enable slots 3-12. */ +#define PSC_AC97CFG_TXSLOT_ENA(x) (1 << (((x) - 3) + 11)) +#define PSC_AC97CFG_RXSLOT_ENA(x) (1 << (((x) - 3) + 1)) + +/* + * The word length equation is ((x) * 2) + 2, so choose 'x' appropriately. + * The only sensible numbers are 7, 9, or possibly 11. Nah, just do the + * arithmetic in the macro. + */ +#define PSC_AC97CFG_SET_LEN(x) (((((x) - 2) / 2) & 0xf) << 21) +#define PSC_AC97CFG_GET_LEN(x) (((((x) >> 21) & 0xf) * 2) + 2) + +/* AC97 Mask Register. */ +#define PSC_AC97MSK_GR (1 << 25) +#define PSC_AC97MSK_CD (1 << 24) +#define PSC_AC97MSK_RR (1 << 13) +#define PSC_AC97MSK_RO (1 << 12) +#define PSC_AC97MSK_RU (1 << 11) +#define PSC_AC97MSK_TR (1 << 10) +#define PSC_AC97MSK_TO (1 << 9) +#define PSC_AC97MSK_TU (1 << 8) +#define PSC_AC97MSK_RD (1 << 5) +#define PSC_AC97MSK_TD (1 << 4) +#define PSC_AC97MSK_ALLMASK (PSC_AC97MSK_GR | PSC_AC97MSK_CD | \ + PSC_AC97MSK_RR | PSC_AC97MSK_RO | \ + PSC_AC97MSK_RU | PSC_AC97MSK_TR | \ + PSC_AC97MSK_TO | PSC_AC97MSK_TU | \ + PSC_AC97MSK_RD | PSC_AC97MSK_TD) + +/* AC97 Protocol Control Register. */ +#define PSC_AC97PCR_RC (1 << 6) +#define PSC_AC97PCR_RP (1 << 5) +#define PSC_AC97PCR_RS (1 << 4) +#define PSC_AC97PCR_TC (1 << 2) +#define PSC_AC97PCR_TP (1 << 1) +#define PSC_AC97PCR_TS (1 << 0) + +/* AC97 Status register (read only). */ +#define PSC_AC97STAT_CB (1 << 26) +#define PSC_AC97STAT_CP (1 << 25) +#define PSC_AC97STAT_CR (1 << 24) +#define PSC_AC97STAT_RF (1 << 13) +#define PSC_AC97STAT_RE (1 << 12) +#define PSC_AC97STAT_RR (1 << 11) +#define PSC_AC97STAT_TF (1 << 10) +#define PSC_AC97STAT_TE (1 << 9) +#define PSC_AC97STAT_TR (1 << 8) +#define PSC_AC97STAT_RB (1 << 5) +#define PSC_AC97STAT_TB (1 << 4) +#define PSC_AC97STAT_DI (1 << 2) +#define PSC_AC97STAT_DR (1 << 1) +#define PSC_AC97STAT_SR (1 << 0) + +/* AC97 Event Register. */ +#define PSC_AC97EVNT_GR (1 << 25) +#define PSC_AC97EVNT_CD (1 << 24) +#define PSC_AC97EVNT_RR (1 << 13) +#define PSC_AC97EVNT_RO (1 << 12) +#define PSC_AC97EVNT_RU (1 << 11) +#define PSC_AC97EVNT_TR (1 << 10) +#define PSC_AC97EVNT_TO (1 << 9) +#define PSC_AC97EVNT_TU (1 << 8) +#define PSC_AC97EVNT_RD (1 << 5) +#define PSC_AC97EVNT_TD (1 << 4) + +/* CODEC Command Register. */ +#define PSC_AC97CDC_RD (1 << 25) +#define PSC_AC97CDC_ID_MASK (3 << 23) +#define PSC_AC97CDC_INDX_MASK (0x7f << 16) +#define PSC_AC97CDC_ID(x) (((x) & 0x03) << 23) +#define PSC_AC97CDC_INDX(x) (((x) & 0x7f) << 16) + +/* AC97 Reset Control Register. */ +#define PSC_AC97RST_RST (1 << 1) +#define PSC_AC97RST_SNC (1 << 0) + +/* PSC in I2S Mode. */ +typedef struct psc_i2s { + u32 psc_sel; + u32 psc_ctrl; + u32 psc_i2scfg; + u32 psc_i2smsk; + u32 psc_i2spcr; + u32 psc_i2sstat; + u32 psc_i2sevent; + u32 psc_i2stxrx; + u32 psc_i2sudf; +} psc_i2s_t; + +#define PSC_I2SCFG_OFFSET 0x08 +#define PSC_I2SMASK_OFFSET 0x0C +#define PSC_I2SPCR_OFFSET 0x10 +#define PSC_I2SSTAT_OFFSET 0x14 +#define PSC_I2SEVENT_OFFSET 0x18 +#define PSC_I2SRXTX_OFFSET 0x1C +#define PSC_I2SUDF_OFFSET 0x20 + +/* I2S Config Register. */ +#define PSC_I2SCFG_RT_MASK (3 << 30) +#define PSC_I2SCFG_RT_FIFO1 (0 << 30) +#define PSC_I2SCFG_RT_FIFO2 (1 << 30) +#define PSC_I2SCFG_RT_FIFO4 (2 << 30) +#define PSC_I2SCFG_RT_FIFO8 (3 << 30) + +#define PSC_I2SCFG_TT_MASK (3 << 28) +#define PSC_I2SCFG_TT_FIFO1 (0 << 28) +#define PSC_I2SCFG_TT_FIFO2 (1 << 28) +#define PSC_I2SCFG_TT_FIFO4 (2 << 28) +#define PSC_I2SCFG_TT_FIFO8 (3 << 28) + +#define PSC_I2SCFG_DD_DISABLE (1 << 27) +#define PSC_I2SCFG_DE_ENABLE (1 << 26) +#define PSC_I2SCFG_SET_WS(x) (((((x) / 2) - 1) & 0x7f) << 16) +#define PSC_I2SCFG_WS(n) ((n & 0xFF) << 16) +#define PSC_I2SCFG_WS_MASK (PSC_I2SCFG_WS(0x3F)) +#define PSC_I2SCFG_WI (1 << 15) + +#define PSC_I2SCFG_DIV_MASK (3 << 13) +#define PSC_I2SCFG_DIV2 (0 << 13) +#define PSC_I2SCFG_DIV4 (1 << 13) +#define PSC_I2SCFG_DIV8 (2 << 13) +#define PSC_I2SCFG_DIV16 (3 << 13) + +#define PSC_I2SCFG_BI (1 << 12) +#define PSC_I2SCFG_BUF (1 << 11) +#define PSC_I2SCFG_MLJ (1 << 10) +#define PSC_I2SCFG_XM (1 << 9) + +/* The word length equation is simply LEN+1. */ +#define PSC_I2SCFG_SET_LEN(x) ((((x) - 1) & 0x1f) << 4) +#define PSC_I2SCFG_GET_LEN(x) ((((x) >> 4) & 0x1f) + 1) + +#define PSC_I2SCFG_LB (1 << 2) +#define PSC_I2SCFG_MLF (1 << 1) +#define PSC_I2SCFG_MS (1 << 0) + +/* I2S Mask Register. */ +#define PSC_I2SMSK_RR (1 << 13) +#define PSC_I2SMSK_RO (1 << 12) +#define PSC_I2SMSK_RU (1 << 11) +#define PSC_I2SMSK_TR (1 << 10) +#define PSC_I2SMSK_TO (1 << 9) +#define PSC_I2SMSK_TU (1 << 8) +#define PSC_I2SMSK_RD (1 << 5) +#define PSC_I2SMSK_TD (1 << 4) +#define PSC_I2SMSK_ALLMASK (PSC_I2SMSK_RR | PSC_I2SMSK_RO | \ + PSC_I2SMSK_RU | PSC_I2SMSK_TR | \ + PSC_I2SMSK_TO | PSC_I2SMSK_TU | \ + PSC_I2SMSK_RD | PSC_I2SMSK_TD) + +/* I2S Protocol Control Register. */ +#define PSC_I2SPCR_RC (1 << 6) +#define PSC_I2SPCR_RP (1 << 5) +#define PSC_I2SPCR_RS (1 << 4) +#define PSC_I2SPCR_TC (1 << 2) +#define PSC_I2SPCR_TP (1 << 1) +#define PSC_I2SPCR_TS (1 << 0) + +/* I2S Status register (read only). */ +#define PSC_I2SSTAT_RF (1 << 13) +#define PSC_I2SSTAT_RE (1 << 12) +#define PSC_I2SSTAT_RR (1 << 11) +#define PSC_I2SSTAT_TF (1 << 10) +#define PSC_I2SSTAT_TE (1 << 9) +#define PSC_I2SSTAT_TR (1 << 8) +#define PSC_I2SSTAT_RB (1 << 5) +#define PSC_I2SSTAT_TB (1 << 4) +#define PSC_I2SSTAT_DI (1 << 2) +#define PSC_I2SSTAT_DR (1 << 1) +#define PSC_I2SSTAT_SR (1 << 0) + +/* I2S Event Register. */ +#define PSC_I2SEVNT_RR (1 << 13) +#define PSC_I2SEVNT_RO (1 << 12) +#define PSC_I2SEVNT_RU (1 << 11) +#define PSC_I2SEVNT_TR (1 << 10) +#define PSC_I2SEVNT_TO (1 << 9) +#define PSC_I2SEVNT_TU (1 << 8) +#define PSC_I2SEVNT_RD (1 << 5) +#define PSC_I2SEVNT_TD (1 << 4) + +/* PSC in SPI Mode. */ +typedef struct psc_spi { + u32 psc_sel; + u32 psc_ctrl; + u32 psc_spicfg; + u32 psc_spimsk; + u32 psc_spipcr; + u32 psc_spistat; + u32 psc_spievent; + u32 psc_spitxrx; +} psc_spi_t; + +/* SPI Config Register. */ +#define PSC_SPICFG_RT_MASK (3 << 30) +#define PSC_SPICFG_RT_FIFO1 (0 << 30) +#define PSC_SPICFG_RT_FIFO2 (1 << 30) +#define PSC_SPICFG_RT_FIFO4 (2 << 30) +#define PSC_SPICFG_RT_FIFO8 (3 << 30) + +#define PSC_SPICFG_TT_MASK (3 << 28) +#define PSC_SPICFG_TT_FIFO1 (0 << 28) +#define PSC_SPICFG_TT_FIFO2 (1 << 28) +#define PSC_SPICFG_TT_FIFO4 (2 << 28) +#define PSC_SPICFG_TT_FIFO8 (3 << 28) + +#define PSC_SPICFG_DD_DISABLE (1 << 27) +#define PSC_SPICFG_DE_ENABLE (1 << 26) +#define PSC_SPICFG_CLR_BAUD(x) ((x) & ~((0x3f) << 15)) +#define PSC_SPICFG_SET_BAUD(x) (((x) & 0x3f) << 15) + +#define PSC_SPICFG_SET_DIV(x) (((x) & 0x03) << 13) +#define PSC_SPICFG_DIV2 0 +#define PSC_SPICFG_DIV4 1 +#define PSC_SPICFG_DIV8 2 +#define PSC_SPICFG_DIV16 3 + +#define PSC_SPICFG_BI (1 << 12) +#define PSC_SPICFG_PSE (1 << 11) +#define PSC_SPICFG_CGE (1 << 10) +#define PSC_SPICFG_CDE (1 << 9) + +#define PSC_SPICFG_CLR_LEN(x) ((x) & ~((0x1f) << 4)) +#define PSC_SPICFG_SET_LEN(x) (((x-1) & 0x1f) << 4) + +#define PSC_SPICFG_LB (1 << 3) +#define PSC_SPICFG_MLF (1 << 1) +#define PSC_SPICFG_MO (1 << 0) + +/* SPI Mask Register. */ +#define PSC_SPIMSK_MM (1 << 16) +#define PSC_SPIMSK_RR (1 << 13) +#define PSC_SPIMSK_RO (1 << 12) +#define PSC_SPIMSK_RU (1 << 11) +#define PSC_SPIMSK_TR (1 << 10) +#define PSC_SPIMSK_TO (1 << 9) +#define PSC_SPIMSK_TU (1 << 8) +#define PSC_SPIMSK_SD (1 << 5) +#define PSC_SPIMSK_MD (1 << 4) +#define PSC_SPIMSK_ALLMASK (PSC_SPIMSK_MM | PSC_SPIMSK_RR | \ + PSC_SPIMSK_RO | PSC_SPIMSK_TO | \ + PSC_SPIMSK_TU | PSC_SPIMSK_SD | \ + PSC_SPIMSK_MD) + +/* SPI Protocol Control Register. */ +#define PSC_SPIPCR_RC (1 << 6) +#define PSC_SPIPCR_SP (1 << 5) +#define PSC_SPIPCR_SS (1 << 4) +#define PSC_SPIPCR_TC (1 << 2) +#define PSC_SPIPCR_MS (1 << 0) + +/* SPI Status register (read only). */ +#define PSC_SPISTAT_RF (1 << 13) +#define PSC_SPISTAT_RE (1 << 12) +#define PSC_SPISTAT_RR (1 << 11) +#define PSC_SPISTAT_TF (1 << 10) +#define PSC_SPISTAT_TE (1 << 9) +#define PSC_SPISTAT_TR (1 << 8) +#define PSC_SPISTAT_SB (1 << 5) +#define PSC_SPISTAT_MB (1 << 4) +#define PSC_SPISTAT_DI (1 << 2) +#define PSC_SPISTAT_DR (1 << 1) +#define PSC_SPISTAT_SR (1 << 0) + +/* SPI Event Register. */ +#define PSC_SPIEVNT_MM (1 << 16) +#define PSC_SPIEVNT_RR (1 << 13) +#define PSC_SPIEVNT_RO (1 << 12) +#define PSC_SPIEVNT_RU (1 << 11) +#define PSC_SPIEVNT_TR (1 << 10) +#define PSC_SPIEVNT_TO (1 << 9) +#define PSC_SPIEVNT_TU (1 << 8) +#define PSC_SPIEVNT_SD (1 << 5) +#define PSC_SPIEVNT_MD (1 << 4) + +/* Transmit register control. */ +#define PSC_SPITXRX_LC (1 << 29) +#define PSC_SPITXRX_SR (1 << 28) + +/* PSC in SMBus (I2C) Mode. */ +typedef struct psc_smb { + u32 psc_sel; + u32 psc_ctrl; + u32 psc_smbcfg; + u32 psc_smbmsk; + u32 psc_smbpcr; + u32 psc_smbstat; + u32 psc_smbevnt; + u32 psc_smbtxrx; + u32 psc_smbtmr; +} psc_smb_t; + +/* SMBus Config Register. */ +#define PSC_SMBCFG_RT_MASK (3 << 30) +#define PSC_SMBCFG_RT_FIFO1 (0 << 30) +#define PSC_SMBCFG_RT_FIFO2 (1 << 30) +#define PSC_SMBCFG_RT_FIFO4 (2 << 30) +#define PSC_SMBCFG_RT_FIFO8 (3 << 30) + +#define PSC_SMBCFG_TT_MASK (3 << 28) +#define PSC_SMBCFG_TT_FIFO1 (0 << 28) +#define PSC_SMBCFG_TT_FIFO2 (1 << 28) +#define PSC_SMBCFG_TT_FIFO4 (2 << 28) +#define PSC_SMBCFG_TT_FIFO8 (3 << 28) + +#define PSC_SMBCFG_DD_DISABLE (1 << 27) +#define PSC_SMBCFG_DE_ENABLE (1 << 26) + +#define PSC_SMBCFG_SET_DIV(x) (((x) & 0x03) << 13) +#define PSC_SMBCFG_DIV2 0 +#define PSC_SMBCFG_DIV4 1 +#define PSC_SMBCFG_DIV8 2 +#define PSC_SMBCFG_DIV16 3 + +#define PSC_SMBCFG_GCE (1 << 9) +#define PSC_SMBCFG_SFM (1 << 8) + +#define PSC_SMBCFG_SET_SLV(x) (((x) & 0x7f) << 1) + +/* SMBus Mask Register. */ +#define PSC_SMBMSK_DN (1 << 30) +#define PSC_SMBMSK_AN (1 << 29) +#define PSC_SMBMSK_AL (1 << 28) +#define PSC_SMBMSK_RR (1 << 13) +#define PSC_SMBMSK_RO (1 << 12) +#define PSC_SMBMSK_RU (1 << 11) +#define PSC_SMBMSK_TR (1 << 10) +#define PSC_SMBMSK_TO (1 << 9) +#define PSC_SMBMSK_TU (1 << 8) +#define PSC_SMBMSK_SD (1 << 5) +#define PSC_SMBMSK_MD (1 << 4) +#define PSC_SMBMSK_ALLMASK (PSC_SMBMSK_DN | PSC_SMBMSK_AN | \ + PSC_SMBMSK_AL | PSC_SMBMSK_RR | \ + PSC_SMBMSK_RO | PSC_SMBMSK_TO | \ + PSC_SMBMSK_TU | PSC_SMBMSK_SD | \ + PSC_SMBMSK_MD) + +/* SMBus Protocol Control Register. */ +#define PSC_SMBPCR_DC (1 << 2) +#define PSC_SMBPCR_MS (1 << 0) + +/* SMBus Status register (read only). */ +#define PSC_SMBSTAT_BB (1 << 28) +#define PSC_SMBSTAT_RF (1 << 13) +#define PSC_SMBSTAT_RE (1 << 12) +#define PSC_SMBSTAT_RR (1 << 11) +#define PSC_SMBSTAT_TF (1 << 10) +#define PSC_SMBSTAT_TE (1 << 9) +#define PSC_SMBSTAT_TR (1 << 8) +#define PSC_SMBSTAT_SB (1 << 5) +#define PSC_SMBSTAT_MB (1 << 4) +#define PSC_SMBSTAT_DI (1 << 2) +#define PSC_SMBSTAT_DR (1 << 1) +#define PSC_SMBSTAT_SR (1 << 0) + +/* SMBus Event Register. */ +#define PSC_SMBEVNT_DN (1 << 30) +#define PSC_SMBEVNT_AN (1 << 29) +#define PSC_SMBEVNT_AL (1 << 28) +#define PSC_SMBEVNT_RR (1 << 13) +#define PSC_SMBEVNT_RO (1 << 12) +#define PSC_SMBEVNT_RU (1 << 11) +#define PSC_SMBEVNT_TR (1 << 10) +#define PSC_SMBEVNT_TO (1 << 9) +#define PSC_SMBEVNT_TU (1 << 8) +#define PSC_SMBEVNT_SD (1 << 5) +#define PSC_SMBEVNT_MD (1 << 4) +#define PSC_SMBEVNT_ALLCLR (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | \ + PSC_SMBEVNT_AL | PSC_SMBEVNT_RR | \ + PSC_SMBEVNT_RO | PSC_SMBEVNT_TO | \ + PSC_SMBEVNT_TU | PSC_SMBEVNT_SD | \ + PSC_SMBEVNT_MD) + +/* Transmit register control. */ +#define PSC_SMBTXRX_RSR (1 << 28) +#define PSC_SMBTXRX_STP (1 << 29) +#define PSC_SMBTXRX_DATAMASK 0xff + +/* SMBus protocol timers register. */ +#define PSC_SMBTMR_SET_TH(x) (((x) & 0x03) << 30) +#define PSC_SMBTMR_SET_PS(x) (((x) & 0x1f) << 25) +#define PSC_SMBTMR_SET_PU(x) (((x) & 0x1f) << 20) +#define PSC_SMBTMR_SET_SH(x) (((x) & 0x1f) << 15) +#define PSC_SMBTMR_SET_SU(x) (((x) & 0x1f) << 10) +#define PSC_SMBTMR_SET_CL(x) (((x) & 0x1f) << 5) +#define PSC_SMBTMR_SET_CH(x) (((x) & 0x1f) << 0) + +#endif /* _AU1000_PSC_H_ */ diff --git a/arch/mips/include/asm/mach-au1x00/gpio.h b/arch/mips/include/asm/mach-au1x00/gpio.h new file mode 100644 index 00000000000..2dc61e009a0 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/gpio.h @@ -0,0 +1,69 @@ +#ifndef _AU1XXX_GPIO_H_ +#define _AU1XXX_GPIO_H_ + +#include + +#define AU1XXX_GPIO_BASE 200 + +struct au1x00_gpio2 { + u32 dir; + u32 reserved; + u32 output; + u32 pinstate; + u32 inten; + u32 enable; +}; + +extern int au1xxx_gpio_get_value(unsigned gpio); +extern void au1xxx_gpio_set_value(unsigned gpio, int value); +extern int au1xxx_gpio_direction_input(unsigned gpio); +extern int au1xxx_gpio_direction_output(unsigned gpio, int value); + + +/* Wrappers for the arch-neutral GPIO API */ + +static inline int gpio_request(unsigned gpio, const char *label) +{ + /* Not yet implemented */ + return 0; +} + +static inline void gpio_free(unsigned gpio) +{ + /* Not yet implemented */ +} + +static inline int gpio_direction_input(unsigned gpio) +{ + return au1xxx_gpio_direction_input(gpio); +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return au1xxx_gpio_direction_output(gpio, value); +} + +static inline int gpio_get_value(unsigned gpio) +{ + return au1xxx_gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + au1xxx_gpio_set_value(gpio, value); +} + +static inline int gpio_to_irq(unsigned gpio) +{ + return gpio; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return irq; +} + +/* For cansleep */ +#include + +#endif /* _AU1XXX_GPIO_H_ */ diff --git a/arch/mips/include/asm/mach-au1x00/ioremap.h b/arch/mips/include/asm/mach-au1x00/ioremap.h new file mode 100644 index 00000000000..364cea2dc71 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/ioremap.h @@ -0,0 +1,42 @@ +/* + * include/asm-mips/mach-au1x00/ioremap.h + * + * 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. + */ +#ifndef __ASM_MACH_AU1X00_IOREMAP_H +#define __ASM_MACH_AU1X00_IOREMAP_H + +#include + +#ifdef CONFIG_64BIT_PHYS_ADDR +extern phys_t __fixup_bigphys_addr(phys_t, phys_t); +#else +static inline phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + return phys_addr; +} +#endif + +/* + * Allow physical addresses to be fixed up to help 36-bit peripherals. + */ +static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + return __fixup_bigphys_addr(phys_addr, size); +} + +static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, + unsigned long flags) +{ + return NULL; +} + +static inline int plat_iounmap(const volatile void __iomem *addr) +{ + return 0; +} + +#endif /* __ASM_MACH_AU1X00_IOREMAP_H */ diff --git a/arch/mips/include/asm/mach-au1x00/prom.h b/arch/mips/include/asm/mach-au1x00/prom.h new file mode 100644 index 00000000000..e38715577c5 --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/prom.h @@ -0,0 +1,13 @@ +#ifndef __AU1X00_PROM_H +#define __AU1X00_PROM_H + +extern int prom_argc; +extern char **prom_argv; +extern char **prom_envp; + +extern void prom_init_cmdline(void); +extern char *prom_getcmdline(void); +extern char *prom_getenv(char *envname); +extern int prom_get_ethernet_addr(char *ethernet_addr); + +#endif diff --git a/arch/mips/include/asm/mach-au1x00/war.h b/arch/mips/include/asm/mach-au1x00/war.h new file mode 100644 index 00000000000..dd57d03d68b --- /dev/null +++ b/arch/mips/include/asm/mach-au1x00/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_AU1X00_WAR_H +#define __ASM_MIPS_MACH_AU1X00_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_AU1X00_WAR_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h new file mode 100644 index 00000000000..d008f47a28b --- /dev/null +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2007 Aurelien Jarno + * + * 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_BCM47XX_H +#define __ASM_BCM47XX_H + +/* SSB bus */ +extern struct ssb_bus ssb_bcm47xx; + +#endif /* __ASM_BCM47XX_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h new file mode 100644 index 00000000000..cfc8f4d618c --- /dev/null +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h @@ -0,0 +1,59 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 Aurelien Jarno + */ + +#ifndef __BCM47XX_GPIO_H +#define __BCM47XX_GPIO_H + +#define BCM47XX_EXTIF_GPIO_LINES 5 +#define BCM47XX_CHIPCO_GPIO_LINES 16 + +extern int bcm47xx_gpio_to_irq(unsigned gpio); +extern int bcm47xx_gpio_get_value(unsigned gpio); +extern void bcm47xx_gpio_set_value(unsigned gpio, int value); +extern int bcm47xx_gpio_direction_input(unsigned gpio); +extern int bcm47xx_gpio_direction_output(unsigned gpio, int value); + +static inline int gpio_request(unsigned gpio, const char *label) +{ + return 0; +} + +static inline void gpio_free(unsigned gpio) +{ +} + +static inline int gpio_to_irq(unsigned gpio) +{ + return bcm47xx_gpio_to_irq(gpio); +} + +static inline int gpio_get_value(unsigned gpio) +{ + return bcm47xx_gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + bcm47xx_gpio_set_value(gpio, value); +} + +static inline int gpio_direction_input(unsigned gpio) +{ + return bcm47xx_gpio_direction_input(gpio); +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return bcm47xx_gpio_direction_output(gpio, value); +} + + +/* cansleep wrappers */ +#include + +#endif /* __BCM47XX_GPIO_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/war.h b/arch/mips/include/asm/mach-bcm47xx/war.h new file mode 100644 index 00000000000..4a2b7986b58 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm47xx/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_BCM947XX_WAR_H +#define __ASM_MIPS_MACH_BCM947XX_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_BCM947XX_WAR_H */ diff --git a/arch/mips/include/asm/mach-cobalt/cobalt.h b/arch/mips/include/asm/mach-cobalt/cobalt.h new file mode 100644 index 00000000000..5b9fce73f11 --- /dev/null +++ b/arch/mips/include/asm/mach-cobalt/cobalt.h @@ -0,0 +1,22 @@ +/* + * The Cobalt board ID information. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997 Cobalt Microserver + * Copyright (C) 1997, 2003 Ralf Baechle + * Copyright (C) 2001, 2002, 2003 Liam Davies (ldavies@agile.tv) + */ +#ifndef __ASM_COBALT_H +#define __ASM_COBALT_H + +extern int cobalt_board_id; + +#define COBALT_BRD_ID_QUBE1 0x3 +#define COBALT_BRD_ID_RAQ1 0x4 +#define COBALT_BRD_ID_QUBE2 0x5 +#define COBALT_BRD_ID_RAQ2 0x6 + +#endif /* __ASM_COBALT_H */ diff --git a/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h new file mode 100644 index 00000000000..b3314cf5319 --- /dev/null +++ b/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h @@ -0,0 +1,56 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006, 07 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_COBALT_CPU_FEATURE_OVERRIDES_H +#define __ASM_COBALT_CPU_FEATURE_OVERRIDES_H + + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_fpu 1 +#define cpu_has_32fpr 1 +#define cpu_has_counter 1 +#define cpu_has_watch 0 +#define cpu_has_divec 1 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 0 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_inclusive_pcaches 0 +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 +#define cpu_scache_line_size() 0 + +#ifdef CONFIG_64BIT +#define cpu_has_llsc 0 +#else +#define cpu_has_llsc 1 +#endif + +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 +#define cpu_has_vtag_icache 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_icache_snoops_remote_store 0 +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_COBALT_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-cobalt/irq.h b/arch/mips/include/asm/mach-cobalt/irq.h new file mode 100644 index 00000000000..57c8c9ac585 --- /dev/null +++ b/arch/mips/include/asm/mach-cobalt/irq.h @@ -0,0 +1,57 @@ +/* + * Cobalt IRQ definitions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997 Cobalt Microserver + * Copyright (C) 1997, 2003 Ralf Baechle + * Copyright (C) 2001-2003 Liam Davies (ldavies@agile.tv) + * Copyright (C) 2007 Yoichi Yuasa + */ +#ifndef _ASM_COBALT_IRQ_H +#define _ASM_COBALT_IRQ_H + +/* + * i8259 interrupts used on Cobalt: + * + * 8 - RTC + * 9 - PCI slot + * 14 - IDE0 + * 15 - IDE1(no connector on board) + */ +#define I8259A_IRQ_BASE 0 + +#define PCISLOT_IRQ (I8259A_IRQ_BASE + 9) + +/* + * CPU interrupts used on Cobalt: + * + * 0 - Software interrupt 0 (unused) + * 1 - Software interrupt 0 (unused) + * 2 - cascade GT64111 + * 3 - ethernet or SCSI host controller + * 4 - ethernet + * 5 - 16550 UART + * 6 - cascade i8259 + * 7 - CP0 counter + */ +#define MIPS_CPU_IRQ_BASE 16 + +#define GT641XX_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 2) +#define RAQ2_SCSI_IRQ (MIPS_CPU_IRQ_BASE + 3) +#define ETH0_IRQ (MIPS_CPU_IRQ_BASE + 3) +#define QUBE1_ETH0_IRQ (MIPS_CPU_IRQ_BASE + 4) +#define ETH1_IRQ (MIPS_CPU_IRQ_BASE + 4) +#define SERIAL_IRQ (MIPS_CPU_IRQ_BASE + 5) +#define SCSI_IRQ (MIPS_CPU_IRQ_BASE + 5) +#define I8259_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 6) + +#define GT641XX_IRQ_BASE 24 + +#include + +#define NR_IRQS (GT641XX_PCI_INT3_IRQ + 1) + +#endif /* _ASM_COBALT_IRQ_H */ diff --git a/arch/mips/include/asm/mach-cobalt/mach-gt64120.h b/arch/mips/include/asm/mach-cobalt/mach-gt64120.h new file mode 100644 index 00000000000..ae9c5523c7e --- /dev/null +++ b/arch/mips/include/asm/mach-cobalt/mach-gt64120.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2006 Yoichi Yuasa + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _COBALT_MACH_GT64120_H +#define _COBALT_MACH_GT64120_H + +/* + * Cobalt uses GT64111. GT64111 is almost the same as GT64120. + */ + +#define GT64120_BASE CKSEG1ADDR(GT_DEF_BASE) + +#endif /* _COBALT_MACH_GT64120_H */ diff --git a/arch/mips/include/asm/mach-cobalt/war.h b/arch/mips/include/asm/mach-cobalt/war.h new file mode 100644 index 00000000000..97884fd18ac --- /dev/null +++ b/arch/mips/include/asm/mach-cobalt/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_COBALT_WAR_H +#define __ASM_MIPS_MACH_COBALT_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_COBALT_WAR_H */ diff --git a/arch/mips/include/asm/mach-db1x00/db1200.h b/arch/mips/include/asm/mach-db1x00/db1200.h new file mode 100644 index 00000000000..27f26102b1b --- /dev/null +++ b/arch/mips/include/asm/mach-db1x00/db1200.h @@ -0,0 +1,230 @@ +/* + * AMD Alchemy DBAu1200 Reference Board + * Board register defines. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_DB1200_H +#define __ASM_DB1200_H + +#include +#include + +#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX +#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX +#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC1_TX +#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC1_RX + +/* + * SPI and SMB are muxed on the DBAu1200 board. + * Refer to board documentation. + */ +#define SPI_PSC_BASE PSC0_BASE_ADDR +#define SMBUS_PSC_BASE PSC0_BASE_ADDR +/* + * AC'97 and I2S are muxed on the DBAu1200 board. + * Refer to board documentation. + */ +#define AC97_PSC_BASE PSC1_BASE_ADDR +#define I2S_PSC_BASE PSC1_BASE_ADDR + +#define BCSR_KSEG1_ADDR 0xB9800000 + +typedef volatile struct +{ + /*00*/ u16 whoami; + u16 reserved0; + /*04*/ u16 status; + u16 reserved1; + /*08*/ u16 switches; + u16 reserved2; + /*0C*/ u16 resets; + u16 reserved3; + + /*10*/ u16 pcmcia; + u16 reserved4; + /*14*/ u16 board; + u16 reserved5; + /*18*/ u16 disk_leds; + u16 reserved6; + /*1C*/ u16 system; + u16 reserved7; + + /*20*/ u16 intclr; + u16 reserved8; + /*24*/ u16 intset; + u16 reserved9; + /*28*/ u16 intclr_mask; + u16 reserved10; + /*2C*/ u16 intset_mask; + u16 reserved11; + + /*30*/ u16 sig_status; + u16 reserved12; + /*34*/ u16 int_status; + u16 reserved13; + /*38*/ u16 reserved14; + u16 reserved15; + /*3C*/ u16 reserved16; + u16 reserved17; + +} BCSR; + +static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; + +/* + * Register bit definitions for the BCSRs + */ +#define BCSR_WHOAMI_DCID 0x000F +#define BCSR_WHOAMI_CPLD 0x00F0 +#define BCSR_WHOAMI_BOARD 0x0F00 + +#define BCSR_STATUS_PCMCIA0VS 0x0003 +#define BCSR_STATUS_PCMCIA1VS 0x000C +#define BCSR_STATUS_SWAPBOOT 0x0040 +#define BCSR_STATUS_FLASHBUSY 0x0100 +#define BCSR_STATUS_IDECBLID 0x0200 +#define BCSR_STATUS_SD0WP 0x0400 +#define BCSR_STATUS_U0RXD 0x1000 +#define BCSR_STATUS_U1RXD 0x2000 + +#define BCSR_SWITCHES_OCTAL 0x00FF +#define BCSR_SWITCHES_DIP_1 0x0080 +#define BCSR_SWITCHES_DIP_2 0x0040 +#define BCSR_SWITCHES_DIP_3 0x0020 +#define BCSR_SWITCHES_DIP_4 0x0010 +#define BCSR_SWITCHES_DIP_5 0x0008 +#define BCSR_SWITCHES_DIP_6 0x0004 +#define BCSR_SWITCHES_DIP_7 0x0002 +#define BCSR_SWITCHES_DIP_8 0x0001 +#define BCSR_SWITCHES_ROTARY 0x0F00 + +#define BCSR_RESETS_ETH 0x0001 +#define BCSR_RESETS_CAMERA 0x0002 +#define BCSR_RESETS_DC 0x0004 +#define BCSR_RESETS_IDE 0x0008 +#define BCSR_RESETS_TV 0x0010 +/* Not resets but in the same register */ +#define BCSR_RESETS_PWMR1MUX 0x0800 +#define BCSR_RESETS_PCS0MUX 0x1000 +#define BCSR_RESETS_PCS1MUX 0x2000 +#define BCSR_RESETS_SPISEL 0x4000 + +#define BCSR_PCMCIA_PC0VPP 0x0003 +#define BCSR_PCMCIA_PC0VCC 0x000C +#define BCSR_PCMCIA_PC0DRVEN 0x0010 +#define BCSR_PCMCIA_PC0RST 0x0080 +#define BCSR_PCMCIA_PC1VPP 0x0300 +#define BCSR_PCMCIA_PC1VCC 0x0C00 +#define BCSR_PCMCIA_PC1DRVEN 0x1000 +#define BCSR_PCMCIA_PC1RST 0x8000 + +#define BCSR_BOARD_LCDVEE 0x0001 +#define BCSR_BOARD_LCDVDD 0x0002 +#define BCSR_BOARD_LCDBL 0x0004 +#define BCSR_BOARD_CAMSNAP 0x0010 +#define BCSR_BOARD_CAMPWR 0x0020 +#define BCSR_BOARD_SD0PWR 0x0040 + +#define BCSR_LEDS_DECIMALS 0x0003 +#define BCSR_LEDS_LED0 0x0100 +#define BCSR_LEDS_LED1 0x0200 +#define BCSR_LEDS_LED2 0x0400 +#define BCSR_LEDS_LED3 0x0800 + +#define BCSR_SYSTEM_POWEROFF 0x4000 +#define BCSR_SYSTEM_RESET 0x8000 + +/* Bit positions for the different interrupt sources */ +#define BCSR_INT_IDE 0x0001 +#define BCSR_INT_ETH 0x0002 +#define BCSR_INT_PC0 0x0004 +#define BCSR_INT_PC0STSCHG 0x0008 +#define BCSR_INT_PC1 0x0010 +#define BCSR_INT_PC1STSCHG 0x0020 +#define BCSR_INT_DC 0x0040 +#define BCSR_INT_FLASHBUSY 0x0080 +#define BCSR_INT_PC0INSERT 0x0100 +#define BCSR_INT_PC0EJECT 0x0200 +#define BCSR_INT_PC1INSERT 0x0400 +#define BCSR_INT_PC1EJECT 0x0800 +#define BCSR_INT_SD0INSERT 0x1000 +#define BCSR_INT_SD0EJECT 0x2000 + +#define SMC91C111_PHYS_ADDR 0x19000300 +#define SMC91C111_INT DB1200_ETH_INT + +#define IDE_PHYS_ADDR 0x18800000 +#define IDE_REG_SHIFT 5 +#define IDE_PHYS_LEN (16 << IDE_REG_SHIFT) +#define IDE_INT DB1200_IDE_INT +#define IDE_DDMA_REQ DSCR_CMD0_DMA_REQ1 +#define IDE_RQSIZE 128 + +#define NAND_PHYS_ADDR 0x20000000 + +/* + * External Interrupts for DBAu1200 as of 8/6/2004. + * Bit positions in the CPLD registers can be calculated by taking + * the interrupt define and subtracting the DB1200_INT_BEGIN value. + * + * Example: IDE bis pos is = 64 - 64 + * ETH bit pos is = 65 - 64 + */ +enum external_pb1200_ints { + DB1200_INT_BEGIN = AU1000_MAX_INTR + 1, + + DB1200_IDE_INT = DB1200_INT_BEGIN, + DB1200_ETH_INT, + DB1200_PC0_INT, + DB1200_PC0_STSCHG_INT, + DB1200_PC1_INT, + DB1200_PC1_STSCHG_INT, + DB1200_DC_INT, + DB1200_FLASHBUSY_INT, + DB1200_PC0_INSERT_INT, + DB1200_PC0_EJECT_INT, + DB1200_PC1_INSERT_INT, + DB1200_PC1_EJECT_INT, + DB1200_SD0_INSERT_INT, + DB1200_SD0_EJECT_INT, + + DB1200_INT_END = DB1200_INT_BEGIN + 15, +}; + + +/* + * DBAu1200 specific PCMCIA defines for drivers/pcmcia/au1000_db1x00.c + */ +#define PCMCIA_MAX_SOCK 1 +#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) + +/* VPP/VCC */ +#define SET_VCC_VPP(VCC, VPP, SLOT) \ + ((((VCC) << 2) | ((VPP) << 0)) << ((SLOT) * 8)) + +#define BOARD_PC0_INT DB1200_PC0_INT +#define BOARD_PC1_INT DB1200_PC1_INT +#define BOARD_CARD_INSERTED(SOCKET) bcsr->sig_status & (1 << (8 + (2 * SOCKET))) + +/* NAND chip select */ +#define NAND_CS 1 + +#endif /* __ASM_DB1200_H */ diff --git a/arch/mips/include/asm/mach-db1x00/db1x00.h b/arch/mips/include/asm/mach-db1x00/db1x00.h new file mode 100644 index 00000000000..1a515b8c870 --- /dev/null +++ b/arch/mips/include/asm/mach-db1x00/db1x00.h @@ -0,0 +1,179 @@ +/* + * AMD Alchemy DBAu1x00 Reference Boards + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_DB1X00_H +#define __ASM_DB1X00_H + +#include + +#ifdef CONFIG_MIPS_DB1550 + +#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX +#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX +#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC3_TX +#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC3_RX + +#define SPI_PSC_BASE PSC0_BASE_ADDR +#define AC97_PSC_BASE PSC1_BASE_ADDR +#define SMBUS_PSC_BASE PSC2_BASE_ADDR +#define I2S_PSC_BASE PSC3_BASE_ADDR + +#define BCSR_KSEG1_ADDR 0xAF000000 +#define NAND_PHYS_ADDR 0x20000000 + +#else +#define BCSR_KSEG1_ADDR 0xAE000000 +#endif + +/* + * Overlay data structure of the DBAu1x00 board registers. + * Registers are located at physical 0E0000xx, KSEG1 0xAE0000xx. + */ +typedef volatile struct +{ + /*00*/ unsigned short whoami; + unsigned short reserved0; + /*04*/ unsigned short status; + unsigned short reserved1; + /*08*/ unsigned short switches; + unsigned short reserved2; + /*0C*/ unsigned short resets; + unsigned short reserved3; + /*10*/ unsigned short pcmcia; + unsigned short reserved4; + /*14*/ unsigned short specific; + unsigned short reserved5; + /*18*/ unsigned short leds; + unsigned short reserved6; + /*1C*/ unsigned short swreset; + unsigned short reserved7; + +} BCSR; + + +/* + * Register/mask bit definitions for the BCSRs + */ +#define BCSR_WHOAMI_DCID 0x000F +#define BCSR_WHOAMI_CPLD 0x00F0 +#define BCSR_WHOAMI_BOARD 0x0F00 + +#define BCSR_STATUS_PC0VS 0x0003 +#define BCSR_STATUS_PC1VS 0x000C +#define BCSR_STATUS_PC0FI 0x0010 +#define BCSR_STATUS_PC1FI 0x0020 +#define BCSR_STATUS_FLASHBUSY 0x0100 +#define BCSR_STATUS_ROMBUSY 0x0400 +#define BCSR_STATUS_SWAPBOOT 0x2000 +#define BCSR_STATUS_FLASHDEN 0xC000 + +#define BCSR_SWITCHES_DIP 0x00FF +#define BCSR_SWITCHES_DIP_1 0x0080 +#define BCSR_SWITCHES_DIP_2 0x0040 +#define BCSR_SWITCHES_DIP_3 0x0020 +#define BCSR_SWITCHES_DIP_4 0x0010 +#define BCSR_SWITCHES_DIP_5 0x0008 +#define BCSR_SWITCHES_DIP_6 0x0004 +#define BCSR_SWITCHES_DIP_7 0x0002 +#define BCSR_SWITCHES_DIP_8 0x0001 +#define BCSR_SWITCHES_ROTARY 0x0F00 + +#define BCSR_RESETS_PHY0 0x0001 +#define BCSR_RESETS_PHY1 0x0002 +#define BCSR_RESETS_DC 0x0004 +#define BCSR_RESETS_FIR_SEL 0x2000 +#define BCSR_RESETS_IRDA_MODE_MASK 0xC000 +#define BCSR_RESETS_IRDA_MODE_FULL 0x0000 +#define BCSR_RESETS_IRDA_MODE_OFF 0x4000 +#define BCSR_RESETS_IRDA_MODE_2_3 0x8000 +#define BCSR_RESETS_IRDA_MODE_1_3 0xC000 + +#define BCSR_PCMCIA_PC0VPP 0x0003 +#define BCSR_PCMCIA_PC0VCC 0x000C +#define BCSR_PCMCIA_PC0DRVEN 0x0010 +#define BCSR_PCMCIA_PC0RST 0x0080 +#define BCSR_PCMCIA_PC1VPP 0x0300 +#define BCSR_PCMCIA_PC1VCC 0x0C00 +#define BCSR_PCMCIA_PC1DRVEN 0x1000 +#define BCSR_PCMCIA_PC1RST 0x8000 + +#define BCSR_BOARD_PCIM66EN 0x0001 +#define BCSR_BOARD_SD0_PWR 0x0040 +#define BCSR_BOARD_SD1_PWR 0x0080 +#define BCSR_BOARD_PCIM33 0x0100 +#define BCSR_BOARD_GPIO200RST 0x0400 +#define BCSR_BOARD_PCICFG 0x1000 +#define BCSR_BOARD_SD0_WP 0x4000 +#define BCSR_BOARD_SD1_WP 0x8000 + +#define BCSR_LEDS_DECIMALS 0x0003 +#define BCSR_LEDS_LED0 0x0100 +#define BCSR_LEDS_LED1 0x0200 +#define BCSR_LEDS_LED2 0x0400 +#define BCSR_LEDS_LED3 0x0800 + +#define BCSR_SWRESET_RESET 0x0080 + +/* PCMCIA DBAu1x00 specific defines */ +#define PCMCIA_MAX_SOCK 1 +#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) + +/* VPP/VCC */ +#define SET_VCC_VPP(VCC, VPP, SLOT)\ + ((((VCC) << 2) | ((VPP) << 0)) << ((SLOT) * 8)) + +/* + * NAND defines + * + * Timing values as described in databook, * ns value stripped of the + * lower 2 bits. + * These defines are here rather than an Au1550 generic file because + * the parts chosen on another board may be different and may require + * different timings. + */ +#define NAND_T_H (18 >> 2) +#define NAND_T_PUL (30 >> 2) +#define NAND_T_SU (30 >> 2) +#define NAND_T_WH (30 >> 2) + +/* Bitfield shift amounts */ +#define NAND_T_H_SHIFT 0 +#define NAND_T_PUL_SHIFT 4 +#define NAND_T_SU_SHIFT 8 +#define NAND_T_WH_SHIFT 12 + +#define NAND_TIMING (((NAND_T_H & 0xF) << NAND_T_H_SHIFT) | \ + ((NAND_T_PUL & 0xF) << NAND_T_PUL_SHIFT) | \ + ((NAND_T_SU & 0xF) << NAND_T_SU_SHIFT) | \ + ((NAND_T_WH & 0xF) << NAND_T_WH_SHIFT)) +#define NAND_CS 1 + +/* Should be done by YAMON */ +#define NAND_STCFG 0x00400005 /* 8-bit NAND */ +#define NAND_STTIME 0x00007774 /* valid for 396 MHz SD=2 only */ +#define NAND_STADDR 0x12000FFF /* physical address 0x20000000 */ + +#endif /* __ASM_DB1X00_H */ diff --git a/arch/mips/include/asm/mach-dec/mc146818rtc.h b/arch/mips/include/asm/mach-dec/mc146818rtc.h new file mode 100644 index 00000000000..6724e99e43e --- /dev/null +++ b/arch/mips/include/asm/mach-dec/mc146818rtc.h @@ -0,0 +1,43 @@ +/* + * RTC definitions for DECstation style attached Dallas DS1287 chip. + * + * Copyright (C) 1998, 2001 by Ralf Baechle + * Copyright (C) 1998 by Harald Koerfgen + * Copyright (C) 2002, 2005 Maciej W. Rozycki + * + * 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. + */ +#ifndef __ASM_MIPS_DEC_RTC_DEC_H +#define __ASM_MIPS_DEC_RTC_DEC_H + +#include +#include +#include + +extern volatile u8 *dec_rtc_base; + +#define ARCH_RTC_LOCATION + +#define RTC_PORT(x) CPHYSADDR((long)dec_rtc_base) +#define RTC_IO_EXTENT dec_kn_slot_size +#define RTC_IOMAPPED 0 +#undef RTC_IRQ + +#define RTC_DEC_YEAR 0x3f /* Where we store the real year on DECs. */ + +static inline unsigned char CMOS_READ(unsigned long addr) +{ + return dec_rtc_base[addr * 4]; +} + +static inline void CMOS_WRITE(unsigned char data, unsigned long addr) +{ + dec_rtc_base[addr * 4] = data; +} + +#define RTC_ALWAYS_BCD 0 + +#endif /* __ASM_MIPS_DEC_RTC_DEC_H */ diff --git a/arch/mips/include/asm/mach-dec/war.h b/arch/mips/include/asm/mach-dec/war.h new file mode 100644 index 00000000000..ca5e2ef909a --- /dev/null +++ b/arch/mips/include/asm/mach-dec/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_DEC_WAR_H +#define __ASM_MIPS_MACH_DEC_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_DEC_WAR_H */ diff --git a/arch/mips/include/asm/mach-emma2rh/irq.h b/arch/mips/include/asm/mach-emma2rh/irq.h new file mode 100644 index 00000000000..5439eb85646 --- /dev/null +++ b/arch/mips/include/asm/mach-emma2rh/irq.h @@ -0,0 +1,15 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 by Ralf Baechle + */ +#ifndef __ASM_MACH_EMMA2RH_IRQ_H +#define __ASM_MACH_EMMA2RH_IRQ_H + +#define NR_IRQS 256 + +#include_next + +#endif /* __ASM_MACH_EMMA2RH_IRQ_H */ diff --git a/arch/mips/include/asm/mach-emma2rh/war.h b/arch/mips/include/asm/mach-emma2rh/war.h new file mode 100644 index 00000000000..b660a4c30e6 --- /dev/null +++ b/arch/mips/include/asm/mach-emma2rh/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_EMMA2RH_WAR_H +#define __ASM_MIPS_MACH_EMMA2RH_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_EMMA2RH_WAR_H */ diff --git a/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h b/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h new file mode 100644 index 00000000000..107104c3cd1 --- /dev/null +++ b/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h @@ -0,0 +1,48 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004 Thomas Koeller + * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H + +/* + * Basler eXcite has an RM9122 processor. + */ +#define cpu_has_watch 1 +#define cpu_has_mips16 0 +#define cpu_has_divec 0 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 0 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_icache_snoops_remote_store 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_inclusive_pcaches 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 +#define cpu_scache_line_size() 32 + +#endif /* __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-excite/excite.h b/arch/mips/include/asm/mach-excite/excite.h new file mode 100644 index 00000000000..4c29ba44992 --- /dev/null +++ b/arch/mips/include/asm/mach-excite/excite.h @@ -0,0 +1,154 @@ +#ifndef __EXCITE_H__ +#define __EXCITE_H__ + +#include +#include +#include + +#define EXCITE_CPU_EXT_CLOCK 100000000 + +#if !defined(__ASSEMBLY__) +void __init excite_kgdb_init(void); +void excite_procfs_init(void); +extern unsigned long memsize; +extern char modetty[]; +extern u32 unit_id; +#endif + +/* Base name for XICAP devices */ +#define XICAP_NAME "xicap_gpi" + +/* OCD register offsets */ +#define LKB0 0x0038 +#define LKB5 0x0128 +#define LKM5 0x012C +#define LKB7 0x0138 +#define LKM7 0x013c +#define LKB8 0x0140 +#define LKM8 0x0144 +#define LKB9 0x0148 +#define LKM9 0x014c +#define LKB10 0x0150 +#define LKM10 0x0154 +#define LKB11 0x0158 +#define LKM11 0x015c +#define LKB12 0x0160 +#define LKM12 0x0164 +#define LKB13 0x0168 +#define LKM13 0x016c +#define LDP0 0x0200 +#define LDP1 0x0210 +#define LDP2 0x0220 +#define LDP3 0x0230 +#define INTPIN0 0x0A40 +#define INTPIN1 0x0A44 +#define INTPIN2 0x0A48 +#define INTPIN3 0x0A4C +#define INTPIN4 0x0A50 +#define INTPIN5 0x0A54 +#define INTPIN6 0x0A58 +#define INTPIN7 0x0A5C + + + + +/* TITAN register offsets */ +#define CPRR 0x0004 +#define CPDSR 0x0008 +#define CPTC0R 0x000c +#define CPTC1R 0x0010 +#define CPCFG0 0x0020 +#define CPCFG1 0x0024 +#define CPDST0A 0x0028 +#define CPDST0B 0x002c +#define CPDST1A 0x0030 +#define CPDST1B 0x0034 +#define CPXDSTA 0x0038 +#define CPXDSTB 0x003c +#define CPXCISRA 0x0048 +#define CPXCISRB 0x004c +#define CPGIG0ER 0x0050 +#define CPGIG1ER 0x0054 +#define CPGRWL 0x0068 +#define CPURSLMT 0x00f8 +#define UACFG 0x0200 +#define UAINTS 0x0204 +#define SDRXFCIE 0x4828 +#define SDTXFCIE 0x4928 +#define INTP0Status0 0x1B00 +#define INTP0Mask0 0x1B04 +#define INTP0Set0 0x1B08 +#define INTP0Clear0 0x1B0C +#define GXCFG 0x5000 +#define GXDMADRPFX 0x5018 +#define GXDMA_DESCADR 0x501c +#define GXCH0TDESSTRT 0x5054 + +/* IRQ definitions */ +#define NMICONFIG 0xac0 +#define TITAN_MSGINT 0xc4 +#define TITAN_IRQ ((TITAN_MSGINT / 0x20) + 2) +#define FPGA0_MSGINT 0x5a +#define FPGA0_IRQ ((FPGA0_MSGINT / 0x20) + 2) +#define FPGA1_MSGINT 0x7b +#define FPGA1_IRQ ((FPGA1_MSGINT / 0x20) + 2) +#define PHY_MSGINT 0x9c +#define PHY_IRQ ((PHY_MSGINT / 0x20) + 2) + +#if defined(CONFIG_BASLER_EXCITE_PROTOTYPE) +/* Pre-release units used interrupt pin #9 */ +#define USB_IRQ 11 +#else +/* Re-designed units use interrupt pin #1 */ +#define USB_MSGINT 0x39 +#define USB_IRQ ((USB_MSGINT / 0x20) + 2) +#endif +#define TIMER_IRQ 12 + + +/* Device address ranges */ +#define EXCITE_OFFS_OCD 0x1fffc000 +#define EXCITE_SIZE_OCD (16 * 1024) +#define EXCITE_PHYS_OCD CPHYSADDR(EXCITE_OFFS_OCD) +#define EXCITE_ADDR_OCD CKSEG1ADDR(EXCITE_OFFS_OCD) + +#define EXCITE_OFFS_SCRAM 0x1fffa000 +#define EXCITE_SIZE_SCRAM (8 << 10) +#define EXCITE_PHYS_SCRAM CPHYSADDR(EXCITE_OFFS_SCRAM) +#define EXCITE_ADDR_SCRAM CKSEG1ADDR(EXCITE_OFFS_SCRAM) + +#define EXCITE_OFFS_PCI_IO 0x1fff8000 +#define EXCITE_SIZE_PCI_IO (8 << 10) +#define EXCITE_PHYS_PCI_IO CPHYSADDR(EXCITE_OFFS_PCI_IO) +#define EXCITE_ADDR_PCI_IO CKSEG1ADDR(EXCITE_OFFS_PCI_IO) + +#define EXCITE_OFFS_TITAN 0x1fff0000 +#define EXCITE_SIZE_TITAN (32 << 10) +#define EXCITE_PHYS_TITAN CPHYSADDR(EXCITE_OFFS_TITAN) +#define EXCITE_ADDR_TITAN CKSEG1ADDR(EXCITE_OFFS_TITAN) + +#define EXCITE_OFFS_PCI_MEM 0x1ffe0000 +#define EXCITE_SIZE_PCI_MEM (64 << 10) +#define EXCITE_PHYS_PCI_MEM CPHYSADDR(EXCITE_OFFS_PCI_MEM) +#define EXCITE_ADDR_PCI_MEM CKSEG1ADDR(EXCITE_OFFS_PCI_MEM) + +#define EXCITE_OFFS_FPGA 0x1ffdc000 +#define EXCITE_SIZE_FPGA (16 << 10) +#define EXCITE_PHYS_FPGA CPHYSADDR(EXCITE_OFFS_FPGA) +#define EXCITE_ADDR_FPGA CKSEG1ADDR(EXCITE_OFFS_FPGA) + +#define EXCITE_OFFS_NAND 0x1ffd8000 +#define EXCITE_SIZE_NAND (16 << 10) +#define EXCITE_PHYS_NAND CPHYSADDR(EXCITE_OFFS_NAND) +#define EXCITE_ADDR_NAND CKSEG1ADDR(EXCITE_OFFS_NAND) + +#define EXCITE_OFFS_BOOTROM 0x1f000000 +#define EXCITE_SIZE_BOOTROM (8 << 20) +#define EXCITE_PHYS_BOOTROM CPHYSADDR(EXCITE_OFFS_BOOTROM) +#define EXCITE_ADDR_BOOTROM CKSEG1ADDR(EXCITE_OFFS_BOOTROM) + +/* FPGA address offsets */ +#define EXCITE_FPGA_DPR 0x0104 /* dual-ported ram */ +#define EXCITE_FPGA_SYSCTL 0x0200 /* system control register block */ + +#endif /* __EXCITE_H__ */ diff --git a/arch/mips/include/asm/mach-excite/excite_fpga.h b/arch/mips/include/asm/mach-excite/excite_fpga.h new file mode 100644 index 00000000000..0a1ef69bece --- /dev/null +++ b/arch/mips/include/asm/mach-excite/excite_fpga.h @@ -0,0 +1,80 @@ +#ifndef EXCITE_FPGA_H_INCLUDED +#define EXCITE_FPGA_H_INCLUDED + + +/** + * Address alignment of the individual FPGA bytes. + * The address arrangement of the individual bytes of the FPGA is two + * byte aligned at the embedded MK2 platform. + */ +#ifdef EXCITE_CCI_FPGA_MK2 +typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2))); +#else +typedef unsigned char excite_cci_fpga_align_t; +#endif + + +/** + * Size of Dual Ported RAM. + */ +#define EXCITE_DPR_SIZE 263 + + +/** + * Size of Reserved Status Fields in Dual Ported RAM. + */ +#define EXCITE_DPR_STATUS_SIZE 7 + + + +/** + * FPGA. + * Hardware register layout of the FPGA interface. The FPGA must accessed + * byte wise solely. + * @see EXCITE_CCI_DPR_MK2 + */ +typedef struct excite_fpga { + + /** + * Dual Ported RAM. + */ + excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE]; + + /** + * Status. + */ + excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE]; + +#ifdef EXCITE_CCI_FPGA_MK2 + /** + * RM9000 Interrupt. + * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite. + */ + excite_cci_fpga_align_t rm9k_int; +#else + /** + * MK2 Interrupt. + * Write access initiates interrupt at the ARM processor of the MK2. + */ + excite_cci_fpga_align_t mk2_int; + + excite_cci_fpga_align_t gap[0x1000-0x10f]; + + /** + * IRQ Source/Acknowledge. + */ + excite_cci_fpga_align_t rm9k_irq_src; + + /** + * IRQ Mask. + * Set bits enable the related interrupt. + */ + excite_cci_fpga_align_t rm9k_irq_mask; +#endif + + +} excite_fpga; + + + +#endif /* ndef EXCITE_FPGA_H_INCLUDED */ diff --git a/arch/mips/include/asm/mach-excite/excite_nandflash.h b/arch/mips/include/asm/mach-excite/excite_nandflash.h new file mode 100644 index 00000000000..c4cf6140622 --- /dev/null +++ b/arch/mips/include/asm/mach-excite/excite_nandflash.h @@ -0,0 +1,7 @@ +#ifndef __EXCITE_NANDFLASH_H__ +#define __EXCITE_NANDFLASH_H__ + +/* Resource names */ +#define EXCITE_NANDFLASH_RESOURCE_REGS "excite_nandflash_regs" + +#endif /* __EXCITE_NANDFLASH_H__ */ diff --git a/arch/mips/include/asm/mach-excite/rm9k_eth.h b/arch/mips/include/asm/mach-excite/rm9k_eth.h new file mode 100644 index 00000000000..94705a46f72 --- /dev/null +++ b/arch/mips/include/asm/mach-excite/rm9k_eth.h @@ -0,0 +1,23 @@ +#if !defined(__RM9K_ETH_H__) +#define __RM9K_ETH_H__ + +#define RM9K_GE_NAME "rm9k_ge" + +/* Resource names */ +#define RM9K_GE_RESOURCE_MAC "rm9k_ge_mac" +#define RM9K_GE_RESOURCE_MSTAT "rm9k_ge_mstat" +#define RM9K_GE_RESOURCE_PKTPROC "rm9k_ge_pktproc" +#define RM9K_GE_RESOURCE_XDMA "rm9k_ge_xdma" +#define RM9K_GE_RESOURCE_FIFO_RX "rm9k_ge_fifo_rx" +#define RM9K_GE_RESOURCE_FIFO_TX "rm9k_ge_fifo_tx" +#define RM9K_GE_RESOURCE_FIFOMEM_RX "rm9k_ge_fifo_memory_rx" +#define RM9K_GE_RESOURCE_FIFOMEM_TX "rm9k_ge_fifo_memory_tx" +#define RM9K_GE_RESOURCE_PHY "rm9k_ge_phy" +#define RM9K_GE_RESOURCE_DMADESC_RX "rm9k_ge_dmadesc_rx" +#define RM9K_GE_RESOURCE_DMADESC_TX "rm9k_ge_dmadesc_tx" +#define RM9K_GE_RESOURCE_IRQ_MAIN "rm9k_ge_irq_main" +#define RM9K_GE_RESOURCE_IRQ_PHY "rm9k_ge_irq_phy" +#define RM9K_GE_RESOURCE_GPI_SLICE "rm9k_ge_gpi_slice" +#define RM9K_GE_RESOURCE_MDIO_CHANNEL "rm9k_ge_mdio_channel" + +#endif /* !defined(__RM9K_ETH_H__) */ diff --git a/arch/mips/include/asm/mach-excite/rm9k_wdt.h b/arch/mips/include/asm/mach-excite/rm9k_wdt.h new file mode 100644 index 00000000000..3fa3c08d2da --- /dev/null +++ b/arch/mips/include/asm/mach-excite/rm9k_wdt.h @@ -0,0 +1,12 @@ +#ifndef __RM9K_WDT_H__ +#define __RM9K_WDT_H__ + +/* Device name */ +#define WDT_NAME "wdt_gpi" + +/* Resource names */ +#define WDT_RESOURCE_REGS "excite_watchdog_regs" +#define WDT_RESOURCE_IRQ "excite_watchdog_irq" +#define WDT_RESOURCE_COUNTER "excite_watchdog_counter" + +#endif /* __RM9K_WDT_H__ */ diff --git a/arch/mips/include/asm/mach-excite/rm9k_xicap.h b/arch/mips/include/asm/mach-excite/rm9k_xicap.h new file mode 100644 index 00000000000..009577734a8 --- /dev/null +++ b/arch/mips/include/asm/mach-excite/rm9k_xicap.h @@ -0,0 +1,16 @@ +#ifndef __EXCITE_XICAP_H__ +#define __EXCITE_XICAP_H__ + + +/* Resource names */ +#define XICAP_RESOURCE_FIFO_RX "xicap_fifo_rx" +#define XICAP_RESOURCE_FIFO_TX "xicap_fifo_tx" +#define XICAP_RESOURCE_XDMA "xicap_xdma" +#define XICAP_RESOURCE_DMADESC "xicap_dmadesc" +#define XICAP_RESOURCE_PKTPROC "xicap_pktproc" +#define XICAP_RESOURCE_IRQ "xicap_irq" +#define XICAP_RESOURCE_GPI_SLICE "xicap_gpi_slice" +#define XICAP_RESOURCE_FIFO_BLK "xicap_fifo_blocks" +#define XICAP_RESOURCE_PKT_STREAM "xicap_pkt_stream" + +#endif /* __EXCITE_XICAP_H__ */ diff --git a/arch/mips/include/asm/mach-excite/war.h b/arch/mips/include/asm/mach-excite/war.h new file mode 100644 index 00000000000..1f82180c159 --- /dev/null +++ b/arch/mips/include/asm/mach-excite/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_EXCITE_WAR_H +#define __ASM_MIPS_MACH_EXCITE_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 1 +#define ICACHE_REFILLS_WORKAROUND_WAR 1 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_EXCITE_WAR_H */ diff --git a/arch/mips/include/asm/mach-generic/cpu-feature-overrides.h b/arch/mips/include/asm/mach-generic/cpu-feature-overrides.h new file mode 100644 index 00000000000..7c185bb06f1 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/cpu-feature-overrides.h @@ -0,0 +1,13 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 Ralf Baechle + */ +#ifndef __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H + +/* Intentionally empty file ... */ + +#endif /* __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h new file mode 100644 index 00000000000..76e04e7feb8 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/dma-coherence.h @@ -0,0 +1,45 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Ralf Baechle + * + */ +#ifndef __ASM_MACH_GENERIC_DMA_COHERENCE_H +#define __ASM_MACH_GENERIC_DMA_COHERENCE_H + +struct device; + +static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, + size_t size) +{ + return virt_to_phys(addr); +} + +static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, + struct page *page) +{ + return page_to_phys(page); +} + +static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) +{ + return dma_addr; +} + +static inline void plat_unmap_dma_mem(dma_addr_t dma_addr) +{ +} + +static inline int plat_device_is_coherent(struct device *dev) +{ +#ifdef CONFIG_DMA_COHERENT + return 1; +#endif +#ifdef CONFIG_DMA_NONCOHERENT + return 0; +#endif +} + +#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-generic/floppy.h b/arch/mips/include/asm/mach-generic/floppy.h new file mode 100644 index 00000000000..001a8ce17c1 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/floppy.h @@ -0,0 +1,139 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1998, 2003 by Ralf Baechle + */ +#ifndef __ASM_MACH_GENERIC_FLOPPY_H +#define __ASM_MACH_GENERIC_FLOPPY_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * How to access the FDC's registers. + */ +static inline unsigned char fd_inb(unsigned int port) +{ + return inb_p(port); +} + +static inline void fd_outb(unsigned char value, unsigned int port) +{ + outb_p(value, port); +} + +/* + * How to access the floppy DMA functions. + */ +static inline void fd_enable_dma(void) +{ + enable_dma(FLOPPY_DMA); +} + +static inline void fd_disable_dma(void) +{ + disable_dma(FLOPPY_DMA); +} + +static inline int fd_request_dma(void) +{ + return request_dma(FLOPPY_DMA, "floppy"); +} + +static inline void fd_free_dma(void) +{ + free_dma(FLOPPY_DMA); +} + +static inline void fd_clear_dma_ff(void) +{ + clear_dma_ff(FLOPPY_DMA); +} + +static inline void fd_set_dma_mode(char mode) +{ + set_dma_mode(FLOPPY_DMA, mode); +} + +static inline void fd_set_dma_addr(char *addr) +{ + set_dma_addr(FLOPPY_DMA, (unsigned long) addr); +} + +static inline void fd_set_dma_count(unsigned int count) +{ + set_dma_count(FLOPPY_DMA, count); +} + +static inline int fd_get_dma_residue(void) +{ + return get_dma_residue(FLOPPY_DMA); +} + +static inline void fd_enable_irq(void) +{ + enable_irq(FLOPPY_IRQ); +} + +static inline void fd_disable_irq(void) +{ + disable_irq(FLOPPY_IRQ); +} + +static inline int fd_request_irq(void) +{ + return request_irq(FLOPPY_IRQ, floppy_interrupt, + IRQF_DISABLED, "floppy", NULL); +} + +static inline void fd_free_irq(void) +{ + free_irq(FLOPPY_IRQ, NULL); +} + +#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); + + +static inline unsigned long fd_getfdaddr1(void) +{ + return 0x3f0; +} + +static inline unsigned long fd_dma_mem_alloc(unsigned long size) +{ + unsigned long mem; + + mem = __get_dma_pages(GFP_KERNEL, get_order(size)); + + return mem; +} + +static inline void fd_dma_mem_free(unsigned long addr, unsigned long size) +{ + free_pages(addr, get_order(size)); +} + +static inline unsigned long fd_drive_type(unsigned long n) +{ + if (n == 0) + return 4; /* 3,5", 1.44mb */ + + return 0; +} + +#endif /* __ASM_MACH_GENERIC_FLOPPY_H */ diff --git a/arch/mips/include/asm/mach-generic/gpio.h b/arch/mips/include/asm/mach-generic/gpio.h new file mode 100644 index 00000000000..b4e70208da6 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/gpio.h @@ -0,0 +1,21 @@ +#ifndef __ASM_MACH_GENERIC_GPIO_H +#define __ASM_MACH_GENERIC_GPIO_H + +#ifdef CONFIG_GPIOLIB +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#else +int gpio_request(unsigned gpio, const char *label); +void gpio_free(unsigned gpio); +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +void gpio_set_value(unsigned gpio, int value); +#endif +int gpio_to_irq(unsigned gpio); +int irq_to_gpio(unsigned irq); + +#include /* cansleep wrappers */ + +#endif /* __ASM_MACH_GENERIC_GPIO_H */ diff --git a/arch/mips/include/asm/mach-generic/ide.h b/arch/mips/include/asm/mach-generic/ide.h new file mode 100644 index 00000000000..73008f7bdc9 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/ide.h @@ -0,0 +1,167 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994-1996 Linus Torvalds & authors + * + * Copied from i386; many of the especially older MIPS or ISA-based platforms + * are basically identical. Using this file probably implies i8259 PIC + * support in a system but the very least interrupt numbers 0 - 15 need to + * be put aside for legacy devices. + */ +#ifndef __ASM_MACH_GENERIC_IDE_H +#define __ASM_MACH_GENERIC_IDE_H + +#ifdef __KERNEL__ + +#include +#include +#include + +static __inline__ int ide_probe_legacy(void) +{ +#ifdef CONFIG_PCI + struct pci_dev *dev; + /* + * This can be called on the ide_setup() path, super-early in + * boot. But the down_read() will enable local interrupts, + * which can cause some machines to crash. So here we detect + * and flag that situation and bail out early. + */ + if (no_pci_devices()) + return 0; + dev = pci_get_class(PCI_CLASS_BRIDGE_EISA << 8, NULL); + if (dev) + goto found; + dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); + if (dev) + goto found; + return 0; +found: + pci_dev_put(dev); + return 1; +#elif defined(CONFIG_EISA) || defined(CONFIG_ISA) + return 1; +#else + return 0; +#endif +} + +/* MIPS port and memory-mapped I/O string operations. */ +static inline void __ide_flush_prologue(void) +{ +#ifdef CONFIG_SMP + if (cpu_has_dc_aliases) + preempt_disable(); +#endif +} + +static inline void __ide_flush_epilogue(void) +{ +#ifdef CONFIG_SMP + if (cpu_has_dc_aliases) + preempt_enable(); +#endif +} + +static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size) +{ + if (cpu_has_dc_aliases) { + unsigned long end = addr + size; + + while (addr < end) { + local_flush_data_cache_page((void *)addr); + addr += PAGE_SIZE; + } + } +} + +/* + * insw() and gang might be called with interrupts disabled, so we can't + * send IPIs for flushing due to the potencial of deadlocks, see the comment + * above smp_call_function() in arch/mips/kernel/smp.c. We work around the + * problem by disabling preemption so we know we actually perform the flush + * on the processor that actually has the lines to be flushed which hopefully + * is even better for performance anyway. + */ +static inline void __ide_insw(unsigned long port, void *addr, + unsigned int count) +{ + __ide_flush_prologue(); + insw(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 2); + __ide_flush_epilogue(); +} + +static inline void __ide_insl(unsigned long port, void *addr, unsigned int count) +{ + __ide_flush_prologue(); + insl(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 4); + __ide_flush_epilogue(); +} + +static inline void __ide_outsw(unsigned long port, const void *addr, + unsigned long count) +{ + __ide_flush_prologue(); + outsw(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 2); + __ide_flush_epilogue(); +} + +static inline void __ide_outsl(unsigned long port, const void *addr, + unsigned long count) +{ + __ide_flush_prologue(); + outsl(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 4); + __ide_flush_epilogue(); +} + +static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count) +{ + __ide_flush_prologue(); + readsw(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 2); + __ide_flush_epilogue(); +} + +static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count) +{ + __ide_flush_prologue(); + readsl(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 4); + __ide_flush_epilogue(); +} + +static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count) +{ + __ide_flush_prologue(); + writesw(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 2); + __ide_flush_epilogue(); +} + +static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count) +{ + __ide_flush_prologue(); + writesl(port, addr, count); + __ide_flush_dcache_range((unsigned long)addr, count * 4); + __ide_flush_epilogue(); +} + +/* ide_insw calls insw, not __ide_insw. Why? */ +#undef insw +#undef insl +#undef outsw +#undef outsl +#define insw(port, addr, count) __ide_insw(port, addr, count) +#define insl(port, addr, count) __ide_insl(port, addr, count) +#define outsw(port, addr, count) __ide_outsw(port, addr, count) +#define outsl(port, addr, count) __ide_outsl(port, addr, count) + +#endif /* __KERNEL__ */ + +#endif /* __ASM_MACH_GENERIC_IDE_H */ diff --git a/arch/mips/include/asm/mach-generic/ioremap.h b/arch/mips/include/asm/mach-generic/ioremap.h new file mode 100644 index 00000000000..b379938d47f --- /dev/null +++ b/arch/mips/include/asm/mach-generic/ioremap.h @@ -0,0 +1,34 @@ +/* + * include/asm-mips/mach-generic/ioremap.h + * + * 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. + */ +#ifndef __ASM_MACH_GENERIC_IOREMAP_H +#define __ASM_MACH_GENERIC_IOREMAP_H + +#include + +/* + * Allow physical addresses to be fixed up to help peripherals located + * outside the low 32-bit range -- generic pass-through version. + */ +static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + return phys_addr; +} + +static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, + unsigned long flags) +{ + return NULL; +} + +static inline int plat_iounmap(const volatile void __iomem *addr) +{ + return 0; +} + +#endif /* __ASM_MACH_GENERIC_IOREMAP_H */ diff --git a/arch/mips/include/asm/mach-generic/irq.h b/arch/mips/include/asm/mach-generic/irq.h new file mode 100644 index 00000000000..70d9a25132c --- /dev/null +++ b/arch/mips/include/asm/mach-generic/irq.h @@ -0,0 +1,45 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 by Ralf Baechle + */ +#ifndef __ASM_MACH_GENERIC_IRQ_H +#define __ASM_MACH_GENERIC_IRQ_H + +#ifndef NR_IRQS +#define NR_IRQS 128 +#endif + +#ifdef CONFIG_I8259 +#ifndef I8259A_IRQ_BASE +#define I8259A_IRQ_BASE 0 +#endif +#endif + +#ifdef CONFIG_IRQ_CPU + +#ifndef MIPS_CPU_IRQ_BASE +#ifdef CONFIG_I8259 +#define MIPS_CPU_IRQ_BASE 16 +#else +#define MIPS_CPU_IRQ_BASE 0 +#endif /* CONFIG_I8259 */ +#endif + +#ifdef CONFIG_IRQ_CPU_RM7K +#ifndef RM7K_CPU_IRQ_BASE +#define RM7K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+8) +#endif +#endif + +#ifdef CONFIG_IRQ_CPU_RM9K +#ifndef RM9K_CPU_IRQ_BASE +#define RM9K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+12) +#endif +#endif + +#endif /* CONFIG_IRQ_CPU */ + +#endif /* __ASM_MACH_GENERIC_IRQ_H */ diff --git a/arch/mips/include/asm/mach-generic/kernel-entry-init.h b/arch/mips/include/asm/mach-generic/kernel-entry-init.h new file mode 100644 index 00000000000..7e66505fa57 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/kernel-entry-init.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005 Embedded Alley Solutions, Inc + * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_MACH_GENERIC_KERNEL_ENTRY_H +#define __ASM_MACH_GENERIC_KERNEL_ENTRY_H + +/* Intentionally empty macro, used in head.S. Override in + * arch/mips/mach-xxx/kernel-entry-init.h when necessary. + */ +.macro kernel_entry_setup +.endm + +/* + * Do SMP slave processor setup necessary before we can savely execute C code. + */ + .macro smp_slave_setup + .endm + + +#endif /* __ASM_MACH_GENERIC_KERNEL_ENTRY_H */ diff --git a/arch/mips/include/asm/mach-generic/kmalloc.h b/arch/mips/include/asm/mach-generic/kmalloc.h new file mode 100644 index 00000000000..b8e6deba352 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/kmalloc.h @@ -0,0 +1,13 @@ +#ifndef __ASM_MACH_GENERIC_KMALLOC_H +#define __ASM_MACH_GENERIC_KMALLOC_H + + +#ifndef CONFIG_DMA_COHERENT +/* + * Total overkill for most systems but need as a safe default. + * Set this one if any device in the system might do non-coherent DMA. + */ +#define ARCH_KMALLOC_MINALIGN 128 +#endif + +#endif /* __ASM_MACH_GENERIC_KMALLOC_H */ diff --git a/arch/mips/include/asm/mach-generic/mangle-port.h b/arch/mips/include/asm/mach-generic/mangle-port.h new file mode 100644 index 00000000000..f49dc990214 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/mangle-port.h @@ -0,0 +1,52 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 2004 Ralf Baechle + */ +#ifndef __ASM_MACH_GENERIC_MANGLE_PORT_H +#define __ASM_MACH_GENERIC_MANGLE_PORT_H + +#define __swizzle_addr_b(port) (port) +#define __swizzle_addr_w(port) (port) +#define __swizzle_addr_l(port) (port) +#define __swizzle_addr_q(port) (port) + +/* + * Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware; + * less sane hardware forces software to fiddle with this... + * + * Regardless, if the host bus endianness mismatches that of PCI/ISA, then + * you can't have the numerical value of data and byte addresses within + * multibyte quantities both preserved at the same time. Hence two + * variations of functions: non-prefixed ones that preserve the value + * and prefixed ones that preserve byte addresses. The latters are + * typically used for moving raw data between a peripheral and memory (cf. + * string I/O functions), hence the "__mem_" prefix. + */ +#if defined(CONFIG_SWAP_IO_SPACE) + +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) le16_to_cpu(x) +# define __mem_ioswabw(a, x) (x) +# define ioswabl(a, x) le32_to_cpu(x) +# define __mem_ioswabl(a, x) (x) +# define ioswabq(a, x) le64_to_cpu(x) +# define __mem_ioswabq(a, x) (x) + +#else + +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) (x) +# define __mem_ioswabw(a, x) cpu_to_le16(x) +# define ioswabl(a, x) (x) +# define __mem_ioswabl(a, x) cpu_to_le32(x) +# define ioswabq(a, x) (x) +# define __mem_ioswabq(a, x) cpu_to_le32(x) + +#endif + +#endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */ diff --git a/arch/mips/include/asm/mach-generic/mc146818rtc.h b/arch/mips/include/asm/mach-generic/mc146818rtc.h new file mode 100644 index 00000000000..0b9a942f079 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/mc146818rtc.h @@ -0,0 +1,36 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2001, 03 by Ralf Baechle + * + * RTC routines for PC style attached Dallas chip. + */ +#ifndef __ASM_MACH_GENERIC_MC146818RTC_H +#define __ASM_MACH_GENERIC_MC146818RTC_H + +#include + +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_IRQ 8 + +static inline unsigned char CMOS_READ(unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + return inb_p(RTC_PORT(1)); +} + +static inline void CMOS_WRITE(unsigned char data, unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + outb_p(data, RTC_PORT(1)); +} + +#define RTC_ALWAYS_BCD 1 + +#ifndef mc146818_decode_year +#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1900) +#endif + +#endif /* __ASM_MACH_GENERIC_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h new file mode 100644 index 00000000000..c9fa4b14968 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/spaces.h @@ -0,0 +1,85 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_MACH_GENERIC_SPACES_H +#define _ASM_MACH_GENERIC_SPACES_H + +#include + +/* + * This gives the physical RAM offset. + */ +#ifndef PHYS_OFFSET +#define PHYS_OFFSET _AC(0, UL) +#endif + +#ifdef CONFIG_32BIT + +#define CAC_BASE _AC(0x80000000, UL) +#define IO_BASE _AC(0xa0000000, UL) +#define UNCAC_BASE _AC(0xa0000000, UL) + +#ifndef MAP_BASE +#define MAP_BASE _AC(0xc0000000, UL) +#endif + +/* + * Memory above this physical address will be considered highmem. + */ +#ifndef HIGHMEM_START +#define HIGHMEM_START _AC(0x20000000, UL) +#endif + +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT + +#ifndef CAC_BASE +#ifdef CONFIG_DMA_NONCOHERENT +#define CAC_BASE _AC(0x9800000000000000, UL) +#else +#define CAC_BASE _AC(0xa800000000000000, UL) +#endif +#endif + +#ifndef IO_BASE +#define IO_BASE _AC(0x9000000000000000, UL) +#endif + +#ifndef UNCAC_BASE +#define UNCAC_BASE _AC(0x9000000000000000, UL) +#endif + +#ifndef MAP_BASE +#define MAP_BASE _AC(0xc000000000000000, UL) +#endif + +/* + * Memory above this physical address will be considered highmem. + * Fixme: 59 bits is a fictive number and makes assumptions about processors + * in the distant future. Nobody will care for a few years :-) + */ +#ifndef HIGHMEM_START +#define HIGHMEM_START (_AC(1, UL) << _AC(59, UL)) +#endif + +#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK)) +#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK)) +#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK)) + +#endif /* CONFIG_64BIT */ + +/* + * This handles the memory map. + */ +#ifndef PAGE_OFFSET +#define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET) +#endif + +#endif /* __ASM_MACH_GENERIC_SPACES_H */ diff --git a/arch/mips/include/asm/mach-generic/topology.h b/arch/mips/include/asm/mach-generic/topology.h new file mode 100644 index 00000000000..5428f333a02 --- /dev/null +++ b/arch/mips/include/asm/mach-generic/topology.h @@ -0,0 +1 @@ +#include diff --git a/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h new file mode 100644 index 00000000000..9c8735158da --- /dev/null +++ b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h @@ -0,0 +1,44 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 07 Ralf Baechle + */ +#ifndef __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H + +/* + * IP22 with a variety of processors so we can't use defaults for everything. + */ +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_4k_cache 1 +#define cpu_has_fpu 1 +#define cpu_has_32fpr 1 +#define cpu_has_counter 1 +#define cpu_has_mips16 0 +#define cpu_has_divec 0 +#define cpu_has_cache_cdex_p 1 +#define cpu_has_prefetch 0 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 0 /* Needs to change for R8000 */ +#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000) +#define cpu_has_ic_fills_f_dc 0 + +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ip22/ds1286.h b/arch/mips/include/asm/mach-ip22/ds1286.h new file mode 100644 index 00000000000..f19f1eafbc7 --- /dev/null +++ b/arch/mips/include/asm/mach-ip22/ds1286.h @@ -0,0 +1,18 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2001, 03 by Ralf Baechle + * + * RTC routines for PC style attached Dallas chip. + */ +#ifndef __ASM_MACH_IP22_DS1286_H +#define __ASM_MACH_IP22_DS1286_H + +#include + +#define rtc_read(reg) (hpc3c0->rtcregs[(reg)] & 0xff) +#define rtc_write(data, reg) do { hpc3c0->rtcregs[(reg)] = (data); } while(0) + +#endif /* __ASM_MACH_IP22_DS1286_H */ diff --git a/arch/mips/include/asm/mach-ip22/spaces.h b/arch/mips/include/asm/mach-ip22/spaces.h new file mode 100644 index 00000000000..7f9fa6f6605 --- /dev/null +++ b/arch/mips/include/asm/mach-ip22/spaces.h @@ -0,0 +1,27 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_MACH_IP22_SPACES_H +#define _ASM_MACH_IP22_SPACES_H + + +#ifdef CONFIG_64BIT + +#define PAGE_OFFSET 0xffffffff80000000UL + +#define CAC_BASE 0xffffffff80000000 +#define IO_BASE 0xffffffffa0000000 +#define UNCAC_BASE 0xffffffffa0000000 +#define MAP_BASE 0xc000000000000000 + +#endif /* CONFIG_64BIT */ + +#include + +#endif /* __ASM_MACH_IP22_SPACES_H */ diff --git a/arch/mips/include/asm/mach-ip22/war.h b/arch/mips/include/asm/mach-ip22/war.h new file mode 100644 index 00000000000..a44fa9656a8 --- /dev/null +++ b/arch/mips/include/asm/mach-ip22/war.h @@ -0,0 +1,29 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_IP22_WAR_H +#define __ASM_MIPS_MACH_IP22_WAR_H + +/* + * R4600 CPU modules for the Indy come with both V1.7 and V2.0 processors. + */ + +#define R4600_V1_INDEX_ICACHEOP_WAR 1 +#define R4600_V1_HIT_CACHEOP_WAR 1 +#define R4600_V2_HIT_CACHEOP_WAR 1 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_IP22_WAR_H */ diff --git a/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h new file mode 100644 index 00000000000..7d3112b148d --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h @@ -0,0 +1,54 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 07 Ralf Baechle + */ +#ifndef __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H + +/* + * IP27 only comes with R10000 family processors all using the same config + */ +#define cpu_has_watch 1 +#define cpu_has_mips16 0 +#define cpu_has_divec 0 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 0 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_icache_snoops_remote_store 1 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 + +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_6k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_8k_cache 0 +#define cpu_has_tx39_cache 0 + +#define cpu_has_inclusive_pcaches 1 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 64 +#define cpu_scache_line_size() 128 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h new file mode 100644 index 00000000000..ed7e6222dc1 --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h @@ -0,0 +1,50 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Ralf Baechle + * + */ +#ifndef __ASM_MACH_IP27_DMA_COHERENCE_H +#define __ASM_MACH_IP27_DMA_COHERENCE_H + +#include + +#define pdev_to_baddr(pdev, addr) \ + (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr)) +#define dev_to_baddr(dev, addr) \ + pdev_to_baddr(to_pci_dev(dev), (addr)) + +struct device; + +static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, + size_t size) +{ + dma_addr_t pa = dev_to_baddr(dev, virt_to_phys(addr)); + + return pa; +} + +static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) +{ + dma_addr_t pa = dev_to_baddr(dev, page_to_phys(page)); + + return pa; +} + +static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) +{ + return dma_addr & ~(0xffUL << 56); +} + +static inline void plat_unmap_dma_mem(dma_addr_t dma_addr) +{ +} + +static inline int plat_device_is_coherent(struct device *dev) +{ + return 1; /* IP27 non-cohernet mode is unsupported */ +} + +#endif /* __ASM_MACH_IP27_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-ip27/irq.h b/arch/mips/include/asm/mach-ip27/irq.h new file mode 100644 index 00000000000..cf4384bfa84 --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/irq.h @@ -0,0 +1,22 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999, 2000, 01, 02, 03 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 Kanoj Sarcar + */ +#ifndef __ASM_MACH_IP27_IRQ_H +#define __ASM_MACH_IP27_IRQ_H + +/* + * A hardwired interrupt number is completly stupid for this system - a + * large configuration might have thousands if not tenthousands of + * interrupts. + */ +#define NR_IRQS 256 + +#include_next + +#endif /* __ASM_MACH_IP27_IRQ_H */ diff --git a/arch/mips/include/asm/mach-ip27/kernel-entry-init.h b/arch/mips/include/asm/mach-ip27/kernel-entry-init.h new file mode 100644 index 00000000000..624d66c7f29 --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/kernel-entry-init.h @@ -0,0 +1,59 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2005 Ralf Baechle + */ +#ifndef __ASM_MACH_IP27_KERNEL_ENTRY_H +#define __ASM_MACH_IP27_KERNEL_ENTRY_H + +#include +#include +#include + +/* + * Returns the local nasid into res. + */ + .macro GET_NASID_ASM res + dli \res, LOCAL_HUB_ADDR(NI_STATUS_REV_ID) + ld \res, (\res) + and \res, NSRI_NODEID_MASK + dsrl \res, NSRI_NODEID_SHFT + .endm + +/* + * Intentionally empty macro, used in head.S. Override in + * arch/mips/mach-xxx/kernel-entry-init.h when necessary. + */ + .macro kernel_entry_setup + GET_NASID_ASM t1 + move t2, t1 # text and data are here + MAPPED_KERNEL_SETUP_TLB + .endm + +/* + * Do SMP slave processor setup necessary before we can savely execute C code. + */ + .macro smp_slave_setup + GET_NASID_ASM t1 + dli t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \ + KLDIR_OFF_POINTER + CAC_BASE + dsll t1, NASID_SHFT + or t0, t0, t1 + ld t0, 0(t0) # t0 points to kern_vars struct + lh t1, KV_RO_NASID_OFFSET(t0) + lh t2, KV_RW_NASID_OFFSET(t0) + MAPPED_KERNEL_SETUP_TLB + + /* + * We might not get launched at the address the kernel is linked to, + * so we jump there. + */ + PTR_LA t0, 0f + jr t0 +0: + .endm + +#endif /* __ASM_MACH_IP27_KERNEL_ENTRY_H */ diff --git a/arch/mips/include/asm/mach-ip27/kmalloc.h b/arch/mips/include/asm/mach-ip27/kmalloc.h new file mode 100644 index 00000000000..426bd049b2d --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/kmalloc.h @@ -0,0 +1,8 @@ +#ifndef __ASM_MACH_IP27_KMALLOC_H +#define __ASM_MACH_IP27_KMALLOC_H + +/* + * All happy, no need to define ARCH_KMALLOC_MINALIGN + */ + +#endif /* __ASM_MACH_IP27_KMALLOC_H */ diff --git a/arch/mips/include/asm/mach-ip27/mangle-port.h b/arch/mips/include/asm/mach-ip27/mangle-port.h new file mode 100644 index 00000000000..f6e4912ea06 --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/mangle-port.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 2004 Ralf Baechle + */ +#ifndef __ASM_MACH_IP27_MANGLE_PORT_H +#define __ASM_MACH_IP27_MANGLE_PORT_H + +#define __swizzle_addr_b(port) (port) +#define __swizzle_addr_w(port) ((port) ^ 2) +#define __swizzle_addr_l(port) (port) +#define __swizzle_addr_q(port) (port) + +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) (x) +# define __mem_ioswabw(a, x) cpu_to_le16(x) +# define ioswabl(a, x) (x) +# define __mem_ioswabl(a, x) cpu_to_le32(x) +# define ioswabq(a, x) (x) +# define __mem_ioswabq(a, x) cpu_to_le32(x) + +#endif /* __ASM_MACH_IP27_MANGLE_PORT_H */ diff --git a/arch/mips/include/asm/mach-ip27/mmzone.h b/arch/mips/include/asm/mach-ip27/mmzone.h new file mode 100644 index 00000000000..986a3b9b59a --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/mmzone.h @@ -0,0 +1,36 @@ +#ifndef _ASM_MACH_MMZONE_H +#define _ASM_MACH_MMZONE_H + +#include +#include +#include + +#define pa_to_nid(addr) NASID_TO_COMPACT_NODEID(NASID_GET(addr)) + +#define LEVELS_PER_SLICE 128 + +struct slice_data { + unsigned long irq_enable_mask[2]; + int level_to_irq[LEVELS_PER_SLICE]; +}; + +struct hub_data { + kern_vars_t kern_vars; + DECLARE_BITMAP(h_bigwin_used, HUB_NUM_BIG_WINDOW); + cpumask_t h_cpus; + unsigned long slice_map; + unsigned long irq_alloc_mask[2]; + struct slice_data slice[2]; +}; + +struct node_data { + struct pglist_data pglist; + struct hub_data hub; +}; + +extern struct node_data *__node_data[]; + +#define NODE_DATA(n) (&__node_data[(n)]->pglist) +#define hub_data(n) (&__node_data[(n)]->hub) + +#endif /* _ASM_MACH_MMZONE_H */ diff --git a/arch/mips/include/asm/mach-ip27/spaces.h b/arch/mips/include/asm/mach-ip27/spaces.h new file mode 100644 index 00000000000..b18802a0b17 --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/spaces.h @@ -0,0 +1,30 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 99 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999 by Silicon Graphics, Inc. + */ +#ifndef _ASM_MACH_IP27_SPACES_H +#define _ASM_MACH_IP27_SPACES_H + +/* + * IP27 uses the R10000's uncached attribute feature. Attribute 3 selects + * uncached memory addressing. + */ + +#define HSPEC_BASE 0x9000000000000000 +#define IO_BASE 0x9200000000000000 +#define MSPEC_BASE 0x9400000000000000 +#define UNCAC_BASE 0x9600000000000000 + +#define TO_MSPEC(x) (MSPEC_BASE | ((x) & TO_PHYS_MASK)) +#define TO_HSPEC(x) (HSPEC_BASE | ((x) & TO_PHYS_MASK)) + +#define HIGHMEM_START (~0UL) + +#include + +#endif /* _ASM_MACH_IP27_SPACES_H */ diff --git a/arch/mips/include/asm/mach-ip27/topology.h b/arch/mips/include/asm/mach-ip27/topology.h new file mode 100644 index 00000000000..7785bec732f --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/topology.h @@ -0,0 +1,59 @@ +#ifndef _ASM_MACH_TOPOLOGY_H +#define _ASM_MACH_TOPOLOGY_H 1 + +#include +#include +#include + +struct cpuinfo_ip27 { +// cpuid_t p_cpuid; /* PROM assigned cpuid */ + cnodeid_t p_nodeid; /* my node ID in compact-id-space */ + nasid_t p_nasid; /* my node ID in numa-as-id-space */ + unsigned char p_slice; /* Physical position on node board */ +#if 0 + unsigned long loops_per_sec; + unsigned long ipi_count; + unsigned long irq_attempt[NR_IRQS]; + unsigned long smp_local_irq_count; + unsigned long prof_multiplier; + unsigned long prof_counter; +#endif +}; + +extern struct cpuinfo_ip27 sn_cpu_info[NR_CPUS]; + +#define cpu_to_node(cpu) (sn_cpu_info[(cpu)].p_nodeid) +#define parent_node(node) (node) +#define node_to_cpumask(node) (hub_data(node)->h_cpus) +#define node_to_first_cpu(node) (first_cpu(node_to_cpumask(node))) +struct pci_bus; +extern int pcibus_to_node(struct pci_bus *); + +#define pcibus_to_cpumask(bus) (cpu_online_map) + +extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; + +#define node_distance(from, to) (__node_distances[(from)][(to)]) + +/* sched_domains SD_NODE_INIT for SGI IP27 machines */ +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .child = NULL, \ + .groups = NULL, \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_nice_tries = 1, \ + .flags = SD_LOAD_BALANCE \ + | SD_BALANCE_EXEC \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +} + +#include + +#endif /* _ASM_MACH_TOPOLOGY_H */ diff --git a/arch/mips/include/asm/mach-ip27/war.h b/arch/mips/include/asm/mach-ip27/war.h new file mode 100644 index 00000000000..e2ddcc9b1ff --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_IP27_WAR_H +#define __ASM_MIPS_MACH_IP27_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 1 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_IP27_WAR_H */ diff --git a/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h new file mode 100644 index 00000000000..9a53b326f84 --- /dev/null +++ b/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h @@ -0,0 +1,50 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 Ralf Baechle + * 6/2004 pf + */ +#ifndef __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H + +/* + * IP28 only comes with R10000 family processors all using the same config + */ +#define cpu_has_watch 1 +#define cpu_has_mips16 0 +#define cpu_has_divec 0 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 0 +#define cpu_has_dc_aliases 0 /* see probe_pcache() */ +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_icache_snoops_remote_store 1 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 + +#define cpu_has_4kex 1 +#define cpu_has_4k_cache 1 + +#define cpu_has_inclusive_pcaches 1 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 64 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ip28/ds1286.h b/arch/mips/include/asm/mach-ip28/ds1286.h new file mode 100644 index 00000000000..471bb9a33e0 --- /dev/null +++ b/arch/mips/include/asm/mach-ip28/ds1286.h @@ -0,0 +1,4 @@ +#ifndef __ASM_MACH_IP28_DS1286_H +#define __ASM_MACH_IP28_DS1286_H +#include +#endif /* __ASM_MACH_IP28_DS1286_H */ diff --git a/arch/mips/include/asm/mach-ip28/spaces.h b/arch/mips/include/asm/mach-ip28/spaces.h new file mode 100644 index 00000000000..05aabb27e5e --- /dev/null +++ b/arch/mips/include/asm/mach-ip28/spaces.h @@ -0,0 +1,22 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + * 2004 pf + */ +#ifndef _ASM_MACH_IP28_SPACES_H +#define _ASM_MACH_IP28_SPACES_H + +#define CAC_BASE 0xa800000000000000 + +#define HIGHMEM_START (~0UL) + +#define PHYS_OFFSET _AC(0x20000000, UL) + +#include + +#endif /* _ASM_MACH_IP28_SPACES_H */ diff --git a/arch/mips/include/asm/mach-ip28/war.h b/arch/mips/include/asm/mach-ip28/war.h new file mode 100644 index 00000000000..a1baafab486 --- /dev/null +++ b/arch/mips/include/asm/mach-ip28/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_IP28_WAR_H +#define __ASM_MIPS_MACH_IP28_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 1 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_IP28_WAR_H */ diff --git a/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h new file mode 100644 index 00000000000..6782fccebe8 --- /dev/null +++ b/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h @@ -0,0 +1,50 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005 Ilya A. Volynets-Evenbakh + * Copyright (C) 2005, 07 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H + + +/* + * R5000 has an interesting "restriction": ll(d)/sc(d) + * instructions to XKPHYS region simply do uncached bus + * requests. This breaks all the atomic bitops functions. + * so, for 64bit IP32 kernel we just don't use ll/sc. + * This does not affect luserland. + */ +#if (defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_NEVADA)) && defined(CONFIG_64BIT) +#define cpu_has_llsc 0 +#else +#define cpu_has_llsc 1 +#endif + +/* Settings which are common for all ip32 CPUs */ +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_fpu 1 +#define cpu_has_32fpr 1 +#define cpu_has_counter 1 +#define cpu_has_mips16 0 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 +#define cpu_has_vtag_icache 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_has_4k_cache 1 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h new file mode 100644 index 00000000000..a5511ebb2d5 --- /dev/null +++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h @@ -0,0 +1,72 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Ralf Baechle + * + */ +#ifndef __ASM_MACH_IP32_DMA_COHERENCE_H +#define __ASM_MACH_IP32_DMA_COHERENCE_H + +#include + +struct device; + +/* + * Few notes. + * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M + * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for + * native-endian) + * 3. All other devices see memory as one big chunk at 0x40000000 + * 4. Non-PCI devices will pass NULL as struct device* + * + * Thus we translate differently, depending on device. + */ + +#define RAM_OFFSET_MASK 0x3fffffffUL + +static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, + size_t size) +{ + dma_addr_t pa = virt_to_phys(addr) & RAM_OFFSET_MASK; + + if (dev == NULL) + pa += CRIME_HI_MEM_BASE; + + return pa; +} + +static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) +{ + dma_addr_t pa; + + pa = page_to_phys(page) & RAM_OFFSET_MASK; + + if (dev == NULL) + pa += CRIME_HI_MEM_BASE; + + return pa; +} + +/* This is almost certainly wrong but it's what dma-ip32.c used to use */ +static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) +{ + unsigned long addr = dma_addr & RAM_OFFSET_MASK; + + if (dma_addr >= 256*1024*1024) + addr += CRIME_HI_MEM_BASE; + + return addr; +} + +static inline void plat_unmap_dma_mem(dma_addr_t dma_addr) +{ +} + +static inline int plat_device_is_coherent(struct device *dev) +{ + return 0; /* IP32 is non-cohernet */ +} + +#endif /* __ASM_MACH_IP32_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-ip32/kmalloc.h b/arch/mips/include/asm/mach-ip32/kmalloc.h new file mode 100644 index 00000000000..b1e0be60f72 --- /dev/null +++ b/arch/mips/include/asm/mach-ip32/kmalloc.h @@ -0,0 +1,11 @@ +#ifndef __ASM_MACH_IP32_KMALLOC_H +#define __ASM_MACH_IP32_KMALLOC_H + + +#if defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_RM7000) +#define ARCH_KMALLOC_MINALIGN 32 +#else +#define ARCH_KMALLOC_MINALIGN 128 +#endif + +#endif /* __ASM_MACH_IP32_KMALLOC_H */ diff --git a/arch/mips/include/asm/mach-ip32/mangle-port.h b/arch/mips/include/asm/mach-ip32/mangle-port.h new file mode 100644 index 00000000000..f1d0f1756a9 --- /dev/null +++ b/arch/mips/include/asm/mach-ip32/mangle-port.h @@ -0,0 +1,26 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 Ladislav Michl + * Copyright (C) 2004 Ralf Baechle + */ +#ifndef __ASM_MACH_IP32_MANGLE_PORT_H +#define __ASM_MACH_IP32_MANGLE_PORT_H + +#define __swizzle_addr_b(port) ((port) ^ 3) +#define __swizzle_addr_w(port) ((port) ^ 2) +#define __swizzle_addr_l(port) (port) +#define __swizzle_addr_q(port) (port) + +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) (x) +# define __mem_ioswabw(a, x) cpu_to_le16(x) +# define ioswabl(a, x) (x) +# define __mem_ioswabl(a, x) cpu_to_le32(x) +# define ioswabq(a, x) (x) +# define __mem_ioswabq(a, x) cpu_to_le32(x) + +#endif /* __ASM_MACH_IP32_MANGLE_PORT_H */ diff --git a/arch/mips/include/asm/mach-ip32/mc146818rtc.h b/arch/mips/include/asm/mach-ip32/mc146818rtc.h new file mode 100644 index 00000000000..c28ba8d8407 --- /dev/null +++ b/arch/mips/include/asm/mach-ip32/mc146818rtc.h @@ -0,0 +1,36 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2001, 03 by Ralf Baechle + * Copyright (C) 2000 Harald Koerfgen + * + * RTC routines for IP32 style attached Dallas chip. + */ +#ifndef __ASM_MACH_IP32_MC146818RTC_H +#define __ASM_MACH_IP32_MC146818RTC_H + +#include + +#define RTC_PORT(x) (0x70 + (x)) + +static unsigned char CMOS_READ(unsigned long addr) +{ + return mace->isa.rtc[addr << 8]; +} + +static inline void CMOS_WRITE(unsigned char data, unsigned long addr) +{ + mace->isa.rtc[addr << 8] = data; +} + +/* + * FIXME: Do it right. For now just assume that noone lives in 20th century + * and no O2 user in 22th century ;-) + */ +#define mc146818_decode_year(year) ((year) + 2000) + +#define RTC_ALWAYS_BCD 0 + +#endif /* __ASM_MACH_IP32_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-ip32/war.h b/arch/mips/include/asm/mach-ip32/war.h new file mode 100644 index 00000000000..d194056dcd7 --- /dev/null +++ b/arch/mips/include/asm/mach-ip32/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_IP32_WAR_H +#define __ASM_MIPS_MACH_IP32_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 1 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_IP32_WAR_H */ diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h new file mode 100644 index 00000000000..d66979a124a --- /dev/null +++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h @@ -0,0 +1,40 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Ralf Baechle + */ +#ifndef __ASM_MACH_JAZZ_DMA_COHERENCE_H +#define __ASM_MACH_JAZZ_DMA_COHERENCE_H + +#include + +struct device; + +static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) +{ + return vdma_alloc(virt_to_phys(addr), size); +} + +static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) +{ + return vdma_alloc(page_to_phys(page), PAGE_SIZE); +} + +static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) +{ + return vdma_log2phys(dma_addr); +} + +static void plat_unmap_dma_mem(dma_addr_t dma_addr) +{ + vdma_free(dma_addr); +} + +static inline int plat_device_is_coherent(struct device *dev) +{ + return 0; +} + +#endif /* __ASM_MACH_JAZZ_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-jazz/floppy.h b/arch/mips/include/asm/mach-jazz/floppy.h new file mode 100644 index 00000000000..56e9ca6ae42 --- /dev/null +++ b/arch/mips/include/asm/mach-jazz/floppy.h @@ -0,0 +1,135 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2003 by Ralf Baechle + */ +#ifndef __ASM_MACH_JAZZ_FLOPPY_H +#define __ASM_MACH_JAZZ_FLOPPY_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline unsigned char fd_inb(unsigned int port) +{ + unsigned char c; + + c = *(volatile unsigned char *) port; + udelay(1); + + return c; +} + +static inline void fd_outb(unsigned char value, unsigned int port) +{ + *(volatile unsigned char *) port = value; +} + +/* + * How to access the floppy DMA functions. + */ +static inline void fd_enable_dma(void) +{ + vdma_enable(JAZZ_FLOPPY_DMA); +} + +static inline void fd_disable_dma(void) +{ + vdma_disable(JAZZ_FLOPPY_DMA); +} + +static inline int fd_request_dma(void) +{ + return 0; +} + +static inline void fd_free_dma(void) +{ +} + +static inline void fd_clear_dma_ff(void) +{ +} + +static inline void fd_set_dma_mode(char mode) +{ + vdma_set_mode(JAZZ_FLOPPY_DMA, mode); +} + +static inline void fd_set_dma_addr(char *a) +{ + vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(CPHYSADDR((unsigned long)a))); +} + +static inline void fd_set_dma_count(unsigned int count) +{ + vdma_set_count(JAZZ_FLOPPY_DMA, count); +} + +static inline int fd_get_dma_residue(void) +{ + return vdma_get_residue(JAZZ_FLOPPY_DMA); +} + +static inline void fd_enable_irq(void) +{ +} + +static inline void fd_disable_irq(void) +{ +} + +static inline int fd_request_irq(void) +{ + return request_irq(FLOPPY_IRQ, floppy_interrupt, + IRQF_DISABLED, "floppy", NULL); +} + +static inline void fd_free_irq(void) +{ + free_irq(FLOPPY_IRQ, NULL); +} + +static inline unsigned long fd_getfdaddr1(void) +{ + return JAZZ_FDC_BASE; +} + +static inline unsigned long fd_dma_mem_alloc(unsigned long size) +{ + unsigned long mem; + + mem = __get_dma_pages(GFP_KERNEL, get_order(size)); + if(!mem) + return 0; + vdma_alloc(CPHYSADDR(mem), size); /* XXX error checking */ + + return mem; +} + +static inline void fd_dma_mem_free(unsigned long addr, unsigned long size) +{ + vdma_free(vdma_phys2log(CPHYSADDR(addr))); + free_pages(addr, get_order(size)); +} + +static inline unsigned long fd_drive_type(unsigned long n) +{ + /* XXX This is wrong for machines with ED 2.88mb disk drives like the + Olivetti M700. Anyway, we should suck this from the ARC + firmware. */ + if (n == 0) + return 4; /* 3,5", 1.44mb */ + + return 0; +} + +#endif /* __ASM_MACH_JAZZ_FLOPPY_H */ diff --git a/arch/mips/include/asm/mach-jazz/mc146818rtc.h b/arch/mips/include/asm/mach-jazz/mc146818rtc.h new file mode 100644 index 00000000000..987f727afe2 --- /dev/null +++ b/arch/mips/include/asm/mach-jazz/mc146818rtc.h @@ -0,0 +1,38 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2001, 03 by Ralf Baechle + * Copyright (C) 2007 Thomas Bogendoerfer + * + * RTC routines for Jazz style attached Dallas chip. + */ +#ifndef __ASM_MACH_JAZZ_MC146818RTC_H +#define __ASM_MACH_JAZZ_MC146818RTC_H + +#include + +#include +#include + +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_IRQ 8 + +static inline unsigned char CMOS_READ(unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + return *(volatile char *)JAZZ_RTC_BASE; +} + +static inline void CMOS_WRITE(unsigned char data, unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + *(volatile char *)JAZZ_RTC_BASE = data; +} + +#define RTC_ALWAYS_BCD 0 + +#define mc146818_decode_year(year) ((year) + 1980) + +#endif /* __ASM_MACH_JAZZ_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-jazz/war.h b/arch/mips/include/asm/mach-jazz/war.h new file mode 100644 index 00000000000..6158ee861bf --- /dev/null +++ b/arch/mips/include/asm/mach-jazz/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_JAZZ_WAR_H +#define __ASM_MIPS_MACH_JAZZ_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_JAZZ_WAR_H */ diff --git a/arch/mips/include/asm/mach-lasat/irq.h b/arch/mips/include/asm/mach-lasat/irq.h new file mode 100644 index 00000000000..3a282419d5f --- /dev/null +++ b/arch/mips/include/asm/mach-lasat/irq.h @@ -0,0 +1,13 @@ +#ifndef _ASM_MACH_LASAT_IRQ_H +#define _ASM_MACH_LASAT_IRQ_H + +#define LASAT_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 2) + +#define LASAT_IRQ_BASE 8 +#define LASAT_IRQ_END 23 + +#define NR_IRQS 24 + +#include_next + +#endif /* _ASM_MACH_LASAT_IRQ_H */ diff --git a/arch/mips/include/asm/mach-lasat/mach-gt64120.h b/arch/mips/include/asm/mach-lasat/mach-gt64120.h new file mode 100644 index 00000000000..1a9ad45cc13 --- /dev/null +++ b/arch/mips/include/asm/mach-lasat/mach-gt64120.h @@ -0,0 +1,27 @@ +/* + * This is a direct copy of the ev96100.h file, with a global + * search and replace. The numbers are the same. + * + * The reason I'm duplicating this is so that the 64120/96100 + * defines won't be confusing in the source code. + */ +#ifndef _ASM_GT64120_LASAT_GT64120_DEP_H +#define _ASM_GT64120_LASAT_GT64120_DEP_H + +/* + * GT64120 config space base address on Lasat 100 + */ +#define GT64120_BASE (KSEG1ADDR(0x14000000)) + +/* + * PCI Bus allocation + * + * (Guessing ...) + */ +#define GT_PCI_MEM_BASE 0x12000000UL +#define GT_PCI_MEM_SIZE 0x02000000UL +#define GT_PCI_IO_BASE 0x10000000UL +#define GT_PCI_IO_SIZE 0x02000000UL +#define GT_ISA_IO_BASE PCI_IO_BASE + +#endif /* _ASM_GT64120_LASAT_GT64120_DEP_H */ diff --git a/arch/mips/include/asm/mach-lasat/war.h b/arch/mips/include/asm/mach-lasat/war.h new file mode 100644 index 00000000000..bb1e0325c9b --- /dev/null +++ b/arch/mips/include/asm/mach-lasat/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_LASAT_WAR_H +#define __ASM_MIPS_MACH_LASAT_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_LASAT_WAR_H */ diff --git a/arch/mips/include/asm/mach-lemote/dma-coherence.h b/arch/mips/include/asm/mach-lemote/dma-coherence.h new file mode 100644 index 00000000000..7e914777ebc --- /dev/null +++ b/arch/mips/include/asm/mach-lemote/dma-coherence.h @@ -0,0 +1,42 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006, 07 Ralf Baechle + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@lemote.com + * + */ +#ifndef __ASM_MACH_LEMOTE_DMA_COHERENCE_H +#define __ASM_MACH_LEMOTE_DMA_COHERENCE_H + +struct device; + +static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, + size_t size) +{ + return virt_to_phys(addr) | 0x80000000; +} + +static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, + struct page *page) +{ + return page_to_phys(page) | 0x80000000; +} + +static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) +{ + return dma_addr & 0x7fffffff; +} + +static inline void plat_unmap_dma_mem(dma_addr_t dma_addr) +{ +} + +static inline int plat_device_is_coherent(struct device *dev) +{ + return 0; +} + +#endif /* __ASM_MACH_LEMOTE_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-lemote/mc146818rtc.h b/arch/mips/include/asm/mach-lemote/mc146818rtc.h new file mode 100644 index 00000000000..ed5147e1108 --- /dev/null +++ b/arch/mips/include/asm/mach-lemote/mc146818rtc.h @@ -0,0 +1,36 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2001, 03, 07 by Ralf Baechle (ralf@linux-mips.org) + * + * RTC routines for PC style attached Dallas chip. + */ +#ifndef __ASM_MACH_LEMOTE_MC146818RTC_H +#define __ASM_MACH_LEMOTE_MC146818RTC_H + +#include + +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_IRQ 8 + +static inline unsigned char CMOS_READ(unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + return inb_p(RTC_PORT(1)); +} + +static inline void CMOS_WRITE(unsigned char data, unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + outb_p(data, RTC_PORT(1)); +} + +#define RTC_ALWAYS_BCD 0 + +#ifndef mc146818_decode_year +#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970) +#endif + +#endif /* __ASM_MACH_LEMOTE_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-lemote/war.h b/arch/mips/include/asm/mach-lemote/war.h new file mode 100644 index 00000000000..05f89e0f2a1 --- /dev/null +++ b/arch/mips/include/asm/mach-lemote/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_LEMOTE_WAR_H +#define __ASM_MIPS_MACH_LEMOTE_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_LEMOTE_WAR_H */ diff --git a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h new file mode 100644 index 00000000000..7f3e3f9bd23 --- /dev/null +++ b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h @@ -0,0 +1,72 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 2004 Chris Dearman + * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H + + +/* + * CPU feature overrides for MIPS boards + */ +#ifdef CONFIG_CPU_MIPS32 +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_4k_cache 1 +/* #define cpu_has_fpu ? */ +/* #define cpu_has_32fpr ? */ +#define cpu_has_counter 1 +/* #define cpu_has_watch ? */ +#define cpu_has_divec 1 +#define cpu_has_vce 0 +/* #define cpu_has_cache_cdex_p ? */ +/* #define cpu_has_cache_cdex_s ? */ +/* #define cpu_has_prefetch ? */ +#define cpu_has_mcheck 1 +/* #define cpu_has_ejtag ? */ +#ifdef CONFIG_CPU_HAS_LLSC +#define cpu_has_llsc 1 +#else +#define cpu_has_llsc 0 +#endif +/* #define cpu_has_vtag_icache ? */ +/* #define cpu_has_dc_aliases ? */ +/* #define cpu_has_ic_fills_f_dc ? */ +#define cpu_has_nofpuex 0 +/* #define cpu_has_64bits ? */ +/* #define cpu_has_64bit_zero_reg ? */ +/* #define cpu_has_inclusive_pcaches ? */ +#define cpu_icache_snoops_remote_store 1 +#endif + +#ifdef CONFIG_CPU_MIPS64 +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_4k_cache 1 +/* #define cpu_has_fpu ? */ +/* #define cpu_has_32fpr ? */ +#define cpu_has_counter 1 +/* #define cpu_has_watch ? */ +#define cpu_has_divec 1 +#define cpu_has_vce 0 +/* #define cpu_has_cache_cdex_p ? */ +/* #define cpu_has_cache_cdex_s ? */ +/* #define cpu_has_prefetch ? */ +#define cpu_has_mcheck 1 +/* #define cpu_has_ejtag ? */ +#define cpu_has_llsc 1 +/* #define cpu_has_vtag_icache ? */ +/* #define cpu_has_dc_aliases ? */ +/* #define cpu_has_ic_fills_f_dc ? */ +#define cpu_has_nofpuex 0 +/* #define cpu_has_64bits ? */ +/* #define cpu_has_64bit_zero_reg ? */ +/* #define cpu_has_inclusive_pcaches ? */ +#define cpu_icache_snoops_remote_store 1 +#endif + +#endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-malta/irq.h b/arch/mips/include/asm/mach-malta/irq.h new file mode 100644 index 00000000000..9b9da26683c --- /dev/null +++ b/arch/mips/include/asm/mach-malta/irq.h @@ -0,0 +1,9 @@ +#ifndef __ASM_MACH_MIPS_IRQ_H +#define __ASM_MACH_MIPS_IRQ_H + + +#define NR_IRQS 256 + +#include_next + +#endif /* __ASM_MACH_MIPS_IRQ_H */ diff --git a/arch/mips/include/asm/mach-malta/kernel-entry-init.h b/arch/mips/include/asm/mach-malta/kernel-entry-init.h new file mode 100644 index 00000000000..0b793e7bf67 --- /dev/null +++ b/arch/mips/include/asm/mach-malta/kernel-entry-init.h @@ -0,0 +1,52 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Chris Dearman (chris@mips.com) + * Copyright (C) 2007 Mips Technologies, Inc. + */ +#ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H +#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H + + .macro kernel_entry_setup +#ifdef CONFIG_MIPS_MT_SMTC + mfc0 t0, CP0_CONFIG + bgez t0, 9f + mfc0 t0, CP0_CONFIG, 1 + bgez t0, 9f + mfc0 t0, CP0_CONFIG, 2 + bgez t0, 9f + mfc0 t0, CP0_CONFIG, 3 + and t0, 1<<2 + bnez t0, 0f +9: + /* Assume we came from YAMON... */ + PTR_LA v0, 0x9fc00534 /* YAMON print */ + lw v0, (v0) + move a0, zero + PTR_LA a1, nonmt_processor + jal v0 + + PTR_LA v0, 0x9fc00520 /* YAMON exit */ + lw v0, (v0) + li a0, 1 + jal v0 + +1: b 1b + + __INITDATA +nonmt_processor: + .asciz "SMTC kernel requires the MT ASE to run\n" + __FINIT +0: +#endif + .endm + +/* + * Do SMP slave processor setup necessary before we can safely execute C code. + */ + .macro smp_slave_setup + .endm + +#endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */ diff --git a/arch/mips/include/asm/mach-malta/mach-gt64120.h b/arch/mips/include/asm/mach-malta/mach-gt64120.h new file mode 100644 index 00000000000..0f863148f3b --- /dev/null +++ b/arch/mips/include/asm/mach-malta/mach-gt64120.h @@ -0,0 +1,19 @@ +/* + * This is a direct copy of the ev96100.h file, with a global + * search and replace. The numbers are the same. + * + * The reason I'm duplicating this is so that the 64120/96100 + * defines won't be confusing in the source code. + */ +#ifndef _ASM_MACH_MIPS_MACH_GT64120_DEP_H +#define _ASM_MACH_MIPS_MACH_GT64120_DEP_H + +#define MIPS_GT_BASE 0x1be00000 + +extern unsigned long _pcictrl_gt64120; +/* + * GT64120 config space base address + */ +#define GT64120_BASE _pcictrl_gt64120 + +#endif /* _ASM_MACH_MIPS_MACH_GT64120_DEP_H */ diff --git a/arch/mips/include/asm/mach-malta/mc146818rtc.h b/arch/mips/include/asm/mach-malta/mc146818rtc.h new file mode 100644 index 00000000000..ea612f37f61 --- /dev/null +++ b/arch/mips/include/asm/mach-malta/mc146818rtc.h @@ -0,0 +1,48 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2003 by Ralf Baechle + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * RTC routines for Malta style attached PIIX4 device, which contains a + * Motorola MC146818A-compatible Real Time Clock. + */ +#ifndef __ASM_MACH_MALTA_MC146818RTC_H +#define __ASM_MACH_MALTA_MC146818RTC_H + +#include +#include +#include + +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_IRQ 8 + +static inline unsigned char CMOS_READ(unsigned long addr) +{ + outb(addr, MALTA_RTC_ADR_REG); + return inb(MALTA_RTC_DAT_REG); +} + +static inline void CMOS_WRITE(unsigned char data, unsigned long addr) +{ + outb(addr, MALTA_RTC_ADR_REG); + outb(data, MALTA_RTC_DAT_REG); +} + +#define RTC_ALWAYS_BCD 0 + +#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1900) + +#endif /* __ASM_MACH_MALTA_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-malta/war.h b/arch/mips/include/asm/mach-malta/war.h new file mode 100644 index 00000000000..7c6931d5f45 --- /dev/null +++ b/arch/mips/include/asm/mach-malta/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_MIPS_WAR_H +#define __ASM_MIPS_MACH_MIPS_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 1 +#define MIPS_CACHE_SYNC_WAR 1 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 1 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_MIPS_WAR_H */ diff --git a/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h new file mode 100644 index 00000000000..779b0220573 --- /dev/null +++ b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h @@ -0,0 +1,65 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 2004 Chris Dearman + */ +#ifndef __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H + + +/* + * CPU feature overrides for MIPS boards + */ +#ifdef CONFIG_CPU_MIPS32 +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_4k_cache 1 +#define cpu_has_fpu 0 +/* #define cpu_has_32fpr ? */ +#define cpu_has_counter 1 +/* #define cpu_has_watch ? */ +#define cpu_has_divec 1 +#define cpu_has_vce 0 +/* #define cpu_has_cache_cdex_p ? */ +/* #define cpu_has_cache_cdex_s ? */ +/* #define cpu_has_prefetch ? */ +#define cpu_has_mcheck 1 +/* #define cpu_has_ejtag ? */ +#define cpu_has_llsc 1 +/* #define cpu_has_vtag_icache ? */ +/* #define cpu_has_dc_aliases ? */ +/* #define cpu_has_ic_fills_f_dc ? */ +#define cpu_has_nofpuex 0 +/* #define cpu_has_64bits ? */ +/* #define cpu_has_64bit_zero_reg ? */ +/* #define cpu_has_inclusive_pcaches ? */ +#endif + +#ifdef CONFIG_CPU_MIPS64 +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_4k_cache 1 +/* #define cpu_has_fpu ? */ +/* #define cpu_has_32fpr ? */ +#define cpu_has_counter 1 +/* #define cpu_has_watch ? */ +#define cpu_has_divec 1 +#define cpu_has_vce 0 +/* #define cpu_has_cache_cdex_p ? */ +/* #define cpu_has_cache_cdex_s ? */ +/* #define cpu_has_prefetch ? */ +#define cpu_has_mcheck 1 +/* #define cpu_has_ejtag ? */ +#define cpu_has_llsc 1 +/* #define cpu_has_vtag_icache ? */ +/* #define cpu_has_dc_aliases ? */ +/* #define cpu_has_ic_fills_f_dc ? */ +#define cpu_has_nofpuex 0 +/* #define cpu_has_64bits ? */ +/* #define cpu_has_64bit_zero_reg ? */ +/* #define cpu_has_inclusive_pcaches ? */ +#endif + +#endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-mipssim/war.h b/arch/mips/include/asm/mach-mipssim/war.h new file mode 100644 index 00000000000..c8a74a3515e --- /dev/null +++ b/arch/mips/include/asm/mach-mipssim/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_MIPSSIM_WAR_H +#define __ASM_MIPS_MACH_MIPSSIM_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_MIPSSIM_WAR_H */ diff --git a/arch/mips/include/asm/mach-pb1x00/mc146818rtc.h b/arch/mips/include/asm/mach-pb1x00/mc146818rtc.h new file mode 100644 index 00000000000..622c58710e5 --- /dev/null +++ b/arch/mips/include/asm/mach-pb1x00/mc146818rtc.h @@ -0,0 +1,34 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 2001, 03 by Ralf Baechle + * + * RTC routines for PC style attached Dallas chip. + */ +#ifndef __ASM_MACH_AU1XX_MC146818RTC_H +#define __ASM_MACH_AU1XX_MC146818RTC_H + +#include +#include + +#define RTC_PORT(x) (0x0c000000 + (x)) +#define RTC_IRQ 8 +#define PB1500_RTC_ADDR 0x0c000000 + +static inline unsigned char CMOS_READ(unsigned long offset) +{ + offset <<= 2; + return (u8)(au_readl(offset + PB1500_RTC_ADDR) & 0xff); +} + +static inline void CMOS_WRITE(unsigned char data, unsigned long offset) +{ + offset <<= 2; + au_writel(data, offset + PB1500_RTC_ADDR); +} + +#define RTC_ALWAYS_BCD 1 + +#endif /* __ASM_MACH_AU1XX_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-pb1x00/pb1000.h b/arch/mips/include/asm/mach-pb1x00/pb1000.h new file mode 100644 index 00000000000..6d1ff9060e4 --- /dev/null +++ b/arch/mips/include/asm/mach-pb1x00/pb1000.h @@ -0,0 +1,87 @@ +/* + * Alchemy Semi Pb1000 Referrence Board + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_PB1000_H +#define __ASM_PB1000_H + +/* PCMCIA PB1000 specific defines */ +#define PCMCIA_MAX_SOCK 1 +#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) + +#define PB1000_PCR 0xBE000000 +# define PCR_SLOT_0_VPP0 (1 << 0) +# define PCR_SLOT_0_VPP1 (1 << 1) +# define PCR_SLOT_0_VCC0 (1 << 2) +# define PCR_SLOT_0_VCC1 (1 << 3) +# define PCR_SLOT_0_RST (1 << 4) +# define PCR_SLOT_1_VPP0 (1 << 8) +# define PCR_SLOT_1_VPP1 (1 << 9) +# define PCR_SLOT_1_VCC0 (1 << 10) +# define PCR_SLOT_1_VCC1 (1 << 11) +# define PCR_SLOT_1_RST (1 << 12) + +#define PB1000_MDR 0xBE000004 +# define MDR_PI (1 << 5) /* PCMCIA int latch */ +# define MDR_EPI (1 << 14) /* enable PCMCIA int */ +# define MDR_CPI (1 << 15) /* clear PCMCIA int */ + +#define PB1000_ACR1 0xBE000008 +# define ACR1_SLOT_0_CD1 (1 << 0) /* card detect 1 */ +# define ACR1_SLOT_0_CD2 (1 << 1) /* card detect 2 */ +# define ACR1_SLOT_0_READY (1 << 2) /* ready */ +# define ACR1_SLOT_0_STATUS (1 << 3) /* status change */ +# define ACR1_SLOT_0_VS1 (1 << 4) /* voltage sense 1 */ +# define ACR1_SLOT_0_VS2 (1 << 5) /* voltage sense 2 */ +# define ACR1_SLOT_0_INPACK (1 << 6) /* inpack pin status */ +# define ACR1_SLOT_1_CD1 (1 << 8) /* card detect 1 */ +# define ACR1_SLOT_1_CD2 (1 << 9) /* card detect 2 */ +# define ACR1_SLOT_1_READY (1 << 10) /* ready */ +# define ACR1_SLOT_1_STATUS (1 << 11) /* status change */ +# define ACR1_SLOT_1_VS1 (1 << 12) /* voltage sense 1 */ +# define ACR1_SLOT_1_VS2 (1 << 13) /* voltage sense 2 */ +# define ACR1_SLOT_1_INPACK (1 << 14) /* inpack pin status */ + +#define CPLD_AUX0 0xBE00000C +#define CPLD_AUX1 0xBE000010 +#define CPLD_AUX2 0xBE000014 + +/* Voltage levels */ + +/* VPPEN1 - VPPEN0 */ +#define VPP_GND ((0 << 1) | (0 << 0)) +#define VPP_5V ((1 << 1) | (0 << 0)) +#define VPP_3V ((0 << 1) | (1 << 0)) +#define VPP_12V ((0 << 1) | (1 << 0)) +#define VPP_HIZ ((1 << 1) | (1 << 0)) + +/* VCCEN1 - VCCEN0 */ +#define VCC_3V ((0 << 1) | (1 << 0)) +#define VCC_5V ((1 << 1) | (0 << 0)) +#define VCC_HIZ ((0 << 1) | (0 << 0)) + +/* VPP/VCC */ +#define SET_VCC_VPP(VCC, VPP, SLOT) \ + ((((VCC) << 2) | ((VPP) << 0)) << ((SLOT) * 8)) +#endif /* __ASM_PB1000_H */ diff --git a/arch/mips/include/asm/mach-pb1x00/pb1100.h b/arch/mips/include/asm/mach-pb1x00/pb1100.h new file mode 100644 index 00000000000..b1a60f1cbd0 --- /dev/null +++ b/arch/mips/include/asm/mach-pb1x00/pb1100.h @@ -0,0 +1,85 @@ +/* + * Alchemy Semi Pb1100 Referrence Board + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_PB1100_H +#define __ASM_PB1100_H + +#define PB1100_IDENT 0xAE000000 +#define BOARD_STATUS_REG 0xAE000004 +# define PB1100_ROM_SEL (1 << 15) +# define PB1100_ROM_SIZ (1 << 14) +# define PB1100_SWAP_BOOT (1 << 13) +# define PB1100_FLASH_WP (1 << 12) +# define PB1100_ROM_H_STS (1 << 11) +# define PB1100_ROM_L_STS (1 << 10) +# define PB1100_FLASH_H_STS (1 << 9) +# define PB1100_FLASH_L_STS (1 << 8) +# define PB1100_SRAM_SIZ (1 << 7) +# define PB1100_TSC_BUSY (1 << 6) +# define PB1100_PCMCIA_VS_MASK (3 << 4) +# define PB1100_RS232_CD (1 << 3) +# define PB1100_RS232_CTS (1 << 2) +# define PB1100_RS232_DSR (1 << 1) +# define PB1100_RS232_RI (1 << 0) + +#define PB1100_IRDA_RS232 0xAE00000C +# define PB1100_IRDA_FULL (0 << 14) /* full power */ +# define PB1100_IRDA_SHUTDOWN (1 << 14) +# define PB1100_IRDA_TT (2 << 14) /* 2/3 power */ +# define PB1100_IRDA_OT (3 << 14) /* 1/3 power */ +# define PB1100_IRDA_FIR (1 << 13) + +#define PCMCIA_BOARD_REG 0xAE000010 +# define PB1100_SD_WP1_RO (1 << 15) /* read only */ +# define PB1100_SD_WP0_RO (1 << 14) /* read only */ +# define PB1100_SD_PWR1 (1 << 11) /* applies power to SD1 */ +# define PB1100_SD_PWR0 (1 << 10) /* applies power to SD0 */ +# define PB1100_SEL_SD_CONN1 (1 << 9) +# define PB1100_SEL_SD_CONN0 (1 << 8) +# define PC_DEASSERT_RST (1 << 7) +# define PC_DRV_EN (1 << 4) + +#define PB1100_G_CONTROL 0xAE000014 /* graphics control */ + +#define PB1100_RST_VDDI 0xAE00001C +# define PB1100_SOFT_RESET (1 << 15) /* clear to reset the board */ +# define PB1100_VDDI_MASK 0x1F + +#define PB1100_LEDS 0xAE000018 + +/* + * 11:8 is 4 discreet LEDs. Clearing a bit illuminates the LED. + * 7:0 is the LED Display's decimal points. + */ +#define PB1100_HEX_LED 0xAE000018 + +/* PCMCIA Pb1100 specific defines */ +#define PCMCIA_MAX_SOCK 0 +#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) + +/* VPP/VCC */ +#define SET_VCC_VPP(VCC, VPP) (((VCC) << 2) | ((VPP) << 0)) + +#endif /* __ASM_PB1100_H */ diff --git a/arch/mips/include/asm/mach-pb1x00/pb1200.h b/arch/mips/include/asm/mach-pb1x00/pb1200.h new file mode 100644 index 00000000000..c8618df88cb --- /dev/null +++ b/arch/mips/include/asm/mach-pb1x00/pb1200.h @@ -0,0 +1,259 @@ +/* + * AMD Alchemy Pb1200 Referrence Board + * Board Registers defines. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_PB1200_H +#define __ASM_PB1200_H + +#include +#include + +#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX +#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX +#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC1_TX +#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC1_RX + +/* + * SPI and SMB are muxed on the Pb1200 board. + * Refer to board documentation. + */ +#define SPI_PSC_BASE PSC0_BASE_ADDR +#define SMBUS_PSC_BASE PSC0_BASE_ADDR +/* + * AC97 and I2S are muxed on the Pb1200 board. + * Refer to board documentation. + */ +#define AC97_PSC_BASE PSC1_BASE_ADDR +#define I2S_PSC_BASE PSC1_BASE_ADDR + +#define BCSR_KSEG1_ADDR 0xAD800000 + +typedef volatile struct +{ + /*00*/ u16 whoami; + u16 reserved0; + /*04*/ u16 status; + u16 reserved1; + /*08*/ u16 switches; + u16 reserved2; + /*0C*/ u16 resets; + u16 reserved3; + + /*10*/ u16 pcmcia; + u16 reserved4; + /*14*/ u16 board; + u16 reserved5; + /*18*/ u16 disk_leds; + u16 reserved6; + /*1C*/ u16 system; + u16 reserved7; + + /*20*/ u16 intclr; + u16 reserved8; + /*24*/ u16 intset; + u16 reserved9; + /*28*/ u16 intclr_mask; + u16 reserved10; + /*2C*/ u16 intset_mask; + u16 reserved11; + + /*30*/ u16 sig_status; + u16 reserved12; + /*34*/ u16 int_status; + u16 reserved13; + /*38*/ u16 reserved14; + u16 reserved15; + /*3C*/ u16 reserved16; + u16 reserved17; + +} BCSR; + +static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; + +/* + * Register bit definitions for the BCSRs + */ +#define BCSR_WHOAMI_DCID 0x000F +#define BCSR_WHOAMI_CPLD 0x00F0 +#define BCSR_WHOAMI_BOARD 0x0F00 + +#define BCSR_STATUS_PCMCIA0VS 0x0003 +#define BCSR_STATUS_PCMCIA1VS 0x000C +#define BCSR_STATUS_SWAPBOOT 0x0040 +#define BCSR_STATUS_FLASHBUSY 0x0100 +#define BCSR_STATUS_IDECBLID 0x0200 +#define BCSR_STATUS_SD0WP 0x0400 +#define BCSR_STATUS_SD1WP 0x0800 +#define BCSR_STATUS_U0RXD 0x1000 +#define BCSR_STATUS_U1RXD 0x2000 + +#define BCSR_SWITCHES_OCTAL 0x00FF +#define BCSR_SWITCHES_DIP_1 0x0080 +#define BCSR_SWITCHES_DIP_2 0x0040 +#define BCSR_SWITCHES_DIP_3 0x0020 +#define BCSR_SWITCHES_DIP_4 0x0010 +#define BCSR_SWITCHES_DIP_5 0x0008 +#define BCSR_SWITCHES_DIP_6 0x0004 +#define BCSR_SWITCHES_DIP_7 0x0002 +#define BCSR_SWITCHES_DIP_8 0x0001 +#define BCSR_SWITCHES_ROTARY 0x0F00 + +#define BCSR_RESETS_ETH 0x0001 +#define BCSR_RESETS_CAMERA 0x0002 +#define BCSR_RESETS_DC 0x0004 +#define BCSR_RESETS_IDE 0x0008 +/* not resets but in the same register */ +#define BCSR_RESETS_WSCFSM 0x0800 +#define BCSR_RESETS_PCS0MUX 0x1000 +#define BCSR_RESETS_PCS1MUX 0x2000 +#define BCSR_RESETS_SPISEL 0x4000 +#define BCSR_RESETS_SD1MUX 0x8000 + +#define BCSR_PCMCIA_PC0VPP 0x0003 +#define BCSR_PCMCIA_PC0VCC 0x000C +#define BCSR_PCMCIA_PC0DRVEN 0x0010 +#define BCSR_PCMCIA_PC0RST 0x0080 +#define BCSR_PCMCIA_PC1VPP 0x0300 +#define BCSR_PCMCIA_PC1VCC 0x0C00 +#define BCSR_PCMCIA_PC1DRVEN 0x1000 +#define BCSR_PCMCIA_PC1RST 0x8000 + +#define BCSR_BOARD_LCDVEE 0x0001 +#define BCSR_BOARD_LCDVDD 0x0002 +#define BCSR_BOARD_LCDBL 0x0004 +#define BCSR_BOARD_CAMSNAP 0x0010 +#define BCSR_BOARD_CAMPWR 0x0020 +#define BCSR_BOARD_SD0PWR 0x0040 +#define BCSR_BOARD_SD1PWR 0x0080 + +#define BCSR_LEDS_DECIMALS 0x00FF +#define BCSR_LEDS_LED0 0x0100 +#define BCSR_LEDS_LED1 0x0200 +#define BCSR_LEDS_LED2 0x0400 +#define BCSR_LEDS_LED3 0x0800 + +#define BCSR_SYSTEM_VDDI 0x001F +#define BCSR_SYSTEM_POWEROFF 0x4000 +#define BCSR_SYSTEM_RESET 0x8000 + +/* Bit positions for the different interrupt sources */ +#define BCSR_INT_IDE 0x0001 +#define BCSR_INT_ETH 0x0002 +#define BCSR_INT_PC0 0x0004 +#define BCSR_INT_PC0STSCHG 0x0008 +#define BCSR_INT_PC1 0x0010 +#define BCSR_INT_PC1STSCHG 0x0020 +#define BCSR_INT_DC 0x0040 +#define BCSR_INT_FLASHBUSY 0x0080 +#define BCSR_INT_PC0INSERT 0x0100 +#define BCSR_INT_PC0EJECT 0x0200 +#define BCSR_INT_PC1INSERT 0x0400 +#define BCSR_INT_PC1EJECT 0x0800 +#define BCSR_INT_SD0INSERT 0x1000 +#define BCSR_INT_SD0EJECT 0x2000 +#define BCSR_INT_SD1INSERT 0x4000 +#define BCSR_INT_SD1EJECT 0x8000 + +#define SMC91C111_PHYS_ADDR 0x0D000300 +#define SMC91C111_INT PB1200_ETH_INT + +#define IDE_PHYS_ADDR 0x0C800000 +#define IDE_REG_SHIFT 5 +#define IDE_PHYS_LEN (16 << IDE_REG_SHIFT) +#define IDE_INT PB1200_IDE_INT +#define IDE_DDMA_REQ DSCR_CMD0_DMA_REQ1 +#define IDE_RQSIZE 128 + +#define NAND_PHYS_ADDR 0x1C000000 + +/* + * Timing values as described in databook, * ns value stripped of + * lower 2 bits. + * These defines are here rather than an Au1200 generic file because + * the parts chosen on another board may be different and may require + * different timings. + */ +#define NAND_T_H (18 >> 2) +#define NAND_T_PUL (30 >> 2) +#define NAND_T_SU (30 >> 2) +#define NAND_T_WH (30 >> 2) + +/* Bitfield shift amounts */ +#define NAND_T_H_SHIFT 0 +#define NAND_T_PUL_SHIFT 4 +#define NAND_T_SU_SHIFT 8 +#define NAND_T_WH_SHIFT 12 + +#define NAND_TIMING (((NAND_T_H & 0xF) << NAND_T_H_SHIFT) | \ + ((NAND_T_PUL & 0xF) << NAND_T_PUL_SHIFT) | \ + ((NAND_T_SU & 0xF) << NAND_T_SU_SHIFT) | \ + ((NAND_T_WH & 0xF) << NAND_T_WH_SHIFT)) + +/* + * External Interrupts for Pb1200 as of 8/6/2004. + * Bit positions in the CPLD registers can be calculated by taking + * the interrupt define and subtracting the PB1200_INT_BEGIN value. + * + * Example: IDE bis pos is = 64 - 64 + * ETH bit pos is = 65 - 64 + */ +enum external_pb1200_ints { + PB1200_INT_BEGIN = AU1000_MAX_INTR + 1, + + PB1200_IDE_INT = PB1200_INT_BEGIN, + PB1200_ETH_INT, + PB1200_PC0_INT, + PB1200_PC0_STSCHG_INT, + PB1200_PC1_INT, + PB1200_PC1_STSCHG_INT, + PB1200_DC_INT, + PB1200_FLASHBUSY_INT, + PB1200_PC0_INSERT_INT, + PB1200_PC0_EJECT_INT, + PB1200_PC1_INSERT_INT, + PB1200_PC1_EJECT_INT, + PB1200_SD0_INSERT_INT, + PB1200_SD0_EJECT_INT, + PB1200_SD1_INSERT_INT, + PB1200_SD1_EJECT_INT, + + PB1200_INT_END = PB1200_INT_BEGIN + 15 +}; + +/* + * Pb1200 specific PCMCIA defines for drivers/pcmcia/au1000_db1x00.c + */ +#define PCMCIA_MAX_SOCK 1 +#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) + +/* VPP/VCC */ +#define SET_VCC_VPP(VCC, VPP, SLOT) \ + ((((VCC) << 2) | ((VPP) << 0)) << ((SLOT) * 8)) + +#define BOARD_PC0_INT PB1200_PC0_INT +#define BOARD_PC1_INT PB1200_PC1_INT +#define BOARD_CARD_INSERTED(SOCKET) bcsr->sig_status & (1 << (8 + (2 * SOCKET))) + +/* NAND chip select */ +#define NAND_CS 1 + +#endif /* __ASM_PB1200_H */ diff --git a/arch/mips/include/asm/mach-pb1x00/pb1500.h b/arch/mips/include/asm/mach-pb1x00/pb1500.h new file mode 100644 index 00000000000..da51a2eb7b8 --- /dev/null +++ b/arch/mips/include/asm/mach-pb1x00/pb1500.h @@ -0,0 +1,49 @@ +/* + * Alchemy Semi Pb1500 Referrence Board + * + * Copyright 2001, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_PB1500_H +#define __ASM_PB1500_H + +#define IDENT_BOARD_REG 0xAE000000 +#define BOARD_STATUS_REG 0xAE000004 +#define PCI_BOARD_REG 0xAE000010 +#define PCMCIA_BOARD_REG 0xAE000010 +# define PC_DEASSERT_RST 0x80 +# define PC_DRV_EN 0x10 +#define PB1500_G_CONTROL 0xAE000014 +#define PB1500_RST_VDDI 0xAE00001C +#define PB1500_LEDS 0xAE000018 + +#define PB1500_HEX_LED 0xAF000004 +#define PB1500_HEX_LED_BLANK 0xAF000008 + +/* PCMCIA Pb1500 specific defines */ +#define PCMCIA_MAX_SOCK 0 +#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) + +/* VPP/VCC */ +#define SET_VCC_VPP(VCC, VPP) (((VCC) << 2) | ((VPP) << 0)) + +#endif /* __ASM_PB1500_H */ diff --git a/arch/mips/include/asm/mach-pb1x00/pb1550.h b/arch/mips/include/asm/mach-pb1x00/pb1550.h new file mode 100644 index 00000000000..6704a11497d --- /dev/null +++ b/arch/mips/include/asm/mach-pb1x00/pb1550.h @@ -0,0 +1,177 @@ +/* + * AMD Alchemy Semi PB1550 Referrence Board + * Board Registers defines. + * + * Copyright 2004 Embedded Edge LLC. + * Copyright 2005 Ralf Baechle (ralf@linux-mips.org) + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_PB1550_H +#define __ASM_PB1550_H + +#include +#include + +#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX +#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX +#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC3_TX +#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC3_RX + +#define SPI_PSC_BASE PSC0_BASE_ADDR +#define AC97_PSC_BASE PSC1_BASE_ADDR +#define SMBUS_PSC_BASE PSC2_BASE_ADDR +#define I2S_PSC_BASE PSC3_BASE_ADDR + +#define BCSR_PHYS_ADDR 0xAF000000 + +typedef volatile struct +{ + /*00*/ u16 whoami; + u16 reserved0; + /*04*/ u16 status; + u16 reserved1; + /*08*/ u16 switches; + u16 reserved2; + /*0C*/ u16 resets; + u16 reserved3; + /*10*/ u16 pcmcia; + u16 reserved4; + /*14*/ u16 pci; + u16 reserved5; + /*18*/ u16 leds; + u16 reserved6; + /*1C*/ u16 system; + u16 reserved7; + +} BCSR; + +static BCSR * const bcsr = (BCSR *)BCSR_PHYS_ADDR; + +/* + * Register bit definitions for the BCSRs + */ +#define BCSR_WHOAMI_DCID 0x000F +#define BCSR_WHOAMI_CPLD 0x00F0 +#define BCSR_WHOAMI_BOARD 0x0F00 + +#define BCSR_STATUS_PCMCIA0VS 0x0003 +#define BCSR_STATUS_PCMCIA1VS 0x000C +#define BCSR_STATUS_PCMCIA0FI 0x0010 +#define BCSR_STATUS_PCMCIA1FI 0x0020 +#define BCSR_STATUS_SWAPBOOT 0x0040 +#define BCSR_STATUS_SRAMWIDTH 0x0080 +#define BCSR_STATUS_FLASHBUSY 0x0100 +#define BCSR_STATUS_ROMBUSY 0x0200 +#define BCSR_STATUS_USBOTGID 0x0800 +#define BCSR_STATUS_U0RXD 0x1000 +#define BCSR_STATUS_U1RXD 0x2000 +#define BCSR_STATUS_U3RXD 0x8000 + +#define BCSR_SWITCHES_OCTAL 0x00FF +#define BCSR_SWITCHES_DIP_1 0x0080 +#define BCSR_SWITCHES_DIP_2 0x0040 +#define BCSR_SWITCHES_DIP_3 0x0020 +#define BCSR_SWITCHES_DIP_4 0x0010 +#define BCSR_SWITCHES_DIP_5 0x0008 +#define BCSR_SWITCHES_DIP_6 0x0004 +#define BCSR_SWITCHES_DIP_7 0x0002 +#define BCSR_SWITCHES_DIP_8 0x0001 +#define BCSR_SWITCHES_ROTARY 0x0F00 + +#define BCSR_RESETS_PHY0 0x0001 +#define BCSR_RESETS_PHY1 0x0002 +#define BCSR_RESETS_DC 0x0004 +#define BCSR_RESETS_WSC 0x2000 +#define BCSR_RESETS_SPISEL 0x4000 +#define BCSR_RESETS_DMAREQ 0x8000 + +#define BCSR_PCMCIA_PC0VPP 0x0003 +#define BCSR_PCMCIA_PC0VCC 0x000C +#define BCSR_PCMCIA_PC0DRVEN 0x0010 +#define BCSR_PCMCIA_PC0RST 0x0080 +#define BCSR_PCMCIA_PC1VPP 0x0300 +#define BCSR_PCMCIA_PC1VCC 0x0C00 +#define BCSR_PCMCIA_PC1DRVEN 0x1000 +#define BCSR_PCMCIA_PC1RST 0x8000 + +#define BCSR_PCI_M66EN 0x0001 +#define BCSR_PCI_M33 0x0100 +#define BCSR_PCI_EXTERNARB 0x0200 +#define BCSR_PCI_GPIO200RST 0x0400 +#define BCSR_PCI_CLKOUT 0x0800 +#define BCSR_PCI_CFGHOST 0x1000 + +#define BCSR_LEDS_DECIMALS 0x00FF +#define BCSR_LEDS_LED0 0x0100 +#define BCSR_LEDS_LED1 0x0200 +#define BCSR_LEDS_LED2 0x0400 +#define BCSR_LEDS_LED3 0x0800 + +#define BCSR_SYSTEM_VDDI 0x001F +#define BCSR_SYSTEM_POWEROFF 0x4000 +#define BCSR_SYSTEM_RESET 0x8000 + +#define PCMCIA_MAX_SOCK 1 +#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) + +/* VPP/VCC */ +#define SET_VCC_VPP(VCC, VPP, SLOT) \ + ((((VCC) << 2) | ((VPP) << 0)) << ((SLOT) * 8)) + +#if defined(CONFIG_MTD_PB1550_BOOT) && defined(CONFIG_MTD_PB1550_USER) +#define PB1550_BOTH_BANKS +#elif defined(CONFIG_MTD_PB1550_BOOT) && !defined(CONFIG_MTD_PB1550_USER) +#define PB1550_BOOT_ONLY +#elif !defined(CONFIG_MTD_PB1550_BOOT) && defined(CONFIG_MTD_PB1550_USER) +#define PB1550_USER_ONLY +#endif + +/* + * Timing values as described in databook, * ns value stripped of + * lower 2 bits. + * These defines are here rather than an SOC1550 generic file because + * the parts chosen on another board may be different and may require + * different timings. + */ +#define NAND_T_H (18 >> 2) +#define NAND_T_PUL (30 >> 2) +#define NAND_T_SU (30 >> 2) +#define NAND_T_WH (30 >> 2) + +/* Bitfield shift amounts */ +#define NAND_T_H_SHIFT 0 +#define NAND_T_PUL_SHIFT 4 +#define NAND_T_SU_SHIFT 8 +#define NAND_T_WH_SHIFT 12 + +#define NAND_TIMING (((NAND_T_H & 0xF) << NAND_T_H_SHIFT) | \ + ((NAND_T_PUL & 0xF) << NAND_T_PUL_SHIFT) | \ + ((NAND_T_SU & 0xF) << NAND_T_SU_SHIFT) | \ + ((NAND_T_WH & 0xF) << NAND_T_WH_SHIFT)) + +#define NAND_CS 1 + +/* Should be done by YAMON */ +#define NAND_STCFG 0x00400005 /* 8-bit NAND */ +#define NAND_STTIME 0x00007774 /* valid for 396 MHz SD=2 only */ +#define NAND_STADDR 0x12000FFF /* physical address 0x20000000 */ + +#endif /* __ASM_PB1550_H */ diff --git a/arch/mips/include/asm/mach-pnx8550/cm.h b/arch/mips/include/asm/mach-pnx8550/cm.h new file mode 100644 index 00000000000..bb0a56c7d01 --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/cm.h @@ -0,0 +1,43 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Clock module specific definitions + * + * Author: source@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 __PNX8550_CM_H +#define __PNX8550_CM_H + +#define PNX8550_CM_BASE 0xBBE47000 + +#define PNX8550_CM_PLL0_CTL *(volatile unsigned long *)(PNX8550_CM_BASE + 0x000) +#define PNX8550_CM_PLL1_CTL *(volatile unsigned long *)(PNX8550_CM_BASE + 0x004) +#define PNX8550_CM_PLL2_CTL *(volatile unsigned long *)(PNX8550_CM_BASE + 0x008) +#define PNX8550_CM_PLL3_CTL *(volatile unsigned long *)(PNX8550_CM_BASE + 0x00C) + +// Table not complete..... + +#define PNX8550_CM_PLL_BLOCKED_MASK 0x80000000 +#define PNX8550_CM_PLL_LOCK_MASK 0x40000000 +#define PNX8550_CM_PLL_CURRENT_ADJ_MASK 0x3c000000 +#define PNX8550_CM_PLL_N_MASK 0x01ff0000 +#define PNX8550_CM_PLL_M_MASK 0x00003f00 +#define PNX8550_CM_PLL_P_MASK 0x0000000c +#define PNX8550_CM_PLL_PD_MASK 0x00000002 + + +#endif diff --git a/arch/mips/include/asm/mach-pnx8550/glb.h b/arch/mips/include/asm/mach-pnx8550/glb.h new file mode 100644 index 00000000000..07aa85e609b --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/glb.h @@ -0,0 +1,86 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PNX8550 global definitions + * + * Author: source@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 __PNX8550_GLB_H +#define __PNX8550_GLB_H + +#define PNX8550_GLB1_BASE 0xBBE63000 +#define PNX8550_GLB2_BASE 0xBBE4d000 +#define PNX8550_RESET_BASE 0xBBE60000 + +/* PCI Inta Output Enable Registers */ +#define PNX8550_GLB2_ENAB_INTA_O *(volatile unsigned long *)(PNX8550_GLB2_BASE + 0x050) + +/* Bit 1:Enable DAC Powerdown + 0:DACs are enabled and are working normally + 1:DACs are powerdown +*/ +#define PNX8550_GLB_DAC_PD 0x2 +/* Bit 0:Enable of PCI inta output + 0 = Disable PCI inta output + 1 = Enable PCI inta output +*/ +#define PNX8550_GLB_ENABLE_INTA_O 0x1 + +/* PCI Direct Mappings */ +#define PNX8550_PCIMEM 0x12000000 +#define PNX8550_PCIMEM_SIZE 0x08000000 +#define PNX8550_PCIIO 0x1c000000 +#define PNX8550_PCIIO_SIZE 0x02000000 /* 32M */ + +#define PNX8550_PORT_BASE KSEG1 + +// GPIO def +#define PNX8550_GPIO_BASE 0x1Be00000 + +#define PNX8550_GPIO_DIRQ0 (PNX8550_GPIO_BASE + 0x104500) +#define PNX8550_GPIO_MC1 (PNX8550_GPIO_BASE + 0x104004) +#define PNX8550_GPIO_MC_31_BIT 30 +#define PNX8550_GPIO_MC_30_BIT 28 +#define PNX8550_GPIO_MC_29_BIT 26 +#define PNX8550_GPIO_MC_28_BIT 24 +#define PNX8550_GPIO_MC_27_BIT 22 +#define PNX8550_GPIO_MC_26_BIT 20 +#define PNX8550_GPIO_MC_25_BIT 18 +#define PNX8550_GPIO_MC_24_BIT 16 +#define PNX8550_GPIO_MC_23_BIT 14 +#define PNX8550_GPIO_MC_22_BIT 12 +#define PNX8550_GPIO_MC_21_BIT 10 +#define PNX8550_GPIO_MC_20_BIT 8 +#define PNX8550_GPIO_MC_19_BIT 6 +#define PNX8550_GPIO_MC_18_BIT 4 +#define PNX8550_GPIO_MC_17_BIT 2 +#define PNX8550_GPIO_MC_16_BIT 0 + +#define PNX8550_GPIO_MODE_PRIMOP 0x1 +#define PNX8550_GPIO_MODE_NO_OPENDR 0x2 +#define PNX8550_GPIO_MODE_OPENDR 0x3 + +// RESET module +#define PNX8550_RST_CTL *(volatile unsigned long *)(PNX8550_RESET_BASE + 0x0) +#define PNX8550_RST_CAUSE *(volatile unsigned long *)(PNX8550_RESET_BASE + 0x4) +#define PNX8550_RST_EN_WATCHDOG *(volatile unsigned long *)(PNX8550_RESET_BASE + 0x8) + +#define PNX8550_RST_REL_MIPS_RST_N 0x8 +#define PNX8550_RST_DO_SW_RST 0x4 +#define PNX8550_RST_REL_SYS_RST_OUT 0x2 +#define PNX8550_RST_ASSERT_SYS_RST_OUT 0x1 +#endif diff --git a/arch/mips/include/asm/mach-pnx8550/int.h b/arch/mips/include/asm/mach-pnx8550/int.h new file mode 100644 index 00000000000..0e0668b524f --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/int.h @@ -0,0 +1,140 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Interrupt specific definitions + * + * Author: source@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 __PNX8550_INT_H +#define __PNX8550_INT_H + +#define PNX8550_GIC_BASE 0xBBE3E000 + +#define PNX8550_GIC_PRIMASK_0 *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x000) +#define PNX8550_GIC_PRIMASK_1 *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x004) +#define PNX8550_GIC_VECTOR_0 *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x100) +#define PNX8550_GIC_VECTOR_1 *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x104) +#define PNX8550_GIC_PEND_1_31 *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x200) +#define PNX8550_GIC_PEND_32_63 *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x204) +#define PNX8550_GIC_PEND_64_70 *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x208) +#define PNX8550_GIC_FEATURES *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x300) +#define PNX8550_GIC_REQ(x) *(volatile unsigned long *)(PNX8550_GIC_BASE + 0x400 + (x)*4) +#define PNX8550_GIC_MOD_ID *(volatile unsigned long *)(PNX8550_GIC_BASE + 0xFFC) + +// cp0 is two software + six hw exceptions +#define PNX8550_INT_CP0_TOTINT 8 +#define PNX8550_INT_CP0_MIN 0 +#define PNX8550_INT_CP0_MAX (PNX8550_INT_CP0_MIN + PNX8550_INT_CP0_TOTINT - 1) + +#define MIPS_CPU_GIC_IRQ 2 +#define MIPS_CPU_TIMER_IRQ 7 + +// GIC are 71 exceptions connected to cp0's first hardware exception +#define PNX8550_INT_GIC_TOTINT 71 +#define PNX8550_INT_GIC_MIN (PNX8550_INT_CP0_MAX+1) +#define PNX8550_INT_GIC_MAX (PNX8550_INT_GIC_MIN + PNX8550_INT_GIC_TOTINT - 1) + +#define PNX8550_INT_UNDEF (PNX8550_INT_GIC_MIN+0) +#define PNX8550_INT_IPC_TARGET0_MIPS (PNX8550_INT_GIC_MIN+1) +#define PNX8550_INT_IPC_TARGET1_TM32_1 (PNX8550_INT_GIC_MIN+2) +#define PNX8550_INT_IPC_TARGET1_TM32_2 (PNX8550_INT_GIC_MIN+3) +#define PNX8550_INT_RESERVED_4 (PNX8550_INT_GIC_MIN+4) +#define PNX8550_INT_USB (PNX8550_INT_GIC_MIN+5) +#define PNX8550_INT_GPIO_EQ1 (PNX8550_INT_GIC_MIN+6) +#define PNX8550_INT_GPIO_EQ2 (PNX8550_INT_GIC_MIN+7) +#define PNX8550_INT_GPIO_EQ3 (PNX8550_INT_GIC_MIN+8) +#define PNX8550_INT_GPIO_EQ4 (PNX8550_INT_GIC_MIN+9) + +#define PNX8550_INT_GPIO_EQ5 (PNX8550_INT_GIC_MIN+10) +#define PNX8550_INT_GPIO_EQ6 (PNX8550_INT_GIC_MIN+11) +#define PNX8550_INT_RESERVED_12 (PNX8550_INT_GIC_MIN+12) +#define PNX8550_INT_QVCP1 (PNX8550_INT_GIC_MIN+13) +#define PNX8550_INT_QVCP2 (PNX8550_INT_GIC_MIN+14) +#define PNX8550_INT_I2C1 (PNX8550_INT_GIC_MIN+15) +#define PNX8550_INT_I2C2 (PNX8550_INT_GIC_MIN+16) +#define PNX8550_INT_ISO_UART1 (PNX8550_INT_GIC_MIN+17) +#define PNX8550_INT_ISO_UART2 (PNX8550_INT_GIC_MIN+18) +#define PNX8550_INT_UART1 (PNX8550_INT_GIC_MIN+19) + +#define PNX8550_INT_UART2 (PNX8550_INT_GIC_MIN+20) +#define PNX8550_INT_QNTR (PNX8550_INT_GIC_MIN+21) +#define PNX8550_INT_RESERVED22 (PNX8550_INT_GIC_MIN+22) +#define PNX8550_INT_T_DSC (PNX8550_INT_GIC_MIN+23) +#define PNX8550_INT_M_DSC (PNX8550_INT_GIC_MIN+24) +#define PNX8550_INT_RESERVED25 (PNX8550_INT_GIC_MIN+25) +#define PNX8550_INT_2D_DRAW_ENG (PNX8550_INT_GIC_MIN+26) +#define PNX8550_INT_MEM_BASED_SCALAR1 (PNX8550_INT_GIC_MIN+27) +#define PNX8550_INT_VIDEO_MPEG (PNX8550_INT_GIC_MIN+28) +#define PNX8550_INT_VIDEO_INPUT_P1 (PNX8550_INT_GIC_MIN+29) + +#define PNX8550_INT_VIDEO_INPUT_P2 (PNX8550_INT_GIC_MIN+30) +#define PNX8550_INT_SPDI1 (PNX8550_INT_GIC_MIN+31) +#define PNX8550_INT_SPDO (PNX8550_INT_GIC_MIN+32) +#define PNX8550_INT_AUDIO_INPUT1 (PNX8550_INT_GIC_MIN+33) +#define PNX8550_INT_AUDIO_OUTPUT1 (PNX8550_INT_GIC_MIN+34) +#define PNX8550_INT_AUDIO_INPUT2 (PNX8550_INT_GIC_MIN+35) +#define PNX8550_INT_AUDIO_OUTPUT2 (PNX8550_INT_GIC_MIN+36) +#define PNX8550_INT_MEMBASED_SCALAR2 (PNX8550_INT_GIC_MIN+37) +#define PNX8550_INT_VPK (PNX8550_INT_GIC_MIN+38) +#define PNX8550_INT_MPEG1_MIPS (PNX8550_INT_GIC_MIN+39) + +#define PNX8550_INT_MPEG1_TM (PNX8550_INT_GIC_MIN+40) +#define PNX8550_INT_MPEG2_MIPS (PNX8550_INT_GIC_MIN+41) +#define PNX8550_INT_MPEG2_TM (PNX8550_INT_GIC_MIN+42) +#define PNX8550_INT_TS_DMA (PNX8550_INT_GIC_MIN+43) +#define PNX8550_INT_EDMA (PNX8550_INT_GIC_MIN+44) +#define PNX8550_INT_TM_DEBUG1 (PNX8550_INT_GIC_MIN+45) +#define PNX8550_INT_TM_DEBUG2 (PNX8550_INT_GIC_MIN+46) +#define PNX8550_INT_PCI_INTA (PNX8550_INT_GIC_MIN+47) +#define PNX8550_INT_CLOCK_MODULE (PNX8550_INT_GIC_MIN+48) +#define PNX8550_INT_PCI_XIO_INTA_PCI (PNX8550_INT_GIC_MIN+49) + +#define PNX8550_INT_PCI_XIO_INTB_DMA (PNX8550_INT_GIC_MIN+50) +#define PNX8550_INT_PCI_XIO_INTC_GPPM (PNX8550_INT_GIC_MIN+51) +#define PNX8550_INT_PCI_XIO_INTD_GPXIO (PNX8550_INT_GIC_MIN+52) +#define PNX8550_INT_DVD_CSS (PNX8550_INT_GIC_MIN+53) +#define PNX8550_INT_VLD (PNX8550_INT_GIC_MIN+54) +#define PNX8550_INT_GPIO_TSU_7_0 (PNX8550_INT_GIC_MIN+55) +#define PNX8550_INT_GPIO_TSU_15_8 (PNX8550_INT_GIC_MIN+56) +#define PNX8550_INT_GPIO_CTU_IR (PNX8550_INT_GIC_MIN+57) +#define PNX8550_INT_GPIO0 (PNX8550_INT_GIC_MIN+58) +#define PNX8550_INT_GPIO1 (PNX8550_INT_GIC_MIN+59) + +#define PNX8550_INT_GPIO2 (PNX8550_INT_GIC_MIN+60) +#define PNX8550_INT_GPIO3 (PNX8550_INT_GIC_MIN+61) +#define PNX8550_INT_GPIO4 (PNX8550_INT_GIC_MIN+62) +#define PNX8550_INT_GPIO5 (PNX8550_INT_GIC_MIN+63) +#define PNX8550_INT_GPIO6 (PNX8550_INT_GIC_MIN+64) +#define PNX8550_INT_GPIO7 (PNX8550_INT_GIC_MIN+65) +#define PNX8550_INT_PMAN_SECURITY (PNX8550_INT_GIC_MIN+66) +#define PNX8550_INT_I2C3 (PNX8550_INT_GIC_MIN+67) +#define PNX8550_INT_RESERVED_68 (PNX8550_INT_GIC_MIN+68) +#define PNX8550_INT_SPDI2 (PNX8550_INT_GIC_MIN+69) + +#define PNX8550_INT_I2C4 (PNX8550_INT_GIC_MIN+70) + +// Timer are 3 exceptions connected to cp0's 7th hardware exception +#define PNX8550_INT_TIMER_TOTINT 3 +#define PNX8550_INT_TIMER_MIN (PNX8550_INT_GIC_MAX+1) +#define PNX8550_INT_TIMER_MAX (PNX8550_INT_TIMER_MIN + PNX8550_INT_TIMER_TOTINT - 1) + +#define PNX8550_INT_TIMER1 (PNX8550_INT_TIMER_MIN+0) +#define PNX8550_INT_TIMER2 (PNX8550_INT_TIMER_MIN+1) +#define PNX8550_INT_TIMER3 (PNX8550_INT_TIMER_MIN+2) +#define PNX8550_INT_WATCHDOG PNX8550_INT_TIMER3 + +#endif diff --git a/arch/mips/include/asm/mach-pnx8550/kernel-entry-init.h b/arch/mips/include/asm/mach-pnx8550/kernel-entry-init.h new file mode 100644 index 00000000000..bdde00c9199 --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/kernel-entry-init.h @@ -0,0 +1,262 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005 Embedded Alley Solutions, Inc + */ +#ifndef __ASM_MACH_KERNEL_ENTRY_INIT_H +#define __ASM_MACH_KERNEL_ENTRY_INIT_H + +#include +#include + +#define CO_CONFIGPR_VALID 0x3F1F41FF /* valid bits to write to ConfigPR */ +#define HAZARD_CP0 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; +#define CACHE_OPC 0xBC000000 /* MIPS cache instruction opcode */ +#define ICACHE_LINE_SIZE 32 /* Instruction cache line size bytes */ +#define DCACHE_LINE_SIZE 32 /* Data cache line size in bytes */ + +#define ICACHE_SET_COUNT 256 /* Instruction cache set count */ +#define DCACHE_SET_COUNT 128 /* Data cache set count */ + +#define ICACHE_SET_SIZE (ICACHE_SET_COUNT * ICACHE_LINE_SIZE) +#define DCACHE_SET_SIZE (DCACHE_SET_COUNT * DCACHE_LINE_SIZE) + + .macro kernel_entry_setup + .set push + .set noreorder + /* + * PNX8550 entry point, when running a non compressed + * kernel. When loading a zImage, the head.S code in + * arch/mips/zboot/pnx8550 will init the caches and, + * decompress the kernel, and branch to kernel_entry. + */ +cache_begin: li t0, (1<<28) + mtc0 t0, CP0_STATUS /* cp0 usable */ + HAZARD_CP0 + + mtc0 zero, CP0_CAUSE + HAZARD_CP0 + + + /* Set static virtual to phys address translation and TLB disabled */ + mfc0 t0, CP0_CONFIG, 7 + HAZARD_CP0 + + and t0, ~((1<<19) | (1<<20)) /* TLB/MAP cleared */ + mtc0 t0, CP0_CONFIG, 7 + HAZARD_CP0 + + /* CPU boots with kseg0 cache algo set to 0x2 -- uncached */ + + init_icache + nop + init_dcache + nop + + cachePr4450ICReset + nop + + cachePr4450DCReset + nop + + /* read ConfigPR into t0 */ + mfc0 t0, CP0_CONFIG, 7 + HAZARD_CP0 + + /* enable the TLB */ + or t0, (1<<19) + + /* disable the ICACHE: at least 10x slower */ + /* or t0, (1<<26) */ + + /* disable the DCACHE; CONFIG_CPU_HAS_LLSC should not be set */ + /* or t0, (1<<27) */ + + and t0, CO_CONFIGPR_VALID + + /* enable TLB. */ + mtc0 t0, CP0_CONFIG, 7 + HAZARD_CP0 +cache_end: + /* Setup CMEM_0 to MMIO address space, 2MB */ + lui t0, 0x1BE0 + addi t0, t0, 0x3 + mtc0 $8, $22, 4 + nop + + /* Setup CMEM_1, 128MB */ + lui t0, 0x1000 + addi t0, t0, 0xf + mtc0 $8, $22, 5 + nop + + + /* Setup CMEM_2, 32MB */ + lui t0, 0x1C00 + addi t0, t0, 0xb + mtc0 $8, $22, 6 + nop + + /* Setup CMEM_3, 0MB */ + lui t0, 0x0 + addi t0, t0, 0x0 + mtc0 $8, $22, 7 + nop + + /* Enable cache */ + mfc0 t0, CP0_CONFIG + HAZARD_CP0 + and t0, t0, 0xFFFFFFF8 + or t0, t0, 3 + mtc0 t0, CP0_CONFIG + HAZARD_CP0 + .set pop + .endm + + .macro init_icache + .set push + .set noreorder + + /* Get Cache Configuration */ + mfc0 t3, CP0_CONFIG, 1 + HAZARD_CP0 + + /* get cache Line size */ + + srl t1, t3, 19 /* C0_CONFIGPR_IL_SHIFT */ + andi t1, t1, 0x7 /* C0_CONFIGPR_IL_MASK */ + beq t1, zero, pr4450_instr_cache_invalidated /* if zero instruction cache is absent */ + nop + addiu t0, t1, 1 + ori t1, zero, 1 + sllv t1, t1, t0 + + /* get max cache Index */ + srl t2, t3, 22 /* C0_CONFIGPR_IS_SHIFT */ + andi t2, t2, 0x7 /* C0_CONFIGPR_IS_MASK */ + addiu t0, t2, 6 + ori t2, zero, 1 + sllv t2, t2, t0 + + /* get max cache way */ + srl t3, t3, 16 /* C0_CONFIGPR_IA_SHIFT */ + andi t3, t3, 0x7 /* C0_CONFIGPR_IA_MASK */ + addiu t3, t3, 1 + + /* total no of cache lines */ + multu t2, t3 /* max index * max way */ + mflo t2 + addiu t2, t2, -1 + + move t0, zero +pr4450_next_instruction_cache_set: + cache Index_Invalidate_I, 0(t0) + addu t0, t0, t1 /* add bytes in a line */ + bne t2, zero, pr4450_next_instruction_cache_set + addiu t2, t2, -1 /* reduce no of lines to invalidate by one */ +pr4450_instr_cache_invalidated: + .set pop + .endm + + .macro init_dcache + .set push + .set noreorder + move t1, zero + + /* Store Tag Information */ + mtc0 zero, CP0_TAGLO, 0 + HAZARD_CP0 + + mtc0 zero, CP0_TAGHI, 0 + HAZARD_CP0 + + /* Cache size is 16384 = 512 lines x 32 bytes per line */ + or t2, zero, (128*4)-1 /* 512 lines */ + /* Invalidate all lines */ +2: + cache Index_Store_Tag_D, 0(t1) + addiu t2, t2, -1 + bne t2, zero, 2b + addiu t1, t1, 32 /* 32 bytes in a line */ + .set pop + .endm + + .macro cachePr4450ICReset + .set push + .set noreorder + + /* Save CP0 status reg on entry; */ + /* disable interrupts during cache reset */ + mfc0 t0, CP0_STATUS /* T0 = interrupt status on entry */ + HAZARD_CP0 + + mtc0 zero, CP0_STATUS /* disable CPU interrupts */ + HAZARD_CP0 + + or t1, zero, zero /* T1 = starting cache index (0) */ + ori t2, zero, (256 - 1) /* T2 = inst cache set cnt - 1 */ + + icache_invd_loop: + /* 9 == register t1 */ + .word CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \ + (0 * ICACHE_SET_SIZE) /* invalidate inst cache WAY0 */ + .word CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \ + (1 * ICACHE_SET_SIZE) /* invalidate inst cache WAY1 */ + + addiu t1, t1, ICACHE_LINE_SIZE /* T1 = next cache line index */ + bne t2, zero, icache_invd_loop /* T2 = 0 if all sets invalidated */ + addiu t2, t2, -1 /* decrement T2 set cnt (delay slot) */ + + /* Initialize the latches in the instruction cache tag */ + /* that drive the way selection tri-state bus drivers, by doing a */ + /* dummy load while the instruction cache is still disabled. */ + /* TODO: Is this needed ? */ + la t1, KSEG0 /* T1 = cached memory base address */ + lw zero, 0x0000(t1) /* (dummy read of first memory word) */ + + mtc0 t0, CP0_STATUS /* restore interrupt status on entry */ + HAZARD_CP0 + .set pop + .endm + + .macro cachePr4450DCReset + .set push + .set noreorder + mfc0 t0, CP0_STATUS /* T0 = interrupt status on entry */ + HAZARD_CP0 + mtc0 zero, CP0_STATUS /* disable CPU interrupts */ + HAZARD_CP0 + + /* Writeback/invalidate entire data cache sets/ways/lines */ + or t1, zero, zero /* T1 = starting cache index (0) */ + ori t2, zero, (DCACHE_SET_COUNT - 1) /* T2 = data cache set cnt - 1 */ + + dcache_wbinvd_loop: + /* 9 == register t1 */ + .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ + (0 * DCACHE_SET_SIZE) /* writeback/invalidate WAY0 */ + .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ + (1 * DCACHE_SET_SIZE) /* writeback/invalidate WAY1 */ + .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ + (2 * DCACHE_SET_SIZE) /* writeback/invalidate WAY2 */ + .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ + (3 * DCACHE_SET_SIZE) /* writeback/invalidate WAY3 */ + + addiu t1, t1, DCACHE_LINE_SIZE /* T1 = next data cache line index */ + bne t2, zero, dcache_wbinvd_loop /* T2 = 0 when wbinvd entire cache */ + addiu t2, t2, -1 /* decrement T2 set cnt (delay slot) */ + + /* Initialize the latches in the data cache tag that drive the way + selection tri-state bus drivers, by doing a dummy load while the + data cache is still in the disabled mode. TODO: Is this needed ? */ + la t1, KSEG0 /* T1 = cached memory base address */ + lw zero, 0x0000(t1) /* (dummy read of first memory word) */ + + mtc0 t0, CP0_STATUS /* restore interrupt status on entry */ + HAZARD_CP0 + .set pop + .endm + +#endif /* __ASM_MACH_KERNEL_ENTRY_INIT_H */ diff --git a/arch/mips/include/asm/mach-pnx8550/nand.h b/arch/mips/include/asm/mach-pnx8550/nand.h new file mode 100644 index 00000000000..aefbc514ab0 --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/nand.h @@ -0,0 +1,121 @@ +#ifndef __PNX8550_NAND_H +#define __PNX8550_NAND_H + +#define PNX8550_NAND_BASE_ADDR 0x10000000 +#define PNX8550_PCIXIO_BASE 0xBBE40000 + +#define PNX8550_DMA_EXT_ADDR *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x800) +#define PNX8550_DMA_INT_ADDR *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x804) +#define PNX8550_DMA_TRANS_SIZE *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x808) +#define PNX8550_DMA_CTRL *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x80c) +#define PNX8550_XIO_SEL0 *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x814) +#define PNX8550_GPXIO_ADDR *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x820) +#define PNX8550_GPXIO_WR *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x824) +#define PNX8550_GPXIO_RD *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x828) +#define PNX8550_GPXIO_CTRL *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x82C) +#define PNX8550_XIO_FLASH_CTRL *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x830) +#define PNX8550_GPXIO_INT_STATUS *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfb0) +#define PNX8550_GPXIO_INT_ENABLE *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfb4) +#define PNX8550_GPXIO_INT_CLEAR *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfb8) +#define PNX8550_DMA_INT_STATUS *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfd0) +#define PNX8550_DMA_INT_ENABLE *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfd4) +#define PNX8550_DMA_INT_CLEAR *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfd8) + +#define PNX8550_XIO_SEL0_EN_16BIT 0x00800000 +#define PNX8550_XIO_SEL0_USE_ACK 0x00400000 +#define PNX8550_XIO_SEL0_REN_HIGH 0x00100000 +#define PNX8550_XIO_SEL0_REN_LOW 0x00040000 +#define PNX8550_XIO_SEL0_WEN_HIGH 0x00010000 +#define PNX8550_XIO_SEL0_WEN_LOW 0x00004000 +#define PNX8550_XIO_SEL0_WAIT 0x00000200 +#define PNX8550_XIO_SEL0_OFFSET 0x00000020 +#define PNX8550_XIO_SEL0_TYPE_68360 0x00000000 +#define PNX8550_XIO_SEL0_TYPE_NOR 0x00000008 +#define PNX8550_XIO_SEL0_TYPE_NAND 0x00000010 +#define PNX8550_XIO_SEL0_TYPE_IDE 0x00000018 +#define PNX8550_XIO_SEL0_SIZE_8MB 0x00000000 +#define PNX8550_XIO_SEL0_SIZE_16MB 0x00000002 +#define PNX8550_XIO_SEL0_SIZE_32MB 0x00000004 +#define PNX8550_XIO_SEL0_SIZE_64MB 0x00000006 +#define PNX8550_XIO_SEL0_ENAB 0x00000001 + +#define PNX8550_SEL0_DEFAULT ((PNX8550_XIO_SEL0_EN_16BIT) | \ + (PNX8550_XIO_SEL0_REN_HIGH*0)| \ + (PNX8550_XIO_SEL0_REN_LOW*2) | \ + (PNX8550_XIO_SEL0_WEN_HIGH*0)| \ + (PNX8550_XIO_SEL0_WEN_LOW*2) | \ + (PNX8550_XIO_SEL0_WAIT*4) | \ + (PNX8550_XIO_SEL0_OFFSET*0) | \ + (PNX8550_XIO_SEL0_TYPE_NAND) | \ + (PNX8550_XIO_SEL0_SIZE_32MB) | \ + (PNX8550_XIO_SEL0_ENAB)) + +#define PNX8550_GPXIO_PENDING 0x00000200 +#define PNX8550_GPXIO_DONE 0x00000100 +#define PNX8550_GPXIO_CLR_DONE 0x00000080 +#define PNX8550_GPXIO_INIT 0x00000040 +#define PNX8550_GPXIO_READ_CMD 0x00000010 +#define PNX8550_GPXIO_BEN 0x0000000F + +#define PNX8550_XIO_FLASH_64MB 0x00200000 +#define PNX8550_XIO_FLASH_INC_DATA 0x00100000 +#define PNX8550_XIO_FLASH_CMD_PH 0x000C0000 +#define PNX8550_XIO_FLASH_CMD_PH2 0x00080000 +#define PNX8550_XIO_FLASH_CMD_PH1 0x00040000 +#define PNX8550_XIO_FLASH_CMD_PH0 0x00000000 +#define PNX8550_XIO_FLASH_ADR_PH 0x00030000 +#define PNX8550_XIO_FLASH_ADR_PH3 0x00030000 +#define PNX8550_XIO_FLASH_ADR_PH2 0x00020000 +#define PNX8550_XIO_FLASH_ADR_PH1 0x00010000 +#define PNX8550_XIO_FLASH_ADR_PH0 0x00000000 +#define PNX8550_XIO_FLASH_CMD_B(x) ((x<<8) & 0x0000FF00) +#define PNX8550_XIO_FLASH_CMD_A(x) (x & 0x000000FF) + +#define PNX8550_XIO_INT_ACK 0x00004000 +#define PNX8550_XIO_INT_COMPL 0x00002000 +#define PNX8550_XIO_INT_NONSUP 0x00000200 +#define PNX8550_XIO_INT_ABORT 0x00000004 + +#define PNX8550_DMA_CTRL_SINGLE_DATA 0x00000400 +#define PNX8550_DMA_CTRL_SND2XIO 0x00000200 +#define PNX8550_DMA_CTRL_FIX_ADDR 0x00000100 +#define PNX8550_DMA_CTRL_BURST_8 0x00000000 +#define PNX8550_DMA_CTRL_BURST_16 0x00000020 +#define PNX8550_DMA_CTRL_BURST_32 0x00000040 +#define PNX8550_DMA_CTRL_BURST_64 0x00000060 +#define PNX8550_DMA_CTRL_BURST_128 0x00000080 +#define PNX8550_DMA_CTRL_BURST_256 0x000000A0 +#define PNX8550_DMA_CTRL_BURST_512 0x000000C0 +#define PNX8550_DMA_CTRL_BURST_NORES 0x000000E0 +#define PNX8550_DMA_CTRL_INIT_DMA 0x00000010 +#define PNX8550_DMA_CTRL_CMD_TYPE 0x0000000F + +/* see PCI system arch, page 100 for the full list: */ +#define PNX8550_DMA_CTRL_PCI_CMD_READ 0x00000006 +#define PNX8550_DMA_CTRL_PCI_CMD_WRITE 0x00000007 + +#define PNX8550_DMA_INT_STAT_ACK_DONE (1<<14) +#define PNX8550_DMA_INT_STAT_DMA_DONE (1<<12) +#define PNX8550_DMA_INT_STAT_DMA_ERR (1<<9) +#define PNX8550_DMA_INT_STAT_PERR5 (1<<5) +#define PNX8550_DMA_INT_STAT_PERR4 (1<<4) +#define PNX8550_DMA_INT_STAT_M_ABORT (1<<2) +#define PNX8550_DMA_INT_STAT_T_ABORT (1<<1) + +#define PNX8550_DMA_INT_EN_ACK_DONE (1<<14) +#define PNX8550_DMA_INT_EN_DMA_DONE (1<<12) +#define PNX8550_DMA_INT_EN_DMA_ERR (1<<9) +#define PNX8550_DMA_INT_EN_PERR5 (1<<5) +#define PNX8550_DMA_INT_EN_PERR4 (1<<4) +#define PNX8550_DMA_INT_EN_M_ABORT (1<<2) +#define PNX8550_DMA_INT_EN_T_ABORT (1<<1) + +#define PNX8550_DMA_INT_CLR_ACK_DONE (1<<14) +#define PNX8550_DMA_INT_CLR_DMA_DONE (1<<12) +#define PNX8550_DMA_INT_CLR_DMA_ERR (1<<9) +#define PNX8550_DMA_INT_CLR_PERR5 (1<<5) +#define PNX8550_DMA_INT_CLR_PERR4 (1<<4) +#define PNX8550_DMA_INT_CLR_M_ABORT (1<<2) +#define PNX8550_DMA_INT_CLR_T_ABORT (1<<1) + +#endif diff --git a/arch/mips/include/asm/mach-pnx8550/pci.h b/arch/mips/include/asm/mach-pnx8550/pci.h new file mode 100644 index 00000000000..b921508d701 --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/pci.h @@ -0,0 +1,185 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PCI specific definitions + * + * Author: source@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 __PNX8550_PCI_H +#define __PNX8550_PCI_H + +#include +#include +#include +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#define PCI_CMD_IOR 0x20 +#define PCI_CMD_IOW 0x30 +#define PCI_CMD_CONFIG_READ 0xa0 +#define PCI_CMD_CONFIG_WRITE 0xb0 + +#define PCI_IO_TIMEOUT 1000 +#define PCI_IO_RETRY 5 +/* Timeout for IO and CFG accesses. + This is in 1/1024 th of a jiffie(=10ms) + i.e. approx 10us */ +#define PCI_IO_JIFFIES_TIMEOUT 40 +#define PCI_IO_JIFFIES_SHIFT 10 + +#define PCI_BYTE_ENABLE_MASK 0x0000000f +#define PCI_CFG_BUS_SHIFT 16 +#define PCI_CFG_FUNC_SHIFT 8 +#define PCI_CFG_REG_SHIFT 2 + +#define PCI_BASE 0x1be00000 +#define PCI_SETUP 0x00040010 +#define PCI_DIS_REQGNT (1<<30) +#define PCI_DIS_REQGNTA (1<<29) +#define PCI_DIS_REQGNTB (1<<28) +#define PCI_D2_SUPPORT (1<<27) +#define PCI_D1_SUPPORT (1<<26) +#define PCI_EN_TA (1<<24) +#define PCI_EN_PCI2MMI (1<<23) +#define PCI_EN_XIO (1<<22) +#define PCI_BASE18_PREF (1<<21) +#define SIZE_16M 0x3 +#define SIZE_32M 0x4 +#define SIZE_64M 0x5 +#define SIZE_128M 0x6 +#define PCI_SETUP_BASE18_SIZE(X) (X<<18) +#define PCI_SETUP_BASE18_EN (1<<17) +#define PCI_SETUP_BASE14_PREF (1<<16) +#define PCI_SETUP_BASE14_SIZE(X) (X<<12) +#define PCI_SETUP_BASE14_EN (1<<11) +#define PCI_SETUP_BASE10_PREF (1<<10) +#define PCI_SETUP_BASE10_SIZE(X) (X<<7) +#define PCI_SETUP_CFGMANAGE_EN (1<<1) +#define PCI_SETUP_PCIARB_EN (1<<0) + +#define PCI_CTRL 0x040014 +#define PCI_SWPB_DCS_PCI (1<<16) +#define PCI_SWPB_PCI_PCI (1<<15) +#define PCI_SWPB_PCI_DCS (1<<14) +#define PCI_REG_WR_POST (1<<13) +#define PCI_XIO_WR_POST (1<<12) +#define PCI_PCI2_WR_POST (1<<13) +#define PCI_PCI1_WR_POST (1<<12) +#define PCI_SERR_SEEN (1<<11) +#define PCI_B10_SPEC_RD (1<<6) +#define PCI_B14_SPEC_RD (1<<5) +#define PCI_B18_SPEC_RD (1<<4) +#define PCI_B10_NOSUBWORD (1<<3) +#define PCI_B14_NOSUBWORD (1<<2) +#define PCI_B18_NOSUBWORD (1<<1) +#define PCI_RETRY_TMREN (1<<0) + +#define PCI_BASE1_LO 0x040018 +#define PCI_BASE1_HI 0x04001C +#define PCI_BASE2_LO 0x040020 +#define PCI_BASE2_HI 0x040024 +#define PCI_RDLIFETIM 0x040028 +#define PCI_GPPM_ADDR 0x04002C +#define PCI_GPPM_WDAT 0x040030 +#define PCI_GPPM_RDAT 0x040034 +#define PCI_GPPM_CTRL 0x040038 +#define GPPM_DONE (1<<10) +#define INIT_PCI_CYCLE (1<<9) +#define GPPM_CMD(X) (((X)&0xf)<<4) +#define GPPM_BYTEEN(X) ((X)&0xf) +#define PCI_UNLOCKREG 0x04003C +#define UNLOCK_SSID(X) (((X)&0xff)<<8) +#define UNLOCK_SETUP(X) (((X)&0xff)<<0) +#define UNLOCK_MAGIC 0xCA +#define PCI_DEV_VEND_ID 0x040040 +#define DEVICE_ID(X) (((X)>>16)&0xffff) +#define VENDOR_ID(X) (((X)&0xffff)) +#define PCI_CFG_CMDSTAT 0x040044 +#define PCI_CFG_STATUS(X) (((X)>>16)&0xffff) +#define PCI_CFG_COMMAND(X) ((X)&0xffff) +#define PCI_CLASS_REV 0x040048 +#define PCI_CLASSCODE(X) (((X)>>8)&0xffffff) +#define PCI_REVID(X) ((X)&0xff) +#define PCI_LAT_TMR 0x04004c +#define PCI_BASE10 0x040050 +#define PCI_BASE14 0x040054 +#define PCI_BASE18 0x040058 +#define PCI_SUBSYS_ID 0x04006c +#define PCI_CAP_PTR 0x040074 +#define PCI_CFG_MISC 0x04007c +#define PCI_PMC 0x040080 +#define PCI_PWR_STATE 0x040084 +#define PCI_IO 0x040088 +#define PCI_SLVTUNING 0x04008C +#define PCI_DMATUNING 0x040090 +#define PCI_DMAEADDR 0x040800 +#define PCI_DMAIADDR 0x040804 +#define PCI_DMALEN 0x040808 +#define PCI_DMACTRL 0x04080C +#define PCI_XIOCTRL 0x040810 +#define PCI_SEL0PROF 0x040814 +#define PCI_SEL1PROF 0x040818 +#define PCI_SEL2PROF 0x04081C +#define PCI_GPXIOADDR 0x040820 +#define PCI_NANDCTRLS 0x400830 +#define PCI_SEL3PROF 0x040834 +#define PCI_SEL4PROF 0x040838 +#define PCI_GPXIO_STAT 0x040FB0 +#define PCI_GPXIO_IMASK 0x040FB4 +#define PCI_GPXIO_ICLR 0x040FB8 +#define PCI_GPXIO_ISET 0x040FBC +#define PCI_GPPM_STATUS 0x040FC0 +#define GPPM_DONE (1<<10) +#define GPPM_ERR (1<<9) +#define GPPM_MPAR_ERR (1<<8) +#define GPPM_PAR_ERR (1<<7) +#define GPPM_R_MABORT (1<<2) +#define GPPM_R_TABORT (1<<1) +#define PCI_GPPM_IMASK 0x040FC4 +#define PCI_GPPM_ICLR 0x040FC8 +#define PCI_GPPM_ISET 0x040FCC +#define PCI_DMA_STATUS 0x040FD0 +#define PCI_DMA_IMASK 0x040FD4 +#define PCI_DMA_ICLR 0x040FD8 +#define PCI_DMA_ISET 0x040FDC +#define PCI_ISTATUS 0x040FE0 +#define PCI_IMASK 0x040FE4 +#define PCI_ICLR 0x040FE8 +#define PCI_ISET 0x040FEC +#define PCI_MOD_ID 0x040FFC + +/* + * PCI configuration cycle AD bus definition + */ +/* Type 0 */ +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 + +/* Type 1 */ +#define PCI_CFG_TYPE1_REG_SHF 0 +#define PCI_CFG_TYPE1_FUNC_SHF 8 +#define PCI_CFG_TYPE1_DEV_SHF 11 +#define PCI_CFG_TYPE1_BUS_SHF 16 + +/* + * Ethernet device DP83816 definition + */ +#define DP83816_IRQ_ETHER 66 + +#endif diff --git a/arch/mips/include/asm/mach-pnx8550/uart.h b/arch/mips/include/asm/mach-pnx8550/uart.h new file mode 100644 index 00000000000..ad7608d4487 --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/uart.h @@ -0,0 +1,30 @@ +#ifndef __IP3106_UART_H +#define __IP3106_UART_H + +#include + +/* early macros for kgdb use. fixme: clean this up */ + +#define UART_BASE 0xbbe4a000 /* PNX8550 */ + +#define PNX8550_UART_PORT0 (UART_BASE) +#define PNX8550_UART_PORT1 (UART_BASE + 0x1000) + +#define PNX8550_UART_INT(x) (PNX8550_INT_GIC_MIN+19+x) +#define IRQ_TO_UART(x) (x-PNX8550_INT_GIC_MIN-19) + +/* early macros needed for prom/kgdb */ + +#define ip3106_lcr(base, port) *(volatile u32 *)(base+(port*0x1000) + 0x000) +#define ip3106_mcr(base, port) *(volatile u32 *)(base+(port*0x1000) + 0x004) +#define ip3106_baud(base, port) *(volatile u32 *)(base+(port*0x1000) + 0x008) +#define ip3106_cfg(base, port) *(volatile u32 *)(base+(port*0x1000) + 0x00C) +#define ip3106_fifo(base, port) *(volatile u32 *)(base+(port*0x1000) + 0x028) +#define ip3106_istat(base, port) *(volatile u32 *)(base+(port*0x1000) + 0xFE0) +#define ip3106_ien(base, port) *(volatile u32 *)(base+(port*0x1000) + 0xFE4) +#define ip3106_iclr(base, port) *(volatile u32 *)(base+(port*0x1000) + 0xFE8) +#define ip3106_iset(base, port) *(volatile u32 *)(base+(port*0x1000) + 0xFEC) +#define ip3106_pd(base, port) *(volatile u32 *)(base+(port*0x1000) + 0xFF4) +#define ip3106_mid(base, port) *(volatile u32 *)(base+(port*0x1000) + 0xFFC) + +#endif diff --git a/arch/mips/include/asm/mach-pnx8550/usb.h b/arch/mips/include/asm/mach-pnx8550/usb.h new file mode 100644 index 00000000000..483b7fc65d4 --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/usb.h @@ -0,0 +1,32 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * USB specific definitions + * + * Author: source@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 __PNX8550_USB_H +#define __PNX8550_USB_H + +/* + * USB Host controller + */ + +#define PNX8550_USB_OHCI_OP_BASE 0x1be48000 +#define PNX8550_USB_OHCI_OP_LEN 0x1000 + +#endif diff --git a/arch/mips/include/asm/mach-pnx8550/war.h b/arch/mips/include/asm/mach-pnx8550/war.h new file mode 100644 index 00000000000..d0458dd082f --- /dev/null +++ b/arch/mips/include/asm/mach-pnx8550/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_PNX8550_WAR_H +#define __ASM_MIPS_MACH_PNX8550_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_PNX8550_WAR_H */ diff --git a/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h b/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h new file mode 100644 index 00000000000..f3bc7efa260 --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h @@ -0,0 +1,81 @@ +/* + * IDT RC32434 specific CPU feature overrides + * + * Copyright (C) 2008 Florian Fainelli + * + * This file was derived from: include/asm-mips/cpu-features.h + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef __ASM_MACH_RC32434_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_RC32434_CPU_FEATURE_OVERRIDES_H + +/* + * The IDT RC32434 SOC has a built-in MIPS 4Kc core. + */ +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_divec 1 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 + +#define cpu_has_vtag_icache 0 +/* #define cpu_has_dc_aliases ? */ +/* #define cpu_has_ic_fills_f_dc ? */ +/* #define cpu_has_pindexed_dcache ? */ + +/* #define cpu_icache_snoops_remote_store ? */ + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 + +/* #define cpu_has_nofpuex ? */ +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +#define cpu_has_inclusive_pcaches 0 + +#define cpu_dcache_line_size() 16 +#define cpu_icache_line_size() 16 + +#endif /* __ASM_MACH_RC32434_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-rc32434/ddr.h b/arch/mips/include/asm/mach-rc32434/ddr.h new file mode 100644 index 00000000000..291e2cf9dde --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/ddr.h @@ -0,0 +1,141 @@ +/* + * Definitions for the DDR registers + * + * Copyright 2002 Ryan Holm + * Copyright 2008 Florian Fainelli + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _ASM_RC32434_DDR_H_ +#define _ASM_RC32434_DDR_H_ + +#include + +/* DDR register structure */ +struct ddr_ram { + u32 ddrbase; + u32 ddrmask; + u32 res1; + u32 res2; + u32 ddrc; + u32 ddrabase; + u32 ddramask; + u32 ddramap; + u32 ddrcust; + u32 ddrrdc; + u32 ddrspare; +}; + +#define DDR0_PHYS_ADDR 0x18018000 + +/* DDR banks masks */ +#define DDR_MASK 0xffff0000 +#define DDR0_BASE_MSK DDR_MASK +#define DDR1_BASE_MSK DDR_MASK + +/* DDR bank0 registers */ +#define RC32434_DDR0_ATA_BIT 5 +#define RC32434_DDR0_ATA_MSK 0x000000E0 +#define RC32434_DDR0_DBW_BIT 8 +#define RC32434_DDR0_DBW_MSK 0x00000100 +#define RC32434_DDR0_WR_BIT 9 +#define RC32434_DDR0_WR_MSK 0x00000600 +#define RC32434_DDR0_PS_BIT 11 +#define RC32434_DDR0_PS_MSK 0x00001800 +#define RC32434_DDR0_DTYPE_BIT 13 +#define RC32434_DDR0_DTYPE_MSK 0x0000e000 +#define RC32434_DDR0_RFC_BIT 16 +#define RC32434_DDR0_RFC_MSK 0x000f0000 +#define RC32434_DDR0_RP_BIT 20 +#define RC32434_DDR0_RP_MSK 0x00300000 +#define RC32434_DDR0_AP_BIT 22 +#define RC32434_DDR0_AP_MSK 0x00400000 +#define RC32434_DDR0_RCD_BIT 23 +#define RC32434_DDR0_RCD_MSK 0x01800000 +#define RC32434_DDR0_CL_BIT 25 +#define RC32434_DDR0_CL_MSK 0x06000000 +#define RC32434_DDR0_DBM_BIT 27 +#define RC32434_DDR0_DBM_MSK 0x08000000 +#define RC32434_DDR0_SDS_BIT 28 +#define RC32434_DDR0_SDS_MSK 0x10000000 +#define RC32434_DDR0_ATP_BIT 29 +#define RC32434_DDR0_ATP_MSK 0x60000000 +#define RC32434_DDR0_RE_BIT 31 +#define RC32434_DDR0_RE_MSK 0x80000000 + +/* DDR bank C registers */ +#define RC32434_DDRC_MSK(x) BIT_TO_MASK(x) +#define RC32434_DDRC_CES_BIT 0 +#define RC32434_DDRC_ACE_BIT 1 + +/* Custom DDR bank registers */ +#define RC32434_DCST_MSK(x) BIT_TO_MASK(x) +#define RC32434_DCST_CS_BIT 0 +#define RC32434_DCST_CS_MSK 0x00000003 +#define RC32434_DCST_WE_BIT 2 +#define RC32434_DCST_RAS_BIT 3 +#define RC32434_DCST_CAS_BIT 4 +#define RC32434_DSCT_CKE_BIT 5 +#define RC32434_DSCT_BA_BIT 6 +#define RC32434_DSCT_BA_MSK 0x000000c0 + +/* DDR QSC registers */ +#define RC32434_QSC_DM_BIT 0 +#define RC32434_QSC_DM_MSK 0x00000003 +#define RC32434_QSC_DQSBS_BIT 2 +#define RC32434_QSC_DQSBS_MSK 0x000000fc +#define RC32434_QSC_DB_BIT 8 +#define RC32434_QSC_DB_MSK 0x00000100 +#define RC32434_QSC_DBSP_BIT 9 +#define RC32434_QSC_DBSP_MSK 0x01fffe00 +#define RC32434_QSC_BDP_BIT 25 +#define RC32434_QSC_BDP_MSK 0x7e000000 + +/* DDR LLC registers */ +#define RC32434_LLC_EAO_BIT 0 +#define RC32434_LLC_EAO_MSK 0x00000001 +#define RC32434_LLC_EO_BIT 1 +#define RC32434_LLC_EO_MSK 0x0000003e +#define RC32434_LLC_FS_BIT 6 +#define RC32434_LLC_FS_MSK 0x000000c0 +#define RC32434_LLC_AS_BIT 8 +#define RC32434_LLC_AS_MSK 0x00000700 +#define RC32434_LLC_SP_BIT 11 +#define RC32434_LLC_SP_MSK 0x001ff800 + +/* DDR LLFC registers */ +#define RC32434_LLFC_MSK(x) BIT_TO_MASK(x) +#define RC32434_LLFC_MEN_BIT 0 +#define RC32434_LLFC_EAN_BIT 1 +#define RC32434_LLFC_FF_BIT 2 + +/* DDR DLLTA registers */ +#define RC32434_DLLTA_ADDR_BIT 2 +#define RC32434_DLLTA_ADDR_MSK 0xfffffffc + +/* DDR DLLED registers */ +#define RC32434_DLLED_MSK(x) BIT_TO_MASK(x) +#define RC32434_DLLED_DBE_BIT 0 +#define RC32434_DLLED_DTE_BIT 1 + +#endif /* _ASM_RC32434_DDR_H_ */ diff --git a/arch/mips/include/asm/mach-rc32434/dma.h b/arch/mips/include/asm/mach-rc32434/dma.h new file mode 100644 index 00000000000..5f898b5873f --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/dma.h @@ -0,0 +1,103 @@ +/* + * Copyright 2002 Integrated Device Technology, Inc. + * All rights reserved. + * + * DMA register definition. + * + * Author : ryan.holmQVist@idt.com + * Date : 20011005 + */ + +#ifndef __ASM_RC32434_DMA_H +#define __ASM_RC32434_DMA_H + +#include + +#define DMA0_BASE_ADDR 0x18040000 + +/* + * DMA descriptor (in physical memory). + */ + +struct dma_desc { + u32 control; /* Control. use DMAD_* */ + u32 ca; /* Current Address. */ + u32 devcs; /* Device control and status. */ + u32 link; /* Next descriptor in chain. */ +}; + +#define DMA_DESC_SIZ sizeof(struct dma_desc) +#define DMA_DESC_COUNT_BIT 0 +#define DMA_DESC_COUNT_MSK 0x0003ffff +#define DMA_DESC_DS_BIT 20 +#define DMA_DESC_DS_MSK 0x00300000 + +#define DMA_DESC_DEV_CMD_BIT 22 +#define DMA_DESC_DEV_CMD_MSK 0x01c00000 + +/* DMA command sizes */ +#define DMA_DESC_DEV_CMD_BYTE 0 +#define DMA_DESC_DEV_CMD_HLF_WD 1 +#define DMA_DESC_DEV_CMD_WORD 2 +#define DMA_DESC_DEV_CMD_2WORDS 3 +#define DMA_DESC_DEV_CMD_4WORDS 4 +#define DMA_DESC_DEV_CMD_6WORDS 5 +#define DMA_DESC_DEV_CMD_8WORDS 6 +#define DMA_DESC_DEV_CMD_16WORDS 7 + +/* DMA descriptors interrupts */ +#define DMA_DESC_COF (1 << 25) /* Chain on finished */ +#define DMA_DESC_COD (1 << 26) /* Chain on done */ +#define DMA_DESC_IOF (1 << 27) /* Interrupt on finished */ +#define DMA_DESC_IOD (1 << 28) /* Interrupt on done */ +#define DMA_DESC_TERM (1 << 29) /* Terminated */ +#define DMA_DESC_DONE (1 << 30) /* Done */ +#define DMA_DESC_FINI (1 << 31) /* Finished */ + +/* + * DMA register (within Internal Register Map). + */ + +struct dma_reg { + u32 dmac; /* Control. */ + u32 dmas; /* Status. */ + u32 dmasm; /* Mask. */ + u32 dmadptr; /* Descriptor pointer. */ + u32 dmandptr; /* Next descriptor pointer. */ +}; + +/* DMA channels specific registers */ +#define DMA_CHAN_RUN_BIT (1 << 0) +#define DMA_CHAN_DONE_BIT (1 << 1) +#define DMA_CHAN_MODE_BIT (1 << 2) +#define DMA_CHAN_MODE_MSK 0x0000000c +#define DMA_CHAN_MODE_AUTO 0 +#define DMA_CHAN_MODE_BURST 1 +#define DMA_CHAN_MODE_XFRT 2 +#define DMA_CHAN_MODE_RSVD 3 +#define DMA_CHAN_ACT_BIT (1 << 4) + +/* DMA status registers */ +#define DMA_STAT_FINI (1 << 0) +#define DMA_STAT_DONE (1 << 1) +#define DMA_STAT_CHAIN (1 << 2) +#define DMA_STAT_ERR (1 << 3) +#define DMA_STAT_HALT (1 << 4) + +/* + * DMA channel definitions + */ + +#define DMA_CHAN_ETH_RCV 0 +#define DMA_CHAN_ETH_XMT 1 +#define DMA_CHAN_MEM_TO_FIFO 2 +#define DMA_CHAN_FIFO_TO_MEM 3 +#define DMA_CHAN_PCI_TO_MEM 4 +#define DMA_CHAN_MEM_TO_PCI 5 +#define DMA_CHAN_COUNT 6 + +struct dma_channel { + struct dma_reg ch[DMA_CHAN_COUNT]; +}; + +#endif /* __ASM_RC32434_DMA_H */ diff --git a/arch/mips/include/asm/mach-rc32434/dma_v.h b/arch/mips/include/asm/mach-rc32434/dma_v.h new file mode 100644 index 00000000000..173a9f9146c --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/dma_v.h @@ -0,0 +1,52 @@ +/* + * Copyright 2002 Integrated Device Technology, Inc. + * All rights reserved. + * + * DMA register definition. + * + * Author : ryan.holmQVist@idt.com + * Date : 20011005 + */ + +#ifndef _ASM_RC32434_DMA_V_H_ +#define _ASM_RC32434_DMA_V_H_ + +#include +#include + +#define DMA_CHAN_OFFSET 0x14 +#define IS_DMA_USED(X) (((X) & \ + (DMA_DESC_FINI | DMA_DESC_DONE | DMA_DESC_TERM)) \ + != 0) +#define DMA_COUNT(count) ((count) & DMA_DESC_COUNT_MSK) + +#define DMA_HALT_TIMEOUT 500 + +static inline int rc32434_halt_dma(struct dma_reg *ch) +{ + int timeout = 1; + if (__raw_readl(&ch->dmac) & DMA_CHAN_RUN_BIT) { + __raw_writel(0, &ch->dmac); + for (timeout = DMA_HALT_TIMEOUT; timeout > 0; timeout--) { + if (__raw_readl(&ch->dmas) & DMA_STAT_HALT) { + __raw_writel(0, &ch->dmas); + break; + } + } + } + + return timeout ? 0 : 1; +} + +static inline void rc32434_start_dma(struct dma_reg *ch, u32 dma_addr) +{ + __raw_writel(0, &ch->dmandptr); + __raw_writel(dma_addr, &ch->dmadptr); +} + +static inline void rc32434_chain_dma(struct dma_reg *ch, u32 dma_addr) +{ + __raw_writel(dma_addr, &ch->dmandptr); +} + +#endif /* _ASM_RC32434_DMA_V_H_ */ diff --git a/arch/mips/include/asm/mach-rc32434/eth.h b/arch/mips/include/asm/mach-rc32434/eth.h new file mode 100644 index 00000000000..a25cbc56173 --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/eth.h @@ -0,0 +1,220 @@ +/* + * Definitions for the Ethernet registers + * + * Copyright 2002 Allend Stichter + * Copyright 2008 Florian Fainelli + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __ASM_RC32434_ETH_H +#define __ASM_RC32434_ETH_H + + +#define ETH0_BASE_ADDR 0x18060000 + +struct eth_regs { + u32 ethintfc; + u32 ethfifott; + u32 etharc; + u32 ethhash0; + u32 ethhash1; + u32 ethu0[4]; /* Reserved. */ + u32 ethpfs; + u32 ethmcp; + u32 eth_u1[10]; /* Reserved. */ + u32 ethspare; + u32 eth_u2[42]; /* Reserved. */ + u32 ethsal0; + u32 ethsah0; + u32 ethsal1; + u32 ethsah1; + u32 ethsal2; + u32 ethsah2; + u32 ethsal3; + u32 ethsah3; + u32 ethrbc; + u32 ethrpc; + u32 ethrupc; + u32 ethrfc; + u32 ethtbc; + u32 ethgpf; + u32 eth_u9[50]; /* Reserved. */ + u32 ethmac1; + u32 ethmac2; + u32 ethipgt; + u32 ethipgr; + u32 ethclrt; + u32 ethmaxf; + u32 eth_u10; /* Reserved. */ + u32 ethmtest; + u32 miimcfg; + u32 miimcmd; + u32 miimaddr; + u32 miimwtd; + u32 miimrdd; + u32 miimind; + u32 eth_u11; /* Reserved. */ + u32 eth_u12; /* Reserved. */ + u32 ethcfsa0; + u32 ethcfsa1; + u32 ethcfsa2; +}; + +/* Ethernet interrupt registers */ +#define ETH_INT_FC_EN (1 << 0) +#define ETH_INT_FC_ITS (1 << 1) +#define ETH_INT_FC_RIP (1 << 2) +#define ETH_INT_FC_JAM (1 << 3) +#define ETH_INT_FC_OVR (1 << 4) +#define ETH_INT_FC_UND (1 << 5) +#define ETH_INT_FC_IOC 0x000000c0 + +/* Ethernet FIFO registers */ +#define ETH_FIFI_TT_TTH_BIT 0 +#define ETH_FIFO_TT_TTH 0x0000007f + +/* Ethernet ARC/multicast registers */ +#define ETH_ARC_PRO (1 << 0) +#define ETH_ARC_AM (1 << 1) +#define ETH_ARC_AFM (1 << 2) +#define ETH_ARC_AB (1 << 3) + +/* Ethernet SAL registers */ +#define ETH_SAL_BYTE_5 0x000000ff +#define ETH_SAL_BYTE_4 0x0000ff00 +#define ETH_SAL_BYTE_3 0x00ff0000 +#define ETH_SAL_BYTE_2 0xff000000 + +/* Ethernet SAH registers */ +#define ETH_SAH_BYTE1 0x000000ff +#define ETH_SAH_BYTE0 0x0000ff00 + +/* Ethernet GPF register */ +#define ETH_GPF_PTV 0x0000ffff + +/* Ethernet PFG register */ +#define ETH_PFS_PFD (1 << 0) + +/* Ethernet CFSA[0-3] registers */ +#define ETH_CFSA0_CFSA4 0x000000ff +#define ETH_CFSA0_CFSA5 0x0000ff00 +#define ETH_CFSA1_CFSA2 0x000000ff +#define ETH_CFSA1_CFSA3 0x0000ff00 +#define ETH_CFSA1_CFSA0 0x000000ff +#define ETH_CFSA1_CFSA1 0x0000ff00 + +/* Ethernet MAC1 registers */ +#define ETH_MAC1_RE (1 << 0) +#define ETH_MAC1_PAF (1 << 1) +#define ETH_MAC1_RFC (1 << 2) +#define ETH_MAC1_TFC (1 << 3) +#define ETH_MAC1_LB (1 << 4) +#define ETH_MAC1_MR (1 << 31) + +/* Ethernet MAC2 registers */ +#define ETH_MAC2_FD (1 << 0) +#define ETH_MAC2_FLC (1 << 1) +#define ETH_MAC2_HFE (1 << 2) +#define ETH_MAC2_DC (1 << 3) +#define ETH_MAC2_CEN (1 << 4) +#define ETH_MAC2_PE (1 << 5) +#define ETH_MAC2_VPE (1 << 6) +#define ETH_MAC2_APE (1 << 7) +#define ETH_MAC2_PPE (1 << 8) +#define ETH_MAC2_LPE (1 << 9) +#define ETH_MAC2_NB (1 << 12) +#define ETH_MAC2_BP (1 << 13) +#define ETH_MAC2_ED (1 << 14) + +/* Ethernet IPGT register */ +#define ETH_IPGT 0x0000007f + +/* Ethernet IPGR registers */ +#define ETH_IPGR_IPGR2 0x0000007f +#define ETH_IPGR_IPGR1 0x00007f00 + +/* Ethernet CLRT registers */ +#define ETH_CLRT_MAX_RET 0x0000000f +#define ETH_CLRT_COL_WIN 0x00003f00 + +/* Ethernet MAXF register */ +#define ETH_MAXF 0x0000ffff + +/* Ethernet test registers */ +#define ETH_TEST_REG (1 << 2) +#define ETH_MCP_DIV 0x000000ff + +/* MII registers */ +#define ETH_MII_CFG_RSVD 0x0000000c +#define ETH_MII_CMD_RD (1 << 0) +#define ETH_MII_CMD_SCN (1 << 1) +#define ETH_MII_REG_ADDR 0x0000001f +#define ETH_MII_PHY_ADDR 0x00001f00 +#define ETH_MII_WTD_DATA 0x0000ffff +#define ETH_MII_RDD_DATA 0x0000ffff +#define ETH_MII_IND_BSY (1 << 0) +#define ETH_MII_IND_SCN (1 << 1) +#define ETH_MII_IND_NV (1 << 2) + +/* + * Values for the DEVCS field of the Ethernet DMA Rx and Tx descriptors. + */ + +#define ETH_RX_FD (1 << 0) +#define ETH_RX_LD (1 << 1) +#define ETH_RX_ROK (1 << 2) +#define ETH_RX_FM (1 << 3) +#define ETH_RX_MP (1 << 4) +#define ETH_RX_BP (1 << 5) +#define ETH_RX_VLT (1 << 6) +#define ETH_RX_CF (1 << 7) +#define ETH_RX_OVR (1 << 8) +#define ETH_RX_CRC (1 << 9) +#define ETH_RX_CV (1 << 10) +#define ETH_RX_DB (1 << 11) +#define ETH_RX_LE (1 << 12) +#define ETH_RX_LOR (1 << 13) +#define ETH_RX_CES (1 << 14) +#define ETH_RX_LEN_BIT 16 +#define ETH_RX_LEN 0xffff0000 + +#define ETH_TX_FD (1 << 0) +#define ETH_TX_LD (1 << 1) +#define ETH_TX_OEN (1 << 2) +#define ETH_TX_PEN (1 << 3) +#define ETH_TX_CEN (1 << 4) +#define ETH_TX_HEN (1 << 5) +#define ETH_TX_TOK (1 << 6) +#define ETH_TX_MP (1 << 7) +#define ETH_TX_BP (1 << 8) +#define ETH_TX_UND (1 << 9) +#define ETH_TX_OF (1 << 10) +#define ETH_TX_ED (1 << 11) +#define ETH_TX_EC (1 << 12) +#define ETH_TX_LC (1 << 13) +#define ETH_TX_TD (1 << 14) +#define ETH_TX_CRC (1 << 15) +#define ETH_TX_LE (1 << 16) +#define ETH_TX_CC 0x001E0000 + +#endif /* __ASM_RC32434_ETH_H */ diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h new file mode 100644 index 00000000000..3a70b41cd7a --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/gpio.h @@ -0,0 +1,88 @@ +/* + * Copyright 2002 Integrated Device Technology, Inc. + * All rights reserved. + * + * GPIO register definition. + * + * Author : ryan.holmQVist@idt.com + * Date : 20011005 + * Copyright (C) 2001, 2002 Ryan Holm + * Copyright (C) 2008 Florian Fainelli + */ + +#ifndef _RC32434_GPIO_H_ +#define _RC32434_GPIO_H_ + +#include + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value + +#define gpio_cansleep __gpio_cansleep + +#define gpio_to_irq(gpio) IRQ_GPIO(gpio) +#define irq_to_gpio(irq) IRQ_TO_GPIO(irq) + +#include + +struct rb532_gpio_reg { + u32 gpiofunc; /* GPIO Function Register + * gpiofunc[x]==0 bit = gpio + * func[x]==1 bit = altfunc + */ + u32 gpiocfg; /* GPIO Configuration Register + * gpiocfg[x]==0 bit = input + * gpiocfg[x]==1 bit = output + */ + u32 gpiod; /* GPIO Data Register + * gpiod[x] read/write gpio pinX status + */ + u32 gpioilevel; /* GPIO Interrupt Status Register + * interrupt level (see gpioistat) + */ + u32 gpioistat; /* Gpio Interrupt Status Register + * istat[x] = (gpiod[x] == level[x]) + * cleared in ISR (STICKY bits) + */ + u32 gpionmien; /* GPIO Non-maskable Interrupt Enable Register */ +}; + +/* UART GPIO signals */ +#define RC32434_UART0_SOUT (1 << 0) +#define RC32434_UART0_SIN (1 << 1) +#define RC32434_UART0_RTS (1 << 2) +#define RC32434_UART0_CTS (1 << 3) + +/* M & P bus GPIO signals */ +#define RC32434_MP_BIT_22 (1 << 4) +#define RC32434_MP_BIT_23 (1 << 5) +#define RC32434_MP_BIT_24 (1 << 6) +#define RC32434_MP_BIT_25 (1 << 7) + +/* CPU GPIO signals */ +#define RC32434_CPU_GPIO (1 << 8) + +/* Reserved GPIO signals */ +#define RC32434_AF_SPARE_6 (1 << 9) +#define RC32434_AF_SPARE_4 (1 << 10) +#define RC32434_AF_SPARE_3 (1 << 11) +#define RC32434_AF_SPARE_2 (1 << 12) + +/* PCI messaging unit */ +#define RC32434_PCI_MSU_GPIO (1 << 13) + +/* NAND GPIO signals */ +#define GPIO_RDY 8 +#define GPIO_WPX 9 +#define GPIO_ALE 10 +#define GPIO_CLE 11 + +/* Compact Flash GPIO pin */ +#define CF_GPIO_NUM 13 + +extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val); +extern unsigned get_434_reg(unsigned reg_offs); +extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask); +extern unsigned char get_latch_u5(void); + +#endif /* _RC32434_GPIO_H_ */ diff --git a/arch/mips/include/asm/mach-rc32434/integ.h b/arch/mips/include/asm/mach-rc32434/integ.h new file mode 100644 index 00000000000..fa65bc3d880 --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/integ.h @@ -0,0 +1,59 @@ +/* + * Definitions for the Watchdog registers + * + * Copyright 2002 Ryan Holm + * Copyright 2008 Florian Fainelli + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __RC32434_INTEG_H__ +#define __RC32434_INTEG_H__ + +#include + +#define INTEG0_BASE_ADDR 0x18030030 + +struct integ { + u32 errcs; /* sticky use ERRCS_ */ + u32 wtcount; /* Watchdog timer count reg. */ + u32 wtcompare; /* Watchdog timer timeout value. */ + u32 wtc; /* Watchdog timer control. use WTC_ */ +}; + +/* Error counters */ +#define RC32434_ERR_WTO 0 +#define RC32434_ERR_WNE 1 +#define RC32434_ERR_UCW 2 +#define RC32434_ERR_UCR 3 +#define RC32434_ERR_UPW 4 +#define RC32434_ERR_UPR 5 +#define RC32434_ERR_UDW 6 +#define RC32434_ERR_UDR 7 +#define RC32434_ERR_SAE 8 +#define RC32434_ERR_WRE 9 + +/* Watchdog control bits */ +#define RC32434_WTC_EN 0 +#define RC32434_WTC_TO 1 + +#endif /* __RC32434_INTEG_H__ */ diff --git a/arch/mips/include/asm/mach-rc32434/irq.h b/arch/mips/include/asm/mach-rc32434/irq.h new file mode 100644 index 00000000000..56738d8ec4e --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/irq.h @@ -0,0 +1,33 @@ +#ifndef __ASM_RC32434_IRQ_H +#define __ASM_RC32434_IRQ_H + +#define NR_IRQS 256 + +#include +#include + +/* Interrupt Controller */ +#define IC_GROUP0_PEND (REGBASE + 0x38000) +#define IC_GROUP0_MASK (REGBASE + 0x38008) +#define IC_GROUP_OFFSET 0x0C + +#define NUM_INTR_GROUPS 5 + +/* 16550 UARTs */ +#define GROUP0_IRQ_BASE 8 /* GRP2 IRQ numbers start here */ + /* GRP3 IRQ numbers start here */ +#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) + /* GRP4 IRQ numbers start here */ +#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) + /* GRP5 IRQ numbers start here */ +#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) +#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32) + +#define UART0_IRQ (GROUP3_IRQ_BASE + 0) + +#define ETH0_DMA_RX_IRQ (GROUP1_IRQ_BASE + 0) +#define ETH0_DMA_TX_IRQ (GROUP1_IRQ_BASE + 1) +#define ETH0_RX_OVR_IRQ (GROUP3_IRQ_BASE + 9) +#define ETH0_TX_UND_IRQ (GROUP3_IRQ_BASE + 10) + +#endif /* __ASM_RC32434_IRQ_H */ diff --git a/arch/mips/include/asm/mach-rc32434/pci.h b/arch/mips/include/asm/mach-rc32434/pci.h new file mode 100644 index 00000000000..410638f2af7 --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/pci.h @@ -0,0 +1,481 @@ +/* + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Copyright 2004 IDT Inc. (rischelp@idt.com) + * + * Initial Release + */ + +#ifndef _ASM_RC32434_PCI_H_ +#define _ASM_RC32434_PCI_H_ + +#define epld_mask ((volatile unsigned char *)0xB900000d) + +#define PCI0_BASE_ADDR 0x18080000 +#define PCI_LBA_COUNT 4 + +struct pci_map { + u32 address; /* Address. */ + u32 control; /* Control. */ + u32 mapping; /* mapping. */ +}; + +struct pci_reg { + u32 pcic; + u32 pcis; + u32 pcism; + u32 pcicfga; + u32 pcicfgd; + volatile struct pci_map pcilba[PCI_LBA_COUNT]; + u32 pcidac; + u32 pcidas; + u32 pcidasm; + u32 pcidad; + u32 pcidma8c; + u32 pcidma9c; + u32 pcitc; +}; + +#define PCI_MSU_COUNT 2 + +struct pci_msu { + u32 pciim[PCI_MSU_COUNT]; + u32 pciom[PCI_MSU_COUNT]; + u32 pciid; + u32 pciiic; + u32 pciiim; + u32 pciiod; + u32 pciioic; + u32 pciioim; +}; + +/* + * PCI Control Register + */ + +#define PCI_CTL_EN (1 << 0) +#define PCI_CTL_TNR (1 << 1) +#define PCI_CTL_SCE (1 << 2) +#define PCI_CTL_IEN (1 << 3) +#define PCI_CTL_AAA (1 << 4) +#define PCI_CTL_EAP (1 << 5) +#define PCI_CTL_PCIM_BIT 6 +#define PCI_CTL_PCIM 0x000001c0 + +#define PCI_CTL_PCIM_DIS 0 +#define PCI_CTL_PCIM_TNR 1 /* Satellite - target not ready */ +#define PCI_CTL_PCIM_SUS 2 /* Satellite - suspended CPU. */ +#define PCI_CTL_PCIM_EXT 3 /* Host - external arbiter. */ +#define PCI_CTL PCIM_PRIO 4 /* Host - fixed priority arb. */ +#define PCI_CTL_PCIM_RR 5 /* Host - round robin priority. */ +#define PCI_CTL_PCIM_RSVD6 6 +#define PCI_CTL_PCIM_RSVD7 7 + +#define PCI_CTL_IGM (1 << 9) + +/* + * PCI Status Register + */ + +#define PCI_STAT_EED (1 << 0) +#define PCI_STAT_WR (1 << 1) +#define PCI_STAT_NMI (1 << 2) +#define PCI_STAT_II (1 << 3) +#define PCI_STAT_CWE (1 << 4) +#define PCI_STAT_CRE (1 << 5) +#define PCI_STAT_MDPE (1 << 6) +#define PCI_STAT_STA (1 << 7) +#define PCI_STAT_RTA (1 << 8) +#define PCI_STAT_RMA (1 << 9) +#define PCI_STAT_SSE (1 << 10) +#define PCI_STAT_OSE (1 << 11) +#define PCI_STAT_PE (1 << 12) +#define PCI_STAT_TAE (1 << 13) +#define PCI_STAT_RLE (1 << 14) +#define PCI_STAT_BME (1 << 15) +#define PCI_STAT_PRD (1 << 16) +#define PCI_STAT_RIP (1 << 17) + +/* + * PCI Status Mask Register + */ + +#define PCI_STATM_EED PCI_STAT_EED +#define PCI_STATM_WR PCI_STAT_WR +#define PCI_STATM_NMI PCI_STAT_NMI +#define PCI_STATM_II PCI_STAT_II +#define PCI_STATM_CWE PCI_STAT_CWE +#define PCI_STATM_CRE PCI_STAT_CRE +#define PCI_STATM_MDPE PCI_STAT_MDPE +#define PCI_STATM_STA PCI_STAT_STA +#define PCI_STATM_RTA PCI_STAT_RTA +#define PCI_STATM_RMA PCI_STAT_RMA +#define PCI_STATM_SSE PCI_STAT_SSE +#define PCI_STATM_OSE PCI_STAT_OSE +#define PCI_STATM_PE PCI_STAT_PE +#define PCI_STATM_TAE PCI_STAT_TAE +#define PCI_STATM_RLE PCI_STAT_RLE +#define PCI_STATM_BME PCI_STAT_BME +#define PCI_STATM_PRD PCI_STAT_PRD +#define PCI_STATM_RIP PCI_STAT_RIP + +/* + * PCI Configuration Address Register + */ +#define PCI_CFGA_REG_BIT 2 +#define PCI_CFGA_REG 0x000000fc +#define PCI_CFGA_REG_ID (0x00 >> 2) /* use PCFGID */ +#define PCI_CFGA_REG_04 (0x04 >> 2) /* use PCFG04_ */ +#define PCI_CFGA_REG_08 (0x08 >> 2) /* use PCFG08_ */ +#define PCI_CFGA_REG_0C (0x0C >> 2) /* use PCFG0C_ */ +#define PCI_CFGA_REG_PBA0 (0x10 >> 2) /* use PCIPBA_ */ +#define PCI_CFGA_REG_PBA1 (0x14 >> 2) /* use PCIPBA_ */ +#define PCI_CFGA_REG_PBA2 (0x18 >> 2) /* use PCIPBA_ */ +#define PCI_CFGA_REG_PBA3 (0x1c >> 2) /* use PCIPBA_ */ +#define PCI_CFGA_REG_SUBSYS (0x2c >> 2) /* use PCFGSS_ */ +#define PCI_CFGA_REG_3C (0x3C >> 2) /* use PCFG3C_ */ +#define PCI_CFGA_REG_PBBA0C (0x44 >> 2) /* use PCIPBAC_ */ +#define PCI_CFGA_REG_PBA0M (0x48 >> 2) +#define PCI_CFGA_REG_PBA1C (0x4c >> 2) /* use PCIPBAC_ */ +#define PCI_CFGA_REG_PBA1M (0x50 >> 2) +#define PCI_CFGA_REG_PBA2C (0x54 >> 2) /* use PCIPBAC_ */ +#define PCI_CFGA_REG_PBA2M (0x58 >> 2) +#define PCI_CFGA_REG_PBA3C (0x5c >> 2) /* use PCIPBAC_ */ +#define PCI_CFGA_REG_PBA3M (0x60 >> 2) +#define PCI_CFGA_REG_PMGT (0x64 >> 2) +#define PCI_CFGA_FUNC_BIT 8 +#define PCI_CFGA_FUNC 0x00000700 +#define PCI_CFGA_DEV_BIT 11 +#define PCI_CFGA_DEV 0x0000f800 +#define PCI_CFGA_DEV_INTERN 0 +#define PCI_CFGA_BUS_BIT 16 +#define PCI CFGA_BUS 0x00ff0000 +#define PCI_CFGA_BUS_TYPE0 0 +#define PCI_CFGA_EN (1 << 31) + +/* PCI CFG04 commands */ +#define PCI_CFG04_CMD_IO_ENA (1 << 0) +#define PCI_CFG04_CMD_MEM_ENA (1 << 1) +#define PCI_CFG04_CMD_BM_ENA (1 << 2) +#define PCI_CFG04_CMD_MW_INV (1 << 4) +#define PCI_CFG04_CMD_PAR_ENA (1 << 6) +#define PCI_CFG04_CMD_SER_ENA (1 << 8) +#define PCI_CFG04_CMD_FAST_ENA (1 << 9) + +/* PCI CFG04 status fields */ +#define PCI_CFG04_STAT_BIT 16 +#define PCI_CFG04_STAT 0xffff0000 +#define PCI_CFG04_STAT_66_MHZ (1 << 21) +#define PCI_CFG04_STAT_FBB (1 << 23) +#define PCI_CFG04_STAT_MDPE (1 << 24) +#define PCI_CFG04_STAT_DST (1 << 25) +#define PCI_CFG04_STAT_STA (1 << 27) +#define PCI_CFG04_STAT_RTA (1 << 28) +#define PCI_CFG04_STAT_RMA (1 << 29) +#define PCI_CFG04_STAT_SSE (1 << 30) +#define PCI_CFG04_STAT_PE (1 << 31) + +#define PCI_PBA_MSI (1 << 0) +#define PCI_PBA_P (1 << 2) + +/* PCI PBAC registers */ +#define PCI_PBAC_MSI (1 << 0) +#define PCI_PBAC_P (1 << 1) +#define PCI_PBAC_SIZE_BIT 2 +#define PCI_PBAC_SIZE 0x0000007c +#define PCI_PBAC_SB (1 << 7) +#define PCI_PBAC_PP (1 << 8) +#define PCI_PBAC_MR_BIT 9 +#define PCI_PBAC_MR 0x00000600 +#define PCI_PBAC_MR_RD 0 +#define PCI_PBAC_MR_RD_LINE 1 +#define PCI_PBAC_MR_RD_MULT 2 +#define PCI_PBAC_MRL (1 << 11) +#define PCI_PBAC_MRM (1 << 12) +#define PCI_PBAC_TRP (1 << 13) + +#define PCI_CFG40_TRDY_TIM 0x000000ff +#define PCI_CFG40_RET_LIM 0x0000ff00 + +/* + * PCI Local Base Address [0|1|2|3] Register + */ + +#define PCI_LBA_BADDR_BIT 0 +#define PCI_LBA_BADDR 0xffffff00 + +/* + * PCI Local Base Address Control Register + */ + +#define PCI_LBAC_MSI (1 << 0) +#define PCI_LBAC_MSI_MEM 0 +#define PCI_LBAC_MSI_IO 1 +#define PCI_LBAC_SIZE_BIT 2 +#define PCI_LBAC_SIZE 0x0000007c +#define PCI_LBAC_SB (1 << 7) +#define PCI_LBAC_RT (1 << 8) +#define PCI_LBAC_RT_NO_PREF 0 +#define PCI_LBAC_RT_PREF 1 + +/* + * PCI Local Base Address [0|1|2|3] Mapping Register + */ +#define PCI_LBAM_MADDR_BIT 8 +#define PCI_LBAM_MADDR 0xffffff00 + +/* + * PCI Decoupled Access Control Register + */ +#define PCI_DAC_DEN (1 << 0) + +/* + * PCI Decoupled Access Status Register + */ +#define PCI_DAS_D (1 << 0) +#define PCI_DAS_B (1 << 1) +#define PCI_DAS_E (1 << 2) +#define PCI_DAS_OFE (1 << 3) +#define PCI_DAS_OFF (1 << 4) +#define PCI_DAS_IFE (1 << 5) +#define PCI_DAS_IFF (1 << 6) + +/* + * PCI DMA Channel 8 Configuration Register + */ +#define PCI_DMA8C_MBS_BIT 0 +#define PCI_DMA8C_MBS 0x00000fff /* Maximum Burst Size. */ +#define PCI_DMA8C_OUR (1 << 12) + +/* + * PCI DMA Channel 9 Configuration Register + */ +#define PCI_DMA9C_MBS_BIT 0 /* Maximum Burst Size. */ +#define PCI_DMA9C_MBS 0x00000fff + +/* + * PCI to Memory(DMA Channel 8) AND Memory to PCI DMA(DMA Channel 9)Descriptors + */ + +#define PCI_DMAD_PT_BIT 22 /* in DEVCMD field (descriptor) */ +#define PCI_DMAD_PT 0x00c00000 /* preferred transaction field */ +/* These are for reads (DMA channel 8) */ +#define PCI_DMAD_DEVCMD_MR 0 /* memory read */ +#define PCI_DMAD_DEVCMD_MRL 1 /* memory read line */ +#define PCI_DMAD_DEVCMD_MRM 2 /* memory read multiple */ +#define PCI_DMAD_DEVCMD_IOR 3 /* I/O read */ +/* These are for writes (DMA channel 9) */ +#define PCI_DMAD_DEVCMD_MW 0 /* memory write */ +#define PCI_DMAD_DEVCMD_MWI 1 /* memory write invalidate */ +#define PCI_DMAD_DEVCMD_IOW 3 /* I/O write */ + +/* Swap byte field applies to both DMA channel 8 and 9 */ +#define PCI_DMAD_SB (1 << 24) /* swap byte field */ + + +/* + * PCI Target Control Register + */ + +#define PCI_TC_RTIMER_BIT 0 +#define PCI_TC_RTIMER 0x000000ff +#define PCI_TC_DTIMER_BIT 8 +#define PCI_TC_DTIMER 0x0000ff00 +#define PCI_TC_RDR (1 << 18) +#define PCI_TC_DDT (1 << 19) + +/* + * PCI messaging unit [applies to both inbound and outbound registers ] + */ +#define PCI_MSU_M0 (1 << 0) +#define PCI_MSU_M1 (1 << 1) +#define PCI_MSU_DB (1 << 2) + +#define PCI_MSG_ADDR 0xB8088010 +#define PCI0_ADDR 0xB8080000 +#define rc32434_pci ((struct pci_reg *) PCI0_ADDR) +#define rc32434_pci_msg ((struct pci_msu *) PCI_MSG_ADDR) + +#define PCIM_SHFT 0x6 +#define PCIM_BIT_LEN 0x7 +#define PCIM_H_EA 0x3 +#define PCIM_H_IA_FIX 0x4 +#define PCIM_H_IA_RR 0x5 +#if 0 +#define PCI_ADDR_START 0x13000000 +#endif + +#define PCI_ADDR_START 0x50000000 + +#define CPUTOPCI_MEM_WIN 0x02000000 +#define CPUTOPCI_IO_WIN 0x00100000 +#define PCILBA_SIZE_SHFT 2 +#define PCILBA_SIZE_MASK 0x1F +#define SIZE_256MB 0x1C +#define SIZE_128MB 0x1B +#define SIZE_64MB 0x1A +#define SIZE_32MB 0x19 +#define SIZE_16MB 0x18 +#define SIZE_4MB 0x16 +#define SIZE_2MB 0x15 +#define SIZE_1MB 0x14 +#define KORINA_CONFIG0_ADDR 0x80000000 +#define KORINA_CONFIG1_ADDR 0x80000004 +#define KORINA_CONFIG2_ADDR 0x80000008 +#define KORINA_CONFIG3_ADDR 0x8000000C +#define KORINA_CONFIG4_ADDR 0x80000010 +#define KORINA_CONFIG5_ADDR 0x80000014 +#define KORINA_CONFIG6_ADDR 0x80000018 +#define KORINA_CONFIG7_ADDR 0x8000001C +#define KORINA_CONFIG8_ADDR 0x80000020 +#define KORINA_CONFIG9_ADDR 0x80000024 +#define KORINA_CONFIG10_ADDR 0x80000028 +#define KORINA_CONFIG11_ADDR 0x8000002C +#define KORINA_CONFIG12_ADDR 0x80000030 +#define KORINA_CONFIG13_ADDR 0x80000034 +#define KORINA_CONFIG14_ADDR 0x80000038 +#define KORINA_CONFIG15_ADDR 0x8000003C +#define KORINA_CONFIG16_ADDR 0x80000040 +#define KORINA_CONFIG17_ADDR 0x80000044 +#define KORINA_CONFIG18_ADDR 0x80000048 +#define KORINA_CONFIG19_ADDR 0x8000004C +#define KORINA_CONFIG20_ADDR 0x80000050 +#define KORINA_CONFIG21_ADDR 0x80000054 +#define KORINA_CONFIG22_ADDR 0x80000058 +#define KORINA_CONFIG23_ADDR 0x8000005C +#define KORINA_CONFIG24_ADDR 0x80000060 +#define KORINA_CONFIG25_ADDR 0x80000064 +#define KORINA_CMD (PCI_CFG04_CMD_IO_ENA | \ + PCI_CFG04_CMD_MEM_ENA | \ + PCI_CFG04_CMD_BM_ENA | \ + PCI_CFG04_CMD_MW_INV | \ + PCI_CFG04_CMD_PAR_ENA | \ + PCI_CFG04_CMD_SER_ENA) + +#define KORINA_STAT (PCI_CFG04_STAT_MDPE | \ + PCI_CFG04_STAT_STA | \ + PCI_CFG04_STAT_RTA | \ + PCI_CFG04_STAT_RMA | \ + PCI_CFG04_STAT_SSE | \ + PCI_CFG04_STAT_PE) + +#define KORINA_CNFG1 ((KORINA_STAT<<16)|KORINA_CMD) + +#define KORINA_REVID 0 +#define KORINA_CLASS_CODE 0 +#define KORINA_CNFG2 ((KORINA_CLASS_CODE<<8) | \ + KORINA_REVID) + +#define KORINA_CACHE_LINE_SIZE 4 +#define KORINA_MASTER_LAT 0x3c +#define KORINA_HEADER_TYPE 0 +#define KORINA_BIST 0 + +#define KORINA_CNFG3 ((KORINA_BIST << 24) | \ + (KORINA_HEADER_TYPE<<16) | \ + (KORINA_MASTER_LAT<<8) | \ + KORINA_CACHE_LINE_SIZE) + +#define KORINA_BAR0 0x00000008 /* 128 MB Memory */ +#define KORINA_BAR1 0x18800001 /* 1 MB IO */ +#define KORINA_BAR2 0x18000001 /* 2 MB IO window for Korina + internal Registers */ +#define KORINA_BAR3 0x48000008 /* Spare 128 MB Memory */ + +#define KORINA_CNFG4 KORINA_BAR0 +#define KORINA_CNFG5 KORINA_BAR1 +#define KORINA_CNFG6 KORINA_BAR2 +#define KORINA_CNFG7 KORINA_BAR3 + +#define KORINA_SUBSYS_VENDOR_ID 0x011d +#define KORINA_SUBSYSTEM_ID 0x0214 +#define KORINA_CNFG8 0 +#define KORINA_CNFG9 0 +#define KORINA_CNFG10 0 +#define KORINA_CNFG11 ((KORINA_SUBSYS_VENDOR_ID<<16) | \ + KORINA_SUBSYSTEM_ID) +#define KORINA_INT_LINE 1 +#define KORINA_INT_PIN 1 +#define KORINA_MIN_GNT 8 +#define KORINA_MAX_LAT 0x38 +#define KORINA_CNFG12 0 +#define KORINA_CNFG13 0 +#define KORINA_CNFG14 0 +#define KORINA_CNFG15 ((KORINA_MAX_LAT<<24) | \ + (KORINA_MIN_GNT<<16) | \ + (KORINA_INT_PIN<<8) | \ + KORINA_INT_LINE) +#define KORINA_RETRY_LIMIT 0x80 +#define KORINA_TRDY_LIMIT 0x80 +#define KORINA_CNFG16 ((KORINA_RETRY_LIMIT<<8) | \ + KORINA_TRDY_LIMIT) +#define PCI_PBAxC_R 0x0 +#define PCI_PBAxC_RL 0x1 +#define PCI_PBAxC_RM 0x2 +#define SIZE_SHFT 2 + +#if defined(__MIPSEB__) +#define KORINA_PBA0C (PCI_PBAC_MRL | PCI_PBAC_SB | \ + ((PCI_PBAxC_RM & 0x3) << PCI_PBAC_MR_BIT) | \ + PCI_PBAC_PP | \ + (SIZE_128MB< + * Copyright 2008 Florian Fainelli + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define PROM_ENTRY(x) (0xbfc00000 + ((x) * 8)) + +#define SR_NMI 0x00180000 +#define SERIAL_SPEED_ENTRY 0x00000001 + +#define FREQ_TAG "HZ=" +#define KMAC_TAG "kmac=" +#define MEM_TAG "mem=" +#define BOARD_TAG "board=" + +#define BOARD_RB532 "500" +#define BOARD_RB532A "500r5" diff --git a/arch/mips/include/asm/mach-rc32434/rb.h b/arch/mips/include/asm/mach-rc32434/rb.h new file mode 100644 index 00000000000..79e8ef67d0d --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/rb.h @@ -0,0 +1,84 @@ +/* + * 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. + * + * Copyright (C) 2004 IDT Inc. + * Copyright (C) 2006 Felix Fietkau + */ +#ifndef __ASM_RC32434_RB_H +#define __ASM_RC32434_RB_H + +#include + +#define REGBASE 0x18000000 +#define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(REGBASE)) +#define UART0BASE 0x58000 +#define RST (1 << 15) +#define DEV0BASE 0x010000 +#define DEV0MASK 0x010004 +#define DEV0C 0x010008 +#define DEV0T 0x01000C +#define DEV1BASE 0x010010 +#define DEV1MASK 0x010014 +#define DEV1C 0x010018 +#define DEV1TC 0x01001C +#define DEV2BASE 0x010020 +#define DEV2MASK 0x010024 +#define DEV2C 0x010028 +#define DEV2TC 0x01002C +#define DEV3BASE 0x010030 +#define DEV3MASK 0x010034 +#define DEV3C 0x010038 +#define DEV3TC 0x01003C +#define BTCS 0x010040 +#define BTCOMPARE 0x010044 +#define GPIOBASE 0x050000 +#define GPIOCFG 0x050004 +#define GPIOD 0x050008 +#define GPIOILEVEL 0x05000C +#define GPIOISTAT 0x050010 +#define GPIONMIEN 0x050014 +#define IMASK6 0x038038 +#define LO_WPX (1 << 0) +#define LO_ALE (1 << 1) +#define LO_CLE (1 << 2) +#define LO_CEX (1 << 3) +#define LO_FOFF (1 << 5) +#define LO_SPICS (1 << 6) +#define LO_ULED (1 << 7) + +#define BIT_TO_MASK(x) (1 << x) + +struct dev_reg { + u32 base; + u32 mask; + u32 ctl; + u32 timing; +}; + +struct korina_device { + char *name; + unsigned char mac[6]; + struct net_device *dev; +}; + +struct cf_device { + int gpio_pin; + void *dev; + struct gendisk *gd; +}; + +struct mpmc_device { + unsigned char state; + spinlock_t lock; + void __iomem *base; +}; + +#endif /* __ASM_RC32434_RB_H */ diff --git a/arch/mips/include/asm/mach-rc32434/rc32434.h b/arch/mips/include/asm/mach-rc32434/rc32434.h new file mode 100644 index 00000000000..fce25d4231f --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/rc32434.h @@ -0,0 +1,19 @@ +/* + * Definitions for IDT RC323434 CPU. + */ + +#ifndef _ASM_RC32434_RC32434_H_ +#define _ASM_RC32434_RC32434_H_ + +#include +#include + +#define IDT_CLOCK_MULT 2 + +/* cpu pipeline flush */ +static inline void rc32434_sync(void) +{ + __asm__ volatile ("sync"); +} + +#endif /* _ASM_RC32434_RC32434_H_ */ diff --git a/arch/mips/include/asm/mach-rc32434/timer.h b/arch/mips/include/asm/mach-rc32434/timer.h new file mode 100644 index 00000000000..e49b1d57a01 --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/timer.h @@ -0,0 +1,65 @@ +/* + * Definitions for timer registers + * + * Copyright 2004 Philip Rischel + * Copyright 2008 Florian Fainelli + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __ASM_RC32434_TIMER_H +#define __ASM_RC32434_TIMER_H + +#include + +#define TIMER0_BASE_ADDR 0x18028000 +#define TIMER_COUNT 3 + +struct timer_counter { + u32 count; + u32 compare; + u32 ctc; /*use CTC_ */ +}; + +struct timer { + struct timer_counter tim[TIMER_COUNT]; + u32 rcount; /* use RCOUNT_ */ + u32 rcompare; /* use RCOMPARE_ */ + u32 rtc; /* use RTC_ */ +}; + +#define RC32434_CTC_EN_BIT 0 +#define RC32434_CTC_TO_BIT 1 + +/* Real time clock registers */ +#define RC32434_RTC_MSK(x) BIT_TO_MASK(x) +#define RC32434_RTC_CE_BIT 0 +#define RC32434_RTC_TO_BIT 1 +#define RC32434_RTC_RQE_BIT 2 + +/* Counter registers */ +#define RC32434_RCOUNT_BIT 0 +#define RC32434_RCOUNT_MSK 0x0000ffff +#define RC32434_RCOMP_BIT 0 +#define RC32434_RCOMP_MSK 0x0000ffff + +#endif /* __ASM_RC32434_TIMER_H */ diff --git a/arch/mips/include/asm/mach-rc32434/war.h b/arch/mips/include/asm/mach-rc32434/war.h new file mode 100644 index 00000000000..3ddf187e98a --- /dev/null +++ b/arch/mips/include/asm/mach-rc32434/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_MIPS_WAR_H +#define __ASM_MIPS_MACH_MIPS_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 1 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_MIPS_WAR_H */ diff --git a/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h b/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h new file mode 100644 index 00000000000..ccf54336353 --- /dev/null +++ b/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h @@ -0,0 +1,43 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 04, 07 Ralf Baechle (ralf@linux-mips.org) + * + * SNI RM200 C apparently was only shipped with R4600 V2.0 and R5000 processors. + */ +#ifndef __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H + +#include + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_4k_cache 1 +#define cpu_has_fpu 1 +#define cpu_has_32fpr 1 +#define cpu_has_counter 1 +#define cpu_has_watch 0 +#define cpu_has_mips16 0 +#define cpu_has_divec 0 +#define cpu_has_cache_cdex_p 1 +#define cpu_has_prefetch 0 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 0 +#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000) +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-rm/mc146818rtc.h b/arch/mips/include/asm/mach-rm/mc146818rtc.h new file mode 100644 index 00000000000..145bce096fe --- /dev/null +++ b/arch/mips/include/asm/mach-rm/mc146818rtc.h @@ -0,0 +1,21 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004 by Ralf Baechle + * + * RTC routines for PC style attached Dallas chip with ARC epoch. + */ +#ifndef __ASM_MACH_RM_MC146818RTC_H +#define __ASM_MACH_RM_MC146818RTC_H + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1900) +#else +#define mc146818_decode_year(year) ((year) + 1980) +#endif + +#include_next + +#endif /* __ASM_MACH_RM_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-rm/war.h b/arch/mips/include/asm/mach-rm/war.h new file mode 100644 index 00000000000..948d3129a11 --- /dev/null +++ b/arch/mips/include/asm/mach-rm/war.h @@ -0,0 +1,29 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_RM_WAR_H +#define __ASM_MIPS_MACH_RM_WAR_H + +/* + * The RM200C seems to have been shipped only with V2.0 R4600s + */ + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 1 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_RM_WAR_H */ diff --git a/arch/mips/include/asm/mach-sibyte/cpu-feature-overrides.h b/arch/mips/include/asm/mach-sibyte/cpu-feature-overrides.h new file mode 100644 index 00000000000..1c1f92415b9 --- /dev/null +++ b/arch/mips/include/asm/mach-sibyte/cpu-feature-overrides.h @@ -0,0 +1,47 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 04, 07 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_MACH_SIBYTE_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_SIBYTE_CPU_FEATURE_OVERRIDES_H + +/* + * Sibyte are MIPS64 processors wired to a specific configuration + */ +#define cpu_has_watch 1 +#define cpu_has_mips16 0 +#define cpu_has_divec 1 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 1 +#define cpu_has_ejtag 1 + +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 1 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 +#define cpu_icache_snoops_remote_store 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 1 +#define cpu_has_mips64r2 0 + +#define cpu_has_inclusive_pcaches 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 +#define cpu_scache_line_size() 32 + +#endif /* __ASM_MACH_SIBYTE_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-sibyte/war.h b/arch/mips/include/asm/mach-sibyte/war.h new file mode 100644 index 00000000000..7950ef4f032 --- /dev/null +++ b/arch/mips/include/asm/mach-sibyte/war.h @@ -0,0 +1,37 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_SIBYTE_WAR_H +#define __ASM_MIPS_MACH_SIBYTE_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 + +#if defined(CONFIG_SB1_PASS_1_WORKAROUNDS) || \ + defined(CONFIG_SB1_PASS_2_WORKAROUNDS) + +#define BCM1250_M3_WAR 1 +#define SIBYTE_1956_WAR 1 + +#else + +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 + +#endif + +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_SIBYTE_WAR_H */ diff --git a/arch/mips/include/asm/mach-tx39xx/ioremap.h b/arch/mips/include/asm/mach-tx39xx/ioremap.h new file mode 100644 index 00000000000..93c6c04ffda --- /dev/null +++ b/arch/mips/include/asm/mach-tx39xx/ioremap.h @@ -0,0 +1,38 @@ +/* + * include/asm-mips/mach-tx39xx/ioremap.h + * + * 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. + */ +#ifndef __ASM_MACH_TX39XX_IOREMAP_H +#define __ASM_MACH_TX39XX_IOREMAP_H + +#include + +/* + * Allow physical addresses to be fixed up to help peripherals located + * outside the low 32-bit range -- generic pass-through version. + */ +static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + return phys_addr; +} + +static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, + unsigned long flags) +{ +#define TXX9_DIRECTMAP_BASE 0xff000000ul + if (offset >= TXX9_DIRECTMAP_BASE && + offset < TXX9_DIRECTMAP_BASE + 0xff0000) + return (void __iomem *)offset; + return NULL; +} + +static inline int plat_iounmap(const volatile void __iomem *addr) +{ + return (unsigned long)addr >= TXX9_DIRECTMAP_BASE; +} + +#endif /* __ASM_MACH_TX39XX_IOREMAP_H */ diff --git a/arch/mips/include/asm/mach-tx39xx/mangle-port.h b/arch/mips/include/asm/mach-tx39xx/mangle-port.h new file mode 100644 index 00000000000..ef0b502fd8b --- /dev/null +++ b/arch/mips/include/asm/mach-tx39xx/mangle-port.h @@ -0,0 +1,23 @@ +#ifndef __ASM_MACH_TX39XX_MANGLE_PORT_H +#define __ASM_MACH_TX39XX_MANGLE_PORT_H + +#if defined(CONFIG_TOSHIBA_JMR3927) +extern unsigned long (*__swizzle_addr_b)(unsigned long port); +#define NEEDS_TXX9_SWIZZLE_ADDR_B +#else +#define __swizzle_addr_b(port) (port) +#endif +#define __swizzle_addr_w(port) (port) +#define __swizzle_addr_l(port) (port) +#define __swizzle_addr_q(port) (port) + +#define ioswabb(a, x) (x) +#define __mem_ioswabb(a, x) (x) +#define ioswabw(a, x) le16_to_cpu(x) +#define __mem_ioswabw(a, x) (x) +#define ioswabl(a, x) le32_to_cpu(x) +#define __mem_ioswabl(a, x) (x) +#define ioswabq(a, x) le64_to_cpu(x) +#define __mem_ioswabq(a, x) (x) + +#endif /* __ASM_MACH_TX39XX_MANGLE_PORT_H */ diff --git a/arch/mips/include/asm/mach-tx39xx/war.h b/arch/mips/include/asm/mach-tx39xx/war.h new file mode 100644 index 00000000000..43381461635 --- /dev/null +++ b/arch/mips/include/asm/mach-tx39xx/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_TX39XX_WAR_H +#define __ASM_MIPS_MACH_TX39XX_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_TX39XX_WAR_H */ diff --git a/arch/mips/include/asm/mach-tx49xx/cpu-feature-overrides.h b/arch/mips/include/asm/mach-tx49xx/cpu-feature-overrides.h new file mode 100644 index 00000000000..275eaf92c74 --- /dev/null +++ b/arch/mips/include/asm/mach-tx49xx/cpu-feature-overrides.h @@ -0,0 +1,23 @@ +#ifndef __ASM_MACH_TX49XX_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_TX49XX_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_llsc 1 +#define cpu_has_64bits 1 +#define cpu_has_inclusive_pcaches 0 + +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 +#define cpu_has_vtag_icache 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_TX49XX_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-tx49xx/ioremap.h b/arch/mips/include/asm/mach-tx49xx/ioremap.h new file mode 100644 index 00000000000..1e7beae7222 --- /dev/null +++ b/arch/mips/include/asm/mach-tx49xx/ioremap.h @@ -0,0 +1,43 @@ +/* + * include/asm-mips/mach-tx49xx/ioremap.h + * + * 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. + */ +#ifndef __ASM_MACH_TX49XX_IOREMAP_H +#define __ASM_MACH_TX49XX_IOREMAP_H + +#include + +/* + * Allow physical addresses to be fixed up to help peripherals located + * outside the low 32-bit range -- generic pass-through version. + */ +static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + return phys_addr; +} + +static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, + unsigned long flags) +{ +#ifdef CONFIG_64BIT +#define TXX9_DIRECTMAP_BASE 0xfff000000ul +#else +#define TXX9_DIRECTMAP_BASE 0xff000000ul +#endif + if (offset >= TXX9_DIRECTMAP_BASE && + offset < TXX9_DIRECTMAP_BASE + 0x400000) + return (void __iomem *)(unsigned long)(int)offset; + return NULL; +} + +static inline int plat_iounmap(const volatile void __iomem *addr) +{ + return (unsigned long)addr >= + (unsigned long)(int)(TXX9_DIRECTMAP_BASE & 0xffffffff); +} + +#endif /* __ASM_MACH_TX49XX_IOREMAP_H */ diff --git a/arch/mips/include/asm/mach-tx49xx/kmalloc.h b/arch/mips/include/asm/mach-tx49xx/kmalloc.h new file mode 100644 index 00000000000..913ff196259 --- /dev/null +++ b/arch/mips/include/asm/mach-tx49xx/kmalloc.h @@ -0,0 +1,8 @@ +#ifndef __ASM_MACH_TX49XX_KMALLOC_H +#define __ASM_MACH_TX49XX_KMALLOC_H + +/* + * All happy, no need to define ARCH_KMALLOC_MINALIGN + */ + +#endif /* __ASM_MACH_TX49XX_KMALLOC_H */ diff --git a/arch/mips/include/asm/mach-tx49xx/war.h b/arch/mips/include/asm/mach-tx49xx/war.h new file mode 100644 index 00000000000..39b5d1177c5 --- /dev/null +++ b/arch/mips/include/asm/mach-tx49xx/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_TX49XX_WAR_H +#define __ASM_MIPS_MACH_TX49XX_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 1 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_TX49XX_WAR_H */ diff --git a/arch/mips/include/asm/mach-vr41xx/irq.h b/arch/mips/include/asm/mach-vr41xx/irq.h new file mode 100644 index 00000000000..862058d3f81 --- /dev/null +++ b/arch/mips/include/asm/mach-vr41xx/irq.h @@ -0,0 +1,8 @@ +#ifndef __ASM_MACH_VR41XX_IRQ_H +#define __ASM_MACH_VR41XX_IRQ_H + +#include /* for MIPS_CPU_IRQ_BASE */ + +#include_next + +#endif /* __ASM_MACH_VR41XX_IRQ_H */ diff --git a/arch/mips/include/asm/mach-vr41xx/war.h b/arch/mips/include/asm/mach-vr41xx/war.h new file mode 100644 index 00000000000..56a38926412 --- /dev/null +++ b/arch/mips/include/asm/mach-vr41xx/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_VR41XX_WAR_H +#define __ASM_MIPS_MACH_VR41XX_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_VR41XX_WAR_H */ diff --git a/arch/mips/include/asm/mach-wrppmc/mach-gt64120.h b/arch/mips/include/asm/mach-wrppmc/mach-gt64120.h new file mode 100644 index 00000000000..83746b84a5e --- /dev/null +++ b/arch/mips/include/asm/mach-wrppmc/mach-gt64120.h @@ -0,0 +1,83 @@ +/* + * This is a direct copy of the ev96100.h file, with a global + * search and replace. The numbers are the same. + * + * The reason I'm duplicating this is so that the 64120/96100 + * defines won't be confusing in the source code. + */ +#ifndef __ASM_MIPS_GT64120_H +#define __ASM_MIPS_GT64120_H + +/* + * This is the CPU physical memory map of PPMC Board: + * + * 0x00000000-0x03FFFFFF - 64MB SDRAM (SCS[0]#) + * 0x1C000000-0x1C000000 - LED (CS0) + * 0x1C800000-0x1C800007 - UART 16550 port (CS1) + * 0x1F000000-0x1F000000 - MailBox (CS3) + * 0x1FC00000-0x20000000 - 4MB Flash (BOOT CS) + */ + +#define WRPPMC_SDRAM_SCS0_BASE 0x00000000 +#define WRPPMC_SDRAM_SCS0_SIZE 0x04000000 + +#define WRPPMC_UART16550_BASE 0x1C800000 +#define WRPPMC_UART16550_CLOCK 3686400 /* 3.68MHZ */ + +#define WRPPMC_LED_BASE 0x1C000000 +#define WRPPMC_MBOX_BASE 0x1F000000 + +#define WRPPMC_BOOTROM_BASE 0x1FC00000 +#define WRPPMC_BOOTROM_SIZE 0x00400000 /* 4M Flash */ + +#define WRPPMC_MIPS_TIMER_IRQ 7 /* MIPS compare/count timer interrupt */ +#define WRPPMC_UART16550_IRQ 6 +#define WRPPMC_PCI_INTA_IRQ 3 + +/* + * PCI Bus I/O and Memory resources allocation + * + * NOTE: We only have PCI_0 hose interface + */ +#define GT_PCI_MEM_BASE 0x13000000UL +#define GT_PCI_MEM_SIZE 0x02000000UL +#define GT_PCI_IO_BASE 0x11000000UL +#define GT_PCI_IO_SIZE 0x02000000UL + +/* + * PCI interrupts will come in on either the INTA or INTD interrupt lines, + * which are mapped to the #2 and #5 interrupt pins of the MIPS. On our + * boards, they all either come in on IntD or they all come in on IntA, they + * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the + * "requested" interrupt numbers and go through the list whenever we get an + * IntA/D. + * + * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and + * INTD is 11. + */ +#define GT_TIMER 4 +#define GT_INTA 2 +#define GT_INTD 5 + +#ifndef __ASSEMBLY__ + +/* + * GT64120 internal register space base address + */ +extern unsigned long gt64120_base; + +#define GT64120_BASE (gt64120_base) + +/* define WRPPMC_EARLY_DEBUG to enable early output something to UART */ +#undef WRPPMC_EARLY_DEBUG + +#ifdef WRPPMC_EARLY_DEBUG +extern void wrppmc_led_on(int mask); +extern void wrppmc_led_off(int mask); +extern void wrppmc_early_printk(const char *fmt, ...); +#else +#define wrppmc_early_printk(fmt, ...) do {} while (0) +#endif /* WRPPMC_EARLY_DEBUG */ + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_MIPS_GT64120_H */ diff --git a/arch/mips/include/asm/mach-wrppmc/war.h b/arch/mips/include/asm/mach-wrppmc/war.h new file mode 100644 index 00000000000..ac48629bb1c --- /dev/null +++ b/arch/mips/include/asm/mach-wrppmc/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_WRPPMC_WAR_H +#define __ASM_MIPS_MACH_WRPPMC_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 1 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_WRPPMC_WAR_H */ diff --git a/arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h b/arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h new file mode 100644 index 00000000000..470e5e9e10d --- /dev/null +++ b/arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h @@ -0,0 +1,47 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003, 04, 07 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H + +/* + * Momentum Jaguar ATX always has the RM9000 processor. + */ +#define cpu_has_watch 1 +#define cpu_has_mips16 0 +#define cpu_has_divec 0 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 0 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 +#define cpu_icache_snoops_remote_store 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 + +#define cpu_has_inclusive_pcaches 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 +#define cpu_scache_line_size() 32 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-yosemite/war.h b/arch/mips/include/asm/mach-yosemite/war.h new file mode 100644 index 00000000000..e5c6d53efc8 --- /dev/null +++ b/arch/mips/include/asm/mach-yosemite/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_YOSEMITE_WAR_H +#define __ASM_MIPS_MACH_YOSEMITE_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 1 +#define ICACHE_REFILLS_WORKAROUND_WAR 1 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_YOSEMITE_WAR_H */ diff --git a/arch/mips/include/asm/mc146818-time.h b/arch/mips/include/asm/mc146818-time.h new file mode 100644 index 00000000000..cdc379a0a94 --- /dev/null +++ b/arch/mips/include/asm/mc146818-time.h @@ -0,0 +1,119 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Machine dependent access functions for RTC registers. + */ +#ifndef __ASM_MC146818_TIME_H +#define __ASM_MC146818_TIME_H + +#include +#include +#include + +/* + * For check timing call set_rtc_mmss() 500ms; used in timer interrupt. + */ +#define USEC_AFTER 500000 +#define USEC_BEFORE 500000 + +/* + * In order to set the CMOS clock precisely, set_rtc_mmss has to be + * called 500 ms after the second nowtime has started, because when + * nowtime is written into the registers of the CMOS clock, it will + * jump to the next second precisely 500 ms later. Check the Motorola + * MC146818A or Dallas DS12887 data sheet for details. + * + * BUG: This routine does not handle hour overflow properly; it just + * sets the minutes. Usually you'll only notice that after reboot! + */ +static inline int mc146818_set_rtc_mmss(unsigned long nowtime) +{ + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds, RTC_SECONDS); + CMOS_WRITE(real_minutes, RTC_MINUTES); + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock_irqrestore(&rtc_lock, flags); + + return retval; +} + +static inline unsigned long mc146818_get_cmos_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + + do { + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + spin_unlock_irqrestore(&rtc_lock, flags); + year = mc146818_decode_year(year); + + return mktime(year, mon, day, hour, min, sec); +} + +#endif /* __ASM_MC146818_TIME_H */ diff --git a/arch/mips/include/asm/mc146818rtc.h b/arch/mips/include/asm/mc146818rtc.h new file mode 100644 index 00000000000..68b4da6d520 --- /dev/null +++ b/arch/mips/include/asm/mc146818rtc.h @@ -0,0 +1,16 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Machine dependent access functions for RTC registers. + * + * Copyright (C) 1996, 1997, 1998, 2000 Ralf Baechle + * Copyright (C) 2002 Maciej W. Rozycki + */ +#ifndef _ASM_MC146818RTC_H +#define _ASM_MC146818RTC_H + +#include + +#endif /* _ASM_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mips-boards/bonito64.h b/arch/mips/include/asm/mips-boards/bonito64.h new file mode 100644 index 00000000000..a0f04bb99c9 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/bonito64.h @@ -0,0 +1,436 @@ +/* + * Bonito Register Map + * + * This file is the original bonito.h from Algorithmics with minor changes + * to fit into linux. + * + * Copyright (c) 1999 Algorithmics Ltd + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2001 MIPS Technologies, Inc. All rights reserved. + * + * Algorithmics gives permission for anyone to use and modify this file + * without any obligation or license condition except that you retain + * this copyright message in any source redistribution in whole or part. + * + */ + +/* Revision 1.48 autogenerated on 08/17/99 15:20:01 */ +/* This bonito64 version editted from bonito.h Revision 1.48 on 11/09/00 */ + +#ifndef _ASM_MIPS_BOARDS_BONITO64_H +#define _ASM_MIPS_BOARDS_BONITO64_H + +#ifdef __ASSEMBLY__ + +/* offsets from base register */ +#define BONITO(x) (x) + +#elif defined(CONFIG_LEMOTE_FULONG) + +#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x))) +#define BONITO_IRQ_BASE 32 + +#else + +/* + * Algorithmics Bonito64 system controller register base. + */ +extern unsigned long _pcictrl_bonito; +extern unsigned long _pcictrl_bonito_pcicfg; + +#define BONITO(x) *(volatile u32 *)(_pcictrl_bonito + (x)) + +#endif /* __ASSEMBLY__ */ + + +#define BONITO_BOOT_BASE 0x1fc00000 +#define BONITO_BOOT_SIZE 0x00100000 +#define BONITO_BOOT_TOP (BONITO_BOOT_BASE+BONITO_BOOT_SIZE-1) +#define BONITO_FLASH_BASE 0x1c000000 +#define BONITO_FLASH_SIZE 0x03000000 +#define BONITO_FLASH_TOP (BONITO_FLASH_BASE+BONITO_FLASH_SIZE-1) +#define BONITO_SOCKET_BASE 0x1f800000 +#define BONITO_SOCKET_SIZE 0x00400000 +#define BONITO_SOCKET_TOP (BONITO_SOCKET_BASE+BONITO_SOCKET_SIZE-1) +#define BONITO_REG_BASE 0x1fe00000 +#define BONITO_REG_SIZE 0x00040000 +#define BONITO_REG_TOP (BONITO_REG_BASE+BONITO_REG_SIZE-1) +#define BONITO_DEV_BASE 0x1ff00000 +#define BONITO_DEV_SIZE 0x00100000 +#define BONITO_DEV_TOP (BONITO_DEV_BASE+BONITO_DEV_SIZE-1) +#define BONITO_PCILO_BASE 0x10000000 +#define BONITO_PCILO_SIZE 0x0c000000 +#define BONITO_PCILO_TOP (BONITO_PCILO_BASE+BONITO_PCILO_SIZE-1) +#define BONITO_PCILO0_BASE 0x10000000 +#define BONITO_PCILO1_BASE 0x14000000 +#define BONITO_PCILO2_BASE 0x18000000 +#define BONITO_PCIHI_BASE 0x20000000 +#define BONITO_PCIHI_SIZE 0x20000000 +#define BONITO_PCIHI_TOP (BONITO_PCIHI_BASE+BONITO_PCIHI_SIZE-1) +#define BONITO_PCIIO_BASE 0x1fd00000 +#define BONITO_PCIIO_SIZE 0x00100000 +#define BONITO_PCIIO_TOP (BONITO_PCIIO_BASE+BONITO_PCIIO_SIZE-1) +#define BONITO_PCICFG_BASE 0x1fe80000 +#define BONITO_PCICFG_SIZE 0x00080000 +#define BONITO_PCICFG_TOP (BONITO_PCICFG_BASE+BONITO_PCICFG_SIZE-1) + + +/* Bonito Register Bases */ + +#define BONITO_PCICONFIGBASE 0x00 +#define BONITO_REGBASE 0x100 + + +/* PCI Configuration Registers */ + +#define BONITO_PCI_REG(x) BONITO(BONITO_PCICONFIGBASE + (x)) +#define BONITO_PCIDID BONITO_PCI_REG(0x00) +#define BONITO_PCICMD BONITO_PCI_REG(0x04) +#define BONITO_PCICLASS BONITO_PCI_REG(0x08) +#define BONITO_PCILTIMER BONITO_PCI_REG(0x0c) +#define BONITO_PCIBASE0 BONITO_PCI_REG(0x10) +#define BONITO_PCIBASE1 BONITO_PCI_REG(0x14) +#define BONITO_PCIBASE2 BONITO_PCI_REG(0x18) +#define BONITO_PCIEXPRBASE BONITO_PCI_REG(0x30) +#define BONITO_PCIINT BONITO_PCI_REG(0x3c) + +#define BONITO_PCICMD_PERR_CLR 0x80000000 +#define BONITO_PCICMD_SERR_CLR 0x40000000 +#define BONITO_PCICMD_MABORT_CLR 0x20000000 +#define BONITO_PCICMD_MTABORT_CLR 0x10000000 +#define BONITO_PCICMD_TABORT_CLR 0x08000000 +#define BONITO_PCICMD_MPERR_CLR 0x01000000 +#define BONITO_PCICMD_PERRRESPEN 0x00000040 +#define BONITO_PCICMD_ASTEPEN 0x00000080 +#define BONITO_PCICMD_SERREN 0x00000100 +#define BONITO_PCILTIMER_BUSLATENCY 0x0000ff00 +#define BONITO_PCILTIMER_BUSLATENCY_SHIFT 8 + + + + +/* 1. Bonito h/w Configuration */ +/* Power on register */ + +#define BONITO_BONPONCFG BONITO(BONITO_REGBASE + 0x00) + +#define BONITO_BONPONCFG_SYSCONTROLLERRD 0x00040000 +#define BONITO_BONPONCFG_ROMCS1SAMP 0x00020000 +#define BONITO_BONPONCFG_ROMCS0SAMP 0x00010000 +#define BONITO_BONPONCFG_CPUBIGEND 0x00004000 +/* Added by RPF 11-9-00 */ +#define BONITO_BONPONCFG_BURSTORDER 0x00001000 +/* --- */ +#define BONITO_BONPONCFG_CPUPARITY 0x00002000 +#define BONITO_BONPONCFG_CPUTYPE 0x00000007 +#define BONITO_BONPONCFG_CPUTYPE_SHIFT 0 +#define BONITO_BONPONCFG_PCIRESET_OUT 0x00000008 +#define BONITO_BONPONCFG_IS_ARBITER 0x00000010 +#define BONITO_BONPONCFG_ROMBOOT 0x000000c0 +#define BONITO_BONPONCFG_ROMBOOT_SHIFT 6 + +#define BONITO_BONPONCFG_ROMBOOT_FLASH (0x0<>26) & BONITO_PCIMAP_PCIMAP_LO0) << ((WIN)*6)) + +#define BONITO_PCIMAP_WINSIZE (1<<26) +#define BONITO_PCIMAP_WINOFFSET(ADDR) ((ADDR) & (BONITO_PCIMAP_WINSIZE - 1)) +#define BONITO_PCIMAP_WINBASE(ADDR) ((ADDR) << 26) + +/* pcimembaseCfg */ + +#define BONITO_PCIMEMBASECFG_MASK 0xf0000000 +#define BONITO_PCIMEMBASECFG_MEMBASE0_MASK 0x0000001f +#define BONITO_PCIMEMBASECFG_MEMBASE0_MASK_SHIFT 0 +#define BONITO_PCIMEMBASECFG_MEMBASE0_TRANS 0x000003e0 +#define BONITO_PCIMEMBASECFG_MEMBASE0_TRANS_SHIFT 5 +#define BONITO_PCIMEMBASECFG_MEMBASE0_CACHED 0x00000400 +#define BONITO_PCIMEMBASECFG_MEMBASE0_IO 0x00000800 + +#define BONITO_PCIMEMBASECFG_MEMBASE1_MASK 0x0001f000 +#define BONITO_PCIMEMBASECFG_MEMBASE1_MASK_SHIFT 12 +#define BONITO_PCIMEMBASECFG_MEMBASE1_TRANS 0x003e0000 +#define BONITO_PCIMEMBASECFG_MEMBASE1_TRANS_SHIFT 17 +#define BONITO_PCIMEMBASECFG_MEMBASE1_CACHED 0x00400000 +#define BONITO_PCIMEMBASECFG_MEMBASE1_IO 0x00800000 + +#define BONITO_PCIMEMBASECFG_ASHIFT 23 +#define BONITO_PCIMEMBASECFG_AMASK 0x007fffff +#define BONITO_PCIMEMBASECFGSIZE(WIN, SIZE) (((~((SIZE)-1))>>(BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT)) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) +#define BONITO_PCIMEMBASECFGBASE(WIN, BASE) (((BASE)>>(BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS_SHIFT)) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS) + +#define BONITO_PCIMEMBASECFG_SIZE(WIN, CFG) (((((~(CFG)) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK)) << (BONITO_PCIMEMBASECFG_ASHIFT - BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT)) | BONITO_PCIMEMBASECFG_AMASK) + + +#define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT) +#define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT) +#define BONITO_PCIMEMBASECFG_ADDRTRANS(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT) + +#define BONITO_PCITOPHYS(WIN, ADDR, CFG) ( \ + (((ADDR) & (~(BONITO_PCIMEMBASECFG_MASK))) & (~(BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG)))) | \ + (BONITO_PCIMEMBASECFG_ADDRTRANS(WIN, CFG)) \ + ) + +/* PCICmd */ + +#define BONITO_PCICMD_MEMEN 0x00000002 +#define BONITO_PCICMD_MSTREN 0x00000004 + + +#endif /* _ASM_MIPS_BOARDS_BONITO64_H */ diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h new file mode 100644 index 00000000000..7f0b034dd9a --- /dev/null +++ b/arch/mips/include/asm/mips-boards/generic.h @@ -0,0 +1,104 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Defines of the MIPS boards specific address-MAP, registers, etc. + */ +#ifndef __ASM_MIPS_BOARDS_GENERIC_H +#define __ASM_MIPS_BOARDS_GENERIC_H + +#include +#include +#include + +/* + * Display register base. + */ +#define ASCII_DISPLAY_WORD_BASE 0x1f000410 +#define ASCII_DISPLAY_POS_BASE 0x1f000418 + + +/* + * Yamon Prom print address. + */ +#define YAMON_PROM_PRINT_ADDR 0x1fc00504 + + +/* + * Reset register. + */ +#define SOFTRES_REG 0x1f000500 +#define GORESET 0x42 + +/* + * Revision register. + */ +#define MIPS_REVISION_REG 0x1fc00010 +#define MIPS_REVISION_CORID_QED_RM5261 0 +#define MIPS_REVISION_CORID_CORE_LV 1 +#define MIPS_REVISION_CORID_BONITO64 2 +#define MIPS_REVISION_CORID_CORE_20K 3 +#define MIPS_REVISION_CORID_CORE_FPGA 4 +#define MIPS_REVISION_CORID_CORE_MSC 5 +#define MIPS_REVISION_CORID_CORE_EMUL 6 +#define MIPS_REVISION_CORID_CORE_FPGA2 7 +#define MIPS_REVISION_CORID_CORE_FPGAR2 8 +#define MIPS_REVISION_CORID_CORE_FPGA3 9 +#define MIPS_REVISION_CORID_CORE_24K 10 +#define MIPS_REVISION_CORID_CORE_FPGA4 11 +#define MIPS_REVISION_CORID_CORE_FPGA5 12 + +/**** Artificial corid defines ****/ +/* + * CoreEMUL with Bonito System Controller is treated like a Core20K + * CoreEMUL with SOC-it 101 System Controller is treated like a CoreMSC + */ +#define MIPS_REVISION_CORID_CORE_EMUL_BON -1 +#define MIPS_REVISION_CORID_CORE_EMUL_MSC -2 + +#define MIPS_REVISION_CORID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f) + +extern int mips_revision_corid; + +#define MIPS_REVISION_SCON_OTHER 0 +#define MIPS_REVISION_SCON_SOCITSC 1 +#define MIPS_REVISION_SCON_SOCITSCP 2 + +/* Artificial SCON defines for MIPS_REVISION_SCON_OTHER */ +#define MIPS_REVISION_SCON_UNKNOWN -1 +#define MIPS_REVISION_SCON_GT64120 -2 +#define MIPS_REVISION_SCON_BONITO -3 +#define MIPS_REVISION_SCON_BRTL -4 +#define MIPS_REVISION_SCON_SOCIT -5 +#define MIPS_REVISION_SCON_ROCIT -6 + +#define MIPS_REVISION_SCONID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 24) & 0xff) + +extern int mips_revision_sconid; + +extern void mips_reboot_setup(void); + +#ifdef CONFIG_PCI +extern void mips_pcibios_init(void); +#else +#define mips_pcibios_init() do { } while (0) +#endif + +#ifdef CONFIG_KGDB +extern void kgdb_config(void); +#endif + +#endif /* __ASM_MIPS_BOARDS_GENERIC_H */ diff --git a/arch/mips/include/asm/mips-boards/launch.h b/arch/mips/include/asm/mips-boards/launch.h new file mode 100644 index 00000000000..d8ae7f95a52 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/launch.h @@ -0,0 +1,35 @@ +/* + * + */ + +#ifndef _ASSEMBLER_ + +struct cpulaunch { + unsigned long pc; + unsigned long gp; + unsigned long sp; + unsigned long a0; + unsigned long _pad[3]; /* pad to cache line size to avoid thrashing */ + unsigned long flags; +}; + +#else + +#define LOG2CPULAUNCH 5 +#define LAUNCH_PC 0 +#define LAUNCH_GP 4 +#define LAUNCH_SP 8 +#define LAUNCH_A0 12 +#define LAUNCH_FLAGS 28 + +#endif + +#define LAUNCH_FREADY 1 +#define LAUNCH_FGO 2 +#define LAUNCH_FGONE 4 + +#define CPULAUNCH 0x00000f00 +#define NCPULAUNCH 8 + +/* Polling period in count cycles for secondary CPU's */ +#define LAUNCHPERIOD 10000 diff --git a/arch/mips/include/asm/mips-boards/malta.h b/arch/mips/include/asm/mips-boards/malta.h new file mode 100644 index 00000000000..c1891578fa6 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/malta.h @@ -0,0 +1,102 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Defines of the Malta board specific address-MAP, registers, etc. + */ +#ifndef __ASM_MIPS_BOARDS_MALTA_H +#define __ASM_MIPS_BOARDS_MALTA_H + +#include +#include +#include +#include + +/* Mips interrupt controller found in SOCit variations */ +#define MIPS_MSC01_IC_REG_BASE 0x1bc40000 +#define MIPS_SOCITSC_IC_REG_BASE 0x1ffa0000 + +/* + * Malta I/O ports base address for the Galileo GT64120 and Algorithmics + * Bonito system controllers. + */ +#define MALTA_GT_PORT_BASE get_gt_port_base(GT_PCI0IOLD_OFS) +#define MALTA_BONITO_PORT_BASE ((unsigned long)ioremap (0x1fd00000, 0x10000)) +#define MALTA_MSC_PORT_BASE get_msc_port_base(MSC01_PCI_SC2PIOBASL) + +static inline unsigned long get_gt_port_base(unsigned long reg) +{ + unsigned long addr; + addr = GT_READ(reg); + return (unsigned long) ioremap (((addr & 0xffff) << 21), 0x10000); +} + +static inline unsigned long get_msc_port_base(unsigned long reg) +{ + unsigned long addr; + MSC_READ(reg, addr); + return (unsigned long) ioremap(addr, 0x10000); +} + +/* + * GCMP Specific definitions + */ +#define GCMP_BASE_ADDR 0x1fbf8000 +#define GCMP_ADDRSPACE_SZ (256 * 1024) + +/* + * GIC Specific definitions + */ +#define GIC_BASE_ADDR 0x1bdc0000 +#define GIC_ADDRSPACE_SZ (128 * 1024) + +/* + * MSC01 BIU Specific definitions + * FIXME : These should be elsewhere ? + */ +#define MSC01_BIU_REG_BASE 0x1bc80000 +#define MSC01_BIU_ADDRSPACE_SZ (256 * 1024) +#define MSC01_SC_CFG_OFS 0x0110 +#define MSC01_SC_CFG_GICPRES_MSK 0x00000004 +#define MSC01_SC_CFG_GICPRES_SHF 2 +#define MSC01_SC_CFG_GICENA_SHF 3 + +/* + * Malta RTC-device indirect register access. + */ +#define MALTA_RTC_ADR_REG 0x70 +#define MALTA_RTC_DAT_REG 0x71 + +/* + * Malta SMSC FDC37M817 Super I/O Controller register. + */ +#define SMSC_CONFIG_REG 0x3f0 +#define SMSC_DATA_REG 0x3f1 + +#define SMSC_CONFIG_DEVNUM 0x7 +#define SMSC_CONFIG_ACTIVATE 0x30 +#define SMSC_CONFIG_ENTER 0x55 +#define SMSC_CONFIG_EXIT 0xaa + +#define SMSC_CONFIG_DEVNUM_FLOPPY 0 + +#define SMSC_CONFIG_ACTIVATE_ENABLE 1 + +#define SMSC_WRITE(x, a) outb(x, a) + +#define MALTA_JMPRS_REG 0x1f000210 + +#endif /* __ASM_MIPS_BOARDS_MALTA_H */ diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h new file mode 100644 index 00000000000..cea872fc6f5 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/maltaint.h @@ -0,0 +1,110 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * ######################################################################## + * + * Defines for the Malta interrupt controller. + * + */ +#ifndef _MIPS_MALTAINT_H +#define _MIPS_MALTAINT_H + +#include + +/* + * Interrupts 0..15 are used for Malta ISA compatible interrupts + */ +#define MALTA_INT_BASE 0 + +/* CPU interrupt offsets */ +#define MIPSCPU_INT_SW0 0 +#define MIPSCPU_INT_SW1 1 +#define MIPSCPU_INT_MB0 2 +#define MIPSCPU_INT_I8259A MIPSCPU_INT_MB0 +#define MIPSCPU_INT_MB1 3 +#define MIPSCPU_INT_SMI MIPSCPU_INT_MB1 +#define MIPSCPU_INT_IPI0 MIPSCPU_INT_MB1 /* GIC IPI */ +#define MIPSCPU_INT_MB2 4 +#define MIPSCPU_INT_IPI1 MIPSCPU_INT_MB2 /* GIC IPI */ +#define MIPSCPU_INT_MB3 5 +#define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3 +#define MIPSCPU_INT_MB4 6 +#define MIPSCPU_INT_CORELO MIPSCPU_INT_MB4 + +/* + * Interrupts 64..127 are used for Soc-it Classic interrupts + */ +#define MSC01C_INT_BASE 64 + +/* SOC-it Classic interrupt offsets */ +#define MSC01C_INT_TMR 0 +#define MSC01C_INT_PCI 1 + +/* + * Interrupts 64..127 are used for Soc-it EIC interrupts + */ +#define MSC01E_INT_BASE 64 + +/* SOC-it EIC interrupt offsets */ +#define MSC01E_INT_SW0 1 +#define MSC01E_INT_SW1 2 +#define MSC01E_INT_MB0 3 +#define MSC01E_INT_I8259A MSC01E_INT_MB0 +#define MSC01E_INT_MB1 4 +#define MSC01E_INT_SMI MSC01E_INT_MB1 +#define MSC01E_INT_MB2 5 +#define MSC01E_INT_MB3 6 +#define MSC01E_INT_COREHI MSC01E_INT_MB3 +#define MSC01E_INT_MB4 7 +#define MSC01E_INT_CORELO MSC01E_INT_MB4 +#define MSC01E_INT_TMR 8 +#define MSC01E_INT_PCI 9 +#define MSC01E_INT_PERFCTR 10 +#define MSC01E_INT_CPUCTR 11 + +/* GIC's Nomenclature for Core Interrupt Pins on the Malta */ +#define GIC_CPU_INT0 0 /* Core Interrupt 2 */ +#define GIC_CPU_INT1 1 /* . */ +#define GIC_CPU_INT2 2 /* . */ +#define GIC_CPU_INT3 3 /* . */ +#define GIC_CPU_INT4 4 /* . */ +#define GIC_CPU_INT5 5 /* Core Interrupt 5 */ + +#define GIC_EXT_INTR(x) x + +/* Dummy data */ +#define X 0xdead + +/* External Interrupts used for IPI */ +#define GIC_IPI_EXT_INTR_RESCHED_VPE0 16 +#define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17 +#define GIC_IPI_EXT_INTR_RESCHED_VPE1 18 +#define GIC_IPI_EXT_INTR_CALLFNC_VPE1 19 +#define GIC_IPI_EXT_INTR_RESCHED_VPE2 20 +#define GIC_IPI_EXT_INTR_CALLFNC_VPE2 21 +#define GIC_IPI_EXT_INTR_RESCHED_VPE3 22 +#define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23 + +#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) + +#ifndef __ASSEMBLY__ +extern void maltaint_init(void); +#endif + +#endif /* !(_MIPS_MALTAINT_H) */ diff --git a/arch/mips/include/asm/mips-boards/msc01_pci.h b/arch/mips/include/asm/mips-boards/msc01_pci.h new file mode 100644 index 00000000000..e036b7dd6de --- /dev/null +++ b/arch/mips/include/asm/mips-boards/msc01_pci.h @@ -0,0 +1,258 @@ +/* + * PCI Register definitions for the MIPS System Controller. + * + * Copyright (C) 2002, 2005 MIPS Technologies, Inc. All rights reserved. + * Authors: Carsten Langgaard + * Maciej W. Rozycki + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_MIPS_BOARDS_MSC01_PCI_H +#define __ASM_MIPS_BOARDS_MSC01_PCI_H + +/* + * Register offset addresses + */ + +#define MSC01_PCI_ID_OFS 0x0000 +#define MSC01_PCI_SC2PMBASL_OFS 0x0208 +#define MSC01_PCI_SC2PMMSKL_OFS 0x0218 +#define MSC01_PCI_SC2PMMAPL_OFS 0x0228 +#define MSC01_PCI_SC2PIOBASL_OFS 0x0248 +#define MSC01_PCI_SC2PIOMSKL_OFS 0x0258 +#define MSC01_PCI_SC2PIOMAPL_OFS 0x0268 +#define MSC01_PCI_P2SCMSKL_OFS 0x0308 +#define MSC01_PCI_P2SCMAPL_OFS 0x0318 +#define MSC01_PCI_INTCFG_OFS 0x0600 +#define MSC01_PCI_INTSTAT_OFS 0x0608 +#define MSC01_PCI_CFGADDR_OFS 0x0610 +#define MSC01_PCI_CFGDATA_OFS 0x0618 +#define MSC01_PCI_IACK_OFS 0x0620 +#define MSC01_PCI_HEAD0_OFS 0x2000 /* DevID, VendorID */ +#define MSC01_PCI_HEAD1_OFS 0x2008 /* Status, Command */ +#define MSC01_PCI_HEAD2_OFS 0x2010 /* Class code, RevID */ +#define MSC01_PCI_HEAD3_OFS 0x2018 /* bist, header, latency */ +#define MSC01_PCI_HEAD4_OFS 0x2020 /* BAR 0 */ +#define MSC01_PCI_HEAD5_OFS 0x2028 /* BAR 1 */ +#define MSC01_PCI_HEAD6_OFS 0x2030 /* BAR 2 */ +#define MSC01_PCI_HEAD7_OFS 0x2038 /* BAR 3 */ +#define MSC01_PCI_HEAD8_OFS 0x2040 /* BAR 4 */ +#define MSC01_PCI_HEAD9_OFS 0x2048 /* BAR 5 */ +#define MSC01_PCI_HEAD10_OFS 0x2050 /* CardBus CIS Ptr */ +#define MSC01_PCI_HEAD11_OFS 0x2058 /* SubSystem ID, -VendorID */ +#define MSC01_PCI_HEAD12_OFS 0x2060 /* ROM BAR */ +#define MSC01_PCI_HEAD13_OFS 0x2068 /* Capabilities ptr */ +#define MSC01_PCI_HEAD14_OFS 0x2070 /* reserved */ +#define MSC01_PCI_HEAD15_OFS 0x2078 /* Maxl, ming, intpin, int */ +#define MSC01_PCI_BAR0_OFS 0x2220 +#define MSC01_PCI_CFG_OFS 0x2380 +#define MSC01_PCI_SWAP_OFS 0x2388 + + +/***************************************************************************** + * Register encodings + ****************************************************************************/ + +#define MSC01_PCI_ID_ID_SHF 16 +#define MSC01_PCI_ID_ID_MSK 0x00ff0000 +#define MSC01_PCI_ID_ID_HOSTBRIDGE 82 +#define MSC01_PCI_ID_MAR_SHF 8 +#define MSC01_PCI_ID_MAR_MSK 0x0000ff00 +#define MSC01_PCI_ID_MIR_SHF 0 +#define MSC01_PCI_ID_MIR_MSK 0x000000ff + +#define MSC01_PCI_SC2PMBASL_BAS_SHF 24 +#define MSC01_PCI_SC2PMBASL_BAS_MSK 0xff000000 + +#define MSC01_PCI_SC2PMMSKL_MSK_SHF 24 +#define MSC01_PCI_SC2PMMSKL_MSK_MSK 0xff000000 + +#define MSC01_PCI_SC2PMMAPL_MAP_SHF 24 +#define MSC01_PCI_SC2PMMAPL_MAP_MSK 0xff000000 + +#define MSC01_PCI_SC2PIOBASL_BAS_SHF 24 +#define MSC01_PCI_SC2PIOBASL_BAS_MSK 0xff000000 + +#define MSC01_PCI_SC2PIOMSKL_MSK_SHF 24 +#define MSC01_PCI_SC2PIOMSKL_MSK_MSK 0xff000000 + +#define MSC01_PCI_SC2PIOMAPL_MAP_SHF 24 +#define MSC01_PCI_SC2PIOMAPL_MAP_MSK 0xff000000 + +#define MSC01_PCI_P2SCMSKL_MSK_SHF 24 +#define MSC01_PCI_P2SCMSKL_MSK_MSK 0xff000000 + +#define MSC01_PCI_P2SCMAPL_MAP_SHF 24 +#define MSC01_PCI_P2SCMAPL_MAP_MSK 0xff000000 + +#define MSC01_PCI_INTCFG_RST_SHF 10 +#define MSC01_PCI_INTCFG_RST_MSK 0x00000400 +#define MSC01_PCI_INTCFG_RST_BIT 0x00000400 +#define MSC01_PCI_INTCFG_MWE_SHF 9 +#define MSC01_PCI_INTCFG_MWE_MSK 0x00000200 +#define MSC01_PCI_INTCFG_MWE_BIT 0x00000200 +#define MSC01_PCI_INTCFG_DTO_SHF 8 +#define MSC01_PCI_INTCFG_DTO_MSK 0x00000100 +#define MSC01_PCI_INTCFG_DTO_BIT 0x00000100 +#define MSC01_PCI_INTCFG_MA_SHF 7 +#define MSC01_PCI_INTCFG_MA_MSK 0x00000080 +#define MSC01_PCI_INTCFG_MA_BIT 0x00000080 +#define MSC01_PCI_INTCFG_TA_SHF 6 +#define MSC01_PCI_INTCFG_TA_MSK 0x00000040 +#define MSC01_PCI_INTCFG_TA_BIT 0x00000040 +#define MSC01_PCI_INTCFG_RTY_SHF 5 +#define MSC01_PCI_INTCFG_RTY_MSK 0x00000020 +#define MSC01_PCI_INTCFG_RTY_BIT 0x00000020 +#define MSC01_PCI_INTCFG_MWP_SHF 4 +#define MSC01_PCI_INTCFG_MWP_MSK 0x00000010 +#define MSC01_PCI_INTCFG_MWP_BIT 0x00000010 +#define MSC01_PCI_INTCFG_MRP_SHF 3 +#define MSC01_PCI_INTCFG_MRP_MSK 0x00000008 +#define MSC01_PCI_INTCFG_MRP_BIT 0x00000008 +#define MSC01_PCI_INTCFG_SWP_SHF 2 +#define MSC01_PCI_INTCFG_SWP_MSK 0x00000004 +#define MSC01_PCI_INTCFG_SWP_BIT 0x00000004 +#define MSC01_PCI_INTCFG_SRP_SHF 1 +#define MSC01_PCI_INTCFG_SRP_MSK 0x00000002 +#define MSC01_PCI_INTCFG_SRP_BIT 0x00000002 +#define MSC01_PCI_INTCFG_SE_SHF 0 +#define MSC01_PCI_INTCFG_SE_MSK 0x00000001 +#define MSC01_PCI_INTCFG_SE_BIT 0x00000001 + +#define MSC01_PCI_INTSTAT_RST_SHF 10 +#define MSC01_PCI_INTSTAT_RST_MSK 0x00000400 +#define MSC01_PCI_INTSTAT_RST_BIT 0x00000400 +#define MSC01_PCI_INTSTAT_MWE_SHF 9 +#define MSC01_PCI_INTSTAT_MWE_MSK 0x00000200 +#define MSC01_PCI_INTSTAT_MWE_BIT 0x00000200 +#define MSC01_PCI_INTSTAT_DTO_SHF 8 +#define MSC01_PCI_INTSTAT_DTO_MSK 0x00000100 +#define MSC01_PCI_INTSTAT_DTO_BIT 0x00000100 +#define MSC01_PCI_INTSTAT_MA_SHF 7 +#define MSC01_PCI_INTSTAT_MA_MSK 0x00000080 +#define MSC01_PCI_INTSTAT_MA_BIT 0x00000080 +#define MSC01_PCI_INTSTAT_TA_SHF 6 +#define MSC01_PCI_INTSTAT_TA_MSK 0x00000040 +#define MSC01_PCI_INTSTAT_TA_BIT 0x00000040 +#define MSC01_PCI_INTSTAT_RTY_SHF 5 +#define MSC01_PCI_INTSTAT_RTY_MSK 0x00000020 +#define MSC01_PCI_INTSTAT_RTY_BIT 0x00000020 +#define MSC01_PCI_INTSTAT_MWP_SHF 4 +#define MSC01_PCI_INTSTAT_MWP_MSK 0x00000010 +#define MSC01_PCI_INTSTAT_MWP_BIT 0x00000010 +#define MSC01_PCI_INTSTAT_MRP_SHF 3 +#define MSC01_PCI_INTSTAT_MRP_MSK 0x00000008 +#define MSC01_PCI_INTSTAT_MRP_BIT 0x00000008 +#define MSC01_PCI_INTSTAT_SWP_SHF 2 +#define MSC01_PCI_INTSTAT_SWP_MSK 0x00000004 +#define MSC01_PCI_INTSTAT_SWP_BIT 0x00000004 +#define MSC01_PCI_INTSTAT_SRP_SHF 1 +#define MSC01_PCI_INTSTAT_SRP_MSK 0x00000002 +#define MSC01_PCI_INTSTAT_SRP_BIT 0x00000002 +#define MSC01_PCI_INTSTAT_SE_SHF 0 +#define MSC01_PCI_INTSTAT_SE_MSK 0x00000001 +#define MSC01_PCI_INTSTAT_SE_BIT 0x00000001 + +#define MSC01_PCI_CFGADDR_BNUM_SHF 16 +#define MSC01_PCI_CFGADDR_BNUM_MSK 0x00ff0000 +#define MSC01_PCI_CFGADDR_DNUM_SHF 11 +#define MSC01_PCI_CFGADDR_DNUM_MSK 0x0000f800 +#define MSC01_PCI_CFGADDR_FNUM_SHF 8 +#define MSC01_PCI_CFGADDR_FNUM_MSK 0x00000700 +#define MSC01_PCI_CFGADDR_RNUM_SHF 2 +#define MSC01_PCI_CFGADDR_RNUM_MSK 0x000000fc + +#define MSC01_PCI_CFGDATA_DATA_SHF 0 +#define MSC01_PCI_CFGDATA_DATA_MSK 0xffffffff + +/* The defines below are ONLY valid for a MEM bar! */ +#define MSC01_PCI_BAR0_SIZE_SHF 4 +#define MSC01_PCI_BAR0_SIZE_MSK 0xfffffff0 +#define MSC01_PCI_BAR0_P_SHF 3 +#define MSC01_PCI_BAR0_P_MSK 0x00000008 +#define MSC01_PCI_BAR0_P_BIT MSC01_PCI_BAR0_P_MSK +#define MSC01_PCI_BAR0_D_SHF 1 +#define MSC01_PCI_BAR0_D_MSK 0x00000006 +#define MSC01_PCI_BAR0_T_SHF 0 +#define MSC01_PCI_BAR0_T_MSK 0x00000001 +#define MSC01_PCI_BAR0_T_BIT MSC01_PCI_BAR0_T_MSK + + +#define MSC01_PCI_CFG_RA_SHF 17 +#define MSC01_PCI_CFG_RA_MSK 0x00020000 +#define MSC01_PCI_CFG_RA_BIT MSC01_PCI_CFG_RA_MSK +#define MSC01_PCI_CFG_G_SHF 16 +#define MSC01_PCI_CFG_G_MSK 0x00010000 +#define MSC01_PCI_CFG_G_BIT MSC01_PCI_CFG_G_MSK +#define MSC01_PCI_CFG_EN_SHF 15 +#define MSC01_PCI_CFG_EN_MSK 0x00008000 +#define MSC01_PCI_CFG_EN_BIT MSC01_PCI_CFG_EN_MSK +#define MSC01_PCI_CFG_MAXRTRY_SHF 0 +#define MSC01_PCI_CFG_MAXRTRY_MSK 0x00000fff + +#define MSC01_PCI_SWAP_IO_SHF 18 +#define MSC01_PCI_SWAP_IO_MSK 0x000c0000 +#define MSC01_PCI_SWAP_MEM_SHF 16 +#define MSC01_PCI_SWAP_MEM_MSK 0x00030000 +#define MSC01_PCI_SWAP_BAR0_SHF 0 +#define MSC01_PCI_SWAP_BAR0_MSK 0x00000003 +#define MSC01_PCI_SWAP_NOSWAP 0 +#define MSC01_PCI_SWAP_BYTESWAP 1 + +/* + * MIPS System controller PCI register base. + * + * FIXME - are these macros specific to Malta and co or to the MSC? If the + * latter, they should be moved elsewhere. + */ +#define MIPS_MSC01_PCI_REG_BASE 0x1bd00000 +#define MIPS_SOCITSC_PCI_REG_BASE 0x1ff10000 + +extern unsigned long _pcictrl_msc; + +#define MSC01_PCI_REG_BASE _pcictrl_msc + +#define MSC_WRITE(reg, data) do { *(volatile u32 *)(reg) = data; } while (0) +#define MSC_READ(reg, data) do { data = *(volatile u32 *)(reg); } while (0) + +/* + * Registers absolute addresses + */ + +#define MSC01_PCI_ID (MSC01_PCI_REG_BASE + MSC01_PCI_ID_OFS) +#define MSC01_PCI_SC2PMBASL (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMBASL_OFS) +#define MSC01_PCI_SC2PMMSKL (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMMSKL_OFS) +#define MSC01_PCI_SC2PMMAPL (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMMAPL_OFS) +#define MSC01_PCI_SC2PIOBASL (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOBASL_OFS) +#define MSC01_PCI_SC2PIOMSKL (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOMSKL_OFS) +#define MSC01_PCI_SC2PIOMAPL (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOMAPL_OFS) +#define MSC01_PCI_P2SCMSKL (MSC01_PCI_REG_BASE + MSC01_PCI_P2SCMSKL_OFS) +#define MSC01_PCI_P2SCMAPL (MSC01_PCI_REG_BASE + MSC01_PCI_P2SCMAPL_OFS) +#define MSC01_PCI_INTCFG (MSC01_PCI_REG_BASE + MSC01_PCI_INTCFG_OFS) +#define MSC01_PCI_INTSTAT (MSC01_PCI_REG_BASE + MSC01_PCI_INTSTAT_OFS) +#define MSC01_PCI_CFGADDR (MSC01_PCI_REG_BASE + MSC01_PCI_CFGADDR_OFS) +#define MSC01_PCI_CFGDATA (MSC01_PCI_REG_BASE + MSC01_PCI_CFGDATA_OFS) +#define MSC01_PCI_IACK (MSC01_PCI_REG_BASE + MSC01_PCI_IACK_OFS) +#define MSC01_PCI_HEAD0 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD0_OFS) +#define MSC01_PCI_HEAD1 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD1_OFS) +#define MSC01_PCI_HEAD2 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD2_OFS) +#define MSC01_PCI_HEAD3 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD3_OFS) +#define MSC01_PCI_HEAD4 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD4_OFS) +#define MSC01_PCI_HEAD5 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD5_OFS) +#define MSC01_PCI_HEAD6 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD6_OFS) +#define MSC01_PCI_HEAD7 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD7_OFS) +#define MSC01_PCI_HEAD8 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD8_OFS) +#define MSC01_PCI_HEAD9 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD9_OFS) +#define MSC01_PCI_HEAD10 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD10_OFS) +#define MSC01_PCI_HEAD11 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS) +#define MSC01_PCI_HEAD12 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS) +#define MSC01_PCI_HEAD13 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS) +#define MSC01_PCI_HEAD14 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS) +#define MSC01_PCI_HEAD15 (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS) +#define MSC01_PCI_BAR0 (MSC01_PCI_REG_BASE + MSC01_PCI_BAR0_OFS) +#define MSC01_PCI_CFG (MSC01_PCI_REG_BASE + MSC01_PCI_CFG_OFS) +#define MSC01_PCI_SWAP (MSC01_PCI_REG_BASE + MSC01_PCI_SWAP_OFS) + +#endif /* __ASM_MIPS_BOARDS_MSC01_PCI_H */ diff --git a/arch/mips/include/asm/mips-boards/piix4.h b/arch/mips/include/asm/mips-boards/piix4.h new file mode 100644 index 00000000000..2971d60f2e9 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/piix4.h @@ -0,0 +1,80 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Register definitions for Intel PIIX4 South Bridge Device. + */ +#ifndef __ASM_MIPS_BOARDS_PIIX4_H +#define __ASM_MIPS_BOARDS_PIIX4_H + +/************************************************************************ + * IO register offsets + ************************************************************************/ +#define PIIX4_ICTLR1_ICW1 0x20 +#define PIIX4_ICTLR1_ICW2 0x21 +#define PIIX4_ICTLR1_ICW3 0x21 +#define PIIX4_ICTLR1_ICW4 0x21 +#define PIIX4_ICTLR2_ICW1 0xa0 +#define PIIX4_ICTLR2_ICW2 0xa1 +#define PIIX4_ICTLR2_ICW3 0xa1 +#define PIIX4_ICTLR2_ICW4 0xa1 +#define PIIX4_ICTLR1_OCW1 0x21 +#define PIIX4_ICTLR1_OCW2 0x20 +#define PIIX4_ICTLR1_OCW3 0x20 +#define PIIX4_ICTLR1_OCW4 0x20 +#define PIIX4_ICTLR2_OCW1 0xa1 +#define PIIX4_ICTLR2_OCW2 0xa0 +#define PIIX4_ICTLR2_OCW3 0xa0 +#define PIIX4_ICTLR2_OCW4 0xa0 + + +/************************************************************************ + * Register encodings. + ************************************************************************/ +#define PIIX4_OCW2_NSEOI (0x1 << 5) +#define PIIX4_OCW2_SEOI (0x3 << 5) +#define PIIX4_OCW2_RNSEOI (0x5 << 5) +#define PIIX4_OCW2_RAEOIS (0x4 << 5) +#define PIIX4_OCW2_RAEOIC (0x0 << 5) +#define PIIX4_OCW2_RSEOI (0x7 << 5) +#define PIIX4_OCW2_SP (0x6 << 5) +#define PIIX4_OCW2_NOP (0x2 << 5) + +#define PIIX4_OCW2_SEL (0x0 << 3) + +#define PIIX4_OCW2_ILS_0 0 +#define PIIX4_OCW2_ILS_1 1 +#define PIIX4_OCW2_ILS_2 2 +#define PIIX4_OCW2_ILS_3 3 +#define PIIX4_OCW2_ILS_4 4 +#define PIIX4_OCW2_ILS_5 5 +#define PIIX4_OCW2_ILS_6 6 +#define PIIX4_OCW2_ILS_7 7 +#define PIIX4_OCW2_ILS_8 0 +#define PIIX4_OCW2_ILS_9 1 +#define PIIX4_OCW2_ILS_10 2 +#define PIIX4_OCW2_ILS_11 3 +#define PIIX4_OCW2_ILS_12 4 +#define PIIX4_OCW2_ILS_13 5 +#define PIIX4_OCW2_ILS_14 6 +#define PIIX4_OCW2_ILS_15 7 + +#define PIIX4_OCW3_SEL (0x1 << 3) + +#define PIIX4_OCW3_IRR 0x2 +#define PIIX4_OCW3_ISR 0x3 + +#endif /* __ASM_MIPS_BOARDS_PIIX4_H */ diff --git a/arch/mips/include/asm/mips-boards/prom.h b/arch/mips/include/asm/mips-boards/prom.h new file mode 100644 index 00000000000..a9db576a976 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/prom.h @@ -0,0 +1,47 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * ######################################################################## + * + * MIPS boards bootprom interface for the Linux kernel. + * + */ + +#ifndef _MIPS_PROM_H +#define _MIPS_PROM_H + +extern char *prom_getcmdline(void); +extern char *prom_getenv(char *name); +extern void prom_init_cmdline(void); +extern void prom_meminit(void); +extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); +extern void mips_display_message(const char *str); +extern void mips_display_word(unsigned int num); +extern void mips_scroll_message(void); +extern int get_ethernet_addr(char *ethernet_addr); + +/* Memory descriptor management. */ +#define PROM_MAX_PMEMBLOCKS 32 +struct prom_pmemblock { + unsigned long base; /* Within KSEG0. */ + unsigned int size; /* In bytes. */ + unsigned int type; /* free or prom memory */ +}; + +#endif /* !(_MIPS_PROM_H) */ diff --git a/arch/mips/include/asm/mips-boards/sim.h b/arch/mips/include/asm/mips-boards/sim.h new file mode 100644 index 00000000000..acb7c2331d9 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/sim.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_MIPS_BOARDS_SIM_H +#define _ASM_MIPS_BOARDS_SIM_H + +#define STATS_ON 1 +#define STATS_OFF 2 +#define STATS_CLEAR 3 +#define STATS_DUMP 4 +#define TRACE_ON 5 +#define TRACE_OFF 6 + + +#define simcfg(code) \ +({ \ + __asm__ __volatile__( \ + "sltiu $0,$0, %0" \ + ::"i"(code) \ + ); \ +}) + + + +#endif diff --git a/arch/mips/include/asm/mips-boards/simint.h b/arch/mips/include/asm/mips-boards/simint.h new file mode 100644 index 00000000000..8ef6db76d5c --- /dev/null +++ b/arch/mips/include/asm/mips-boards/simint.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 _MIPS_SIMINT_H +#define _MIPS_SIMINT_H + +#include + +#define SIM_INT_BASE 0 +#define MIPSCPU_INT_MB0 2 +#define MIPS_CPU_TIMER_IRQ 7 + + +#define MSC01E_INT_BASE 64 + +#define MSC01E_INT_CPUCTR 11 + +#endif diff --git a/arch/mips/include/asm/mips_mt.h b/arch/mips/include/asm/mips_mt.h new file mode 100644 index 00000000000..ac7935203f8 --- /dev/null +++ b/arch/mips/include/asm/mips_mt.h @@ -0,0 +1,26 @@ +/* + * Definitions and decalrations for MIPS MT support + * that are common between SMTC, VSMP, and/or AP/SP + * kernel models. + */ +#ifndef __ASM_MIPS_MT_H +#define __ASM_MIPS_MT_H + +#include + +/* + * How many VPEs and TCs is Linux allowed to use? 0 means no limit. + */ +extern int tclimit; +extern int vpelimit; + +extern cpumask_t mt_fpu_cpumask; +extern unsigned long mt_fpemul_threshold; + +extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value); +extern void mips_mt_set_cpuoptions(void); + +struct class; +extern struct class *mt_class; + +#endif /* __ASM_MIPS_MT_H */ diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h new file mode 100644 index 00000000000..c9420aa97e3 --- /dev/null +++ b/arch/mips/include/asm/mipsmtregs.h @@ -0,0 +1,395 @@ +/* + * MT regs definitions, follows on from mipsregs.h + * Copyright (C) 2004 - 2005 MIPS Technologies, Inc. All rights reserved. + * Elizabeth Clarke et. al. + * + */ +#ifndef _ASM_MIPSMTREGS_H +#define _ASM_MIPSMTREGS_H + +#include +#include + +#ifndef __ASSEMBLY__ + +/* + * C macros + */ + +#define read_c0_mvpcontrol() __read_32bit_c0_register($0, 1) +#define write_c0_mvpcontrol(val) __write_32bit_c0_register($0, 1, val) + +#define read_c0_mvpconf0() __read_32bit_c0_register($0, 2) +#define read_c0_mvpconf1() __read_32bit_c0_register($0, 3) + +#define read_c0_vpecontrol() __read_32bit_c0_register($1, 1) +#define write_c0_vpecontrol(val) __write_32bit_c0_register($1, 1, val) + +#define read_c0_vpeconf0() __read_32bit_c0_register($1, 2) +#define write_c0_vpeconf0(val) __write_32bit_c0_register($1, 2, val) + +#define read_c0_tcstatus() __read_32bit_c0_register($2, 1) +#define write_c0_tcstatus(val) __write_32bit_c0_register($2, 1, val) + +#define read_c0_tcbind() __read_32bit_c0_register($2, 2) + +#define read_c0_tccontext() __read_32bit_c0_register($2, 5) +#define write_c0_tccontext(val) __write_32bit_c0_register($2, 5, val) + +#else /* Assembly */ +/* + * Macros for use in assembly language code + */ + +#define CP0_MVPCONTROL $0, 1 +#define CP0_MVPCONF0 $0, 2 +#define CP0_MVPCONF1 $0, 3 +#define CP0_VPECONTROL $1, 1 +#define CP0_VPECONF0 $1, 2 +#define CP0_VPECONF1 $1, 3 +#define CP0_YQMASK $1, 4 +#define CP0_VPESCHEDULE $1, 5 +#define CP0_VPESCHEFBK $1, 6 +#define CP0_TCSTATUS $2, 1 +#define CP0_TCBIND $2, 2 +#define CP0_TCRESTART $2, 3 +#define CP0_TCHALT $2, 4 +#define CP0_TCCONTEXT $2, 5 +#define CP0_TCSCHEDULE $2, 6 +#define CP0_TCSCHEFBK $2, 7 +#define CP0_SRSCONF0 $6, 1 +#define CP0_SRSCONF1 $6, 2 +#define CP0_SRSCONF2 $6, 3 +#define CP0_SRSCONF3 $6, 4 +#define CP0_SRSCONF4 $6, 5 + +#endif + +/* MVPControl fields */ +#define MVPCONTROL_EVP (_ULCAST_(1)) + +#define MVPCONTROL_VPC_SHIFT 1 +#define MVPCONTROL_VPC (_ULCAST_(1) << MVPCONTROL_VPC_SHIFT) + +#define MVPCONTROL_STLB_SHIFT 2 +#define MVPCONTROL_STLB (_ULCAST_(1) << MVPCONTROL_STLB_SHIFT) + + +/* MVPConf0 fields */ +#define MVPCONF0_PTC_SHIFT 0 +#define MVPCONF0_PTC ( _ULCAST_(0xff)) +#define MVPCONF0_PVPE_SHIFT 10 +#define MVPCONF0_PVPE ( _ULCAST_(0xf) << MVPCONF0_PVPE_SHIFT) +#define MVPCONF0_TCA_SHIFT 15 +#define MVPCONF0_TCA ( _ULCAST_(1) << MVPCONF0_TCA_SHIFT) +#define MVPCONF0_PTLBE_SHIFT 16 +#define MVPCONF0_PTLBE (_ULCAST_(0x3ff) << MVPCONF0_PTLBE_SHIFT) +#define MVPCONF0_TLBS_SHIFT 29 +#define MVPCONF0_TLBS (_ULCAST_(1) << MVPCONF0_TLBS_SHIFT) +#define MVPCONF0_M_SHIFT 31 +#define MVPCONF0_M (_ULCAST_(0x1) << MVPCONF0_M_SHIFT) + + +/* config3 fields */ +#define CONFIG3_MT_SHIFT 2 +#define CONFIG3_MT (_ULCAST_(1) << CONFIG3_MT_SHIFT) + + +/* VPEControl fields (per VPE) */ +#define VPECONTROL_TARGTC (_ULCAST_(0xff)) + +#define VPECONTROL_TE_SHIFT 15 +#define VPECONTROL_TE (_ULCAST_(1) << VPECONTROL_TE_SHIFT) +#define VPECONTROL_EXCPT_SHIFT 16 +#define VPECONTROL_EXCPT (_ULCAST_(0x7) << VPECONTROL_EXCPT_SHIFT) + +/* Thread Exception Codes for EXCPT field */ +#define THREX_TU 0 +#define THREX_TO 1 +#define THREX_IYQ 2 +#define THREX_GSX 3 +#define THREX_YSCH 4 +#define THREX_GSSCH 5 + +#define VPECONTROL_GSI_SHIFT 20 +#define VPECONTROL_GSI (_ULCAST_(1) << VPECONTROL_GSI_SHIFT) +#define VPECONTROL_YSI_SHIFT 21 +#define VPECONTROL_YSI (_ULCAST_(1) << VPECONTROL_YSI_SHIFT) + +/* VPEConf0 fields (per VPE) */ +#define VPECONF0_VPA_SHIFT 0 +#define VPECONF0_VPA (_ULCAST_(1) << VPECONF0_VPA_SHIFT) +#define VPECONF0_MVP_SHIFT 1 +#define VPECONF0_MVP (_ULCAST_(1) << VPECONF0_MVP_SHIFT) +#define VPECONF0_XTC_SHIFT 21 +#define VPECONF0_XTC (_ULCAST_(0xff) << VPECONF0_XTC_SHIFT) + +/* TCStatus fields (per TC) */ +#define TCSTATUS_TASID (_ULCAST_(0xff)) +#define TCSTATUS_IXMT_SHIFT 10 +#define TCSTATUS_IXMT (_ULCAST_(1) << TCSTATUS_IXMT_SHIFT) +#define TCSTATUS_TKSU_SHIFT 11 +#define TCSTATUS_TKSU (_ULCAST_(3) << TCSTATUS_TKSU_SHIFT) +#define TCSTATUS_A_SHIFT 13 +#define TCSTATUS_A (_ULCAST_(1) << TCSTATUS_A_SHIFT) +#define TCSTATUS_DA_SHIFT 15 +#define TCSTATUS_DA (_ULCAST_(1) << TCSTATUS_DA_SHIFT) +#define TCSTATUS_DT_SHIFT 20 +#define TCSTATUS_DT (_ULCAST_(1) << TCSTATUS_DT_SHIFT) +#define TCSTATUS_TDS_SHIFT 21 +#define TCSTATUS_TDS (_ULCAST_(1) << TCSTATUS_TDS_SHIFT) +#define TCSTATUS_TSST_SHIFT 22 +#define TCSTATUS_TSST (_ULCAST_(1) << TCSTATUS_TSST_SHIFT) +#define TCSTATUS_RNST_SHIFT 23 +#define TCSTATUS_RNST (_ULCAST_(3) << TCSTATUS_RNST_SHIFT) +/* Codes for RNST */ +#define TC_RUNNING 0 +#define TC_WAITING 1 +#define TC_YIELDING 2 +#define TC_GATED 3 + +#define TCSTATUS_TMX_SHIFT 27 +#define TCSTATUS_TMX (_ULCAST_(1) << TCSTATUS_TMX_SHIFT) +/* TCStatus TCU bits can use same definitions/offsets as CU bits in Status */ + +/* TCBind */ +#define TCBIND_CURVPE_SHIFT 0 +#define TCBIND_CURVPE (_ULCAST_(0xf)) + +#define TCBIND_CURTC_SHIFT 21 + +#define TCBIND_CURTC (_ULCAST_(0xff) << TCBIND_CURTC_SHIFT) + +/* TCHalt */ +#define TCHALT_H (_ULCAST_(1)) + +#ifndef __ASSEMBLY__ + +static inline unsigned int dvpe(void) +{ + int res = 0; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips32r2 \n" + " .word 0x41610001 # dvpe $1 \n" + " move %0, $1 \n" + " ehb \n" + " .set pop \n" + : "=r" (res)); + + instruction_hazard(); + + return res; +} + +static inline void __raw_evpe(void) +{ + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips32r2 \n" + " .word 0x41600021 # evpe \n" + " ehb \n" + " .set pop \n"); +} + +/* Enable virtual processor execution if previous suggested it should be. + EVPE_ENABLE to force */ + +#define EVPE_ENABLE MVPCONTROL_EVP + +static inline void evpe(int previous) +{ + if ((previous & MVPCONTROL_EVP)) + __raw_evpe(); +} + +static inline unsigned int dmt(void) +{ + int res; + + __asm__ __volatile__( + " .set push \n" + " .set mips32r2 \n" + " .set noat \n" + " .word 0x41610BC1 # dmt $1 \n" + " ehb \n" + " move %0, $1 \n" + " .set pop \n" + : "=r" (res)); + + instruction_hazard(); + + return res; +} + +static inline void __raw_emt(void) +{ + __asm__ __volatile__( + " .set noreorder \n" + " .set mips32r2 \n" + " .word 0x41600be1 # emt \n" + " ehb \n" + " .set mips0 \n" + " .set reorder"); +} + +/* enable multi-threaded execution if previous suggested it should be. + EMT_ENABLE to force */ + +#define EMT_ENABLE VPECONTROL_TE + +static inline void emt(int previous) +{ + if ((previous & EMT_ENABLE)) + __raw_emt(); +} + +static inline void ehb(void) +{ + __asm__ __volatile__( + " .set mips32r2 \n" + " ehb \n" + " .set mips0 \n"); +} + +#define mftc0(rt,sel) \ +({ \ + unsigned long __res; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set mips32r2 \n" \ + " .set noat \n" \ + " # mftc0 $1, $" #rt ", " #sel " \n" \ + " .word 0x41000800 | (" #rt " << 16) | " #sel " \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__res)); \ + \ + __res; \ +}) + +#define mftgpr(rt) \ +({ \ + unsigned long __res; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips32r2 \n" \ + " # mftgpr $1," #rt " \n" \ + " .word 0x41000820 | (" #rt " << 16) \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__res)); \ + \ + __res; \ +}) + +#define mftr(rt, u, sel) \ +({ \ + unsigned long __res; \ + \ + __asm__ __volatile__( \ + " mftr %0, " #rt ", " #u ", " #sel " \n" \ + : "=r" (__res)); \ + \ + __res; \ +}) + +#define mttgpr(rd,v) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set mips32r2 \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mttgpr $1, " #rd " \n" \ + " .word 0x41810020 | (" #rd " << 11) \n" \ + " .set pop \n" \ + : : "r" (v)); \ +} while (0) + +#define mttc0(rd, sel, v) \ +({ \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set mips32r2 \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mttc0 %0," #rd ", " #sel " \n" \ + " .word 0x41810000 | (" #rd " << 11) | " #sel " \n" \ + " .set pop \n" \ + : \ + : "r" (v)); \ +}) + + +#define mttr(rd, u, sel, v) \ +({ \ + __asm__ __volatile__( \ + "mttr %0," #rd ", " #u ", " #sel \ + : : "r" (v)); \ +}) + + +#define settc(tc) \ +do { \ + write_c0_vpecontrol((read_c0_vpecontrol()&~VPECONTROL_TARGTC) | (tc)); \ + ehb(); \ +} while (0) + + +/* you *must* set the target tc (settc) before trying to use these */ +#define read_vpe_c0_vpecontrol() mftc0(1, 1) +#define write_vpe_c0_vpecontrol(val) mttc0(1, 1, val) +#define read_vpe_c0_vpeconf0() mftc0(1, 2) +#define write_vpe_c0_vpeconf0(val) mttc0(1, 2, val) +#define read_vpe_c0_count() mftc0(9, 0) +#define write_vpe_c0_count(val) mttc0(9, 0, val) +#define read_vpe_c0_status() mftc0(12, 0) +#define write_vpe_c0_status(val) mttc0(12, 0, val) +#define read_vpe_c0_cause() mftc0(13, 0) +#define write_vpe_c0_cause(val) mttc0(13, 0, val) +#define read_vpe_c0_config() mftc0(16, 0) +#define write_vpe_c0_config(val) mttc0(16, 0, val) +#define read_vpe_c0_config1() mftc0(16, 1) +#define write_vpe_c0_config1(val) mttc0(16, 1, val) +#define read_vpe_c0_config7() mftc0(16, 7) +#define write_vpe_c0_config7(val) mttc0(16, 7, val) +#define read_vpe_c0_ebase() mftc0(15, 1) +#define write_vpe_c0_ebase(val) mttc0(15, 1, val) +#define write_vpe_c0_compare(val) mttc0(11, 0, val) +#define read_vpe_c0_badvaddr() mftc0(8, 0) +#define read_vpe_c0_epc() mftc0(14, 0) +#define write_vpe_c0_epc(val) mttc0(14, 0, val) + + +/* TC */ +#define read_tc_c0_tcstatus() mftc0(2, 1) +#define write_tc_c0_tcstatus(val) mttc0(2, 1, val) +#define read_tc_c0_tcbind() mftc0(2, 2) +#define write_tc_c0_tcbind(val) mttc0(2, 2, val) +#define read_tc_c0_tcrestart() mftc0(2, 3) +#define write_tc_c0_tcrestart(val) mttc0(2, 3, val) +#define read_tc_c0_tchalt() mftc0(2, 4) +#define write_tc_c0_tchalt(val) mttc0(2, 4, val) +#define read_tc_c0_tccontext() mftc0(2, 5) +#define write_tc_c0_tccontext(val) mttc0(2, 5, val) + +/* GPR */ +#define read_tc_gpr_sp() mftgpr(29) +#define write_tc_gpr_sp(val) mttgpr(29, val) +#define read_tc_gpr_gp() mftgpr(28) +#define write_tc_gpr_gp(val) mttgpr(28, val) + +__BUILD_SET_C0(mvpcontrol) + +#endif /* Not __ASSEMBLY__ */ + +#endif diff --git a/arch/mips/include/asm/mipsprom.h b/arch/mips/include/asm/mipsprom.h new file mode 100644 index 00000000000..146d41b67ad --- /dev/null +++ b/arch/mips/include/asm/mipsprom.h @@ -0,0 +1,76 @@ +#ifndef __ASM_MIPS_PROM_H +#define __ASM_MIPS_PROM_H + +#define PROM_RESET 0 +#define PROM_EXEC 1 +#define PROM_RESTART 2 +#define PROM_REINIT 3 +#define PROM_REBOOT 4 +#define PROM_AUTOBOOT 5 +#define PROM_OPEN 6 +#define PROM_READ 7 +#define PROM_WRITE 8 +#define PROM_IOCTL 9 +#define PROM_CLOSE 10 +#define PROM_GETCHAR 11 +#define PROM_PUTCHAR 12 +#define PROM_SHOWCHAR 13 /* XXX */ +#define PROM_GETS 14 /* XXX */ +#define PROM_PUTS 15 /* XXX */ +#define PROM_PRINTF 16 /* XXX */ + +/* What are these for? */ +#define PROM_INITPROTO 17 /* XXX */ +#define PROM_PROTOENABLE 18 /* XXX */ +#define PROM_PROTODISABLE 19 /* XXX */ +#define PROM_GETPKT 20 /* XXX */ +#define PROM_PUTPKT 21 /* XXX */ + +/* More PROM shit. Probably has to do with VME RMW cycles??? */ +#define PROM_ORW_RMW 22 /* XXX */ +#define PROM_ORH_RMW 23 /* XXX */ +#define PROM_ORB_RMW 24 /* XXX */ +#define PROM_ANDW_RMW 25 /* XXX */ +#define PROM_ANDH_RMW 26 /* XXX */ +#define PROM_ANDB_RMW 27 /* XXX */ + +/* Cache handling stuff */ +#define PROM_FLUSHCACHE 28 /* XXX */ +#define PROM_CLEARCACHE 29 /* XXX */ + +/* Libc alike stuff */ +#define PROM_SETJMP 30 /* XXX */ +#define PROM_LONGJMP 31 /* XXX */ +#define PROM_BEVUTLB 32 /* XXX */ +#define PROM_GETENV 33 /* XXX */ +#define PROM_SETENV 34 /* XXX */ +#define PROM_ATOB 35 /* XXX */ +#define PROM_STRCMP 36 /* XXX */ +#define PROM_STRLEN 37 /* XXX */ +#define PROM_STRCPY 38 /* XXX */ +#define PROM_STRCAT 39 /* XXX */ + +/* Misc stuff */ +#define PROM_PARSER 40 /* XXX */ +#define PROM_RANGE 41 /* XXX */ +#define PROM_ARGVIZE 42 /* XXX */ +#define PROM_HELP 43 /* XXX */ + +/* Entry points for some PROM commands */ +#define PROM_DUMPCMD 44 /* XXX */ +#define PROM_SETENVCMD 45 /* XXX */ +#define PROM_UNSETENVCMD 46 /* XXX */ +#define PROM_PRINTENVCMD 47 /* XXX */ +#define PROM_BEVEXCEPT 48 /* XXX */ +#define PROM_ENABLECMD 49 /* XXX */ +#define PROM_DISABLECMD 50 /* XXX */ + +#define PROM_CLEARNOFAULT 51 /* XXX */ +#define PROM_NOTIMPLEMENT 52 /* XXX */ + +#define PROM_NV_GET 53 /* XXX */ +#define PROM_NV_SET 54 /* XXX */ + +extern char *prom_getenv(char *); + +#endif /* __ASM_MIPS_PROM_H */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h new file mode 100644 index 00000000000..979866000da --- /dev/null +++ b/arch/mips/include/asm/mipsregs.h @@ -0,0 +1,1526 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000, 07 MIPS Technologies, Inc. + * Copyright (C) 2003, 2004 Maciej W. Rozycki + */ +#ifndef _ASM_MIPSREGS_H +#define _ASM_MIPSREGS_H + +#include +#include +#include + +/* + * The following macros are especially useful for __asm__ + * inline assembler. + */ +#ifndef __STR +#define __STR(x) #x +#endif +#ifndef STR +#define STR(x) __STR(x) +#endif + +/* + * Configure language + */ +#ifdef __ASSEMBLY__ +#define _ULCAST_ +#else +#define _ULCAST_ (unsigned long) +#endif + +/* + * Coprocessor 0 register names + */ +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONF $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_INFO $7 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_DEBUG $23 +#define CP0_DEPC $24 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 +#define CP0_DESAVE $31 + +/* + * R4640/R4650 cp0 register names. These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux. A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/* + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0 $26 +#define CP0_S1_DERRADDR1 $27 +#define CP0_S1_INTCONTROL $20 + +/* + * Coprocessor 0 Set 2 register names + */ +#define CP0_S2_SRSCTL $12 /* MIPSR2 */ + +/* + * Coprocessor 0 Set 3 register names + */ +#define CP0_S3_SRSMAP $12 /* MIPSR2 */ + +/* + * TX39 Series + */ +#define CP0_TX39_CACHE $7 + +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_STATUS $31 + +/* + * FPU Status Register Values + */ +/* + * Status Register Values + */ + +#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ +#define FPU_CSR_COND 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ +#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ +#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ +#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ +#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ +#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ +#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X 0x00020000 +#define FPU_CSR_INV_X 0x00010000 +#define FPU_CSR_DIV_X 0x00008000 +#define FPU_CSR_OVF_X 0x00004000 +#define FPU_CSR_UDF_X 0x00002000 +#define FPU_CSR_INE_X 0x00001000 + +#define FPU_CSR_ALL_E 0x00000f80 +#define FPU_CSR_INV_E 0x00000800 +#define FPU_CSR_DIV_E 0x00000400 +#define FPU_CSR_OVF_E 0x00000200 +#define FPU_CSR_UDF_E 0x00000100 +#define FPU_CSR_INE_E 0x00000080 + +#define FPU_CSR_ALL_S 0x0000007c +#define FPU_CSR_INV_S 0x00000040 +#define FPU_CSR_DIV_S 0x00000020 +#define FPU_CSR_OVF_S 0x00000010 +#define FPU_CSR_UDF_S 0x00000008 +#define FPU_CSR_INE_S 0x00000004 + +/* rounding mode */ +#define FPU_CSR_RN 0x0 /* nearest */ +#define FPU_CSR_RZ 0x1 /* towards zero */ +#define FPU_CSR_RU 0x2 /* towards +Infinity */ +#define FPU_CSR_RD 0x3 /* towards -Infinity */ + + +/* + * Values for PageMask register + */ +#ifdef CONFIG_CPU_VR41XX + +/* Why doesn't stupidity hurt ... */ + +#define PM_1K 0x00000000 +#define PM_4K 0x00001800 +#define PM_16K 0x00007800 +#define PM_64K 0x0001f800 +#define PM_256K 0x0007f800 + +#else + +#define PM_4K 0x00000000 +#define PM_16K 0x00006000 +#define PM_64K 0x0001e000 +#define PM_256K 0x0007e000 +#define PM_1M 0x001fe000 +#define PM_4M 0x007fe000 +#define PM_16M 0x01ffe000 +#define PM_64M 0x07ffe000 +#define PM_256M 0x1fffe000 + +#endif + +/* + * Default page size for a given kernel configuration + */ +#ifdef CONFIG_PAGE_SIZE_4KB +#define PM_DEFAULT_MASK PM_4K +#elif defined(CONFIG_PAGE_SIZE_16KB) +#define PM_DEFAULT_MASK PM_16K +#elif defined(CONFIG_PAGE_SIZE_64KB) +#define PM_DEFAULT_MASK PM_64K +#else +#error Bad page size configuration! +#endif + + +/* + * Values used for computation of new tlb entries + */ +#define PL_4K 12 +#define PL_16K 14 +#define PL_64K 16 +#define PL_256K 18 +#define PL_1M 20 +#define PL_4M 22 +#define PL_16M 24 +#define PL_64M 26 +#define PL_256M 28 + +/* + * R4x00 interrupt enable / cause bits + */ +#define IE_SW0 (_ULCAST_(1) << 8) +#define IE_SW1 (_ULCAST_(1) << 9) +#define IE_IRQ0 (_ULCAST_(1) << 10) +#define IE_IRQ1 (_ULCAST_(1) << 11) +#define IE_IRQ2 (_ULCAST_(1) << 12) +#define IE_IRQ3 (_ULCAST_(1) << 13) +#define IE_IRQ4 (_ULCAST_(1) << 14) +#define IE_IRQ5 (_ULCAST_(1) << 15) + +/* + * R4x00 interrupt cause bits + */ +#define C_SW0 (_ULCAST_(1) << 8) +#define C_SW1 (_ULCAST_(1) << 9) +#define C_IRQ0 (_ULCAST_(1) << 10) +#define C_IRQ1 (_ULCAST_(1) << 11) +#define C_IRQ2 (_ULCAST_(1) << 12) +#define C_IRQ3 (_ULCAST_(1) << 13) +#define C_IRQ4 (_ULCAST_(1) << 14) +#define C_IRQ5 (_ULCAST_(1) << 15) + +/* + * Bitfields in the R4xx0 cp0 status register + */ +#define ST0_IE 0x00000001 +#define ST0_EXL 0x00000002 +#define ST0_ERL 0x00000004 +#define ST0_KSU 0x00000018 +# define KSU_USER 0x00000010 +# define KSU_SUPERVISOR 0x00000008 +# define KSU_KERNEL 0x00000000 +#define ST0_UX 0x00000020 +#define ST0_SX 0x00000040 +#define ST0_KX 0x00000080 +#define ST0_DE 0x00010000 +#define ST0_CE 0x00020000 + +/* + * Setting c0_status.co enables Hit_Writeback and Hit_Writeback_Invalidate + * cacheops in userspace. This bit exists only on RM7000 and RM9000 + * processors. + */ +#define ST0_CO 0x08000000 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_IEC 0x00000001 +#define ST0_KUC 0x00000002 +#define ST0_IEP 0x00000004 +#define ST0_KUP 0x00000008 +#define ST0_IEO 0x00000010 +#define ST0_KUO 0x00000020 +/* bits 6 & 7 are reserved on R[23]000 */ +#define ST0_ISC 0x00010000 +#define ST0_SWC 0x00020000 +#define ST0_CM 0x00080000 + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM (_ULCAST_(1) << 4) +#define ST0_IL (_ULCAST_(1) << 23) +#define ST0_DL (_ULCAST_(1) << 24) + +/* + * Enable the MIPS MDMX and DSP ASEs + */ +#define ST0_MX 0x01000000 + +/* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT 19 +#define TX39_CONF_ICS_MASK 0x00380000 +#define TX39_CONF_ICS_1KB 0x00000000 +#define TX39_CONF_ICS_2KB 0x00080000 +#define TX39_CONF_ICS_4KB 0x00100000 +#define TX39_CONF_ICS_8KB 0x00180000 +#define TX39_CONF_ICS_16KB 0x00200000 + +#define TX39_CONF_DCS_SHIFT 16 +#define TX39_CONF_DCS_MASK 0x00070000 +#define TX39_CONF_DCS_1KB 0x00000000 +#define TX39_CONF_DCS_2KB 0x00010000 +#define TX39_CONF_DCS_4KB 0x00020000 +#define TX39_CONF_DCS_8KB 0x00030000 +#define TX39_CONF_DCS_16KB 0x00040000 + +#define TX39_CONF_CWFON 0x00004000 +#define TX39_CONF_WBON 0x00002000 +#define TX39_CONF_RF_SHIFT 10 +#define TX39_CONF_RF_MASK 0x00000c00 +#define TX39_CONF_DOZE 0x00000200 +#define TX39_CONF_HALT 0x00000100 +#define TX39_CONF_LOCK 0x00000080 +#define TX39_CONF_ICE 0x00000020 +#define TX39_CONF_DCE 0x00000010 +#define TX39_CONF_IRSIZE_SHIFT 2 +#define TX39_CONF_IRSIZE_MASK 0x0000000c +#define TX39_CONF_DRSIZE_SHIFT 0 +#define TX39_CONF_DRSIZE_MASK 0x00000003 + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM 0x0000ff00 +#define STATUSB_IP0 8 +#define STATUSF_IP0 (_ULCAST_(1) << 8) +#define STATUSB_IP1 9 +#define STATUSF_IP1 (_ULCAST_(1) << 9) +#define STATUSB_IP2 10 +#define STATUSF_IP2 (_ULCAST_(1) << 10) +#define STATUSB_IP3 11 +#define STATUSF_IP3 (_ULCAST_(1) << 11) +#define STATUSB_IP4 12 +#define STATUSF_IP4 (_ULCAST_(1) << 12) +#define STATUSB_IP5 13 +#define STATUSF_IP5 (_ULCAST_(1) << 13) +#define STATUSB_IP6 14 +#define STATUSF_IP6 (_ULCAST_(1) << 14) +#define STATUSB_IP7 15 +#define STATUSF_IP7 (_ULCAST_(1) << 15) +#define STATUSB_IP8 0 +#define STATUSF_IP8 (_ULCAST_(1) << 0) +#define STATUSB_IP9 1 +#define STATUSF_IP9 (_ULCAST_(1) << 1) +#define STATUSB_IP10 2 +#define STATUSF_IP10 (_ULCAST_(1) << 2) +#define STATUSB_IP11 3 +#define STATUSF_IP11 (_ULCAST_(1) << 3) +#define STATUSB_IP12 4 +#define STATUSF_IP12 (_ULCAST_(1) << 4) +#define STATUSB_IP13 5 +#define STATUSF_IP13 (_ULCAST_(1) << 5) +#define STATUSB_IP14 6 +#define STATUSF_IP14 (_ULCAST_(1) << 6) +#define STATUSB_IP15 7 +#define STATUSF_IP15 (_ULCAST_(1) << 7) +#define ST0_CH 0x00040000 +#define ST0_SR 0x00100000 +#define ST0_TS 0x00200000 +#define ST0_BEV 0x00400000 +#define ST0_RE 0x02000000 +#define ST0_FR 0x04000000 +#define ST0_CU 0xf0000000 +#define ST0_CU0 0x10000000 +#define ST0_CU1 0x20000000 +#define ST0_CU2 0x40000000 +#define ST0_CU3 0x80000000 +#define ST0_XX 0x80000000 /* MIPS IV naming */ + +/* + * Bitfields and bit numbers in the coprocessor 0 cause register. + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define CAUSEB_EXCCODE 2 +#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) +#define CAUSEB_IP 8 +#define CAUSEF_IP (_ULCAST_(255) << 8) +#define CAUSEB_IP0 8 +#define CAUSEF_IP0 (_ULCAST_(1) << 8) +#define CAUSEB_IP1 9 +#define CAUSEF_IP1 (_ULCAST_(1) << 9) +#define CAUSEB_IP2 10 +#define CAUSEF_IP2 (_ULCAST_(1) << 10) +#define CAUSEB_IP3 11 +#define CAUSEF_IP3 (_ULCAST_(1) << 11) +#define CAUSEB_IP4 12 +#define CAUSEF_IP4 (_ULCAST_(1) << 12) +#define CAUSEB_IP5 13 +#define CAUSEF_IP5 (_ULCAST_(1) << 13) +#define CAUSEB_IP6 14 +#define CAUSEF_IP6 (_ULCAST_(1) << 14) +#define CAUSEB_IP7 15 +#define CAUSEF_IP7 (_ULCAST_(1) << 15) +#define CAUSEB_IV 23 +#define CAUSEF_IV (_ULCAST_(1) << 23) +#define CAUSEB_CE 28 +#define CAUSEF_CE (_ULCAST_(3) << 28) +#define CAUSEB_BD 31 +#define CAUSEF_BD (_ULCAST_(1) << 31) + +/* + * Bits in the coprocessor 0 config register. + */ +/* Generic bits. */ +#define CONF_CM_CACHABLE_NO_WA 0 +#define CONF_CM_CACHABLE_WA 1 +#define CONF_CM_UNCACHED 2 +#define CONF_CM_CACHABLE_NONCOHERENT 3 +#define CONF_CM_CACHABLE_CE 4 +#define CONF_CM_CACHABLE_COW 5 +#define CONF_CM_CACHABLE_CUW 6 +#define CONF_CM_CACHABLE_ACCELERATED 7 +#define CONF_CM_CMASK 7 +#define CONF_BE (_ULCAST_(1) << 15) + +/* Bits common to various processors. */ +#define CONF_CU (_ULCAST_(1) << 3) +#define CONF_DB (_ULCAST_(1) << 4) +#define CONF_IB (_ULCAST_(1) << 5) +#define CONF_DC (_ULCAST_(7) << 6) +#define CONF_IC (_ULCAST_(7) << 9) +#define CONF_EB (_ULCAST_(1) << 13) +#define CONF_EM (_ULCAST_(1) << 14) +#define CONF_SM (_ULCAST_(1) << 16) +#define CONF_SC (_ULCAST_(1) << 17) +#define CONF_EW (_ULCAST_(3) << 18) +#define CONF_EP (_ULCAST_(15)<< 24) +#define CONF_EC (_ULCAST_(7) << 28) +#define CONF_CM (_ULCAST_(1) << 31) + +/* Bits specific to the R4xx0. */ +#define R4K_CONF_SW (_ULCAST_(1) << 20) +#define R4K_CONF_SS (_ULCAST_(1) << 21) +#define R4K_CONF_SB (_ULCAST_(3) << 22) + +/* Bits specific to the R5000. */ +#define R5K_CONF_SE (_ULCAST_(1) << 12) +#define R5K_CONF_SS (_ULCAST_(3) << 20) + +/* Bits specific to the RM7000. */ +#define RM7K_CONF_SE (_ULCAST_(1) << 3) +#define RM7K_CONF_TE (_ULCAST_(1) << 12) +#define RM7K_CONF_CLK (_ULCAST_(1) << 16) +#define RM7K_CONF_TC (_ULCAST_(1) << 17) +#define RM7K_CONF_SI (_ULCAST_(3) << 20) +#define RM7K_CONF_SC (_ULCAST_(1) << 31) + +/* Bits specific to the R10000. */ +#define R10K_CONF_DN (_ULCAST_(3) << 3) +#define R10K_CONF_CT (_ULCAST_(1) << 5) +#define R10K_CONF_PE (_ULCAST_(1) << 6) +#define R10K_CONF_PM (_ULCAST_(3) << 7) +#define R10K_CONF_EC (_ULCAST_(15)<< 9) +#define R10K_CONF_SB (_ULCAST_(1) << 13) +#define R10K_CONF_SK (_ULCAST_(1) << 14) +#define R10K_CONF_SS (_ULCAST_(7) << 16) +#define R10K_CONF_SC (_ULCAST_(7) << 19) +#define R10K_CONF_DC (_ULCAST_(7) << 26) +#define R10K_CONF_IC (_ULCAST_(7) << 29) + +/* Bits specific to the VR41xx. */ +#define VR41_CONF_CS (_ULCAST_(1) << 12) +#define VR41_CONF_P4K (_ULCAST_(1) << 13) +#define VR41_CONF_BP (_ULCAST_(1) << 16) +#define VR41_CONF_M16 (_ULCAST_(1) << 20) +#define VR41_CONF_AD (_ULCAST_(1) << 23) + +/* Bits specific to the R30xx. */ +#define R30XX_CONF_FDM (_ULCAST_(1) << 19) +#define R30XX_CONF_REV (_ULCAST_(1) << 22) +#define R30XX_CONF_AC (_ULCAST_(1) << 23) +#define R30XX_CONF_RF (_ULCAST_(1) << 24) +#define R30XX_CONF_HALT (_ULCAST_(1) << 25) +#define R30XX_CONF_FPINT (_ULCAST_(7) << 26) +#define R30XX_CONF_DBR (_ULCAST_(1) << 29) +#define R30XX_CONF_SB (_ULCAST_(1) << 30) +#define R30XX_CONF_LOCK (_ULCAST_(1) << 31) + +/* Bits specific to the TX49. */ +#define TX49_CONF_DC (_ULCAST_(1) << 16) +#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ +#define TX49_CONF_HALT (_ULCAST_(1) << 18) +#define TX49_CONF_CWFON (_ULCAST_(1) << 27) + +/* Bits specific to the MIPS32/64 PRA. */ +#define MIPS_CONF_MT (_ULCAST_(7) << 7) +#define MIPS_CONF_AR (_ULCAST_(7) << 10) +#define MIPS_CONF_AT (_ULCAST_(3) << 13) +#define MIPS_CONF_M (_ULCAST_(1) << 31) + +/* + * Bits in the MIPS32/64 PRA coprocessor 0 config registers 1 and above. + */ +#define MIPS_CONF1_FP (_ULCAST_(1) << 0) +#define MIPS_CONF1_EP (_ULCAST_(1) << 1) +#define MIPS_CONF1_CA (_ULCAST_(1) << 2) +#define MIPS_CONF1_WR (_ULCAST_(1) << 3) +#define MIPS_CONF1_PC (_ULCAST_(1) << 4) +#define MIPS_CONF1_MD (_ULCAST_(1) << 5) +#define MIPS_CONF1_C2 (_ULCAST_(1) << 6) +#define MIPS_CONF1_DA (_ULCAST_(7) << 7) +#define MIPS_CONF1_DL (_ULCAST_(7) << 10) +#define MIPS_CONF1_DS (_ULCAST_(7) << 13) +#define MIPS_CONF1_IA (_ULCAST_(7) << 16) +#define MIPS_CONF1_IL (_ULCAST_(7) << 19) +#define MIPS_CONF1_IS (_ULCAST_(7) << 22) +#define MIPS_CONF1_TLBS (_ULCAST_(63)<< 25) + +#define MIPS_CONF2_SA (_ULCAST_(15)<< 0) +#define MIPS_CONF2_SL (_ULCAST_(15)<< 4) +#define MIPS_CONF2_SS (_ULCAST_(15)<< 8) +#define MIPS_CONF2_SU (_ULCAST_(15)<< 12) +#define MIPS_CONF2_TA (_ULCAST_(15)<< 16) +#define MIPS_CONF2_TL (_ULCAST_(15)<< 20) +#define MIPS_CONF2_TS (_ULCAST_(15)<< 24) +#define MIPS_CONF2_TU (_ULCAST_(7) << 28) + +#define MIPS_CONF3_TL (_ULCAST_(1) << 0) +#define MIPS_CONF3_SM (_ULCAST_(1) << 1) +#define MIPS_CONF3_MT (_ULCAST_(1) << 2) +#define MIPS_CONF3_SP (_ULCAST_(1) << 4) +#define MIPS_CONF3_VINT (_ULCAST_(1) << 5) +#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6) +#define MIPS_CONF3_LPA (_ULCAST_(1) << 7) +#define MIPS_CONF3_DSP (_ULCAST_(1) << 10) +#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13) + +#define MIPS_CONF7_WII (_ULCAST_(1) << 31) + +#define MIPS_CONF7_RPS (_ULCAST_(1) << 2) + + +/* + * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. + */ +#define MIPS_FPIR_S (_ULCAST_(1) << 16) +#define MIPS_FPIR_D (_ULCAST_(1) << 17) +#define MIPS_FPIR_PS (_ULCAST_(1) << 18) +#define MIPS_FPIR_3D (_ULCAST_(1) << 19) +#define MIPS_FPIR_W (_ULCAST_(1) << 20) +#define MIPS_FPIR_L (_ULCAST_(1) << 21) +#define MIPS_FPIR_F64 (_ULCAST_(1) << 22) + +#ifndef __ASSEMBLY__ + +/* + * Functions to access the R10000 performance counters. These are basically + * mfc0 and mtc0 instructions from and to coprocessor register with a 5-bit + * performance counter number encoded into bits 1 ... 5 of the instruction. + * Only performance counters 0 to 1 actually exist, so for a non-R10000 aware + * disassembler these will look like an access to sel 0 or 1. + */ +#define read_r10k_perf_cntr(counter) \ +({ \ + unsigned int __res; \ + __asm__ __volatile__( \ + "mfpc\t%0, %1" \ + : "=r" (__res) \ + : "i" (counter)); \ + \ + __res; \ +}) + +#define write_r10k_perf_cntr(counter,val) \ +do { \ + __asm__ __volatile__( \ + "mtpc\t%0, %1" \ + : \ + : "r" (val), "i" (counter)); \ +} while (0) + +#define read_r10k_perf_event(counter) \ +({ \ + unsigned int __res; \ + __asm__ __volatile__( \ + "mfps\t%0, %1" \ + : "=r" (__res) \ + : "i" (counter)); \ + \ + __res; \ +}) + +#define write_r10k_perf_cntl(counter,val) \ +do { \ + __asm__ __volatile__( \ + "mtps\t%0, %1" \ + : \ + : "r" (val), "i" (counter)); \ +} while (0) + + +/* + * Macros to access the system control coprocessor + */ + +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read_64bit_c0_register(source, sel) \ +({ unsigned long long __res; \ + if (sizeof(unsigned long) == 4) \ + __res = __read_64bit_c0_split(source, sel); \ + else if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmfc0\t%0, " #source "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mtc0\t%z0, " #register "\n\t" \ + : : "Jr" ((unsigned int)(value))); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +#define __write_64bit_c0_register(register, sel, value) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_64bit_c0_split(register, sel, value); \ + else if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmtc0\t%z0, " #register "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ +} while (0) + +#define __read_ulong_c0_register(reg, sel) \ + ((sizeof(unsigned long) == 4) ? \ + (unsigned long) __read_32bit_c0_register(reg, sel) : \ + (unsigned long) __read_64bit_c0_register(reg, sel)) + +#define __write_ulong_c0_register(reg, sel, val) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_32bit_c0_register(reg, sel, val); \ + else \ + __write_64bit_c0_register(reg, sel, val); \ +} while (0) + +/* + * On RM7000/RM9000 these are uses to access cop0 set 1 registers + */ +#define __read_32bit_c0_ctrl_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + "cfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_ctrl_register(register, value) \ +do { \ + __asm__ __volatile__( \ + "ctc0\t%z0, " #register "\n\t" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +/* + * These versions are only needed for systems with more than 38 bits of + * physical address space running the 32-bit kernel. That's none atm :-) + */ +#define __read_64bit_c0_split(source, sel) \ +({ \ + unsigned long long __val; \ + unsigned long __flags; \ + \ + local_irq_save(__flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsrl\t%M0, %M0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (__val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source ", " #sel "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsrl\t%M0, %M0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (__val)); \ + local_irq_restore(__flags); \ + \ + __val; \ +}) + +#define __write_64bit_c0_split(source, sel, val) \ +do { \ + unsigned long __flags; \ + \ + local_irq_save(__flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + local_irq_restore(__flags); \ +} while (0) + +#define read_c0_index() __read_32bit_c0_register($0, 0) +#define write_c0_index(val) __write_32bit_c0_register($0, 0, val) + +#define read_c0_random() __read_32bit_c0_register($1, 0) +#define write_c0_random(val) __write_32bit_c0_register($1, 0, val) + +#define read_c0_entrylo0() __read_ulong_c0_register($2, 0) +#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) + +#define read_c0_entrylo1() __read_ulong_c0_register($3, 0) +#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) + +#define read_c0_conf() __read_32bit_c0_register($3, 0) +#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) + +#define read_c0_context() __read_ulong_c0_register($4, 0) +#define write_c0_context(val) __write_ulong_c0_register($4, 0, val) + +#define read_c0_userlocal() __read_ulong_c0_register($4, 2) +#define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val) + +#define read_c0_pagemask() __read_32bit_c0_register($5, 0) +#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) + +#define read_c0_wired() __read_32bit_c0_register($6, 0) +#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val) + +#define read_c0_info() __read_32bit_c0_register($7, 0) + +#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ +#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) + +#define read_c0_badvaddr() __read_ulong_c0_register($8, 0) +#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val) + +#define read_c0_count() __read_32bit_c0_register($9, 0) +#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) + +#define read_c0_count2() __read_32bit_c0_register($9, 6) /* pnx8550 */ +#define write_c0_count2(val) __write_32bit_c0_register($9, 6, val) + +#define read_c0_count3() __read_32bit_c0_register($9, 7) /* pnx8550 */ +#define write_c0_count3(val) __write_32bit_c0_register($9, 7, val) + +#define read_c0_entryhi() __read_ulong_c0_register($10, 0) +#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) + +#define read_c0_compare() __read_32bit_c0_register($11, 0) +#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) + +#define read_c0_compare2() __read_32bit_c0_register($11, 6) /* pnx8550 */ +#define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val) + +#define read_c0_compare3() __read_32bit_c0_register($11, 7) /* pnx8550 */ +#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) + +#define read_c0_status() __read_32bit_c0_register($12, 0) +#ifdef CONFIG_MIPS_MT_SMTC +#define write_c0_status(val) \ +do { \ + __write_32bit_c0_register($12, 0, val); \ + __ehb(); \ +} while (0) +#else +/* + * Legacy non-SMTC code, which may be hazardous + * but which might not support EHB + */ +#define write_c0_status(val) __write_32bit_c0_register($12, 0, val) +#endif /* CONFIG_MIPS_MT_SMTC */ + +#define read_c0_cause() __read_32bit_c0_register($13, 0) +#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) + +#define read_c0_epc() __read_ulong_c0_register($14, 0) +#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) + +#define read_c0_prid() __read_32bit_c0_register($15, 0) + +#define read_c0_config() __read_32bit_c0_register($16, 0) +#define read_c0_config1() __read_32bit_c0_register($16, 1) +#define read_c0_config2() __read_32bit_c0_register($16, 2) +#define read_c0_config3() __read_32bit_c0_register($16, 3) +#define read_c0_config4() __read_32bit_c0_register($16, 4) +#define read_c0_config5() __read_32bit_c0_register($16, 5) +#define read_c0_config6() __read_32bit_c0_register($16, 6) +#define read_c0_config7() __read_32bit_c0_register($16, 7) +#define write_c0_config(val) __write_32bit_c0_register($16, 0, val) +#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val) +#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val) +#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val) +#define write_c0_config4(val) __write_32bit_c0_register($16, 4, val) +#define write_c0_config5(val) __write_32bit_c0_register($16, 5, val) +#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val) +#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val) + +/* + * The WatchLo register. There may be upto 8 of them. + */ +#define read_c0_watchlo0() __read_ulong_c0_register($18, 0) +#define read_c0_watchlo1() __read_ulong_c0_register($18, 1) +#define read_c0_watchlo2() __read_ulong_c0_register($18, 2) +#define read_c0_watchlo3() __read_ulong_c0_register($18, 3) +#define read_c0_watchlo4() __read_ulong_c0_register($18, 4) +#define read_c0_watchlo5() __read_ulong_c0_register($18, 5) +#define read_c0_watchlo6() __read_ulong_c0_register($18, 6) +#define read_c0_watchlo7() __read_ulong_c0_register($18, 7) +#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val) +#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val) +#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val) +#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val) +#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val) +#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val) +#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val) +#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val) + +/* + * The WatchHi register. There may be upto 8 of them. + */ +#define read_c0_watchhi0() __read_32bit_c0_register($19, 0) +#define read_c0_watchhi1() __read_32bit_c0_register($19, 1) +#define read_c0_watchhi2() __read_32bit_c0_register($19, 2) +#define read_c0_watchhi3() __read_32bit_c0_register($19, 3) +#define read_c0_watchhi4() __read_32bit_c0_register($19, 4) +#define read_c0_watchhi5() __read_32bit_c0_register($19, 5) +#define read_c0_watchhi6() __read_32bit_c0_register($19, 6) +#define read_c0_watchhi7() __read_32bit_c0_register($19, 7) + +#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val) +#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val) +#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val) +#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val) +#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val) +#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val) +#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val) +#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val) + +#define read_c0_xcontext() __read_ulong_c0_register($20, 0) +#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val) + +#define read_c0_intcontrol() __read_32bit_c0_ctrl_register($20) +#define write_c0_intcontrol(val) __write_32bit_c0_ctrl_register($20, val) + +#define read_c0_framemask() __read_32bit_c0_register($21, 0) +#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val) + +/* RM9000 PerfControl performance counter control register */ +#define read_c0_perfcontrol() __read_32bit_c0_register($22, 0) +#define write_c0_perfcontrol(val) __write_32bit_c0_register($22, 0, val) + +#define read_c0_diag() __read_32bit_c0_register($22, 0) +#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val) + +#define read_c0_diag1() __read_32bit_c0_register($22, 1) +#define write_c0_diag1(val) __write_32bit_c0_register($22, 1, val) + +#define read_c0_diag2() __read_32bit_c0_register($22, 2) +#define write_c0_diag2(val) __write_32bit_c0_register($22, 2, val) + +#define read_c0_diag3() __read_32bit_c0_register($22, 3) +#define write_c0_diag3(val) __write_32bit_c0_register($22, 3, val) + +#define read_c0_diag4() __read_32bit_c0_register($22, 4) +#define write_c0_diag4(val) __write_32bit_c0_register($22, 4, val) + +#define read_c0_diag5() __read_32bit_c0_register($22, 5) +#define write_c0_diag5(val) __write_32bit_c0_register($22, 5, val) + +#define read_c0_debug() __read_32bit_c0_register($23, 0) +#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val) + +#define read_c0_depc() __read_ulong_c0_register($24, 0) +#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val) + +/* + * MIPS32 / MIPS64 performance counters + */ +#define read_c0_perfctrl0() __read_32bit_c0_register($25, 0) +#define write_c0_perfctrl0(val) __write_32bit_c0_register($25, 0, val) +#define read_c0_perfcntr0() __read_32bit_c0_register($25, 1) +#define write_c0_perfcntr0(val) __write_32bit_c0_register($25, 1, val) +#define read_c0_perfctrl1() __read_32bit_c0_register($25, 2) +#define write_c0_perfctrl1(val) __write_32bit_c0_register($25, 2, val) +#define read_c0_perfcntr1() __read_32bit_c0_register($25, 3) +#define write_c0_perfcntr1(val) __write_32bit_c0_register($25, 3, val) +#define read_c0_perfctrl2() __read_32bit_c0_register($25, 4) +#define write_c0_perfctrl2(val) __write_32bit_c0_register($25, 4, val) +#define read_c0_perfcntr2() __read_32bit_c0_register($25, 5) +#define write_c0_perfcntr2(val) __write_32bit_c0_register($25, 5, val) +#define read_c0_perfctrl3() __read_32bit_c0_register($25, 6) +#define write_c0_perfctrl3(val) __write_32bit_c0_register($25, 6, val) +#define read_c0_perfcntr3() __read_32bit_c0_register($25, 7) +#define write_c0_perfcntr3(val) __write_32bit_c0_register($25, 7, val) + +/* RM9000 PerfCount performance counter register */ +#define read_c0_perfcount() __read_64bit_c0_register($25, 0) +#define write_c0_perfcount(val) __write_64bit_c0_register($25, 0, val) + +#define read_c0_ecc() __read_32bit_c0_register($26, 0) +#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val) + +#define read_c0_derraddr0() __read_ulong_c0_register($26, 1) +#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val) + +#define read_c0_cacheerr() __read_32bit_c0_register($27, 0) + +#define read_c0_derraddr1() __read_ulong_c0_register($27, 1) +#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val) + +#define read_c0_taglo() __read_32bit_c0_register($28, 0) +#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) + +#define read_c0_dtaglo() __read_32bit_c0_register($28, 2) +#define write_c0_dtaglo(val) __write_32bit_c0_register($28, 2, val) + +#define read_c0_taghi() __read_32bit_c0_register($29, 0) +#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) + +#define read_c0_errorepc() __read_ulong_c0_register($30, 0) +#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val) + +/* MIPSR2 */ +#define read_c0_hwrena() __read_32bit_c0_register($7, 0) +#define write_c0_hwrena(val) __write_32bit_c0_register($7, 0, val) + +#define read_c0_intctl() __read_32bit_c0_register($12, 1) +#define write_c0_intctl(val) __write_32bit_c0_register($12, 1, val) + +#define read_c0_srsctl() __read_32bit_c0_register($12, 2) +#define write_c0_srsctl(val) __write_32bit_c0_register($12, 2, val) + +#define read_c0_srsmap() __read_32bit_c0_register($12, 3) +#define write_c0_srsmap(val) __write_32bit_c0_register($12, 3, val) + +#define read_c0_ebase() __read_32bit_c0_register($15, 1) +#define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) + +/* + * Macros to access the floating point coprocessor control registers + */ +#define read_32bit_cp1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc1\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +#define rddsp(mask) \ +({ \ + unsigned int __res; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # rddsp $1, %x1 \n" \ + " .word 0x7c000cb8 | (%x1 << 16) \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__res) \ + : "i" (mask)); \ + __res; \ +}) + +#define wrdsp(val, mask) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # wrdsp $1, %x1 \n" \ + " .word 0x7c2004f8 | (%x1 << 11) \n" \ + " .set pop \n" \ + : \ + : "r" (val), "i" (mask)); \ +} while (0) + +#if 0 /* Need DSP ASE capable assembler ... */ +#define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;}) +#define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;}) +#define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;}) +#define mflo3() ({ long mflo3; __asm__("mflo %0, $ac3" : "=r" (mflo3)); mflo3;}) + +#define mfhi0() ({ long mfhi0; __asm__("mfhi %0, $ac0" : "=r" (mfhi0)); mfhi0;}) +#define mfhi1() ({ long mfhi1; __asm__("mfhi %0, $ac1" : "=r" (mfhi1)); mfhi1;}) +#define mfhi2() ({ long mfhi2; __asm__("mfhi %0, $ac2" : "=r" (mfhi2)); mfhi2;}) +#define mfhi3() ({ long mfhi3; __asm__("mfhi %0, $ac3" : "=r" (mfhi3)); mfhi3;}) + +#define mtlo0(x) __asm__("mtlo %0, $ac0" ::"r" (x)) +#define mtlo1(x) __asm__("mtlo %0, $ac1" ::"r" (x)) +#define mtlo2(x) __asm__("mtlo %0, $ac2" ::"r" (x)) +#define mtlo3(x) __asm__("mtlo %0, $ac3" ::"r" (x)) + +#define mthi0(x) __asm__("mthi %0, $ac0" ::"r" (x)) +#define mthi1(x) __asm__("mthi %0, $ac1" ::"r" (x)) +#define mthi2(x) __asm__("mthi %0, $ac2" ::"r" (x)) +#define mthi3(x) __asm__("mthi %0, $ac3" ::"r" (x)) + +#else + +#define mfhi0() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mfhi %0, $ac0 \n" \ + " .word 0x00000810 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mfhi1() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mfhi %0, $ac1 \n" \ + " .word 0x00200810 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mfhi2() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mfhi %0, $ac2 \n" \ + " .word 0x00400810 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mfhi3() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mfhi %0, $ac3 \n" \ + " .word 0x00600810 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mflo0() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mflo %0, $ac0 \n" \ + " .word 0x00000812 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mflo1() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mflo %0, $ac1 \n" \ + " .word 0x00200812 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mflo2() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mflo %0, $ac2 \n" \ + " .word 0x00400812 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mflo3() \ +({ \ + unsigned long __treg; \ + \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " # mflo %0, $ac3 \n" \ + " .word 0x00600812 \n" \ + " move %0, $1 \n" \ + " .set pop \n" \ + : "=r" (__treg)); \ + __treg; \ +}) + +#define mthi0(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mthi $1, $ac0 \n" \ + " .word 0x00200011 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#define mthi1(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mthi $1, $ac1 \n" \ + " .word 0x00200811 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#define mthi2(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mthi $1, $ac2 \n" \ + " .word 0x00201011 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#define mthi3(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mthi $1, $ac3 \n" \ + " .word 0x00201811 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#define mtlo0(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mtlo $1, $ac0 \n" \ + " .word 0x00200013 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#define mtlo1(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mtlo $1, $ac1 \n" \ + " .word 0x00200813 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#define mtlo2(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mtlo $1, $ac2 \n" \ + " .word 0x00201013 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#define mtlo3(x) \ +do { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " move $1, %0 \n" \ + " # mtlo $1, $ac3 \n" \ + " .word 0x00201813 \n" \ + " .set pop \n" \ + : \ + : "r" (x)); \ +} while (0) + +#endif + +/* + * TLB operations. + * + * It is responsibility of the caller to take care of any TLB hazards. + */ +static inline void tlb_probe(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbp\n\t" + ".set reorder"); +} + +static inline void tlb_read(void) +{ +#if MIPS34K_MISSED_ITLB_WAR + int res = 0; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips32r2 \n" + " .word 0x41610001 # dvpe $1 \n" + " move %0, $1 \n" + " ehb \n" + " .set pop \n" + : "=r" (res)); + + instruction_hazard(); +#endif + + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbr\n\t" + ".set reorder"); + +#if MIPS34K_MISSED_ITLB_WAR + if ((res & _ULCAST_(1))) + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips32r2 \n" + " .word 0x41600021 # evpe \n" + " ehb \n" + " .set pop \n"); +#endif +} + +static inline void tlb_write_indexed(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwi\n\t" + ".set reorder"); +} + +static inline void tlb_write_random(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwr\n\t" + ".set reorder"); +} + +/* + * Manipulate bits in a c0 register. + */ +#ifndef CONFIG_MIPS_MT_SMTC +/* + * SMTC Linux requires shutting-down microthread scheduling + * during CP0 register read-modify-write sequences. + */ +#define __BUILD_SET_C0(name) \ +static inline unsigned int \ +set_c0_##name(unsigned int set) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res |= set; \ + write_c0_##name(res); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +clear_c0_##name(unsigned int clear) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res &= ~clear; \ + write_c0_##name(res); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +change_c0_##name(unsigned int change, unsigned int new) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res &= ~change; \ + res |= (new & change); \ + write_c0_##name(res); \ + \ + return res; \ +} + +#else /* SMTC versions that manage MT scheduling */ + +#include + +/* + * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with + * header file recursion. + */ +static inline unsigned int __dmt(void) +{ + int res; + + __asm__ __volatile__( + " .set push \n" + " .set mips32r2 \n" + " .set noat \n" + " .word 0x41610BC1 # dmt $1 \n" + " ehb \n" + " move %0, $1 \n" + " .set pop \n" + : "=r" (res)); + + instruction_hazard(); + + return res; +} + +#define __VPECONTROL_TE_SHIFT 15 +#define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT) + +#define __EMT_ENABLE __VPECONTROL_TE + +static inline void __emt(unsigned int previous) +{ + if ((previous & __EMT_ENABLE)) + __asm__ __volatile__( + " .set mips32r2 \n" + " .word 0x41600be1 # emt \n" + " ehb \n" + " .set mips0 \n"); +} + +static inline void __ehb(void) +{ + __asm__ __volatile__( + " .set mips32r2 \n" + " ehb \n" " .set mips0 \n"); +} + +/* + * Note that local_irq_save/restore affect TC-specific IXMT state, + * not Status.IE as in non-SMTC kernel. + */ + +#define __BUILD_SET_C0(name) \ +static inline unsigned int \ +set_c0_##name(unsigned int set) \ +{ \ + unsigned int res; \ + unsigned int omt; \ + unsigned long flags; \ + \ + local_irq_save(flags); \ + omt = __dmt(); \ + res = read_c0_##name(); \ + res |= set; \ + write_c0_##name(res); \ + __emt(omt); \ + local_irq_restore(flags); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +clear_c0_##name(unsigned int clear) \ +{ \ + unsigned int res; \ + unsigned int omt; \ + unsigned long flags; \ + \ + local_irq_save(flags); \ + omt = __dmt(); \ + res = read_c0_##name(); \ + res &= ~clear; \ + write_c0_##name(res); \ + __emt(omt); \ + local_irq_restore(flags); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +change_c0_##name(unsigned int change, unsigned int new) \ +{ \ + unsigned int res; \ + unsigned int omt; \ + unsigned long flags; \ + \ + local_irq_save(flags); \ + \ + omt = __dmt(); \ + res = read_c0_##name(); \ + res &= ~change; \ + res |= (new & change); \ + write_c0_##name(res); \ + __emt(omt); \ + local_irq_restore(flags); \ + \ + return res; \ +} +#endif + +__BUILD_SET_C0(status) +__BUILD_SET_C0(cause) +__BUILD_SET_C0(config) +__BUILD_SET_C0(intcontrol) +__BUILD_SET_C0(intctl) +__BUILD_SET_C0(srsmap) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_MIPSREGS_H */ diff --git a/arch/mips/include/asm/mman.h b/arch/mips/include/asm/mman.h new file mode 100644 index 00000000000..e4d6f1fb1cf --- /dev/null +++ b/arch/mips/include/asm/mman.h @@ -0,0 +1,77 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999, 2002 by Ralf Baechle + */ +#ifndef _ASM_MMAN_H +#define _ASM_MMAN_H + +/* + * Protections are chosen from these bits, OR'd together. The + * implementation does not necessarily support PROT_EXEC or PROT_WRITE + * without PROT_READ. The only guarantees are that no writing will be + * allowed without PROT_WRITE and no access will be allowed for PROT_NONE. + */ +#define PROT_NONE 0x00 /* page can not be accessed */ +#define PROT_READ 0x01 /* page can be read */ +#define PROT_WRITE 0x02 /* page can be written */ +#define PROT_EXEC 0x04 /* page can be executed */ +/* 0x08 reserved for PROT_EXEC_NOFLUSH */ +#define PROT_SEM 0x10 /* page may be used for atomic ops */ +#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ +#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ + +/* + * Flags for mmap + */ +#define MAP_SHARED 0x001 /* Share changes */ +#define MAP_PRIVATE 0x002 /* Changes are private */ +#define MAP_TYPE 0x00f /* Mask for type of mapping */ +#define MAP_FIXED 0x010 /* Interpret addr exactly */ + +/* not used by linux, but here to make sure we don't clash with ABI defines */ +#define MAP_RENAME 0x020 /* Assign page to file */ +#define MAP_AUTOGROW 0x040 /* File may grow by writing */ +#define MAP_LOCAL 0x080 /* Copy on fork/sproc */ +#define MAP_AUTORSRV 0x100 /* Logical swap reserved on demand */ + +/* These are linux-specific */ +#define MAP_NORESERVE 0x0400 /* don't check for reservations */ +#define MAP_ANONYMOUS 0x0800 /* don't use a file */ +#define MAP_GROWSDOWN 0x1000 /* stack-like segment */ +#define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x4000 /* mark it as an executable */ +#define MAP_LOCKED 0x8000 /* pages are locked */ +#define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x20000 /* do not block on IO */ + +/* + * Flags for msync + */ +#define MS_ASYNC 0x0001 /* sync memory asynchronously */ +#define MS_INVALIDATE 0x0002 /* invalidate mappings & caches */ +#define MS_SYNC 0x0004 /* synchronous memory sync */ + +/* + * Flags for mlockall + */ +#define MCL_CURRENT 1 /* lock all current mappings */ +#define MCL_FUTURE 2 /* lock all future mappings */ + +#define MADV_NORMAL 0 /* no further special treatment */ +#define MADV_RANDOM 1 /* expect random page references */ +#define MADV_SEQUENTIAL 2 /* expect sequential page references */ +#define MADV_WILLNEED 3 /* will need these pages */ +#define MADV_DONTNEED 4 /* don't need these pages */ + +/* common parameters: try to keep these consistent across architectures */ +#define MADV_REMOVE 9 /* remove these pages & resources */ +#define MADV_DONTFORK 10 /* don't inherit across fork */ +#define MADV_DOFORK 11 /* do inherit across fork */ + +/* compatibility flags */ +#define MAP_FILE 0 + +#endif /* _ASM_MMAN_H */ diff --git a/arch/mips/include/asm/mmu.h b/arch/mips/include/asm/mmu.h new file mode 100644 index 00000000000..4063edd7962 --- /dev/null +++ b/arch/mips/include/asm/mmu.h @@ -0,0 +1,6 @@ +#ifndef __ASM_MMU_H +#define __ASM_MMU_H + +typedef unsigned long mm_context_t[NR_CPUS]; + +#endif /* __ASM_MMU_H */ diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h new file mode 100644 index 00000000000..d7f3eb03ad1 --- /dev/null +++ b/arch/mips/include/asm/mmu_context.h @@ -0,0 +1,297 @@ +/* + * Switch a MMU context. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_MMU_CONTEXT_H +#define _ASM_MMU_CONTEXT_H + +#include +#include +#include +#include +#include +#ifdef CONFIG_MIPS_MT_SMTC +#include +#include +#endif /* SMTC */ +#include + +/* + * For the fast tlb miss handlers, we keep a per cpu array of pointers + * to the current pgd for each processor. Also, the proc. id is stuffed + * into the context register. + */ +extern unsigned long pgd_current[]; + +#define TLBMISS_HANDLER_SETUP_PGD(pgd) \ + pgd_current[smp_processor_id()] = (unsigned long)(pgd) + +#ifdef CONFIG_32BIT +#define TLBMISS_HANDLER_SETUP() \ + write_c0_context((unsigned long) smp_processor_id() << 25); \ + TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) +#endif +#ifdef CONFIG_64BIT +#define TLBMISS_HANDLER_SETUP() \ + write_c0_context((unsigned long) smp_processor_id() << 26); \ + TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) +#endif + +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + +#define ASID_INC 0x40 +#define ASID_MASK 0xfc0 + +#elif defined(CONFIG_CPU_R8000) + +#define ASID_INC 0x10 +#define ASID_MASK 0xff0 + +#elif defined(CONFIG_CPU_RM9000) + +#define ASID_INC 0x1 +#define ASID_MASK 0xfff + +/* SMTC/34K debug hack - but maybe we'll keep it */ +#elif defined(CONFIG_MIPS_MT_SMTC) + +#define ASID_INC 0x1 +extern unsigned long smtc_asid_mask; +#define ASID_MASK (smtc_asid_mask) +#define HW_ASID_MASK 0xff +/* End SMTC/34K debug hack */ +#else /* FIXME: not correct for R6000 */ + +#define ASID_INC 0x1 +#define ASID_MASK 0xff + +#endif + +#define cpu_context(cpu, mm) ((mm)->context[cpu]) +#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK) +#define asid_cache(cpu) (cpu_data[cpu].asid_cache) + +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ +} + +/* + * All unused by hardware upper bits will be considered + * as a software asid extension. + */ +#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1))) +#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1) + +#ifndef CONFIG_MIPS_MT_SMTC +/* Normal, classic MIPS get_new_mmu_context */ +static inline void +get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) +{ + unsigned long asid = asid_cache(cpu); + + if (! ((asid += ASID_INC) & ASID_MASK) ) { + if (cpu_has_vtag_icache) + flush_icache_all(); + local_flush_tlb_all(); /* start new asid cycle */ + if (!asid) /* fix version if needed */ + asid = ASID_FIRST_VERSION; + } + cpu_context(cpu, mm) = asid_cache(cpu) = asid; +} + +#else /* CONFIG_MIPS_MT_SMTC */ + +#define get_new_mmu_context(mm, cpu) smtc_get_new_mmu_context((mm), (cpu)) + +#endif /* CONFIG_MIPS_MT_SMTC */ + +/* + * Initialize the context related info for a new mm_struct + * instance. + */ +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + int i; + + for_each_online_cpu(i) + cpu_context(i, mm) = 0; + + return 0; +} + +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + unsigned int cpu = smp_processor_id(); + unsigned long flags; +#ifdef CONFIG_MIPS_MT_SMTC + unsigned long oldasid; + unsigned long mtflags; + int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id; + local_irq_save(flags); + mtflags = dvpe(); +#else /* Not SMTC */ + local_irq_save(flags); +#endif /* CONFIG_MIPS_MT_SMTC */ + + /* Check if our ASID is of an older version and thus invalid */ + if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK) + get_new_mmu_context(next, cpu); +#ifdef CONFIG_MIPS_MT_SMTC + /* + * If the EntryHi ASID being replaced happens to be + * the value flagged at ASID recycling time as having + * an extended life, clear the bit showing it being + * in use by this "CPU", and if that's the last bit, + * free up the ASID value for use and flush any old + * instances of it from the TLB. + */ + oldasid = (read_c0_entryhi() & ASID_MASK); + if(smtc_live_asid[mytlb][oldasid]) { + smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); + if(smtc_live_asid[mytlb][oldasid] == 0) + smtc_flush_tlb_asid(oldasid); + } + /* + * Tread softly on EntryHi, and so long as we support + * having ASID_MASK smaller than the hardware maximum, + * make sure no "soft" bits become "hard"... + */ + write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) + | (cpu_context(cpu, next) & ASID_MASK)); + ehb(); /* Make sure it propagates to TCStatus */ + evpe(mtflags); +#else + write_c0_entryhi(cpu_context(cpu, next)); +#endif /* CONFIG_MIPS_MT_SMTC */ + TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + /* + * Mark current->active_mm as not "active" anymore. + * We don't want to mislead possible IPI tlb flush routines. + */ + cpu_clear(cpu, prev->cpu_vm_mask); + cpu_set(cpu, next->cpu_vm_mask); + + local_irq_restore(flags); +} + +/* + * Destroy context related info for an mm_struct that is about + * to be put to rest. + */ +static inline void destroy_context(struct mm_struct *mm) +{ +} + +#define deactivate_mm(tsk, mm) do { } while (0) + +/* + * After we have set current->mm to a new value, this activates + * the context for the new mm so we see the new mappings. + */ +static inline void +activate_mm(struct mm_struct *prev, struct mm_struct *next) +{ + unsigned long flags; + unsigned int cpu = smp_processor_id(); + +#ifdef CONFIG_MIPS_MT_SMTC + unsigned long oldasid; + unsigned long mtflags; + int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id; +#endif /* CONFIG_MIPS_MT_SMTC */ + + local_irq_save(flags); + + /* Unconditionally get a new ASID. */ + get_new_mmu_context(next, cpu); + +#ifdef CONFIG_MIPS_MT_SMTC + /* See comments for similar code above */ + mtflags = dvpe(); + oldasid = read_c0_entryhi() & ASID_MASK; + if(smtc_live_asid[mytlb][oldasid]) { + smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); + if(smtc_live_asid[mytlb][oldasid] == 0) + smtc_flush_tlb_asid(oldasid); + } + /* See comments for similar code above */ + write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) | + (cpu_context(cpu, next) & ASID_MASK)); + ehb(); /* Make sure it propagates to TCStatus */ + evpe(mtflags); +#else + write_c0_entryhi(cpu_context(cpu, next)); +#endif /* CONFIG_MIPS_MT_SMTC */ + TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + /* mark mmu ownership change */ + cpu_clear(cpu, prev->cpu_vm_mask); + cpu_set(cpu, next->cpu_vm_mask); + + local_irq_restore(flags); +} + +/* + * If mm is currently active_mm, we can't really drop it. Instead, + * we will get a new one for it. + */ +static inline void +drop_mmu_context(struct mm_struct *mm, unsigned cpu) +{ + unsigned long flags; +#ifdef CONFIG_MIPS_MT_SMTC + unsigned long oldasid; + /* Can't use spinlock because called from TLB flush within DVPE */ + unsigned int prevvpe; + int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id; +#endif /* CONFIG_MIPS_MT_SMTC */ + + local_irq_save(flags); + + if (cpu_isset(cpu, mm->cpu_vm_mask)) { + get_new_mmu_context(mm, cpu); +#ifdef CONFIG_MIPS_MT_SMTC + /* See comments for similar code above */ + prevvpe = dvpe(); + oldasid = (read_c0_entryhi() & ASID_MASK); + if (smtc_live_asid[mytlb][oldasid]) { + smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); + if(smtc_live_asid[mytlb][oldasid] == 0) + smtc_flush_tlb_asid(oldasid); + } + /* See comments for similar code above */ + write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) + | cpu_asid(cpu, mm)); + ehb(); /* Make sure it propagates to TCStatus */ + evpe(prevvpe); +#else /* not CONFIG_MIPS_MT_SMTC */ + write_c0_entryhi(cpu_asid(cpu, mm)); +#endif /* CONFIG_MIPS_MT_SMTC */ + } else { + /* will get a new context next time */ +#ifndef CONFIG_MIPS_MT_SMTC + cpu_context(cpu, mm) = 0; +#else /* SMTC */ + int i; + + /* SMTC shares the TLB (and ASIDs) across VPEs */ + for_each_online_cpu(i) { + if((smtc_status & SMTC_TLB_SHARED) + || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id)) + cpu_context(i, mm) = 0; + } +#endif /* CONFIG_MIPS_MT_SMTC */ + } + local_irq_restore(flags); +} + +#endif /* _ASM_MMU_CONTEXT_H */ diff --git a/arch/mips/include/asm/mmzone.h b/arch/mips/include/asm/mmzone.h new file mode 100644 index 00000000000..f53ec54c92f --- /dev/null +++ b/arch/mips/include/asm/mmzone.h @@ -0,0 +1,17 @@ +/* + * Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99 + * Rewritten for Linux 2.6 by Christoph Hellwig (hch@lst.de) Jan 2004 + */ +#ifndef _ASM_MMZONE_H_ +#define _ASM_MMZONE_H_ + +#include +#include + +#ifdef CONFIG_DISCONTIGMEM + +#define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT) + +#endif /* CONFIG_DISCONTIGMEM */ + +#endif /* _ASM_MMZONE_H_ */ diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h new file mode 100644 index 00000000000..de6d09ebbd8 --- /dev/null +++ b/arch/mips/include/asm/module.h @@ -0,0 +1,136 @@ +#ifndef _ASM_MODULE_H +#define _ASM_MODULE_H + +#include +#include + +struct mod_arch_specific { + /* Data Bus Error exception tables */ + struct list_head dbe_list; + const struct exception_table_entry *dbe_start; + const struct exception_table_entry *dbe_end; +}; + +typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ + +typedef struct { + Elf64_Addr r_offset; /* Address of relocation. */ + Elf64_Word r_sym; /* Symbol index. */ + Elf64_Byte r_ssym; /* Special symbol. */ + Elf64_Byte r_type3; /* Third relocation. */ + Elf64_Byte r_type2; /* Second relocation. */ + Elf64_Byte r_type; /* First relocation. */ +} Elf64_Mips_Rel; + +typedef struct { + Elf64_Addr r_offset; /* Address of relocation. */ + Elf64_Word r_sym; /* Symbol index. */ + Elf64_Byte r_ssym; /* Special symbol. */ + Elf64_Byte r_type3; /* Third relocation. */ + Elf64_Byte r_type2; /* Second relocation. */ + Elf64_Byte r_type; /* First relocation. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Mips_Rela; + +#ifdef CONFIG_32BIT + +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Addr Elf32_Addr + +#define Elf_Mips_Rel Elf32_Rel +#define Elf_Mips_Rela Elf32_Rela + +#define ELF_MIPS_R_SYM(rel) ELF32_R_SYM(rel.r_info) +#define ELF_MIPS_R_TYPE(rel) ELF32_R_TYPE(rel.r_info) + +#endif + +#ifdef CONFIG_64BIT + +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Addr Elf64_Addr + +#define Elf_Mips_Rel Elf64_Mips_Rel +#define Elf_Mips_Rela Elf64_Mips_Rela + +#define ELF_MIPS_R_SYM(rel) (rel.r_sym) +#define ELF_MIPS_R_TYPE(rel) (rel.r_type) + +#endif + +#ifdef CONFIG_MODULES +/* Given an address, look for it in the exception tables. */ +const struct exception_table_entry*search_module_dbetables(unsigned long addr); +#else +/* Given an address, look for it in the exception tables. */ +static inline const struct exception_table_entry * +search_module_dbetables(unsigned long addr) +{ + return NULL; +} +#endif + +#ifdef CONFIG_CPU_MIPS32_R1 +#define MODULE_PROC_FAMILY "MIPS32_R1 " +#elif defined CONFIG_CPU_MIPS32_R2 +#define MODULE_PROC_FAMILY "MIPS32_R2 " +#elif defined CONFIG_CPU_MIPS64_R1 +#define MODULE_PROC_FAMILY "MIPS64_R1 " +#elif defined CONFIG_CPU_MIPS64_R2 +#define MODULE_PROC_FAMILY "MIPS64_R2 " +#elif defined CONFIG_CPU_R3000 +#define MODULE_PROC_FAMILY "R3000 " +#elif defined CONFIG_CPU_TX39XX +#define MODULE_PROC_FAMILY "TX39XX " +#elif defined CONFIG_CPU_VR41XX +#define MODULE_PROC_FAMILY "VR41XX " +#elif defined CONFIG_CPU_R4300 +#define MODULE_PROC_FAMILY "R4300 " +#elif defined CONFIG_CPU_R4X00 +#define MODULE_PROC_FAMILY "R4X00 " +#elif defined CONFIG_CPU_TX49XX +#define MODULE_PROC_FAMILY "TX49XX " +#elif defined CONFIG_CPU_R5000 +#define MODULE_PROC_FAMILY "R5000 " +#elif defined CONFIG_CPU_R5432 +#define MODULE_PROC_FAMILY "R5432 " +#elif defined CONFIG_CPU_R6000 +#define MODULE_PROC_FAMILY "R6000 " +#elif defined CONFIG_CPU_NEVADA +#define MODULE_PROC_FAMILY "NEVADA " +#elif defined CONFIG_CPU_R8000 +#define MODULE_PROC_FAMILY "R8000 " +#elif defined CONFIG_CPU_R10000 +#define MODULE_PROC_FAMILY "R10000 " +#elif defined CONFIG_CPU_RM7000 +#define MODULE_PROC_FAMILY "RM7000 " +#elif defined CONFIG_CPU_RM9000 +#define MODULE_PROC_FAMILY "RM9000 " +#elif defined CONFIG_CPU_SB1 +#define MODULE_PROC_FAMILY "SB1 " +#elif defined CONFIG_CPU_LOONGSON2 +#define MODULE_PROC_FAMILY "LOONGSON2 " +#else +#error MODULE_PROC_FAMILY undefined for your processor configuration +#endif + +#ifdef CONFIG_32BIT +#define MODULE_KERNEL_TYPE "32BIT " +#elif defined CONFIG_64BIT +#define MODULE_KERNEL_TYPE "64BIT " +#endif + +#ifdef CONFIG_MIPS_MT_SMTC +#define MODULE_KERNEL_SMTC "MT_SMTC " +#else +#define MODULE_KERNEL_SMTC "" +#endif + +#define MODULE_ARCH_VERMAGIC \ + MODULE_PROC_FAMILY MODULE_KERNEL_TYPE MODULE_KERNEL_SMTC + +#endif /* _ASM_MODULE_H */ diff --git a/arch/mips/include/asm/msc01_ic.h b/arch/mips/include/asm/msc01_ic.h new file mode 100644 index 00000000000..7989b9ffc1d --- /dev/null +++ b/arch/mips/include/asm/msc01_ic.h @@ -0,0 +1,148 @@ +/* + * PCI Register definitions for the MIPS System Controller. + * + * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#ifndef __ASM_MIPS_BOARDS_MSC01_IC_H +#define __ASM_MIPS_BOARDS_MSC01_IC_H + +/***************************************************************************** + * Register offset addresses + *****************************************************************************/ + +#define MSC01_IC_RST_OFS 0x00008 /* Software reset */ +#define MSC01_IC_ENAL_OFS 0x00100 /* Int_in enable mask 31:0 */ +#define MSC01_IC_ENAH_OFS 0x00108 /* Int_in enable mask 63:32 */ +#define MSC01_IC_DISL_OFS 0x00120 /* Int_in disable mask 31:0 */ +#define MSC01_IC_DISH_OFS 0x00128 /* Int_in disable mask 63:32 */ +#define MSC01_IC_ISBL_OFS 0x00140 /* Raw int_in 31:0 */ +#define MSC01_IC_ISBH_OFS 0x00148 /* Raw int_in 63:32 */ +#define MSC01_IC_ISAL_OFS 0x00160 /* Masked int_in 31:0 */ +#define MSC01_IC_ISAH_OFS 0x00168 /* Masked int_in 63:32 */ +#define MSC01_IC_LVL_OFS 0x00180 /* Disable priority int_out */ +#define MSC01_IC_RAMW_OFS 0x00180 /* Shadow set RAM (EI) */ +#define MSC01_IC_OSB_OFS 0x00188 /* Raw int_out */ +#define MSC01_IC_OSA_OFS 0x00190 /* Masked int_out */ +#define MSC01_IC_GENA_OFS 0x00198 /* Global HW int enable */ +#define MSC01_IC_BASE_OFS 0x001a0 /* Base address of IC_VEC */ +#define MSC01_IC_VEC_OFS 0x001b0 /* Active int's vector address */ +#define MSC01_IC_EOI_OFS 0x001c0 /* Enable lower level ints */ +#define MSC01_IC_CFG_OFS 0x001c8 /* Configuration register */ +#define MSC01_IC_TRLD_OFS 0x001d0 /* Interval timer reload val */ +#define MSC01_IC_TVAL_OFS 0x001e0 /* Interval timer current val */ +#define MSC01_IC_TCFG_OFS 0x001f0 /* Interval timer config */ +#define MSC01_IC_SUP_OFS 0x00200 /* Set up int_in line 0 */ +#define MSC01_IC_ENA_OFS 0x00800 /* Int_in enable mask 63:0 */ +#define MSC01_IC_DIS_OFS 0x00820 /* Int_in disable mask 63:0 */ +#define MSC01_IC_ISB_OFS 0x00840 /* Raw int_in 63:0 */ +#define MSC01_IC_ISA_OFS 0x00860 /* Masked int_in 63:0 */ + +/***************************************************************************** + * Register field encodings + *****************************************************************************/ + +#define MSC01_IC_RST_RST_SHF 0 +#define MSC01_IC_RST_RST_MSK 0x00000001 +#define MSC01_IC_RST_RST_BIT MSC01_IC_RST_RST_MSK +#define MSC01_IC_LVL_LVL_SHF 0 +#define MSC01_IC_LVL_LVL_MSK 0x000000ff +#define MSC01_IC_LVL_SPUR_SHF 16 +#define MSC01_IC_LVL_SPUR_MSK 0x00010000 +#define MSC01_IC_LVL_SPUR_BIT MSC01_IC_LVL_SPUR_MSK +#define MSC01_IC_RAMW_RIPL_SHF 0 +#define MSC01_IC_RAMW_RIPL_MSK 0x0000003f +#define MSC01_IC_RAMW_DATA_SHF 6 +#define MSC01_IC_RAMW_DATA_MSK 0x00000fc0 +#define MSC01_IC_RAMW_ADDR_SHF 25 +#define MSC01_IC_RAMW_ADDR_MSK 0x7e000000 +#define MSC01_IC_RAMW_READ_SHF 31 +#define MSC01_IC_RAMW_READ_MSK 0x80000000 +#define MSC01_IC_RAMW_READ_BIT MSC01_IC_RAMW_READ_MSK +#define MSC01_IC_OSB_OSB_SHF 0 +#define MSC01_IC_OSB_OSB_MSK 0x000000ff +#define MSC01_IC_OSA_OSA_SHF 0 +#define MSC01_IC_OSA_OSA_MSK 0x000000ff +#define MSC01_IC_GENA_GENA_SHF 0 +#define MSC01_IC_GENA_GENA_MSK 0x00000001 +#define MSC01_IC_GENA_GENA_BIT MSC01_IC_GENA_GENA_MSK +#define MSC01_IC_CFG_DIS_SHF 0 +#define MSC01_IC_CFG_DIS_MSK 0x00000001 +#define MSC01_IC_CFG_DIS_BIT MSC01_IC_CFG_DIS_MSK +#define MSC01_IC_CFG_SHFT_SHF 8 +#define MSC01_IC_CFG_SHFT_MSK 0x00000f00 +#define MSC01_IC_TCFG_ENA_SHF 0 +#define MSC01_IC_TCFG_ENA_MSK 0x00000001 +#define MSC01_IC_TCFG_ENA_BIT MSC01_IC_TCFG_ENA_MSK +#define MSC01_IC_TCFG_INT_SHF 8 +#define MSC01_IC_TCFG_INT_MSK 0x00000100 +#define MSC01_IC_TCFG_INT_BIT MSC01_IC_TCFG_INT_MSK +#define MSC01_IC_TCFG_EDGE_SHF 16 +#define MSC01_IC_TCFG_EDGE_MSK 0x00010000 +#define MSC01_IC_TCFG_EDGE_BIT MSC01_IC_TCFG_EDGE_MSK +#define MSC01_IC_SUP_PRI_SHF 0 +#define MSC01_IC_SUP_PRI_MSK 0x00000007 +#define MSC01_IC_SUP_EDGE_SHF 8 +#define MSC01_IC_SUP_EDGE_MSK 0x00000100 +#define MSC01_IC_SUP_EDGE_BIT MSC01_IC_SUP_EDGE_MSK +#define MSC01_IC_SUP_STEP 8 + +/* + * MIPS System controller interrupt register base. + * + */ + +/***************************************************************************** + * Absolute register addresses + *****************************************************************************/ + +#define MSC01_IC_RST (MSC01_IC_REG_BASE + MSC01_IC_RST_OFS) +#define MSC01_IC_ENAL (MSC01_IC_REG_BASE + MSC01_IC_ENAL_OFS) +#define MSC01_IC_ENAH (MSC01_IC_REG_BASE + MSC01_IC_ENAH_OFS) +#define MSC01_IC_DISL (MSC01_IC_REG_BASE + MSC01_IC_DISL_OFS) +#define MSC01_IC_DISH (MSC01_IC_REG_BASE + MSC01_IC_DISH_OFS) +#define MSC01_IC_ISBL (MSC01_IC_REG_BASE + MSC01_IC_ISBL_OFS) +#define MSC01_IC_ISBH (MSC01_IC_REG_BASE + MSC01_IC_ISBH_OFS) +#define MSC01_IC_ISAL (MSC01_IC_REG_BASE + MSC01_IC_ISAL_OFS) +#define MSC01_IC_ISAH (MSC01_IC_REG_BASE + MSC01_IC_ISAH_OFS) +#define MSC01_IC_LVL (MSC01_IC_REG_BASE + MSC01_IC_LVL_OFS) +#define MSC01_IC_RAMW (MSC01_IC_REG_BASE + MSC01_IC_RAMW_OFS) +#define MSC01_IC_OSB (MSC01_IC_REG_BASE + MSC01_IC_OSB_OFS) +#define MSC01_IC_OSA (MSC01_IC_REG_BASE + MSC01_IC_OSA_OFS) +#define MSC01_IC_GENA (MSC01_IC_REG_BASE + MSC01_IC_GENA_OFS) +#define MSC01_IC_BASE (MSC01_IC_REG_BASE + MSC01_IC_BASE_OFS) +#define MSC01_IC_VEC (MSC01_IC_REG_BASE + MSC01_IC_VEC_OFS) +#define MSC01_IC_EOI (MSC01_IC_REG_BASE + MSC01_IC_EOI_OFS) +#define MSC01_IC_CFG (MSC01_IC_REG_BASE + MSC01_IC_CFG_OFS) +#define MSC01_IC_TRLD (MSC01_IC_REG_BASE + MSC01_IC_TRLD_OFS) +#define MSC01_IC_TVAL (MSC01_IC_REG_BASE + MSC01_IC_TVAL_OFS) +#define MSC01_IC_TCFG (MSC01_IC_REG_BASE + MSC01_IC_TCFG_OFS) +#define MSC01_IC_SUP (MSC01_IC_REG_BASE + MSC01_IC_SUP_OFS) +#define MSC01_IC_ENA (MSC01_IC_REG_BASE + MSC01_IC_ENA_OFS) +#define MSC01_IC_DIS (MSC01_IC_REG_BASE + MSC01_IC_DIS_OFS) +#define MSC01_IC_ISB (MSC01_IC_REG_BASE + MSC01_IC_ISB_OFS) +#define MSC01_IC_ISA (MSC01_IC_REG_BASE + MSC01_IC_ISA_OFS) + +/* + * Soc-it interrupts are configurable. + * Every board describes its IRQ mapping with this table. + */ +typedef struct msc_irqmap { + int im_irq; + int im_type; + int im_lvl; +} msc_irqmap_t; + +/* im_type */ +#define MSC01_IRQ_LEVEL 0 +#define MSC01_IRQ_EDGE 1 + +extern void __init init_msc_irqs(unsigned long icubase, unsigned int base, msc_irqmap_t *imp, int nirq); +extern void ll_msc_irq(void); + +#endif /* __ASM_MIPS_BOARDS_MSC01_IC_H */ + diff --git a/arch/mips/include/asm/msgbuf.h b/arch/mips/include/asm/msgbuf.h new file mode 100644 index 00000000000..0d6c7f14de3 --- /dev/null +++ b/arch/mips/include/asm/msgbuf.h @@ -0,0 +1,47 @@ +#ifndef _ASM_MSGBUF_H +#define _ASM_MSGBUF_H + + +/* + * The msqid64_ds structure for the MIPS architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - extension of time_t to 64-bit on 32-bitsystem to solve the y2038 problem + * - 2 miscellaneous unsigned long values + */ + +struct msqid64_ds { + struct ipc64_perm msg_perm; +#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN) + unsigned long __unused1; +#endif + __kernel_time_t msg_stime; /* last msgsnd time */ +#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN) + unsigned long __unused1; +#endif +#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN) + unsigned long __unused2; +#endif + __kernel_time_t msg_rtime; /* last msgrcv time */ +#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN) + unsigned long __unused2; +#endif +#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN) + unsigned long __unused3; +#endif + __kernel_time_t msg_ctime; /* last change time */ +#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN) + unsigned long __unused3; +#endif + unsigned long msg_cbytes; /* current number of bytes on queue */ + unsigned long msg_qnum; /* number of messages in queue */ + unsigned long msg_qbytes; /* max number of bytes on queue */ + __kernel_pid_t msg_lspid; /* pid of last msgsnd */ + __kernel_pid_t msg_lrpid; /* last receive pid */ + unsigned long __unused4; + unsigned long __unused5; +}; + +#endif /* _ASM_MSGBUF_H */ diff --git a/arch/mips/include/asm/mutex.h b/arch/mips/include/asm/mutex.h new file mode 100644 index 00000000000..458c1f7fbc1 --- /dev/null +++ b/arch/mips/include/asm/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include diff --git a/arch/mips/include/asm/nile4.h b/arch/mips/include/asm/nile4.h new file mode 100644 index 00000000000..c3ca959aa4d --- /dev/null +++ b/arch/mips/include/asm/nile4.h @@ -0,0 +1,310 @@ +/* + * asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + * + * This file is based on the following documentation: + * + * NEC Vrc 5074 System Controller Data Sheet, June 1998 + */ + +#ifndef _ASM_NILE4_H +#define _ASM_NILE4_H + +#define NILE4_BASE 0xbfa00000 +#define NILE4_SIZE 0x00200000 /* 2 MB */ + + + /* + * Physical Device Address Registers (PDARs) + */ + +#define NILE4_SDRAM0 0x0000 /* SDRAM Bank 0 [R/W] */ +#define NILE4_SDRAM1 0x0008 /* SDRAM Bank 1 [R/W] */ +#define NILE4_DCS2 0x0010 /* Device Chip-Select 2 [R/W] */ +#define NILE4_DCS3 0x0018 /* Device Chip-Select 3 [R/W] */ +#define NILE4_DCS4 0x0020 /* Device Chip-Select 4 [R/W] */ +#define NILE4_DCS5 0x0028 /* Device Chip-Select 5 [R/W] */ +#define NILE4_DCS6 0x0030 /* Device Chip-Select 6 [R/W] */ +#define NILE4_DCS7 0x0038 /* Device Chip-Select 7 [R/W] */ +#define NILE4_DCS8 0x0040 /* Device Chip-Select 8 [R/W] */ +#define NILE4_PCIW0 0x0060 /* PCI Address Window 0 [R/W] */ +#define NILE4_PCIW1 0x0068 /* PCI Address Window 1 [R/W] */ +#define NILE4_INTCS 0x0070 /* Controller Internal Registers and Devices */ + /* [R/W] */ +#define NILE4_BOOTCS 0x0078 /* Boot ROM Chip-Select [R/W] */ + + + /* + * CPU Interface Registers + */ + +#define NILE4_CPUSTAT 0x0080 /* CPU Status [R/W] */ +#define NILE4_INTCTRL 0x0088 /* Interrupt Control [R/W] */ +#define NILE4_INTSTAT0 0x0090 /* Interrupt Status 0 [R] */ +#define NILE4_INTSTAT1 0x0098 /* Interrupt Status 1 and CPU Interrupt */ + /* Enable [R/W] */ +#define NILE4_INTCLR 0x00A0 /* Interrupt Clear [R/W] */ +#define NILE4_INTPPES 0x00A8 /* PCI Interrupt Control [R/W] */ + + + /* + * Memory-Interface Registers + */ + +#define NILE4_MEMCTRL 0x00C0 /* Memory Control */ +#define NILE4_ACSTIME 0x00C8 /* Memory Access Timing [R/W] */ +#define NILE4_CHKERR 0x00D0 /* Memory Check Error Status [R] */ + + + /* + * PCI-Bus Registers + */ + +#define NILE4_PCICTRL 0x00E0 /* PCI Control [R/W] */ +#define NILE4_PCIARB 0x00E8 /* PCI Arbiter [R/W] */ +#define NILE4_PCIINIT0 0x00F0 /* PCI Master (Initiator) 0 [R/W] */ +#define NILE4_PCIINIT1 0x00F8 /* PCI Master (Initiator) 1 [R/W] */ +#define NILE4_PCIERR 0x00B8 /* PCI Error [R/W] */ + + + /* + * Local-Bus Registers + */ + +#define NILE4_LCNFG 0x0100 /* Local Bus Configuration [R/W] */ +#define NILE4_LCST2 0x0110 /* Local Bus Chip-Select Timing 2 [R/W] */ +#define NILE4_LCST3 0x0118 /* Local Bus Chip-Select Timing 3 [R/W] */ +#define NILE4_LCST4 0x0120 /* Local Bus Chip-Select Timing 4 [R/W] */ +#define NILE4_LCST5 0x0128 /* Local Bus Chip-Select Timing 5 [R/W] */ +#define NILE4_LCST6 0x0130 /* Local Bus Chip-Select Timing 6 [R/W] */ +#define NILE4_LCST7 0x0138 /* Local Bus Chip-Select Timing 7 [R/W] */ +#define NILE4_LCST8 0x0140 /* Local Bus Chip-Select Timing 8 [R/W] */ +#define NILE4_DCSFN 0x0150 /* Device Chip-Select Muxing and Output */ + /* Enables [R/W] */ +#define NILE4_DCSIO 0x0158 /* Device Chip-Selects As I/O Bits [R/W] */ +#define NILE4_BCST 0x0178 /* Local Boot Chip-Select Timing [R/W] */ + + + /* + * DMA Registers + */ + +#define NILE4_DMACTRL0 0x0180 /* DMA Control 0 [R/W] */ +#define NILE4_DMASRCA0 0x0188 /* DMA Source Address 0 [R/W] */ +#define NILE4_DMADESA0 0x0190 /* DMA Destination Address 0 [R/W] */ +#define NILE4_DMACTRL1 0x0198 /* DMA Control 1 [R/W] */ +#define NILE4_DMASRCA1 0x01A0 /* DMA Source Address 1 [R/W] */ +#define NILE4_DMADESA1 0x01A8 /* DMA Destination Address 1 [R/W] */ + + + /* + * Timer Registers + */ + +#define NILE4_T0CTRL 0x01C0 /* SDRAM Refresh Control [R/W] */ +#define NILE4_T0CNTR 0x01C8 /* SDRAM Refresh Counter [R/W] */ +#define NILE4_T1CTRL 0x01D0 /* CPU-Bus Read Time-Out Control [R/W] */ +#define NILE4_T1CNTR 0x01D8 /* CPU-Bus Read Time-Out Counter [R/W] */ +#define NILE4_T2CTRL 0x01E0 /* General-Purpose Timer Control [R/W] */ +#define NILE4_T2CNTR 0x01E8 /* General-Purpose Timer Counter [R/W] */ +#define NILE4_T3CTRL 0x01F0 /* Watchdog Timer Control [R/W] */ +#define NILE4_T3CNTR 0x01F8 /* Watchdog Timer Counter [R/W] */ + + + /* + * PCI Configuration Space Registers + */ + +#define NILE4_PCI_BASE 0x0200 + +#define NILE4_VID 0x0200 /* PCI Vendor ID [R] */ +#define NILE4_DID 0x0202 /* PCI Device ID [R] */ +#define NILE4_PCICMD 0x0204 /* PCI Command [R/W] */ +#define NILE4_PCISTS 0x0206 /* PCI Status [R/W] */ +#define NILE4_REVID 0x0208 /* PCI Revision ID [R] */ +#define NILE4_CLASS 0x0209 /* PCI Class Code [R] */ +#define NILE4_CLSIZ 0x020C /* PCI Cache Line Size [R/W] */ +#define NILE4_MLTIM 0x020D /* PCI Latency Timer [R/W] */ +#define NILE4_HTYPE 0x020E /* PCI Header Type [R] */ +#define NILE4_BIST 0x020F /* BIST [R] (unimplemented) */ +#define NILE4_BARC 0x0210 /* PCI Base Address Register Control [R/W] */ +#define NILE4_BAR0 0x0218 /* PCI Base Address Register 0 [R/W] */ +#define NILE4_BAR1 0x0220 /* PCI Base Address Register 1 [R/W] */ +#define NILE4_CIS 0x0228 /* PCI Cardbus CIS Pointer [R] */ + /* (unimplemented) */ +#define NILE4_SSVID 0x022C /* PCI Sub-System Vendor ID [R/W] */ +#define NILE4_SSID 0x022E /* PCI Sub-System ID [R/W] */ +#define NILE4_ROM 0x0230 /* Expansion ROM Base Address [R] */ + /* (unimplemented) */ +#define NILE4_INTLIN 0x023C /* PCI Interrupt Line [R/W] */ +#define NILE4_INTPIN 0x023D /* PCI Interrupt Pin [R] */ +#define NILE4_MINGNT 0x023E /* PCI Min_Gnt [R] (unimplemented) */ +#define NILE4_MAXLAT 0x023F /* PCI Max_Lat [R] (unimplemented) */ +#define NILE4_BAR2 0x0240 /* PCI Base Address Register 2 [R/W] */ +#define NILE4_BAR3 0x0248 /* PCI Base Address Register 3 [R/W] */ +#define NILE4_BAR4 0x0250 /* PCI Base Address Register 4 [R/W] */ +#define NILE4_BAR5 0x0258 /* PCI Base Address Register 5 [R/W] */ +#define NILE4_BAR6 0x0260 /* PCI Base Address Register 6 [R/W] */ +#define NILE4_BAR7 0x0268 /* PCI Base Address Register 7 [R/W] */ +#define NILE4_BAR8 0x0270 /* PCI Base Address Register 8 [R/W] */ +#define NILE4_BARB 0x0278 /* PCI Base Address Register BOOT [R/W] */ + + + /* + * Serial-Port Registers + */ + +#define NILE4_UART_BASE 0x0300 + +#define NILE4_UARTRBR 0x0300 /* UART Receiver Data Buffer [R] */ +#define NILE4_UARTTHR 0x0300 /* UART Transmitter Data Holding [W] */ +#define NILE4_UARTIER 0x0308 /* UART Interrupt Enable [R/W] */ +#define NILE4_UARTDLL 0x0300 /* UART Divisor Latch LSB [R/W] */ +#define NILE4_UARTDLM 0x0308 /* UART Divisor Latch MSB [R/W] */ +#define NILE4_UARTIIR 0x0310 /* UART Interrupt ID [R] */ +#define NILE4_UARTFCR 0x0310 /* UART FIFO Control [W] */ +#define NILE4_UARTLCR 0x0318 /* UART Line Control [R/W] */ +#define NILE4_UARTMCR 0x0320 /* UART Modem Control [R/W] */ +#define NILE4_UARTLSR 0x0328 /* UART Line Status [R/W] */ +#define NILE4_UARTMSR 0x0330 /* UART Modem Status [R/W] */ +#define NILE4_UARTSCR 0x0338 /* UART Scratch [R/W] */ + +#define NILE4_UART_BASE_BAUD 520833 /* 100 MHz / 12 / 16 */ + + + /* + * Interrupt Lines + */ + +#define NILE4_INT_CPCE 0 /* CPU-Interface Parity-Error Interrupt */ +#define NILE4_INT_CNTD 1 /* CPU No-Target Decode Interrupt */ +#define NILE4_INT_MCE 2 /* Memory-Check Error Interrupt */ +#define NILE4_INT_DMA 3 /* DMA Controller Interrupt */ +#define NILE4_INT_UART 4 /* UART Interrupt */ +#define NILE4_INT_WDOG 5 /* Watchdog Timer Interrupt */ +#define NILE4_INT_GPT 6 /* General-Purpose Timer Interrupt */ +#define NILE4_INT_LBRTD 7 /* Local-Bus Ready Timer Interrupt */ +#define NILE4_INT_INTA 8 /* PCI Interrupt Signal INTA# */ +#define NILE4_INT_INTB 9 /* PCI Interrupt Signal INTB# */ +#define NILE4_INT_INTC 10 /* PCI Interrupt Signal INTC# */ +#define NILE4_INT_INTD 11 /* PCI Interrupt Signal INTD# */ +#define NILE4_INT_INTE 12 /* PCI Interrupt Signal INTE# (ISA cascade) */ +#define NILE4_INT_RESV 13 /* Reserved */ +#define NILE4_INT_PCIS 14 /* PCI SERR# Interrupt */ +#define NILE4_INT_PCIE 15 /* PCI Internal Error Interrupt */ + + + /* + * Nile 4 Register Access + */ + +static inline void nile4_sync(void) +{ + volatile u32 *p = (volatile u32 *)0xbfc00000; + (void)(*p); +} + +static inline void nile4_out32(u32 offset, u32 val) +{ + *(volatile u32 *)(NILE4_BASE+offset) = val; + nile4_sync(); +} + +static inline u32 nile4_in32(u32 offset) +{ + u32 val = *(volatile u32 *)(NILE4_BASE+offset); + nile4_sync(); + return val; +} + +static inline void nile4_out16(u32 offset, u16 val) +{ + *(volatile u16 *)(NILE4_BASE+offset) = val; + nile4_sync(); +} + +static inline u16 nile4_in16(u32 offset) +{ + u16 val = *(volatile u16 *)(NILE4_BASE+offset); + nile4_sync(); + return val; +} + +static inline void nile4_out8(u32 offset, u8 val) +{ + *(volatile u8 *)(NILE4_BASE+offset) = val; + nile4_sync(); +} + +static inline u8 nile4_in8(u32 offset) +{ + u8 val = *(volatile u8 *)(NILE4_BASE+offset); + nile4_sync(); + return val; +} + + + /* + * Physical Device Address Registers + */ + +extern void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width, + int on_memory_bus, int visible); + + + /* + * PCI Master Registers + */ + +#define NILE4_PCICMD_IACK 0 /* PCI Interrupt Acknowledge */ +#define NILE4_PCICMD_IO 1 /* PCI I/O Space */ +#define NILE4_PCICMD_MEM 3 /* PCI Memory Space */ +#define NILE4_PCICMD_CFG 5 /* PCI Configuration Space */ + + + /* + * PCI Address Spaces + * + * Note that these are multiplexed using PCIINIT[01]! + */ + +#define NILE4_PCI_IO_BASE 0xa6000000 +#define NILE4_PCI_MEM_BASE 0xa8000000 +#define NILE4_PCI_CFG_BASE NILE4_PCI_MEM_BASE +#define NILE4_PCI_IACK_BASE NILE4_PCI_IO_BASE + + +extern void nile4_set_pmr(u32 pmr, u32 type, u32 addr); + + + /* + * Interrupt Programming + */ + +#define NUM_I8259_INTERRUPTS 16 +#define NUM_NILE4_INTERRUPTS 16 + +#define IRQ_I8259_CASCADE NILE4_INT_INTE +#define is_i8259_irq(irq) ((irq) < NUM_I8259_INTERRUPTS) +#define nile4_to_irq(n) ((n)+NUM_I8259_INTERRUPTS) +#define irq_to_nile4(n) ((n)-NUM_I8259_INTERRUPTS) + +extern void nile4_map_irq(int nile4_irq, int cpu_irq); +extern void nile4_map_irq_all(int cpu_irq); +extern void nile4_enable_irq(unsigned int nile4_irq); +extern void nile4_disable_irq(unsigned int nile4_irq); +extern void nile4_disable_irq_all(void); +extern u16 nile4_get_irq_stat(int cpu_irq); +extern void nile4_enable_irq_output(int cpu_irq); +extern void nile4_disable_irq_output(int cpu_irq); +extern void nile4_set_pci_irq_polarity(int pci_irq, int high); +extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level); +extern void nile4_clear_irq(int nile4_irq); +extern void nile4_clear_irq_mask(u32 mask); +extern u8 nile4_i8259_iack(void); +extern void nile4_dump_irq_status(void); /* Debug */ + +#endif + diff --git a/arch/mips/include/asm/paccess.h b/arch/mips/include/asm/paccess.h new file mode 100644 index 00000000000..c2394f8b0fe --- /dev/null +++ b/arch/mips/include/asm/paccess.h @@ -0,0 +1,112 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * + * Protected memory access. Used for everything that might take revenge + * by sending a DBE error like accessing possibly non-existant memory or + * devices. + */ +#ifndef _ASM_PACCESS_H +#define _ASM_PACCESS_H + +#include + +#ifdef CONFIG_32BIT +#define __PA_ADDR ".word" +#endif +#ifdef CONFIG_64BIT +#define __PA_ADDR ".dword" +#endif + +extern asmlinkage void handle_ibe(void); +extern asmlinkage void handle_dbe(void); + +#define put_dbe(x, ptr) __put_dbe((x), (ptr), sizeof(*(ptr))) +#define get_dbe(x, ptr) __get_dbe((x), (ptr), sizeof(*(ptr))) + +struct __large_pstruct { unsigned long buf[100]; }; +#define __mp(x) (*(struct __large_pstruct *)(x)) + +#define __get_dbe(x, ptr, size) \ +({ \ + long __gu_err; \ + __typeof__(*(ptr)) __gu_val; \ + unsigned long __gu_addr; \ + __asm__("":"=r" (__gu_val)); \ + __gu_addr = (unsigned long) (ptr); \ + __asm__("":"=r" (__gu_err)); \ + switch (size) { \ + case 1: __get_dbe_asm("lb"); break; \ + case 2: __get_dbe_asm("lh"); break; \ + case 4: __get_dbe_asm("lw"); break; \ + case 8: __get_dbe_asm("ld"); break; \ + default: __get_dbe_unknown(); break; \ + } \ + x = (__typeof__(*(ptr))) __gu_val; \ + __gu_err; \ +}) + +#define __get_dbe_asm(insn) \ +{ \ + __asm__ __volatile__( \ + "1:\t" insn "\t%1,%2\n\t" \ + "move\t%0,$0\n" \ + "2:\n\t" \ + ".section\t.fixup,\"ax\"\n" \ + "3:\tli\t%0,%3\n\t" \ + "move\t%1,$0\n\t" \ + "j\t2b\n\t" \ + ".previous\n\t" \ + ".section\t__dbe_table,\"a\"\n\t" \ + __PA_ADDR "\t1b, 3b\n\t" \ + ".previous" \ + :"=r" (__gu_err), "=r" (__gu_val) \ + :"o" (__mp(__gu_addr)), "i" (-EFAULT)); \ +} + +extern void __get_dbe_unknown(void); + +#define __put_dbe(x, ptr, size) \ +({ \ + long __pu_err; \ + __typeof__(*(ptr)) __pu_val; \ + long __pu_addr; \ + __pu_val = (x); \ + __pu_addr = (long) (ptr); \ + __asm__("":"=r" (__pu_err)); \ + switch (size) { \ + case 1: __put_dbe_asm("sb"); break; \ + case 2: __put_dbe_asm("sh"); break; \ + case 4: __put_dbe_asm("sw"); break; \ + case 8: __put_dbe_asm("sd"); break; \ + default: __put_dbe_unknown(); break; \ + } \ + __pu_err; \ +}) + +#define __put_dbe_asm(insn) \ +{ \ + __asm__ __volatile__( \ + "1:\t" insn "\t%1,%2\n\t" \ + "move\t%0,$0\n" \ + "2:\n\t" \ + ".section\t.fixup,\"ax\"\n" \ + "3:\tli\t%0,%3\n\t" \ + "j\t2b\n\t" \ + ".previous\n\t" \ + ".section\t__dbe_table,\"a\"\n\t" \ + __PA_ADDR "\t1b, 3b\n\t" \ + ".previous" \ + : "=r" (__pu_err) \ + : "r" (__pu_val), "o" (__mp(__pu_addr)), "i" (-EFAULT)); \ +} + +extern void __put_dbe_unknown(void); + +extern unsigned long search_dbe_table(unsigned long addr); + +#endif /* _ASM_PACCESS_H */ diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h new file mode 100644 index 00000000000..fe7a88ea066 --- /dev/null +++ b/arch/mips/include/asm/page.h @@ -0,0 +1,191 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_PAGE_H +#define _ASM_PAGE_H + +#include + +/* + * PAGE_SHIFT determines the page size + */ +#ifdef CONFIG_PAGE_SIZE_4KB +#define PAGE_SHIFT 12 +#endif +#ifdef CONFIG_PAGE_SIZE_8KB +#define PAGE_SHIFT 13 +#endif +#ifdef CONFIG_PAGE_SIZE_16KB +#define PAGE_SHIFT 14 +#endif +#ifdef CONFIG_PAGE_SIZE_64KB +#define PAGE_SHIFT 16 +#endif +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) + +#ifndef __ASSEMBLY__ + +#include +#include + +extern void build_clear_page(void); +extern void build_copy_page(void); + +/* + * It's normally defined only for FLATMEM config but it's + * used in our early mem init code for all memory models. + * So always define it. + */ +#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET) + +extern void clear_page(void * page); +extern void copy_page(void * to, void * from); + +extern unsigned long shm_align_mask; + +static inline unsigned long pages_do_alias(unsigned long addr1, + unsigned long addr2) +{ + return (addr1 ^ addr2) & shm_align_mask; +} + +struct page; + +static inline void clear_user_page(void *addr, unsigned long vaddr, + struct page *page) +{ + extern void (*flush_data_cache_page)(unsigned long addr); + + clear_page(addr); + if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK)) + flush_data_cache_page((unsigned long)addr); +} + +extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, + struct page *to); +struct vm_area_struct; +extern void copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); + +#define __HAVE_ARCH_COPY_USER_HIGHPAGE + +/* + * These are used to make use of C type-checking.. + */ +#ifdef CONFIG_64BIT_PHYS_ADDR + #ifdef CONFIG_CPU_MIPS32 + typedef struct { unsigned long pte_low, pte_high; } pte_t; + #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) + #define __pte(x) ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; }) + #else + typedef struct { unsigned long long pte; } pte_t; + #define pte_val(x) ((x).pte) + #define __pte(x) ((pte_t) { (x) } ) + #endif +#else +typedef struct { unsigned long pte; } pte_t; +#define pte_val(x) ((x).pte) +#define __pte(x) ((pte_t) { (x) } ) +#endif +typedef struct page *pgtable_t; + +/* + * For 3-level pagetables we defines these ourselves, for 2-level the + * definitions are supplied by . + */ +#ifdef CONFIG_64BIT + +typedef struct { unsigned long pmd; } pmd_t; +#define pmd_val(x) ((x).pmd) +#define __pmd(x) ((pmd_t) { (x) } ) + +#endif + +/* + * Right now we don't support 4-level pagetables, so all pud-related + * definitions come from . + */ + +/* + * Finall the top of the hierarchy, the pgd + */ +typedef struct { unsigned long pgd; } pgd_t; +#define pgd_val(x) ((x).pgd) +#define __pgd(x) ((pgd_t) { (x) } ) + +/* + * Manipulate page protection bits + */ +typedef struct { unsigned long pgprot; } pgprot_t; +#define pgprot_val(x) ((x).pgprot) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +/* + * On R4000-style MMUs where a TLB entry is mapping a adjacent even / odd + * pair of pages we only have a single global bit per pair of pages. When + * writing to the TLB make sure we always have the bit set for both pages + * or none. This macro is used to access the `buddy' of the pte we're just + * working on. + */ +#define ptep_buddy(x) ((pte_t *)((unsigned long)(x) ^ sizeof(pte_t))) + +#endif /* !__ASSEMBLY__ */ + +/* + * __pa()/__va() should be used only during mem init. + */ +#ifdef CONFIG_64BIT +#define __pa(x) \ +({ \ + unsigned long __x = (unsigned long)(x); \ + __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x); \ +}) +#else +#define __pa(x) \ + ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) +#endif +#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) +#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0)) + +#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) + +#ifdef CONFIG_FLATMEM + +#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr) + +#elif defined(CONFIG_SPARSEMEM) + +/* pfn_valid is defined in linux/mmzone.h */ + +#elif defined(CONFIG_NEED_MULTIPLE_NODES) + +#define pfn_valid(pfn) \ +({ \ + unsigned long __pfn = (pfn); \ + int __n = pfn_to_nid(__pfn); \ + ((__n >= 0) ? (__pfn < NODE_DATA(__n)->node_start_pfn + \ + NODE_DATA(__n)->node_spanned_pages) \ + : 0); \ +}) + +#endif + +#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(virt_to_phys(kaddr))) +#define virt_addr_valid(kaddr) pfn_valid(PFN_DOWN(virt_to_phys(kaddr))) + +#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) +#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) + +#include +#include + +#endif /* _ASM_PAGE_H */ diff --git a/arch/mips/include/asm/param.h b/arch/mips/include/asm/param.h new file mode 100644 index 00000000000..1d9bb8c5ab2 --- /dev/null +++ b/arch/mips/include/asm/param.h @@ -0,0 +1,31 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright 1994 - 2000, 2002 Ralf Baechle (ralf@gnu.org) + * Copyright 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_PARAM_H +#define _ASM_PARAM_H + +#ifdef __KERNEL__ + +# define HZ CONFIG_HZ /* Internal kernel timer frequency */ +# define USER_HZ 100 /* .. some user interfaces are in "ticks" */ +# define CLOCKS_PER_SEC (USER_HZ) /* like times() */ +#endif + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 65536 + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _ASM_PARAM_H */ diff --git a/arch/mips/include/asm/parport.h b/arch/mips/include/asm/parport.h new file mode 100644 index 00000000000..f52656826cc --- /dev/null +++ b/arch/mips/include/asm/parport.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 1999, 2000 Tim Waugh + * + * This file should only be included by drivers/parport/parport_pc.c. + */ +#ifndef _ASM_PARPORT_H +#define _ASM_PARPORT_H + +static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma); +static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma) +{ + return parport_pc_find_isa_ports(autoirq, autodma); +} + +#endif /* _ASM_PARPORT_H */ diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h new file mode 100644 index 00000000000..5510c53b7fe --- /dev/null +++ b/arch/mips/include/asm/pci.h @@ -0,0 +1,179 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef _ASM_PCI_H +#define _ASM_PCI_H + +#include + +#ifdef __KERNEL__ + +/* + * This file essentially defines the interface between board + * specific PCI code and MIPS common PCI code. Should potentially put + * into include/asm/pci.h file. + */ + +#include + +/* + * Each pci channel is a top-level PCI bus seem by CPU. A machine with + * multiple PCI channels may have multiple PCI host controllers or a + * single controller supporting multiple channels. + */ +struct pci_controller { + struct pci_controller *next; + struct pci_bus *bus; + + struct pci_ops *pci_ops; + struct resource *mem_resource; + unsigned long mem_offset; + struct resource *io_resource; + unsigned long io_offset; + unsigned long io_map_base; + + unsigned int index; + /* For compatibility with current (as of July 2003) pciutils + and XFree86. Eventually will be removed. */ + unsigned int need_domain_info; + + int iommu; + + /* Optional access methods for reading/writing the bus number + of the PCI controller */ + int (*get_busno)(void); + void (*set_busno)(int busno); +}; + +/* + * Used by boards to register their PCI busses before the actual scanning. + */ +extern struct pci_controller * alloc_pci_controller(void); +extern void register_pci_controller(struct pci_controller *hose); + +/* + * board supplied pci irq fixup routine + */ +extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); + + +/* Can be used to override the logic in pci_scan_bus for skipping + already-configured bus numbers - to be used for buggy BIOSes + or architectures with incomplete PCI setup by the loader */ + +extern unsigned int pcibios_assign_all_busses(void); + +#define pcibios_scan_all_fns(a, b) 0 + +extern unsigned long PCIBIOS_MIN_IO; +extern unsigned long PCIBIOS_MIN_MEM; + +#define PCIBIOS_MIN_CARDBUS_IO 0x4000 + +extern void pcibios_set_master(struct pci_dev *dev); + +static inline void pcibios_penalize_isa_irq(int irq, int active) +{ + /* We don't do dynamic PCI IRQ allocation */ +} + +/* + * Dynamic DMA mapping stuff. + * MIPS has everything mapped statically. + */ + +#include +#include +#include +#include +#include + +struct pci_dev; + +/* + * The PCI address space does equal the physical memory address space. The + * networking and block device layers use this boolean for bounce buffer + * decisions. This is set if any hose does not have an IOMMU. + */ +extern unsigned int PCI_DMA_BUS_IS_PHYS; + +#ifdef CONFIG_DMA_NEED_PCI_MAP_STATE + +/* pci_unmap_{single,page} is not a nop, thus... */ +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME; +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME; +#define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) +#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) + +#else /* CONFIG_DMA_NEED_PCI_MAP_STATE */ + +/* pci_unmap_{page,single} is a nop so... */ +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) +#define pci_unmap_addr(PTR, ADDR_NAME) (0) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) +#define pci_unmap_len(PTR, LEN_NAME) (0) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) + +#endif /* CONFIG_DMA_NEED_PCI_MAP_STATE */ + +#ifdef CONFIG_PCI +static inline void pci_dma_burst_advice(struct pci_dev *pdev, + enum pci_dma_burst_strategy *strat, + unsigned long *strategy_parameter) +{ + *strat = PCI_DMA_BURST_INFINITY; + *strategy_parameter = ~0UL; +} +#endif + +extern void pcibios_resource_to_bus(struct pci_dev *dev, + struct pci_bus_region *region, struct resource *res); + +extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); + +static inline struct resource * +pcibios_select_root(struct pci_dev *pdev, struct resource *res) +{ + struct resource *root = NULL; + + if (res->flags & IORESOURCE_IO) + root = &ioport_resource; + if (res->flags & IORESOURCE_MEM) + root = &iomem_resource; + + return root; +} + +#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index + +static inline int pci_proc_domain(struct pci_bus *bus) +{ + struct pci_controller *hose = bus->sysdata; + return hose->need_domain_info; +} + +#endif /* __KERNEL__ */ + +/* implement the pci_ DMA API in terms of the generic device dma_ one */ +#include + +/* Do platform specific device initialization at pci_enable_device() time */ +extern int pcibios_plat_dev_init(struct pci_dev *dev); + +/* Chances are this interrupt is wired PC-style ... */ +static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) +{ + return channel ? 15 : 14; +} + +extern int pci_probe_only; + +extern char * (*pcibios_plat_setup)(char *str); + +#endif /* _ASM_PCI_H */ diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h new file mode 100644 index 00000000000..5f4b9d4e411 --- /dev/null +++ b/arch/mips/include/asm/pci/bridge.h @@ -0,0 +1,854 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * bridge.h - bridge chip header file, derived from IRIX , + * revision 1.76. + * + * Copyright (C) 1996, 1999 Silcon Graphics, Inc. + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + */ +#ifndef _ASM_PCI_BRIDGE_H +#define _ASM_PCI_BRIDGE_H + +#include +#include +#include /* generic widget header */ +#include + +/* I/O page size */ + +#define IOPFNSHIFT 12 /* 4K per mapped page */ + +#define IOPGSIZE (1 << IOPFNSHIFT) +#define IOPG(x) ((x) >> IOPFNSHIFT) +#define IOPGOFF(x) ((x) & (IOPGSIZE-1)) + +/* Bridge RAM sizes */ + +#define BRIDGE_ATE_RAM_SIZE 0x00000400 /* 1kB ATE RAM */ + +#define BRIDGE_CONFIG_BASE 0x20000 +#define BRIDGE_CONFIG1_BASE 0x28000 +#define BRIDGE_CONFIG_END 0x30000 +#define BRIDGE_CONFIG_SLOT_SIZE 0x1000 + +#define BRIDGE_SSRAM_512K 0x00080000 /* 512kB */ +#define BRIDGE_SSRAM_128K 0x00020000 /* 128kB */ +#define BRIDGE_SSRAM_64K 0x00010000 /* 64kB */ +#define BRIDGE_SSRAM_0K 0x00000000 /* 0kB */ + +/* ======================================================================== + * Bridge address map + */ + +#ifndef __ASSEMBLY__ + +/* + * All accesses to bridge hardware registers must be done + * using 32-bit loads and stores. + */ +typedef u32 bridgereg_t; + +typedef u64 bridge_ate_t; + +/* pointers to bridge ATEs + * are always "pointer to volatile" + */ +typedef volatile bridge_ate_t *bridge_ate_p; + +/* + * It is generally preferred that hardware registers on the bridge + * are located from C code via this structure. + * + * Generated from Bridge spec dated 04oct95 + */ + +typedef volatile struct bridge_s { + /* Local Registers 0x000000-0x00FFFF */ + + /* standard widget configuration 0x000000-0x000057 */ + widget_cfg_t b_widget; /* 0x000000 */ + + /* helper fieldnames for accessing bridge widget */ + +#define b_wid_id b_widget.w_id +#define b_wid_stat b_widget.w_status +#define b_wid_err_upper b_widget.w_err_upper_addr +#define b_wid_err_lower b_widget.w_err_lower_addr +#define b_wid_control b_widget.w_control +#define b_wid_req_timeout b_widget.w_req_timeout +#define b_wid_int_upper b_widget.w_intdest_upper_addr +#define b_wid_int_lower b_widget.w_intdest_lower_addr +#define b_wid_err_cmdword b_widget.w_err_cmd_word +#define b_wid_llp b_widget.w_llp_cfg +#define b_wid_tflush b_widget.w_tflush + + /* bridge-specific widget configuration 0x000058-0x00007F */ + bridgereg_t _pad_000058; + bridgereg_t b_wid_aux_err; /* 0x00005C */ + bridgereg_t _pad_000060; + bridgereg_t b_wid_resp_upper; /* 0x000064 */ + bridgereg_t _pad_000068; + bridgereg_t b_wid_resp_lower; /* 0x00006C */ + bridgereg_t _pad_000070; + bridgereg_t b_wid_tst_pin_ctrl; /* 0x000074 */ + bridgereg_t _pad_000078[2]; + + /* PMU & Map 0x000080-0x00008F */ + bridgereg_t _pad_000080; + bridgereg_t b_dir_map; /* 0x000084 */ + bridgereg_t _pad_000088[2]; + + /* SSRAM 0x000090-0x00009F */ + bridgereg_t _pad_000090; + bridgereg_t b_ram_perr; /* 0x000094 */ + bridgereg_t _pad_000098[2]; + + /* Arbitration 0x0000A0-0x0000AF */ + bridgereg_t _pad_0000A0; + bridgereg_t b_arb; /* 0x0000A4 */ + bridgereg_t _pad_0000A8[2]; + + /* Number In A Can 0x0000B0-0x0000BF */ + bridgereg_t _pad_0000B0; + bridgereg_t b_nic; /* 0x0000B4 */ + bridgereg_t _pad_0000B8[2]; + + /* PCI/GIO 0x0000C0-0x0000FF */ + bridgereg_t _pad_0000C0; + bridgereg_t b_bus_timeout; /* 0x0000C4 */ +#define b_pci_bus_timeout b_bus_timeout + + bridgereg_t _pad_0000C8; + bridgereg_t b_pci_cfg; /* 0x0000CC */ + bridgereg_t _pad_0000D0; + bridgereg_t b_pci_err_upper; /* 0x0000D4 */ + bridgereg_t _pad_0000D8; + bridgereg_t b_pci_err_lower; /* 0x0000DC */ + bridgereg_t _pad_0000E0[8]; +#define b_gio_err_lower b_pci_err_lower +#define b_gio_err_upper b_pci_err_upper + + /* Interrupt 0x000100-0x0001FF */ + bridgereg_t _pad_000100; + bridgereg_t b_int_status; /* 0x000104 */ + bridgereg_t _pad_000108; + bridgereg_t b_int_enable; /* 0x00010C */ + bridgereg_t _pad_000110; + bridgereg_t b_int_rst_stat; /* 0x000114 */ + bridgereg_t _pad_000118; + bridgereg_t b_int_mode; /* 0x00011C */ + bridgereg_t _pad_000120; + bridgereg_t b_int_device; /* 0x000124 */ + bridgereg_t _pad_000128; + bridgereg_t b_int_host_err; /* 0x00012C */ + + struct { + bridgereg_t __pad; /* 0x0001{30,,,68} */ + bridgereg_t addr; /* 0x0001{34,,,6C} */ + } b_int_addr[8]; /* 0x000130 */ + + bridgereg_t _pad_000170[36]; + + /* Device 0x000200-0x0003FF */ + struct { + bridgereg_t __pad; /* 0x0002{00,,,38} */ + bridgereg_t reg; /* 0x0002{04,,,3C} */ + } b_device[8]; /* 0x000200 */ + + struct { + bridgereg_t __pad; /* 0x0002{40,,,78} */ + bridgereg_t reg; /* 0x0002{44,,,7C} */ + } b_wr_req_buf[8]; /* 0x000240 */ + + struct { + bridgereg_t __pad; /* 0x0002{80,,,88} */ + bridgereg_t reg; /* 0x0002{84,,,8C} */ + } b_rrb_map[2]; /* 0x000280 */ +#define b_even_resp b_rrb_map[0].reg /* 0x000284 */ +#define b_odd_resp b_rrb_map[1].reg /* 0x00028C */ + + bridgereg_t _pad_000290; + bridgereg_t b_resp_status; /* 0x000294 */ + bridgereg_t _pad_000298; + bridgereg_t b_resp_clear; /* 0x00029C */ + + bridgereg_t _pad_0002A0[24]; + + char _pad_000300[0x10000 - 0x000300]; + + /* Internal Address Translation Entry RAM 0x010000-0x0103FF */ + union { + bridge_ate_t wr; /* write-only */ + struct { + bridgereg_t _p_pad; + bridgereg_t rd; /* read-only */ + } hi; + } b_int_ate_ram[128]; + + char _pad_010400[0x11000 - 0x010400]; + + /* Internal Address Translation Entry RAM LOW 0x011000-0x0113FF */ + struct { + bridgereg_t _p_pad; + bridgereg_t rd; /* read-only */ + } b_int_ate_ram_lo[128]; + + char _pad_011400[0x20000 - 0x011400]; + + /* PCI Device Configuration Spaces 0x020000-0x027FFF */ + union { /* make all access sizes available. */ + u8 c[0x1000 / 1]; + u16 s[0x1000 / 2]; + u32 l[0x1000 / 4]; + u64 d[0x1000 / 8]; + union { + u8 c[0x100 / 1]; + u16 s[0x100 / 2]; + u32 l[0x100 / 4]; + u64 d[0x100 / 8]; + } f[8]; + } b_type0_cfg_dev[8]; /* 0x020000 */ + + /* PCI Type 1 Configuration Space 0x028000-0x028FFF */ + union { /* make all access sizes available. */ + u8 c[0x1000 / 1]; + u16 s[0x1000 / 2]; + u32 l[0x1000 / 4]; + u64 d[0x1000 / 8]; + } b_type1_cfg; /* 0x028000-0x029000 */ + + char _pad_029000[0x007000]; /* 0x029000-0x030000 */ + + /* PCI Interrupt Acknowledge Cycle 0x030000 */ + union { + u8 c[8 / 1]; + u16 s[8 / 2]; + u32 l[8 / 4]; + u64 d[8 / 8]; + } b_pci_iack; /* 0x030000 */ + + u8 _pad_030007[0x04fff8]; /* 0x030008-0x07FFFF */ + + /* External Address Translation Entry RAM 0x080000-0x0FFFFF */ + bridge_ate_t b_ext_ate_ram[0x10000]; + + /* Reserved 0x100000-0x1FFFFF */ + char _pad_100000[0x200000-0x100000]; + + /* PCI/GIO Device Spaces 0x200000-0xBFFFFF */ + union { /* make all access sizes available. */ + u8 c[0x100000 / 1]; + u16 s[0x100000 / 2]; + u32 l[0x100000 / 4]; + u64 d[0x100000 / 8]; + } b_devio_raw[10]; /* 0x200000 */ + + /* b_devio macro is a bit strange; it reflects the + * fact that the Bridge ASIC provides 2M for the + * first two DevIO windows and 1M for the other six. + */ +#define b_devio(n) b_devio_raw[((n)<2)?(n*2):(n+2)] + + /* External Flash Proms 1,0 0xC00000-0xFFFFFF */ + union { /* make all access sizes available. */ + u8 c[0x400000 / 1]; /* read-only */ + u16 s[0x400000 / 2]; /* read-write */ + u32 l[0x400000 / 4]; /* read-only */ + u64 d[0x400000 / 8]; /* read-only */ + } b_external_flash; /* 0xC00000 */ +} bridge_t; + +/* + * Field formats for Error Command Word and Auxillary Error Command Word + * of bridge. + */ +typedef struct bridge_err_cmdword_s { + union { + u32 cmd_word; + struct { + u32 didn:4, /* Destination ID */ + sidn:4, /* Source ID */ + pactyp:4, /* Packet type */ + tnum:5, /* Trans Number */ + coh:1, /* Coh Transacti */ + ds:2, /* Data size */ + gbr:1, /* GBR enable */ + vbpm:1, /* VBPM message */ + error:1, /* Error occurred */ + barr:1, /* Barrier op */ + rsvd:8; + } berr_st; + } berr_un; +} bridge_err_cmdword_t; + +#define berr_field berr_un.berr_st +#endif /* !__ASSEMBLY__ */ + +/* + * The values of these macros can and should be crosschecked + * regularly against the offsets of the like-named fields + * within the "bridge_t" structure above. + */ + +/* Byte offset macros for Bridge internal registers */ + +#define BRIDGE_WID_ID WIDGET_ID +#define BRIDGE_WID_STAT WIDGET_STATUS +#define BRIDGE_WID_ERR_UPPER WIDGET_ERR_UPPER_ADDR +#define BRIDGE_WID_ERR_LOWER WIDGET_ERR_LOWER_ADDR +#define BRIDGE_WID_CONTROL WIDGET_CONTROL +#define BRIDGE_WID_REQ_TIMEOUT WIDGET_REQ_TIMEOUT +#define BRIDGE_WID_INT_UPPER WIDGET_INTDEST_UPPER_ADDR +#define BRIDGE_WID_INT_LOWER WIDGET_INTDEST_LOWER_ADDR +#define BRIDGE_WID_ERR_CMDWORD WIDGET_ERR_CMD_WORD +#define BRIDGE_WID_LLP WIDGET_LLP_CFG +#define BRIDGE_WID_TFLUSH WIDGET_TFLUSH + +#define BRIDGE_WID_AUX_ERR 0x00005C /* Aux Error Command Word */ +#define BRIDGE_WID_RESP_UPPER 0x000064 /* Response Buf Upper Addr */ +#define BRIDGE_WID_RESP_LOWER 0x00006C /* Response Buf Lower Addr */ +#define BRIDGE_WID_TST_PIN_CTRL 0x000074 /* Test pin control */ + +#define BRIDGE_DIR_MAP 0x000084 /* Direct Map reg */ + +#define BRIDGE_RAM_PERR 0x000094 /* SSRAM Parity Error */ + +#define BRIDGE_ARB 0x0000A4 /* Arbitration Priority reg */ + +#define BRIDGE_NIC 0x0000B4 /* Number In A Can */ + +#define BRIDGE_BUS_TIMEOUT 0x0000C4 /* Bus Timeout Register */ +#define BRIDGE_PCI_BUS_TIMEOUT BRIDGE_BUS_TIMEOUT +#define BRIDGE_PCI_CFG 0x0000CC /* PCI Type 1 Config reg */ +#define BRIDGE_PCI_ERR_UPPER 0x0000D4 /* PCI error Upper Addr */ +#define BRIDGE_PCI_ERR_LOWER 0x0000DC /* PCI error Lower Addr */ + +#define BRIDGE_INT_STATUS 0x000104 /* Interrupt Status */ +#define BRIDGE_INT_ENABLE 0x00010C /* Interrupt Enables */ +#define BRIDGE_INT_RST_STAT 0x000114 /* Reset Intr Status */ +#define BRIDGE_INT_MODE 0x00011C /* Interrupt Mode */ +#define BRIDGE_INT_DEVICE 0x000124 /* Interrupt Device */ +#define BRIDGE_INT_HOST_ERR 0x00012C /* Host Error Field */ + +#define BRIDGE_INT_ADDR0 0x000134 /* Host Address Reg */ +#define BRIDGE_INT_ADDR_OFF 0x000008 /* Host Addr offset (1..7) */ +#define BRIDGE_INT_ADDR(x) (BRIDGE_INT_ADDR0+(x)*BRIDGE_INT_ADDR_OFF) + +#define BRIDGE_DEVICE0 0x000204 /* Device 0 */ +#define BRIDGE_DEVICE_OFF 0x000008 /* Device offset (1..7) */ +#define BRIDGE_DEVICE(x) (BRIDGE_DEVICE0+(x)*BRIDGE_DEVICE_OFF) + +#define BRIDGE_WR_REQ_BUF0 0x000244 /* Write Request Buffer 0 */ +#define BRIDGE_WR_REQ_BUF_OFF 0x000008 /* Buffer Offset (1..7) */ +#define BRIDGE_WR_REQ_BUF(x) (BRIDGE_WR_REQ_BUF0+(x)*BRIDGE_WR_REQ_BUF_OFF) + +#define BRIDGE_EVEN_RESP 0x000284 /* Even Device Response Buf */ +#define BRIDGE_ODD_RESP 0x00028C /* Odd Device Response Buf */ + +#define BRIDGE_RESP_STATUS 0x000294 /* Read Response Status reg */ +#define BRIDGE_RESP_CLEAR 0x00029C /* Read Response Clear reg */ + +/* Byte offset macros for Bridge I/O space */ + +#define BRIDGE_ATE_RAM 0x00010000 /* Internal Addr Xlat Ram */ + +#define BRIDGE_TYPE0_CFG_DEV0 0x00020000 /* Type 0 Cfg, Device 0 */ +#define BRIDGE_TYPE0_CFG_SLOT_OFF 0x00001000 /* Type 0 Cfg Slot Offset (1..7) */ +#define BRIDGE_TYPE0_CFG_FUNC_OFF 0x00000100 /* Type 0 Cfg Func Offset (1..7) */ +#define BRIDGE_TYPE0_CFG_DEV(s) (BRIDGE_TYPE0_CFG_DEV0+\ + (s)*BRIDGE_TYPE0_CFG_SLOT_OFF) +#define BRIDGE_TYPE0_CFG_DEVF(s, f) (BRIDGE_TYPE0_CFG_DEV0+\ + (s)*BRIDGE_TYPE0_CFG_SLOT_OFF+\ + (f)*BRIDGE_TYPE0_CFG_FUNC_OFF) + +#define BRIDGE_TYPE1_CFG 0x00028000 /* Type 1 Cfg space */ + +#define BRIDGE_PCI_IACK 0x00030000 /* PCI Interrupt Ack */ +#define BRIDGE_EXT_SSRAM 0x00080000 /* Extern SSRAM (ATE) */ + +/* Byte offset macros for Bridge device IO spaces */ + +#define BRIDGE_DEV_CNT 8 /* Up to 8 devices per bridge */ +#define BRIDGE_DEVIO0 0x00200000 /* Device IO 0 Addr */ +#define BRIDGE_DEVIO1 0x00400000 /* Device IO 1 Addr */ +#define BRIDGE_DEVIO2 0x00600000 /* Device IO 2 Addr */ +#define BRIDGE_DEVIO_OFF 0x00100000 /* Device IO Offset (3..7) */ + +#define BRIDGE_DEVIO_2MB 0x00200000 /* Device IO Offset (0..1) */ +#define BRIDGE_DEVIO_1MB 0x00100000 /* Device IO Offset (2..7) */ + +#define BRIDGE_DEVIO(x) ((x)<=1 ? BRIDGE_DEVIO0+(x)*BRIDGE_DEVIO_2MB : BRIDGE_DEVIO2+((x)-2)*BRIDGE_DEVIO_1MB) + +#define BRIDGE_EXTERNAL_FLASH 0x00C00000 /* External Flash PROMS */ + +/* ======================================================================== + * Bridge register bit field definitions + */ + +/* Widget part number of bridge */ +#define BRIDGE_WIDGET_PART_NUM 0xc002 +#define XBRIDGE_WIDGET_PART_NUM 0xd002 + +/* Manufacturer of bridge */ +#define BRIDGE_WIDGET_MFGR_NUM 0x036 +#define XBRIDGE_WIDGET_MFGR_NUM 0x024 + +/* Revision numbers for known Bridge revisions */ +#define BRIDGE_REV_A 0x1 +#define BRIDGE_REV_B 0x2 +#define BRIDGE_REV_C 0x3 +#define BRIDGE_REV_D 0x4 + +/* Bridge widget status register bits definition */ + +#define BRIDGE_STAT_LLP_REC_CNT (0xFFu << 24) +#define BRIDGE_STAT_LLP_TX_CNT (0xFF << 16) +#define BRIDGE_STAT_FLASH_SELECT (0x1 << 6) +#define BRIDGE_STAT_PCI_GIO_N (0x1 << 5) +#define BRIDGE_STAT_PENDING (0x1F << 0) + +/* Bridge widget control register bits definition */ +#define BRIDGE_CTRL_FLASH_WR_EN (0x1ul << 31) +#define BRIDGE_CTRL_EN_CLK50 (0x1 << 30) +#define BRIDGE_CTRL_EN_CLK40 (0x1 << 29) +#define BRIDGE_CTRL_EN_CLK33 (0x1 << 28) +#define BRIDGE_CTRL_RST(n) ((n) << 24) +#define BRIDGE_CTRL_RST_MASK (BRIDGE_CTRL_RST(0xF)) +#define BRIDGE_CTRL_RST_PIN(x) (BRIDGE_CTRL_RST(0x1 << (x))) +#define BRIDGE_CTRL_IO_SWAP (0x1 << 23) +#define BRIDGE_CTRL_MEM_SWAP (0x1 << 22) +#define BRIDGE_CTRL_PAGE_SIZE (0x1 << 21) +#define BRIDGE_CTRL_SS_PAR_BAD (0x1 << 20) +#define BRIDGE_CTRL_SS_PAR_EN (0x1 << 19) +#define BRIDGE_CTRL_SSRAM_SIZE(n) ((n) << 17) +#define BRIDGE_CTRL_SSRAM_SIZE_MASK (BRIDGE_CTRL_SSRAM_SIZE(0x3)) +#define BRIDGE_CTRL_SSRAM_512K (BRIDGE_CTRL_SSRAM_SIZE(0x3)) +#define BRIDGE_CTRL_SSRAM_128K (BRIDGE_CTRL_SSRAM_SIZE(0x2)) +#define BRIDGE_CTRL_SSRAM_64K (BRIDGE_CTRL_SSRAM_SIZE(0x1)) +#define BRIDGE_CTRL_SSRAM_1K (BRIDGE_CTRL_SSRAM_SIZE(0x0)) +#define BRIDGE_CTRL_F_BAD_PKT (0x1 << 16) +#define BRIDGE_CTRL_LLP_XBAR_CRD(n) ((n) << 12) +#define BRIDGE_CTRL_LLP_XBAR_CRD_MASK (BRIDGE_CTRL_LLP_XBAR_CRD(0xf)) +#define BRIDGE_CTRL_CLR_RLLP_CNT (0x1 << 11) +#define BRIDGE_CTRL_CLR_TLLP_CNT (0x1 << 10) +#define BRIDGE_CTRL_SYS_END (0x1 << 9) +#define BRIDGE_CTRL_MAX_TRANS(n) ((n) << 4) +#define BRIDGE_CTRL_MAX_TRANS_MASK (BRIDGE_CTRL_MAX_TRANS(0x1f)) +#define BRIDGE_CTRL_WIDGET_ID(n) ((n) << 0) +#define BRIDGE_CTRL_WIDGET_ID_MASK (BRIDGE_CTRL_WIDGET_ID(0xf)) + +/* Bridge Response buffer Error Upper Register bit fields definition */ +#define BRIDGE_RESP_ERRUPPR_DEVNUM_SHFT (20) +#define BRIDGE_RESP_ERRUPPR_DEVNUM_MASK (0x7 << BRIDGE_RESP_ERRUPPR_DEVNUM_SHFT) +#define BRIDGE_RESP_ERRUPPR_BUFNUM_SHFT (16) +#define BRIDGE_RESP_ERRUPPR_BUFNUM_MASK (0xF << BRIDGE_RESP_ERRUPPR_BUFNUM_SHFT) +#define BRIDGE_RESP_ERRRUPPR_BUFMASK (0xFFFF) + +#define BRIDGE_RESP_ERRUPPR_BUFNUM(x) \ + (((x) & BRIDGE_RESP_ERRUPPR_BUFNUM_MASK) >> \ + BRIDGE_RESP_ERRUPPR_BUFNUM_SHFT) + +#define BRIDGE_RESP_ERRUPPR_DEVICE(x) \ + (((x) & BRIDGE_RESP_ERRUPPR_DEVNUM_MASK) >> \ + BRIDGE_RESP_ERRUPPR_DEVNUM_SHFT) + +/* Bridge direct mapping register bits definition */ +#define BRIDGE_DIRMAP_W_ID_SHFT 20 +#define BRIDGE_DIRMAP_W_ID (0xf << BRIDGE_DIRMAP_W_ID_SHFT) +#define BRIDGE_DIRMAP_RMF_64 (0x1 << 18) +#define BRIDGE_DIRMAP_ADD512 (0x1 << 17) +#define BRIDGE_DIRMAP_OFF (0x1ffff << 0) +#define BRIDGE_DIRMAP_OFF_ADDRSHFT (31) /* lsbit of DIRMAP_OFF is xtalk address bit 31 */ + +/* Bridge Arbitration register bits definition */ +#define BRIDGE_ARB_REQ_WAIT_TICK(x) ((x) << 16) +#define BRIDGE_ARB_REQ_WAIT_TICK_MASK BRIDGE_ARB_REQ_WAIT_TICK(0x3) +#define BRIDGE_ARB_REQ_WAIT_EN(x) ((x) << 8) +#define BRIDGE_ARB_REQ_WAIT_EN_MASK BRIDGE_ARB_REQ_WAIT_EN(0xff) +#define BRIDGE_ARB_FREEZE_GNT (1 << 6) +#define BRIDGE_ARB_HPRI_RING_B2 (1 << 5) +#define BRIDGE_ARB_HPRI_RING_B1 (1 << 4) +#define BRIDGE_ARB_HPRI_RING_B0 (1 << 3) +#define BRIDGE_ARB_LPRI_RING_B2 (1 << 2) +#define BRIDGE_ARB_LPRI_RING_B1 (1 << 1) +#define BRIDGE_ARB_LPRI_RING_B0 (1 << 0) + +/* Bridge Bus time-out register bits definition */ +#define BRIDGE_BUS_PCI_RETRY_HLD(x) ((x) << 16) +#define BRIDGE_BUS_PCI_RETRY_HLD_MASK BRIDGE_BUS_PCI_RETRY_HLD(0x1f) +#define BRIDGE_BUS_GIO_TIMEOUT (1 << 12) +#define BRIDGE_BUS_PCI_RETRY_CNT(x) ((x) << 0) +#define BRIDGE_BUS_PCI_RETRY_MASK BRIDGE_BUS_PCI_RETRY_CNT(0x3ff) + +/* Bridge interrupt status register bits definition */ +#define BRIDGE_ISR_MULTI_ERR (0x1u << 31) +#define BRIDGE_ISR_PMU_ESIZE_FAULT (0x1 << 30) +#define BRIDGE_ISR_UNEXP_RESP (0x1 << 29) +#define BRIDGE_ISR_BAD_XRESP_PKT (0x1 << 28) +#define BRIDGE_ISR_BAD_XREQ_PKT (0x1 << 27) +#define BRIDGE_ISR_RESP_XTLK_ERR (0x1 << 26) +#define BRIDGE_ISR_REQ_XTLK_ERR (0x1 << 25) +#define BRIDGE_ISR_INVLD_ADDR (0x1 << 24) +#define BRIDGE_ISR_UNSUPPORTED_XOP (0x1 << 23) +#define BRIDGE_ISR_XREQ_FIFO_OFLOW (0x1 << 22) +#define BRIDGE_ISR_LLP_REC_SNERR (0x1 << 21) +#define BRIDGE_ISR_LLP_REC_CBERR (0x1 << 20) +#define BRIDGE_ISR_LLP_RCTY (0x1 << 19) +#define BRIDGE_ISR_LLP_TX_RETRY (0x1 << 18) +#define BRIDGE_ISR_LLP_TCTY (0x1 << 17) +#define BRIDGE_ISR_SSRAM_PERR (0x1 << 16) +#define BRIDGE_ISR_PCI_ABORT (0x1 << 15) +#define BRIDGE_ISR_PCI_PARITY (0x1 << 14) +#define BRIDGE_ISR_PCI_SERR (0x1 << 13) +#define BRIDGE_ISR_PCI_PERR (0x1 << 12) +#define BRIDGE_ISR_PCI_MST_TIMEOUT (0x1 << 11) +#define BRIDGE_ISR_GIO_MST_TIMEOUT BRIDGE_ISR_PCI_MST_TIMEOUT +#define BRIDGE_ISR_PCI_RETRY_CNT (0x1 << 10) +#define BRIDGE_ISR_XREAD_REQ_TIMEOUT (0x1 << 9) +#define BRIDGE_ISR_GIO_B_ENBL_ERR (0x1 << 8) +#define BRIDGE_ISR_INT_MSK (0xff << 0) +#define BRIDGE_ISR_INT(x) (0x1 << (x)) + +#define BRIDGE_ISR_LINK_ERROR \ + (BRIDGE_ISR_LLP_REC_SNERR|BRIDGE_ISR_LLP_REC_CBERR| \ + BRIDGE_ISR_LLP_RCTY|BRIDGE_ISR_LLP_TX_RETRY| \ + BRIDGE_ISR_LLP_TCTY) + +#define BRIDGE_ISR_PCIBUS_PIOERR \ + (BRIDGE_ISR_PCI_MST_TIMEOUT|BRIDGE_ISR_PCI_ABORT) + +#define BRIDGE_ISR_PCIBUS_ERROR \ + (BRIDGE_ISR_PCIBUS_PIOERR|BRIDGE_ISR_PCI_PERR| \ + BRIDGE_ISR_PCI_SERR|BRIDGE_ISR_PCI_RETRY_CNT| \ + BRIDGE_ISR_PCI_PARITY) + +#define BRIDGE_ISR_XTALK_ERROR \ + (BRIDGE_ISR_XREAD_REQ_TIMEOUT|BRIDGE_ISR_XREQ_FIFO_OFLOW|\ + BRIDGE_ISR_UNSUPPORTED_XOP|BRIDGE_ISR_INVLD_ADDR| \ + BRIDGE_ISR_REQ_XTLK_ERR|BRIDGE_ISR_RESP_XTLK_ERR| \ + BRIDGE_ISR_BAD_XREQ_PKT|BRIDGE_ISR_BAD_XRESP_PKT| \ + BRIDGE_ISR_UNEXP_RESP) + +#define BRIDGE_ISR_ERRORS \ + (BRIDGE_ISR_LINK_ERROR|BRIDGE_ISR_PCIBUS_ERROR| \ + BRIDGE_ISR_XTALK_ERROR|BRIDGE_ISR_SSRAM_PERR| \ + BRIDGE_ISR_PMU_ESIZE_FAULT) + +/* + * List of Errors which are fatal and kill the system + */ +#define BRIDGE_ISR_ERROR_FATAL \ + ((BRIDGE_ISR_XTALK_ERROR & ~BRIDGE_ISR_XREAD_REQ_TIMEOUT)|\ + BRIDGE_ISR_PCI_SERR|BRIDGE_ISR_PCI_PARITY ) + +#define BRIDGE_ISR_ERROR_DUMP \ + (BRIDGE_ISR_PCIBUS_ERROR|BRIDGE_ISR_PMU_ESIZE_FAULT| \ + BRIDGE_ISR_XTALK_ERROR|BRIDGE_ISR_SSRAM_PERR) + +/* Bridge interrupt enable register bits definition */ +#define BRIDGE_IMR_UNEXP_RESP BRIDGE_ISR_UNEXP_RESP +#define BRIDGE_IMR_PMU_ESIZE_FAULT BRIDGE_ISR_PMU_ESIZE_FAULT +#define BRIDGE_IMR_BAD_XRESP_PKT BRIDGE_ISR_BAD_XRESP_PKT +#define BRIDGE_IMR_BAD_XREQ_PKT BRIDGE_ISR_BAD_XREQ_PKT +#define BRIDGE_IMR_RESP_XTLK_ERR BRIDGE_ISR_RESP_XTLK_ERR +#define BRIDGE_IMR_REQ_XTLK_ERR BRIDGE_ISR_REQ_XTLK_ERR +#define BRIDGE_IMR_INVLD_ADDR BRIDGE_ISR_INVLD_ADDR +#define BRIDGE_IMR_UNSUPPORTED_XOP BRIDGE_ISR_UNSUPPORTED_XOP +#define BRIDGE_IMR_XREQ_FIFO_OFLOW BRIDGE_ISR_XREQ_FIFO_OFLOW +#define BRIDGE_IMR_LLP_REC_SNERR BRIDGE_ISR_LLP_REC_SNERR +#define BRIDGE_IMR_LLP_REC_CBERR BRIDGE_ISR_LLP_REC_CBERR +#define BRIDGE_IMR_LLP_RCTY BRIDGE_ISR_LLP_RCTY +#define BRIDGE_IMR_LLP_TX_RETRY BRIDGE_ISR_LLP_TX_RETRY +#define BRIDGE_IMR_LLP_TCTY BRIDGE_ISR_LLP_TCTY +#define BRIDGE_IMR_SSRAM_PERR BRIDGE_ISR_SSRAM_PERR +#define BRIDGE_IMR_PCI_ABORT BRIDGE_ISR_PCI_ABORT +#define BRIDGE_IMR_PCI_PARITY BRIDGE_ISR_PCI_PARITY +#define BRIDGE_IMR_PCI_SERR BRIDGE_ISR_PCI_SERR +#define BRIDGE_IMR_PCI_PERR BRIDGE_ISR_PCI_PERR +#define BRIDGE_IMR_PCI_MST_TIMEOUT BRIDGE_ISR_PCI_MST_TIMEOUT +#define BRIDGE_IMR_GIO_MST_TIMEOUT BRIDGE_ISR_GIO_MST_TIMEOUT +#define BRIDGE_IMR_PCI_RETRY_CNT BRIDGE_ISR_PCI_RETRY_CNT +#define BRIDGE_IMR_XREAD_REQ_TIMEOUT BRIDGE_ISR_XREAD_REQ_TIMEOUT +#define BRIDGE_IMR_GIO_B_ENBL_ERR BRIDGE_ISR_GIO_B_ENBL_ERR +#define BRIDGE_IMR_INT_MSK BRIDGE_ISR_INT_MSK +#define BRIDGE_IMR_INT(x) BRIDGE_ISR_INT(x) + +/* Bridge interrupt reset register bits definition */ +#define BRIDGE_IRR_MULTI_CLR (0x1 << 6) +#define BRIDGE_IRR_CRP_GRP_CLR (0x1 << 5) +#define BRIDGE_IRR_RESP_BUF_GRP_CLR (0x1 << 4) +#define BRIDGE_IRR_REQ_DSP_GRP_CLR (0x1 << 3) +#define BRIDGE_IRR_LLP_GRP_CLR (0x1 << 2) +#define BRIDGE_IRR_SSRAM_GRP_CLR (0x1 << 1) +#define BRIDGE_IRR_PCI_GRP_CLR (0x1 << 0) +#define BRIDGE_IRR_GIO_GRP_CLR (0x1 << 0) +#define BRIDGE_IRR_ALL_CLR 0x7f + +#define BRIDGE_IRR_CRP_GRP (BRIDGE_ISR_UNEXP_RESP | \ + BRIDGE_ISR_XREQ_FIFO_OFLOW) +#define BRIDGE_IRR_RESP_BUF_GRP (BRIDGE_ISR_BAD_XRESP_PKT | \ + BRIDGE_ISR_RESP_XTLK_ERR | \ + BRIDGE_ISR_XREAD_REQ_TIMEOUT) +#define BRIDGE_IRR_REQ_DSP_GRP (BRIDGE_ISR_UNSUPPORTED_XOP | \ + BRIDGE_ISR_BAD_XREQ_PKT | \ + BRIDGE_ISR_REQ_XTLK_ERR | \ + BRIDGE_ISR_INVLD_ADDR) +#define BRIDGE_IRR_LLP_GRP (BRIDGE_ISR_LLP_REC_SNERR | \ + BRIDGE_ISR_LLP_REC_CBERR | \ + BRIDGE_ISR_LLP_RCTY | \ + BRIDGE_ISR_LLP_TX_RETRY | \ + BRIDGE_ISR_LLP_TCTY) +#define BRIDGE_IRR_SSRAM_GRP (BRIDGE_ISR_SSRAM_PERR | \ + BRIDGE_ISR_PMU_ESIZE_FAULT) +#define BRIDGE_IRR_PCI_GRP (BRIDGE_ISR_PCI_ABORT | \ + BRIDGE_ISR_PCI_PARITY | \ + BRIDGE_ISR_PCI_SERR | \ + BRIDGE_ISR_PCI_PERR | \ + BRIDGE_ISR_PCI_MST_TIMEOUT | \ + BRIDGE_ISR_PCI_RETRY_CNT) + +#define BRIDGE_IRR_GIO_GRP (BRIDGE_ISR_GIO_B_ENBL_ERR | \ + BRIDGE_ISR_GIO_MST_TIMEOUT) + +/* Bridge INT_DEV register bits definition */ +#define BRIDGE_INT_DEV_SHFT(n) ((n)*3) +#define BRIDGE_INT_DEV_MASK(n) (0x7 << BRIDGE_INT_DEV_SHFT(n)) +#define BRIDGE_INT_DEV_SET(_dev, _line) (_dev << BRIDGE_INT_DEV_SHFT(_line)) + +/* Bridge interrupt(x) register bits definition */ +#define BRIDGE_INT_ADDR_HOST 0x0003FF00 +#define BRIDGE_INT_ADDR_FLD 0x000000FF + +#define BRIDGE_TMO_PCI_RETRY_HLD_MASK 0x1f0000 +#define BRIDGE_TMO_GIO_TIMEOUT_MASK 0x001000 +#define BRIDGE_TMO_PCI_RETRY_CNT_MASK 0x0003ff + +#define BRIDGE_TMO_PCI_RETRY_CNT_MAX 0x3ff + +/* + * The NASID should be shifted by this amount and stored into the + * interrupt(x) register. + */ +#define BRIDGE_INT_ADDR_NASID_SHFT 8 + +/* + * The BRIDGE_INT_ADDR_DEST_IO bit should be set to send an interrupt to + * memory. + */ +#define BRIDGE_INT_ADDR_DEST_IO (1 << 17) +#define BRIDGE_INT_ADDR_DEST_MEM 0 +#define BRIDGE_INT_ADDR_MASK (1 << 17) + +/* Bridge device(x) register bits definition */ +#define BRIDGE_DEV_ERR_LOCK_EN 0x10000000 +#define BRIDGE_DEV_PAGE_CHK_DIS 0x08000000 +#define BRIDGE_DEV_FORCE_PCI_PAR 0x04000000 +#define BRIDGE_DEV_VIRTUAL_EN 0x02000000 +#define BRIDGE_DEV_PMU_WRGA_EN 0x01000000 +#define BRIDGE_DEV_DIR_WRGA_EN 0x00800000 +#define BRIDGE_DEV_DEV_SIZE 0x00400000 +#define BRIDGE_DEV_RT 0x00200000 +#define BRIDGE_DEV_SWAP_PMU 0x00100000 +#define BRIDGE_DEV_SWAP_DIR 0x00080000 +#define BRIDGE_DEV_PREF 0x00040000 +#define BRIDGE_DEV_PRECISE 0x00020000 +#define BRIDGE_DEV_COH 0x00010000 +#define BRIDGE_DEV_BARRIER 0x00008000 +#define BRIDGE_DEV_GBR 0x00004000 +#define BRIDGE_DEV_DEV_SWAP 0x00002000 +#define BRIDGE_DEV_DEV_IO_MEM 0x00001000 +#define BRIDGE_DEV_OFF_MASK 0x00000fff +#define BRIDGE_DEV_OFF_ADDR_SHFT 20 + +#define BRIDGE_DEV_PMU_BITS (BRIDGE_DEV_PMU_WRGA_EN | \ + BRIDGE_DEV_SWAP_PMU) +#define BRIDGE_DEV_D32_BITS (BRIDGE_DEV_DIR_WRGA_EN | \ + BRIDGE_DEV_SWAP_DIR | \ + BRIDGE_DEV_PREF | \ + BRIDGE_DEV_PRECISE | \ + BRIDGE_DEV_COH | \ + BRIDGE_DEV_BARRIER) +#define BRIDGE_DEV_D64_BITS (BRIDGE_DEV_DIR_WRGA_EN | \ + BRIDGE_DEV_SWAP_DIR | \ + BRIDGE_DEV_COH | \ + BRIDGE_DEV_BARRIER) + +/* Bridge Error Upper register bit field definition */ +#define BRIDGE_ERRUPPR_DEVMASTER (0x1 << 20) /* Device was master */ +#define BRIDGE_ERRUPPR_PCIVDEV (0x1 << 19) /* Virtual Req value */ +#define BRIDGE_ERRUPPR_DEVNUM_SHFT (16) +#define BRIDGE_ERRUPPR_DEVNUM_MASK (0x7 << BRIDGE_ERRUPPR_DEVNUM_SHFT) +#define BRIDGE_ERRUPPR_DEVICE(err) (((err) >> BRIDGE_ERRUPPR_DEVNUM_SHFT) & 0x7) +#define BRIDGE_ERRUPPR_ADDRMASK (0xFFFF) + +/* Bridge interrupt mode register bits definition */ +#define BRIDGE_INTMODE_CLR_PKT_EN(x) (0x1 << (x)) + +/* this should be written to the xbow's link_control(x) register */ +#define BRIDGE_CREDIT 3 + +/* RRB assignment register */ +#define BRIDGE_RRB_EN 0x8 /* after shifting down */ +#define BRIDGE_RRB_DEV 0x7 /* after shifting down */ +#define BRIDGE_RRB_VDEV 0x4 /* after shifting down */ +#define BRIDGE_RRB_PDEV 0x3 /* after shifting down */ + +/* RRB status register */ +#define BRIDGE_RRB_VALID(r) (0x00010000<<(r)) +#define BRIDGE_RRB_INUSE(r) (0x00000001<<(r)) + +/* RRB clear register */ +#define BRIDGE_RRB_CLEAR(r) (0x00000001<<(r)) + +/* xbox system controller declarations */ +#define XBOX_BRIDGE_WID 8 +#define FLASH_PROM1_BASE 0xE00000 /* To read the xbox sysctlr status */ +#define XBOX_RPS_EXISTS 1 << 6 /* RPS bit in status register */ +#define XBOX_RPS_FAIL 1 << 4 /* RPS status bit in register */ + +/* ======================================================================== + */ +/* + * Macros for Xtalk to Bridge bus (PCI/GIO) PIO + * refer to section 4.2.1 of Bridge Spec for xtalk to PCI/GIO PIO mappings + */ +/* XTALK addresses that map into Bridge Bus addr space */ +#define BRIDGE_PIO32_XTALK_ALIAS_BASE 0x000040000000L +#define BRIDGE_PIO32_XTALK_ALIAS_LIMIT 0x00007FFFFFFFL +#define BRIDGE_PIO64_XTALK_ALIAS_BASE 0x000080000000L +#define BRIDGE_PIO64_XTALK_ALIAS_LIMIT 0x0000BFFFFFFFL +#define BRIDGE_PCIIO_XTALK_ALIAS_BASE 0x000100000000L +#define BRIDGE_PCIIO_XTALK_ALIAS_LIMIT 0x0001FFFFFFFFL + +/* Ranges of PCI bus space that can be accessed via PIO from xtalk */ +#define BRIDGE_MIN_PIO_ADDR_MEM 0x00000000 /* 1G PCI memory space */ +#define BRIDGE_MAX_PIO_ADDR_MEM 0x3fffffff +#define BRIDGE_MIN_PIO_ADDR_IO 0x00000000 /* 4G PCI IO space */ +#define BRIDGE_MAX_PIO_ADDR_IO 0xffffffff + +/* XTALK addresses that map into PCI addresses */ +#define BRIDGE_PCI_MEM32_BASE BRIDGE_PIO32_XTALK_ALIAS_BASE +#define BRIDGE_PCI_MEM32_LIMIT BRIDGE_PIO32_XTALK_ALIAS_LIMIT +#define BRIDGE_PCI_MEM64_BASE BRIDGE_PIO64_XTALK_ALIAS_BASE +#define BRIDGE_PCI_MEM64_LIMIT BRIDGE_PIO64_XTALK_ALIAS_LIMIT +#define BRIDGE_PCI_IO_BASE BRIDGE_PCIIO_XTALK_ALIAS_BASE +#define BRIDGE_PCI_IO_LIMIT BRIDGE_PCIIO_XTALK_ALIAS_LIMIT + +/* + * Macros for Bridge bus (PCI/GIO) to Xtalk DMA + */ +/* Bridge Bus DMA addresses */ +#define BRIDGE_LOCAL_BASE 0 +#define BRIDGE_DMA_MAPPED_BASE 0x40000000 +#define BRIDGE_DMA_MAPPED_SIZE 0x40000000 /* 1G Bytes */ +#define BRIDGE_DMA_DIRECT_BASE 0x80000000 +#define BRIDGE_DMA_DIRECT_SIZE 0x80000000 /* 2G Bytes */ + +#define PCI32_LOCAL_BASE BRIDGE_LOCAL_BASE + +/* PCI addresses of regions decoded by Bridge for DMA */ +#define PCI32_MAPPED_BASE BRIDGE_DMA_MAPPED_BASE +#define PCI32_DIRECT_BASE BRIDGE_DMA_DIRECT_BASE + +#define IS_PCI32_LOCAL(x) ((ulong_t)(x) < PCI32_MAPPED_BASE) +#define IS_PCI32_MAPPED(x) ((ulong_t)(x) < PCI32_DIRECT_BASE && \ + (ulong_t)(x) >= PCI32_MAPPED_BASE) +#define IS_PCI32_DIRECT(x) ((ulong_t)(x) >= PCI32_MAPPED_BASE) +#define IS_PCI64(x) ((ulong_t)(x) >= PCI64_BASE) + +/* + * The GIO address space. + */ +/* Xtalk to GIO PIO */ +#define BRIDGE_GIO_MEM32_BASE BRIDGE_PIO32_XTALK_ALIAS_BASE +#define BRIDGE_GIO_MEM32_LIMIT BRIDGE_PIO32_XTALK_ALIAS_LIMIT + +#define GIO_LOCAL_BASE BRIDGE_LOCAL_BASE + +/* GIO addresses of regions decoded by Bridge for DMA */ +#define GIO_MAPPED_BASE BRIDGE_DMA_MAPPED_BASE +#define GIO_DIRECT_BASE BRIDGE_DMA_DIRECT_BASE + +#define IS_GIO_LOCAL(x) ((ulong_t)(x) < GIO_MAPPED_BASE) +#define IS_GIO_MAPPED(x) ((ulong_t)(x) < GIO_DIRECT_BASE && \ + (ulong_t)(x) >= GIO_MAPPED_BASE) +#define IS_GIO_DIRECT(x) ((ulong_t)(x) >= GIO_MAPPED_BASE) + +/* PCI to xtalk mapping */ + +/* given a DIR_OFF value and a pci/gio 32 bits direct address, determine + * which xtalk address is accessed + */ +#define BRIDGE_DIRECT_32_SEG_SIZE BRIDGE_DMA_DIRECT_SIZE +#define BRIDGE_DIRECT_32_TO_XTALK(dir_off,adr) \ + ((dir_off) * BRIDGE_DIRECT_32_SEG_SIZE + \ + ((adr) & (BRIDGE_DIRECT_32_SEG_SIZE - 1)) + PHYS_RAMBASE) + +/* 64-bit address attribute masks */ +#define PCI64_ATTR_TARG_MASK 0xf000000000000000 +#define PCI64_ATTR_TARG_SHFT 60 +#define PCI64_ATTR_PREF 0x0800000000000000 +#define PCI64_ATTR_PREC 0x0400000000000000 +#define PCI64_ATTR_VIRTUAL 0x0200000000000000 +#define PCI64_ATTR_BAR 0x0100000000000000 +#define PCI64_ATTR_RMF_MASK 0x00ff000000000000 +#define PCI64_ATTR_RMF_SHFT 48 + +#ifndef __ASSEMBLY__ +/* Address translation entry for mapped pci32 accesses */ +typedef union ate_u { + u64 ent; + struct ate_s { + u64 rmf:16; + u64 addr:36; + u64 targ:4; + u64 reserved:3; + u64 barrier:1; + u64 prefetch:1; + u64 precise:1; + u64 coherent:1; + u64 valid:1; + } field; +} ate_t; +#endif /* !__ASSEMBLY__ */ + +#define ATE_V 0x01 +#define ATE_CO 0x02 +#define ATE_PREC 0x04 +#define ATE_PREF 0x08 +#define ATE_BAR 0x10 + +#define ATE_PFNSHIFT 12 +#define ATE_TIDSHIFT 8 +#define ATE_RMFSHIFT 48 + +#define mkate(xaddr, xid, attr) ((xaddr) & 0x0000fffffffff000ULL) | \ + ((xid)<sysdata)) + +extern void register_bridge_irq(unsigned int irq); +extern int request_bridge_irq(struct bridge_controller *bc); + +extern struct pci_ops bridge_pci_ops; + +#endif /* _ASM_PCI_BRIDGE_H */ diff --git a/arch/mips/include/asm/percpu.h b/arch/mips/include/asm/percpu.h new file mode 100644 index 00000000000..844e763e933 --- /dev/null +++ b/arch/mips/include/asm/percpu.h @@ -0,0 +1,6 @@ +#ifndef __ASM_PERCPU_H +#define __ASM_PERCPU_H + +#include + +#endif /* __ASM_PERCPU_H */ diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h new file mode 100644 index 00000000000..1275831dda2 --- /dev/null +++ b/arch/mips/include/asm/pgalloc.h @@ -0,0 +1,143 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 2001, 2003 by Ralf Baechle + * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. + */ +#ifndef _ASM_PGALLOC_H +#define _ASM_PGALLOC_H + +#include +#include +#include + +static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, + pte_t *pte) +{ + set_pmd(pmd, __pmd((unsigned long)pte)); +} + +static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, + pgtable_t pte) +{ + set_pmd(pmd, __pmd((unsigned long)page_address(pte))); +} +#define pmd_pgtable(pmd) pmd_page(pmd) + +/* + * Initialize a new pmd table with invalid pointers. + */ +extern void pmd_init(unsigned long page, unsigned long pagetable); + +#ifdef CONFIG_64BIT + +static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) +{ + set_pud(pud, __pud((unsigned long)pmd)); +} +#endif + +/* + * Initialize a new pgd / pmd table with invalid pointers. + */ +extern void pgd_init(unsigned long page); + +static inline pgd_t *pgd_alloc(struct mm_struct *mm) +{ + pgd_t *ret, *init; + + ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER); + if (ret) { + init = pgd_offset(&init_mm, 0UL); + pgd_init((unsigned long)ret); + memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + } + + return ret; +} + +static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) +{ + free_pages((unsigned long)pgd, PGD_ORDER); +} + +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long address) +{ + pte_t *pte; + + pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, PTE_ORDER); + + return pte; +} + +static inline struct page *pte_alloc_one(struct mm_struct *mm, + unsigned long address) +{ + struct page *pte; + + pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER); + if (pte) { + clear_highpage(pte); + pgtable_page_ctor(pte); + } + return pte; +} + +static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) +{ + free_pages((unsigned long)pte, PTE_ORDER); +} + +static inline void pte_free(struct mm_struct *mm, pgtable_t pte) +{ + pgtable_page_dtor(pte); + __free_pages(pte, PTE_ORDER); +} + +#define __pte_free_tlb(tlb,pte) \ +do { \ + pgtable_page_dtor(pte); \ + tlb_remove_page((tlb), pte); \ +} while (0) + +#ifdef CONFIG_32BIT + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_free(mm, x) do { } while (0) +#define __pmd_free_tlb(tlb, x) do { } while (0) + +#endif + +#ifdef CONFIG_64BIT + +static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) +{ + pmd_t *pmd; + + pmd = (pmd_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, PMD_ORDER); + if (pmd) + pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table); + return pmd; +} + +static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) +{ + free_pages((unsigned long)pmd, PMD_ORDER); +} + +#define __pmd_free_tlb(tlb, x) pmd_free((tlb)->mm, x) + +#endif + +#define check_pgt_cache() do { } while (0) + +extern void pagetable_init(void); + +#endif /* _ASM_PGALLOC_H */ diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h new file mode 100644 index 00000000000..55813d6150c --- /dev/null +++ b/arch/mips/include/asm/pgtable-32.h @@ -0,0 +1,234 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 2003 Ralf Baechle + * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. + */ +#ifndef _ASM_PGTABLE_32_H +#define _ASM_PGTABLE_32_H + +#include +#include + +#include +#include +#include + +#include + +/* + * - add_wired_entry() add a fixed TLB entry, and move wired register + */ +extern void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + +/* + * - add_temporary_entry() add a temporary TLB entry. We use TLB entries + * starting at the top and working down. This is for populating the + * TLB before trap_init() puts the TLB miss handler in place. It + * should be used only for entries matching the actual page tables, + * to prevent inconsistencies. + */ +extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + + +/* Basically we have the same two-level (which is the logical three level + * Linux page table layout folded) page tables as the i386. Some day + * when we have proper page coloring support we can have a 1% quicker + * tlb refill handling mechanism, but for now it is a bit slower but + * works even with the cache aliasing problem the R4k and above have. + */ + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT (2 * PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * Entries per page directory level: we use two-level, so + * we don't really have any PUD/PMD directory physically. + */ +#define __PGD_ORDER (32 - 3 * PAGE_SHIFT + PGD_T_LOG2 + PTE_T_LOG2) +#define PGD_ORDER (__PGD_ORDER >= 0 ? __PGD_ORDER : 0) +#define PUD_ORDER aieeee_attempt_to_allocate_pud +#define PMD_ORDER 1 +#define PTE_ORDER 0 + +#define PTRS_PER_PGD (USER_PTRS_PER_PGD * 2) +#define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) + +#define USER_PTRS_PER_PGD (0x80000000UL/PGDIR_SIZE) +#define FIRST_USER_ADDRESS 0 + +#define VMALLOC_START MAP_BASE + +#define PKMAP_BASE (0xfe000000UL) + +#ifdef CONFIG_HIGHMEM +# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) +#else +# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) +#endif + +#ifdef CONFIG_64BIT_PHYS_ADDR +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %016Lx.\n", __FILE__, __LINE__, pte_val(e)) +#else +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) +#endif +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) + +extern void load_pgd(unsigned long pg_dir); + +extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)]; + +/* + * Empty pgd/pmd entries point to the invalid_pte_table. + */ +static inline int pmd_none(pmd_t pmd) +{ + return pmd_val(pmd) == (unsigned long) invalid_pte_table; +} + +#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) + +static inline int pmd_present(pmd_t pmd) +{ + return pmd_val(pmd) != (unsigned long) invalid_pte_table; +} + +static inline void pmd_clear(pmd_t *pmdp) +{ + pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); +} + +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) +#define pte_page(x) pfn_to_page(pte_pfn(x)) +#define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) +static inline pte_t +pfn_pte(unsigned long pfn, pgprot_t prot) +{ + pte_t pte; + pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f); + pte.pte_low = pgprot_val(prot); + return pte; +} + +#else + +#define pte_page(x) pfn_to_page(pte_pfn(x)) + +#ifdef CONFIG_CPU_VR41XX +#define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) +#define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) +#else +#define pte_pfn(x) ((unsigned long)((x).pte >> PAGE_SHIFT)) +#define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#endif +#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */ + +#define __pgd_offset(address) pgd_index(address) +#define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) +#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) + +/* to find an entry in a kernel page-table-directory */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) + +/* to find an entry in a page-table-directory */ +#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) + +/* Find an entry in the third-level page table.. */ +#define __pte_offset(address) \ + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +#define pte_offset(dir, address) \ + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) +#define pte_offset_kernel(dir, address) \ + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) + +#define pte_offset_map(dir, address) \ + ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) +#define pte_offset_map_nested(dir, address) \ + ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) +#define pte_unmap(pte) ((void)(pte)) +#define pte_unmap_nested(pte) ((void)(pte)) + +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + +/* Swap entries must have VALID bit cleared. */ +#define __swp_type(x) (((x).val >> 10) & 0x1f) +#define __swp_offset(x) ((x).val >> 15) +#define __swp_entry(type,offset) \ + ((swp_entry_t) { ((type) << 10) | ((offset) << 15) }) + +/* + * Bits 0, 4, 8, and 9 are taken, split up 28 bits of offset into this range: + */ +#define PTE_FILE_MAX_BITS 28 + +#define pte_to_pgoff(_pte) ((((_pte).pte >> 1 ) & 0x07) | \ + (((_pte).pte >> 2 ) & 0x38) | \ + (((_pte).pte >> 10) << 6 )) + +#define pgoff_to_pte(off) ((pte_t) { (((off) & 0x07) << 1 ) | \ + (((off) & 0x38) << 2 ) | \ + (((off) >> 6 ) << 10) | \ + _PAGE_FILE }) + +#else + +/* Swap entries must have VALID and GLOBAL bits cleared. */ +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) +#define __swp_type(x) (((x).val >> 2) & 0x1f) +#define __swp_offset(x) ((x).val >> 7) +#define __swp_entry(type,offset) \ + ((swp_entry_t) { ((type) << 2) | ((offset) << 7) }) +#else +#define __swp_type(x) (((x).val >> 8) & 0x1f) +#define __swp_offset(x) ((x).val >> 13) +#define __swp_entry(type,offset) \ + ((swp_entry_t) { ((type) << 8) | ((offset) << 13) }) +#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */ + +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) +/* + * Bits 0 and 1 of pte_high are taken, use the rest for the page offset... + */ +#define PTE_FILE_MAX_BITS 30 + +#define pte_to_pgoff(_pte) ((_pte).pte_high >> 2) +#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) << 2 }) + +#else +/* + * Bits 0, 4, 6, and 7 are taken, split up 28 bits of offset into this range: + */ +#define PTE_FILE_MAX_BITS 28 + +#define pte_to_pgoff(_pte) ((((_pte).pte >> 1) & 0x7) | \ + (((_pte).pte >> 2) & 0x8) | \ + (((_pte).pte >> 8) << 4)) + +#define pgoff_to_pte(off) ((pte_t) { (((off) & 0x7) << 1) | \ + (((off) & 0x8) << 2) | \ + (((off) >> 4) << 8) | \ + _PAGE_FILE }) +#endif + +#endif + +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) +#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) +#else +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) +#endif + +#endif /* _ASM_PGTABLE_32_H */ diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h new file mode 100644 index 00000000000..943515f0ef8 --- /dev/null +++ b/arch/mips/include/asm/pgtable-64.h @@ -0,0 +1,253 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 2003 Ralf Baechle + * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. + */ +#ifndef _ASM_PGTABLE_64_H +#define _ASM_PGTABLE_64_H + +#include + +#include +#include +#include +#include + +#include + +/* + * Each address space has 2 4K pages as its page directory, giving 1024 + * (== PTRS_PER_PGD) 8 byte pointers to pmd tables. Each pmd table is a + * single 4K page, giving 512 (== PTRS_PER_PMD) 8 byte pointers to page + * tables. Each page table is also a single 4K page, giving 512 (== + * PTRS_PER_PTE) 8 byte ptes. Each pud entry is initialized to point to + * invalid_pmd_table, each pmd entry is initialized to point to + * invalid_pte_table, each pte is initialized to 0. When memory is low, + * and a pmd table or a page table allocation fails, empty_bad_pmd_table + * and empty_bad_page_table is returned back to higher layer code, so + * that the failure is recognized later on. Linux does not seem to + * handle these failures very well though. The empty_bad_page_table has + * invalid pte entries in it, to force page faults. + * + * Kernel mappings: kernel mappings are held in the swapper_pg_table. + * The layout is identical to userspace except it's indexed with the + * fault address - VMALLOC_START. + */ + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT + PTE_ORDER - 3)) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * For 4kB page size we use a 3 level page tree and an 8kB pud, which + * permits us mapping 40 bits of virtual address space. + * + * We used to implement 41 bits by having an order 1 pmd level but that seemed + * rather pointless. + * + * For 8kB page size we use a 3 level page tree which permits a total of + * 8TB of address space. Alternatively a 33-bit / 8GB organization using + * two levels would be easy to implement. + * + * For 16kB page size we use a 2 level page tree which permits a total of + * 36 bits of virtual address space. We could add a third level but it seems + * like at the moment there's no need for this. + * + * For 64kB page size we use a 2 level page table tree for a total of 42 bits + * of virtual address space. + */ +#ifdef CONFIG_PAGE_SIZE_4KB +#define PGD_ORDER 1 +#define PUD_ORDER aieeee_attempt_to_allocate_pud +#define PMD_ORDER 0 +#define PTE_ORDER 0 +#endif +#ifdef CONFIG_PAGE_SIZE_8KB +#define PGD_ORDER 0 +#define PUD_ORDER aieeee_attempt_to_allocate_pud +#define PMD_ORDER 0 +#define PTE_ORDER 0 +#endif +#ifdef CONFIG_PAGE_SIZE_16KB +#define PGD_ORDER 0 +#define PUD_ORDER aieeee_attempt_to_allocate_pud +#define PMD_ORDER 0 +#define PTE_ORDER 0 +#endif +#ifdef CONFIG_PAGE_SIZE_64KB +#define PGD_ORDER 0 +#define PUD_ORDER aieeee_attempt_to_allocate_pud +#define PMD_ORDER 0 +#define PTE_ORDER 0 +#endif + +#define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t)) +#define PTRS_PER_PMD ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t)) +#define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) + +#if PGDIR_SIZE >= TASK_SIZE +#define USER_PTRS_PER_PGD (1) +#else +#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) +#endif +#define FIRST_USER_ADDRESS 0UL + +#define VMALLOC_START MAP_BASE +#define VMALLOC_END \ + (VMALLOC_START + PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE) +#if defined(CONFIG_MODULES) && defined(KBUILD_64BIT_SYM32) && \ + VMALLOC_START != CKSSEG +/* Load modules into 32bit-compatible segment. */ +#define MODULE_START CKSSEG +#define MODULE_END (FIXADDR_START-2*PAGE_SIZE) +extern pgd_t module_pg_dir[PTRS_PER_PGD]; +#endif + +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) +#define pmd_ERROR(e) \ + printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) + +extern pte_t invalid_pte_table[PTRS_PER_PTE]; +extern pte_t empty_bad_page_table[PTRS_PER_PTE]; +extern pmd_t invalid_pmd_table[PTRS_PER_PMD]; +extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD]; + +/* + * Empty pgd/pmd entries point to the invalid_pte_table. + */ +static inline int pmd_none(pmd_t pmd) +{ + return pmd_val(pmd) == (unsigned long) invalid_pte_table; +} + +#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) + +static inline int pmd_present(pmd_t pmd) +{ + return pmd_val(pmd) != (unsigned long) invalid_pte_table; +} + +static inline void pmd_clear(pmd_t *pmdp) +{ + pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); +} + +/* + * Empty pud entries point to the invalid_pmd_table. + */ +static inline int pud_none(pud_t pud) +{ + return pud_val(pud) == (unsigned long) invalid_pmd_table; +} + +static inline int pud_bad(pud_t pud) +{ + return pud_val(pud) & ~PAGE_MASK; +} + +static inline int pud_present(pud_t pud) +{ + return pud_val(pud) != (unsigned long) invalid_pmd_table; +} + +static inline void pud_clear(pud_t *pudp) +{ + pud_val(*pudp) = ((unsigned long) invalid_pmd_table); +} + +#define pte_page(x) pfn_to_page(pte_pfn(x)) + +#ifdef CONFIG_CPU_VR41XX +#define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) +#define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) +#else +#define pte_pfn(x) ((unsigned long)((x).pte >> PAGE_SHIFT)) +#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#endif + +#define __pgd_offset(address) pgd_index(address) +#define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) +#define __pmd_offset(address) pmd_index(address) + +/* to find an entry in a kernel page-table-directory */ +#ifdef MODULE_START +#define pgd_offset_k(address) \ + ((address) >= MODULE_START ? module_pg_dir : pgd_offset(&init_mm, 0UL)) +#else +#define pgd_offset_k(address) pgd_offset(&init_mm, 0UL) +#endif + +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) + +/* to find an entry in a page-table-directory */ +#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) + +static inline unsigned long pud_page_vaddr(pud_t pud) +{ + return pud_val(pud); +} +#define pud_phys(pud) virt_to_phys((void *)pud_val(pud)) +#define pud_page(pud) (pfn_to_page(pud_phys(pud) >> PAGE_SHIFT)) + +/* Find an entry in the second-level page table.. */ +static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) +{ + return (pmd_t *) pud_page_vaddr(*pud) + pmd_index(address); +} + +/* Find an entry in the third-level page table.. */ +#define __pte_offset(address) \ + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +#define pte_offset(dir, address) \ + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) +#define pte_offset_kernel(dir, address) \ + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) +#define pte_offset_map(dir, address) \ + ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) +#define pte_offset_map_nested(dir, address) \ + ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) +#define pte_unmap(pte) ((void)(pte)) +#define pte_unmap_nested(pte) ((void)(pte)) + +/* + * Initialize a new pgd / pmd table with invalid pointers. + */ +extern void pgd_init(unsigned long page); +extern void pmd_init(unsigned long page, unsigned long pagetable); + +/* + * Non-present pages: high 24 bits are offset, next 8 bits type, + * low 32 bits zero. + */ +static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) +{ pte_t pte; pte_val(pte) = (type << 32) | (offset << 40); return pte; } + +#define __swp_type(x) (((x).val >> 32) & 0xff) +#define __swp_offset(x) ((x).val >> 40) +#define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + +/* + * Bits 0, 4, 6, and 7 are taken. Let's leave bits 1, 2, 3, and 5 alone to + * make things easier, and only use the upper 56 bits for the page offset... + */ +#define PTE_FILE_MAX_BITS 56 + +#define pte_to_pgoff(_pte) ((_pte).pte >> 8) +#define pgoff_to_pte(off) ((pte_t) { ((off) << 8) | _PAGE_FILE }) + +#endif /* _ASM_PGTABLE_64_H */ diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h new file mode 100644 index 00000000000..51b34a48c84 --- /dev/null +++ b/arch/mips/include/asm/pgtable-bits.h @@ -0,0 +1,137 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 2002 by Ralf Baechle + * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. + * Copyright (C) 2002 Maciej W. Rozycki + */ +#ifndef _ASM_PGTABLE_BITS_H +#define _ASM_PGTABLE_BITS_H + + +/* + * Note that we shift the lower 32bits of each EntryLo[01] entry + * 6 bits to the left. That way we can convert the PFN into the + * physical address by a single 'and' operation and gain 6 additional + * bits for storing information which isn't present in a normal + * MIPS page table. + * + * Similar to the Alpha port, we need to keep track of the ref + * and mod bits in software. We have a software "yeah you can read + * from this page" bit, and a hardware one which actually lets the + * process read from the page. On the same token we have a software + * writable bit and the real hardware one which actually lets the + * process write to the page, this keeps a mod bit via the hardware + * dirty bit. + * + * Certain revisions of the R4000 and R5000 have a bug where if a + * certain sequence occurs in the last 3 instructions of an executable + * page, and the following page is not mapped, the cpu can do + * unpredictable things. The code (when it is written) to deal with + * this problem will be in the update_mmu_cache() code for the r4k. + */ +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) + +#define _PAGE_PRESENT (1<<6) /* implemented in software */ +#define _PAGE_READ (1<<7) /* implemented in software */ +#define _PAGE_WRITE (1<<8) /* implemented in software */ +#define _PAGE_ACCESSED (1<<9) /* implemented in software */ +#define _PAGE_MODIFIED (1<<10) /* implemented in software */ +#define _PAGE_FILE (1<<10) /* set:pagecache unset:swap */ + +#define _PAGE_R4KBUG (1<<0) /* workaround for r4k bug */ +#define _PAGE_GLOBAL (1<<0) +#define _PAGE_VALID (1<<1) +#define _PAGE_SILENT_READ (1<<1) /* synonym */ +#define _PAGE_DIRTY (1<<2) /* The MIPS dirty bit */ +#define _PAGE_SILENT_WRITE (1<<2) +#define _CACHE_SHIFT 3 +#define _CACHE_MASK (7<<3) + +#else + +#define _PAGE_PRESENT (1<<0) /* implemented in software */ +#define _PAGE_READ (1<<1) /* implemented in software */ +#define _PAGE_WRITE (1<<2) /* implemented in software */ +#define _PAGE_ACCESSED (1<<3) /* implemented in software */ +#define _PAGE_MODIFIED (1<<4) /* implemented in software */ +#define _PAGE_FILE (1<<4) /* set:pagecache unset:swap */ + +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + +#define _PAGE_GLOBAL (1<<8) +#define _PAGE_VALID (1<<9) +#define _PAGE_SILENT_READ (1<<9) /* synonym */ +#define _PAGE_DIRTY (1<<10) /* The MIPS dirty bit */ +#define _PAGE_SILENT_WRITE (1<<10) +#define _CACHE_UNCACHED (1<<11) +#define _CACHE_MASK (1<<11) + +#else + +#define _PAGE_R4KBUG (1<<5) /* workaround for r4k bug */ +#define _PAGE_GLOBAL (1<<6) +#define _PAGE_VALID (1<<7) +#define _PAGE_SILENT_READ (1<<7) /* synonym */ +#define _PAGE_DIRTY (1<<8) /* The MIPS dirty bit */ +#define _PAGE_SILENT_WRITE (1<<8) +#define _CACHE_SHIFT 9 +#define _CACHE_MASK (7<<9) + +#endif +#endif /* defined(CONFIG_64BIT_PHYS_ADDR && defined(CONFIG_CPU_MIPS32) */ + + +/* + * Cache attributes + */ +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + +#define _CACHE_CACHABLE_NONCOHERENT 0 + +#elif defined(CONFIG_CPU_SB1) + +/* No penalty for being coherent on the SB1, so just + use it for "noncoherent" spaces, too. Shouldn't hurt. */ + +#define _CACHE_UNCACHED (2<<_CACHE_SHIFT) +#define _CACHE_CACHABLE_COW (5<<_CACHE_SHIFT) +#define _CACHE_CACHABLE_NONCOHERENT (5<<_CACHE_SHIFT) +#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT) + +#elif defined(CONFIG_CPU_RM9000) + +#define _CACHE_WT (0<<_CACHE_SHIFT) +#define _CACHE_WTWA (1<<_CACHE_SHIFT) +#define _CACHE_UC_B (2<<_CACHE_SHIFT) +#define _CACHE_WB (3<<_CACHE_SHIFT) +#define _CACHE_CWBEA (4<<_CACHE_SHIFT) +#define _CACHE_CWB (5<<_CACHE_SHIFT) +#define _CACHE_UCNB (6<<_CACHE_SHIFT) +#define _CACHE_FPC (7<<_CACHE_SHIFT) + +#define _CACHE_UNCACHED _CACHE_UC_B +#define _CACHE_CACHABLE_NONCOHERENT _CACHE_WB + +#else + +#define _CACHE_CACHABLE_NO_WA (0<<_CACHE_SHIFT) /* R4600 only */ +#define _CACHE_CACHABLE_WA (1<<_CACHE_SHIFT) /* R4600 only */ +#define _CACHE_UNCACHED (2<<_CACHE_SHIFT) /* R4[0246]00 */ +#define _CACHE_CACHABLE_NONCOHERENT (3<<_CACHE_SHIFT) /* R4[0246]00 */ +#define _CACHE_CACHABLE_CE (4<<_CACHE_SHIFT) /* R4[04]00MC only */ +#define _CACHE_CACHABLE_COW (5<<_CACHE_SHIFT) /* R4[04]00MC only */ +#define _CACHE_CACHABLE_COHERENT (5<<_CACHE_SHIFT) /* MIPS32R2 CMP */ +#define _CACHE_CACHABLE_CUW (6<<_CACHE_SHIFT) /* R4[04]00MC only */ +#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT) /* R10000 only */ + +#endif + +#define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED) +#define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED) + +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK) + +#endif /* _ASM_PGTABLE_BITS_H */ diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h new file mode 100644 index 00000000000..6a0edf72ffb --- /dev/null +++ b/arch/mips/include/asm/pgtable.h @@ -0,0 +1,383 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 Ralf Baechle + */ +#ifndef _ASM_PGTABLE_H +#define _ASM_PGTABLE_H + +#ifdef CONFIG_32BIT +#include +#endif +#ifdef CONFIG_64BIT +#include +#endif + +#include +#include + +struct mm_struct; +struct vm_area_struct; + +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _page_cachable_default) +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ + _page_cachable_default) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ + _page_cachable_default) +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ + _PAGE_GLOBAL | _page_cachable_default) +#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _page_cachable_default) +#define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \ + __WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED) + +/* + * MIPS can't do page protection for execute, and considers that the same like + * read. Also, write permissions imply read permissions. This is the closest + * we can get by reasonable means.. + */ + +/* + * Dummy values to fill the table in mmap.c + * The real values will be generated at runtime + */ +#define __P000 __pgprot(0) +#define __P001 __pgprot(0) +#define __P010 __pgprot(0) +#define __P011 __pgprot(0) +#define __P100 __pgprot(0) +#define __P101 __pgprot(0) +#define __P110 __pgprot(0) +#define __P111 __pgprot(0) + +#define __S000 __pgprot(0) +#define __S001 __pgprot(0) +#define __S010 __pgprot(0) +#define __S011 __pgprot(0) +#define __S100 __pgprot(0) +#define __S101 __pgprot(0) +#define __S110 __pgprot(0) +#define __S111 __pgprot(0) + +extern unsigned long _page_cachable_default; + +/* + * ZERO_PAGE is a global shared page that is always zero; used + * for zero-mapped memory areas etc.. + */ + +extern unsigned long empty_zero_page; +extern unsigned long zero_page_mask; + +#define ZERO_PAGE(vaddr) \ + (virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))) + +extern void paging_init(void); + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +#define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) +#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) +#define pmd_page_vaddr(pmd) pmd_val(pmd) + +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) + +#define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) +#define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) + +static inline void set_pte(pte_t *ptep, pte_t pte) +{ + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; + //printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low); + + if (pte.pte_low & _PAGE_GLOBAL) { + pte_t *buddy = ptep_buddy(ptep); + /* + * Make sure the buddy is global too (if it's !none, + * it better already be global) + */ + if (pte_none(*buddy)) { + buddy->pte_low |= _PAGE_GLOBAL; + buddy->pte_high |= _PAGE_GLOBAL; + } + } +} +#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) + +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + pte_t null = __pte(0); + + /* Preserve global status for the pair */ + if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) + null.pte_low = null.pte_high = _PAGE_GLOBAL; + + set_pte_at(mm, addr, ptep, null); +} +#else + +#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) +#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) + +/* + * Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +static inline void set_pte(pte_t *ptep, pte_t pteval) +{ + *ptep = pteval; +#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX) + if (pte_val(pteval) & _PAGE_GLOBAL) { + pte_t *buddy = ptep_buddy(ptep); + /* + * Make sure the buddy is global too (if it's !none, + * it better already be global) + */ + if (pte_none(*buddy)) + pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; + } +#endif +} +#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) + +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ +#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX) + /* Preserve global status for the pair */ + if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL) + set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL)); + else +#endif + set_pte_at(mm, addr, ptep, __pte(0)); +} +#endif + +/* + * (pmds are folded into puds so this doesn't get actually called, + * but the define is needed for a generic inline function.) + */ +#define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while(0) + +#ifdef CONFIG_64BIT +/* + * (puds are folded into pgds so this doesn't get actually called, + * but the define is needed for a generic inline function.) + */ +#define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while(0) +#endif + +#define PGD_T_LOG2 (__builtin_ffs(sizeof(pgd_t)) - 1) +#define PMD_T_LOG2 (__builtin_ffs(sizeof(pmd_t)) - 1) +#define PTE_T_LOG2 (__builtin_ffs(sizeof(pte_t)) - 1) + +/* + * We used to declare this array with size but gcc 3.3 and older are not able + * to find that this expression is a constant, so the size is dropped. + */ +extern pgd_t swapper_pg_dir[]; + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) +static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; } +static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; } +static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } +static inline int pte_file(pte_t pte) { return pte.pte_low & _PAGE_FILE; } + +static inline pte_t pte_wrprotect(pte_t pte) +{ + pte.pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); + pte.pte_high &= ~_PAGE_SILENT_WRITE; + return pte; +} + +static inline pte_t pte_mkclean(pte_t pte) +{ + pte.pte_low &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); + pte.pte_high &= ~_PAGE_SILENT_WRITE; + return pte; +} + +static inline pte_t pte_mkold(pte_t pte) +{ + pte.pte_low &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); + pte.pte_high &= ~_PAGE_SILENT_READ; + return pte; +} + +static inline pte_t pte_mkwrite(pte_t pte) +{ + pte.pte_low |= _PAGE_WRITE; + if (pte.pte_low & _PAGE_MODIFIED) { + pte.pte_low |= _PAGE_SILENT_WRITE; + pte.pte_high |= _PAGE_SILENT_WRITE; + } + return pte; +} + +static inline pte_t pte_mkdirty(pte_t pte) +{ + pte.pte_low |= _PAGE_MODIFIED; + if (pte.pte_low & _PAGE_WRITE) { + pte.pte_low |= _PAGE_SILENT_WRITE; + pte.pte_high |= _PAGE_SILENT_WRITE; + } + return pte; +} + +static inline pte_t pte_mkyoung(pte_t pte) +{ + pte.pte_low |= _PAGE_ACCESSED; + if (pte.pte_low & _PAGE_READ) { + pte.pte_low |= _PAGE_SILENT_READ; + pte.pte_high |= _PAGE_SILENT_READ; + } + return pte; +} +#else +static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } +static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } +static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } + +static inline pte_t pte_wrprotect(pte_t pte) +{ + pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); + return pte; +} + +static inline pte_t pte_mkclean(pte_t pte) +{ + pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); + return pte; +} + +static inline pte_t pte_mkold(pte_t pte) +{ + pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); + return pte; +} + +static inline pte_t pte_mkwrite(pte_t pte) +{ + pte_val(pte) |= _PAGE_WRITE; + if (pte_val(pte) & _PAGE_MODIFIED) + pte_val(pte) |= _PAGE_SILENT_WRITE; + return pte; +} + +static inline pte_t pte_mkdirty(pte_t pte) +{ + pte_val(pte) |= _PAGE_MODIFIED; + if (pte_val(pte) & _PAGE_WRITE) + pte_val(pte) |= _PAGE_SILENT_WRITE; + return pte; +} + +static inline pte_t pte_mkyoung(pte_t pte) +{ + pte_val(pte) |= _PAGE_ACCESSED; + if (pte_val(pte) & _PAGE_READ) + pte_val(pte) |= _PAGE_SILENT_READ; + return pte; +} +#endif +static inline int pte_special(pte_t pte) { return 0; } +static inline pte_t pte_mkspecial(pte_t pte) { return pte; } + +/* + * Macro to make mark a page protection value as "uncacheable". Note + * that "protection" is really a misnomer here as the protection value + * contains the memory attribute bits, dirty bits, and various other + * bits as well. + */ +#define pgprot_noncached pgprot_noncached + +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED; + + return __pgprot(prot); +} + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) + +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte.pte_low &= _PAGE_CHG_MASK; + pte.pte_high &= ~0x3f; + pte.pte_low |= pgprot_val(newprot); + pte.pte_high |= pgprot_val(newprot) & 0x3f; + return pte; +} +#else +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); +} +#endif + + +extern void __update_tlb(struct vm_area_struct *vma, unsigned long address, + pte_t pte); +extern void __update_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte); + +static inline void update_mmu_cache(struct vm_area_struct *vma, + unsigned long address, pte_t pte) +{ + __update_tlb(vma, address, pte); + __update_cache(vma, address, pte); +} + +#define kern_addr_valid(addr) (1) + +#ifdef CONFIG_64BIT_PHYS_ADDR +extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot); + +static inline int io_remap_pfn_range(struct vm_area_struct *vma, + unsigned long vaddr, + unsigned long pfn, + unsigned long size, + pgprot_t prot) +{ + phys_t phys_addr_high = fixup_bigphys_addr(pfn << PAGE_SHIFT, size); + return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot); +} +#else +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) +#endif + +#include + +/* + * We provide our own get_unmapped area to cope with the virtual aliasing + * constraints placed on us by the cache architecture. + */ +#define HAVE_ARCH_UNMAPPED_AREA + +/* + * No page table caches to initialise + */ +#define pgtable_cache_init() do { } while (0) + +#endif /* _ASM_PGTABLE_H */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/gpio.h b/arch/mips/include/asm/pmc-sierra/msp71xx/gpio.h new file mode 100644 index 00000000000..ebdbab973e4 --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/gpio.h @@ -0,0 +1,46 @@ +/* + * include/asm-mips/pmc-sierra/msp71xx/gpio.h + * + * 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. + * + * @author Patrick Glass + */ + +#ifndef __PMC_MSP71XX_GPIO_H +#define __PMC_MSP71XX_GPIO_H + +/* Max number of gpio's is 28 on chip plus 3 banks of I2C IO Expanders */ +#define ARCH_NR_GPIOS (28 + (3 * 8)) + +/* new generic GPIO API - see Documentation/gpio.txt */ +#include + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep + +/* Setup calls for the gpio and gpio extended */ +extern void msp71xx_init_gpio(void); +extern void msp71xx_init_gpio_extended(void); +extern int msp71xx_set_output_drive(unsigned gpio, int value); + +/* Custom output drive functionss */ +static inline int gpio_set_output_drive(unsigned gpio, int value) +{ + return msp71xx_set_output_drive(gpio, value); +} + +/* IRQ's are not supported for gpio lines */ +static inline int gpio_to_irq(unsigned gpio) +{ + return -EINVAL; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return -EINVAL; +} + +#endif /* __PMC_MSP71XX_GPIO_H */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_cic_int.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_cic_int.h new file mode 100644 index 00000000000..c84bcf9570b --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_cic_int.h @@ -0,0 +1,151 @@ +/* + * Defines for the MSP interrupt controller. + * + * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved. + * Author: Carsten Langgaard, carstenl@mips.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 _MSP_CIC_INT_H +#define _MSP_CIC_INT_H + +/* + * The PMC-Sierra CIC interrupts are all centrally managed by the + * CIC sub-system. + * We attempt to keep the interrupt numbers as consistent as possible + * across all of the MSP devices, but some differences will creep in ... + * The interrupts which are directly forwarded to the MIPS core interrupts + * are assigned interrupts in the range 0-7, interrupts cascaded through + * the CIC are assigned interrupts 8-39. The cascade occurs on C_IRQ4 + * (MSP_INT_CIC). Currently we don't really distinguish between VPE1 + * and VPE0 (or thread contexts for that matter). Will have to fix. + * The PER interrupts are assigned interrupts in the range 40-71. +*/ + + +/* + * IRQs directly forwarded to the CPU + */ +#define MSP_MIPS_INTBASE 0 +#define MSP_INT_SW0 0 /* IRQ for swint0, C_SW0 */ +#define MSP_INT_SW1 1 /* IRQ for swint1, C_SW1 */ +#define MSP_INT_MAC0 2 /* IRQ for MAC 0, C_IRQ0 */ +#define MSP_INT_MAC1 3 /* IRQ for MAC 1, C_IRQ1 */ +#define MSP_INT_USB 4 /* IRQ for USB, C_IRQ2 */ +#define MSP_INT_SAR 5 /* IRQ for ADSL2+ SAR, C_IRQ3 */ +#define MSP_INT_CIC 6 /* IRQ for CIC block, C_IRQ4 */ +#define MSP_INT_SEC 7 /* IRQ for Sec engine, C_IRQ5 */ + +/* + * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4) + * These defines should be tied to the register definitions for the CIC + * interrupt routine. For now, just use hard-coded values. + */ +#define MSP_CIC_INTBASE (MSP_MIPS_INTBASE + 8) +#define MSP_INT_EXT0 (MSP_CIC_INTBASE + 0) + /* External interrupt 0 */ +#define MSP_INT_EXT1 (MSP_CIC_INTBASE + 1) + /* External interrupt 1 */ +#define MSP_INT_EXT2 (MSP_CIC_INTBASE + 2) + /* External interrupt 2 */ +#define MSP_INT_EXT3 (MSP_CIC_INTBASE + 3) + /* External interrupt 3 */ +#define MSP_INT_CPUIF (MSP_CIC_INTBASE + 4) + /* CPU interface interrupt */ +#define MSP_INT_EXT4 (MSP_CIC_INTBASE + 5) + /* External interrupt 4 */ +#define MSP_INT_CIC_USB (MSP_CIC_INTBASE + 6) + /* Cascaded IRQ for USB */ +#define MSP_INT_MBOX (MSP_CIC_INTBASE + 7) + /* Sec engine mailbox IRQ */ +#define MSP_INT_EXT5 (MSP_CIC_INTBASE + 8) + /* External interrupt 5 */ +#define MSP_INT_TDM (MSP_CIC_INTBASE + 9) + /* TDM interrupt */ +#define MSP_INT_CIC_MAC0 (MSP_CIC_INTBASE + 10) + /* Cascaded IRQ for MAC 0 */ +#define MSP_INT_CIC_MAC1 (MSP_CIC_INTBASE + 11) + /* Cascaded IRQ for MAC 1 */ +#define MSP_INT_CIC_SEC (MSP_CIC_INTBASE + 12) + /* Cascaded IRQ for sec engine */ +#define MSP_INT_PER (MSP_CIC_INTBASE + 13) + /* Peripheral interrupt */ +#define MSP_INT_TIMER0 (MSP_CIC_INTBASE + 14) + /* SLP timer 0 */ +#define MSP_INT_TIMER1 (MSP_CIC_INTBASE + 15) + /* SLP timer 1 */ +#define MSP_INT_TIMER2 (MSP_CIC_INTBASE + 16) + /* SLP timer 2 */ +#define MSP_INT_VPE0_TIMER (MSP_CIC_INTBASE + 17) + /* VPE0 MIPS timer */ +#define MSP_INT_BLKCP (MSP_CIC_INTBASE + 18) + /* Block Copy */ +#define MSP_INT_UART0 (MSP_CIC_INTBASE + 19) + /* UART 0 */ +#define MSP_INT_PCI (MSP_CIC_INTBASE + 20) + /* PCI subsystem */ +#define MSP_INT_EXT6 (MSP_CIC_INTBASE + 21) + /* External interrupt 5 */ +#define MSP_INT_PCI_MSI (MSP_CIC_INTBASE + 22) + /* PCI Message Signal */ +#define MSP_INT_CIC_SAR (MSP_CIC_INTBASE + 23) + /* Cascaded ADSL2+ SAR IRQ */ +#define MSP_INT_DSL (MSP_CIC_INTBASE + 24) + /* ADSL2+ IRQ */ +#define MSP_INT_CIC_ERR (MSP_CIC_INTBASE + 25) + /* SLP error condition */ +#define MSP_INT_VPE1_TIMER (MSP_CIC_INTBASE + 26) + /* VPE1 MIPS timer */ +#define MSP_INT_VPE0_PC (MSP_CIC_INTBASE + 27) + /* VPE0 Performance counter */ +#define MSP_INT_VPE1_PC (MSP_CIC_INTBASE + 28) + /* VPE1 Performance counter */ +#define MSP_INT_EXT7 (MSP_CIC_INTBASE + 29) + /* External interrupt 5 */ +#define MSP_INT_VPE0_SW (MSP_CIC_INTBASE + 30) + /* VPE0 Software interrupt */ +#define MSP_INT_VPE1_SW (MSP_CIC_INTBASE + 31) + /* VPE0 Software interrupt */ + +/* + * IRQs cascaded on CIC PER interrupt (MSP_INT_PER) + */ +#define MSP_PER_INTBASE (MSP_CIC_INTBASE + 32) +/* Reserved 0-1 */ +#define MSP_INT_UART1 (MSP_PER_INTBASE + 2) + /* UART 1 */ +/* Reserved 3-5 */ +#define MSP_INT_2WIRE (MSP_PER_INTBASE + 6) + /* 2-wire */ +#define MSP_INT_TM0 (MSP_PER_INTBASE + 7) + /* Peripheral timer block out 0 */ +#define MSP_INT_TM1 (MSP_PER_INTBASE + 8) + /* Peripheral timer block out 1 */ +/* Reserved 9 */ +#define MSP_INT_SPRX (MSP_PER_INTBASE + 10) + /* SPI RX complete */ +#define MSP_INT_SPTX (MSP_PER_INTBASE + 11) + /* SPI TX complete */ +#define MSP_INT_GPIO (MSP_PER_INTBASE + 12) + /* GPIO */ +#define MSP_INT_PER_ERR (MSP_PER_INTBASE + 13) + /* Peripheral error */ +/* Reserved 14-31 */ + +#endif /* !_MSP_CIC_INT_H */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_int.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_int.h new file mode 100644 index 00000000000..1d9f0547482 --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_int.h @@ -0,0 +1,43 @@ +/* + * Defines for the MSP interrupt handlers. + * + * Copyright (C) 2005, PMC-Sierra, Inc. All rights reserved. + * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 _MSP_INT_H +#define _MSP_INT_H + +/* + * The PMC-Sierra MSP product line has at least two different interrupt + * controllers, the SLP register based scheme and the CIC interrupt + * controller block mechanism. This file distinguishes between them + * so that devices see a uniform interface. + */ + +#if defined(CONFIG_IRQ_MSP_SLP) + #include "msp_slp_int.h" +#elif defined(CONFIG_IRQ_MSP_CIC) + #include "msp_cic_int.h" +#else + #error "What sort of interrupt controller does *your* MSP have?" +#endif + +#endif /* !_MSP_INT_H */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_pci.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_pci.h new file mode 100644 index 00000000000..41560690361 --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_pci.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2000-2006 PMC-Sierra INC. + * + * 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., 675 Mass Ave, Cambridge, MA + * 02139, USA. + * + * PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS + * SOFTWARE. + */ + +#ifndef _MSP_PCI_H_ +#define _MSP_PCI_H_ + +#define MSP_HAS_PCI(ID) (((u32)(ID) <= 0x4236) && ((u32)(ID) >= 0x4220)) + +/* + * It is convenient to program the OATRAN register so that + * Athena virtual address space and PCI address space are + * the same. This is not a requirement, just a convenience. + * + * The only hard restrictions on the value of OATRAN is that + * OATRAN must not be programmed to allow translated memory + * addresses to fall within the lowest 512MB of + * PCI address space. This region is hardcoded + * for use as Athena PCI Host Controller target + * access memory space to the Athena's SDRAM. + * + * Note that OATRAN applies only to memory accesses, not + * to I/O accesses. + * + * To program OATRAN to make Athena virtual address space + * and PCI address space have the same values, OATRAN + * is to be programmed to 0xB8000000. The top seven + * bits of the value mimic the seven bits clipped off + * by the PCI Host controller. + * + * With OATRAN at the said value, when the CPU does + * an access to its virtual address at, say 0xB900_5000, + * the address appearing on the PCI bus will be + * 0xB900_5000. + * - Michael Penner + */ +#define MSP_PCI_OATRAN 0xB8000000UL + +#define MSP_PCI_SPACE_BASE (MSP_PCI_OATRAN + 0x1002000UL) +#define MSP_PCI_SPACE_SIZE (0x3000000UL - 0x2000) +#define MSP_PCI_SPACE_END \ + (MSP_PCI_SPACE_BASE + MSP_PCI_SPACE_SIZE - 1) +#define MSP_PCI_IOSPACE_BASE (MSP_PCI_OATRAN + 0x1001000UL) +#define MSP_PCI_IOSPACE_SIZE 0x1000 +#define MSP_PCI_IOSPACE_END \ + (MSP_PCI_IOSPACE_BASE + MSP_PCI_IOSPACE_SIZE - 1) + +/* IRQ for PCI status interrupts */ +#define PCI_STAT_IRQ 20 + +#define QFLUSH_REG_1 0xB7F40000 + +typedef volatile unsigned int pcireg; +typedef void * volatile ppcireg; + +struct pci_block_copy +{ + pcireg unused1; /* +0x00 */ + pcireg unused2; /* +0x04 */ + ppcireg unused3; /* +0x08 */ + ppcireg unused4; /* +0x0C */ + pcireg unused5; /* +0x10 */ + pcireg unused6; /* +0x14 */ + pcireg unused7; /* +0x18 */ + ppcireg unused8; /* +0x1C */ + ppcireg unused9; /* +0x20 */ + pcireg unusedA; /* +0x24 */ + ppcireg unusedB; /* +0x28 */ + ppcireg unusedC; /* +0x2C */ +}; + +enum +{ + config_device_vendor, /* 0 */ + config_status_command, /* 1 */ + config_class_revision, /* 2 */ + config_BIST_header_latency_cache, /* 3 */ + config_BAR0, /* 4 */ + config_BAR1, /* 5 */ + config_BAR2, /* 6 */ + config_not_used7, /* 7 */ + config_not_used8, /* 8 */ + config_not_used9, /* 9 */ + config_CIS, /* 10 */ + config_subsystem, /* 11 */ + config_not_used12, /* 12 */ + config_capabilities, /* 13 */ + config_not_used14, /* 14 */ + config_lat_grant_irq, /* 15 */ + config_message_control,/* 16 */ + config_message_addr, /* 17 */ + config_message_data, /* 18 */ + config_VPD_addr, /* 19 */ + config_VPD_data, /* 20 */ + config_maxregs /* 21 - number of registers */ +}; + +struct msp_pci_regs +{ + pcireg hop_unused_00; /* +0x00 */ + pcireg hop_unused_04; /* +0x04 */ + pcireg hop_unused_08; /* +0x08 */ + pcireg hop_unused_0C; /* +0x0C */ + pcireg hop_unused_10; /* +0x10 */ + pcireg hop_unused_14; /* +0x14 */ + pcireg hop_unused_18; /* +0x18 */ + pcireg hop_unused_1C; /* +0x1C */ + pcireg hop_unused_20; /* +0x20 */ + pcireg hop_unused_24; /* +0x24 */ + pcireg hop_unused_28; /* +0x28 */ + pcireg hop_unused_2C; /* +0x2C */ + pcireg hop_unused_30; /* +0x30 */ + pcireg hop_unused_34; /* +0x34 */ + pcireg if_control; /* +0x38 */ + pcireg oatran; /* +0x3C */ + pcireg reset_ctl; /* +0x40 */ + pcireg config_addr; /* +0x44 */ + pcireg hop_unused_48; /* +0x48 */ + pcireg msg_signaled_int_status; /* +0x4C */ + pcireg msg_signaled_int_mask; /* +0x50 */ + pcireg if_status; /* +0x54 */ + pcireg if_mask; /* +0x58 */ + pcireg hop_unused_5C; /* +0x5C */ + pcireg hop_unused_60; /* +0x60 */ + pcireg hop_unused_64; /* +0x64 */ + pcireg hop_unused_68; /* +0x68 */ + pcireg hop_unused_6C; /* +0x6C */ + pcireg hop_unused_70; /* +0x70 */ + + struct pci_block_copy pci_bc[2] __attribute__((aligned(64))); + + pcireg error_hdr1; /* +0xE0 */ + pcireg error_hdr2; /* +0xE4 */ + + pcireg config[config_maxregs] __attribute__((aligned(256))); + +}; + +#define BPCI_CFGADDR_BUSNUM_SHF 16 +#define BPCI_CFGADDR_FUNCTNUM_SHF 8 +#define BPCI_CFGADDR_REGNUM_SHF 2 +#define BPCI_CFGADDR_ENABLE (1<<31) + +#define BPCI_IFCONTROL_RTO (1<<20) /* Retry timeout */ +#define BPCI_IFCONTROL_HCE (1<<16) /* Host configuration enable */ +#define BPCI_IFCONTROL_CTO_SHF 12 /* Shift count for CTO bits */ +#define BPCI_IFCONTROL_SE (1<<5) /* Enable exceptions on errors */ +#define BPCI_IFCONTROL_BIST (1<<4) /* Use BIST in per. mode */ +#define BPCI_IFCONTROL_CAP (1<<3) /* Enable capabilities */ +#define BPCI_IFCONTROL_MMC_SHF 0 /* Shift count for MMC bits */ + +#define BPCI_IFSTATUS_MGT (1<<8) /* Master Grant timeout */ +#define BPCI_IFSTATUS_MTT (1<<9) /* Master TRDY timeout */ +#define BPCI_IFSTATUS_MRT (1<<10) /* Master retry timeout */ +#define BPCI_IFSTATUS_BC0F (1<<13) /* Block copy 0 fault */ +#define BPCI_IFSTATUS_BC1F (1<<14) /* Block copy 1 fault */ +#define BPCI_IFSTATUS_PCIU (1<<15) /* PCI unable to respond */ +#define BPCI_IFSTATUS_BSIZ (1<<16) /* PCI access with illegal size */ +#define BPCI_IFSTATUS_BADD (1<<17) /* PCI access with illegal addr */ +#define BPCI_IFSTATUS_RTO (1<<18) /* Retry time out */ +#define BPCI_IFSTATUS_SER (1<<19) /* System error */ +#define BPCI_IFSTATUS_PER (1<<20) /* Parity error */ +#define BPCI_IFSTATUS_LCA (1<<21) /* Local CPU abort */ +#define BPCI_IFSTATUS_MEM (1<<22) /* Memory prot. violation */ +#define BPCI_IFSTATUS_ARB (1<<23) /* Arbiter timed out */ +#define BPCI_IFSTATUS_STA (1<<27) /* Signaled target abort */ +#define BPCI_IFSTATUS_TA (1<<28) /* Target abort */ +#define BPCI_IFSTATUS_MA (1<<29) /* Master abort */ +#define BPCI_IFSTATUS_PEI (1<<30) /* Parity error as initiator */ +#define BPCI_IFSTATUS_PET (1<<31) /* Parity error as target */ + +#define BPCI_RESETCTL_PR (1<<0) /* True if reset asserted */ +#define BPCI_RESETCTL_RT (1<<4) /* Release time */ +#define BPCI_RESETCTL_CT (1<<8) /* Config time */ +#define BPCI_RESETCTL_PE (1<<12) /* PCI enabled */ +#define BPCI_RESETCTL_HM (1<<13) /* PCI host mode */ +#define BPCI_RESETCTL_RI (1<<14) /* PCI reset in */ + +extern struct msp_pci_regs msp_pci_regs + __attribute__((section(".register"))); +extern unsigned long msp_pci_config_space + __attribute__((section(".register"))); + +#endif /* !_MSP_PCI_H_ */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h new file mode 100644 index 00000000000..14ca7dc382a --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h @@ -0,0 +1,176 @@ +/* + * MIPS boards bootprom interface for the Linux kernel. + * + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * Author: Carsten Langgaard, carstenl@mips.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_MSP_PROM_H +#define _ASM_MSP_PROM_H + +#include + +#define DEVICEID "deviceid" +#define FEATURES "features" +#define PROM_ENV "prom_env" +#define PROM_ENV_FILE "/proc/"PROM_ENV +#define PROM_ENV_SIZE 256 + +#define CPU_DEVID_FAMILY 0x0000ff00 +#define CPU_DEVID_REVISION 0x000000ff + +#define FPGA_IS_POLO(revision) \ + (((revision >= 0xb0) && (revision < 0xd0))) +#define FPGA_IS_5000(revision) \ + ((revision >= 0x80) && (revision <= 0x90)) +#define FPGA_IS_ZEUS(revision) ((revision < 0x7f)) +#define FPGA_IS_DUET(revision) \ + (((revision >= 0xa0) && (revision < 0xb0))) +#define FPGA_IS_MSP4200(revision) ((revision >= 0xd0)) +#define FPGA_IS_MSP7100(revision) ((revision >= 0xd0)) + +#define MACHINE_TYPE_POLO "POLO" +#define MACHINE_TYPE_DUET "DUET" +#define MACHINE_TYPE_ZEUS "ZEUS" +#define MACHINE_TYPE_MSP2000REVB "MSP2000REVB" +#define MACHINE_TYPE_MSP5000 "MSP5000" +#define MACHINE_TYPE_MSP4200 "MSP4200" +#define MACHINE_TYPE_MSP7120 "MSP7120" +#define MACHINE_TYPE_MSP7130 "MSP7130" +#define MACHINE_TYPE_OTHER "OTHER" + +#define MACHINE_TYPE_POLO_FPGA "POLO-FPGA" +#define MACHINE_TYPE_DUET_FPGA "DUET-FPGA" +#define MACHINE_TYPE_ZEUS_FPGA "ZEUS_FPGA" +#define MACHINE_TYPE_MSP2000REVB_FPGA "MSP2000REVB-FPGA" +#define MACHINE_TYPE_MSP5000_FPGA "MSP5000-FPGA" +#define MACHINE_TYPE_MSP4200_FPGA "MSP4200-FPGA" +#define MACHINE_TYPE_MSP7100_FPGA "MSP7100-FPGA" +#define MACHINE_TYPE_OTHER_FPGA "OTHER-FPGA" + +/* Device Family definitions */ +#define FAMILY_FPGA 0x0000 +#define FAMILY_ZEUS 0x1000 +#define FAMILY_POLO 0x2000 +#define FAMILY_DUET 0x4000 +#define FAMILY_TRIAD 0x5000 +#define FAMILY_MSP4200 0x4200 +#define FAMILY_MSP4200_FPGA 0x4f00 +#define FAMILY_MSP7100 0x7100 +#define FAMILY_MSP7100_FPGA 0x7f00 + +/* Device Type definitions */ +#define TYPE_MSP7120 0x7120 +#define TYPE_MSP7130 0x7130 + +#define ENET_KEY 'E' +#define ENETTXD_KEY 'e' +#define PCI_KEY 'P' +#define PCIMUX_KEY 'p' +#define SEC_KEY 'S' +#define SPAD_KEY 'D' +#define TDM_KEY 'T' +#define ZSP_KEY 'Z' + +#define FEATURE_NOEXIST '-' +#define FEATURE_EXIST '+' + +#define ENET_MII 'M' +#define ENET_RMII 'R' + +#define ENETTXD_FALLING 'F' +#define ENETTXD_RISING 'R' + +#define PCI_HOST 'H' +#define PCI_PERIPHERAL 'P' + +#define PCIMUX_FULL 'F' +#define PCIMUX_SINGLE 'S' + +#define SEC_DUET 'D' +#define SEC_POLO 'P' +#define SEC_SLOW 'S' +#define SEC_TRIAD 'T' + +#define SPAD_POLO 'P' + +#define TDM_DUET 'D' /* DUET TDMs might exist */ +#define TDM_POLO 'P' /* POLO TDMs might exist */ +#define TDM_TRIAD 'T' /* TRIAD TDMs might exist */ + +#define ZSP_DUET 'D' /* one DUET zsp engine */ +#define ZSP_TRIAD 'T' /* two TRIAD zsp engines */ + +extern char *prom_getcmdline(void); +extern char *prom_getenv(char *name); +extern void prom_init_cmdline(void); +extern void prom_meminit(void); +extern void prom_fixup_mem_map(unsigned long start_mem, + unsigned long end_mem); + +#ifdef CONFIG_MTD_PMC_MSP_RAMROOT +extern bool get_ramroot(void **start, unsigned long *size); +#endif + +extern int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr); +extern unsigned long get_deviceid(void); +extern char identify_enet(unsigned long interface_num); +extern char identify_enetTxD(unsigned long interface_num); +extern char identify_pci(void); +extern char identify_sec(void); +extern char identify_spad(void); +extern char identify_sec(void); +extern char identify_tdm(void); +extern char identify_zsp(void); +extern unsigned long identify_family(void); +extern unsigned long identify_revision(void); + +/* + * The following macro calls prom_printf and puts the format string + * into an init section so it can be reclaimed. + */ +#define ppfinit(f, x...) \ + do { \ + static char _f[] __initdata = KERN_INFO f; \ + printk(_f, ## x); \ + } while (0) + +/* Memory descriptor management. */ +#define PROM_MAX_PMEMBLOCKS 7 /* 6 used */ + +enum yamon_memtypes { + yamon_dontuse, + yamon_prom, + yamon_free, +}; + +struct prom_pmemblock { + unsigned long base; /* Within KSEG0. */ + unsigned int size; /* In bytes. */ + unsigned int type; /* free or prom memory */ +}; + +extern int prom_argc; +extern char **prom_argv; +extern char **prom_envp; +extern int *prom_vec; +extern struct prom_pmemblock *prom_getmdesc(void); + +#endif /* !_ASM_MSP_PROM_H */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h new file mode 100644 index 00000000000..60a5a38dd5b --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h @@ -0,0 +1,236 @@ +/* + * SMP/VPE-safe functions to access "registers" (see note). + * + * NOTES: +* - These macros use ll/sc instructions, so it is your responsibility to + * ensure these are available on your platform before including this file. + * - The MIPS32 spec states that ll/sc results are undefined for uncached + * accesses. This means they can't be used on HW registers accessed + * through kseg1. Code which requires these macros for this purpose must + * front-end the registers with cached memory "registers" and have a single + * thread update the actual HW registers. + * - A maximum of 2k of code can be inserted between ll and sc. Every + * memory accesses between the instructions will increase the chance of + * sc failing and having to loop. + * - When using custom_read_reg32/custom_write_reg32 only perform the + * necessary logical operations on the register value in between these + * two calls. All other logic should be performed before the first call. + * - There is a bug on the R10000 chips which has a workaround. If you + * are affected by this bug, make sure to define the symbol 'R10000_LLSC_WAR' + * to be non-zero. If you are using this header from within linux, you may + * include before including this file to have this defined + * appropriately for you. + * + * Copyright 2005-2007 PMC-Sierra, Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_REGOPS_H__ +#define __ASM_REGOPS_H__ + +#include + +#include + +#ifndef R10000_LLSC_WAR +#define R10000_LLSC_WAR 0 +#endif + +#if R10000_LLSC_WAR == 1 +#define __beqz "beqzl " +#else +#define __beqz "beqz " +#endif + +#ifndef _LINUX_TYPES_H +typedef unsigned int u32; +#endif + +/* + * Sets all the masked bits to the corresponding value bits + */ +static inline void set_value_reg32(volatile u32 *const addr, + u32 const mask, + u32 const value) +{ + u32 temp; + + __asm__ __volatile__( + " .set push \n" + " .set mips3 \n" + "1: ll %0, %1 # set_value_reg32 \n" + " and %0, %2 \n" + " or %0, %3 \n" + " sc %0, %1 \n" + " "__beqz"%0, 1b \n" + " nop \n" + " .set pop \n" + : "=&r" (temp), "=m" (*addr) + : "ir" (~mask), "ir" (value), "m" (*addr)); +} + +/* + * Sets all the masked bits to '1' + */ +static inline void set_reg32(volatile u32 *const addr, + u32 const mask) +{ + u32 temp; + + __asm__ __volatile__( + " .set push \n" + " .set mips3 \n" + "1: ll %0, %1 # set_reg32 \n" + " or %0, %2 \n" + " sc %0, %1 \n" + " "__beqz"%0, 1b \n" + " nop \n" + " .set pop \n" + : "=&r" (temp), "=m" (*addr) + : "ir" (mask), "m" (*addr)); +} + +/* + * Sets all the masked bits to '0' + */ +static inline void clear_reg32(volatile u32 *const addr, + u32 const mask) +{ + u32 temp; + + __asm__ __volatile__( + " .set push \n" + " .set mips3 \n" + "1: ll %0, %1 # clear_reg32 \n" + " and %0, %2 \n" + " sc %0, %1 \n" + " "__beqz"%0, 1b \n" + " nop \n" + " .set pop \n" + : "=&r" (temp), "=m" (*addr) + : "ir" (~mask), "m" (*addr)); +} + +/* + * Toggles all masked bits from '0' to '1' and '1' to '0' + */ +static inline void toggle_reg32(volatile u32 *const addr, + u32 const mask) +{ + u32 temp; + + __asm__ __volatile__( + " .set push \n" + " .set mips3 \n" + "1: ll %0, %1 # toggle_reg32 \n" + " xor %0, %2 \n" + " sc %0, %1 \n" + " "__beqz"%0, 1b \n" + " nop \n" + " .set pop \n" + : "=&r" (temp), "=m" (*addr) + : "ir" (mask), "m" (*addr)); +} + +/* + * Read all masked bits others are returned as '0' + */ +static inline u32 read_reg32(volatile u32 *const addr, + u32 const mask) +{ + u32 temp; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " lw %0, %1 # read \n" + " and %0, %2 # mask \n" + " .set pop \n" + : "=&r" (temp) + : "m" (*addr), "ir" (mask)); + + return temp; +} + +/* + * blocking_read_reg32 - Read address with blocking load + * + * Uncached writes need to be read back to ensure they reach RAM. + * The returned value must be 'used' to prevent from becoming a + * non-blocking load. + */ +static inline u32 blocking_read_reg32(volatile u32 *const addr) +{ + u32 temp; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " lw %0, %1 # read \n" + " move %0, %0 # block \n" + " .set pop \n" + : "=&r" (temp) + : "m" (*addr)); + + return temp; +} + +/* + * For special strange cases only: + * + * If you need custom processing within a ll/sc loop, use the following macros + * VERY CAREFULLY: + * + * u32 tmp; <-- Define a variable to hold the data + * + * custom_read_reg32(address, tmp); <-- Reads the address and put the value + * in the 'tmp' variable given + * + * From here on out, you are (basicly) atomic, so don't do anything too + * fancy! + * Also, this code may loop if the end of this block fails to write + * everything back safely due do the other CPU, so do NOT do anything + * with side-effects! + * + * custom_write_reg32(address, tmp); <-- Writes back 'tmp' safely. + */ +#define custom_read_reg32(address, tmp) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set mips3 \n" \ + "1: ll %0, %1 #custom_read_reg32 \n" \ + " .set pop \n" \ + : "=r" (tmp), "=m" (*address) \ + : "m" (*address)) + +#define custom_write_reg32(address, tmp) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set mips3 \n" \ + " sc %0, %1 #custom_write_reg32 \n" \ + " "__beqz"%0, 1b \n" \ + " nop \n" \ + " .set pop \n" \ + : "=&r" (tmp), "=m" (*address) \ + : "0" (tmp), "m" (*address)) + +#endif /* __ASM_REGOPS_H__ */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h new file mode 100644 index 00000000000..603eb737b4a --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h @@ -0,0 +1,663 @@ +/* + * Defines for the address space, registers and register configuration + * (bit masks, access macros etc) for the PMC-Sierra line of MSP products. + * This file contains addess maps for all the devices in the line of + * products but only has register definitions and configuration masks for + * registers which aren't definitely associated with any device. Things + * like clock settings, reset access, the ELB etc. Individual device + * drivers will reference the appropriate XXX_BASE value defined here + * and have individual registers offset from that. + * + * Copyright (C) 2005-2007 PMC-Sierra, Inc. All rights reserved. + * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 + +#ifndef _ASM_MSP_REGS_H +#define _ASM_MSP_REGS_H + +/* + ######################################################################## + # Address space and device base definitions # + ######################################################################## + */ + +/* + *************************************************************************** + * System Logic and Peripherals (ELB, UART0, etc) device address space * + *************************************************************************** + */ +#define MSP_SLP_BASE 0x1c000000 + /* System Logic and Peripherals */ +#define MSP_RST_BASE (MSP_SLP_BASE + 0x10) + /* System reset register base */ +#define MSP_RST_SIZE 0x0C /* System reset register space */ + +#define MSP_WTIMER_BASE (MSP_SLP_BASE + 0x04C) + /* watchdog timer base */ +#define MSP_ITIMER_BASE (MSP_SLP_BASE + 0x054) + /* internal timer base */ +#define MSP_UART0_BASE (MSP_SLP_BASE + 0x100) + /* UART0 controller base */ +#define MSP_BCPY_CTRL_BASE (MSP_SLP_BASE + 0x120) + /* Block Copy controller base */ +#define MSP_BCPY_DESC_BASE (MSP_SLP_BASE + 0x160) + /* Block Copy descriptor base */ + +/* + *************************************************************************** + * PCI address space * + *************************************************************************** + */ +#define MSP_PCI_BASE 0x19000000 + +/* + *************************************************************************** + * MSbus device address space * + *************************************************************************** + */ +#define MSP_MSB_BASE 0x18000000 + /* MSbus address start */ +#define MSP_PER_BASE (MSP_MSB_BASE + 0x400000) + /* Peripheral device registers */ +#define MSP_MAC0_BASE (MSP_MSB_BASE + 0x600000) + /* MAC A device registers */ +#define MSP_MAC1_BASE (MSP_MSB_BASE + 0x700000) + /* MAC B device registers */ +#define MSP_MAC_SIZE 0xE0 /* MAC register space */ + +#define MSP_SEC_BASE (MSP_MSB_BASE + 0x800000) + /* Security Engine registers */ +#define MSP_MAC2_BASE (MSP_MSB_BASE + 0x900000) + /* MAC C device registers */ +#define MSP_ADSL2_BASE (MSP_MSB_BASE + 0xA80000) + /* ADSL2 device registers */ +#define MSP_USB_BASE (MSP_MSB_BASE + 0xB40000) + /* USB device registers */ +#define MSP_USB_BASE_START (MSP_MSB_BASE + 0xB40100) + /* USB device registers */ +#define MSP_USB_BASE_END (MSP_MSB_BASE + 0xB401FF) + /* USB device registers */ +#define MSP_CPUIF_BASE (MSP_MSB_BASE + 0xC00000) + /* CPU interface registers */ + +/* Devices within the MSbus peripheral block */ +#define MSP_UART1_BASE (MSP_PER_BASE + 0x030) + /* UART1 controller base */ +#define MSP_SPI_BASE (MSP_PER_BASE + 0x058) + /* SPI/MPI control registers */ +#define MSP_TWI_BASE (MSP_PER_BASE + 0x090) + /* Two-wire control registers */ +#define MSP_PTIMER_BASE (MSP_PER_BASE + 0x0F0) + /* Programmable timer control */ + +/* + *************************************************************************** + * Physical Memory configuration address space * + *************************************************************************** + */ +#define MSP_MEM_CFG_BASE 0x17f00000 + +#define MSP_MEM_INDIRECT_CTL_10 0x10 + +/* + * Notes: + * 1) The SPI registers are split into two blocks, one offset from the + * MSP_SPI_BASE by 0x00 and the other offset from the MSP_SPI_BASE by + * 0x68. The SPI driver definitions for the register must be aware + * of this. + * 2) The block copy engine register are divided into two regions, one + * for the control/configuration of the engine proper and one for the + * values of the descriptors used in the copy process. These have + * different base defines (CTRL_BASE vs DESC_BASE) + * 3) These constants are for physical addresses which means that they + * work correctly with "ioremap" and friends. This means that device + * drivers will need to remap these addresses using ioremap and perhaps + * the readw/writew macros. Or they could use the regptr() macro + * defined below, but the readw/writew calls are the correct thing. + * 4) The UARTs have an additional status register offset from the base + * address. This register isn't used in the standard 8250 driver but + * may be used in other software. Consult the hardware datasheet for + * offset details. + * 5) For some unknown reason the security engine (MSP_SEC_BASE) registers + * start at an offset of 0x84 from the base address but the block of + * registers before this is reserved for the security engine. The + * driver will have to be aware of this but it makes the register + * definitions line up better with the documentation. + */ + +/* + ######################################################################## + # System register definitions. Not associated with a specific device # + ######################################################################## + */ + +/* + * This macro maps the physical register number into uncached space + * and (for C code) casts it into a u32 pointer so it can be dereferenced + * Normally these would be accessed with ioremap and readX/writeX, but + * these are convenient for a lot of internal kernel code. + */ +#ifdef __ASSEMBLER__ + #define regptr(addr) (KSEG1ADDR(addr)) +#else + #define regptr(addr) ((volatile u32 *const)(KSEG1ADDR(addr))) +#endif + +/* + *************************************************************************** + * System Logic and Peripherals (RESET, ELB, etc) registers * + *************************************************************************** + */ + +/* System Control register definitions */ +#define DEV_ID_REG regptr(MSP_SLP_BASE + 0x00) + /* Device-ID RO */ +#define FWR_ID_REG regptr(MSP_SLP_BASE + 0x04) + /* Firmware-ID Register RW */ +#define SYS_ID_REG0 regptr(MSP_SLP_BASE + 0x08) + /* System-ID Register-0 RW */ +#define SYS_ID_REG1 regptr(MSP_SLP_BASE + 0x0C) + /* System-ID Register-1 RW */ + +/* System Reset register definitions */ +#define RST_STS_REG regptr(MSP_SLP_BASE + 0x10) + /* System Reset Status RO */ +#define RST_SET_REG regptr(MSP_SLP_BASE + 0x14) + /* System Set Reset WO */ +#define RST_CLR_REG regptr(MSP_SLP_BASE + 0x18) + /* System Clear Reset WO */ + +/* System Clock Registers */ +#define PCI_SLP_REG regptr(MSP_SLP_BASE + 0x1C) + /* PCI clock generator RW */ +#define URT_SLP_REG regptr(MSP_SLP_BASE + 0x20) + /* UART clock generator RW */ +/* reserved (MSP_SLP_BASE + 0x24) */ +/* reserved (MSP_SLP_BASE + 0x28) */ +#define PLL1_SLP_REG regptr(MSP_SLP_BASE + 0x2C) + /* PLL1 clock generator RW */ +#define PLL0_SLP_REG regptr(MSP_SLP_BASE + 0x30) + /* PLL0 clock generator RW */ +#define MIPS_SLP_REG regptr(MSP_SLP_BASE + 0x34) + /* MIPS clock generator RW */ +#define VE_SLP_REG regptr(MSP_SLP_BASE + 0x38) + /* Voice Eng clock generator RW */ +/* reserved (MSP_SLP_BASE + 0x3C) */ +#define MSB_SLP_REG regptr(MSP_SLP_BASE + 0x40) + /* MS-Bus clock generator RW */ +#define SMAC_SLP_REG regptr(MSP_SLP_BASE + 0x44) + /* Sec & MAC clock generator RW */ +#define PERF_SLP_REG regptr(MSP_SLP_BASE + 0x48) + /* Per & TDM clock generator RW */ + +/* Interrupt Controller Registers */ +#define SLP_INT_STS_REG regptr(MSP_SLP_BASE + 0x70) + /* Interrupt status register RW */ +#define SLP_INT_MSK_REG regptr(MSP_SLP_BASE + 0x74) + /* Interrupt enable/mask RW */ +#define SE_MBOX_REG regptr(MSP_SLP_BASE + 0x78) + /* Security Engine mailbox RW */ +#define VE_MBOX_REG regptr(MSP_SLP_BASE + 0x7C) + /* Voice Engine mailbox RW */ + +/* ELB Controller Registers */ +#define CS0_CNFG_REG regptr(MSP_SLP_BASE + 0x80) + /* ELB CS0 Configuration Reg */ +#define CS0_ADDR_REG regptr(MSP_SLP_BASE + 0x84) + /* ELB CS0 Base Address Reg */ +#define CS0_MASK_REG regptr(MSP_SLP_BASE + 0x88) + /* ELB CS0 Mask Register */ +#define CS0_ACCESS_REG regptr(MSP_SLP_BASE + 0x8C) + /* ELB CS0 access register */ + +#define CS1_CNFG_REG regptr(MSP_SLP_BASE + 0x90) + /* ELB CS1 Configuration Reg */ +#define CS1_ADDR_REG regptr(MSP_SLP_BASE + 0x94) + /* ELB CS1 Base Address Reg */ +#define CS1_MASK_REG regptr(MSP_SLP_BASE + 0x98) + /* ELB CS1 Mask Register */ +#define CS1_ACCESS_REG regptr(MSP_SLP_BASE + 0x9C) + /* ELB CS1 access register */ + +#define CS2_CNFG_REG regptr(MSP_SLP_BASE + 0xA0) + /* ELB CS2 Configuration Reg */ +#define CS2_ADDR_REG regptr(MSP_SLP_BASE + 0xA4) + /* ELB CS2 Base Address Reg */ +#define CS2_MASK_REG regptr(MSP_SLP_BASE + 0xA8) + /* ELB CS2 Mask Register */ +#define CS2_ACCESS_REG regptr(MSP_SLP_BASE + 0xAC) + /* ELB CS2 access register */ + +#define CS3_CNFG_REG regptr(MSP_SLP_BASE + 0xB0) + /* ELB CS3 Configuration Reg */ +#define CS3_ADDR_REG regptr(MSP_SLP_BASE + 0xB4) + /* ELB CS3 Base Address Reg */ +#define CS3_MASK_REG regptr(MSP_SLP_BASE + 0xB8) + /* ELB CS3 Mask Register */ +#define CS3_ACCESS_REG regptr(MSP_SLP_BASE + 0xBC) + /* ELB CS3 access register */ + +#define CS4_CNFG_REG regptr(MSP_SLP_BASE + 0xC0) + /* ELB CS4 Configuration Reg */ +#define CS4_ADDR_REG regptr(MSP_SLP_BASE + 0xC4) + /* ELB CS4 Base Address Reg */ +#define CS4_MASK_REG regptr(MSP_SLP_BASE + 0xC8) + /* ELB CS4 Mask Register */ +#define CS4_ACCESS_REG regptr(MSP_SLP_BASE + 0xCC) + /* ELB CS4 access register */ + +#define CS5_CNFG_REG regptr(MSP_SLP_BASE + 0xD0) + /* ELB CS5 Configuration Reg */ +#define CS5_ADDR_REG regptr(MSP_SLP_BASE + 0xD4) + /* ELB CS5 Base Address Reg */ +#define CS5_MASK_REG regptr(MSP_SLP_BASE + 0xD8) + /* ELB CS5 Mask Register */ +#define CS5_ACCESS_REG regptr(MSP_SLP_BASE + 0xDC) + /* ELB CS5 access register */ + +/* reserved 0xE0 - 0xE8 */ +#define ELB_1PC_EN_REG regptr(MSP_SLP_BASE + 0xEC) + /* ELB single PC card detect */ + +/* reserved 0xF0 - 0xF8 */ +#define ELB_CLK_CFG_REG regptr(MSP_SLP_BASE + 0xFC) + /* SDRAM read/ELB timing Reg */ + +/* Extended UART status registers */ +#define UART0_STATUS_REG regptr(MSP_UART0_BASE + 0x0c0) + /* UART Status Register 0 */ +#define UART1_STATUS_REG regptr(MSP_UART1_BASE + 0x170) + /* UART Status Register 1 */ + +/* Performance monitoring registers */ +#define PERF_MON_CTRL_REG regptr(MSP_SLP_BASE + 0x140) + /* Performance monitor control */ +#define PERF_MON_CLR_REG regptr(MSP_SLP_BASE + 0x144) + /* Performance monitor clear */ +#define PERF_MON_CNTH_REG regptr(MSP_SLP_BASE + 0x148) + /* Perf monitor counter high */ +#define PERF_MON_CNTL_REG regptr(MSP_SLP_BASE + 0x14C) + /* Perf monitor counter low */ + +/* System control registers */ +#define SYS_CTRL_REG regptr(MSP_SLP_BASE + 0x150) + /* System control register */ +#define SYS_ERR1_REG regptr(MSP_SLP_BASE + 0x154) + /* System Error status 1 */ +#define SYS_ERR2_REG regptr(MSP_SLP_BASE + 0x158) + /* System Error status 2 */ +#define SYS_INT_CFG_REG regptr(MSP_SLP_BASE + 0x15C) + /* System Interrupt config */ + +/* Voice Engine Memory configuration */ +#define VE_MEM_REG regptr(MSP_SLP_BASE + 0x17C) + /* Voice engine memory config */ + +/* CPU/SLP Error Status registers */ +#define CPU_ERR1_REG regptr(MSP_SLP_BASE + 0x180) + /* CPU/SLP Error status 1 */ +#define CPU_ERR2_REG regptr(MSP_SLP_BASE + 0x184) + /* CPU/SLP Error status 1 */ + +#define EXTENDED_GPIO_REG regptr(MSP_SLP_BASE + 0x188) + /* Extended GPIO register */ + +/* System Error registers */ +#define SLP_ERR_STS_REG regptr(MSP_SLP_BASE + 0x190) + /* Int status for SLP errors */ +#define SLP_ERR_MSK_REG regptr(MSP_SLP_BASE + 0x194) + /* Int mask for SLP errors */ +#define SLP_ELB_ERST_REG regptr(MSP_SLP_BASE + 0x198) + /* External ELB reset */ +#define SLP_BOOT_STS_REG regptr(MSP_SLP_BASE + 0x19C) + /* Boot Status */ + +/* Extended ELB addressing */ +#define CS0_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A0) + /* CS0 Extended address */ +#define CS1_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A4) + /* CS1 Extended address */ +#define CS2_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A8) + /* CS2 Extended address */ +#define CS3_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1AC) + /* CS3 Extended address */ +/* reserved 0x1B0 */ +#define CS5_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1B4) + /* CS5 Extended address */ + +/* PLL Adjustment registers */ +#define PLL_LOCK_REG regptr(MSP_SLP_BASE + 0x200) + /* PLL0 lock status */ +#define PLL_ARST_REG regptr(MSP_SLP_BASE + 0x204) + /* PLL Analog reset status */ +#define PLL0_ADJ_REG regptr(MSP_SLP_BASE + 0x208) + /* PLL0 Adjustment value */ +#define PLL1_ADJ_REG regptr(MSP_SLP_BASE + 0x20C) + /* PLL1 Adjustment value */ + +/* + *************************************************************************** + * Peripheral Register definitions * + *************************************************************************** + */ + +/* Peripheral status */ +#define PER_CTRL_REG regptr(MSP_PER_BASE + 0x50) + /* Peripheral control register */ +#define PER_STS_REG regptr(MSP_PER_BASE + 0x54) + /* Peripheral status register */ + +/* SPI/MPI Registers */ +#define SMPI_TX_SZ_REG regptr(MSP_PER_BASE + 0x58) + /* SPI/MPI Tx Size register */ +#define SMPI_RX_SZ_REG regptr(MSP_PER_BASE + 0x5C) + /* SPI/MPI Rx Size register */ +#define SMPI_CTL_REG regptr(MSP_PER_BASE + 0x60) + /* SPI/MPI Control register */ +#define SMPI_MS_REG regptr(MSP_PER_BASE + 0x64) + /* SPI/MPI Chip Select reg */ +#define SMPI_CORE_DATA_REG regptr(MSP_PER_BASE + 0xC0) + /* SPI/MPI Core Data reg */ +#define SMPI_CORE_CTRL_REG regptr(MSP_PER_BASE + 0xC4) + /* SPI/MPI Core Control reg */ +#define SMPI_CORE_STAT_REG regptr(MSP_PER_BASE + 0xC8) + /* SPI/MPI Core Status reg */ +#define SMPI_CORE_SSEL_REG regptr(MSP_PER_BASE + 0xCC) + /* SPI/MPI Core Ssel reg */ +#define SMPI_FIFO_REG regptr(MSP_PER_BASE + 0xD0) + /* SPI/MPI Data FIFO reg */ + +/* Peripheral Block Error Registers */ +#define PER_ERR_STS_REG regptr(MSP_PER_BASE + 0x70) + /* Error Bit Status Register */ +#define PER_ERR_MSK_REG regptr(MSP_PER_BASE + 0x74) + /* Error Bit Mask Register */ +#define PER_HDR1_REG regptr(MSP_PER_BASE + 0x78) + /* Error Header 1 Register */ +#define PER_HDR2_REG regptr(MSP_PER_BASE + 0x7C) + /* Error Header 2 Register */ + +/* Peripheral Block Interrupt Registers */ +#define PER_INT_STS_REG regptr(MSP_PER_BASE + 0x80) + /* Interrupt status register */ +#define PER_INT_MSK_REG regptr(MSP_PER_BASE + 0x84) + /* Interrupt Mask Register */ +#define GPIO_INT_STS_REG regptr(MSP_PER_BASE + 0x88) + /* GPIO interrupt status reg */ +#define GPIO_INT_MSK_REG regptr(MSP_PER_BASE + 0x8C) + /* GPIO interrupt MASK Reg */ + +/* POLO GPIO registers */ +#define POLO_GPIO_DAT1_REG regptr(MSP_PER_BASE + 0x0E0) + /* Polo GPIO[8:0] data reg */ +#define POLO_GPIO_CFG1_REG regptr(MSP_PER_BASE + 0x0E4) + /* Polo GPIO[7:0] config reg */ +#define POLO_GPIO_CFG2_REG regptr(MSP_PER_BASE + 0x0E8) + /* Polo GPIO[15:8] config reg */ +#define POLO_GPIO_OD1_REG regptr(MSP_PER_BASE + 0x0EC) + /* Polo GPIO[31:0] output drive */ +#define POLO_GPIO_CFG3_REG regptr(MSP_PER_BASE + 0x170) + /* Polo GPIO[23:16] config reg */ +#define POLO_GPIO_DAT2_REG regptr(MSP_PER_BASE + 0x174) + /* Polo GPIO[15:9] data reg */ +#define POLO_GPIO_DAT3_REG regptr(MSP_PER_BASE + 0x178) + /* Polo GPIO[23:16] data reg */ +#define POLO_GPIO_DAT4_REG regptr(MSP_PER_BASE + 0x17C) + /* Polo GPIO[31:24] data reg */ +#define POLO_GPIO_DAT5_REG regptr(MSP_PER_BASE + 0x180) + /* Polo GPIO[39:32] data reg */ +#define POLO_GPIO_DAT6_REG regptr(MSP_PER_BASE + 0x184) + /* Polo GPIO[47:40] data reg */ +#define POLO_GPIO_DAT7_REG regptr(MSP_PER_BASE + 0x188) + /* Polo GPIO[54:48] data reg */ +#define POLO_GPIO_CFG4_REG regptr(MSP_PER_BASE + 0x18C) + /* Polo GPIO[31:24] config reg */ +#define POLO_GPIO_CFG5_REG regptr(MSP_PER_BASE + 0x190) + /* Polo GPIO[39:32] config reg */ +#define POLO_GPIO_CFG6_REG regptr(MSP_PER_BASE + 0x194) + /* Polo GPIO[47:40] config reg */ +#define POLO_GPIO_CFG7_REG regptr(MSP_PER_BASE + 0x198) + /* Polo GPIO[54:48] config reg */ +#define POLO_GPIO_OD2_REG regptr(MSP_PER_BASE + 0x19C) + /* Polo GPIO[54:32] output drive */ + +/* Generic GPIO registers */ +#define GPIO_DATA1_REG regptr(MSP_PER_BASE + 0x170) + /* GPIO[1:0] data register */ +#define GPIO_DATA2_REG regptr(MSP_PER_BASE + 0x174) + /* GPIO[5:2] data register */ +#define GPIO_DATA3_REG regptr(MSP_PER_BASE + 0x178) + /* GPIO[9:6] data register */ +#define GPIO_DATA4_REG regptr(MSP_PER_BASE + 0x17C) + /* GPIO[15:10] data register */ +#define GPIO_CFG1_REG regptr(MSP_PER_BASE + 0x180) + /* GPIO[1:0] config register */ +#define GPIO_CFG2_REG regptr(MSP_PER_BASE + 0x184) + /* GPIO[5:2] config register */ +#define GPIO_CFG3_REG regptr(MSP_PER_BASE + 0x188) + /* GPIO[9:6] config register */ +#define GPIO_CFG4_REG regptr(MSP_PER_BASE + 0x18C) + /* GPIO[15:10] config register */ +#define GPIO_OD_REG regptr(MSP_PER_BASE + 0x190) + /* GPIO[15:0] output drive */ + +/* + *************************************************************************** + * CPU Interface register definitions * + *************************************************************************** + */ +#define PCI_FLUSH_REG regptr(MSP_CPUIF_BASE + 0x00) + /* PCI-SDRAM queue flush trigger */ +#define OCP_ERR1_REG regptr(MSP_CPUIF_BASE + 0x04) + /* OCP Error Attribute 1 */ +#define OCP_ERR2_REG regptr(MSP_CPUIF_BASE + 0x08) + /* OCP Error Attribute 2 */ +#define OCP_STS_REG regptr(MSP_CPUIF_BASE + 0x0C) + /* OCP Error Status */ +#define CPUIF_PM_REG regptr(MSP_CPUIF_BASE + 0x10) + /* CPU policy configuration */ +#define CPUIF_CFG_REG regptr(MSP_CPUIF_BASE + 0x10) + /* Misc configuration options */ + +/* Central Interrupt Controller Registers */ +#define MSP_CIC_BASE (MSP_CPUIF_BASE + 0x8000) + /* Central Interrupt registers */ +#define CIC_EXT_CFG_REG regptr(MSP_CIC_BASE + 0x00) + /* External interrupt config */ +#define CIC_STS_REG regptr(MSP_CIC_BASE + 0x04) + /* CIC Interrupt Status */ +#define CIC_VPE0_MSK_REG regptr(MSP_CIC_BASE + 0x08) + /* VPE0 Interrupt Mask */ +#define CIC_VPE1_MSK_REG regptr(MSP_CIC_BASE + 0x0C) + /* VPE1 Interrupt Mask */ +#define CIC_TC0_MSK_REG regptr(MSP_CIC_BASE + 0x10) + /* Thread Context 0 Int Mask */ +#define CIC_TC1_MSK_REG regptr(MSP_CIC_BASE + 0x14) + /* Thread Context 1 Int Mask */ +#define CIC_TC2_MSK_REG regptr(MSP_CIC_BASE + 0x18) + /* Thread Context 2 Int Mask */ +#define CIC_TC3_MSK_REG regptr(MSP_CIC_BASE + 0x18) + /* Thread Context 3 Int Mask */ +#define CIC_TC4_MSK_REG regptr(MSP_CIC_BASE + 0x18) + /* Thread Context 4 Int Mask */ +#define CIC_PCIMSI_STS_REG regptr(MSP_CIC_BASE + 0x18) +#define CIC_PCIMSI_MSK_REG regptr(MSP_CIC_BASE + 0x18) +#define CIC_PCIFLSH_REG regptr(MSP_CIC_BASE + 0x18) +#define CIC_VPE0_SWINT_REG regptr(MSP_CIC_BASE + 0x08) + + +/* + *************************************************************************** + * Memory controller registers * + *************************************************************************** + */ +#define MEM_CFG1_REG regptr(MSP_MEM_CFG_BASE + 0x00) +#define MEM_SS_ADDR regptr(MSP_MEM_CFG_BASE + 0x00) +#define MEM_SS_DATA regptr(MSP_MEM_CFG_BASE + 0x04) +#define MEM_SS_WRITE regptr(MSP_MEM_CFG_BASE + 0x08) + +/* + *************************************************************************** + * PCI controller registers * + *************************************************************************** + */ +#define PCI_BASE_REG regptr(MSP_PCI_BASE + 0x00) +#define PCI_CONFIG_SPACE_REG regptr(MSP_PCI_BASE + 0x800) +#define PCI_JTAG_DEVID_REG regptr(MSP_SLP_BASE + 0x13c) + +/* + ######################################################################## + # Register content & macro definitions # + ######################################################################## + */ + +/* + *************************************************************************** + * DEV_ID defines * + *************************************************************************** + */ +#define DEV_ID_PCI_DIS (1 << 26) /* Set if PCI disabled */ +#define DEV_ID_PCI_HOST (1 << 20) /* Set if PCI host */ +#define DEV_ID_SINGLE_PC (1 << 19) /* Set if single PC Card */ +#define DEV_ID_FAMILY (0xff << 8) /* family ID code */ +#define POLO_ZEUS_SUB_FAMILY (0x7 << 16) /* sub family for Polo/Zeus */ + +#define MSPFPGA_ID (0x00 << 8) /* you are on your own here */ +#define MSP5000_ID (0x50 << 8) +#define MSP4F00_ID (0x4f << 8) /* FPGA version of MSP4200 */ +#define MSP4E00_ID (0x4f << 8) /* FPGA version of MSP7120 */ +#define MSP4200_ID (0x42 << 8) +#define MSP4000_ID (0x40 << 8) +#define MSP2XXX_ID (0x20 << 8) +#define MSPZEUS_ID (0x10 << 8) + +#define MSP2004_SUB_ID (0x0 << 16) +#define MSP2005_SUB_ID (0x1 << 16) +#define MSP2006_SUB_ID (0x1 << 16) +#define MSP2007_SUB_ID (0x2 << 16) +#define MSP2010_SUB_ID (0x3 << 16) +#define MSP2015_SUB_ID (0x4 << 16) +#define MSP2020_SUB_ID (0x5 << 16) +#define MSP2100_SUB_ID (0x6 << 16) + +/* + *************************************************************************** + * RESET defines * + *************************************************************************** + */ +#define MSP_GR_RST (0x01 << 0) /* Global reset bit */ +#define MSP_MR_RST (0x01 << 1) /* MIPS reset bit */ +#define MSP_PD_RST (0x01 << 2) /* PVC DMA reset bit */ +#define MSP_PP_RST (0x01 << 3) /* PVC reset bit */ +/* reserved */ +#define MSP_EA_RST (0x01 << 6) /* Mac A reset bit */ +#define MSP_EB_RST (0x01 << 7) /* Mac B reset bit */ +#define MSP_SE_RST (0x01 << 8) /* Security Eng reset bit */ +#define MSP_PB_RST (0x01 << 9) /* Per block reset bit */ +#define MSP_EC_RST (0x01 << 10) /* Mac C reset bit */ +#define MSP_TW_RST (0x01 << 11) /* TWI reset bit */ +#define MSP_SPI_RST (0x01 << 12) /* SPI/MPI reset bit */ +#define MSP_U1_RST (0x01 << 13) /* UART1 reset bit */ +#define MSP_U0_RST (0x01 << 14) /* UART0 reset bit */ + +/* + *************************************************************************** + * UART defines * + *************************************************************************** + */ +#define MSP_BASE_BAUD 25000000 +#define MSP_UART_REG_LEN 0x20 + +/* + *************************************************************************** + * ELB defines * + *************************************************************************** + */ +#define PCCARD_32 0x02 /* Set if is PCCARD 32 (Cardbus) */ +#define SINGLE_PCCARD 0x01 /* Set to enable single PC card */ + +/* + *************************************************************************** + * CIC defines * + *************************************************************************** + */ + +/* CIC_EXT_CFG_REG */ +#define EXT_INT_POL(eirq) (1 << (eirq + 8)) +#define EXT_INT_EDGE(eirq) (1 << eirq) + +#define CIC_EXT_SET_TRIGGER_LEVEL(reg, eirq) (reg &= ~EXT_INT_EDGE(eirq)) +#define CIC_EXT_SET_TRIGGER_EDGE(reg, eirq) (reg |= EXT_INT_EDGE(eirq)) +#define CIC_EXT_SET_ACTIVE_HI(reg, eirq) (reg |= EXT_INT_POL(eirq)) +#define CIC_EXT_SET_ACTIVE_LO(reg, eirq) (reg &= ~EXT_INT_POL(eirq)) +#define CIC_EXT_SET_ACTIVE_RISING CIC_EXT_SET_ACTIVE_HI +#define CIC_EXT_SET_ACTIVE_FALLING CIC_EXT_SET_ACTIVE_LO + +#define CIC_EXT_IS_TRIGGER_LEVEL(reg, eirq) \ + ((reg & EXT_INT_EDGE(eirq)) == 0) +#define CIC_EXT_IS_TRIGGER_EDGE(reg, eirq) (reg & EXT_INT_EDGE(eirq)) +#define CIC_EXT_IS_ACTIVE_HI(reg, eirq) (reg & EXT_INT_POL(eirq)) +#define CIC_EXT_IS_ACTIVE_LO(reg, eirq) \ + ((reg & EXT_INT_POL(eirq)) == 0) +#define CIC_EXT_IS_ACTIVE_RISING CIC_EXT_IS_ACTIVE_HI +#define CIC_EXT_IS_ACTIVE_FALLING CIC_EXT_IS_ACTIVE_LO + +/* + *************************************************************************** + * Memory Controller defines * + *************************************************************************** + */ + +/* Indirect memory controller registers */ +#define DDRC_CFG(n) (n) +#define DDRC_DEBUG(n) (0x04 + n) +#define DDRC_CTL(n) (0x40 + n) + +/* Macro to perform DDRC indirect write */ +#define DDRC_INDIRECT_WRITE(reg, mask, value) \ +({ \ + *MEM_SS_ADDR = (((mask) & 0xf) << 8) | ((reg) & 0xff); \ + *MEM_SS_DATA = (value); \ + *MEM_SS_WRITE = 1; \ +}) + +/* + *************************************************************************** + * SPI/MPI Mode * + *************************************************************************** + */ +#define SPI_MPI_RX_BUSY 0x00008000 /* SPI/MPI Receive Busy */ +#define SPI_MPI_FIFO_EMPTY 0x00004000 /* SPI/MPI Fifo Empty */ +#define SPI_MPI_TX_BUSY 0x00002000 /* SPI/MPI Transmit Busy */ +#define SPI_MPI_FIFO_FULL 0x00001000 /* SPI/MPU FIFO full */ + +/* + *************************************************************************** + * SPI/MPI Control Register * + *************************************************************************** + */ +#define SPI_MPI_RX_START 0x00000004 /* Start receive command */ +#define SPI_MPI_FLUSH_Q 0x00000002 /* Flush SPI/MPI Queue */ +#define SPI_MPI_TX_START 0x00000001 /* Start Transmit Command */ + +#endif /* !_ASM_MSP_REGS_H */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_slp_int.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_slp_int.h new file mode 100644 index 00000000000..96d4c8ce8c8 --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_slp_int.h @@ -0,0 +1,141 @@ +/* + * Defines for the MSP interrupt controller. + * + * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved. + * Author: Carsten Langgaard, carstenl@mips.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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 _MSP_SLP_INT_H +#define _MSP_SLP_INT_H + +/* + * The PMC-Sierra SLP interrupts are arranged in a 3 level cascaded + * hierarchical system. The first level are the direct MIPS interrupts + * and are assigned the interrupt range 0-7. The second level is the SLM + * interrupt controller and is assigned the range 8-39. The third level + * comprises the Peripherial block, the PCI block, the PCI MSI block and + * the SLP. The PCI interrupts and the SLP errors are handled by the + * relevant subsystems so the core interrupt code needs only concern + * itself with the Peripheral block. These are assigned interrupts in + * the range 40-71. + */ + +/* + * IRQs directly connected to CPU + */ +#define MSP_MIPS_INTBASE 0 +#define MSP_INT_SW0 0 /* IRQ for swint0, C_SW0 */ +#define MSP_INT_SW1 1 /* IRQ for swint1, C_SW1 */ +#define MSP_INT_MAC0 2 /* IRQ for MAC 0, C_IRQ0 */ +#define MSP_INT_MAC1 3 /* IRQ for MAC 1, C_IRQ1 */ +#define MSP_INT_C_IRQ2 4 /* Wired off, C_IRQ2 */ +#define MSP_INT_VE 5 /* IRQ for Voice Engine, C_IRQ3 */ +#define MSP_INT_SLP 6 /* IRQ for SLM block, C_IRQ4 */ +#define MSP_INT_TIMER 7 /* IRQ for the MIPS timer, C_IRQ5 */ + +/* + * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4) + * These defines should be tied to the register definition for the SLM + * interrupt routine. For now, just use hard-coded values. + */ +#define MSP_SLP_INTBASE (MSP_MIPS_INTBASE + 8) +#define MSP_INT_EXT0 (MSP_SLP_INTBASE + 0) + /* External interrupt 0 */ +#define MSP_INT_EXT1 (MSP_SLP_INTBASE + 1) + /* External interrupt 1 */ +#define MSP_INT_EXT2 (MSP_SLP_INTBASE + 2) + /* External interrupt 2 */ +#define MSP_INT_EXT3 (MSP_SLP_INTBASE + 3) + /* External interrupt 3 */ +/* Reserved 4-7 */ + +/* + ************************************************************************* + * DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER * + * Some MSP produces have this interrupt labelled as Voice and some are * + * SEC mbox ... * + ************************************************************************* + */ +#define MSP_INT_SLP_VE (MSP_SLP_INTBASE + 8) + /* Cascaded IRQ for Voice Engine*/ +#define MSP_INT_SLP_TDM (MSP_SLP_INTBASE + 9) + /* TDM interrupt */ +#define MSP_INT_SLP_MAC0 (MSP_SLP_INTBASE + 10) + /* Cascaded IRQ for MAC 0 */ +#define MSP_INT_SLP_MAC1 (MSP_SLP_INTBASE + 11) + /* Cascaded IRQ for MAC 1 */ +#define MSP_INT_SEC (MSP_SLP_INTBASE + 12) + /* IRQ for security engine */ +#define MSP_INT_PER (MSP_SLP_INTBASE + 13) + /* Peripheral interrupt */ +#define MSP_INT_TIMER0 (MSP_SLP_INTBASE + 14) + /* SLP timer 0 */ +#define MSP_INT_TIMER1 (MSP_SLP_INTBASE + 15) + /* SLP timer 1 */ +#define MSP_INT_TIMER2 (MSP_SLP_INTBASE + 16) + /* SLP timer 2 */ +#define MSP_INT_SLP_TIMER (MSP_SLP_INTBASE + 17) + /* Cascaded MIPS timer */ +#define MSP_INT_BLKCP (MSP_SLP_INTBASE + 18) + /* Block Copy */ +#define MSP_INT_UART0 (MSP_SLP_INTBASE + 19) + /* UART 0 */ +#define MSP_INT_PCI (MSP_SLP_INTBASE + 20) + /* PCI subsystem */ +#define MSP_INT_PCI_DBELL (MSP_SLP_INTBASE + 21) + /* PCI doorbell */ +#define MSP_INT_PCI_MSI (MSP_SLP_INTBASE + 22) + /* PCI Message Signal */ +#define MSP_INT_PCI_BC0 (MSP_SLP_INTBASE + 23) + /* PCI Block Copy 0 */ +#define MSP_INT_PCI_BC1 (MSP_SLP_INTBASE + 24) + /* PCI Block Copy 1 */ +#define MSP_INT_SLP_ERR (MSP_SLP_INTBASE + 25) + /* SLP error condition */ +#define MSP_INT_MAC2 (MSP_SLP_INTBASE + 26) + /* IRQ for MAC2 */ +/* Reserved 26-31 */ + +/* + * IRQs cascaded on SLP PER interrupt (MSP_INT_PER) + */ +#define MSP_PER_INTBASE (MSP_SLP_INTBASE + 32) +/* Reserved 0-1 */ +#define MSP_INT_UART1 (MSP_PER_INTBASE + 2) + /* UART 1 */ +/* Reserved 3-5 */ +#define MSP_INT_2WIRE (MSP_PER_INTBASE + 6) + /* 2-wire */ +#define MSP_INT_TM0 (MSP_PER_INTBASE + 7) + /* Peripheral timer block out 0 */ +#define MSP_INT_TM1 (MSP_PER_INTBASE + 8) + /* Peripheral timer block out 1 */ +/* Reserved 9 */ +#define MSP_INT_SPRX (MSP_PER_INTBASE + 10) + /* SPI RX complete */ +#define MSP_INT_SPTX (MSP_PER_INTBASE + 11) + /* SPI TX complete */ +#define MSP_INT_GPIO (MSP_PER_INTBASE + 12) + /* GPIO */ +#define MSP_INT_PER_ERR (MSP_PER_INTBASE + 13) + /* Peripheral error */ +/* Reserved 14-31 */ + +#endif /* !_MSP_SLP_INT_H */ diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/war.h b/arch/mips/include/asm/pmc-sierra/msp71xx/war.h new file mode 100644 index 00000000000..0bf48fc1892 --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/war.h @@ -0,0 +1,28 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_PMC_SIERRA_WAR_H +#define __ASM_MIPS_PMC_SIERRA_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \ + defined(CONFIG_PMC_MSP7120_FPGA) +#define MIPS34K_MISSED_ITLB_WAR 1 +#endif + +#endif /* __ASM_MIPS_PMC_SIERRA_WAR_H */ diff --git a/arch/mips/include/asm/pmon.h b/arch/mips/include/asm/pmon.h new file mode 100644 index 00000000000..6ad519189ce --- /dev/null +++ b/arch/mips/include/asm/pmon.h @@ -0,0 +1,46 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004 by Ralf Baechle + * + * The cpustart method is a PMC-Sierra's function to start the secondary CPU. + * Stock PMON 2000 has the smpfork, semlock and semunlock methods instead. + */ +#ifndef _ASM_PMON_H +#define _ASM_PMON_H + +struct callvectors { + int (*open) (char*, int, int); + int (*close) (int); + int (*read) (int, void*, int); + int (*write) (int, void*, int); + off_t (*lseek) (int, off_t, int); + int (*printf) (const char*, ...); + void (*cacheflush) (void); + char* (*gets) (char*); + union { + int (*smpfork) (unsigned long cp, char *sp); + int (*cpustart) (long, void (*)(void), void *, long); + } _s; + int (*semlock) (int sem); + void (*semunlock) (int sem); +}; + +extern struct callvectors *debug_vectors; + +#define pmon_open(name, flags, mode) debug_vectors->open(name, flage, mode) +#define pmon_close(fd) debug_vectors->close(fd) +#define pmon_read(fd, buf, count) debug_vectors->read(fd, buf, count) +#define pmon_write(fd, buf, count) debug_vectors->write(fd, buf, count) +#define pmon_lseek(fd, off, whence) debug_vectors->lseek(fd, off, whence) +#define pmon_printf(fmt...) debug_vectors->printf(fmt) +#define pmon_cacheflush() debug_vectors->cacheflush() +#define pmon_gets(s) debug_vectors->gets(s) +#define pmon_cpustart(n, f, sp, gp) debug_vectors->_s.cpustart(n, f, sp, gp) +#define pmon_smpfork(cp, sp) debug_vectors->_s.smpfork(cp, sp) +#define pmon_semlock(sem) debug_vectors->semlock(sem) +#define pmon_semunlock(sem) debug_vectors->semunlock(sem) + +#endif /* _ASM_PMON_H */ diff --git a/arch/mips/include/asm/poll.h b/arch/mips/include/asm/poll.h new file mode 100644 index 00000000000..47b95208043 --- /dev/null +++ b/arch/mips/include/asm/poll.h @@ -0,0 +1,9 @@ +#ifndef __ASM_POLL_H +#define __ASM_POLL_H + +#define POLLWRNORM POLLOUT +#define POLLWRBAND 0x0100 + +#include + +#endif /* __ASM_POLL_H */ diff --git a/arch/mips/include/asm/posix_types.h b/arch/mips/include/asm/posix_types.h new file mode 100644 index 00000000000..c200102c858 --- /dev/null +++ b/arch/mips/include/asm/posix_types.h @@ -0,0 +1,144 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 97, 98, 99, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +#include + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +#if (_MIPS_SZLONG == 32) +typedef unsigned long __kernel_nlink_t; +#endif +#if (_MIPS_SZLONG == 64) +typedef unsigned int __kernel_nlink_t; +#endif +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +#if (_MIPS_SZLONG == 32) +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +#endif +#if (_MIPS_SZLONG == 64) +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +#endif +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; + +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if (_MIPS_SZLONG == 32) + long val[2]; +#endif +#if (_MIPS_SZLONG == 64) + int val[2]; +#endif +} __kernel_fsid_t; + +#if defined(__KERNEL__) + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + __fdsetp->fds_bits[__tmp] |= (1UL<<__rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *__p) +{ + unsigned long *__tmp = __p->fds_bits; + int __i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 16: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + __tmp[ 4] = 0; __tmp[ 5] = 0; + __tmp[ 6] = 0; __tmp[ 7] = 0; + __tmp[ 8] = 0; __tmp[ 9] = 0; + __tmp[10] = 0; __tmp[11] = 0; + __tmp[12] = 0; __tmp[13] = 0; + __tmp[14] = 0; __tmp[15] = 0; + return; + + case 8: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + __tmp[ 4] = 0; __tmp[ 5] = 0; + __tmp[ 6] = 0; __tmp[ 7] = 0; + return; + + case 4: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + return; + } + } + __i = __FDSET_LONGS; + while (__i) { + __i--; + *__tmp = 0; + __tmp++; + } +} + +#endif /* defined(__KERNEL__) */ + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/arch/mips/include/asm/prefetch.h b/arch/mips/include/asm/prefetch.h new file mode 100644 index 00000000000..17850834ccb --- /dev/null +++ b/arch/mips/include/asm/prefetch.h @@ -0,0 +1,87 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 by Ralf Baechle + */ +#ifndef __ASM_PREFETCH_H +#define __ASM_PREFETCH_H + + +/* + * R5000 and RM5200 implements pref and prefx instructions but they're nops, so + * rather than wasting time we pretend these processors don't support + * prefetching at all. + * + * R5432 implements Load, Store, LoadStreamed, StoreStreamed, LoadRetained, + * StoreRetained and WriteBackInvalidate but not Pref_PrepareForStore. + * + * Hell (and the book on my shelf I can't open ...) know what the R8000 does. + * + * RM7000 version 1.0 interprets all hints as Pref_Load; version 2.0 implements + * Pref_PrepareForStore also. + * + * RM9000 is MIPS IV but implements prefetching like MIPS32/MIPS64; it's + * Pref_WriteBackInvalidate is a nop and Pref_PrepareForStore is broken in + * current versions due to erratum G105. + * + * VR7701 only implements the Load prefetch. + * + * Finally MIPS32 and MIPS64 implement all of the following hints. + */ + +#define Pref_Load 0 +#define Pref_Store 1 + /* 2 and 3 are reserved */ +#define Pref_LoadStreamed 4 +#define Pref_StoreStreamed 5 +#define Pref_LoadRetained 6 +#define Pref_StoreRetained 7 + /* 8 ... 24 are reserved */ +#define Pref_WriteBackInvalidate 25 +#define Pref_PrepareForStore 30 + +#ifdef __ASSEMBLY__ + + .macro __pref hint addr +#ifdef CONFIG_CPU_HAS_PREFETCH + pref \hint, \addr +#endif + .endm + + .macro pref_load addr + __pref Pref_Load, \addr + .endm + + .macro pref_store addr + __pref Pref_Store, \addr + .endm + + .macro pref_load_streamed addr + __pref Pref_LoadStreamed, \addr + .endm + + .macro pref_store_streamed addr + __pref Pref_StoreStreamed, \addr + .endm + + .macro pref_load_retained addr + __pref Pref_LoadRetained, \addr + .endm + + .macro pref_store_retained addr + __pref Pref_StoreRetained, \addr + .endm + + .macro pref_wback_inv addr + __pref Pref_WriteBackInvalidate, \addr + .endm + + .macro pref_prepare_for_store addr + __pref Pref_PrepareForStore, \addr + .endm + +#endif + +#endif /* __ASM_PREFETCH_H */ diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h new file mode 100644 index 00000000000..a1e4453469f --- /dev/null +++ b/arch/mips/include/asm/processor.h @@ -0,0 +1,263 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 Waldorf GMBH + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003 Ralf Baechle + * Copyright (C) 1996 Paul M. Antoine + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_PROCESSOR_H +#define _ASM_PROCESSOR_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * Return current * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l;}) + +/* + * System setup and hardware flags.. + */ +extern void (*cpu_wait)(void); + +extern unsigned int vced_count, vcei_count; + +#ifdef CONFIG_32BIT +/* + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. + */ +#define TASK_SIZE 0x7fff8000UL +#define STACK_TOP TASK_SIZE + +/* + * This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE ((TASK_SIZE / 3) & ~(PAGE_SIZE)) +#endif + +#ifdef CONFIG_64BIT +/* + * User space process size: 1TB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. TASK_SIZE + * is limited to 1TB by the R4000 architecture; R10000 and better can + * support 16TB; the architectural reserve for future expansion is + * 8192EB ... + */ +#define TASK_SIZE32 0x7fff8000UL +#define TASK_SIZE 0x10000000000UL +#define STACK_TOP \ + (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE) + +/* + * This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE \ + (test_thread_flag(TIF_32BIT_ADDR) ? \ + PAGE_ALIGN(TASK_SIZE32 / 3) : PAGE_ALIGN(TASK_SIZE / 3)) +#define TASK_SIZE_OF(tsk) \ + (test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE) +#endif + +#ifdef __KERNEL__ +#define STACK_TOP_MAX TASK_SIZE +#endif + +#define NUM_FPU_REGS 32 + +typedef __u64 fpureg_t; + +/* + * It would be nice to add some more fields for emulator statistics, but there + * are a number of fixed offsets in offset.h and elsewhere that would have to + * be recalculated by hand. So the additional information will be private to + * the FPU emulator for now. See asm-mips/fpu_emulator.h. + */ + +struct mips_fpu_struct { + fpureg_t fpr[NUM_FPU_REGS]; + unsigned int fcr31; +}; + +#define NUM_DSP_REGS 6 + +typedef __u32 dspreg_t; + +struct mips_dsp_state { + dspreg_t dspr[NUM_DSP_REGS]; + unsigned int dspcontrol; +}; + +#define INIT_CPUMASK { \ + {0,} \ +} + +typedef struct { + unsigned long seg; +} mm_segment_t; + +#define ARCH_MIN_TASKALIGN 8 + +struct mips_abi; + +/* + * If you change thread_struct remember to change the #defines below too! + */ +struct thread_struct { + /* Saved main processor registers. */ + unsigned long reg16; + unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23; + unsigned long reg29, reg30, reg31; + + /* Saved cp0 stuff. */ + unsigned long cp0_status; + + /* Saved fpu/fpu emulator stuff. */ + struct mips_fpu_struct fpu; +#ifdef CONFIG_MIPS_MT_FPAFF + /* Emulated instruction count */ + unsigned long emulated_fp; + /* Saved per-thread scheduler affinity mask */ + cpumask_t user_cpus_allowed; +#endif /* CONFIG_MIPS_MT_FPAFF */ + + /* Saved state of the DSP ASE, if available. */ + struct mips_dsp_state dsp; + + /* Other stuff associated with the thread. */ + unsigned long cp0_badvaddr; /* Last user fault */ + unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ + unsigned long error_code; + unsigned long trap_no; + unsigned long irix_trampoline; /* Wheee... */ + unsigned long irix_oldctx; + struct mips_abi *abi; +}; + +#ifdef CONFIG_MIPS_MT_FPAFF +#define FPAFF_INIT \ + .emulated_fp = 0, \ + .user_cpus_allowed = INIT_CPUMASK, +#else +#define FPAFF_INIT +#endif /* CONFIG_MIPS_MT_FPAFF */ + +#define INIT_THREAD { \ + /* \ + * Saved main processor registers \ + */ \ + .reg16 = 0, \ + .reg17 = 0, \ + .reg18 = 0, \ + .reg19 = 0, \ + .reg20 = 0, \ + .reg21 = 0, \ + .reg22 = 0, \ + .reg23 = 0, \ + .reg29 = 0, \ + .reg30 = 0, \ + .reg31 = 0, \ + /* \ + * Saved cp0 stuff \ + */ \ + .cp0_status = 0, \ + /* \ + * Saved FPU/FPU emulator stuff \ + */ \ + .fpu = { \ + .fpr = {0,}, \ + .fcr31 = 0, \ + }, \ + /* \ + * FPU affinity state (null if not FPAFF) \ + */ \ + FPAFF_INIT \ + /* \ + * Saved DSP stuff \ + */ \ + .dsp = { \ + .dspr = {0, }, \ + .dspcontrol = 0, \ + }, \ + /* \ + * Other stuff associated with the process \ + */ \ + .cp0_badvaddr = 0, \ + .cp0_baduaddr = 0, \ + .error_code = 0, \ + .trap_no = 0, \ + .irix_trampoline = 0, \ + .irix_oldctx = 0, \ +} + +struct task_struct; + +/* Free all resources held by a thread. */ +#define release_thread(thread) do { } while(0) + +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + +extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + +extern unsigned long thread_saved_pc(struct task_struct *tsk); + +/* + * Do necessary setup to start up a newly executed thread. + */ +extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp); + +unsigned long get_wchan(struct task_struct *p); + +#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + THREAD_SIZE - 32) +#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk) - 1) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->cp0_epc) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29]) +#define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status) + +#define cpu_relax() barrier() + +/* + * Return_address is a replacement for __builtin_return_address(count) + * which on certain architectures cannot reasonably be implemented in GCC + * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386). + * Note that __builtin_return_address(x>=1) is forbidden because GCC + * aborts compilation on some CPUs. It's simply not possible to unwind + * some CPU's stackframes. + * + * __builtin_return_address works only for non-leaf functions. We avoid the + * overhead of a function call by forcing the compiler to save the return + * address register on the stack. + */ +#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) + +#ifdef CONFIG_CPU_HAS_PREFETCH + +#define ARCH_HAS_PREFETCH + +static inline void prefetch(const void *addr) +{ + __asm__ __volatile__( + " .set mips4 \n" + " pref %0, (%1) \n" + " .set mips0 \n" + : + : "i" (Pref_Load), "r" (addr)); +} + +#endif + +#endif /* _ASM_PROCESSOR_H */ diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h new file mode 100644 index 00000000000..c00cca24dae --- /dev/null +++ b/arch/mips/include/asm/ptrace.h @@ -0,0 +1,102 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_PTRACE_H +#define _ASM_PTRACE_H + +#ifdef CONFIG_64BIT +#define __ARCH_WANT_COMPAT_SYS_PTRACE +#endif + +/* 0 - 31 are integer registers, 32 - 63 are fp registers. */ +#define FPR_BASE 32 +#define PC 64 +#define CAUSE 65 +#define BADVADDR 66 +#define MMHI 67 +#define MMLO 68 +#define FPC_CSR 69 +#define FPC_EIR 70 +#define DSP_BASE 71 /* 3 more hi / lo register pairs */ +#define DSP_CONTROL 77 +#define ACX 78 + +/* + * This struct defines the way the registers are stored on the stack during a + * system call/exception. As usual the registers k0/k1 aren't being saved. + */ +struct pt_regs { +#ifdef CONFIG_32BIT + /* Pad bytes for argument save space on the stack. */ + unsigned long pad0[6]; +#endif + + /* Saved main processor registers. */ + unsigned long regs[32]; + + /* Saved special registers. */ + unsigned long cp0_status; + unsigned long hi; + unsigned long lo; +#ifdef CONFIG_CPU_HAS_SMARTMIPS + unsigned long acx; +#endif + unsigned long cp0_badvaddr; + unsigned long cp0_cause; + unsigned long cp0_epc; +#ifdef CONFIG_MIPS_MT_SMTC + unsigned long cp0_tcstatus; +#endif /* CONFIG_MIPS_MT_SMTC */ +} __attribute__ ((aligned (8))); + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 +/* #define PTRACE_GETFPXREGS 18 */ +/* #define PTRACE_SETFPXREGS 19 */ + +#define PTRACE_OLDSETOPTIONS 21 + +#define PTRACE_GET_THREAD_AREA 25 +#define PTRACE_SET_THREAD_AREA 26 + +/* Calls to trace a 64bit program from a 32bit program. */ +#define PTRACE_PEEKTEXT_3264 0xc0 +#define PTRACE_PEEKDATA_3264 0xc1 +#define PTRACE_POKETEXT_3264 0xc2 +#define PTRACE_POKEDATA_3264 0xc3 +#define PTRACE_GET_THREAD_AREA_3264 0xc4 + +#ifdef __KERNEL__ + +#include +#include + +/* + * Does the process account for user or for system time? + */ +#define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER) + +#define instruction_pointer(regs) ((regs)->cp0_epc) +#define profile_pc(regs) instruction_pointer(regs) + +extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit); + +extern NORET_TYPE void die(const char *, const struct pt_regs *) ATTRIB_NORET; + +static inline void die_if_kernel(const char *str, const struct pt_regs *regs) +{ + if (unlikely(!user_mode(regs))) + die(str, regs); +} + +#endif + +#endif /* _ASM_PTRACE_H */ diff --git a/arch/mips/include/asm/r4k-timer.h b/arch/mips/include/asm/r4k-timer.h new file mode 100644 index 00000000000..a37d12b3b61 --- /dev/null +++ b/arch/mips/include/asm/r4k-timer.h @@ -0,0 +1,30 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2008 by Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_R4K_TYPES_H +#define __ASM_R4K_TYPES_H + +#include + +#ifdef CONFIG_SYNC_R4K + +extern void synchronise_count_master(void); +extern void synchronise_count_slave(void); + +#else + +static inline void synchronise_count_master(void) +{ +} + +static inline void synchronise_count_slave(void) +{ +} + +#endif + +#endif /* __ASM_R4K_TYPES_H */ diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h new file mode 100644 index 00000000000..4c140db3678 --- /dev/null +++ b/arch/mips/include/asm/r4kcache.h @@ -0,0 +1,443 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Inline assembly cache operations. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997 - 2002 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef _ASM_R4KCACHE_H +#define _ASM_R4KCACHE_H + +#include +#include +#include +#include + +/* + * This macro return a properly sign-extended address suitable as base address + * for indexed cache operations. Two issues here: + * + * - The MIPS32 and MIPS64 specs permit an implementation to directly derive + * the index bits from the virtual address. This breaks with tradition + * set by the R4000. To keep unpleasant surprises from happening we pick + * an address in KSEG0 / CKSEG0. + * - We need a properly sign extended address for 64-bit code. To get away + * without ifdefs we let the compiler do it by a type cast. + */ +#define INDEX_BASE CKSEG0 + +#define cache_op(op,addr) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noreorder \n" \ + " .set mips3\n\t \n" \ + " cache %0, %1 \n" \ + " .set pop \n" \ + : \ + : "i" (op), "R" (*(unsigned char *)(addr))) + +#ifdef CONFIG_MIPS_MT +/* + * Temporary hacks for SMTC debug. Optionally force single-threaded + * execution during I-cache flushes. + */ + +#define PROTECT_CACHE_FLUSHES 1 + +#ifdef PROTECT_CACHE_FLUSHES + +extern int mt_protiflush; +extern int mt_protdflush; +extern void mt_cflush_lockdown(void); +extern void mt_cflush_release(void); + +#define BEGIN_MT_IPROT \ + unsigned long flags = 0; \ + unsigned long mtflags = 0; \ + if(mt_protiflush) { \ + local_irq_save(flags); \ + ehb(); \ + mtflags = dvpe(); \ + mt_cflush_lockdown(); \ + } + +#define END_MT_IPROT \ + if(mt_protiflush) { \ + mt_cflush_release(); \ + evpe(mtflags); \ + local_irq_restore(flags); \ + } + +#define BEGIN_MT_DPROT \ + unsigned long flags = 0; \ + unsigned long mtflags = 0; \ + if(mt_protdflush) { \ + local_irq_save(flags); \ + ehb(); \ + mtflags = dvpe(); \ + mt_cflush_lockdown(); \ + } + +#define END_MT_DPROT \ + if(mt_protdflush) { \ + mt_cflush_release(); \ + evpe(mtflags); \ + local_irq_restore(flags); \ + } + +#else + +#define BEGIN_MT_IPROT +#define BEGIN_MT_DPROT +#define END_MT_IPROT +#define END_MT_DPROT + +#endif /* PROTECT_CACHE_FLUSHES */ + +#define __iflush_prologue \ + unsigned long redundance; \ + extern int mt_n_iflushes; \ + BEGIN_MT_IPROT \ + for (redundance = 0; redundance < mt_n_iflushes; redundance++) { + +#define __iflush_epilogue \ + END_MT_IPROT \ + } + +#define __dflush_prologue \ + unsigned long redundance; \ + extern int mt_n_dflushes; \ + BEGIN_MT_DPROT \ + for (redundance = 0; redundance < mt_n_dflushes; redundance++) { + +#define __dflush_epilogue \ + END_MT_DPROT \ + } + +#define __inv_dflush_prologue __dflush_prologue +#define __inv_dflush_epilogue __dflush_epilogue +#define __sflush_prologue { +#define __sflush_epilogue } +#define __inv_sflush_prologue __sflush_prologue +#define __inv_sflush_epilogue __sflush_epilogue + +#else /* CONFIG_MIPS_MT */ + +#define __iflush_prologue { +#define __iflush_epilogue } +#define __dflush_prologue { +#define __dflush_epilogue } +#define __inv_dflush_prologue { +#define __inv_dflush_epilogue } +#define __sflush_prologue { +#define __sflush_epilogue } +#define __inv_sflush_prologue { +#define __inv_sflush_epilogue } + +#endif /* CONFIG_MIPS_MT */ + +static inline void flush_icache_line_indexed(unsigned long addr) +{ + __iflush_prologue + cache_op(Index_Invalidate_I, addr); + __iflush_epilogue +} + +static inline void flush_dcache_line_indexed(unsigned long addr) +{ + __dflush_prologue + cache_op(Index_Writeback_Inv_D, addr); + __dflush_epilogue +} + +static inline void flush_scache_line_indexed(unsigned long addr) +{ + cache_op(Index_Writeback_Inv_SD, addr); +} + +static inline void flush_icache_line(unsigned long addr) +{ + __iflush_prologue + cache_op(Hit_Invalidate_I, addr); + __iflush_epilogue +} + +static inline void flush_dcache_line(unsigned long addr) +{ + __dflush_prologue + cache_op(Hit_Writeback_Inv_D, addr); + __dflush_epilogue +} + +static inline void invalidate_dcache_line(unsigned long addr) +{ + __dflush_prologue + cache_op(Hit_Invalidate_D, addr); + __dflush_epilogue +} + +static inline void invalidate_scache_line(unsigned long addr) +{ + cache_op(Hit_Invalidate_SD, addr); +} + +static inline void flush_scache_line(unsigned long addr) +{ + cache_op(Hit_Writeback_Inv_SD, addr); +} + +#define protected_cache_op(op,addr) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noreorder \n" \ + " .set mips3 \n" \ + "1: cache %0, (%1) \n" \ + "2: .set pop \n" \ + " .section __ex_table,\"a\" \n" \ + " "STR(PTR)" 1b, 2b \n" \ + " .previous" \ + : \ + : "i" (op), "r" (addr)) + +/* + * The next two are for badland addresses like signal trampolines. + */ +static inline void protected_flush_icache_line(unsigned long addr) +{ + protected_cache_op(Hit_Invalidate_I, addr); +} + +/* + * R10000 / R12000 hazard - these processors don't support the Hit_Writeback_D + * cacheop so we use Hit_Writeback_Inv_D which is supported by all R4000-style + * caches. We're talking about one cacheline unnecessarily getting invalidated + * here so the penalty isn't overly hard. + */ +static inline void protected_writeback_dcache_line(unsigned long addr) +{ + protected_cache_op(Hit_Writeback_Inv_D, addr); +} + +static inline void protected_writeback_scache_line(unsigned long addr) +{ + protected_cache_op(Hit_Writeback_Inv_SD, addr); +} + +/* + * This one is RM7000-specific + */ +static inline void invalidate_tcache_page(unsigned long addr) +{ + cache_op(Page_Invalidate_T, addr); +} + +#define cache16_unroll32(base,op) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noreorder \n" \ + " .set mips3 \n" \ + " cache %1, 0x000(%0); cache %1, 0x010(%0) \n" \ + " cache %1, 0x020(%0); cache %1, 0x030(%0) \n" \ + " cache %1, 0x040(%0); cache %1, 0x050(%0) \n" \ + " cache %1, 0x060(%0); cache %1, 0x070(%0) \n" \ + " cache %1, 0x080(%0); cache %1, 0x090(%0) \n" \ + " cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) \n" \ + " cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) \n" \ + " cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) \n" \ + " cache %1, 0x100(%0); cache %1, 0x110(%0) \n" \ + " cache %1, 0x120(%0); cache %1, 0x130(%0) \n" \ + " cache %1, 0x140(%0); cache %1, 0x150(%0) \n" \ + " cache %1, 0x160(%0); cache %1, 0x170(%0) \n" \ + " cache %1, 0x180(%0); cache %1, 0x190(%0) \n" \ + " cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) \n" \ + " cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) \n" \ + " cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) \n" \ + " .set pop \n" \ + : \ + : "r" (base), \ + "i" (op)); + +#define cache32_unroll32(base,op) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noreorder \n" \ + " .set mips3 \n" \ + " cache %1, 0x000(%0); cache %1, 0x020(%0) \n" \ + " cache %1, 0x040(%0); cache %1, 0x060(%0) \n" \ + " cache %1, 0x080(%0); cache %1, 0x0a0(%0) \n" \ + " cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) \n" \ + " cache %1, 0x100(%0); cache %1, 0x120(%0) \n" \ + " cache %1, 0x140(%0); cache %1, 0x160(%0) \n" \ + " cache %1, 0x180(%0); cache %1, 0x1a0(%0) \n" \ + " cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) \n" \ + " cache %1, 0x200(%0); cache %1, 0x220(%0) \n" \ + " cache %1, 0x240(%0); cache %1, 0x260(%0) \n" \ + " cache %1, 0x280(%0); cache %1, 0x2a0(%0) \n" \ + " cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) \n" \ + " cache %1, 0x300(%0); cache %1, 0x320(%0) \n" \ + " cache %1, 0x340(%0); cache %1, 0x360(%0) \n" \ + " cache %1, 0x380(%0); cache %1, 0x3a0(%0) \n" \ + " cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) \n" \ + " .set pop \n" \ + : \ + : "r" (base), \ + "i" (op)); + +#define cache64_unroll32(base,op) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noreorder \n" \ + " .set mips3 \n" \ + " cache %1, 0x000(%0); cache %1, 0x040(%0) \n" \ + " cache %1, 0x080(%0); cache %1, 0x0c0(%0) \n" \ + " cache %1, 0x100(%0); cache %1, 0x140(%0) \n" \ + " cache %1, 0x180(%0); cache %1, 0x1c0(%0) \n" \ + " cache %1, 0x200(%0); cache %1, 0x240(%0) \n" \ + " cache %1, 0x280(%0); cache %1, 0x2c0(%0) \n" \ + " cache %1, 0x300(%0); cache %1, 0x340(%0) \n" \ + " cache %1, 0x380(%0); cache %1, 0x3c0(%0) \n" \ + " cache %1, 0x400(%0); cache %1, 0x440(%0) \n" \ + " cache %1, 0x480(%0); cache %1, 0x4c0(%0) \n" \ + " cache %1, 0x500(%0); cache %1, 0x540(%0) \n" \ + " cache %1, 0x580(%0); cache %1, 0x5c0(%0) \n" \ + " cache %1, 0x600(%0); cache %1, 0x640(%0) \n" \ + " cache %1, 0x680(%0); cache %1, 0x6c0(%0) \n" \ + " cache %1, 0x700(%0); cache %1, 0x740(%0) \n" \ + " cache %1, 0x780(%0); cache %1, 0x7c0(%0) \n" \ + " .set pop \n" \ + : \ + : "r" (base), \ + "i" (op)); + +#define cache128_unroll32(base,op) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noreorder \n" \ + " .set mips3 \n" \ + " cache %1, 0x000(%0); cache %1, 0x080(%0) \n" \ + " cache %1, 0x100(%0); cache %1, 0x180(%0) \n" \ + " cache %1, 0x200(%0); cache %1, 0x280(%0) \n" \ + " cache %1, 0x300(%0); cache %1, 0x380(%0) \n" \ + " cache %1, 0x400(%0); cache %1, 0x480(%0) \n" \ + " cache %1, 0x500(%0); cache %1, 0x580(%0) \n" \ + " cache %1, 0x600(%0); cache %1, 0x680(%0) \n" \ + " cache %1, 0x700(%0); cache %1, 0x780(%0) \n" \ + " cache %1, 0x800(%0); cache %1, 0x880(%0) \n" \ + " cache %1, 0x900(%0); cache %1, 0x980(%0) \n" \ + " cache %1, 0xa00(%0); cache %1, 0xa80(%0) \n" \ + " cache %1, 0xb00(%0); cache %1, 0xb80(%0) \n" \ + " cache %1, 0xc00(%0); cache %1, 0xc80(%0) \n" \ + " cache %1, 0xd00(%0); cache %1, 0xd80(%0) \n" \ + " cache %1, 0xe00(%0); cache %1, 0xe80(%0) \n" \ + " cache %1, 0xf00(%0); cache %1, 0xf80(%0) \n" \ + " .set pop \n" \ + : \ + : "r" (base), \ + "i" (op)); + +/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \ +static inline void blast_##pfx##cache##lsize(void) \ +{ \ + unsigned long start = INDEX_BASE; \ + unsigned long end = start + current_cpu_data.desc.waysize; \ + unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ + unsigned long ws_end = current_cpu_data.desc.ways << \ + current_cpu_data.desc.waybit; \ + unsigned long ws, addr; \ + \ + __##pfx##flush_prologue \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws, indexop); \ + \ + __##pfx##flush_epilogue \ +} \ + \ +static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ +{ \ + unsigned long start = page; \ + unsigned long end = page + PAGE_SIZE; \ + \ + __##pfx##flush_prologue \ + \ + do { \ + cache##lsize##_unroll32(start, hitop); \ + start += lsize * 32; \ + } while (start < end); \ + \ + __##pfx##flush_epilogue \ +} \ + \ +static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ +{ \ + unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ + unsigned long start = INDEX_BASE + (page & indexmask); \ + unsigned long end = start + PAGE_SIZE; \ + unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ + unsigned long ws_end = current_cpu_data.desc.ways << \ + current_cpu_data.desc.waybit; \ + unsigned long ws, addr; \ + \ + __##pfx##flush_prologue \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws, indexop); \ + \ + __##pfx##flush_epilogue \ +} + +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) + +__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16) +__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128) + +/* build blast_xxx_range, protected_blast_xxx_range */ +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \ +static inline void prot##blast_##pfx##cache##_range(unsigned long start, \ + unsigned long end) \ +{ \ + unsigned long lsize = cpu_##desc##_line_size(); \ + unsigned long addr = start & ~(lsize - 1); \ + unsigned long aend = (end - 1) & ~(lsize - 1); \ + \ + __##pfx##flush_prologue \ + \ + while (1) { \ + prot##cache_op(hitop, addr); \ + if (addr == aend) \ + break; \ + addr += lsize; \ + } \ + \ + __##pfx##flush_epilogue \ +} + +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_) +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_) +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_) +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, ) +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, ) +/* blast_inv_dcache_range */ +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, ) +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, ) + +#endif /* _ASM_R4KCACHE_H */ diff --git a/arch/mips/include/asm/reboot.h b/arch/mips/include/asm/reboot.h new file mode 100644 index 00000000000..e48c0bfab25 --- /dev/null +++ b/arch/mips/include/asm/reboot.h @@ -0,0 +1,15 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 1999, 2001, 06 by Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef _ASM_REBOOT_H +#define _ASM_REBOOT_H + +extern void (*_machine_restart)(char *command); +extern void (*_machine_halt)(void); + +#endif /* _ASM_REBOOT_H */ diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h new file mode 100644 index 00000000000..634b55d7e7f --- /dev/null +++ b/arch/mips/include/asm/reg.h @@ -0,0 +1,128 @@ +/* + * Various register offset definitions for debuggers, core file + * examiners and whatnot. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 Ralf Baechle + * Copyright (C) 1995, 1999 Silicon Graphics + */ +#ifndef __ASM_MIPS_REG_H +#define __ASM_MIPS_REG_H + + +#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H) + +#define EF_R0 6 +#define EF_R1 7 +#define EF_R2 8 +#define EF_R3 9 +#define EF_R4 10 +#define EF_R5 11 +#define EF_R6 12 +#define EF_R7 13 +#define EF_R8 14 +#define EF_R9 15 +#define EF_R10 16 +#define EF_R11 17 +#define EF_R12 18 +#define EF_R13 19 +#define EF_R14 20 +#define EF_R15 21 +#define EF_R16 22 +#define EF_R17 23 +#define EF_R18 24 +#define EF_R19 25 +#define EF_R20 26 +#define EF_R21 27 +#define EF_R22 28 +#define EF_R23 29 +#define EF_R24 30 +#define EF_R25 31 + +/* + * k0/k1 unsaved + */ +#define EF_R26 32 +#define EF_R27 33 + +#define EF_R28 34 +#define EF_R29 35 +#define EF_R30 36 +#define EF_R31 37 + +/* + * Saved special registers + */ +#define EF_LO 38 +#define EF_HI 39 + +#define EF_CP0_EPC 40 +#define EF_CP0_BADVADDR 41 +#define EF_CP0_STATUS 42 +#define EF_CP0_CAUSE 43 +#define EF_UNUSED0 44 + +#define EF_SIZE 180 + +#endif + +#ifdef CONFIG_64BIT + +#define EF_R0 0 +#define EF_R1 1 +#define EF_R2 2 +#define EF_R3 3 +#define EF_R4 4 +#define EF_R5 5 +#define EF_R6 6 +#define EF_R7 7 +#define EF_R8 8 +#define EF_R9 9 +#define EF_R10 10 +#define EF_R11 11 +#define EF_R12 12 +#define EF_R13 13 +#define EF_R14 14 +#define EF_R15 15 +#define EF_R16 16 +#define EF_R17 17 +#define EF_R18 18 +#define EF_R19 19 +#define EF_R20 20 +#define EF_R21 21 +#define EF_R22 22 +#define EF_R23 23 +#define EF_R24 24 +#define EF_R25 25 + +/* + * k0/k1 unsaved + */ +#define EF_R26 26 +#define EF_R27 27 + + +#define EF_R28 28 +#define EF_R29 29 +#define EF_R30 30 +#define EF_R31 31 + +/* + * Saved special registers + */ +#define EF_LO 32 +#define EF_HI 33 + +#define EF_CP0_EPC 34 +#define EF_CP0_BADVADDR 35 +#define EF_CP0_STATUS 36 +#define EF_CP0_CAUSE 37 + +#define EF_SIZE 304 /* size in bytes */ + +#endif /* CONFIG_64BIT */ + +#endif /* __ASM_MIPS_REG_H */ diff --git a/arch/mips/include/asm/regdef.h b/arch/mips/include/asm/regdef.h new file mode 100644 index 00000000000..7c8ecb6b9c4 --- /dev/null +++ b/arch/mips/include/asm/regdef.h @@ -0,0 +1,100 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1985 MIPS Computer Systems, Inc. + * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle + * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_REGDEF_H +#define _ASM_REGDEF_H + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ + +#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 + +#define zero $0 /* wired zero */ +#define AT $at /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value - caller saved */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define a4 $8 /* arg reg 64 bit; caller saved in 32 bit */ +#define ta0 $8 +#define a5 $9 +#define ta1 $9 +#define a6 $10 +#define ta2 $10 +#define a7 $11 +#define ta3 $11 +#define t0 $12 /* caller saved */ +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 /* callee address for PIC/temp */ +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel temporary */ +#define k1 $27 +#define gp $28 /* global pointer - caller saved for PIC */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* callee saved */ +#define ra $31 /* return address */ + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */ + +#endif /* _ASM_REGDEF_H */ diff --git a/arch/mips/include/asm/resource.h b/arch/mips/include/asm/resource.h new file mode 100644 index 00000000000..87cb3085269 --- /dev/null +++ b/arch/mips/include/asm/resource.h @@ -0,0 +1,35 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 98, 99, 2000 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_RESOURCE_H +#define _ASM_RESOURCE_H + + +/* + * These five resource limit IDs have a MIPS/Linux-specific ordering, + * the rest comes from the generic header: + */ +#define RLIMIT_NOFILE 5 /* max number of open files */ +#define RLIMIT_AS 6 /* address space limit */ +#define RLIMIT_RSS 7 /* max resident set size */ +#define RLIMIT_NPROC 8 /* max number of processes */ +#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */ + +/* + * SuS says limits have to be unsigned. + * Which makes a ton more sense anyway, + * but we keep the old value on MIPS32, + * for compatibility: + */ +#ifdef CONFIG_32BIT +# define RLIM_INFINITY 0x7fffffffUL +#endif + +#include + +#endif /* _ASM_RESOURCE_H */ diff --git a/arch/mips/include/asm/rm9k-ocd.h b/arch/mips/include/asm/rm9k-ocd.h new file mode 100644 index 00000000000..b0b80d9ecf9 --- /dev/null +++ b/arch/mips/include/asm/rm9k-ocd.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * 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 + */ + +#if !defined(_ASM_RM9K_OCD_H) +#define _ASM_RM9K_OCD_H + +#include +#include +#include + +extern volatile void __iomem * const ocd_base; +extern volatile void __iomem * const titan_base; + +#define ocd_addr(__x__) (ocd_base + (__x__)) +#define titan_addr(__x__) (titan_base + (__x__)) +#define scram_addr(__x__) (scram_base + (__x__)) + +/* OCD register access */ +#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__)) +#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__)) +#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__)) +#define ocd_writel(__val__, __offs__) \ + __raw_writel((__val__), ocd_addr(__offs__)) +#define ocd_writew(__val__, __offs__) \ + __raw_writew((__val__), ocd_addr(__offs__)) +#define ocd_writeb(__val__, __offs__) \ + __raw_writeb((__val__), ocd_addr(__offs__)) + +/* TITAN register access - 32 bit-wide only */ +#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__)) +#define titan_writel(__val__, __offs__) \ + __raw_writel((__val__), titan_addr(__offs__)) + +/* Protect access to shared TITAN registers */ +extern spinlock_t titan_lock; +extern int titan_irqflags; +#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags) +#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags) + +#endif /* !defined(_ASM_RM9K_OCD_H) */ diff --git a/arch/mips/include/asm/rtlx.h b/arch/mips/include/asm/rtlx.h new file mode 100644 index 00000000000..4ca3063ed2c --- /dev/null +++ b/arch/mips/include/asm/rtlx.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * + */ + +#ifndef __ASM_RTLX_H_ +#define __ASM_RTLX_H_ + +#include + +#define LX_NODE_BASE 10 + +#define MIPS_CPU_RTLX_IRQ 0 + +#define RTLX_VERSION 2 +#define RTLX_xID 0x12345600 +#define RTLX_ID (RTLX_xID | RTLX_VERSION) +#define RTLX_CHANNELS 8 + +#define RTLX_CHANNEL_STDIO 0 +#define RTLX_CHANNEL_DBG 1 +#define RTLX_CHANNEL_SYSIO 2 + +extern int rtlx_open(int index, int can_sleep); +extern int rtlx_release(int index); +extern ssize_t rtlx_read(int index, void __user *buff, size_t count); +extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count); +extern unsigned int rtlx_read_poll(int index, int can_sleep); +extern unsigned int rtlx_write_poll(int index); + +enum rtlx_state { + RTLX_STATE_UNUSED = 0, + RTLX_STATE_INITIALISED, + RTLX_STATE_REMOTE_READY, + RTLX_STATE_OPENED +}; + +#define RTLX_BUFFER_SIZE 2048 + +/* each channel supports read and write. + linux (vpe0) reads lx_buffer and writes rt_buffer + SP (vpe1) reads rt_buffer and writes lx_buffer +*/ +struct rtlx_channel { + enum rtlx_state rt_state; + enum rtlx_state lx_state; + + int buffer_size; + + /* read and write indexes per buffer */ + int rt_write, rt_read; + char *rt_buffer; + + int lx_write, lx_read; + char *lx_buffer; +}; + +struct rtlx_info { + unsigned long id; + enum rtlx_state state; + + struct rtlx_channel channel[RTLX_CHANNELS]; +}; + +#endif /* __ASM_RTLX_H_ */ diff --git a/arch/mips/include/asm/scatterlist.h b/arch/mips/include/asm/scatterlist.h new file mode 100644 index 00000000000..83d69fe17c9 --- /dev/null +++ b/arch/mips/include/asm/scatterlist.h @@ -0,0 +1,28 @@ +#ifndef __ASM_SCATTERLIST_H +#define __ASM_SCATTERLIST_H + +#include + +struct scatterlist { +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; + unsigned int offset; + dma_addr_t dma_address; + unsigned int length; +}; + +/* + * These macros should be used after a pci_map_sg call has been done + * to get bus addresses of each of the SG entries and their lengths. + * You should only work with the number of sg entries pci_map_sg + * returns, or alternatively stop on the first sg_dma_len(sg) which + * is 0. + */ +#define sg_dma_address(sg) ((sg)->dma_address) +#define sg_dma_len(sg) ((sg)->length) + +#define ISA_DMA_THRESHOLD (0x00ffffffUL) + +#endif /* __ASM_SCATTERLIST_H */ diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h new file mode 100644 index 00000000000..36ed4407025 --- /dev/null +++ b/arch/mips/include/asm/seccomp.h @@ -0,0 +1,37 @@ +#ifndef __ASM_SECCOMP_H + +#include +#include + +#define __NR_seccomp_read __NR_read +#define __NR_seccomp_write __NR_write +#define __NR_seccomp_exit __NR_exit +#define __NR_seccomp_sigreturn __NR_rt_sigreturn + +/* + * Kludge alert: + * + * The generic seccomp code currently allows only a single compat ABI. Until + * this is fixed we priorize O32 as the compat ABI over N32. + */ +#ifdef CONFIG_MIPS32_O32 + +#define TIF_32BIT TIF_32BIT_REGS + +#define __NR_seccomp_read_32 4003 +#define __NR_seccomp_write_32 4004 +#define __NR_seccomp_exit_32 4001 +#define __NR_seccomp_sigreturn_32 4193 /* rt_sigreturn */ + +#elif defined(CONFIG_MIPS32_N32) + +#define TIF_32BIT _TIF_32BIT_ADDR + +#define __NR_seccomp_read_32 6000 +#define __NR_seccomp_write_32 6001 +#define __NR_seccomp_exit_32 6058 +#define __NR_seccomp_sigreturn_32 6211 /* rt_sigreturn */ + +#endif /* CONFIG_MIPS32_O32 */ + +#endif /* __ASM_SECCOMP_H */ diff --git a/arch/mips/include/asm/sections.h b/arch/mips/include/asm/sections.h new file mode 100644 index 00000000000..b7e37262c24 --- /dev/null +++ b/arch/mips/include/asm/sections.h @@ -0,0 +1,6 @@ +#ifndef _ASM_SECTIONS_H +#define _ASM_SECTIONS_H + +#include + +#endif /* _ASM_SECTIONS_H */ diff --git a/arch/mips/include/asm/segment.h b/arch/mips/include/asm/segment.h new file mode 100644 index 00000000000..92ac001fc48 --- /dev/null +++ b/arch/mips/include/asm/segment.h @@ -0,0 +1,6 @@ +#ifndef _ASM_SEGMENT_H +#define _ASM_SEGMENT_H + +/* Only here because we have some old header files that expect it.. */ + +#endif /* _ASM_SEGMENT_H */ diff --git a/arch/mips/include/asm/sembuf.h b/arch/mips/include/asm/sembuf.h new file mode 100644 index 00000000000..7281a4decaa --- /dev/null +++ b/arch/mips/include/asm/sembuf.h @@ -0,0 +1,22 @@ +#ifndef _ASM_SEMBUF_H +#define _ASM_SEMBUF_H + +/* + * The semid64_ds structure for the MIPS architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 2 miscellaneous 64-bit values + */ + +struct semid64_ds { + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ + __kernel_time_t sem_otime; /* last semop time */ + __kernel_time_t sem_ctime; /* last change time */ + unsigned long sem_nsems; /* no. of semaphores in array */ + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _ASM_SEMBUF_H */ diff --git a/arch/mips/include/asm/serial.h b/arch/mips/include/asm/serial.h new file mode 100644 index 00000000000..c07ebd8eb9e --- /dev/null +++ b/arch/mips/include/asm/serial.h @@ -0,0 +1,22 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_SERIAL_H +#define _ASM_SERIAL_H + + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#endif /* _ASM_SERIAL_H */ diff --git a/arch/mips/include/asm/setup.h b/arch/mips/include/asm/setup.h new file mode 100644 index 00000000000..e600cedda97 --- /dev/null +++ b/arch/mips/include/asm/setup.h @@ -0,0 +1,10 @@ +#ifndef _MIPS_SETUP_H +#define _MIPS_SETUP_H + +#define COMMAND_LINE_SIZE 256 + +#ifdef __KERNEL__ +extern void setup_early_printk(void); +#endif /* __KERNEL__ */ + +#endif /* __SETUP_H */ diff --git a/arch/mips/include/asm/sgi/gio.h b/arch/mips/include/asm/sgi/gio.h new file mode 100644 index 00000000000..889cf028c95 --- /dev/null +++ b/arch/mips/include/asm/sgi/gio.h @@ -0,0 +1,86 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * gio.h: Definitions for SGI GIO bus + * + * Copyright (C) 2002 Ladislav Michl + */ + +#ifndef _SGI_GIO_H +#define _SGI_GIO_H + +/* + * GIO bus addresses + * + * The Indigo and Indy have two GIO bus connectors. Indigo2 (all models) have + * three physical connectors, but only two slots, GFX and EXP0. + * + * There is 10MB of GIO address space for GIO64 slot devices + * slot# slot type address range size + * ----- --------- ----------------------- ----- + * 0 GFX 0x1f000000 - 0x1f3fffff 4MB + * 1 EXP0 0x1f400000 - 0x1f5fffff 2MB + * 2 EXP1 0x1f600000 - 0x1f9fffff 4MB + * + * There are un-slotted devices, HPC, I/O and misc devices, which are grouped + * into the HPC address space. + * - MISC 0x1fb00000 - 0x1fbfffff 1MB + * + * Following space is reserved and unused + * - RESERVED 0x18000000 - 0x1effffff 112MB + * + * GIO bus IDs + * + * Each GIO bus device identifies itself to the system by answering a + * read with an "ID" value. IDs are either 8 or 32 bits long. IDs less + * than 128 are 8 bits long, with the most significant 24 bits read from + * the slot undefined. + * + * 32-bit IDs are divided into + * bits 0:6 the product ID; ranges from 0x00 to 0x7F. + * bit 7 0=GIO Product ID is 8 bits wide + * 1=GIO Product ID is 32 bits wide. + * bits 8:15 manufacturer version for the product. + * bit 16 0=GIO32 and GIO32-bis, 1=GIO64. + * bit 17 0=no ROM present + * 1=ROM present on this board AND next three words + * space define the ROM. + * bits 18:31 up to manufacturer. + * + * IDs above 0x50/0xd0 are of 3rd party boards. + * + * 8-bit IDs + * 0x01 XPI low cost FDDI + * 0x02 GTR TokenRing + * 0x04 Synchronous ISDN + * 0x05 ATM board [*] + * 0x06 Canon Interface + * 0x07 16 bit SCSI Card [*] + * 0x08 JPEG (Double Wide) + * 0x09 JPEG (Single Wide) + * 0x0a XPI mez. FDDI device 0 + * 0x0b XPI mez. FDDI device 1 + * 0x0c SMPTE 259M Video [*] + * 0x0d Babblefish Compression [*] + * 0x0e E-Plex 8-port Ethernet + * 0x30 Lyon Lamb IVAS + * 0xb8 GIO 100BaseTX Fast Ethernet (gfe) + * + * [*] Device provide 32-bit ID. + * + */ + +#define GIO_ID(x) (x & 0x7f) +#define GIO_32BIT_ID 0x80 +#define GIO_REV(x) ((x >> 8) & 0xff) +#define GIO_64BIT_IFACE 0x10000 +#define GIO_ROM_PRESENT 0x20000 +#define GIO_VENDOR_CODE(x) ((x >> 18) & 0x3fff) + +#define GIO_SLOT_GFX_BASE 0x1f000000 +#define GIO_SLOT_EXP0_BASE 0x1f400000 +#define GIO_SLOT_EXP1_BASE 0x1f600000 + +#endif /* _SGI_GIO_H */ diff --git a/arch/mips/include/asm/sgi/hpc3.h b/arch/mips/include/asm/sgi/hpc3.h new file mode 100644 index 00000000000..c4729f53191 --- /dev/null +++ b/arch/mips/include/asm/sgi/hpc3.h @@ -0,0 +1,317 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * hpc3.h: Definitions for SGI HPC3 controller + * + * Copyright (C) 1996 David S. Miller + * Copyright (C) 1998 Ralf Baechle + */ + +#ifndef _SGI_HPC3_H +#define _SGI_HPC3_H + +#include +#include + +/* An HPC DMA descriptor. */ +struct hpc_dma_desc { + u32 pbuf; /* physical address of data buffer */ + u32 cntinfo; /* counter and info bits */ +#define HPCDMA_EOX 0x80000000 /* last desc in chain for tx */ +#define HPCDMA_EOR 0x80000000 /* last desc in chain for rx */ +#define HPCDMA_EOXP 0x40000000 /* end of packet for tx */ +#define HPCDMA_EORP 0x40000000 /* end of packet for rx */ +#define HPCDMA_XIE 0x20000000 /* irq generated when at end of this desc */ +#define HPCDMA_XIU 0x01000000 /* Tx buffer in use by CPU. */ +#define HPCDMA_EIPC 0x00ff0000 /* SEEQ ethernet special xternal bytecount */ +#define HPCDMA_ETXD 0x00008000 /* set to one by HPC when packet tx'd */ +#define HPCDMA_OWN 0x00004000 /* Denotes ring buffer ownership on rx */ +#define HPCDMA_BCNT 0x00003fff /* size in bytes of this dma buffer */ + + u32 pnext; /* paddr of next hpc_dma_desc if any */ +}; + +/* The set of regs for each HPC3 PBUS DMA channel. */ +struct hpc3_pbus_dmacregs { + volatile u32 pbdma_bptr; /* pbus dma channel buffer ptr */ + volatile u32 pbdma_dptr; /* pbus dma channel desc ptr */ + u32 _unused0[0x1000/4 - 2]; /* padding */ + volatile u32 pbdma_ctrl; /* pbus dma channel control register has + * copletely different meaning for read + * compared with write */ + /* read */ +#define HPC3_PDMACTRL_INT 0x00000001 /* interrupt (cleared after read) */ +#define HPC3_PDMACTRL_ISACT 0x00000002 /* channel active */ + /* write */ +#define HPC3_PDMACTRL_SEL 0x00000002 /* little endian transfer */ +#define HPC3_PDMACTRL_RCV 0x00000004 /* direction is receive */ +#define HPC3_PDMACTRL_FLSH 0x00000008 /* enable flush for receive DMA */ +#define HPC3_PDMACTRL_ACT 0x00000010 /* start dma transfer */ +#define HPC3_PDMACTRL_LD 0x00000020 /* load enable for ACT */ +#define HPC3_PDMACTRL_RT 0x00000040 /* Use realtime GIO bus servicing */ +#define HPC3_PDMACTRL_HW 0x0000ff00 /* DMA High-water mark */ +#define HPC3_PDMACTRL_FB 0x003f0000 /* Ptr to beginning of fifo */ +#define HPC3_PDMACTRL_FE 0x3f000000 /* Ptr to end of fifo */ + + u32 _unused1[0x1000/4 - 1]; /* padding */ +}; + +/* The HPC3 SCSI registers, this does not include external ones. */ +struct hpc3_scsiregs { + volatile u32 cbptr; /* current dma buffer ptr, diagnostic use only */ + volatile u32 ndptr; /* next dma descriptor ptr */ + u32 _unused0[0x1000/4 - 2]; /* padding */ + volatile u32 bcd; /* byte count info */ +#define HPC3_SBCD_BCNTMSK 0x00003fff /* bytes to transfer from/to memory */ +#define HPC3_SBCD_XIE 0x00004000 /* Send IRQ when done with cur buf */ +#define HPC3_SBCD_EOX 0x00008000 /* Indicates this is last buf in chain */ + + volatile u32 ctrl; /* control register */ +#define HPC3_SCTRL_IRQ 0x01 /* IRQ asserted, either dma done or parity */ +#define HPC3_SCTRL_ENDIAN 0x02 /* DMA endian mode, 0=big 1=little */ +#define HPC3_SCTRL_DIR 0x04 /* DMA direction, 1=dev2mem 0=mem2dev */ +#define HPC3_SCTRL_FLUSH 0x08 /* Tells HPC3 to flush scsi fifos */ +#define HPC3_SCTRL_ACTIVE 0x10 /* SCSI DMA channel is active */ +#define HPC3_SCTRL_AMASK 0x20 /* DMA active inhibits PIO */ +#define HPC3_SCTRL_CRESET 0x40 /* Resets dma channel and external controller */ +#define HPC3_SCTRL_PERR 0x80 /* Bad parity on HPC3 iface to scsi controller */ + + volatile u32 gfptr; /* current GIO fifo ptr */ + volatile u32 dfptr; /* current device fifo ptr */ + volatile u32 dconfig; /* DMA configuration register */ +#define HPC3_SDCFG_HCLK 0x00001 /* Enable DMA half clock mode */ +#define HPC3_SDCFG_D1 0x00006 /* Cycles to spend in D1 state */ +#define HPC3_SDCFG_D2 0x00038 /* Cycles to spend in D2 state */ +#define HPC3_SDCFG_D3 0x001c0 /* Cycles to spend in D3 state */ +#define HPC3_SDCFG_HWAT 0x00e00 /* DMA high water mark */ +#define HPC3_SDCFG_HW 0x01000 /* Enable 16-bit halfword DMA accesses to scsi */ +#define HPC3_SDCFG_SWAP 0x02000 /* Byte swap all DMA accesses */ +#define HPC3_SDCFG_EPAR 0x04000 /* Enable parity checking for DMA */ +#define HPC3_SDCFG_POLL 0x08000 /* hd_dreq polarity control */ +#define HPC3_SDCFG_ERLY 0x30000 /* hd_dreq behavior control bits */ + + volatile u32 pconfig; /* PIO configuration register */ +#define HPC3_SPCFG_P3 0x0003 /* Cycles to spend in P3 state */ +#define HPC3_SPCFG_P2W 0x001c /* Cycles to spend in P2 state for writes */ +#define HPC3_SPCFG_P2R 0x01e0 /* Cycles to spend in P2 state for reads */ +#define HPC3_SPCFG_P1 0x0e00 /* Cycles to spend in P1 state */ +#define HPC3_SPCFG_HW 0x1000 /* Enable 16-bit halfword PIO accesses to scsi */ +#define HPC3_SPCFG_SWAP 0x2000 /* Byte swap all PIO accesses */ +#define HPC3_SPCFG_EPAR 0x4000 /* Enable parity checking for PIO */ +#define HPC3_SPCFG_FUJI 0x8000 /* Fujitsu scsi controller mode for faster dma/pio */ + + u32 _unused1[0x1000/4 - 6]; /* padding */ +}; + +/* SEEQ ethernet HPC3 registers, only one seeq per HPC3. */ +struct hpc3_ethregs { + /* Receiver registers. */ + volatile u32 rx_cbptr; /* current dma buffer ptr, diagnostic use only */ + volatile u32 rx_ndptr; /* next dma descriptor ptr */ + u32 _unused0[0x1000/4 - 2]; /* padding */ + volatile u32 rx_bcd; /* byte count info */ +#define HPC3_ERXBCD_BCNTMSK 0x00003fff /* bytes to be sent to memory */ +#define HPC3_ERXBCD_XIE 0x20000000 /* HPC3 interrupts cpu at end of this buf */ +#define HPC3_ERXBCD_EOX 0x80000000 /* flags this as end of descriptor chain */ + + volatile u32 rx_ctrl; /* control register */ +#define HPC3_ERXCTRL_STAT50 0x0000003f /* Receive status reg bits of Seeq8003 */ +#define HPC3_ERXCTRL_STAT6 0x00000040 /* Rdonly irq status */ +#define HPC3_ERXCTRL_STAT7 0x00000080 /* Rdonlt old/new status bit from Seeq */ +#define HPC3_ERXCTRL_ENDIAN 0x00000100 /* Endian for dma channel, little=1 big=0 */ +#define HPC3_ERXCTRL_ACTIVE 0x00000200 /* Tells if DMA transfer is in progress */ +#define HPC3_ERXCTRL_AMASK 0x00000400 /* Tells if ACTIVE inhibits PIO's to hpc3 */ +#define HPC3_ERXCTRL_RBO 0x00000800 /* Receive buffer overflow if set to 1 */ + + volatile u32 rx_gfptr; /* current GIO fifo ptr */ + volatile u32 rx_dfptr; /* current device fifo ptr */ + u32 _unused1; /* padding */ + volatile u32 reset; /* reset register */ +#define HPC3_ERST_CRESET 0x1 /* Reset dma channel and external controller */ +#define HPC3_ERST_CLRIRQ 0x2 /* Clear channel interrupt */ +#define HPC3_ERST_LBACK 0x4 /* Enable diagnostic loopback mode of Seeq8003 */ + + volatile u32 dconfig; /* DMA configuration register */ +#define HPC3_EDCFG_D1 0x0000f /* Cycles to spend in D1 state for PIO */ +#define HPC3_EDCFG_D2 0x000f0 /* Cycles to spend in D2 state for PIO */ +#define HPC3_EDCFG_D3 0x00f00 /* Cycles to spend in D3 state for PIO */ +#define HPC3_EDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */ +#define HPC3_EDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */ +#define HPC3_EDCFG_FEOP 0x04000 /* Bad packet marker timeout enable */ +#define HPC3_EDCFG_FIRQ 0x08000 /* Another bad packet timeout enable */ +#define HPC3_EDCFG_PTO 0x30000 /* Programmed timeout value for above two */ + + volatile u32 pconfig; /* PIO configuration register */ +#define HPC3_EPCFG_P1 0x000f /* Cycles to spend in P1 state for PIO */ +#define HPC3_EPCFG_P2 0x00f0 /* Cycles to spend in P2 state for PIO */ +#define HPC3_EPCFG_P3 0x0f00 /* Cycles to spend in P3 state for PIO */ +#define HPC3_EPCFG_TST 0x1000 /* Diagnistic ram test feature bit */ + + u32 _unused2[0x1000/4 - 8]; /* padding */ + + /* Transmitter registers. */ + volatile u32 tx_cbptr; /* current dma buffer ptr, diagnostic use only */ + volatile u32 tx_ndptr; /* next dma descriptor ptr */ + u32 _unused3[0x1000/4 - 2]; /* padding */ + volatile u32 tx_bcd; /* byte count info */ +#define HPC3_ETXBCD_BCNTMSK 0x00003fff /* bytes to be read from memory */ +#define HPC3_ETXBCD_ESAMP 0x10000000 /* if set, too late to add descriptor */ +#define HPC3_ETXBCD_XIE 0x20000000 /* Interrupt cpu at end of cur desc */ +#define HPC3_ETXBCD_EOP 0x40000000 /* Last byte of cur buf is end of packet */ +#define HPC3_ETXBCD_EOX 0x80000000 /* This buf is the end of desc chain */ + + volatile u32 tx_ctrl; /* control register */ +#define HPC3_ETXCTRL_STAT30 0x0000000f /* Rdonly copy of seeq tx stat reg */ +#define HPC3_ETXCTRL_STAT4 0x00000010 /* Indicate late collision occurred */ +#define HPC3_ETXCTRL_STAT75 0x000000e0 /* Rdonly irq status from seeq */ +#define HPC3_ETXCTRL_ENDIAN 0x00000100 /* DMA channel endian mode, 1=little 0=big */ +#define HPC3_ETXCTRL_ACTIVE 0x00000200 /* DMA tx channel is active */ +#define HPC3_ETXCTRL_AMASK 0x00000400 /* Indicates ACTIVE inhibits PIO's */ + + volatile u32 tx_gfptr; /* current GIO fifo ptr */ + volatile u32 tx_dfptr; /* current device fifo ptr */ + u32 _unused4[0x1000/4 - 4]; /* padding */ +}; + +struct hpc3_regs { + /* First regs for the PBUS 8 dma channels. */ + struct hpc3_pbus_dmacregs pbdma[8]; + + /* Now the HPC scsi registers, we get two scsi reg sets. */ + struct hpc3_scsiregs scsi_chan0, scsi_chan1; + + /* The SEEQ hpc3 ethernet dma/control registers. */ + struct hpc3_ethregs ethregs; + + /* Here are where the hpc3 fifo's can be directly accessed + * via PIO accesses. Under normal operation we never stick + * our grubby paws in here so it's just padding. */ + u32 _unused0[0x18000/4]; + + /* HPC3 irq status regs. Due to a peculiar bug you need to + * look at two different register addresses to get at all of + * the status bits. The first reg can only reliably report + * bits 4:0 of the status, and the second reg can only + * reliably report bits 9:5 of the hpc3 irq status. I told + * you it was a peculiar bug. ;-) + */ + volatile u32 istat0; /* Irq status, only bits <4:0> reliable. */ +#define HPC3_ISTAT_PBIMASK 0x0ff /* irq bits for pbus devs 0 --> 7 */ +#define HPC3_ISTAT_SC0MASK 0x100 /* irq bit for scsi channel 0 */ +#define HPC3_ISTAT_SC1MASK 0x200 /* irq bit for scsi channel 1 */ + + volatile u32 gio_misc; /* GIO misc control bits. */ +#define HPC3_GIOMISC_ERTIME 0x1 /* Enable external timer real time. */ +#define HPC3_GIOMISC_DENDIAN 0x2 /* dma descriptor endian, 1=lit 0=big */ + + u32 eeprom; /* EEPROM data reg. */ +#define HPC3_EEPROM_EPROT 0x01 /* Protect register enable */ +#define HPC3_EEPROM_CSEL 0x02 /* Chip select */ +#define HPC3_EEPROM_ECLK 0x04 /* EEPROM clock */ +#define HPC3_EEPROM_DATO 0x08 /* Data out */ +#define HPC3_EEPROM_DATI 0x10 /* Data in */ + + volatile u32 istat1; /* Irq status, only bits <9:5> reliable. */ + volatile u32 bestat; /* Bus error interrupt status reg. */ +#define HPC3_BESTAT_BLMASK 0x000ff /* Bus lane where bad parity occurred */ +#define HPC3_BESTAT_CTYPE 0x00100 /* Bus cycle type, 0=PIO 1=DMA */ +#define HPC3_BESTAT_PIDSHIFT 9 +#define HPC3_BESTAT_PIDMASK 0x3f700 /* DMA channel parity identifier */ + + u32 _unused1[0x14000/4 - 5]; /* padding */ + + /* Now direct PIO per-HPC3 peripheral access to external regs. */ + volatile u32 scsi0_ext[256]; /* SCSI channel 0 external regs */ + u32 _unused2[0x7c00/4]; + volatile u32 scsi1_ext[256]; /* SCSI channel 1 external regs */ + u32 _unused3[0x7c00/4]; + volatile u32 eth_ext[320]; /* Ethernet external registers */ + u32 _unused4[0x3b00/4]; + + /* Per-peripheral device external registers and DMA/PIO control. */ + volatile u32 pbus_extregs[16][256]; + volatile u32 pbus_dmacfg[8][128]; + /* Cycles to spend in D3 for reads */ +#define HPC3_DMACFG_D3R_MASK 0x00000001 +#define HPC3_DMACFG_D3R_SHIFT 0 + /* Cycles to spend in D4 for reads */ +#define HPC3_DMACFG_D4R_MASK 0x0000001e +#define HPC3_DMACFG_D4R_SHIFT 1 + /* Cycles to spend in D5 for reads */ +#define HPC3_DMACFG_D5R_MASK 0x000001e0 +#define HPC3_DMACFG_D5R_SHIFT 5 + /* Cycles to spend in D3 for writes */ +#define HPC3_DMACFG_D3W_MASK 0x00000200 +#define HPC3_DMACFG_D3W_SHIFT 9 + /* Cycles to spend in D4 for writes */ +#define HPC3_DMACFG_D4W_MASK 0x00003c00 +#define HPC3_DMACFG_D4W_SHIFT 10 + /* Cycles to spend in D5 for writes */ +#define HPC3_DMACFG_D5W_MASK 0x0003c000 +#define HPC3_DMACFG_D5W_SHIFT 14 + /* Enable 16-bit DMA access mode */ +#define HPC3_DMACFG_DS16 0x00040000 + /* Places halfwords on high 16 bits of bus */ +#define HPC3_DMACFG_EVENHI 0x00080000 + /* Make this device real time */ +#define HPC3_DMACFG_RTIME 0x00200000 + /* 5 bit burst count for DMA device */ +#define HPC3_DMACFG_BURST_MASK 0x07c00000 +#define HPC3_DMACFG_BURST_SHIFT 22 + /* Use live pbus_dreq unsynchronized signal */ +#define HPC3_DMACFG_DRQLIVE 0x08000000 + volatile u32 pbus_piocfg[16][64]; + /* Cycles to spend in P2 state for reads */ +#define HPC3_PIOCFG_P2R_MASK 0x00001 +#define HPC3_PIOCFG_P2R_SHIFT 0 + /* Cycles to spend in P3 state for reads */ +#define HPC3_PIOCFG_P3R_MASK 0x0001e +#define HPC3_PIOCFG_P3R_SHIFT 1 + /* Cycles to spend in P4 state for reads */ +#define HPC3_PIOCFG_P4R_MASK 0x001e0 +#define HPC3_PIOCFG_P4R_SHIFT 5 + /* Cycles to spend in P2 state for writes */ +#define HPC3_PIOCFG_P2W_MASK 0x00200 +#define HPC3_PIOCFG_P2W_SHIFT 9 + /* Cycles to spend in P3 state for writes */ +#define HPC3_PIOCFG_P3W_MASK 0x03c00 +#define HPC3_PIOCFG_P3W_SHIFT 10 + /* Cycles to spend in P4 state for writes */ +#define HPC3_PIOCFG_P4W_MASK 0x3c000 +#define HPC3_PIOCFG_P4W_SHIFT 14 + /* Enable 16-bit PIO accesses */ +#define HPC3_PIOCFG_DS16 0x40000 + /* Place even address bits in bits <15:8> */ +#define HPC3_PIOCFG_EVENHI 0x80000 + + /* PBUS PROM control regs. */ + volatile u32 pbus_promwe; /* PROM write enable register */ +#define HPC3_PROM_WENAB 0x1 /* Enable writes to the PROM */ + + u32 _unused5[0x0800/4 - 1]; + volatile u32 pbus_promswap; /* Chip select swap reg */ +#define HPC3_PROM_SWAP 0x1 /* invert GIO addr bit to select prom0 or prom1 */ + + u32 _unused6[0x0800/4 - 1]; + volatile u32 pbus_gout; /* PROM general purpose output reg */ +#define HPC3_PROM_STAT 0x1 /* General purpose status bit in gout */ + + u32 _unused7[0x1000/4 - 1]; + volatile u32 rtcregs[14]; /* Dallas clock registers */ + u32 _unused8[50]; + volatile u32 bbram[8192-50-14]; /* Battery backed ram */ +}; + +/* + * It is possible to have two HPC3's within the address space on + * one machine, though only having one is more likely on an Indy. + */ +extern struct hpc3_regs *hpc3c0, *hpc3c1; +#define HPC3_CHIP0_BASE 0x1fb80000 /* physical */ +#define HPC3_CHIP1_BASE 0x1fb00000 /* physical */ + +extern void sgihpc_init(void); + +#endif /* _SGI_HPC3_H */ diff --git a/arch/mips/include/asm/sgi/ioc.h b/arch/mips/include/asm/sgi/ioc.h new file mode 100644 index 00000000000..343ed15f8dc --- /dev/null +++ b/arch/mips/include/asm/sgi/ioc.h @@ -0,0 +1,200 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * ioc.h: Definitions for SGI I/O Controller + * + * Copyright (C) 1996 David S. Miller + * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle + * Copyright (C) 2001, 2003 Ladislav Michl + */ + +#ifndef _SGI_IOC_H +#define _SGI_IOC_H + +#include +#include + +/* + * All registers are 8-bit wide alligned on 32-bit boundary. Bad things + * happen if you try word access them. You have been warned. + */ + +struct sgioc_uart_regs { + u8 _ctrl1[3]; + volatile u8 ctrl1; + u8 _data1[3]; + volatile u8 data1; + u8 _ctrl2[3]; + volatile u8 ctrl2; + u8 _data2[3]; + volatile u8 data2; +}; + +struct sgioc_keyb_regs { + u8 _data[3]; + volatile u8 data; + u8 _command[3]; + volatile u8 command; +}; + +struct sgint_regs { + u8 _istat0[3]; + volatile u8 istat0; /* Interrupt status zero */ +#define SGINT_ISTAT0_FFULL 0x01 +#define SGINT_ISTAT0_SCSI0 0x02 +#define SGINT_ISTAT0_SCSI1 0x04 +#define SGINT_ISTAT0_ENET 0x08 +#define SGINT_ISTAT0_GFXDMA 0x10 +#define SGINT_ISTAT0_PPORT 0x20 +#define SGINT_ISTAT0_HPC2 0x40 +#define SGINT_ISTAT0_LIO2 0x80 + u8 _imask0[3]; + volatile u8 imask0; /* Interrupt mask zero */ + u8 _istat1[3]; + volatile u8 istat1; /* Interrupt status one */ +#define SGINT_ISTAT1_ISDNI 0x01 +#define SGINT_ISTAT1_PWR 0x02 +#define SGINT_ISTAT1_ISDNH 0x04 +#define SGINT_ISTAT1_LIO3 0x08 +#define SGINT_ISTAT1_HPC3 0x10 +#define SGINT_ISTAT1_AFAIL 0x20 +#define SGINT_ISTAT1_VIDEO 0x40 +#define SGINT_ISTAT1_GIO2 0x80 + u8 _imask1[3]; + volatile u8 imask1; /* Interrupt mask one */ + u8 _vmeistat[3]; + volatile u8 vmeistat; /* VME interrupt status */ + u8 _cmeimask0[3]; + volatile u8 cmeimask0; /* VME interrupt mask zero */ + u8 _cmeimask1[3]; + volatile u8 cmeimask1; /* VME interrupt mask one */ + u8 _cmepol[3]; + volatile u8 cmepol; /* VME polarity */ + u8 _tclear[3]; + volatile u8 tclear; + u8 _errstat[3]; + volatile u8 errstat; /* Error status reg, reserved on INT2 */ + u32 _unused0[2]; + u8 _tcnt0[3]; + volatile u8 tcnt0; /* counter 0 */ + u8 _tcnt1[3]; + volatile u8 tcnt1; /* counter 1 */ + u8 _tcnt2[3]; + volatile u8 tcnt2; /* counter 2 */ + u8 _tcword[3]; + volatile u8 tcword; /* control word */ +#define SGINT_TCWORD_BCD 0x01 /* Use BCD mode for counters */ +#define SGINT_TCWORD_MMASK 0x0e /* Mode bitmask. */ +#define SGINT_TCWORD_MITC 0x00 /* IRQ on terminal count (doesn't work) */ +#define SGINT_TCWORD_MOS 0x02 /* One-shot IRQ mode. */ +#define SGINT_TCWORD_MRGEN 0x04 /* Normal rate generation */ +#define SGINT_TCWORD_MSWGEN 0x06 /* Square wave generator mode */ +#define SGINT_TCWORD_MSWST 0x08 /* Software strobe */ +#define SGINT_TCWORD_MHWST 0x0a /* Hardware strobe */ +#define SGINT_TCWORD_CMASK 0x30 /* Command mask */ +#define SGINT_TCWORD_CLAT 0x00 /* Latch command */ +#define SGINT_TCWORD_CLSB 0x10 /* LSB read/write */ +#define SGINT_TCWORD_CMSB 0x20 /* MSB read/write */ +#define SGINT_TCWORD_CALL 0x30 /* Full counter read/write */ +#define SGINT_TCWORD_CNT0 0x00 /* Select counter zero */ +#define SGINT_TCWORD_CNT1 0x40 /* Select counter one */ +#define SGINT_TCWORD_CNT2 0x80 /* Select counter two */ +#define SGINT_TCWORD_CRBCK 0xc0 /* Readback command */ +}; + +/* + * The timer is the good old 8254. Unlike in PCs it's clocked at exactly 1MHz + */ +#define SGINT_TIMER_CLOCK 1000000 + +/* + * This is the constant we're using for calibrating the counter. + */ +#define SGINT_TCSAMP_COUNTER ((SGINT_TIMER_CLOCK / HZ) + 255) + +/* We need software copies of these because they are write only. */ +extern u8 sgi_ioc_reset, sgi_ioc_write; + +struct sgioc_regs { + struct pi1_regs pport; + u32 _unused0[2]; + struct sgioc_uart_regs uart; + struct sgioc_keyb_regs kbdmouse; + u8 _gcsel[3]; + volatile u8 gcsel; + u8 _genctrl[3]; + volatile u8 genctrl; + u8 _panel[3]; + volatile u8 panel; +#define SGIOC_PANEL_POWERON 0x01 +#define SGIOC_PANEL_POWERINTR 0x02 +#define SGIOC_PANEL_VOLDNINTR 0x10 +#define SGIOC_PANEL_VOLDNHOLD 0x20 +#define SGIOC_PANEL_VOLUPINTR 0x40 +#define SGIOC_PANEL_VOLUPHOLD 0x80 + u32 _unused1; + u8 _sysid[3]; + volatile u8 sysid; +#define SGIOC_SYSID_FULLHOUSE 0x01 +#define SGIOC_SYSID_BOARDREV(x) (((x) & 0x1e) >> 1) +#define SGIOC_SYSID_CHIPREV(x) (((x) & 0xe0) >> 5) + u32 _unused2; + u8 _read[3]; + volatile u8 read; + u32 _unused3; + u8 _dmasel[3]; + volatile u8 dmasel; +#define SGIOC_DMASEL_SCLK10MHZ 0x00 /* use 10MHZ serial clock */ +#define SGIOC_DMASEL_ISDNB 0x01 /* enable isdn B */ +#define SGIOC_DMASEL_ISDNA 0x02 /* enable isdn A */ +#define SGIOC_DMASEL_PPORT 0x04 /* use parallel DMA */ +#define SGIOC_DMASEL_SCLK667MHZ 0x10 /* use 6.67MHZ serial clock */ +#define SGIOC_DMASEL_SCLKEXT 0x20 /* use external serial clock */ + u32 _unused4; + u8 _reset[3]; + volatile u8 reset; +#define SGIOC_RESET_PPORT 0x01 /* 0=parport reset, 1=nornal */ +#define SGIOC_RESET_KBDMOUSE 0x02 /* 0=kbdmouse reset, 1=normal */ +#define SGIOC_RESET_EISA 0x04 /* 0=eisa reset, 1=normal */ +#define SGIOC_RESET_ISDN 0x08 /* 0=isdn reset, 1=normal */ +#define SGIOC_RESET_LC0OFF 0x10 /* guiness: turn led off (red, else green) */ +#define SGIOC_RESET_LC1OFF 0x20 /* guiness: turn led off (green, else amber) */ + u32 _unused5; + u8 _write[3]; + volatile u8 write; +#define SGIOC_WRITE_NTHRESH 0x01 /* use 4.5db threshhold */ +#define SGIOC_WRITE_TPSPEED 0x02 /* use 100ohm TP speed */ +#define SGIOC_WRITE_EPSEL 0x04 /* force cable mode: 1=AUI 0=TP */ +#define SGIOC_WRITE_EASEL 0x08 /* 1=autoselect 0=manual cable selection */ +#define SGIOC_WRITE_U1AMODE 0x10 /* 1=PC 0=MAC UART mode */ +#define SGIOC_WRITE_U0AMODE 0x20 /* 1=PC 0=MAC UART mode */ +#define SGIOC_WRITE_MLO 0x40 /* 1=4.75V 0=+5V */ +#define SGIOC_WRITE_MHI 0x80 /* 1=5.25V 0=+5V */ + u32 _unused6; + struct sgint_regs int3; + u32 _unused7[16]; + volatile u32 extio; /* FullHouse only */ +#define EXTIO_S0_IRQ_3 0x8000 /* S0: vid.vsync */ +#define EXTIO_S0_IRQ_2 0x4000 /* S0: gfx.fifofull */ +#define EXTIO_S0_IRQ_1 0x2000 /* S0: gfx.int */ +#define EXTIO_S0_RETRACE 0x1000 +#define EXTIO_SG_IRQ_3 0x0800 /* SG: vid.vsync */ +#define EXTIO_SG_IRQ_2 0x0400 /* SG: gfx.fifofull */ +#define EXTIO_SG_IRQ_1 0x0200 /* SG: gfx.int */ +#define EXTIO_SG_RETRACE 0x0100 +#define EXTIO_GIO_33MHZ 0x0080 +#define EXTIO_EISA_BUSERR 0x0040 +#define EXTIO_MC_BUSERR 0x0020 +#define EXTIO_HPC3_BUSERR 0x0010 +#define EXTIO_S0_STAT_1 0x0008 +#define EXTIO_S0_STAT_0 0x0004 +#define EXTIO_SG_STAT_1 0x0002 +#define EXTIO_SG_STAT_0 0x0001 +}; + +extern struct sgioc_regs *sgioc; +extern struct sgint_regs *sgint; + +#endif diff --git a/arch/mips/include/asm/sgi/ip22.h b/arch/mips/include/asm/sgi/ip22.h new file mode 100644 index 00000000000..c0501f91719 --- /dev/null +++ b/arch/mips/include/asm/sgi/ip22.h @@ -0,0 +1,78 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * ip22.h: Definitions for SGI IP22 machines + * + * Copyright (C) 1996 David S. Miller + * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle + */ + +#ifndef _SGI_IP22_H +#define _SGI_IP22_H + +/* + * These are the virtual IRQ numbers, we divide all IRQ's into + * 'spaces', the 'space' determines where and how to enable/disable + * that particular IRQ on an SGI machine. HPC DMA and MC DMA interrupts + * are not supported this way. Driver is supposed to allocate HPC/MC + * interrupt as shareable and then look to proper status bit (see + * HAL2 driver). This will prevent many complications, trust me ;-) + */ + +#include +#include + +#define SGINT_EISA 0 /* 16 EISA irq levels (Indigo2) */ +#define SGINT_CPU MIPS_CPU_IRQ_BASE /* MIPS CPU define 8 interrupt sources */ +#define SGINT_LOCAL0 (SGINT_CPU+8) /* 8 local0 irq levels */ +#define SGINT_LOCAL1 (SGINT_CPU+16) /* 8 local1 irq levels */ +#define SGINT_LOCAL2 (SGINT_CPU+24) /* 8 local2 vectored irq levels */ +#define SGINT_LOCAL3 (SGINT_CPU+32) /* 8 local3 vectored irq levels */ +#define SGINT_END (SGINT_CPU+40) /* End of 'spaces' */ + +/* + * Individual interrupt definitions for the Indy and Indigo2 + */ + +#define SGI_SOFT_0_IRQ SGINT_CPU + 0 +#define SGI_SOFT_1_IRQ SGINT_CPU + 1 +#define SGI_LOCAL_0_IRQ SGINT_CPU + 2 +#define SGI_LOCAL_1_IRQ SGINT_CPU + 3 +#define SGI_8254_0_IRQ SGINT_CPU + 4 +#define SGI_8254_1_IRQ SGINT_CPU + 5 +#define SGI_BUSERR_IRQ SGINT_CPU + 6 +#define SGI_TIMER_IRQ SGINT_CPU + 7 + +#define SGI_FIFO_IRQ SGINT_LOCAL0 + 0 /* FIFO full */ +#define SGI_GIO_0_IRQ SGI_FIFO_IRQ /* GIO-0 */ +#define SGI_WD93_0_IRQ SGINT_LOCAL0 + 1 /* 1st onboard WD93 */ +#define SGI_WD93_1_IRQ SGINT_LOCAL0 + 2 /* 2nd onboard WD93 */ +#define SGI_ENET_IRQ SGINT_LOCAL0 + 3 /* onboard ethernet */ +#define SGI_MCDMA_IRQ SGINT_LOCAL0 + 4 /* MC DMA done */ +#define SGI_PARPORT_IRQ SGINT_LOCAL0 + 5 /* Parallel port */ +#define SGI_GIO_1_IRQ SGINT_LOCAL0 + 6 /* GE / GIO-1 / 2nd-HPC */ +#define SGI_MAP_0_IRQ SGINT_LOCAL0 + 7 /* Mappable interrupt 0 */ + +#define SGI_GPL0_IRQ SGINT_LOCAL1 + 0 /* General Purpose LOCAL1_N<0> */ +#define SGI_PANEL_IRQ SGINT_LOCAL1 + 1 /* front panel */ +#define SGI_GPL2_IRQ SGINT_LOCAL1 + 2 /* General Purpose LOCAL1_N<2> */ +#define SGI_MAP_1_IRQ SGINT_LOCAL1 + 3 /* Mappable interrupt 1 */ +#define SGI_HPCDMA_IRQ SGINT_LOCAL1 + 4 /* HPC DMA done */ +#define SGI_ACFAIL_IRQ SGINT_LOCAL1 + 5 /* AC fail */ +#define SGI_VINO_IRQ SGINT_LOCAL1 + 6 /* Indy VINO */ +#define SGI_GIO_2_IRQ SGINT_LOCAL1 + 7 /* Vert retrace / GIO-2 */ + +/* Mapped interrupts. These interrupts may be mapped to either 0, or 1 */ +#define SGI_VERT_IRQ SGINT_LOCAL2 + 0 /* INT3: newport vertical status */ +#define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ +#define SGI_KEYBD_IRQ SGINT_LOCAL2 + 4 /* keyboard */ +#define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ + +#define ip22_is_fullhouse() (sgioc->sysid & SGIOC_SYSID_FULLHOUSE) + +extern unsigned short ip22_eeprom_read(unsigned int *ctrl, int reg); +extern unsigned short ip22_nvram_read(int reg); + +#endif diff --git a/arch/mips/include/asm/sgi/mc.h b/arch/mips/include/asm/sgi/mc.h new file mode 100644 index 00000000000..1576c2394de --- /dev/null +++ b/arch/mips/include/asm/sgi/mc.h @@ -0,0 +1,231 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * mc.h: Definitions for SGI Memory Controller + * + * Copyright (C) 1996 David S. Miller + * Copyright (C) 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ + +#ifndef _SGI_MC_H +#define _SGI_MC_H + +struct sgimc_regs { + u32 _unused0; + volatile u32 cpuctrl0; /* CPU control register 0, readwrite */ +#define SGIMC_CCTRL0_REFS 0x0000000f /* REFS mask */ +#define SGIMC_CCTRL0_EREFRESH 0x00000010 /* Memory refresh enable */ +#define SGIMC_CCTRL0_EPERRGIO 0x00000020 /* GIO parity error enable */ +#define SGIMC_CCTRL0_EPERRMEM 0x00000040 /* Main mem parity error enable */ +#define SGIMC_CCTRL0_EPERRCPU 0x00000080 /* CPU bus parity error enable */ +#define SGIMC_CCTRL0_WDOG 0x00000100 /* Watchdog timer enable */ +#define SGIMC_CCTRL0_SYSINIT 0x00000200 /* System init bit */ +#define SGIMC_CCTRL0_GFXRESET 0x00000400 /* Graphics interface reset */ +#define SGIMC_CCTRL0_EISALOCK 0x00000800 /* Lock CPU from memory for EISA */ +#define SGIMC_CCTRL0_EPERRSCMD 0x00001000 /* SysCMD bus parity error enable */ +#define SGIMC_CCTRL0_IENAB 0x00002000 /* Allow interrupts from MC */ +#define SGIMC_CCTRL0_ESNOOP 0x00004000 /* Snooping I/O enable */ +#define SGIMC_CCTRL0_EPROMWR 0x00008000 /* Prom writes from cpu enable */ +#define SGIMC_CCTRL0_WRESETPMEM 0x00010000 /* Perform warm reset, preserves mem */ +#define SGIMC_CCTRL0_LENDIAN 0x00020000 /* Put MC in little-endian mode */ +#define SGIMC_CCTRL0_WRESETDMEM 0x00040000 /* Warm reset, destroys mem contents */ +#define SGIMC_CCTRL0_CMEMBADPAR 0x02000000 /* Generate bad perr from cpu to mem */ +#define SGIMC_CCTRL0_R4KNOCHKPARR 0x04000000 /* Don't chk parity on mem data reads */ +#define SGIMC_CCTRL0_GIOBTOB 0x08000000 /* Allow GIO back to back writes */ + u32 _unused1; + volatile u32 cpuctrl1; /* CPU control register 1, readwrite */ +#define SGIMC_CCTRL1_EGIOTIMEO 0x00000010 /* GIO bus timeout enable */ +#define SGIMC_CCTRL1_FIXEDEHPC 0x00001000 /* Fixed HPC endianness */ +#define SGIMC_CCTRL1_LITTLEHPC 0x00002000 /* Little endian HPC */ +#define SGIMC_CCTRL1_FIXEDEEXP0 0x00004000 /* Fixed EXP0 endianness */ +#define SGIMC_CCTRL1_LITTLEEXP0 0x00008000 /* Little endian EXP0 */ +#define SGIMC_CCTRL1_FIXEDEEXP1 0x00010000 /* Fixed EXP1 endianness */ +#define SGIMC_CCTRL1_LITTLEEXP1 0x00020000 /* Little endian EXP1 */ + + u32 _unused2; + volatile u32 watchdogt; /* Watchdog reg rdonly, write clears */ + + u32 _unused3; + volatile u32 systemid; /* MC system ID register, readonly */ +#define SGIMC_SYSID_MASKREV 0x0000000f /* Revision of MC controller */ +#define SGIMC_SYSID_EPRESENT 0x00000010 /* Indicates presence of EISA bus */ + + u32 _unused4[3]; + volatile u32 divider; /* Divider reg for RPSS */ + + u32 _unused5; + u32 eeprom; /* EEPROM byte reg for r4k */ +#define SGIMC_EEPROM_PRE 0x00000001 /* eeprom chip PRE pin assertion */ +#define SGIMC_EEPROM_CSEL 0x00000002 /* Active high, eeprom chip select */ +#define SGIMC_EEPROM_SECLOCK 0x00000004 /* EEPROM serial clock */ +#define SGIMC_EEPROM_SDATAO 0x00000008 /* Serial EEPROM data-out */ +#define SGIMC_EEPROM_SDATAI 0x00000010 /* Serial EEPROM data-in */ + + u32 _unused6[3]; + volatile u32 rcntpre; /* Preload refresh counter */ + + u32 _unused7; + volatile u32 rcounter; /* Readonly refresh counter */ + + u32 _unused8[13]; + volatile u32 giopar; /* Parameter word for GIO64 */ +#define SGIMC_GIOPAR_HPC64 0x00000001 /* HPC talks to GIO using 64-bits */ +#define SGIMC_GIOPAR_GFX64 0x00000002 /* GFX talks to GIO using 64-bits */ +#define SGIMC_GIOPAR_EXP064 0x00000004 /* EXP(slot0) talks using 64-bits */ +#define SGIMC_GIOPAR_EXP164 0x00000008 /* EXP(slot1) talks using 64-bits */ +#define SGIMC_GIOPAR_EISA64 0x00000010 /* EISA bus talks 64-bits to GIO */ +#define SGIMC_GIOPAR_HPC264 0x00000020 /* 2nd HPX talks 64-bits to GIO */ +#define SGIMC_GIOPAR_RTIMEGFX 0x00000040 /* GFX device has realtime attr */ +#define SGIMC_GIOPAR_RTIMEEXP0 0x00000080 /* EXP(slot0) has realtime attr */ +#define SGIMC_GIOPAR_RTIMEEXP1 0x00000100 /* EXP(slot1) has realtime attr */ +#define SGIMC_GIOPAR_MASTEREISA 0x00000200 /* EISA bus can act as bus master */ +#define SGIMC_GIOPAR_ONEBUS 0x00000400 /* Exists one GIO64 pipelined bus */ +#define SGIMC_GIOPAR_MASTERGFX 0x00000800 /* GFX can act as a bus master */ +#define SGIMC_GIOPAR_MASTEREXP0 0x00001000 /* EXP(slot0) can bus master */ +#define SGIMC_GIOPAR_MASTEREXP1 0x00002000 /* EXP(slot1) can bus master */ +#define SGIMC_GIOPAR_PLINEEXP0 0x00004000 /* EXP(slot0) has pipeline attr */ +#define SGIMC_GIOPAR_PLINEEXP1 0x00008000 /* EXP(slot1) has pipeline attr */ + + u32 _unused9; + volatile u32 cputp; /* CPU bus arb time period */ + + u32 _unused10[3]; + volatile u32 lbursttp; /* Time period for long bursts */ + + /* MC chip can drive up to 4 bank 4 SIMMs each. All SIMMs in bank must + * be the same size. The size encoding for supported SIMMs is bellow */ + u32 _unused11[9]; + volatile u32 mconfig0; /* Memory config register zero */ + u32 _unused12; + volatile u32 mconfig1; /* Memory config register one */ +#define SGIMC_MCONFIG_BASEADDR 0x000000ff /* Base address of bank*/ +#define SGIMC_MCONFIG_RMASK 0x00001f00 /* Ram config bitmask */ +#define SGIMC_MCONFIG_BVALID 0x00002000 /* Bank is valid */ +#define SGIMC_MCONFIG_SBANKS 0x00004000 /* Number of subbanks */ + + u32 _unused13; + volatile u32 cmacc; /* Mem access config for CPU */ + u32 _unused14; + volatile u32 gmacc; /* Mem access config for GIO */ + + /* This define applies to both cmacc and gmacc registers above. */ +#define SGIMC_MACC_ALIASBIG 0x20000000 /* 512MB home for alias */ + + /* Error address/status regs from GIO and CPU perspectives. */ + u32 _unused15; + volatile u32 cerr; /* Error address reg for CPU */ + u32 _unused16; + volatile u32 cstat; /* Status reg for CPU */ +#define SGIMC_CSTAT_RD 0x00000100 /* read parity error */ +#define SGIMC_CSTAT_PAR 0x00000200 /* CPU parity error */ +#define SGIMC_CSTAT_ADDR 0x00000400 /* memory bus error bad addr */ +#define SGIMC_CSTAT_SYSAD_PAR 0x00000800 /* sysad parity error */ +#define SGIMC_CSTAT_SYSCMD_PAR 0x00001000 /* syscmd parity error */ +#define SGIMC_CSTAT_BAD_DATA 0x00002000 /* bad data identifier */ +#define SGIMC_CSTAT_PAR_MASK 0x00001f00 /* parity error mask */ +#define SGIMC_CSTAT_RD_PAR (SGIMC_CSTAT_RD | SGIMC_CSTAT_PAR) + + u32 _unused17; + volatile u32 gerr; /* Error address reg for GIO */ + u32 _unused18; + volatile u32 gstat; /* Status reg for GIO */ +#define SGIMC_GSTAT_RD 0x00000100 /* read parity error */ +#define SGIMC_GSTAT_WR 0x00000200 /* write parity error */ +#define SGIMC_GSTAT_TIME 0x00000400 /* GIO bus timed out */ +#define SGIMC_GSTAT_PROM 0x00000800 /* write to PROM when PROM_EN not set */ +#define SGIMC_GSTAT_ADDR 0x00001000 /* parity error on addr cycle */ +#define SGIMC_GSTAT_BC 0x00002000 /* parity error on byte count cycle */ +#define SGIMC_GSTAT_PIO_RD 0x00004000 /* read data parity on pio */ +#define SGIMC_GSTAT_PIO_WR 0x00008000 /* write data parity on pio */ + + /* Special hard bus locking registers. */ + u32 _unused19; + volatile u32 syssembit; /* Uni-bit system semaphore */ + u32 _unused20; + volatile u32 mlock; /* Global GIO memory access lock */ + u32 _unused21; + volatile u32 elock; /* Locks EISA from GIO accesses */ + + /* GIO dma control registers. */ + u32 _unused22[15]; + volatile u32 gio_dma_trans; /* DMA mask to translation GIO addrs */ + u32 _unused23; + volatile u32 gio_dma_sbits; /* DMA GIO addr substitution bits */ + u32 _unused24; + volatile u32 dma_intr_cause; /* DMA IRQ cause indicator bits */ + u32 _unused25; + volatile u32 dma_ctrl; /* Main DMA control reg */ + + /* DMA TLB entry 0 */ + u32 _unused26[5]; + volatile u32 dtlb_hi0; + u32 _unused27; + volatile u32 dtlb_lo0; + + /* DMA TLB entry 1 */ + u32 _unused28; + volatile u32 dtlb_hi1; + u32 _unused29; + volatile u32 dtlb_lo1; + + /* DMA TLB entry 2 */ + u32 _unused30; + volatile u32 dtlb_hi2; + u32 _unused31; + volatile u32 dtlb_lo2; + + /* DMA TLB entry 3 */ + u32 _unused32; + volatile u32 dtlb_hi3; + u32 _unused33; + volatile u32 dtlb_lo3; + + u32 _unused34[0x0392]; + + u32 _unused35; + volatile u32 rpsscounter; /* Chirps at 100ns */ + + u32 _unused36[0x1000/4-2*4]; + + u32 _unused37; + volatile u32 maddronly; /* Address DMA goes at */ + u32 _unused38; + volatile u32 maddrpdeflts; /* Same as above, plus set defaults */ + u32 _unused39; + volatile u32 dmasz; /* DMA count */ + u32 _unused40; + volatile u32 ssize; /* DMA stride size */ + u32 _unused41; + volatile u32 gmaddronly; /* Set GIO DMA but don't start trans */ + u32 _unused42; + volatile u32 dmaddnpgo; /* Set GIO DMA addr + start transfer */ + u32 _unused43; + volatile u32 dmamode; /* DMA mode config bit settings */ + u32 _unused44; + volatile u32 dmaccount; /* Zoom and byte count for DMA */ + u32 _unused45; + volatile u32 dmastart; /* Pedal to the metal. */ + u32 _unused46; + volatile u32 dmarunning; /* DMA op is in progress */ + u32 _unused47; + volatile u32 maddrdefstart; /* Set dma addr, defaults, and kick it */ +}; + +extern struct sgimc_regs *sgimc; +#define SGIMC_BASE 0x1fa00000 /* physical */ + +/* Base location of the two ram banks found in IP2[0268] machines. */ +#define SGIMC_SEG0_BADDR 0x08000000 +#define SGIMC_SEG1_BADDR 0x20000000 + +/* Maximum size of the above banks are per machine. */ +#define SGIMC_SEG0_SIZE_ALL 0x10000000 /* 256MB */ +#define SGIMC_SEG1_SIZE_IP20_IP22 0x08000000 /* 128MB */ +#define SGIMC_SEG1_SIZE_IP26_IP28 0x20000000 /* 512MB */ + +extern void sgimc_init(void); + +#endif /* _SGI_MC_H */ diff --git a/arch/mips/include/asm/sgi/pi1.h b/arch/mips/include/asm/sgi/pi1.h new file mode 100644 index 00000000000..c9506915dc5 --- /dev/null +++ b/arch/mips/include/asm/sgi/pi1.h @@ -0,0 +1,71 @@ +/* + * pi1.h: Definitions for SGI PI1 parallel port + */ + +#ifndef _SGI_PI1_H +#define _SGI_PI1_H + +struct pi1_regs { + u8 _data[3]; + volatile u8 data; + u8 _ctrl[3]; + volatile u8 ctrl; +#define PI1_CTRL_STROBE_N 0x01 +#define PI1_CTRL_AFD_N 0x02 +#define PI1_CTRL_INIT_N 0x04 +#define PI1_CTRL_SLIN_N 0x08 +#define PI1_CTRL_IRQ_ENA 0x10 +#define PI1_CTRL_DIR 0x20 +#define PI1_CTRL_SEL 0x40 + u8 _status[3]; + volatile u8 status; +#define PI1_STAT_DEVID 0x03 /* bits 0-1 */ +#define PI1_STAT_NOINK 0x04 /* SGI MODE only */ +#define PI1_STAT_ERROR 0x08 +#define PI1_STAT_ONLINE 0x10 +#define PI1_STAT_PE 0x20 +#define PI1_STAT_ACK 0x40 +#define PI1_STAT_BUSY 0x80 + u8 _dmactrl[3]; + volatile u8 dmactrl; +#define PI1_DMACTRL_FIFO_EMPTY 0x01 /* fifo empty R/O */ +#define PI1_DMACTRL_ABORT 0x02 /* reset DMA and internal fifo W/O */ +#define PI1_DMACTRL_STDMODE 0x00 /* bits 2-3 */ +#define PI1_DMACTRL_SGIMODE 0x04 /* bits 2-3 */ +#define PI1_DMACTRL_RICOHMODE 0x08 /* bits 2-3 */ +#define PI1_DMACTRL_HPMODE 0x0c /* bits 2-3 */ +#define PI1_DMACTRL_BLKMODE 0x10 /* block mode */ +#define PI1_DMACTRL_FIFO_CLEAR 0x20 /* clear fifo W/O */ +#define PI1_DMACTRL_READ 0x40 /* read */ +#define PI1_DMACTRL_RUN 0x80 /* pedal to the metal */ + u8 _intstat[3]; + volatile u8 intstat; +#define PI1_INTSTAT_ACK 0x04 +#define PI1_INTSTAT_FEMPTY 0x08 +#define PI1_INTSTAT_NOINK 0x10 +#define PI1_INTSTAT_ONLINE 0x20 +#define PI1_INTSTAT_ERR 0x40 +#define PI1_INTSTAT_PE 0x80 + u8 _intmask[3]; + volatile u8 intmask; /* enabled low, reset high*/ +#define PI1_INTMASK_ACK 0x04 +#define PI1_INTMASK_FIFO_EMPTY 0x08 +#define PI1_INTMASK_NOINK 0x10 +#define PI1_INTMASK_ONLINE 0x20 +#define PI1_INTMASK_ERR 0x40 +#define PI1_INTMASK_PE 0x80 + u8 _timer1[3]; + volatile u8 timer1; +#define PI1_TIME1 0x27 + u8 _timer2[3]; + volatile u8 timer2; +#define PI1_TIME2 0x13 + u8 _timer3[3]; + volatile u8 timer3; +#define PI1_TIME3 0x10 + u8 _timer4[3]; + volatile u8 timer4; +#define PI1_TIME4 0x00 +}; + +#endif diff --git a/arch/mips/include/asm/sgi/seeq.h b/arch/mips/include/asm/sgi/seeq.h new file mode 100644 index 00000000000..af0ffd76899 --- /dev/null +++ b/arch/mips/include/asm/sgi/seeq.h @@ -0,0 +1,21 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle + */ +#ifndef __ASM_SGI_SEEQ_H +#define __ASM_SGI_SEEQ_H + +#include + +#include + +struct sgiseeq_platform_data { + struct hpc3_regs *hpc; + unsigned int irq; + unsigned char mac[ETH_ALEN]; +}; + +#endif /* __ASM_SGI_SEEQ_H */ diff --git a/arch/mips/include/asm/sgi/sgi.h b/arch/mips/include/asm/sgi/sgi.h new file mode 100644 index 00000000000..645cea7c0f8 --- /dev/null +++ b/arch/mips/include/asm/sgi/sgi.h @@ -0,0 +1,47 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * sgi.h: Definitions specific to SGI machines. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + */ +#ifndef _ASM_SGI_SGI_H +#define _ASM_SGI_SGI_H + +/* UP=UniProcessor MP=MultiProcessor(capable) */ +enum sgi_mach { + ip4, /* R2k UP */ + ip5, /* R2k MP */ + ip6, /* R3k UP */ + ip7, /* R3k MP */ + ip9, /* R3k UP */ + ip12, /* R3kA UP, Indigo */ + ip15, /* R3kA MP */ + ip17, /* R4K UP */ + ip19, /* R4K MP */ + ip20, /* R4K UP, Indigo */ + ip21, /* TFP MP */ + ip22, /* R4x00 UP, Indigo2 */ + ip25, /* R10k MP */ + ip26, /* TFP UP, Indigo2 */ + ip27, /* R10k MP, R12k MP, Origin */ + ip28, /* R10k UP, Indigo2 */ + ip30, /* Octane */ + ip32, /* O2 */ +}; + +extern enum sgi_mach sgimach; +extern void sgi_sysinit(void); + +/* Many I/O space registers are byte sized and are contained within + * one byte per word, specifically the MSB, this macro helps out. + */ +#ifdef __MIPSEL__ +#define SGI_MSB(regaddr) (regaddr) +#else +#define SGI_MSB(regaddr) ((regaddr) | 0x3) +#endif + +#endif /* _ASM_SGI_SGI_H */ diff --git a/arch/mips/include/asm/sgi/wd.h b/arch/mips/include/asm/sgi/wd.h new file mode 100644 index 00000000000..0d6c3a4da89 --- /dev/null +++ b/arch/mips/include/asm/sgi/wd.h @@ -0,0 +1,20 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle + */ +#ifndef __ASM_SGI_WD_H +#define __ASM_SGI_WD_H + +#include + +struct sgiwd93_platform_data { + unsigned int unit; + unsigned int irq; + struct hpc3_scsiregs *hregs; + unsigned char *wdregs; +}; + +#endif /* __ASM_SGI_WD_H */ diff --git a/arch/mips/include/asm/sgialib.h b/arch/mips/include/asm/sgialib.h new file mode 100644 index 00000000000..bfce5c786f1 --- /dev/null +++ b/arch/mips/include/asm/sgialib.h @@ -0,0 +1,124 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SGI ARCS firmware interface library for the Linux kernel. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 2001, 2002 Ralf Baechle (ralf@gnu.org) + */ +#ifndef _ASM_SGIALIB_H +#define _ASM_SGIALIB_H + +#include + +extern struct linux_romvec *romvec; +extern int prom_argc; + +extern LONG *_prom_argv, *_prom_envp; + +/* A 32-bit ARC PROM pass arguments and environment as 32-bit pointer. + These macros take care of sign extension. */ +#define prom_argv(index) ((char *) (long) _prom_argv[(index)]) +#define prom_argc(index) ((char *) (long) _prom_argc[(index)]) + +extern int prom_flags; + +#define PROM_FLAG_ARCS 1 +#define PROM_FLAG_USE_AS_CONSOLE 2 +#define PROM_FLAG_DONT_FREE_TEMP 4 + +/* Simple char-by-char console I/O. */ +extern void prom_putchar(char c); +extern char prom_getchar(void); + +/* Memory descriptor management. */ +#define PROM_MAX_PMEMBLOCKS 32 +struct prom_pmemblock { + LONG base; /* Within KSEG0 or XKPHYS. */ + ULONG size; /* In bytes. */ + ULONG type; /* free or prom memory */ +}; + +/* Get next memory descriptor after CURR, returns first descriptor + * in chain is CURR is NULL. + */ +extern struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr); +#define PROM_NULL_MDESC ((struct linux_mdesc *) 0) + +/* Called by prom_init to setup the physical memory pmemblock + * array. + */ +extern void prom_meminit(void); +extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); + +/* PROM device tree library routines. */ +#define PROM_NULL_COMPONENT ((pcomponent *) 0) + +/* Get sibling component of THIS. */ +extern pcomponent *ArcGetPeer(pcomponent *this); + +/* Get child component of THIS. */ +extern pcomponent *ArcGetChild(pcomponent *this); + +/* Get parent component of CHILD. */ +extern pcomponent *prom_getparent(pcomponent *child); + +/* Copy component opaque data of component THIS into BUFFER + * if component THIS has opaque data. Returns success or + * failure status. + */ +extern long prom_getcdata(void *buffer, pcomponent *this); + +/* Other misc. component routines. */ +extern pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data); +extern long prom_delcomponent(pcomponent *this); +extern pcomponent *prom_componentbypath(char *path); + +/* This is called at prom_init time to identify the + * ARC architecture we are running on + */ +extern void prom_identify_arch(void); + +/* Environment variable routines. */ +extern PCHAR ArcGetEnvironmentVariable(PCHAR name); +extern LONG ArcSetEnvironmentVariable(PCHAR name, PCHAR value); + +/* ARCS command line acquisition and parsing. */ +extern char *prom_getcmdline(void); +extern void prom_init_cmdline(void); + +/* Acquiring info about the current time, etc. */ +extern struct linux_tinfo *prom_gettinfo(void); +extern unsigned long prom_getrtime(void); + +/* File operations. */ +extern long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt); +extern long prom_open(char *name, enum linux_omode md, unsigned long *fd); +extern long prom_close(unsigned long fd); +extern LONG ArcRead(ULONG fd, PVOID buf, ULONG num, PULONG cnt); +extern long prom_getrstatus(unsigned long fd); +extern LONG ArcWrite(ULONG fd, PVOID buf, ULONG num, PULONG cnt); +extern long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm); +extern long prom_mount(char *name, enum linux_mountops op); +extern long prom_getfinfo(unsigned long fd, struct linux_finfo *buf); +extern long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk); + +/* Running stand-along programs. */ +extern long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr); +extern long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp); +extern long prom_exec(char *name, long argc, char **argv, char **envp); + +/* Misc. routines. */ +extern VOID prom_halt(VOID) __attribute__((noreturn)); +extern VOID prom_powerdown(VOID) __attribute__((noreturn)); +extern VOID prom_restart(VOID) __attribute__((noreturn)); +extern VOID ArcReboot(VOID) __attribute__((noreturn)); +extern VOID ArcEnterInteractiveMode(VOID) __attribute__((noreturn)); +extern long prom_cfgsave(VOID); +extern struct linux_sysid *prom_getsysid(VOID); +extern VOID ArcFlushAllCaches(VOID); +extern DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID); + +#endif /* _ASM_SGIALIB_H */ diff --git a/arch/mips/include/asm/sgiarcs.h b/arch/mips/include/asm/sgiarcs.h new file mode 100644 index 00000000000..721327f8860 --- /dev/null +++ b/arch/mips/include/asm/sgiarcs.h @@ -0,0 +1,548 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * ARC firmware interface defines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1999, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_SGIARCS_H +#define _ASM_SGIARCS_H + +#include +#include + +/* Various ARCS error codes. */ +#define PROM_ESUCCESS 0x00 +#define PROM_E2BIG 0x01 +#define PROM_EACCESS 0x02 +#define PROM_EAGAIN 0x03 +#define PROM_EBADF 0x04 +#define PROM_EBUSY 0x05 +#define PROM_EFAULT 0x06 +#define PROM_EINVAL 0x07 +#define PROM_EIO 0x08 +#define PROM_EISDIR 0x09 +#define PROM_EMFILE 0x0a +#define PROM_EMLINK 0x0b +#define PROM_ENAMETOOLONG 0x0c +#define PROM_ENODEV 0x0d +#define PROM_ENOENT 0x0e +#define PROM_ENOEXEC 0x0f +#define PROM_ENOMEM 0x10 +#define PROM_ENOSPC 0x11 +#define PROM_ENOTDIR 0x12 +#define PROM_ENOTTY 0x13 +#define PROM_ENXIO 0x14 +#define PROM_EROFS 0x15 +/* SGI ARCS specific errno's. */ +#define PROM_EADDRNOTAVAIL 0x1f +#define PROM_ETIMEDOUT 0x20 +#define PROM_ECONNABORTED 0x21 +#define PROM_ENOCONNECT 0x22 + +/* Device classes, types, and identifiers for prom + * device inventory queries. + */ +enum linux_devclass { + system, processor, cache, adapter, controller, peripheral, memory +}; + +enum linux_devtypes { + /* Generic stuff. */ + Arc, Cpu, Fpu, + + /* Primary insn and data caches. */ + picache, pdcache, + + /* Secondary insn, data, and combined caches. */ + sicache, sdcache, sccache, + + memdev, eisa_adapter, tc_adapter, scsi_adapter, dti_adapter, + multifunc_adapter, dsk_controller, tp_controller, cdrom_controller, + worm_controller, serial_controller, net_controller, disp_controller, + parallel_controller, ptr_controller, kbd_controller, audio_controller, + misc_controller, disk_peripheral, flpy_peripheral, tp_peripheral, + modem_peripheral, monitor_peripheral, printer_peripheral, + ptr_peripheral, kbd_peripheral, term_peripheral, line_peripheral, + net_peripheral, misc_peripheral, anon +}; + +enum linux_identifier { + bogus, ronly, removable, consin, consout, input, output +}; + +/* A prom device tree component. */ +struct linux_component { + enum linux_devclass class; /* node class */ + enum linux_devtypes type; /* node type */ + enum linux_identifier iflags; /* node flags */ + USHORT vers; /* node version */ + USHORT rev; /* node revision */ + ULONG key; /* completely magic */ + ULONG amask; /* XXX affinity mask??? */ + ULONG cdsize; /* size of configuration data */ + ULONG ilen; /* length of string identifier */ + _PULONG iname; /* string identifier */ +}; +typedef struct linux_component pcomponent; + +struct linux_sysid { + char vend[8], prod[8]; +}; + +/* ARCS prom memory descriptors. */ +enum arcs_memtypes { + arcs_eblock, /* exception block */ + arcs_rvpage, /* ARCS romvec page */ + arcs_fcontig, /* Contiguous and free */ + arcs_free, /* Generic free memory */ + arcs_bmem, /* Borken memory, don't use */ + arcs_prog, /* A loaded program resides here */ + arcs_atmp, /* ARCS temporary storage area, wish Sparc OpenBoot told this */ + arcs_aperm, /* ARCS permanent storage... */ +}; + +/* ARC has slightly different types than ARCS */ +enum arc_memtypes { + arc_eblock, /* exception block */ + arc_rvpage, /* romvec page */ + arc_free, /* Generic free memory */ + arc_bmem, /* Borken memory, don't use */ + arc_prog, /* A loaded program resides here */ + arc_atmp, /* temporary storage area */ + arc_aperm, /* permanent storage */ + arc_fcontig, /* Contiguous and free */ +}; + +union linux_memtypes { + enum arcs_memtypes arcs; + enum arc_memtypes arc; +}; + +struct linux_mdesc { + union linux_memtypes type; + ULONG base; + ULONG pages; +}; + +/* Time of day descriptor. */ +struct linux_tinfo { + unsigned short yr; + unsigned short mnth; + unsigned short day; + unsigned short hr; + unsigned short min; + unsigned short sec; + unsigned short msec; +}; + +/* ARCS virtual dirents. */ +struct linux_vdirent { + ULONG namelen; + unsigned char attr; + char fname[32]; /* XXX imperical, should be a define */ +}; + +/* Other stuff for files. */ +enum linux_omode { + rdonly, wronly, rdwr, wronly_creat, rdwr_creat, + wronly_ssede, rdwr_ssede, dirent, dirent_creat +}; + +enum linux_seekmode { + absolute, relative +}; + +enum linux_mountops { + media_load, media_unload +}; + +/* This prom has a bolixed design. */ +struct linux_bigint { +#ifdef __MIPSEL__ + u32 lo; + s32 hi; +#else /* !(__MIPSEL__) */ + s32 hi; + u32 lo; +#endif +}; + +struct linux_finfo { + struct linux_bigint begin; + struct linux_bigint end; + struct linux_bigint cur; + enum linux_devtypes dtype; + unsigned long namelen; + unsigned char attr; + char name[32]; /* XXX imperical, should be define */ +}; + +/* This describes the vector containing function pointers to the ARC + firmware functions. */ +struct linux_romvec { + LONG load; /* Load an executable image. */ + LONG invoke; /* Invoke a standalong image. */ + LONG exec; /* Load and begin execution of a + standalone image. */ + LONG halt; /* Halt the machine. */ + LONG pdown; /* Power down the machine. */ + LONG restart; /* XXX soft reset??? */ + LONG reboot; /* Reboot the machine. */ + LONG imode; /* Enter PROM interactive mode. */ + LONG _unused1; /* Was ReturnFromMain(). */ + + /* PROM device tree interface. */ + LONG next_component; + LONG child_component; + LONG parent_component; + LONG component_data; + LONG child_add; + LONG comp_del; + LONG component_by_path; + + /* Misc. stuff. */ + LONG cfg_save; + LONG get_sysid; + + /* Probing for memory. */ + LONG get_mdesc; + LONG _unused2; /* was Signal() */ + + LONG get_tinfo; + LONG get_rtime; + + /* File type operations. */ + LONG get_vdirent; + LONG open; + LONG close; + LONG read; + LONG get_rstatus; + LONG write; + LONG seek; + LONG mount; + + /* Dealing with firmware environment variables. */ + LONG get_evar; + LONG set_evar; + + LONG get_finfo; + LONG set_finfo; + + /* Miscellaneous. */ + LONG cache_flush; + LONG TestUnicodeCharacter; /* ARC; not sure if ARCS too */ + LONG GetDisplayStatus; +}; + +/* The SGI ARCS parameter block is in a fixed location for standalone + * programs to access PROM facilities easily. + */ +typedef struct _SYSTEM_PARAMETER_BLOCK { + ULONG magic; /* magic cookie */ +#define PROMBLOCK_MAGIC 0x53435241 + + ULONG len; /* length of parm block */ + USHORT ver; /* ARCS firmware version */ + USHORT rev; /* ARCS firmware revision */ + _PLONG rs_block; /* Restart block. */ + _PLONG dbg_block; /* Debug block. */ + _PLONG gevect; /* XXX General vector??? */ + _PLONG utlbvect; /* XXX UTLB vector??? */ + ULONG rveclen; /* Size of romvec struct. */ + _PVOID romvec; /* Function interface. */ + ULONG pveclen; /* Length of private vector. */ + _PVOID pvector; /* Private vector. */ + ULONG adap_cnt; /* Adapter count. */ + ULONG adap_typ0; /* First adapter type. */ + ULONG adap_vcnt0; /* Adapter 0 vector count. */ + _PVOID adap_vector; /* Adapter 0 vector ptr. */ + ULONG adap_typ1; /* Second adapter type. */ + ULONG adap_vcnt1; /* Adapter 1 vector count. */ + _PVOID adap_vector1; /* Adapter 1 vector ptr. */ + /* More adapter vectors go here... */ +} SYSTEM_PARAMETER_BLOCK, *PSYSTEM_PARAMETER_BLOCK; + +#define PROMBLOCK ((PSYSTEM_PARAMETER_BLOCK) (int)0xA0001000) +#define ROMVECTOR ((struct linux_romvec *) (long)(PROMBLOCK)->romvec) + +/* Cache layout parameter block. */ +union linux_cache_key { + struct param { +#ifdef __MIPSEL__ + unsigned short size; + unsigned char lsize; + unsigned char bsize; +#else /* !(__MIPSEL__) */ + unsigned char bsize; + unsigned char lsize; + unsigned short size; +#endif + } info; + unsigned long allinfo; +}; + +/* Configuration data. */ +struct linux_cdata { + char *name; + int mlen; + enum linux_devtypes type; +}; + +/* Common SGI ARCS firmware file descriptors. */ +#define SGIPROM_STDIN 0 +#define SGIPROM_STDOUT 1 + +/* Common SGI ARCS firmware file types. */ +#define SGIPROM_ROFILE 0x01 /* read-only file */ +#define SGIPROM_HFILE 0x02 /* hidden file */ +#define SGIPROM_SFILE 0x04 /* System file */ +#define SGIPROM_AFILE 0x08 /* Archive file */ +#define SGIPROM_DFILE 0x10 /* Directory file */ +#define SGIPROM_DELFILE 0x20 /* Deleted file */ + +/* SGI ARCS boot record information. */ +struct sgi_partition { + unsigned char flag; +#define SGIPART_UNUSED 0x00 +#define SGIPART_ACTIVE 0x80 + + unsigned char shead, ssect, scyl; /* unused */ + unsigned char systype; /* OS type, Irix or NT */ + unsigned char ehead, esect, ecyl; /* unused */ + unsigned char rsect0, rsect1, rsect2, rsect3; + unsigned char tsect0, tsect1, tsect2, tsect3; +}; + +#define SGIBBLOCK_MAGIC 0xaa55 +#define SGIBBLOCK_MAXPART 0x0004 + +struct sgi_bootblock { + unsigned char _unused[446]; + struct sgi_partition partitions[SGIBBLOCK_MAXPART]; + unsigned short magic; +}; + +/* BIOS parameter block. */ +struct sgi_bparm_block { + unsigned short bytes_sect; /* bytes per sector */ + unsigned char sect_clust; /* sectors per cluster */ + unsigned short sect_resv; /* reserved sectors */ + unsigned char nfats; /* # of allocation tables */ + unsigned short nroot_dirents; /* # of root directory entries */ + unsigned short sect_volume; /* sectors in volume */ + unsigned char media_type; /* media descriptor */ + unsigned short sect_fat; /* sectors per allocation table */ + unsigned short sect_track; /* sectors per track */ + unsigned short nheads; /* # of heads */ + unsigned short nhsects; /* # of hidden sectors */ +}; + +struct sgi_bsector { + unsigned char jmpinfo[3]; + unsigned char manuf_name[8]; + struct sgi_bparm_block info; +}; + +/* Debugging block used with SGI symmon symbolic debugger. */ +#define SMB_DEBUG_MAGIC 0xfeeddead +struct linux_smonblock { + unsigned long magic; + void (*handler)(void); /* Breakpoint routine. */ + unsigned long dtable_base; /* Base addr of dbg table. */ + int (*printf)(const char *fmt, ...); + unsigned long btable_base; /* Breakpoint table. */ + unsigned long mpflushreqs; /* SMP cache flush request list. */ + unsigned long ntab; /* Name table. */ + unsigned long stab; /* Symbol table. */ + int smax; /* Max # of symbols. */ +}; + +/* + * Macros for calling a 32-bit ARC implementation from 64-bit code + */ + +#if defined(CONFIG_64BIT) && defined(CONFIG_ARC32) + +#define __arc_clobbers \ + "$2", "$3" /* ... */, "$8", "$9", "$10", "$11", \ + "$12", "$13", "$14", "$15", "$16", "$24", "$25", "$31" + +#define ARC_CALL0(dest) \ +({ long __res; \ + long __vec = (long) romvec->dest; \ + __asm__ __volatile__( \ + "dsubu\t$29, 32\n\t" \ + "jalr\t%1\n\t" \ + "daddu\t$29, 32\n\t" \ + "move\t%0, $2" \ + : "=r" (__res), "=r" (__vec) \ + : "1" (__vec) \ + : __arc_clobbers, "$4", "$5", "$6", "$7"); \ + (unsigned long) __res; \ +}) + +#define ARC_CALL1(dest, a1) \ +({ long __res; \ + register signed int __a1 __asm__("$4") = (int) (long) (a1); \ + long __vec = (long) romvec->dest; \ + __asm__ __volatile__( \ + "dsubu\t$29, 32\n\t" \ + "jalr\t%1\n\t" \ + "daddu\t$29, 32\n\t" \ + "move\t%0, $2" \ + : "=r" (__res), "=r" (__vec) \ + : "1" (__vec), "r" (__a1) \ + : __arc_clobbers, "$5", "$6", "$7"); \ + (unsigned long) __res; \ +}) + +#define ARC_CALL2(dest, a1, a2) \ +({ long __res; \ + register signed int __a1 __asm__("$4") = (int) (long) (a1); \ + register signed int __a2 __asm__("$5") = (int) (long) (a2); \ + long __vec = (long) romvec->dest; \ + __asm__ __volatile__( \ + "dsubu\t$29, 32\n\t" \ + "jalr\t%1\n\t" \ + "daddu\t$29, 32\n\t" \ + "move\t%0, $2" \ + : "=r" (__res), "=r" (__vec) \ + : "1" (__vec), "r" (__a1), "r" (__a2) \ + : __arc_clobbers, "$6", "$7"); \ + __res; \ +}) + +#define ARC_CALL3(dest, a1, a2, a3) \ +({ long __res; \ + register signed int __a1 __asm__("$4") = (int) (long) (a1); \ + register signed int __a2 __asm__("$5") = (int) (long) (a2); \ + register signed int __a3 __asm__("$6") = (int) (long) (a3); \ + long __vec = (long) romvec->dest; \ + __asm__ __volatile__( \ + "dsubu\t$29, 32\n\t" \ + "jalr\t%1\n\t" \ + "daddu\t$29, 32\n\t" \ + "move\t%0, $2" \ + : "=r" (__res), "=r" (__vec) \ + : "1" (__vec), "r" (__a1), "r" (__a2), "r" (__a3) \ + : __arc_clobbers, "$7"); \ + __res; \ +}) + +#define ARC_CALL4(dest, a1, a2, a3, a4) \ +({ long __res; \ + register signed int __a1 __asm__("$4") = (int) (long) (a1); \ + register signed int __a2 __asm__("$5") = (int) (long) (a2); \ + register signed int __a3 __asm__("$6") = (int) (long) (a3); \ + register signed int __a4 __asm__("$7") = (int) (long) (a4); \ + long __vec = (long) romvec->dest; \ + __asm__ __volatile__( \ + "dsubu\t$29, 32\n\t" \ + "jalr\t%1\n\t" \ + "daddu\t$29, 32\n\t" \ + "move\t%0, $2" \ + : "=r" (__res), "=r" (__vec) \ + : "1" (__vec), "r" (__a1), "r" (__a2), "r" (__a3), \ + "r" (__a4) \ + : __arc_clobbers); \ + __res; \ +}) + +#define ARC_CALL5(dest, a1, a2, a3, a4, a5) \ +({ long __res; \ + register signed int __a1 __asm__("$4") = (int) (long) (a1); \ + register signed int __a2 __asm__("$5") = (int) (long) (a2); \ + register signed int __a3 __asm__("$6") = (int) (long) (a3); \ + register signed int __a4 __asm__("$7") = (int) (long) (a4); \ + register signed int __a5 = (int) (long) (a5); \ + long __vec = (long) romvec->dest; \ + __asm__ __volatile__( \ + "dsubu\t$29, 32\n\t" \ + "sw\t%7, 16($29)\n\t" \ + "jalr\t%1\n\t" \ + "daddu\t$29, 32\n\t" \ + "move\t%0, $2" \ + : "=r" (__res), "=r" (__vec) \ + : "1" (__vec), \ + "r" (__a1), "r" (__a2), "r" (__a3), "r" (__a4), \ + "r" (__a5) \ + : __arc_clobbers); \ + __res; \ +}) + +#endif /* defined(CONFIG_64BIT) && defined(CONFIG_ARC32) */ + +#if (defined(CONFIG_32BIT) && defined(CONFIG_ARC32)) || \ + (defined(CONFIG_64BIT) && defined(CONFIG_ARC64)) + +#define ARC_CALL0(dest) \ +({ long __res; \ + long (*__vec)(void) = (void *) romvec->dest; \ + \ + __res = __vec(); \ + __res; \ +}) + +#define ARC_CALL1(dest, a1) \ +({ long __res; \ + long __a1 = (long) (a1); \ + long (*__vec)(long) = (void *) romvec->dest; \ + \ + __res = __vec(__a1); \ + __res; \ +}) + +#define ARC_CALL2(dest, a1, a2) \ +({ long __res; \ + long __a1 = (long) (a1); \ + long __a2 = (long) (a2); \ + long (*__vec)(long, long) = (void *) romvec->dest; \ + \ + __res = __vec(__a1, __a2); \ + __res; \ +}) + +#define ARC_CALL3(dest, a1, a2, a3) \ +({ long __res; \ + long __a1 = (long) (a1); \ + long __a2 = (long) (a2); \ + long __a3 = (long) (a3); \ + long (*__vec)(long, long, long) = (void *) romvec->dest; \ + \ + __res = __vec(__a1, __a2, __a3); \ + __res; \ +}) + +#define ARC_CALL4(dest, a1, a2, a3, a4) \ +({ long __res; \ + long __a1 = (long) (a1); \ + long __a2 = (long) (a2); \ + long __a3 = (long) (a3); \ + long __a4 = (long) (a4); \ + long (*__vec)(long, long, long, long) = (void *) romvec->dest; \ + \ + __res = __vec(__a1, __a2, __a3, __a4); \ + __res; \ +}) + +#define ARC_CALL5(dest, a1, a2, a3, a4, a5) \ +({ long __res; \ + long __a1 = (long) (a1); \ + long __a2 = (long) (a2); \ + long __a3 = (long) (a3); \ + long __a4 = (long) (a4); \ + long __a5 = (long) (a5); \ + long (*__vec)(long, long, long, long, long); \ + __vec = (void *) romvec->dest; \ + \ + __res = __vec(__a1, __a2, __a3, __a4, __a5); \ + __res; \ +}) +#endif /* both kernel and ARC either 32-bit or 64-bit */ + +#endif /* _ASM_SGIARCS_H */ diff --git a/arch/mips/include/asm/sgidefs.h b/arch/mips/include/asm/sgidefs.h new file mode 100644 index 00000000000..876442fcfb3 --- /dev/null +++ b/arch/mips/include/asm/sgidefs.h @@ -0,0 +1,44 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1999, 2001 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +/* + * Using a Linux compiler for building Linux seems logic but not to + * everybody. + */ +#ifndef __linux__ +#error Use a Linux compiler or give up. +#endif + +/* + * Definitions for the ISA levels + * + * With the introduction of MIPS32 / MIPS64 instruction sets definitions + * MIPS ISAs are no longer subsets of each other. Therefore comparisons + * on these symbols except with == may result in unexpected results and + * are forbidden! + */ +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 +#define _MIPS_ISA_MIPS32 6 +#define _MIPS_ISA_MIPS64 7 + +/* + * Subprogram calling convention + */ +#define _MIPS_SIM_ABI32 1 +#define _MIPS_SIM_NABI32 2 +#define _MIPS_SIM_ABI64 3 + +#endif /* __ASM_SGIDEFS_H */ diff --git a/arch/mips/include/asm/shmbuf.h b/arch/mips/include/asm/shmbuf.h new file mode 100644 index 00000000000..f994438277b --- /dev/null +++ b/arch/mips/include/asm/shmbuf.h @@ -0,0 +1,38 @@ +#ifndef _ASM_SHMBUF_H +#define _ASM_SHMBUF_H + +/* + * The shmid64_ds structure for the MIPS architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 2 miscellaneous 32-bit rsp. 64-bit values + */ + +struct shmid64_ds { + struct ipc64_perm shm_perm; /* operation perms */ + size_t shm_segsz; /* size of segment (bytes) */ + __kernel_time_t shm_atime; /* last attach time */ + __kernel_time_t shm_dtime; /* last detach time */ + __kernel_time_t shm_ctime; /* last change time */ + __kernel_pid_t shm_cpid; /* pid of creator */ + __kernel_pid_t shm_lpid; /* pid of last operator */ + unsigned long shm_nattch; /* no. of current attaches */ + unsigned long __unused1; + unsigned long __unused2; +}; + +struct shminfo64 { + unsigned long shmmax; + unsigned long shmmin; + unsigned long shmmni; + unsigned long shmseg; + unsigned long shmall; + unsigned long __unused1; + unsigned long __unused2; + unsigned long __unused3; + unsigned long __unused4; +}; + +#endif /* _ASM_SHMBUF_H */ diff --git a/arch/mips/include/asm/shmparam.h b/arch/mips/include/asm/shmparam.h new file mode 100644 index 00000000000..09290720751 --- /dev/null +++ b/arch/mips/include/asm/shmparam.h @@ -0,0 +1,13 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef _ASM_SHMPARAM_H +#define _ASM_SHMPARAM_H + +#define __ARCH_FORCE_SHMLBA 1 + +#define SHMLBA 0x40000 /* attach addr a multiple of this */ + +#endif /* _ASM_SHMPARAM_H */ diff --git a/arch/mips/include/asm/sibyte/bcm1480_int.h b/arch/mips/include/asm/sibyte/bcm1480_int.h new file mode 100644 index 00000000000..6109557c14e --- /dev/null +++ b/arch/mips/include/asm/sibyte/bcm1480_int.h @@ -0,0 +1,312 @@ +/* ********************************************************************* + * BCM1280/BCM1480 Board Support Package + * + * Interrupt Mapper definitions File: bcm1480_int.h + * + * This module contains constants for manipulating the + * BCM1255/BCM1280/BCM1455/BCM1480's interrupt mapper and + * definitions for the interrupt sources. + * + * BCM1480 specification level: 1X55_1X80-UM100-D4 (11/24/03) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _BCM1480_INT_H +#define _BCM1480_INT_H + +#include "sb1250_defs.h" + +/* ********************************************************************* + * Interrupt Mapper Constants + ********************************************************************* */ + +/* + * The interrupt mapper deals with 128-bit logical registers that are + * implemented as pairs of 64-bit registers, with the "low" 64 bits in + * a register that has an address 0x1000 higher(!) than the + * corresponding "high" register. + * + * For appropriate registers, bit 0 of the "high" register is a + * cascade bit that summarizes (as a bit-OR) the 64 bits of the "low" + * register. + */ + +/* + * This entire file uses _BCM1480_ in all the symbols because it is + * entirely BCM1480 specific. + */ + +/* + * Interrupt sources (Table 22) + */ + +#define K_BCM1480_INT_SOURCES 128 + +#define _BCM1480_INT_HIGH(k) (k) +#define _BCM1480_INT_LOW(k) ((k)+64) + +#define K_BCM1480_INT_ADDR_TRAP _BCM1480_INT_HIGH(1) +#define K_BCM1480_INT_GPIO_0 _BCM1480_INT_HIGH(4) +#define K_BCM1480_INT_GPIO_1 _BCM1480_INT_HIGH(5) +#define K_BCM1480_INT_GPIO_2 _BCM1480_INT_HIGH(6) +#define K_BCM1480_INT_GPIO_3 _BCM1480_INT_HIGH(7) +#define K_BCM1480_INT_PCI_INTA _BCM1480_INT_HIGH(8) +#define K_BCM1480_INT_PCI_INTB _BCM1480_INT_HIGH(9) +#define K_BCM1480_INT_PCI_INTC _BCM1480_INT_HIGH(10) +#define K_BCM1480_INT_PCI_INTD _BCM1480_INT_HIGH(11) +#define K_BCM1480_INT_CYCLE_CP0 _BCM1480_INT_HIGH(12) +#define K_BCM1480_INT_CYCLE_CP1 _BCM1480_INT_HIGH(13) +#define K_BCM1480_INT_CYCLE_CP2 _BCM1480_INT_HIGH(14) +#define K_BCM1480_INT_CYCLE_CP3 _BCM1480_INT_HIGH(15) +#define K_BCM1480_INT_TIMER_0 _BCM1480_INT_HIGH(20) +#define K_BCM1480_INT_TIMER_1 _BCM1480_INT_HIGH(21) +#define K_BCM1480_INT_TIMER_2 _BCM1480_INT_HIGH(22) +#define K_BCM1480_INT_TIMER_3 _BCM1480_INT_HIGH(23) +#define K_BCM1480_INT_DM_CH_0 _BCM1480_INT_HIGH(28) +#define K_BCM1480_INT_DM_CH_1 _BCM1480_INT_HIGH(29) +#define K_BCM1480_INT_DM_CH_2 _BCM1480_INT_HIGH(30) +#define K_BCM1480_INT_DM_CH_3 _BCM1480_INT_HIGH(31) +#define K_BCM1480_INT_MAC_0 _BCM1480_INT_HIGH(36) +#define K_BCM1480_INT_MAC_0_CH1 _BCM1480_INT_HIGH(37) +#define K_BCM1480_INT_MAC_1 _BCM1480_INT_HIGH(38) +#define K_BCM1480_INT_MAC_1_CH1 _BCM1480_INT_HIGH(39) +#define K_BCM1480_INT_MAC_2 _BCM1480_INT_HIGH(40) +#define K_BCM1480_INT_MAC_2_CH1 _BCM1480_INT_HIGH(41) +#define K_BCM1480_INT_MAC_3 _BCM1480_INT_HIGH(42) +#define K_BCM1480_INT_MAC_3_CH1 _BCM1480_INT_HIGH(43) +#define K_BCM1480_INT_PMI_LOW _BCM1480_INT_HIGH(52) +#define K_BCM1480_INT_PMI_HIGH _BCM1480_INT_HIGH(53) +#define K_BCM1480_INT_PMO_LOW _BCM1480_INT_HIGH(54) +#define K_BCM1480_INT_PMO_HIGH _BCM1480_INT_HIGH(55) +#define K_BCM1480_INT_MBOX_0_0 _BCM1480_INT_HIGH(56) +#define K_BCM1480_INT_MBOX_0_1 _BCM1480_INT_HIGH(57) +#define K_BCM1480_INT_MBOX_0_2 _BCM1480_INT_HIGH(58) +#define K_BCM1480_INT_MBOX_0_3 _BCM1480_INT_HIGH(59) +#define K_BCM1480_INT_MBOX_1_0 _BCM1480_INT_HIGH(60) +#define K_BCM1480_INT_MBOX_1_1 _BCM1480_INT_HIGH(61) +#define K_BCM1480_INT_MBOX_1_2 _BCM1480_INT_HIGH(62) +#define K_BCM1480_INT_MBOX_1_3 _BCM1480_INT_HIGH(63) + +#define K_BCM1480_INT_BAD_ECC _BCM1480_INT_LOW(1) +#define K_BCM1480_INT_COR_ECC _BCM1480_INT_LOW(2) +#define K_BCM1480_INT_IO_BUS _BCM1480_INT_LOW(3) +#define K_BCM1480_INT_PERF_CNT _BCM1480_INT_LOW(4) +#define K_BCM1480_INT_SW_PERF_CNT _BCM1480_INT_LOW(5) +#define K_BCM1480_INT_TRACE_FREEZE _BCM1480_INT_LOW(6) +#define K_BCM1480_INT_SW_TRACE_FREEZE _BCM1480_INT_LOW(7) +#define K_BCM1480_INT_WATCHDOG_TIMER_0 _BCM1480_INT_LOW(8) +#define K_BCM1480_INT_WATCHDOG_TIMER_1 _BCM1480_INT_LOW(9) +#define K_BCM1480_INT_WATCHDOG_TIMER_2 _BCM1480_INT_LOW(10) +#define K_BCM1480_INT_WATCHDOG_TIMER_3 _BCM1480_INT_LOW(11) +#define K_BCM1480_INT_PCI_ERROR _BCM1480_INT_LOW(16) +#define K_BCM1480_INT_PCI_RESET _BCM1480_INT_LOW(17) +#define K_BCM1480_INT_NODE_CONTROLLER _BCM1480_INT_LOW(18) +#define K_BCM1480_INT_HOST_BRIDGE _BCM1480_INT_LOW(19) +#define K_BCM1480_INT_PORT_0_FATAL _BCM1480_INT_LOW(20) +#define K_BCM1480_INT_PORT_0_NONFATAL _BCM1480_INT_LOW(21) +#define K_BCM1480_INT_PORT_1_FATAL _BCM1480_INT_LOW(22) +#define K_BCM1480_INT_PORT_1_NONFATAL _BCM1480_INT_LOW(23) +#define K_BCM1480_INT_PORT_2_FATAL _BCM1480_INT_LOW(24) +#define K_BCM1480_INT_PORT_2_NONFATAL _BCM1480_INT_LOW(25) +#define K_BCM1480_INT_LDT_SMI _BCM1480_INT_LOW(32) +#define K_BCM1480_INT_LDT_NMI _BCM1480_INT_LOW(33) +#define K_BCM1480_INT_LDT_INIT _BCM1480_INT_LOW(34) +#define K_BCM1480_INT_LDT_STARTUP _BCM1480_INT_LOW(35) +#define K_BCM1480_INT_LDT_EXT _BCM1480_INT_LOW(36) +#define K_BCM1480_INT_SMB_0 _BCM1480_INT_LOW(40) +#define K_BCM1480_INT_SMB_1 _BCM1480_INT_LOW(41) +#define K_BCM1480_INT_PCMCIA _BCM1480_INT_LOW(42) +#define K_BCM1480_INT_UART_0 _BCM1480_INT_LOW(44) +#define K_BCM1480_INT_UART_1 _BCM1480_INT_LOW(45) +#define K_BCM1480_INT_UART_2 _BCM1480_INT_LOW(46) +#define K_BCM1480_INT_UART_3 _BCM1480_INT_LOW(47) +#define K_BCM1480_INT_GPIO_4 _BCM1480_INT_LOW(52) +#define K_BCM1480_INT_GPIO_5 _BCM1480_INT_LOW(53) +#define K_BCM1480_INT_GPIO_6 _BCM1480_INT_LOW(54) +#define K_BCM1480_INT_GPIO_7 _BCM1480_INT_LOW(55) +#define K_BCM1480_INT_GPIO_8 _BCM1480_INT_LOW(56) +#define K_BCM1480_INT_GPIO_9 _BCM1480_INT_LOW(57) +#define K_BCM1480_INT_GPIO_10 _BCM1480_INT_LOW(58) +#define K_BCM1480_INT_GPIO_11 _BCM1480_INT_LOW(59) +#define K_BCM1480_INT_GPIO_12 _BCM1480_INT_LOW(60) +#define K_BCM1480_INT_GPIO_13 _BCM1480_INT_LOW(61) +#define K_BCM1480_INT_GPIO_14 _BCM1480_INT_LOW(62) +#define K_BCM1480_INT_GPIO_15 _BCM1480_INT_LOW(63) + +/* + * Mask values for each interrupt + */ + +#define _BCM1480_INT_MASK(w, n) _SB_MAKEMASK(w, ((n) & 0x3F)) +#define _BCM1480_INT_MASK1(n) _SB_MAKEMASK1(((n) & 0x3F)) +#define _BCM1480_INT_OFFSET(n) (((n) & 0x40) << 6) + +#define M_BCM1480_INT_CASCADE _BCM1480_INT_MASK1(_BCM1480_INT_HIGH(0)) + +#define M_BCM1480_INT_ADDR_TRAP _BCM1480_INT_MASK1(K_BCM1480_INT_ADDR_TRAP) +#define M_BCM1480_INT_GPIO_0 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_0) +#define M_BCM1480_INT_GPIO_1 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_1) +#define M_BCM1480_INT_GPIO_2 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_2) +#define M_BCM1480_INT_GPIO_3 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_3) +#define M_BCM1480_INT_PCI_INTA _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTA) +#define M_BCM1480_INT_PCI_INTB _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTB) +#define M_BCM1480_INT_PCI_INTC _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTC) +#define M_BCM1480_INT_PCI_INTD _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTD) +#define M_BCM1480_INT_CYCLE_CP0 _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP0) +#define M_BCM1480_INT_CYCLE_CP1 _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP1) +#define M_BCM1480_INT_CYCLE_CP2 _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP2) +#define M_BCM1480_INT_CYCLE_CP3 _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP3) +#define M_BCM1480_INT_TIMER_0 _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_0) +#define M_BCM1480_INT_TIMER_1 _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_1) +#define M_BCM1480_INT_TIMER_2 _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_2) +#define M_BCM1480_INT_TIMER_3 _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_3) +#define M_BCM1480_INT_DM_CH_0 _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_0) +#define M_BCM1480_INT_DM_CH_1 _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_1) +#define M_BCM1480_INT_DM_CH_2 _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_2) +#define M_BCM1480_INT_DM_CH_3 _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_3) +#define M_BCM1480_INT_MAC_0 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_0) +#define M_BCM1480_INT_MAC_0_CH1 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_0_CH1) +#define M_BCM1480_INT_MAC_1 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_1) +#define M_BCM1480_INT_MAC_1_CH1 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_1_CH1) +#define M_BCM1480_INT_MAC_2 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_2) +#define M_BCM1480_INT_MAC_2_CH1 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_2_CH1) +#define M_BCM1480_INT_MAC_3 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_3) +#define M_BCM1480_INT_MAC_3_CH1 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_3_CH1) +#define M_BCM1480_INT_PMI_LOW _BCM1480_INT_MASK1(K_BCM1480_INT_PMI_LOW) +#define M_BCM1480_INT_PMI_HIGH _BCM1480_INT_MASK1(K_BCM1480_INT_PMI_HIGH) +#define M_BCM1480_INT_PMO_LOW _BCM1480_INT_MASK1(K_BCM1480_INT_PMO_LOW) +#define M_BCM1480_INT_PMO_HIGH _BCM1480_INT_MASK1(K_BCM1480_INT_PMO_HIGH) +#define M_BCM1480_INT_MBOX_ALL _BCM1480_INT_MASK(8, K_BCM1480_INT_MBOX_0_0) +#define M_BCM1480_INT_MBOX_0_0 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_0) +#define M_BCM1480_INT_MBOX_0_1 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_1) +#define M_BCM1480_INT_MBOX_0_2 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_2) +#define M_BCM1480_INT_MBOX_0_3 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_3) +#define M_BCM1480_INT_MBOX_1_0 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_0) +#define M_BCM1480_INT_MBOX_1_1 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_1) +#define M_BCM1480_INT_MBOX_1_2 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_2) +#define M_BCM1480_INT_MBOX_1_3 _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_3) +#define M_BCM1480_INT_BAD_ECC _BCM1480_INT_MASK1(K_BCM1480_INT_BAD_ECC) +#define M_BCM1480_INT_COR_ECC _BCM1480_INT_MASK1(K_BCM1480_INT_COR_ECC) +#define M_BCM1480_INT_IO_BUS _BCM1480_INT_MASK1(K_BCM1480_INT_IO_BUS) +#define M_BCM1480_INT_PERF_CNT _BCM1480_INT_MASK1(K_BCM1480_INT_PERF_CNT) +#define M_BCM1480_INT_SW_PERF_CNT _BCM1480_INT_MASK1(K_BCM1480_INT_SW_PERF_CNT) +#define M_BCM1480_INT_TRACE_FREEZE _BCM1480_INT_MASK1(K_BCM1480_INT_TRACE_FREEZE) +#define M_BCM1480_INT_SW_TRACE_FREEZE _BCM1480_INT_MASK1(K_BCM1480_INT_SW_TRACE_FREEZE) +#define M_BCM1480_INT_WATCHDOG_TIMER_0 _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_0) +#define M_BCM1480_INT_WATCHDOG_TIMER_1 _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_1) +#define M_BCM1480_INT_WATCHDOG_TIMER_2 _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_2) +#define M_BCM1480_INT_WATCHDOG_TIMER_3 _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_3) +#define M_BCM1480_INT_PCI_ERROR _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_ERROR) +#define M_BCM1480_INT_PCI_RESET _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_RESET) +#define M_BCM1480_INT_NODE_CONTROLLER _BCM1480_INT_MASK1(K_BCM1480_INT_NODE_CONTROLLER) +#define M_BCM1480_INT_HOST_BRIDGE _BCM1480_INT_MASK1(K_BCM1480_INT_HOST_BRIDGE) +#define M_BCM1480_INT_PORT_0_FATAL _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_0_FATAL) +#define M_BCM1480_INT_PORT_0_NONFATAL _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_0_NONFATAL) +#define M_BCM1480_INT_PORT_1_FATAL _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_1_FATAL) +#define M_BCM1480_INT_PORT_1_NONFATAL _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_1_NONFATAL) +#define M_BCM1480_INT_PORT_2_FATAL _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_2_FATAL) +#define M_BCM1480_INT_PORT_2_NONFATAL _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_2_NONFATAL) +#define M_BCM1480_INT_LDT_SMI _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_SMI) +#define M_BCM1480_INT_LDT_NMI _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_NMI) +#define M_BCM1480_INT_LDT_INIT _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_INIT) +#define M_BCM1480_INT_LDT_STARTUP _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_STARTUP) +#define M_BCM1480_INT_LDT_EXT _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_EXT) +#define M_BCM1480_INT_SMB_0 _BCM1480_INT_MASK1(K_BCM1480_INT_SMB_0) +#define M_BCM1480_INT_SMB_1 _BCM1480_INT_MASK1(K_BCM1480_INT_SMB_1) +#define M_BCM1480_INT_PCMCIA _BCM1480_INT_MASK1(K_BCM1480_INT_PCMCIA) +#define M_BCM1480_INT_UART_0 _BCM1480_INT_MASK1(K_BCM1480_INT_UART_0) +#define M_BCM1480_INT_UART_1 _BCM1480_INT_MASK1(K_BCM1480_INT_UART_1) +#define M_BCM1480_INT_UART_2 _BCM1480_INT_MASK1(K_BCM1480_INT_UART_2) +#define M_BCM1480_INT_UART_3 _BCM1480_INT_MASK1(K_BCM1480_INT_UART_3) +#define M_BCM1480_INT_GPIO_4 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_4) +#define M_BCM1480_INT_GPIO_5 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_5) +#define M_BCM1480_INT_GPIO_6 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_6) +#define M_BCM1480_INT_GPIO_7 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_7) +#define M_BCM1480_INT_GPIO_8 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_8) +#define M_BCM1480_INT_GPIO_9 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_9) +#define M_BCM1480_INT_GPIO_10 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_10) +#define M_BCM1480_INT_GPIO_11 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_11) +#define M_BCM1480_INT_GPIO_12 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_12) +#define M_BCM1480_INT_GPIO_13 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_13) +#define M_BCM1480_INT_GPIO_14 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_14) +#define M_BCM1480_INT_GPIO_15 _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_15) + +/* + * Interrupt mappings (Table 18) + */ + +#define K_BCM1480_INT_MAP_I0 0 /* interrupt pins on processor */ +#define K_BCM1480_INT_MAP_I1 1 +#define K_BCM1480_INT_MAP_I2 2 +#define K_BCM1480_INT_MAP_I3 3 +#define K_BCM1480_INT_MAP_I4 4 +#define K_BCM1480_INT_MAP_I5 5 +#define K_BCM1480_INT_MAP_NMI 6 /* nonmaskable */ +#define K_BCM1480_INT_MAP_DINT 7 /* debug interrupt */ + +/* + * Interrupt LDT Set Register (Table 19) + */ + +#define S_BCM1480_INT_HT_INTMSG 0 +#define M_BCM1480_INT_HT_INTMSG _SB_MAKEMASK(3, S_BCM1480_INT_HT_INTMSG) +#define V_BCM1480_INT_HT_INTMSG(x) _SB_MAKEVALUE(x, S_BCM1480_INT_HT_INTMSG) +#define G_BCM1480_INT_HT_INTMSG(x) _SB_GETVALUE(x, S_BCM1480_INT_HT_INTMSG, M_BCM1480_INT_HT_INTMSG) + +#define K_BCM1480_INT_HT_INTMSG_FIXED 0 +#define K_BCM1480_INT_HT_INTMSG_ARBITRATED 1 +#define K_BCM1480_INT_HT_INTMSG_SMI 2 +#define K_BCM1480_INT_HT_INTMSG_NMI 3 +#define K_BCM1480_INT_HT_INTMSG_INIT 4 +#define K_BCM1480_INT_HT_INTMSG_STARTUP 5 +#define K_BCM1480_INT_HT_INTMSG_EXTINT 6 +#define K_BCM1480_INT_HT_INTMSG_RESERVED 7 + +#define M_BCM1480_INT_HT_TRIGGERMODE _SB_MAKEMASK1(3) +#define V_BCM1480_INT_HT_EDGETRIGGER 0 +#define V_BCM1480_INT_HT_LEVELTRIGGER M_BCM1480_INT_HT_TRIGGERMODE + +#define M_BCM1480_INT_HT_DESTMODE _SB_MAKEMASK1(4) +#define V_BCM1480_INT_HT_PHYSICALDEST 0 +#define V_BCM1480_INT_HT_LOGICALDEST M_BCM1480_INT_HT_DESTMODE + +#define S_BCM1480_INT_HT_INTDEST 5 +#define M_BCM1480_INT_HT_INTDEST _SB_MAKEMASK(8, S_BCM1480_INT_HT_INTDEST) +#define V_BCM1480_INT_HT_INTDEST(x) _SB_MAKEVALUE(x, S_BCM1480_INT_HT_INTDEST) +#define G_BCM1480_INT_HT_INTDEST(x) _SB_GETVALUE(x, S_BCM1480_INT_HT_INTDEST, M_BCM1480_INT_HT_INTDEST) + +#define S_BCM1480_INT_HT_VECTOR 13 +#define M_BCM1480_INT_HT_VECTOR _SB_MAKEMASK(8, S_BCM1480_INT_HT_VECTOR) +#define V_BCM1480_INT_HT_VECTOR(x) _SB_MAKEVALUE(x, S_BCM1480_INT_HT_VECTOR) +#define G_BCM1480_INT_HT_VECTOR(x) _SB_GETVALUE(x, S_BCM1480_INT_HT_VECTOR, M_BCM1480_INT_HT_VECTOR) + +/* + * Vector prefix (Table 4-7) + */ + +#define M_BCM1480_HTVECT_RAISE_INTLDT_HIGH 0x00 +#define M_BCM1480_HTVECT_RAISE_MBOX_0 0x40 +#define M_BCM1480_HTVECT_RAISE_INTLDT_LO 0x80 +#define M_BCM1480_HTVECT_RAISE_MBOX_1 0xC0 + +#endif /* _BCM1480_INT_H */ diff --git a/arch/mips/include/asm/sibyte/bcm1480_l2c.h b/arch/mips/include/asm/sibyte/bcm1480_l2c.h new file mode 100644 index 00000000000..fd75817f7ac --- /dev/null +++ b/arch/mips/include/asm/sibyte/bcm1480_l2c.h @@ -0,0 +1,176 @@ +/* ********************************************************************* + * BCM1280/BCM1480 Board Support Package + * + * L2 Cache constants and macros File: bcm1480_l2c.h + * + * This module contains constants useful for manipulating the + * level 2 cache. + * + * BCM1400 specification level: 1280-UM100-D2 (11/14/03) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _BCM1480_L2C_H +#define _BCM1480_L2C_H + +#include "sb1250_defs.h" + +/* + * Format of level 2 cache management address (Table 55) + */ + +#define S_BCM1480_L2C_MGMT_INDEX 5 +#define M_BCM1480_L2C_MGMT_INDEX _SB_MAKEMASK(12, S_BCM1480_L2C_MGMT_INDEX) +#define V_BCM1480_L2C_MGMT_INDEX(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_MGMT_INDEX) +#define G_BCM1480_L2C_MGMT_INDEX(x) _SB_GETVALUE(x, S_BCM1480_L2C_MGMT_INDEX, M_BCM1480_L2C_MGMT_INDEX) + +#define S_BCM1480_L2C_MGMT_WAY 17 +#define M_BCM1480_L2C_MGMT_WAY _SB_MAKEMASK(3, S_BCM1480_L2C_MGMT_WAY) +#define V_BCM1480_L2C_MGMT_WAY(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_MGMT_WAY) +#define G_BCM1480_L2C_MGMT_WAY(x) _SB_GETVALUE(x, S_BCM1480_L2C_MGMT_WAY, M_BCM1480_L2C_MGMT_WAY) + +#define M_BCM1480_L2C_MGMT_DIRTY _SB_MAKEMASK1(20) +#define M_BCM1480_L2C_MGMT_VALID _SB_MAKEMASK1(21) + +#define S_BCM1480_L2C_MGMT_ECC_DIAG 22 +#define M_BCM1480_L2C_MGMT_ECC_DIAG _SB_MAKEMASK(2, S_BCM1480_L2C_MGMT_ECC_DIAG) +#define V_BCM1480_L2C_MGMT_ECC_DIAG(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_MGMT_ECC_DIAG) +#define G_BCM1480_L2C_MGMT_ECC_DIAG(x) _SB_GETVALUE(x, S_BCM1480_L2C_MGMT_ECC_DIAG, M_BCM1480_L2C_MGMT_ECC_DIAG) + +#define A_BCM1480_L2C_MGMT_TAG_BASE 0x00D0000000 + +#define BCM1480_L2C_ENTRIES_PER_WAY 4096 +#define BCM1480_L2C_NUM_WAYS 8 + + +/* + * Level 2 Cache Tag register (Table 59) + */ + +#define S_BCM1480_L2C_TAG_MBZ 0 +#define M_BCM1480_L2C_TAG_MBZ _SB_MAKEMASK(5, S_BCM1480_L2C_TAG_MBZ) + +#define S_BCM1480_L2C_TAG_INDEX 5 +#define M_BCM1480_L2C_TAG_INDEX _SB_MAKEMASK(12, S_BCM1480_L2C_TAG_INDEX) +#define V_BCM1480_L2C_TAG_INDEX(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_TAG_INDEX) +#define G_BCM1480_L2C_TAG_INDEX(x) _SB_GETVALUE(x, S_BCM1480_L2C_TAG_INDEX, M_BCM1480_L2C_TAG_INDEX) + +/* Note that index bit 16 is also tag bit 40 */ +#define S_BCM1480_L2C_TAG_TAG 17 +#define M_BCM1480_L2C_TAG_TAG _SB_MAKEMASK(23, S_BCM1480_L2C_TAG_TAG) +#define V_BCM1480_L2C_TAG_TAG(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_TAG_TAG) +#define G_BCM1480_L2C_TAG_TAG(x) _SB_GETVALUE(x, S_BCM1480_L2C_TAG_TAG, M_BCM1480_L2C_TAG_TAG) + +#define S_BCM1480_L2C_TAG_ECC 40 +#define M_BCM1480_L2C_TAG_ECC _SB_MAKEMASK(6, S_BCM1480_L2C_TAG_ECC) +#define V_BCM1480_L2C_TAG_ECC(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_TAG_ECC) +#define G_BCM1480_L2C_TAG_ECC(x) _SB_GETVALUE(x, S_BCM1480_L2C_TAG_ECC, M_BCM1480_L2C_TAG_ECC) + +#define S_BCM1480_L2C_TAG_WAY 46 +#define M_BCM1480_L2C_TAG_WAY _SB_MAKEMASK(3, S_BCM1480_L2C_TAG_WAY) +#define V_BCM1480_L2C_TAG_WAY(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_TAG_WAY) +#define G_BCM1480_L2C_TAG_WAY(x) _SB_GETVALUE(x, S_BCM1480_L2C_TAG_WAY, M_BCM1480_L2C_TAG_WAY) + +#define M_BCM1480_L2C_TAG_DIRTY _SB_MAKEMASK1(49) +#define M_BCM1480_L2C_TAG_VALID _SB_MAKEMASK1(50) + +#define S_BCM1480_L2C_DATA_ECC 51 +#define M_BCM1480_L2C_DATA_ECC _SB_MAKEMASK(10, S_BCM1480_L2C_DATA_ECC) +#define V_BCM1480_L2C_DATA_ECC(x) _SB_MAKEVALUE(x, S_BCM1480_L2C_DATA_ECC) +#define G_BCM1480_L2C_DATA_ECC(x) _SB_GETVALUE(x, S_BCM1480_L2C_DATA_ECC, M_BCM1480_L2C_DATA_ECC) + + +/* + * L2 Misc0 Value Register (Table 60) + */ + +#define S_BCM1480_L2C_MISC0_WAY_REMOTE 0 +#define M_BCM1480_L2C_MISC0_WAY_REMOTE _SB_MAKEMASK(8, S_BCM1480_L2C_MISC0_WAY_REMOTE) +#define G_BCM1480_L2C_MISC0_WAY_REMOTE(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC0_WAY_REMOTE, M_BCM1480_L2C_MISC0_WAY_REMOTE) + +#define S_BCM1480_L2C_MISC0_WAY_LOCAL 8 +#define M_BCM1480_L2C_MISC0_WAY_LOCAL _SB_MAKEMASK(8, S_BCM1480_L2C_MISC0_WAY_LOCAL) +#define G_BCM1480_L2C_MISC0_WAY_LOCAL(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC0_WAY_LOCAL, M_BCM1480_L2C_MISC0_WAY_LOCAL) + +#define S_BCM1480_L2C_MISC0_WAY_ENABLE 16 +#define M_BCM1480_L2C_MISC0_WAY_ENABLE _SB_MAKEMASK(8, S_BCM1480_L2C_MISC0_WAY_ENABLE) +#define G_BCM1480_L2C_MISC0_WAY_ENABLE(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC0_WAY_ENABLE, M_BCM1480_L2C_MISC0_WAY_ENABLE) + +#define S_BCM1480_L2C_MISC0_CACHE_DISABLE 24 +#define M_BCM1480_L2C_MISC0_CACHE_DISABLE _SB_MAKEMASK(2, S_BCM1480_L2C_MISC0_CACHE_DISABLE) +#define G_BCM1480_L2C_MISC0_CACHE_DISABLE(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC0_CACHE_DISABLE, M_BCM1480_L2C_MISC0_CACHE_DISABLE) + +#define S_BCM1480_L2C_MISC0_CACHE_QUAD 26 +#define M_BCM1480_L2C_MISC0_CACHE_QUAD _SB_MAKEMASK(2, S_BCM1480_L2C_MISC0_CACHE_QUAD) +#define G_BCM1480_L2C_MISC0_CACHE_QUAD(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC0_CACHE_QUAD, M_BCM1480_L2C_MISC0_CACHE_QUAD) + +#define S_BCM1480_L2C_MISC0_MC_PRIORITY 30 +#define M_BCM1480_L2C_MISC0_MC_PRIORITY _SB_MAKEMASK1(S_BCM1480_L2C_MISC0_MC_PRIORITY) + +#define S_BCM1480_L2C_MISC0_ECC_CLEANUP 31 +#define M_BCM1480_L2C_MISC0_ECC_CLEANUP _SB_MAKEMASK1(S_BCM1480_L2C_MISC0_ECC_CLEANUP) + + +/* + * L2 Misc1 Value Register (Table 60) + */ + +#define S_BCM1480_L2C_MISC1_WAY_AGENT_0 0 +#define M_BCM1480_L2C_MISC1_WAY_AGENT_0 _SB_MAKEMASK(8, S_BCM1480_L2C_MISC1_WAY_AGENT_0) +#define G_BCM1480_L2C_MISC1_WAY_AGENT_0(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC1_WAY_AGENT_0, M_BCM1480_L2C_MISC1_WAY_AGENT_0) + +#define S_BCM1480_L2C_MISC1_WAY_AGENT_1 8 +#define M_BCM1480_L2C_MISC1_WAY_AGENT_1 _SB_MAKEMASK(8, S_BCM1480_L2C_MISC1_WAY_AGENT_1) +#define G_BCM1480_L2C_MISC1_WAY_AGENT_1(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC1_WAY_AGENT_1, M_BCM1480_L2C_MISC1_WAY_AGENT_1) + +#define S_BCM1480_L2C_MISC1_WAY_AGENT_2 16 +#define M_BCM1480_L2C_MISC1_WAY_AGENT_2 _SB_MAKEMASK(8, S_BCM1480_L2C_MISC1_WAY_AGENT_2) +#define G_BCM1480_L2C_MISC1_WAY_AGENT_2(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC1_WAY_AGENT_2, M_BCM1480_L2C_MISC1_WAY_AGENT_2) + +#define S_BCM1480_L2C_MISC1_WAY_AGENT_3 24 +#define M_BCM1480_L2C_MISC1_WAY_AGENT_3 _SB_MAKEMASK(8, S_BCM1480_L2C_MISC1_WAY_AGENT_3) +#define G_BCM1480_L2C_MISC1_WAY_AGENT_3(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC1_WAY_AGENT_3, M_BCM1480_L2C_MISC1_WAY_AGENT_3) + +#define S_BCM1480_L2C_MISC1_WAY_AGENT_4 32 +#define M_BCM1480_L2C_MISC1_WAY_AGENT_4 _SB_MAKEMASK(8, S_BCM1480_L2C_MISC1_WAY_AGENT_4) +#define G_BCM1480_L2C_MISC1_WAY_AGENT_4(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC1_WAY_AGENT_4, M_BCM1480_L2C_MISC1_WAY_AGENT_4) + + +/* + * L2 Misc2 Value Register (Table 60) + */ + +#define S_BCM1480_L2C_MISC2_WAY_AGENT_8 0 +#define M_BCM1480_L2C_MISC2_WAY_AGENT_8 _SB_MAKEMASK(8, S_BCM1480_L2C_MISC2_WAY_AGENT_8) +#define G_BCM1480_L2C_MISC2_WAY_AGENT_8(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC2_WAY_AGENT_8, M_BCM1480_L2C_MISC2_WAY_AGENT_8) + +#define S_BCM1480_L2C_MISC2_WAY_AGENT_9 8 +#define M_BCM1480_L2C_MISC2_WAY_AGENT_9 _SB_MAKEMASK(8, S_BCM1480_L2C_MISC2_WAY_AGENT_9) +#define G_BCM1480_L2C_MISC2_WAY_AGENT_9(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC2_WAY_AGENT_9, M_BCM1480_L2C_MISC2_WAY_AGENT_9) + +#define S_BCM1480_L2C_MISC2_WAY_AGENT_A 16 +#define M_BCM1480_L2C_MISC2_WAY_AGENT_A _SB_MAKEMASK(8, S_BCM1480_L2C_MISC2_WAY_AGENT_A) +#define G_BCM1480_L2C_MISC2_WAY_AGENT_A(x) _SB_GETVALUE(x, S_BCM1480_L2C_MISC2_WAY_AGENT_A, M_BCM1480_L2C_MISC2_WAY_AGENT_A) + + +#endif /* _BCM1480_L2C_H */ diff --git a/arch/mips/include/asm/sibyte/bcm1480_mc.h b/arch/mips/include/asm/sibyte/bcm1480_mc.h new file mode 100644 index 00000000000..f26a41a82b5 --- /dev/null +++ b/arch/mips/include/asm/sibyte/bcm1480_mc.h @@ -0,0 +1,984 @@ +/* ********************************************************************* + * BCM1280/BCM1480 Board Support Package + * + * Memory Controller constants File: bcm1480_mc.h + * + * This module contains constants and macros useful for + * programming the memory controller. + * + * BCM1400 specification level: 1280-UM100-D1 (11/14/03 Review Copy) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _BCM1480_MC_H +#define _BCM1480_MC_H + +#include "sb1250_defs.h" + +/* + * Memory Channel Configuration Register (Table 81) + */ + +#define S_BCM1480_MC_INTLV0 0 +#define M_BCM1480_MC_INTLV0 _SB_MAKEMASK(6, S_BCM1480_MC_INTLV0) +#define V_BCM1480_MC_INTLV0(x) _SB_MAKEVALUE(x, S_BCM1480_MC_INTLV0) +#define G_BCM1480_MC_INTLV0(x) _SB_GETVALUE(x, S_BCM1480_MC_INTLV0, M_BCM1480_MC_INTLV0) +#define V_BCM1480_MC_INTLV0_DEFAULT V_BCM1480_MC_INTLV0(0) + +#define S_BCM1480_MC_INTLV1 8 +#define M_BCM1480_MC_INTLV1 _SB_MAKEMASK(6, S_BCM1480_MC_INTLV1) +#define V_BCM1480_MC_INTLV1(x) _SB_MAKEVALUE(x, S_BCM1480_MC_INTLV1) +#define G_BCM1480_MC_INTLV1(x) _SB_GETVALUE(x, S_BCM1480_MC_INTLV1, M_BCM1480_MC_INTLV1) +#define V_BCM1480_MC_INTLV1_DEFAULT V_BCM1480_MC_INTLV1(0) + +#define S_BCM1480_MC_INTLV2 16 +#define M_BCM1480_MC_INTLV2 _SB_MAKEMASK(6, S_BCM1480_MC_INTLV2) +#define V_BCM1480_MC_INTLV2(x) _SB_MAKEVALUE(x, S_BCM1480_MC_INTLV2) +#define G_BCM1480_MC_INTLV2(x) _SB_GETVALUE(x, S_BCM1480_MC_INTLV2, M_BCM1480_MC_INTLV2) +#define V_BCM1480_MC_INTLV2_DEFAULT V_BCM1480_MC_INTLV2(0) + +#define S_BCM1480_MC_CS_MODE 32 +#define M_BCM1480_MC_CS_MODE _SB_MAKEMASK(8, S_BCM1480_MC_CS_MODE) +#define V_BCM1480_MC_CS_MODE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS_MODE) +#define G_BCM1480_MC_CS_MODE(x) _SB_GETVALUE(x, S_BCM1480_MC_CS_MODE, M_BCM1480_MC_CS_MODE) +#define V_BCM1480_MC_CS_MODE_DEFAULT V_BCM1480_MC_CS_MODE(0) + +#define V_BCM1480_MC_CONFIG_DEFAULT (V_BCM1480_MC_INTLV0_DEFAULT | \ + V_BCM1480_MC_INTLV1_DEFAULT | \ + V_BCM1480_MC_INTLV2_DEFAULT | \ + V_BCM1480_MC_CS_MODE_DEFAULT) + +#define K_BCM1480_MC_CS01_MODE 0x03 +#define K_BCM1480_MC_CS02_MODE 0x05 +#define K_BCM1480_MC_CS0123_MODE 0x0F +#define K_BCM1480_MC_CS0246_MODE 0x55 +#define K_BCM1480_MC_CS0145_MODE 0x33 +#define K_BCM1480_MC_CS0167_MODE 0xC3 +#define K_BCM1480_MC_CSFULL_MODE 0xFF + +/* + * Chip Select Start Address Register (Table 82) + */ + +#define S_BCM1480_MC_CS0_START 0 +#define M_BCM1480_MC_CS0_START _SB_MAKEMASK(12, S_BCM1480_MC_CS0_START) +#define V_BCM1480_MC_CS0_START(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS0_START) +#define G_BCM1480_MC_CS0_START(x) _SB_GETVALUE(x, S_BCM1480_MC_CS0_START, M_BCM1480_MC_CS0_START) + +#define S_BCM1480_MC_CS1_START 16 +#define M_BCM1480_MC_CS1_START _SB_MAKEMASK(12, S_BCM1480_MC_CS1_START) +#define V_BCM1480_MC_CS1_START(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS1_START) +#define G_BCM1480_MC_CS1_START(x) _SB_GETVALUE(x, S_BCM1480_MC_CS1_START, M_BCM1480_MC_CS1_START) + +#define S_BCM1480_MC_CS2_START 32 +#define M_BCM1480_MC_CS2_START _SB_MAKEMASK(12, S_BCM1480_MC_CS2_START) +#define V_BCM1480_MC_CS2_START(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS2_START) +#define G_BCM1480_MC_CS2_START(x) _SB_GETVALUE(x, S_BCM1480_MC_CS2_START, M_BCM1480_MC_CS2_START) + +#define S_BCM1480_MC_CS3_START 48 +#define M_BCM1480_MC_CS3_START _SB_MAKEMASK(12, S_BCM1480_MC_CS3_START) +#define V_BCM1480_MC_CS3_START(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS3_START) +#define G_BCM1480_MC_CS3_START(x) _SB_GETVALUE(x, S_BCM1480_MC_CS3_START, M_BCM1480_MC_CS3_START) + +/* + * Chip Select End Address Register (Table 83) + */ + +#define S_BCM1480_MC_CS0_END 0 +#define M_BCM1480_MC_CS0_END _SB_MAKEMASK(12, S_BCM1480_MC_CS0_END) +#define V_BCM1480_MC_CS0_END(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS0_END) +#define G_BCM1480_MC_CS0_END(x) _SB_GETVALUE(x, S_BCM1480_MC_CS0_END, M_BCM1480_MC_CS0_END) + +#define S_BCM1480_MC_CS1_END 16 +#define M_BCM1480_MC_CS1_END _SB_MAKEMASK(12, S_BCM1480_MC_CS1_END) +#define V_BCM1480_MC_CS1_END(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS1_END) +#define G_BCM1480_MC_CS1_END(x) _SB_GETVALUE(x, S_BCM1480_MC_CS1_END, M_BCM1480_MC_CS1_END) + +#define S_BCM1480_MC_CS2_END 32 +#define M_BCM1480_MC_CS2_END _SB_MAKEMASK(12, S_BCM1480_MC_CS2_END) +#define V_BCM1480_MC_CS2_END(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS2_END) +#define G_BCM1480_MC_CS2_END(x) _SB_GETVALUE(x, S_BCM1480_MC_CS2_END, M_BCM1480_MC_CS2_END) + +#define S_BCM1480_MC_CS3_END 48 +#define M_BCM1480_MC_CS3_END _SB_MAKEMASK(12, S_BCM1480_MC_CS3_END) +#define V_BCM1480_MC_CS3_END(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS3_END) +#define G_BCM1480_MC_CS3_END(x) _SB_GETVALUE(x, S_BCM1480_MC_CS3_END, M_BCM1480_MC_CS3_END) + +/* + * Row Address Bit Select Register 0 (Table 84) + */ + +#define S_BCM1480_MC_ROW00 0 +#define M_BCM1480_MC_ROW00 _SB_MAKEMASK(6, S_BCM1480_MC_ROW00) +#define V_BCM1480_MC_ROW00(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW00) +#define G_BCM1480_MC_ROW00(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW00, M_BCM1480_MC_ROW00) + +#define S_BCM1480_MC_ROW01 8 +#define M_BCM1480_MC_ROW01 _SB_MAKEMASK(6, S_BCM1480_MC_ROW01) +#define V_BCM1480_MC_ROW01(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW01) +#define G_BCM1480_MC_ROW01(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW01, M_BCM1480_MC_ROW01) + +#define S_BCM1480_MC_ROW02 16 +#define M_BCM1480_MC_ROW02 _SB_MAKEMASK(6, S_BCM1480_MC_ROW02) +#define V_BCM1480_MC_ROW02(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW02) +#define G_BCM1480_MC_ROW02(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW02, M_BCM1480_MC_ROW02) + +#define S_BCM1480_MC_ROW03 24 +#define M_BCM1480_MC_ROW03 _SB_MAKEMASK(6, S_BCM1480_MC_ROW03) +#define V_BCM1480_MC_ROW03(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW03) +#define G_BCM1480_MC_ROW03(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW03, M_BCM1480_MC_ROW03) + +#define S_BCM1480_MC_ROW04 32 +#define M_BCM1480_MC_ROW04 _SB_MAKEMASK(6, S_BCM1480_MC_ROW04) +#define V_BCM1480_MC_ROW04(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW04) +#define G_BCM1480_MC_ROW04(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW04, M_BCM1480_MC_ROW04) + +#define S_BCM1480_MC_ROW05 40 +#define M_BCM1480_MC_ROW05 _SB_MAKEMASK(6, S_BCM1480_MC_ROW05) +#define V_BCM1480_MC_ROW05(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW05) +#define G_BCM1480_MC_ROW05(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW05, M_BCM1480_MC_ROW05) + +#define S_BCM1480_MC_ROW06 48 +#define M_BCM1480_MC_ROW06 _SB_MAKEMASK(6, S_BCM1480_MC_ROW06) +#define V_BCM1480_MC_ROW06(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW06) +#define G_BCM1480_MC_ROW06(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW06, M_BCM1480_MC_ROW06) + +#define S_BCM1480_MC_ROW07 56 +#define M_BCM1480_MC_ROW07 _SB_MAKEMASK(6, S_BCM1480_MC_ROW07) +#define V_BCM1480_MC_ROW07(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW07) +#define G_BCM1480_MC_ROW07(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW07, M_BCM1480_MC_ROW07) + +/* + * Row Address Bit Select Register 1 (Table 85) + */ + +#define S_BCM1480_MC_ROW08 0 +#define M_BCM1480_MC_ROW08 _SB_MAKEMASK(6, S_BCM1480_MC_ROW08) +#define V_BCM1480_MC_ROW08(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW08) +#define G_BCM1480_MC_ROW08(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW08, M_BCM1480_MC_ROW08) + +#define S_BCM1480_MC_ROW09 8 +#define M_BCM1480_MC_ROW09 _SB_MAKEMASK(6, S_BCM1480_MC_ROW09) +#define V_BCM1480_MC_ROW09(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW09) +#define G_BCM1480_MC_ROW09(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW09, M_BCM1480_MC_ROW09) + +#define S_BCM1480_MC_ROW10 16 +#define M_BCM1480_MC_ROW10 _SB_MAKEMASK(6, S_BCM1480_MC_ROW10) +#define V_BCM1480_MC_ROW10(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW10) +#define G_BCM1480_MC_ROW10(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW10, M_BCM1480_MC_ROW10) + +#define S_BCM1480_MC_ROW11 24 +#define M_BCM1480_MC_ROW11 _SB_MAKEMASK(6, S_BCM1480_MC_ROW11) +#define V_BCM1480_MC_ROW11(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW11) +#define G_BCM1480_MC_ROW11(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW11, M_BCM1480_MC_ROW11) + +#define S_BCM1480_MC_ROW12 32 +#define M_BCM1480_MC_ROW12 _SB_MAKEMASK(6, S_BCM1480_MC_ROW12) +#define V_BCM1480_MC_ROW12(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW12) +#define G_BCM1480_MC_ROW12(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW12, M_BCM1480_MC_ROW12) + +#define S_BCM1480_MC_ROW13 40 +#define M_BCM1480_MC_ROW13 _SB_MAKEMASK(6, S_BCM1480_MC_ROW13) +#define V_BCM1480_MC_ROW13(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW13) +#define G_BCM1480_MC_ROW13(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW13, M_BCM1480_MC_ROW13) + +#define S_BCM1480_MC_ROW14 48 +#define M_BCM1480_MC_ROW14 _SB_MAKEMASK(6, S_BCM1480_MC_ROW14) +#define V_BCM1480_MC_ROW14(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ROW14) +#define G_BCM1480_MC_ROW14(x) _SB_GETVALUE(x, S_BCM1480_MC_ROW14, M_BCM1480_MC_ROW14) + +#define K_BCM1480_MC_ROWX_BIT_SPACING 8 + +/* + * Column Address Bit Select Register 0 (Table 86) + */ + +#define S_BCM1480_MC_COL00 0 +#define M_BCM1480_MC_COL00 _SB_MAKEMASK(6, S_BCM1480_MC_COL00) +#define V_BCM1480_MC_COL00(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL00) +#define G_BCM1480_MC_COL00(x) _SB_GETVALUE(x, S_BCM1480_MC_COL00, M_BCM1480_MC_COL00) + +#define S_BCM1480_MC_COL01 8 +#define M_BCM1480_MC_COL01 _SB_MAKEMASK(6, S_BCM1480_MC_COL01) +#define V_BCM1480_MC_COL01(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL01) +#define G_BCM1480_MC_COL01(x) _SB_GETVALUE(x, S_BCM1480_MC_COL01, M_BCM1480_MC_COL01) + +#define S_BCM1480_MC_COL02 16 +#define M_BCM1480_MC_COL02 _SB_MAKEMASK(6, S_BCM1480_MC_COL02) +#define V_BCM1480_MC_COL02(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL02) +#define G_BCM1480_MC_COL02(x) _SB_GETVALUE(x, S_BCM1480_MC_COL02, M_BCM1480_MC_COL02) + +#define S_BCM1480_MC_COL03 24 +#define M_BCM1480_MC_COL03 _SB_MAKEMASK(6, S_BCM1480_MC_COL03) +#define V_BCM1480_MC_COL03(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL03) +#define G_BCM1480_MC_COL03(x) _SB_GETVALUE(x, S_BCM1480_MC_COL03, M_BCM1480_MC_COL03) + +#define S_BCM1480_MC_COL04 32 +#define M_BCM1480_MC_COL04 _SB_MAKEMASK(6, S_BCM1480_MC_COL04) +#define V_BCM1480_MC_COL04(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL04) +#define G_BCM1480_MC_COL04(x) _SB_GETVALUE(x, S_BCM1480_MC_COL04, M_BCM1480_MC_COL04) + +#define S_BCM1480_MC_COL05 40 +#define M_BCM1480_MC_COL05 _SB_MAKEMASK(6, S_BCM1480_MC_COL05) +#define V_BCM1480_MC_COL05(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL05) +#define G_BCM1480_MC_COL05(x) _SB_GETVALUE(x, S_BCM1480_MC_COL05, M_BCM1480_MC_COL05) + +#define S_BCM1480_MC_COL06 48 +#define M_BCM1480_MC_COL06 _SB_MAKEMASK(6, S_BCM1480_MC_COL06) +#define V_BCM1480_MC_COL06(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL06) +#define G_BCM1480_MC_COL06(x) _SB_GETVALUE(x, S_BCM1480_MC_COL06, M_BCM1480_MC_COL06) + +#define S_BCM1480_MC_COL07 56 +#define M_BCM1480_MC_COL07 _SB_MAKEMASK(6, S_BCM1480_MC_COL07) +#define V_BCM1480_MC_COL07(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL07) +#define G_BCM1480_MC_COL07(x) _SB_GETVALUE(x, S_BCM1480_MC_COL07, M_BCM1480_MC_COL07) + +/* + * Column Address Bit Select Register 1 (Table 87) + */ + +#define S_BCM1480_MC_COL08 0 +#define M_BCM1480_MC_COL08 _SB_MAKEMASK(6, S_BCM1480_MC_COL08) +#define V_BCM1480_MC_COL08(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL08) +#define G_BCM1480_MC_COL08(x) _SB_GETVALUE(x, S_BCM1480_MC_COL08, M_BCM1480_MC_COL08) + +#define S_BCM1480_MC_COL09 8 +#define M_BCM1480_MC_COL09 _SB_MAKEMASK(6, S_BCM1480_MC_COL09) +#define V_BCM1480_MC_COL09(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL09) +#define G_BCM1480_MC_COL09(x) _SB_GETVALUE(x, S_BCM1480_MC_COL09, M_BCM1480_MC_COL09) + +#define S_BCM1480_MC_COL10 16 /* not a valid position, must be prog as 0 */ + +#define S_BCM1480_MC_COL11 24 +#define M_BCM1480_MC_COL11 _SB_MAKEMASK(6, S_BCM1480_MC_COL11) +#define V_BCM1480_MC_COL11(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL11) +#define G_BCM1480_MC_COL11(x) _SB_GETVALUE(x, S_BCM1480_MC_COL11, M_BCM1480_MC_COL11) + +#define S_BCM1480_MC_COL12 32 +#define M_BCM1480_MC_COL12 _SB_MAKEMASK(6, S_BCM1480_MC_COL12) +#define V_BCM1480_MC_COL12(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL12) +#define G_BCM1480_MC_COL12(x) _SB_GETVALUE(x, S_BCM1480_MC_COL12, M_BCM1480_MC_COL12) + +#define S_BCM1480_MC_COL13 40 +#define M_BCM1480_MC_COL13 _SB_MAKEMASK(6, S_BCM1480_MC_COL13) +#define V_BCM1480_MC_COL13(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL13) +#define G_BCM1480_MC_COL13(x) _SB_GETVALUE(x, S_BCM1480_MC_COL13, M_BCM1480_MC_COL13) + +#define S_BCM1480_MC_COL14 48 +#define M_BCM1480_MC_COL14 _SB_MAKEMASK(6, S_BCM1480_MC_COL14) +#define V_BCM1480_MC_COL14(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COL14) +#define G_BCM1480_MC_COL14(x) _SB_GETVALUE(x, S_BCM1480_MC_COL14, M_BCM1480_MC_COL14) + +#define K_BCM1480_MC_COLX_BIT_SPACING 8 + +/* + * CS0 and CS1 Bank Address Bit Select Register (Table 88) + */ + +#define S_BCM1480_MC_CS01_BANK0 0 +#define M_BCM1480_MC_CS01_BANK0 _SB_MAKEMASK(6, S_BCM1480_MC_CS01_BANK0) +#define V_BCM1480_MC_CS01_BANK0(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS01_BANK0) +#define G_BCM1480_MC_CS01_BANK0(x) _SB_GETVALUE(x, S_BCM1480_MC_CS01_BANK0, M_BCM1480_MC_CS01_BANK0) + +#define S_BCM1480_MC_CS01_BANK1 8 +#define M_BCM1480_MC_CS01_BANK1 _SB_MAKEMASK(6, S_BCM1480_MC_CS01_BANK1) +#define V_BCM1480_MC_CS01_BANK1(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS01_BANK1) +#define G_BCM1480_MC_CS01_BANK1(x) _SB_GETVALUE(x, S_BCM1480_MC_CS01_BANK1, M_BCM1480_MC_CS01_BANK1) + +#define S_BCM1480_MC_CS01_BANK2 16 +#define M_BCM1480_MC_CS01_BANK2 _SB_MAKEMASK(6, S_BCM1480_MC_CS01_BANK2) +#define V_BCM1480_MC_CS01_BANK2(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS01_BANK2) +#define G_BCM1480_MC_CS01_BANK2(x) _SB_GETVALUE(x, S_BCM1480_MC_CS01_BANK2, M_BCM1480_MC_CS01_BANK2) + +/* + * CS2 and CS3 Bank Address Bit Select Register (Table 89) + */ + +#define S_BCM1480_MC_CS23_BANK0 0 +#define M_BCM1480_MC_CS23_BANK0 _SB_MAKEMASK(6, S_BCM1480_MC_CS23_BANK0) +#define V_BCM1480_MC_CS23_BANK0(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS23_BANK0) +#define G_BCM1480_MC_CS23_BANK0(x) _SB_GETVALUE(x, S_BCM1480_MC_CS23_BANK0, M_BCM1480_MC_CS23_BANK0) + +#define S_BCM1480_MC_CS23_BANK1 8 +#define M_BCM1480_MC_CS23_BANK1 _SB_MAKEMASK(6, S_BCM1480_MC_CS23_BANK1) +#define V_BCM1480_MC_CS23_BANK1(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS23_BANK1) +#define G_BCM1480_MC_CS23_BANK1(x) _SB_GETVALUE(x, S_BCM1480_MC_CS23_BANK1, M_BCM1480_MC_CS23_BANK1) + +#define S_BCM1480_MC_CS23_BANK2 16 +#define M_BCM1480_MC_CS23_BANK2 _SB_MAKEMASK(6, S_BCM1480_MC_CS23_BANK2) +#define V_BCM1480_MC_CS23_BANK2(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS23_BANK2) +#define G_BCM1480_MC_CS23_BANK2(x) _SB_GETVALUE(x, S_BCM1480_MC_CS23_BANK2, M_BCM1480_MC_CS23_BANK2) + +#define K_BCM1480_MC_CSXX_BANKX_BIT_SPACING 8 + +/* + * DRAM Command Register (Table 90) + */ + +#define S_BCM1480_MC_COMMAND 0 +#define M_BCM1480_MC_COMMAND _SB_MAKEMASK(4, S_BCM1480_MC_COMMAND) +#define V_BCM1480_MC_COMMAND(x) _SB_MAKEVALUE(x, S_BCM1480_MC_COMMAND) +#define G_BCM1480_MC_COMMAND(x) _SB_GETVALUE(x, S_BCM1480_MC_COMMAND, M_BCM1480_MC_COMMAND) + +#define K_BCM1480_MC_COMMAND_EMRS 0 +#define K_BCM1480_MC_COMMAND_MRS 1 +#define K_BCM1480_MC_COMMAND_PRE 2 +#define K_BCM1480_MC_COMMAND_AR 3 +#define K_BCM1480_MC_COMMAND_SETRFSH 4 +#define K_BCM1480_MC_COMMAND_CLRRFSH 5 +#define K_BCM1480_MC_COMMAND_SETPWRDN 6 +#define K_BCM1480_MC_COMMAND_CLRPWRDN 7 + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define K_BCM1480_MC_COMMAND_EMRS2 8 +#define K_BCM1480_MC_COMMAND_EMRS3 9 +#define K_BCM1480_MC_COMMAND_ENABLE_MCLK 10 +#define K_BCM1480_MC_COMMAND_DISABLE_MCLK 11 +#endif + +#define V_BCM1480_MC_COMMAND_EMRS V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_EMRS) +#define V_BCM1480_MC_COMMAND_MRS V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_MRS) +#define V_BCM1480_MC_COMMAND_PRE V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_PRE) +#define V_BCM1480_MC_COMMAND_AR V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_AR) +#define V_BCM1480_MC_COMMAND_SETRFSH V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_SETRFSH) +#define V_BCM1480_MC_COMMAND_CLRRFSH V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_CLRRFSH) +#define V_BCM1480_MC_COMMAND_SETPWRDN V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_SETPWRDN) +#define V_BCM1480_MC_COMMAND_CLRPWRDN V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_CLRPWRDN) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define V_BCM1480_MC_COMMAND_EMRS2 V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_EMRS2) +#define V_BCM1480_MC_COMMAND_EMRS3 V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_EMRS3) +#define V_BCM1480_MC_COMMAND_ENABLE_MCLK V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_ENABLE_MCLK) +#define V_BCM1480_MC_COMMAND_DISABLE_MCLK V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_DISABLE_MCLK) +#endif + +#define S_BCM1480_MC_CS0 4 +#define M_BCM1480_MC_CS0 _SB_MAKEMASK1(4) +#define M_BCM1480_MC_CS1 _SB_MAKEMASK1(5) +#define M_BCM1480_MC_CS2 _SB_MAKEMASK1(6) +#define M_BCM1480_MC_CS3 _SB_MAKEMASK1(7) +#define M_BCM1480_MC_CS4 _SB_MAKEMASK1(8) +#define M_BCM1480_MC_CS5 _SB_MAKEMASK1(9) +#define M_BCM1480_MC_CS6 _SB_MAKEMASK1(10) +#define M_BCM1480_MC_CS7 _SB_MAKEMASK1(11) + +#define M_BCM1480_MC_CS _SB_MAKEMASK(8, S_BCM1480_MC_CS0) +#define V_BCM1480_MC_CS(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CS0) +#define G_BCM1480_MC_CS(x) _SB_GETVALUE(x, S_BCM1480_MC_CS0, M_BCM1480_MC_CS0) + +#define M_BCM1480_MC_CMD_ACTIVE _SB_MAKEMASK1(16) + +/* + * DRAM Mode Register (Table 91) + */ + +#define S_BCM1480_MC_EMODE 0 +#define M_BCM1480_MC_EMODE _SB_MAKEMASK(15, S_BCM1480_MC_EMODE) +#define V_BCM1480_MC_EMODE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_EMODE) +#define G_BCM1480_MC_EMODE(x) _SB_GETVALUE(x, S_BCM1480_MC_EMODE, M_BCM1480_MC_EMODE) +#define V_BCM1480_MC_EMODE_DEFAULT V_BCM1480_MC_EMODE(0) + +#define S_BCM1480_MC_MODE 16 +#define M_BCM1480_MC_MODE _SB_MAKEMASK(15, S_BCM1480_MC_MODE) +#define V_BCM1480_MC_MODE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_MODE) +#define G_BCM1480_MC_MODE(x) _SB_GETVALUE(x, S_BCM1480_MC_MODE, M_BCM1480_MC_MODE) +#define V_BCM1480_MC_MODE_DEFAULT V_BCM1480_MC_MODE(0) + +#define S_BCM1480_MC_DRAM_TYPE 32 +#define M_BCM1480_MC_DRAM_TYPE _SB_MAKEMASK(4, S_BCM1480_MC_DRAM_TYPE) +#define V_BCM1480_MC_DRAM_TYPE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DRAM_TYPE) +#define G_BCM1480_MC_DRAM_TYPE(x) _SB_GETVALUE(x, S_BCM1480_MC_DRAM_TYPE, M_BCM1480_MC_DRAM_TYPE) + +#define K_BCM1480_MC_DRAM_TYPE_JEDEC 0 +#define K_BCM1480_MC_DRAM_TYPE_FCRAM 1 + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define K_BCM1480_MC_DRAM_TYPE_DDR2 2 +#endif + +#define K_BCM1480_MC_DRAM_TYPE_DDR2_PASS1 0 + +#define V_BCM1480_MC_DRAM_TYPE_JEDEC V_BCM1480_MC_DRAM_TYPE(K_BCM1480_MC_DRAM_TYPE_JEDEC) +#define V_BCM1480_MC_DRAM_TYPE_FCRAM V_BCM1480_MC_DRAM_TYPE(K_BCM1480_MC_DRAM_TYPE_FCRAM) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define V_BCM1480_MC_DRAM_TYPE_DDR2 V_BCM1480_MC_DRAM_TYPE(K_BCM1480_MC_DRAM_TYPE_DDR2) +#endif + +#define M_BCM1480_MC_GANGED _SB_MAKEMASK1(36) +#define M_BCM1480_MC_BY9_INTF _SB_MAKEMASK1(37) +#define M_BCM1480_MC_FORCE_ECC64 _SB_MAKEMASK1(38) +#define M_BCM1480_MC_ECC_DISABLE _SB_MAKEMASK1(39) + +#define S_BCM1480_MC_PG_POLICY 40 +#define M_BCM1480_MC_PG_POLICY _SB_MAKEMASK(2, S_BCM1480_MC_PG_POLICY) +#define V_BCM1480_MC_PG_POLICY(x) _SB_MAKEVALUE(x, S_BCM1480_MC_PG_POLICY) +#define G_BCM1480_MC_PG_POLICY(x) _SB_GETVALUE(x, S_BCM1480_MC_PG_POLICY, M_BCM1480_MC_PG_POLICY) + +#define K_BCM1480_MC_PG_POLICY_CLOSED 0 +#define K_BCM1480_MC_PG_POLICY_CAS_TIME_CHK 1 + +#define V_BCM1480_MC_PG_POLICY_CLOSED V_BCM1480_MC_PG_POLICY(K_BCM1480_MC_PG_POLICY_CLOSED) +#define V_BCM1480_MC_PG_POLICY_CAS_TIME_CHK V_BCM1480_MC_PG_POLICY(K_BCM1480_MC_PG_POLICY_CAS_TIME_CHK) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define M_BCM1480_MC_2T_CMD _SB_MAKEMASK1(42) +#define M_BCM1480_MC_ECC_COR_DIS _SB_MAKEMASK1(43) +#endif + +#define V_BCM1480_MC_DRAMMODE_DEFAULT V_BCM1480_MC_EMODE_DEFAULT | V_BCM1480_MC_MODE_DEFAULT | V_BCM1480_MC_DRAM_TYPE_JEDEC | \ + V_BCM1480_MC_PG_POLICY(K_BCM1480_MC_PG_POLICY_CAS_TIME_CHK) + +/* + * Memory Clock Configuration Register (Table 92) + */ + +#define S_BCM1480_MC_CLK_RATIO 0 +#define M_BCM1480_MC_CLK_RATIO _SB_MAKEMASK(6, S_BCM1480_MC_CLK_RATIO) +#define V_BCM1480_MC_CLK_RATIO(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CLK_RATIO) +#define G_BCM1480_MC_CLK_RATIO(x) _SB_GETVALUE(x, S_BCM1480_MC_CLK_RATIO, M_BCM1480_MC_CLK_RATIO) + +#define V_BCM1480_MC_CLK_RATIO_DEFAULT V_BCM1480_MC_CLK_RATIO(10) + +#define S_BCM1480_MC_REF_RATE 8 +#define M_BCM1480_MC_REF_RATE _SB_MAKEMASK(8, S_BCM1480_MC_REF_RATE) +#define V_BCM1480_MC_REF_RATE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_REF_RATE) +#define G_BCM1480_MC_REF_RATE(x) _SB_GETVALUE(x, S_BCM1480_MC_REF_RATE, M_BCM1480_MC_REF_RATE) + +#define K_BCM1480_MC_REF_RATE_100MHz 0x31 +#define K_BCM1480_MC_REF_RATE_200MHz 0x62 +#define K_BCM1480_MC_REF_RATE_400MHz 0xC4 + +#define V_BCM1480_MC_REF_RATE_100MHz V_BCM1480_MC_REF_RATE(K_BCM1480_MC_REF_RATE_100MHz) +#define V_BCM1480_MC_REF_RATE_200MHz V_BCM1480_MC_REF_RATE(K_BCM1480_MC_REF_RATE_200MHz) +#define V_BCM1480_MC_REF_RATE_400MHz V_BCM1480_MC_REF_RATE(K_BCM1480_MC_REF_RATE_400MHz) +#define V_BCM1480_MC_REF_RATE_DEFAULT V_BCM1480_MC_REF_RATE_400MHz + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define M_BCM1480_MC_AUTO_REF_DIS _SB_MAKEMASK1(16) +#endif + +/* + * ODT Register (Table 99) + */ + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define M_BCM1480_MC_RD_ODT0_CS0 _SB_MAKEMASK1(0) +#define M_BCM1480_MC_RD_ODT0_CS2 _SB_MAKEMASK1(1) +#define M_BCM1480_MC_RD_ODT0_CS4 _SB_MAKEMASK1(2) +#define M_BCM1480_MC_RD_ODT0_CS6 _SB_MAKEMASK1(3) +#define M_BCM1480_MC_WR_ODT0_CS0 _SB_MAKEMASK1(4) +#define M_BCM1480_MC_WR_ODT0_CS2 _SB_MAKEMASK1(5) +#define M_BCM1480_MC_WR_ODT0_CS4 _SB_MAKEMASK1(6) +#define M_BCM1480_MC_WR_ODT0_CS6 _SB_MAKEMASK1(7) +#define M_BCM1480_MC_RD_ODT2_CS0 _SB_MAKEMASK1(8) +#define M_BCM1480_MC_RD_ODT2_CS2 _SB_MAKEMASK1(9) +#define M_BCM1480_MC_RD_ODT2_CS4 _SB_MAKEMASK1(10) +#define M_BCM1480_MC_RD_ODT2_CS6 _SB_MAKEMASK1(11) +#define M_BCM1480_MC_WR_ODT2_CS0 _SB_MAKEMASK1(12) +#define M_BCM1480_MC_WR_ODT2_CS2 _SB_MAKEMASK1(13) +#define M_BCM1480_MC_WR_ODT2_CS4 _SB_MAKEMASK1(14) +#define M_BCM1480_MC_WR_ODT2_CS6 _SB_MAKEMASK1(15) +#define M_BCM1480_MC_RD_ODT4_CS0 _SB_MAKEMASK1(16) +#define M_BCM1480_MC_RD_ODT4_CS2 _SB_MAKEMASK1(17) +#define M_BCM1480_MC_RD_ODT4_CS4 _SB_MAKEMASK1(18) +#define M_BCM1480_MC_RD_ODT4_CS6 _SB_MAKEMASK1(19) +#define M_BCM1480_MC_WR_ODT4_CS0 _SB_MAKEMASK1(20) +#define M_BCM1480_MC_WR_ODT4_CS2 _SB_MAKEMASK1(21) +#define M_BCM1480_MC_WR_ODT4_CS4 _SB_MAKEMASK1(22) +#define M_BCM1480_MC_WR_ODT4_CS6 _SB_MAKEMASK1(23) +#define M_BCM1480_MC_RD_ODT6_CS0 _SB_MAKEMASK1(24) +#define M_BCM1480_MC_RD_ODT6_CS2 _SB_MAKEMASK1(25) +#define M_BCM1480_MC_RD_ODT6_CS4 _SB_MAKEMASK1(26) +#define M_BCM1480_MC_RD_ODT6_CS6 _SB_MAKEMASK1(27) +#define M_BCM1480_MC_WR_ODT6_CS0 _SB_MAKEMASK1(28) +#define M_BCM1480_MC_WR_ODT6_CS2 _SB_MAKEMASK1(29) +#define M_BCM1480_MC_WR_ODT6_CS4 _SB_MAKEMASK1(30) +#define M_BCM1480_MC_WR_ODT6_CS6 _SB_MAKEMASK1(31) + +#define M_BCM1480_MC_CS_ODD_ODT_EN _SB_MAKEMASK1(32) + +#define S_BCM1480_MC_ODT0 0 +#define M_BCM1480_MC_ODT0 _SB_MAKEMASK(8, S_BCM1480_MC_ODT0) +#define V_BCM1480_MC_ODT0(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ODT0) + +#define S_BCM1480_MC_ODT2 8 +#define M_BCM1480_MC_ODT2 _SB_MAKEMASK(8, S_BCM1480_MC_ODT2) +#define V_BCM1480_MC_ODT2(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ODT2) + +#define S_BCM1480_MC_ODT4 16 +#define M_BCM1480_MC_ODT4 _SB_MAKEMASK(8, S_BCM1480_MC_ODT4) +#define V_BCM1480_MC_ODT4(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ODT4) + +#define S_BCM1480_MC_ODT6 24 +#define M_BCM1480_MC_ODT6 _SB_MAKEMASK(8, S_BCM1480_MC_ODT6) +#define V_BCM1480_MC_ODT6(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ODT6) +#endif + +/* + * Memory DLL Configuration Register (Table 93) + */ + +#define S_BCM1480_MC_ADDR_COARSE_ADJ 0 +#define M_BCM1480_MC_ADDR_COARSE_ADJ _SB_MAKEMASK(6, S_BCM1480_MC_ADDR_COARSE_ADJ) +#define V_BCM1480_MC_ADDR_COARSE_ADJ(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ADDR_COARSE_ADJ) +#define G_BCM1480_MC_ADDR_COARSE_ADJ(x) _SB_GETVALUE(x, S_BCM1480_MC_ADDR_COARSE_ADJ, M_BCM1480_MC_ADDR_COARSE_ADJ) +#define V_BCM1480_MC_ADDR_COARSE_ADJ_DEFAULT V_BCM1480_MC_ADDR_COARSE_ADJ(0x0) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_ADDR_FREQ_RANGE 8 +#define M_BCM1480_MC_ADDR_FREQ_RANGE _SB_MAKEMASK(4, S_BCM1480_MC_ADDR_FREQ_RANGE) +#define V_BCM1480_MC_ADDR_FREQ_RANGE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ADDR_FREQ_RANGE) +#define G_BCM1480_MC_ADDR_FREQ_RANGE(x) _SB_GETVALUE(x, S_BCM1480_MC_ADDR_FREQ_RANGE, M_BCM1480_MC_ADDR_FREQ_RANGE) +#define V_BCM1480_MC_ADDR_FREQ_RANGE_DEFAULT V_BCM1480_MC_ADDR_FREQ_RANGE(0x4) +#endif + +#define S_BCM1480_MC_ADDR_FINE_ADJ 8 +#define M_BCM1480_MC_ADDR_FINE_ADJ _SB_MAKEMASK(4, S_BCM1480_MC_ADDR_FINE_ADJ) +#define V_BCM1480_MC_ADDR_FINE_ADJ(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ADDR_FINE_ADJ) +#define G_BCM1480_MC_ADDR_FINE_ADJ(x) _SB_GETVALUE(x, S_BCM1480_MC_ADDR_FINE_ADJ, M_BCM1480_MC_ADDR_FINE_ADJ) +#define V_BCM1480_MC_ADDR_FINE_ADJ_DEFAULT V_BCM1480_MC_ADDR_FINE_ADJ(0x8) + +#define S_BCM1480_MC_DQI_COARSE_ADJ 16 +#define M_BCM1480_MC_DQI_COARSE_ADJ _SB_MAKEMASK(6, S_BCM1480_MC_DQI_COARSE_ADJ) +#define V_BCM1480_MC_DQI_COARSE_ADJ(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DQI_COARSE_ADJ) +#define G_BCM1480_MC_DQI_COARSE_ADJ(x) _SB_GETVALUE(x, S_BCM1480_MC_DQI_COARSE_ADJ, M_BCM1480_MC_DQI_COARSE_ADJ) +#define V_BCM1480_MC_DQI_COARSE_ADJ_DEFAULT V_BCM1480_MC_DQI_COARSE_ADJ(0x0) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_DQI_FREQ_RANGE 24 +#define M_BCM1480_MC_DQI_FREQ_RANGE _SB_MAKEMASK(4, S_BCM1480_MC_DQI_FREQ_RANGE) +#define V_BCM1480_MC_DQI_FREQ_RANGE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DQI_FREQ_RANGE) +#define G_BCM1480_MC_DQI_FREQ_RANGE(x) _SB_GETVALUE(x, S_BCM1480_MC_DQI_FREQ_RANGE, M_BCM1480_MC_DQI_FREQ_RANGE) +#define V_BCM1480_MC_DQI_FREQ_RANGE_DEFAULT V_BCM1480_MC_DQI_FREQ_RANGE(0x4) +#endif + +#define S_BCM1480_MC_DQI_FINE_ADJ 24 +#define M_BCM1480_MC_DQI_FINE_ADJ _SB_MAKEMASK(4, S_BCM1480_MC_DQI_FINE_ADJ) +#define V_BCM1480_MC_DQI_FINE_ADJ(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DQI_FINE_ADJ) +#define G_BCM1480_MC_DQI_FINE_ADJ(x) _SB_GETVALUE(x, S_BCM1480_MC_DQI_FINE_ADJ, M_BCM1480_MC_DQI_FINE_ADJ) +#define V_BCM1480_MC_DQI_FINE_ADJ_DEFAULT V_BCM1480_MC_DQI_FINE_ADJ(0x8) + +#define S_BCM1480_MC_DQO_COARSE_ADJ 32 +#define M_BCM1480_MC_DQO_COARSE_ADJ _SB_MAKEMASK(6, S_BCM1480_MC_DQO_COARSE_ADJ) +#define V_BCM1480_MC_DQO_COARSE_ADJ(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DQO_COARSE_ADJ) +#define G_BCM1480_MC_DQO_COARSE_ADJ(x) _SB_GETVALUE(x, S_BCM1480_MC_DQO_COARSE_ADJ, M_BCM1480_MC_DQO_COARSE_ADJ) +#define V_BCM1480_MC_DQO_COARSE_ADJ_DEFAULT V_BCM1480_MC_DQO_COARSE_ADJ(0x0) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_DQO_FREQ_RANGE 40 +#define M_BCM1480_MC_DQO_FREQ_RANGE _SB_MAKEMASK(4, S_BCM1480_MC_DQO_FREQ_RANGE) +#define V_BCM1480_MC_DQO_FREQ_RANGE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DQO_FREQ_RANGE) +#define G_BCM1480_MC_DQO_FREQ_RANGE(x) _SB_GETVALUE(x, S_BCM1480_MC_DQO_FREQ_RANGE, M_BCM1480_MC_DQO_FREQ_RANGE) +#define V_BCM1480_MC_DQO_FREQ_RANGE_DEFAULT V_BCM1480_MC_DQO_FREQ_RANGE(0x4) +#endif + +#define S_BCM1480_MC_DQO_FINE_ADJ 40 +#define M_BCM1480_MC_DQO_FINE_ADJ _SB_MAKEMASK(4, S_BCM1480_MC_DQO_FINE_ADJ) +#define V_BCM1480_MC_DQO_FINE_ADJ(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DQO_FINE_ADJ) +#define G_BCM1480_MC_DQO_FINE_ADJ(x) _SB_GETVALUE(x, S_BCM1480_MC_DQO_FINE_ADJ, M_BCM1480_MC_DQO_FINE_ADJ) +#define V_BCM1480_MC_DQO_FINE_ADJ_DEFAULT V_BCM1480_MC_DQO_FINE_ADJ(0x8) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_DLL_PDSEL 44 +#define M_BCM1480_MC_DLL_PDSEL _SB_MAKEMASK(2, S_BCM1480_MC_DLL_PDSEL) +#define V_BCM1480_MC_DLL_PDSEL(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DLL_PDSEL) +#define G_BCM1480_MC_DLL_PDSEL(x) _SB_GETVALUE(x, S_BCM1480_MC_DLL_PDSEL, M_BCM1480_MC_DLL_PDSEL) +#define V_BCM1480_MC_DLL_DEFAULT_PDSEL V_BCM1480_MC_DLL_PDSEL(0x0) + +#define M_BCM1480_MC_DLL_REGBYPASS _SB_MAKEMASK1(46) +#define M_BCM1480_MC_DQO_SHIFT _SB_MAKEMASK1(47) +#endif + +#define S_BCM1480_MC_DLL_DEFAULT 48 +#define M_BCM1480_MC_DLL_DEFAULT _SB_MAKEMASK(6, S_BCM1480_MC_DLL_DEFAULT) +#define V_BCM1480_MC_DLL_DEFAULT(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DLL_DEFAULT) +#define G_BCM1480_MC_DLL_DEFAULT(x) _SB_GETVALUE(x, S_BCM1480_MC_DLL_DEFAULT, M_BCM1480_MC_DLL_DEFAULT) +#define V_BCM1480_MC_DLL_DEFAULT_DEFAULT V_BCM1480_MC_DLL_DEFAULT(0x10) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_DLL_REGCTRL 54 +#define M_BCM1480_MC_DLL_REGCTRL _SB_MAKEMASK(2, S_BCM1480_MC_DLL_REGCTRL) +#define V_BCM1480_MC_DLL_REGCTRL(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DLL_REGCTRL) +#define G_BCM1480_MC_DLL_REGCTRL(x) _SB_GETVALUE(x, S_BCM1480_MC_DLL_REGCTRL, M_BCM1480_MC_DLL_REGCTRL) +#define V_BCM1480_MC_DLL_DEFAULT_REGCTRL V_BCM1480_MC_DLL_REGCTRL(0x0) +#endif + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_DLL_FREQ_RANGE 56 +#define M_BCM1480_MC_DLL_FREQ_RANGE _SB_MAKEMASK(4, S_BCM1480_MC_DLL_FREQ_RANGE) +#define V_BCM1480_MC_DLL_FREQ_RANGE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DLL_FREQ_RANGE) +#define G_BCM1480_MC_DLL_FREQ_RANGE(x) _SB_GETVALUE(x, S_BCM1480_MC_DLL_FREQ_RANGE, M_BCM1480_MC_DLL_FREQ_RANGE) +#define V_BCM1480_MC_DLL_FREQ_RANGE_DEFAULT V_BCM1480_MC_DLL_FREQ_RANGE(0x4) +#endif + +#define S_BCM1480_MC_DLL_STEP_SIZE 56 +#define M_BCM1480_MC_DLL_STEP_SIZE _SB_MAKEMASK(4, S_BCM1480_MC_DLL_STEP_SIZE) +#define V_BCM1480_MC_DLL_STEP_SIZE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DLL_STEP_SIZE) +#define G_BCM1480_MC_DLL_STEP_SIZE(x) _SB_GETVALUE(x, S_BCM1480_MC_DLL_STEP_SIZE, M_BCM1480_MC_DLL_STEP_SIZE) +#define V_BCM1480_MC_DLL_STEP_SIZE_DEFAULT V_BCM1480_MC_DLL_STEP_SIZE(0x8) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_DLL_BGCTRL 60 +#define M_BCM1480_MC_DLL_BGCTRL _SB_MAKEMASK(2, S_BCM1480_MC_DLL_BGCTRL) +#define V_BCM1480_MC_DLL_BGCTRL(x) _SB_MAKEVALUE(x, S_BCM1480_MC_DLL_BGCTRL) +#define G_BCM1480_MC_DLL_BGCTRL(x) _SB_GETVALUE(x, S_BCM1480_MC_DLL_BGCTRL, M_BCM1480_MC_DLL_BGCTRL) +#define V_BCM1480_MC_DLL_DEFAULT_BGCTRL V_BCM1480_MC_DLL_BGCTRL(0x0) +#endif + +#define M_BCM1480_MC_DLL_BYPASS _SB_MAKEMASK1(63) + +/* + * Memory Drive Configuration Register (Table 94) + */ + +#define S_BCM1480_MC_RTT_BYP_PULLDOWN 0 +#define M_BCM1480_MC_RTT_BYP_PULLDOWN _SB_MAKEMASK(3, S_BCM1480_MC_RTT_BYP_PULLDOWN) +#define V_BCM1480_MC_RTT_BYP_PULLDOWN(x) _SB_MAKEVALUE(x, S_BCM1480_MC_RTT_BYP_PULLDOWN) +#define G_BCM1480_MC_RTT_BYP_PULLDOWN(x) _SB_GETVALUE(x, S_BCM1480_MC_RTT_BYP_PULLDOWN, M_BCM1480_MC_RTT_BYP_PULLDOWN) + +#define S_BCM1480_MC_RTT_BYP_PULLUP 6 +#define M_BCM1480_MC_RTT_BYP_PULLUP _SB_MAKEMASK(3, S_BCM1480_MC_RTT_BYP_PULLUP) +#define V_BCM1480_MC_RTT_BYP_PULLUP(x) _SB_MAKEVALUE(x, S_BCM1480_MC_RTT_BYP_PULLUP) +#define G_BCM1480_MC_RTT_BYP_PULLUP(x) _SB_GETVALUE(x, S_BCM1480_MC_RTT_BYP_PULLUP, M_BCM1480_MC_RTT_BYP_PULLUP) + +#define M_BCM1480_MC_RTT_BYPASS _SB_MAKEMASK1(8) +#define M_BCM1480_MC_RTT_COMP_MOV_AVG _SB_MAKEMASK1(9) + +#define S_BCM1480_MC_PVT_BYP_C1_PULLDOWN 10 +#define M_BCM1480_MC_PVT_BYP_C1_PULLDOWN _SB_MAKEMASK(4, S_BCM1480_MC_PVT_BYP_C1_PULLDOWN) +#define V_BCM1480_MC_PVT_BYP_C1_PULLDOWN(x) _SB_MAKEVALUE(x, S_BCM1480_MC_PVT_BYP_C1_PULLDOWN) +#define G_BCM1480_MC_PVT_BYP_C1_PULLDOWN(x) _SB_GETVALUE(x, S_BCM1480_MC_PVT_BYP_C1_PULLDOWN, M_BCM1480_MC_PVT_BYP_C1_PULLDOWN) + +#define S_BCM1480_MC_PVT_BYP_C1_PULLUP 15 +#define M_BCM1480_MC_PVT_BYP_C1_PULLUP _SB_MAKEMASK(4, S_BCM1480_MC_PVT_BYP_C1_PULLUP) +#define V_BCM1480_MC_PVT_BYP_C1_PULLUP(x) _SB_MAKEVALUE(x, S_BCM1480_MC_PVT_BYP_C1_PULLUP) +#define G_BCM1480_MC_PVT_BYP_C1_PULLUP(x) _SB_GETVALUE(x, S_BCM1480_MC_PVT_BYP_C1_PULLUP, M_BCM1480_MC_PVT_BYP_C1_PULLUP) + +#define S_BCM1480_MC_PVT_BYP_C2_PULLDOWN 20 +#define M_BCM1480_MC_PVT_BYP_C2_PULLDOWN _SB_MAKEMASK(4, S_BCM1480_MC_PVT_BYP_C2_PULLDOWN) +#define V_BCM1480_MC_PVT_BYP_C2_PULLDOWN(x) _SB_MAKEVALUE(x, S_BCM1480_MC_PVT_BYP_C2_PULLDOWN) +#define G_BCM1480_MC_PVT_BYP_C2_PULLDOWN(x) _SB_GETVALUE(x, S_BCM1480_MC_PVT_BYP_C2_PULLDOWN, M_BCM1480_MC_PVT_BYP_C2_PULLDOWN) + +#define S_BCM1480_MC_PVT_BYP_C2_PULLUP 25 +#define M_BCM1480_MC_PVT_BYP_C2_PULLUP _SB_MAKEMASK(4, S_BCM1480_MC_PVT_BYP_C2_PULLUP) +#define V_BCM1480_MC_PVT_BYP_C2_PULLUP(x) _SB_MAKEVALUE(x, S_BCM1480_MC_PVT_BYP_C2_PULLUP) +#define G_BCM1480_MC_PVT_BYP_C2_PULLUP(x) _SB_GETVALUE(x, S_BCM1480_MC_PVT_BYP_C2_PULLUP, M_BCM1480_MC_PVT_BYP_C2_PULLUP) + +#define M_BCM1480_MC_PVT_BYPASS _SB_MAKEMASK1(30) +#define M_BCM1480_MC_PVT_COMP_MOV_AVG _SB_MAKEMASK1(31) + +#define M_BCM1480_MC_CLK_CLASS _SB_MAKEMASK1(34) +#define M_BCM1480_MC_DATA_CLASS _SB_MAKEMASK1(35) +#define M_BCM1480_MC_ADDR_CLASS _SB_MAKEMASK1(36) + +#define M_BCM1480_MC_DQ_ODT_75 _SB_MAKEMASK1(37) +#define M_BCM1480_MC_DQ_ODT_150 _SB_MAKEMASK1(38) +#define M_BCM1480_MC_DQS_ODT_75 _SB_MAKEMASK1(39) +#define M_BCM1480_MC_DQS_ODT_150 _SB_MAKEMASK1(40) +#define M_BCM1480_MC_DQS_DIFF _SB_MAKEMASK1(41) + +/* + * ECC Test Data Register (Table 95) + */ + +#define S_BCM1480_MC_DATA_INVERT 0 +#define M_DATA_ECC_INVERT _SB_MAKEMASK(64, S_BCM1480_MC_ECC_INVERT) + +/* + * ECC Test ECC Register (Table 96) + */ + +#define S_BCM1480_MC_ECC_INVERT 0 +#define M_BCM1480_MC_ECC_INVERT _SB_MAKEMASK(8, S_BCM1480_MC_ECC_INVERT) + +/* + * SDRAM Timing Register (Table 97) + */ + +#define S_BCM1480_MC_tRCD 0 +#define M_BCM1480_MC_tRCD _SB_MAKEMASK(4, S_BCM1480_MC_tRCD) +#define V_BCM1480_MC_tRCD(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRCD) +#define G_BCM1480_MC_tRCD(x) _SB_GETVALUE(x, S_BCM1480_MC_tRCD, M_BCM1480_MC_tRCD) +#define K_BCM1480_MC_tRCD_DEFAULT 3 +#define V_BCM1480_MC_tRCD_DEFAULT V_BCM1480_MC_tRCD(K_BCM1480_MC_tRCD_DEFAULT) + +#define S_BCM1480_MC_tCL 4 +#define M_BCM1480_MC_tCL _SB_MAKEMASK(4, S_BCM1480_MC_tCL) +#define V_BCM1480_MC_tCL(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tCL) +#define G_BCM1480_MC_tCL(x) _SB_GETVALUE(x, S_BCM1480_MC_tCL, M_BCM1480_MC_tCL) +#define K_BCM1480_MC_tCL_DEFAULT 2 +#define V_BCM1480_MC_tCL_DEFAULT V_BCM1480_MC_tCL(K_BCM1480_MC_tCL_DEFAULT) + +#define M_BCM1480_MC_tCrDh _SB_MAKEMASK1(8) + +#define S_BCM1480_MC_tWR 9 +#define M_BCM1480_MC_tWR _SB_MAKEMASK(3, S_BCM1480_MC_tWR) +#define V_BCM1480_MC_tWR(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tWR) +#define G_BCM1480_MC_tWR(x) _SB_GETVALUE(x, S_BCM1480_MC_tWR, M_BCM1480_MC_tWR) +#define K_BCM1480_MC_tWR_DEFAULT 2 +#define V_BCM1480_MC_tWR_DEFAULT V_BCM1480_MC_tWR(K_BCM1480_MC_tWR_DEFAULT) + +#define S_BCM1480_MC_tCwD 12 +#define M_BCM1480_MC_tCwD _SB_MAKEMASK(4, S_BCM1480_MC_tCwD) +#define V_BCM1480_MC_tCwD(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tCwD) +#define G_BCM1480_MC_tCwD(x) _SB_GETVALUE(x, S_BCM1480_MC_tCwD, M_BCM1480_MC_tCwD) +#define K_BCM1480_MC_tCwD_DEFAULT 1 +#define V_BCM1480_MC_tCwD_DEFAULT V_BCM1480_MC_tCwD(K_BCM1480_MC_tCwD_DEFAULT) + +#define S_BCM1480_MC_tRP 16 +#define M_BCM1480_MC_tRP _SB_MAKEMASK(4, S_BCM1480_MC_tRP) +#define V_BCM1480_MC_tRP(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRP) +#define G_BCM1480_MC_tRP(x) _SB_GETVALUE(x, S_BCM1480_MC_tRP, M_BCM1480_MC_tRP) +#define K_BCM1480_MC_tRP_DEFAULT 4 +#define V_BCM1480_MC_tRP_DEFAULT V_BCM1480_MC_tRP(K_BCM1480_MC_tRP_DEFAULT) + +#define S_BCM1480_MC_tRRD 20 +#define M_BCM1480_MC_tRRD _SB_MAKEMASK(4, S_BCM1480_MC_tRRD) +#define V_BCM1480_MC_tRRD(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRRD) +#define G_BCM1480_MC_tRRD(x) _SB_GETVALUE(x, S_BCM1480_MC_tRRD, M_BCM1480_MC_tRRD) +#define K_BCM1480_MC_tRRD_DEFAULT 2 +#define V_BCM1480_MC_tRRD_DEFAULT V_BCM1480_MC_tRRD(K_BCM1480_MC_tRRD_DEFAULT) + +#define S_BCM1480_MC_tRCw 24 +#define M_BCM1480_MC_tRCw _SB_MAKEMASK(5, S_BCM1480_MC_tRCw) +#define V_BCM1480_MC_tRCw(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRCw) +#define G_BCM1480_MC_tRCw(x) _SB_GETVALUE(x, S_BCM1480_MC_tRCw, M_BCM1480_MC_tRCw) +#define K_BCM1480_MC_tRCw_DEFAULT 10 +#define V_BCM1480_MC_tRCw_DEFAULT V_BCM1480_MC_tRCw(K_BCM1480_MC_tRCw_DEFAULT) + +#define S_BCM1480_MC_tRCr 32 +#define M_BCM1480_MC_tRCr _SB_MAKEMASK(5, S_BCM1480_MC_tRCr) +#define V_BCM1480_MC_tRCr(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRCr) +#define G_BCM1480_MC_tRCr(x) _SB_GETVALUE(x, S_BCM1480_MC_tRCr, M_BCM1480_MC_tRCr) +#define K_BCM1480_MC_tRCr_DEFAULT 9 +#define V_BCM1480_MC_tRCr_DEFAULT V_BCM1480_MC_tRCr(K_BCM1480_MC_tRCr_DEFAULT) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define S_BCM1480_MC_tFAW 40 +#define M_BCM1480_MC_tFAW _SB_MAKEMASK(6, S_BCM1480_MC_tFAW) +#define V_BCM1480_MC_tFAW(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tFAW) +#define G_BCM1480_MC_tFAW(x) _SB_GETVALUE(x, S_BCM1480_MC_tFAW, M_BCM1480_MC_tFAW) +#define K_BCM1480_MC_tFAW_DEFAULT 0 +#define V_BCM1480_MC_tFAW_DEFAULT V_BCM1480_MC_tFAW(K_BCM1480_MC_tFAW_DEFAULT) +#endif + +#define S_BCM1480_MC_tRFC 48 +#define M_BCM1480_MC_tRFC _SB_MAKEMASK(7, S_BCM1480_MC_tRFC) +#define V_BCM1480_MC_tRFC(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRFC) +#define G_BCM1480_MC_tRFC(x) _SB_GETVALUE(x, S_BCM1480_MC_tRFC, M_BCM1480_MC_tRFC) +#define K_BCM1480_MC_tRFC_DEFAULT 12 +#define V_BCM1480_MC_tRFC_DEFAULT V_BCM1480_MC_tRFC(K_BCM1480_MC_tRFC_DEFAULT) + +#define S_BCM1480_MC_tFIFO 56 +#define M_BCM1480_MC_tFIFO _SB_MAKEMASK(2, S_BCM1480_MC_tFIFO) +#define V_BCM1480_MC_tFIFO(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tFIFO) +#define G_BCM1480_MC_tFIFO(x) _SB_GETVALUE(x, S_BCM1480_MC_tFIFO, M_BCM1480_MC_tFIFO) +#define K_BCM1480_MC_tFIFO_DEFAULT 0 +#define V_BCM1480_MC_tFIFO_DEFAULT V_BCM1480_MC_tFIFO(K_BCM1480_MC_tFIFO_DEFAULT) + +#define S_BCM1480_MC_tW2R 58 +#define M_BCM1480_MC_tW2R _SB_MAKEMASK(2, S_BCM1480_MC_tW2R) +#define V_BCM1480_MC_tW2R(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tW2R) +#define G_BCM1480_MC_tW2R(x) _SB_GETVALUE(x, S_BCM1480_MC_tW2R, M_BCM1480_MC_tW2R) +#define K_BCM1480_MC_tW2R_DEFAULT 1 +#define V_BCM1480_MC_tW2R_DEFAULT V_BCM1480_MC_tW2R(K_BCM1480_MC_tW2R_DEFAULT) + +#define S_BCM1480_MC_tR2W 60 +#define M_BCM1480_MC_tR2W _SB_MAKEMASK(2, S_BCM1480_MC_tR2W) +#define V_BCM1480_MC_tR2W(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tR2W) +#define G_BCM1480_MC_tR2W(x) _SB_GETVALUE(x, S_BCM1480_MC_tR2W, M_BCM1480_MC_tR2W) +#define K_BCM1480_MC_tR2W_DEFAULT 0 +#define V_BCM1480_MC_tR2W_DEFAULT V_BCM1480_MC_tR2W(K_BCM1480_MC_tR2W_DEFAULT) + +#define M_BCM1480_MC_tR2R _SB_MAKEMASK1(62) + +#define V_BCM1480_MC_TIMING_DEFAULT (M_BCM1480_MC_tR2R | \ + V_BCM1480_MC_tFIFO_DEFAULT | \ + V_BCM1480_MC_tR2W_DEFAULT | \ + V_BCM1480_MC_tW2R_DEFAULT | \ + V_BCM1480_MC_tRFC_DEFAULT | \ + V_BCM1480_MC_tRCr_DEFAULT | \ + V_BCM1480_MC_tRCw_DEFAULT | \ + V_BCM1480_MC_tRRD_DEFAULT | \ + V_BCM1480_MC_tRP_DEFAULT | \ + V_BCM1480_MC_tCwD_DEFAULT | \ + V_BCM1480_MC_tWR_DEFAULT | \ + M_BCM1480_MC_tCrDh | \ + V_BCM1480_MC_tCL_DEFAULT | \ + V_BCM1480_MC_tRCD_DEFAULT) + +/* + * SDRAM Timing Register 2 + */ + +#if SIBYTE_HDR_FEATURE(1480, PASS2) + +#define S_BCM1480_MC_tAL 0 +#define M_BCM1480_MC_tAL _SB_MAKEMASK(4, S_BCM1480_MC_tAL) +#define V_BCM1480_MC_tAL(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tAL) +#define G_BCM1480_MC_tAL(x) _SB_GETVALUE(x, S_BCM1480_MC_tAL, M_BCM1480_MC_tAL) +#define K_BCM1480_MC_tAL_DEFAULT 0 +#define V_BCM1480_MC_tAL_DEFAULT V_BCM1480_MC_tAL(K_BCM1480_MC_tAL_DEFAULT) + +#define S_BCM1480_MC_tRTP 4 +#define M_BCM1480_MC_tRTP _SB_MAKEMASK(3, S_BCM1480_MC_tRTP) +#define V_BCM1480_MC_tRTP(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRTP) +#define G_BCM1480_MC_tRTP(x) _SB_GETVALUE(x, S_BCM1480_MC_tRTP, M_BCM1480_MC_tRTP) +#define K_BCM1480_MC_tRTP_DEFAULT 2 +#define V_BCM1480_MC_tRTP_DEFAULT V_BCM1480_MC_tRTP(K_BCM1480_MC_tRTP_DEFAULT) + +#define S_BCM1480_MC_tW2W 8 +#define M_BCM1480_MC_tW2W _SB_MAKEMASK(2, S_BCM1480_MC_tW2W) +#define V_BCM1480_MC_tW2W(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tW2W) +#define G_BCM1480_MC_tW2W(x) _SB_GETVALUE(x, S_BCM1480_MC_tW2W, M_BCM1480_MC_tW2W) +#define K_BCM1480_MC_tW2W_DEFAULT 0 +#define V_BCM1480_MC_tW2W_DEFAULT V_BCM1480_MC_tW2W(K_BCM1480_MC_tW2W_DEFAULT) + +#define S_BCM1480_MC_tRAP 12 +#define M_BCM1480_MC_tRAP _SB_MAKEMASK(4, S_BCM1480_MC_tRAP) +#define V_BCM1480_MC_tRAP(x) _SB_MAKEVALUE(x, S_BCM1480_MC_tRAP) +#define G_BCM1480_MC_tRAP(x) _SB_GETVALUE(x, S_BCM1480_MC_tRAP, M_BCM1480_MC_tRAP) +#define K_BCM1480_MC_tRAP_DEFAULT 0 +#define V_BCM1480_MC_tRAP_DEFAULT V_BCM1480_MC_tRAP(K_BCM1480_MC_tRAP_DEFAULT) + +#endif + + + +/* + * Global Registers: single instances per BCM1480 + */ + +/* + * Global Configuration Register (Table 99) + */ + +#define S_BCM1480_MC_BLK_SET_MARK 8 +#define M_BCM1480_MC_BLK_SET_MARK _SB_MAKEMASK(4, S_BCM1480_MC_BLK_SET_MARK) +#define V_BCM1480_MC_BLK_SET_MARK(x) _SB_MAKEVALUE(x, S_BCM1480_MC_BLK_SET_MARK) +#define G_BCM1480_MC_BLK_SET_MARK(x) _SB_GETVALUE(x, S_BCM1480_MC_BLK_SET_MARK, M_BCM1480_MC_BLK_SET_MARK) + +#define S_BCM1480_MC_BLK_CLR_MARK 12 +#define M_BCM1480_MC_BLK_CLR_MARK _SB_MAKEMASK(4, S_BCM1480_MC_BLK_CLR_MARK) +#define V_BCM1480_MC_BLK_CLR_MARK(x) _SB_MAKEVALUE(x, S_BCM1480_MC_BLK_CLR_MARK) +#define G_BCM1480_MC_BLK_CLR_MARK(x) _SB_GETVALUE(x, S_BCM1480_MC_BLK_CLR_MARK, M_BCM1480_MC_BLK_CLR_MARK) + +#define M_BCM1480_MC_PKT_PRIORITY _SB_MAKEMASK1(16) + +#define S_BCM1480_MC_MAX_AGE 20 +#define M_BCM1480_MC_MAX_AGE _SB_MAKEMASK(4, S_BCM1480_MC_MAX_AGE) +#define V_BCM1480_MC_MAX_AGE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_MAX_AGE) +#define G_BCM1480_MC_MAX_AGE(x) _SB_GETVALUE(x, S_BCM1480_MC_MAX_AGE, M_BCM1480_MC_MAX_AGE) + +#define M_BCM1480_MC_BERR_DISABLE _SB_MAKEMASK1(29) +#define M_BCM1480_MC_FORCE_SEQ _SB_MAKEMASK1(30) +#define M_BCM1480_MC_VGEN _SB_MAKEMASK1(32) + +#define S_BCM1480_MC_SLEW 33 +#define M_BCM1480_MC_SLEW _SB_MAKEMASK(2, S_BCM1480_MC_SLEW) +#define V_BCM1480_MC_SLEW(x) _SB_MAKEVALUE(x, S_BCM1480_MC_SLEW) +#define G_BCM1480_MC_SLEW(x) _SB_GETVALUE(x, S_BCM1480_MC_SLEW, M_BCM1480_MC_SLEW) + +#define M_BCM1480_MC_SSTL_VOLTAGE _SB_MAKEMASK1(35) + +/* + * Global Channel Interleave Register (Table 100) + */ + +#define S_BCM1480_MC_INTLV0 0 +#define M_BCM1480_MC_INTLV0 _SB_MAKEMASK(6, S_BCM1480_MC_INTLV0) +#define V_BCM1480_MC_INTLV0(x) _SB_MAKEVALUE(x, S_BCM1480_MC_INTLV0) +#define G_BCM1480_MC_INTLV0(x) _SB_GETVALUE(x, S_BCM1480_MC_INTLV0, M_BCM1480_MC_INTLV0) + +#define S_BCM1480_MC_INTLV1 8 +#define M_BCM1480_MC_INTLV1 _SB_MAKEMASK(6, S_BCM1480_MC_INTLV1) +#define V_BCM1480_MC_INTLV1(x) _SB_MAKEVALUE(x, S_BCM1480_MC_INTLV1) +#define G_BCM1480_MC_INTLV1(x) _SB_GETVALUE(x, S_BCM1480_MC_INTLV1, M_BCM1480_MC_INTLV1) + +#define S_BCM1480_MC_INTLV_MODE 16 +#define M_BCM1480_MC_INTLV_MODE _SB_MAKEMASK(3, S_BCM1480_MC_INTLV_MODE) +#define V_BCM1480_MC_INTLV_MODE(x) _SB_MAKEVALUE(x, S_BCM1480_MC_INTLV_MODE) +#define G_BCM1480_MC_INTLV_MODE(x) _SB_GETVALUE(x, S_BCM1480_MC_INTLV_MODE, M_BCM1480_MC_INTLV_MODE) + +#define K_BCM1480_MC_INTLV_MODE_NONE 0x0 +#define K_BCM1480_MC_INTLV_MODE_01 0x1 +#define K_BCM1480_MC_INTLV_MODE_23 0x2 +#define K_BCM1480_MC_INTLV_MODE_01_23 0x3 +#define K_BCM1480_MC_INTLV_MODE_0123 0x4 + +#define V_BCM1480_MC_INTLV_MODE_NONE V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_NONE) +#define V_BCM1480_MC_INTLV_MODE_01 V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_01) +#define V_BCM1480_MC_INTLV_MODE_23 V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_23) +#define V_BCM1480_MC_INTLV_MODE_01_23 V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_01_23) +#define V_BCM1480_MC_INTLV_MODE_0123 V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_0123) + +/* + * ECC Status Register + */ + +#define S_BCM1480_MC_ECC_ERR_ADDR 0 +#define M_BCM1480_MC_ECC_ERR_ADDR _SB_MAKEMASK(37, S_BCM1480_MC_ECC_ERR_ADDR) +#define V_BCM1480_MC_ECC_ERR_ADDR(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ECC_ERR_ADDR) +#define G_BCM1480_MC_ECC_ERR_ADDR(x) _SB_GETVALUE(x, S_BCM1480_MC_ECC_ERR_ADDR, M_BCM1480_MC_ECC_ERR_ADDR) + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define M_BCM1480_MC_ECC_ERR_RMW _SB_MAKEMASK1(60) +#endif + +#define M_BCM1480_MC_ECC_MULT_ERR_DET _SB_MAKEMASK1(61) +#define M_BCM1480_MC_ECC_UERR_DET _SB_MAKEMASK1(62) +#define M_BCM1480_MC_ECC_CERR_DET _SB_MAKEMASK1(63) + +/* + * Global ECC Address Register (Table 102) + */ + +#define S_BCM1480_MC_ECC_CORR_ADDR 0 +#define M_BCM1480_MC_ECC_CORR_ADDR _SB_MAKEMASK(37, S_BCM1480_MC_ECC_CORR_ADDR) +#define V_BCM1480_MC_ECC_CORR_ADDR(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ECC_CORR_ADDR) +#define G_BCM1480_MC_ECC_CORR_ADDR(x) _SB_GETVALUE(x, S_BCM1480_MC_ECC_CORR_ADDR, M_BCM1480_MC_ECC_CORR_ADDR) + +/* + * Global ECC Correction Register (Table 103) + */ + +#define S_BCM1480_MC_ECC_CORRECT 0 +#define M_BCM1480_MC_ECC_CORRECT _SB_MAKEMASK(64, S_BCM1480_MC_ECC_CORRECT) +#define V_BCM1480_MC_ECC_CORRECT(x) _SB_MAKEVALUE(x, S_BCM1480_MC_ECC_CORRECT) +#define G_BCM1480_MC_ECC_CORRECT(x) _SB_GETVALUE(x, S_BCM1480_MC_ECC_CORRECT, M_BCM1480_MC_ECC_CORRECT) + +/* + * Global ECC Performance Counters Control Register (Table 104) + */ + +#define S_BCM1480_MC_CHANNEL_SELECT 0 +#define M_BCM1480_MC_CHANNEL_SELECT _SB_MAKEMASK(4, S_BCM1480_MC_CHANNEL_SELECT) +#define V_BCM1480_MC_CHANNEL_SELECT(x) _SB_MAKEVALUE(x, S_BCM1480_MC_CHANNEL_SELECT) +#define G_BCM1480_MC_CHANNEL_SELECT(x) _SB_GETVALUE(x, S_BCM1480_MC_CHANNEL_SELECT, M_BCM1480_MC_CHANNEL_SELECT) +#define K_BCM1480_MC_CHANNEL_SELECT_0 0x1 +#define K_BCM1480_MC_CHANNEL_SELECT_1 0x2 +#define K_BCM1480_MC_CHANNEL_SELECT_2 0x4 +#define K_BCM1480_MC_CHANNEL_SELECT_3 0x8 + +#endif /* _BCM1480_MC_H */ diff --git a/arch/mips/include/asm/sibyte/bcm1480_regs.h b/arch/mips/include/asm/sibyte/bcm1480_regs.h new file mode 100644 index 00000000000..b4077bb7261 --- /dev/null +++ b/arch/mips/include/asm/sibyte/bcm1480_regs.h @@ -0,0 +1,902 @@ +/* ********************************************************************* + * BCM1255/BCM1280/BCM1455/BCM1480 Board Support Package + * + * Register Definitions File: bcm1480_regs.h + * + * This module contains the addresses of the on-chip peripherals + * on the BCM1280 and BCM1480. + * + * BCM1480 specification level: 1X55_1X80-UM100-D4 (11/24/03) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _BCM1480_REGS_H +#define _BCM1480_REGS_H + +#include "sb1250_defs.h" + +/* ********************************************************************* + * Pull in the BCM1250's registers since a great deal of the 1480's + * functions are the same as the BCM1250. + ********************************************************************* */ + +#include "sb1250_regs.h" + + +/* ********************************************************************* + * Some general notes: + * + * Register addresses are grouped by function and follow the order + * of the User Manual. + * + * For the most part, when there is more than one peripheral + * of the same type on the SOC, the constants below will be + * offsets from the base of each peripheral. For example, + * the MAC registers are described as offsets from the first + * MAC register, and there will be a MAC_REGISTER() macro + * to calculate the base address of a given MAC. + * + * The information in this file is based on the BCM1X55/BCM1X80 + * User Manual, Document 1X55_1X80-UM100-R, 22/12/03. + * + * This file is basically a "what's new" header file. Since the + * BCM1250 and the new BCM1480 (and derivatives) share many common + * features, this file contains only what's new or changed from + * the 1250. (above, you can see that we include the 1250 symbols + * to get the base functionality). + * + * In software, be sure to use the correct symbols, particularly + * for blocks that are different between the two chip families. + * All BCM1480-specific symbols have _BCM1480_ in their names, + * and all BCM1250-specific and "base" functions that are common in + * both chips have no special names (this is for compatibility with + * older include files). Therefore, if you're working with the + * SCD, which is very different on each chip, A_SCD_xxx implies + * the BCM1250 version and A_BCM1480_SCD_xxx implies the BCM1480 + * version. + ********************************************************************* */ + + +/* ********************************************************************* + * Memory Controller Registers (Section 6) + ********************************************************************* */ + +#define A_BCM1480_MC_BASE_0 0x0010050000 +#define A_BCM1480_MC_BASE_1 0x0010051000 +#define A_BCM1480_MC_BASE_2 0x0010052000 +#define A_BCM1480_MC_BASE_3 0x0010053000 +#define BCM1480_MC_REGISTER_SPACING 0x1000 + +#define A_BCM1480_MC_BASE(ctlid) (A_BCM1480_MC_BASE_0+(ctlid)*BCM1480_MC_REGISTER_SPACING) +#define A_BCM1480_MC_REGISTER(ctlid, reg) (A_BCM1480_MC_BASE(ctlid)+(reg)) + +#define R_BCM1480_MC_CONFIG 0x0000000100 +#define R_BCM1480_MC_CS_START 0x0000000120 +#define R_BCM1480_MC_CS_END 0x0000000140 +#define S_BCM1480_MC_CS_STARTEND 24 + +#define R_BCM1480_MC_CS01_ROW0 0x0000000180 +#define R_BCM1480_MC_CS01_ROW1 0x00000001A0 +#define R_BCM1480_MC_CS23_ROW0 0x0000000200 +#define R_BCM1480_MC_CS23_ROW1 0x0000000220 +#define R_BCM1480_MC_CS01_COL0 0x0000000280 +#define R_BCM1480_MC_CS01_COL1 0x00000002A0 +#define R_BCM1480_MC_CS23_COL0 0x0000000300 +#define R_BCM1480_MC_CS23_COL1 0x0000000320 + +#define R_BCM1480_MC_CSX_BASE 0x0000000180 +#define R_BCM1480_MC_CSX_ROW0 0x0000000000 /* relative to CSX_BASE */ +#define R_BCM1480_MC_CSX_ROW1 0x0000000020 /* relative to CSX_BASE */ +#define R_BCM1480_MC_CSX_COL0 0x0000000100 /* relative to CSX_BASE */ +#define R_BCM1480_MC_CSX_COL1 0x0000000120 /* relative to CSX_BASE */ +#define BCM1480_MC_CSX_SPACING 0x0000000080 /* CS23 relative to CS01 */ + +#define R_BCM1480_MC_CS01_BA 0x0000000380 +#define R_BCM1480_MC_CS23_BA 0x00000003A0 +#define R_BCM1480_MC_DRAMCMD 0x0000000400 +#define R_BCM1480_MC_DRAMMODE 0x0000000420 +#define R_BCM1480_MC_CLOCK_CFG 0x0000000440 +#define R_BCM1480_MC_MCLK_CFG R_BCM1480_MC_CLOCK_CFG +#define R_BCM1480_MC_TEST_DATA 0x0000000480 +#define R_BCM1480_MC_TEST_ECC 0x00000004A0 +#define R_BCM1480_MC_TIMING1 0x00000004C0 +#define R_BCM1480_MC_TIMING2 0x00000004E0 +#define R_BCM1480_MC_DLL_CFG 0x0000000500 +#define R_BCM1480_MC_DRIVE_CFG 0x0000000520 + +#if SIBYTE_HDR_FEATURE(1480, PASS2) +#define R_BCM1480_MC_ODT 0x0000000460 +#define R_BCM1480_MC_ECC_STATUS 0x0000000540 +#endif + +/* Global registers (single instance) */ +#define A_BCM1480_MC_GLB_CONFIG 0x0010054100 +#define A_BCM1480_MC_GLB_INTLV 0x0010054120 +#define A_BCM1480_MC_GLB_ECC_STATUS 0x0010054140 +#define A_BCM1480_MC_GLB_ECC_ADDR 0x0010054160 +#define A_BCM1480_MC_GLB_ECC_CORRECT 0x0010054180 +#define A_BCM1480_MC_GLB_PERF_CNT_CONTROL 0x00100541A0 + +/* ********************************************************************* + * L2 Cache Control Registers (Section 5) + ********************************************************************* */ + +#define A_BCM1480_L2_BASE 0x0010040000 + +#define A_BCM1480_L2_READ_TAG 0x0010040018 +#define A_BCM1480_L2_ECC_TAG 0x0010040038 +#define A_BCM1480_L2_MISC0_VALUE 0x0010040058 +#define A_BCM1480_L2_MISC1_VALUE 0x0010040078 +#define A_BCM1480_L2_MISC2_VALUE 0x0010040098 +#define A_BCM1480_L2_MISC_CONFIG 0x0010040040 /* x040 */ +#define A_BCM1480_L2_CACHE_DISABLE 0x0010040060 /* x060 */ +#define A_BCM1480_L2_MAKECACHEDISABLE(x) (A_BCM1480_L2_CACHE_DISABLE | (((x)&0xF) << 12)) +#define A_BCM1480_L2_WAY_ENABLE_3_0 0x0010040080 /* x080 */ +#define A_BCM1480_L2_WAY_ENABLE_7_4 0x00100400A0 /* x0A0 */ +#define A_BCM1480_L2_MAKE_WAY_ENABLE_LO(x) (A_BCM1480_L2_WAY_ENABLE_3_0 | (((x)&0xF) << 12)) +#define A_BCM1480_L2_MAKE_WAY_ENABLE_HI(x) (A_BCM1480_L2_WAY_ENABLE_7_4 | (((x)&0xF) << 12)) +#define A_BCM1480_L2_MAKE_WAY_DISABLE_LO(x) (A_BCM1480_L2_WAY_ENABLE_3_0 | (((~x)&0xF) << 12)) +#define A_BCM1480_L2_MAKE_WAY_DISABLE_HI(x) (A_BCM1480_L2_WAY_ENABLE_7_4 | (((~x)&0xF) << 12)) +#define A_BCM1480_L2_WAY_LOCAL_3_0 0x0010040100 /* x100 */ +#define A_BCM1480_L2_WAY_LOCAL_7_4 0x0010040120 /* x120 */ +#define A_BCM1480_L2_WAY_REMOTE_3_0 0x0010040140 /* x140 */ +#define A_BCM1480_L2_WAY_REMOTE_7_4 0x0010040160 /* x160 */ +#define A_BCM1480_L2_WAY_AGENT_3_0 0x00100400C0 /* xxC0 */ +#define A_BCM1480_L2_WAY_AGENT_7_4 0x00100400E0 /* xxE0 */ +#define A_BCM1480_L2_WAY_ENABLE(A, banks) (A | (((~(banks))&0x0F) << 8)) +#define A_BCM1480_L2_BANK_BASE 0x00D0300000 +#define A_BCM1480_L2_BANK_ADDRESS(b) (A_BCM1480_L2_BANK_BASE | (((b)&0x7)<<17)) +#define A_BCM1480_L2_MGMT_TAG_BASE 0x00D0000000 + + +/* ********************************************************************* + * PCI-X Interface Registers (Section 7) + ********************************************************************* */ + +#define A_BCM1480_PCI_BASE 0x0010061400 + +#define A_BCM1480_PCI_RESET 0x0010061400 +#define A_BCM1480_PCI_DLL 0x0010061500 + +#define A_BCM1480_PCI_TYPE00_HEADER 0x002E000000 + +/* ********************************************************************* + * Ethernet MAC Registers (Section 11) and DMA Registers (Section 10.6) + ********************************************************************* */ + +/* No register changes with Rev.C BCM1250, but one additional MAC */ + +#define A_BCM1480_MAC_BASE_2 0x0010066000 + +#ifndef A_MAC_BASE_2 +#define A_MAC_BASE_2 A_BCM1480_MAC_BASE_2 +#endif + +#define A_BCM1480_MAC_BASE_3 0x0010067000 +#define A_MAC_BASE_3 A_BCM1480_MAC_BASE_3 + +#define R_BCM1480_MAC_DMA_OODPKTLOST 0x00000038 + +#ifndef R_MAC_DMA_OODPKTLOST +#define R_MAC_DMA_OODPKTLOST R_BCM1480_MAC_DMA_OODPKTLOST +#endif + + +/* ********************************************************************* + * DUART Registers (Section 14) + ********************************************************************* */ + +/* No significant differences from BCM1250, two DUARTs */ + +/* Conventions, per user manual: + * DUART generic, channels A,B,C,D + * DUART0 implementing channels A,B + * DUART1 inplementing channels C,D + */ + +#define BCM1480_DUART_NUM_PORTS 4 + +#define A_BCM1480_DUART0 0x0010060000 +#define A_BCM1480_DUART1 0x0010060400 +#define A_BCM1480_DUART(chan) ((((chan)&2) == 0)? A_BCM1480_DUART0 : A_BCM1480_DUART1) + +#define BCM1480_DUART_CHANREG_SPACING 0x100 +#define A_BCM1480_DUART_CHANREG(chan, reg) \ + (A_BCM1480_DUART(chan) + \ + BCM1480_DUART_CHANREG_SPACING * (((chan) & 1) + 1) + (reg)) +#define A_BCM1480_DUART_CTRLREG(chan, reg) \ + (A_BCM1480_DUART(chan) + \ + BCM1480_DUART_CHANREG_SPACING * 3 + (reg)) + +#define DUART_IMRISR_SPACING 0x20 +#define DUART_INCHNG_SPACING 0x10 + +#define R_BCM1480_DUART_IMRREG(chan) \ + (R_DUART_IMR_A + ((chan) & 1) * DUART_IMRISR_SPACING) +#define R_BCM1480_DUART_ISRREG(chan) \ + (R_DUART_ISR_A + ((chan) & 1) * DUART_IMRISR_SPACING) +#define R_BCM1480_DUART_INCHREG(chan) \ + (R_DUART_IN_CHNG_A + ((chan) & 1) * DUART_INCHNG_SPACING) + +#define A_BCM1480_DUART_IMRREG(chan) \ + (A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_IMRREG(chan))) +#define A_BCM1480_DUART_ISRREG(chan) \ + (A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_ISRREG(chan))) + +#define A_BCM1480_DUART_IN_PORT(chan) \ + (A_BCM1480_DUART_CTRLREG((chan), R_DUART_IN_PORT)) + +/* + * These constants are the absolute addresses. + */ + +#define A_BCM1480_DUART_MODE_REG_1_C 0x0010060400 +#define A_BCM1480_DUART_MODE_REG_2_C 0x0010060410 +#define A_BCM1480_DUART_STATUS_C 0x0010060420 +#define A_BCM1480_DUART_CLK_SEL_C 0x0010060430 +#define A_BCM1480_DUART_FULL_CTL_C 0x0010060440 +#define A_BCM1480_DUART_CMD_C 0x0010060450 +#define A_BCM1480_DUART_RX_HOLD_C 0x0010060460 +#define A_BCM1480_DUART_TX_HOLD_C 0x0010060470 +#define A_BCM1480_DUART_OPCR_C 0x0010060480 +#define A_BCM1480_DUART_AUX_CTRL_C 0x0010060490 + +#define A_BCM1480_DUART_MODE_REG_1_D 0x0010060500 +#define A_BCM1480_DUART_MODE_REG_2_D 0x0010060510 +#define A_BCM1480_DUART_STATUS_D 0x0010060520 +#define A_BCM1480_DUART_CLK_SEL_D 0x0010060530 +#define A_BCM1480_DUART_FULL_CTL_D 0x0010060540 +#define A_BCM1480_DUART_CMD_D 0x0010060550 +#define A_BCM1480_DUART_RX_HOLD_D 0x0010060560 +#define A_BCM1480_DUART_TX_HOLD_D 0x0010060570 +#define A_BCM1480_DUART_OPCR_D 0x0010060580 +#define A_BCM1480_DUART_AUX_CTRL_D 0x0010060590 + +#define A_BCM1480_DUART_INPORT_CHNG_CD 0x0010060600 +#define A_BCM1480_DUART_AUX_CTRL_CD 0x0010060610 +#define A_BCM1480_DUART_ISR_C 0x0010060620 +#define A_BCM1480_DUART_IMR_C 0x0010060630 +#define A_BCM1480_DUART_ISR_D 0x0010060640 +#define A_BCM1480_DUART_IMR_D 0x0010060650 +#define A_BCM1480_DUART_OUT_PORT_CD 0x0010060660 +#define A_BCM1480_DUART_OPCR_CD 0x0010060670 +#define A_BCM1480_DUART_IN_PORT_CD 0x0010060680 +#define A_BCM1480_DUART_ISR_CD 0x0010060690 +#define A_BCM1480_DUART_IMR_CD 0x00100606A0 +#define A_BCM1480_DUART_SET_OPR_CD 0x00100606B0 +#define A_BCM1480_DUART_CLEAR_OPR_CD 0x00100606C0 +#define A_BCM1480_DUART_INPORT_CHNG_C 0x00100606D0 +#define A_BCM1480_DUART_INPORT_CHNG_D 0x00100606E0 + + +/* ********************************************************************* + * Generic Bus Registers (Section 15) and PCMCIA Registers (Section 16) + ********************************************************************* */ + +#define A_BCM1480_IO_PCMCIA_CFG_B 0x0010061A58 +#define A_BCM1480_IO_PCMCIA_STATUS_B 0x0010061A68 + +/* ********************************************************************* + * GPIO Registers (Section 17) + ********************************************************************* */ + +/* One additional GPIO register, placed _before_ the BCM1250's GPIO block base */ + +#define A_BCM1480_GPIO_INT_ADD_TYPE 0x0010061A78 +#define R_BCM1480_GPIO_INT_ADD_TYPE (-8) + +#define A_GPIO_INT_ADD_TYPE A_BCM1480_GPIO_INT_ADD_TYPE +#define R_GPIO_INT_ADD_TYPE R_BCM1480_GPIO_INT_ADD_TYPE + +/* ********************************************************************* + * SMBus Registers (Section 18) + ********************************************************************* */ + +/* No changes from BCM1250 */ + +/* ********************************************************************* + * Timer Registers (Sections 4.6) + ********************************************************************* */ + +/* BCM1480 has two additional watchdogs */ + +/* Watchdog timers */ + +#define A_BCM1480_SCD_WDOG_2 0x0010022050 +#define A_BCM1480_SCD_WDOG_3 0x0010022150 + +#define BCM1480_SCD_NUM_WDOGS 4 + +#define A_BCM1480_SCD_WDOG_BASE(w) (A_BCM1480_SCD_WDOG_0+((w)&2)*0x1000 + ((w)&1)*0x100) +#define A_BCM1480_SCD_WDOG_REGISTER(w, r) (A_BCM1480_SCD_WDOG_BASE(w) + (r)) + +#define A_BCM1480_SCD_WDOG_INIT_2 0x0010022050 +#define A_BCM1480_SCD_WDOG_CNT_2 0x0010022058 +#define A_BCM1480_SCD_WDOG_CFG_2 0x0010022060 + +#define A_BCM1480_SCD_WDOG_INIT_3 0x0010022150 +#define A_BCM1480_SCD_WDOG_CNT_3 0x0010022158 +#define A_BCM1480_SCD_WDOG_CFG_3 0x0010022160 + +/* BCM1480 has two additional compare registers */ + +#define A_BCM1480_SCD_ZBBUS_CYCLE_COUNT A_SCD_ZBBUS_CYCLE_COUNT +#define A_BCM1480_SCD_ZBBUS_CYCLE_CP_BASE 0x0010020C00 +#define A_BCM1480_SCD_ZBBUS_CYCLE_CP0 A_SCD_ZBBUS_CYCLE_CP0 +#define A_BCM1480_SCD_ZBBUS_CYCLE_CP1 A_SCD_ZBBUS_CYCLE_CP1 +#define A_BCM1480_SCD_ZBBUS_CYCLE_CP2 0x0010020C10 +#define A_BCM1480_SCD_ZBBUS_CYCLE_CP3 0x0010020C18 + +/* ********************************************************************* + * System Control Registers (Section 4.2) + ********************************************************************* */ + +/* Scratch register in different place */ + +#define A_BCM1480_SCD_SCRATCH 0x100200A0 + +/* ********************************************************************* + * System Address Trap Registers (Section 4.9) + ********************************************************************* */ + +/* No changes from BCM1250 */ + +/* ********************************************************************* + * System Interrupt Mapper Registers (Sections 4.3-4.5) + ********************************************************************* */ + +#define A_BCM1480_IMR_CPU0_BASE 0x0010020000 +#define A_BCM1480_IMR_CPU1_BASE 0x0010022000 +#define A_BCM1480_IMR_CPU2_BASE 0x0010024000 +#define A_BCM1480_IMR_CPU3_BASE 0x0010026000 +#define BCM1480_IMR_REGISTER_SPACING 0x2000 +#define BCM1480_IMR_REGISTER_SPACING_SHIFT 13 + +#define A_BCM1480_IMR_MAPPER(cpu) (A_BCM1480_IMR_CPU0_BASE+(cpu)*BCM1480_IMR_REGISTER_SPACING) +#define A_BCM1480_IMR_REGISTER(cpu, reg) (A_BCM1480_IMR_MAPPER(cpu)+(reg)) + +/* Most IMR registers are 128 bits, implemented as non-contiguous + 64-bit registers high (_H) and low (_L) */ +#define BCM1480_IMR_HL_SPACING 0x1000 + +#define R_BCM1480_IMR_INTERRUPT_DIAG_H 0x0010 +#define R_BCM1480_IMR_LDT_INTERRUPT_H 0x0018 +#define R_BCM1480_IMR_LDT_INTERRUPT_CLR_H 0x0020 +#define R_BCM1480_IMR_INTERRUPT_MASK_H 0x0028 +#define R_BCM1480_IMR_INTERRUPT_TRACE_H 0x0038 +#define R_BCM1480_IMR_INTERRUPT_SOURCE_STATUS_H 0x0040 +#define R_BCM1480_IMR_LDT_INTERRUPT_SET 0x0048 +#define R_BCM1480_IMR_MAILBOX_0_CPU 0x00C0 +#define R_BCM1480_IMR_MAILBOX_0_SET_CPU 0x00C8 +#define R_BCM1480_IMR_MAILBOX_0_CLR_CPU 0x00D0 +#define R_BCM1480_IMR_MAILBOX_1_CPU 0x00E0 +#define R_BCM1480_IMR_MAILBOX_1_SET_CPU 0x00E8 +#define R_BCM1480_IMR_MAILBOX_1_CLR_CPU 0x00F0 +#define R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H 0x0100 +#define BCM1480_IMR_INTERRUPT_STATUS_COUNT 8 +#define R_BCM1480_IMR_INTERRUPT_MAP_BASE_H 0x0200 +#define BCM1480_IMR_INTERRUPT_MAP_COUNT 64 + +#define R_BCM1480_IMR_INTERRUPT_DIAG_L 0x1010 +#define R_BCM1480_IMR_LDT_INTERRUPT_L 0x1018 +#define R_BCM1480_IMR_LDT_INTERRUPT_CLR_L 0x1020 +#define R_BCM1480_IMR_INTERRUPT_MASK_L 0x1028 +#define R_BCM1480_IMR_INTERRUPT_TRACE_L 0x1038 +#define R_BCM1480_IMR_INTERRUPT_SOURCE_STATUS_L 0x1040 +#define R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L 0x1100 +#define R_BCM1480_IMR_INTERRUPT_MAP_BASE_L 0x1200 + +#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU0_BASE 0x0010028000 +#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU1_BASE 0x0010028100 +#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU2_BASE 0x0010028200 +#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU3_BASE 0x0010028300 +#define BCM1480_IMR_ALIAS_MAILBOX_SPACING 0100 + +#define A_BCM1480_IMR_ALIAS_MAILBOX(cpu) (A_BCM1480_IMR_ALIAS_MAILBOX_CPU0_BASE + \ + (cpu)*BCM1480_IMR_ALIAS_MAILBOX_SPACING) +#define A_BCM1480_IMR_ALIAS_MAILBOX_REGISTER(cpu, reg) (A_BCM1480_IMR_ALIAS_MAILBOX(cpu)+(reg)) + +#define R_BCM1480_IMR_ALIAS_MAILBOX_0 0x0000 /* 0x0x0 */ +#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET 0x0008 /* 0x0x8 */ + +/* + * these macros work together to build the address of a mailbox + * register, e.g., A_BCM1480_MAILBOX_REGISTER(0,R_BCM1480_IMR_MAILBOX_SET,2) + * for mbox_0_set_cpu2 returns 0x00100240C8 + */ +#define R_BCM1480_IMR_MAILBOX_CPU 0x00 +#define R_BCM1480_IMR_MAILBOX_SET 0x08 +#define R_BCM1480_IMR_MAILBOX_CLR 0x10 +#define R_BCM1480_IMR_MAILBOX_NUM_SPACING 0x20 +#define A_BCM1480_MAILBOX_REGISTER(num, reg, cpu) \ + (A_BCM1480_IMR_CPU0_BASE + \ + (num * R_BCM1480_IMR_MAILBOX_NUM_SPACING) + \ + (cpu * BCM1480_IMR_REGISTER_SPACING) + \ + (R_BCM1480_IMR_MAILBOX_0_CPU + reg)) + +/* ********************************************************************* + * System Performance Counter Registers (Section 4.7) + ********************************************************************* */ + +/* BCM1480 has four more performance counter registers, and two control + registers. */ + +#define A_BCM1480_SCD_PERF_CNT_BASE 0x00100204C0 + +#define A_BCM1480_SCD_PERF_CNT_CFG0 0x00100204C0 +#define A_BCM1480_SCD_PERF_CNT_CFG_0 A_BCM1480_SCD_PERF_CNT_CFG0 +#define A_BCM1480_SCD_PERF_CNT_CFG1 0x00100204C8 +#define A_BCM1480_SCD_PERF_CNT_CFG_1 A_BCM1480_SCD_PERF_CNT_CFG1 + +#define A_BCM1480_SCD_PERF_CNT_0 A_SCD_PERF_CNT_0 +#define A_BCM1480_SCD_PERF_CNT_1 A_SCD_PERF_CNT_1 +#define A_BCM1480_SCD_PERF_CNT_2 A_SCD_PERF_CNT_2 +#define A_BCM1480_SCD_PERF_CNT_3 A_SCD_PERF_CNT_3 + +#define A_BCM1480_SCD_PERF_CNT_4 0x00100204F0 +#define A_BCM1480_SCD_PERF_CNT_5 0x00100204F8 +#define A_BCM1480_SCD_PERF_CNT_6 0x0010020500 +#define A_BCM1480_SCD_PERF_CNT_7 0x0010020508 + +#define BCM1480_SCD_NUM_PERF_CNT 8 +#define BCM1480_SCD_PERF_CNT_SPACING 8 +#define A_BCM1480_SCD_PERF_CNT(n) (A_SCD_PERF_CNT_0+(n*BCM1480_SCD_PERF_CNT_SPACING)) + +/* ********************************************************************* + * System Bus Watcher Registers (Section 4.8) + ********************************************************************* */ + + +/* Same as 1250 except BUS_ERR_STATUS_DEBUG is in a different place. */ + +#define A_BCM1480_BUS_ERR_STATUS_DEBUG 0x00100208D8 + +/* ********************************************************************* + * System Debug Controller Registers (Section 19) + ********************************************************************* */ + +/* Same as 1250 */ + +/* ********************************************************************* + * System Trace Unit Registers (Sections 4.10) + ********************************************************************* */ + +/* Same as 1250 */ + +/* ********************************************************************* + * Data Mover DMA Registers (Section 10.7) + ********************************************************************* */ + +/* Same as 1250 */ + + +/* ********************************************************************* + * HyperTransport Interface Registers (Section 8) + ********************************************************************* */ + +#define BCM1480_HT_NUM_PORTS 3 +#define BCM1480_HT_PORT_SPACING 0x800 +#define A_BCM1480_HT_PORT_HEADER(x) (A_BCM1480_HT_PORT0_HEADER + ((x)*BCM1480_HT_PORT_SPACING)) + +#define A_BCM1480_HT_PORT0_HEADER 0x00FE000000 +#define A_BCM1480_HT_PORT1_HEADER 0x00FE000800 +#define A_BCM1480_HT_PORT2_HEADER 0x00FE001000 +#define A_BCM1480_HT_TYPE00_HEADER 0x00FE002000 + + +/* ********************************************************************* + * Node Controller Registers (Section 9) + ********************************************************************* */ + +#define A_BCM1480_NC_BASE 0x00DFBD0000 + +#define A_BCM1480_NC_RLD_FIELD 0x00DFBD0000 +#define A_BCM1480_NC_RLD_TRIGGER 0x00DFBD0020 +#define A_BCM1480_NC_RLD_BAD_ERROR 0x00DFBD0040 +#define A_BCM1480_NC_RLD_COR_ERROR 0x00DFBD0060 +#define A_BCM1480_NC_RLD_ECC_STATUS 0x00DFBD0080 +#define A_BCM1480_NC_RLD_WAY_ENABLE 0x00DFBD00A0 +#define A_BCM1480_NC_RLD_RANDOM_LFSR 0x00DFBD00C0 + +#define A_BCM1480_NC_INTERRUPT_STATUS 0x00DFBD00E0 +#define A_BCM1480_NC_INTERRUPT_ENABLE 0x00DFBD0100 +#define A_BCM1480_NC_TIMEOUT_COUNTER 0x00DFBD0120 +#define A_BCM1480_NC_TIMEOUT_COUNTER_SEL 0x00DFBD0140 + +#define A_BCM1480_NC_CREDIT_STATUS_REG0 0x00DFBD0200 +#define A_BCM1480_NC_CREDIT_STATUS_REG1 0x00DFBD0220 +#define A_BCM1480_NC_CREDIT_STATUS_REG2 0x00DFBD0240 +#define A_BCM1480_NC_CREDIT_STATUS_REG3 0x00DFBD0260 +#define A_BCM1480_NC_CREDIT_STATUS_REG4 0x00DFBD0280 +#define A_BCM1480_NC_CREDIT_STATUS_REG5 0x00DFBD02A0 +#define A_BCM1480_NC_CREDIT_STATUS_REG6 0x00DFBD02C0 +#define A_BCM1480_NC_CREDIT_STATUS_REG7 0x00DFBD02E0 +#define A_BCM1480_NC_CREDIT_STATUS_REG8 0x00DFBD0300 +#define A_BCM1480_NC_CREDIT_STATUS_REG9 0x00DFBD0320 +#define A_BCM1480_NC_CREDIT_STATUS_REG10 0x00DFBE0000 +#define A_BCM1480_NC_CREDIT_STATUS_REG11 0x00DFBE0020 +#define A_BCM1480_NC_CREDIT_STATUS_REG12 0x00DFBE0040 + +#define A_BCM1480_NC_SR_TIMEOUT_COUNTER 0x00DFBE0060 +#define A_BCM1480_NC_SR_TIMEOUT_COUNTER_SEL 0x00DFBE0080 + + +/* ********************************************************************* + * H&R Block Configuration Registers (Section 12.4) + ********************************************************************* */ + +#define A_BCM1480_HR_BASE_0 0x00DF820000 +#define A_BCM1480_HR_BASE_1 0x00DF8A0000 +#define A_BCM1480_HR_BASE_2 0x00DF920000 +#define BCM1480_HR_REGISTER_SPACING 0x80000 + +#define A_BCM1480_HR_BASE(idx) (A_BCM1480_HR_BASE_0 + ((idx)*BCM1480_HR_REGISTER_SPACING)) +#define A_BCM1480_HR_REGISTER(idx, reg) (A_BCM1480_HR_BASE(idx) + (reg)) + +#define R_BCM1480_HR_CFG 0x0000000000 + +#define R_BCM1480_HR_MAPPING 0x0000010010 + +#define BCM1480_HR_RULE_SPACING 0x0000000010 +#define BCM1480_HR_NUM_RULES 16 +#define BCM1480_HR_OP_OFFSET 0x0000000100 +#define BCM1480_HR_TYPE_OFFSET 0x0000000108 +#define R_BCM1480_HR_RULE_OP(idx) (BCM1480_HR_OP_OFFSET + ((idx)*BCM1480_HR_RULE_SPACING)) +#define R_BCM1480_HR_RULE_TYPE(idx) (BCM1480_HR_TYPE_OFFSET + ((idx)*BCM1480_HR_RULE_SPACING)) + +#define BCM1480_HR_LEAF_SPACING 0x0000000010 +#define BCM1480_HR_NUM_LEAVES 10 +#define BCM1480_HR_LEAF_OFFSET 0x0000000300 +#define R_BCM1480_HR_HA_LEAF0(idx) (BCM1480_HR_LEAF_OFFSET + ((idx)*BCM1480_HR_LEAF_SPACING)) + +#define R_BCM1480_HR_EX_LEAF0 0x00000003A0 + +#define BCM1480_HR_PATH_SPACING 0x0000000010 +#define BCM1480_HR_NUM_PATHS 16 +#define BCM1480_HR_PATH_OFFSET 0x0000000600 +#define R_BCM1480_HR_PATH(idx) (BCM1480_HR_PATH_OFFSET + ((idx)*BCM1480_HR_PATH_SPACING)) + +#define R_BCM1480_HR_PATH_DEFAULT 0x0000000700 + +#define BCM1480_HR_ROUTE_SPACING 8 +#define BCM1480_HR_NUM_ROUTES 512 +#define BCM1480_HR_ROUTE_OFFSET 0x0000001000 +#define R_BCM1480_HR_RT_WORD(idx) (BCM1480_HR_ROUTE_OFFSET + ((idx)*BCM1480_HR_ROUTE_SPACING)) + + +/* checked to here - ehs */ +/* ********************************************************************* + * Packet Manager DMA Registers (Section 12.5) + ********************************************************************* */ + +#define A_BCM1480_PM_BASE 0x0010056000 + +#define A_BCM1480_PMI_LCL_0 0x0010058000 +#define A_BCM1480_PMO_LCL_0 0x001005C000 +#define A_BCM1480_PMI_OFFSET_0 (A_BCM1480_PMI_LCL_0 - A_BCM1480_PM_BASE) +#define A_BCM1480_PMO_OFFSET_0 (A_BCM1480_PMO_LCL_0 - A_BCM1480_PM_BASE) + +#define BCM1480_PM_LCL_REGISTER_SPACING 0x100 +#define BCM1480_PM_NUM_CHANNELS 32 + +#define A_BCM1480_PMI_LCL_BASE(idx) (A_BCM1480_PMI_LCL_0 + ((idx)*BCM1480_PM_LCL_REGISTER_SPACING)) +#define A_BCM1480_PMI_LCL_REGISTER(idx, reg) (A_BCM1480_PMI_LCL_BASE(idx) + (reg)) +#define A_BCM1480_PMO_LCL_BASE(idx) (A_BCM1480_PMO_LCL_0 + ((idx)*BCM1480_PM_LCL_REGISTER_SPACING)) +#define A_BCM1480_PMO_LCL_REGISTER(idx, reg) (A_BCM1480_PMO_LCL_BASE(idx) + (reg)) + +#define BCM1480_PM_INT_PACKING 8 +#define BCM1480_PM_INT_FUNCTION_SPACING 0x40 +#define BCM1480_PM_INT_NUM_FUNCTIONS 3 + +/* + * DMA channel registers relative to A_BCM1480_PMI_LCL_BASE(n) and A_BCM1480_PMO_LCL_BASE(n) + */ + +#define R_BCM1480_PM_BASE_SIZE 0x0000000000 +#define R_BCM1480_PM_CNT 0x0000000008 +#define R_BCM1480_PM_PFCNT 0x0000000010 +#define R_BCM1480_PM_LAST 0x0000000018 +#define R_BCM1480_PM_PFINDX 0x0000000020 +#define R_BCM1480_PM_INT_WMK 0x0000000028 +#define R_BCM1480_PM_CONFIG0 0x0000000030 +#define R_BCM1480_PM_LOCALDEBUG 0x0000000078 +#define R_BCM1480_PM_CACHEABILITY 0x0000000080 /* PMI only */ +#define R_BCM1480_PM_INT_CNFG 0x0000000088 +#define R_BCM1480_PM_DESC_MERGE_TIMER 0x0000000090 +#define R_BCM1480_PM_LOCALDEBUG_PIB 0x00000000F8 /* PMI only */ +#define R_BCM1480_PM_LOCALDEBUG_POB 0x00000000F8 /* PMO only */ + +/* + * Global Registers (Not Channelized) + */ + +#define A_BCM1480_PMI_GLB_0 0x0010056000 +#define A_BCM1480_PMO_GLB_0 0x0010057000 + +/* + * PM to TX Mapping Register relative to A_BCM1480_PMI_GLB_0 and A_BCM1480_PMO_GLB_0 + */ + +#define R_BCM1480_PM_PMO_MAPPING 0x00000008C8 /* PMO only */ + +#define A_BCM1480_PM_PMO_MAPPING (A_BCM1480_PMO_GLB_0 + R_BCM1480_PM_PMO_MAPPING) + +/* + * Interrupt mapping registers + */ + + +#define A_BCM1480_PMI_INT_0 0x0010056800 +#define A_BCM1480_PMI_INT(q) (A_BCM1480_PMI_INT_0 + ((q>>8)<<8)) +#define A_BCM1480_PMI_INT_OFFSET_0 (A_BCM1480_PMI_INT_0 - A_BCM1480_PM_BASE) +#define A_BCM1480_PMO_INT_0 0x0010057800 +#define A_BCM1480_PMO_INT(q) (A_BCM1480_PMO_INT_0 + ((q>>8)<<8)) +#define A_BCM1480_PMO_INT_OFFSET_0 (A_BCM1480_PMO_INT_0 - A_BCM1480_PM_BASE) + +/* + * Interrupt registers relative to A_BCM1480_PMI_INT_0 and A_BCM1480_PMO_INT_0 + */ + +#define R_BCM1480_PM_INT_ST 0x0000000000 +#define R_BCM1480_PM_INT_MSK 0x0000000040 +#define R_BCM1480_PM_INT_CLR 0x0000000080 +#define R_BCM1480_PM_MRGD_INT 0x00000000C0 + +/* + * Debug registers (global) + */ + +#define A_BCM1480_PM_GLOBALDEBUGMODE_PMI 0x0010056000 +#define A_BCM1480_PM_GLOBALDEBUG_PID 0x00100567F8 +#define A_BCM1480_PM_GLOBALDEBUG_PIB 0x0010056FF8 +#define A_BCM1480_PM_GLOBALDEBUGMODE_PMO 0x0010057000 +#define A_BCM1480_PM_GLOBALDEBUG_POD 0x00100577F8 +#define A_BCM1480_PM_GLOBALDEBUG_POB 0x0010057FF8 + +/* ********************************************************************* + * Switch performance counters + ********************************************************************* */ + +#define A_BCM1480_SWPERF_CFG 0xdfb91800 +#define A_BCM1480_SWPERF_CNT0 0xdfb91880 +#define A_BCM1480_SWPERF_CNT1 0xdfb91888 +#define A_BCM1480_SWPERF_CNT2 0xdfb91890 +#define A_BCM1480_SWPERF_CNT3 0xdfb91898 + + +/* ********************************************************************* + * Switch Trace Unit + ********************************************************************* */ + +#define A_BCM1480_SWTRC_MATCH_CONTROL_0 0xDFB91000 +#define A_BCM1480_SWTRC_MATCH_DATA_VALUE_0 0xDFB91100 +#define A_BCM1480_SWTRC_MATCH_DATA_MASK_0 0xDFB91108 +#define A_BCM1480_SWTRC_MATCH_TAG_VALUE_0 0xDFB91200 +#define A_BCM1480_SWTRC_MATCH_TAG_MAKS_0 0xDFB91208 +#define A_BCM1480_SWTRC_EVENT_0 0xDFB91300 +#define A_BCM1480_SWTRC_SEQUENCE_0 0xDFB91400 + +#define A_BCM1480_SWTRC_CFG 0xDFB91500 +#define A_BCM1480_SWTRC_READ 0xDFB91508 + +#define A_BCM1480_SWDEBUG_SCHEDSTOP 0xDFB92000 + +#define A_BCM1480_SWTRC_MATCH_CONTROL(x) (A_BCM1480_SWTRC_MATCH_CONTROL_0 + ((x)*8)) +#define A_BCM1480_SWTRC_EVENT(x) (A_BCM1480_SWTRC_EVENT_0 + ((x)*8)) +#define A_BCM1480_SWTRC_SEQUENCE(x) (A_BCM1480_SWTRC_SEQUENCE_0 + ((x)*8)) + +#define A_BCM1480_SWTRC_MATCH_DATA_VALUE(x) (A_BCM1480_SWTRC_MATCH_DATA_VALUE_0 + ((x)*16)) +#define A_BCM1480_SWTRC_MATCH_DATA_MASK(x) (A_BCM1480_SWTRC_MATCH_DATA_MASK_0 + ((x)*16)) +#define A_BCM1480_SWTRC_MATCH_TAG_VALUE(x) (A_BCM1480_SWTRC_MATCH_TAG_VALUE_0 + ((x)*16)) +#define A_BCM1480_SWTRC_MATCH_TAG_MASK(x) (A_BCM1480_SWTRC_MATCH_TAG_MASK_0 + ((x)*16)) + + + +/* ********************************************************************* + * High-Speed Port Registers (Section 13) + ********************************************************************* */ + +#define A_BCM1480_HSP_BASE_0 0x00DF810000 +#define A_BCM1480_HSP_BASE_1 0x00DF890000 +#define A_BCM1480_HSP_BASE_2 0x00DF910000 +#define BCM1480_HSP_REGISTER_SPACING 0x80000 + +#define A_BCM1480_HSP_BASE(idx) (A_BCM1480_HSP_BASE_0 + ((idx)*BCM1480_HSP_REGISTER_SPACING)) +#define A_BCM1480_HSP_REGISTER(idx, reg) (A_BCM1480_HSP_BASE(idx) + (reg)) + +#define R_BCM1480_HSP_RX_SPI4_CFG_0 0x0000000000 +#define R_BCM1480_HSP_RX_SPI4_CFG_1 0x0000000008 +#define R_BCM1480_HSP_RX_SPI4_DESKEW_OVERRIDE 0x0000000010 +#define R_BCM1480_HSP_RX_SPI4_DESKEW_DATAPATH 0x0000000018 +#define R_BCM1480_HSP_RX_SPI4_PORT_INT_EN 0x0000000020 +#define R_BCM1480_HSP_RX_SPI4_PORT_INT_STATUS 0x0000000028 + +#define R_BCM1480_HSP_RX_SPI4_CALENDAR_0 0x0000000200 +#define R_BCM1480_HSP_RX_SPI4_CALENDAR_1 0x0000000208 + +#define R_BCM1480_HSP_RX_PLL_CNFG 0x0000000800 +#define R_BCM1480_HSP_RX_CALIBRATION 0x0000000808 +#define R_BCM1480_HSP_RX_TEST 0x0000000810 +#define R_BCM1480_HSP_RX_DIAG_DETAILS 0x0000000818 +#define R_BCM1480_HSP_RX_DIAG_CRC_0 0x0000000820 +#define R_BCM1480_HSP_RX_DIAG_CRC_1 0x0000000828 +#define R_BCM1480_HSP_RX_DIAG_HTCMD 0x0000000830 +#define R_BCM1480_HSP_RX_DIAG_PKTCTL 0x0000000838 + +#define R_BCM1480_HSP_RX_VIS_FLCTRL_COUNTER 0x0000000870 + +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_0 0x0000020020 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_1 0x0000020028 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_2 0x0000020030 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_3 0x0000020038 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_4 0x0000020040 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_5 0x0000020048 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_6 0x0000020050 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC_7 0x0000020058 +#define R_BCM1480_HSP_RX_PKT_RAMALLOC(idx) (R_BCM1480_HSP_RX_PKT_RAMALLOC_0 + 8*(idx)) + +/* XXX Following registers were shuffled. Renamed/renumbered per errata. */ +#define R_BCM1480_HSP_RX_HT_RAMALLOC_0 0x0000020078 +#define R_BCM1480_HSP_RX_HT_RAMALLOC_1 0x0000020080 +#define R_BCM1480_HSP_RX_HT_RAMALLOC_2 0x0000020088 +#define R_BCM1480_HSP_RX_HT_RAMALLOC_3 0x0000020090 +#define R_BCM1480_HSP_RX_HT_RAMALLOC_4 0x0000020098 +#define R_BCM1480_HSP_RX_HT_RAMALLOC_5 0x00000200A0 + +#define R_BCM1480_HSP_RX_SPI_WATERMARK_0 0x00000200B0 +#define R_BCM1480_HSP_RX_SPI_WATERMARK_1 0x00000200B8 +#define R_BCM1480_HSP_RX_SPI_WATERMARK_2 0x00000200C0 +#define R_BCM1480_HSP_RX_SPI_WATERMARK_3 0x00000200C8 +#define R_BCM1480_HSP_RX_SPI_WATERMARK_4 0x00000200D0 +#define R_BCM1480_HSP_RX_SPI_WATERMARK_5 0x00000200D8 +#define R_BCM1480_HSP_RX_SPI_WATERMARK_6 0x00000200E0 +#define R_BCM1480_HSP_RX_SPI_WATERMARK_7 0x00000200E8 +#define R_BCM1480_HSP_RX_SPI_WATERMARK(idx) (R_BCM1480_HSP_RX_SPI_WATERMARK_0 + 8*(idx)) + +#define R_BCM1480_HSP_RX_VIS_CMDQ_0 0x00000200F0 +#define R_BCM1480_HSP_RX_VIS_CMDQ_1 0x00000200F8 +#define R_BCM1480_HSP_RX_VIS_CMDQ_2 0x0000020100 +#define R_BCM1480_HSP_RX_RAM_READCTL 0x0000020108 +#define R_BCM1480_HSP_RX_RAM_READWINDOW 0x0000020110 +#define R_BCM1480_HSP_RX_RF_READCTL 0x0000020118 +#define R_BCM1480_HSP_RX_RF_READWINDOW 0x0000020120 + +#define R_BCM1480_HSP_TX_SPI4_CFG_0 0x0000040000 +#define R_BCM1480_HSP_TX_SPI4_CFG_1 0x0000040008 +#define R_BCM1480_HSP_TX_SPI4_TRAINING_FMT 0x0000040010 + +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_0 0x0000040020 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_1 0x0000040028 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_2 0x0000040030 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_3 0x0000040038 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_4 0x0000040040 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_5 0x0000040048 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_6 0x0000040050 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC_7 0x0000040058 +#define R_BCM1480_HSP_TX_PKT_RAMALLOC(idx) (R_BCM1480_HSP_TX_PKT_RAMALLOC_0 + 8*(idx)) +#define R_BCM1480_HSP_TX_NPC_RAMALLOC 0x0000040078 +#define R_BCM1480_HSP_TX_RSP_RAMALLOC 0x0000040080 +#define R_BCM1480_HSP_TX_PC_RAMALLOC 0x0000040088 +#define R_BCM1480_HSP_TX_HTCC_RAMALLOC_0 0x0000040090 +#define R_BCM1480_HSP_TX_HTCC_RAMALLOC_1 0x0000040098 +#define R_BCM1480_HSP_TX_HTCC_RAMALLOC_2 0x00000400A0 + +#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_0 0x00000400B0 +#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_1 0x00000400B8 +#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_2 0x00000400C0 +#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_3 0x00000400C8 +#define R_BCM1480_HSP_TX_PKT_RXPHITCNT(idx) (R_BCM1480_HSP_TX_PKT_RXPHITCNT_0 + 8*(idx)) +#define R_BCM1480_HSP_TX_HTIO_RXPHITCNT 0x00000400D0 +#define R_BCM1480_HSP_TX_HTCC_RXPHITCNT 0x00000400D8 + +#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_0 0x00000400E0 +#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_1 0x00000400E8 +#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_2 0x00000400F0 +#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_3 0x00000400F8 +#define R_BCM1480_HSP_TX_PKT_TXPHITCNT(idx) (R_BCM1480_HSP_TX_PKT_TXPHITCNT_0 + 8*(idx)) +#define R_BCM1480_HSP_TX_HTIO_TXPHITCNT 0x0000040100 +#define R_BCM1480_HSP_TX_HTCC_TXPHITCNT 0x0000040108 + +#define R_BCM1480_HSP_TX_SPI4_CALENDAR_0 0x0000040200 +#define R_BCM1480_HSP_TX_SPI4_CALENDAR_1 0x0000040208 + +#define R_BCM1480_HSP_TX_PLL_CNFG 0x0000040800 +#define R_BCM1480_HSP_TX_CALIBRATION 0x0000040808 +#define R_BCM1480_HSP_TX_TEST 0x0000040810 + +#define R_BCM1480_HSP_TX_VIS_CMDQ_0 0x0000040840 +#define R_BCM1480_HSP_TX_VIS_CMDQ_1 0x0000040848 +#define R_BCM1480_HSP_TX_VIS_CMDQ_2 0x0000040850 +#define R_BCM1480_HSP_TX_RAM_READCTL 0x0000040860 +#define R_BCM1480_HSP_TX_RAM_READWINDOW 0x0000040868 +#define R_BCM1480_HSP_TX_RF_READCTL 0x0000040870 +#define R_BCM1480_HSP_TX_RF_READWINDOW 0x0000040878 + +#define R_BCM1480_HSP_TX_SPI4_PORT_INT_STATUS 0x0000040880 +#define R_BCM1480_HSP_TX_SPI4_PORT_INT_EN 0x0000040888 + +#define R_BCM1480_HSP_TX_NEXT_ADDR_BASE 0x000040400 +#define R_BCM1480_HSP_TX_NEXT_ADDR_REGISTER(x) (R_BCM1480_HSP_TX_NEXT_ADDR_BASE+ 8*(x)) + + + +/* ********************************************************************* + * Physical Address Map (Table 10 and Figure 7) + ********************************************************************* */ + +#define A_BCM1480_PHYS_MEMORY_0 _SB_MAKE64(0x0000000000) +#define A_BCM1480_PHYS_MEMORY_SIZE _SB_MAKE64((256*1024*1024)) +#define A_BCM1480_PHYS_SYSTEM_CTL _SB_MAKE64(0x0010000000) +#define A_BCM1480_PHYS_IO_SYSTEM _SB_MAKE64(0x0010060000) +#define A_BCM1480_PHYS_GENBUS _SB_MAKE64(0x0010090000) +#define A_BCM1480_PHYS_GENBUS_END _SB_MAKE64(0x0028000000) +#define A_BCM1480_PHYS_PCI_MISC_MATCH_BYTES _SB_MAKE64(0x0028000000) +#define A_BCM1480_PHYS_PCI_IACK_MATCH_BYTES _SB_MAKE64(0x0029000000) +#define A_BCM1480_PHYS_PCI_IO_MATCH_BYTES _SB_MAKE64(0x002C000000) +#define A_BCM1480_PHYS_PCI_CFG_MATCH_BYTES _SB_MAKE64(0x002E000000) +#define A_BCM1480_PHYS_PCI_OMAP_MATCH_BYTES _SB_MAKE64(0x002F000000) +#define A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES _SB_MAKE64(0x0030000000) +#define A_BCM1480_PHYS_HT_MEM_MATCH_BYTES _SB_MAKE64(0x0040000000) +#define A_BCM1480_PHYS_HT_MEM_MATCH_BITS _SB_MAKE64(0x0060000000) +#define A_BCM1480_PHYS_MEMORY_1 _SB_MAKE64(0x0080000000) +#define A_BCM1480_PHYS_MEMORY_2 _SB_MAKE64(0x0090000000) +#define A_BCM1480_PHYS_PCI_MISC_MATCH_BITS _SB_MAKE64(0x00A8000000) +#define A_BCM1480_PHYS_PCI_IACK_MATCH_BITS _SB_MAKE64(0x00A9000000) +#define A_BCM1480_PHYS_PCI_IO_MATCH_BITS _SB_MAKE64(0x00AC000000) +#define A_BCM1480_PHYS_PCI_CFG_MATCH_BITS _SB_MAKE64(0x00AE000000) +#define A_BCM1480_PHYS_PCI_OMAP_MATCH_BITS _SB_MAKE64(0x00AF000000) +#define A_BCM1480_PHYS_PCI_MEM_MATCH_BITS _SB_MAKE64(0x00B0000000) +#define A_BCM1480_PHYS_MEMORY_3 _SB_MAKE64(0x00C0000000) +#define A_BCM1480_PHYS_L2_CACHE_TEST _SB_MAKE64(0x00D0000000) +#define A_BCM1480_PHYS_HT_SPECIAL_MATCH_BYTES _SB_MAKE64(0x00D8000000) +#define A_BCM1480_PHYS_HT_IO_MATCH_BYTES _SB_MAKE64(0x00DC000000) +#define A_BCM1480_PHYS_HT_CFG_MATCH_BYTES _SB_MAKE64(0x00DE000000) +#define A_BCM1480_PHYS_HS_SUBSYS _SB_MAKE64(0x00DF000000) +#define A_BCM1480_PHYS_HT_SPECIAL_MATCH_BITS _SB_MAKE64(0x00F8000000) +#define A_BCM1480_PHYS_HT_IO_MATCH_BITS _SB_MAKE64(0x00FC000000) +#define A_BCM1480_PHYS_HT_CFG_MATCH_BITS _SB_MAKE64(0x00FE000000) +#define A_BCM1480_PHYS_MEMORY_EXP _SB_MAKE64(0x0100000000) +#define A_BCM1480_PHYS_MEMORY_EXP_SIZE _SB_MAKE64((508*1024*1024*1024)) +#define A_BCM1480_PHYS_PCI_UPPER _SB_MAKE64(0x1000000000) +#define A_BCM1480_PHYS_HT_UPPER_MATCH_BYTES _SB_MAKE64(0x2000000000) +#define A_BCM1480_PHYS_HT_UPPER_MATCH_BITS _SB_MAKE64(0x3000000000) +#define A_BCM1480_PHYS_HT_NODE_ALIAS _SB_MAKE64(0x4000000000) +#define A_BCM1480_PHYS_HT_FULLACCESS _SB_MAKE64(0xF000000000) + + +/* ********************************************************************* + * L2 Cache as RAM (Table 54) + ********************************************************************* */ + +#define A_BCM1480_PHYS_L2CACHE_WAY_SIZE _SB_MAKE64(0x0000020000) +#define BCM1480_PHYS_L2CACHE_NUM_WAYS 8 +#define A_BCM1480_PHYS_L2CACHE_TOTAL_SIZE _SB_MAKE64(0x0000100000) +#define A_BCM1480_PHYS_L2CACHE_WAY0 _SB_MAKE64(0x00D0300000) +#define A_BCM1480_PHYS_L2CACHE_WAY1 _SB_MAKE64(0x00D0320000) +#define A_BCM1480_PHYS_L2CACHE_WAY2 _SB_MAKE64(0x00D0340000) +#define A_BCM1480_PHYS_L2CACHE_WAY3 _SB_MAKE64(0x00D0360000) +#define A_BCM1480_PHYS_L2CACHE_WAY4 _SB_MAKE64(0x00D0380000) +#define A_BCM1480_PHYS_L2CACHE_WAY5 _SB_MAKE64(0x00D03A0000) +#define A_BCM1480_PHYS_L2CACHE_WAY6 _SB_MAKE64(0x00D03C0000) +#define A_BCM1480_PHYS_L2CACHE_WAY7 _SB_MAKE64(0x00D03E0000) + +#endif /* _BCM1480_REGS_H */ diff --git a/arch/mips/include/asm/sibyte/bcm1480_scd.h b/arch/mips/include/asm/sibyte/bcm1480_scd.h new file mode 100644 index 00000000000..25ef24cbb92 --- /dev/null +++ b/arch/mips/include/asm/sibyte/bcm1480_scd.h @@ -0,0 +1,406 @@ +/* ********************************************************************* + * BCM1280/BCM1400 Board Support Package + * + * SCD Constants and Macros File: bcm1480_scd.h + * + * This module contains constants and macros useful for + * manipulating the System Control and Debug module. + * + * BCM1400 specification level: 1X55_1X80-UM100-R (12/18/03) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003,2004,2005 + * Broadcom Corporation. All rights reserved. + * + * 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 _BCM1480_SCD_H +#define _BCM1480_SCD_H + +#include "sb1250_defs.h" + +/* ********************************************************************* + * Pull in the BCM1250's SCD since lots of stuff is the same. + ********************************************************************* */ + +#include "sb1250_scd.h" + +/* ********************************************************************* + * Some general notes: + * + * This file is basically a "what's new" header file. Since the + * BCM1250 and the new BCM1480 (and derivatives) share many common + * features, this file contains only what's new or changed from + * the 1250. (above, you can see that we include the 1250 symbols + * to get the base functionality). + * + * In software, be sure to use the correct symbols, particularly + * for blocks that are different between the two chip families. + * All BCM1480-specific symbols have _BCM1480_ in their names, + * and all BCM1250-specific and "base" functions that are common in + * both chips have no special names (this is for compatibility with + * older include files). Therefore, if you're working with the + * SCD, which is very different on each chip, A_SCD_xxx implies + * the BCM1250 version and A_BCM1480_SCD_xxx implies the BCM1480 + * version. + ********************************************************************* */ + +/* ********************************************************************* + * System control/debug registers + ********************************************************************* */ + +/* + * System Identification and Revision Register (Table 12) + * Register: SCD_SYSTEM_REVISION + * This register is field compatible with the 1250. + */ + +/* + * New part definitions + */ + +#define K_SYS_PART_BCM1480 0x1406 +#define K_SYS_PART_BCM1280 0x1206 +#define K_SYS_PART_BCM1455 0x1407 +#define K_SYS_PART_BCM1255 0x1257 +#define K_SYS_PART_BCM1158 0x1156 + +/* + * Manufacturing Information Register (Table 14) + * Register: SCD_SYSTEM_MANUF + */ + +/* + * System Configuration Register (Table 15) + * Register: SCD_SYSTEM_CFG + * Entire register is different from 1250, all new constants below + */ + +#define M_BCM1480_SYS_RESERVED0 _SB_MAKEMASK1(0) +#define M_BCM1480_SYS_HT_MINRSTCNT _SB_MAKEMASK1(1) +#define M_BCM1480_SYS_RESERVED2 _SB_MAKEMASK1(2) +#define M_BCM1480_SYS_RESERVED3 _SB_MAKEMASK1(3) +#define M_BCM1480_SYS_RESERVED4 _SB_MAKEMASK1(4) +#define M_BCM1480_SYS_IOB_DIV _SB_MAKEMASK1(5) + +#define S_BCM1480_SYS_PLL_DIV _SB_MAKE64(6) +#define M_BCM1480_SYS_PLL_DIV _SB_MAKEMASK(5, S_BCM1480_SYS_PLL_DIV) +#define V_BCM1480_SYS_PLL_DIV(x) _SB_MAKEVALUE(x, S_BCM1480_SYS_PLL_DIV) +#define G_BCM1480_SYS_PLL_DIV(x) _SB_GETVALUE(x, S_BCM1480_SYS_PLL_DIV, M_BCM1480_SYS_PLL_DIV) + +#define S_BCM1480_SYS_SW_DIV _SB_MAKE64(11) +#define M_BCM1480_SYS_SW_DIV _SB_MAKEMASK(5, S_BCM1480_SYS_SW_DIV) +#define V_BCM1480_SYS_SW_DIV(x) _SB_MAKEVALUE(x, S_BCM1480_SYS_SW_DIV) +#define G_BCM1480_SYS_SW_DIV(x) _SB_GETVALUE(x, S_BCM1480_SYS_SW_DIV, M_BCM1480_SYS_SW_DIV) + +#define M_BCM1480_SYS_PCMCIA_ENABLE _SB_MAKEMASK1(16) +#define M_BCM1480_SYS_DUART1_ENABLE _SB_MAKEMASK1(17) + +#define S_BCM1480_SYS_BOOT_MODE _SB_MAKE64(18) +#define M_BCM1480_SYS_BOOT_MODE _SB_MAKEMASK(2, S_BCM1480_SYS_BOOT_MODE) +#define V_BCM1480_SYS_BOOT_MODE(x) _SB_MAKEVALUE(x, S_BCM1480_SYS_BOOT_MODE) +#define G_BCM1480_SYS_BOOT_MODE(x) _SB_GETVALUE(x, S_BCM1480_SYS_BOOT_MODE, M_BCM1480_SYS_BOOT_MODE) +#define K_BCM1480_SYS_BOOT_MODE_ROM32 0 +#define K_BCM1480_SYS_BOOT_MODE_ROM8 1 +#define K_BCM1480_SYS_BOOT_MODE_SMBUS_SMALL 2 +#define K_BCM1480_SYS_BOOT_MODE_SMBUS_BIG 3 +#define M_BCM1480_SYS_BOOT_MODE_SMBUS _SB_MAKEMASK1(19) + +#define M_BCM1480_SYS_PCI_HOST _SB_MAKEMASK1(20) +#define M_BCM1480_SYS_PCI_ARBITER _SB_MAKEMASK1(21) +#define M_BCM1480_SYS_BIG_ENDIAN _SB_MAKEMASK1(22) +#define M_BCM1480_SYS_GENCLK_EN _SB_MAKEMASK1(23) +#define M_BCM1480_SYS_GEN_PARITY_EN _SB_MAKEMASK1(24) +#define M_BCM1480_SYS_RESERVED25 _SB_MAKEMASK1(25) + +#define S_BCM1480_SYS_CONFIG 26 +#define M_BCM1480_SYS_CONFIG _SB_MAKEMASK(6, S_BCM1480_SYS_CONFIG) +#define V_BCM1480_SYS_CONFIG(x) _SB_MAKEVALUE(x, S_BCM1480_SYS_CONFIG) +#define G_BCM1480_SYS_CONFIG(x) _SB_GETVALUE(x, S_BCM1480_SYS_CONFIG, M_BCM1480_SYS_CONFIG) + +#define M_BCM1480_SYS_RESERVED32 _SB_MAKEMASK(32, 15) + +#define S_BCM1480_SYS_NODEID 47 +#define M_BCM1480_SYS_NODEID _SB_MAKEMASK(4, S_BCM1480_SYS_NODEID) +#define V_BCM1480_SYS_NODEID(x) _SB_MAKEVALUE(x, S_BCM1480_SYS_NODEID) +#define G_BCM1480_SYS_NODEID(x) _SB_GETVALUE(x, S_BCM1480_SYS_NODEID, M_BCM1480_SYS_NODEID) + +#define M_BCM1480_SYS_CCNUMA_EN _SB_MAKEMASK1(51) +#define M_BCM1480_SYS_CPU_RESET_0 _SB_MAKEMASK1(52) +#define M_BCM1480_SYS_CPU_RESET_1 _SB_MAKEMASK1(53) +#define M_BCM1480_SYS_CPU_RESET_2 _SB_MAKEMASK1(54) +#define M_BCM1480_SYS_CPU_RESET_3 _SB_MAKEMASK1(55) +#define S_BCM1480_SYS_DISABLECPU0 56 +#define M_BCM1480_SYS_DISABLECPU0 _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU0) +#define S_BCM1480_SYS_DISABLECPU1 57 +#define M_BCM1480_SYS_DISABLECPU1 _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU1) +#define S_BCM1480_SYS_DISABLECPU2 58 +#define M_BCM1480_SYS_DISABLECPU2 _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU2) +#define S_BCM1480_SYS_DISABLECPU3 59 +#define M_BCM1480_SYS_DISABLECPU3 _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU3) + +#define M_BCM1480_SYS_SB_SOFTRES _SB_MAKEMASK1(60) +#define M_BCM1480_SYS_EXT_RESET _SB_MAKEMASK1(61) +#define M_BCM1480_SYS_SYSTEM_RESET _SB_MAKEMASK1(62) +#define M_BCM1480_SYS_SW_FLAG _SB_MAKEMASK1(63) + +/* + * Scratch Register (Table 16) + * Register: SCD_SYSTEM_SCRATCH + * Same as BCM1250 + */ + + +/* + * Mailbox Registers (Table 17) + * Registers: SCD_MBOX_{0,1}_CPU_x + * Same as BCM1250 + */ + + +/* + * See bcm1480_int.h for interrupt mapper registers. + */ + + +/* + * Watchdog Timer Initial Count Registers (Table 23) + * Registers: SCD_WDOG_INIT_CNT_x + * + * The watchdogs are almost the same as the 1250, except + * the configuration register has more bits to control the + * other CPUs. + */ + + +/* + * Watchdog Timer Configuration Registers (Table 25) + * Registers: SCD_WDOG_CFG_x + */ + +#define M_BCM1480_SCD_WDOG_ENABLE _SB_MAKEMASK1(0) + +#define S_BCM1480_SCD_WDOG_RESET_TYPE 2 +#define M_BCM1480_SCD_WDOG_RESET_TYPE _SB_MAKEMASK(5, S_BCM1480_SCD_WDOG_RESET_TYPE) +#define V_BCM1480_SCD_WDOG_RESET_TYPE(x) _SB_MAKEVALUE(x, S_BCM1480_SCD_WDOG_RESET_TYPE) +#define G_BCM1480_SCD_WDOG_RESET_TYPE(x) _SB_GETVALUE(x, S_BCM1480_SCD_WDOG_RESET_TYPE, M_BCM1480_SCD_WDOG_RESET_TYPE) + +#define K_BCM1480_SCD_WDOG_RESET_FULL 0 /* actually, (x & 1) == 0 */ +#define K_BCM1480_SCD_WDOG_RESET_SOFT 1 +#define K_BCM1480_SCD_WDOG_RESET_CPU0 3 +#define K_BCM1480_SCD_WDOG_RESET_CPU1 5 +#define K_BCM1480_SCD_WDOG_RESET_CPU2 9 +#define K_BCM1480_SCD_WDOG_RESET_CPU3 17 +#define K_BCM1480_SCD_WDOG_RESET_ALL_CPUS 31 + + +#define M_BCM1480_SCD_WDOG_HAS_RESET _SB_MAKEMASK1(8) + +/* + * General Timer Initial Count Registers (Table 26) + * Registers: SCD_TIMER_INIT_x + * + * The timer registers are the same as the BCM1250 + */ + + +/* + * ZBbus Count Register (Table 29) + * Register: ZBBUS_CYCLE_COUNT + * + * Same as BCM1250 + */ + +/* + * ZBbus Compare Registers (Table 30) + * Registers: ZBBUS_CYCLE_CPx + * + * Same as BCM1250 + */ + + +/* + * System Performance Counter Configuration Register (Table 31) + * Register: PERF_CNT_CFG_0 + * + * SPC_CFG_SRC[0-3] is the same as the 1250. + * SPC_CFG_SRC[4-7] only exist on the 1480 + * The clear/enable bits are in different locations on the 1250 and 1480. + */ + +#define S_SPC_CFG_SRC4 32 +#define M_SPC_CFG_SRC4 _SB_MAKEMASK(8, S_SPC_CFG_SRC4) +#define V_SPC_CFG_SRC4(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC4) +#define G_SPC_CFG_SRC4(x) _SB_GETVALUE(x, S_SPC_CFG_SRC4, M_SPC_CFG_SRC4) + +#define S_SPC_CFG_SRC5 40 +#define M_SPC_CFG_SRC5 _SB_MAKEMASK(8, S_SPC_CFG_SRC5) +#define V_SPC_CFG_SRC5(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC5) +#define G_SPC_CFG_SRC5(x) _SB_GETVALUE(x, S_SPC_CFG_SRC5, M_SPC_CFG_SRC5) + +#define S_SPC_CFG_SRC6 48 +#define M_SPC_CFG_SRC6 _SB_MAKEMASK(8, S_SPC_CFG_SRC6) +#define V_SPC_CFG_SRC6(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC6) +#define G_SPC_CFG_SRC6(x) _SB_GETVALUE(x, S_SPC_CFG_SRC6, M_SPC_CFG_SRC6) + +#define S_SPC_CFG_SRC7 56 +#define M_SPC_CFG_SRC7 _SB_MAKEMASK(8, S_SPC_CFG_SRC7) +#define V_SPC_CFG_SRC7(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC7) +#define G_SPC_CFG_SRC7(x) _SB_GETVALUE(x, S_SPC_CFG_SRC7, M_SPC_CFG_SRC7) + +/* + * System Performance Counter Control Register (Table 32) + * Register: PERF_CNT_CFG_1 + * BCM1480 specific + */ +#define M_BCM1480_SPC_CFG_CLEAR _SB_MAKEMASK1(0) +#define M_BCM1480_SPC_CFG_ENABLE _SB_MAKEMASK1(1) +#if SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_SPC_CFG_CLEAR M_BCM1480_SPC_CFG_CLEAR +#define M_SPC_CFG_ENABLE M_BCM1480_SPC_CFG_ENABLE +#endif + +/* + * System Performance Counters (Table 33) + * Registers: PERF_CNT_x + */ + +#define S_BCM1480_SPC_CNT_COUNT 0 +#define M_BCM1480_SPC_CNT_COUNT _SB_MAKEMASK(40, S_BCM1480_SPC_CNT_COUNT) +#define V_BCM1480_SPC_CNT_COUNT(x) _SB_MAKEVALUE(x, S_BCM1480_SPC_CNT_COUNT) +#define G_BCM1480_SPC_CNT_COUNT(x) _SB_GETVALUE(x, S_BCM1480_SPC_CNT_COUNT, M_BCM1480_SPC_CNT_COUNT) + +#define M_BCM1480_SPC_CNT_OFLOW _SB_MAKEMASK1(40) + + +/* + * Bus Watcher Error Status Register (Tables 36, 37) + * Registers: BUS_ERR_STATUS, BUS_ERR_STATUS_DEBUG + * Same as BCM1250. + */ + +/* + * Bus Watcher Error Data Registers (Table 38) + * Registers: BUS_ERR_DATA_x + * Same as BCM1250. + */ + +/* + * Bus Watcher L2 ECC Counter Register (Table 39) + * Register: BUS_L2_ERRORS + * Same as BCM1250. + */ + + +/* + * Bus Watcher Memory and I/O Error Counter Register (Table 40) + * Register: BUS_MEM_IO_ERRORS + * Same as BCM1250. + */ + + +/* + * Address Trap Registers + * + * Register layout same as BCM1250, almost. The bus agents + * are different, and the address trap configuration bits are + * slightly different. + */ + +#define M_BCM1480_ATRAP_INDEX _SB_MAKEMASK(4, 0) +#define M_BCM1480_ATRAP_ADDRESS _SB_MAKEMASK(40, 0) + +#define S_BCM1480_ATRAP_CFG_CNT 0 +#define M_BCM1480_ATRAP_CFG_CNT _SB_MAKEMASK(3, S_BCM1480_ATRAP_CFG_CNT) +#define V_BCM1480_ATRAP_CFG_CNT(x) _SB_MAKEVALUE(x, S_BCM1480_ATRAP_CFG_CNT) +#define G_BCM1480_ATRAP_CFG_CNT(x) _SB_GETVALUE(x, S_BCM1480_ATRAP_CFG_CNT, M_BCM1480_ATRAP_CFG_CNT) + +#define M_BCM1480_ATRAP_CFG_WRITE _SB_MAKEMASK1(3) +#define M_BCM1480_ATRAP_CFG_ALL _SB_MAKEMASK1(4) +#define M_BCM1480_ATRAP_CFG_INV _SB_MAKEMASK1(5) +#define M_BCM1480_ATRAP_CFG_USESRC _SB_MAKEMASK1(6) +#define M_BCM1480_ATRAP_CFG_SRCINV _SB_MAKEMASK1(7) + +#define S_BCM1480_ATRAP_CFG_AGENTID 8 +#define M_BCM1480_ATRAP_CFG_AGENTID _SB_MAKEMASK(4, S_BCM1480_ATRAP_CFG_AGENTID) +#define V_BCM1480_ATRAP_CFG_AGENTID(x) _SB_MAKEVALUE(x, S_BCM1480_ATRAP_CFG_AGENTID) +#define G_BCM1480_ATRAP_CFG_AGENTID(x) _SB_GETVALUE(x, S_BCM1480_ATRAP_CFG_AGENTID, M_BCM1480_ATRAP_CFG_AGENTID) + + +#define K_BCM1480_BUS_AGENT_CPU0 0 +#define K_BCM1480_BUS_AGENT_CPU1 1 +#define K_BCM1480_BUS_AGENT_NC 2 +#define K_BCM1480_BUS_AGENT_IOB 3 +#define K_BCM1480_BUS_AGENT_SCD 4 +#define K_BCM1480_BUS_AGENT_L2C 6 +#define K_BCM1480_BUS_AGENT_MC 7 +#define K_BCM1480_BUS_AGENT_CPU2 8 +#define K_BCM1480_BUS_AGENT_CPU3 9 +#define K_BCM1480_BUS_AGENT_PM 10 + +#define S_BCM1480_ATRAP_CFG_CATTR 12 +#define M_BCM1480_ATRAP_CFG_CATTR _SB_MAKEMASK(2, S_BCM1480_ATRAP_CFG_CATTR) +#define V_BCM1480_ATRAP_CFG_CATTR(x) _SB_MAKEVALUE(x, S_BCM1480_ATRAP_CFG_CATTR) +#define G_BCM1480_ATRAP_CFG_CATTR(x) _SB_GETVALUE(x, S_BCM1480_ATRAP_CFG_CATTR, M_BCM1480_ATRAP_CFG_CATTR) + +#define K_BCM1480_ATRAP_CFG_CATTR_IGNORE 0 +#define K_BCM1480_ATRAP_CFG_CATTR_UNC 1 +#define K_BCM1480_ATRAP_CFG_CATTR_NONCOH 2 +#define K_BCM1480_ATRAP_CFG_CATTR_COHERENT 3 + +#define M_BCM1480_ATRAP_CFG_CATTRINV _SB_MAKEMASK1(14) + + +/* + * Trace Event Registers (Table 47) + * Same as BCM1250. + */ + +/* + * Trace Sequence Control Registers (Table 48) + * Registers: TRACE_SEQUENCE_x + * + * Same as BCM1250 except for two new fields. + */ + + +#define M_BCM1480_SCD_TRSEQ_TID_MATCH_EN _SB_MAKEMASK1(25) + +#define S_BCM1480_SCD_TRSEQ_SWFUNC 26 +#define M_BCM1480_SCD_TRSEQ_SWFUNC _SB_MAKEMASK(2, S_BCM1480_SCD_TRSEQ_SWFUNC) +#define V_BCM1480_SCD_TRSEQ_SWFUNC(x) _SB_MAKEVALUE(x, S_BCM1480_SCD_TRSEQ_SWFUNC) +#define G_BCM1480_SCD_TRSEQ_SWFUNC(x) _SB_GETVALUE(x, S_BCM1480_SCD_TRSEQ_SWFUNC, M_BCM1480_SCD_TRSEQ_SWFUNC) + +/* + * Trace Control Register (Table 49) + * Register: TRACE_CFG + * + * BCM1480 changes to this register (other than location of the CUR_ADDR field) + * are defined below. + */ + +#define S_BCM1480_SCD_TRACE_CFG_MODE 16 +#define M_BCM1480_SCD_TRACE_CFG_MODE _SB_MAKEMASK(2, S_BCM1480_SCD_TRACE_CFG_MODE) +#define V_BCM1480_SCD_TRACE_CFG_MODE(x) _SB_MAKEVALUE(x, S_BCM1480_SCD_TRACE_CFG_MODE) +#define G_BCM1480_SCD_TRACE_CFG_MODE(x) _SB_GETVALUE(x, S_BCM1480_SCD_TRACE_CFG_MODE, M_BCM1480_SCD_TRACE_CFG_MODE) + +#define K_BCM1480_SCD_TRACE_CFG_MODE_BLOCKERS 0 +#define K_BCM1480_SCD_TRACE_CFG_MODE_BYTEEN_INT 1 +#define K_BCM1480_SCD_TRACE_CFG_MODE_FLOW_ID 2 + +#endif /* _BCM1480_SCD_H */ diff --git a/arch/mips/include/asm/sibyte/bigsur.h b/arch/mips/include/asm/sibyte/bigsur.h new file mode 100644 index 00000000000..ebefe797fc1 --- /dev/null +++ b/arch/mips/include/asm/sibyte/bigsur.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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_SIBYTE_BIGSUR_H +#define __ASM_SIBYTE_BIGSUR_H + +#include +#include + +#ifdef CONFIG_SIBYTE_BIGSUR +#define SIBYTE_BOARD_NAME "BCM91x80A/B (BigSur)" +#define SIBYTE_HAVE_PCMCIA 1 +#define SIBYTE_HAVE_IDE 1 +#endif + +/* Generic bus chip selects */ +#define LEDS_CS 3 +#define LEDS_PHYS 0x100a0000 + +#ifdef SIBYTE_HAVE_IDE +#define IDE_CS 4 +#define IDE_PHYS 0x100b0000 +#define K_GPIO_GB_IDE 4 +#define K_INT_GB_IDE (K_INT_GPIO_0 + K_GPIO_GB_IDE) +#endif + +#ifdef SIBYTE_HAVE_PCMCIA +#define PCMCIA_CS 6 +#define PCMCIA_PHYS 0x11000000 +#define K_GPIO_PC_READY 9 +#define K_INT_PC_READY (K_INT_GPIO_0 + K_GPIO_PC_READY) +#endif + +#endif /* __ASM_SIBYTE_BIGSUR_H */ + diff --git a/arch/mips/include/asm/sibyte/board.h b/arch/mips/include/asm/sibyte/board.h new file mode 100644 index 00000000000..25372ae0e81 --- /dev/null +++ b/arch/mips/include/asm/sibyte/board.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 _SIBYTE_BOARD_H +#define _SIBYTE_BOARD_H + +#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_CRHONE) || \ + defined(CONFIG_SIBYTE_CRHINE) || defined(CONFIG_SIBYTE_LITTLESUR) +#include +#endif + +#if defined(CONFIG_SIBYTE_SENTOSA) || defined(CONFIG_SIBYTE_RHONE) +#include +#endif + +#ifdef CONFIG_SIBYTE_CARMEL +#include +#endif + +#ifdef CONFIG_SIBYTE_BIGSUR +#include +#endif + +#ifdef __ASSEMBLY__ + +#ifdef LEDS_PHYS +#define setleds(t0, t1, c0, c1, c2, c3) \ + li t0, (LEDS_PHYS|0xa0000000); \ + li t1, c0; \ + sb t1, 0x18(t0); \ + li t1, c1; \ + sb t1, 0x10(t0); \ + li t1, c2; \ + sb t1, 0x08(t0); \ + li t1, c3; \ + sb t1, 0x00(t0) +#else +#define setleds(t0, t1, c0, c1, c2, c3) +#endif /* LEDS_PHYS */ + +#else + +void swarm_setup(void); + +#ifdef LEDS_PHYS +extern void setleds(char *str); +#else +#define setleds(s) do { } while (0) +#endif /* LEDS_PHYS */ + +#endif /* __ASSEMBLY__ */ + +#endif /* _SIBYTE_BOARD_H */ diff --git a/arch/mips/include/asm/sibyte/carmel.h b/arch/mips/include/asm/sibyte/carmel.h new file mode 100644 index 00000000000..11cad71323e --- /dev/null +++ b/arch/mips/include/asm/sibyte/carmel.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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_SIBYTE_CARMEL_H +#define __ASM_SIBYTE_CARMEL_H + +#include +#include + +#define SIBYTE_BOARD_NAME "Carmel" + +#define GPIO_PHY_INTERRUPT 2 +#define GPIO_NONMASKABLE_INT 3 +#define GPIO_CF_INSERTED 6 +#define GPIO_MONTEREY_RESET 7 +#define GPIO_QUADUART_INT 8 +#define GPIO_CF_INT 9 +#define GPIO_FPGA_CCLK 10 +#define GPIO_FPGA_DOUT 11 +#define GPIO_FPGA_DIN 12 +#define GPIO_FPGA_PGM 13 +#define GPIO_FPGA_DONE 14 +#define GPIO_FPGA_INIT 15 + +#define LEDS_CS 2 +#define LEDS_PHYS 0x100C0000 +#define MLEDS_CS 3 +#define MLEDS_PHYS 0x100A0000 +#define UART_CS 4 +#define UART_PHYS 0x100D0000 +#define ARAVALI_CS 5 +#define ARAVALI_PHYS 0x11000000 +#define IDE_CS 6 +#define IDE_PHYS 0x100B0000 +#define ARAVALI2_CS 7 +#define ARAVALI2_PHYS 0x100E0000 + +#if defined(CONFIG_SIBYTE_CARMEL) +#define K_GPIO_GB_IDE 9 +#define K_INT_GB_IDE (K_INT_GPIO_0 + K_GPIO_GB_IDE) +#endif + + +#endif /* __ASM_SIBYTE_CARMEL_H */ diff --git a/arch/mips/include/asm/sibyte/sb1250.h b/arch/mips/include/asm/sibyte/sb1250.h new file mode 100644 index 00000000000..80c1a052662 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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_SIBYTE_SB1250_H +#define _ASM_SIBYTE_SB1250_H + +/* + * yymmddpp: year, month, day, patch. + * should sync with Makefile EXTRAVERSION + */ +#define SIBYTE_RELEASE 0x02111403 + +#define SB1250_NR_IRQS 64 + +#define BCM1480_NR_IRQS 128 +#define BCM1480_NR_IRQS_HALF 64 + +#define SB1250_DUART_MINOR_BASE 64 + +#ifndef __ASSEMBLY__ + +#include + +/* For revision/pass information */ +#include +#include +extern unsigned int sb1_pass; +extern unsigned int soc_pass; +extern unsigned int soc_type; +extern unsigned int periph_rev; +extern unsigned int zbbus_mhz; + +extern void sb1250_time_init(void); +extern void sb1250_mask_irq(int cpu, int irq); +extern void sb1250_unmask_irq(int cpu, int irq); + +extern void bcm1480_time_init(void); +extern void bcm1480_mask_irq(int cpu, int irq); +extern void bcm1480_unmask_irq(int cpu, int irq); + +#define AT_spin \ + __asm__ __volatile__ ( \ + ".set noat\n" \ + "li $at, 0\n" \ + "1: beqz $at, 1b\n" \ + ".set at\n" \ + ) + +#endif + +#define IOADDR(a) ((void __iomem *)(IO_BASE + (a))) + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_defs.h b/arch/mips/include/asm/sibyte/sb1250_defs.h new file mode 100644 index 00000000000..09365f9111f --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_defs.h @@ -0,0 +1,259 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Global constants and macros File: sb1250_defs.h + * + * This file contains macros and definitions used by the other + * include files. + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_DEFS_H +#define _SB1250_DEFS_H + +/* + * These headers require ANSI C89 string concatenation, and GCC or other + * 'long long' (64-bit integer) support. + */ +#if !defined(__STDC__) && !defined(_MSC_VER) +#error SiByte headers require ANSI C89 support +#endif + + +/* ********************************************************************* + * Macros for feature tests, used to enable include file features + * for chip features only present in certain chip revisions. + * + * SIBYTE_HDR_FEATURES may be defined to be the mask value chip/revision + * which is to be exposed by the headers. If undefined, it defaults to + * "all features." + * + * Use like: + * + * #define SIBYTE_HDR_FEATURES SIBYTE_HDR_FMASK_112x_PASS1 + * + * Generate defines only for that revision of chip. + * + * #if SIBYTE_HDR_FEATURE(chip,pass) + * + * True if header features for that revision or later of + * that particular chip type are enabled in SIBYTE_HDR_FEATURES. + * (Use this to bracket #defines for features present in a given + * revision and later.) + * + * Note that there is no implied ordering between chip types. + * + * Note also that 'chip' and 'pass' must textually exactly + * match the defines below. So, for example, + * SIBYTE_HDR_FEATURE(112x, PASS1) is OK, but + * SIBYTE_HDR_FEATURE(1120, pass1) is not (for two reasons). + * + * #if SIBYTE_HDR_FEATURE_UP_TO(chip,pass) + * + * Same as SIBYTE_HDR_FEATURE, but true for the named revision + * and earlier revisions of the named chip type. + * + * #if SIBYTE_HDR_FEATURE_EXACT(chip,pass) + * + * Same as SIBYTE_HDR_FEATURE, but only true for the named + * revision of the named chip type. (Note that this CANNOT + * be used to verify that you're compiling only for that + * particular chip/revision. It will be true any time this + * chip/revision is included in SIBYTE_HDR_FEATURES.) + * + * #if SIBYTE_HDR_FEATURE_CHIP(chip) + * + * True if header features for (any revision of) that chip type + * are enabled in SIBYTE_HDR_FEATURES. (Use this to bracket + * #defines for features specific to a given chip type.) + * + * Mask values currently include room for additional revisions of each + * chip type, but can be renumbered at will. Note that they MUST fit + * into 31 bits and may not include C type constructs, for safe use in + * CPP conditionals. Bit positions within chip types DO indicate + * ordering, so be careful when adding support for new minor revs. + ********************************************************************* */ + +#define SIBYTE_HDR_FMASK_1250_ALL 0x000000ff +#define SIBYTE_HDR_FMASK_1250_PASS1 0x00000001 +#define SIBYTE_HDR_FMASK_1250_PASS2 0x00000002 +#define SIBYTE_HDR_FMASK_1250_PASS3 0x00000004 + +#define SIBYTE_HDR_FMASK_112x_ALL 0x00000f00 +#define SIBYTE_HDR_FMASK_112x_PASS1 0x00000100 + +#define SIBYTE_HDR_FMASK_1480_ALL 0x0000f000 +#define SIBYTE_HDR_FMASK_1480_PASS1 0x00001000 +#define SIBYTE_HDR_FMASK_1480_PASS2 0x00002000 + +/* Bit mask for chip/revision. (use _ALL for all revisions of a chip). */ +#define SIBYTE_HDR_FMASK(chip, pass) \ + (SIBYTE_HDR_FMASK_ ## chip ## _ ## pass) +#define SIBYTE_HDR_FMASK_ALLREVS(chip) \ + (SIBYTE_HDR_FMASK_ ## chip ## _ALL) + +/* Default constant value for all chips, all revisions */ +#define SIBYTE_HDR_FMASK_ALL \ + (SIBYTE_HDR_FMASK_1250_ALL | SIBYTE_HDR_FMASK_112x_ALL \ + | SIBYTE_HDR_FMASK_1480_ALL) + +/* This one is used for the "original" BCM1250/BCM112x chips. We use this + to weed out constants and macros that do not exist on later chips like + the BCM1480 */ +#define SIBYTE_HDR_FMASK_1250_112x_ALL \ + (SIBYTE_HDR_FMASK_1250_ALL | SIBYTE_HDR_FMASK_112x_ALL) +#define SIBYTE_HDR_FMASK_1250_112x SIBYTE_HDR_FMASK_1250_112x_ALL + +#ifndef SIBYTE_HDR_FEATURES +#define SIBYTE_HDR_FEATURES SIBYTE_HDR_FMASK_ALL +#endif + + +/* Bit mask for revisions of chip exclusively before the named revision. */ +#define SIBYTE_HDR_FMASK_BEFORE(chip, pass) \ + ((SIBYTE_HDR_FMASK(chip, pass) - 1) & SIBYTE_HDR_FMASK_ALLREVS(chip)) + +/* Bit mask for revisions of chip exclusively after the named revision. */ +#define SIBYTE_HDR_FMASK_AFTER(chip, pass) \ + (~(SIBYTE_HDR_FMASK(chip, pass) \ + | (SIBYTE_HDR_FMASK(chip, pass) - 1)) & SIBYTE_HDR_FMASK_ALLREVS(chip)) + + +/* True if header features enabled for (any revision of) that chip type. */ +#define SIBYTE_HDR_FEATURE_CHIP(chip) \ + (!! (SIBYTE_HDR_FMASK_ALLREVS(chip) & SIBYTE_HDR_FEATURES)) + +/* True for all versions of the BCM1250 and BCM1125, but not true for + anything else */ +#define SIBYTE_HDR_FEATURE_1250_112x \ + (SIBYTE_HDR_FEATURE_CHIP(1250) || SIBYTE_HDR_FEATURE_CHIP(112x)) +/* (!! (SIBYTE_HDR_FEATURES & SIBYHTE_HDR_FMASK_1250_112x)) */ + +/* True if header features enabled for that rev or later, inclusive. */ +#define SIBYTE_HDR_FEATURE(chip, pass) \ + (!! ((SIBYTE_HDR_FMASK(chip, pass) \ + | SIBYTE_HDR_FMASK_AFTER(chip, pass)) & SIBYTE_HDR_FEATURES)) + +/* True if header features enabled for exactly that rev. */ +#define SIBYTE_HDR_FEATURE_EXACT(chip, pass) \ + (!! (SIBYTE_HDR_FMASK(chip, pass) & SIBYTE_HDR_FEATURES)) + +/* True if header features enabled for that rev or before, inclusive. */ +#define SIBYTE_HDR_FEATURE_UP_TO(chip, pass) \ + (!! ((SIBYTE_HDR_FMASK(chip, pass) \ + | SIBYTE_HDR_FMASK_BEFORE(chip, pass)) & SIBYTE_HDR_FEATURES)) + + +/* ********************************************************************* + * Naming schemes for constants in these files: + * + * M_xxx MASK constant (identifies bits in a register). + * For multi-bit fields, all bits in the field will + * be set. + * + * K_xxx "Code" constant (value for data in a multi-bit + * field). The value is right justified. + * + * V_xxx "Value" constant. This is the same as the + * corresponding "K_xxx" constant, except it is + * shifted to the correct position in the register. + * + * S_xxx SHIFT constant. This is the number of bits that + * a field value (code) needs to be shifted + * (towards the left) to put the value in the right + * position for the register. + * + * A_xxx ADDRESS constant. This will be a physical + * address. Use the PHYS_TO_K1 macro to generate + * a K1SEG address. + * + * R_xxx RELATIVE offset constant. This is an offset from + * an A_xxx constant (usually the first register in + * a group). + * + * G_xxx(X) GET value. This macro obtains a multi-bit field + * from a register, masks it, and shifts it to + * the bottom of the register (retrieving a K_xxx + * value, for example). + * + * V_xxx(X) VALUE. This macro computes the value of a + * K_xxx constant shifted to the correct position + * in the register. + ********************************************************************* */ + + + + +/* + * Cast to 64-bit number. Presumably the syntax is different in + * assembly language. + * + * Note: you'll need to define uint32_t and uint64_t in your headers. + */ + +#if !defined(__ASSEMBLY__) +#define _SB_MAKE64(x) ((uint64_t)(x)) +#define _SB_MAKE32(x) ((uint32_t)(x)) +#else +#define _SB_MAKE64(x) (x) +#define _SB_MAKE32(x) (x) +#endif + + +/* + * Make a mask for 1 bit at position 'n' + */ + +#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n)) +#define _SB_MAKEMASK1_32(n) (_SB_MAKE32(1) << _SB_MAKE32(n)) + +/* + * Make a mask for 'v' bits at position 'n' + */ + +#define _SB_MAKEMASK(v, n) (_SB_MAKE64((_SB_MAKE64(1)<<(v))-1) << _SB_MAKE64(n)) +#define _SB_MAKEMASK_32(v, n) (_SB_MAKE32((_SB_MAKE32(1)<<(v))-1) << _SB_MAKE32(n)) + +/* + * Make a value at 'v' at bit position 'n' + */ + +#define _SB_MAKEVALUE(v, n) (_SB_MAKE64(v) << _SB_MAKE64(n)) +#define _SB_MAKEVALUE_32(v, n) (_SB_MAKE32(v) << _SB_MAKE32(n)) + +#define _SB_GETVALUE(v, n, m) ((_SB_MAKE64(v) & _SB_MAKE64(m)) >> _SB_MAKE64(n)) +#define _SB_GETVALUE_32(v, n, m) ((_SB_MAKE32(v) & _SB_MAKE32(m)) >> _SB_MAKE32(n)) + +/* + * Macros to read/write on-chip registers + * XXX should we do the PHYS_TO_K1 here? + */ + + +#if defined(__mips64) && !defined(__ASSEMBLY__) +#define SBWRITECSR(csr, val) *((volatile uint64_t *) PHYS_TO_K1(csr)) = (val) +#define SBREADCSR(csr) (*((volatile uint64_t *) PHYS_TO_K1(csr))) +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_dma.h b/arch/mips/include/asm/sibyte/sb1250_dma.h new file mode 100644 index 00000000000..bad56171d74 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_dma.h @@ -0,0 +1,594 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * DMA definitions File: sb1250_dma.h + * + * This module contains constants and macros useful for + * programming the SB1250's DMA controllers, both the data mover + * and the Ethernet DMA. + * + * SB1250 specification level: User's manual 10/21/02 + * BCM1280 specification level: User's manual 11/24/03 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_DMA_H +#define _SB1250_DMA_H + + +#include "sb1250_defs.h" + +/* ********************************************************************* + * DMA Registers + ********************************************************************* */ + +/* + * Ethernet and Serial DMA Configuration Register 0 (Table 7-4) + * Registers: DMA_CONFIG0_MAC_x_RX_CH_0 + * Registers: DMA_CONFIG0_MAC_x_TX_CH_0 + * Registers: DMA_CONFIG0_SER_x_RX + * Registers: DMA_CONFIG0_SER_x_TX + */ + + +#define M_DMA_DROP _SB_MAKEMASK1(0) + +#define M_DMA_CHAIN_SEL _SB_MAKEMASK1(1) +#define M_DMA_RESERVED1 _SB_MAKEMASK1(2) + +#define S_DMA_DESC_TYPE _SB_MAKE64(1) +#define M_DMA_DESC_TYPE _SB_MAKEMASK(2, S_DMA_DESC_TYPE) +#define V_DMA_DESC_TYPE(x) _SB_MAKEVALUE(x, S_DMA_DESC_TYPE) +#define G_DMA_DESC_TYPE(x) _SB_GETVALUE(x, S_DMA_DESC_TYPE, M_DMA_DESC_TYPE) + +#define K_DMA_DESC_TYPE_RING_AL 0 +#define K_DMA_DESC_TYPE_CHAIN_AL 1 + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define K_DMA_DESC_TYPE_RING_UAL_WI 2 +#define K_DMA_DESC_TYPE_RING_UAL_RMW 3 +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define M_DMA_EOP_INT_EN _SB_MAKEMASK1(3) +#define M_DMA_HWM_INT_EN _SB_MAKEMASK1(4) +#define M_DMA_LWM_INT_EN _SB_MAKEMASK1(5) +#define M_DMA_TBX_EN _SB_MAKEMASK1(6) +#define M_DMA_TDX_EN _SB_MAKEMASK1(7) + +#define S_DMA_INT_PKTCNT _SB_MAKE64(8) +#define M_DMA_INT_PKTCNT _SB_MAKEMASK(8, S_DMA_INT_PKTCNT) +#define V_DMA_INT_PKTCNT(x) _SB_MAKEVALUE(x, S_DMA_INT_PKTCNT) +#define G_DMA_INT_PKTCNT(x) _SB_GETVALUE(x, S_DMA_INT_PKTCNT, M_DMA_INT_PKTCNT) + +#define S_DMA_RINGSZ _SB_MAKE64(16) +#define M_DMA_RINGSZ _SB_MAKEMASK(16, S_DMA_RINGSZ) +#define V_DMA_RINGSZ(x) _SB_MAKEVALUE(x, S_DMA_RINGSZ) +#define G_DMA_RINGSZ(x) _SB_GETVALUE(x, S_DMA_RINGSZ, M_DMA_RINGSZ) + +#define S_DMA_HIGH_WATERMARK _SB_MAKE64(32) +#define M_DMA_HIGH_WATERMARK _SB_MAKEMASK(16, S_DMA_HIGH_WATERMARK) +#define V_DMA_HIGH_WATERMARK(x) _SB_MAKEVALUE(x, S_DMA_HIGH_WATERMARK) +#define G_DMA_HIGH_WATERMARK(x) _SB_GETVALUE(x, S_DMA_HIGH_WATERMARK, M_DMA_HIGH_WATERMARK) + +#define S_DMA_LOW_WATERMARK _SB_MAKE64(48) +#define M_DMA_LOW_WATERMARK _SB_MAKEMASK(16, S_DMA_LOW_WATERMARK) +#define V_DMA_LOW_WATERMARK(x) _SB_MAKEVALUE(x, S_DMA_LOW_WATERMARK) +#define G_DMA_LOW_WATERMARK(x) _SB_GETVALUE(x, S_DMA_LOW_WATERMARK, M_DMA_LOW_WATERMARK) + +/* + * Ethernet and Serial DMA Configuration Register 1 (Table 7-5) + * Registers: DMA_CONFIG1_MAC_x_RX_CH_0 + * Registers: DMA_CONFIG1_DMA_x_TX_CH_0 + * Registers: DMA_CONFIG1_SER_x_RX + * Registers: DMA_CONFIG1_SER_x_TX + */ + +#define M_DMA_HDR_CF_EN _SB_MAKEMASK1(0) +#define M_DMA_ASIC_XFR_EN _SB_MAKEMASK1(1) +#define M_DMA_PRE_ADDR_EN _SB_MAKEMASK1(2) +#define M_DMA_FLOW_CTL_EN _SB_MAKEMASK1(3) +#define M_DMA_NO_DSCR_UPDT _SB_MAKEMASK1(4) +#define M_DMA_L2CA _SB_MAKEMASK1(5) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_DMA_RX_XTRA_STATUS _SB_MAKEMASK1(6) +#define M_DMA_TX_CPU_PAUSE _SB_MAKEMASK1(6) +#define M_DMA_TX_FC_PAUSE_EN _SB_MAKEMASK1(7) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define M_DMA_MBZ1 _SB_MAKEMASK(6, 15) + +#define S_DMA_HDR_SIZE _SB_MAKE64(21) +#define M_DMA_HDR_SIZE _SB_MAKEMASK(9, S_DMA_HDR_SIZE) +#define V_DMA_HDR_SIZE(x) _SB_MAKEVALUE(x, S_DMA_HDR_SIZE) +#define G_DMA_HDR_SIZE(x) _SB_GETVALUE(x, S_DMA_HDR_SIZE, M_DMA_HDR_SIZE) + +#define M_DMA_MBZ2 _SB_MAKEMASK(5, 32) + +#define S_DMA_ASICXFR_SIZE _SB_MAKE64(37) +#define M_DMA_ASICXFR_SIZE _SB_MAKEMASK(9, S_DMA_ASICXFR_SIZE) +#define V_DMA_ASICXFR_SIZE(x) _SB_MAKEVALUE(x, S_DMA_ASICXFR_SIZE) +#define G_DMA_ASICXFR_SIZE(x) _SB_GETVALUE(x, S_DMA_ASICXFR_SIZE, M_DMA_ASICXFR_SIZE) + +#define S_DMA_INT_TIMEOUT _SB_MAKE64(48) +#define M_DMA_INT_TIMEOUT _SB_MAKEMASK(16, S_DMA_INT_TIMEOUT) +#define V_DMA_INT_TIMEOUT(x) _SB_MAKEVALUE(x, S_DMA_INT_TIMEOUT) +#define G_DMA_INT_TIMEOUT(x) _SB_GETVALUE(x, S_DMA_INT_TIMEOUT, M_DMA_INT_TIMEOUT) + +/* + * Ethernet and Serial DMA Descriptor base address (Table 7-6) + */ + +#define M_DMA_DSCRBASE_MBZ _SB_MAKEMASK(4, 0) + + +/* + * ASIC Mode Base Address (Table 7-7) + */ + +#define M_DMA_ASIC_BASE_MBZ _SB_MAKEMASK(20, 0) + +/* + * DMA Descriptor Count Registers (Table 7-8) + */ + +/* No bitfields */ + + +/* + * Current Descriptor Address Register (Table 7-11) + */ + +#define S_DMA_CURDSCR_ADDR _SB_MAKE64(0) +#define M_DMA_CURDSCR_ADDR _SB_MAKEMASK(40, S_DMA_CURDSCR_ADDR) +#define S_DMA_CURDSCR_COUNT _SB_MAKE64(40) +#define M_DMA_CURDSCR_COUNT _SB_MAKEMASK(16, S_DMA_CURDSCR_COUNT) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_DMA_TX_CH_PAUSE_ON _SB_MAKEMASK1(56) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +/* + * Receive Packet Drop Registers + */ +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_DMA_OODLOST_RX _SB_MAKE64(0) +#define M_DMA_OODLOST_RX _SB_MAKEMASK(16, S_DMA_OODLOST_RX) +#define G_DMA_OODLOST_RX(x) _SB_GETVALUE(x, S_DMA_OODLOST_RX, M_DMA_OODLOST_RX) + +#define S_DMA_EOP_COUNT_RX _SB_MAKE64(16) +#define M_DMA_EOP_COUNT_RX _SB_MAKEMASK(8, S_DMA_EOP_COUNT_RX) +#define G_DMA_EOP_COUNT_RX(x) _SB_GETVALUE(x, S_DMA_EOP_COUNT_RX, M_DMA_EOP_COUNT_RX) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +/* ********************************************************************* + * DMA Descriptors + ********************************************************************* */ + +/* + * Descriptor doubleword "A" (Table 7-12) + */ + +#define S_DMA_DSCRA_OFFSET _SB_MAKE64(0) +#define M_DMA_DSCRA_OFFSET _SB_MAKEMASK(5, S_DMA_DSCRA_OFFSET) +#define V_DMA_DSCRA_OFFSET(x) _SB_MAKEVALUE(x, S_DMA_DSCRA_OFFSET) +#define G_DMA_DSCRA_OFFSET(x) _SB_GETVALUE(x, S_DMA_DSCRA_OFFSET, M_DMA_DSCRA_OFFSET) + +/* Note: Don't shift the address over, just mask it with the mask below */ +#define S_DMA_DSCRA_A_ADDR _SB_MAKE64(5) +#define M_DMA_DSCRA_A_ADDR _SB_MAKEMASK(35, S_DMA_DSCRA_A_ADDR) + +#define M_DMA_DSCRA_A_ADDR_OFFSET (M_DMA_DSCRA_OFFSET | M_DMA_DSCRA_A_ADDR) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_DMA_DSCRA_A_ADDR_UA _SB_MAKE64(0) +#define M_DMA_DSCRA_A_ADDR_UA _SB_MAKEMASK(40, S_DMA_DSCRA_A_ADDR_UA) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define S_DMA_DSCRA_A_SIZE _SB_MAKE64(40) +#define M_DMA_DSCRA_A_SIZE _SB_MAKEMASK(9, S_DMA_DSCRA_A_SIZE) +#define V_DMA_DSCRA_A_SIZE(x) _SB_MAKEVALUE(x, S_DMA_DSCRA_A_SIZE) +#define G_DMA_DSCRA_A_SIZE(x) _SB_GETVALUE(x, S_DMA_DSCRA_A_SIZE, M_DMA_DSCRA_A_SIZE) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_DMA_DSCRA_DSCR_CNT _SB_MAKE64(40) +#define M_DMA_DSCRA_DSCR_CNT _SB_MAKEMASK(8, S_DMA_DSCRA_DSCR_CNT) +#define G_DMA_DSCRA_DSCR_CNT(x) _SB_GETVALUE(x, S_DMA_DSCRA_DSCR_CNT, M_DMA_DSCRA_DSCR_CNT) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define M_DMA_DSCRA_INTERRUPT _SB_MAKEMASK1(49) +#define M_DMA_DSCRA_OFFSETB _SB_MAKEMASK1(50) + +#define S_DMA_DSCRA_STATUS _SB_MAKE64(51) +#define M_DMA_DSCRA_STATUS _SB_MAKEMASK(13, S_DMA_DSCRA_STATUS) +#define V_DMA_DSCRA_STATUS(x) _SB_MAKEVALUE(x, S_DMA_DSCRA_STATUS) +#define G_DMA_DSCRA_STATUS(x) _SB_GETVALUE(x, S_DMA_DSCRA_STATUS, M_DMA_DSCRA_STATUS) + +/* + * Descriptor doubleword "B" (Table 7-13) + */ + + +#define S_DMA_DSCRB_OPTIONS _SB_MAKE64(0) +#define M_DMA_DSCRB_OPTIONS _SB_MAKEMASK(4, S_DMA_DSCRB_OPTIONS) +#define V_DMA_DSCRB_OPTIONS(x) _SB_MAKEVALUE(x, S_DMA_DSCRB_OPTIONS) +#define G_DMA_DSCRB_OPTIONS(x) _SB_GETVALUE(x, S_DMA_DSCRB_OPTIONS, M_DMA_DSCRB_OPTIONS) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_DMA_DSCRB_A_SIZE _SB_MAKE64(8) +#define M_DMA_DSCRB_A_SIZE _SB_MAKEMASK(14, S_DMA_DSCRB_A_SIZE) +#define V_DMA_DSCRB_A_SIZE(x) _SB_MAKEVALUE(x, S_DMA_DSCRB_A_SIZE) +#define G_DMA_DSCRB_A_SIZE(x) _SB_GETVALUE(x, S_DMA_DSCRB_A_SIZE, M_DMA_DSCRB_A_SIZE) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define R_DMA_DSCRB_ADDR _SB_MAKE64(0x10) + +/* Note: Don't shift the address over, just mask it with the mask below */ +#define S_DMA_DSCRB_B_ADDR _SB_MAKE64(5) +#define M_DMA_DSCRB_B_ADDR _SB_MAKEMASK(35, S_DMA_DSCRB_B_ADDR) + +#define S_DMA_DSCRB_B_SIZE _SB_MAKE64(40) +#define M_DMA_DSCRB_B_SIZE _SB_MAKEMASK(9, S_DMA_DSCRB_B_SIZE) +#define V_DMA_DSCRB_B_SIZE(x) _SB_MAKEVALUE(x, S_DMA_DSCRB_B_SIZE) +#define G_DMA_DSCRB_B_SIZE(x) _SB_GETVALUE(x, S_DMA_DSCRB_B_SIZE, M_DMA_DSCRB_B_SIZE) + +#define M_DMA_DSCRB_B_VALID _SB_MAKEMASK1(49) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_DMA_DSCRB_PKT_SIZE_MSB _SB_MAKE64(48) +#define M_DMA_DSCRB_PKT_SIZE_MSB _SB_MAKEMASK(2, S_DMA_DSCRB_PKT_SIZE_MSB) +#define V_DMA_DSCRB_PKT_SIZE_MSB(x) _SB_MAKEVALUE(x, S_DMA_DSCRB_PKT_SIZE_MSB) +#define G_DMA_DSCRB_PKT_SIZE_MSB(x) _SB_GETVALUE(x, S_DMA_DSCRB_PKT_SIZE_MSB, M_DMA_DSCRB_PKT_SIZE_MSB) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define S_DMA_DSCRB_PKT_SIZE _SB_MAKE64(50) +#define M_DMA_DSCRB_PKT_SIZE _SB_MAKEMASK(14, S_DMA_DSCRB_PKT_SIZE) +#define V_DMA_DSCRB_PKT_SIZE(x) _SB_MAKEVALUE(x, S_DMA_DSCRB_PKT_SIZE) +#define G_DMA_DSCRB_PKT_SIZE(x) _SB_GETVALUE(x, S_DMA_DSCRB_PKT_SIZE, M_DMA_DSCRB_PKT_SIZE) + +/* + * from pass2 some bits in dscr_b are also used for rx status + */ +#define S_DMA_DSCRB_STATUS _SB_MAKE64(0) +#define M_DMA_DSCRB_STATUS _SB_MAKEMASK(1, S_DMA_DSCRB_STATUS) +#define V_DMA_DSCRB_STATUS(x) _SB_MAKEVALUE(x, S_DMA_DSCRB_STATUS) +#define G_DMA_DSCRB_STATUS(x) _SB_GETVALUE(x, S_DMA_DSCRB_STATUS, M_DMA_DSCRB_STATUS) + +/* + * Ethernet Descriptor Status Bits (Table 7-15) + */ + +#define M_DMA_ETHRX_BADIP4CS _SB_MAKEMASK1(51) +#define M_DMA_ETHRX_DSCRERR _SB_MAKEMASK1(52) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +/* Note: This bit is in the DSCR_B options field */ +#define M_DMA_ETHRX_BADTCPCS _SB_MAKEMASK1(0) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +/* Note: These bits are in the DSCR_B options field */ +#define M_DMA_ETH_VLAN_FLAG _SB_MAKEMASK1(1) +#define M_DMA_ETH_CRC_FLAG _SB_MAKEMASK1(2) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define S_DMA_ETHRX_RXCH 53 +#define M_DMA_ETHRX_RXCH _SB_MAKEMASK(2, S_DMA_ETHRX_RXCH) +#define V_DMA_ETHRX_RXCH(x) _SB_MAKEVALUE(x, S_DMA_ETHRX_RXCH) +#define G_DMA_ETHRX_RXCH(x) _SB_GETVALUE(x, S_DMA_ETHRX_RXCH, M_DMA_ETHRX_RXCH) + +#define S_DMA_ETHRX_PKTTYPE 55 +#define M_DMA_ETHRX_PKTTYPE _SB_MAKEMASK(3, S_DMA_ETHRX_PKTTYPE) +#define V_DMA_ETHRX_PKTTYPE(x) _SB_MAKEVALUE(x, S_DMA_ETHRX_PKTTYPE) +#define G_DMA_ETHRX_PKTTYPE(x) _SB_GETVALUE(x, S_DMA_ETHRX_PKTTYPE, M_DMA_ETHRX_PKTTYPE) + +#define K_DMA_ETHRX_PKTTYPE_IPV4 0 +#define K_DMA_ETHRX_PKTTYPE_ARPV4 1 +#define K_DMA_ETHRX_PKTTYPE_802 2 +#define K_DMA_ETHRX_PKTTYPE_OTHER 3 +#define K_DMA_ETHRX_PKTTYPE_USER0 4 +#define K_DMA_ETHRX_PKTTYPE_USER1 5 +#define K_DMA_ETHRX_PKTTYPE_USER2 6 +#define K_DMA_ETHRX_PKTTYPE_USER3 7 + +#define M_DMA_ETHRX_MATCH_HASH _SB_MAKEMASK1(58) +#define M_DMA_ETHRX_MATCH_EXACT _SB_MAKEMASK1(59) +#define M_DMA_ETHRX_BCAST _SB_MAKEMASK1(60) +#define M_DMA_ETHRX_MCAST _SB_MAKEMASK1(61) +#define M_DMA_ETHRX_BAD _SB_MAKEMASK1(62) +#define M_DMA_ETHRX_SOP _SB_MAKEMASK1(63) + +/* + * Ethernet Transmit Status Bits (Table 7-16) + */ + +#define M_DMA_ETHTX_SOP _SB_MAKEMASK1(63) + +/* + * Ethernet Transmit Options (Table 7-17) + */ + +#define K_DMA_ETHTX_NOTSOP _SB_MAKE64(0x00) +#define K_DMA_ETHTX_APPENDCRC _SB_MAKE64(0x01) +#define K_DMA_ETHTX_REPLACECRC _SB_MAKE64(0x02) +#define K_DMA_ETHTX_APPENDCRC_APPENDPAD _SB_MAKE64(0x03) +#define K_DMA_ETHTX_APPENDVLAN_REPLACECRC _SB_MAKE64(0x04) +#define K_DMA_ETHTX_REMOVEVLAN_REPLACECRC _SB_MAKE64(0x05) +#define K_DMA_ETHTX_REPLACEVLAN_REPLACECRC _SB_MAKE64(0x6) +#define K_DMA_ETHTX_NOMODS _SB_MAKE64(0x07) +#define K_DMA_ETHTX_RESERVED1 _SB_MAKE64(0x08) +#define K_DMA_ETHTX_REPLACESADDR_APPENDCRC _SB_MAKE64(0x09) +#define K_DMA_ETHTX_REPLACESADDR_REPLACECRC _SB_MAKE64(0x0A) +#define K_DMA_ETHTX_REPLACESADDR_APPENDCRC_APPENDPAD _SB_MAKE64(0x0B) +#define K_DMA_ETHTX_REPLACESADDR_APPENDVLAN_REPLACECRC _SB_MAKE64(0x0C) +#define K_DMA_ETHTX_REPLACESADDR_REMOVEVLAN_REPLACECRC _SB_MAKE64(0x0D) +#define K_DMA_ETHTX_REPLACESADDR_REPLACEVLAN_REPLACECRC _SB_MAKE64(0x0E) +#define K_DMA_ETHTX_RESERVED2 _SB_MAKE64(0x0F) + +/* + * Serial Receive Options (Table 7-18) + */ +#define M_DMA_SERRX_CRC_ERROR _SB_MAKEMASK1(56) +#define M_DMA_SERRX_ABORT _SB_MAKEMASK1(57) +#define M_DMA_SERRX_OCTET_ERROR _SB_MAKEMASK1(58) +#define M_DMA_SERRX_LONGFRAME_ERROR _SB_MAKEMASK1(59) +#define M_DMA_SERRX_SHORTFRAME_ERROR _SB_MAKEMASK1(60) +#define M_DMA_SERRX_OVERRUN_ERROR _SB_MAKEMASK1(61) +#define M_DMA_SERRX_GOOD _SB_MAKEMASK1(62) +#define M_DMA_SERRX_SOP _SB_MAKEMASK1(63) + +/* + * Serial Transmit Status Bits (Table 7-20) + */ + +#define M_DMA_SERTX_FLAG _SB_MAKEMASK1(63) + +/* + * Serial Transmit Options (Table 7-21) + */ + +#define K_DMA_SERTX_RESERVED _SB_MAKEMASK1(0) +#define K_DMA_SERTX_APPENDCRC _SB_MAKEMASK1(1) +#define K_DMA_SERTX_APPENDPAD _SB_MAKEMASK1(2) +#define K_DMA_SERTX_ABORT _SB_MAKEMASK1(3) + + +/* ********************************************************************* + * Data Mover Registers + ********************************************************************* */ + +/* + * Data Mover Descriptor Base Address Register (Table 7-22) + * Register: DM_DSCR_BASE_0 + * Register: DM_DSCR_BASE_1 + * Register: DM_DSCR_BASE_2 + * Register: DM_DSCR_BASE_3 + */ + +#define M_DM_DSCR_BASE_MBZ _SB_MAKEMASK(4, 0) + +/* Note: Just mask the base address and then OR it in. */ +#define S_DM_DSCR_BASE_ADDR _SB_MAKE64(4) +#define M_DM_DSCR_BASE_ADDR _SB_MAKEMASK(36, S_DM_DSCR_BASE_ADDR) + +#define S_DM_DSCR_BASE_RINGSZ _SB_MAKE64(40) +#define M_DM_DSCR_BASE_RINGSZ _SB_MAKEMASK(16, S_DM_DSCR_BASE_RINGSZ) +#define V_DM_DSCR_BASE_RINGSZ(x) _SB_MAKEVALUE(x, S_DM_DSCR_BASE_RINGSZ) +#define G_DM_DSCR_BASE_RINGSZ(x) _SB_GETVALUE(x, S_DM_DSCR_BASE_RINGSZ, M_DM_DSCR_BASE_RINGSZ) + +#define S_DM_DSCR_BASE_PRIORITY _SB_MAKE64(56) +#define M_DM_DSCR_BASE_PRIORITY _SB_MAKEMASK(3, S_DM_DSCR_BASE_PRIORITY) +#define V_DM_DSCR_BASE_PRIORITY(x) _SB_MAKEVALUE(x, S_DM_DSCR_BASE_PRIORITY) +#define G_DM_DSCR_BASE_PRIORITY(x) _SB_GETVALUE(x, S_DM_DSCR_BASE_PRIORITY, M_DM_DSCR_BASE_PRIORITY) + +#define K_DM_DSCR_BASE_PRIORITY_1 0 +#define K_DM_DSCR_BASE_PRIORITY_2 1 +#define K_DM_DSCR_BASE_PRIORITY_4 2 +#define K_DM_DSCR_BASE_PRIORITY_8 3 +#define K_DM_DSCR_BASE_PRIORITY_16 4 + +#define M_DM_DSCR_BASE_ACTIVE _SB_MAKEMASK1(59) +#define M_DM_DSCR_BASE_INTERRUPT _SB_MAKEMASK1(60) +#define M_DM_DSCR_BASE_RESET _SB_MAKEMASK1(61) /* write register */ +#define M_DM_DSCR_BASE_ERROR _SB_MAKEMASK1(61) /* read register */ +#define M_DM_DSCR_BASE_ABORT _SB_MAKEMASK1(62) +#define M_DM_DSCR_BASE_ENABL _SB_MAKEMASK1(63) + +/* + * Data Mover Descriptor Count Register (Table 7-25) + */ + +/* no bitfields */ + +/* + * Data Mover Current Descriptor Address (Table 7-24) + * Register: DM_CUR_DSCR_ADDR_0 + * Register: DM_CUR_DSCR_ADDR_1 + * Register: DM_CUR_DSCR_ADDR_2 + * Register: DM_CUR_DSCR_ADDR_3 + */ + +#define S_DM_CUR_DSCR_DSCR_ADDR _SB_MAKE64(0) +#define M_DM_CUR_DSCR_DSCR_ADDR _SB_MAKEMASK(40, S_DM_CUR_DSCR_DSCR_ADDR) + +#define S_DM_CUR_DSCR_DSCR_COUNT _SB_MAKE64(48) +#define M_DM_CUR_DSCR_DSCR_COUNT _SB_MAKEMASK(16, S_DM_CUR_DSCR_DSCR_COUNT) +#define V_DM_CUR_DSCR_DSCR_COUNT(r) _SB_MAKEVALUE(r, S_DM_CUR_DSCR_DSCR_COUNT) +#define G_DM_CUR_DSCR_DSCR_COUNT(r) _SB_GETVALUE(r, S_DM_CUR_DSCR_DSCR_COUNT,\ + M_DM_CUR_DSCR_DSCR_COUNT) + + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +/* + * Data Mover Channel Partial Result Registers + * Register: DM_PARTIAL_0 + * Register: DM_PARTIAL_1 + * Register: DM_PARTIAL_2 + * Register: DM_PARTIAL_3 + */ +#define S_DM_PARTIAL_CRC_PARTIAL _SB_MAKE64(0) +#define M_DM_PARTIAL_CRC_PARTIAL _SB_MAKEMASK(32, S_DM_PARTIAL_CRC_PARTIAL) +#define V_DM_PARTIAL_CRC_PARTIAL(r) _SB_MAKEVALUE(r, S_DM_PARTIAL_CRC_PARTIAL) +#define G_DM_PARTIAL_CRC_PARTIAL(r) _SB_GETVALUE(r, S_DM_PARTIAL_CRC_PARTIAL,\ + M_DM_PARTIAL_CRC_PARTIAL) + +#define S_DM_PARTIAL_TCPCS_PARTIAL _SB_MAKE64(32) +#define M_DM_PARTIAL_TCPCS_PARTIAL _SB_MAKEMASK(16, S_DM_PARTIAL_TCPCS_PARTIAL) +#define V_DM_PARTIAL_TCPCS_PARTIAL(r) _SB_MAKEVALUE(r, S_DM_PARTIAL_TCPCS_PARTIAL) +#define G_DM_PARTIAL_TCPCS_PARTIAL(r) _SB_GETVALUE(r, S_DM_PARTIAL_TCPCS_PARTIAL,\ + M_DM_PARTIAL_TCPCS_PARTIAL) + +#define M_DM_PARTIAL_ODD_BYTE _SB_MAKEMASK1(48) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +/* + * Data Mover CRC Definition Registers + * Register: CRC_DEF_0 + * Register: CRC_DEF_1 + */ +#define S_CRC_DEF_CRC_INIT _SB_MAKE64(0) +#define M_CRC_DEF_CRC_INIT _SB_MAKEMASK(32, S_CRC_DEF_CRC_INIT) +#define V_CRC_DEF_CRC_INIT(r) _SB_MAKEVALUE(r, S_CRC_DEF_CRC_INIT) +#define G_CRC_DEF_CRC_INIT(r) _SB_GETVALUE(r, S_CRC_DEF_CRC_INIT,\ + M_CRC_DEF_CRC_INIT) + +#define S_CRC_DEF_CRC_POLY _SB_MAKE64(32) +#define M_CRC_DEF_CRC_POLY _SB_MAKEMASK(32, S_CRC_DEF_CRC_POLY) +#define V_CRC_DEF_CRC_POLY(r) _SB_MAKEVALUE(r, S_CRC_DEF_CRC_POLY) +#define G_CRC_DEF_CRC_POLY(r) _SB_GETVALUE(r, S_CRC_DEF_CRC_POLY,\ + M_CRC_DEF_CRC_POLY) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +/* + * Data Mover CRC/Checksum Definition Registers + * Register: CTCP_DEF_0 + * Register: CTCP_DEF_1 + */ +#define S_CTCP_DEF_CRC_TXOR _SB_MAKE64(0) +#define M_CTCP_DEF_CRC_TXOR _SB_MAKEMASK(32, S_CTCP_DEF_CRC_TXOR) +#define V_CTCP_DEF_CRC_TXOR(r) _SB_MAKEVALUE(r, S_CTCP_DEF_CRC_TXOR) +#define G_CTCP_DEF_CRC_TXOR(r) _SB_GETVALUE(r, S_CTCP_DEF_CRC_TXOR,\ + M_CTCP_DEF_CRC_TXOR) + +#define S_CTCP_DEF_TCPCS_INIT _SB_MAKE64(32) +#define M_CTCP_DEF_TCPCS_INIT _SB_MAKEMASK(16, S_CTCP_DEF_TCPCS_INIT) +#define V_CTCP_DEF_TCPCS_INIT(r) _SB_MAKEVALUE(r, S_CTCP_DEF_TCPCS_INIT) +#define G_CTCP_DEF_TCPCS_INIT(r) _SB_GETVALUE(r, S_CTCP_DEF_TCPCS_INIT,\ + M_CTCP_DEF_TCPCS_INIT) + +#define S_CTCP_DEF_CRC_WIDTH _SB_MAKE64(48) +#define M_CTCP_DEF_CRC_WIDTH _SB_MAKEMASK(2, S_CTCP_DEF_CRC_WIDTH) +#define V_CTCP_DEF_CRC_WIDTH(r) _SB_MAKEVALUE(r, S_CTCP_DEF_CRC_WIDTH) +#define G_CTCP_DEF_CRC_WIDTH(r) _SB_GETVALUE(r, S_CTCP_DEF_CRC_WIDTH,\ + M_CTCP_DEF_CRC_WIDTH) + +#define K_CTCP_DEF_CRC_WIDTH_4 0 +#define K_CTCP_DEF_CRC_WIDTH_2 1 +#define K_CTCP_DEF_CRC_WIDTH_1 2 + +#define M_CTCP_DEF_CRC_BIT_ORDER _SB_MAKEMASK1(50) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + + +/* + * Data Mover Descriptor Doubleword "A" (Table 7-26) + */ + +#define S_DM_DSCRA_DST_ADDR _SB_MAKE64(0) +#define M_DM_DSCRA_DST_ADDR _SB_MAKEMASK(40, S_DM_DSCRA_DST_ADDR) + +#define M_DM_DSCRA_UN_DEST _SB_MAKEMASK1(40) +#define M_DM_DSCRA_UN_SRC _SB_MAKEMASK1(41) +#define M_DM_DSCRA_INTERRUPT _SB_MAKEMASK1(42) +#if SIBYTE_HDR_FEATURE_UP_TO(1250, PASS1) +#define M_DM_DSCRA_THROTTLE _SB_MAKEMASK1(43) +#endif /* up to 1250 PASS1 */ + +#define S_DM_DSCRA_DIR_DEST _SB_MAKE64(44) +#define M_DM_DSCRA_DIR_DEST _SB_MAKEMASK(2, S_DM_DSCRA_DIR_DEST) +#define V_DM_DSCRA_DIR_DEST(x) _SB_MAKEVALUE(x, S_DM_DSCRA_DIR_DEST) +#define G_DM_DSCRA_DIR_DEST(x) _SB_GETVALUE(x, S_DM_DSCRA_DIR_DEST, M_DM_DSCRA_DIR_DEST) + +#define K_DM_DSCRA_DIR_DEST_INCR 0 +#define K_DM_DSCRA_DIR_DEST_DECR 1 +#define K_DM_DSCRA_DIR_DEST_CONST 2 + +#define V_DM_DSCRA_DIR_DEST_INCR _SB_MAKEVALUE(K_DM_DSCRA_DIR_DEST_INCR, S_DM_DSCRA_DIR_DEST) +#define V_DM_DSCRA_DIR_DEST_DECR _SB_MAKEVALUE(K_DM_DSCRA_DIR_DEST_DECR, S_DM_DSCRA_DIR_DEST) +#define V_DM_DSCRA_DIR_DEST_CONST _SB_MAKEVALUE(K_DM_DSCRA_DIR_DEST_CONST, S_DM_DSCRA_DIR_DEST) + +#define S_DM_DSCRA_DIR_SRC _SB_MAKE64(46) +#define M_DM_DSCRA_DIR_SRC _SB_MAKEMASK(2, S_DM_DSCRA_DIR_SRC) +#define V_DM_DSCRA_DIR_SRC(x) _SB_MAKEVALUE(x, S_DM_DSCRA_DIR_SRC) +#define G_DM_DSCRA_DIR_SRC(x) _SB_GETVALUE(x, S_DM_DSCRA_DIR_SRC, M_DM_DSCRA_DIR_SRC) + +#define K_DM_DSCRA_DIR_SRC_INCR 0 +#define K_DM_DSCRA_DIR_SRC_DECR 1 +#define K_DM_DSCRA_DIR_SRC_CONST 2 + +#define V_DM_DSCRA_DIR_SRC_INCR _SB_MAKEVALUE(K_DM_DSCRA_DIR_SRC_INCR, S_DM_DSCRA_DIR_SRC) +#define V_DM_DSCRA_DIR_SRC_DECR _SB_MAKEVALUE(K_DM_DSCRA_DIR_SRC_DECR, S_DM_DSCRA_DIR_SRC) +#define V_DM_DSCRA_DIR_SRC_CONST _SB_MAKEVALUE(K_DM_DSCRA_DIR_SRC_CONST, S_DM_DSCRA_DIR_SRC) + + +#define M_DM_DSCRA_ZERO_MEM _SB_MAKEMASK1(48) +#define M_DM_DSCRA_PREFETCH _SB_MAKEMASK1(49) +#define M_DM_DSCRA_L2C_DEST _SB_MAKEMASK1(50) +#define M_DM_DSCRA_L2C_SRC _SB_MAKEMASK1(51) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_DM_DSCRA_RD_BKOFF _SB_MAKEMASK1(52) +#define M_DM_DSCRA_WR_BKOFF _SB_MAKEMASK1(53) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_DM_DSCRA_TCPCS_EN _SB_MAKEMASK1(54) +#define M_DM_DSCRA_TCPCS_RES _SB_MAKEMASK1(55) +#define M_DM_DSCRA_TCPCS_AP _SB_MAKEMASK1(56) +#define M_DM_DSCRA_CRC_EN _SB_MAKEMASK1(57) +#define M_DM_DSCRA_CRC_RES _SB_MAKEMASK1(58) +#define M_DM_DSCRA_CRC_AP _SB_MAKEMASK1(59) +#define M_DM_DSCRA_CRC_DFN _SB_MAKEMASK1(60) +#define M_DM_DSCRA_CRC_XBIT _SB_MAKEMASK1(61) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define M_DM_DSCRA_RESERVED2 _SB_MAKEMASK(3, 61) + +/* + * Data Mover Descriptor Doubleword "B" (Table 7-25) + */ + +#define S_DM_DSCRB_SRC_ADDR _SB_MAKE64(0) +#define M_DM_DSCRB_SRC_ADDR _SB_MAKEMASK(40, S_DM_DSCRB_SRC_ADDR) + +#define S_DM_DSCRB_SRC_LENGTH _SB_MAKE64(40) +#define M_DM_DSCRB_SRC_LENGTH _SB_MAKEMASK(20, S_DM_DSCRB_SRC_LENGTH) +#define V_DM_DSCRB_SRC_LENGTH(x) _SB_MAKEVALUE(x, S_DM_DSCRB_SRC_LENGTH) +#define G_DM_DSCRB_SRC_LENGTH(x) _SB_GETVALUE(x, S_DM_DSCRB_SRC_LENGTH, M_DM_DSCRB_SRC_LENGTH) + + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_genbus.h b/arch/mips/include/asm/sibyte/sb1250_genbus.h new file mode 100644 index 00000000000..94e9c7c8e78 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_genbus.h @@ -0,0 +1,474 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Generic Bus Constants File: sb1250_genbus.h + * + * This module contains constants and macros useful for + * manipulating the SB1250's Generic Bus interface + * + * SB1250 specification level: User's manual 10/21/02 + * BCM1280 specification level: User's Manual 11/14/03 + * + ********************************************************************* + * + * Copyright 2000, 2001, 2002, 2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_GENBUS_H +#define _SB1250_GENBUS_H + +#include "sb1250_defs.h" + +/* + * Generic Bus Region Configuration Registers (Table 11-4) + */ + +#define S_IO_RDY_ACTIVE 0 +#define M_IO_RDY_ACTIVE _SB_MAKEMASK1(S_IO_RDY_ACTIVE) + +#define S_IO_ENA_RDY 1 +#define M_IO_ENA_RDY _SB_MAKEMASK1(S_IO_ENA_RDY) + +#define S_IO_WIDTH_SEL 2 +#define M_IO_WIDTH_SEL _SB_MAKEMASK(2, S_IO_WIDTH_SEL) +#define K_IO_WIDTH_SEL_1 0 +#define K_IO_WIDTH_SEL_2 1 +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \ + || SIBYTE_HDR_FEATURE_CHIP(1480) +#define K_IO_WIDTH_SEL_1L 2 +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ +#define K_IO_WIDTH_SEL_4 3 +#define V_IO_WIDTH_SEL(x) _SB_MAKEVALUE(x, S_IO_WIDTH_SEL) +#define G_IO_WIDTH_SEL(x) _SB_GETVALUE(x, S_IO_WIDTH_SEL, M_IO_WIDTH_SEL) + +#define S_IO_PARITY_ENA 4 +#define M_IO_PARITY_ENA _SB_MAKEMASK1(S_IO_PARITY_ENA) +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \ + || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_IO_BURST_EN 5 +#define M_IO_BURST_EN _SB_MAKEMASK1(S_IO_BURST_EN) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ +#define S_IO_PARITY_ODD 6 +#define M_IO_PARITY_ODD _SB_MAKEMASK1(S_IO_PARITY_ODD) +#define S_IO_NONMUX 7 +#define M_IO_NONMUX _SB_MAKEMASK1(S_IO_NONMUX) + +#define S_IO_TIMEOUT 8 +#define M_IO_TIMEOUT _SB_MAKEMASK(8, S_IO_TIMEOUT) +#define V_IO_TIMEOUT(x) _SB_MAKEVALUE(x, S_IO_TIMEOUT) +#define G_IO_TIMEOUT(x) _SB_GETVALUE(x, S_IO_TIMEOUT, M_IO_TIMEOUT) + +/* + * Generic Bus Region Size register (Table 11-5) + */ + +#define S_IO_MULT_SIZE 0 +#define M_IO_MULT_SIZE _SB_MAKEMASK(12, S_IO_MULT_SIZE) +#define V_IO_MULT_SIZE(x) _SB_MAKEVALUE(x, S_IO_MULT_SIZE) +#define G_IO_MULT_SIZE(x) _SB_GETVALUE(x, S_IO_MULT_SIZE, M_IO_MULT_SIZE) + +#define S_IO_REGSIZE 16 /* # bits to shift size for this reg */ + +/* + * Generic Bus Region Address (Table 11-6) + */ + +#define S_IO_START_ADDR 0 +#define M_IO_START_ADDR _SB_MAKEMASK(14, S_IO_START_ADDR) +#define V_IO_START_ADDR(x) _SB_MAKEVALUE(x, S_IO_START_ADDR) +#define G_IO_START_ADDR(x) _SB_GETVALUE(x, S_IO_START_ADDR, M_IO_START_ADDR) + +#define S_IO_ADDRBASE 16 /* # bits to shift addr for this reg */ + +#define M_IO_BLK_CACHE _SB_MAKEMASK1(15) + + +/* + * Generic Bus Timing 0 Registers (Table 11-7) + */ + +#define S_IO_ALE_WIDTH 0 +#define M_IO_ALE_WIDTH _SB_MAKEMASK(3, S_IO_ALE_WIDTH) +#define V_IO_ALE_WIDTH(x) _SB_MAKEVALUE(x, S_IO_ALE_WIDTH) +#define G_IO_ALE_WIDTH(x) _SB_GETVALUE(x, S_IO_ALE_WIDTH, M_IO_ALE_WIDTH) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \ + || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_IO_EARLY_CS _SB_MAKEMASK1(3) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#define S_IO_ALE_TO_CS 4 +#define M_IO_ALE_TO_CS _SB_MAKEMASK(2, S_IO_ALE_TO_CS) +#define V_IO_ALE_TO_CS(x) _SB_MAKEVALUE(x, S_IO_ALE_TO_CS) +#define G_IO_ALE_TO_CS(x) _SB_GETVALUE(x, S_IO_ALE_TO_CS, M_IO_ALE_TO_CS) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \ + || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_IO_BURST_WIDTH _SB_MAKE64(6) +#define M_IO_BURST_WIDTH _SB_MAKEMASK(2, S_IO_BURST_WIDTH) +#define V_IO_BURST_WIDTH(x) _SB_MAKEVALUE(x, S_IO_BURST_WIDTH) +#define G_IO_BURST_WIDTH(x) _SB_GETVALUE(x, S_IO_BURST_WIDTH, M_IO_BURST_WIDTH) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#define S_IO_CS_WIDTH 8 +#define M_IO_CS_WIDTH _SB_MAKEMASK(5, S_IO_CS_WIDTH) +#define V_IO_CS_WIDTH(x) _SB_MAKEVALUE(x, S_IO_CS_WIDTH) +#define G_IO_CS_WIDTH(x) _SB_GETVALUE(x, S_IO_CS_WIDTH, M_IO_CS_WIDTH) + +#define S_IO_RDY_SMPLE 13 +#define M_IO_RDY_SMPLE _SB_MAKEMASK(3, S_IO_RDY_SMPLE) +#define V_IO_RDY_SMPLE(x) _SB_MAKEVALUE(x, S_IO_RDY_SMPLE) +#define G_IO_RDY_SMPLE(x) _SB_GETVALUE(x, S_IO_RDY_SMPLE, M_IO_RDY_SMPLE) + + +/* + * Generic Bus Timing 1 Registers (Table 11-8) + */ + +#define S_IO_ALE_TO_WRITE 0 +#define M_IO_ALE_TO_WRITE _SB_MAKEMASK(3, S_IO_ALE_TO_WRITE) +#define V_IO_ALE_TO_WRITE(x) _SB_MAKEVALUE(x, S_IO_ALE_TO_WRITE) +#define G_IO_ALE_TO_WRITE(x) _SB_GETVALUE(x, S_IO_ALE_TO_WRITE, M_IO_ALE_TO_WRITE) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \ + || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_IO_RDY_SYNC _SB_MAKEMASK1(3) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#define S_IO_WRITE_WIDTH 4 +#define M_IO_WRITE_WIDTH _SB_MAKEMASK(4, S_IO_WRITE_WIDTH) +#define V_IO_WRITE_WIDTH(x) _SB_MAKEVALUE(x, S_IO_WRITE_WIDTH) +#define G_IO_WRITE_WIDTH(x) _SB_GETVALUE(x, S_IO_WRITE_WIDTH, M_IO_WRITE_WIDTH) + +#define S_IO_IDLE_CYCLE 8 +#define M_IO_IDLE_CYCLE _SB_MAKEMASK(4, S_IO_IDLE_CYCLE) +#define V_IO_IDLE_CYCLE(x) _SB_MAKEVALUE(x, S_IO_IDLE_CYCLE) +#define G_IO_IDLE_CYCLE(x) _SB_GETVALUE(x, S_IO_IDLE_CYCLE, M_IO_IDLE_CYCLE) + +#define S_IO_OE_TO_CS 12 +#define M_IO_OE_TO_CS _SB_MAKEMASK(2, S_IO_OE_TO_CS) +#define V_IO_OE_TO_CS(x) _SB_MAKEVALUE(x, S_IO_OE_TO_CS) +#define G_IO_OE_TO_CS(x) _SB_GETVALUE(x, S_IO_OE_TO_CS, M_IO_OE_TO_CS) + +#define S_IO_CS_TO_OE 14 +#define M_IO_CS_TO_OE _SB_MAKEMASK(2, S_IO_CS_TO_OE) +#define V_IO_CS_TO_OE(x) _SB_MAKEVALUE(x, S_IO_CS_TO_OE) +#define G_IO_CS_TO_OE(x) _SB_GETVALUE(x, S_IO_CS_TO_OE, M_IO_CS_TO_OE) + +/* + * Generic Bus Interrupt Status Register (Table 11-9) + */ + +#define M_IO_CS_ERR_INT _SB_MAKEMASK(0, 8) +#define M_IO_CS0_ERR_INT _SB_MAKEMASK1(0) +#define M_IO_CS1_ERR_INT _SB_MAKEMASK1(1) +#define M_IO_CS2_ERR_INT _SB_MAKEMASK1(2) +#define M_IO_CS3_ERR_INT _SB_MAKEMASK1(3) +#define M_IO_CS4_ERR_INT _SB_MAKEMASK1(4) +#define M_IO_CS5_ERR_INT _SB_MAKEMASK1(5) +#define M_IO_CS6_ERR_INT _SB_MAKEMASK1(6) +#define M_IO_CS7_ERR_INT _SB_MAKEMASK1(7) + +#define M_IO_RD_PAR_INT _SB_MAKEMASK1(9) +#define M_IO_TIMEOUT_INT _SB_MAKEMASK1(10) +#define M_IO_ILL_ADDR_INT _SB_MAKEMASK1(11) +#define M_IO_MULT_CS_INT _SB_MAKEMASK1(12) +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_IO_COH_ERR _SB_MAKEMASK1(14) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + + +/* + * Generic Bus Output Drive Control Register 0 (Table 14-18) + */ + +#define S_IO_SLEW0 0 +#define M_IO_SLEW0 _SB_MAKEMASK(2, S_IO_SLEW0) +#define V_IO_SLEW0(x) _SB_MAKEVALUE(x, S_IO_SLEW0) +#define G_IO_SLEW0(x) _SB_GETVALUE(x, S_IO_SLEW0, M_IO_SLEW0) + +#define S_IO_DRV_A 2 +#define M_IO_DRV_A _SB_MAKEMASK(2, S_IO_DRV_A) +#define V_IO_DRV_A(x) _SB_MAKEVALUE(x, S_IO_DRV_A) +#define G_IO_DRV_A(x) _SB_GETVALUE(x, S_IO_DRV_A, M_IO_DRV_A) + +#define S_IO_DRV_B 6 +#define M_IO_DRV_B _SB_MAKEMASK(2, S_IO_DRV_B) +#define V_IO_DRV_B(x) _SB_MAKEVALUE(x, S_IO_DRV_B) +#define G_IO_DRV_B(x) _SB_GETVALUE(x, S_IO_DRV_B, M_IO_DRV_B) + +#define S_IO_DRV_C 10 +#define M_IO_DRV_C _SB_MAKEMASK(2, S_IO_DRV_C) +#define V_IO_DRV_C(x) _SB_MAKEVALUE(x, S_IO_DRV_C) +#define G_IO_DRV_C(x) _SB_GETVALUE(x, S_IO_DRV_C, M_IO_DRV_C) + +#define S_IO_DRV_D 14 +#define M_IO_DRV_D _SB_MAKEMASK(2, S_IO_DRV_D) +#define V_IO_DRV_D(x) _SB_MAKEVALUE(x, S_IO_DRV_D) +#define G_IO_DRV_D(x) _SB_GETVALUE(x, S_IO_DRV_D, M_IO_DRV_D) + +/* + * Generic Bus Output Drive Control Register 1 (Table 14-19) + */ + +#define S_IO_DRV_E 2 +#define M_IO_DRV_E _SB_MAKEMASK(2, S_IO_DRV_E) +#define V_IO_DRV_E(x) _SB_MAKEVALUE(x, S_IO_DRV_E) +#define G_IO_DRV_E(x) _SB_GETVALUE(x, S_IO_DRV_E, M_IO_DRV_E) + +#define S_IO_DRV_F 6 +#define M_IO_DRV_F _SB_MAKEMASK(2, S_IO_DRV_F) +#define V_IO_DRV_F(x) _SB_MAKEVALUE(x, S_IO_DRV_F) +#define G_IO_DRV_F(x) _SB_GETVALUE(x, S_IO_DRV_F, M_IO_DRV_F) + +#define S_IO_SLEW1 8 +#define M_IO_SLEW1 _SB_MAKEMASK(2, S_IO_SLEW1) +#define V_IO_SLEW1(x) _SB_MAKEVALUE(x, S_IO_SLEW1) +#define G_IO_SLEW1(x) _SB_GETVALUE(x, S_IO_SLEW1, M_IO_SLEW1) + +#define S_IO_DRV_G 10 +#define M_IO_DRV_G _SB_MAKEMASK(2, S_IO_DRV_G) +#define V_IO_DRV_G(x) _SB_MAKEVALUE(x, S_IO_DRV_G) +#define G_IO_DRV_G(x) _SB_GETVALUE(x, S_IO_DRV_G, M_IO_DRV_G) + +#define S_IO_SLEW2 12 +#define M_IO_SLEW2 _SB_MAKEMASK(2, S_IO_SLEW2) +#define V_IO_SLEW2(x) _SB_MAKEVALUE(x, S_IO_SLEW2) +#define G_IO_SLEW2(x) _SB_GETVALUE(x, S_IO_SLEW2, M_IO_SLEW2) + +#define S_IO_DRV_H 14 +#define M_IO_DRV_H _SB_MAKEMASK(2, S_IO_DRV_H) +#define V_IO_DRV_H(x) _SB_MAKEVALUE(x, S_IO_DRV_H) +#define G_IO_DRV_H(x) _SB_GETVALUE(x, S_IO_DRV_H, M_IO_DRV_H) + +/* + * Generic Bus Output Drive Control Register 2 (Table 14-20) + */ + +#define S_IO_DRV_J 2 +#define M_IO_DRV_J _SB_MAKEMASK(2, S_IO_DRV_J) +#define V_IO_DRV_J(x) _SB_MAKEVALUE(x, S_IO_DRV_J) +#define G_IO_DRV_J(x) _SB_GETVALUE(x, S_IO_DRV_J, M_IO_DRV_J) + +#define S_IO_DRV_K 6 +#define M_IO_DRV_K _SB_MAKEMASK(2, S_IO_DRV_K) +#define V_IO_DRV_K(x) _SB_MAKEVALUE(x, S_IO_DRV_K) +#define G_IO_DRV_K(x) _SB_GETVALUE(x, S_IO_DRV_K, M_IO_DRV_K) + +#define S_IO_DRV_L 10 +#define M_IO_DRV_L _SB_MAKEMASK(2, S_IO_DRV_L) +#define V_IO_DRV_L(x) _SB_MAKEVALUE(x, S_IO_DRV_L) +#define G_IO_DRV_L(x) _SB_GETVALUE(x, S_IO_DRV_L, M_IO_DRV_L) + +#define S_IO_DRV_M 14 +#define M_IO_DRV_M _SB_MAKEMASK(2, S_IO_DRV_M) +#define V_IO_DRV_M(x) _SB_MAKEVALUE(x, S_IO_DRV_M) +#define G_IO_DRV_M(x) _SB_GETVALUE(x, S_IO_DRV_M, M_IO_DRV_M) + +/* + * Generic Bus Output Drive Control Register 3 (Table 14-21) + */ + +#define S_IO_SLEW3 0 +#define M_IO_SLEW3 _SB_MAKEMASK(2, S_IO_SLEW3) +#define V_IO_SLEW3(x) _SB_MAKEVALUE(x, S_IO_SLEW3) +#define G_IO_SLEW3(x) _SB_GETVALUE(x, S_IO_SLEW3, M_IO_SLEW3) + +#define S_IO_DRV_N 2 +#define M_IO_DRV_N _SB_MAKEMASK(2, S_IO_DRV_N) +#define V_IO_DRV_N(x) _SB_MAKEVALUE(x, S_IO_DRV_N) +#define G_IO_DRV_N(x) _SB_GETVALUE(x, S_IO_DRV_N, M_IO_DRV_N) + +#define S_IO_DRV_P 6 +#define M_IO_DRV_P _SB_MAKEMASK(2, S_IO_DRV_P) +#define V_IO_DRV_P(x) _SB_MAKEVALUE(x, S_IO_DRV_P) +#define G_IO_DRV_P(x) _SB_GETVALUE(x, S_IO_DRV_P, M_IO_DRV_P) + +#define S_IO_DRV_Q 10 +#define M_IO_DRV_Q _SB_MAKEMASK(2, S_IO_DRV_Q) +#define V_IO_DRV_Q(x) _SB_MAKEVALUE(x, S_IO_DRV_Q) +#define G_IO_DRV_Q(x) _SB_GETVALUE(x, S_IO_DRV_Q, M_IO_DRV_Q) + +#define S_IO_DRV_R 14 +#define M_IO_DRV_R _SB_MAKEMASK(2, S_IO_DRV_R) +#define V_IO_DRV_R(x) _SB_MAKEVALUE(x, S_IO_DRV_R) +#define G_IO_DRV_R(x) _SB_GETVALUE(x, S_IO_DRV_R, M_IO_DRV_R) + + +/* + * PCMCIA configuration register (Table 12-6) + */ + +#define M_PCMCIA_CFG_ATTRMEM _SB_MAKEMASK1(0) +#define M_PCMCIA_CFG_3VEN _SB_MAKEMASK1(1) +#define M_PCMCIA_CFG_5VEN _SB_MAKEMASK1(2) +#define M_PCMCIA_CFG_VPPEN _SB_MAKEMASK1(3) +#define M_PCMCIA_CFG_RESET _SB_MAKEMASK1(4) +#define M_PCMCIA_CFG_APWRONEN _SB_MAKEMASK1(5) +#define M_PCMCIA_CFG_CDMASK _SB_MAKEMASK1(6) +#define M_PCMCIA_CFG_WPMASK _SB_MAKEMASK1(7) +#define M_PCMCIA_CFG_RDYMASK _SB_MAKEMASK1(8) +#define M_PCMCIA_CFG_PWRCTL _SB_MAKEMASK1(9) + +#if SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_PCMCIA_MODE 16 +#define M_PCMCIA_MODE _SB_MAKEMASK(3, S_PCMCIA_MODE) +#define V_PCMCIA_MODE(x) _SB_MAKEVALUE(x, S_PCMCIA_MODE) +#define G_PCMCIA_MODE(x) _SB_GETVALUE(x, S_PCMCIA_MODE, M_PCMCIA_MODE) + +#define K_PCMCIA_MODE_PCMA_NOB 0 /* standard PCMCIA "A", no "B" */ +#define K_PCMCIA_MODE_IDEA_NOB 1 /* IDE "A", no "B" */ +#define K_PCMCIA_MODE_PCMIOA_NOB 2 /* PCMCIA with I/O "A", no "B" */ +#define K_PCMCIA_MODE_PCMA_PCMB 4 /* standard PCMCIA "A", standard PCMCIA "B" */ +#define K_PCMCIA_MODE_IDEA_PCMB 5 /* IDE "A", standard PCMCIA "B" */ +#define K_PCMCIA_MODE_PCMA_IDEB 6 /* standard PCMCIA "A", IDE "B" */ +#define K_PCMCIA_MODE_IDEA_IDEB 7 /* IDE "A", IDE "B" */ +#endif + + +/* + * PCMCIA status register (Table 12-7) + */ + +#define M_PCMCIA_STATUS_CD1 _SB_MAKEMASK1(0) +#define M_PCMCIA_STATUS_CD2 _SB_MAKEMASK1(1) +#define M_PCMCIA_STATUS_VS1 _SB_MAKEMASK1(2) +#define M_PCMCIA_STATUS_VS2 _SB_MAKEMASK1(3) +#define M_PCMCIA_STATUS_WP _SB_MAKEMASK1(4) +#define M_PCMCIA_STATUS_RDY _SB_MAKEMASK1(5) +#define M_PCMCIA_STATUS_3VEN _SB_MAKEMASK1(6) +#define M_PCMCIA_STATUS_5VEN _SB_MAKEMASK1(7) +#define M_PCMCIA_STATUS_CDCHG _SB_MAKEMASK1(8) +#define M_PCMCIA_STATUS_WPCHG _SB_MAKEMASK1(9) +#define M_PCMCIA_STATUS_RDYCHG _SB_MAKEMASK1(10) + +/* + * GPIO Interrupt Type Register (table 13-3) + */ + +#define K_GPIO_INTR_DISABLE 0 +#define K_GPIO_INTR_EDGE 1 +#define K_GPIO_INTR_LEVEL 2 +#define K_GPIO_INTR_SPLIT 3 + +#define S_GPIO_INTR_TYPEX(n) (((n)/2)*2) +#define M_GPIO_INTR_TYPEX(n) _SB_MAKEMASK(2, S_GPIO_INTR_TYPEX(n)) +#define V_GPIO_INTR_TYPEX(n, x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPEX(n)) +#define G_GPIO_INTR_TYPEX(n, x) _SB_GETVALUE(x, S_GPIO_INTR_TYPEX(n), M_GPIO_INTR_TYPEX(n)) + +#define S_GPIO_INTR_TYPE0 0 +#define M_GPIO_INTR_TYPE0 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE0) +#define V_GPIO_INTR_TYPE0(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE0) +#define G_GPIO_INTR_TYPE0(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE0, M_GPIO_INTR_TYPE0) + +#define S_GPIO_INTR_TYPE2 2 +#define M_GPIO_INTR_TYPE2 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE2) +#define V_GPIO_INTR_TYPE2(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE2) +#define G_GPIO_INTR_TYPE2(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE2, M_GPIO_INTR_TYPE2) + +#define S_GPIO_INTR_TYPE4 4 +#define M_GPIO_INTR_TYPE4 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE4) +#define V_GPIO_INTR_TYPE4(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE4) +#define G_GPIO_INTR_TYPE4(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE4, M_GPIO_INTR_TYPE4) + +#define S_GPIO_INTR_TYPE6 6 +#define M_GPIO_INTR_TYPE6 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE6) +#define V_GPIO_INTR_TYPE6(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE6) +#define G_GPIO_INTR_TYPE6(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE6, M_GPIO_INTR_TYPE6) + +#define S_GPIO_INTR_TYPE8 8 +#define M_GPIO_INTR_TYPE8 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE8) +#define V_GPIO_INTR_TYPE8(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE8) +#define G_GPIO_INTR_TYPE8(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE8, M_GPIO_INTR_TYPE8) + +#define S_GPIO_INTR_TYPE10 10 +#define M_GPIO_INTR_TYPE10 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE10) +#define V_GPIO_INTR_TYPE10(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE10) +#define G_GPIO_INTR_TYPE10(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE10, M_GPIO_INTR_TYPE10) + +#define S_GPIO_INTR_TYPE12 12 +#define M_GPIO_INTR_TYPE12 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE12) +#define V_GPIO_INTR_TYPE12(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE12) +#define G_GPIO_INTR_TYPE12(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE12, M_GPIO_INTR_TYPE12) + +#define S_GPIO_INTR_TYPE14 14 +#define M_GPIO_INTR_TYPE14 _SB_MAKEMASK(2, S_GPIO_INTR_TYPE14) +#define V_GPIO_INTR_TYPE14(x) _SB_MAKEVALUE(x, S_GPIO_INTR_TYPE14) +#define G_GPIO_INTR_TYPE14(x) _SB_GETVALUE(x, S_GPIO_INTR_TYPE14, M_GPIO_INTR_TYPE14) + +#if SIBYTE_HDR_FEATURE_CHIP(1480) + +/* + * GPIO Interrupt Additional Type Register + */ + +#define K_GPIO_INTR_BOTHEDGE 0 +#define K_GPIO_INTR_RISEEDGE 1 +#define K_GPIO_INTR_UNPRED1 2 +#define K_GPIO_INTR_UNPRED2 3 + +#define S_GPIO_INTR_ATYPEX(n) (((n)/2)*2) +#define M_GPIO_INTR_ATYPEX(n) _SB_MAKEMASK(2, S_GPIO_INTR_ATYPEX(n)) +#define V_GPIO_INTR_ATYPEX(n, x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPEX(n)) +#define G_GPIO_INTR_ATYPEX(n, x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPEX(n), M_GPIO_INTR_ATYPEX(n)) + +#define S_GPIO_INTR_ATYPE0 0 +#define M_GPIO_INTR_ATYPE0 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE0) +#define V_GPIO_INTR_ATYPE0(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE0) +#define G_GPIO_INTR_ATYPE0(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE0, M_GPIO_INTR_ATYPE0) + +#define S_GPIO_INTR_ATYPE2 2 +#define M_GPIO_INTR_ATYPE2 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE2) +#define V_GPIO_INTR_ATYPE2(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE2) +#define G_GPIO_INTR_ATYPE2(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE2, M_GPIO_INTR_ATYPE2) + +#define S_GPIO_INTR_ATYPE4 4 +#define M_GPIO_INTR_ATYPE4 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE4) +#define V_GPIO_INTR_ATYPE4(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE4) +#define G_GPIO_INTR_ATYPE4(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE4, M_GPIO_INTR_ATYPE4) + +#define S_GPIO_INTR_ATYPE6 6 +#define M_GPIO_INTR_ATYPE6 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE6) +#define V_GPIO_INTR_ATYPE6(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE6) +#define G_GPIO_INTR_ATYPE6(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE6, M_GPIO_INTR_ATYPE6) + +#define S_GPIO_INTR_ATYPE8 8 +#define M_GPIO_INTR_ATYPE8 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE8) +#define V_GPIO_INTR_ATYPE8(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE8) +#define G_GPIO_INTR_ATYPE8(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE8, M_GPIO_INTR_ATYPE8) + +#define S_GPIO_INTR_ATYPE10 10 +#define M_GPIO_INTR_ATYPE10 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE10) +#define V_GPIO_INTR_ATYPE10(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE10) +#define G_GPIO_INTR_ATYPE10(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE10, M_GPIO_INTR_ATYPE10) + +#define S_GPIO_INTR_ATYPE12 12 +#define M_GPIO_INTR_ATYPE12 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE12) +#define V_GPIO_INTR_ATYPE12(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE12) +#define G_GPIO_INTR_ATYPE12(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE12, M_GPIO_INTR_ATYPE12) + +#define S_GPIO_INTR_ATYPE14 14 +#define M_GPIO_INTR_ATYPE14 _SB_MAKEMASK(2, S_GPIO_INTR_ATYPE14) +#define V_GPIO_INTR_ATYPE14(x) _SB_MAKEVALUE(x, S_GPIO_INTR_ATYPE14) +#define G_GPIO_INTR_ATYPE14(x) _SB_GETVALUE(x, S_GPIO_INTR_ATYPE14, M_GPIO_INTR_ATYPE14) +#endif + + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_int.h b/arch/mips/include/asm/sibyte/sb1250_int.h new file mode 100644 index 00000000000..f2850b4bcfd --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_int.h @@ -0,0 +1,248 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Interrupt Mapper definitions File: sb1250_int.h + * + * This module contains constants for manipulating the SB1250's + * interrupt mapper and definitions for the interrupt sources. + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000, 2001, 2002, 2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_INT_H +#define _SB1250_INT_H + +#include "sb1250_defs.h" + +/* ********************************************************************* + * Interrupt Mapper Constants + ********************************************************************* */ + +/* + * Interrupt sources (Table 4-8, UM 0.2) + * + * First, the interrupt numbers. + */ + +#define K_INT_SOURCES 64 + +#define K_INT_WATCHDOG_TIMER_0 0 +#define K_INT_WATCHDOG_TIMER_1 1 +#define K_INT_TIMER_0 2 +#define K_INT_TIMER_1 3 +#define K_INT_TIMER_2 4 +#define K_INT_TIMER_3 5 +#define K_INT_SMB_0 6 +#define K_INT_SMB_1 7 +#define K_INT_UART_0 8 +#define K_INT_UART_1 9 +#define K_INT_SER_0 10 +#define K_INT_SER_1 11 +#define K_INT_PCMCIA 12 +#define K_INT_ADDR_TRAP 13 +#define K_INT_PERF_CNT 14 +#define K_INT_TRACE_FREEZE 15 +#define K_INT_BAD_ECC 16 +#define K_INT_COR_ECC 17 +#define K_INT_IO_BUS 18 +#define K_INT_MAC_0 19 +#define K_INT_MAC_1 20 +#define K_INT_MAC_2 21 +#define K_INT_DM_CH_0 22 +#define K_INT_DM_CH_1 23 +#define K_INT_DM_CH_2 24 +#define K_INT_DM_CH_3 25 +#define K_INT_MBOX_0 26 +#define K_INT_MBOX_1 27 +#define K_INT_MBOX_2 28 +#define K_INT_MBOX_3 29 +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define K_INT_CYCLE_CP0_INT 30 +#define K_INT_CYCLE_CP1_INT 31 +#endif /* 1250 PASS2 || 112x PASS1 */ +#define K_INT_GPIO_0 32 +#define K_INT_GPIO_1 33 +#define K_INT_GPIO_2 34 +#define K_INT_GPIO_3 35 +#define K_INT_GPIO_4 36 +#define K_INT_GPIO_5 37 +#define K_INT_GPIO_6 38 +#define K_INT_GPIO_7 39 +#define K_INT_GPIO_8 40 +#define K_INT_GPIO_9 41 +#define K_INT_GPIO_10 42 +#define K_INT_GPIO_11 43 +#define K_INT_GPIO_12 44 +#define K_INT_GPIO_13 45 +#define K_INT_GPIO_14 46 +#define K_INT_GPIO_15 47 +#define K_INT_LDT_FATAL 48 +#define K_INT_LDT_NONFATAL 49 +#define K_INT_LDT_SMI 50 +#define K_INT_LDT_NMI 51 +#define K_INT_LDT_INIT 52 +#define K_INT_LDT_STARTUP 53 +#define K_INT_LDT_EXT 54 +#define K_INT_PCI_ERROR 55 +#define K_INT_PCI_INTA 56 +#define K_INT_PCI_INTB 57 +#define K_INT_PCI_INTC 58 +#define K_INT_PCI_INTD 59 +#define K_INT_SPARE_2 60 +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define K_INT_MAC_0_CH1 61 +#define K_INT_MAC_1_CH1 62 +#define K_INT_MAC_2_CH1 63 +#endif /* 1250 PASS2 || 112x PASS1 */ + +/* + * Mask values for each interrupt + */ + +#define M_INT_WATCHDOG_TIMER_0 _SB_MAKEMASK1(K_INT_WATCHDOG_TIMER_0) +#define M_INT_WATCHDOG_TIMER_1 _SB_MAKEMASK1(K_INT_WATCHDOG_TIMER_1) +#define M_INT_TIMER_0 _SB_MAKEMASK1(K_INT_TIMER_0) +#define M_INT_TIMER_1 _SB_MAKEMASK1(K_INT_TIMER_1) +#define M_INT_TIMER_2 _SB_MAKEMASK1(K_INT_TIMER_2) +#define M_INT_TIMER_3 _SB_MAKEMASK1(K_INT_TIMER_3) +#define M_INT_SMB_0 _SB_MAKEMASK1(K_INT_SMB_0) +#define M_INT_SMB_1 _SB_MAKEMASK1(K_INT_SMB_1) +#define M_INT_UART_0 _SB_MAKEMASK1(K_INT_UART_0) +#define M_INT_UART_1 _SB_MAKEMASK1(K_INT_UART_1) +#define M_INT_SER_0 _SB_MAKEMASK1(K_INT_SER_0) +#define M_INT_SER_1 _SB_MAKEMASK1(K_INT_SER_1) +#define M_INT_PCMCIA _SB_MAKEMASK1(K_INT_PCMCIA) +#define M_INT_ADDR_TRAP _SB_MAKEMASK1(K_INT_ADDR_TRAP) +#define M_INT_PERF_CNT _SB_MAKEMASK1(K_INT_PERF_CNT) +#define M_INT_TRACE_FREEZE _SB_MAKEMASK1(K_INT_TRACE_FREEZE) +#define M_INT_BAD_ECC _SB_MAKEMASK1(K_INT_BAD_ECC) +#define M_INT_COR_ECC _SB_MAKEMASK1(K_INT_COR_ECC) +#define M_INT_IO_BUS _SB_MAKEMASK1(K_INT_IO_BUS) +#define M_INT_MAC_0 _SB_MAKEMASK1(K_INT_MAC_0) +#define M_INT_MAC_1 _SB_MAKEMASK1(K_INT_MAC_1) +#define M_INT_MAC_2 _SB_MAKEMASK1(K_INT_MAC_2) +#define M_INT_DM_CH_0 _SB_MAKEMASK1(K_INT_DM_CH_0) +#define M_INT_DM_CH_1 _SB_MAKEMASK1(K_INT_DM_CH_1) +#define M_INT_DM_CH_2 _SB_MAKEMASK1(K_INT_DM_CH_2) +#define M_INT_DM_CH_3 _SB_MAKEMASK1(K_INT_DM_CH_3) +#define M_INT_MBOX_0 _SB_MAKEMASK1(K_INT_MBOX_0) +#define M_INT_MBOX_1 _SB_MAKEMASK1(K_INT_MBOX_1) +#define M_INT_MBOX_2 _SB_MAKEMASK1(K_INT_MBOX_2) +#define M_INT_MBOX_3 _SB_MAKEMASK1(K_INT_MBOX_3) +#define M_INT_MBOX_ALL _SB_MAKEMASK(4, K_INT_MBOX_0) +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define M_INT_CYCLE_CP0_INT _SB_MAKEMASK1(K_INT_CYCLE_CP0_INT) +#define M_INT_CYCLE_CP1_INT _SB_MAKEMASK1(K_INT_CYCLE_CP1_INT) +#endif /* 1250 PASS2 || 112x PASS1 */ +#define M_INT_GPIO_0 _SB_MAKEMASK1(K_INT_GPIO_0) +#define M_INT_GPIO_1 _SB_MAKEMASK1(K_INT_GPIO_1) +#define M_INT_GPIO_2 _SB_MAKEMASK1(K_INT_GPIO_2) +#define M_INT_GPIO_3 _SB_MAKEMASK1(K_INT_GPIO_3) +#define M_INT_GPIO_4 _SB_MAKEMASK1(K_INT_GPIO_4) +#define M_INT_GPIO_5 _SB_MAKEMASK1(K_INT_GPIO_5) +#define M_INT_GPIO_6 _SB_MAKEMASK1(K_INT_GPIO_6) +#define M_INT_GPIO_7 _SB_MAKEMASK1(K_INT_GPIO_7) +#define M_INT_GPIO_8 _SB_MAKEMASK1(K_INT_GPIO_8) +#define M_INT_GPIO_9 _SB_MAKEMASK1(K_INT_GPIO_9) +#define M_INT_GPIO_10 _SB_MAKEMASK1(K_INT_GPIO_10) +#define M_INT_GPIO_11 _SB_MAKEMASK1(K_INT_GPIO_11) +#define M_INT_GPIO_12 _SB_MAKEMASK1(K_INT_GPIO_12) +#define M_INT_GPIO_13 _SB_MAKEMASK1(K_INT_GPIO_13) +#define M_INT_GPIO_14 _SB_MAKEMASK1(K_INT_GPIO_14) +#define M_INT_GPIO_15 _SB_MAKEMASK1(K_INT_GPIO_15) +#define M_INT_LDT_FATAL _SB_MAKEMASK1(K_INT_LDT_FATAL) +#define M_INT_LDT_NONFATAL _SB_MAKEMASK1(K_INT_LDT_NONFATAL) +#define M_INT_LDT_SMI _SB_MAKEMASK1(K_INT_LDT_SMI) +#define M_INT_LDT_NMI _SB_MAKEMASK1(K_INT_LDT_NMI) +#define M_INT_LDT_INIT _SB_MAKEMASK1(K_INT_LDT_INIT) +#define M_INT_LDT_STARTUP _SB_MAKEMASK1(K_INT_LDT_STARTUP) +#define M_INT_LDT_EXT _SB_MAKEMASK1(K_INT_LDT_EXT) +#define M_INT_PCI_ERROR _SB_MAKEMASK1(K_INT_PCI_ERROR) +#define M_INT_PCI_INTA _SB_MAKEMASK1(K_INT_PCI_INTA) +#define M_INT_PCI_INTB _SB_MAKEMASK1(K_INT_PCI_INTB) +#define M_INT_PCI_INTC _SB_MAKEMASK1(K_INT_PCI_INTC) +#define M_INT_PCI_INTD _SB_MAKEMASK1(K_INT_PCI_INTD) +#define M_INT_SPARE_2 _SB_MAKEMASK1(K_INT_SPARE_2) +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define M_INT_MAC_0_CH1 _SB_MAKEMASK1(K_INT_MAC_0_CH1) +#define M_INT_MAC_1_CH1 _SB_MAKEMASK1(K_INT_MAC_1_CH1) +#define M_INT_MAC_2_CH1 _SB_MAKEMASK1(K_INT_MAC_2_CH1) +#endif /* 1250 PASS2 || 112x PASS1 */ + +/* + * Interrupt mappings + */ + +#define K_INT_MAP_I0 0 /* interrupt pins on processor */ +#define K_INT_MAP_I1 1 +#define K_INT_MAP_I2 2 +#define K_INT_MAP_I3 3 +#define K_INT_MAP_I4 4 +#define K_INT_MAP_I5 5 +#define K_INT_MAP_NMI 6 /* nonmaskable */ +#define K_INT_MAP_DINT 7 /* debug interrupt */ + +/* + * LDT Interrupt Set Register (table 4-5) + */ + +#define S_INT_LDT_INTMSG 0 +#define M_INT_LDT_INTMSG _SB_MAKEMASK(3, S_INT_LDT_INTMSG) +#define V_INT_LDT_INTMSG(x) _SB_MAKEVALUE(x, S_INT_LDT_INTMSG) +#define G_INT_LDT_INTMSG(x) _SB_GETVALUE(x, S_INT_LDT_INTMSG, M_INT_LDT_INTMSG) + +#define K_INT_LDT_INTMSG_FIXED 0 +#define K_INT_LDT_INTMSG_ARBITRATED 1 +#define K_INT_LDT_INTMSG_SMI 2 +#define K_INT_LDT_INTMSG_NMI 3 +#define K_INT_LDT_INTMSG_INIT 4 +#define K_INT_LDT_INTMSG_STARTUP 5 +#define K_INT_LDT_INTMSG_EXTINT 6 +#define K_INT_LDT_INTMSG_RESERVED 7 + +#define M_INT_LDT_EDGETRIGGER 0 +#define M_INT_LDT_LEVELTRIGGER _SB_MAKEMASK1(3) + +#define M_INT_LDT_PHYSICALDEST 0 +#define M_INT_LDT_LOGICALDEST _SB_MAKEMASK1(4) + +#define S_INT_LDT_INTDEST 5 +#define M_INT_LDT_INTDEST _SB_MAKEMASK(10, S_INT_LDT_INTDEST) +#define V_INT_LDT_INTDEST(x) _SB_MAKEVALUE(x, S_INT_LDT_INTDEST) +#define G_INT_LDT_INTDEST(x) _SB_GETVALUE(x, S_INT_LDT_INTDEST, M_INT_LDT_INTDEST) + +#define S_INT_LDT_VECTOR 13 +#define M_INT_LDT_VECTOR _SB_MAKEMASK(8, S_INT_LDT_VECTOR) +#define V_INT_LDT_VECTOR(x) _SB_MAKEVALUE(x, S_INT_LDT_VECTOR) +#define G_INT_LDT_VECTOR(x) _SB_GETVALUE(x, S_INT_LDT_VECTOR, M_INT_LDT_VECTOR) + +/* + * Vector format (Table 4-6) + */ + +#define M_LDTVECT_RAISEINT 0x00 +#define M_LDTVECT_RAISEMBOX 0x40 + + +#endif /* 1250/112x */ diff --git a/arch/mips/include/asm/sibyte/sb1250_l2c.h b/arch/mips/include/asm/sibyte/sb1250_l2c.h new file mode 100644 index 00000000000..6554dcf05cf --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_l2c.h @@ -0,0 +1,131 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * L2 Cache constants and macros File: sb1250_l2c.h + * + * This module contains constants useful for manipulating the + * level 2 cache. + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_L2C_H +#define _SB1250_L2C_H + +#include "sb1250_defs.h" + +/* + * Level 2 Cache Tag register (Table 5-3) + */ + +#define S_L2C_TAG_MBZ 0 +#define M_L2C_TAG_MBZ _SB_MAKEMASK(5, S_L2C_TAG_MBZ) + +#define S_L2C_TAG_INDEX 5 +#define M_L2C_TAG_INDEX _SB_MAKEMASK(12, S_L2C_TAG_INDEX) +#define V_L2C_TAG_INDEX(x) _SB_MAKEVALUE(x, S_L2C_TAG_INDEX) +#define G_L2C_TAG_INDEX(x) _SB_GETVALUE(x, S_L2C_TAG_INDEX, M_L2C_TAG_INDEX) + +#define S_L2C_TAG_TAG 17 +#define M_L2C_TAG_TAG _SB_MAKEMASK(23, S_L2C_TAG_TAG) +#define V_L2C_TAG_TAG(x) _SB_MAKEVALUE(x, S_L2C_TAG_TAG) +#define G_L2C_TAG_TAG(x) _SB_GETVALUE(x, S_L2C_TAG_TAG, M_L2C_TAG_TAG) + +#define S_L2C_TAG_ECC 40 +#define M_L2C_TAG_ECC _SB_MAKEMASK(6, S_L2C_TAG_ECC) +#define V_L2C_TAG_ECC(x) _SB_MAKEVALUE(x, S_L2C_TAG_ECC) +#define G_L2C_TAG_ECC(x) _SB_GETVALUE(x, S_L2C_TAG_ECC, M_L2C_TAG_ECC) + +#define S_L2C_TAG_WAY 46 +#define M_L2C_TAG_WAY _SB_MAKEMASK(2, S_L2C_TAG_WAY) +#define V_L2C_TAG_WAY(x) _SB_MAKEVALUE(x, S_L2C_TAG_WAY) +#define G_L2C_TAG_WAY(x) _SB_GETVALUE(x, S_L2C_TAG_WAY, M_L2C_TAG_WAY) + +#define M_L2C_TAG_DIRTY _SB_MAKEMASK1(48) +#define M_L2C_TAG_VALID _SB_MAKEMASK1(49) + +/* + * Format of level 2 cache management address (table 5-2) + */ + +#define S_L2C_MGMT_INDEX 5 +#define M_L2C_MGMT_INDEX _SB_MAKEMASK(12, S_L2C_MGMT_INDEX) +#define V_L2C_MGMT_INDEX(x) _SB_MAKEVALUE(x, S_L2C_MGMT_INDEX) +#define G_L2C_MGMT_INDEX(x) _SB_GETVALUE(x, S_L2C_MGMT_INDEX, M_L2C_MGMT_INDEX) + +#define S_L2C_MGMT_QUADRANT 15 +#define M_L2C_MGMT_QUADRANT _SB_MAKEMASK(2, S_L2C_MGMT_QUADRANT) +#define V_L2C_MGMT_QUADRANT(x) _SB_MAKEVALUE(x, S_L2C_MGMT_QUADRANT) +#define G_L2C_MGMT_QUADRANT(x) _SB_GETVALUE(x, S_L2C_MGMT_QUADRANT, M_L2C_MGMT_QUADRANT) + +#define S_L2C_MGMT_HALF 16 +#define M_L2C_MGMT_HALF _SB_MAKEMASK(1, S_L2C_MGMT_HALF) + +#define S_L2C_MGMT_WAY 17 +#define M_L2C_MGMT_WAY _SB_MAKEMASK(2, S_L2C_MGMT_WAY) +#define V_L2C_MGMT_WAY(x) _SB_MAKEVALUE(x, S_L2C_MGMT_WAY) +#define G_L2C_MGMT_WAY(x) _SB_GETVALUE(x, S_L2C_MGMT_WAY, M_L2C_MGMT_WAY) + +#define S_L2C_MGMT_ECC_DIAG 21 +#define M_L2C_MGMT_ECC_DIAG _SB_MAKEMASK(2, S_L2C_MGMT_ECC_DIAG) +#define V_L2C_MGMT_ECC_DIAG(x) _SB_MAKEVALUE(x, S_L2C_MGMT_ECC_DIAG) +#define G_L2C_MGMT_ECC_DIAG(x) _SB_GETVALUE(x, S_L2C_MGMT_ECC_DIAG, M_L2C_MGMT_ECC_DIAG) + +#define S_L2C_MGMT_TAG 23 +#define M_L2C_MGMT_TAG _SB_MAKEMASK(4, S_L2C_MGMT_TAG) +#define V_L2C_MGMT_TAG(x) _SB_MAKEVALUE(x, S_L2C_MGMT_TAG) +#define G_L2C_MGMT_TAG(x) _SB_GETVALUE(x, S_L2C_MGMT_TAG, M_L2C_MGMT_TAG) + +#define M_L2C_MGMT_DIRTY _SB_MAKEMASK1(19) +#define M_L2C_MGMT_VALID _SB_MAKEMASK1(20) + +#define A_L2C_MGMT_TAG_BASE 0x00D0000000 + +#define L2C_ENTRIES_PER_WAY 4096 +#define L2C_NUM_WAYS 4 + + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +/* + * L2 Read Misc. register (A_L2_READ_MISC) + */ +#define S_L2C_MISC_NO_WAY 10 +#define M_L2C_MISC_NO_WAY _SB_MAKEMASK(4, S_L2C_MISC_NO_WAY) +#define V_L2C_MISC_NO_WAY(x) _SB_MAKEVALUE(x, S_L2C_MISC_NO_WAY) +#define G_L2C_MISC_NO_WAY(x) _SB_GETVALUE(x, S_L2C_MISC_NO_WAY, M_L2C_MISC_NO_WAY) + +#define M_L2C_MISC_ECC_CLEANUP_DIS _SB_MAKEMASK1(9) +#define M_L2C_MISC_MC_PRIO_LOW _SB_MAKEMASK1(8) +#define M_L2C_MISC_SOFT_DISABLE_T _SB_MAKEMASK1(7) +#define M_L2C_MISC_SOFT_DISABLE_B _SB_MAKEMASK1(6) +#define M_L2C_MISC_SOFT_DISABLE_R _SB_MAKEMASK1(5) +#define M_L2C_MISC_SOFT_DISABLE_L _SB_MAKEMASK1(4) +#define M_L2C_MISC_SCACHE_DISABLE_T _SB_MAKEMASK1(3) +#define M_L2C_MISC_SCACHE_DISABLE_B _SB_MAKEMASK1(2) +#define M_L2C_MISC_SCACHE_DISABLE_R _SB_MAKEMASK1(1) +#define M_L2C_MISC_SCACHE_DISABLE_L _SB_MAKEMASK1(0) +#endif /* 1250 PASS3 || 112x PASS1 */ + + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_ldt.h b/arch/mips/include/asm/sibyte/sb1250_ldt.h new file mode 100644 index 00000000000..081e8b1c4ad --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_ldt.h @@ -0,0 +1,423 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * LDT constants File: sb1250_ldt.h + * + * This module contains constants and macros to describe + * the LDT interface on the SB1250. + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000, 2001, 2002, 2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_LDT_H +#define _SB1250_LDT_H + +#include "sb1250_defs.h" + +#define K_LDT_VENDOR_SIBYTE 0x166D +#define K_LDT_DEVICE_SB1250 0x0002 + +/* + * LDT Interface Type 1 (bridge) configuration header + */ + +#define R_LDT_TYPE1_DEVICEID 0x0000 +#define R_LDT_TYPE1_CMDSTATUS 0x0004 +#define R_LDT_TYPE1_CLASSREV 0x0008 +#define R_LDT_TYPE1_DEVHDR 0x000C +#define R_LDT_TYPE1_BAR0 0x0010 /* not used */ +#define R_LDT_TYPE1_BAR1 0x0014 /* not used */ + +#define R_LDT_TYPE1_BUSID 0x0018 /* bus ID register */ +#define R_LDT_TYPE1_SECSTATUS 0x001C /* secondary status / I/O base/limit */ +#define R_LDT_TYPE1_MEMLIMIT 0x0020 +#define R_LDT_TYPE1_PREFETCH 0x0024 +#define R_LDT_TYPE1_PREF_BASE 0x0028 +#define R_LDT_TYPE1_PREF_LIMIT 0x002C +#define R_LDT_TYPE1_IOLIMIT 0x0030 +#define R_LDT_TYPE1_CAPPTR 0x0034 +#define R_LDT_TYPE1_ROMADDR 0x0038 +#define R_LDT_TYPE1_BRCTL 0x003C +#define R_LDT_TYPE1_CMD 0x0040 +#define R_LDT_TYPE1_LINKCTRL 0x0044 +#define R_LDT_TYPE1_LINKFREQ 0x0048 +#define R_LDT_TYPE1_RESERVED1 0x004C +#define R_LDT_TYPE1_SRICMD 0x0050 +#define R_LDT_TYPE1_SRITXNUM 0x0054 +#define R_LDT_TYPE1_SRIRXNUM 0x0058 +#define R_LDT_TYPE1_ERRSTATUS 0x0068 +#define R_LDT_TYPE1_SRICTRL 0x006C +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define R_LDT_TYPE1_ADDSTATUS 0x0070 +#endif /* 1250 PASS2 || 112x PASS1 */ +#define R_LDT_TYPE1_TXBUFCNT 0x00C8 +#define R_LDT_TYPE1_EXPCRC 0x00DC +#define R_LDT_TYPE1_RXCRC 0x00F0 + + +/* + * LDT Device ID register + */ + +#define S_LDT_DEVICEID_VENDOR 0 +#define M_LDT_DEVICEID_VENDOR _SB_MAKEMASK_32(16, S_LDT_DEVICEID_VENDOR) +#define V_LDT_DEVICEID_VENDOR(x) _SB_MAKEVALUE_32(x, S_LDT_DEVICEID_VENDOR) +#define G_LDT_DEVICEID_VENDOR(x) _SB_GETVALUE_32(x, S_LDT_DEVICEID_VENDOR, M_LDT_DEVICEID_VENDOR) + +#define S_LDT_DEVICEID_DEVICEID 16 +#define M_LDT_DEVICEID_DEVICEID _SB_MAKEMASK_32(16, S_LDT_DEVICEID_DEVICEID) +#define V_LDT_DEVICEID_DEVICEID(x) _SB_MAKEVALUE_32(x, S_LDT_DEVICEID_DEVICEID) +#define G_LDT_DEVICEID_DEVICEID(x) _SB_GETVALUE_32(x, S_LDT_DEVICEID_DEVICEID, M_LDT_DEVICEID_DEVICEID) + + +/* + * LDT Command Register (Table 8-13) + */ + +#define M_LDT_CMD_IOSPACE_EN _SB_MAKEMASK1_32(0) +#define M_LDT_CMD_MEMSPACE_EN _SB_MAKEMASK1_32(1) +#define M_LDT_CMD_MASTER_EN _SB_MAKEMASK1_32(2) +#define M_LDT_CMD_SPECCYC_EN _SB_MAKEMASK1_32(3) +#define M_LDT_CMD_MEMWRINV_EN _SB_MAKEMASK1_32(4) +#define M_LDT_CMD_VGAPALSNP_EN _SB_MAKEMASK1_32(5) +#define M_LDT_CMD_PARERRRESP _SB_MAKEMASK1_32(6) +#define M_LDT_CMD_WAITCYCCTRL _SB_MAKEMASK1_32(7) +#define M_LDT_CMD_SERR_EN _SB_MAKEMASK1_32(8) +#define M_LDT_CMD_FASTB2B_EN _SB_MAKEMASK1_32(9) + +/* + * LDT class and revision registers + */ + +#define S_LDT_CLASSREV_REV 0 +#define M_LDT_CLASSREV_REV _SB_MAKEMASK_32(8, S_LDT_CLASSREV_REV) +#define V_LDT_CLASSREV_REV(x) _SB_MAKEVALUE_32(x, S_LDT_CLASSREV_REV) +#define G_LDT_CLASSREV_REV(x) _SB_GETVALUE_32(x, S_LDT_CLASSREV_REV, M_LDT_CLASSREV_REV) + +#define S_LDT_CLASSREV_CLASS 8 +#define M_LDT_CLASSREV_CLASS _SB_MAKEMASK_32(24, S_LDT_CLASSREV_CLASS) +#define V_LDT_CLASSREV_CLASS(x) _SB_MAKEVALUE_32(x, S_LDT_CLASSREV_CLASS) +#define G_LDT_CLASSREV_CLASS(x) _SB_GETVALUE_32(x, S_LDT_CLASSREV_CLASS, M_LDT_CLASSREV_CLASS) + +#define K_LDT_REV 0x01 +#define K_LDT_CLASS 0x060000 + +/* + * Device Header (offset 0x0C) + */ + +#define S_LDT_DEVHDR_CLINESZ 0 +#define M_LDT_DEVHDR_CLINESZ _SB_MAKEMASK_32(8, S_LDT_DEVHDR_CLINESZ) +#define V_LDT_DEVHDR_CLINESZ(x) _SB_MAKEVALUE_32(x, S_LDT_DEVHDR_CLINESZ) +#define G_LDT_DEVHDR_CLINESZ(x) _SB_GETVALUE_32(x, S_LDT_DEVHDR_CLINESZ, M_LDT_DEVHDR_CLINESZ) + +#define S_LDT_DEVHDR_LATTMR 8 +#define M_LDT_DEVHDR_LATTMR _SB_MAKEMASK_32(8, S_LDT_DEVHDR_LATTMR) +#define V_LDT_DEVHDR_LATTMR(x) _SB_MAKEVALUE_32(x, S_LDT_DEVHDR_LATTMR) +#define G_LDT_DEVHDR_LATTMR(x) _SB_GETVALUE_32(x, S_LDT_DEVHDR_LATTMR, M_LDT_DEVHDR_LATTMR) + +#define S_LDT_DEVHDR_HDRTYPE 16 +#define M_LDT_DEVHDR_HDRTYPE _SB_MAKEMASK_32(8, S_LDT_DEVHDR_HDRTYPE) +#define V_LDT_DEVHDR_HDRTYPE(x) _SB_MAKEVALUE_32(x, S_LDT_DEVHDR_HDRTYPE) +#define G_LDT_DEVHDR_HDRTYPE(x) _SB_GETVALUE_32(x, S_LDT_DEVHDR_HDRTYPE, M_LDT_DEVHDR_HDRTYPE) + +#define K_LDT_DEVHDR_HDRTYPE_TYPE1 1 + +#define S_LDT_DEVHDR_BIST 24 +#define M_LDT_DEVHDR_BIST _SB_MAKEMASK_32(8, S_LDT_DEVHDR_BIST) +#define V_LDT_DEVHDR_BIST(x) _SB_MAKEVALUE_32(x, S_LDT_DEVHDR_BIST) +#define G_LDT_DEVHDR_BIST(x) _SB_GETVALUE_32(x, S_LDT_DEVHDR_BIST, M_LDT_DEVHDR_BIST) + + + +/* + * LDT Status Register (Table 8-14). Note that these constants + * assume you've read the command and status register + * together (32-bit read at offset 0x04) + * + * These bits also apply to the secondary status + * register (Table 8-15), offset 0x1C + */ + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define M_LDT_STATUS_VGAEN _SB_MAKEMASK1_32(3) +#endif /* 1250 PASS2 || 112x PASS1 */ +#define M_LDT_STATUS_CAPLIST _SB_MAKEMASK1_32(20) +#define M_LDT_STATUS_66MHZCAP _SB_MAKEMASK1_32(21) +#define M_LDT_STATUS_RESERVED2 _SB_MAKEMASK1_32(22) +#define M_LDT_STATUS_FASTB2BCAP _SB_MAKEMASK1_32(23) +#define M_LDT_STATUS_MSTRDPARERR _SB_MAKEMASK1_32(24) + +#define S_LDT_STATUS_DEVSELTIMING 25 +#define M_LDT_STATUS_DEVSELTIMING _SB_MAKEMASK_32(2, S_LDT_STATUS_DEVSELTIMING) +#define V_LDT_STATUS_DEVSELTIMING(x) _SB_MAKEVALUE_32(x, S_LDT_STATUS_DEVSELTIMING) +#define G_LDT_STATUS_DEVSELTIMING(x) _SB_GETVALUE_32(x, S_LDT_STATUS_DEVSELTIMING, M_LDT_STATUS_DEVSELTIMING) + +#define M_LDT_STATUS_SIGDTGTABORT _SB_MAKEMASK1_32(27) +#define M_LDT_STATUS_RCVDTGTABORT _SB_MAKEMASK1_32(28) +#define M_LDT_STATUS_RCVDMSTRABORT _SB_MAKEMASK1_32(29) +#define M_LDT_STATUS_SIGDSERR _SB_MAKEMASK1_32(30) +#define M_LDT_STATUS_DETPARERR _SB_MAKEMASK1_32(31) + +/* + * Bridge Control Register (Table 8-16). Note that these + * constants assume you've read the register as a 32-bit + * read (offset 0x3C) + */ + +#define M_LDT_BRCTL_PARERRRESP_EN _SB_MAKEMASK1_32(16) +#define M_LDT_BRCTL_SERR_EN _SB_MAKEMASK1_32(17) +#define M_LDT_BRCTL_ISA_EN _SB_MAKEMASK1_32(18) +#define M_LDT_BRCTL_VGA_EN _SB_MAKEMASK1_32(19) +#define M_LDT_BRCTL_MSTRABORTMODE _SB_MAKEMASK1_32(21) +#define M_LDT_BRCTL_SECBUSRESET _SB_MAKEMASK1_32(22) +#define M_LDT_BRCTL_FASTB2B_EN _SB_MAKEMASK1_32(23) +#define M_LDT_BRCTL_PRIDISCARD _SB_MAKEMASK1_32(24) +#define M_LDT_BRCTL_SECDISCARD _SB_MAKEMASK1_32(25) +#define M_LDT_BRCTL_DISCARDSTAT _SB_MAKEMASK1_32(26) +#define M_LDT_BRCTL_DISCARDSERR_EN _SB_MAKEMASK1_32(27) + +/* + * LDT Command Register (Table 8-17). Note that these constants + * assume you've read the command and status register together + * 32-bit read at offset 0x40 + */ + +#define M_LDT_CMD_WARMRESET _SB_MAKEMASK1_32(16) +#define M_LDT_CMD_DOUBLEENDED _SB_MAKEMASK1_32(17) + +#define S_LDT_CMD_CAPTYPE 29 +#define M_LDT_CMD_CAPTYPE _SB_MAKEMASK_32(3, S_LDT_CMD_CAPTYPE) +#define V_LDT_CMD_CAPTYPE(x) _SB_MAKEVALUE_32(x, S_LDT_CMD_CAPTYPE) +#define G_LDT_CMD_CAPTYPE(x) _SB_GETVALUE_32(x, S_LDT_CMD_CAPTYPE, M_LDT_CMD_CAPTYPE) + +/* + * LDT link control register (Table 8-18), and (Table 8-19) + */ + +#define M_LDT_LINKCTRL_CAPSYNCFLOOD_EN _SB_MAKEMASK1_32(1) +#define M_LDT_LINKCTRL_CRCSTARTTEST _SB_MAKEMASK1_32(2) +#define M_LDT_LINKCTRL_CRCFORCEERR _SB_MAKEMASK1_32(3) +#define M_LDT_LINKCTRL_LINKFAIL _SB_MAKEMASK1_32(4) +#define M_LDT_LINKCTRL_INITDONE _SB_MAKEMASK1_32(5) +#define M_LDT_LINKCTRL_EOC _SB_MAKEMASK1_32(6) +#define M_LDT_LINKCTRL_XMITOFF _SB_MAKEMASK1_32(7) + +#define S_LDT_LINKCTRL_CRCERR 8 +#define M_LDT_LINKCTRL_CRCERR _SB_MAKEMASK_32(4, S_LDT_LINKCTRL_CRCERR) +#define V_LDT_LINKCTRL_CRCERR(x) _SB_MAKEVALUE_32(x, S_LDT_LINKCTRL_CRCERR) +#define G_LDT_LINKCTRL_CRCERR(x) _SB_GETVALUE_32(x, S_LDT_LINKCTRL_CRCERR, M_LDT_LINKCTRL_CRCERR) + +#define S_LDT_LINKCTRL_MAXIN 16 +#define M_LDT_LINKCTRL_MAXIN _SB_MAKEMASK_32(3, S_LDT_LINKCTRL_MAXIN) +#define V_LDT_LINKCTRL_MAXIN(x) _SB_MAKEVALUE_32(x, S_LDT_LINKCTRL_MAXIN) +#define G_LDT_LINKCTRL_MAXIN(x) _SB_GETVALUE_32(x, S_LDT_LINKCTRL_MAXIN, M_LDT_LINKCTRL_MAXIN) + +#define M_LDT_LINKCTRL_DWFCLN _SB_MAKEMASK1_32(19) + +#define S_LDT_LINKCTRL_MAXOUT 20 +#define M_LDT_LINKCTRL_MAXOUT _SB_MAKEMASK_32(3, S_LDT_LINKCTRL_MAXOUT) +#define V_LDT_LINKCTRL_MAXOUT(x) _SB_MAKEVALUE_32(x, S_LDT_LINKCTRL_MAXOUT) +#define G_LDT_LINKCTRL_MAXOUT(x) _SB_GETVALUE_32(x, S_LDT_LINKCTRL_MAXOUT, M_LDT_LINKCTRL_MAXOUT) + +#define M_LDT_LINKCTRL_DWFCOUT _SB_MAKEMASK1_32(23) + +#define S_LDT_LINKCTRL_WIDTHIN 24 +#define M_LDT_LINKCTRL_WIDTHIN _SB_MAKEMASK_32(3, S_LDT_LINKCTRL_WIDTHIN) +#define V_LDT_LINKCTRL_WIDTHIN(x) _SB_MAKEVALUE_32(x, S_LDT_LINKCTRL_WIDTHIN) +#define G_LDT_LINKCTRL_WIDTHIN(x) _SB_GETVALUE_32(x, S_LDT_LINKCTRL_WIDTHIN, M_LDT_LINKCTRL_WIDTHIN) + +#define M_LDT_LINKCTRL_DWFCLIN_EN _SB_MAKEMASK1_32(27) + +#define S_LDT_LINKCTRL_WIDTHOUT 28 +#define M_LDT_LINKCTRL_WIDTHOUT _SB_MAKEMASK_32(3, S_LDT_LINKCTRL_WIDTHOUT) +#define V_LDT_LINKCTRL_WIDTHOUT(x) _SB_MAKEVALUE_32(x, S_LDT_LINKCTRL_WIDTHOUT) +#define G_LDT_LINKCTRL_WIDTHOUT(x) _SB_GETVALUE_32(x, S_LDT_LINKCTRL_WIDTHOUT, M_LDT_LINKCTRL_WIDTHOUT) + +#define M_LDT_LINKCTRL_DWFCOUT_EN _SB_MAKEMASK1_32(31) + +/* + * LDT Link frequency register (Table 8-20) offset 0x48 + */ + +#define S_LDT_LINKFREQ_FREQ 8 +#define M_LDT_LINKFREQ_FREQ _SB_MAKEMASK_32(4, S_LDT_LINKFREQ_FREQ) +#define V_LDT_LINKFREQ_FREQ(x) _SB_MAKEVALUE_32(x, S_LDT_LINKFREQ_FREQ) +#define G_LDT_LINKFREQ_FREQ(x) _SB_GETVALUE_32(x, S_LDT_LINKFREQ_FREQ, M_LDT_LINKFREQ_FREQ) + +#define K_LDT_LINKFREQ_200MHZ 0 +#define K_LDT_LINKFREQ_300MHZ 1 +#define K_LDT_LINKFREQ_400MHZ 2 +#define K_LDT_LINKFREQ_500MHZ 3 +#define K_LDT_LINKFREQ_600MHZ 4 +#define K_LDT_LINKFREQ_800MHZ 5 +#define K_LDT_LINKFREQ_1000MHZ 6 + +/* + * LDT SRI Command Register (Table 8-21). Note that these constants + * assume you've read the command and status register together + * 32-bit read at offset 0x50 + */ + +#define M_LDT_SRICMD_SIPREADY _SB_MAKEMASK1_32(16) +#define M_LDT_SRICMD_SYNCPTRCTL _SB_MAKEMASK1_32(17) +#define M_LDT_SRICMD_REDUCESYNCZERO _SB_MAKEMASK1_32(18) +#if SIBYTE_HDR_FEATURE_UP_TO(1250, PASS1) +#define M_LDT_SRICMD_DISSTARVATIONCNT _SB_MAKEMASK1_32(19) /* PASS1 */ +#endif /* up to 1250 PASS1 */ +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define M_LDT_SRICMD_DISMULTTXVLD _SB_MAKEMASK1_32(19) +#define M_LDT_SRICMD_EXPENDIAN _SB_MAKEMASK1_32(26) +#endif /* 1250 PASS2 || 112x PASS1 */ + + +#define S_LDT_SRICMD_RXMARGIN 20 +#define M_LDT_SRICMD_RXMARGIN _SB_MAKEMASK_32(5, S_LDT_SRICMD_RXMARGIN) +#define V_LDT_SRICMD_RXMARGIN(x) _SB_MAKEVALUE_32(x, S_LDT_SRICMD_RXMARGIN) +#define G_LDT_SRICMD_RXMARGIN(x) _SB_GETVALUE_32(x, S_LDT_SRICMD_RXMARGIN, M_LDT_SRICMD_RXMARGIN) + +#define M_LDT_SRICMD_LDTPLLCOMPAT _SB_MAKEMASK1_32(25) + +#define S_LDT_SRICMD_TXINITIALOFFSET 28 +#define M_LDT_SRICMD_TXINITIALOFFSET _SB_MAKEMASK_32(3, S_LDT_SRICMD_TXINITIALOFFSET) +#define V_LDT_SRICMD_TXINITIALOFFSET(x) _SB_MAKEVALUE_32(x, S_LDT_SRICMD_TXINITIALOFFSET) +#define G_LDT_SRICMD_TXINITIALOFFSET(x) _SB_GETVALUE_32(x, S_LDT_SRICMD_TXINITIALOFFSET, M_LDT_SRICMD_TXINITIALOFFSET) + +#define M_LDT_SRICMD_LINKFREQDIRECT _SB_MAKEMASK1_32(31) + +/* + * LDT Error control and status register (Table 8-22) (Table 8-23) + */ + +#define M_LDT_ERRCTL_PROTFATAL_EN _SB_MAKEMASK1_32(0) +#define M_LDT_ERRCTL_PROTNONFATAL_EN _SB_MAKEMASK1_32(1) +#define M_LDT_ERRCTL_PROTSYNCFLOOD_EN _SB_MAKEMASK1_32(2) +#define M_LDT_ERRCTL_OVFFATAL_EN _SB_MAKEMASK1_32(3) +#define M_LDT_ERRCTL_OVFNONFATAL_EN _SB_MAKEMASK1_32(4) +#define M_LDT_ERRCTL_OVFSYNCFLOOD_EN _SB_MAKEMASK1_32(5) +#define M_LDT_ERRCTL_EOCNXAFATAL_EN _SB_MAKEMASK1_32(6) +#define M_LDT_ERRCTL_EOCNXANONFATAL_EN _SB_MAKEMASK1_32(7) +#define M_LDT_ERRCTL_EOCNXASYNCFLOOD_EN _SB_MAKEMASK1_32(8) +#define M_LDT_ERRCTL_CRCFATAL_EN _SB_MAKEMASK1_32(9) +#define M_LDT_ERRCTL_CRCNONFATAL_EN _SB_MAKEMASK1_32(10) +#define M_LDT_ERRCTL_SERRFATAL_EN _SB_MAKEMASK1_32(11) +#define M_LDT_ERRCTL_SRCTAGFATAL_EN _SB_MAKEMASK1_32(12) +#define M_LDT_ERRCTL_SRCTAGNONFATAL_EN _SB_MAKEMASK1_32(13) +#define M_LDT_ERRCTL_SRCTAGSYNCFLOOD_EN _SB_MAKEMASK1_32(14) +#define M_LDT_ERRCTL_MAPNXAFATAL_EN _SB_MAKEMASK1_32(15) +#define M_LDT_ERRCTL_MAPNXANONFATAL_EN _SB_MAKEMASK1_32(16) +#define M_LDT_ERRCTL_MAPNXASYNCFLOOD_EN _SB_MAKEMASK1_32(17) + +#define M_LDT_ERRCTL_PROTOERR _SB_MAKEMASK1_32(24) +#define M_LDT_ERRCTL_OVFERR _SB_MAKEMASK1_32(25) +#define M_LDT_ERRCTL_EOCNXAERR _SB_MAKEMASK1_32(26) +#define M_LDT_ERRCTL_SRCTAGERR _SB_MAKEMASK1_32(27) +#define M_LDT_ERRCTL_MAPNXAERR _SB_MAKEMASK1_32(28) + +/* + * SRI Control register (Table 8-24, 8-25) Offset 0x6C + */ + +#define S_LDT_SRICTRL_NEEDRESP 0 +#define M_LDT_SRICTRL_NEEDRESP _SB_MAKEMASK_32(2, S_LDT_SRICTRL_NEEDRESP) +#define V_LDT_SRICTRL_NEEDRESP(x) _SB_MAKEVALUE_32(x, S_LDT_SRICTRL_NEEDRESP) +#define G_LDT_SRICTRL_NEEDRESP(x) _SB_GETVALUE_32(x, S_LDT_SRICTRL_NEEDRESP, M_LDT_SRICTRL_NEEDRESP) + +#define S_LDT_SRICTRL_NEEDNPREQ 2 +#define M_LDT_SRICTRL_NEEDNPREQ _SB_MAKEMASK_32(2, S_LDT_SRICTRL_NEEDNPREQ) +#define V_LDT_SRICTRL_NEEDNPREQ(x) _SB_MAKEVALUE_32(x, S_LDT_SRICTRL_NEEDNPREQ) +#define G_LDT_SRICTRL_NEEDNPREQ(x) _SB_GETVALUE_32(x, S_LDT_SRICTRL_NEEDNPREQ, M_LDT_SRICTRL_NEEDNPREQ) + +#define S_LDT_SRICTRL_NEEDPREQ 4 +#define M_LDT_SRICTRL_NEEDPREQ _SB_MAKEMASK_32(2, S_LDT_SRICTRL_NEEDPREQ) +#define V_LDT_SRICTRL_NEEDPREQ(x) _SB_MAKEVALUE_32(x, S_LDT_SRICTRL_NEEDPREQ) +#define G_LDT_SRICTRL_NEEDPREQ(x) _SB_GETVALUE_32(x, S_LDT_SRICTRL_NEEDPREQ, M_LDT_SRICTRL_NEEDPREQ) + +#define S_LDT_SRICTRL_WANTRESP 8 +#define M_LDT_SRICTRL_WANTRESP _SB_MAKEMASK_32(2, S_LDT_SRICTRL_WANTRESP) +#define V_LDT_SRICTRL_WANTRESP(x) _SB_MAKEVALUE_32(x, S_LDT_SRICTRL_WANTRESP) +#define G_LDT_SRICTRL_WANTRESP(x) _SB_GETVALUE_32(x, S_LDT_SRICTRL_WANTRESP, M_LDT_SRICTRL_WANTRESP) + +#define S_LDT_SRICTRL_WANTNPREQ 10 +#define M_LDT_SRICTRL_WANTNPREQ _SB_MAKEMASK_32(2, S_LDT_SRICTRL_WANTNPREQ) +#define V_LDT_SRICTRL_WANTNPREQ(x) _SB_MAKEVALUE_32(x, S_LDT_SRICTRL_WANTNPREQ) +#define G_LDT_SRICTRL_WANTNPREQ(x) _SB_GETVALUE_32(x, S_LDT_SRICTRL_WANTNPREQ, M_LDT_SRICTRL_WANTNPREQ) + +#define S_LDT_SRICTRL_WANTPREQ 12 +#define M_LDT_SRICTRL_WANTPREQ _SB_MAKEMASK_32(2, S_LDT_SRICTRL_WANTPREQ) +#define V_LDT_SRICTRL_WANTPREQ(x) _SB_MAKEVALUE_32(x, S_LDT_SRICTRL_WANTPREQ) +#define G_LDT_SRICTRL_WANTPREQ(x) _SB_GETVALUE_32(x, S_LDT_SRICTRL_WANTPREQ, M_LDT_SRICTRL_WANTPREQ) + +#define S_LDT_SRICTRL_BUFRELSPACE 16 +#define M_LDT_SRICTRL_BUFRELSPACE _SB_MAKEMASK_32(4, S_LDT_SRICTRL_BUFRELSPACE) +#define V_LDT_SRICTRL_BUFRELSPACE(x) _SB_MAKEVALUE_32(x, S_LDT_SRICTRL_BUFRELSPACE) +#define G_LDT_SRICTRL_BUFRELSPACE(x) _SB_GETVALUE_32(x, S_LDT_SRICTRL_BUFRELSPACE, M_LDT_SRICTRL_BUFRELSPACE) + +/* + * LDT SRI Transmit Buffer Count register (Table 8-26) + */ + +#define S_LDT_TXBUFCNT_PCMD 0 +#define M_LDT_TXBUFCNT_PCMD _SB_MAKEMASK_32(4, S_LDT_TXBUFCNT_PCMD) +#define V_LDT_TXBUFCNT_PCMD(x) _SB_MAKEVALUE_32(x, S_LDT_TXBUFCNT_PCMD) +#define G_LDT_TXBUFCNT_PCMD(x) _SB_GETVALUE_32(x, S_LDT_TXBUFCNT_PCMD, M_LDT_TXBUFCNT_PCMD) + +#define S_LDT_TXBUFCNT_PDATA 4 +#define M_LDT_TXBUFCNT_PDATA _SB_MAKEMASK_32(4, S_LDT_TXBUFCNT_PDATA) +#define V_LDT_TXBUFCNT_PDATA(x) _SB_MAKEVALUE_32(x, S_LDT_TXBUFCNT_PDATA) +#define G_LDT_TXBUFCNT_PDATA(x) _SB_GETVALUE_32(x, S_LDT_TXBUFCNT_PDATA, M_LDT_TXBUFCNT_PDATA) + +#define S_LDT_TXBUFCNT_NPCMD 8 +#define M_LDT_TXBUFCNT_NPCMD _SB_MAKEMASK_32(4, S_LDT_TXBUFCNT_NPCMD) +#define V_LDT_TXBUFCNT_NPCMD(x) _SB_MAKEVALUE_32(x, S_LDT_TXBUFCNT_NPCMD) +#define G_LDT_TXBUFCNT_NPCMD(x) _SB_GETVALUE_32(x, S_LDT_TXBUFCNT_NPCMD, M_LDT_TXBUFCNT_NPCMD) + +#define S_LDT_TXBUFCNT_NPDATA 12 +#define M_LDT_TXBUFCNT_NPDATA _SB_MAKEMASK_32(4, S_LDT_TXBUFCNT_NPDATA) +#define V_LDT_TXBUFCNT_NPDATA(x) _SB_MAKEVALUE_32(x, S_LDT_TXBUFCNT_NPDATA) +#define G_LDT_TXBUFCNT_NPDATA(x) _SB_GETVALUE_32(x, S_LDT_TXBUFCNT_NPDATA, M_LDT_TXBUFCNT_NPDATA) + +#define S_LDT_TXBUFCNT_RCMD 16 +#define M_LDT_TXBUFCNT_RCMD _SB_MAKEMASK_32(4, S_LDT_TXBUFCNT_RCMD) +#define V_LDT_TXBUFCNT_RCMD(x) _SB_MAKEVALUE_32(x, S_LDT_TXBUFCNT_RCMD) +#define G_LDT_TXBUFCNT_RCMD(x) _SB_GETVALUE_32(x, S_LDT_TXBUFCNT_RCMD, M_LDT_TXBUFCNT_RCMD) + +#define S_LDT_TXBUFCNT_RDATA 20 +#define M_LDT_TXBUFCNT_RDATA _SB_MAKEMASK_32(4, S_LDT_TXBUFCNT_RDATA) +#define V_LDT_TXBUFCNT_RDATA(x) _SB_MAKEVALUE_32(x, S_LDT_TXBUFCNT_RDATA) +#define G_LDT_TXBUFCNT_RDATA(x) _SB_GETVALUE_32(x, S_LDT_TXBUFCNT_RDATA, M_LDT_TXBUFCNT_RDATA) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +/* + * Additional Status Register + */ + +#define S_LDT_ADDSTATUS_TGTDONE 0 +#define M_LDT_ADDSTATUS_TGTDONE _SB_MAKEMASK_32(8, S_LDT_ADDSTATUS_TGTDONE) +#define V_LDT_ADDSTATUS_TGTDONE(x) _SB_MAKEVALUE_32(x, S_LDT_ADDSTATUS_TGTDONE) +#define G_LDT_ADDSTATUS_TGTDONE(x) _SB_GETVALUE_32(x, S_LDT_ADDSTATUS_TGTDONE, M_LDT_ADDSTATUS_TGTDONE) +#endif /* 1250 PASS2 || 112x PASS1 */ + +#endif + diff --git a/arch/mips/include/asm/sibyte/sb1250_mac.h b/arch/mips/include/asm/sibyte/sb1250_mac.h new file mode 100644 index 00000000000..b6faf08ca81 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_mac.h @@ -0,0 +1,656 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * MAC constants and macros File: sb1250_mac.h + * + * This module contains constants and macros for the SB1250's + * ethernet controllers. + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_MAC_H +#define _SB1250_MAC_H + +#include "sb1250_defs.h" + +/* ********************************************************************* + * Ethernet MAC Registers + ********************************************************************* */ + +/* + * MAC Configuration Register (Table 9-13) + * Register: MAC_CFG_0 + * Register: MAC_CFG_1 + * Register: MAC_CFG_2 + */ + + +#define M_MAC_RESERVED0 _SB_MAKEMASK1(0) +#define M_MAC_TX_HOLD_SOP_EN _SB_MAKEMASK1(1) +#define M_MAC_RETRY_EN _SB_MAKEMASK1(2) +#define M_MAC_RET_DRPREQ_EN _SB_MAKEMASK1(3) +#define M_MAC_RET_UFL_EN _SB_MAKEMASK1(4) +#define M_MAC_BURST_EN _SB_MAKEMASK1(5) + +#define S_MAC_TX_PAUSE _SB_MAKE64(6) +#define M_MAC_TX_PAUSE_CNT _SB_MAKEMASK(3, S_MAC_TX_PAUSE) +#define V_MAC_TX_PAUSE_CNT(x) _SB_MAKEVALUE(x, S_MAC_TX_PAUSE) + +#define K_MAC_TX_PAUSE_CNT_512 0 +#define K_MAC_TX_PAUSE_CNT_1K 1 +#define K_MAC_TX_PAUSE_CNT_2K 2 +#define K_MAC_TX_PAUSE_CNT_4K 3 +#define K_MAC_TX_PAUSE_CNT_8K 4 +#define K_MAC_TX_PAUSE_CNT_16K 5 +#define K_MAC_TX_PAUSE_CNT_32K 6 +#define K_MAC_TX_PAUSE_CNT_64K 7 + +#define V_MAC_TX_PAUSE_CNT_512 V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_512) +#define V_MAC_TX_PAUSE_CNT_1K V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_1K) +#define V_MAC_TX_PAUSE_CNT_2K V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_2K) +#define V_MAC_TX_PAUSE_CNT_4K V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_4K) +#define V_MAC_TX_PAUSE_CNT_8K V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_8K) +#define V_MAC_TX_PAUSE_CNT_16K V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_16K) +#define V_MAC_TX_PAUSE_CNT_32K V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_32K) +#define V_MAC_TX_PAUSE_CNT_64K V_MAC_TX_PAUSE_CNT(K_MAC_TX_PAUSE_CNT_64K) + +#define M_MAC_RESERVED1 _SB_MAKEMASK(8, 9) + +#define M_MAC_AP_STAT_EN _SB_MAKEMASK1(17) + +#if SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_TIMESTAMP _SB_MAKEMASK1(18) +#endif +#define M_MAC_DRP_ERRPKT_EN _SB_MAKEMASK1(19) +#define M_MAC_DRP_FCSERRPKT_EN _SB_MAKEMASK1(20) +#define M_MAC_DRP_CODEERRPKT_EN _SB_MAKEMASK1(21) +#define M_MAC_DRP_DRBLERRPKT_EN _SB_MAKEMASK1(22) +#define M_MAC_DRP_RNTPKT_EN _SB_MAKEMASK1(23) +#define M_MAC_DRP_OSZPKT_EN _SB_MAKEMASK1(24) +#define M_MAC_DRP_LENERRPKT_EN _SB_MAKEMASK1(25) + +#define M_MAC_RESERVED3 _SB_MAKEMASK(6, 26) + +#define M_MAC_BYPASS_SEL _SB_MAKEMASK1(32) +#define M_MAC_HDX_EN _SB_MAKEMASK1(33) + +#define S_MAC_SPEED_SEL _SB_MAKE64(34) +#define M_MAC_SPEED_SEL _SB_MAKEMASK(2, S_MAC_SPEED_SEL) +#define V_MAC_SPEED_SEL(x) _SB_MAKEVALUE(x, S_MAC_SPEED_SEL) +#define G_MAC_SPEED_SEL(x) _SB_GETVALUE(x, S_MAC_SPEED_SEL, M_MAC_SPEED_SEL) + +#define K_MAC_SPEED_SEL_10MBPS 0 +#define K_MAC_SPEED_SEL_100MBPS 1 +#define K_MAC_SPEED_SEL_1000MBPS 2 +#define K_MAC_SPEED_SEL_RESERVED 3 + +#define V_MAC_SPEED_SEL_10MBPS V_MAC_SPEED_SEL(K_MAC_SPEED_SEL_10MBPS) +#define V_MAC_SPEED_SEL_100MBPS V_MAC_SPEED_SEL(K_MAC_SPEED_SEL_100MBPS) +#define V_MAC_SPEED_SEL_1000MBPS V_MAC_SPEED_SEL(K_MAC_SPEED_SEL_1000MBPS) +#define V_MAC_SPEED_SEL_RESERVED V_MAC_SPEED_SEL(K_MAC_SPEED_SEL_RESERVED) + +#define M_MAC_TX_CLK_EDGE_SEL _SB_MAKEMASK1(36) +#define M_MAC_LOOPBACK_SEL _SB_MAKEMASK1(37) +#define M_MAC_FAST_SYNC _SB_MAKEMASK1(38) +#define M_MAC_SS_EN _SB_MAKEMASK1(39) + +#define S_MAC_BYPASS_CFG _SB_MAKE64(40) +#define M_MAC_BYPASS_CFG _SB_MAKEMASK(2, S_MAC_BYPASS_CFG) +#define V_MAC_BYPASS_CFG(x) _SB_MAKEVALUE(x, S_MAC_BYPASS_CFG) +#define G_MAC_BYPASS_CFG(x) _SB_GETVALUE(x, S_MAC_BYPASS_CFG, M_MAC_BYPASS_CFG) + +#define K_MAC_BYPASS_GMII 0 +#define K_MAC_BYPASS_ENCODED 1 +#define K_MAC_BYPASS_SOP 2 +#define K_MAC_BYPASS_EOP 3 + +#define M_MAC_BYPASS_16 _SB_MAKEMASK1(42) +#define M_MAC_BYPASS_FCS_CHK _SB_MAKEMASK1(43) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_RX_CH_SEL_MSB _SB_MAKEMASK1(44) +#endif /* 1250 PASS2 || 112x PASS1 || 1480*/ + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_SPLIT_CH_SEL _SB_MAKEMASK1(45) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define S_MAC_BYPASS_IFG _SB_MAKE64(46) +#define M_MAC_BYPASS_IFG _SB_MAKEMASK(8, S_MAC_BYPASS_IFG) +#define V_MAC_BYPASS_IFG(x) _SB_MAKEVALUE(x, S_MAC_BYPASS_IFG) +#define G_MAC_BYPASS_IFG(x) _SB_GETVALUE(x, S_MAC_BYPASS_IFG, M_MAC_BYPASS_IFG) + +#define K_MAC_FC_CMD_DISABLED 0 +#define K_MAC_FC_CMD_ENABLED 1 +#define K_MAC_FC_CMD_ENAB_FALSECARR 2 + +#define V_MAC_FC_CMD_DISABLED V_MAC_FC_CMD(K_MAC_FC_CMD_DISABLED) +#define V_MAC_FC_CMD_ENABLED V_MAC_FC_CMD(K_MAC_FC_CMD_ENABLED) +#define V_MAC_FC_CMD_ENAB_FALSECARR V_MAC_FC_CMD(K_MAC_FC_CMD_ENAB_FALSECARR) + +#define M_MAC_FC_SEL _SB_MAKEMASK1(54) + +#define S_MAC_FC_CMD _SB_MAKE64(55) +#define M_MAC_FC_CMD _SB_MAKEMASK(2, S_MAC_FC_CMD) +#define V_MAC_FC_CMD(x) _SB_MAKEVALUE(x, S_MAC_FC_CMD) +#define G_MAC_FC_CMD(x) _SB_GETVALUE(x, S_MAC_FC_CMD, M_MAC_FC_CMD) + +#define S_MAC_RX_CH_SEL _SB_MAKE64(57) +#define M_MAC_RX_CH_SEL _SB_MAKEMASK(7, S_MAC_RX_CH_SEL) +#define V_MAC_RX_CH_SEL(x) _SB_MAKEVALUE(x, S_MAC_RX_CH_SEL) +#define G_MAC_RX_CH_SEL(x) _SB_GETVALUE(x, S_MAC_RX_CH_SEL, M_MAC_RX_CH_SEL) + + +/* + * MAC Enable Registers + * Register: MAC_ENABLE_0 + * Register: MAC_ENABLE_1 + * Register: MAC_ENABLE_2 + */ + +#define M_MAC_RXDMA_EN0 _SB_MAKEMASK1(0) +#define M_MAC_RXDMA_EN1 _SB_MAKEMASK1(1) +#define M_MAC_TXDMA_EN0 _SB_MAKEMASK1(4) +#define M_MAC_TXDMA_EN1 _SB_MAKEMASK1(5) + +#define M_MAC_PORT_RESET _SB_MAKEMASK1(8) + +#if (SIBYTE_HDR_FEATURE_CHIP(1250) || SIBYTE_HDR_FEATURE_CHIP(112x)) +#define M_MAC_RX_ENABLE _SB_MAKEMASK1(10) +#define M_MAC_TX_ENABLE _SB_MAKEMASK1(11) +#define M_MAC_BYP_RX_ENABLE _SB_MAKEMASK1(12) +#define M_MAC_BYP_TX_ENABLE _SB_MAKEMASK1(13) +#endif + +/* + * MAC reset information register (1280/1255) + */ +#if SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_RX_CH0_PAUSE_ON _SB_MAKEMASK1(8) +#define M_MAC_RX_CH1_PAUSE_ON _SB_MAKEMASK1(16) +#define M_MAC_TX_CH0_PAUSE_ON _SB_MAKEMASK1(24) +#define M_MAC_TX_CH1_PAUSE_ON _SB_MAKEMASK1(32) +#endif + +/* + * MAC DMA Control Register + * Register: MAC_TXD_CTL_0 + * Register: MAC_TXD_CTL_1 + * Register: MAC_TXD_CTL_2 + */ + +#define S_MAC_TXD_WEIGHT0 _SB_MAKE64(0) +#define M_MAC_TXD_WEIGHT0 _SB_MAKEMASK(4, S_MAC_TXD_WEIGHT0) +#define V_MAC_TXD_WEIGHT0(x) _SB_MAKEVALUE(x, S_MAC_TXD_WEIGHT0) +#define G_MAC_TXD_WEIGHT0(x) _SB_GETVALUE(x, S_MAC_TXD_WEIGHT0, M_MAC_TXD_WEIGHT0) + +#define S_MAC_TXD_WEIGHT1 _SB_MAKE64(4) +#define M_MAC_TXD_WEIGHT1 _SB_MAKEMASK(4, S_MAC_TXD_WEIGHT1) +#define V_MAC_TXD_WEIGHT1(x) _SB_MAKEVALUE(x, S_MAC_TXD_WEIGHT1) +#define G_MAC_TXD_WEIGHT1(x) _SB_GETVALUE(x, S_MAC_TXD_WEIGHT1, M_MAC_TXD_WEIGHT1) + +/* + * MAC Fifo Threshhold registers (Table 9-14) + * Register: MAC_THRSH_CFG_0 + * Register: MAC_THRSH_CFG_1 + * Register: MAC_THRSH_CFG_2 + */ + +#define S_MAC_TX_WR_THRSH _SB_MAKE64(0) +#if SIBYTE_HDR_FEATURE_UP_TO(1250, PASS1) +/* XXX: Can't enable, as it has the same name as a pass2+ define below. */ +/* #define M_MAC_TX_WR_THRSH _SB_MAKEMASK(6, S_MAC_TX_WR_THRSH) */ +#endif /* up to 1250 PASS1 */ +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_TX_WR_THRSH _SB_MAKEMASK(7, S_MAC_TX_WR_THRSH) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ +#define V_MAC_TX_WR_THRSH(x) _SB_MAKEVALUE(x, S_MAC_TX_WR_THRSH) +#define G_MAC_TX_WR_THRSH(x) _SB_GETVALUE(x, S_MAC_TX_WR_THRSH, M_MAC_TX_WR_THRSH) + +#define S_MAC_TX_RD_THRSH _SB_MAKE64(8) +#if SIBYTE_HDR_FEATURE_UP_TO(1250, PASS1) +/* XXX: Can't enable, as it has the same name as a pass2+ define below. */ +/* #define M_MAC_TX_RD_THRSH _SB_MAKEMASK(6, S_MAC_TX_RD_THRSH) */ +#endif /* up to 1250 PASS1 */ +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_TX_RD_THRSH _SB_MAKEMASK(7, S_MAC_TX_RD_THRSH) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ +#define V_MAC_TX_RD_THRSH(x) _SB_MAKEVALUE(x, S_MAC_TX_RD_THRSH) +#define G_MAC_TX_RD_THRSH(x) _SB_GETVALUE(x, S_MAC_TX_RD_THRSH, M_MAC_TX_RD_THRSH) + +#define S_MAC_TX_RL_THRSH _SB_MAKE64(16) +#define M_MAC_TX_RL_THRSH _SB_MAKEMASK(4, S_MAC_TX_RL_THRSH) +#define V_MAC_TX_RL_THRSH(x) _SB_MAKEVALUE(x, S_MAC_TX_RL_THRSH) +#define G_MAC_TX_RL_THRSH(x) _SB_GETVALUE(x, S_MAC_TX_RL_THRSH, M_MAC_TX_RL_THRSH) + +#define S_MAC_RX_PL_THRSH _SB_MAKE64(24) +#define M_MAC_RX_PL_THRSH _SB_MAKEMASK(6, S_MAC_RX_PL_THRSH) +#define V_MAC_RX_PL_THRSH(x) _SB_MAKEVALUE(x, S_MAC_RX_PL_THRSH) +#define G_MAC_RX_PL_THRSH(x) _SB_GETVALUE(x, S_MAC_RX_PL_THRSH, M_MAC_RX_PL_THRSH) + +#define S_MAC_RX_RD_THRSH _SB_MAKE64(32) +#define M_MAC_RX_RD_THRSH _SB_MAKEMASK(6, S_MAC_RX_RD_THRSH) +#define V_MAC_RX_RD_THRSH(x) _SB_MAKEVALUE(x, S_MAC_RX_RD_THRSH) +#define G_MAC_RX_RD_THRSH(x) _SB_GETVALUE(x, S_MAC_RX_RD_THRSH, M_MAC_RX_RD_THRSH) + +#define S_MAC_RX_RL_THRSH _SB_MAKE64(40) +#define M_MAC_RX_RL_THRSH _SB_MAKEMASK(6, S_MAC_RX_RL_THRSH) +#define V_MAC_RX_RL_THRSH(x) _SB_MAKEVALUE(x, S_MAC_RX_RL_THRSH) +#define G_MAC_RX_RL_THRSH(x) _SB_GETVALUE(x, S_MAC_RX_RL_THRSH, M_MAC_RX_RL_THRSH) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_MAC_ENC_FC_THRSH _SB_MAKE64(56) +#define M_MAC_ENC_FC_THRSH _SB_MAKEMASK(6, S_MAC_ENC_FC_THRSH) +#define V_MAC_ENC_FC_THRSH(x) _SB_MAKEVALUE(x, S_MAC_ENC_FC_THRSH) +#define G_MAC_ENC_FC_THRSH(x) _SB_GETVALUE(x, S_MAC_ENC_FC_THRSH, M_MAC_ENC_FC_THRSH) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +/* + * MAC Frame Configuration Registers (Table 9-15) + * Register: MAC_FRAME_CFG_0 + * Register: MAC_FRAME_CFG_1 + * Register: MAC_FRAME_CFG_2 + */ + +/* XXXCGD: ??? Unused in pass2? */ +#define S_MAC_IFG_RX _SB_MAKE64(0) +#define M_MAC_IFG_RX _SB_MAKEMASK(6, S_MAC_IFG_RX) +#define V_MAC_IFG_RX(x) _SB_MAKEVALUE(x, S_MAC_IFG_RX) +#define G_MAC_IFG_RX(x) _SB_GETVALUE(x, S_MAC_IFG_RX, M_MAC_IFG_RX) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_MAC_PRE_LEN _SB_MAKE64(0) +#define M_MAC_PRE_LEN _SB_MAKEMASK(6, S_MAC_PRE_LEN) +#define V_MAC_PRE_LEN(x) _SB_MAKEVALUE(x, S_MAC_PRE_LEN) +#define G_MAC_PRE_LEN(x) _SB_GETVALUE(x, S_MAC_PRE_LEN, M_MAC_PRE_LEN) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define S_MAC_IFG_TX _SB_MAKE64(6) +#define M_MAC_IFG_TX _SB_MAKEMASK(6, S_MAC_IFG_TX) +#define V_MAC_IFG_TX(x) _SB_MAKEVALUE(x, S_MAC_IFG_TX) +#define G_MAC_IFG_TX(x) _SB_GETVALUE(x, S_MAC_IFG_TX, M_MAC_IFG_TX) + +#define S_MAC_IFG_THRSH _SB_MAKE64(12) +#define M_MAC_IFG_THRSH _SB_MAKEMASK(6, S_MAC_IFG_THRSH) +#define V_MAC_IFG_THRSH(x) _SB_MAKEVALUE(x, S_MAC_IFG_THRSH) +#define G_MAC_IFG_THRSH(x) _SB_GETVALUE(x, S_MAC_IFG_THRSH, M_MAC_IFG_THRSH) + +#define S_MAC_BACKOFF_SEL _SB_MAKE64(18) +#define M_MAC_BACKOFF_SEL _SB_MAKEMASK(4, S_MAC_BACKOFF_SEL) +#define V_MAC_BACKOFF_SEL(x) _SB_MAKEVALUE(x, S_MAC_BACKOFF_SEL) +#define G_MAC_BACKOFF_SEL(x) _SB_GETVALUE(x, S_MAC_BACKOFF_SEL, M_MAC_BACKOFF_SEL) + +#define S_MAC_LFSR_SEED _SB_MAKE64(22) +#define M_MAC_LFSR_SEED _SB_MAKEMASK(8, S_MAC_LFSR_SEED) +#define V_MAC_LFSR_SEED(x) _SB_MAKEVALUE(x, S_MAC_LFSR_SEED) +#define G_MAC_LFSR_SEED(x) _SB_GETVALUE(x, S_MAC_LFSR_SEED, M_MAC_LFSR_SEED) + +#define S_MAC_SLOT_SIZE _SB_MAKE64(30) +#define M_MAC_SLOT_SIZE _SB_MAKEMASK(10, S_MAC_SLOT_SIZE) +#define V_MAC_SLOT_SIZE(x) _SB_MAKEVALUE(x, S_MAC_SLOT_SIZE) +#define G_MAC_SLOT_SIZE(x) _SB_GETVALUE(x, S_MAC_SLOT_SIZE, M_MAC_SLOT_SIZE) + +#define S_MAC_MIN_FRAMESZ _SB_MAKE64(40) +#define M_MAC_MIN_FRAMESZ _SB_MAKEMASK(8, S_MAC_MIN_FRAMESZ) +#define V_MAC_MIN_FRAMESZ(x) _SB_MAKEVALUE(x, S_MAC_MIN_FRAMESZ) +#define G_MAC_MIN_FRAMESZ(x) _SB_GETVALUE(x, S_MAC_MIN_FRAMESZ, M_MAC_MIN_FRAMESZ) + +#define S_MAC_MAX_FRAMESZ _SB_MAKE64(48) +#define M_MAC_MAX_FRAMESZ _SB_MAKEMASK(16, S_MAC_MAX_FRAMESZ) +#define V_MAC_MAX_FRAMESZ(x) _SB_MAKEVALUE(x, S_MAC_MAX_FRAMESZ) +#define G_MAC_MAX_FRAMESZ(x) _SB_GETVALUE(x, S_MAC_MAX_FRAMESZ, M_MAC_MAX_FRAMESZ) + +/* + * These constants are used to configure the fields within the Frame + * Configuration Register. + */ + +#define K_MAC_IFG_RX_10 _SB_MAKE64(0) /* See table 176, not used */ +#define K_MAC_IFG_RX_100 _SB_MAKE64(0) +#define K_MAC_IFG_RX_1000 _SB_MAKE64(0) + +#define K_MAC_IFG_TX_10 _SB_MAKE64(20) +#define K_MAC_IFG_TX_100 _SB_MAKE64(20) +#define K_MAC_IFG_TX_1000 _SB_MAKE64(8) + +#define K_MAC_IFG_THRSH_10 _SB_MAKE64(4) +#define K_MAC_IFG_THRSH_100 _SB_MAKE64(4) +#define K_MAC_IFG_THRSH_1000 _SB_MAKE64(0) + +#define K_MAC_SLOT_SIZE_10 _SB_MAKE64(0) +#define K_MAC_SLOT_SIZE_100 _SB_MAKE64(0) +#define K_MAC_SLOT_SIZE_1000 _SB_MAKE64(0) + +#define V_MAC_IFG_RX_10 V_MAC_IFG_RX(K_MAC_IFG_RX_10) +#define V_MAC_IFG_RX_100 V_MAC_IFG_RX(K_MAC_IFG_RX_100) +#define V_MAC_IFG_RX_1000 V_MAC_IFG_RX(K_MAC_IFG_RX_1000) + +#define V_MAC_IFG_TX_10 V_MAC_IFG_TX(K_MAC_IFG_TX_10) +#define V_MAC_IFG_TX_100 V_MAC_IFG_TX(K_MAC_IFG_TX_100) +#define V_MAC_IFG_TX_1000 V_MAC_IFG_TX(K_MAC_IFG_TX_1000) + +#define V_MAC_IFG_THRSH_10 V_MAC_IFG_THRSH(K_MAC_IFG_THRSH_10) +#define V_MAC_IFG_THRSH_100 V_MAC_IFG_THRSH(K_MAC_IFG_THRSH_100) +#define V_MAC_IFG_THRSH_1000 V_MAC_IFG_THRSH(K_MAC_IFG_THRSH_1000) + +#define V_MAC_SLOT_SIZE_10 V_MAC_SLOT_SIZE(K_MAC_SLOT_SIZE_10) +#define V_MAC_SLOT_SIZE_100 V_MAC_SLOT_SIZE(K_MAC_SLOT_SIZE_100) +#define V_MAC_SLOT_SIZE_1000 V_MAC_SLOT_SIZE(K_MAC_SLOT_SIZE_1000) + +#define K_MAC_MIN_FRAMESZ_FIFO _SB_MAKE64(9) +#define K_MAC_MIN_FRAMESZ_DEFAULT _SB_MAKE64(64) +#define K_MAC_MAX_FRAMESZ_DEFAULT _SB_MAKE64(1518) +#define K_MAC_MAX_FRAMESZ_JUMBO _SB_MAKE64(9216) + +#define V_MAC_MIN_FRAMESZ_FIFO V_MAC_MIN_FRAMESZ(K_MAC_MIN_FRAMESZ_FIFO) +#define V_MAC_MIN_FRAMESZ_DEFAULT V_MAC_MIN_FRAMESZ(K_MAC_MIN_FRAMESZ_DEFAULT) +#define V_MAC_MAX_FRAMESZ_DEFAULT V_MAC_MAX_FRAMESZ(K_MAC_MAX_FRAMESZ_DEFAULT) +#define V_MAC_MAX_FRAMESZ_JUMBO V_MAC_MAX_FRAMESZ(K_MAC_MAX_FRAMESZ_JUMBO) + +/* + * MAC VLAN Tag Registers (Table 9-16) + * Register: MAC_VLANTAG_0 + * Register: MAC_VLANTAG_1 + * Register: MAC_VLANTAG_2 + */ + +#define S_MAC_VLAN_TAG _SB_MAKE64(0) +#define M_MAC_VLAN_TAG _SB_MAKEMASK(32, S_MAC_VLAN_TAG) +#define V_MAC_VLAN_TAG(x) _SB_MAKEVALUE(x, S_MAC_VLAN_TAG) +#define G_MAC_VLAN_TAG(x) _SB_GETVALUE(x, S_MAC_VLAN_TAG, M_MAC_VLAN_TAG) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define S_MAC_TX_PKT_OFFSET _SB_MAKE64(32) +#define M_MAC_TX_PKT_OFFSET _SB_MAKEMASK(8, S_MAC_TX_PKT_OFFSET) +#define V_MAC_TX_PKT_OFFSET(x) _SB_MAKEVALUE(x, S_MAC_TX_PKT_OFFSET) +#define G_MAC_TX_PKT_OFFSET(x) _SB_GETVALUE(x, S_MAC_TX_PKT_OFFSET, M_MAC_TX_PKT_OFFSET) + +#define S_MAC_TX_CRC_OFFSET _SB_MAKE64(40) +#define M_MAC_TX_CRC_OFFSET _SB_MAKEMASK(8, S_MAC_TX_CRC_OFFSET) +#define V_MAC_TX_CRC_OFFSET(x) _SB_MAKEVALUE(x, S_MAC_TX_CRC_OFFSET) +#define G_MAC_TX_CRC_OFFSET(x) _SB_GETVALUE(x, S_MAC_TX_CRC_OFFSET, M_MAC_TX_CRC_OFFSET) + +#define M_MAC_CH_BASE_FC_EN _SB_MAKEMASK1(48) +#endif /* 1250 PASS3 || 112x PASS1 */ + +/* + * MAC Status Registers (Table 9-17) + * Also used for the MAC Interrupt Mask Register (Table 9-18) + * Register: MAC_STATUS_0 + * Register: MAC_STATUS_1 + * Register: MAC_STATUS_2 + * Register: MAC_INT_MASK_0 + * Register: MAC_INT_MASK_1 + * Register: MAC_INT_MASK_2 + */ + +/* + * Use these constants to shift the appropriate channel + * into the CH0 position so the same tests can be used + * on each channel. + */ + +#define S_MAC_RX_CH0 _SB_MAKE64(0) +#define S_MAC_RX_CH1 _SB_MAKE64(8) +#define S_MAC_TX_CH0 _SB_MAKE64(16) +#define S_MAC_TX_CH1 _SB_MAKE64(24) + +#define S_MAC_TXCHANNELS _SB_MAKE64(16) /* this is 1st TX chan */ +#define S_MAC_CHANWIDTH _SB_MAKE64(8) /* bits between channels */ + +/* + * These are the same as RX channel 0. The idea here + * is that you'll use one of the "S_" things above + * and pass just the six bits to a DMA-channel-specific ISR + */ +#define M_MAC_INT_CHANNEL _SB_MAKEMASK(8, 0) +#define M_MAC_INT_EOP_COUNT _SB_MAKEMASK1(0) +#define M_MAC_INT_EOP_TIMER _SB_MAKEMASK1(1) +#define M_MAC_INT_EOP_SEEN _SB_MAKEMASK1(2) +#define M_MAC_INT_HWM _SB_MAKEMASK1(3) +#define M_MAC_INT_LWM _SB_MAKEMASK1(4) +#define M_MAC_INT_DSCR _SB_MAKEMASK1(5) +#define M_MAC_INT_ERR _SB_MAKEMASK1(6) +#define M_MAC_INT_DZERO _SB_MAKEMASK1(7) /* only for TX channels */ +#define M_MAC_INT_DROP _SB_MAKEMASK1(7) /* only for RX channels */ + +/* + * In the following definitions we use ch (0/1) and txrx (TX=1, RX=0, see + * also DMA_TX/DMA_RX in sb_regs.h). + */ +#define S_MAC_STATUS_CH_OFFSET(ch, txrx) _SB_MAKE64(((ch) + 2 * (txrx)) * S_MAC_CHANWIDTH) + +#define M_MAC_STATUS_CHANNEL(ch, txrx) _SB_MAKEVALUE(_SB_MAKEMASK(8, 0), S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_EOP_COUNT(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_EOP_COUNT, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_EOP_TIMER(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_EOP_TIMER, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_EOP_SEEN(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_EOP_SEEN, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_HWM(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_HWM, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_LWM(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_LWM, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_DSCR(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_DSCR, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_ERR(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_ERR, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_DZERO(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_DZERO, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_DROP(ch, txrx) _SB_MAKEVALUE(M_MAC_INT_DROP, S_MAC_STATUS_CH_OFFSET(ch, txrx)) +#define M_MAC_STATUS_OTHER_ERR _SB_MAKEVALUE(_SB_MAKEMASK(7, 0), 40) + + +#define M_MAC_RX_UNDRFL _SB_MAKEMASK1(40) +#define M_MAC_RX_OVRFL _SB_MAKEMASK1(41) +#define M_MAC_TX_UNDRFL _SB_MAKEMASK1(42) +#define M_MAC_TX_OVRFL _SB_MAKEMASK1(43) +#define M_MAC_LTCOL_ERR _SB_MAKEMASK1(44) +#define M_MAC_EXCOL_ERR _SB_MAKEMASK1(45) +#define M_MAC_CNTR_OVRFL_ERR _SB_MAKEMASK1(46) +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_SPLIT_EN _SB_MAKEMASK1(47) /* interrupt mask only */ +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#define S_MAC_COUNTER_ADDR _SB_MAKE64(47) +#define M_MAC_COUNTER_ADDR _SB_MAKEMASK(5, S_MAC_COUNTER_ADDR) +#define V_MAC_COUNTER_ADDR(x) _SB_MAKEVALUE(x, S_MAC_COUNTER_ADDR) +#define G_MAC_COUNTER_ADDR(x) _SB_GETVALUE(x, S_MAC_COUNTER_ADDR, M_MAC_COUNTER_ADDR) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_TX_PAUSE_ON _SB_MAKEMASK1(52) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +/* + * MAC Fifo Pointer Registers (Table 9-19) [Debug register] + * Register: MAC_FIFO_PTRS_0 + * Register: MAC_FIFO_PTRS_1 + * Register: MAC_FIFO_PTRS_2 + */ + +#define S_MAC_TX_WRPTR _SB_MAKE64(0) +#define M_MAC_TX_WRPTR _SB_MAKEMASK(6, S_MAC_TX_WRPTR) +#define V_MAC_TX_WRPTR(x) _SB_MAKEVALUE(x, S_MAC_TX_WRPTR) +#define G_MAC_TX_WRPTR(x) _SB_GETVALUE(x, S_MAC_TX_WRPTR, M_MAC_TX_WRPTR) + +#define S_MAC_TX_RDPTR _SB_MAKE64(8) +#define M_MAC_TX_RDPTR _SB_MAKEMASK(6, S_MAC_TX_RDPTR) +#define V_MAC_TX_RDPTR(x) _SB_MAKEVALUE(x, S_MAC_TX_RDPTR) +#define G_MAC_TX_RDPTR(x) _SB_GETVALUE(x, S_MAC_TX_RDPTR, M_MAC_TX_RDPTR) + +#define S_MAC_RX_WRPTR _SB_MAKE64(16) +#define M_MAC_RX_WRPTR _SB_MAKEMASK(6, S_MAC_RX_WRPTR) +#define V_MAC_RX_WRPTR(x) _SB_MAKEVALUE(x, S_MAC_RX_WRPTR) +#define G_MAC_RX_WRPTR(x) _SB_GETVALUE(x, S_MAC_RX_WRPTR, M_MAC_TX_WRPTR) + +#define S_MAC_RX_RDPTR _SB_MAKE64(24) +#define M_MAC_RX_RDPTR _SB_MAKEMASK(6, S_MAC_RX_RDPTR) +#define V_MAC_RX_RDPTR(x) _SB_MAKEVALUE(x, S_MAC_RX_RDPTR) +#define G_MAC_RX_RDPTR(x) _SB_GETVALUE(x, S_MAC_RX_RDPTR, M_MAC_TX_RDPTR) + +/* + * MAC Fifo End Of Packet Count Registers (Table 9-20) [Debug register] + * Register: MAC_EOPCNT_0 + * Register: MAC_EOPCNT_1 + * Register: MAC_EOPCNT_2 + */ + +#define S_MAC_TX_EOP_COUNTER _SB_MAKE64(0) +#define M_MAC_TX_EOP_COUNTER _SB_MAKEMASK(6, S_MAC_TX_EOP_COUNTER) +#define V_MAC_TX_EOP_COUNTER(x) _SB_MAKEVALUE(x, S_MAC_TX_EOP_COUNTER) +#define G_MAC_TX_EOP_COUNTER(x) _SB_GETVALUE(x, S_MAC_TX_EOP_COUNTER, M_MAC_TX_EOP_COUNTER) + +#define S_MAC_RX_EOP_COUNTER _SB_MAKE64(8) +#define M_MAC_RX_EOP_COUNTER _SB_MAKEMASK(6, S_MAC_RX_EOP_COUNTER) +#define V_MAC_RX_EOP_COUNTER(x) _SB_MAKEVALUE(x, S_MAC_RX_EOP_COUNTER) +#define G_MAC_RX_EOP_COUNTER(x) _SB_GETVALUE(x, S_MAC_RX_EOP_COUNTER, M_MAC_RX_EOP_COUNTER) + +/* + * MAC Recieve Address Filter Exact Match Registers (Table 9-21) + * Registers: MAC_ADDR0_0 through MAC_ADDR7_0 + * Registers: MAC_ADDR0_1 through MAC_ADDR7_1 + * Registers: MAC_ADDR0_2 through MAC_ADDR7_2 + */ + +/* No bitfields */ + +/* + * MAC Receive Address Filter Mask Registers + * Registers: MAC_ADDRMASK0_0 and MAC_ADDRMASK0_1 + * Registers: MAC_ADDRMASK1_0 and MAC_ADDRMASK1_1 + * Registers: MAC_ADDRMASK2_0 and MAC_ADDRMASK2_1 + */ + +/* No bitfields */ + +/* + * MAC Recieve Address Filter Hash Match Registers (Table 9-22) + * Registers: MAC_HASH0_0 through MAC_HASH7_0 + * Registers: MAC_HASH0_1 through MAC_HASH7_1 + * Registers: MAC_HASH0_2 through MAC_HASH7_2 + */ + +/* No bitfields */ + +/* + * MAC Transmit Source Address Registers (Table 9-23) + * Register: MAC_ETHERNET_ADDR_0 + * Register: MAC_ETHERNET_ADDR_1 + * Register: MAC_ETHERNET_ADDR_2 + */ + +/* No bitfields */ + +/* + * MAC Packet Type Configuration Register + * Register: MAC_TYPE_CFG_0 + * Register: MAC_TYPE_CFG_1 + * Register: MAC_TYPE_CFG_2 + */ + +#define S_TYPECFG_TYPESIZE _SB_MAKE64(16) + +#define S_TYPECFG_TYPE0 _SB_MAKE64(0) +#define M_TYPECFG_TYPE0 _SB_MAKEMASK(16, S_TYPECFG_TYPE0) +#define V_TYPECFG_TYPE0(x) _SB_MAKEVALUE(x, S_TYPECFG_TYPE0) +#define G_TYPECFG_TYPE0(x) _SB_GETVALUE(x, S_TYPECFG_TYPE0, M_TYPECFG_TYPE0) + +#define S_TYPECFG_TYPE1 _SB_MAKE64(0) +#define M_TYPECFG_TYPE1 _SB_MAKEMASK(16, S_TYPECFG_TYPE1) +#define V_TYPECFG_TYPE1(x) _SB_MAKEVALUE(x, S_TYPECFG_TYPE1) +#define G_TYPECFG_TYPE1(x) _SB_GETVALUE(x, S_TYPECFG_TYPE1, M_TYPECFG_TYPE1) + +#define S_TYPECFG_TYPE2 _SB_MAKE64(0) +#define M_TYPECFG_TYPE2 _SB_MAKEMASK(16, S_TYPECFG_TYPE2) +#define V_TYPECFG_TYPE2(x) _SB_MAKEVALUE(x, S_TYPECFG_TYPE2) +#define G_TYPECFG_TYPE2(x) _SB_GETVALUE(x, S_TYPECFG_TYPE2, M_TYPECFG_TYPE2) + +#define S_TYPECFG_TYPE3 _SB_MAKE64(0) +#define M_TYPECFG_TYPE3 _SB_MAKEMASK(16, S_TYPECFG_TYPE3) +#define V_TYPECFG_TYPE3(x) _SB_MAKEVALUE(x, S_TYPECFG_TYPE3) +#define G_TYPECFG_TYPE3(x) _SB_GETVALUE(x, S_TYPECFG_TYPE3, M_TYPECFG_TYPE3) + +/* + * MAC Receive Address Filter Control Registers (Table 9-24) + * Register: MAC_ADFILTER_CFG_0 + * Register: MAC_ADFILTER_CFG_1 + * Register: MAC_ADFILTER_CFG_2 + */ + +#define M_MAC_ALLPKT_EN _SB_MAKEMASK1(0) +#define M_MAC_UCAST_EN _SB_MAKEMASK1(1) +#define M_MAC_UCAST_INV _SB_MAKEMASK1(2) +#define M_MAC_MCAST_EN _SB_MAKEMASK1(3) +#define M_MAC_MCAST_INV _SB_MAKEMASK1(4) +#define M_MAC_BCAST_EN _SB_MAKEMASK1(5) +#define M_MAC_DIRECT_INV _SB_MAKEMASK1(6) +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_MAC_ALLMCAST_EN _SB_MAKEMASK1(7) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#define S_MAC_IPHDR_OFFSET _SB_MAKE64(8) +#define M_MAC_IPHDR_OFFSET _SB_MAKEMASK(8, S_MAC_IPHDR_OFFSET) +#define V_MAC_IPHDR_OFFSET(x) _SB_MAKEVALUE(x, S_MAC_IPHDR_OFFSET) +#define G_MAC_IPHDR_OFFSET(x) _SB_GETVALUE(x, S_MAC_IPHDR_OFFSET, M_MAC_IPHDR_OFFSET) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_MAC_RX_CRC_OFFSET _SB_MAKE64(16) +#define M_MAC_RX_CRC_OFFSET _SB_MAKEMASK(8, S_MAC_RX_CRC_OFFSET) +#define V_MAC_RX_CRC_OFFSET(x) _SB_MAKEVALUE(x, S_MAC_RX_CRC_OFFSET) +#define G_MAC_RX_CRC_OFFSET(x) _SB_GETVALUE(x, S_MAC_RX_CRC_OFFSET, M_MAC_RX_CRC_OFFSET) + +#define S_MAC_RX_PKT_OFFSET _SB_MAKE64(24) +#define M_MAC_RX_PKT_OFFSET _SB_MAKEMASK(8, S_MAC_RX_PKT_OFFSET) +#define V_MAC_RX_PKT_OFFSET(x) _SB_MAKEVALUE(x, S_MAC_RX_PKT_OFFSET) +#define G_MAC_RX_PKT_OFFSET(x) _SB_GETVALUE(x, S_MAC_RX_PKT_OFFSET, M_MAC_RX_PKT_OFFSET) + +#define M_MAC_FWDPAUSE_EN _SB_MAKEMASK1(32) +#define M_MAC_VLAN_DET_EN _SB_MAKEMASK1(33) + +#define S_MAC_RX_CH_MSN_SEL _SB_MAKE64(34) +#define M_MAC_RX_CH_MSN_SEL _SB_MAKEMASK(8, S_MAC_RX_CH_MSN_SEL) +#define V_MAC_RX_CH_MSN_SEL(x) _SB_MAKEVALUE(x, S_MAC_RX_CH_MSN_SEL) +#define G_MAC_RX_CH_MSN_SEL(x) _SB_GETVALUE(x, S_MAC_RX_CH_MSN_SEL, M_MAC_RX_CH_MSN_SEL) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +/* + * MAC Receive Channel Select Registers (Table 9-25) + */ + +/* no bitfields */ + +/* + * MAC MII Management Interface Registers (Table 9-26) + * Register: MAC_MDIO_0 + * Register: MAC_MDIO_1 + * Register: MAC_MDIO_2 + */ + +#define S_MAC_MDC 0 +#define S_MAC_MDIO_DIR 1 +#define S_MAC_MDIO_OUT 2 +#define S_MAC_GENC 3 +#define S_MAC_MDIO_IN 4 + +#define M_MAC_MDC _SB_MAKEMASK1(S_MAC_MDC) +#define M_MAC_MDIO_DIR _SB_MAKEMASK1(S_MAC_MDIO_DIR) +#define M_MAC_MDIO_DIR_INPUT _SB_MAKEMASK1(S_MAC_MDIO_DIR) +#define M_MAC_MDIO_OUT _SB_MAKEMASK1(S_MAC_MDIO_OUT) +#define M_MAC_GENC _SB_MAKEMASK1(S_MAC_GENC) +#define M_MAC_MDIO_IN _SB_MAKEMASK1(S_MAC_MDIO_IN) + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_mc.h b/arch/mips/include/asm/sibyte/sb1250_mc.h new file mode 100644 index 00000000000..1eb1b5a8873 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_mc.h @@ -0,0 +1,550 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Memory Controller constants File: sb1250_mc.h + * + * This module contains constants and macros useful for + * programming the memory controller. + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000, 2001, 2002, 2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_MC_H +#define _SB1250_MC_H + +#include "sb1250_defs.h" + +/* + * Memory Channel Config Register (table 6-14) + */ + +#define S_MC_RESERVED0 0 +#define M_MC_RESERVED0 _SB_MAKEMASK(8, S_MC_RESERVED0) + +#define S_MC_CHANNEL_SEL 8 +#define M_MC_CHANNEL_SEL _SB_MAKEMASK(8, S_MC_CHANNEL_SEL) +#define V_MC_CHANNEL_SEL(x) _SB_MAKEVALUE(x, S_MC_CHANNEL_SEL) +#define G_MC_CHANNEL_SEL(x) _SB_GETVALUE(x, S_MC_CHANNEL_SEL, M_MC_CHANNEL_SEL) + +#define S_MC_BANK0_MAP 16 +#define M_MC_BANK0_MAP _SB_MAKEMASK(4, S_MC_BANK0_MAP) +#define V_MC_BANK0_MAP(x) _SB_MAKEVALUE(x, S_MC_BANK0_MAP) +#define G_MC_BANK0_MAP(x) _SB_GETVALUE(x, S_MC_BANK0_MAP, M_MC_BANK0_MAP) + +#define K_MC_BANK0_MAP_DEFAULT 0x00 +#define V_MC_BANK0_MAP_DEFAULT V_MC_BANK0_MAP(K_MC_BANK0_MAP_DEFAULT) + +#define S_MC_BANK1_MAP 20 +#define M_MC_BANK1_MAP _SB_MAKEMASK(4, S_MC_BANK1_MAP) +#define V_MC_BANK1_MAP(x) _SB_MAKEVALUE(x, S_MC_BANK1_MAP) +#define G_MC_BANK1_MAP(x) _SB_GETVALUE(x, S_MC_BANK1_MAP, M_MC_BANK1_MAP) + +#define K_MC_BANK1_MAP_DEFAULT 0x08 +#define V_MC_BANK1_MAP_DEFAULT V_MC_BANK1_MAP(K_MC_BANK1_MAP_DEFAULT) + +#define S_MC_BANK2_MAP 24 +#define M_MC_BANK2_MAP _SB_MAKEMASK(4, S_MC_BANK2_MAP) +#define V_MC_BANK2_MAP(x) _SB_MAKEVALUE(x, S_MC_BANK2_MAP) +#define G_MC_BANK2_MAP(x) _SB_GETVALUE(x, S_MC_BANK2_MAP, M_MC_BANK2_MAP) + +#define K_MC_BANK2_MAP_DEFAULT 0x09 +#define V_MC_BANK2_MAP_DEFAULT V_MC_BANK2_MAP(K_MC_BANK2_MAP_DEFAULT) + +#define S_MC_BANK3_MAP 28 +#define M_MC_BANK3_MAP _SB_MAKEMASK(4, S_MC_BANK3_MAP) +#define V_MC_BANK3_MAP(x) _SB_MAKEVALUE(x, S_MC_BANK3_MAP) +#define G_MC_BANK3_MAP(x) _SB_GETVALUE(x, S_MC_BANK3_MAP, M_MC_BANK3_MAP) + +#define K_MC_BANK3_MAP_DEFAULT 0x0C +#define V_MC_BANK3_MAP_DEFAULT V_MC_BANK3_MAP(K_MC_BANK3_MAP_DEFAULT) + +#define M_MC_RESERVED1 _SB_MAKEMASK(8, 32) + +#define S_MC_QUEUE_SIZE 40 +#define M_MC_QUEUE_SIZE _SB_MAKEMASK(4, S_MC_QUEUE_SIZE) +#define V_MC_QUEUE_SIZE(x) _SB_MAKEVALUE(x, S_MC_QUEUE_SIZE) +#define G_MC_QUEUE_SIZE(x) _SB_GETVALUE(x, S_MC_QUEUE_SIZE, M_MC_QUEUE_SIZE) +#define V_MC_QUEUE_SIZE_DEFAULT V_MC_QUEUE_SIZE(0x0A) + +#define S_MC_AGE_LIMIT 44 +#define M_MC_AGE_LIMIT _SB_MAKEMASK(4, S_MC_AGE_LIMIT) +#define V_MC_AGE_LIMIT(x) _SB_MAKEVALUE(x, S_MC_AGE_LIMIT) +#define G_MC_AGE_LIMIT(x) _SB_GETVALUE(x, S_MC_AGE_LIMIT, M_MC_AGE_LIMIT) +#define V_MC_AGE_LIMIT_DEFAULT V_MC_AGE_LIMIT(8) + +#define S_MC_WR_LIMIT 48 +#define M_MC_WR_LIMIT _SB_MAKEMASK(4, S_MC_WR_LIMIT) +#define V_MC_WR_LIMIT(x) _SB_MAKEVALUE(x, S_MC_WR_LIMIT) +#define G_MC_WR_LIMIT(x) _SB_GETVALUE(x, S_MC_WR_LIMIT, M_MC_WR_LIMIT) +#define V_MC_WR_LIMIT_DEFAULT V_MC_WR_LIMIT(5) + +#define M_MC_IOB1HIGHPRIORITY _SB_MAKEMASK1(52) + +#define M_MC_RESERVED2 _SB_MAKEMASK(3, 53) + +#define S_MC_CS_MODE 56 +#define M_MC_CS_MODE _SB_MAKEMASK(4, S_MC_CS_MODE) +#define V_MC_CS_MODE(x) _SB_MAKEVALUE(x, S_MC_CS_MODE) +#define G_MC_CS_MODE(x) _SB_GETVALUE(x, S_MC_CS_MODE, M_MC_CS_MODE) + +#define K_MC_CS_MODE_MSB_CS 0 +#define K_MC_CS_MODE_INTLV_CS 15 +#define K_MC_CS_MODE_MIXED_CS_10 12 +#define K_MC_CS_MODE_MIXED_CS_30 6 +#define K_MC_CS_MODE_MIXED_CS_32 3 + +#define V_MC_CS_MODE_MSB_CS V_MC_CS_MODE(K_MC_CS_MODE_MSB_CS) +#define V_MC_CS_MODE_INTLV_CS V_MC_CS_MODE(K_MC_CS_MODE_INTLV_CS) +#define V_MC_CS_MODE_MIXED_CS_10 V_MC_CS_MODE(K_MC_CS_MODE_MIXED_CS_10) +#define V_MC_CS_MODE_MIXED_CS_30 V_MC_CS_MODE(K_MC_CS_MODE_MIXED_CS_30) +#define V_MC_CS_MODE_MIXED_CS_32 V_MC_CS_MODE(K_MC_CS_MODE_MIXED_CS_32) + +#define M_MC_ECC_DISABLE _SB_MAKEMASK1(60) +#define M_MC_BERR_DISABLE _SB_MAKEMASK1(61) +#define M_MC_FORCE_SEQ _SB_MAKEMASK1(62) +#define M_MC_DEBUG _SB_MAKEMASK1(63) + +#define V_MC_CONFIG_DEFAULT V_MC_WR_LIMIT_DEFAULT | V_MC_AGE_LIMIT_DEFAULT | \ + V_MC_BANK0_MAP_DEFAULT | V_MC_BANK1_MAP_DEFAULT | \ + V_MC_BANK2_MAP_DEFAULT | V_MC_BANK3_MAP_DEFAULT | V_MC_CHANNEL_SEL(0) | \ + M_MC_IOB1HIGHPRIORITY | V_MC_QUEUE_SIZE_DEFAULT + + +/* + * Memory clock config register (Table 6-15) + * + * Note: this field has been updated to be consistent with the errata to 0.2 + */ + +#define S_MC_CLK_RATIO 0 +#define M_MC_CLK_RATIO _SB_MAKEMASK(4, S_MC_CLK_RATIO) +#define V_MC_CLK_RATIO(x) _SB_MAKEVALUE(x, S_MC_CLK_RATIO) +#define G_MC_CLK_RATIO(x) _SB_GETVALUE(x, S_MC_CLK_RATIO, M_MC_CLK_RATIO) + +#define K_MC_CLK_RATIO_2X 4 +#define K_MC_CLK_RATIO_25X 5 +#define K_MC_CLK_RATIO_3X 6 +#define K_MC_CLK_RATIO_35X 7 +#define K_MC_CLK_RATIO_4X 8 +#define K_MC_CLK_RATIO_45X 9 + +#define V_MC_CLK_RATIO_2X V_MC_CLK_RATIO(K_MC_CLK_RATIO_2X) +#define V_MC_CLK_RATIO_25X V_MC_CLK_RATIO(K_MC_CLK_RATIO_25X) +#define V_MC_CLK_RATIO_3X V_MC_CLK_RATIO(K_MC_CLK_RATIO_3X) +#define V_MC_CLK_RATIO_35X V_MC_CLK_RATIO(K_MC_CLK_RATIO_35X) +#define V_MC_CLK_RATIO_4X V_MC_CLK_RATIO(K_MC_CLK_RATIO_4X) +#define V_MC_CLK_RATIO_45X V_MC_CLK_RATIO(K_MC_CLK_RATIO_45X) +#define V_MC_CLK_RATIO_DEFAULT V_MC_CLK_RATIO_25X + +#define S_MC_REF_RATE 8 +#define M_MC_REF_RATE _SB_MAKEMASK(8, S_MC_REF_RATE) +#define V_MC_REF_RATE(x) _SB_MAKEVALUE(x, S_MC_REF_RATE) +#define G_MC_REF_RATE(x) _SB_GETVALUE(x, S_MC_REF_RATE, M_MC_REF_RATE) + +#define K_MC_REF_RATE_100MHz 0x62 +#define K_MC_REF_RATE_133MHz 0x81 +#define K_MC_REF_RATE_200MHz 0xC4 + +#define V_MC_REF_RATE_100MHz V_MC_REF_RATE(K_MC_REF_RATE_100MHz) +#define V_MC_REF_RATE_133MHz V_MC_REF_RATE(K_MC_REF_RATE_133MHz) +#define V_MC_REF_RATE_200MHz V_MC_REF_RATE(K_MC_REF_RATE_200MHz) +#define V_MC_REF_RATE_DEFAULT V_MC_REF_RATE_100MHz + +#define S_MC_CLOCK_DRIVE 16 +#define M_MC_CLOCK_DRIVE _SB_MAKEMASK(4, S_MC_CLOCK_DRIVE) +#define V_MC_CLOCK_DRIVE(x) _SB_MAKEVALUE(x, S_MC_CLOCK_DRIVE) +#define G_MC_CLOCK_DRIVE(x) _SB_GETVALUE(x, S_MC_CLOCK_DRIVE, M_MC_CLOCK_DRIVE) +#define V_MC_CLOCK_DRIVE_DEFAULT V_MC_CLOCK_DRIVE(0xF) + +#define S_MC_DATA_DRIVE 20 +#define M_MC_DATA_DRIVE _SB_MAKEMASK(4, S_MC_DATA_DRIVE) +#define V_MC_DATA_DRIVE(x) _SB_MAKEVALUE(x, S_MC_DATA_DRIVE) +#define G_MC_DATA_DRIVE(x) _SB_GETVALUE(x, S_MC_DATA_DRIVE, M_MC_DATA_DRIVE) +#define V_MC_DATA_DRIVE_DEFAULT V_MC_DATA_DRIVE(0x0) + +#define S_MC_ADDR_DRIVE 24 +#define M_MC_ADDR_DRIVE _SB_MAKEMASK(4, S_MC_ADDR_DRIVE) +#define V_MC_ADDR_DRIVE(x) _SB_MAKEVALUE(x, S_MC_ADDR_DRIVE) +#define G_MC_ADDR_DRIVE(x) _SB_GETVALUE(x, S_MC_ADDR_DRIVE, M_MC_ADDR_DRIVE) +#define V_MC_ADDR_DRIVE_DEFAULT V_MC_ADDR_DRIVE(0x0) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define M_MC_REF_DISABLE _SB_MAKEMASK1(30) +#endif /* 1250 PASS3 || 112x PASS1 */ + +#define M_MC_DLL_BYPASS _SB_MAKEMASK1(31) + +#define S_MC_DQI_SKEW 32 +#define M_MC_DQI_SKEW _SB_MAKEMASK(8, S_MC_DQI_SKEW) +#define V_MC_DQI_SKEW(x) _SB_MAKEVALUE(x, S_MC_DQI_SKEW) +#define G_MC_DQI_SKEW(x) _SB_GETVALUE(x, S_MC_DQI_SKEW, M_MC_DQI_SKEW) +#define V_MC_DQI_SKEW_DEFAULT V_MC_DQI_SKEW(0) + +#define S_MC_DQO_SKEW 40 +#define M_MC_DQO_SKEW _SB_MAKEMASK(8, S_MC_DQO_SKEW) +#define V_MC_DQO_SKEW(x) _SB_MAKEVALUE(x, S_MC_DQO_SKEW) +#define G_MC_DQO_SKEW(x) _SB_GETVALUE(x, S_MC_DQO_SKEW, M_MC_DQO_SKEW) +#define V_MC_DQO_SKEW_DEFAULT V_MC_DQO_SKEW(0) + +#define S_MC_ADDR_SKEW 48 +#define M_MC_ADDR_SKEW _SB_MAKEMASK(8, S_MC_ADDR_SKEW) +#define V_MC_ADDR_SKEW(x) _SB_MAKEVALUE(x, S_MC_ADDR_SKEW) +#define G_MC_ADDR_SKEW(x) _SB_GETVALUE(x, S_MC_ADDR_SKEW, M_MC_ADDR_SKEW) +#define V_MC_ADDR_SKEW_DEFAULT V_MC_ADDR_SKEW(0x0F) + +#define S_MC_DLL_DEFAULT 56 +#define M_MC_DLL_DEFAULT _SB_MAKEMASK(8, S_MC_DLL_DEFAULT) +#define V_MC_DLL_DEFAULT(x) _SB_MAKEVALUE(x, S_MC_DLL_DEFAULT) +#define G_MC_DLL_DEFAULT(x) _SB_GETVALUE(x, S_MC_DLL_DEFAULT, M_MC_DLL_DEFAULT) +#define V_MC_DLL_DEFAULT_DEFAULT V_MC_DLL_DEFAULT(0x10) + +#define V_MC_CLKCONFIG_DEFAULT V_MC_DLL_DEFAULT_DEFAULT | \ + V_MC_ADDR_SKEW_DEFAULT | \ + V_MC_DQO_SKEW_DEFAULT | \ + V_MC_DQI_SKEW_DEFAULT | \ + V_MC_ADDR_DRIVE_DEFAULT | \ + V_MC_DATA_DRIVE_DEFAULT | \ + V_MC_CLOCK_DRIVE_DEFAULT | \ + V_MC_REF_RATE_DEFAULT + + + +/* + * DRAM Command Register (Table 6-13) + */ + +#define S_MC_COMMAND 0 +#define M_MC_COMMAND _SB_MAKEMASK(4, S_MC_COMMAND) +#define V_MC_COMMAND(x) _SB_MAKEVALUE(x, S_MC_COMMAND) +#define G_MC_COMMAND(x) _SB_GETVALUE(x, S_MC_COMMAND, M_MC_COMMAND) + +#define K_MC_COMMAND_EMRS 0 +#define K_MC_COMMAND_MRS 1 +#define K_MC_COMMAND_PRE 2 +#define K_MC_COMMAND_AR 3 +#define K_MC_COMMAND_SETRFSH 4 +#define K_MC_COMMAND_CLRRFSH 5 +#define K_MC_COMMAND_SETPWRDN 6 +#define K_MC_COMMAND_CLRPWRDN 7 + +#define V_MC_COMMAND_EMRS V_MC_COMMAND(K_MC_COMMAND_EMRS) +#define V_MC_COMMAND_MRS V_MC_COMMAND(K_MC_COMMAND_MRS) +#define V_MC_COMMAND_PRE V_MC_COMMAND(K_MC_COMMAND_PRE) +#define V_MC_COMMAND_AR V_MC_COMMAND(K_MC_COMMAND_AR) +#define V_MC_COMMAND_SETRFSH V_MC_COMMAND(K_MC_COMMAND_SETRFSH) +#define V_MC_COMMAND_CLRRFSH V_MC_COMMAND(K_MC_COMMAND_CLRRFSH) +#define V_MC_COMMAND_SETPWRDN V_MC_COMMAND(K_MC_COMMAND_SETPWRDN) +#define V_MC_COMMAND_CLRPWRDN V_MC_COMMAND(K_MC_COMMAND_CLRPWRDN) + +#define M_MC_CS0 _SB_MAKEMASK1(4) +#define M_MC_CS1 _SB_MAKEMASK1(5) +#define M_MC_CS2 _SB_MAKEMASK1(6) +#define M_MC_CS3 _SB_MAKEMASK1(7) + +/* + * DRAM Mode Register (Table 6-14) + */ + +#define S_MC_EMODE 0 +#define M_MC_EMODE _SB_MAKEMASK(15, S_MC_EMODE) +#define V_MC_EMODE(x) _SB_MAKEVALUE(x, S_MC_EMODE) +#define G_MC_EMODE(x) _SB_GETVALUE(x, S_MC_EMODE, M_MC_EMODE) +#define V_MC_EMODE_DEFAULT V_MC_EMODE(0) + +#define S_MC_MODE 16 +#define M_MC_MODE _SB_MAKEMASK(15, S_MC_MODE) +#define V_MC_MODE(x) _SB_MAKEVALUE(x, S_MC_MODE) +#define G_MC_MODE(x) _SB_GETVALUE(x, S_MC_MODE, M_MC_MODE) +#define V_MC_MODE_DEFAULT V_MC_MODE(0x22) + +#define S_MC_DRAM_TYPE 32 +#define M_MC_DRAM_TYPE _SB_MAKEMASK(3, S_MC_DRAM_TYPE) +#define V_MC_DRAM_TYPE(x) _SB_MAKEVALUE(x, S_MC_DRAM_TYPE) +#define G_MC_DRAM_TYPE(x) _SB_GETVALUE(x, S_MC_DRAM_TYPE, M_MC_DRAM_TYPE) + +#define K_MC_DRAM_TYPE_JEDEC 0 +#define K_MC_DRAM_TYPE_FCRAM 1 +#define K_MC_DRAM_TYPE_SGRAM 2 + +#define V_MC_DRAM_TYPE_JEDEC V_MC_DRAM_TYPE(K_MC_DRAM_TYPE_JEDEC) +#define V_MC_DRAM_TYPE_FCRAM V_MC_DRAM_TYPE(K_MC_DRAM_TYPE_FCRAM) +#define V_MC_DRAM_TYPE_SGRAM V_MC_DRAM_TYPE(K_MC_DRAM_TYPE_SGRAM) + +#define M_MC_EXTERNALDECODE _SB_MAKEMASK1(35) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define M_MC_PRE_ON_A8 _SB_MAKEMASK1(36) +#define M_MC_RAM_WITH_A13 _SB_MAKEMASK1(37) +#endif /* 1250 PASS3 || 112x PASS1 */ + + + +/* + * SDRAM Timing Register (Table 6-15) + */ + +#define M_MC_w2rIDLE_TWOCYCLES _SB_MAKEMASK1(60) +#define M_MC_r2wIDLE_TWOCYCLES _SB_MAKEMASK1(61) +#define M_MC_r2rIDLE_TWOCYCLES _SB_MAKEMASK1(62) + +#define S_MC_tFIFO 56 +#define M_MC_tFIFO _SB_MAKEMASK(4, S_MC_tFIFO) +#define V_MC_tFIFO(x) _SB_MAKEVALUE(x, S_MC_tFIFO) +#define G_MC_tFIFO(x) _SB_GETVALUE(x, S_MC_tFIFO, M_MC_tFIFO) +#define K_MC_tFIFO_DEFAULT 1 +#define V_MC_tFIFO_DEFAULT V_MC_tFIFO(K_MC_tFIFO_DEFAULT) + +#define S_MC_tRFC 52 +#define M_MC_tRFC _SB_MAKEMASK(4, S_MC_tRFC) +#define V_MC_tRFC(x) _SB_MAKEVALUE(x, S_MC_tRFC) +#define G_MC_tRFC(x) _SB_GETVALUE(x, S_MC_tRFC, M_MC_tRFC) +#define K_MC_tRFC_DEFAULT 12 +#define V_MC_tRFC_DEFAULT V_MC_tRFC(K_MC_tRFC_DEFAULT) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) +#define M_MC_tRFC_PLUS16 _SB_MAKEMASK1(51) /* 1250C3 and later. */ +#endif + +#define S_MC_tCwCr 40 +#define M_MC_tCwCr _SB_MAKEMASK(4, S_MC_tCwCr) +#define V_MC_tCwCr(x) _SB_MAKEVALUE(x, S_MC_tCwCr) +#define G_MC_tCwCr(x) _SB_GETVALUE(x, S_MC_tCwCr, M_MC_tCwCr) +#define K_MC_tCwCr_DEFAULT 4 +#define V_MC_tCwCr_DEFAULT V_MC_tCwCr(K_MC_tCwCr_DEFAULT) + +#define S_MC_tRCr 28 +#define M_MC_tRCr _SB_MAKEMASK(4, S_MC_tRCr) +#define V_MC_tRCr(x) _SB_MAKEVALUE(x, S_MC_tRCr) +#define G_MC_tRCr(x) _SB_GETVALUE(x, S_MC_tRCr, M_MC_tRCr) +#define K_MC_tRCr_DEFAULT 9 +#define V_MC_tRCr_DEFAULT V_MC_tRCr(K_MC_tRCr_DEFAULT) + +#define S_MC_tRCw 24 +#define M_MC_tRCw _SB_MAKEMASK(4, S_MC_tRCw) +#define V_MC_tRCw(x) _SB_MAKEVALUE(x, S_MC_tRCw) +#define G_MC_tRCw(x) _SB_GETVALUE(x, S_MC_tRCw, M_MC_tRCw) +#define K_MC_tRCw_DEFAULT 10 +#define V_MC_tRCw_DEFAULT V_MC_tRCw(K_MC_tRCw_DEFAULT) + +#define S_MC_tRRD 20 +#define M_MC_tRRD _SB_MAKEMASK(4, S_MC_tRRD) +#define V_MC_tRRD(x) _SB_MAKEVALUE(x, S_MC_tRRD) +#define G_MC_tRRD(x) _SB_GETVALUE(x, S_MC_tRRD, M_MC_tRRD) +#define K_MC_tRRD_DEFAULT 2 +#define V_MC_tRRD_DEFAULT V_MC_tRRD(K_MC_tRRD_DEFAULT) + +#define S_MC_tRP 16 +#define M_MC_tRP _SB_MAKEMASK(4, S_MC_tRP) +#define V_MC_tRP(x) _SB_MAKEVALUE(x, S_MC_tRP) +#define G_MC_tRP(x) _SB_GETVALUE(x, S_MC_tRP, M_MC_tRP) +#define K_MC_tRP_DEFAULT 4 +#define V_MC_tRP_DEFAULT V_MC_tRP(K_MC_tRP_DEFAULT) + +#define S_MC_tCwD 8 +#define M_MC_tCwD _SB_MAKEMASK(4, S_MC_tCwD) +#define V_MC_tCwD(x) _SB_MAKEVALUE(x, S_MC_tCwD) +#define G_MC_tCwD(x) _SB_GETVALUE(x, S_MC_tCwD, M_MC_tCwD) +#define K_MC_tCwD_DEFAULT 1 +#define V_MC_tCwD_DEFAULT V_MC_tCwD(K_MC_tCwD_DEFAULT) + +#define M_tCrDh _SB_MAKEMASK1(7) +#define M_MC_tCrDh M_tCrDh + +#define S_MC_tCrD 4 +#define M_MC_tCrD _SB_MAKEMASK(3, S_MC_tCrD) +#define V_MC_tCrD(x) _SB_MAKEVALUE(x, S_MC_tCrD) +#define G_MC_tCrD(x) _SB_GETVALUE(x, S_MC_tCrD, M_MC_tCrD) +#define K_MC_tCrD_DEFAULT 2 +#define V_MC_tCrD_DEFAULT V_MC_tCrD(K_MC_tCrD_DEFAULT) + +#define S_MC_tRCD 0 +#define M_MC_tRCD _SB_MAKEMASK(4, S_MC_tRCD) +#define V_MC_tRCD(x) _SB_MAKEVALUE(x, S_MC_tRCD) +#define G_MC_tRCD(x) _SB_GETVALUE(x, S_MC_tRCD, M_MC_tRCD) +#define K_MC_tRCD_DEFAULT 3 +#define V_MC_tRCD_DEFAULT V_MC_tRCD(K_MC_tRCD_DEFAULT) + +#define V_MC_TIMING_DEFAULT V_MC_tFIFO(K_MC_tFIFO_DEFAULT) | \ + V_MC_tRFC(K_MC_tRFC_DEFAULT) | \ + V_MC_tCwCr(K_MC_tCwCr_DEFAULT) | \ + V_MC_tRCr(K_MC_tRCr_DEFAULT) | \ + V_MC_tRCw(K_MC_tRCw_DEFAULT) | \ + V_MC_tRRD(K_MC_tRRD_DEFAULT) | \ + V_MC_tRP(K_MC_tRP_DEFAULT) | \ + V_MC_tCwD(K_MC_tCwD_DEFAULT) | \ + V_MC_tCrD(K_MC_tCrD_DEFAULT) | \ + V_MC_tRCD(K_MC_tRCD_DEFAULT) | \ + M_MC_r2rIDLE_TWOCYCLES + +/* + * Errata says these are not the default + * M_MC_w2rIDLE_TWOCYCLES | \ + * M_MC_r2wIDLE_TWOCYCLES | \ + */ + + +/* + * Chip Select Start Address Register (Table 6-17) + */ + +#define S_MC_CS0_START 0 +#define M_MC_CS0_START _SB_MAKEMASK(16, S_MC_CS0_START) +#define V_MC_CS0_START(x) _SB_MAKEVALUE(x, S_MC_CS0_START) +#define G_MC_CS0_START(x) _SB_GETVALUE(x, S_MC_CS0_START, M_MC_CS0_START) + +#define S_MC_CS1_START 16 +#define M_MC_CS1_START _SB_MAKEMASK(16, S_MC_CS1_START) +#define V_MC_CS1_START(x) _SB_MAKEVALUE(x, S_MC_CS1_START) +#define G_MC_CS1_START(x) _SB_GETVALUE(x, S_MC_CS1_START, M_MC_CS1_START) + +#define S_MC_CS2_START 32 +#define M_MC_CS2_START _SB_MAKEMASK(16, S_MC_CS2_START) +#define V_MC_CS2_START(x) _SB_MAKEVALUE(x, S_MC_CS2_START) +#define G_MC_CS2_START(x) _SB_GETVALUE(x, S_MC_CS2_START, M_MC_CS2_START) + +#define S_MC_CS3_START 48 +#define M_MC_CS3_START _SB_MAKEMASK(16, S_MC_CS3_START) +#define V_MC_CS3_START(x) _SB_MAKEVALUE(x, S_MC_CS3_START) +#define G_MC_CS3_START(x) _SB_GETVALUE(x, S_MC_CS3_START, M_MC_CS3_START) + +/* + * Chip Select End Address Register (Table 6-18) + */ + +#define S_MC_CS0_END 0 +#define M_MC_CS0_END _SB_MAKEMASK(16, S_MC_CS0_END) +#define V_MC_CS0_END(x) _SB_MAKEVALUE(x, S_MC_CS0_END) +#define G_MC_CS0_END(x) _SB_GETVALUE(x, S_MC_CS0_END, M_MC_CS0_END) + +#define S_MC_CS1_END 16 +#define M_MC_CS1_END _SB_MAKEMASK(16, S_MC_CS1_END) +#define V_MC_CS1_END(x) _SB_MAKEVALUE(x, S_MC_CS1_END) +#define G_MC_CS1_END(x) _SB_GETVALUE(x, S_MC_CS1_END, M_MC_CS1_END) + +#define S_MC_CS2_END 32 +#define M_MC_CS2_END _SB_MAKEMASK(16, S_MC_CS2_END) +#define V_MC_CS2_END(x) _SB_MAKEVALUE(x, S_MC_CS2_END) +#define G_MC_CS2_END(x) _SB_GETVALUE(x, S_MC_CS2_END, M_MC_CS2_END) + +#define S_MC_CS3_END 48 +#define M_MC_CS3_END _SB_MAKEMASK(16, S_MC_CS3_END) +#define V_MC_CS3_END(x) _SB_MAKEVALUE(x, S_MC_CS3_END) +#define G_MC_CS3_END(x) _SB_GETVALUE(x, S_MC_CS3_END, M_MC_CS3_END) + +/* + * Chip Select Interleave Register (Table 6-19) + */ + +#define S_MC_INTLV_RESERVED 0 +#define M_MC_INTLV_RESERVED _SB_MAKEMASK(5, S_MC_INTLV_RESERVED) + +#define S_MC_INTERLEAVE 7 +#define M_MC_INTERLEAVE _SB_MAKEMASK(18, S_MC_INTERLEAVE) +#define V_MC_INTERLEAVE(x) _SB_MAKEVALUE(x, S_MC_INTERLEAVE) + +#define S_MC_INTLV_MBZ 25 +#define M_MC_INTLV_MBZ _SB_MAKEMASK(39, S_MC_INTLV_MBZ) + +/* + * Row Address Bits Register (Table 6-20) + */ + +#define S_MC_RAS_RESERVED 0 +#define M_MC_RAS_RESERVED _SB_MAKEMASK(5, S_MC_RAS_RESERVED) + +#define S_MC_RAS_SELECT 12 +#define M_MC_RAS_SELECT _SB_MAKEMASK(25, S_MC_RAS_SELECT) +#define V_MC_RAS_SELECT(x) _SB_MAKEVALUE(x, S_MC_RAS_SELECT) + +#define S_MC_RAS_MBZ 37 +#define M_MC_RAS_MBZ _SB_MAKEMASK(27, S_MC_RAS_MBZ) + + +/* + * Column Address Bits Register (Table 6-21) + */ + +#define S_MC_CAS_RESERVED 0 +#define M_MC_CAS_RESERVED _SB_MAKEMASK(5, S_MC_CAS_RESERVED) + +#define S_MC_CAS_SELECT 5 +#define M_MC_CAS_SELECT _SB_MAKEMASK(18, S_MC_CAS_SELECT) +#define V_MC_CAS_SELECT(x) _SB_MAKEVALUE(x, S_MC_CAS_SELECT) + +#define S_MC_CAS_MBZ 23 +#define M_MC_CAS_MBZ _SB_MAKEMASK(41, S_MC_CAS_MBZ) + + +/* + * Bank Address Address Bits Register (Table 6-22) + */ + +#define S_MC_BA_RESERVED 0 +#define M_MC_BA_RESERVED _SB_MAKEMASK(5, S_MC_BA_RESERVED) + +#define S_MC_BA_SELECT 5 +#define M_MC_BA_SELECT _SB_MAKEMASK(20, S_MC_BA_SELECT) +#define V_MC_BA_SELECT(x) _SB_MAKEVALUE(x, S_MC_BA_SELECT) + +#define S_MC_BA_MBZ 25 +#define M_MC_BA_MBZ _SB_MAKEMASK(39, S_MC_BA_MBZ) + +/* + * Chip Select Attribute Register (Table 6-23) + */ + +#define K_MC_CS_ATTR_CLOSED 0 +#define K_MC_CS_ATTR_CASCHECK 1 +#define K_MC_CS_ATTR_HINT 2 +#define K_MC_CS_ATTR_OPEN 3 + +#define S_MC_CS0_PAGE 0 +#define M_MC_CS0_PAGE _SB_MAKEMASK(2, S_MC_CS0_PAGE) +#define V_MC_CS0_PAGE(x) _SB_MAKEVALUE(x, S_MC_CS0_PAGE) +#define G_MC_CS0_PAGE(x) _SB_GETVALUE(x, S_MC_CS0_PAGE, M_MC_CS0_PAGE) + +#define S_MC_CS1_PAGE 16 +#define M_MC_CS1_PAGE _SB_MAKEMASK(2, S_MC_CS1_PAGE) +#define V_MC_CS1_PAGE(x) _SB_MAKEVALUE(x, S_MC_CS1_PAGE) +#define G_MC_CS1_PAGE(x) _SB_GETVALUE(x, S_MC_CS1_PAGE, M_MC_CS1_PAGE) + +#define S_MC_CS2_PAGE 32 +#define M_MC_CS2_PAGE _SB_MAKEMASK(2, S_MC_CS2_PAGE) +#define V_MC_CS2_PAGE(x) _SB_MAKEVALUE(x, S_MC_CS2_PAGE) +#define G_MC_CS2_PAGE(x) _SB_GETVALUE(x, S_MC_CS2_PAGE, M_MC_CS2_PAGE) + +#define S_MC_CS3_PAGE 48 +#define M_MC_CS3_PAGE _SB_MAKEMASK(2, S_MC_CS3_PAGE) +#define V_MC_CS3_PAGE(x) _SB_MAKEVALUE(x, S_MC_CS3_PAGE) +#define G_MC_CS3_PAGE(x) _SB_GETVALUE(x, S_MC_CS3_PAGE, M_MC_CS3_PAGE) + +/* + * ECC Test ECC Register (Table 6-25) + */ + +#define S_MC_ECC_INVERT 0 +#define M_MC_ECC_INVERT _SB_MAKEMASK(8, S_MC_ECC_INVERT) + + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_regs.h b/arch/mips/include/asm/sibyte/sb1250_regs.h new file mode 100644 index 00000000000..8f53ec817a5 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_regs.h @@ -0,0 +1,893 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Register Definitions File: sb1250_regs.h + * + * This module contains the addresses of the on-chip peripherals + * on the SB1250. + * + * SB1250 specification level: 01/02/2002 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_REGS_H +#define _SB1250_REGS_H + +#include "sb1250_defs.h" + + +/* ********************************************************************* + * Some general notes: + * + * For the most part, when there is more than one peripheral + * of the same type on the SOC, the constants below will be + * offsets from the base of each peripheral. For example, + * the MAC registers are described as offsets from the first + * MAC register, and there will be a MAC_REGISTER() macro + * to calculate the base address of a given MAC. + * + * The information in this file is based on the SB1250 SOC + * manual version 0.2, July 2000. + ********************************************************************* */ + + +/* ********************************************************************* + * Memory Controller Registers + ********************************************************************* */ + +/* + * XXX: can't remove MC base 0 if 112x, since it's used by other macros, + * since there is one reg there (but it could get its addr/offset constant). + */ + +#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */ +#define A_MC_BASE_0 0x0010051000 +#define A_MC_BASE_1 0x0010052000 +#define MC_REGISTER_SPACING 0x1000 + +#define A_MC_BASE(ctlid) ((ctlid)*MC_REGISTER_SPACING+A_MC_BASE_0) +#define A_MC_REGISTER(ctlid, reg) (A_MC_BASE(ctlid)+(reg)) + +#define R_MC_CONFIG 0x0000000100 +#define R_MC_DRAMCMD 0x0000000120 +#define R_MC_DRAMMODE 0x0000000140 +#define R_MC_TIMING1 0x0000000160 +#define R_MC_TIMING2 0x0000000180 +#define R_MC_CS_START 0x00000001A0 +#define R_MC_CS_END 0x00000001C0 +#define R_MC_CS_INTERLEAVE 0x00000001E0 +#define S_MC_CS_STARTEND 16 + +#define R_MC_CSX_BASE 0x0000000200 +#define R_MC_CSX_ROW 0x0000000000 /* relative to CSX_BASE, above */ +#define R_MC_CSX_COL 0x0000000020 /* relative to CSX_BASE, above */ +#define R_MC_CSX_BA 0x0000000040 /* relative to CSX_BASE, above */ +#define MC_CSX_SPACING 0x0000000060 /* relative to CSX_BASE, above */ + +#define R_MC_CS0_ROW 0x0000000200 +#define R_MC_CS0_COL 0x0000000220 +#define R_MC_CS0_BA 0x0000000240 +#define R_MC_CS1_ROW 0x0000000260 +#define R_MC_CS1_COL 0x0000000280 +#define R_MC_CS1_BA 0x00000002A0 +#define R_MC_CS2_ROW 0x00000002C0 +#define R_MC_CS2_COL 0x00000002E0 +#define R_MC_CS2_BA 0x0000000300 +#define R_MC_CS3_ROW 0x0000000320 +#define R_MC_CS3_COL 0x0000000340 +#define R_MC_CS3_BA 0x0000000360 +#define R_MC_CS_ATTR 0x0000000380 +#define R_MC_TEST_DATA 0x0000000400 +#define R_MC_TEST_ECC 0x0000000420 +#define R_MC_MCLK_CFG 0x0000000500 + +#endif /* 1250 & 112x */ + +/* ********************************************************************* + * L2 Cache Control Registers + ********************************************************************* */ + +#if SIBYTE_HDR_FEATURE_1250_112x /* This L2C only on 1250/112x */ + +#define A_L2_READ_TAG 0x0010040018 +#define A_L2_ECC_TAG 0x0010040038 +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define A_L2_READ_MISC 0x0010040058 +#endif /* 1250 PASS3 || 112x PASS1 */ +#define A_L2_WAY_DISABLE 0x0010041000 +#define A_L2_MAKEDISABLE(x) (A_L2_WAY_DISABLE | (((~(x))&0x0F) << 8)) +#define A_L2_MGMT_TAG_BASE 0x00D0000000 + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define A_L2_CACHE_DISABLE 0x0010042000 +#define A_L2_MAKECACHEDISABLE(x) (A_L2_CACHE_DISABLE | (((x)&0x0F) << 8)) +#define A_L2_MISC_CONFIG 0x0010043000 +#endif /* 1250 PASS2 || 112x PASS1 */ + +/* Backward-compatibility definitions. */ +/* XXX: discourage people from using these constants. */ +#define A_L2_READ_ADDRESS A_L2_READ_TAG +#define A_L2_EEC_ADDRESS A_L2_ECC_TAG + +#endif + + +/* ********************************************************************* + * PCI Interface Registers + ********************************************************************* */ + +#if SIBYTE_HDR_FEATURE_1250_112x /* This PCI/HT only on 1250/112x */ +#define A_PCI_TYPE00_HEADER 0x00DE000000 +#define A_PCI_TYPE01_HEADER 0x00DE000800 +#endif + + +/* ********************************************************************* + * Ethernet DMA and MACs + ********************************************************************* */ + +#define A_MAC_BASE_0 0x0010064000 +#define A_MAC_BASE_1 0x0010065000 +#if SIBYTE_HDR_FEATURE_CHIP(1250) +#define A_MAC_BASE_2 0x0010066000 +#endif /* 1250 */ + +#define MAC_SPACING 0x1000 +#define MAC_DMA_TXRX_SPACING 0x0400 +#define MAC_DMA_CHANNEL_SPACING 0x0100 +#define DMA_RX 0 +#define DMA_TX 1 +#define MAC_NUM_DMACHAN 2 /* channels per direction */ + +/* XXX: not correct; depends on SOC type. */ +#define MAC_NUM_PORTS 3 + +#define A_MAC_CHANNEL_BASE(macnum) \ + (A_MAC_BASE_0 + \ + MAC_SPACING*(macnum)) + +#define A_MAC_REGISTER(macnum,reg) \ + (A_MAC_BASE_0 + \ + MAC_SPACING*(macnum) + (reg)) + + +#define R_MAC_DMA_CHANNELS 0x800 /* Relative to A_MAC_CHANNEL_BASE */ + +#define A_MAC_DMA_CHANNEL_BASE(macnum, txrx, chan) \ + ((A_MAC_CHANNEL_BASE(macnum)) + \ + R_MAC_DMA_CHANNELS + \ + (MAC_DMA_TXRX_SPACING*(txrx)) + \ + (MAC_DMA_CHANNEL_SPACING*(chan))) + +#define R_MAC_DMA_CHANNEL_BASE(txrx, chan) \ + (R_MAC_DMA_CHANNELS + \ + (MAC_DMA_TXRX_SPACING*(txrx)) + \ + (MAC_DMA_CHANNEL_SPACING*(chan))) + +#define A_MAC_DMA_REGISTER(macnum, txrx, chan, reg) \ + (A_MAC_DMA_CHANNEL_BASE(macnum, txrx, chan) + \ + (reg)) + +#define R_MAC_DMA_REGISTER(txrx, chan, reg) \ + (R_MAC_DMA_CHANNEL_BASE(txrx, chan) + \ + (reg)) + +/* + * DMA channel registers, relative to A_MAC_DMA_CHANNEL_BASE + */ + +#define R_MAC_DMA_CONFIG0 0x00000000 +#define R_MAC_DMA_CONFIG1 0x00000008 +#define R_MAC_DMA_DSCR_BASE 0x00000010 +#define R_MAC_DMA_DSCR_CNT 0x00000018 +#define R_MAC_DMA_CUR_DSCRA 0x00000020 +#define R_MAC_DMA_CUR_DSCRB 0x00000028 +#define R_MAC_DMA_CUR_DSCRADDR 0x00000030 +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define R_MAC_DMA_OODPKTLOST_RX 0x00000038 /* rx only */ +#endif /* 1250 PASS3 || 112x PASS1 */ + +/* + * RMON Counters + */ + +#define R_MAC_RMON_TX_BYTES 0x00000000 +#define R_MAC_RMON_COLLISIONS 0x00000008 +#define R_MAC_RMON_LATE_COL 0x00000010 +#define R_MAC_RMON_EX_COL 0x00000018 +#define R_MAC_RMON_FCS_ERROR 0x00000020 +#define R_MAC_RMON_TX_ABORT 0x00000028 +/* Counter #6 (0x30) now reserved */ +#define R_MAC_RMON_TX_BAD 0x00000038 +#define R_MAC_RMON_TX_GOOD 0x00000040 +#define R_MAC_RMON_TX_RUNT 0x00000048 +#define R_MAC_RMON_TX_OVERSIZE 0x00000050 +#define R_MAC_RMON_RX_BYTES 0x00000080 +#define R_MAC_RMON_RX_MCAST 0x00000088 +#define R_MAC_RMON_RX_BCAST 0x00000090 +#define R_MAC_RMON_RX_BAD 0x00000098 +#define R_MAC_RMON_RX_GOOD 0x000000A0 +#define R_MAC_RMON_RX_RUNT 0x000000A8 +#define R_MAC_RMON_RX_OVERSIZE 0x000000B0 +#define R_MAC_RMON_RX_FCS_ERROR 0x000000B8 +#define R_MAC_RMON_RX_LENGTH_ERROR 0x000000C0 +#define R_MAC_RMON_RX_CODE_ERROR 0x000000C8 +#define R_MAC_RMON_RX_ALIGN_ERROR 0x000000D0 + +/* Updated to spec 0.2 */ +#define R_MAC_CFG 0x00000100 +#define R_MAC_THRSH_CFG 0x00000108 +#define R_MAC_VLANTAG 0x00000110 +#define R_MAC_FRAMECFG 0x00000118 +#define R_MAC_EOPCNT 0x00000120 +#define R_MAC_FIFO_PTRS 0x00000128 +#define R_MAC_ADFILTER_CFG 0x00000200 +#define R_MAC_ETHERNET_ADDR 0x00000208 +#define R_MAC_PKT_TYPE 0x00000210 +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define R_MAC_ADMASK0 0x00000218 +#define R_MAC_ADMASK1 0x00000220 +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ +#define R_MAC_HASH_BASE 0x00000240 +#define R_MAC_ADDR_BASE 0x00000280 +#define R_MAC_CHLO0_BASE 0x00000300 +#define R_MAC_CHUP0_BASE 0x00000320 +#define R_MAC_ENABLE 0x00000400 +#define R_MAC_STATUS 0x00000408 +#define R_MAC_INT_MASK 0x00000410 +#define R_MAC_TXD_CTL 0x00000420 +#define R_MAC_MDIO 0x00000428 +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define R_MAC_STATUS1 0x00000430 +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ +#define R_MAC_DEBUG_STATUS 0x00000448 + +#define MAC_HASH_COUNT 8 +#define MAC_ADDR_COUNT 8 +#define MAC_CHMAP_COUNT 4 + + +/* ********************************************************************* + * DUART Registers + ********************************************************************* */ + + +#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */ +#define R_DUART_NUM_PORTS 2 + +#define A_DUART 0x0010060000 + +#define DUART_CHANREG_SPACING 0x100 + +#define A_DUART_CHANREG(chan, reg) \ + (A_DUART + DUART_CHANREG_SPACING * ((chan) + 1) + (reg)) +#endif /* 1250 & 112x */ + +#define R_DUART_MODE_REG_1 0x000 +#define R_DUART_MODE_REG_2 0x010 +#define R_DUART_STATUS 0x020 +#define R_DUART_CLK_SEL 0x030 +#define R_DUART_CMD 0x050 +#define R_DUART_RX_HOLD 0x060 +#define R_DUART_TX_HOLD 0x070 + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define R_DUART_FULL_CTL 0x040 +#define R_DUART_OPCR_X 0x080 +#define R_DUART_AUXCTL_X 0x090 +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + + +/* + * The IMR and ISR can't be addressed with A_DUART_CHANREG, + * so use these macros instead. + */ + +#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */ +#define DUART_IMRISR_SPACING 0x20 +#define DUART_INCHNG_SPACING 0x10 + +#define A_DUART_CTRLREG(reg) \ + (A_DUART + DUART_CHANREG_SPACING * 3 + (reg)) + +#define R_DUART_IMRREG(chan) \ + (R_DUART_IMR_A + (chan) * DUART_IMRISR_SPACING) +#define R_DUART_ISRREG(chan) \ + (R_DUART_ISR_A + (chan) * DUART_IMRISR_SPACING) +#define R_DUART_INCHREG(chan) \ + (R_DUART_IN_CHNG_A + (chan) * DUART_INCHNG_SPACING) + +#define A_DUART_IMRREG(chan) A_DUART_CTRLREG(R_DUART_IMRREG(chan)) +#define A_DUART_ISRREG(chan) A_DUART_CTRLREG(R_DUART_ISRREG(chan)) +#define A_DUART_INCHREG(chan) A_DUART_CTRLREG(R_DUART_INCHREG(chan)) +#endif /* 1250 & 112x */ + +#define R_DUART_AUX_CTRL 0x010 +#define R_DUART_ISR_A 0x020 +#define R_DUART_IMR_A 0x030 +#define R_DUART_ISR_B 0x040 +#define R_DUART_IMR_B 0x050 +#define R_DUART_OUT_PORT 0x060 +#define R_DUART_OPCR 0x070 +#define R_DUART_IN_PORT 0x080 + +#define R_DUART_SET_OPR 0x0B0 +#define R_DUART_CLEAR_OPR 0x0C0 +#define R_DUART_IN_CHNG_A 0x0D0 +#define R_DUART_IN_CHNG_B 0x0E0 + + +/* + * These constants are the absolute addresses. + */ + +#define A_DUART_MODE_REG_1_A 0x0010060100 +#define A_DUART_MODE_REG_2_A 0x0010060110 +#define A_DUART_STATUS_A 0x0010060120 +#define A_DUART_CLK_SEL_A 0x0010060130 +#define A_DUART_CMD_A 0x0010060150 +#define A_DUART_RX_HOLD_A 0x0010060160 +#define A_DUART_TX_HOLD_A 0x0010060170 + +#define A_DUART_MODE_REG_1_B 0x0010060200 +#define A_DUART_MODE_REG_2_B 0x0010060210 +#define A_DUART_STATUS_B 0x0010060220 +#define A_DUART_CLK_SEL_B 0x0010060230 +#define A_DUART_CMD_B 0x0010060250 +#define A_DUART_RX_HOLD_B 0x0010060260 +#define A_DUART_TX_HOLD_B 0x0010060270 + +#define A_DUART_INPORT_CHNG 0x0010060300 +#define A_DUART_AUX_CTRL 0x0010060310 +#define A_DUART_ISR_A 0x0010060320 +#define A_DUART_IMR_A 0x0010060330 +#define A_DUART_ISR_B 0x0010060340 +#define A_DUART_IMR_B 0x0010060350 +#define A_DUART_OUT_PORT 0x0010060360 +#define A_DUART_OPCR 0x0010060370 +#define A_DUART_IN_PORT 0x0010060380 +#define A_DUART_ISR 0x0010060390 +#define A_DUART_IMR 0x00100603A0 +#define A_DUART_SET_OPR 0x00100603B0 +#define A_DUART_CLEAR_OPR 0x00100603C0 +#define A_DUART_INPORT_CHNG_A 0x00100603D0 +#define A_DUART_INPORT_CHNG_B 0x00100603E0 + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define A_DUART_FULL_CTL_A 0x0010060140 +#define A_DUART_FULL_CTL_B 0x0010060240 + +#define A_DUART_OPCR_A 0x0010060180 +#define A_DUART_OPCR_B 0x0010060280 + +#define A_DUART_INPORT_CHNG_DEBUG 0x00100603F0 +#endif /* 1250 PASS2 || 112x PASS1 */ + + +/* ********************************************************************* + * Synchronous Serial Registers + ********************************************************************* */ + + +#if SIBYTE_HDR_FEATURE_1250_112x /* sync serial only on 1250/112x */ + +#define A_SER_BASE_0 0x0010060400 +#define A_SER_BASE_1 0x0010060800 +#define SER_SPACING 0x400 + +#define SER_DMA_TXRX_SPACING 0x80 + +#define SER_NUM_PORTS 2 + +#define A_SER_CHANNEL_BASE(sernum) \ + (A_SER_BASE_0 + \ + SER_SPACING*(sernum)) + +#define A_SER_REGISTER(sernum,reg) \ + (A_SER_BASE_0 + \ + SER_SPACING*(sernum) + (reg)) + + +#define R_SER_DMA_CHANNELS 0 /* Relative to A_SER_BASE_x */ + +#define A_SER_DMA_CHANNEL_BASE(sernum,txrx) \ + ((A_SER_CHANNEL_BASE(sernum)) + \ + R_SER_DMA_CHANNELS + \ + (SER_DMA_TXRX_SPACING*(txrx))) + +#define A_SER_DMA_REGISTER(sernum, txrx, reg) \ + (A_SER_DMA_CHANNEL_BASE(sernum, txrx) + \ + (reg)) + + +/* + * DMA channel registers, relative to A_SER_DMA_CHANNEL_BASE + */ + +#define R_SER_DMA_CONFIG0 0x00000000 +#define R_SER_DMA_CONFIG1 0x00000008 +#define R_SER_DMA_DSCR_BASE 0x00000010 +#define R_SER_DMA_DSCR_CNT 0x00000018 +#define R_SER_DMA_CUR_DSCRA 0x00000020 +#define R_SER_DMA_CUR_DSCRB 0x00000028 +#define R_SER_DMA_CUR_DSCRADDR 0x00000030 + +#define R_SER_DMA_CONFIG0_RX 0x00000000 +#define R_SER_DMA_CONFIG1_RX 0x00000008 +#define R_SER_DMA_DSCR_BASE_RX 0x00000010 +#define R_SER_DMA_DSCR_COUNT_RX 0x00000018 +#define R_SER_DMA_CUR_DSCR_A_RX 0x00000020 +#define R_SER_DMA_CUR_DSCR_B_RX 0x00000028 +#define R_SER_DMA_CUR_DSCR_ADDR_RX 0x00000030 + +#define R_SER_DMA_CONFIG0_TX 0x00000080 +#define R_SER_DMA_CONFIG1_TX 0x00000088 +#define R_SER_DMA_DSCR_BASE_TX 0x00000090 +#define R_SER_DMA_DSCR_COUNT_TX 0x00000098 +#define R_SER_DMA_CUR_DSCR_A_TX 0x000000A0 +#define R_SER_DMA_CUR_DSCR_B_TX 0x000000A8 +#define R_SER_DMA_CUR_DSCR_ADDR_TX 0x000000B0 + +#define R_SER_MODE 0x00000100 +#define R_SER_MINFRM_SZ 0x00000108 +#define R_SER_MAXFRM_SZ 0x00000110 +#define R_SER_ADDR 0x00000118 +#define R_SER_USR0_ADDR 0x00000120 +#define R_SER_USR1_ADDR 0x00000128 +#define R_SER_USR2_ADDR 0x00000130 +#define R_SER_USR3_ADDR 0x00000138 +#define R_SER_CMD 0x00000140 +#define R_SER_TX_RD_THRSH 0x00000160 +#define R_SER_TX_WR_THRSH 0x00000168 +#define R_SER_RX_RD_THRSH 0x00000170 +#define R_SER_LINE_MODE 0x00000178 +#define R_SER_DMA_ENABLE 0x00000180 +#define R_SER_INT_MASK 0x00000190 +#define R_SER_STATUS 0x00000188 +#define R_SER_STATUS_DEBUG 0x000001A8 +#define R_SER_RX_TABLE_BASE 0x00000200 +#define SER_RX_TABLE_COUNT 16 +#define R_SER_TX_TABLE_BASE 0x00000300 +#define SER_TX_TABLE_COUNT 16 + +/* RMON Counters */ +#define R_SER_RMON_TX_BYTE_LO 0x000001C0 +#define R_SER_RMON_TX_BYTE_HI 0x000001C8 +#define R_SER_RMON_RX_BYTE_LO 0x000001D0 +#define R_SER_RMON_RX_BYTE_HI 0x000001D8 +#define R_SER_RMON_TX_UNDERRUN 0x000001E0 +#define R_SER_RMON_RX_OVERFLOW 0x000001E8 +#define R_SER_RMON_RX_ERRORS 0x000001F0 +#define R_SER_RMON_RX_BADADDR 0x000001F8 + +#endif /* 1250/112x */ + +/* ********************************************************************* + * Generic Bus Registers + ********************************************************************* */ + +#define IO_EXT_CFG_COUNT 8 + +#define A_IO_EXT_BASE 0x0010061000 +#define A_IO_EXT_REG(r) (A_IO_EXT_BASE + (r)) + +#define A_IO_EXT_CFG_BASE 0x0010061000 +#define A_IO_EXT_MULT_SIZE_BASE 0x0010061100 +#define A_IO_EXT_START_ADDR_BASE 0x0010061200 +#define A_IO_EXT_TIME_CFG0_BASE 0x0010061600 +#define A_IO_EXT_TIME_CFG1_BASE 0x0010061700 + +#define IO_EXT_REGISTER_SPACING 8 +#define A_IO_EXT_CS_BASE(cs) (A_IO_EXT_CFG_BASE+IO_EXT_REGISTER_SPACING*(cs)) +#define R_IO_EXT_REG(reg, cs) ((cs)*IO_EXT_REGISTER_SPACING + (reg)) + +#define R_IO_EXT_CFG 0x0000 +#define R_IO_EXT_MULT_SIZE 0x0100 +#define R_IO_EXT_START_ADDR 0x0200 +#define R_IO_EXT_TIME_CFG0 0x0600 +#define R_IO_EXT_TIME_CFG1 0x0700 + + +#define A_IO_INTERRUPT_STATUS 0x0010061A00 +#define A_IO_INTERRUPT_DATA0 0x0010061A10 +#define A_IO_INTERRUPT_DATA1 0x0010061A18 +#define A_IO_INTERRUPT_DATA2 0x0010061A20 +#define A_IO_INTERRUPT_DATA3 0x0010061A28 +#define A_IO_INTERRUPT_ADDR0 0x0010061A30 +#define A_IO_INTERRUPT_ADDR1 0x0010061A40 +#define A_IO_INTERRUPT_PARITY 0x0010061A50 +#define A_IO_PCMCIA_CFG 0x0010061A60 +#define A_IO_PCMCIA_STATUS 0x0010061A70 +#define A_IO_DRIVE_0 0x0010061300 +#define A_IO_DRIVE_1 0x0010061308 +#define A_IO_DRIVE_2 0x0010061310 +#define A_IO_DRIVE_3 0x0010061318 +#define A_IO_DRIVE_BASE A_IO_DRIVE_0 +#define IO_DRIVE_REGISTER_SPACING 8 +#define R_IO_DRIVE(x) ((x)*IO_DRIVE_REGISTER_SPACING) +#define A_IO_DRIVE(x) (A_IO_DRIVE_BASE + R_IO_DRIVE(x)) + +#define R_IO_INTERRUPT_STATUS 0x0A00 +#define R_IO_INTERRUPT_DATA0 0x0A10 +#define R_IO_INTERRUPT_DATA1 0x0A18 +#define R_IO_INTERRUPT_DATA2 0x0A20 +#define R_IO_INTERRUPT_DATA3 0x0A28 +#define R_IO_INTERRUPT_ADDR0 0x0A30 +#define R_IO_INTERRUPT_ADDR1 0x0A40 +#define R_IO_INTERRUPT_PARITY 0x0A50 +#define R_IO_PCMCIA_CFG 0x0A60 +#define R_IO_PCMCIA_STATUS 0x0A70 + +/* ********************************************************************* + * GPIO Registers + ********************************************************************* */ + +#define A_GPIO_CLR_EDGE 0x0010061A80 +#define A_GPIO_INT_TYPE 0x0010061A88 +#define A_GPIO_INPUT_INVERT 0x0010061A90 +#define A_GPIO_GLITCH 0x0010061A98 +#define A_GPIO_READ 0x0010061AA0 +#define A_GPIO_DIRECTION 0x0010061AA8 +#define A_GPIO_PIN_CLR 0x0010061AB0 +#define A_GPIO_PIN_SET 0x0010061AB8 + +#define A_GPIO_BASE 0x0010061A80 + +#define R_GPIO_CLR_EDGE 0x00 +#define R_GPIO_INT_TYPE 0x08 +#define R_GPIO_INPUT_INVERT 0x10 +#define R_GPIO_GLITCH 0x18 +#define R_GPIO_READ 0x20 +#define R_GPIO_DIRECTION 0x28 +#define R_GPIO_PIN_CLR 0x30 +#define R_GPIO_PIN_SET 0x38 + +/* ********************************************************************* + * SMBus Registers + ********************************************************************* */ + +#define A_SMB_XTRA_0 0x0010060000 +#define A_SMB_XTRA_1 0x0010060008 +#define A_SMB_FREQ_0 0x0010060010 +#define A_SMB_FREQ_1 0x0010060018 +#define A_SMB_STATUS_0 0x0010060020 +#define A_SMB_STATUS_1 0x0010060028 +#define A_SMB_CMD_0 0x0010060030 +#define A_SMB_CMD_1 0x0010060038 +#define A_SMB_START_0 0x0010060040 +#define A_SMB_START_1 0x0010060048 +#define A_SMB_DATA_0 0x0010060050 +#define A_SMB_DATA_1 0x0010060058 +#define A_SMB_CONTROL_0 0x0010060060 +#define A_SMB_CONTROL_1 0x0010060068 +#define A_SMB_PEC_0 0x0010060070 +#define A_SMB_PEC_1 0x0010060078 + +#define A_SMB_0 0x0010060000 +#define A_SMB_1 0x0010060008 +#define SMB_REGISTER_SPACING 0x8 +#define A_SMB_BASE(idx) (A_SMB_0+(idx)*SMB_REGISTER_SPACING) +#define A_SMB_REGISTER(idx, reg) (A_SMB_BASE(idx)+(reg)) + +#define R_SMB_XTRA 0x0000000000 +#define R_SMB_FREQ 0x0000000010 +#define R_SMB_STATUS 0x0000000020 +#define R_SMB_CMD 0x0000000030 +#define R_SMB_START 0x0000000040 +#define R_SMB_DATA 0x0000000050 +#define R_SMB_CONTROL 0x0000000060 +#define R_SMB_PEC 0x0000000070 + +/* ********************************************************************* + * Timer Registers + ********************************************************************* */ + +/* + * Watchdog timers + */ + +#define A_SCD_WDOG_0 0x0010020050 +#define A_SCD_WDOG_1 0x0010020150 +#define SCD_WDOG_SPACING 0x100 +#define SCD_NUM_WDOGS 2 +#define A_SCD_WDOG_BASE(w) (A_SCD_WDOG_0+SCD_WDOG_SPACING*(w)) +#define A_SCD_WDOG_REGISTER(w, r) (A_SCD_WDOG_BASE(w) + (r)) + +#define R_SCD_WDOG_INIT 0x0000000000 +#define R_SCD_WDOG_CNT 0x0000000008 +#define R_SCD_WDOG_CFG 0x0000000010 + +#define A_SCD_WDOG_INIT_0 0x0010020050 +#define A_SCD_WDOG_CNT_0 0x0010020058 +#define A_SCD_WDOG_CFG_0 0x0010020060 + +#define A_SCD_WDOG_INIT_1 0x0010020150 +#define A_SCD_WDOG_CNT_1 0x0010020158 +#define A_SCD_WDOG_CFG_1 0x0010020160 + +/* + * Generic timers + */ + +#define A_SCD_TIMER_0 0x0010020070 +#define A_SCD_TIMER_1 0x0010020078 +#define A_SCD_TIMER_2 0x0010020170 +#define A_SCD_TIMER_3 0x0010020178 +#define SCD_NUM_TIMERS 4 +#define A_SCD_TIMER_BASE(w) (A_SCD_TIMER_0+0x08*((w)&1)+0x100*(((w)&2)>>1)) +#define A_SCD_TIMER_REGISTER(w, r) (A_SCD_TIMER_BASE(w) + (r)) + +#define R_SCD_TIMER_INIT 0x0000000000 +#define R_SCD_TIMER_CNT 0x0000000010 +#define R_SCD_TIMER_CFG 0x0000000020 + +#define A_SCD_TIMER_INIT_0 0x0010020070 +#define A_SCD_TIMER_CNT_0 0x0010020080 +#define A_SCD_TIMER_CFG_0 0x0010020090 + +#define A_SCD_TIMER_INIT_1 0x0010020078 +#define A_SCD_TIMER_CNT_1 0x0010020088 +#define A_SCD_TIMER_CFG_1 0x0010020098 + +#define A_SCD_TIMER_INIT_2 0x0010020170 +#define A_SCD_TIMER_CNT_2 0x0010020180 +#define A_SCD_TIMER_CFG_2 0x0010020190 + +#define A_SCD_TIMER_INIT_3 0x0010020178 +#define A_SCD_TIMER_CNT_3 0x0010020188 +#define A_SCD_TIMER_CFG_3 0x0010020198 + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define A_SCD_SCRATCH 0x0010020C10 +#endif /* 1250 PASS2 || 112x PASS1 */ + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define A_SCD_ZBBUS_CYCLE_COUNT 0x0010030000 +#define A_SCD_ZBBUS_CYCLE_CP0 0x0010020C00 +#define A_SCD_ZBBUS_CYCLE_CP1 0x0010020C08 +#endif + +/* ********************************************************************* + * System Control Registers + ********************************************************************* */ + +#define A_SCD_SYSTEM_REVISION 0x0010020000 +#define A_SCD_SYSTEM_CFG 0x0010020008 +#define A_SCD_SYSTEM_MANUF 0x0010038000 + +/* ********************************************************************* + * System Address Trap Registers + ********************************************************************* */ + +#define A_ADDR_TRAP_INDEX 0x00100200B0 +#define A_ADDR_TRAP_REG 0x00100200B8 +#define A_ADDR_TRAP_UP_0 0x0010020400 +#define A_ADDR_TRAP_UP_1 0x0010020408 +#define A_ADDR_TRAP_UP_2 0x0010020410 +#define A_ADDR_TRAP_UP_3 0x0010020418 +#define A_ADDR_TRAP_DOWN_0 0x0010020420 +#define A_ADDR_TRAP_DOWN_1 0x0010020428 +#define A_ADDR_TRAP_DOWN_2 0x0010020430 +#define A_ADDR_TRAP_DOWN_3 0x0010020438 +#define A_ADDR_TRAP_CFG_0 0x0010020440 +#define A_ADDR_TRAP_CFG_1 0x0010020448 +#define A_ADDR_TRAP_CFG_2 0x0010020450 +#define A_ADDR_TRAP_CFG_3 0x0010020458 +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define A_ADDR_TRAP_REG_DEBUG 0x0010020460 +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#define ADDR_TRAP_SPACING 8 +#define NUM_ADDR_TRAP 4 +#define A_ADDR_TRAP_UP(n) (A_ADDR_TRAP_UP_0 + ((n) * ADDR_TRAP_SPACING)) +#define A_ADDR_TRAP_DOWN(n) (A_ADDR_TRAP_DOWN_0 + ((n) * ADDR_TRAP_SPACING)) +#define A_ADDR_TRAP_CFG(n) (A_ADDR_TRAP_CFG_0 + ((n) * ADDR_TRAP_SPACING)) + + +/* ********************************************************************* + * System Interrupt Mapper Registers + ********************************************************************* */ + +#define A_IMR_CPU0_BASE 0x0010020000 +#define A_IMR_CPU1_BASE 0x0010022000 +#define IMR_REGISTER_SPACING 0x2000 +#define IMR_REGISTER_SPACING_SHIFT 13 + +#define A_IMR_MAPPER(cpu) (A_IMR_CPU0_BASE+(cpu)*IMR_REGISTER_SPACING) +#define A_IMR_REGISTER(cpu, reg) (A_IMR_MAPPER(cpu)+(reg)) + +#define R_IMR_INTERRUPT_DIAG 0x0010 +#define R_IMR_INTERRUPT_LDT 0x0018 +#define R_IMR_INTERRUPT_MASK 0x0028 +#define R_IMR_INTERRUPT_TRACE 0x0038 +#define R_IMR_INTERRUPT_SOURCE_STATUS 0x0040 +#define R_IMR_LDT_INTERRUPT_SET 0x0048 +#define R_IMR_LDT_INTERRUPT 0x0018 +#define R_IMR_LDT_INTERRUPT_CLR 0x0020 +#define R_IMR_MAILBOX_CPU 0x00c0 +#define R_IMR_ALIAS_MAILBOX_CPU 0x1000 +#define R_IMR_MAILBOX_SET_CPU 0x00C8 +#define R_IMR_ALIAS_MAILBOX_SET_CPU 0x1008 +#define R_IMR_MAILBOX_CLR_CPU 0x00D0 +#define R_IMR_INTERRUPT_STATUS_BASE 0x0100 +#define R_IMR_INTERRUPT_STATUS_COUNT 7 +#define R_IMR_INTERRUPT_MAP_BASE 0x0200 +#define R_IMR_INTERRUPT_MAP_COUNT 64 + +/* + * these macros work together to build the address of a mailbox + * register, e.g., A_MAILBOX_REGISTER(R_IMR_MAILBOX_SET_CPU,1) + * for mbox_0_set_cpu2 returns 0x00100240C8 + */ +#define A_MAILBOX_REGISTER(reg,cpu) \ + (A_IMR_CPU0_BASE + (cpu * IMR_REGISTER_SPACING) + reg) + +/* ********************************************************************* + * System Performance Counter Registers + ********************************************************************* */ + +#define A_SCD_PERF_CNT_CFG 0x00100204C0 +#define A_SCD_PERF_CNT_0 0x00100204D0 +#define A_SCD_PERF_CNT_1 0x00100204D8 +#define A_SCD_PERF_CNT_2 0x00100204E0 +#define A_SCD_PERF_CNT_3 0x00100204E8 + +#define SCD_NUM_PERF_CNT 4 +#define SCD_PERF_CNT_SPACING 8 +#define A_SCD_PERF_CNT(n) (A_SCD_PERF_CNT_0+(n*SCD_PERF_CNT_SPACING)) + +/* ********************************************************************* + * System Bus Watcher Registers + ********************************************************************* */ + +#define A_SCD_BUS_ERR_STATUS 0x0010020880 +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define A_SCD_BUS_ERR_STATUS_DEBUG 0x00100208D0 +#define A_BUS_ERR_STATUS_DEBUG 0x00100208D0 +#endif /* 1250 PASS2 || 112x PASS1 */ +#define A_BUS_ERR_DATA_0 0x00100208A0 +#define A_BUS_ERR_DATA_1 0x00100208A8 +#define A_BUS_ERR_DATA_2 0x00100208B0 +#define A_BUS_ERR_DATA_3 0x00100208B8 +#define A_BUS_L2_ERRORS 0x00100208C0 +#define A_BUS_MEM_IO_ERRORS 0x00100208C8 + +/* ********************************************************************* + * System Debug Controller Registers + ********************************************************************* */ + +#define A_SCD_JTAG_BASE 0x0010000000 + +/* ********************************************************************* + * System Trace Buffer Registers + ********************************************************************* */ + +#define A_SCD_TRACE_CFG 0x0010020A00 +#define A_SCD_TRACE_READ 0x0010020A08 +#define A_SCD_TRACE_EVENT_0 0x0010020A20 +#define A_SCD_TRACE_EVENT_1 0x0010020A28 +#define A_SCD_TRACE_EVENT_2 0x0010020A30 +#define A_SCD_TRACE_EVENT_3 0x0010020A38 +#define A_SCD_TRACE_SEQUENCE_0 0x0010020A40 +#define A_SCD_TRACE_SEQUENCE_1 0x0010020A48 +#define A_SCD_TRACE_SEQUENCE_2 0x0010020A50 +#define A_SCD_TRACE_SEQUENCE_3 0x0010020A58 +#define A_SCD_TRACE_EVENT_4 0x0010020A60 +#define A_SCD_TRACE_EVENT_5 0x0010020A68 +#define A_SCD_TRACE_EVENT_6 0x0010020A70 +#define A_SCD_TRACE_EVENT_7 0x0010020A78 +#define A_SCD_TRACE_SEQUENCE_4 0x0010020A80 +#define A_SCD_TRACE_SEQUENCE_5 0x0010020A88 +#define A_SCD_TRACE_SEQUENCE_6 0x0010020A90 +#define A_SCD_TRACE_SEQUENCE_7 0x0010020A98 + +#define TRACE_REGISTER_SPACING 8 +#define TRACE_NUM_REGISTERS 8 +#define A_SCD_TRACE_EVENT(n) (((n) & 4) ? \ + (A_SCD_TRACE_EVENT_4 + (((n) & 3) * TRACE_REGISTER_SPACING)) : \ + (A_SCD_TRACE_EVENT_0 + ((n) * TRACE_REGISTER_SPACING))) +#define A_SCD_TRACE_SEQUENCE(n) (((n) & 4) ? \ + (A_SCD_TRACE_SEQUENCE_4 + (((n) & 3) * TRACE_REGISTER_SPACING)) : \ + (A_SCD_TRACE_SEQUENCE_0 + ((n) * TRACE_REGISTER_SPACING))) + +/* ********************************************************************* + * System Generic DMA Registers + ********************************************************************* */ + +#define A_DM_0 0x0010020B00 +#define A_DM_1 0x0010020B20 +#define A_DM_2 0x0010020B40 +#define A_DM_3 0x0010020B60 +#define DM_REGISTER_SPACING 0x20 +#define DM_NUM_CHANNELS 4 +#define A_DM_BASE(idx) (A_DM_0 + ((idx) * DM_REGISTER_SPACING)) +#define A_DM_REGISTER(idx, reg) (A_DM_BASE(idx) + (reg)) + +#define R_DM_DSCR_BASE 0x0000000000 +#define R_DM_DSCR_COUNT 0x0000000008 +#define R_DM_CUR_DSCR_ADDR 0x0000000010 +#define R_DM_DSCR_BASE_DEBUG 0x0000000018 + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define A_DM_PARTIAL_0 0x0010020ba0 +#define A_DM_PARTIAL_1 0x0010020ba8 +#define A_DM_PARTIAL_2 0x0010020bb0 +#define A_DM_PARTIAL_3 0x0010020bb8 +#define DM_PARTIAL_REGISTER_SPACING 0x8 +#define A_DM_PARTIAL(idx) (A_DM_PARTIAL_0 + ((idx) * DM_PARTIAL_REGISTER_SPACING)) +#endif /* 1250 PASS3 || 112x PASS1 */ + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define A_DM_CRC_0 0x0010020b80 +#define A_DM_CRC_1 0x0010020b90 +#define DM_CRC_REGISTER_SPACING 0x10 +#define DM_CRC_NUM_CHANNELS 2 +#define A_DM_CRC_BASE(idx) (A_DM_CRC_0 + ((idx) * DM_CRC_REGISTER_SPACING)) +#define A_DM_CRC_REGISTER(idx, reg) (A_DM_CRC_BASE(idx) + (reg)) + +#define R_CRC_DEF_0 0x00 +#define R_CTCP_DEF_0 0x08 +#endif /* 1250 PASS3 || 112x PASS1 */ + +/* ********************************************************************* + * Physical Address Map + ********************************************************************* */ + +#if SIBYTE_HDR_FEATURE_1250_112x +#define A_PHYS_MEMORY_0 _SB_MAKE64(0x0000000000) +#define A_PHYS_MEMORY_SIZE _SB_MAKE64((256*1024*1024)) +#define A_PHYS_SYSTEM_CTL _SB_MAKE64(0x0010000000) +#define A_PHYS_IO_SYSTEM _SB_MAKE64(0x0010060000) +#define A_PHYS_GENBUS _SB_MAKE64(0x0010090000) +#define A_PHYS_GENBUS_END _SB_MAKE64(0x0040000000) +#define A_PHYS_LDTPCI_IO_MATCH_BYTES_32 _SB_MAKE64(0x0040000000) +#define A_PHYS_LDTPCI_IO_MATCH_BITS_32 _SB_MAKE64(0x0060000000) +#define A_PHYS_MEMORY_1 _SB_MAKE64(0x0080000000) +#define A_PHYS_MEMORY_2 _SB_MAKE64(0x0090000000) +#define A_PHYS_MEMORY_3 _SB_MAKE64(0x00C0000000) +#define A_PHYS_L2_CACHE_TEST _SB_MAKE64(0x00D0000000) +#define A_PHYS_LDT_SPECIAL_MATCH_BYTES _SB_MAKE64(0x00D8000000) +#define A_PHYS_LDTPCI_IO_MATCH_BYTES _SB_MAKE64(0x00DC000000) +#define A_PHYS_LDTPCI_CFG_MATCH_BYTES _SB_MAKE64(0x00DE000000) +#define A_PHYS_LDT_SPECIAL_MATCH_BITS _SB_MAKE64(0x00F8000000) +#define A_PHYS_LDTPCI_IO_MATCH_BITS _SB_MAKE64(0x00FC000000) +#define A_PHYS_LDTPCI_CFG_MATCH_BITS _SB_MAKE64(0x00FE000000) +#define A_PHYS_MEMORY_EXP _SB_MAKE64(0x0100000000) +#define A_PHYS_MEMORY_EXP_SIZE _SB_MAKE64((508*1024*1024*1024)) +#define A_PHYS_LDT_EXP _SB_MAKE64(0x8000000000) +#define A_PHYS_PCI_FULLACCESS_BYTES _SB_MAKE64(0xF000000000) +#define A_PHYS_PCI_FULLACCESS_BITS _SB_MAKE64(0xF100000000) +#define A_PHYS_RESERVED _SB_MAKE64(0xF200000000) +#define A_PHYS_RESERVED_SPECIAL_LDT _SB_MAKE64(0xFD00000000) + +#define A_PHYS_L2CACHE_WAY_SIZE _SB_MAKE64(0x0000020000) +#define PHYS_L2CACHE_NUM_WAYS 4 +#define A_PHYS_L2CACHE_TOTAL_SIZE _SB_MAKE64(0x0000080000) +#define A_PHYS_L2CACHE_WAY0 _SB_MAKE64(0x00D0180000) +#define A_PHYS_L2CACHE_WAY1 _SB_MAKE64(0x00D01A0000) +#define A_PHYS_L2CACHE_WAY2 _SB_MAKE64(0x00D01C0000) +#define A_PHYS_L2CACHE_WAY3 _SB_MAKE64(0x00D01E0000) +#endif + + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_scd.h b/arch/mips/include/asm/sibyte/sb1250_scd.h new file mode 100644 index 00000000000..e49c3e89b5e --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_scd.h @@ -0,0 +1,654 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * SCD Constants and Macros File: sb1250_scd.h + * + * This module contains constants and macros useful for + * manipulating the System Control and Debug module on the 1250. + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003,2004,2005 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_SCD_H +#define _SB1250_SCD_H + +#include "sb1250_defs.h" + +/* ********************************************************************* + * System control/debug registers + ********************************************************************* */ + +/* + * System Revision Register (Table 4-1) + */ + +#define M_SYS_RESERVED _SB_MAKEMASK(8, 0) + +#define S_SYS_REVISION _SB_MAKE64(8) +#define M_SYS_REVISION _SB_MAKEMASK(8, S_SYS_REVISION) +#define V_SYS_REVISION(x) _SB_MAKEVALUE(x, S_SYS_REVISION) +#define G_SYS_REVISION(x) _SB_GETVALUE(x, S_SYS_REVISION, M_SYS_REVISION) + +#define K_SYS_REVISION_BCM1250_PASS1 0x01 + +#define K_SYS_REVISION_BCM1250_PASS2 0x03 +#define K_SYS_REVISION_BCM1250_A1 0x03 /* Pass 2.0 WB */ +#define K_SYS_REVISION_BCM1250_A2 0x04 /* Pass 2.0 FC */ +#define K_SYS_REVISION_BCM1250_A3 0x05 /* Pass 2.1 FC */ +#define K_SYS_REVISION_BCM1250_A4 0x06 /* Pass 2.1 WB */ +#define K_SYS_REVISION_BCM1250_A6 0x07 /* OR 0x04 (A2) w/WID != 0 */ +#define K_SYS_REVISION_BCM1250_A8 0x0b /* A8/A10 */ +#define K_SYS_REVISION_BCM1250_A9 0x08 +#define K_SYS_REVISION_BCM1250_A10 K_SYS_REVISION_BCM1250_A8 + +#define K_SYS_REVISION_BCM1250_PASS2_2 0x10 +#define K_SYS_REVISION_BCM1250_B0 K_SYS_REVISION_BCM1250_B1 +#define K_SYS_REVISION_BCM1250_B1 0x10 +#define K_SYS_REVISION_BCM1250_B2 0x11 + +#define K_SYS_REVISION_BCM1250_C0 0x20 +#define K_SYS_REVISION_BCM1250_C1 0x21 +#define K_SYS_REVISION_BCM1250_C2 0x22 +#define K_SYS_REVISION_BCM1250_C3 0x23 + +#if SIBYTE_HDR_FEATURE_CHIP(1250) +/* XXX: discourage people from using these constants. */ +#define K_SYS_REVISION_PASS1 K_SYS_REVISION_BCM1250_PASS1 +#define K_SYS_REVISION_PASS2 K_SYS_REVISION_BCM1250_PASS2 +#define K_SYS_REVISION_PASS2_2 K_SYS_REVISION_BCM1250_PASS2_2 +#define K_SYS_REVISION_PASS3 K_SYS_REVISION_BCM1250_PASS3 +#define K_SYS_REVISION_BCM1250_PASS3 K_SYS_REVISION_BCM1250_C0 +#endif /* 1250 */ + +#define K_SYS_REVISION_BCM112x_A1 0x20 +#define K_SYS_REVISION_BCM112x_A2 0x21 +#define K_SYS_REVISION_BCM112x_A3 0x22 +#define K_SYS_REVISION_BCM112x_A4 0x23 +#define K_SYS_REVISION_BCM112x_B0 0x30 + +#define K_SYS_REVISION_BCM1480_S0 0x01 +#define K_SYS_REVISION_BCM1480_A1 0x02 +#define K_SYS_REVISION_BCM1480_A2 0x03 +#define K_SYS_REVISION_BCM1480_A3 0x04 +#define K_SYS_REVISION_BCM1480_B0 0x11 + +/*Cache size - 23:20 of revision register*/ +#define S_SYS_L2C_SIZE _SB_MAKE64(20) +#define M_SYS_L2C_SIZE _SB_MAKEMASK(4, S_SYS_L2C_SIZE) +#define V_SYS_L2C_SIZE(x) _SB_MAKEVALUE(x, S_SYS_L2C_SIZE) +#define G_SYS_L2C_SIZE(x) _SB_GETVALUE(x, S_SYS_L2C_SIZE, M_SYS_L2C_SIZE) + +#define K_SYS_L2C_SIZE_1MB 0 +#define K_SYS_L2C_SIZE_512KB 5 +#define K_SYS_L2C_SIZE_256KB 2 +#define K_SYS_L2C_SIZE_128KB 1 + +#define K_SYS_L2C_SIZE_BCM1250 K_SYS_L2C_SIZE_512KB +#define K_SYS_L2C_SIZE_BCM1125 K_SYS_L2C_SIZE_256KB +#define K_SYS_L2C_SIZE_BCM1122 K_SYS_L2C_SIZE_128KB + + +/* Number of CPU cores, bits 27:24 of revision register*/ +#define S_SYS_NUM_CPUS _SB_MAKE64(24) +#define M_SYS_NUM_CPUS _SB_MAKEMASK(4, S_SYS_NUM_CPUS) +#define V_SYS_NUM_CPUS(x) _SB_MAKEVALUE(x, S_SYS_NUM_CPUS) +#define G_SYS_NUM_CPUS(x) _SB_GETVALUE(x, S_SYS_NUM_CPUS, M_SYS_NUM_CPUS) + + +/* XXX: discourage people from using these constants. */ +#define S_SYS_PART _SB_MAKE64(16) +#define M_SYS_PART _SB_MAKEMASK(16, S_SYS_PART) +#define V_SYS_PART(x) _SB_MAKEVALUE(x, S_SYS_PART) +#define G_SYS_PART(x) _SB_GETVALUE(x, S_SYS_PART, M_SYS_PART) + +/* XXX: discourage people from using these constants. */ +#define K_SYS_PART_SB1250 0x1250 +#define K_SYS_PART_BCM1120 0x1121 +#define K_SYS_PART_BCM1125 0x1123 +#define K_SYS_PART_BCM1125H 0x1124 +#define K_SYS_PART_BCM1122 0x1113 + + +/* The "peripheral set" (SOC type) is the low 4 bits of the "part" field. */ +#define S_SYS_SOC_TYPE _SB_MAKE64(16) +#define M_SYS_SOC_TYPE _SB_MAKEMASK(4, S_SYS_SOC_TYPE) +#define V_SYS_SOC_TYPE(x) _SB_MAKEVALUE(x, S_SYS_SOC_TYPE) +#define G_SYS_SOC_TYPE(x) _SB_GETVALUE(x, S_SYS_SOC_TYPE, M_SYS_SOC_TYPE) + +#define K_SYS_SOC_TYPE_BCM1250 0x0 +#define K_SYS_SOC_TYPE_BCM1120 0x1 +#define K_SYS_SOC_TYPE_BCM1250_ALT 0x2 /* 1250pass2 w/ 1/4 L2. */ +#define K_SYS_SOC_TYPE_BCM1125 0x3 +#define K_SYS_SOC_TYPE_BCM1125H 0x4 +#define K_SYS_SOC_TYPE_BCM1250_ALT2 0x5 /* 1250pass2 w/ 1/2 L2. */ +#define K_SYS_SOC_TYPE_BCM1x80 0x6 +#define K_SYS_SOC_TYPE_BCM1x55 0x7 + +/* + * Calculate correct SOC type given a copy of system revision register. + * + * (For the assembler version, sysrev and dest may be the same register. + * Also, it clobbers AT.) + */ +#ifdef __ASSEMBLER__ +#define SYS_SOC_TYPE(dest, sysrev) \ + .set push ; \ + .set reorder ; \ + dsrl dest, sysrev, S_SYS_SOC_TYPE ; \ + andi dest, dest, (M_SYS_SOC_TYPE >> S_SYS_SOC_TYPE); \ + beq dest, K_SYS_SOC_TYPE_BCM1250_ALT, 991f ; \ + beq dest, K_SYS_SOC_TYPE_BCM1250_ALT2, 991f ; \ + b 992f ; \ +991: li dest, K_SYS_SOC_TYPE_BCM1250 ; \ +992: \ + .set pop +#else +#define SYS_SOC_TYPE(sysrev) \ + ((G_SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1250_ALT \ + || G_SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1250_ALT2) \ + ? K_SYS_SOC_TYPE_BCM1250 : G_SYS_SOC_TYPE(sysrev)) +#endif + +#define S_SYS_WID _SB_MAKE64(32) +#define M_SYS_WID _SB_MAKEMASK(32, S_SYS_WID) +#define V_SYS_WID(x) _SB_MAKEVALUE(x, S_SYS_WID) +#define G_SYS_WID(x) _SB_GETVALUE(x, S_SYS_WID, M_SYS_WID) + +/* + * System Manufacturing Register + * Register: SCD_SYSTEM_MANUF + */ + +#if SIBYTE_HDR_FEATURE_1250_112x +/* Wafer ID: bits 31:0 */ +#define S_SYS_WAFERID1_200 _SB_MAKE64(0) +#define M_SYS_WAFERID1_200 _SB_MAKEMASK(32, S_SYS_WAFERID1_200) +#define V_SYS_WAFERID1_200(x) _SB_MAKEVALUE(x, S_SYS_WAFERID1_200) +#define G_SYS_WAFERID1_200(x) _SB_GETVALUE(x, S_SYS_WAFERID1_200, M_SYS_WAFERID1_200) + +#define S_SYS_BIN _SB_MAKE64(32) +#define M_SYS_BIN _SB_MAKEMASK(4, S_SYS_BIN) +#define V_SYS_BIN(x) _SB_MAKEVALUE(x, S_SYS_BIN) +#define G_SYS_BIN(x) _SB_GETVALUE(x, S_SYS_BIN, M_SYS_BIN) + +/* Wafer ID: bits 39:36 */ +#define S_SYS_WAFERID2_200 _SB_MAKE64(36) +#define M_SYS_WAFERID2_200 _SB_MAKEMASK(4, S_SYS_WAFERID2_200) +#define V_SYS_WAFERID2_200(x) _SB_MAKEVALUE(x, S_SYS_WAFERID2_200) +#define G_SYS_WAFERID2_200(x) _SB_GETVALUE(x, S_SYS_WAFERID2_200, M_SYS_WAFERID2_200) + +/* Wafer ID: bits 39:0 */ +#define S_SYS_WAFERID_300 _SB_MAKE64(0) +#define M_SYS_WAFERID_300 _SB_MAKEMASK(40, S_SYS_WAFERID_300) +#define V_SYS_WAFERID_300(x) _SB_MAKEVALUE(x, S_SYS_WAFERID_300) +#define G_SYS_WAFERID_300(x) _SB_GETVALUE(x, S_SYS_WAFERID_300, M_SYS_WAFERID_300) + +#define S_SYS_XPOS _SB_MAKE64(40) +#define M_SYS_XPOS _SB_MAKEMASK(6, S_SYS_XPOS) +#define V_SYS_XPOS(x) _SB_MAKEVALUE(x, S_SYS_XPOS) +#define G_SYS_XPOS(x) _SB_GETVALUE(x, S_SYS_XPOS, M_SYS_XPOS) + +#define S_SYS_YPOS _SB_MAKE64(46) +#define M_SYS_YPOS _SB_MAKEMASK(6, S_SYS_YPOS) +#define V_SYS_YPOS(x) _SB_MAKEVALUE(x, S_SYS_YPOS) +#define G_SYS_YPOS(x) _SB_GETVALUE(x, S_SYS_YPOS, M_SYS_YPOS) +#endif + + +/* + * System Config Register (Table 4-2) + * Register: SCD_SYSTEM_CFG + */ + +#if SIBYTE_HDR_FEATURE_1250_112x +#define M_SYS_LDT_PLL_BYP _SB_MAKEMASK1(3) +#define M_SYS_PCI_SYNC_TEST_MODE _SB_MAKEMASK1(4) +#define M_SYS_IOB0_DIV _SB_MAKEMASK1(5) +#define M_SYS_IOB1_DIV _SB_MAKEMASK1(6) + +#define S_SYS_PLL_DIV _SB_MAKE64(7) +#define M_SYS_PLL_DIV _SB_MAKEMASK(5, S_SYS_PLL_DIV) +#define V_SYS_PLL_DIV(x) _SB_MAKEVALUE(x, S_SYS_PLL_DIV) +#define G_SYS_PLL_DIV(x) _SB_GETVALUE(x, S_SYS_PLL_DIV, M_SYS_PLL_DIV) + +#define M_SYS_SER0_ENABLE _SB_MAKEMASK1(12) +#define M_SYS_SER0_RSTB_EN _SB_MAKEMASK1(13) +#define M_SYS_SER1_ENABLE _SB_MAKEMASK1(14) +#define M_SYS_SER1_RSTB_EN _SB_MAKEMASK1(15) +#define M_SYS_PCMCIA_ENABLE _SB_MAKEMASK1(16) + +#define S_SYS_BOOT_MODE _SB_MAKE64(17) +#define M_SYS_BOOT_MODE _SB_MAKEMASK(2, S_SYS_BOOT_MODE) +#define V_SYS_BOOT_MODE(x) _SB_MAKEVALUE(x, S_SYS_BOOT_MODE) +#define G_SYS_BOOT_MODE(x) _SB_GETVALUE(x, S_SYS_BOOT_MODE, M_SYS_BOOT_MODE) +#define K_SYS_BOOT_MODE_ROM32 0 +#define K_SYS_BOOT_MODE_ROM8 1 +#define K_SYS_BOOT_MODE_SMBUS_SMALL 2 +#define K_SYS_BOOT_MODE_SMBUS_BIG 3 + +#define M_SYS_PCI_HOST _SB_MAKEMASK1(19) +#define M_SYS_PCI_ARBITER _SB_MAKEMASK1(20) +#define M_SYS_SOUTH_ON_LDT _SB_MAKEMASK1(21) +#define M_SYS_BIG_ENDIAN _SB_MAKEMASK1(22) +#define M_SYS_GENCLK_EN _SB_MAKEMASK1(23) +#define M_SYS_LDT_TEST_EN _SB_MAKEMASK1(24) +#define M_SYS_GEN_PARITY_EN _SB_MAKEMASK1(25) + +#define S_SYS_CONFIG 26 +#define M_SYS_CONFIG _SB_MAKEMASK(6, S_SYS_CONFIG) +#define V_SYS_CONFIG(x) _SB_MAKEVALUE(x, S_SYS_CONFIG) +#define G_SYS_CONFIG(x) _SB_GETVALUE(x, S_SYS_CONFIG, M_SYS_CONFIG) + +/* The following bits are writeable by JTAG only. */ + +#define M_SYS_CLKSTOP _SB_MAKEMASK1(32) +#define M_SYS_CLKSTEP _SB_MAKEMASK1(33) + +#define S_SYS_CLKCOUNT 34 +#define M_SYS_CLKCOUNT _SB_MAKEMASK(8, S_SYS_CLKCOUNT) +#define V_SYS_CLKCOUNT(x) _SB_MAKEVALUE(x, S_SYS_CLKCOUNT) +#define G_SYS_CLKCOUNT(x) _SB_GETVALUE(x, S_SYS_CLKCOUNT, M_SYS_CLKCOUNT) + +#define M_SYS_PLL_BYPASS _SB_MAKEMASK1(42) + +#define S_SYS_PLL_IREF 43 +#define M_SYS_PLL_IREF _SB_MAKEMASK(2, S_SYS_PLL_IREF) + +#define S_SYS_PLL_VCO 45 +#define M_SYS_PLL_VCO _SB_MAKEMASK(2, S_SYS_PLL_VCO) + +#define S_SYS_PLL_VREG 47 +#define M_SYS_PLL_VREG _SB_MAKEMASK(2, S_SYS_PLL_VREG) + +#define M_SYS_MEM_RESET _SB_MAKEMASK1(49) +#define M_SYS_L2C_RESET _SB_MAKEMASK1(50) +#define M_SYS_IO_RESET_0 _SB_MAKEMASK1(51) +#define M_SYS_IO_RESET_1 _SB_MAKEMASK1(52) +#define M_SYS_SCD_RESET _SB_MAKEMASK1(53) + +/* End of bits writable by JTAG only. */ + +#define M_SYS_CPU_RESET_0 _SB_MAKEMASK1(54) +#define M_SYS_CPU_RESET_1 _SB_MAKEMASK1(55) + +#define M_SYS_UNICPU0 _SB_MAKEMASK1(56) +#define M_SYS_UNICPU1 _SB_MAKEMASK1(57) + +#define M_SYS_SB_SOFTRES _SB_MAKEMASK1(58) +#define M_SYS_EXT_RESET _SB_MAKEMASK1(59) +#define M_SYS_SYSTEM_RESET _SB_MAKEMASK1(60) + +#define M_SYS_MISR_MODE _SB_MAKEMASK1(61) +#define M_SYS_MISR_RESET _SB_MAKEMASK1(62) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) +#define M_SYS_SW_FLAG _SB_MAKEMASK1(63) +#endif /* 1250 PASS2 || 112x PASS1 */ + +#endif + + +/* + * Mailbox Registers (Table 4-3) + * Registers: SCD_MBOX_CPU_x + */ + +#define S_MBOX_INT_3 0 +#define M_MBOX_INT_3 _SB_MAKEMASK(16, S_MBOX_INT_3) +#define S_MBOX_INT_2 16 +#define M_MBOX_INT_2 _SB_MAKEMASK(16, S_MBOX_INT_2) +#define S_MBOX_INT_1 32 +#define M_MBOX_INT_1 _SB_MAKEMASK(16, S_MBOX_INT_1) +#define S_MBOX_INT_0 48 +#define M_MBOX_INT_0 _SB_MAKEMASK(16, S_MBOX_INT_0) + +/* + * Watchdog Registers (Table 4-8) (Table 4-9) (Table 4-10) + * Registers: SCD_WDOG_INIT_CNT_x + */ + +#define V_SCD_WDOG_FREQ 1000000 + +#define S_SCD_WDOG_INIT 0 +#define M_SCD_WDOG_INIT _SB_MAKEMASK(23, S_SCD_WDOG_INIT) + +#define S_SCD_WDOG_CNT 0 +#define M_SCD_WDOG_CNT _SB_MAKEMASK(23, S_SCD_WDOG_CNT) + +#define S_SCD_WDOG_ENABLE 0 +#define M_SCD_WDOG_ENABLE _SB_MAKEMASK1(S_SCD_WDOG_ENABLE) + +#define S_SCD_WDOG_RESET_TYPE 2 +#define M_SCD_WDOG_RESET_TYPE _SB_MAKEMASK(3, S_SCD_WDOG_RESET_TYPE) +#define V_SCD_WDOG_RESET_TYPE(x) _SB_MAKEVALUE(x, S_SCD_WDOG_RESET_TYPE) +#define G_SCD_WDOG_RESET_TYPE(x) _SB_GETVALUE(x, S_SCD_WDOG_RESET_TYPE, M_SCD_WDOG_RESET_TYPE) + +#define K_SCD_WDOG_RESET_FULL 0 /* actually, (x & 1) == 0 */ +#define K_SCD_WDOG_RESET_SOFT 1 +#define K_SCD_WDOG_RESET_CPU0 3 +#define K_SCD_WDOG_RESET_CPU1 5 +#define K_SCD_WDOG_RESET_BOTH_CPUS 7 + +/* This feature is present in 1250 C0 and later, but *not* in 112x A revs. */ +#if SIBYTE_HDR_FEATURE(1250, PASS3) +#define S_SCD_WDOG_HAS_RESET 8 +#define M_SCD_WDOG_HAS_RESET _SB_MAKEMASK1(S_SCD_WDOG_HAS_RESET) +#endif + + +/* + * Timer Registers (Table 4-11) (Table 4-12) (Table 4-13) + */ + +#define V_SCD_TIMER_FREQ 1000000 + +#define S_SCD_TIMER_INIT 0 +#define M_SCD_TIMER_INIT _SB_MAKEMASK(23, S_SCD_TIMER_INIT) +#define V_SCD_TIMER_INIT(x) _SB_MAKEVALUE(x, S_SCD_TIMER_INIT) +#define G_SCD_TIMER_INIT(x) _SB_GETVALUE(x, S_SCD_TIMER_INIT, M_SCD_TIMER_INIT) + +#define V_SCD_TIMER_WIDTH 23 +#define S_SCD_TIMER_CNT 0 +#define M_SCD_TIMER_CNT _SB_MAKEMASK(V_SCD_TIMER_WIDTH, S_SCD_TIMER_CNT) +#define V_SCD_TIMER_CNT(x) _SB_MAKEVALUE(x, S_SCD_TIMER_CNT) +#define G_SCD_TIMER_CNT(x) _SB_GETVALUE(x, S_SCD_TIMER_CNT, M_SCD_TIMER_CNT) + +#define M_SCD_TIMER_ENABLE _SB_MAKEMASK1(0) +#define M_SCD_TIMER_MODE _SB_MAKEMASK1(1) +#define M_SCD_TIMER_MODE_CONTINUOUS M_SCD_TIMER_MODE + +/* + * System Performance Counters + */ + +#define S_SPC_CFG_SRC0 0 +#define M_SPC_CFG_SRC0 _SB_MAKEMASK(8, S_SPC_CFG_SRC0) +#define V_SPC_CFG_SRC0(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC0) +#define G_SPC_CFG_SRC0(x) _SB_GETVALUE(x, S_SPC_CFG_SRC0, M_SPC_CFG_SRC0) + +#define S_SPC_CFG_SRC1 8 +#define M_SPC_CFG_SRC1 _SB_MAKEMASK(8, S_SPC_CFG_SRC1) +#define V_SPC_CFG_SRC1(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC1) +#define G_SPC_CFG_SRC1(x) _SB_GETVALUE(x, S_SPC_CFG_SRC1, M_SPC_CFG_SRC1) + +#define S_SPC_CFG_SRC2 16 +#define M_SPC_CFG_SRC2 _SB_MAKEMASK(8, S_SPC_CFG_SRC2) +#define V_SPC_CFG_SRC2(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC2) +#define G_SPC_CFG_SRC2(x) _SB_GETVALUE(x, S_SPC_CFG_SRC2, M_SPC_CFG_SRC2) + +#define S_SPC_CFG_SRC3 24 +#define M_SPC_CFG_SRC3 _SB_MAKEMASK(8, S_SPC_CFG_SRC3) +#define V_SPC_CFG_SRC3(x) _SB_MAKEVALUE(x, S_SPC_CFG_SRC3) +#define G_SPC_CFG_SRC3(x) _SB_GETVALUE(x, S_SPC_CFG_SRC3, M_SPC_CFG_SRC3) + +#if SIBYTE_HDR_FEATURE_1250_112x +#define M_SPC_CFG_CLEAR _SB_MAKEMASK1(32) +#define M_SPC_CFG_ENABLE _SB_MAKEMASK1(33) +#endif + + +/* + * Bus Watcher + */ + +#define S_SCD_BERR_TID 8 +#define M_SCD_BERR_TID _SB_MAKEMASK(10, S_SCD_BERR_TID) +#define V_SCD_BERR_TID(x) _SB_MAKEVALUE(x, S_SCD_BERR_TID) +#define G_SCD_BERR_TID(x) _SB_GETVALUE(x, S_SCD_BERR_TID, M_SCD_BERR_TID) + +#define S_SCD_BERR_RID 18 +#define M_SCD_BERR_RID _SB_MAKEMASK(4, S_SCD_BERR_RID) +#define V_SCD_BERR_RID(x) _SB_MAKEVALUE(x, S_SCD_BERR_RID) +#define G_SCD_BERR_RID(x) _SB_GETVALUE(x, S_SCD_BERR_RID, M_SCD_BERR_RID) + +#define S_SCD_BERR_DCODE 22 +#define M_SCD_BERR_DCODE _SB_MAKEMASK(3, S_SCD_BERR_DCODE) +#define V_SCD_BERR_DCODE(x) _SB_MAKEVALUE(x, S_SCD_BERR_DCODE) +#define G_SCD_BERR_DCODE(x) _SB_GETVALUE(x, S_SCD_BERR_DCODE, M_SCD_BERR_DCODE) + +#define M_SCD_BERR_MULTERRS _SB_MAKEMASK1(30) + + +#define S_SCD_L2ECC_CORR_D 0 +#define M_SCD_L2ECC_CORR_D _SB_MAKEMASK(8, S_SCD_L2ECC_CORR_D) +#define V_SCD_L2ECC_CORR_D(x) _SB_MAKEVALUE(x, S_SCD_L2ECC_CORR_D) +#define G_SCD_L2ECC_CORR_D(x) _SB_GETVALUE(x, S_SCD_L2ECC_CORR_D, M_SCD_L2ECC_CORR_D) + +#define S_SCD_L2ECC_BAD_D 8 +#define M_SCD_L2ECC_BAD_D _SB_MAKEMASK(8, S_SCD_L2ECC_BAD_D) +#define V_SCD_L2ECC_BAD_D(x) _SB_MAKEVALUE(x, S_SCD_L2ECC_BAD_D) +#define G_SCD_L2ECC_BAD_D(x) _SB_GETVALUE(x, S_SCD_L2ECC_BAD_D, M_SCD_L2ECC_BAD_D) + +#define S_SCD_L2ECC_CORR_T 16 +#define M_SCD_L2ECC_CORR_T _SB_MAKEMASK(8, S_SCD_L2ECC_CORR_T) +#define V_SCD_L2ECC_CORR_T(x) _SB_MAKEVALUE(x, S_SCD_L2ECC_CORR_T) +#define G_SCD_L2ECC_CORR_T(x) _SB_GETVALUE(x, S_SCD_L2ECC_CORR_T, M_SCD_L2ECC_CORR_T) + +#define S_SCD_L2ECC_BAD_T 24 +#define M_SCD_L2ECC_BAD_T _SB_MAKEMASK(8, S_SCD_L2ECC_BAD_T) +#define V_SCD_L2ECC_BAD_T(x) _SB_MAKEVALUE(x, S_SCD_L2ECC_BAD_T) +#define G_SCD_L2ECC_BAD_T(x) _SB_GETVALUE(x, S_SCD_L2ECC_BAD_T, M_SCD_L2ECC_BAD_T) + +#define S_SCD_MEM_ECC_CORR 0 +#define M_SCD_MEM_ECC_CORR _SB_MAKEMASK(8, S_SCD_MEM_ECC_CORR) +#define V_SCD_MEM_ECC_CORR(x) _SB_MAKEVALUE(x, S_SCD_MEM_ECC_CORR) +#define G_SCD_MEM_ECC_CORR(x) _SB_GETVALUE(x, S_SCD_MEM_ECC_CORR, M_SCD_MEM_ECC_CORR) + +#define S_SCD_MEM_ECC_BAD 8 +#define M_SCD_MEM_ECC_BAD _SB_MAKEMASK(8, S_SCD_MEM_ECC_BAD) +#define V_SCD_MEM_ECC_BAD(x) _SB_MAKEVALUE(x, S_SCD_MEM_ECC_BAD) +#define G_SCD_MEM_ECC_BAD(x) _SB_GETVALUE(x, S_SCD_MEM_ECC_BAD, M_SCD_MEM_ECC_BAD) + +#define S_SCD_MEM_BUSERR 16 +#define M_SCD_MEM_BUSERR _SB_MAKEMASK(8, S_SCD_MEM_BUSERR) +#define V_SCD_MEM_BUSERR(x) _SB_MAKEVALUE(x, S_SCD_MEM_BUSERR) +#define G_SCD_MEM_BUSERR(x) _SB_GETVALUE(x, S_SCD_MEM_BUSERR, M_SCD_MEM_BUSERR) + + +/* + * Address Trap Registers + */ + +#if SIBYTE_HDR_FEATURE_1250_112x +#define M_ATRAP_INDEX _SB_MAKEMASK(4, 0) +#define M_ATRAP_ADDRESS _SB_MAKEMASK(40, 0) + +#define S_ATRAP_CFG_CNT 0 +#define M_ATRAP_CFG_CNT _SB_MAKEMASK(3, S_ATRAP_CFG_CNT) +#define V_ATRAP_CFG_CNT(x) _SB_MAKEVALUE(x, S_ATRAP_CFG_CNT) +#define G_ATRAP_CFG_CNT(x) _SB_GETVALUE(x, S_ATRAP_CFG_CNT, M_ATRAP_CFG_CNT) + +#define M_ATRAP_CFG_WRITE _SB_MAKEMASK1(3) +#define M_ATRAP_CFG_ALL _SB_MAKEMASK1(4) +#define M_ATRAP_CFG_INV _SB_MAKEMASK1(5) +#define M_ATRAP_CFG_USESRC _SB_MAKEMASK1(6) +#define M_ATRAP_CFG_SRCINV _SB_MAKEMASK1(7) + +#define S_ATRAP_CFG_AGENTID 8 +#define M_ATRAP_CFG_AGENTID _SB_MAKEMASK(4, S_ATRAP_CFG_AGENTID) +#define V_ATRAP_CFG_AGENTID(x) _SB_MAKEVALUE(x, S_ATRAP_CFG_AGENTID) +#define G_ATRAP_CFG_AGENTID(x) _SB_GETVALUE(x, S_ATRAP_CFG_AGENTID, M_ATRAP_CFG_AGENTID) + +#define K_BUS_AGENT_CPU0 0 +#define K_BUS_AGENT_CPU1 1 +#define K_BUS_AGENT_IOB0 2 +#define K_BUS_AGENT_IOB1 3 +#define K_BUS_AGENT_SCD 4 +#define K_BUS_AGENT_L2C 6 +#define K_BUS_AGENT_MC 7 + +#define S_ATRAP_CFG_CATTR 12 +#define M_ATRAP_CFG_CATTR _SB_MAKEMASK(3, S_ATRAP_CFG_CATTR) +#define V_ATRAP_CFG_CATTR(x) _SB_MAKEVALUE(x, S_ATRAP_CFG_CATTR) +#define G_ATRAP_CFG_CATTR(x) _SB_GETVALUE(x, S_ATRAP_CFG_CATTR, M_ATRAP_CFG_CATTR) + +#define K_ATRAP_CFG_CATTR_IGNORE 0 +#define K_ATRAP_CFG_CATTR_UNC 1 +#define K_ATRAP_CFG_CATTR_CACHEABLE 2 +#define K_ATRAP_CFG_CATTR_NONCOH 3 +#define K_ATRAP_CFG_CATTR_COHERENT 4 +#define K_ATRAP_CFG_CATTR_NOTUNC 5 +#define K_ATRAP_CFG_CATTR_NOTNONCOH 6 +#define K_ATRAP_CFG_CATTR_NOTCOHERENT 7 + +#endif /* 1250/112x */ + +/* + * Trace Buffer Config register + */ + +#define M_SCD_TRACE_CFG_RESET _SB_MAKEMASK1(0) +#define M_SCD_TRACE_CFG_START_READ _SB_MAKEMASK1(1) +#define M_SCD_TRACE_CFG_START _SB_MAKEMASK1(2) +#define M_SCD_TRACE_CFG_STOP _SB_MAKEMASK1(3) +#define M_SCD_TRACE_CFG_FREEZE _SB_MAKEMASK1(4) +#define M_SCD_TRACE_CFG_FREEZE_FULL _SB_MAKEMASK1(5) +#define M_SCD_TRACE_CFG_DEBUG_FULL _SB_MAKEMASK1(6) +#define M_SCD_TRACE_CFG_FULL _SB_MAKEMASK1(7) +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define M_SCD_TRACE_CFG_FORCECNT _SB_MAKEMASK1(8) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +/* + * This field is the same on the 1250/112x and 1480, just located in + * a slightly different place in the register. + */ +#if SIBYTE_HDR_FEATURE_1250_112x +#define S_SCD_TRACE_CFG_CUR_ADDR 10 +#else +#if SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_SCD_TRACE_CFG_CUR_ADDR 24 +#endif /* 1480 */ +#endif /* 1250/112x */ + +#define M_SCD_TRACE_CFG_CUR_ADDR _SB_MAKEMASK(8, S_SCD_TRACE_CFG_CUR_ADDR) +#define V_SCD_TRACE_CFG_CUR_ADDR(x) _SB_MAKEVALUE(x, S_SCD_TRACE_CFG_CUR_ADDR) +#define G_SCD_TRACE_CFG_CUR_ADDR(x) _SB_GETVALUE(x, S_SCD_TRACE_CFG_CUR_ADDR, M_SCD_TRACE_CFG_CUR_ADDR) + +/* + * Trace Event registers + */ + +#define S_SCD_TREVT_ADDR_MATCH 0 +#define M_SCD_TREVT_ADDR_MATCH _SB_MAKEMASK(4, S_SCD_TREVT_ADDR_MATCH) +#define V_SCD_TREVT_ADDR_MATCH(x) _SB_MAKEVALUE(x, S_SCD_TREVT_ADDR_MATCH) +#define G_SCD_TREVT_ADDR_MATCH(x) _SB_GETVALUE(x, S_SCD_TREVT_ADDR_MATCH, M_SCD_TREVT_ADDR_MATCH) + +#define M_SCD_TREVT_REQID_MATCH _SB_MAKEMASK1(4) +#define M_SCD_TREVT_DATAID_MATCH _SB_MAKEMASK1(5) +#define M_SCD_TREVT_RESPID_MATCH _SB_MAKEMASK1(6) +#define M_SCD_TREVT_INTERRUPT _SB_MAKEMASK1(7) +#define M_SCD_TREVT_DEBUG_PIN _SB_MAKEMASK1(9) +#define M_SCD_TREVT_WRITE _SB_MAKEMASK1(10) +#define M_SCD_TREVT_READ _SB_MAKEMASK1(11) + +#define S_SCD_TREVT_REQID 12 +#define M_SCD_TREVT_REQID _SB_MAKEMASK(4, S_SCD_TREVT_REQID) +#define V_SCD_TREVT_REQID(x) _SB_MAKEVALUE(x, S_SCD_TREVT_REQID) +#define G_SCD_TREVT_REQID(x) _SB_GETVALUE(x, S_SCD_TREVT_REQID, M_SCD_TREVT_REQID) + +#define S_SCD_TREVT_RESPID 16 +#define M_SCD_TREVT_RESPID _SB_MAKEMASK(4, S_SCD_TREVT_RESPID) +#define V_SCD_TREVT_RESPID(x) _SB_MAKEVALUE(x, S_SCD_TREVT_RESPID) +#define G_SCD_TREVT_RESPID(x) _SB_GETVALUE(x, S_SCD_TREVT_RESPID, M_SCD_TREVT_RESPID) + +#define S_SCD_TREVT_DATAID 20 +#define M_SCD_TREVT_DATAID _SB_MAKEMASK(4, S_SCD_TREVT_DATAID) +#define V_SCD_TREVT_DATAID(x) _SB_MAKEVALUE(x, S_SCD_TREVT_DATAID) +#define G_SCD_TREVT_DATAID(x) _SB_GETVALUE(x, S_SCD_TREVT_DATAID, M_SCD_TREVT_DATID) + +#define S_SCD_TREVT_COUNT 24 +#define M_SCD_TREVT_COUNT _SB_MAKEMASK(8, S_SCD_TREVT_COUNT) +#define V_SCD_TREVT_COUNT(x) _SB_MAKEVALUE(x, S_SCD_TREVT_COUNT) +#define G_SCD_TREVT_COUNT(x) _SB_GETVALUE(x, S_SCD_TREVT_COUNT, M_SCD_TREVT_COUNT) + +/* + * Trace Sequence registers + */ + +#define S_SCD_TRSEQ_EVENT4 0 +#define M_SCD_TRSEQ_EVENT4 _SB_MAKEMASK(4, S_SCD_TRSEQ_EVENT4) +#define V_SCD_TRSEQ_EVENT4(x) _SB_MAKEVALUE(x, S_SCD_TRSEQ_EVENT4) +#define G_SCD_TRSEQ_EVENT4(x) _SB_GETVALUE(x, S_SCD_TRSEQ_EVENT4, M_SCD_TRSEQ_EVENT4) + +#define S_SCD_TRSEQ_EVENT3 4 +#define M_SCD_TRSEQ_EVENT3 _SB_MAKEMASK(4, S_SCD_TRSEQ_EVENT3) +#define V_SCD_TRSEQ_EVENT3(x) _SB_MAKEVALUE(x, S_SCD_TRSEQ_EVENT3) +#define G_SCD_TRSEQ_EVENT3(x) _SB_GETVALUE(x, S_SCD_TRSEQ_EVENT3, M_SCD_TRSEQ_EVENT3) + +#define S_SCD_TRSEQ_EVENT2 8 +#define M_SCD_TRSEQ_EVENT2 _SB_MAKEMASK(4, S_SCD_TRSEQ_EVENT2) +#define V_SCD_TRSEQ_EVENT2(x) _SB_MAKEVALUE(x, S_SCD_TRSEQ_EVENT2) +#define G_SCD_TRSEQ_EVENT2(x) _SB_GETVALUE(x, S_SCD_TRSEQ_EVENT2, M_SCD_TRSEQ_EVENT2) + +#define S_SCD_TRSEQ_EVENT1 12 +#define M_SCD_TRSEQ_EVENT1 _SB_MAKEMASK(4, S_SCD_TRSEQ_EVENT1) +#define V_SCD_TRSEQ_EVENT1(x) _SB_MAKEVALUE(x, S_SCD_TRSEQ_EVENT1) +#define G_SCD_TRSEQ_EVENT1(x) _SB_GETVALUE(x, S_SCD_TRSEQ_EVENT1, M_SCD_TRSEQ_EVENT1) + +#define K_SCD_TRSEQ_E0 0 +#define K_SCD_TRSEQ_E1 1 +#define K_SCD_TRSEQ_E2 2 +#define K_SCD_TRSEQ_E3 3 +#define K_SCD_TRSEQ_E0_E1 4 +#define K_SCD_TRSEQ_E1_E2 5 +#define K_SCD_TRSEQ_E2_E3 6 +#define K_SCD_TRSEQ_E0_E1_E2 7 +#define K_SCD_TRSEQ_E0_E1_E2_E3 8 +#define K_SCD_TRSEQ_E0E1 9 +#define K_SCD_TRSEQ_E0E1E2 10 +#define K_SCD_TRSEQ_E0E1E2E3 11 +#define K_SCD_TRSEQ_E0E1_E2 12 +#define K_SCD_TRSEQ_E0E1_E2E3 13 +#define K_SCD_TRSEQ_E0E1_E2_E3 14 +#define K_SCD_TRSEQ_IGNORED 15 + +#define K_SCD_TRSEQ_TRIGGER_ALL (V_SCD_TRSEQ_EVENT1(K_SCD_TRSEQ_IGNORED) | \ + V_SCD_TRSEQ_EVENT2(K_SCD_TRSEQ_IGNORED) | \ + V_SCD_TRSEQ_EVENT3(K_SCD_TRSEQ_IGNORED) | \ + V_SCD_TRSEQ_EVENT4(K_SCD_TRSEQ_IGNORED)) + +#define S_SCD_TRSEQ_FUNCTION 16 +#define M_SCD_TRSEQ_FUNCTION _SB_MAKEMASK(4, S_SCD_TRSEQ_FUNCTION) +#define V_SCD_TRSEQ_FUNCTION(x) _SB_MAKEVALUE(x, S_SCD_TRSEQ_FUNCTION) +#define G_SCD_TRSEQ_FUNCTION(x) _SB_GETVALUE(x, S_SCD_TRSEQ_FUNCTION, M_SCD_TRSEQ_FUNCTION) + +#define K_SCD_TRSEQ_FUNC_NOP 0 +#define K_SCD_TRSEQ_FUNC_START 1 +#define K_SCD_TRSEQ_FUNC_STOP 2 +#define K_SCD_TRSEQ_FUNC_FREEZE 3 + +#define V_SCD_TRSEQ_FUNC_NOP V_SCD_TRSEQ_FUNCTION(K_SCD_TRSEQ_FUNC_NOP) +#define V_SCD_TRSEQ_FUNC_START V_SCD_TRSEQ_FUNCTION(K_SCD_TRSEQ_FUNC_START) +#define V_SCD_TRSEQ_FUNC_STOP V_SCD_TRSEQ_FUNCTION(K_SCD_TRSEQ_FUNC_STOP) +#define V_SCD_TRSEQ_FUNC_FREEZE V_SCD_TRSEQ_FUNCTION(K_SCD_TRSEQ_FUNC_FREEZE) + +#define M_SCD_TRSEQ_ASAMPLE _SB_MAKEMASK1(18) +#define M_SCD_TRSEQ_DSAMPLE _SB_MAKEMASK1(19) +#define M_SCD_TRSEQ_DEBUGPIN _SB_MAKEMASK1(20) +#define M_SCD_TRSEQ_DEBUGCPU _SB_MAKEMASK1(21) +#define M_SCD_TRSEQ_CLEARUSE _SB_MAKEMASK1(22) +#define M_SCD_TRSEQ_ALLD_A _SB_MAKEMASK1(23) +#define M_SCD_TRSEQ_ALL_A _SB_MAKEMASK1(24) + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_smbus.h b/arch/mips/include/asm/sibyte/sb1250_smbus.h new file mode 100644 index 00000000000..04769923cf1 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_smbus.h @@ -0,0 +1,204 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * SMBUS Constants File: sb1250_smbus.h + * + * This module contains constants and macros useful for + * manipulating the SB1250's SMbus devices. + * + * SB1250 specification level: 10/21/02 + * BCM1280 specification level: 11/24/03 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_SMBUS_H +#define _SB1250_SMBUS_H + +#include "sb1250_defs.h" + +/* + * SMBus Clock Frequency Register (Table 14-2) + */ + +#define S_SMB_FREQ_DIV 0 +#define M_SMB_FREQ_DIV _SB_MAKEMASK(13, S_SMB_FREQ_DIV) +#define V_SMB_FREQ_DIV(x) _SB_MAKEVALUE(x, S_SMB_FREQ_DIV) + +#define K_SMB_FREQ_400KHZ 0x1F +#define K_SMB_FREQ_100KHZ 0x7D +#define K_SMB_FREQ_10KHZ 1250 + +#define S_SMB_CMD 0 +#define M_SMB_CMD _SB_MAKEMASK(8, S_SMB_CMD) +#define V_SMB_CMD(x) _SB_MAKEVALUE(x, S_SMB_CMD) + +/* + * SMBus control register (Table 14-4) + */ + +#define M_SMB_ERR_INTR _SB_MAKEMASK1(0) +#define M_SMB_FINISH_INTR _SB_MAKEMASK1(1) + +#define S_SMB_DATA_OUT 4 +#define M_SMB_DATA_OUT _SB_MAKEMASK1(S_SMB_DATA_OUT) +#define V_SMB_DATA_OUT(x) _SB_MAKEVALUE(x, S_SMB_DATA_OUT) + +#define M_SMB_DATA_DIR _SB_MAKEMASK1(5) +#define M_SMB_DATA_DIR_OUTPUT M_SMB_DATA_DIR +#define M_SMB_CLK_OUT _SB_MAKEMASK1(6) +#define M_SMB_DIRECT_ENABLE _SB_MAKEMASK1(7) + +/* + * SMBus status registers (Table 14-5) + */ + +#define M_SMB_BUSY _SB_MAKEMASK1(0) +#define M_SMB_ERROR _SB_MAKEMASK1(1) +#define M_SMB_ERROR_TYPE _SB_MAKEMASK1(2) + +#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +#define S_SMB_SCL_IN 5 +#define M_SMB_SCL_IN _SB_MAKEMASK1(S_SMB_SCL_IN) +#define V_SMB_SCL_IN(x) _SB_MAKEVALUE(x, S_SMB_SCL_IN) +#define G_SMB_SCL_IN(x) _SB_GETVALUE(x, S_SMB_SCL_IN, M_SMB_SCL_IN) +#endif /* 1250 PASS3 || 112x PASS1 || 1480 */ + +#define S_SMB_REF 6 +#define M_SMB_REF _SB_MAKEMASK1(S_SMB_REF) +#define V_SMB_REF(x) _SB_MAKEVALUE(x, S_SMB_REF) +#define G_SMB_REF(x) _SB_GETVALUE(x, S_SMB_REF, M_SMB_REF) + +#define S_SMB_DATA_IN 7 +#define M_SMB_DATA_IN _SB_MAKEMASK1(S_SMB_DATA_IN) +#define V_SMB_DATA_IN(x) _SB_MAKEVALUE(x, S_SMB_DATA_IN) +#define G_SMB_DATA_IN(x) _SB_GETVALUE(x, S_SMB_DATA_IN, M_SMB_DATA_IN) + +/* + * SMBus Start/Command registers (Table 14-9) + */ + +#define S_SMB_ADDR 0 +#define M_SMB_ADDR _SB_MAKEMASK(7, S_SMB_ADDR) +#define V_SMB_ADDR(x) _SB_MAKEVALUE(x, S_SMB_ADDR) +#define G_SMB_ADDR(x) _SB_GETVALUE(x, S_SMB_ADDR, M_SMB_ADDR) + +#define M_SMB_QDATA _SB_MAKEMASK1(7) + +#define S_SMB_TT 8 +#define M_SMB_TT _SB_MAKEMASK(3, S_SMB_TT) +#define V_SMB_TT(x) _SB_MAKEVALUE(x, S_SMB_TT) +#define G_SMB_TT(x) _SB_GETVALUE(x, S_SMB_TT, M_SMB_TT) + +#define K_SMB_TT_WR1BYTE 0 +#define K_SMB_TT_WR2BYTE 1 +#define K_SMB_TT_WR3BYTE 2 +#define K_SMB_TT_CMD_RD1BYTE 3 +#define K_SMB_TT_CMD_RD2BYTE 4 +#define K_SMB_TT_RD1BYTE 5 +#define K_SMB_TT_QUICKCMD 6 +#define K_SMB_TT_EEPROMREAD 7 + +#define V_SMB_TT_WR1BYTE V_SMB_TT(K_SMB_TT_WR1BYTE) +#define V_SMB_TT_WR2BYTE V_SMB_TT(K_SMB_TT_WR2BYTE) +#define V_SMB_TT_WR3BYTE V_SMB_TT(K_SMB_TT_WR3BYTE) +#define V_SMB_TT_CMD_RD1BYTE V_SMB_TT(K_SMB_TT_CMD_RD1BYTE) +#define V_SMB_TT_CMD_RD2BYTE V_SMB_TT(K_SMB_TT_CMD_RD2BYTE) +#define V_SMB_TT_RD1BYTE V_SMB_TT(K_SMB_TT_RD1BYTE) +#define V_SMB_TT_QUICKCMD V_SMB_TT(K_SMB_TT_QUICKCMD) +#define V_SMB_TT_EEPROMREAD V_SMB_TT(K_SMB_TT_EEPROMREAD) + +#define M_SMB_PEC _SB_MAKEMASK1(15) + +/* + * SMBus Data Register (Table 14-6) and SMBus Extra Register (Table 14-7) + */ + +#define S_SMB_LB 0 +#define M_SMB_LB _SB_MAKEMASK(8, S_SMB_LB) +#define V_SMB_LB(x) _SB_MAKEVALUE(x, S_SMB_LB) + +#define S_SMB_MB 8 +#define M_SMB_MB _SB_MAKEMASK(8, S_SMB_MB) +#define V_SMB_MB(x) _SB_MAKEVALUE(x, S_SMB_MB) + + +/* + * SMBus Packet Error Check register (Table 14-8) + */ + +#define S_SPEC_PEC 0 +#define M_SPEC_PEC _SB_MAKEMASK(8, S_SPEC_PEC) +#define V_SPEC_MB(x) _SB_MAKEVALUE(x, S_SPEC_PEC) + + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) + +#define S_SMB_CMDH 8 +#define M_SMB_CMDH _SB_MAKEMASK(8, S_SMB_CMDH) +#define V_SMB_CMDH(x) _SB_MAKEVALUE(x, S_SMB_CMDH) + +#define M_SMB_EXTEND _SB_MAKEMASK1(14) + +#define S_SMB_DFMT 8 +#define M_SMB_DFMT _SB_MAKEMASK(3, S_SMB_DFMT) +#define V_SMB_DFMT(x) _SB_MAKEVALUE(x, S_SMB_DFMT) +#define G_SMB_DFMT(x) _SB_GETVALUE(x, S_SMB_DFMT, M_SMB_DFMT) + +#define K_SMB_DFMT_1BYTE 0 +#define K_SMB_DFMT_2BYTE 1 +#define K_SMB_DFMT_3BYTE 2 +#define K_SMB_DFMT_4BYTE 3 +#define K_SMB_DFMT_NODATA 4 +#define K_SMB_DFMT_CMD4BYTE 5 +#define K_SMB_DFMT_CMD5BYTE 6 +#define K_SMB_DFMT_RESERVED 7 + +#define V_SMB_DFMT_1BYTE V_SMB_DFMT(K_SMB_DFMT_1BYTE) +#define V_SMB_DFMT_2BYTE V_SMB_DFMT(K_SMB_DFMT_2BYTE) +#define V_SMB_DFMT_3BYTE V_SMB_DFMT(K_SMB_DFMT_3BYTE) +#define V_SMB_DFMT_4BYTE V_SMB_DFMT(K_SMB_DFMT_4BYTE) +#define V_SMB_DFMT_NODATA V_SMB_DFMT(K_SMB_DFMT_NODATA) +#define V_SMB_DFMT_CMD4BYTE V_SMB_DFMT(K_SMB_DFMT_CMD4BYTE) +#define V_SMB_DFMT_CMD5BYTE V_SMB_DFMT(K_SMB_DFMT_CMD5BYTE) +#define V_SMB_DFMT_RESERVED V_SMB_DFMT(K_SMB_DFMT_RESERVED) + +#define S_SMB_AFMT 11 +#define M_SMB_AFMT _SB_MAKEMASK(2, S_SMB_AFMT) +#define V_SMB_AFMT(x) _SB_MAKEVALUE(x, S_SMB_AFMT) +#define G_SMB_AFMT(x) _SB_GETVALUE(x, S_SMB_AFMT, M_SMB_AFMT) + +#define K_SMB_AFMT_NONE 0 +#define K_SMB_AFMT_ADDR 1 +#define K_SMB_AFMT_ADDR_CMD1BYTE 2 +#define K_SMB_AFMT_ADDR_CMD2BYTE 3 + +#define V_SMB_AFMT_NONE V_SMB_AFMT(K_SMB_AFMT_NONE) +#define V_SMB_AFMT_ADDR V_SMB_AFMT(K_SMB_AFMT_ADDR) +#define V_SMB_AFMT_ADDR_CMD1BYTE V_SMB_AFMT(K_SMB_AFMT_ADDR_CMD1BYTE) +#define V_SMB_AFMT_ADDR_CMD2BYTE V_SMB_AFMT(K_SMB_AFMT_ADDR_CMD2BYTE) + +#define M_SMB_DIR _SB_MAKEMASK1(13) + +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_syncser.h b/arch/mips/include/asm/sibyte/sb1250_syncser.h new file mode 100644 index 00000000000..d4b8558e0bf --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_syncser.h @@ -0,0 +1,146 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Synchronous Serial Constants File: sb1250_syncser.h + * + * This module contains constants and macros useful for + * manipulating the SB1250's Synchronous Serial + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_SYNCSER_H +#define _SB1250_SYNCSER_H + +#include "sb1250_defs.h" + +/* + * Serial Mode Configuration Register + */ + +#define M_SYNCSER_CRC_MODE _SB_MAKEMASK1(0) +#define M_SYNCSER_MSB_FIRST _SB_MAKEMASK1(1) + +#define S_SYNCSER_FLAG_NUM 2 +#define M_SYNCSER_FLAG_NUM _SB_MAKEMASK(4, S_SYNCSER_FLAG_NUM) +#define V_SYNCSER_FLAG_NUM _SB_MAKEVALUE(x, S_SYNCSER_FLAG_NUM) + +#define M_SYNCSER_FLAG_EN _SB_MAKEMASK1(6) +#define M_SYNCSER_HDLC_EN _SB_MAKEMASK1(7) +#define M_SYNCSER_LOOP_MODE _SB_MAKEMASK1(8) +#define M_SYNCSER_LOOPBACK _SB_MAKEMASK1(9) + +/* + * Serial Clock Source and Line Interface Mode Register + */ + +#define M_SYNCSER_RXCLK_INV _SB_MAKEMASK1(0) +#define M_SYNCSER_RXCLK_EXT _SB_MAKEMASK1(1) + +#define S_SYNCSER_RXSYNC_DLY 2 +#define M_SYNCSER_RXSYNC_DLY _SB_MAKEMASK(2, S_SYNCSER_RXSYNC_DLY) +#define V_SYNCSER_RXSYNC_DLY(x) _SB_MAKEVALUE(x, S_SYNCSER_RXSYNC_DLY) + +#define M_SYNCSER_RXSYNC_LOW _SB_MAKEMASK1(4) +#define M_SYNCSER_RXSTRB_LOW _SB_MAKEMASK1(5) + +#define M_SYNCSER_RXSYNC_EDGE _SB_MAKEMASK1(6) +#define M_SYNCSER_RXSYNC_INT _SB_MAKEMASK1(7) + +#define M_SYNCSER_TXCLK_INV _SB_MAKEMASK1(8) +#define M_SYNCSER_TXCLK_EXT _SB_MAKEMASK1(9) + +#define S_SYNCSER_TXSYNC_DLY 10 +#define M_SYNCSER_TXSYNC_DLY _SB_MAKEMASK(2, S_SYNCSER_TXSYNC_DLY) +#define V_SYNCSER_TXSYNC_DLY(x) _SB_MAKEVALUE(x, S_SYNCSER_TXSYNC_DLY) + +#define M_SYNCSER_TXSYNC_LOW _SB_MAKEMASK1(12) +#define M_SYNCSER_TXSTRB_LOW _SB_MAKEMASK1(13) + +#define M_SYNCSER_TXSYNC_EDGE _SB_MAKEMASK1(14) +#define M_SYNCSER_TXSYNC_INT _SB_MAKEMASK1(15) + +/* + * Serial Command Register + */ + +#define M_SYNCSER_CMD_RX_EN _SB_MAKEMASK1(0) +#define M_SYNCSER_CMD_TX_EN _SB_MAKEMASK1(1) +#define M_SYNCSER_CMD_RX_RESET _SB_MAKEMASK1(2) +#define M_SYNCSER_CMD_TX_RESET _SB_MAKEMASK1(3) +#define M_SYNCSER_CMD_TX_PAUSE _SB_MAKEMASK1(5) + +/* + * Serial DMA Enable Register + */ + +#define M_SYNCSER_DMA_RX_EN _SB_MAKEMASK1(0) +#define M_SYNCSER_DMA_TX_EN _SB_MAKEMASK1(4) + +/* + * Serial Status Register + */ + +#define M_SYNCSER_RX_CRCERR _SB_MAKEMASK1(0) +#define M_SYNCSER_RX_ABORT _SB_MAKEMASK1(1) +#define M_SYNCSER_RX_OCTET _SB_MAKEMASK1(2) +#define M_SYNCSER_RX_LONGFRM _SB_MAKEMASK1(3) +#define M_SYNCSER_RX_SHORTFRM _SB_MAKEMASK1(4) +#define M_SYNCSER_RX_OVERRUN _SB_MAKEMASK1(5) +#define M_SYNCSER_RX_SYNC_ERR _SB_MAKEMASK1(6) +#define M_SYNCSER_TX_CRCERR _SB_MAKEMASK1(8) +#define M_SYNCSER_TX_UNDERRUN _SB_MAKEMASK1(9) +#define M_SYNCSER_TX_SYNC_ERR _SB_MAKEMASK1(10) +#define M_SYNCSER_TX_PAUSE_COMPLETE _SB_MAKEMASK1(11) +#define M_SYNCSER_RX_EOP_COUNT _SB_MAKEMASK1(16) +#define M_SYNCSER_RX_EOP_TIMER _SB_MAKEMASK1(17) +#define M_SYNCSER_RX_EOP_SEEN _SB_MAKEMASK1(18) +#define M_SYNCSER_RX_HWM _SB_MAKEMASK1(19) +#define M_SYNCSER_RX_LWM _SB_MAKEMASK1(20) +#define M_SYNCSER_RX_DSCR _SB_MAKEMASK1(21) +#define M_SYNCSER_RX_DERR _SB_MAKEMASK1(22) +#define M_SYNCSER_TX_EOP_COUNT _SB_MAKEMASK1(24) +#define M_SYNCSER_TX_EOP_TIMER _SB_MAKEMASK1(25) +#define M_SYNCSER_TX_EOP_SEEN _SB_MAKEMASK1(26) +#define M_SYNCSER_TX_HWM _SB_MAKEMASK1(27) +#define M_SYNCSER_TX_LWM _SB_MAKEMASK1(28) +#define M_SYNCSER_TX_DSCR _SB_MAKEMASK1(29) +#define M_SYNCSER_TX_DERR _SB_MAKEMASK1(30) +#define M_SYNCSER_TX_DZERO _SB_MAKEMASK1(31) + +/* + * Sequencer Table Entry format + */ + +#define M_SYNCSER_SEQ_LAST _SB_MAKEMASK1(0) +#define M_SYNCSER_SEQ_BYTE _SB_MAKEMASK1(1) + +#define S_SYNCSER_SEQ_COUNT 2 +#define M_SYNCSER_SEQ_COUNT _SB_MAKEMASK(4, S_SYNCSER_SEQ_COUNT) +#define V_SYNCSER_SEQ_COUNT(x) _SB_MAKEVALUE(x, S_SYNCSER_SEQ_COUNT) + +#define M_SYNCSER_SEQ_ENABLE _SB_MAKEMASK1(6) +#define M_SYNCSER_SEQ_STROBE _SB_MAKEMASK1(7) + +#endif diff --git a/arch/mips/include/asm/sibyte/sb1250_uart.h b/arch/mips/include/asm/sibyte/sb1250_uart.h new file mode 100644 index 00000000000..d835bf28014 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sb1250_uart.h @@ -0,0 +1,362 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * UART Constants File: sb1250_uart.h + * + * This module contains constants and macros useful for + * manipulating the SB1250's UARTs + * + * SB1250 specification level: User's manual 1/02/02 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * 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 _SB1250_UART_H +#define _SB1250_UART_H + +#include "sb1250_defs.h" + +/* ********************************************************************** + * DUART Registers + ********************************************************************** */ + +/* + * DUART Mode Register #1 (Table 10-3) + * Register: DUART_MODE_REG_1_A + * Register: DUART_MODE_REG_1_B + */ + +#define S_DUART_BITS_PER_CHAR 0 +#define M_DUART_BITS_PER_CHAR _SB_MAKEMASK(2, S_DUART_BITS_PER_CHAR) +#define V_DUART_BITS_PER_CHAR(x) _SB_MAKEVALUE(x, S_DUART_BITS_PER_CHAR) + +#define K_DUART_BITS_PER_CHAR_RSV0 0 +#define K_DUART_BITS_PER_CHAR_RSV1 1 +#define K_DUART_BITS_PER_CHAR_7 2 +#define K_DUART_BITS_PER_CHAR_8 3 + +#define V_DUART_BITS_PER_CHAR_RSV0 V_DUART_BITS_PER_CHAR(K_DUART_BITS_PER_CHAR_RSV0) +#define V_DUART_BITS_PER_CHAR_RSV1 V_DUART_BITS_PER_CHAR(K_DUART_BITS_PER_CHAR_RSV1) +#define V_DUART_BITS_PER_CHAR_7 V_DUART_BITS_PER_CHAR(K_DUART_BITS_PER_CHAR_7) +#define V_DUART_BITS_PER_CHAR_8 V_DUART_BITS_PER_CHAR(K_DUART_BITS_PER_CHAR_8) + + +#define M_DUART_PARITY_TYPE_EVEN 0x00 +#define M_DUART_PARITY_TYPE_ODD _SB_MAKEMASK1(2) + +#define S_DUART_PARITY_MODE 3 +#define M_DUART_PARITY_MODE _SB_MAKEMASK(2, S_DUART_PARITY_MODE) +#define V_DUART_PARITY_MODE(x) _SB_MAKEVALUE(x, S_DUART_PARITY_MODE) + +#define K_DUART_PARITY_MODE_ADD 0 +#define K_DUART_PARITY_MODE_ADD_FIXED 1 +#define K_DUART_PARITY_MODE_NONE 2 + +#define V_DUART_PARITY_MODE_ADD V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_ADD) +#define V_DUART_PARITY_MODE_ADD_FIXED V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_ADD_FIXED) +#define V_DUART_PARITY_MODE_NONE V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_NONE) + +#define M_DUART_TX_IRQ_SEL_TXRDY 0 +#define M_DUART_TX_IRQ_SEL_TXEMPT _SB_MAKEMASK1(5) + +#define M_DUART_RX_IRQ_SEL_RXRDY 0 +#define M_DUART_RX_IRQ_SEL_RXFULL _SB_MAKEMASK1(6) + +#define M_DUART_RX_RTS_ENA _SB_MAKEMASK1(7) + +/* + * DUART Mode Register #2 (Table 10-4) + * Register: DUART_MODE_REG_2_A + * Register: DUART_MODE_REG_2_B + */ + +#define M_DUART_MODE_RESERVED1 _SB_MAKEMASK(3, 0) /* ignored */ + +#define M_DUART_STOP_BIT_LEN_2 _SB_MAKEMASK1(3) +#define M_DUART_STOP_BIT_LEN_1 0 + +#define M_DUART_TX_CTS_ENA _SB_MAKEMASK1(4) + + +#define M_DUART_MODE_RESERVED2 _SB_MAKEMASK1(5) /* must be zero */ + +#define S_DUART_CHAN_MODE 6 +#define M_DUART_CHAN_MODE _SB_MAKEMASK(2, S_DUART_CHAN_MODE) +#define V_DUART_CHAN_MODE(x) _SB_MAKEVALUE(x, S_DUART_CHAN_MODE) + +#define K_DUART_CHAN_MODE_NORMAL 0 +#define K_DUART_CHAN_MODE_LCL_LOOP 2 +#define K_DUART_CHAN_MODE_REM_LOOP 3 + +#define V_DUART_CHAN_MODE_NORMAL V_DUART_CHAN_MODE(K_DUART_CHAN_MODE_NORMAL) +#define V_DUART_CHAN_MODE_LCL_LOOP V_DUART_CHAN_MODE(K_DUART_CHAN_MODE_LCL_LOOP) +#define V_DUART_CHAN_MODE_REM_LOOP V_DUART_CHAN_MODE(K_DUART_CHAN_MODE_REM_LOOP) + +/* + * DUART Command Register (Table 10-5) + * Register: DUART_CMD_A + * Register: DUART_CMD_B + */ + +#define M_DUART_RX_EN _SB_MAKEMASK1(0) +#define M_DUART_RX_DIS _SB_MAKEMASK1(1) +#define M_DUART_TX_EN _SB_MAKEMASK1(2) +#define M_DUART_TX_DIS _SB_MAKEMASK1(3) + +#define S_DUART_MISC_CMD 4 +#define M_DUART_MISC_CMD _SB_MAKEMASK(3, S_DUART_MISC_CMD) +#define V_DUART_MISC_CMD(x) _SB_MAKEVALUE(x, S_DUART_MISC_CMD) + +#define K_DUART_MISC_CMD_NOACTION0 0 +#define K_DUART_MISC_CMD_NOACTION1 1 +#define K_DUART_MISC_CMD_RESET_RX 2 +#define K_DUART_MISC_CMD_RESET_TX 3 +#define K_DUART_MISC_CMD_NOACTION4 4 +#define K_DUART_MISC_CMD_RESET_BREAK_INT 5 +#define K_DUART_MISC_CMD_START_BREAK 6 +#define K_DUART_MISC_CMD_STOP_BREAK 7 + +#define V_DUART_MISC_CMD_NOACTION0 V_DUART_MISC_CMD(K_DUART_MISC_CMD_NOACTION0) +#define V_DUART_MISC_CMD_NOACTION1 V_DUART_MISC_CMD(K_DUART_MISC_CMD_NOACTION1) +#define V_DUART_MISC_CMD_RESET_RX V_DUART_MISC_CMD(K_DUART_MISC_CMD_RESET_RX) +#define V_DUART_MISC_CMD_RESET_TX V_DUART_MISC_CMD(K_DUART_MISC_CMD_RESET_TX) +#define V_DUART_MISC_CMD_NOACTION4 V_DUART_MISC_CMD(K_DUART_MISC_CMD_NOACTION4) +#define V_DUART_MISC_CMD_RESET_BREAK_INT V_DUART_MISC_CMD(K_DUART_MISC_CMD_RESET_BREAK_INT) +#define V_DUART_MISC_CMD_START_BREAK V_DUART_MISC_CMD(K_DUART_MISC_CMD_START_BREAK) +#define V_DUART_MISC_CMD_STOP_BREAK V_DUART_MISC_CMD(K_DUART_MISC_CMD_STOP_BREAK) + +#define M_DUART_CMD_RESERVED _SB_MAKEMASK1(7) + +/* + * DUART Status Register (Table 10-6) + * Register: DUART_STATUS_A + * Register: DUART_STATUS_B + * READ-ONLY + */ + +#define M_DUART_RX_RDY _SB_MAKEMASK1(0) +#define M_DUART_RX_FFUL _SB_MAKEMASK1(1) +#define M_DUART_TX_RDY _SB_MAKEMASK1(2) +#define M_DUART_TX_EMT _SB_MAKEMASK1(3) +#define M_DUART_OVRUN_ERR _SB_MAKEMASK1(4) +#define M_DUART_PARITY_ERR _SB_MAKEMASK1(5) +#define M_DUART_FRM_ERR _SB_MAKEMASK1(6) +#define M_DUART_RCVD_BRK _SB_MAKEMASK1(7) + +/* + * DUART Baud Rate Register (Table 10-7) + * Register: DUART_CLK_SEL_A + * Register: DUART_CLK_SEL_B + */ + +#define M_DUART_CLK_COUNTER _SB_MAKEMASK(12, 0) +#define V_DUART_BAUD_RATE(x) (100000000/((x)*20)-1) + +/* + * DUART Data Registers (Table 10-8 and 10-9) + * Register: DUART_RX_HOLD_A + * Register: DUART_RX_HOLD_B + * Register: DUART_TX_HOLD_A + * Register: DUART_TX_HOLD_B + */ + +#define M_DUART_RX_DATA _SB_MAKEMASK(8, 0) +#define M_DUART_TX_DATA _SB_MAKEMASK(8, 0) + +/* + * DUART Input Port Register (Table 10-10) + * Register: DUART_IN_PORT + */ + +#define M_DUART_IN_PIN0_VAL _SB_MAKEMASK1(0) +#define M_DUART_IN_PIN1_VAL _SB_MAKEMASK1(1) +#define M_DUART_IN_PIN2_VAL _SB_MAKEMASK1(2) +#define M_DUART_IN_PIN3_VAL _SB_MAKEMASK1(3) +#define M_DUART_IN_PIN4_VAL _SB_MAKEMASK1(4) +#define M_DUART_IN_PIN5_VAL _SB_MAKEMASK1(5) +#define M_DUART_RIN0_PIN _SB_MAKEMASK1(6) +#define M_DUART_RIN1_PIN _SB_MAKEMASK1(7) + +/* + * DUART Input Port Change Status Register (Tables 10-11, 10-12, and 10-13) + * Register: DUART_INPORT_CHNG + */ + +#define S_DUART_IN_PIN_VAL 0 +#define M_DUART_IN_PIN_VAL _SB_MAKEMASK(4, S_DUART_IN_PIN_VAL) + +#define S_DUART_IN_PIN_CHNG 4 +#define M_DUART_IN_PIN_CHNG _SB_MAKEMASK(4, S_DUART_IN_PIN_CHNG) + + +/* + * DUART Output port control register (Table 10-14) + * Register: DUART_OPCR + */ + +#define M_DUART_OPCR_RESERVED0 _SB_MAKEMASK1(0) /* must be zero */ +#define M_DUART_OPC2_SEL _SB_MAKEMASK1(1) +#define M_DUART_OPCR_RESERVED1 _SB_MAKEMASK1(2) /* must be zero */ +#define M_DUART_OPC3_SEL _SB_MAKEMASK1(3) +#define M_DUART_OPCR_RESERVED2 _SB_MAKEMASK(4, 4) /* must be zero */ + +/* + * DUART Aux Control Register (Table 10-15) + * Register: DUART_AUX_CTRL + */ + +#define M_DUART_IP0_CHNG_ENA _SB_MAKEMASK1(0) +#define M_DUART_IP1_CHNG_ENA _SB_MAKEMASK1(1) +#define M_DUART_IP2_CHNG_ENA _SB_MAKEMASK1(2) +#define M_DUART_IP3_CHNG_ENA _SB_MAKEMASK1(3) +#define M_DUART_ACR_RESERVED _SB_MAKEMASK(4, 4) + +#define M_DUART_CTS_CHNG_ENA _SB_MAKEMASK1(0) +#define M_DUART_CIN_CHNG_ENA _SB_MAKEMASK1(2) + +/* + * DUART Interrupt Status Register (Table 10-16) + * Register: DUART_ISR + */ + +#define M_DUART_ISR_TX_A _SB_MAKEMASK1(0) + +#define S_DUART_ISR_RX_A 1 +#define M_DUART_ISR_RX_A _SB_MAKEMASK1(S_DUART_ISR_RX_A) +#define V_DUART_ISR_RX_A(x) _SB_MAKEVALUE(x, S_DUART_ISR_RX_A) +#define G_DUART_ISR_RX_A(x) _SB_GETVALUE(x, S_DUART_ISR_RX_A, M_DUART_ISR_RX_A) + +#define M_DUART_ISR_BRK_A _SB_MAKEMASK1(2) +#define M_DUART_ISR_IN_A _SB_MAKEMASK1(3) +#define M_DUART_ISR_ALL_A _SB_MAKEMASK(4, 0) + +#define M_DUART_ISR_TX_B _SB_MAKEMASK1(4) +#define M_DUART_ISR_RX_B _SB_MAKEMASK1(5) +#define M_DUART_ISR_BRK_B _SB_MAKEMASK1(6) +#define M_DUART_ISR_IN_B _SB_MAKEMASK1(7) +#define M_DUART_ISR_ALL_B _SB_MAKEMASK(4, 4) + +/* + * DUART Channel A Interrupt Status Register (Table 10-17) + * DUART Channel B Interrupt Status Register (Table 10-18) + * Register: DUART_ISR_A + * Register: DUART_ISR_B + */ + +#define M_DUART_ISR_TX _SB_MAKEMASK1(0) +#define M_DUART_ISR_RX _SB_MAKEMASK1(1) +#define M_DUART_ISR_BRK _SB_MAKEMASK1(2) +#define M_DUART_ISR_IN _SB_MAKEMASK1(3) +#define M_DUART_ISR_ALL _SB_MAKEMASK(4, 0) +#define M_DUART_ISR_RESERVED _SB_MAKEMASK(4, 4) + +/* + * DUART Interrupt Mask Register (Table 10-19) + * Register: DUART_IMR + */ + +#define M_DUART_IMR_TX_A _SB_MAKEMASK1(0) +#define M_DUART_IMR_RX_A _SB_MAKEMASK1(1) +#define M_DUART_IMR_BRK_A _SB_MAKEMASK1(2) +#define M_DUART_IMR_IN_A _SB_MAKEMASK1(3) +#define M_DUART_IMR_ALL_A _SB_MAKEMASK(4, 0) + +#define M_DUART_IMR_TX_B _SB_MAKEMASK1(4) +#define M_DUART_IMR_RX_B _SB_MAKEMASK1(5) +#define M_DUART_IMR_BRK_B _SB_MAKEMASK1(6) +#define M_DUART_IMR_IN_B _SB_MAKEMASK1(7) +#define M_DUART_IMR_ALL_B _SB_MAKEMASK(4, 4) + +/* + * DUART Channel A Interrupt Mask Register (Table 10-20) + * DUART Channel B Interrupt Mask Register (Table 10-21) + * Register: DUART_IMR_A + * Register: DUART_IMR_B + */ + +#define M_DUART_IMR_TX _SB_MAKEMASK1(0) +#define M_DUART_IMR_RX _SB_MAKEMASK1(1) +#define M_DUART_IMR_BRK _SB_MAKEMASK1(2) +#define M_DUART_IMR_IN _SB_MAKEMASK1(3) +#define M_DUART_IMR_ALL _SB_MAKEMASK(4, 0) +#define M_DUART_IMR_RESERVED _SB_MAKEMASK(4, 4) + + +/* + * DUART Output Port Set Register (Table 10-22) + * Register: DUART_SET_OPR + */ + +#define M_DUART_SET_OPR0 _SB_MAKEMASK1(0) +#define M_DUART_SET_OPR1 _SB_MAKEMASK1(1) +#define M_DUART_SET_OPR2 _SB_MAKEMASK1(2) +#define M_DUART_SET_OPR3 _SB_MAKEMASK1(3) +#define M_DUART_OPSR_RESERVED _SB_MAKEMASK(4, 4) + +/* + * DUART Output Port Clear Register (Table 10-23) + * Register: DUART_CLEAR_OPR + */ + +#define M_DUART_CLR_OPR0 _SB_MAKEMASK1(0) +#define M_DUART_CLR_OPR1 _SB_MAKEMASK1(1) +#define M_DUART_CLR_OPR2 _SB_MAKEMASK1(2) +#define M_DUART_CLR_OPR3 _SB_MAKEMASK1(3) +#define M_DUART_OPCR_RESERVED _SB_MAKEMASK(4, 4) + +/* + * DUART Output Port RTS Register (Table 10-24) + * Register: DUART_OUT_PORT + */ + +#define M_DUART_OUT_PIN_SET0 _SB_MAKEMASK1(0) +#define M_DUART_OUT_PIN_SET1 _SB_MAKEMASK1(1) +#define M_DUART_OUT_PIN_CLR0 _SB_MAKEMASK1(2) +#define M_DUART_OUT_PIN_CLR1 _SB_MAKEMASK1(3) +#define M_DUART_OPRR_RESERVED _SB_MAKEMASK(4, 4) + +#define M_DUART_OUT_PIN_SET(chan) \ + (chan == 0 ? M_DUART_OUT_PIN_SET0 : M_DUART_OUT_PIN_SET1) +#define M_DUART_OUT_PIN_CLR(chan) \ + (chan == 0 ? M_DUART_OUT_PIN_CLR0 : M_DUART_OUT_PIN_CLR1) + +#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) +/* + * Full Interrupt Control Register + */ + +#define S_DUART_SIG_FULL _SB_MAKE64(0) +#define M_DUART_SIG_FULL _SB_MAKEMASK(4, S_DUART_SIG_FULL) +#define V_DUART_SIG_FULL(x) _SB_MAKEVALUE(x, S_DUART_SIG_FULL) +#define G_DUART_SIG_FULL(x) _SB_GETVALUE(x, S_DUART_SIG_FULL, M_DUART_SIG_FULL) + +#define S_DUART_INT_TIME _SB_MAKE64(4) +#define M_DUART_INT_TIME _SB_MAKEMASK(4, S_DUART_INT_TIME) +#define V_DUART_INT_TIME(x) _SB_MAKEVALUE(x, S_DUART_INT_TIME) +#define G_DUART_INT_TIME(x) _SB_GETVALUE(x, S_DUART_INT_TIME, M_DUART_INT_TIME) +#endif /* 1250 PASS2 || 112x PASS1 || 1480 */ + + +/* ********************************************************************** */ + + +#endif diff --git a/arch/mips/include/asm/sibyte/sentosa.h b/arch/mips/include/asm/sibyte/sentosa.h new file mode 100644 index 00000000000..64c47874f32 --- /dev/null +++ b/arch/mips/include/asm/sibyte/sentosa.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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_SIBYTE_SENTOSA_H +#define __ASM_SIBYTE_SENTOSA_H + +#include +#include + +#ifdef CONFIG_SIBYTE_SENTOSA +#define SIBYTE_BOARD_NAME "BCM91250E (Sentosa)" +#endif +#ifdef CONFIG_SIBYTE_RHONE +#define SIBYTE_BOARD_NAME "BCM91125E (Rhone)" +#endif + +/* Generic bus chip selects */ +#ifdef CONFIG_SIBYTE_RHONE +#define LEDS_CS 6 +#define LEDS_PHYS 0x1d0a0000 +#endif + +/* GPIOs */ +#define K_GPIO_DBG_LED 0 + +#endif /* __ASM_SIBYTE_SENTOSA_H */ diff --git a/arch/mips/include/asm/sibyte/swarm.h b/arch/mips/include/asm/sibyte/swarm.h new file mode 100644 index 00000000000..114d9d29ca9 --- /dev/null +++ b/arch/mips/include/asm/sibyte/swarm.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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_SIBYTE_SWARM_H +#define __ASM_SIBYTE_SWARM_H + +#include +#include + +#ifdef CONFIG_SIBYTE_SWARM +#define SIBYTE_BOARD_NAME "BCM91250A (SWARM)" +#define SIBYTE_HAVE_PCMCIA 1 +#define SIBYTE_HAVE_IDE 1 +#endif +#ifdef CONFIG_SIBYTE_LITTLESUR +#define SIBYTE_BOARD_NAME "BCM91250C2 (LittleSur)" +#define SIBYTE_HAVE_PCMCIA 0 +#define SIBYTE_HAVE_IDE 1 +#define SIBYTE_DEFAULT_CONSOLE "cfe0" +#endif +#ifdef CONFIG_SIBYTE_CRHONE +#define SIBYTE_BOARD_NAME "BCM91125C (CRhone)" +#define SIBYTE_HAVE_PCMCIA 0 +#define SIBYTE_HAVE_IDE 0 +#endif +#ifdef CONFIG_SIBYTE_CRHINE +#define SIBYTE_BOARD_NAME "BCM91120C (CRhine)" +#define SIBYTE_HAVE_PCMCIA 0 +#define SIBYTE_HAVE_IDE 0 +#endif + +/* Generic bus chip selects */ +#define LEDS_CS 3 +#define LEDS_PHYS 0x100a0000 + +#ifdef SIBYTE_HAVE_IDE +#define IDE_CS 4 +#define IDE_PHYS 0x100b0000 +#define K_GPIO_GB_IDE 4 +#define K_INT_GB_IDE (K_INT_GPIO_0 + K_GPIO_GB_IDE) +#endif + +#ifdef SIBYTE_HAVE_PCMCIA +#define PCMCIA_CS 6 +#define PCMCIA_PHYS 0x11000000 +#define K_GPIO_PC_READY 9 +#define K_INT_PC_READY (K_INT_GPIO_0 + K_GPIO_PC_READY) +#endif + +#endif /* __ASM_SIBYTE_SWARM_H */ diff --git a/arch/mips/include/asm/sigcontext.h b/arch/mips/include/asm/sigcontext.h new file mode 100644 index 00000000000..9ce0607d7a4 --- /dev/null +++ b/arch/mips/include/asm/sigcontext.h @@ -0,0 +1,100 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1999 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_SIGCONTEXT_H +#define _ASM_SIGCONTEXT_H + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + +/* + * Keep this struct definition in sync with the sigcontext fragment + * in arch/mips/tools/offset.c + */ +struct sigcontext { + unsigned int sc_regmask; /* Unused */ + unsigned int sc_status; /* Unused */ + unsigned long long sc_pc; + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned int sc_acx; /* Was sc_ownedfp */ + unsigned int sc_fpc_csr; + unsigned int sc_fpc_eir; /* Unused */ + unsigned int sc_used_math; + unsigned int sc_dsp; /* dsp status, was sc_ssflags */ + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; + unsigned long sc_hi1; /* Was sc_cause */ + unsigned long sc_lo1; /* Was sc_badvaddr */ + unsigned long sc_hi2; /* Was sc_sigset[4] */ + unsigned long sc_lo2; + unsigned long sc_hi3; + unsigned long sc_lo3; +}; + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ + +#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 + +#include +/* + * Keep this struct definition in sync with the sigcontext fragment + * in arch/mips/tools/offset.c + * + * Warning: this structure illdefined with sc_badvaddr being just an unsigned + * int so it was changed to unsigned long in 2.6.0-test1. This may break + * binary compatibility - no prisoners. + * DSP ASE in 2.6.12-rc4. Turn sc_mdhi and sc_mdlo into an array of four + * entries, add sc_dsp and sc_reserved for padding. No prisoners. + */ +struct sigcontext { + __u64 sc_regs[32]; + __u64 sc_fpregs[32]; + __u64 sc_mdhi; + __u64 sc_hi1; + __u64 sc_hi2; + __u64 sc_hi3; + __u64 sc_mdlo; + __u64 sc_lo1; + __u64 sc_lo2; + __u64 sc_lo3; + __u64 sc_pc; + __u32 sc_fpc_csr; + __u32 sc_used_math; + __u32 sc_dsp; + __u32 sc_reserved; +}; + +#ifdef __KERNEL__ + +struct sigcontext32 { + __u32 sc_regmask; /* Unused */ + __u32 sc_status; /* Unused */ + __u64 sc_pc; + __u64 sc_regs[32]; + __u64 sc_fpregs[32]; + __u32 sc_acx; /* Only MIPS32; was sc_ownedfp */ + __u32 sc_fpc_csr; + __u32 sc_fpc_eir; /* Unused */ + __u32 sc_used_math; + __u32 sc_dsp; /* dsp status, was sc_ssflags */ + __u64 sc_mdhi; + __u64 sc_mdlo; + __u32 sc_hi1; /* Was sc_cause */ + __u32 sc_lo1; /* Was sc_badvaddr */ + __u32 sc_hi2; /* Was sc_sigset[4] */ + __u32 sc_lo2; + __u32 sc_hi3; + __u32 sc_lo3; +}; +#endif /* __KERNEL__ */ + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */ + +#endif /* _ASM_SIGCONTEXT_H */ diff --git a/arch/mips/include/asm/siginfo.h b/arch/mips/include/asm/siginfo.h new file mode 100644 index 00000000000..96e28f18dad --- /dev/null +++ b/arch/mips/include/asm/siginfo.h @@ -0,0 +1,130 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 1999, 2001, 2003 Ralf Baechle + * Copyright (C) 2000, 2001 Silicon Graphics, Inc. + */ +#ifndef _ASM_SIGINFO_H +#define _ASM_SIGINFO_H + + +#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(long) + 2*sizeof(int)) +#undef __ARCH_SI_TRAPNO /* exception code needs to fill this ... */ + +#define HAVE_ARCH_SIGINFO_T + +/* + * We duplicate the generic versions - is just borked + * by design ... + */ +#define HAVE_ARCH_COPY_SIGINFO +struct siginfo; + +/* + * Careful to keep union _sifields from shifting ... + */ +#ifdef CONFIG_32BIT +#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int)) +#endif +#ifdef CONFIG_64BIT +#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +#endif + +#include + +typedef struct siginfo { + int si_signo; + int si_code; + int si_errno; + int __pad0[SI_MAX_SIZE / sizeof(int) - SI_PAD_SIZE - 3]; + + union { + int _pad[SI_PAD_SIZE]; + + /* kill() */ + struct { + pid_t _pid; /* sender's pid */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; + sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + pid_t _pid; /* sender's pid */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + pid_t _pid; /* which child */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + int _status; /* exit code */ + clock_t _utime; + clock_t _stime; + } _sigchld; + + /* IRIX SIGCHLD */ + struct { + pid_t _pid; /* which child */ + clock_t _utime; + int _status; /* exit code */ + clock_t _stime; + } _irix_sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + void __user *_addr; /* faulting insn/memory ref. */ +#ifdef __ARCH_SI_TRAPNO + int _trapno; /* TRAP # which caused the signal */ +#endif + } _sigfault; + + /* SIGPOLL, SIGXFSZ (To do ...) */ + struct { + __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} siginfo_t; + +/* + * si_code values + * Again these have been choosen to be IRIX compatible. + */ +#undef SI_ASYNCIO +#undef SI_TIMER +#undef SI_MESGQ +#define SI_ASYNCIO -2 /* sent by AIO completion */ +#define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */ +#define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */ + +#ifdef __KERNEL__ + +/* + * Duplicated here because of braindamage ... + */ +#include + +static inline void copy_siginfo(struct siginfo *to, struct siginfo *from) +{ + if (from->si_code < 0) + memcpy(to, from, sizeof(*to)); + else + /* _sigchld is currently the largest know union member */ + memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld)); +} + +#endif + +#endif /* _ASM_SIGINFO_H */ diff --git a/arch/mips/include/asm/signal.h b/arch/mips/include/asm/signal.h new file mode 100644 index 00000000000..bee5153aca4 --- /dev/null +++ b/arch/mips/include/asm/signal.h @@ -0,0 +1,139 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 97, 98, 99, 2003 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_SIGNAL_H +#define _ASM_SIGNAL_H + +#include + +#define _NSIG 128 +#define _NSIG_BPW (sizeof(unsigned long) * 8) +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +typedef unsigned long old_sigset_t; /* at least 32 bits */ + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGABRT SIGIOT /* Abort (ANSI). */ +#define SIGEMT 7 +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGBUS 10 /* BUS error (4.2 BSD). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGSYS 12 +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGUSR1 16 /* User-defined signal 1 (POSIX). */ +#define SIGUSR2 17 /* User-defined signal 2 (POSIX). */ +#define SIGCHLD 18 /* Child status has changed (POSIX). */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGPWR 19 /* Power failure restart (System V). */ +#define SIGWINCH 20 /* Window size change (4.3 BSD, Sun). */ +#define SIGURG 21 /* Urgent condition on socket (4.2 BSD). */ +#define SIGIO 22 /* I/O now possible (4.2 BSD). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGSTOP 23 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 24 /* Keyboard stop (POSIX). */ +#define SIGCONT 25 /* Continue (POSIX). */ +#define SIGTTIN 26 /* Background read from tty (POSIX). */ +#define SIGTTOU 27 /* Background write to tty (POSIX). */ +#define SIGVTALRM 28 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 29 /* Profiling alarm clock (4.2 BSD). */ +#define SIGXCPU 30 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 31 /* File size limit exceeded (4.2 BSD). */ + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX _NSIG + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_ONSTACK 0x08000000 +#define SA_RESETHAND 0x80000000 +#define SA_RESTART 0x10000000 +#define SA_SIGINFO 0x00000008 +#define SA_NODEFER 0x40000000 +#define SA_NOCLDWAIT 0x00010000 +#define SA_NOCLDSTOP 0x00000001 + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND + +#define SA_RESTORER 0x04000000 /* Only for o32 */ + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +#ifdef __KERNEL__ + +#ifdef CONFIG_TRAD_SIGNALS +#define sig_uses_siginfo(ka) ((ka)->sa.sa_flags & SA_SIGINFO) +#else +#define sig_uses_siginfo(ka) (1) +#endif + +#endif /* __KERNEL__ */ + +#define SIG_BLOCK 1 /* for blocking signals */ +#define SIG_UNBLOCK 2 /* for unblocking signals */ +#define SIG_SETMASK 3 /* for setting the signal mask */ + +#include + +struct sigaction { + unsigned int sa_flags; + __sighandler_t sa_handler; + sigset_t sa_mask; +}; + +struct k_sigaction { + struct sigaction sa; +}; + +/* IRIX compatible stack_t */ +typedef struct sigaltstack { + void __user *ss_sp; + size_t ss_size; + int ss_flags; +} stack_t; + +#ifdef __KERNEL__ +#include +#include + +#define ptrace_signal_deliver(regs, cookie) do { } while (0) + +#endif /* __KERNEL__ */ + +#endif /* _ASM_SIGNAL_H */ diff --git a/arch/mips/include/asm/sim.h b/arch/mips/include/asm/sim.h new file mode 100644 index 00000000000..0cd719fabb5 --- /dev/null +++ b/arch/mips/include/asm/sim.h @@ -0,0 +1,82 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999, 2000, 2003 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_SIM_H +#define _ASM_SIM_H + + +#include + +#define __str2(x) #x +#define __str(x) __str2(x) + +#ifdef CONFIG_32BIT + +#define save_static_function(symbol) \ +__asm__( \ + ".text\n\t" \ + ".globl\t" #symbol "\n\t" \ + ".align\t2\n\t" \ + ".type\t" #symbol ", @function\n\t" \ + ".ent\t" #symbol ", 0\n" \ + #symbol":\n\t" \ + ".frame\t$29, 0, $31\n\t" \ + "sw\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t" \ + "sw\t$17,"__str(PT_R17)"($29)\n\t" \ + "sw\t$18,"__str(PT_R18)"($29)\n\t" \ + "sw\t$19,"__str(PT_R19)"($29)\n\t" \ + "sw\t$20,"__str(PT_R20)"($29)\n\t" \ + "sw\t$21,"__str(PT_R21)"($29)\n\t" \ + "sw\t$22,"__str(PT_R22)"($29)\n\t" \ + "sw\t$23,"__str(PT_R23)"($29)\n\t" \ + "sw\t$30,"__str(PT_R30)"($29)\n\t" \ + "j\t_" #symbol "\n\t" \ + ".end\t" #symbol "\n\t" \ + ".size\t" #symbol",. - " #symbol) + +#define nabi_no_regargs + +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT + +#define save_static_function(symbol) \ +__asm__( \ + ".text\n\t" \ + ".globl\t" #symbol "\n\t" \ + ".align\t2\n\t" \ + ".type\t" #symbol ", @function\n\t" \ + ".ent\t" #symbol ", 0\n" \ + #symbol":\n\t" \ + ".frame\t$29, 0, $31\n\t" \ + "sd\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t" \ + "sd\t$17,"__str(PT_R17)"($29)\n\t" \ + "sd\t$18,"__str(PT_R18)"($29)\n\t" \ + "sd\t$19,"__str(PT_R19)"($29)\n\t" \ + "sd\t$20,"__str(PT_R20)"($29)\n\t" \ + "sd\t$21,"__str(PT_R21)"($29)\n\t" \ + "sd\t$22,"__str(PT_R22)"($29)\n\t" \ + "sd\t$23,"__str(PT_R23)"($29)\n\t" \ + "sd\t$30,"__str(PT_R30)"($29)\n\t" \ + "j\t_" #symbol "\n\t" \ + ".end\t" #symbol "\n\t" \ + ".size\t" #symbol",. - " #symbol) + +#define nabi_no_regargs \ + unsigned long __dummy0, \ + unsigned long __dummy1, \ + unsigned long __dummy2, \ + unsigned long __dummy3, \ + unsigned long __dummy4, \ + unsigned long __dummy5, \ + unsigned long __dummy6, \ + unsigned long __dummy7, + +#endif /* CONFIG_64BIT */ + +#endif /* _ASM_SIM_H */ diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h new file mode 100644 index 00000000000..43c207e72a6 --- /dev/null +++ b/arch/mips/include/asm/smp-ops.h @@ -0,0 +1,57 @@ +/* + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) + * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. + * Copyright (C) 2000, 2001, 2002 Ralf Baechle + * Copyright (C) 2000, 2001 Broadcom Corporation + */ +#ifndef __ASM_SMP_OPS_H +#define __ASM_SMP_OPS_H + +#ifdef CONFIG_SMP + +#include + +struct plat_smp_ops { + void (*send_ipi_single)(int cpu, unsigned int action); + void (*send_ipi_mask)(cpumask_t mask, unsigned int action); + void (*init_secondary)(void); + void (*smp_finish)(void); + void (*cpus_done)(void); + void (*boot_secondary)(int cpu, struct task_struct *idle); + void (*smp_setup)(void); + void (*prepare_cpus)(unsigned int max_cpus); +}; + +extern void register_smp_ops(struct plat_smp_ops *ops); + +static inline void plat_smp_setup(void) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + mp_ops->smp_setup(); +} + +#else /* !CONFIG_SMP */ + +struct plat_smp_ops; + +static inline void plat_smp_setup(void) +{ + /* UP, nothing to do ... */ +} + +static inline void register_smp_ops(struct plat_smp_ops *ops) +{ +} + +#endif /* !CONFIG_SMP */ + +extern struct plat_smp_ops up_smp_ops; +extern struct plat_smp_ops cmp_smp_ops; +extern struct plat_smp_ops vsmp_smp_ops; + +#endif /* __ASM_SMP_OPS_H */ diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h new file mode 100644 index 00000000000..0ff5b523ea7 --- /dev/null +++ b/arch/mips/include/asm/smp.h @@ -0,0 +1,63 @@ +/* + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) + * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. + * Copyright (C) 2000, 2001, 2002 Ralf Baechle + * Copyright (C) 2000, 2001 Broadcom Corporation + */ +#ifndef __ASM_SMP_H +#define __ASM_SMP_H + +#include +#include +#include +#include + +#include +#include + +extern int smp_num_siblings; +extern cpumask_t cpu_sibling_map[]; + +#define raw_smp_processor_id() (current_thread_info()->cpu) + +/* Map from cpu id to sequential logical cpu number. This will only + not be idempotent when cpus failed to come on-line. */ +extern int __cpu_number_map[NR_CPUS]; +#define cpu_number_map(cpu) __cpu_number_map[cpu] + +/* The reverse map from sequential logical cpu number to cpu id. */ +extern int __cpu_logical_map[NR_CPUS]; +#define cpu_logical_map(cpu) __cpu_logical_map[cpu] + +#define NO_PROC_ID (-1) + +#define SMP_RESCHEDULE_YOURSELF 0x1 /* XXX braindead */ +#define SMP_CALL_FUNCTION 0x2 + +extern cpumask_t phys_cpu_present_map; +#define cpu_possible_map phys_cpu_present_map + +extern void asmlinkage smp_bootstrap(void); + +/* + * this function sends a 'reschedule' IPI to another CPU. + * it goes straight through and wastes no time serializing + * anything. Worst case is that we lose a reschedule ... + */ +static inline void smp_send_reschedule(int cpu) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF); +} + +extern asmlinkage void smp_call_function_interrupt(void); + +extern void arch_send_call_function_single_ipi(int cpu); +extern void arch_send_call_function_ipi(cpumask_t mask); + +#endif /* __ASM_SMP_H */ diff --git a/arch/mips/include/asm/smtc.h b/arch/mips/include/asm/smtc.h new file mode 100644 index 00000000000..ea60bf08dcb --- /dev/null +++ b/arch/mips/include/asm/smtc.h @@ -0,0 +1,71 @@ +#ifndef _ASM_SMTC_MT_H +#define _ASM_SMTC_MT_H + +/* + * Definitions for SMTC multitasking on MIPS MT cores + */ + +#include +#include + +/* + * System-wide SMTC status information + */ + +extern unsigned int smtc_status; + +#define SMTC_TLB_SHARED 0x00000001 +#define SMTC_MTC_ACTIVE 0x00000002 + +/* + * TLB/ASID Management information + */ + +#define MAX_SMTC_TLBS 2 +#define MAX_SMTC_ASIDS 256 +#if NR_CPUS <= 8 +typedef char asiduse; +#else +#if NR_CPUS <= 16 +typedef short asiduse; +#else +typedef long asiduse; +#endif +#endif + +extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; + +struct mm_struct; +struct task_struct; + +void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu); +void self_ipi(struct smtc_ipi *); +void smtc_flush_tlb_asid(unsigned long asid); +extern int smtc_build_cpu_map(int startslot); +extern void smtc_prepare_cpus(int cpus); +extern void smtc_smp_finish(void); +extern void smtc_boot_secondary(int cpu, struct task_struct *t); +extern void smtc_cpus_done(void); + + +/* + * Sharing the TLB between multiple VPEs means that the + * "random" index selection function is not allowed to + * select the current value of the Index register. To + * avoid additional TLB pressure, the Index registers + * are "parked" with an non-Valid value. + */ + +#define PARKED_INDEX ((unsigned int)0x80000000) + +/* + * Define low-level interrupt mask for IPIs, if necessary. + * By default, use SW interrupt 1, which requires no external + * hardware support, but which works only for single-core + * MIPS MT systems. + */ +#ifndef MIPS_CPU_IPI_IRQ +#define MIPS_CPU_IPI_IRQ 1 +#endif + +#endif /* _ASM_SMTC_MT_H */ diff --git a/arch/mips/include/asm/smtc_ipi.h b/arch/mips/include/asm/smtc_ipi.h new file mode 100644 index 00000000000..8ce51757434 --- /dev/null +++ b/arch/mips/include/asm/smtc_ipi.h @@ -0,0 +1,128 @@ +/* + * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code. + */ +#ifndef __ASM_SMTC_IPI_H +#define __ASM_SMTC_IPI_H + +#include + +//#define SMTC_IPI_DEBUG + +#ifdef SMTC_IPI_DEBUG +#include +#include +#endif /* SMTC_IPI_DEBUG */ + +/* + * An IPI "message" + */ + +struct smtc_ipi { + struct smtc_ipi *flink; + int type; + void *arg; + int dest; +#ifdef SMTC_IPI_DEBUG + int sender; + long stamp; +#endif /* SMTC_IPI_DEBUG */ +}; + +/* + * Defined IPI Types + */ + +#define LINUX_SMP_IPI 1 +#define SMTC_CLOCK_TICK 2 +#define IRQ_AFFINITY_IPI 3 + +/* + * A queue of IPI messages + */ + +struct smtc_ipi_q { + struct smtc_ipi *head; + spinlock_t lock; + struct smtc_ipi *tail; + int depth; +}; + +static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) +{ + unsigned long flags; + + spin_lock_irqsave(&q->lock, flags); + if (q->head == NULL) + q->head = q->tail = p; + else + q->tail->flink = p; + p->flink = NULL; + q->tail = p; + q->depth++; +#ifdef SMTC_IPI_DEBUG + p->sender = read_c0_tcbind(); + p->stamp = read_c0_count(); +#endif /* SMTC_IPI_DEBUG */ + spin_unlock_irqrestore(&q->lock, flags); +} + +static inline struct smtc_ipi *__smtc_ipi_dq(struct smtc_ipi_q *q) +{ + struct smtc_ipi *p; + + if (q->head == NULL) + p = NULL; + else { + p = q->head; + q->head = q->head->flink; + q->depth--; + /* Arguably unnecessary, but leaves queue cleaner */ + if (q->head == NULL) + q->tail = NULL; + } + + return p; +} + +static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q) +{ + unsigned long flags; + struct smtc_ipi *p; + + spin_lock_irqsave(&q->lock, flags); + p = __smtc_ipi_dq(q); + spin_unlock_irqrestore(&q->lock, flags); + + return p; +} + +static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p) +{ + unsigned long flags; + + spin_lock_irqsave(&q->lock, flags); + if (q->head == NULL) { + q->head = q->tail = p; + p->flink = NULL; + } else { + p->flink = q->head; + q->head = p; + } + q->depth++; + spin_unlock_irqrestore(&q->lock, flags); +} + +static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q) +{ + unsigned long flags; + int retval; + + spin_lock_irqsave(&q->lock, flags); + retval = q->depth; + spin_unlock_irqrestore(&q->lock, flags); + return retval; +} + +extern void smtc_send_ipi(int cpu, int type, unsigned int action); + +#endif /* __ASM_SMTC_IPI_H */ diff --git a/arch/mips/include/asm/smtc_proc.h b/arch/mips/include/asm/smtc_proc.h new file mode 100644 index 00000000000..25da651f1f5 --- /dev/null +++ b/arch/mips/include/asm/smtc_proc.h @@ -0,0 +1,23 @@ +/* + * Definitions for SMTC /proc entries + * Copyright(C) 2005 MIPS Technologies Inc. + */ +#ifndef __ASM_SMTC_PROC_H +#define __ASM_SMTC_PROC_H + +/* + * per-"CPU" statistics + */ + +struct smtc_cpu_proc { + unsigned long timerints; + unsigned long selfipis; +}; + +extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS]; + +/* Count of number of recoveries of "stolen" FPU access rights on 34K */ + +extern atomic_t smtc_fpu_recoveries; + +#endif /* __ASM_SMTC_PROC_H */ diff --git a/arch/mips/include/asm/smvp.h b/arch/mips/include/asm/smvp.h new file mode 100644 index 00000000000..0d0e80a39e8 --- /dev/null +++ b/arch/mips/include/asm/smvp.h @@ -0,0 +1,19 @@ +#ifndef _ASM_SMVP_H +#define _ASM_SMVP_H + +/* + * Definitions for SMVP multitasking on MIPS MT cores + */ +struct task_struct; + +extern void smvp_smp_setup(void); +extern void smvp_smp_finish(void); +extern void smvp_boot_secondary(int cpu, struct task_struct *t); +extern void smvp_init_secondary(void); +extern void smvp_smp_finish(void); +extern void smvp_cpus_done(void); +extern void smvp_prepare_cpus(unsigned int max_cpus); + +/* This is platform specific */ +extern void smvp_send_ipi(int cpu, unsigned int action); +#endif /* _ASM_SMVP_H */ diff --git a/arch/mips/include/asm/sn/addrs.h b/arch/mips/include/asm/sn/addrs.h new file mode 100644 index 00000000000..fec9bdd3491 --- /dev/null +++ b/arch/mips/include/asm/sn/addrs.h @@ -0,0 +1,430 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999, 2000 by Ralf Baechle + */ +#ifndef _ASM_SN_ADDRS_H +#define _ASM_SN_ADDRS_H + + +#ifndef __ASSEMBLY__ +#include +#endif /* !__ASSEMBLY__ */ + +#include +#include + +#if defined(CONFIG_SGI_IP27) +#include +#elif defined(CONFIG_SGI_IP35) +#include +#endif + + +#ifndef __ASSEMBLY__ + +#define PS_UINT_CAST (unsigned long) +#define UINT64_CAST (unsigned long) + +#define HUBREG_CAST (volatile hubreg_t *) + +#else /* __ASSEMBLY__ */ + +#define PS_UINT_CAST +#define UINT64_CAST +#define HUBREG_CAST + +#endif /* __ASSEMBLY__ */ + + +#define NASID_GET_META(_n) ((_n) >> NASID_LOCAL_BITS) +#ifdef CONFIG_SGI_IP27 +#define NASID_GET_LOCAL(_n) ((_n) & 0xf) +#endif +#define NASID_MAKE(_m, _l) (((_m) << NASID_LOCAL_BITS) | (_l)) + +#define NODE_ADDRSPACE_MASK (NODE_ADDRSPACE_SIZE - 1) +#define TO_NODE_ADDRSPACE(_pa) (UINT64_CAST (_pa) & NODE_ADDRSPACE_MASK) + +#define CHANGE_ADDR_NASID(_pa, _nasid) \ + ((UINT64_CAST(_pa) & ~NASID_MASK) | \ + (UINT64_CAST(_nasid) << NASID_SHFT)) + + +/* + * The following macros are used to index to the beginning of a specific + * node's address space. + */ + +#define NODE_OFFSET(_n) (UINT64_CAST (_n) << NODE_SIZE_BITS) + +#define NODE_CAC_BASE(_n) (CAC_BASE + NODE_OFFSET(_n)) +#define NODE_HSPEC_BASE(_n) (HSPEC_BASE + NODE_OFFSET(_n)) +#define NODE_IO_BASE(_n) (IO_BASE + NODE_OFFSET(_n)) +#define NODE_MSPEC_BASE(_n) (MSPEC_BASE + NODE_OFFSET(_n)) +#define NODE_UNCAC_BASE(_n) (UNCAC_BASE + NODE_OFFSET(_n)) + +#define TO_NODE(_n, _x) (NODE_OFFSET(_n) | ((_x) )) +#define TO_NODE_CAC(_n, _x) (NODE_CAC_BASE(_n) | ((_x) & TO_PHYS_MASK)) +#define TO_NODE_UNCAC(_n, _x) (NODE_UNCAC_BASE(_n) | ((_x) & TO_PHYS_MASK)) +#define TO_NODE_MSPEC(_n, _x) (NODE_MSPEC_BASE(_n) | ((_x) & TO_PHYS_MASK)) +#define TO_NODE_HSPEC(_n, _x) (NODE_HSPEC_BASE(_n) | ((_x) & TO_PHYS_MASK)) + + +#define RAW_NODE_SWIN_BASE(nasid, widget) \ + (NODE_IO_BASE(nasid) + (UINT64_CAST(widget) << SWIN_SIZE_BITS)) + +#define WIDGETID_GET(addr) ((unsigned char)((addr >> SWIN_SIZE_BITS) & 0xff)) + +/* + * The following definitions pertain to the IO special address + * space. They define the location of the big and little windows + * of any given node. + */ + +#define SWIN_SIZE_BITS 24 +#define SWIN_SIZE (UINT64_CAST 1 << 24) +#define SWIN_SIZEMASK (SWIN_SIZE - 1) +#define SWIN_WIDGET_MASK 0xF + +/* + * Convert smallwindow address to xtalk address. + * + * 'addr' can be physical or virtual address, but will be converted + * to Xtalk address in the range 0 -> SWINZ_SIZEMASK + */ +#define SWIN_WIDGETADDR(addr) ((addr) & SWIN_SIZEMASK) +#define SWIN_WIDGETNUM(addr) (((addr) >> SWIN_SIZE_BITS) & SWIN_WIDGET_MASK) +/* + * Verify if addr belongs to small window address on node with "nasid" + * + * + * NOTE: "addr" is expected to be XKPHYS address, and NOT physical + * address + * + * + */ +#define NODE_SWIN_ADDR(nasid, addr) \ + (((addr) >= NODE_SWIN_BASE(nasid, 0)) && \ + ((addr) < (NODE_SWIN_BASE(nasid, HUB_NUM_WIDGET) + SWIN_SIZE)\ + )) + +/* + * The following define the major position-independent aliases used + * in SN. + * UALIAS -- 256MB in size, reads in the UALIAS result in + * uncached references to the memory of the reader's node. + * CPU_UALIAS -- 128kb in size, the bottom part of UALIAS is flipped + * depending on which CPU does the access to provide + * all CPUs with unique uncached memory at low addresses. + * LBOOT -- 256MB in size, reads in the LBOOT area result in + * uncached references to the local hub's boot prom and + * other directory-bus connected devices. + * IALIAS -- 8MB in size, reads in the IALIAS result in uncached + * references to the local hub's registers. + */ + +#define UALIAS_BASE HSPEC_BASE +#define UALIAS_SIZE 0x10000000 /* 256 Megabytes */ +#define UALIAS_LIMIT (UALIAS_BASE + UALIAS_SIZE) + +/* + * The bottom of ualias space is flipped depending on whether you're + * processor 0 or 1 within a node. + */ +#ifdef CONFIG_SGI_IP27 +#define UALIAS_FLIP_BASE UALIAS_BASE +#define UALIAS_FLIP_SIZE 0x20000 +#define UALIAS_FLIP_BIT 0x10000 +#define UALIAS_FLIP_ADDR(_x) (cputoslice(smp_processor_id()) ? \ + (_x) ^ UALIAS_FLIP_BIT : (_x)) + +#define LBOOT_BASE (HSPEC_BASE + 0x10000000) +#define LBOOT_SIZE 0x10000000 +#define LBOOT_LIMIT (LBOOT_BASE + LBOOT_SIZE) +#define LBOOT_STRIDE 0 /* IP27 has only one CPU PROM */ + +#endif + +#define HUB_REGISTER_WIDGET 1 +#define IALIAS_BASE NODE_SWIN_BASE(0, HUB_REGISTER_WIDGET) +#define IALIAS_SIZE 0x800000 /* 8 Megabytes */ +#define IS_IALIAS(_a) (((_a) >= IALIAS_BASE) && \ + ((_a) < (IALIAS_BASE + IALIAS_SIZE))) + +/* + * Macro for referring to Hub's RBOOT space + */ + +#ifdef CONFIG_SGI_IP27 +#define RBOOT_SIZE 0x10000000 /* 256 Megabytes */ +#define NODE_RBOOT_BASE(_n) (NODE_HSPEC_BASE(_n) + 0x30000000) +#define NODE_RBOOT_LIMIT(_n) (NODE_RBOOT_BASE(_n) + RBOOT_SIZE) + +#endif + +/* + * Macros for referring the Hub's back door space + * + * These macros correctly process addresses in any node's space. + * WARNING: They won't work in assembler. + * + * BDDIR_ENTRY_LO returns the address of the low double-word of the dir + * entry corresponding to a physical (Cac or Uncac) address. + * BDDIR_ENTRY_HI returns the address of the high double-word of the entry. + * BDPRT_ENTRY returns the address of the double-word protection entry + * corresponding to the page containing the physical address. + * BDPRT_ENTRY_S Stores the value into the protection entry. + * BDPRT_ENTRY_L Load the value from the protection entry. + * BDECC_ENTRY returns the address of the ECC byte corresponding to a + * double-word at a specified physical address. + * BDECC_ENTRY_H returns the address of the two ECC bytes corresponding to a + * quad-word at a specified physical address. + */ +#define NODE_BDOOR_BASE(_n) (NODE_HSPEC_BASE(_n) + (NODE_ADDRSPACE_SIZE/2)) + +#define NODE_BDECC_BASE(_n) (NODE_BDOOR_BASE(_n)) +#define NODE_BDDIR_BASE(_n) (NODE_BDOOR_BASE(_n) + (NODE_ADDRSPACE_SIZE/4)) +#ifdef CONFIG_SGI_IP27 +#define BDDIR_ENTRY_LO(_pa) ((HSPEC_BASE + \ + NODE_ADDRSPACE_SIZE * 3 / 4 + \ + 0x200) | \ + UINT64_CAST(_pa) & NASID_MASK | \ + UINT64_CAST(_pa) >> 2 & BDDIR_UPPER_MASK | \ + UINT64_CAST(_pa) >> 3 & 0x1f << 4) + +#define BDDIR_ENTRY_HI(_pa) ((HSPEC_BASE + \ + NODE_ADDRSPACE_SIZE * 3 / 4 + \ + 0x208) | \ + UINT64_CAST(_pa) & NASID_MASK | \ + UINT64_CAST(_pa) >> 2 & BDDIR_UPPER_MASK | \ + UINT64_CAST(_pa) >> 3 & 0x1f << 4) + +#define BDPRT_ENTRY(_pa, _rgn) ((HSPEC_BASE + \ + NODE_ADDRSPACE_SIZE * 3 / 4) | \ + UINT64_CAST(_pa) & NASID_MASK | \ + UINT64_CAST(_pa) >> 2 & BDDIR_UPPER_MASK | \ + (_rgn) << 3) +#define BDPRT_ENTRY_ADDR(_pa, _rgn) (BDPRT_ENTRY((_pa), (_rgn))) +#define BDPRT_ENTRY_S(_pa, _rgn, _val) (*(__psunsigned_t *)BDPRT_ENTRY((_pa), (_rgn))=(_val)) +#define BDPRT_ENTRY_L(_pa, _rgn) (*(__psunsigned_t *)BDPRT_ENTRY((_pa), (_rgn))) + +#define BDECC_ENTRY(_pa) ((HSPEC_BASE + \ + NODE_ADDRSPACE_SIZE / 2) | \ + UINT64_CAST(_pa) & NASID_MASK | \ + UINT64_CAST(_pa) >> 2 & BDECC_UPPER_MASK | \ + UINT64_CAST(_pa) >> 3 & 3) + +/* + * Macro to convert a back door directory or protection address into the + * raw physical address of the associated cache line or protection page. + */ +#define BDADDR_IS_DIR(_ba) ((UINT64_CAST (_ba) & 0x200) != 0) +#define BDADDR_IS_PRT(_ba) ((UINT64_CAST (_ba) & 0x200) == 0) + +#define BDDIR_TO_MEM(_ba) (UINT64_CAST (_ba) & NASID_MASK | \ + (UINT64_CAST(_ba) & BDDIR_UPPER_MASK)<<2 | \ + (UINT64_CAST(_ba) & 0x1f << 4) << 3) + +#define BDPRT_TO_MEM(_ba) (UINT64_CAST (_ba) & NASID_MASK | \ + (UINT64_CAST(_ba) & BDDIR_UPPER_MASK)<<2) + +#define BDECC_TO_MEM(_ba) (UINT64_CAST (_ba) & NASID_MASK | \ + (UINT64_CAST(_ba) & BDECC_UPPER_MASK)<<2 | \ + (UINT64_CAST(_ba) & 3) << 3) +#endif /* CONFIG_SGI_IP27 */ + + +/* + * The following macros produce the correct base virtual address for + * the hub registers. The LOCAL_HUB_* macros produce the appropriate + * address for the local registers. The REMOTE_HUB_* macro produce + * the address for the specified hub's registers. The intent is + * that the appropriate PI, MD, NI, or II register would be substituted + * for _x. + */ + +/* + * WARNING: + * When certain Hub chip workaround are defined, it's not sufficient + * to dereference the *_HUB_ADDR() macros. You should instead use + * HUB_L() and HUB_S() if you must deal with pointers to hub registers. + * Otherwise, the recommended approach is to use *_HUB_L() and *_HUB_S(). + * They're always safe. + */ +#define LOCAL_HUB_ADDR(_x) (HUBREG_CAST (IALIAS_BASE + (_x))) +#define REMOTE_HUB_ADDR(_n, _x) (HUBREG_CAST (NODE_SWIN_BASE(_n, 1) + \ + 0x800000 + (_x))) +#ifdef CONFIG_SGI_IP27 +#define REMOTE_HUB_PI_ADDR(_n, _sn, _x) (HUBREG_CAST (NODE_SWIN_BASE(_n, 1) + \ + 0x800000 + (_x))) +#endif /* CONFIG_SGI_IP27 */ + +#ifndef __ASSEMBLY__ + +#define HUB_L(_a) *(_a) +#define HUB_S(_a, _d) *(_a) = (_d) + +#define LOCAL_HUB_L(_r) HUB_L(LOCAL_HUB_ADDR(_r)) +#define LOCAL_HUB_S(_r, _d) HUB_S(LOCAL_HUB_ADDR(_r), (_d)) +#define REMOTE_HUB_L(_n, _r) HUB_L(REMOTE_HUB_ADDR((_n), (_r))) +#define REMOTE_HUB_S(_n, _r, _d) HUB_S(REMOTE_HUB_ADDR((_n), (_r)), (_d)) +#define REMOTE_HUB_PI_L(_n, _sn, _r) HUB_L(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r))) +#define REMOTE_HUB_PI_S(_n, _sn, _r, _d) HUB_S(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r)), (_d)) + +#endif /* !__ASSEMBLY__ */ + +/* + * The following macros are used to get to a hub/bridge register, given + * the base of the register space. + */ +#define HUB_REG_PTR(_base, _off) \ + (HUBREG_CAST((__psunsigned_t)(_base) + (__psunsigned_t)(_off))) + +#define HUB_REG_PTR_L(_base, _off) \ + HUB_L(HUB_REG_PTR((_base), (_off))) + +#define HUB_REG_PTR_S(_base, _off, _data) \ + HUB_S(HUB_REG_PTR((_base), (_off)), (_data)) + +/* + * Software structure locations -- permanently fixed + * See diagram in kldir.h + */ + +#define PHYS_RAMBASE 0x0 +#define K0_RAMBASE PHYS_TO_K0(PHYS_RAMBASE) + +#define EX_HANDLER_OFFSET(slice) ((slice) << 16) +#define EX_HANDLER_ADDR(nasid, slice) \ + PHYS_TO_K0(NODE_OFFSET(nasid) | EX_HANDLER_OFFSET(slice)) +#define EX_HANDLER_SIZE 0x0400 + +#define EX_FRAME_OFFSET(slice) ((slice) << 16 | 0x400) +#define EX_FRAME_ADDR(nasid, slice) \ + PHYS_TO_K0(NODE_OFFSET(nasid) | EX_FRAME_OFFSET(slice)) +#define EX_FRAME_SIZE 0x0c00 + +#define ARCS_SPB_OFFSET 0x1000 +#define ARCS_SPB_ADDR(nasid) \ + PHYS_TO_K0(NODE_OFFSET(nasid) | ARCS_SPB_OFFSET) +#define ARCS_SPB_SIZE 0x0400 + +#define KLDIR_OFFSET 0x2000 +#define KLDIR_ADDR(nasid) \ + TO_NODE_UNCAC((nasid), KLDIR_OFFSET) +#define KLDIR_SIZE 0x0400 + + +/* + * Software structure locations -- indirected through KLDIR + * See diagram in kldir.h + * + * Important: All low memory structures must only be accessed + * uncached, except for the symmon stacks. + */ + +#define KLI_LAUNCH 0 /* Dir. entries */ +#define KLI_KLCONFIG 1 +#define KLI_NMI 2 +#define KLI_GDA 3 +#define KLI_FREEMEM 4 +#define KLI_SYMMON_STK 5 +#define KLI_PI_ERROR 6 +#define KLI_KERN_VARS 7 +#define KLI_KERN_XP 8 +#define KLI_KERN_PARTID 9 + +#ifndef __ASSEMBLY__ + +#define KLD_BASE(nasid) ((kldir_ent_t *) KLDIR_ADDR(nasid)) +#define KLD_LAUNCH(nasid) (KLD_BASE(nasid) + KLI_LAUNCH) +#define KLD_NMI(nasid) (KLD_BASE(nasid) + KLI_NMI) +#define KLD_KLCONFIG(nasid) (KLD_BASE(nasid) + KLI_KLCONFIG) +#define KLD_PI_ERROR(nasid) (KLD_BASE(nasid) + KLI_PI_ERROR) +#define KLD_GDA(nasid) (KLD_BASE(nasid) + KLI_GDA) +#define KLD_SYMMON_STK(nasid) (KLD_BASE(nasid) + KLI_SYMMON_STK) +#define KLD_FREEMEM(nasid) (KLD_BASE(nasid) + KLI_FREEMEM) +#define KLD_KERN_VARS(nasid) (KLD_BASE(nasid) + KLI_KERN_VARS) +#define KLD_KERN_XP(nasid) (KLD_BASE(nasid) + KLI_KERN_XP) +#define KLD_KERN_PARTID(nasid) (KLD_BASE(nasid) + KLI_KERN_PARTID) + +#define LAUNCH_OFFSET(nasid, slice) \ + (KLD_LAUNCH(nasid)->offset + \ + KLD_LAUNCH(nasid)->stride * (slice)) +#define LAUNCH_ADDR(nasid, slice) \ + TO_NODE_UNCAC((nasid), LAUNCH_OFFSET(nasid, slice)) +#define LAUNCH_SIZE(nasid) KLD_LAUNCH(nasid)->size + +#define NMI_OFFSET(nasid, slice) \ + (KLD_NMI(nasid)->offset + \ + KLD_NMI(nasid)->stride * (slice)) +#define NMI_ADDR(nasid, slice) \ + TO_NODE_UNCAC((nasid), NMI_OFFSET(nasid, slice)) +#define NMI_SIZE(nasid) KLD_NMI(nasid)->size + +#define KLCONFIG_OFFSET(nasid) KLD_KLCONFIG(nasid)->offset +#define KLCONFIG_ADDR(nasid) \ + TO_NODE_UNCAC((nasid), KLCONFIG_OFFSET(nasid)) +#define KLCONFIG_SIZE(nasid) KLD_KLCONFIG(nasid)->size + +#define GDA_ADDR(nasid) KLD_GDA(nasid)->pointer +#define GDA_SIZE(nasid) KLD_GDA(nasid)->size + +#define SYMMON_STK_OFFSET(nasid, slice) \ + (KLD_SYMMON_STK(nasid)->offset + \ + KLD_SYMMON_STK(nasid)->stride * (slice)) +#define SYMMON_STK_STRIDE(nasid) KLD_SYMMON_STK(nasid)->stride + +#define SYMMON_STK_ADDR(nasid, slice) \ + TO_NODE_CAC((nasid), SYMMON_STK_OFFSET(nasid, slice)) + +#define SYMMON_STK_SIZE(nasid) KLD_SYMMON_STK(nasid)->stride + +#define SYMMON_STK_END(nasid) (SYMMON_STK_ADDR(nasid, 0) + KLD_SYMMON_STK(nasid)->size) + +/* loading symmon 4k below UNIX. the arcs loader needs the topaddr for a + * relocatable program + */ +#define UNIX_DEBUG_LOADADDR 0x300000 +#define SYMMON_LOADADDR(nasid) \ + TO_NODE(nasid, PHYS_TO_K0(UNIX_DEBUG_LOADADDR - 0x1000)) + +#define FREEMEM_OFFSET(nasid) KLD_FREEMEM(nasid)->offset +#define FREEMEM_ADDR(nasid) SYMMON_STK_END(nasid) +/* + * XXX + * Fix this. FREEMEM_ADDR should be aware of if symmon is loaded. + * Also, it should take into account what prom thinks to be a safe + * address + PHYS_TO_K0(NODE_OFFSET(nasid) + FREEMEM_OFFSET(nasid)) + */ +#define FREEMEM_SIZE(nasid) KLD_FREEMEM(nasid)->size + +#define PI_ERROR_OFFSET(nasid) KLD_PI_ERROR(nasid)->offset +#define PI_ERROR_ADDR(nasid) \ + TO_NODE_UNCAC((nasid), PI_ERROR_OFFSET(nasid)) +#define PI_ERROR_SIZE(nasid) KLD_PI_ERROR(nasid)->size + +#define NODE_OFFSET_TO_K0(_nasid, _off) \ + PHYS_TO_K0((NODE_OFFSET(_nasid) + (_off)) | CAC_BASE) +#define NODE_OFFSET_TO_K1(_nasid, _off) \ + TO_UNCAC((NODE_OFFSET(_nasid) + (_off)) | UNCAC_BASE) +#define K0_TO_NODE_OFFSET(_k0addr) \ + ((__psunsigned_t)(_k0addr) & NODE_ADDRSPACE_MASK) + +#define KERN_VARS_ADDR(nasid) KLD_KERN_VARS(nasid)->pointer +#define KERN_VARS_SIZE(nasid) KLD_KERN_VARS(nasid)->size + +#define KERN_XP_ADDR(nasid) KLD_KERN_XP(nasid)->pointer +#define KERN_XP_SIZE(nasid) KLD_KERN_XP(nasid)->size + +#define GPDA_ADDR(nasid) TO_NODE_CAC(nasid, GPDA_OFFSET) + +#endif /* !__ASSEMBLY__ */ + + +#endif /* _ASM_SN_ADDRS_H */ diff --git a/arch/mips/include/asm/sn/agent.h b/arch/mips/include/asm/sn/agent.h new file mode 100644 index 00000000000..ac4ea85c3a5 --- /dev/null +++ b/arch/mips/include/asm/sn/agent.h @@ -0,0 +1,46 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * This file has definitions for the hub and snac interfaces. + * + * Copyright (C) 1992 - 1997, 1999, 2000 Silcon Graphics, Inc. + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + */ +#ifndef _ASM_SGI_SN_AGENT_H +#define _ASM_SGI_SN_AGENT_H + +#include +#include +#include + +#if defined(CONFIG_SGI_IP27) +#include +#elif defined(CONFIG_SGI_IP35) +#include +#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */ + +/* + * NIC register macros + */ + +#if defined(CONFIG_SGI_IP27) +#define HUB_NIC_ADDR(_cpuid) \ + REMOTE_HUB_ADDR(COMPACT_TO_NASID_NODEID(cpu_to_node(_cpuid)), \ + MD_MLAN_CTL) +#endif + +#define SET_HUB_NIC(_my_cpuid, _val) \ + (HUB_S(HUB_NIC_ADDR(_my_cpuid), (_val))) + +#define SET_MY_HUB_NIC(_v) \ + SET_HUB_NIC(cpuid(), (_v)) + +#define GET_HUB_NIC(_my_cpuid) \ + (HUB_L(HUB_NIC_ADDR(_my_cpuid))) + +#define GET_MY_HUB_NIC() \ + GET_HUB_NIC(cpuid()) + +#endif /* _ASM_SGI_SN_AGENT_H */ diff --git a/arch/mips/include/asm/sn/arch.h b/arch/mips/include/asm/sn/arch.h new file mode 100644 index 00000000000..bd75945e10f --- /dev/null +++ b/arch/mips/include/asm/sn/arch.h @@ -0,0 +1,64 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SGI specific setup. + * + * Copyright (C) 1995 - 1997, 1999 Silcon Graphics, Inc. + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + */ +#ifndef _ASM_SN_ARCH_H +#define _ASM_SN_ARCH_H + +#include +#include +#ifdef CONFIG_SGI_IP27 +#include +#endif + +typedef u64 hubreg_t; + +#define cputonasid(cpu) (sn_cpu_info[(cpu)].p_nasid) +#define cputoslice(cpu) (sn_cpu_info[(cpu)].p_slice) +#define makespnum(_nasid, _slice) \ + (((_nasid) << CPUS_PER_NODE_SHFT) | (_slice)) + +#define INVALID_NASID (nasid_t)-1 +#define INVALID_CNODEID (cnodeid_t)-1 +#define INVALID_PNODEID (pnodeid_t)-1 +#define INVALID_MODULE (moduleid_t)-1 +#define INVALID_PARTID (partid_t)-1 + +extern nasid_t get_nasid(void); +extern cnodeid_t get_cpu_cnode(cpuid_t); +extern int get_cpu_slice(cpuid_t); + +/* + * NO ONE should access these arrays directly. The only reason we refer to + * them here is to avoid the procedure call that would be required in the + * macros below. (Really want private data members here :-) + */ +extern cnodeid_t nasid_to_compact_node[MAX_NASIDS]; +extern nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; + +/* + * These macros are used by various parts of the kernel to convert + * between the three different kinds of node numbering. At least some + * of them may change to procedure calls in the future, but the macros + * will continue to work. Don't use the arrays above directly. + */ + +#define NASID_TO_REGION(nnode) \ + ((nnode) >> \ + (is_fine_dirmode() ? NASID_TO_FINEREG_SHFT : NASID_TO_COARSEREG_SHFT)) + +extern cnodeid_t nasid_to_compact_node[MAX_NASIDS]; +extern nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; +extern cnodeid_t cpuid_to_compact_node[MAXCPUS]; + +#define NASID_TO_COMPACT_NODEID(nnode) (nasid_to_compact_node[nnode]) +#define COMPACT_TO_NASID_NODEID(cnode) (compact_to_nasid_node[cnode]) +#define CPUID_TO_COMPACT_NODEID(cpu) (cpuid_to_compact_node[(cpu)]) + +#endif /* _ASM_SN_ARCH_H */ diff --git a/arch/mips/include/asm/sn/fru.h b/arch/mips/include/asm/sn/fru.h new file mode 100644 index 00000000000..b3e3606723b --- /dev/null +++ b/arch/mips/include/asm/sn/fru.h @@ -0,0 +1,44 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX + * + * Copyright (C) 1992 - 1997, 1999 Silcon Graphics, Inc. + * Copyright (C) 1999, 2006 Ralf Baechle (ralf@linux-mips) + */ +#ifndef __ASM_SN_FRU_H +#define __ASM_SN_FRU_H + +#define MAX_DIMMS 8 /* max # of dimm banks */ +#define MAX_PCIDEV 8 /* max # of pci devices on a pci bus */ + +typedef unsigned char confidence_t; + +typedef struct kf_mem_s { + confidence_t km_confidence; /* confidence level that the memory is bad + * is this necessary ? + */ + confidence_t km_dimm[MAX_DIMMS]; + /* confidence level that dimm[i] is bad + *I think this is the right number + */ + +} kf_mem_t; + +typedef struct kf_cpu_s { + confidence_t kc_confidence; /* confidence level that cpu is bad */ + confidence_t kc_icache; /* confidence level that instr. cache is bad */ + confidence_t kc_dcache; /* confidence level that data cache is bad */ + confidence_t kc_scache; /* confidence level that sec. cache is bad */ + confidence_t kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */ +} kf_cpu_t; + +typedef struct kf_pci_bus_s { + confidence_t kpb_belief; /* confidence level that the pci bus is bad */ + confidence_t kpb_pcidev_belief[MAX_PCIDEV]; + /* confidence level that the pci dev is bad */ +} kf_pci_bus_t; + +#endif /* __ASM_SN_FRU_H */ diff --git a/arch/mips/include/asm/sn/gda.h b/arch/mips/include/asm/sn/gda.h new file mode 100644 index 00000000000..9cb6ff77091 --- /dev/null +++ b/arch/mips/include/asm/sn/gda.h @@ -0,0 +1,107 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX . + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * + * gda.h -- Contains the data structure for the global data area, + * The GDA contains information communicated between the + * PROM, SYMMON, and the kernel. + */ +#ifndef _ASM_SN_GDA_H +#define _ASM_SN_GDA_H + +#include + +#define GDA_MAGIC 0x58464552 + +/* + * GDA Version History + * + * Version # | Change + * -------------+------------------------------------------------------- + * 1 | Initial SN0 version + * 2 | Prom sets g_partid field to the partition number. 0 IS + * | a valid partition #. + */ + +#define GDA_VERSION 2 /* Current GDA version # */ + +#define G_MAGICOFF 0 +#define G_VERSIONOFF 4 +#define G_PROMOPOFF 6 +#define G_MASTEROFF 8 +#define G_VDSOFF 12 +#define G_HKDNORMOFF 16 +#define G_HKDUTLBOFF 24 +#define G_HKDXUTLBOFF 32 +#define G_PARTIDOFF 40 +#define G_TABLEOFF 128 + +#ifndef __ASSEMBLY__ + +typedef struct gda { + u32 g_magic; /* GDA magic number */ + u16 g_version; /* Version of this structure */ + u16 g_masterid; /* The NASID:CPUNUM of the master cpu */ + u32 g_promop; /* Passes requests from the kernel to prom */ + u32 g_vds; /* Store the virtual dipswitches here */ + void **g_hooked_norm;/* ptr to pda loc for norm hndlr */ + void **g_hooked_utlb;/* ptr to pda loc for utlb hndlr */ + void **g_hooked_xtlb;/* ptr to pda loc for xtlb hndlr */ + int g_partid; /* partition id */ + int g_symmax; /* Max symbols in name table. */ + void *g_dbstab; /* Address of idbg symbol table */ + char *g_nametab; /* Address of idbg name table */ + void *g_ktext_repmask; + /* Pointer to a mask of nodes with copies + * of the kernel. */ + char g_padding[56]; /* pad out to 128 bytes */ + nasid_t g_nasidtable[MAX_COMPACT_NODES]; /* NASID of each node, + * indexed by cnodeid. + */ +} gda_t; + +#define GDA ((gda_t*) GDA_ADDR(get_nasid())) + +#endif /* !__ASSEMBLY__ */ +/* + * Define: PART_GDA_VERSION + * Purpose: Define the minimum version of the GDA required, lower + * revisions assume GDA is NOT set up, and read partition + * information from the board info. + */ +#define PART_GDA_VERSION 2 + +/* + * The following requests can be sent to the PROM during startup. + */ + +#define PROMOP_MAGIC 0x0ead0000 +#define PROMOP_MAGIC_MASK 0x0fff0000 + +#define PROMOP_BIST_SHIFT 11 +#define PROMOP_BIST_MASK (0x3 << 11) + +#define PROMOP_REG PI_ERR_STACK_ADDR_A + +#define PROMOP_INVALID (PROMOP_MAGIC | 0x00) +#define PROMOP_HALT (PROMOP_MAGIC | 0x10) +#define PROMOP_POWERDOWN (PROMOP_MAGIC | 0x20) +#define PROMOP_RESTART (PROMOP_MAGIC | 0x30) +#define PROMOP_REBOOT (PROMOP_MAGIC | 0x40) +#define PROMOP_IMODE (PROMOP_MAGIC | 0x50) + +#define PROMOP_CMD_MASK 0x00f0 +#define PROMOP_OPTIONS_MASK 0xfff0 + +#define PROMOP_SKIP_DIAGS 0x0100 /* don't bother running diags */ +#define PROMOP_SKIP_MEMINIT 0x0200 /* don't bother initing memory */ +#define PROMOP_SKIP_DEVINIT 0x0400 /* don't bother initing devices */ +#define PROMOP_BIST1 0x0800 /* keep track of which BIST ran */ +#define PROMOP_BIST2 0x1000 /* keep track of which BIST ran */ + +#endif /* _ASM_SN_GDA_H */ diff --git a/arch/mips/include/asm/sn/hub.h b/arch/mips/include/asm/sn/hub.h new file mode 100644 index 00000000000..1992d9254a0 --- /dev/null +++ b/arch/mips/include/asm/sn/hub.h @@ -0,0 +1,16 @@ +#ifndef __ASM_SN_HUB_H +#define __ASM_SN_HUB_H + +#include +#include +#include +#include +#include +#include + +/* ip27-hubio.c */ +extern unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, + unsigned long xtalk_addr, size_t size); +extern void hub_pio_init(cnodeid_t cnode); + +#endif /* __ASM_SN_HUB_H */ diff --git a/arch/mips/include/asm/sn/intr.h b/arch/mips/include/asm/sn/intr.h new file mode 100644 index 00000000000..6718b644b97 --- /dev/null +++ b/arch/mips/include/asm/sn/intr.h @@ -0,0 +1,129 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997 Silicon Graphics, Inc. + */ +#ifndef __ASM_SN_INTR_H +#define __ASM_SN_INTR_H + +/* Number of interrupt levels associated with each interrupt register. */ +#define N_INTPEND_BITS 64 + +#define INT_PEND0_BASELVL 0 +#define INT_PEND1_BASELVL 64 + +#define N_INTPENDJUNK_BITS 8 +#define INTPENDJUNK_CLRBIT 0x80 + +/* + * Macros to manipulate the interrupt register on the calling hub chip. + */ + +#define LOCAL_HUB_SEND_INTR(level) \ + LOCAL_HUB_S(PI_INT_PEND_MOD, (0x100 | (level))) +#define REMOTE_HUB_SEND_INTR(hub, level) \ + REMOTE_HUB_S((hub), PI_INT_PEND_MOD, (0x100 | (level))) + +/* + * When clearing the interrupt, make sure this clear does make it + * to the hub. Otherwise we could end up losing interrupts. + * We do an uncached load of the int_pend0 register to ensure this. + */ + +#define LOCAL_HUB_CLR_INTR(level) \ +do { \ + LOCAL_HUB_S(PI_INT_PEND_MOD, (level)); \ + LOCAL_HUB_L(PI_INT_PEND0); \ +} while (0); + +#define REMOTE_HUB_CLR_INTR(hub, level) \ +do { \ + nasid_t __hub = (hub); \ + \ + REMOTE_HUB_S(__hub, PI_INT_PEND_MOD, (level)); \ + REMOTE_HUB_L(__hub, PI_INT_PEND0); \ +} while (0); + +/* + * Hard-coded interrupt levels: + */ + +/* + * L0 = SW1 + * L1 = SW2 + * L2 = INT_PEND0 + * L3 = INT_PEND1 + * L4 = RTC + * L5 = Profiling Timer + * L6 = Hub Errors + * L7 = Count/Compare (T5 counters) + */ + + +/* + * INT_PEND0 hard-coded bits. + */ + +/* + * INT_PEND0 bits determined by hardware: + */ +#define RESERVED_INTR 0 /* What is this bit? */ +#define GFX_INTR_A 1 +#define GFX_INTR_B 2 +#define PG_MIG_INTR 3 +#define UART_INTR 4 +#define CC_PEND_A 5 +#define CC_PEND_B 6 + +/* + * INT_PEND0 used by the kernel for itself ... + */ +#define CPU_RESCHED_A_IRQ 7 +#define CPU_RESCHED_B_IRQ 8 +#define CPU_CALL_A_IRQ 9 +#define CPU_CALL_B_IRQ 10 +#define MSC_MESG_INTR 11 +#define BASE_PCI_IRQ 12 + +/* + * INT_PEND0 again, bits determined by hardware / hardcoded: + */ +#define SDISK_INTR 63 /* SABLE name */ +#define IP_PEND0_6_63 63 /* What is this bit? */ + +/* + * INT_PEND1 hard-coded bits: + */ +#define NI_BRDCAST_ERR_A 39 +#define NI_BRDCAST_ERR_B 40 + +#define LLP_PFAIL_INTR_A 41 /* see ml/SN/SN0/sysctlr.c */ +#define LLP_PFAIL_INTR_B 42 + +#define TLB_INTR_A 43 /* used for tlb flush random */ +#define TLB_INTR_B 44 + +#define IP27_INTR_0 45 /* Reserved for PROM use */ +#define IP27_INTR_1 46 /* do not use in Kernel */ +#define IP27_INTR_2 47 +#define IP27_INTR_3 48 +#define IP27_INTR_4 49 +#define IP27_INTR_5 50 +#define IP27_INTR_6 51 +#define IP27_INTR_7 52 + +#define BRIDGE_ERROR_INTR 53 /* Setup by PROM to catch */ + /* Bridge Errors */ +#define DEBUG_INTR_A 54 +#define DEBUG_INTR_B 55 /* Used by symmon to stop all cpus */ +#define IO_ERROR_INTR 57 /* Setup by PROM */ +#define CLK_ERR_INTR 58 +#define COR_ERR_INTR_A 59 +#define COR_ERR_INTR_B 60 +#define MD_COR_ERR_INTR 61 +#define NI_ERROR_INTR 62 +#define MSC_PANIC_INTR 63 + +#endif /* __ASM_SN_INTR_H */ diff --git a/arch/mips/include/asm/sn/io.h b/arch/mips/include/asm/sn/io.h new file mode 100644 index 00000000000..24c6775fbb0 --- /dev/null +++ b/arch/mips/include/asm/sn/io.h @@ -0,0 +1,59 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000, 2003 Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_SN_IO_H +#define _ASM_SN_IO_H + +#if defined(CONFIG_SGI_IP27) +#include +#endif + + +#define IIO_ITTE_BASE 0x400160 /* base of translation table entries */ +#define IIO_ITTE(bigwin) (IIO_ITTE_BASE + 8*(bigwin)) + +#define IIO_ITTE_OFFSET_BITS 5 /* size of offset field */ +#define IIO_ITTE_OFFSET_MASK ((1<> BWIN_SIZE_BITS) & \ + IIO_ITTE_OFFSET_MASK) << IIO_ITTE_OFFSET_SHIFT) | \ + (io_or_mem << IIO_ITTE_IOSP_SHIFT) | \ + (((widget) & IIO_ITTE_WIDGET_MASK) << IIO_ITTE_WIDGET_SHIFT))) + +#define IIO_ITTE_DISABLE(nasid, bigwin) \ + IIO_ITTE_PUT((nasid), HUB_PIO_MAP_TO_MEM, \ + (bigwin), IIO_ITTE_INVALID_WIDGET, 0) + +#define IIO_ITTE_GET(nasid, bigwin) REMOTE_HUB_ADDR((nasid), IIO_ITTE(bigwin)) + +/* + * Macro which takes the widget number, and returns the + * IO PRB address of that widget. + * value _x is expected to be a widget number in the range + * 0, 8 - 0xF + */ +#define IIO_IOPRB(_x) (IIO_IOPRB_0 + ( ( (_x) < HUB_WIDGET_ID_MIN ? \ + (_x) : \ + (_x) - (HUB_WIDGET_ID_MIN-1)) << 3) ) + +#endif /* _ASM_SN_IO_H */ diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h new file mode 100644 index 00000000000..099677774d7 --- /dev/null +++ b/arch/mips/include/asm/sn/ioc3.h @@ -0,0 +1,663 @@ +/* + * Copyright (C) 1999, 2000 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _IOC3_H +#define _IOC3_H + +#include + +/* SUPERIO uart register map */ +typedef volatile struct ioc3_uartregs { + union { + volatile u8 rbr; /* read only, DLAB == 0 */ + volatile u8 thr; /* write only, DLAB == 0 */ + volatile u8 dll; /* DLAB == 1 */ + } u1; + union { + volatile u8 ier; /* DLAB == 0 */ + volatile u8 dlm; /* DLAB == 1 */ + } u2; + union { + volatile u8 iir; /* read only */ + volatile u8 fcr; /* write only */ + } u3; + volatile u8 iu_lcr; + volatile u8 iu_mcr; + volatile u8 iu_lsr; + volatile u8 iu_msr; + volatile u8 iu_scr; +} ioc3_uregs_t; + +#define iu_rbr u1.rbr +#define iu_thr u1.thr +#define iu_dll u1.dll +#define iu_ier u2.ier +#define iu_dlm u2.dlm +#define iu_iir u3.iir +#define iu_fcr u3.fcr + +struct ioc3_sioregs { + volatile u8 fill[0x141]; /* starts at 0x141 */ + + volatile u8 uartc; + volatile u8 kbdcg; + + volatile u8 fill0[0x150 - 0x142 - 1]; + + volatile u8 pp_data; + volatile u8 pp_dsr; + volatile u8 pp_dcr; + + volatile u8 fill1[0x158 - 0x152 - 1]; + + volatile u8 pp_fifa; + volatile u8 pp_cfgb; + volatile u8 pp_ecr; + + volatile u8 fill2[0x168 - 0x15a - 1]; + + volatile u8 rtcad; + volatile u8 rtcdat; + + volatile u8 fill3[0x170 - 0x169 - 1]; + + struct ioc3_uartregs uartb; /* 0x20170 */ + struct ioc3_uartregs uarta; /* 0x20178 */ +}; + +/* Register layout of IOC3 in configuration space. */ +struct ioc3 { + volatile u32 pad0[7]; /* 0x00000 */ + volatile u32 sio_ir; /* 0x0001c */ + volatile u32 sio_ies; /* 0x00020 */ + volatile u32 sio_iec; /* 0x00024 */ + volatile u32 sio_cr; /* 0x00028 */ + volatile u32 int_out; /* 0x0002c */ + volatile u32 mcr; /* 0x00030 */ + + /* General Purpose I/O registers */ + volatile u32 gpcr_s; /* 0x00034 */ + volatile u32 gpcr_c; /* 0x00038 */ + volatile u32 gpdr; /* 0x0003c */ + volatile u32 gppr_0; /* 0x00040 */ + volatile u32 gppr_1; /* 0x00044 */ + volatile u32 gppr_2; /* 0x00048 */ + volatile u32 gppr_3; /* 0x0004c */ + volatile u32 gppr_4; /* 0x00050 */ + volatile u32 gppr_5; /* 0x00054 */ + volatile u32 gppr_6; /* 0x00058 */ + volatile u32 gppr_7; /* 0x0005c */ + volatile u32 gppr_8; /* 0x00060 */ + volatile u32 gppr_9; /* 0x00064 */ + volatile u32 gppr_10; /* 0x00068 */ + volatile u32 gppr_11; /* 0x0006c */ + volatile u32 gppr_12; /* 0x00070 */ + volatile u32 gppr_13; /* 0x00074 */ + volatile u32 gppr_14; /* 0x00078 */ + volatile u32 gppr_15; /* 0x0007c */ + + /* Parallel Port Registers */ + volatile u32 ppbr_h_a; /* 0x00080 */ + volatile u32 ppbr_l_a; /* 0x00084 */ + volatile u32 ppcr_a; /* 0x00088 */ + volatile u32 ppcr; /* 0x0008c */ + volatile u32 ppbr_h_b; /* 0x00090 */ + volatile u32 ppbr_l_b; /* 0x00094 */ + volatile u32 ppcr_b; /* 0x00098 */ + + /* Keyboard and Mouse Registers */ + volatile u32 km_csr; /* 0x0009c */ + volatile u32 k_rd; /* 0x000a0 */ + volatile u32 m_rd; /* 0x000a4 */ + volatile u32 k_wd; /* 0x000a8 */ + volatile u32 m_wd; /* 0x000ac */ + + /* Serial Port Registers */ + volatile u32 sbbr_h; /* 0x000b0 */ + volatile u32 sbbr_l; /* 0x000b4 */ + volatile u32 sscr_a; /* 0x000b8 */ + volatile u32 stpir_a; /* 0x000bc */ + volatile u32 stcir_a; /* 0x000c0 */ + volatile u32 srpir_a; /* 0x000c4 */ + volatile u32 srcir_a; /* 0x000c8 */ + volatile u32 srtr_a; /* 0x000cc */ + volatile u32 shadow_a; /* 0x000d0 */ + volatile u32 sscr_b; /* 0x000d4 */ + volatile u32 stpir_b; /* 0x000d8 */ + volatile u32 stcir_b; /* 0x000dc */ + volatile u32 srpir_b; /* 0x000e0 */ + volatile u32 srcir_b; /* 0x000e4 */ + volatile u32 srtr_b; /* 0x000e8 */ + volatile u32 shadow_b; /* 0x000ec */ + + /* Ethernet Registers */ + volatile u32 emcr; /* 0x000f0 */ + volatile u32 eisr; /* 0x000f4 */ + volatile u32 eier; /* 0x000f8 */ + volatile u32 ercsr; /* 0x000fc */ + volatile u32 erbr_h; /* 0x00100 */ + volatile u32 erbr_l; /* 0x00104 */ + volatile u32 erbar; /* 0x00108 */ + volatile u32 ercir; /* 0x0010c */ + volatile u32 erpir; /* 0x00110 */ + volatile u32 ertr; /* 0x00114 */ + volatile u32 etcsr; /* 0x00118 */ + volatile u32 ersr; /* 0x0011c */ + volatile u32 etcdc; /* 0x00120 */ + volatile u32 ebir; /* 0x00124 */ + volatile u32 etbr_h; /* 0x00128 */ + volatile u32 etbr_l; /* 0x0012c */ + volatile u32 etcir; /* 0x00130 */ + volatile u32 etpir; /* 0x00134 */ + volatile u32 emar_h; /* 0x00138 */ + volatile u32 emar_l; /* 0x0013c */ + volatile u32 ehar_h; /* 0x00140 */ + volatile u32 ehar_l; /* 0x00144 */ + volatile u32 micr; /* 0x00148 */ + volatile u32 midr_r; /* 0x0014c */ + volatile u32 midr_w; /* 0x00150 */ + volatile u32 pad1[(0x20000 - 0x00154) / 4]; + + /* SuperIO Registers XXX */ + struct ioc3_sioregs sregs; /* 0x20000 */ + volatile u32 pad2[(0x40000 - 0x20180) / 4]; + + /* SSRAM Diagnostic Access */ + volatile u32 ssram[(0x80000 - 0x40000) / 4]; + + /* Bytebus device offsets + 0x80000 - Access to the generic devices selected with DEV0 + 0x9FFFF bytebus DEV_SEL_0 + 0xA0000 - Access to the generic devices selected with DEV1 + 0xBFFFF bytebus DEV_SEL_1 + 0xC0000 - Access to the generic devices selected with DEV2 + 0xDFFFF bytebus DEV_SEL_2 + 0xE0000 - Access to the generic devices selected with DEV3 + 0xFFFFF bytebus DEV_SEL_3 */ +}; + +/* + * Ethernet RX Buffer + */ +struct ioc3_erxbuf { + u32 w0; /* first word (valid,bcnt,cksum) */ + u32 err; /* second word various errors */ + /* next comes n bytes of padding */ + /* then the received ethernet frame itself */ +}; + +#define ERXBUF_IPCKSUM_MASK 0x0000ffff +#define ERXBUF_BYTECNT_MASK 0x07ff0000 +#define ERXBUF_BYTECNT_SHIFT 16 +#define ERXBUF_V 0x80000000 + +#define ERXBUF_CRCERR 0x00000001 /* aka RSV15 */ +#define ERXBUF_FRAMERR 0x00000002 /* aka RSV14 */ +#define ERXBUF_CODERR 0x00000004 /* aka RSV13 */ +#define ERXBUF_INVPREAMB 0x00000008 /* aka RSV18 */ +#define ERXBUF_LOLEN 0x00007000 /* aka RSV2_0 */ +#define ERXBUF_HILEN 0x03ff0000 /* aka RSV12_3 */ +#define ERXBUF_MULTICAST 0x04000000 /* aka RSV16 */ +#define ERXBUF_BROADCAST 0x08000000 /* aka RSV17 */ +#define ERXBUF_LONGEVENT 0x10000000 /* aka RSV19 */ +#define ERXBUF_BADPKT 0x20000000 /* aka RSV20 */ +#define ERXBUF_GOODPKT 0x40000000 /* aka RSV21 */ +#define ERXBUF_CARRIER 0x80000000 /* aka RSV22 */ + +/* + * Ethernet TX Descriptor + */ +#define ETXD_DATALEN 104 +struct ioc3_etxd { + u32 cmd; /* command field */ + u32 bufcnt; /* buffer counts field */ + u64 p1; /* buffer pointer 1 */ + u64 p2; /* buffer pointer 2 */ + u8 data[ETXD_DATALEN]; /* opt. tx data */ +}; + +#define ETXD_BYTECNT_MASK 0x000007ff /* total byte count */ +#define ETXD_INTWHENDONE 0x00001000 /* intr when done */ +#define ETXD_D0V 0x00010000 /* data 0 valid */ +#define ETXD_B1V 0x00020000 /* buf 1 valid */ +#define ETXD_B2V 0x00040000 /* buf 2 valid */ +#define ETXD_DOCHECKSUM 0x00080000 /* insert ip cksum */ +#define ETXD_CHKOFF_MASK 0x07f00000 /* cksum byte offset */ +#define ETXD_CHKOFF_SHIFT 20 + +#define ETXD_D0CNT_MASK 0x0000007f +#define ETXD_B1CNT_MASK 0x0007ff00 +#define ETXD_B1CNT_SHIFT 8 +#define ETXD_B2CNT_MASK 0x7ff00000 +#define ETXD_B2CNT_SHIFT 20 + +/* + * Bytebus device space + */ +#define IOC3_BYTEBUS_DEV0 0x80000L +#define IOC3_BYTEBUS_DEV1 0xa0000L +#define IOC3_BYTEBUS_DEV2 0xc0000L +#define IOC3_BYTEBUS_DEV3 0xe0000L + +/* ------------------------------------------------------------------------- */ + +/* Superio Registers (PIO Access) */ +#define IOC3_SIO_BASE 0x20000 +#define IOC3_SIO_UARTC (IOC3_SIO_BASE+0x141) /* UART Config */ +#define IOC3_SIO_KBDCG (IOC3_SIO_BASE+0x142) /* KBD Config */ +#define IOC3_SIO_PP_BASE (IOC3_SIO_BASE+PP_BASE) /* Parallel Port */ +#define IOC3_SIO_RTC_BASE (IOC3_SIO_BASE+0x168) /* Real Time Clock */ +#define IOC3_SIO_UB_BASE (IOC3_SIO_BASE+UARTB_BASE) /* UART B */ +#define IOC3_SIO_UA_BASE (IOC3_SIO_BASE+UARTA_BASE) /* UART A */ + +/* SSRAM Diagnostic Access */ +#define IOC3_SSRAM IOC3_RAM_OFF /* base of SSRAM diagnostic access */ +#define IOC3_SSRAM_LEN 0x40000 /* 256kb (address space size, may not be fully populated) */ +#define IOC3_SSRAM_DM 0x0000ffff /* data mask */ +#define IOC3_SSRAM_PM 0x00010000 /* parity mask */ + +/* bitmasks for PCI_SCR */ +#define PCI_SCR_PAR_RESP_EN 0x00000040 /* enb PCI parity checking */ +#define PCI_SCR_SERR_EN 0x00000100 /* enable the SERR# driver */ +#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */ +#define PCI_SCR_RX_SERR (0x1 << 16) +#define PCI_SCR_DROP_MODE (0x1 << 17) +#define PCI_SCR_SIG_PAR_ERR (0x1 << 24) +#define PCI_SCR_SIG_TAR_ABRT (0x1 << 27) +#define PCI_SCR_RX_TAR_ABRT (0x1 << 28) +#define PCI_SCR_SIG_MST_ABRT (0x1 << 29) +#define PCI_SCR_SIG_SERR (0x1 << 30) +#define PCI_SCR_PAR_ERR (0x1 << 31) + +/* bitmasks for IOC3_KM_CSR */ +#define KM_CSR_K_WRT_PEND 0x00000001 /* kbd port xmitting or resetting */ +#define KM_CSR_M_WRT_PEND 0x00000002 /* mouse port xmitting or resetting */ +#define KM_CSR_K_LCB 0x00000004 /* Line Cntrl Bit for last KBD write */ +#define KM_CSR_M_LCB 0x00000008 /* same for mouse */ +#define KM_CSR_K_DATA 0x00000010 /* state of kbd data line */ +#define KM_CSR_K_CLK 0x00000020 /* state of kbd clock line */ +#define KM_CSR_K_PULL_DATA 0x00000040 /* pull kbd data line low */ +#define KM_CSR_K_PULL_CLK 0x00000080 /* pull kbd clock line low */ +#define KM_CSR_M_DATA 0x00000100 /* state of ms data line */ +#define KM_CSR_M_CLK 0x00000200 /* state of ms clock line */ +#define KM_CSR_M_PULL_DATA 0x00000400 /* pull ms data line low */ +#define KM_CSR_M_PULL_CLK 0x00000800 /* pull ms clock line low */ +#define KM_CSR_EMM_MODE 0x00001000 /* emulation mode */ +#define KM_CSR_SIM_MODE 0x00002000 /* clock X8 */ +#define KM_CSR_K_SM_IDLE 0x00004000 /* Keyboard is idle */ +#define KM_CSR_M_SM_IDLE 0x00008000 /* Mouse is idle */ +#define KM_CSR_K_TO 0x00010000 /* Keyboard trying to send/receive */ +#define KM_CSR_M_TO 0x00020000 /* Mouse trying to send/receive */ +#define KM_CSR_K_TO_EN 0x00040000 /* KM_CSR_K_TO + KM_CSR_K_TO_EN = cause + SIO_IR to assert */ +#define KM_CSR_M_TO_EN 0x00080000 /* KM_CSR_M_TO + KM_CSR_M_TO_EN = cause + SIO_IR to assert */ +#define KM_CSR_K_CLAMP_ONE 0x00100000 /* Pull K_CLK low after rec. one char */ +#define KM_CSR_M_CLAMP_ONE 0x00200000 /* Pull M_CLK low after rec. one char */ +#define KM_CSR_K_CLAMP_THREE 0x00400000 /* Pull K_CLK low after rec. three chars */ +#define KM_CSR_M_CLAMP_THREE 0x00800000 /* Pull M_CLK low after rec. three char */ + +/* bitmasks for IOC3_K_RD and IOC3_M_RD */ +#define KM_RD_DATA_2 0x000000ff /* 3rd char recvd since last read */ +#define KM_RD_DATA_2_SHIFT 0 +#define KM_RD_DATA_1 0x0000ff00 /* 2nd char recvd since last read */ +#define KM_RD_DATA_1_SHIFT 8 +#define KM_RD_DATA_0 0x00ff0000 /* 1st char recvd since last read */ +#define KM_RD_DATA_0_SHIFT 16 +#define KM_RD_FRAME_ERR_2 0x01000000 /* framing or parity error in byte 2 */ +#define KM_RD_FRAME_ERR_1 0x02000000 /* same for byte 1 */ +#define KM_RD_FRAME_ERR_0 0x04000000 /* same for byte 0 */ + +#define KM_RD_KBD_MSE 0x08000000 /* 0 if from kbd, 1 if from mouse */ +#define KM_RD_OFLO 0x10000000 /* 4th char recvd before this read */ +#define KM_RD_VALID_2 0x20000000 /* DATA_2 valid */ +#define KM_RD_VALID_1 0x40000000 /* DATA_1 valid */ +#define KM_RD_VALID_0 0x80000000 /* DATA_0 valid */ +#define KM_RD_VALID_ALL (KM_RD_VALID_0|KM_RD_VALID_1|KM_RD_VALID_2) + +/* bitmasks for IOC3_K_WD & IOC3_M_WD */ +#define KM_WD_WRT_DATA 0x000000ff /* write to keyboard/mouse port */ +#define KM_WD_WRT_DATA_SHIFT 0 + +/* bitmasks for serial RX status byte */ +#define RXSB_OVERRUN 0x01 /* char(s) lost */ +#define RXSB_PAR_ERR 0x02 /* parity error */ +#define RXSB_FRAME_ERR 0x04 /* framing error */ +#define RXSB_BREAK 0x08 /* break character */ +#define RXSB_CTS 0x10 /* state of CTS */ +#define RXSB_DCD 0x20 /* state of DCD */ +#define RXSB_MODEM_VALID 0x40 /* DCD, CTS and OVERRUN are valid */ +#define RXSB_DATA_VALID 0x80 /* data byte, FRAME_ERR PAR_ERR & BREAK valid */ + +/* bitmasks for serial TX control byte */ +#define TXCB_INT_WHEN_DONE 0x20 /* interrupt after this byte is sent */ +#define TXCB_INVALID 0x00 /* byte is invalid */ +#define TXCB_VALID 0x40 /* byte is valid */ +#define TXCB_MCR 0x80 /* data<7:0> to modem control register */ +#define TXCB_DELAY 0xc0 /* delay data<7:0> mSec */ + +/* bitmasks for IOC3_SBBR_L */ +#define SBBR_L_SIZE 0x00000001 /* 0 == 1KB rings, 1 == 4KB rings */ +#define SBBR_L_BASE 0xfffff000 /* lower serial ring base addr */ + +/* bitmasks for IOC3_SSCR_ */ +#define SSCR_RX_THRESHOLD 0x000001ff /* hiwater mark */ +#define SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */ +#define SSCR_HFC_EN 0x00020000 /* hardware flow control enabled */ +#define SSCR_RX_RING_DCD 0x00040000 /* post RX record on delta-DCD */ +#define SSCR_RX_RING_CTS 0x00080000 /* post RX record on delta-CTS */ +#define SSCR_HIGH_SPD 0x00100000 /* 4X speed */ +#define SSCR_DIAG 0x00200000 /* bypass clock divider for sim */ +#define SSCR_RX_DRAIN 0x08000000 /* drain RX buffer to memory */ +#define SSCR_DMA_EN 0x10000000 /* enable ring buffer DMA */ +#define SSCR_DMA_PAUSE 0x20000000 /* pause DMA */ +#define SSCR_PAUSE_STATE 0x40000000 /* sets when PAUSE takes effect */ +#define SSCR_RESET 0x80000000 /* reset DMA channels */ + +/* all producer/comsumer pointers are the same bitfield */ +#define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */ +#define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */ +#define PROD_CONS_PTR_OFF 3 + +/* bitmasks for IOC3_SRCIR_ */ +#define SRCIR_ARM 0x80000000 /* arm RX timer */ + +/* bitmasks for IOC3_SRPIR_ */ +#define SRPIR_BYTE_CNT 0x07000000 /* bytes in packer */ +#define SRPIR_BYTE_CNT_SHIFT 24 + +/* bitmasks for IOC3_STCIR_ */ +#define STCIR_BYTE_CNT 0x0f000000 /* bytes in unpacker */ +#define STCIR_BYTE_CNT_SHIFT 24 + +/* bitmasks for IOC3_SHADOW_ */ +#define SHADOW_DR 0x00000001 /* data ready */ +#define SHADOW_OE 0x00000002 /* overrun error */ +#define SHADOW_PE 0x00000004 /* parity error */ +#define SHADOW_FE 0x00000008 /* framing error */ +#define SHADOW_BI 0x00000010 /* break interrupt */ +#define SHADOW_THRE 0x00000020 /* transmit holding register empty */ +#define SHADOW_TEMT 0x00000040 /* transmit shift register empty */ +#define SHADOW_RFCE 0x00000080 /* char in RX fifo has an error */ +#define SHADOW_DCTS 0x00010000 /* delta clear to send */ +#define SHADOW_DDCD 0x00080000 /* delta data carrier detect */ +#define SHADOW_CTS 0x00100000 /* clear to send */ +#define SHADOW_DCD 0x00800000 /* data carrier detect */ +#define SHADOW_DTR 0x01000000 /* data terminal ready */ +#define SHADOW_RTS 0x02000000 /* request to send */ +#define SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */ +#define SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */ +#define SHADOW_LOOP 0x10000000 /* loopback enabled */ + +/* bitmasks for IOC3_SRTR_ */ +#define SRTR_CNT 0x00000fff /* reload value for RX timer */ +#define SRTR_CNT_VAL 0x0fff0000 /* current value of RX timer */ +#define SRTR_CNT_VAL_SHIFT 16 +#define SRTR_HZ 16000 /* SRTR clock frequency */ + +/* bitmasks for IOC3_SIO_IR, IOC3_SIO_IEC and IOC3_SIO_IES */ +#define SIO_IR_SA_TX_MT 0x00000001 /* Serial port A TX empty */ +#define SIO_IR_SA_RX_FULL 0x00000002 /* port A RX buf full */ +#define SIO_IR_SA_RX_HIGH 0x00000004 /* port A RX hiwat */ +#define SIO_IR_SA_RX_TIMER 0x00000008 /* port A RX timeout */ +#define SIO_IR_SA_DELTA_DCD 0x00000010 /* port A delta DCD */ +#define SIO_IR_SA_DELTA_CTS 0x00000020 /* port A delta CTS */ +#define SIO_IR_SA_INT 0x00000040 /* port A pass-thru intr */ +#define SIO_IR_SA_TX_EXPLICIT 0x00000080 /* port A explicit TX thru */ +#define SIO_IR_SA_MEMERR 0x00000100 /* port A PCI error */ +#define SIO_IR_SB_TX_MT 0x00000200 /* */ +#define SIO_IR_SB_RX_FULL 0x00000400 /* */ +#define SIO_IR_SB_RX_HIGH 0x00000800 /* */ +#define SIO_IR_SB_RX_TIMER 0x00001000 /* */ +#define SIO_IR_SB_DELTA_DCD 0x00002000 /* */ +#define SIO_IR_SB_DELTA_CTS 0x00004000 /* */ +#define SIO_IR_SB_INT 0x00008000 /* */ +#define SIO_IR_SB_TX_EXPLICIT 0x00010000 /* */ +#define SIO_IR_SB_MEMERR 0x00020000 /* */ +#define SIO_IR_PP_INT 0x00040000 /* P port pass-thru intr */ +#define SIO_IR_PP_INTA 0x00080000 /* PP context A thru */ +#define SIO_IR_PP_INTB 0x00100000 /* PP context B thru */ +#define SIO_IR_PP_MEMERR 0x00200000 /* PP PCI error */ +#define SIO_IR_KBD_INT 0x00400000 /* kbd/mouse intr */ +#define SIO_IR_RT_INT 0x08000000 /* RT output pulse */ +#define SIO_IR_GEN_INT1 0x10000000 /* RT input pulse */ +#define SIO_IR_GEN_INT_SHIFT 28 + +/* per device interrupt masks */ +#define SIO_IR_SA (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL | \ + SIO_IR_SA_RX_HIGH | SIO_IR_SA_RX_TIMER | \ + SIO_IR_SA_DELTA_DCD | SIO_IR_SA_DELTA_CTS | \ + SIO_IR_SA_INT | SIO_IR_SA_TX_EXPLICIT | \ + SIO_IR_SA_MEMERR) +#define SIO_IR_SB (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL | \ + SIO_IR_SB_RX_HIGH | SIO_IR_SB_RX_TIMER | \ + SIO_IR_SB_DELTA_DCD | SIO_IR_SB_DELTA_CTS | \ + SIO_IR_SB_INT | SIO_IR_SB_TX_EXPLICIT | \ + SIO_IR_SB_MEMERR) +#define SIO_IR_PP (SIO_IR_PP_INT | SIO_IR_PP_INTA | \ + SIO_IR_PP_INTB | SIO_IR_PP_MEMERR) +#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1) + +/* macro to load pending interrupts */ +#define IOC3_PENDING_INTRS(mem) (PCI_INW(&((mem)->sio_ir)) & \ + PCI_INW(&((mem)->sio_ies_ro))) + +/* bitmasks for SIO_CR */ +#define SIO_CR_SIO_RESET 0x00000001 /* reset the SIO */ +#define SIO_CR_SER_A_BASE 0x000000fe /* DMA poll addr port A */ +#define SIO_CR_SER_A_BASE_SHIFT 1 +#define SIO_CR_SER_B_BASE 0x00007f00 /* DMA poll addr port B */ +#define SIO_CR_SER_B_BASE_SHIFT 8 +#define SIO_SR_CMD_PULSE 0x00078000 /* byte bus strobe length */ +#define SIO_CR_CMD_PULSE_SHIFT 15 +#define SIO_CR_ARB_DIAG 0x00380000 /* cur !enet PCI requet (ro) */ +#define SIO_CR_ARB_DIAG_TXA 0x00000000 +#define SIO_CR_ARB_DIAG_RXA 0x00080000 +#define SIO_CR_ARB_DIAG_TXB 0x00100000 +#define SIO_CR_ARB_DIAG_RXB 0x00180000 +#define SIO_CR_ARB_DIAG_PP 0x00200000 +#define SIO_CR_ARB_DIAG_IDLE 0x00400000 /* 0 -> active request (ro) */ + +/* bitmasks for INT_OUT */ +#define INT_OUT_COUNT 0x0000ffff /* pulse interval timer */ +#define INT_OUT_MODE 0x00070000 /* mode mask */ +#define INT_OUT_MODE_0 0x00000000 /* set output to 0 */ +#define INT_OUT_MODE_1 0x00040000 /* set output to 1 */ +#define INT_OUT_MODE_1PULSE 0x00050000 /* send 1 pulse */ +#define INT_OUT_MODE_PULSES 0x00060000 /* send 1 pulse every interval */ +#define INT_OUT_MODE_SQW 0x00070000 /* toggle output every interval */ +#define INT_OUT_DIAG 0x40000000 /* diag mode */ +#define INT_OUT_INT_OUT 0x80000000 /* current state of INT_OUT */ + +/* time constants for INT_OUT */ +#define INT_OUT_NS_PER_TICK (30 * 260) /* 30 ns PCI clock, divisor=260 */ +#define INT_OUT_TICKS_PER_PULSE 3 /* outgoing pulse lasts 3 ticks */ +#define INT_OUT_US_TO_COUNT(x) /* convert uS to a count value */ \ + (((x) * 10 + INT_OUT_NS_PER_TICK / 200) * \ + 100 / INT_OUT_NS_PER_TICK - 1) +#define INT_OUT_COUNT_TO_US(x) /* convert count value to uS */ \ + (((x) + 1) * INT_OUT_NS_PER_TICK / 1000) +#define INT_OUT_MIN_TICKS 3 /* min period is width of pulse in "ticks" */ +#define INT_OUT_MAX_TICKS INT_OUT_COUNT /* largest possible count */ + +/* bitmasks for GPCR */ +#define GPCR_DIR 0x000000ff /* tristate pin input or output */ +#define GPCR_DIR_PIN(x) (1<<(x)) /* access one of the DIR bits */ +#define GPCR_EDGE 0x000f0000 /* extint edge or level sensitive */ +#define GPCR_EDGE_PIN(x) (1<<((x)+15)) /* access one of the EDGE bits */ + +/* values for GPCR */ +#define GPCR_INT_OUT_EN 0x00100000 /* enable INT_OUT to pin 0 */ +#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */ +#define GPCR_DIR_SERA_XCVR 0x00000080 /* Port A Transceiver select enable */ +#define GPCR_DIR_SERB_XCVR 0x00000040 /* Port B Transceiver select enable */ +#define GPCR_DIR_PHY_RST 0x00000020 /* ethernet PHY reset enable */ + +/* defs for some of the generic I/O pins */ +#define GPCR_PHY_RESET 0x20 /* pin is output to PHY reset */ +#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */ +#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */ + +#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */ +#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin controlling uart b mode select */ +#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin controlling uart a mode select */ + +#define EMCR_DUPLEX 0x00000001 +#define EMCR_PROMISC 0x00000002 +#define EMCR_PADEN 0x00000004 +#define EMCR_RXOFF_MASK 0x000001f8 +#define EMCR_RXOFF_SHIFT 3 +#define EMCR_RAMPAR 0x00000200 +#define EMCR_BADPAR 0x00000800 +#define EMCR_BUFSIZ 0x00001000 +#define EMCR_TXDMAEN 0x00002000 +#define EMCR_TXEN 0x00004000 +#define EMCR_RXDMAEN 0x00008000 +#define EMCR_RXEN 0x00010000 +#define EMCR_LOOPBACK 0x00020000 +#define EMCR_ARB_DIAG 0x001c0000 +#define EMCR_ARB_DIAG_IDLE 0x00200000 +#define EMCR_RST 0x80000000 + +#define EISR_RXTIMERINT 0x00000001 +#define EISR_RXTHRESHINT 0x00000002 +#define EISR_RXOFLO 0x00000004 +#define EISR_RXBUFOFLO 0x00000008 +#define EISR_RXMEMERR 0x00000010 +#define EISR_RXPARERR 0x00000020 +#define EISR_TXEMPTY 0x00010000 +#define EISR_TXRTRY 0x00020000 +#define EISR_TXEXDEF 0x00040000 +#define EISR_TXLCOL 0x00080000 +#define EISR_TXGIANT 0x00100000 +#define EISR_TXBUFUFLO 0x00200000 +#define EISR_TXEXPLICIT 0x00400000 +#define EISR_TXCOLLWRAP 0x00800000 +#define EISR_TXDEFERWRAP 0x01000000 +#define EISR_TXMEMERR 0x02000000 +#define EISR_TXPARERR 0x04000000 + +#define ERCSR_THRESH_MASK 0x000001ff /* enet RX threshold */ +#define ERCSR_RX_TMR 0x40000000 /* simulation only */ +#define ERCSR_DIAG_OFLO 0x80000000 /* simulation only */ + +#define ERBR_ALIGNMENT 4096 +#define ERBR_L_RXRINGBASE_MASK 0xfffff000 + +#define ERBAR_BARRIER_BIT 0x0100 +#define ERBAR_RXBARR_MASK 0xffff0000 +#define ERBAR_RXBARR_SHIFT 16 + +#define ERCIR_RXCONSUME_MASK 0x00000fff + +#define ERPIR_RXPRODUCE_MASK 0x00000fff +#define ERPIR_ARM 0x80000000 + +#define ERTR_CNT_MASK 0x000007ff + +#define ETCSR_IPGT_MASK 0x0000007f +#define ETCSR_IPGR1_MASK 0x00007f00 +#define ETCSR_IPGR1_SHIFT 8 +#define ETCSR_IPGR2_MASK 0x007f0000 +#define ETCSR_IPGR2_SHIFT 16 +#define ETCSR_NOTXCLK 0x80000000 + +#define ETCDC_COLLCNT_MASK 0x0000ffff +#define ETCDC_DEFERCNT_MASK 0xffff0000 +#define ETCDC_DEFERCNT_SHIFT 16 + +#define ETBR_ALIGNMENT (64*1024) +#define ETBR_L_RINGSZ_MASK 0x00000001 +#define ETBR_L_RINGSZ128 0 +#define ETBR_L_RINGSZ512 1 +#define ETBR_L_TXRINGBASE_MASK 0xffffc000 + +#define ETCIR_TXCONSUME_MASK 0x0000ffff +#define ETCIR_IDLE 0x80000000 + +#define ETPIR_TXPRODUCE_MASK 0x0000ffff + +#define EBIR_TXBUFPROD_MASK 0x0000001f +#define EBIR_TXBUFCONS_MASK 0x00001f00 +#define EBIR_TXBUFCONS_SHIFT 8 +#define EBIR_RXBUFPROD_MASK 0x007fc000 +#define EBIR_RXBUFPROD_SHIFT 14 +#define EBIR_RXBUFCONS_MASK 0xff800000 +#define EBIR_RXBUFCONS_SHIFT 23 + +#define MICR_REGADDR_MASK 0x0000001f +#define MICR_PHYADDR_MASK 0x000003e0 +#define MICR_PHYADDR_SHIFT 5 +#define MICR_READTRIG 0x00000400 +#define MICR_BUSY 0x00000800 + +#define MIDR_DATA_MASK 0x0000ffff + +#define ERXBUF_IPCKSUM_MASK 0x0000ffff +#define ERXBUF_BYTECNT_MASK 0x07ff0000 +#define ERXBUF_BYTECNT_SHIFT 16 +#define ERXBUF_V 0x80000000 + +#define ERXBUF_CRCERR 0x00000001 /* aka RSV15 */ +#define ERXBUF_FRAMERR 0x00000002 /* aka RSV14 */ +#define ERXBUF_CODERR 0x00000004 /* aka RSV13 */ +#define ERXBUF_INVPREAMB 0x00000008 /* aka RSV18 */ +#define ERXBUF_LOLEN 0x00007000 /* aka RSV2_0 */ +#define ERXBUF_HILEN 0x03ff0000 /* aka RSV12_3 */ +#define ERXBUF_MULTICAST 0x04000000 /* aka RSV16 */ +#define ERXBUF_BROADCAST 0x08000000 /* aka RSV17 */ +#define ERXBUF_LONGEVENT 0x10000000 /* aka RSV19 */ +#define ERXBUF_BADPKT 0x20000000 /* aka RSV20 */ +#define ERXBUF_GOODPKT 0x40000000 /* aka RSV21 */ +#define ERXBUF_CARRIER 0x80000000 /* aka RSV22 */ + +#define ETXD_BYTECNT_MASK 0x000007ff /* total byte count */ +#define ETXD_INTWHENDONE 0x00001000 /* intr when done */ +#define ETXD_D0V 0x00010000 /* data 0 valid */ +#define ETXD_B1V 0x00020000 /* buf 1 valid */ +#define ETXD_B2V 0x00040000 /* buf 2 valid */ +#define ETXD_DOCHECKSUM 0x00080000 /* insert ip cksum */ +#define ETXD_CHKOFF_MASK 0x07f00000 /* cksum byte offset */ +#define ETXD_CHKOFF_SHIFT 20 + +#define ETXD_D0CNT_MASK 0x0000007f +#define ETXD_B1CNT_MASK 0x0007ff00 +#define ETXD_B1CNT_SHIFT 8 +#define ETXD_B2CNT_MASK 0x7ff00000 +#define ETXD_B2CNT_SHIFT 20 + +typedef enum ioc3_subdevs_e { + ioc3_subdev_ether, + ioc3_subdev_generic, + ioc3_subdev_nic, + ioc3_subdev_kbms, + ioc3_subdev_ttya, + ioc3_subdev_ttyb, + ioc3_subdev_ecpp, + ioc3_subdev_rt, + ioc3_nsubdevs +} ioc3_subdev_t; + +/* subdevice disable bits, + * from the standard INFO_LBL_SUBDEVS + */ +#define IOC3_SDB_ETHER (1<. + * + * Copyright (C) 1992 - 1997, 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999, 2000 by Ralf Baechle + */ +#ifndef _ASM_SN_KLCONFIG_H +#define _ASM_SN_KLCONFIG_H + +/* + * The KLCONFIG structures store info about the various BOARDs found + * during Hardware Discovery. In addition, it stores info about the + * components found on the BOARDs. + */ + +/* + * WARNING: + * Certain assembly language routines (notably xxxxx.s) in the IP27PROM + * will depend on the format of the data structures in this file. In + * most cases, rearranging the fields can seriously break things. + * Adding fields in the beginning or middle can also break things. + * Add fields if necessary, to the end of a struct in such a way + * that offsets of existing fields do not change. + */ + +#include +#include + +#if defined(CONFIG_SGI_IP27) + +#include +//#include +// XXX Stolen from : +#define MAX_ROUTER_PORTS (6) /* Max. number of ports on a router */ +#include +//#include +//#include + +#elif defined(CONFIG_SGI_IP35) + +#include +#include +#include +#include + +#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */ + +#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35) +#include +#include +#include +#if defined(CONFIG_SGI_IP35) +// The hack file has to be before vector and after sn0_fru.... +#include +#include +#include +#endif /* CONFIG_SGI_IP35 */ +#endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */ + +typedef u64 nic_t; + +#define KLCFGINFO_MAGIC 0xbeedbabe + +typedef s32 klconf_off_t; + +/* + * Some IMPORTANT OFFSETS. These are the offsets on all NODES. + */ +#define MAX_MODULE_ID 255 +#define SIZE_PAD 4096 /* 4k padding for structures */ +/* + * 1 NODE brd, 2 Router brd (1 8p, 1 meta), 6 Widgets, + * 2 Midplanes assuming no pci card cages + */ +#define MAX_SLOTS_PER_NODE (1 + 2 + 6 + 2) + +/* XXX if each node is guranteed to have some memory */ + +#define MAX_PCI_DEVS 8 + +/* lboard_t->brd_flags fields */ +/* All bits in this field are currently used. Try the pad fields if + you need more flag bits */ + +#define ENABLE_BOARD 0x01 +#define FAILED_BOARD 0x02 +#define DUPLICATE_BOARD 0x04 /* Boards like midplanes/routers which + are discovered twice. Use one of them */ +#define VISITED_BOARD 0x08 /* Used for compact hub numbering. */ +#define LOCAL_MASTER_IO6 0x10 /* master io6 for that node */ +#define GLOBAL_MASTER_IO6 0x20 +#define THIRD_NIC_PRESENT 0x40 /* for future use */ +#define SECOND_NIC_PRESENT 0x80 /* addons like MIO are present */ + +/* klinfo->flags fields */ + +#define KLINFO_ENABLE 0x01 /* This component is enabled */ +#define KLINFO_FAILED 0x02 /* This component failed */ +#define KLINFO_DEVICE 0x04 /* This component is a device */ +#define KLINFO_VISITED 0x08 /* This component has been visited */ +#define KLINFO_CONTROLLER 0x10 /* This component is a device controller */ +#define KLINFO_INSTALL 0x20 /* Install a driver */ +#define KLINFO_HEADLESS 0x40 /* Headless (or hubless) component */ +#define IS_CONSOLE_IOC3(i) ((((klinfo_t *)i)->flags) & KLINFO_INSTALL) + +#define GB2 0x80000000 + +#define MAX_RSV_PTRS 32 + +/* Structures to manage various data storage areas */ +/* The numbers must be contiguous since the array index i + is used in the code to allocate various areas. +*/ + +#define BOARD_STRUCT 0 +#define COMPONENT_STRUCT 1 +#define ERRINFO_STRUCT 2 +#define KLMALLOC_TYPE_MAX (ERRINFO_STRUCT + 1) +#define DEVICE_STRUCT 3 + + +typedef struct console_s { + unsigned long uart_base; + unsigned long config_base; + unsigned long memory_base; + short baud; + short flag; + int type; + nasid_t nasid; + char wid; + char npci; + nic_t baseio_nic; +} console_t; + +typedef struct klc_malloc_hdr { + klconf_off_t km_base; + klconf_off_t km_limit; + klconf_off_t km_current; +} klc_malloc_hdr_t; + +/* Functions/macros needed to use this structure */ + +typedef struct kl_config_hdr { + u64 ch_magic; /* set this to KLCFGINFO_MAGIC */ + u32 ch_version; /* structure version number */ + klconf_off_t ch_malloc_hdr_off; /* offset of ch_malloc_hdr */ + klconf_off_t ch_cons_off; /* offset of ch_cons */ + klconf_off_t ch_board_info; /* the link list of boards */ + console_t ch_cons_info; /* address info of the console */ + klc_malloc_hdr_t ch_malloc_hdr[KLMALLOC_TYPE_MAX]; + confidence_t ch_sw_belief; /* confidence that software is bad*/ + confidence_t ch_sn0net_belief; /* confidence that sn0net is bad */ +} kl_config_hdr_t; + + +#define KL_CONFIG_HDR(_nasid) ((kl_config_hdr_t *)(KLCONFIG_ADDR(_nasid))) +#define KL_CONFIG_INFO_OFFSET(_nasid) \ + (KL_CONFIG_HDR(_nasid)->ch_board_info) +#define KL_CONFIG_INFO_SET_OFFSET(_nasid, _off) \ + (KL_CONFIG_HDR(_nasid)->ch_board_info = (_off)) + +#define KL_CONFIG_INFO(_nasid) \ + (lboard_t *)((KL_CONFIG_HDR(_nasid)->ch_board_info) ? \ + NODE_OFFSET_TO_K1((_nasid), KL_CONFIG_HDR(_nasid)->ch_board_info) : \ + 0) +#define KL_CONFIG_MAGIC(_nasid) (KL_CONFIG_HDR(_nasid)->ch_magic) + +#define KL_CONFIG_CHECK_MAGIC(_nasid) \ + (KL_CONFIG_HDR(_nasid)->ch_magic == KLCFGINFO_MAGIC) + +#define KL_CONFIG_HDR_INIT_MAGIC(_nasid) \ + (KL_CONFIG_HDR(_nasid)->ch_magic = KLCFGINFO_MAGIC) + +/* --- New Macros for the changed kl_config_hdr_t structure --- */ + +#define PTR_CH_MALLOC_HDR(_k) ((klc_malloc_hdr_t *)\ + ((unsigned long)_k + (_k->ch_malloc_hdr_off))) + +#define KL_CONFIG_CH_MALLOC_HDR(_n) PTR_CH_MALLOC_HDR(KL_CONFIG_HDR(_n)) + +#define PTR_CH_CONS_INFO(_k) ((console_t *)\ + ((unsigned long)_k + (_k->ch_cons_off))) + +#define KL_CONFIG_CH_CONS_INFO(_n) PTR_CH_CONS_INFO(KL_CONFIG_HDR(_n)) + +/* ------------------------------------------------------------- */ + +#define KL_CONFIG_INFO_START(_nasid) \ + (klconf_off_t)(KLCONFIG_OFFSET(_nasid) + sizeof(kl_config_hdr_t)) + +#define KL_CONFIG_BOARD_NASID(_brd) ((_brd)->brd_nasid) +#define KL_CONFIG_BOARD_SET_NEXT(_brd, _off) ((_brd)->brd_next = (_off)) + +#define KL_CONFIG_DUPLICATE_BOARD(_brd) ((_brd)->brd_flags & DUPLICATE_BOARD) + +#define XBOW_PORT_TYPE_HUB(_xbowp, _link) \ + ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_flag & XBOW_PORT_HUB) +#define XBOW_PORT_TYPE_IO(_xbowp, _link) \ + ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_flag & XBOW_PORT_IO) + +#define XBOW_PORT_IS_ENABLED(_xbowp, _link) \ + ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_flag & XBOW_PORT_ENABLE) +#define XBOW_PORT_NASID(_xbowp, _link) \ + ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_nasid) + +#define XBOW_PORT_IO 0x1 +#define XBOW_PORT_HUB 0x2 +#define XBOW_PORT_ENABLE 0x4 + +#define SN0_PORT_FENCE_SHFT 0 +#define SN0_PORT_FENCE_MASK (1 << SN0_PORT_FENCE_SHFT) + +/* + * The KLCONFIG area is organized as a LINKED LIST of BOARDs. A BOARD + * can be either 'LOCAL' or 'REMOTE'. LOCAL means it is attached to + * the LOCAL/current NODE. REMOTE means it is attached to a different + * node.(TBD - Need a way to treat ROUTER boards.) + * + * There are 2 different structures to represent these boards - + * lboard - Local board, rboard - remote board. These 2 structures + * can be arbitrarily mixed in the LINKED LIST of BOARDs. (Refer + * Figure below). The first byte of the rboard or lboard structure + * is used to find out its type - no unions are used. + * If it is a lboard, then the config info of this board will be found + * on the local node. (LOCAL NODE BASE + offset value gives pointer to + * the structure. + * If it is a rboard, the local structure contains the node number + * and the offset of the beginning of the LINKED LIST on the remote node. + * The details of the hardware on a remote node can be built locally, + * if required, by reading the LINKED LIST on the remote node and + * ignoring all the rboards on that node. + * + * The local node uses the REMOTE NODE NUMBER + OFFSET to point to the + * First board info on the remote node. The remote node list is + * traversed as the local list, using the REMOTE BASE ADDRESS and not + * the local base address and ignoring all rboard values. + * + * + KLCONFIG + + +------------+ +------------+ +------------+ +------------+ + | lboard | +-->| lboard | +-->| rboard | +-->| lboard | + +------------+ | +------------+ | +------------+ | +------------+ + | board info | | | board info | | |errinfo,bptr| | | board info | + +------------+ | +------------+ | +------------+ | +------------+ + | offset |--+ | offset |--+ | offset |--+ |offset=NULL | + +------------+ +------------+ +------------+ +------------+ + + + +------------+ + | board info | + +------------+ +--------------------------------+ + | compt 1 |------>| type, rev, diaginfo, size ... | (CPU) + +------------+ +--------------------------------+ + | compt 2 |--+ + +------------+ | +--------------------------------+ + | ... | +--->| type, rev, diaginfo, size ... | (MEM_BANK) + +------------+ +--------------------------------+ + | errinfo |--+ + +------------+ | +--------------------------------+ + +--->|r/l brd errinfo,compt err flags | + +--------------------------------+ + + * + * Each BOARD consists of COMPONENTs and the BOARD structure has + * pointers (offsets) to its COMPONENT structure. + * The COMPONENT structure has version info, size and speed info, revision, + * error info and the NIC info. This structure can accommodate any + * BOARD with arbitrary COMPONENT composition. + * + * The ERRORINFO part of each BOARD has error information + * that describes errors about the BOARD itself. It also has flags to + * indicate the COMPONENT(s) on the board that have errors. The error + * information specific to the COMPONENT is present in the respective + * COMPONENT structure. + * + * The ERRORINFO structure is also treated like a COMPONENT, ie. the + * BOARD has pointers(offset) to the ERRORINFO structure. The rboard + * structure also has a pointer to the ERRORINFO structure. This is + * the place to store ERRORINFO about a REMOTE NODE, if the HUB on + * that NODE is not working or if the REMOTE MEMORY is BAD. In cases where + * only the CPU of the REMOTE NODE is disabled, the ERRORINFO pointer can + * be a NODE NUMBER, REMOTE OFFSET combination, pointing to error info + * which is present on the REMOTE NODE.(TBD) + * REMOTE ERRINFO can be stored on any of the nearest nodes + * or on all the nearest nodes.(TBD) + * Like BOARD structures, REMOTE ERRINFO structures can be built locally + * using the rboard errinfo pointer. + * + * In order to get useful information from this Data organization, a set of + * interface routines are provided (TBD). The important thing to remember while + * manipulating the structures, is that, the NODE number information should + * be used. If the NODE is non-zero (remote) then each offset should + * be added to the REMOTE BASE ADDR else it should be added to the LOCAL BASE ADDR. + * This includes offsets for BOARDS, COMPONENTS and ERRORINFO. + * + * Note that these structures do not provide much info about connectivity. + * That info will be part of HWGRAPH, which is an extension of the cfg_t + * data structure. (ref IP27prom/cfg.h) It has to be extended to include + * the IO part of the Network(TBD). + * + * The data structures below define the above concepts. + */ + +/* + * Values for CPU types + */ +#define KL_CPU_R4000 0x1 /* Standard R4000 */ +#define KL_CPU_TFP 0x2 /* TFP processor */ +#define KL_CPU_R10000 0x3 /* R10000 (T5) */ +#define KL_CPU_NONE (-1) /* no cpu present in slot */ + +/* + * IP27 BOARD classes + */ + +#define KLCLASS_MASK 0xf0 +#define KLCLASS_NONE 0x00 +#define KLCLASS_NODE 0x10 /* CPU, Memory and HUB board */ +#define KLCLASS_CPU KLCLASS_NODE +#define KLCLASS_IO 0x20 /* BaseIO, 4 ch SCSI, ethernet, FDDI + and the non-graphics widget boards */ +#define KLCLASS_ROUTER 0x30 /* Router board */ +#define KLCLASS_MIDPLANE 0x40 /* We need to treat this as a board + so that we can record error info */ +#define KLCLASS_GFX 0x50 /* graphics boards */ + +#define KLCLASS_PSEUDO_GFX 0x60 /* HDTV type cards that use a gfx + * hw ifc to xtalk and are not gfx + * class for sw purposes */ + +#define KLCLASS_MAX 7 /* Bump this if a new CLASS is added */ +#define KLTYPE_MAX 10 /* Bump this if a new CLASS is added */ + +#define KLCLASS_UNKNOWN 0xf0 + +#define KLCLASS(_x) ((_x) & KLCLASS_MASK) + +/* + * IP27 board types + */ + +#define KLTYPE_MASK 0x0f +#define KLTYPE_NONE 0x00 +#define KLTYPE_EMPTY 0x00 + +#define KLTYPE_WEIRDCPU (KLCLASS_CPU | 0x0) +#define KLTYPE_IP27 (KLCLASS_CPU | 0x1) /* 2 CPUs(R10K) per board */ + +#define KLTYPE_WEIRDIO (KLCLASS_IO | 0x0) +#define KLTYPE_BASEIO (KLCLASS_IO | 0x1) /* IOC3, SuperIO, Bridge, SCSI */ +#define KLTYPE_IO6 KLTYPE_BASEIO /* Additional name */ +#define KLTYPE_4CHSCSI (KLCLASS_IO | 0x2) +#define KLTYPE_MSCSI KLTYPE_4CHSCSI /* Additional name */ +#define KLTYPE_ETHERNET (KLCLASS_IO | 0x3) +#define KLTYPE_MENET KLTYPE_ETHERNET /* Additional name */ +#define KLTYPE_FDDI (KLCLASS_IO | 0x4) +#define KLTYPE_UNUSED (KLCLASS_IO | 0x5) /* XXX UNUSED */ +#define KLTYPE_HAROLD (KLCLASS_IO | 0x6) /* PCI SHOE BOX */ +#define KLTYPE_PCI KLTYPE_HAROLD +#define KLTYPE_VME (KLCLASS_IO | 0x7) /* Any 3rd party VME card */ +#define KLTYPE_MIO (KLCLASS_IO | 0x8) +#define KLTYPE_FC (KLCLASS_IO | 0x9) +#define KLTYPE_LINC (KLCLASS_IO | 0xA) +#define KLTYPE_TPU (KLCLASS_IO | 0xB) /* Tensor Processing Unit */ +#define KLTYPE_GSN_A (KLCLASS_IO | 0xC) /* Main GSN board */ +#define KLTYPE_GSN_B (KLCLASS_IO | 0xD) /* Auxiliary GSN board */ + +#define KLTYPE_GFX (KLCLASS_GFX | 0x0) /* unknown graphics type */ +#define KLTYPE_GFX_KONA (KLCLASS_GFX | 0x1) /* KONA graphics on IP27 */ +#define KLTYPE_GFX_MGRA (KLCLASS_GFX | 0x3) /* MGRAS graphics on IP27 */ + +#define KLTYPE_WEIRDROUTER (KLCLASS_ROUTER | 0x0) +#define KLTYPE_ROUTER (KLCLASS_ROUTER | 0x1) +#define KLTYPE_ROUTER2 KLTYPE_ROUTER /* Obsolete! */ +#define KLTYPE_NULL_ROUTER (KLCLASS_ROUTER | 0x2) +#define KLTYPE_META_ROUTER (KLCLASS_ROUTER | 0x3) + +#define KLTYPE_WEIRDMIDPLANE (KLCLASS_MIDPLANE | 0x0) +#define KLTYPE_MIDPLANE8 (KLCLASS_MIDPLANE | 0x1) /* 8 slot backplane */ +#define KLTYPE_MIDPLANE KLTYPE_MIDPLANE8 +#define KLTYPE_PBRICK_XBOW (KLCLASS_MIDPLANE | 0x2) + +#define KLTYPE_IOBRICK (KLCLASS_IOBRICK | 0x0) +#define KLTYPE_IBRICK (KLCLASS_IOBRICK | 0x1) +#define KLTYPE_PBRICK (KLCLASS_IOBRICK | 0x2) +#define KLTYPE_XBRICK (KLCLASS_IOBRICK | 0x3) + +#define KLTYPE_PBRICK_BRIDGE KLTYPE_PBRICK + +/* The value of type should be more than 8 so that hinv prints + * out the board name from the NIC string. For values less than + * 8 the name of the board needs to be hard coded in a few places. + * When bringup started nic names had not standardized and so we + * had to hard code. (For people interested in history.) + */ +#define KLTYPE_XTHD (KLCLASS_PSEUDO_GFX | 0x9) + +#define KLTYPE_UNKNOWN (KLCLASS_UNKNOWN | 0xf) + +#define KLTYPE(_x) ((_x) & KLTYPE_MASK) +#define IS_MIO_PRESENT(l) ((l->brd_type == KLTYPE_BASEIO) && \ + (l->brd_flags & SECOND_NIC_PRESENT)) +#define IS_MIO_IOC3(l, n) (IS_MIO_PRESENT(l) && (n > 2)) + +/* + * board structures + */ + +#define MAX_COMPTS_PER_BRD 24 + +#define LOCAL_BOARD 1 +#define REMOTE_BOARD 2 + +#define LBOARD_STRUCT_VERSION 2 + +typedef struct lboard_s { + klconf_off_t brd_next; /* Next BOARD */ + unsigned char struct_type; /* type of structure, local or remote */ + unsigned char brd_type; /* type+class */ + unsigned char brd_sversion; /* version of this structure */ + unsigned char brd_brevision; /* board revision */ + unsigned char brd_promver; /* board prom version, if any */ + unsigned char brd_flags; /* Enabled, Disabled etc */ + unsigned char brd_slot; /* slot number */ + unsigned short brd_debugsw; /* Debug switches */ + moduleid_t brd_module; /* module to which it belongs */ + partid_t brd_partition; /* Partition number */ + unsigned short brd_diagval; /* diagnostic value */ + unsigned short brd_diagparm; /* diagnostic parameter */ + unsigned char brd_inventory; /* inventory history */ + unsigned char brd_numcompts; /* Number of components */ + nic_t brd_nic; /* Number in CAN */ + nasid_t brd_nasid; /* passed parameter */ + klconf_off_t brd_compts[MAX_COMPTS_PER_BRD]; /* pointers to COMPONENTS */ + klconf_off_t brd_errinfo; /* Board's error information */ + struct lboard_s *brd_parent; /* Logical parent for this brd */ + vertex_hdl_t brd_graph_link; /* vertex hdl to connect extern compts */ + confidence_t brd_confidence; /* confidence that the board is bad */ + nasid_t brd_owner; /* who owns this board */ + unsigned char brd_nic_flags; /* To handle 8 more NICs */ + char brd_name[32]; +} lboard_t; + + +/* + * Make sure we pass back the calias space address for local boards. + * klconfig board traversal and error structure extraction defines. + */ + +#define BOARD_SLOT(_brd) ((_brd)->brd_slot) + +#define KLCF_CLASS(_brd) KLCLASS((_brd)->brd_type) +#define KLCF_TYPE(_brd) KLTYPE((_brd)->brd_type) +#define KLCF_REMOTE(_brd) (((_brd)->struct_type & LOCAL_BOARD) ? 0 : 1) +#define KLCF_NUM_COMPS(_brd) ((_brd)->brd_numcompts) +#define KLCF_MODULE_ID(_brd) ((_brd)->brd_module) + +#define KLCF_NEXT(_brd) \ + ((_brd)->brd_next ? \ + (lboard_t *)(NODE_OFFSET_TO_K1(NASID_GET(_brd), (_brd)->brd_next)):\ + NULL) +#define KLCF_COMP(_brd, _ndx) \ + (klinfo_t *)(NODE_OFFSET_TO_K1(NASID_GET(_brd), \ + (_brd)->brd_compts[(_ndx)])) + +#define KLCF_COMP_ERROR(_brd, _comp) \ + (NODE_OFFSET_TO_K1(NASID_GET(_brd), (_comp)->errinfo)) + +#define KLCF_COMP_TYPE(_comp) ((_comp)->struct_type) +#define KLCF_BRIDGE_W_ID(_comp) ((_comp)->physid) /* Widget ID */ + + + +/* + * Generic info structure. This stores common info about a + * component. + */ + +typedef struct klinfo_s { /* Generic info */ + unsigned char struct_type; /* type of this structure */ + unsigned char struct_version; /* version of this structure */ + unsigned char flags; /* Enabled, disabled etc */ + unsigned char revision; /* component revision */ + unsigned short diagval; /* result of diagnostics */ + unsigned short diagparm; /* diagnostic parameter */ + unsigned char inventory; /* previous inventory status */ + nic_t nic; /* MUst be aligned properly */ + unsigned char physid; /* physical id of component */ + unsigned int virtid; /* virtual id as seen by system */ + unsigned char widid; /* Widget id - if applicable */ + nasid_t nasid; /* node number - from parent */ + char pad1; /* pad out structure. */ + char pad2; /* pad out structure. */ + COMPONENT *arcs_compt; /* ptr to the arcs struct for ease*/ + klconf_off_t errinfo; /* component specific errors */ + unsigned short pad3; /* pci fields have moved over to */ + unsigned short pad4; /* klbri_t */ +} klinfo_t ; + +#define KLCONFIG_INFO_ENABLED(_i) ((_i)->flags & KLINFO_ENABLE) +/* + * Component structures. + * Following are the currently identified components: + * CPU, HUB, MEM_BANK, + * XBOW(consists of 16 WIDGETs, each of which can be HUB or GRAPHICS or BRIDGE) + * BRIDGE, IOC3, SuperIO, SCSI, FDDI + * ROUTER + * GRAPHICS + */ +#define KLSTRUCT_UNKNOWN 0 +#define KLSTRUCT_CPU 1 +#define KLSTRUCT_HUB 2 +#define KLSTRUCT_MEMBNK 3 +#define KLSTRUCT_XBOW 4 +#define KLSTRUCT_BRI 5 +#define KLSTRUCT_IOC3 6 +#define KLSTRUCT_PCI 7 +#define KLSTRUCT_VME 8 +#define KLSTRUCT_ROU 9 +#define KLSTRUCT_GFX 10 +#define KLSTRUCT_SCSI 11 +#define KLSTRUCT_FDDI 12 +#define KLSTRUCT_MIO 13 +#define KLSTRUCT_DISK 14 +#define KLSTRUCT_TAPE 15 +#define KLSTRUCT_CDROM 16 +#define KLSTRUCT_HUB_UART 17 +#define KLSTRUCT_IOC3ENET 18 +#define KLSTRUCT_IOC3UART 19 +#define KLSTRUCT_UNUSED 20 /* XXX UNUSED */ +#define KLSTRUCT_IOC3PCKM 21 +#define KLSTRUCT_RAD 22 +#define KLSTRUCT_HUB_TTY 23 +#define KLSTRUCT_IOC3_TTY 24 + +/* Early Access IO proms are compatible + only with KLSTRUCT values upto 24. */ + +#define KLSTRUCT_FIBERCHANNEL 25 +#define KLSTRUCT_MOD_SERIAL_NUM 26 +#define KLSTRUCT_IOC3MS 27 +#define KLSTRUCT_TPU 28 +#define KLSTRUCT_GSN_A 29 +#define KLSTRUCT_GSN_B 30 +#define KLSTRUCT_XTHD 31 + +/* + * These are the indices of various components within a lboard structure. + */ + +#define IP27_CPU0_INDEX 0 +#define IP27_CPU1_INDEX 1 +#define IP27_HUB_INDEX 2 +#define IP27_MEM_INDEX 3 + +#define BASEIO_BRIDGE_INDEX 0 +#define BASEIO_IOC3_INDEX 1 +#define BASEIO_SCSI1_INDEX 2 +#define BASEIO_SCSI2_INDEX 3 + +#define MIDPLANE_XBOW_INDEX 0 +#define ROUTER_COMPONENT_INDEX 0 + +#define CH4SCSI_BRIDGE_INDEX 0 + +/* Info holders for various hardware components */ + +typedef u64 *pci_t; +typedef u64 *vmeb_t; +typedef u64 *vmed_t; +typedef u64 *fddi_t; +typedef u64 *scsi_t; +typedef u64 *mio_t; +typedef u64 *graphics_t; +typedef u64 *router_t; + +/* + * The port info in ip27_cfg area translates to a lboart_t in the + * KLCONFIG area. But since KLCONFIG does not use pointers, lboart_t + * is stored in terms of a nasid and a offset from start of KLCONFIG + * area on that nasid. + */ +typedef struct klport_s { + nasid_t port_nasid; + unsigned char port_flag; + klconf_off_t port_offset; +} klport_t; + +typedef struct klcpu_s { /* CPU */ + klinfo_t cpu_info; + unsigned short cpu_prid; /* Processor PRID value */ + unsigned short cpu_fpirr; /* FPU IRR value */ + unsigned short cpu_speed; /* Speed in MHZ */ + unsigned short cpu_scachesz; /* secondary cache size in MB */ + unsigned short cpu_scachespeed;/* secondary cache speed in MHz */ +} klcpu_t ; + +#define CPU_STRUCT_VERSION 2 + +typedef struct klhub_s { /* HUB */ + klinfo_t hub_info; + unsigned int hub_flags; /* PCFG_HUB_xxx flags */ + klport_t hub_port; /* hub is connected to this */ + nic_t hub_box_nic; /* nic of containing box */ + klconf_off_t hub_mfg_nic; /* MFG NIC string */ + u64 hub_speed; /* Speed of hub in HZ */ +} klhub_t ; + +typedef struct klhub_uart_s { /* HUB */ + klinfo_t hubuart_info; + unsigned int hubuart_flags; /* PCFG_HUB_xxx flags */ + nic_t hubuart_box_nic; /* nic of containing box */ +} klhub_uart_t ; + +#define MEMORY_STRUCT_VERSION 2 + +typedef struct klmembnk_s { /* MEMORY BANK */ + klinfo_t membnk_info; + short membnk_memsz; /* Total memory in megabytes */ + short membnk_dimm_select; /* bank to physical addr mapping*/ + short membnk_bnksz[MD_MEM_BANKS]; /* Memory bank sizes */ + short membnk_attr; +} klmembnk_t ; + +#define KLCONFIG_MEMBNK_SIZE(_info, _bank) \ + ((_info)->membnk_bnksz[(_bank)]) + + +#define MEMBNK_PREMIUM 1 +#define KLCONFIG_MEMBNK_PREMIUM(_info, _bank) \ + ((_info)->membnk_attr & (MEMBNK_PREMIUM << (_bank))) + +#define MAX_SERIAL_NUM_SIZE 10 + +typedef struct klmod_serial_num_s { + klinfo_t snum_info; + union { + char snum_str[MAX_SERIAL_NUM_SIZE]; + unsigned long long snum_int; + } snum; +} klmod_serial_num_t; + +/* Macros needed to access serial number structure in lboard_t. + Hard coded values are necessary since we cannot treat + serial number struct as a component without losing compatibility + between prom versions. */ + +#define GET_SNUM_COMP(_l) ((klmod_serial_num_t *)\ + KLCF_COMP(_l, _l->brd_numcompts)) + +#define MAX_XBOW_LINKS 16 + +typedef struct klxbow_s { /* XBOW */ + klinfo_t xbow_info ; + klport_t xbow_port_info[MAX_XBOW_LINKS] ; /* Module number */ + int xbow_master_hub_link; + /* type of brd connected+component struct ptr+flags */ +} klxbow_t ; + +#define MAX_PCI_SLOTS 8 + +typedef struct klpci_device_s { + s32 pci_device_id; /* 32 bits of vendor/device ID. */ + s32 pci_device_pad; /* 32 bits of padding. */ +} klpci_device_t; + +#define BRIDGE_STRUCT_VERSION 2 + +typedef struct klbri_s { /* BRIDGE */ + klinfo_t bri_info ; + unsigned char bri_eprominfo ; /* IO6prom connected to bridge */ + unsigned char bri_bustype ; /* PCI/VME BUS bridge/GIO */ + pci_t pci_specific ; /* PCI Board config info */ + klpci_device_t bri_devices[MAX_PCI_DEVS] ; /* PCI IDs */ + klconf_off_t bri_mfg_nic ; +} klbri_t ; + +#define MAX_IOC3_TTY 2 + +typedef struct klioc3_s { /* IOC3 */ + klinfo_t ioc3_info ; + unsigned char ioc3_ssram ; /* Info about ssram */ + unsigned char ioc3_nvram ; /* Info about nvram */ + klinfo_t ioc3_superio ; /* Info about superio */ + klconf_off_t ioc3_tty_off ; + klinfo_t ioc3_enet ; + klconf_off_t ioc3_enet_off ; + klconf_off_t ioc3_kbd_off ; +} klioc3_t ; + +#define MAX_VME_SLOTS 8 + +typedef struct klvmeb_s { /* VME BRIDGE - PCI CTLR */ + klinfo_t vmeb_info ; + vmeb_t vmeb_specific ; + klconf_off_t vmeb_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ +} klvmeb_t ; + +typedef struct klvmed_s { /* VME DEVICE - VME BOARD */ + klinfo_t vmed_info ; + vmed_t vmed_specific ; + klconf_off_t vmed_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ +} klvmed_t ; + +#define ROUTER_VECTOR_VERS 2 + +/* XXX - Don't we need the number of ports here?!? */ +typedef struct klrou_s { /* ROUTER */ + klinfo_t rou_info ; + unsigned int rou_flags ; /* PCFG_ROUTER_xxx flags */ + nic_t rou_box_nic ; /* nic of the containing module */ + klport_t rou_port[MAX_ROUTER_PORTS + 1] ; /* array index 1 to 6 */ + klconf_off_t rou_mfg_nic ; /* MFG NIC string */ + u64 rou_vector; /* vector from master node */ +} klrou_t ; + +/* + * Graphics Controller/Device + * + * (IP27/IO6) Prom versions 6.13 (and 6.5.1 kernels) and earlier + * used a couple different structures to store graphics information. + * For compatibility reasons, the newer data structure preserves some + * of the layout so that fields that are used in the old versions remain + * in the same place (with the same info). Determination of what version + * of this structure we have is done by checking the cookie field. + */ +#define KLGFX_COOKIE 0x0c0de000 + +typedef struct klgfx_s { /* GRAPHICS Device */ + klinfo_t gfx_info; + klconf_off_t old_gndevs; /* for compatibility with older proms */ + klconf_off_t old_gdoff0; /* for compatibility with older proms */ + unsigned int cookie; /* for compatibility with older proms */ + unsigned int moduleslot; + struct klgfx_s *gfx_next_pipe; + graphics_t gfx_specific; + klconf_off_t pad0; /* for compatibility with older proms */ + klconf_off_t gfx_mfg_nic; +} klgfx_t; + +typedef struct klxthd_s { + klinfo_t xthd_info ; + klconf_off_t xthd_mfg_nic ; /* MFG NIC string */ +} klxthd_t ; + +typedef struct kltpu_s { /* TPU board */ + klinfo_t tpu_info ; + klconf_off_t tpu_mfg_nic ; /* MFG NIC string */ +} kltpu_t ; + +typedef struct klgsn_s { /* GSN board */ + klinfo_t gsn_info ; + klconf_off_t gsn_mfg_nic ; /* MFG NIC string */ +} klgsn_t ; + +#define MAX_SCSI_DEVS 16 + +/* + * NOTE: THis is the max sized kl* structure and is used in klmalloc.c + * to allocate space of type COMPONENT. Make sure that if the size of + * any other component struct becomes more than this, then redefine + * that as the size to be klmalloced. + */ + +typedef struct klscsi_s { /* SCSI Controller */ + klinfo_t scsi_info ; + scsi_t scsi_specific ; + unsigned char scsi_numdevs ; + klconf_off_t scsi_devinfo[MAX_SCSI_DEVS] ; +} klscsi_t ; + +typedef struct klscdev_s { /* SCSI device */ + klinfo_t scdev_info ; + struct scsidisk_data *scdev_cfg ; /* driver fills up this */ +} klscdev_t ; + +typedef struct klttydev_s { /* TTY device */ + klinfo_t ttydev_info ; + struct terminal_data *ttydev_cfg ; /* driver fills up this */ +} klttydev_t ; + +typedef struct klenetdev_s { /* ENET device */ + klinfo_t enetdev_info ; + struct net_data *enetdev_cfg ; /* driver fills up this */ +} klenetdev_t ; + +typedef struct klkbddev_s { /* KBD device */ + klinfo_t kbddev_info ; + struct keyboard_data *kbddev_cfg ; /* driver fills up this */ +} klkbddev_t ; + +typedef struct klmsdev_s { /* mouse device */ + klinfo_t msdev_info ; + void *msdev_cfg ; +} klmsdev_t ; + +#define MAX_FDDI_DEVS 10 /* XXX Is this true */ + +typedef struct klfddi_s { /* FDDI */ + klinfo_t fddi_info ; + fddi_t fddi_specific ; + klconf_off_t fddi_devinfo[MAX_FDDI_DEVS] ; +} klfddi_t ; + +typedef struct klmio_s { /* MIO */ + klinfo_t mio_info ; + mio_t mio_specific ; +} klmio_t ; + + +typedef union klcomp_s { + klcpu_t kc_cpu; + klhub_t kc_hub; + klmembnk_t kc_mem; + klxbow_t kc_xbow; + klbri_t kc_bri; + klioc3_t kc_ioc3; + klvmeb_t kc_vmeb; + klvmed_t kc_vmed; + klrou_t kc_rou; + klgfx_t kc_gfx; + klscsi_t kc_scsi; + klscdev_t kc_scsi_dev; + klfddi_t kc_fddi; + klmio_t kc_mio; + klmod_serial_num_t kc_snum ; +} klcomp_t; + +typedef union kldev_s { /* for device structure allocation */ + klscdev_t kc_scsi_dev ; + klttydev_t kc_tty_dev ; + klenetdev_t kc_enet_dev ; + klkbddev_t kc_kbd_dev ; +} kldev_t ; + +/* Data structure interface routines. TBD */ + +/* Include launch info in this file itself? TBD */ + +/* + * TBD - Can the ARCS and device driver related info also be included in the + * KLCONFIG area. On the IO4PROM, prom device driver info is part of cfgnode_t + * structure, viz private to the IO4prom. + */ + +/* + * TBD - Allocation issues. + * + * Do we need to Mark off sepatate heaps for lboard_t, rboard_t, component, + * errinfo and allocate from them, or have a single heap and allocate all + * structures from it. Debug is easier in the former method since we can + * dump all similar structs in one command, but there will be lots of holes, + * in memory and max limits are needed for number of structures. + * Another way to make it organized, is to have a union of all components + * and allocate a aligned chunk of memory greater than the biggest + * component. + */ + +typedef union { + lboard_t *lbinfo ; +} biptr_t ; + + +#define BRI_PER_XBOW 6 +#define PCI_PER_BRI 8 +#define DEV_PER_PCI 16 + + +/* Virtual dipswitch values (starting from switch "7"): */ + +#define VDS_NOGFX 0x8000 /* Don't enable gfx and autoboot */ +#define VDS_NOMP 0x100 /* Don't start slave processors */ +#define VDS_MANUMODE 0x80 /* Manufacturing mode */ +#define VDS_NOARB 0x40 /* No bootmaster arbitration */ +#define VDS_PODMODE 0x20 /* Go straight to POD mode */ +#define VDS_NO_DIAGS 0x10 /* Don't run any diags after BM arb */ +#define VDS_DEFAULTS 0x08 /* Use default environment values */ +#define VDS_NOMEMCLEAR 0x04 /* Don't run mem cfg code */ +#define VDS_2ND_IO4 0x02 /* Boot from the second IO4 */ +#define VDS_DEBUG_PROM 0x01 /* Print PROM debugging messages */ + +/* external declarations of Linux kernel functions. */ + +extern lboard_t *find_lboard(lboard_t *start, unsigned char type); +extern klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char type); +extern klinfo_t *find_first_component(lboard_t *brd, unsigned char type); +extern klcpu_t *nasid_slice_to_cpuinfo(nasid_t, int); +extern lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_class); + + +extern klcpu_t *sn_get_cpuinfo(cpuid_t cpu); + +#endif /* _ASM_SN_KLCONFIG_H */ diff --git a/arch/mips/include/asm/sn/kldir.h b/arch/mips/include/asm/sn/kldir.h new file mode 100644 index 00000000000..1327e12e964 --- /dev/null +++ b/arch/mips/include/asm/sn/kldir.h @@ -0,0 +1,217 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX , revision 1.21. + * + * Copyright (C) 1992 - 1997, 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999, 2000 by Ralf Baechle + */ +#ifndef _ASM_SN_KLDIR_H +#define _ASM_SN_KLDIR_H + + +/* + * The kldir memory area resides at a fixed place in each node's memory and + * provides pointers to most other IP27 memory areas. This allows us to + * resize and/or relocate memory areas at a later time without breaking all + * firmware and kernels that use them. Indices in the array are + * permanently dedicated to areas listed below. Some memory areas (marked + * below) reside at a permanently fixed location, but are included in the + * directory for completeness. + */ + +#define KLDIR_MAGIC 0x434d5f53505f5357 + +/* + * The upper portion of the memory map applies during boot + * only and is overwritten by IRIX/SYMMON. + * + * MEMORY MAP PER NODE + * + * 0x2000000 (32M) +-----------------------------------------+ + * | IO6 BUFFERS FOR FLASH ENET IOC3 | + * 0x1F80000 (31.5M) +-----------------------------------------+ + * | IO6 TEXT/DATA/BSS/stack | + * 0x1C00000 (30M) +-----------------------------------------+ + * | IO6 PROM DEBUG TEXT/DATA/BSS/stack | + * 0x0800000 (28M) +-----------------------------------------+ + * | IP27 PROM TEXT/DATA/BSS/stack | + * 0x1B00000 (27M) +-----------------------------------------+ + * | IP27 CFG | + * 0x1A00000 (26M) +-----------------------------------------+ + * | Graphics PROM | + * 0x1800000 (24M) +-----------------------------------------+ + * | 3rd Party PROM drivers | + * 0x1600000 (22M) +-----------------------------------------+ + * | | + * | Free | + * | | + * +-----------------------------------------+ + * | UNIX DEBUG Version | + * 0x190000 (2M--) +-----------------------------------------+ + * | SYMMON | + * | (For UNIX Debug only) | + * 0x34000 (208K) +-----------------------------------------+ + * | SYMMON STACK [NUM_CPU_PER_NODE] | + * | (For UNIX Debug only) | + * 0x25000 (148K) +-----------------------------------------+ + * | KLCONFIG - II (temp) | + * | | + * | ---------------------------- | + * | | + * | UNIX NON-DEBUG Version | + * 0x19000 (100K) +-----------------------------------------+ + * + * + * The lower portion of the memory map contains information that is + * permanent and is used by the IP27PROM, IO6PROM and IRIX. + * + * 0x19000 (100K) +-----------------------------------------+ + * | | + * | PI Error Spools (32K) | + * | | + * 0x12000 (72K) +-----------------------------------------+ + * | Unused | + * 0x11c00 (71K) +-----------------------------------------+ + * | CPU 1 NMI Eframe area | + * 0x11a00 (70.5K) +-----------------------------------------+ + * | CPU 0 NMI Eframe area | + * 0x11800 (70K) +-----------------------------------------+ + * | CPU 1 NMI Register save area | + * 0x11600 (69.5K) +-----------------------------------------+ + * | CPU 0 NMI Register save area | + * 0x11400 (69K) +-----------------------------------------+ + * | GDA (1k) | + * 0x11000 (68K) +-----------------------------------------+ + * | Early cache Exception stack | + * | and/or | + * | kernel/io6prom nmi registers | + * 0x10800 (66k) +-----------------------------------------+ + * | cache error eframe | + * 0x10400 (65K) +-----------------------------------------+ + * | Exception Handlers (UALIAS copy) | + * 0x10000 (64K) +-----------------------------------------+ + * | | + * | | + * | KLCONFIG - I (permanent) (48K) | + * | | + * | | + * | | + * 0x4000 (16K) +-----------------------------------------+ + * | NMI Handler (Protected Page) | + * 0x3000 (12K) +-----------------------------------------+ + * | ARCS PVECTORS (master node only) | + * 0x2c00 (11K) +-----------------------------------------+ + * | ARCS TVECTORS (master node only) | + * 0x2800 (10K) +-----------------------------------------+ + * | LAUNCH [NUM_CPU] | + * 0x2400 (9K) +-----------------------------------------+ + * | Low memory directory (KLDIR) | + * 0x2000 (8K) +-----------------------------------------+ + * | ARCS SPB (1K) | + * 0x1000 (4K) +-----------------------------------------+ + * | Early cache Exception stack | + * | and/or | + * | kernel/io6prom nmi registers | + * 0x800 (2k) +-----------------------------------------+ + * | cache error eframe | + * 0x400 (1K) +-----------------------------------------+ + * | Exception Handlers | + * 0x0 (0K) +-----------------------------------------+ + */ + +#ifdef __ASSEMBLY__ +#define KLDIR_OFF_MAGIC 0x00 +#define KLDIR_OFF_OFFSET 0x08 +#define KLDIR_OFF_POINTER 0x10 +#define KLDIR_OFF_SIZE 0x18 +#define KLDIR_OFF_COUNT 0x20 +#define KLDIR_OFF_STRIDE 0x28 +#endif /* __ASSEMBLY__ */ + +/* + * This is defined here because IP27_SYMMON_STK_SIZE must be at least what + * we define here. Since it's set up in the prom. We can't redefine it later + * and expect more space to be allocated. The way to find out the true size + * of the symmon stacks is to divide SYMMON_STK_SIZE by SYMMON_STK_STRIDE + * for a particular node. + */ +#define SYMMON_STACK_SIZE 0x8000 + +#if defined(PROM) + +/* + * These defines are prom version dependent. No code other than the IP27 + * prom should attempt to use these values. + */ +#define IP27_LAUNCH_OFFSET 0x2400 +#define IP27_LAUNCH_SIZE 0x400 +#define IP27_LAUNCH_COUNT 2 +#define IP27_LAUNCH_STRIDE 0x200 + +#define IP27_KLCONFIG_OFFSET 0x4000 +#define IP27_KLCONFIG_SIZE 0xc000 +#define IP27_KLCONFIG_COUNT 1 +#define IP27_KLCONFIG_STRIDE 0 + +#define IP27_NMI_OFFSET 0x3000 +#define IP27_NMI_SIZE 0x40 +#define IP27_NMI_COUNT 2 +#define IP27_NMI_STRIDE 0x40 + +#define IP27_PI_ERROR_OFFSET 0x12000 +#define IP27_PI_ERROR_SIZE 0x4000 +#define IP27_PI_ERROR_COUNT 1 +#define IP27_PI_ERROR_STRIDE 0 + +#define IP27_SYMMON_STK_OFFSET 0x25000 +#define IP27_SYMMON_STK_SIZE 0xe000 +#define IP27_SYMMON_STK_COUNT 2 +/* IP27_SYMMON_STK_STRIDE must be >= SYMMON_STACK_SIZE */ +#define IP27_SYMMON_STK_STRIDE 0x7000 + +#define IP27_FREEMEM_OFFSET 0x19000 +#define IP27_FREEMEM_SIZE -1 +#define IP27_FREEMEM_COUNT 1 +#define IP27_FREEMEM_STRIDE 0 + +#endif /* PROM */ +/* + * There will be only one of these in a partition so the IO6 must set it up. + */ +#define IO6_GDA_OFFSET 0x11000 +#define IO6_GDA_SIZE 0x400 +#define IO6_GDA_COUNT 1 +#define IO6_GDA_STRIDE 0 + +/* + * save area of kernel nmi regs in the prom format + */ +#define IP27_NMI_KREGS_OFFSET 0x11400 +#define IP27_NMI_KREGS_CPU_SIZE 0x200 +/* + * save area of kernel nmi regs in eframe format + */ +#define IP27_NMI_EFRAME_OFFSET 0x11800 +#define IP27_NMI_EFRAME_SIZE 0x200 + +#define KLDIR_ENT_SIZE 0x40 +#define KLDIR_MAX_ENTRIES (0x400 / 0x40) + +#ifndef __ASSEMBLY__ +typedef struct kldir_ent_s { + u64 magic; /* Indicates validity of entry */ + off_t offset; /* Offset from start of node space */ + unsigned long pointer; /* Pointer to area in some cases */ + size_t size; /* Size in bytes */ + u64 count; /* Repeat count if array, 1 if not */ + size_t stride; /* Stride if array, 0 if not */ + char rsvd[16]; /* Pad entry to 0x40 bytes */ + /* NOTE: These 16 bytes are used in the Partition KLDIR + entry to store partition info. Refer to klpart.h for this. */ +} kldir_ent_t; +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_SN_KLDIR_H */ diff --git a/arch/mips/include/asm/sn/klkernvars.h b/arch/mips/include/asm/sn/klkernvars.h new file mode 100644 index 00000000000..5de4c5e8ab3 --- /dev/null +++ b/arch/mips/include/asm/sn/klkernvars.h @@ -0,0 +1,29 @@ +/* + * File ported from IRIX to Linux by Kanoj Sarcar, 06/08/00. + * Copyright 2000 Silicon Graphics, Inc. + */ +#ifndef __ASM_SN_KLKERNVARS_H +#define __ASM_SN_KLKERNVARS_H + +#define KV_MAGIC_OFFSET 0x0 +#define KV_RO_NASID_OFFSET 0x4 +#define KV_RW_NASID_OFFSET 0x6 + +#define KV_MAGIC 0x5f4b565f + +#ifndef __ASSEMBLY__ + +#include + +typedef struct kern_vars_s { + int kv_magic; + nasid_t kv_ro_nasid; + nasid_t kv_rw_nasid; + unsigned long kv_ro_baseaddr; + unsigned long kv_rw_baseaddr; +} kern_vars_t; + +#endif /* !__ASSEMBLY__ */ + +#endif /* __ASM_SN_KLKERNVARS_H */ + diff --git a/arch/mips/include/asm/sn/launch.h b/arch/mips/include/asm/sn/launch.h new file mode 100644 index 00000000000..b7c2226312c --- /dev/null +++ b/arch/mips/include/asm/sn/launch.h @@ -0,0 +1,106 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ +#ifndef _ASM_SN_LAUNCH_H +#define _ASM_SN_LAUNCH_H + +#include +#include + +/* + * The launch data structure resides at a fixed place in each node's memory + * and is used to communicate between the master processor and the slave + * processors. + * + * The master stores launch parameters in the launch structure + * corresponding to a target processor that is in a slave loop, then sends + * an interrupt to the slave processor. The slave calls the desired + * function, then returns to the slave loop. The master may poll or wait + * for the slaves to finish. + * + * There is an array of launch structures, one per CPU on the node. One + * interrupt level is used per local CPU. + */ + +#define LAUNCH_MAGIC 0xaddbead2addbead3 +#ifdef CONFIG_SGI_IP27 +#define LAUNCH_SIZEOF 0x100 +#define LAUNCH_PADSZ 0xa0 +#endif + +#define LAUNCH_OFF_MAGIC 0x00 /* Struct offsets for assembly */ +#define LAUNCH_OFF_BUSY 0x08 +#define LAUNCH_OFF_CALL 0x10 +#define LAUNCH_OFF_CALLC 0x18 +#define LAUNCH_OFF_CALLPARM 0x20 +#define LAUNCH_OFF_STACK 0x28 +#define LAUNCH_OFF_GP 0x30 +#define LAUNCH_OFF_BEVUTLB 0x38 +#define LAUNCH_OFF_BEVNORMAL 0x40 +#define LAUNCH_OFF_BEVECC 0x48 + +#define LAUNCH_STATE_DONE 0 /* Return value of LAUNCH_POLL */ +#define LAUNCH_STATE_SENT 1 +#define LAUNCH_STATE_RECD 2 + +/* + * The launch routine is called only if the complement address is correct. + * + * Before control is transferred to a routine, the complement address + * is zeroed (invalidated) to prevent an accidental call from a spurious + * interrupt. + * + * The slave_launch routine turns on the BUSY flag, and the slave loop + * clears the BUSY flag after control is returned to it. + */ + +#ifndef __ASSEMBLY__ + +typedef int launch_state_t; +typedef void (*launch_proc_t)(u64 call_parm); + +typedef struct launch_s { + volatile u64 magic; /* Magic number */ + volatile u64 busy; /* Slave currently active */ + volatile launch_proc_t call_addr; /* Func. for slave to call */ + volatile u64 call_addr_c; /* 1's complement of call_addr*/ + volatile u64 call_parm; /* Single parm passed to call*/ + volatile void *stack_addr; /* Stack pointer for slave function */ + volatile void *gp_addr; /* Global pointer for slave func. */ + volatile char *bevutlb;/* Address of bev utlb ex handler */ + volatile char *bevnormal;/*Address of bev normal ex handler */ + volatile char *bevecc;/* Address of bev cache err handler */ + volatile char pad[160]; /* Pad to LAUNCH_SIZEOF */ +} launch_t; + +/* + * PROM entry points for launch routines are determined by IPxxprom/start.s + */ + +#define LAUNCH_SLAVE (*(void (*)(int nasid, int cpu, \ + launch_proc_t call_addr, \ + u64 call_parm, \ + void *stack_addr, \ + void *gp_addr)) \ + IP27PROM_LAUNCHSLAVE) + +#define LAUNCH_WAIT (*(void (*)(int nasid, int cpu, int timeout_msec)) \ + IP27PROM_WAITSLAVE) + +#define LAUNCH_POLL (*(launch_state_t (*)(int nasid, int cpu)) \ + IP27PROM_POLLSLAVE) + +#define LAUNCH_LOOP (*(void (*)(void)) \ + IP27PROM_SLAVELOOP) + +#define LAUNCH_FLASH (*(void (*)(void)) \ + IP27PROM_FLASHLEDS) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_SN_LAUNCH_H */ diff --git a/arch/mips/include/asm/sn/mapped_kernel.h b/arch/mips/include/asm/sn/mapped_kernel.h new file mode 100644 index 00000000000..721496a0bb9 --- /dev/null +++ b/arch/mips/include/asm/sn/mapped_kernel.h @@ -0,0 +1,54 @@ +/* + * File created by Kanoj Sarcar 06/06/00. + * Copyright 2000 Silicon Graphics, Inc. + */ +#ifndef __ASM_SN_MAPPED_KERNEL_H +#define __ASM_SN_MAPPED_KERNEL_H + +#include + +/* + * Note on how mapped kernels work: the text and data section is + * compiled at cksseg segment (LOADADDR = 0xc001c000), and the + * init/setup/data section gets a 16M virtual address bump in the + * ld.script file (so that tlblo0 and tlblo1 maps the sections). + * The vmlinux.64 section addresses are put in the xkseg range + * using the change-addresses makefile option. Use elfdump -of + * on IRIX to see where the sections go. The Origin loader loads + * the two sections contiguously in physical memory. The loader + * sets the entry point into kernel_entry using a xkphys address, + * but instead of using 0xa800000001160000, it uses the address + * 0xa800000000160000, which is where it physically loaded that + * code. So no jumps can be done before we have switched to using + * cksseg addresses. + */ +#include + +#define REP_BASE CAC_BASE + +#ifdef CONFIG_MAPPED_KERNEL + +#define MAPPED_ADDR_RO_TO_PHYS(x) (x - REP_BASE) +#define MAPPED_ADDR_RW_TO_PHYS(x) (x - REP_BASE - 16777216) + +#define MAPPED_KERN_RO_PHYSBASE(n) (hub_data(n)->kern_vars.kv_ro_baseaddr) +#define MAPPED_KERN_RW_PHYSBASE(n) (hub_data(n)->kern_vars.kv_rw_baseaddr) + +#define MAPPED_KERN_RO_TO_PHYS(x) \ + ((unsigned long)MAPPED_ADDR_RO_TO_PHYS(x) | \ + MAPPED_KERN_RO_PHYSBASE(get_compact_nodeid())) +#define MAPPED_KERN_RW_TO_PHYS(x) \ + ((unsigned long)MAPPED_ADDR_RW_TO_PHYS(x) | \ + MAPPED_KERN_RW_PHYSBASE(get_compact_nodeid())) + +#else /* CONFIG_MAPPED_KERNEL */ + +#define MAPPED_KERN_RO_TO_PHYS(x) (x - REP_BASE) +#define MAPPED_KERN_RW_TO_PHYS(x) (x - REP_BASE) + +#endif /* CONFIG_MAPPED_KERNEL */ + +#define MAPPED_KERN_RO_TO_K0(x) PHYS_TO_K0(MAPPED_KERN_RO_TO_PHYS(x)) +#define MAPPED_KERN_RW_TO_K0(x) PHYS_TO_K0(MAPPED_KERN_RW_TO_PHYS(x)) + +#endif /* __ASM_SN_MAPPED_KERNEL_H */ diff --git a/arch/mips/include/asm/sn/nmi.h b/arch/mips/include/asm/sn/nmi.h new file mode 100644 index 00000000000..6b7b0b5f372 --- /dev/null +++ b/arch/mips/include/asm/sn/nmi.h @@ -0,0 +1,125 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997 Silicon Graphics, Inc. + */ +#ifndef __ASM_SN_NMI_H +#define __ASM_SN_NMI_H + +#ident "$Revision: 1.5 $" + +#include + +/* + * The launch data structure resides at a fixed place in each node's memory + * and is used to communicate between the master processor and the slave + * processors. + * + * The master stores launch parameters in the launch structure + * corresponding to a target processor that is in a slave loop, then sends + * an interrupt to the slave processor. The slave calls the desired + * function, followed by an optional rendezvous function, then returns to + * the slave loop. The master does not wait for the slaves before + * returning. + * + * There is an array of launch structures, one per CPU on the node. One + * interrupt level is used per CPU. + */ + +#define NMI_MAGIC 0x48414d4d455201 +#define NMI_SIZEOF 0x40 + +#define NMI_OFF_MAGIC 0x00 /* Struct offsets for assembly */ +#define NMI_OFF_FLAGS 0x08 +#define NMI_OFF_CALL 0x10 +#define NMI_OFF_CALLC 0x18 +#define NMI_OFF_CALLPARM 0x20 +#define NMI_OFF_GMASTER 0x28 + +/* + * The NMI routine is called only if the complement address is + * correct. + * + * Before control is transferred to a routine, the complement address + * is zeroed (invalidated) to prevent an accidental call from a spurious + * interrupt. + * + */ + +#ifndef __ASSEMBLY__ + +typedef struct nmi_s { + volatile unsigned long magic; /* Magic number */ + volatile unsigned long flags; /* Combination of flags above */ + volatile void *call_addr; /* Routine for slave to call */ + volatile void *call_addr_c; /* 1's complement of address */ + volatile void *call_parm; /* Single parm passed to call */ + volatile unsigned long gmaster; /* Flag true only on global master*/ +} nmi_t; + +#endif /* !__ASSEMBLY__ */ + +/* Following definitions are needed both in the prom & the kernel + * to identify the format of the nmi cpu register save area in the + * low memory on each node. + */ +#ifndef __ASSEMBLY__ + +struct reg_struct { + unsigned long gpr[32]; + unsigned long sr; + unsigned long cause; + unsigned long epc; + unsigned long badva; + unsigned long error_epc; + unsigned long cache_err; + unsigned long nmi_sr; +}; + +#endif /* !__ASSEMBLY__ */ + +/* These are the assembly language offsets into the reg_struct structure */ + +#define R0_OFF 0x0 +#define R1_OFF 0x8 +#define R2_OFF 0x10 +#define R3_OFF 0x18 +#define R4_OFF 0x20 +#define R5_OFF 0x28 +#define R6_OFF 0x30 +#define R7_OFF 0x38 +#define R8_OFF 0x40 +#define R9_OFF 0x48 +#define R10_OFF 0x50 +#define R11_OFF 0x58 +#define R12_OFF 0x60 +#define R13_OFF 0x68 +#define R14_OFF 0x70 +#define R15_OFF 0x78 +#define R16_OFF 0x80 +#define R17_OFF 0x88 +#define R18_OFF 0x90 +#define R19_OFF 0x98 +#define R20_OFF 0xa0 +#define R21_OFF 0xa8 +#define R22_OFF 0xb0 +#define R23_OFF 0xb8 +#define R24_OFF 0xc0 +#define R25_OFF 0xc8 +#define R26_OFF 0xd0 +#define R27_OFF 0xd8 +#define R28_OFF 0xe0 +#define R29_OFF 0xe8 +#define R30_OFF 0xf0 +#define R31_OFF 0xf8 +#define SR_OFF 0x100 +#define CAUSE_OFF 0x108 +#define EPC_OFF 0x110 +#define BADVA_OFF 0x118 +#define ERROR_EPC_OFF 0x120 +#define CACHE_ERR_OFF 0x128 +#define NMISR_OFF 0x130 + +#endif /* __ASM_SN_NMI_H */ diff --git a/arch/mips/include/asm/sn/sn0/addrs.h b/arch/mips/include/asm/sn/sn0/addrs.h new file mode 100644 index 00000000000..b06190093bb --- /dev/null +++ b/arch/mips/include/asm/sn/sn0/addrs.h @@ -0,0 +1,288 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX , revision 1.126. + * + * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. + * Copyright (C) 1999 by Ralf Baechle + */ +#ifndef _ASM_SN_SN0_ADDRS_H +#define _ASM_SN_SN0_ADDRS_H + + +/* + * SN0 (on a T5) Address map + * + * This file contains a set of definitions and macros which are used + * to reference into the major address spaces (CAC, HSPEC, IO, MSPEC, + * and UNCAC) used by the SN0 architecture. It also contains addresses + * for "major" statically locatable PROM/Kernel data structures, such as + * the partition table, the configuration data structure, etc. + * We make an implicit assumption that the processor using this file + * follows the R10K's provisions for specifying uncached attributes; + * should this change, the base registers may very well become processor- + * dependent. + * + * For more information on the address spaces, see the "Local Resources" + * chapter of the Hub specification. + * + * NOTE: This header file is included both by C and by assembler source + * files. Please bracket any language-dependent definitions + * appropriately. + */ + +/* + * Some of the macros here need to be casted to appropriate types when used + * from C. They definitely must not be casted from assembly language so we + * use some new ANSI preprocessor stuff to paste these on where needed. + */ + +/* + * The following couple of definitions will eventually need to be variables, + * since the amount of address space assigned to each node depends on + * whether the system is running in N-mode (more nodes with less memory) + * or M-mode (fewer nodes with more memory). We expect that it will + * be a while before we need to make this decision dynamically, though, + * so for now we just use defines bracketed by an ifdef. + */ + +#ifdef CONFIG_SGI_SN_N_MODE + +#define NODE_SIZE_BITS 31 +#define BWIN_SIZE_BITS 28 + +#define NASID_BITS 9 +#define NASID_BITMASK (0x1ffLL) +#define NASID_SHFT 31 +#define NASID_META_BITS 5 +#define NASID_LOCAL_BITS 4 + +#define BDDIR_UPPER_MASK (UINT64_CAST 0x7ffff << 10) +#define BDECC_UPPER_MASK (UINT64_CAST 0x3ffffff << 3) + +#else /* !defined(CONFIG_SGI_SN_N_MODE), assume that M-mode is desired */ + +#define NODE_SIZE_BITS 32 +#define BWIN_SIZE_BITS 29 + +#define NASID_BITMASK (0xffLL) +#define NASID_BITS 8 +#define NASID_SHFT 32 +#define NASID_META_BITS 4 +#define NASID_LOCAL_BITS 4 + +#define BDDIR_UPPER_MASK (UINT64_CAST 0xfffff << 10) +#define BDECC_UPPER_MASK (UINT64_CAST 0x7ffffff << 3) + +#endif /* !defined(CONFIG_SGI_SN_N_MODE) */ + +#define NODE_ADDRSPACE_SIZE (UINT64_CAST 1 << NODE_SIZE_BITS) + +#define NASID_MASK (UINT64_CAST NASID_BITMASK << NASID_SHFT) +#define NASID_GET(_pa) (int) ((UINT64_CAST (_pa) >> \ + NASID_SHFT) & NASID_BITMASK) + +#if !defined(__ASSEMBLY__) + +#define NODE_SWIN_BASE(nasid, widget) \ + ((widget == 0) ? NODE_BWIN_BASE((nasid), SWIN0_BIGWIN) \ + : RAW_NODE_SWIN_BASE(nasid, widget)) +#else /* __ASSEMBLY__ */ +#define NODE_SWIN_BASE(nasid, widget) \ + (NODE_IO_BASE(nasid) + (UINT64_CAST(widget) << SWIN_SIZE_BITS)) +#endif /* __ASSEMBLY__ */ + +/* + * The following definitions pertain to the IO special address + * space. They define the location of the big and little windows + * of any given node. + */ + +#define BWIN_INDEX_BITS 3 +#define BWIN_SIZE (UINT64_CAST 1 << BWIN_SIZE_BITS) +#define BWIN_SIZEMASK (BWIN_SIZE - 1) +#define BWIN_WIDGET_MASK 0x7 +#define NODE_BWIN_BASE0(nasid) (NODE_IO_BASE(nasid) + BWIN_SIZE) +#define NODE_BWIN_BASE(nasid, bigwin) (NODE_BWIN_BASE0(nasid) + \ + (UINT64_CAST(bigwin) << BWIN_SIZE_BITS)) + +#define BWIN_WIDGETADDR(addr) ((addr) & BWIN_SIZEMASK) +#define BWIN_WINDOWNUM(addr) (((addr) >> BWIN_SIZE_BITS) & BWIN_WIDGET_MASK) +/* + * Verify if addr belongs to large window address of node with "nasid" + * + * + * NOTE: "addr" is expected to be XKPHYS address, and NOT physical + * address + * + * + */ + +#define NODE_BWIN_ADDR(nasid, addr) \ + (((addr) >= NODE_BWIN_BASE0(nasid)) && \ + ((addr) < (NODE_BWIN_BASE(nasid, HUB_NUM_BIG_WINDOW) + \ + BWIN_SIZE))) + +/* + * The following define the major position-independent aliases used + * in SN0. + * CALIAS -- Varies in size, points to the first n bytes of memory + * on the reader's node. + */ + +#define CALIAS_BASE CAC_BASE + + + +#define BRIDGE_REG_PTR(_base, _off) ((volatile bridgereg_t *) \ + ((__psunsigned_t)(_base) + (__psunsigned_t)(_off))) + +#define SN0_WIDGET_BASE(_nasid, _wid) (NODE_SWIN_BASE((_nasid), (_wid))) + +/* Turn on sable logging for the processors whose bits are set. */ +#define SABLE_LOG_TRIGGER(_map) + +#ifndef __ASSEMBLY__ +#define KERN_NMI_ADDR(nasid, slice) \ + TO_NODE_UNCAC((nasid), IP27_NMI_KREGS_OFFSET + \ + (IP27_NMI_KREGS_CPU_SIZE * (slice))) +#endif /* !__ASSEMBLY__ */ + +#ifdef PROM + +#define MISC_PROM_BASE PHYS_TO_K0(0x01300000) +#define MISC_PROM_SIZE 0x200000 + +#define DIAG_BASE PHYS_TO_K0(0x01500000) +#define DIAG_SIZE 0x300000 + +#define ROUTE_BASE PHYS_TO_K0(0x01800000) +#define ROUTE_SIZE 0x200000 + +#define IP27PROM_FLASH_HDR PHYS_TO_K0(0x01300000) +#define IP27PROM_FLASH_DATA PHYS_TO_K0(0x01301000) +#define IP27PROM_CORP_MAX 32 +#define IP27PROM_CORP PHYS_TO_K0(0x01800000) +#define IP27PROM_CORP_SIZE 0x10000 +#define IP27PROM_CORP_STK PHYS_TO_K0(0x01810000) +#define IP27PROM_CORP_STKSIZE 0x2000 +#define IP27PROM_DECOMP_BUF PHYS_TO_K0(0x01900000) +#define IP27PROM_DECOMP_SIZE 0xfff00 + +#define IP27PROM_BASE PHYS_TO_K0(0x01a00000) +#define IP27PROM_BASE_MAPPED (UNCAC_BASE | 0x1fc00000) +#define IP27PROM_SIZE_MAX 0x100000 + +#define IP27PROM_PCFG PHYS_TO_K0(0x01b00000) +#define IP27PROM_PCFG_SIZE 0xd0000 +#define IP27PROM_ERRDMP PHYS_TO_K1(0x01bd0000) +#define IP27PROM_ERRDMP_SIZE 0xf000 + +#define IP27PROM_INIT_START PHYS_TO_K1(0x01bd0000) +#define IP27PROM_CONSOLE PHYS_TO_K1(0x01bdf000) +#define IP27PROM_CONSOLE_SIZE 0x200 +#define IP27PROM_NETUART PHYS_TO_K1(0x01bdf200) +#define IP27PROM_NETUART_SIZE 0x100 +#define IP27PROM_UNUSED1 PHYS_TO_K1(0x01bdf300) +#define IP27PROM_UNUSED1_SIZE 0x500 +#define IP27PROM_ELSC_BASE_A PHYS_TO_K0(0x01bdf800) +#define IP27PROM_ELSC_BASE_B PHYS_TO_K0(0x01bdfc00) +#define IP27PROM_STACK_A PHYS_TO_K0(0x01be0000) +#define IP27PROM_STACK_B PHYS_TO_K0(0x01bf0000) +#define IP27PROM_STACK_SHFT 16 +#define IP27PROM_STACK_SIZE (1 << IP27PROM_STACK_SHFT) +#define IP27PROM_INIT_END PHYS_TO_K0(0x01c00000) + +#define SLAVESTACK_BASE PHYS_TO_K0(0x01580000) +#define SLAVESTACK_SIZE 0x40000 + +#define ENETBUFS_BASE PHYS_TO_K0(0x01f80000) +#define ENETBUFS_SIZE 0x20000 + +#define IO6PROM_BASE PHYS_TO_K0(0x01c00000) +#define IO6PROM_SIZE 0x400000 +#define IO6PROM_BASE_MAPPED (UNCAC_BASE | 0x11c00000) +#define IO6DPROM_BASE PHYS_TO_K0(0x01c00000) +#define IO6DPROM_SIZE 0x200000 + +#define NODEBUGUNIX_ADDR PHYS_TO_K0(0x00019000) +#define DEBUGUNIX_ADDR PHYS_TO_K0(0x00100000) + +#define IP27PROM_INT_LAUNCH 10 /* and 11 */ +#define IP27PROM_INT_NETUART 12 /* through 17 */ + +#endif /* PROM */ + +/* + * needed by symmon so it needs to be outside #if PROM + */ +#define IP27PROM_ELSC_SHFT 10 +#define IP27PROM_ELSC_SIZE (1 << IP27PROM_ELSC_SHFT) + +/* + * This address is used by IO6PROM to build MemoryDescriptors of + * free memory. This address is important since unix gets loaded + * at this address, and this memory has to be FREE if unix is to + * be loaded. + */ + +#define FREEMEM_BASE PHYS_TO_K0(0x2000000) + +#define IO6PROM_STACK_SHFT 14 /* stack per cpu */ +#define IO6PROM_STACK_SIZE (1 << IO6PROM_STACK_SHFT) + +/* + * IP27 PROM vectors + */ + +#define IP27PROM_ENTRY PHYS_TO_COMPATK1(0x1fc00000) +#define IP27PROM_RESTART PHYS_TO_COMPATK1(0x1fc00008) +#define IP27PROM_SLAVELOOP PHYS_TO_COMPATK1(0x1fc00010) +#define IP27PROM_PODMODE PHYS_TO_COMPATK1(0x1fc00018) +#define IP27PROM_IOC3UARTPOD PHYS_TO_COMPATK1(0x1fc00020) +#define IP27PROM_FLASHLEDS PHYS_TO_COMPATK1(0x1fc00028) +#define IP27PROM_REPOD PHYS_TO_COMPATK1(0x1fc00030) +#define IP27PROM_LAUNCHSLAVE PHYS_TO_COMPATK1(0x1fc00038) +#define IP27PROM_WAITSLAVE PHYS_TO_COMPATK1(0x1fc00040) +#define IP27PROM_POLLSLAVE PHYS_TO_COMPATK1(0x1fc00048) + +#define KL_UART_BASE LOCAL_HUB_ADDR(MD_UREG0_0) /* base of UART regs */ +#define KL_UART_CMD LOCAL_HUB_ADDR(MD_UREG0_0) /* UART command reg */ +#define KL_UART_DATA LOCAL_HUB_ADDR(MD_UREG0_1) /* UART data reg */ +#define KL_I2C_REG MD_UREG0_0 /* I2C reg */ + +#ifndef __ASSEMBLY__ + +/* Address 0x400 to 0x1000 ualias points to cache error eframe + misc + * CACHE_ERR_SP_PTR could either contain an address to the stack, or + * the stack could start at CACHE_ERR_SP_PTR + */ +#if defined(HUB_ERR_STS_WAR) +#define CACHE_ERR_EFRAME 0x480 +#else /* HUB_ERR_STS_WAR */ +#define CACHE_ERR_EFRAME 0x400 +#endif /* HUB_ERR_STS_WAR */ + +#define CACHE_ERR_ECCFRAME (CACHE_ERR_EFRAME + EF_SIZE) +#define CACHE_ERR_SP_PTR (0x1000 - 32) /* why -32? TBD */ +#define CACHE_ERR_IBASE_PTR (0x1000 - 40) +#define CACHE_ERR_SP (CACHE_ERR_SP_PTR - 16) +#define CACHE_ERR_AREA_SIZE (ARCS_SPB_OFFSET - CACHE_ERR_EFRAME) + +#endif /* !__ASSEMBLY__ */ + +#define _ARCSPROM + +#if defined(HUB_ERR_STS_WAR) + +#define ERR_STS_WAR_REGISTER IIO_IIBUSERR +#define ERR_STS_WAR_ADDR LOCAL_HUB_ADDR(IIO_IIBUSERR) +#define ERR_STS_WAR_PHYSADDR TO_PHYS((__psunsigned_t)ERR_STS_WAR_ADDR) + /* Used to match addr in error reg. */ +#define OLD_ERR_STS_WAR_OFFSET ((MD_MEM_BANKS * MD_BANK_SIZE) - 0x100) + +#endif /* HUB_ERR_STS_WAR */ + +#endif /* _ASM_SN_SN0_ADDRS_H */ diff --git a/arch/mips/include/asm/sn/sn0/arch.h b/arch/mips/include/asm/sn/sn0/arch.h new file mode 100644 index 00000000000..f734f2007f2 --- /dev/null +++ b/arch/mips/include/asm/sn/sn0/arch.h @@ -0,0 +1,72 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SGI IP27 specific setup. + * + * Copyright (C) 1995 - 1997, 1999 Silcon Graphics, Inc. + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + */ +#ifndef _ASM_SN_SN0_ARCH_H +#define _ASM_SN_SN0_ARCH_H + + +#ifndef SN0XXL /* 128 cpu SMP max */ +/* + * This is the maximum number of nodes that can be part of a kernel. + * Effectively, it's the maximum number of compact node ids (cnodeid_t). + */ +#define MAX_COMPACT_NODES 64 + +/* + * MAXCPUS refers to the maximum number of CPUs in a single kernel. + * This is not necessarily the same as MAXNODES * CPUS_PER_NODE + */ +#define MAXCPUS 128 + +#else /* SN0XXL system */ + +#define MAX_COMPACT_NODES 128 +#define MAXCPUS 256 + +#endif /* SN0XXL */ + +/* + * This is the maximum number of NASIDS that can be present in a system. + * (Highest NASID plus one.) + */ +#define MAX_NASIDS 256 + +/* + * MAX_REGIONS refers to the maximum number of hardware partitioned regions. + */ +#define MAX_REGIONS 64 +#define MAX_NONPREMIUM_REGIONS 16 +#define MAX_PREMIUM_REGIONS MAX_REGIONS + +/* + * MAX_PARITIONS refers to the maximum number of logically defined + * partitions the system can support. + */ +#define MAX_PARTITIONS MAX_REGIONS + +#define NASID_MASK_BYTES ((MAX_NASIDS + 7) / 8) + +/* + * Slot constants for SN0 + */ +#ifdef CONFIG_SGI_SN_N_MODE +#define MAX_MEM_SLOTS 16 /* max slots per node */ +#else /* !CONFIG_SGI_SN_N_MODE, assume CONFIG_SGI_SN_M_MODE */ +#define MAX_MEM_SLOTS 32 /* max slots per node */ +#endif /* CONFIG_SGI_SN_M_MODE */ + +#define SLOT_SHIFT (27) +#define SLOT_MIN_MEM_SIZE (32*1024*1024) + +#define CPUS_PER_NODE 2 /* CPUs on a single hub */ +#define CPUS_PER_NODE_SHFT 1 /* Bits to shift in the node number */ +#define CPUS_PER_SUBNODE 2 /* CPUs on a single hub PI */ + +#endif /* _ASM_SN_SN0_ARCH_H */ diff --git a/arch/mips/include/asm/sn/sn0/hub.h b/arch/mips/include/asm/sn/sn0/hub.h new file mode 100644 index 00000000000..3e228f8e796 --- /dev/null +++ b/arch/mips/include/asm/sn/sn0/hub.h @@ -0,0 +1,40 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. + * Copyright (C) 1999 by Ralf Baechle + */ +#ifndef _ASM_SN_SN0_HUB_H +#define _ASM_SN_SN0_HUB_H + +/* The secret password; used to release protection */ +#define HUB_PASSWORD 0x53474972756c6573ull + +#define CHIPID_HUB 0 +#define CHIPID_ROUTER 1 + +#define HUB_REV_1_0 1 +#define HUB_REV_2_0 2 +#define HUB_REV_2_1 3 +#define HUB_REV_2_2 4 +#define HUB_REV_2_3 5 +#define HUB_REV_2_4 6 + +#define MAX_HUB_PATH 80 + +#include +#include +#include +#include +#include +//#include + +/* Translation of uncached attributes */ +#define UATTR_HSPEC 0 +#define UATTR_IO 1 +#define UATTR_MSPEC 2 +#define UATTR_UNCAC 3 + +#endif /* _ASM_SN_SN0_HUB_H */ diff --git a/arch/mips/include/asm/sn/sn0/hubio.h b/arch/mips/include/asm/sn/sn0/hubio.h new file mode 100644 index 00000000000..d0c29d4de08 --- /dev/null +++ b/arch/mips/include/asm/sn/sn0/hubio.h @@ -0,0 +1,972 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX , Revision 1.80. + * + * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. + * Copyright (C) 1999 by Ralf Baechle + */ +#ifndef _ASM_SGI_SN_SN0_HUBIO_H +#define _ASM_SGI_SN_SN0_HUBIO_H + +/* + * Hub I/O interface registers + * + * All registers in this file are subject to change until Hub chip tapeout. + * In general, the longer software name should be used when available. + */ + +/* + * Slightly friendlier names for some common registers. + * The hardware definitions follow. + */ +#define IIO_WIDGET IIO_WID /* Widget identification */ +#define IIO_WIDGET_STAT IIO_WSTAT /* Widget status register */ +#define IIO_WIDGET_CTRL IIO_WCR /* Widget control register */ +#define IIO_WIDGET_TOUT IIO_WRTO /* Widget request timeout */ +#define IIO_WIDGET_FLUSH IIO_WTFR /* Widget target flush */ +#define IIO_PROTECT IIO_ILAPR /* IO interface protection */ +#define IIO_PROTECT_OVRRD IIO_ILAPO /* IO protect override */ +#define IIO_OUTWIDGET_ACCESS IIO_IOWA /* Outbound widget access */ +#define IIO_INWIDGET_ACCESS IIO_IIWA /* Inbound widget access */ +#define IIO_INDEV_ERR_MASK IIO_IIDEM /* Inbound device error mask */ +#define IIO_LLP_CSR IIO_ILCSR /* LLP control and status */ +#define IIO_LLP_LOG IIO_ILLR /* LLP log */ +#define IIO_XTALKCC_TOUT IIO_IXCC /* Xtalk credit count timeout*/ +#define IIO_XTALKTT_TOUT IIO_IXTT /* Xtalk tail timeout */ +#define IIO_IO_ERR_CLR IIO_IECLR /* IO error clear */ +#define IIO_BTE_CRB_CNT IIO_IBCN /* IO BTE CRB count */ + +#define IIO_LLP_CSR_IS_UP 0x00002000 +#define IIO_LLP_CSR_LLP_STAT_MASK 0x00003000 +#define IIO_LLP_CSR_LLP_STAT_SHFT 12 + +/* key to IIO_PROTECT_OVRRD */ +#define IIO_PROTECT_OVRRD_KEY 0x53474972756c6573ull /* "SGIrules" */ + +/* BTE register names */ +#define IIO_BTE_STAT_0 IIO_IBLS_0 /* Also BTE length/status 0 */ +#define IIO_BTE_SRC_0 IIO_IBSA_0 /* Also BTE source address 0 */ +#define IIO_BTE_DEST_0 IIO_IBDA_0 /* Also BTE dest. address 0 */ +#define IIO_BTE_CTRL_0 IIO_IBCT_0 /* Also BTE control/terminate 0 */ +#define IIO_BTE_NOTIFY_0 IIO_IBNA_0 /* Also BTE notification 0 */ +#define IIO_BTE_INT_0 IIO_IBIA_0 /* Also BTE interrupt 0 */ +#define IIO_BTE_OFF_0 0 /* Base offset from BTE 0 regs. */ +#define IIO_BTE_OFF_1 IIO_IBLS_1 - IIO_IBLS_0 /* Offset from base to BTE 1 */ + +/* BTE register offsets from base */ +#define BTEOFF_STAT 0 +#define BTEOFF_SRC (IIO_BTE_SRC_0 - IIO_BTE_STAT_0) +#define BTEOFF_DEST (IIO_BTE_DEST_0 - IIO_BTE_STAT_0) +#define BTEOFF_CTRL (IIO_BTE_CTRL_0 - IIO_BTE_STAT_0) +#define BTEOFF_NOTIFY (IIO_BTE_NOTIFY_0 - IIO_BTE_STAT_0) +#define BTEOFF_INT (IIO_BTE_INT_0 - IIO_BTE_STAT_0) + + +/* + * The following definitions use the names defined in the IO interface + * document for ease of reference. When possible, software should + * generally use the longer but clearer names defined above. + */ + +#define IIO_BASE 0x400000 +#define IIO_BASE_BTE0 0x410000 +#define IIO_BASE_BTE1 0x420000 +#define IIO_BASE_PERF 0x430000 +#define IIO_PERF_CNT 0x430008 + +#define IO_PERF_SETS 32 + +#define IIO_WID 0x400000 /* Widget identification */ +#define IIO_WSTAT 0x400008 /* Widget status */ +#define IIO_WCR 0x400020 /* Widget control */ + +#define IIO_WSTAT_ECRAZY (1ULL << 32) /* Hub gone crazy */ +#define IIO_WSTAT_TXRETRY (1ULL << 9) /* Hub Tx Retry timeout */ +#define IIO_WSTAT_TXRETRY_MASK (0x7F) +#define IIO_WSTAT_TXRETRY_SHFT (16) +#define IIO_WSTAT_TXRETRY_CNT(w) (((w) >> IIO_WSTAT_TXRETRY_SHFT) & \ + IIO_WSTAT_TXRETRY_MASK) + +#define IIO_ILAPR 0x400100 /* Local Access Protection */ +#define IIO_ILAPO 0x400108 /* Protection override */ +#define IIO_IOWA 0x400110 /* outbound widget access */ +#define IIO_IIWA 0x400118 /* inbound widget access */ +#define IIO_IIDEM 0x400120 /* Inbound Device Error Mask */ +#define IIO_ILCSR 0x400128 /* LLP control and status */ +#define IIO_ILLR 0x400130 /* LLP Log */ +#define IIO_IIDSR 0x400138 /* Interrupt destination */ + +#define IIO_IIBUSERR 0x1400208 /* Reads here cause a bus error. */ + +/* IO Interrupt Destination Register */ +#define IIO_IIDSR_SENT_SHIFT 28 +#define IIO_IIDSR_SENT_MASK 0x10000000 +#define IIO_IIDSR_ENB_SHIFT 24 +#define IIO_IIDSR_ENB_MASK 0x01000000 +#define IIO_IIDSR_NODE_SHIFT 8 +#define IIO_IIDSR_NODE_MASK 0x0000ff00 +#define IIO_IIDSR_LVL_SHIFT 0 +#define IIO_IIDSR_LVL_MASK 0x0000003f + + +/* GFX Flow Control Node/Widget Register */ +#define IIO_IGFX_0 0x400140 /* gfx node/widget register 0 */ +#define IIO_IGFX_1 0x400148 /* gfx node/widget register 1 */ +#define IIO_IGFX_W_NUM_BITS 4 /* size of widget num field */ +#define IIO_IGFX_W_NUM_MASK ((1<, revision 1.59. + * + * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. + * Copyright (C) 1999 by Ralf Baechle + */ +#ifndef _ASM_SN_SN0_HUBMD_H +#define _ASM_SN_SN0_HUBMD_H + + +/* + * Hub Memory/Directory interface registers + */ +#define CACHE_SLINE_SIZE 128 /* Secondary cache line size on SN0 */ + +#define MAX_REGIONS 64 + +/* Hardware page size and shift */ + +#define MD_PAGE_SIZE 4096 /* Page size in bytes */ +#define MD_PAGE_NUM_SHFT 12 /* Address to page number shift */ + +/* Register offsets from LOCAL_HUB or REMOTE_HUB */ + +#define MD_BASE 0x200000 +#define MD_BASE_PERF 0x210000 +#define MD_BASE_JUNK 0x220000 + +#define MD_IO_PROTECT 0x200000 /* MD and core register protection */ +#define MD_IO_PROT_OVRRD 0x200008 /* Clear my bit in MD_IO_PROTECT */ +#define MD_HSPEC_PROTECT 0x200010 /* BDDIR, LBOOT, RBOOT protection */ +#define MD_MEMORY_CONFIG 0x200018 /* Memory/Directory DIMM control */ +#define MD_REFRESH_CONTROL 0x200020 /* Memory/Directory refresh ctrl */ +#define MD_FANDOP_CAC_STAT 0x200028 /* Fetch-and-op cache status */ +#define MD_MIG_DIFF_THRESH 0x200030 /* Page migr. count diff thresh. */ +#define MD_MIG_VALUE_THRESH 0x200038 /* Page migr. count abs. thresh. */ +#define MD_MIG_CANDIDATE 0x200040 /* Latest page migration candidate */ +#define MD_MIG_CANDIDATE_CLR 0x200048 /* Clear page migration candidate */ +#define MD_DIR_ERROR 0x200050 /* Directory DIMM error */ +#define MD_DIR_ERROR_CLR 0x200058 /* Directory DIMM error clear */ +#define MD_PROTOCOL_ERROR 0x200060 /* Directory protocol error */ +#define MD_PROTOCOL_ERROR_CLR 0x200068 /* Directory protocol error clear */ +#define MD_MEM_ERROR 0x200070 /* Memory DIMM error */ +#define MD_MEM_ERROR_CLR 0x200078 /* Memory DIMM error clear */ +#define MD_MISC_ERROR 0x200080 /* Miscellaneous MD error */ +#define MD_MISC_ERROR_CLR 0x200088 /* Miscellaneous MD error clear */ +#define MD_MEM_DIMM_INIT 0x200090 /* Memory DIMM mode initization. */ +#define MD_DIR_DIMM_INIT 0x200098 /* Directory DIMM mode init. */ +#define MD_MOQ_SIZE 0x2000a0 /* MD outgoing queue size */ +#define MD_MLAN_CTL 0x2000a8 /* NIC (Microlan) control register */ + +#define MD_PERF_SEL 0x210000 /* Select perf monitor events */ +#define MD_PERF_CNT0 0x210010 /* Performance counter 0 */ +#define MD_PERF_CNT1 0x210018 /* Performance counter 1 */ +#define MD_PERF_CNT2 0x210020 /* Performance counter 2 */ +#define MD_PERF_CNT3 0x210028 /* Performance counter 3 */ +#define MD_PERF_CNT4 0x210030 /* Performance counter 4 */ +#define MD_PERF_CNT5 0x210038 /* Performance counter 5 */ + +#define MD_UREG0_0 0x220000 /* uController/UART 0 register */ +#define MD_UREG0_1 0x220008 /* uController/UART 0 register */ +#define MD_UREG0_2 0x220010 /* uController/UART 0 register */ +#define MD_UREG0_3 0x220018 /* uController/UART 0 register */ +#define MD_UREG0_4 0x220020 /* uController/UART 0 register */ +#define MD_UREG0_5 0x220028 /* uController/UART 0 register */ +#define MD_UREG0_6 0x220030 /* uController/UART 0 register */ +#define MD_UREG0_7 0x220038 /* uController/UART 0 register */ + +#define MD_SLOTID_USTAT 0x220048 /* Hub slot ID & UART/uCtlr status */ +#define MD_LED0 0x220050 /* Eight-bit LED for CPU A */ +#define MD_LED1 0x220058 /* Eight-bit LED for CPU B */ + +#define MD_UREG1_0 0x220080 /* uController/UART 1 register */ +#define MD_UREG1_1 0x220088 /* uController/UART 1 register */ +#define MD_UREG1_2 0x220090 /* uController/UART 1 register */ +#define MD_UREG1_3 0x220098 /* uController/UART 1 register */ +#define MD_UREG1_4 0x2200a0 /* uController/UART 1 register */ +#define MD_UREG1_5 0x2200a8 /* uController/UART 1 register */ +#define MD_UREG1_6 0x2200b0 /* uController/UART 1 register */ +#define MD_UREG1_7 0x2200b8 /* uController/UART 1 register */ +#define MD_UREG1_8 0x2200c0 /* uController/UART 1 register */ +#define MD_UREG1_9 0x2200c8 /* uController/UART 1 register */ +#define MD_UREG1_10 0x2200d0 /* uController/UART 1 register */ +#define MD_UREG1_11 0x2200d8 /* uController/UART 1 register */ +#define MD_UREG1_12 0x2200e0 /* uController/UART 1 register */ +#define MD_UREG1_13 0x2200e8 /* uController/UART 1 register */ +#define MD_UREG1_14 0x2200f0 /* uController/UART 1 register */ +#define MD_UREG1_15 0x2200f8 /* uController/UART 1 register */ + +#ifdef CONFIG_SGI_SN_N_MODE +#define MD_MEM_BANKS 4 /* 4 banks of memory max in N mode */ +#else +#define MD_MEM_BANKS 8 /* 8 banks of memory max in M mode */ +#endif + +/* + * MD_MEMORY_CONFIG fields + * + * MD_SIZE_xxx are useful for representing the size of a SIMM or bank + * (SIMM pair). They correspond to the values needed for the bit + * triplets (MMC_BANK_MASK) in the MD_MEMORY_CONFIG register for bank size. + * Bits not used by the MD are used by software. + */ + +#define MD_SIZE_EMPTY 0 /* Valid in MEMORY_CONFIG */ +#define MD_SIZE_8MB 1 +#define MD_SIZE_16MB 2 +#define MD_SIZE_32MB 3 /* Broken in Hub 1 */ +#define MD_SIZE_64MB 4 /* Valid in MEMORY_CONFIG */ +#define MD_SIZE_128MB 5 /* Valid in MEMORY_CONFIG */ +#define MD_SIZE_256MB 6 +#define MD_SIZE_512MB 7 /* Valid in MEMORY_CONFIG */ +#define MD_SIZE_1GB 8 +#define MD_SIZE_2GB 9 +#define MD_SIZE_4GB 10 + +#define MD_SIZE_BYTES(size) ((size) == 0 ? 0 : 0x400000L << (size)) +#define MD_SIZE_MBYTES(size) ((size) == 0 ? 0 : 4 << (size)) + +#define MMC_FPROM_CYC_SHFT 49 /* Have to use UINT64_CAST, instead */ +#define MMC_FPROM_CYC_MASK (UINT64_CAST 31 << 49) /* of 'L' suffix, */ +#define MMC_FPROM_WR_SHFT 44 /* for assembler */ +#define MMC_FPROM_WR_MASK (UINT64_CAST 31 << 44) +#define MMC_UCTLR_CYC_SHFT 39 +#define MMC_UCTLR_CYC_MASK (UINT64_CAST 31 << 39) +#define MMC_UCTLR_WR_SHFT 34 +#define MMC_UCTLR_WR_MASK (UINT64_CAST 31 << 34) +#define MMC_DIMM0_SEL_SHFT 32 +#define MMC_DIMM0_SEL_MASK (UINT64_CAST 3 << 32) +#define MMC_IO_PROT_EN_SHFT 31 +#define MMC_IO_PROT_EN_MASK (UINT64_CAST 1 << 31) +#define MMC_IO_PROT (UINT64_CAST 1 << 31) +#define MMC_ARB_MLSS_SHFT 30 +#define MMC_ARB_MLSS_MASK (UINT64_CAST 1 << 30) +#define MMC_ARB_MLSS (UINT64_CAST 1 << 30) +#define MMC_IGNORE_ECC_SHFT 29 +#define MMC_IGNORE_ECC_MASK (UINT64_CAST 1 << 29) +#define MMC_IGNORE_ECC (UINT64_CAST 1 << 29) +#define MMC_DIR_PREMIUM_SHFT 28 +#define MMC_DIR_PREMIUM_MASK (UINT64_CAST 1 << 28) +#define MMC_DIR_PREMIUM (UINT64_CAST 1 << 28) +#define MMC_REPLY_GUAR_SHFT 24 +#define MMC_REPLY_GUAR_MASK (UINT64_CAST 15 << 24) +#define MMC_BANK_SHFT(_b) ((_b) * 3) +#define MMC_BANK_MASK(_b) (UINT64_CAST 7 << MMC_BANK_SHFT(_b)) +#define MMC_BANK_ALL_MASK 0xffffff +#define MMC_RESET_DEFAULTS (UINT64_CAST 0x0f << MMC_FPROM_CYC_SHFT | \ + UINT64_CAST 0x07 << MMC_FPROM_WR_SHFT | \ + UINT64_CAST 0x1f << MMC_UCTLR_CYC_SHFT | \ + UINT64_CAST 0x0f << MMC_UCTLR_WR_SHFT | \ + MMC_IGNORE_ECC | MMC_DIR_PREMIUM | \ + UINT64_CAST 0x0f << MMC_REPLY_GUAR_SHFT | \ + MMC_BANK_ALL_MASK) + +/* MD_REFRESH_CONTROL fields */ + +#define MRC_ENABLE_SHFT 63 +#define MRC_ENABLE_MASK (UINT64_CAST 1 << 63) +#define MRC_ENABLE (UINT64_CAST 1 << 63) +#define MRC_COUNTER_SHFT 12 +#define MRC_COUNTER_MASK (UINT64_CAST 0xfff << 12) +#define MRC_CNT_THRESH_MASK 0xfff +#define MRC_RESET_DEFAULTS (UINT64_CAST 0x400) + +/* MD_MEM_DIMM_INIT and MD_DIR_DIMM_INIT fields */ + +#define MDI_SELECT_SHFT 32 +#define MDI_SELECT_MASK (UINT64_CAST 0x0f << 32) +#define MDI_DIMM_MODE_MASK (UINT64_CAST 0xfff) + +/* MD_MOQ_SIZE fields */ + +#define MMS_RP_SIZE_SHFT 8 +#define MMS_RP_SIZE_MASK (UINT64_CAST 0x3f << 8) +#define MMS_RQ_SIZE_SHFT 0 +#define MMS_RQ_SIZE_MASK (UINT64_CAST 0x1f) +#define MMS_RESET_DEFAULTS (0x32 << 8 | 0x12) + +/* MD_FANDOP_CAC_STAT fields */ + +#define MFC_VALID_SHFT 63 +#define MFC_VALID_MASK (UINT64_CAST 1 << 63) +#define MFC_VALID (UINT64_CAST 1 << 63) +#define MFC_ADDR_SHFT 6 +#define MFC_ADDR_MASK (UINT64_CAST 0x3ffffff) + +/* MD_MLAN_CTL fields */ + +#define MLAN_PHI1_SHFT 27 +#define MLAN_PHI1_MASK (UINT64_CAST 0x7f << 27) +#define MLAN_PHI0_SHFT 20 +#define MLAN_PHI0_MASK (UINT64_CAST 0x7f << 27) +#define MLAN_PULSE_SHFT 10 +#define MLAN_PULSE_MASK (UINT64_CAST 0x3ff << 10) +#define MLAN_SAMPLE_SHFT 2 +#define MLAN_SAMPLE_MASK (UINT64_CAST 0xff << 2) +#define MLAN_DONE_SHFT 1 +#define MLAN_DONE_MASK 2 +#define MLAN_DONE (UINT64_CAST 0x02) +#define MLAN_RD_DATA (UINT64_CAST 0x01) +#define MLAN_RESET_DEFAULTS (UINT64_CAST 0x31 << MLAN_PHI1_SHFT | \ + UINT64_CAST 0x31 << MLAN_PHI0_SHFT) + +/* MD_SLOTID_USTAT bit definitions */ + +#define MSU_CORECLK_TST_SHFT 7 /* You don't wanna know */ +#define MSU_CORECLK_TST_MASK (UINT64_CAST 1 << 7) +#define MSU_CORECLK_TST (UINT64_CAST 1 << 7) +#define MSU_CORECLK_SHFT 6 /* You don't wanna know */ +#define MSU_CORECLK_MASK (UINT64_CAST 1 << 6) +#define MSU_CORECLK (UINT64_CAST 1 << 6) +#define MSU_NETSYNC_SHFT 5 /* You don't wanna know */ +#define MSU_NETSYNC_MASK (UINT64_CAST 1 << 5) +#define MSU_NETSYNC (UINT64_CAST 1 << 5) +#define MSU_FPROMRDY_SHFT 4 /* Flash PROM ready bit */ +#define MSU_FPROMRDY_MASK (UINT64_CAST 1 << 4) +#define MSU_FPROMRDY (UINT64_CAST 1 << 4) +#define MSU_I2CINTR_SHFT 3 /* I2C interrupt bit */ +#define MSU_I2CINTR_MASK (UINT64_CAST 1 << 3) +#define MSU_I2CINTR (UINT64_CAST 1 << 3) +#define MSU_SLOTID_MASK 0xff +#define MSU_SN0_SLOTID_SHFT 0 /* Slot ID */ +#define MSU_SN0_SLOTID_MASK (UINT64_CAST 7) +#define MSU_SN00_SLOTID_SHFT 7 +#define MSU_SN00_SLOTID_MASK (UINT64_CAST 0x80) + +#define MSU_PIMM_PSC_SHFT 4 +#define MSU_PIMM_PSC_MASK (0xf << MSU_PIMM_PSC_SHFT) + +/* MD_MIG_DIFF_THRESH bit definitions */ + +#define MD_MIG_DIFF_THRES_VALID_MASK (UINT64_CAST 0x1 << 63) +#define MD_MIG_DIFF_THRES_VALID_SHFT 63 +#define MD_MIG_DIFF_THRES_VALUE_MASK (UINT64_CAST 0xfffff) + +/* MD_MIG_VALUE_THRESH bit definitions */ + +#define MD_MIG_VALUE_THRES_VALID_MASK (UINT64_CAST 0x1 << 63) +#define MD_MIG_VALUE_THRES_VALID_SHFT 63 +#define MD_MIG_VALUE_THRES_VALUE_MASK (UINT64_CAST 0xfffff) + +/* MD_MIG_CANDIDATE bit definitions */ + +#define MD_MIG_CANDIDATE_VALID_MASK (UINT64_CAST 0x1 << 63) +#define MD_MIG_CANDIDATE_VALID_SHFT 63 +#define MD_MIG_CANDIDATE_TYPE_MASK (UINT64_CAST 0x1 << 30) +#define MD_MIG_CANDIDATE_TYPE_SHFT 30 +#define MD_MIG_CANDIDATE_OVERRUN_MASK (UINT64_CAST 0x1 << 29) +#define MD_MIG_CANDIDATE_OVERRUN_SHFT 29 +#define MD_MIG_CANDIDATE_INITIATOR_MASK (UINT64_CAST 0x7ff << 18) +#define MD_MIG_CANDIDATE_INITIATOR_SHFT 18 +#define MD_MIG_CANDIDATE_NODEID_MASK (UINT64_CAST 0x1ff << 20) +#define MD_MIG_CANDIDATE_NODEID_SHFT 20 +#define MD_MIG_CANDIDATE_ADDR_MASK (UINT64_CAST 0x3ffff) +#define MD_MIG_CANDIDATE_ADDR_SHFT 14 /* The address starts at bit 14 */ + +/* Other MD definitions */ + +#define MD_BANK_SHFT 29 /* log2(512 MB) */ +#define MD_BANK_MASK (UINT64_CAST 7 << 29) +#define MD_BANK_SIZE (UINT64_CAST 1 << MD_BANK_SHFT) /* 512 MB */ +#define MD_BANK_OFFSET(_b) (UINT64_CAST (_b) << MD_BANK_SHFT) + +/* + * The following definitions cover the bit field definitions for the + * various MD registers. For multi-bit registers, we define both + * a shift amount and a mask value. By convention, if you want to + * isolate a field, you should mask the field and then shift it down, + * since this makes the masks useful without a shift. + */ + +/* Directory entry states for both premium and standard SIMMs. */ + +#define MD_DIR_SHARED (UINT64_CAST 0x0) /* 000 */ +#define MD_DIR_POISONED (UINT64_CAST 0x1) /* 001 */ +#define MD_DIR_EXCLUSIVE (UINT64_CAST 0x2) /* 010 */ +#define MD_DIR_BUSY_SHARED (UINT64_CAST 0x3) /* 011 */ +#define MD_DIR_BUSY_EXCL (UINT64_CAST 0x4) /* 100 */ +#define MD_DIR_WAIT (UINT64_CAST 0x5) /* 101 */ +#define MD_DIR_UNOWNED (UINT64_CAST 0x7) /* 111 */ + +/* + * The MD_DIR_FORCE_ECC bit can be added directory entry write data + * to forcing the ECC to be written as-is instead of recalculated. + */ + +#define MD_DIR_FORCE_ECC (UINT64_CAST 1 << 63) + +/* + * Premium SIMM directory entry shifts and masks. Each is valid only in the + * context(s) indicated, where A, B, and C indicate the directory entry format + * as shown, and low and/or high indicates which double-word of the entry. + * + * Format A: STATE = shared, FINE = 1 + * Format B: STATE = shared, FINE = 0 + * Format C: STATE != shared (FINE must be 0) + */ + +#define MD_PDIR_MASK 0xffffffffffff /* Whole entry */ +#define MD_PDIR_ECC_SHFT 0 /* ABC low or high */ +#define MD_PDIR_ECC_MASK 0x7f +#define MD_PDIR_PRIO_SHFT 8 /* ABC low */ +#define MD_PDIR_PRIO_MASK (0xf << 8) +#define MD_PDIR_AX_SHFT 7 /* ABC low */ +#define MD_PDIR_AX_MASK (1 << 7) +#define MD_PDIR_AX (1 << 7) +#define MD_PDIR_FINE_SHFT 12 /* ABC low */ +#define MD_PDIR_FINE_MASK (1 << 12) +#define MD_PDIR_FINE (1 << 12) +#define MD_PDIR_OCT_SHFT 13 /* A low */ +#define MD_PDIR_OCT_MASK (7 << 13) +#define MD_PDIR_STATE_SHFT 13 /* BC low */ +#define MD_PDIR_STATE_MASK (7 << 13) +#define MD_PDIR_ONECNT_SHFT 16 /* BC low */ +#define MD_PDIR_ONECNT_MASK (0x3f << 16) +#define MD_PDIR_PTR_SHFT 22 /* C low */ +#define MD_PDIR_PTR_MASK (UINT64_CAST 0x7ff << 22) +#define MD_PDIR_VECMSB_SHFT 22 /* AB low */ +#define MD_PDIR_VECMSB_BITMASK 0x3ffffff +#define MD_PDIR_VECMSB_BITSHFT 27 +#define MD_PDIR_VECMSB_MASK (UINT64_CAST MD_PDIR_VECMSB_BITMASK << 22) +#define MD_PDIR_CWOFF_SHFT 7 /* C high */ +#define MD_PDIR_CWOFF_MASK (7 << 7) +#define MD_PDIR_VECLSB_SHFT 10 /* AB high */ +#define MD_PDIR_VECLSB_BITMASK (UINT64_CAST 0x3fffffffff) +#define MD_PDIR_VECLSB_BITSHFT 0 +#define MD_PDIR_VECLSB_MASK (MD_PDIR_VECLSB_BITMASK << 10) + +/* + * Directory initialization values + */ + +#define MD_PDIR_INIT_LO (MD_DIR_UNOWNED << MD_PDIR_STATE_SHFT | \ + MD_PDIR_AX) +#define MD_PDIR_INIT_HI 0 +#define MD_PDIR_INIT_PROT (MD_PROT_RW << MD_PPROT_IO_SHFT | \ + MD_PROT_RW << MD_PPROT_SHFT) + +/* + * Standard SIMM directory entry shifts and masks. Each is valid only in the + * context(s) indicated, where A and C indicate the directory entry format + * as shown, and low and/or high indicates which double-word of the entry. + * + * Format A: STATE == shared + * Format C: STATE != shared + */ + +#define MD_SDIR_MASK 0xffff /* Whole entry */ +#define MD_SDIR_ECC_SHFT 0 /* AC low or high */ +#define MD_SDIR_ECC_MASK 0x1f +#define MD_SDIR_PRIO_SHFT 6 /* AC low */ +#define MD_SDIR_PRIO_MASK (1 << 6) +#define MD_SDIR_AX_SHFT 5 /* AC low */ +#define MD_SDIR_AX_MASK (1 << 5) +#define MD_SDIR_AX (1 << 5) +#define MD_SDIR_STATE_SHFT 7 /* AC low */ +#define MD_SDIR_STATE_MASK (7 << 7) +#define MD_SDIR_PTR_SHFT 10 /* C low */ +#define MD_SDIR_PTR_MASK (0x3f << 10) +#define MD_SDIR_CWOFF_SHFT 5 /* C high */ +#define MD_SDIR_CWOFF_MASK (7 << 5) +#define MD_SDIR_VECMSB_SHFT 11 /* A low */ +#define MD_SDIR_VECMSB_BITMASK 0x1f +#define MD_SDIR_VECMSB_BITSHFT 7 +#define MD_SDIR_VECMSB_MASK (MD_SDIR_VECMSB_BITMASK << 11) +#define MD_SDIR_VECLSB_SHFT 5 /* A high */ +#define MD_SDIR_VECLSB_BITMASK 0x7ff +#define MD_SDIR_VECLSB_BITSHFT 0 +#define MD_SDIR_VECLSB_MASK (MD_SDIR_VECLSB_BITMASK << 5) + +/* + * Directory initialization values + */ + +#define MD_SDIR_INIT_LO (MD_DIR_UNOWNED << MD_SDIR_STATE_SHFT | \ + MD_SDIR_AX) +#define MD_SDIR_INIT_HI 0 +#define MD_SDIR_INIT_PROT (MD_PROT_RW << MD_SPROT_SHFT) + +/* Protection and migration field values */ + +#define MD_PROT_RW (UINT64_CAST 0x6) +#define MD_PROT_RO (UINT64_CAST 0x3) +#define MD_PROT_NO (UINT64_CAST 0x0) +#define MD_PROT_BAD (UINT64_CAST 0x5) + +/* Premium SIMM protection entry shifts and masks. */ + +#define MD_PPROT_SHFT 0 /* Prot. field */ +#define MD_PPROT_MASK 7 +#define MD_PPROT_MIGMD_SHFT 3 /* Migration mode */ +#define MD_PPROT_MIGMD_MASK (3 << 3) +#define MD_PPROT_REFCNT_SHFT 5 /* Reference count */ +#define MD_PPROT_REFCNT_WIDTH 0x7ffff +#define MD_PPROT_REFCNT_MASK (MD_PPROT_REFCNT_WIDTH << 5) + +#define MD_PPROT_IO_SHFT 45 /* I/O Prot field */ +#define MD_PPROT_IO_MASK (UINT64_CAST 7 << 45) + +/* Standard SIMM protection entry shifts and masks. */ + +#define MD_SPROT_SHFT 0 /* Prot. field */ +#define MD_SPROT_MASK 7 +#define MD_SPROT_MIGMD_SHFT 3 /* Migration mode */ +#define MD_SPROT_MIGMD_MASK (3 << 3) +#define MD_SPROT_REFCNT_SHFT 5 /* Reference count */ +#define MD_SPROT_REFCNT_WIDTH 0x7ff +#define MD_SPROT_REFCNT_MASK (MD_SPROT_REFCNT_WIDTH << 5) + +/* Migration modes used in protection entries */ + +#define MD_PROT_MIGMD_IREL (UINT64_CAST 0x3 << 3) +#define MD_PROT_MIGMD_IABS (UINT64_CAST 0x2 << 3) +#define MD_PROT_MIGMD_PREL (UINT64_CAST 0x1 << 3) +#define MD_PROT_MIGMD_OFF (UINT64_CAST 0x0 << 3) + + +/* + * Operations on page migration threshold register + */ + +#ifndef __ASSEMBLY__ + +/* + * LED register macros + */ + +#define CPU_LED_ADDR(_nasid, _slice) \ + (private.p_sn00 ? \ + REMOTE_HUB_ADDR((_nasid), MD_UREG1_0 + ((_slice) << 5)) : \ + REMOTE_HUB_ADDR((_nasid), MD_LED0 + ((_slice) << 3))) + +#define SET_CPU_LEDS(_nasid, _slice, _val) \ + (HUB_S(CPU_LED_ADDR(_nasid, _slice), (_val))) + +#define SET_MY_LEDS(_v) \ + SET_CPU_LEDS(get_nasid(), get_slice(), (_v)) + +/* + * Operations on Memory/Directory DIMM control register + */ + +#define DIRTYPE_PREMIUM 1 +#define DIRTYPE_STANDARD 0 +#define MD_MEMORY_CONFIG_DIR_TYPE_GET(region) (\ + (REMOTE_HUB_L(region, MD_MEMORY_CONFIG) & MMC_DIR_PREMIUM_MASK) >> \ + MMC_DIR_PREMIUM_SHFT) + + +/* + * Operations on page migration count difference and absolute threshold + * registers + */ + +#define MD_MIG_DIFF_THRESH_GET(region) ( \ + REMOTE_HUB_L((region), MD_MIG_DIFF_THRESH) & \ + MD_MIG_DIFF_THRES_VALUE_MASK) + +#define MD_MIG_DIFF_THRESH_SET(region, value) ( \ + REMOTE_HUB_S((region), MD_MIG_DIFF_THRESH, \ + MD_MIG_DIFF_THRES_VALID_MASK | (value))) + +#define MD_MIG_DIFF_THRESH_DISABLE(region) ( \ + REMOTE_HUB_S((region), MD_MIG_DIFF_THRESH, \ + REMOTE_HUB_L((region), MD_MIG_DIFF_THRESH) \ + & ~MD_MIG_DIFF_THRES_VALID_MASK)) + +#define MD_MIG_DIFF_THRESH_ENABLE(region) ( \ + REMOTE_HUB_S((region), MD_MIG_DIFF_THRESH, \ + REMOTE_HUB_L((region), MD_MIG_DIFF_THRESH) \ + | MD_MIG_DIFF_THRES_VALID_MASK)) + +#define MD_MIG_DIFF_THRESH_IS_ENABLED(region) ( \ + REMOTE_HUB_L((region), MD_MIG_DIFF_THRESH) & \ + MD_MIG_DIFF_THRES_VALID_MASK) + +#define MD_MIG_VALUE_THRESH_GET(region) ( \ + REMOTE_HUB_L((region), MD_MIG_VALUE_THRESH) & \ + MD_MIG_VALUE_THRES_VALUE_MASK) + +#define MD_MIG_VALUE_THRESH_SET(region, value) ( \ + REMOTE_HUB_S((region), MD_MIG_VALUE_THRESH, \ + MD_MIG_VALUE_THRES_VALID_MASK | (value))) + +#define MD_MIG_VALUE_THRESH_DISABLE(region) ( \ + REMOTE_HUB_S((region), MD_MIG_VALUE_THRESH, \ + REMOTE_HUB_L(region, MD_MIG_VALUE_THRESH) \ + & ~MD_MIG_VALUE_THRES_VALID_MASK)) + +#define MD_MIG_VALUE_THRESH_ENABLE(region) ( \ + REMOTE_HUB_S((region), MD_MIG_VALUE_THRESH, \ + REMOTE_HUB_L((region), MD_MIG_VALUE_THRESH) \ + | MD_MIG_VALUE_THRES_VALID_MASK)) + +#define MD_MIG_VALUE_THRESH_IS_ENABLED(region) ( \ + REMOTE_HUB_L((region), MD_MIG_VALUE_THRESH) & \ + MD_MIG_VALUE_THRES_VALID_MASK) + +/* + * Operations on page migration candidate register + */ + +#define MD_MIG_CANDIDATE_GET(my_region_id) ( \ + REMOTE_HUB_L((my_region_id), MD_MIG_CANDIDATE_CLR)) + +#define MD_MIG_CANDIDATE_HWPFN(value) ((value) & MD_MIG_CANDIDATE_ADDR_MASK) + +#define MD_MIG_CANDIDATE_NODEID(value) ( \ + ((value) & MD_MIG_CANDIDATE_NODEID_MASK) >> MD_MIG_CANDIDATE_NODEID_SHFT) + +#define MD_MIG_CANDIDATE_TYPE(value) ( \ + ((value) & MD_MIG_CANDIDATE_TYPE_MASK) >> MD_MIG_CANDIDATE_TYPE_SHFT) + +#define MD_MIG_CANDIDATE_VALID(value) ( \ + ((value) & MD_MIG_CANDIDATE_VALID_MASK) >> MD_MIG_CANDIDATE_VALID_SHFT) + +/* + * Macros to retrieve fields in the protection entry + */ + +/* for Premium SIMM */ +#define MD_PPROT_REFCNT_GET(value) ( \ + ((value) & MD_PPROT_REFCNT_MASK) >> MD_PPROT_REFCNT_SHFT) + +#define MD_PPROT_MIGMD_GET(value) ( \ + ((value) & MD_PPROT_MIGMD_MASK) >> MD_PPROT_MIGMD_SHFT) + +/* for Standard SIMM */ +#define MD_SPROT_REFCNT_GET(value) ( \ + ((value) & MD_SPROT_REFCNT_MASK) >> MD_SPROT_REFCNT_SHFT) + +#define MD_SPROT_MIGMD_GET(value) ( \ + ((value) & MD_SPROT_MIGMD_MASK) >> MD_SPROT_MIGMD_SHFT) + +/* + * Format of dir_error, mem_error, protocol_error and misc_error registers + */ + +struct dir_error_reg { + u64 uce_vld: 1, /* 63: valid directory uce */ + ae_vld: 1, /* 62: valid dir prot ecc error */ + ce_vld: 1, /* 61: valid correctable ECC err*/ + rsvd1: 19, /* 60-42: reserved */ + bad_prot: 3, /* 41-39: encoding, bad access rights*/ + bad_syn: 7, /* 38-32: bad dir syndrome */ + rsvd2: 2, /* 31-30: reserved */ + hspec_addr:27, /* 29-03: bddir space bad entry */ + uce_ovr: 1, /* 2: multiple dir uce's */ + ae_ovr: 1, /* 1: multiple prot ecc errs*/ + ce_ovr: 1; /* 0: multiple correctable errs */ +}; + +typedef union md_dir_error { + u64 derr_reg; /* the entire register */ + struct dir_error_reg derr_fmt; /* the register format */ +} md_dir_error_t; + + +struct mem_error_reg { + u64 uce_vld: 1, /* 63: valid memory uce */ + ce_vld: 1, /* 62: valid correctable ECC err*/ + rsvd1: 22, /* 61-40: reserved */ + bad_syn: 8, /* 39-32: bad mem ecc syndrome */ + address: 29, /* 31-03: bad entry pointer */ + rsvd2: 1, /* 2: reserved */ + uce_ovr: 1, /* 1: multiple mem uce's */ + ce_ovr: 1; /* 0: multiple correctable errs */ +}; + + +typedef union md_mem_error { + u64 merr_reg; /* the entire register */ + struct mem_error_reg merr_fmt; /* format of the mem_error reg */ +} md_mem_error_t; + + +struct proto_error_reg { + u64 valid: 1, /* 63: valid protocol error */ + rsvd1: 2, /* 62-61: reserved */ + initiator:11, /* 60-50: id of request initiator*/ + backoff: 2, /* 49-48: backoff control */ + msg_type: 8, /* 47-40: type of request */ + access: 2, /* 39-38: access rights of initiator*/ + priority: 1, /* 37: priority level of requestor*/ + dir_state: 4, /* 36-33: state of directory */ + pointer_me:1, /* 32: initiator same as dir ptr */ + address: 29, /* 31-03: request address */ + rsvd2: 2, /* 02-01: reserved */ + overrun: 1; /* 0: multiple protocol errs */ +}; + +typedef union md_proto_error { + u64 perr_reg; /* the entire register */ + struct proto_error_reg perr_fmt; /* format of the register */ +} md_proto_error_t; + + +struct md_sdir_high_fmt { + unsigned short sd_hi_bvec : 11, + sd_hi_ecc : 5; +}; + + +typedef union md_sdir_high { + /* The 16 bits of standard directory, upper word */ + unsigned short sd_hi_val; + struct md_sdir_high_fmt sd_hi_fmt; +}md_sdir_high_t; + + +struct md_sdir_low_shared_fmt { + /* The meaning of lower directory, shared */ + unsigned short sds_lo_bvec : 5, + sds_lo_unused: 1, + sds_lo_state : 3, + sds_lo_prio : 1, + sds_lo_ax : 1, + sds_lo_ecc : 5; +}; + +struct md_sdir_low_exclusive_fmt { + /* The meaning of lower directory, exclusive */ + unsigned short sde_lo_ptr : 6, + sde_lo_state : 3, + sde_lo_prio : 1, + sde_lo_ax : 1, + sde_lo_ecc : 5; +}; + + +typedef union md_sdir_low { + /* The 16 bits of standard directory, lower word */ + unsigned short sd_lo_val; + struct md_sdir_low_exclusive_fmt sde_lo_fmt; + struct md_sdir_low_shared_fmt sds_lo_fmt; +}md_sdir_low_t; + + + +struct md_pdir_high_fmt { + u64 pd_hi_unused : 16, + pd_hi_bvec : 38, + pd_hi_unused1 : 3, + pd_hi_ecc : 7; +}; + + +typedef union md_pdir_high { + /* The 48 bits of standard directory, upper word */ + u64 pd_hi_val; + struct md_pdir_high_fmt pd_hi_fmt; +}md_pdir_high_t; + + +struct md_pdir_low_shared_fmt { + /* The meaning of lower directory, shared */ + u64 pds_lo_unused : 16, + pds_lo_bvec : 26, + pds_lo_cnt : 6, + pds_lo_state : 3, + pds_lo_ste : 1, + pds_lo_prio : 4, + pds_lo_ax : 1, + pds_lo_ecc : 7; +}; + +struct md_pdir_low_exclusive_fmt { + /* The meaning of lower directory, exclusive */ + u64 pde_lo_unused : 31, + pde_lo_ptr : 11, + pde_lo_unused1 : 6, + pde_lo_state : 3, + pde_lo_ste : 1, + pde_lo_prio : 4, + pde_lo_ax : 1, + pde_lo_ecc : 7; +}; + + +typedef union md_pdir_loent { + /* The 48 bits of premium directory, lower word */ + u64 pd_lo_val; + struct md_pdir_low_exclusive_fmt pde_lo_fmt; + struct md_pdir_low_shared_fmt pds_lo_fmt; +}md_pdir_low_t; + + +/* + * the following two "union" definitions and two + * "struct" definitions are used in vmdump.c to + * represent directory memory information. + */ + +typedef union md_dir_high { + md_sdir_high_t md_sdir_high; + md_pdir_high_t md_pdir_high; +} md_dir_high_t; + +typedef union md_dir_low { + md_sdir_low_t md_sdir_low; + md_pdir_low_t md_pdir_low; +} md_dir_low_t; + +typedef struct bddir_entry { + md_dir_low_t md_dir_low; + md_dir_high_t md_dir_high; +} bddir_entry_t; + +typedef struct dir_mem_entry { + u64 prcpf[MAX_REGIONS]; + bddir_entry_t directory_words[MD_PAGE_SIZE/CACHE_SLINE_SIZE]; +} dir_mem_entry_t; + + + +typedef union md_perf_sel { + u64 perf_sel_reg; + struct { + u64 perf_rsvd : 60, + perf_en : 1, + perf_sel : 3; + } perf_sel_bits; +} md_perf_sel_t; + +typedef union md_perf_cnt { + u64 perf_cnt; + struct { + u64 perf_rsvd : 44, + perf_cnt : 20; + } perf_cnt_bits; +} md_perf_cnt_t; + + +#endif /* !__ASSEMBLY__ */ + + +#define DIR_ERROR_VALID_MASK 0xe000000000000000 +#define DIR_ERROR_VALID_SHFT 61 +#define DIR_ERROR_VALID_UCE 0x8000000000000000 +#define DIR_ERROR_VALID_AE 0x4000000000000000 +#define DIR_ERROR_VALID_CE 0x2000000000000000 + +#define MEM_ERROR_VALID_MASK 0xc000000000000000 +#define MEM_ERROR_VALID_SHFT 62 +#define MEM_ERROR_VALID_UCE 0x8000000000000000 +#define MEM_ERROR_VALID_CE 0x4000000000000000 + +#define PROTO_ERROR_VALID_MASK 0x8000000000000000 + +#define MISC_ERROR_VALID_MASK 0x3ff + +/* + * Mask for hspec address that is stored in the dir error register. + * This represents bits 29 through 3. + */ +#define DIR_ERR_HSPEC_MASK 0x3ffffff8 +#define ERROR_HSPEC_MASK 0x3ffffff8 +#define ERROR_HSPEC_SHFT 3 +#define ERROR_ADDR_MASK 0xfffffff8 +#define ERROR_ADDR_SHFT 3 + +/* + * MD_MISC_ERROR register defines. + */ + +#define MMCE_VALID_MASK 0x3ff +#define MMCE_ILL_MSG_SHFT 8 +#define MMCE_ILL_MSG_MASK (UINT64_CAST 0x03 << MMCE_ILL_MSG_SHFT) +#define MMCE_ILL_REV_SHFT 6 +#define MMCE_ILL_REV_MASK (UINT64_CAST 0x03 << MMCE_ILL_REV_SHFT) +#define MMCE_LONG_PACK_SHFT 4 +#define MMCE_LONG_PACK_MASK (UINT64_CAST 0x03 << MMCE_lONG_PACK_SHFT) +#define MMCE_SHORT_PACK_SHFT 2 +#define MMCE_SHORT_PACK_MASK (UINT64_CAST 0x03 << MMCE_SHORT_PACK_SHFT) +#define MMCE_BAD_DATA_SHFT 0 +#define MMCE_BAD_DATA_MASK (UINT64_CAST 0x03 << MMCE_BAD_DATA_SHFT) + + +#define MD_PERF_COUNTERS 6 +#define MD_PERF_SETS 6 + +#define MEM_DIMM_MASK 0xe0000000 +#define MEM_DIMM_SHFT 29 + +#endif /* _ASM_SN_SN0_HUBMD_H */ diff --git a/arch/mips/include/asm/sn/sn0/hubni.h b/arch/mips/include/asm/sn/sn0/hubni.h new file mode 100644 index 00000000000..b40d3ef97a1 --- /dev/null +++ b/arch/mips/include/asm/sn/sn0/hubni.h @@ -0,0 +1,255 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX , Revision 1.27. + * + * Copyright (C) 1992-1997, 1999 Silicon Graphics, Inc. + * Copyright (C) 1999 by Ralf Baechle + */ +#ifndef _ASM_SGI_SN0_HUBNI_H +#define _ASM_SGI_SN0_HUBNI_H + +#ifndef __ASSEMBLY__ +#include +#endif + +/* + * Hub Network Interface registers + * + * All registers in this file are subject to change until Hub chip tapeout. + */ + +#define NI_BASE 0x600000 +#define NI_BASE_TABLES 0x630000 + +#define NI_STATUS_REV_ID 0x600000 /* Hub network status, rev, and ID */ +#define NI_PORT_RESET 0x600008 /* Reset the network interface */ +#define NI_PROTECTION 0x600010 /* NI register access permissions */ +#define NI_GLOBAL_PARMS 0x600018 /* LLP parameters */ +#define NI_SCRATCH_REG0 0x600100 /* Scratch register 0 (64 bits) */ +#define NI_SCRATCH_REG1 0x600108 /* Scratch register 1 (64 bits) */ +#define NI_DIAG_PARMS 0x600110 /* Parameters for diags */ + +#define NI_VECTOR_PARMS 0x600200 /* Vector PIO routing parameters */ +#define NI_VECTOR 0x600208 /* Vector PIO route */ +#define NI_VECTOR_DATA 0x600210 /* Vector PIO data */ +#define NI_VECTOR_STATUS 0x600300 /* Vector PIO return status */ +#define NI_RETURN_VECTOR 0x600308 /* Vector PIO return vector */ +#define NI_VECTOR_READ_DATA 0x600310 /* Vector PIO read data */ +#define NI_VECTOR_CLEAR 0x600380 /* Vector PIO read & clear status */ + +#define NI_IO_PROTECT 0x600400 /* PIO protection bits */ +#define NI_IO_PROT_OVRRD 0x600408 /* PIO protection bit override */ + +#define NI_AGE_CPU0_MEMORY 0x600500 /* CPU 0 memory age control */ +#define NI_AGE_CPU0_PIO 0x600508 /* CPU 0 PIO age control */ +#define NI_AGE_CPU1_MEMORY 0x600510 /* CPU 1 memory age control */ +#define NI_AGE_CPU1_PIO 0x600518 /* CPU 1 PIO age control */ +#define NI_AGE_GBR_MEMORY 0x600520 /* GBR memory age control */ +#define NI_AGE_GBR_PIO 0x600528 /* GBR PIO age control */ +#define NI_AGE_IO_MEMORY 0x600530 /* IO memory age control */ +#define NI_AGE_IO_PIO 0x600538 /* IO PIO age control */ +#define NI_AGE_REG_MIN NI_AGE_CPU0_MEMORY +#define NI_AGE_REG_MAX NI_AGE_IO_PIO + +#define NI_PORT_PARMS 0x608000 /* LLP Parameters */ +#define NI_PORT_ERROR 0x608008 /* LLP Errors */ +#define NI_PORT_ERROR_CLEAR 0x608088 /* Clear the error bits */ + +#define NI_META_TABLE0 0x638000 /* First meta routing table entry */ +#define NI_META_TABLE(_x) (NI_META_TABLE0 + (8 * (_x))) +#define NI_META_ENTRIES 32 + +#define NI_LOCAL_TABLE0 0x638100 /* First local routing table entry */ +#define NI_LOCAL_TABLE(_x) (NI_LOCAL_TABLE0 + (8 * (_x))) +#define NI_LOCAL_ENTRIES 16 + +/* + * NI_STATUS_REV_ID mask and shift definitions + * Have to use UINT64_CAST instead of 'L' suffix, for assembler. + */ + +#define NSRI_8BITMODE_SHFT 30 +#define NSRI_8BITMODE_MASK (UINT64_CAST 0x1 << 30) +#define NSRI_LINKUP_SHFT 29 +#define NSRI_LINKUP_MASK (UINT64_CAST 0x1 << 29) +#define NSRI_DOWNREASON_SHFT 28 /* 0=failed, 1=never came */ +#define NSRI_DOWNREASON_MASK (UINT64_CAST 0x1 << 28) /* out of reset. */ +#define NSRI_MORENODES_SHFT 18 +#define NSRI_MORENODES_MASK (UINT64_CAST 1 << 18) /* Max. # of nodes */ +#define MORE_MEMORY 0 +#define MORE_NODES 1 +#define NSRI_REGIONSIZE_SHFT 17 +#define NSRI_REGIONSIZE_MASK (UINT64_CAST 1 << 17) /* Granularity */ +#define REGIONSIZE_FINE 1 +#define REGIONSIZE_COARSE 0 +#define NSRI_NODEID_SHFT 8 +#define NSRI_NODEID_MASK (UINT64_CAST 0x1ff << 8)/* Node (Hub) ID */ +#define NSRI_REV_SHFT 4 +#define NSRI_REV_MASK (UINT64_CAST 0xf << 4) /* Chip Revision */ +#define NSRI_CHIPID_SHFT 0 +#define NSRI_CHIPID_MASK (UINT64_CAST 0xf) /* Chip type ID */ + +/* + * In fine mode, each node is a region. In coarse mode, there are + * eight nodes per region. + */ +#define NASID_TO_FINEREG_SHFT 0 +#define NASID_TO_COARSEREG_SHFT 3 + +/* NI_PORT_RESET mask definitions */ + +#define NPR_PORTRESET (UINT64_CAST 1 << 7) /* Send warm reset */ +#define NPR_LINKRESET (UINT64_CAST 1 << 1) /* Send link reset */ +#define NPR_LOCALRESET (UINT64_CAST 1) /* Reset entire hub */ + +/* NI_PROTECTION mask and shift definitions */ + +#define NPROT_RESETOK (UINT64_CAST 1) + +/* NI_GLOBAL_PARMS mask and shift definitions */ + +#define NGP_MAXRETRY_SHFT 48 /* Maximum retries */ +#define NGP_MAXRETRY_MASK (UINT64_CAST 0x3ff << 48) +#define NGP_TAILTOWRAP_SHFT 32 /* Tail timeout wrap */ +#define NGP_TAILTOWRAP_MASK (UINT64_CAST 0xffff << 32) + +#define NGP_CREDITTOVAL_SHFT 16 /* Tail timeout wrap */ +#define NGP_CREDITTOVAL_MASK (UINT64_CAST 0xf << 16) +#define NGP_TAILTOVAL_SHFT 4 /* Tail timeout value */ +#define NGP_TAILTOVAL_MASK (UINT64_CAST 0xf << 4) + +/* NI_DIAG_PARMS mask and shift definitions */ + +#define NDP_PORTTORESET (UINT64_CAST 1 << 18) /* Port tmout reset */ +#define NDP_LLP8BITMODE (UINT64_CAST 1 << 12) /* LLP 8-bit mode */ +#define NDP_PORTDISABLE (UINT64_CAST 1 << 6) /* Port disable */ +#define NDP_SENDERROR (UINT64_CAST 1) /* Send data error */ + +/* + * NI_VECTOR_PARMS mask and shift definitions. + * TYPE may be any of the first four PIOTYPEs defined under NI_VECTOR_STATUS. + */ + +#define NVP_PIOID_SHFT 40 +#define NVP_PIOID_MASK (UINT64_CAST 0x3ff << 40) +#define NVP_WRITEID_SHFT 32 +#define NVP_WRITEID_MASK (UINT64_CAST 0xff << 32) +#define NVP_ADDRESS_MASK (UINT64_CAST 0xffff8) /* Bits 19:3 */ +#define NVP_TYPE_SHFT 0 +#define NVP_TYPE_MASK (UINT64_CAST 0x3) + +/* NI_VECTOR_STATUS mask and shift definitions */ + +#define NVS_VALID (UINT64_CAST 1 << 63) +#define NVS_OVERRUN (UINT64_CAST 1 << 62) +#define NVS_TARGET_SHFT 51 +#define NVS_TARGET_MASK (UINT64_CAST 0x3ff << 51) +#define NVS_PIOID_SHFT 40 +#define NVS_PIOID_MASK (UINT64_CAST 0x3ff << 40) +#define NVS_WRITEID_SHFT 32 +#define NVS_WRITEID_MASK (UINT64_CAST 0xff << 32) +#define NVS_ADDRESS_MASK (UINT64_CAST 0xfffffff8) /* Bits 31:3 */ +#define NVS_TYPE_SHFT 0 +#define NVS_TYPE_MASK (UINT64_CAST 0x7) +#define NVS_ERROR_MASK (UINT64_CAST 0x4) /* bit set means error */ + + +#define PIOTYPE_READ 0 /* VECTOR_PARMS and VECTOR_STATUS */ +#define PIOTYPE_WRITE 1 /* VECTOR_PARMS and VECTOR_STATUS */ +#define PIOTYPE_UNDEFINED 2 /* VECTOR_PARMS and VECTOR_STATUS */ +#define PIOTYPE_EXCHANGE 3 /* VECTOR_PARMS and VECTOR_STATUS */ +#define PIOTYPE_ADDR_ERR 4 /* VECTOR_STATUS only */ +#define PIOTYPE_CMD_ERR 5 /* VECTOR_STATUS only */ +#define PIOTYPE_PROT_ERR 6 /* VECTOR_STATUS only */ +#define PIOTYPE_UNKNOWN 7 /* VECTOR_STATUS only */ + +/* NI_AGE_XXX mask and shift definitions */ + +#define NAGE_VCH_SHFT 10 +#define NAGE_VCH_MASK (UINT64_CAST 3 << 10) +#define NAGE_CC_SHFT 8 +#define NAGE_CC_MASK (UINT64_CAST 3 << 8) +#define NAGE_AGE_SHFT 0 +#define NAGE_AGE_MASK (UINT64_CAST 0xff) +#define NAGE_MASK (NAGE_VCH_MASK | NAGE_CC_MASK | NAGE_AGE_MASK) + +#define VCHANNEL_A 0 +#define VCHANNEL_B 1 +#define VCHANNEL_ANY 2 + +/* NI_PORT_PARMS mask and shift definitions */ + +#define NPP_NULLTO_SHFT 10 +#define NPP_NULLTO_MASK (UINT64_CAST 0x3f << 16) +#define NPP_MAXBURST_SHFT 0 +#define NPP_MAXBURST_MASK (UINT64_CAST 0x3ff) +#define NPP_RESET_DFLT_HUB20 ((UINT64_CAST 1 << NPP_NULLTO_SHFT) | \ + (UINT64_CAST 0x3f0 << NPP_MAXBURST_SHFT)) +#define NPP_RESET_DEFAULTS ((UINT64_CAST 6 << NPP_NULLTO_SHFT) | \ + (UINT64_CAST 0x3f0 << NPP_MAXBURST_SHFT)) + + +/* NI_PORT_ERROR mask and shift definitions */ + +#define NPE_LINKRESET (UINT64_CAST 1 << 37) +#define NPE_INTERNALERROR (UINT64_CAST 1 << 36) +#define NPE_BADMESSAGE (UINT64_CAST 1 << 35) +#define NPE_BADDEST (UINT64_CAST 1 << 34) +#define NPE_FIFOOVERFLOW (UINT64_CAST 1 << 33) +#define NPE_CREDITTO_SHFT 28 +#define NPE_CREDITTO_MASK (UINT64_CAST 0xf << 28) +#define NPE_TAILTO_SHFT 24 +#define NPE_TAILTO_MASK (UINT64_CAST 0xf << 24) +#define NPE_RETRYCOUNT_SHFT 16 +#define NPE_RETRYCOUNT_MASK (UINT64_CAST 0xff << 16) +#define NPE_CBERRCOUNT_SHFT 8 +#define NPE_CBERRCOUNT_MASK (UINT64_CAST 0xff << 8) +#define NPE_SNERRCOUNT_SHFT 0 +#define NPE_SNERRCOUNT_MASK (UINT64_CAST 0xff << 0) +#define NPE_MASK 0x3effffffff + +#define NPE_COUNT_MAX 0xff + +#define NPE_FATAL_ERRORS (NPE_LINKRESET | NPE_INTERNALERROR | \ + NPE_BADMESSAGE | NPE_BADDEST | \ + NPE_FIFOOVERFLOW | NPE_CREDITTO_MASK | \ + NPE_TAILTO_MASK) + +/* NI_META_TABLE mask and shift definitions */ + +#define NMT_EXIT_PORT_MASK (UINT64_CAST 0xf) + +/* NI_LOCAL_TABLE mask and shift definitions */ + +#define NLT_EXIT_PORT_MASK (UINT64_CAST 0xf) + +#ifndef __ASSEMBLY__ + +typedef union hubni_port_error_u { + u64 nipe_reg_value; + struct { + u64 nipe_rsvd: 26, /* unused */ + nipe_lnk_reset: 1, /* link reset */ + nipe_intl_err: 1, /* internal error */ + nipe_bad_msg: 1, /* bad message */ + nipe_bad_dest: 1, /* bad dest */ + nipe_fifo_ovfl: 1, /* fifo overflow */ + nipe_rsvd1: 1, /* unused */ + nipe_credit_to: 4, /* credit timeout */ + nipe_tail_to: 4, /* tail timeout */ + nipe_retry_cnt: 8, /* retry error count */ + nipe_cb_cnt: 8, /* checkbit error count */ + nipe_sn_cnt: 8; /* sequence number count */ + } nipe_fields_s; +} hubni_port_error_t; + +#define NI_LLP_RETRY_MAX 0xff +#define NI_LLP_CB_MAX 0xff +#define NI_LLP_SN_MAX 0xff + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_SGI_SN0_HUBNI_H */ diff --git a/arch/mips/include/asm/sn/sn0/hubpi.h b/arch/mips/include/asm/sn/sn0/hubpi.h new file mode 100644 index 00000000000..e39f5f9da04 --- /dev/null +++ b/arch/mips/include/asm/sn/sn0/hubpi.h @@ -0,0 +1,409 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX , revision 1.28. + * + * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. + * Copyright (C) 1999 by Ralf Baechle + */ +#ifndef _ASM_SN_SN0_HUBPI_H +#define _ASM_SN_SN0_HUBPI_H + +#include + +/* + * Hub I/O interface registers + * + * All registers in this file are subject to change until Hub chip tapeout. + * All register "addresses" are actually offsets. Use the LOCAL_HUB + * or REMOTE_HUB macros to synthesize an actual address + */ + +#define PI_BASE 0x000000 + +/* General protection and control registers */ + +#define PI_CPU_PROTECT 0x000000 /* CPU Protection */ +#define PI_PROT_OVERRD 0x000008 /* Clear CPU Protection bit */ +#define PI_IO_PROTECT 0x000010 /* Interrupt Pending Protection */ +#define PI_REGION_PRESENT 0x000018 /* Indicates whether region exists */ +#define PI_CPU_NUM 0x000020 /* CPU Number ID */ +#define PI_CALIAS_SIZE 0x000028 /* Cached Alias Size */ +#define PI_MAX_CRB_TIMEOUT 0x000030 /* Maximum Timeout for CRB */ +#define PI_CRB_SFACTOR 0x000038 /* Scale factor for CRB timeout */ + +/* CALIAS values */ +#define PI_CALIAS_SIZE_0 0 +#define PI_CALIAS_SIZE_4K 1 +#define PI_CALIAS_SIZE_8K 2 +#define PI_CALIAS_SIZE_16K 3 +#define PI_CALIAS_SIZE_32K 4 +#define PI_CALIAS_SIZE_64K 5 +#define PI_CALIAS_SIZE_128K 6 +#define PI_CALIAS_SIZE_256K 7 +#define PI_CALIAS_SIZE_512K 8 +#define PI_CALIAS_SIZE_1M 9 +#define PI_CALIAS_SIZE_2M 10 +#define PI_CALIAS_SIZE_4M 11 +#define PI_CALIAS_SIZE_8M 12 +#define PI_CALIAS_SIZE_16M 13 +#define PI_CALIAS_SIZE_32M 14 +#define PI_CALIAS_SIZE_64M 15 + +/* Processor control and status checking */ + +#define PI_CPU_PRESENT_A 0x000040 /* CPU Present A */ +#define PI_CPU_PRESENT_B 0x000048 /* CPU Present B */ +#define PI_CPU_ENABLE_A 0x000050 /* CPU Enable A */ +#define PI_CPU_ENABLE_B 0x000058 /* CPU Enable B */ +#define PI_REPLY_LEVEL 0x000060 /* Reply Level */ +#define PI_HARDRESET_BIT 0x020068 /* Bit cleared by s/w on SR */ +#define PI_NMI_A 0x000070 /* NMI to CPU A */ +#define PI_NMI_B 0x000078 /* NMI to CPU B */ +#define PI_NMI_OFFSET (PI_NMI_B - PI_NMI_A) +#define PI_SOFTRESET 0x000080 /* Softreset (to both CPUs) */ + +/* Regular Interrupt register checking. */ + +#define PI_INT_PEND_MOD 0x000090 /* Write to set pending ints */ +#define PI_INT_PEND0 0x000098 /* Read to get pending ints */ +#define PI_INT_PEND1 0x0000a0 /* Read to get pending ints */ +#define PI_INT_MASK0_A 0x0000a8 /* Interrupt Mask 0 for CPU A */ +#define PI_INT_MASK1_A 0x0000b0 /* Interrupt Mask 1 for CPU A */ +#define PI_INT_MASK0_B 0x0000b8 /* Interrupt Mask 0 for CPU B */ +#define PI_INT_MASK1_B 0x0000c0 /* Interrupt Mask 1 for CPU B */ + +#define PI_INT_MASK_OFFSET 0x10 /* Offset from A to B */ + +/* Crosscall interrupts */ + +#define PI_CC_PEND_SET_A 0x0000c8 /* CC Interrupt Pending Set, CPU A */ +#define PI_CC_PEND_SET_B 0x0000d0 /* CC Interrupt Pending Set, CPU B */ +#define PI_CC_PEND_CLR_A 0x0000d8 /* CC Interrupt Pending Clr, CPU A */ +#define PI_CC_PEND_CLR_B 0x0000e0 /* CC Interrupt Pending Clr, CPU B */ +#define PI_CC_MASK 0x0000e8 /* CC Interrupt mask */ + +#define PI_INT_SET_OFFSET 0x08 /* Offset from A to B */ + +/* Realtime Counter and Profiler control registers */ + +#define PI_RT_COUNT 0x030100 /* Real Time Counter */ +#define PI_RT_COMPARE_A 0x000108 /* Real Time Compare A */ +#define PI_RT_COMPARE_B 0x000110 /* Real Time Compare B */ +#define PI_PROFILE_COMPARE 0x000118 /* L5 int to both cpus when == RTC */ +#define PI_RT_PEND_A 0x000120 /* Set if RT int for A pending */ +#define PI_RT_PEND_B 0x000128 /* Set if RT int for B pending */ +#define PI_PROF_PEND_A 0x000130 /* Set if Prof int for A pending */ +#define PI_PROF_PEND_B 0x000138 /* Set if Prof int for B pending */ +#define PI_RT_EN_A 0x000140 /* RT int for CPU A enable */ +#define PI_RT_EN_B 0x000148 /* RT int for CPU B enable */ +#define PI_PROF_EN_A 0x000150 /* PROF int for CPU A enable */ +#define PI_PROF_EN_B 0x000158 /* PROF int for CPU B enable */ +#define PI_RT_LOCAL_CTRL 0x000160 /* RT control register */ +#define PI_RT_FILTER_CTRL 0x000168 /* GCLK Filter control register */ + +#define PI_COUNT_OFFSET 0x08 /* A to B offset for all counts */ + +/* Built-In Self Test support */ + +#define PI_BIST_WRITE_DATA 0x000200 /* BIST write data */ +#define PI_BIST_READ_DATA 0x000208 /* BIST read data */ +#define PI_BIST_COUNT_TARG 0x000210 /* BIST Count and Target */ +#define PI_BIST_READY 0x000218 /* BIST Ready indicator */ +#define PI_BIST_SHIFT_LOAD 0x000220 /* BIST control */ +#define PI_BIST_SHIFT_UNLOAD 0x000228 /* BIST control */ +#define PI_BIST_ENTER_RUN 0x000230 /* BIST control */ + +/* Graphics control registers */ + +#define PI_GFX_PAGE_A 0x000300 /* Graphics page A */ +#define PI_GFX_CREDIT_CNTR_A 0x000308 /* Graphics credit counter A */ +#define PI_GFX_BIAS_A 0x000310 /* Graphics bias A */ +#define PI_GFX_INT_CNTR_A 0x000318 /* Graphics interrupt counter A */ +#define PI_GFX_INT_CMP_A 0x000320 /* Graphics interrupt comparator A */ +#define PI_GFX_PAGE_B 0x000328 /* Graphics page B */ +#define PI_GFX_CREDIT_CNTR_B 0x000330 /* Graphics credit counter B */ +#define PI_GFX_BIAS_B 0x000338 /* Graphics bias B */ +#define PI_GFX_INT_CNTR_B 0x000340 /* Graphics interrupt counter B */ +#define PI_GFX_INT_CMP_B 0x000348 /* Graphics interrupt comparator B */ + +#define PI_GFX_OFFSET (PI_GFX_PAGE_B - PI_GFX_PAGE_A) +#define PI_GFX_PAGE_ENABLE 0x0000010000000000LL + +/* Error and timeout registers */ +#define PI_ERR_INT_PEND 0x000400 /* Error Interrupt Pending */ +#define PI_ERR_INT_MASK_A 0x000408 /* Error Interrupt mask for CPU A */ +#define PI_ERR_INT_MASK_B 0x000410 /* Error Interrupt mask for CPU B */ +#define PI_ERR_STACK_ADDR_A 0x000418 /* Error stack address for CPU A */ +#define PI_ERR_STACK_ADDR_B 0x000420 /* Error stack address for CPU B */ +#define PI_ERR_STACK_SIZE 0x000428 /* Error Stack Size */ +#define PI_ERR_STATUS0_A 0x000430 /* Error Status 0A */ +#define PI_ERR_STATUS0_A_RCLR 0x000438 /* Error Status 0A clear on read */ +#define PI_ERR_STATUS1_A 0x000440 /* Error Status 1A */ +#define PI_ERR_STATUS1_A_RCLR 0x000448 /* Error Status 1A clear on read */ +#define PI_ERR_STATUS0_B 0x000450 /* Error Status 0B */ +#define PI_ERR_STATUS0_B_RCLR 0x000458 /* Error Status 0B clear on read */ +#define PI_ERR_STATUS1_B 0x000460 /* Error Status 1B */ +#define PI_ERR_STATUS1_B_RCLR 0x000468 /* Error Status 1B clear on read */ +#define PI_SPOOL_CMP_A 0x000470 /* Spool compare for CPU A */ +#define PI_SPOOL_CMP_B 0x000478 /* Spool compare for CPU B */ +#define PI_CRB_TIMEOUT_A 0x000480 /* Timed out CRB entries for A */ +#define PI_CRB_TIMEOUT_B 0x000488 /* Timed out CRB entries for B */ +#define PI_SYSAD_ERRCHK_EN 0x000490 /* Enables SYSAD error checking */ +#define PI_BAD_CHECK_BIT_A 0x000498 /* Force SYSAD check bit error */ +#define PI_BAD_CHECK_BIT_B 0x0004a0 /* Force SYSAD check bit error */ +#define PI_NACK_CNT_A 0x0004a8 /* Consecutive NACK counter */ +#define PI_NACK_CNT_B 0x0004b0 /* " " for CPU B */ +#define PI_NACK_CMP 0x0004b8 /* NACK count compare */ +#define PI_STACKADDR_OFFSET (PI_ERR_STACK_ADDR_B - PI_ERR_STACK_ADDR_A) +#define PI_ERRSTAT_OFFSET (PI_ERR_STATUS0_B - PI_ERR_STATUS0_A) +#define PI_RDCLR_OFFSET (PI_ERR_STATUS0_A_RCLR - PI_ERR_STATUS0_A) + +/* Bits in PI_ERR_INT_PEND */ +#define PI_ERR_SPOOL_CMP_B 0x00000001 /* Spool end hit high water */ +#define PI_ERR_SPOOL_CMP_A 0x00000002 +#define PI_ERR_SPUR_MSG_B 0x00000004 /* Spurious message intr. */ +#define PI_ERR_SPUR_MSG_A 0x00000008 +#define PI_ERR_WRB_TERR_B 0x00000010 /* WRB TERR */ +#define PI_ERR_WRB_TERR_A 0x00000020 +#define PI_ERR_WRB_WERR_B 0x00000040 /* WRB WERR */ +#define PI_ERR_WRB_WERR_A 0x00000080 +#define PI_ERR_SYSSTATE_B 0x00000100 /* SysState parity error */ +#define PI_ERR_SYSSTATE_A 0x00000200 +#define PI_ERR_SYSAD_DATA_B 0x00000400 /* SysAD data parity error */ +#define PI_ERR_SYSAD_DATA_A 0x00000800 +#define PI_ERR_SYSAD_ADDR_B 0x00001000 /* SysAD addr parity error */ +#define PI_ERR_SYSAD_ADDR_A 0x00002000 +#define PI_ERR_SYSCMD_DATA_B 0x00004000 /* SysCmd data parity error */ +#define PI_ERR_SYSCMD_DATA_A 0x00008000 +#define PI_ERR_SYSCMD_ADDR_B 0x00010000 /* SysCmd addr parity error */ +#define PI_ERR_SYSCMD_ADDR_A 0x00020000 +#define PI_ERR_BAD_SPOOL_B 0x00040000 /* Error spooling to memory */ +#define PI_ERR_BAD_SPOOL_A 0x00080000 +#define PI_ERR_UNCAC_UNCORR_B 0x00100000 /* Uncached uncorrectable */ +#define PI_ERR_UNCAC_UNCORR_A 0x00200000 +#define PI_ERR_SYSSTATE_TAG_B 0x00400000 /* SysState tag parity error */ +#define PI_ERR_SYSSTATE_TAG_A 0x00800000 +#define PI_ERR_MD_UNCORR 0x01000000 /* Must be cleared in MD */ + +#define PI_ERR_CLEAR_ALL_A 0x00aaaaaa +#define PI_ERR_CLEAR_ALL_B 0x00555555 + + +/* + * The following three macros define all possible error int pends. + */ + +#define PI_FATAL_ERR_CPU_A (PI_ERR_SYSSTATE_TAG_A | \ + PI_ERR_BAD_SPOOL_A | \ + PI_ERR_SYSCMD_ADDR_A | \ + PI_ERR_SYSCMD_DATA_A | \ + PI_ERR_SYSAD_ADDR_A | \ + PI_ERR_SYSAD_DATA_A | \ + PI_ERR_SYSSTATE_A) + +#define PI_MISC_ERR_CPU_A (PI_ERR_UNCAC_UNCORR_A | \ + PI_ERR_WRB_WERR_A | \ + PI_ERR_WRB_TERR_A | \ + PI_ERR_SPUR_MSG_A | \ + PI_ERR_SPOOL_CMP_A) + +#define PI_FATAL_ERR_CPU_B (PI_ERR_SYSSTATE_TAG_B | \ + PI_ERR_BAD_SPOOL_B | \ + PI_ERR_SYSCMD_ADDR_B | \ + PI_ERR_SYSCMD_DATA_B | \ + PI_ERR_SYSAD_ADDR_B | \ + PI_ERR_SYSAD_DATA_B | \ + PI_ERR_SYSSTATE_B) + +#define PI_MISC_ERR_CPU_B (PI_ERR_UNCAC_UNCORR_B | \ + PI_ERR_WRB_WERR_B | \ + PI_ERR_WRB_TERR_B | \ + PI_ERR_SPUR_MSG_B | \ + PI_ERR_SPOOL_CMP_B) + +#define PI_ERR_GENERIC (PI_ERR_MD_UNCORR) + +/* + * Error types for PI_ERR_STATUS0_[AB] and error stack: + * Use the write types if WRBRRB is 1 else use the read types + */ + +/* Fields in PI_ERR_STATUS0_[AB] */ +#define PI_ERR_ST0_TYPE_MASK 0x0000000000000007 +#define PI_ERR_ST0_TYPE_SHFT 0 +#define PI_ERR_ST0_REQNUM_MASK 0x0000000000000038 +#define PI_ERR_ST0_REQNUM_SHFT 3 +#define PI_ERR_ST0_SUPPL_MASK 0x000000000001ffc0 +#define PI_ERR_ST0_SUPPL_SHFT 6 +#define PI_ERR_ST0_CMD_MASK 0x0000000001fe0000 +#define PI_ERR_ST0_CMD_SHFT 17 +#define PI_ERR_ST0_ADDR_MASK 0x3ffffffffe000000 +#define PI_ERR_ST0_ADDR_SHFT 25 +#define PI_ERR_ST0_OVERRUN_MASK 0x4000000000000000 +#define PI_ERR_ST0_OVERRUN_SHFT 62 +#define PI_ERR_ST0_VALID_MASK 0x8000000000000000 +#define PI_ERR_ST0_VALID_SHFT 63 + +/* Fields in PI_ERR_STATUS1_[AB] */ +#define PI_ERR_ST1_SPOOL_MASK 0x00000000001fffff +#define PI_ERR_ST1_SPOOL_SHFT 0 +#define PI_ERR_ST1_TOUTCNT_MASK 0x000000001fe00000 +#define PI_ERR_ST1_TOUTCNT_SHFT 21 +#define PI_ERR_ST1_INVCNT_MASK 0x0000007fe0000000 +#define PI_ERR_ST1_INVCNT_SHFT 29 +#define PI_ERR_ST1_CRBNUM_MASK 0x0000038000000000 +#define PI_ERR_ST1_CRBNUM_SHFT 39 +#define PI_ERR_ST1_WRBRRB_MASK 0x0000040000000000 +#define PI_ERR_ST1_WRBRRB_SHFT 42 +#define PI_ERR_ST1_CRBSTAT_MASK 0x001ff80000000000 +#define PI_ERR_ST1_CRBSTAT_SHFT 43 +#define PI_ERR_ST1_MSGSRC_MASK 0xffe0000000000000 +#define PI_ERR_ST1_MSGSRC_SHFT 53 + +/* Fields in the error stack */ +#define PI_ERR_STK_TYPE_MASK 0x0000000000000003 +#define PI_ERR_STK_TYPE_SHFT 0 +#define PI_ERR_STK_SUPPL_MASK 0x0000000000000038 +#define PI_ERR_STK_SUPPL_SHFT 3 +#define PI_ERR_STK_REQNUM_MASK 0x00000000000001c0 +#define PI_ERR_STK_REQNUM_SHFT 6 +#define PI_ERR_STK_CRBNUM_MASK 0x0000000000000e00 +#define PI_ERR_STK_CRBNUM_SHFT 9 +#define PI_ERR_STK_WRBRRB_MASK 0x0000000000001000 +#define PI_ERR_STK_WRBRRB_SHFT 12 +#define PI_ERR_STK_CRBSTAT_MASK 0x00000000007fe000 +#define PI_ERR_STK_CRBSTAT_SHFT 13 +#define PI_ERR_STK_CMD_MASK 0x000000007f800000 +#define PI_ERR_STK_CMD_SHFT 23 +#define PI_ERR_STK_ADDR_MASK 0xffffffff80000000 +#define PI_ERR_STK_ADDR_SHFT 31 + +/* Error type in the error status or stack on Read CRBs */ +#define PI_ERR_RD_PRERR 1 +#define PI_ERR_RD_DERR 2 +#define PI_ERR_RD_TERR 3 + +/* Error type in the error status or stack on Write CRBs */ +#define PI_ERR_WR_WERR 0 +#define PI_ERR_WR_PWERR 1 +#define PI_ERR_WR_TERR 3 + +/* Read or Write CRB in error status or stack */ +#define PI_ERR_RRB 0 +#define PI_ERR_WRB 1 +#define PI_ERR_ANY_CRB 2 + +/* Address masks in the error status and error stack are not the same */ +#define ERR_STK_ADDR_SHFT 7 +#define ERR_STAT0_ADDR_SHFT 3 + +#define PI_MIN_STACK_SIZE 4096 /* For figuring out the size to set */ +#define PI_STACK_SIZE_SHFT 12 /* 4k */ + +#define ERR_STACK_SIZE_BYTES(_sz) \ + ((_sz) ? (PI_MIN_STACK_SIZE << ((_sz) - 1)) : 0) + +#ifndef __ASSEMBLY__ +/* + * format of error stack and error status registers. + */ + +struct err_stack_format { + u64 sk_addr : 33, /* address */ + sk_cmd : 8, /* message command */ + sk_crb_sts : 10, /* status from RRB or WRB */ + sk_rw_rb : 1, /* RRB == 0, WRB == 1 */ + sk_crb_num : 3, /* WRB (0 to 7) or RRB (0 to 4) */ + sk_t5_req : 3, /* RRB T5 request number */ + sk_suppl : 3, /* lowest 3 bit of supplemental */ + sk_err_type: 3; /* error type */ +}; + +typedef union pi_err_stack { + u64 pi_stk_word; + struct err_stack_format pi_stk_fmt; +} pi_err_stack_t; + +struct err_status0_format { + u64 s0_valid : 1, /* Valid */ + s0_ovr_run : 1, /* Overrun, spooled to memory */ + s0_addr : 37, /* address */ + s0_cmd : 8, /* message command */ + s0_supl : 11, /* message supplemental field */ + s0_t5_req : 3, /* RRB T5 request number */ + s0_err_type: 3; /* error type */ +}; + +typedef union pi_err_stat0 { + u64 pi_stat0_word; + struct err_status0_format pi_stat0_fmt; +} pi_err_stat0_t; + +struct err_status1_format { + u64 s1_src : 11, /* message source */ + s1_crb_sts : 10, /* status from RRB or WRB */ + s1_rw_rb : 1, /* RRB == 0, WRB == 1 */ + s1_crb_num : 3, /* WRB (0 to 7) or RRB (0 to 4) */ + s1_inval_cnt:10, /* signed invalidate counter RRB */ + s1_to_cnt : 8, /* crb timeout counter */ + s1_spl_cnt : 21; /* number spooled to memory */ +}; + +typedef union pi_err_stat1 { + u64 pi_stat1_word; + struct err_status1_format pi_stat1_fmt; +} pi_err_stat1_t; + +typedef u64 rtc_time_t; + +#endif /* !__ASSEMBLY__ */ + + +/* Bits in PI_SYSAD_ERRCHK_EN */ +#define PI_SYSAD_ERRCHK_ECCGEN 0x01 /* Enable ECC generation */ +#define PI_SYSAD_ERRCHK_QUALGEN 0x02 /* Enable data quality signal gen. */ +#define PI_SYSAD_ERRCHK_SADP 0x04 /* Enable SysAD parity checking */ +#define PI_SYSAD_ERRCHK_CMDP 0x08 /* Enable SysCmd parity checking */ +#define PI_SYSAD_ERRCHK_STATE 0x10 /* Enable SysState parity checking */ +#define PI_SYSAD_ERRCHK_QUAL 0x20 /* Enable data quality checking */ +#define PI_SYSAD_CHECK_ALL 0x3f /* Generate and check all signals. */ + +/* Interrupt pending bits on R10000 */ + +#define HUB_IP_PEND0 0x0400 +#define HUB_IP_PEND1_CC 0x0800 +#define HUB_IP_RT 0x1000 +#define HUB_IP_PROF 0x2000 +#define HUB_IP_ERROR 0x4000 +#define HUB_IP_MASK 0x7c00 + +/* PI_RT_LOCAL_CTRL mask and shift definitions */ + +#define PRLC_USE_INT_SHFT 16 +#define PRLC_USE_INT_MASK (UINT64_CAST 1 << 16) +#define PRLC_USE_INT (UINT64_CAST 1 << 16) +#define PRLC_GCLK_SHFT 15 +#define PRLC_GCLK_MASK (UINT64_CAST 1 << 15) +#define PRLC_GCLK (UINT64_CAST 1 << 15) +#define PRLC_GCLK_COUNT_SHFT 8 +#define PRLC_GCLK_COUNT_MASK (UINT64_CAST 0x7f << 8) +#define PRLC_MAX_COUNT_SHFT 1 +#define PRLC_MAX_COUNT_MASK (UINT64_CAST 0x7f << 1) +#define PRLC_GCLK_EN_SHFT 0 +#define PRLC_GCLK_EN_MASK (UINT64_CAST 1) +#define PRLC_GCLK_EN (UINT64_CAST 1) + +/* PI_RT_FILTER_CTRL mask and shift definitions */ + +/* + * Bits for NACK_CNT_A/B and NACK_CMP + */ +#define PI_NACK_CNT_EN_SHFT 20 +#define PI_NACK_CNT_EN_MASK 0x100000 +#define PI_NACK_CNT_MASK 0x0fffff +#define PI_NACK_CNT_MAX 0x0fffff + +#endif /* _ASM_SN_SN0_HUBPI_H */ diff --git a/arch/mips/include/asm/sn/sn0/ip27.h b/arch/mips/include/asm/sn/sn0/ip27.h new file mode 100644 index 00000000000..3c97e0855c8 --- /dev/null +++ b/arch/mips/include/asm/sn/sn0/ip27.h @@ -0,0 +1,85 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Derived from IRIX . + * + * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. + * Copyright (C) 1999, 2006 by Ralf Baechle + */ +#ifndef _ASM_SN_SN0_IP27_H +#define _ASM_SN_SN0_IP27_H + +#include + +/* + * Simple definitions for the masks which remove SW bits from pte. + */ + +#define TLBLO_HWBITSHIFT 0 /* Shift value, for masking */ + +#ifndef __ASSEMBLY__ + +#define CAUSE_BERRINTR IE_IRQ5 + +#define ECCF_CACHE_ERR 0 +#define ECCF_TAGLO 1 +#define ECCF_ECC 2 +#define ECCF_ERROREPC 3 +#define ECCF_PADDR 4 +#define ECCF_SIZE (5 * sizeof(long)) + +#endif /* !__ASSEMBLY__ */ + +#ifdef __ASSEMBLY__ + +/* + * KL_GET_CPUNUM (similar to EV_GET_SPNUM for EVEREST platform) reads + * the processor number of the calling processor. The proc parameters + * must be a register. + */ +#define KL_GET_CPUNUM(proc) \ + dli proc, LOCAL_HUB(0); \ + ld proc, PI_CPU_NUM(proc) + +#endif /* __ASSEMBLY__ */ + +/* + * R10000 status register interrupt bit mask usage for IP27. + */ +#define SRB_SWTIMO IE_SW0 /* 0x0100 */ +#define SRB_NET IE_SW1 /* 0x0200 */ +#define SRB_DEV0 IE_IRQ0 /* 0x0400 */ +#define SRB_DEV1 IE_IRQ1 /* 0x0800 */ +#define SRB_TIMOCLK IE_IRQ2 /* 0x1000 */ +#define SRB_PROFCLK IE_IRQ3 /* 0x2000 */ +#define SRB_ERR IE_IRQ4 /* 0x4000 */ +#define SRB_SCHEDCLK IE_IRQ5 /* 0x8000 */ + +#define SR_IBIT_HI SRB_DEV0 +#define SR_IBIT_PROF SRB_PROFCLK + +#define SRB_SWTIMO_IDX 0 +#define SRB_NET_IDX 1 +#define SRB_DEV0_IDX 2 +#define SRB_DEV1_IDX 3 +#define SRB_TIMOCLK_IDX 4 +#define SRB_PROFCLK_IDX 5 +#define SRB_ERR_IDX 6 +#define SRB_SCHEDCLK_IDX 7 + +#define NUM_CAUSE_INTRS 8 + +#define SCACHE_LINESIZE 128 +#define SCACHE_LINEMASK (SCACHE_LINESIZE - 1) + +#include + +#define LED_CYCLE_MASK 0x0f +#define LED_CYCLE_SHFT 4 + +#define SEND_NMI(_nasid, _slice) \ + REMOTE_HUB_S((_nasid), (PI_NMI_A + ((_slice) * PI_NMI_OFFSET)), 1) + +#endif /* _ASM_SN_SN0_IP27_H */ diff --git a/arch/mips/include/asm/sn/sn_private.h b/arch/mips/include/asm/sn/sn_private.h new file mode 100644 index 00000000000..1a2c3025bf2 --- /dev/null +++ b/arch/mips/include/asm/sn/sn_private.h @@ -0,0 +1,19 @@ +#ifndef __ASM_SN_SN_PRIVATE_H +#define __ASM_SN_SN_PRIVATE_H + +#include + +extern nasid_t master_nasid; + +extern void cpu_node_probe(void); +extern cnodeid_t get_compact_nodeid(void); +extern void hub_rtc_init(cnodeid_t); +extern void cpu_time_init(void); +extern void per_cpu_init(void); +extern void install_cpu_nmi_handler(int slice); +extern void install_ipi(void); +extern void setup_replication_mask(void); +extern void replicate_kernel_text(void); +extern pfn_t node_getfirstfree(cnodeid_t); + +#endif /* __ASM_SN_SN_PRIVATE_H */ diff --git a/arch/mips/include/asm/sn/types.h b/arch/mips/include/asm/sn/types.h new file mode 100644 index 00000000000..74d0bb260b8 --- /dev/null +++ b/arch/mips/include/asm/sn/types.h @@ -0,0 +1,26 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1999 by Ralf Baechle + */ +#ifndef _ASM_SN_TYPES_H +#define _ASM_SN_TYPES_H + +#include + +typedef unsigned long cpuid_t; +typedef unsigned long cnodemask_t; +typedef signed short nasid_t; /* node id in numa-as-id space */ +typedef signed short cnodeid_t; /* node id in compact-id space */ +typedef signed char partid_t; /* partition ID type */ +typedef signed short moduleid_t; /* user-visible module number type */ +typedef signed short cmoduleid_t; /* kernel compact module id type */ +typedef unsigned char clusterid_t; /* Clusterid of the cell */ +typedef unsigned long pfn_t; + +typedef dev_t vertex_hdl_t; /* hardware graph vertex handle */ + +#endif /* _ASM_SN_TYPES_H */ diff --git a/arch/mips/include/asm/sni.h b/arch/mips/include/asm/sni.h new file mode 100644 index 00000000000..8c1eb02c6d1 --- /dev/null +++ b/arch/mips/include/asm/sni.h @@ -0,0 +1,244 @@ +/* + * SNI specific definitions + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 1998 by Ralf Baechle + * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ +#ifndef __ASM_SNI_H +#define __ASM_SNI_H + +extern unsigned int sni_brd_type; + +#define SNI_BRD_10 2 +#define SNI_BRD_10NEW 3 +#define SNI_BRD_TOWER_OASIC 4 +#define SNI_BRD_MINITOWER 5 +#define SNI_BRD_PCI_TOWER 6 +#define SNI_BRD_RM200 7 +#define SNI_BRD_PCI_MTOWER 8 +#define SNI_BRD_PCI_DESKTOP 9 +#define SNI_BRD_PCI_TOWER_CPLUS 10 +#define SNI_BRD_PCI_MTOWER_CPLUS 11 + +/* RM400 cpu types */ +#define SNI_CPU_M8021 0x01 +#define SNI_CPU_M8030 0x04 +#define SNI_CPU_M8031 0x06 +#define SNI_CPU_M8034 0x0f +#define SNI_CPU_M8037 0x07 +#define SNI_CPU_M8040 0x05 +#define SNI_CPU_M8043 0x09 +#define SNI_CPU_M8050 0x0b +#define SNI_CPU_M8053 0x0d + +#define SNI_PORT_BASE CKSEG1ADDR(0xb4000000) + +#ifndef __MIPSEL__ +/* + * ASIC PCI registers for big endian configuration. + */ +#define PCIMT_UCONF CKSEG1ADDR(0xbfff0004) +#define PCIMT_IOADTIMEOUT2 CKSEG1ADDR(0xbfff000c) +#define PCIMT_IOMEMCONF CKSEG1ADDR(0xbfff0014) +#define PCIMT_IOMMU CKSEG1ADDR(0xbfff001c) +#define PCIMT_IOADTIMEOUT1 CKSEG1ADDR(0xbfff0024) +#define PCIMT_DMAACCESS CKSEG1ADDR(0xbfff002c) +#define PCIMT_DMAHIT CKSEG1ADDR(0xbfff0034) +#define PCIMT_ERRSTATUS CKSEG1ADDR(0xbfff003c) +#define PCIMT_ERRADDR CKSEG1ADDR(0xbfff0044) +#define PCIMT_SYNDROME CKSEG1ADDR(0xbfff004c) +#define PCIMT_ITPEND CKSEG1ADDR(0xbfff0054) +#define IT_INT2 0x01 +#define IT_INTD 0x02 +#define IT_INTC 0x04 +#define IT_INTB 0x08 +#define IT_INTA 0x10 +#define IT_EISA 0x20 +#define IT_SCSI 0x40 +#define IT_ETH 0x80 +#define PCIMT_IRQSEL CKSEG1ADDR(0xbfff005c) +#define PCIMT_TESTMEM CKSEG1ADDR(0xbfff0064) +#define PCIMT_ECCREG CKSEG1ADDR(0xbfff006c) +#define PCIMT_CONFIG_ADDRESS CKSEG1ADDR(0xbfff0074) +#define PCIMT_ASIC_ID CKSEG1ADDR(0xbfff007c) /* read */ +#define PCIMT_SOFT_RESET CKSEG1ADDR(0xbfff007c) /* write */ +#define PCIMT_PIA_OE CKSEG1ADDR(0xbfff0084) +#define PCIMT_PIA_DATAOUT CKSEG1ADDR(0xbfff008c) +#define PCIMT_PIA_DATAIN CKSEG1ADDR(0xbfff0094) +#define PCIMT_CACHECONF CKSEG1ADDR(0xbfff009c) +#define PCIMT_INVSPACE CKSEG1ADDR(0xbfff00a4) +#else +/* + * ASIC PCI registers for little endian configuration. + */ +#define PCIMT_UCONF CKSEG1ADDR(0xbfff0000) +#define PCIMT_IOADTIMEOUT2 CKSEG1ADDR(0xbfff0008) +#define PCIMT_IOMEMCONF CKSEG1ADDR(0xbfff0010) +#define PCIMT_IOMMU CKSEG1ADDR(0xbfff0018) +#define PCIMT_IOADTIMEOUT1 CKSEG1ADDR(0xbfff0020) +#define PCIMT_DMAACCESS CKSEG1ADDR(0xbfff0028) +#define PCIMT_DMAHIT CKSEG1ADDR(0xbfff0030) +#define PCIMT_ERRSTATUS CKSEG1ADDR(0xbfff0038) +#define PCIMT_ERRADDR CKSEG1ADDR(0xbfff0040) +#define PCIMT_SYNDROME CKSEG1ADDR(0xbfff0048) +#define PCIMT_ITPEND CKSEG1ADDR(0xbfff0050) +#define IT_INT2 0x01 +#define IT_INTD 0x02 +#define IT_INTC 0x04 +#define IT_INTB 0x08 +#define IT_INTA 0x10 +#define IT_EISA 0x20 +#define IT_SCSI 0x40 +#define IT_ETH 0x80 +#define PCIMT_IRQSEL CKSEG1ADDR(0xbfff0058) +#define PCIMT_TESTMEM CKSEG1ADDR(0xbfff0060) +#define PCIMT_ECCREG CKSEG1ADDR(0xbfff0068) +#define PCIMT_CONFIG_ADDRESS CKSEG1ADDR(0xbfff0070) +#define PCIMT_ASIC_ID CKSEG1ADDR(0xbfff0078) /* read */ +#define PCIMT_SOFT_RESET CKSEG1ADDR(0xbfff0078) /* write */ +#define PCIMT_PIA_OE CKSEG1ADDR(0xbfff0080) +#define PCIMT_PIA_DATAOUT CKSEG1ADDR(0xbfff0088) +#define PCIMT_PIA_DATAIN CKSEG1ADDR(0xbfff0090) +#define PCIMT_CACHECONF CKSEG1ADDR(0xbfff0098) +#define PCIMT_INVSPACE CKSEG1ADDR(0xbfff00a0) +#endif + +#define PCIMT_PCI_CONF CKSEG1ADDR(0xbfff0100) + +/* + * Data port for the PCI bus in IO space + */ +#define PCIMT_CONFIG_DATA 0x0cfc + +/* + * Board specific registers + */ +#define PCIMT_CSMSR CKSEG1ADDR(0xbfd00000) +#define PCIMT_CSSWITCH CKSEG1ADDR(0xbfd10000) +#define PCIMT_CSITPEND CKSEG1ADDR(0xbfd20000) +#define PCIMT_AUTO_PO_EN CKSEG1ADDR(0xbfd30000) +#define PCIMT_CLR_TEMP CKSEG1ADDR(0xbfd40000) +#define PCIMT_AUTO_PO_DIS CKSEG1ADDR(0xbfd50000) +#define PCIMT_EXMSR CKSEG1ADDR(0xbfd60000) +#define PCIMT_UNUSED1 CKSEG1ADDR(0xbfd70000) +#define PCIMT_CSWCSM CKSEG1ADDR(0xbfd80000) +#define PCIMT_UNUSED2 CKSEG1ADDR(0xbfd90000) +#define PCIMT_CSLED CKSEG1ADDR(0xbfda0000) +#define PCIMT_CSMAPISA CKSEG1ADDR(0xbfdb0000) +#define PCIMT_CSRSTBP CKSEG1ADDR(0xbfdc0000) +#define PCIMT_CLRPOFF CKSEG1ADDR(0xbfdd0000) +#define PCIMT_CSTIMER CKSEG1ADDR(0xbfde0000) +#define PCIMT_PWDN CKSEG1ADDR(0xbfdf0000) + +/* + * A20R based boards + */ +#define A20R_PT_CLOCK_BASE CKSEG1ADDR(0xbc040000) +#define A20R_PT_TIM0_ACK CKSEG1ADDR(0xbc050000) +#define A20R_PT_TIM1_ACK CKSEG1ADDR(0xbc060000) + +#define SNI_A20R_IRQ_BASE MIPS_CPU_IRQ_BASE +#define SNI_A20R_IRQ_TIMER (SNI_A20R_IRQ_BASE+5) + +#define SNI_PCIT_INT_REG CKSEG1ADDR(0xbfff000c) + +#define SNI_PCIT_INT_START 24 +#define SNI_PCIT_INT_END 30 + +#define PCIT_IRQ_ETHERNET (MIPS_CPU_IRQ_BASE + 5) +#define PCIT_IRQ_INTA (SNI_PCIT_INT_START + 0) +#define PCIT_IRQ_INTB (SNI_PCIT_INT_START + 1) +#define PCIT_IRQ_INTC (SNI_PCIT_INT_START + 2) +#define PCIT_IRQ_INTD (SNI_PCIT_INT_START + 3) +#define PCIT_IRQ_SCSI0 (SNI_PCIT_INT_START + 4) +#define PCIT_IRQ_SCSI1 (SNI_PCIT_INT_START + 5) + + +/* + * Interrupt 0-16 are EISA interrupts. Interrupts from 16 on are assigned + * to the other interrupts generated by ASIC PCI. + * + * INT2 is a wired-or of the push button interrupt, high temperature interrupt + * ASIC PCI interrupt. + */ +#define PCIMT_KEYBOARD_IRQ 1 +#define PCIMT_IRQ_INT2 24 +#define PCIMT_IRQ_INTD 25 +#define PCIMT_IRQ_INTC 26 +#define PCIMT_IRQ_INTB 27 +#define PCIMT_IRQ_INTA 28 +#define PCIMT_IRQ_EISA 29 +#define PCIMT_IRQ_SCSI 30 + +#define PCIMT_IRQ_ETHERNET (MIPS_CPU_IRQ_BASE+6) + +#if 0 +#define PCIMT_IRQ_TEMPERATURE 24 +#define PCIMT_IRQ_EISA_NMI 25 +#define PCIMT_IRQ_POWER_OFF 26 +#define PCIMT_IRQ_BUTTON 27 +#endif + +/* + * Base address for the mapped 16mb EISA bus segment. + */ +#define PCIMT_EISA_BASE CKSEG1ADDR(0xb0000000) + +/* PCI EISA Interrupt acknowledge */ +#define PCIMT_INT_ACKNOWLEDGE CKSEG1ADDR(0xba000000) + +/* + * SNI ID PROM + * + * SNI_IDPROM_MEMSIZE Memsize in 16MB quantities + * SNI_IDPROM_BRDTYPE Board Type + * SNI_IDPROM_CPUTYPE CPU Type on RM400 + */ +#ifdef CONFIG_CPU_BIG_ENDIAN +#define __SNI_END 0 +#endif +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define __SNI_END 3 +#endif +#define SNI_IDPROM_BASE CKSEG1ADDR(0x1ff00000) +#define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE + (0x28 ^ __SNI_END)) +#define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE + (0x29 ^ __SNI_END)) +#define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE + (0x30 ^ __SNI_END)) + +#define SNI_IDPROM_SIZE 0x1000 + +/* board specific init functions */ +extern void sni_a20r_init(void); +extern void sni_pcit_init(void); +extern void sni_rm200_init(void); +extern void sni_pcimt_init(void); + +/* board specific irq init functions */ +extern void sni_a20r_irq_init(void); +extern void sni_pcit_irq_init(void); +extern void sni_pcit_cplus_irq_init(void); +extern void sni_rm200_irq_init(void); +extern void sni_pcimt_irq_init(void); + +/* timer inits */ +extern void sni_cpu_time_init(void); + +/* eisa init for RM200/400 */ +#ifdef CONFIG_EISA +extern int sni_eisa_root_init(void); +#else +static inline int sni_eisa_root_init(void) +{ + return 0; +} +#endif + +/* common irq stuff */ +extern void (*sni_hwint)(void); +extern struct irqaction sni_isa_irq; + +#endif /* __ASM_SNI_H */ diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h new file mode 100644 index 00000000000..facc2d7a87c --- /dev/null +++ b/arch/mips/include/asm/socket.h @@ -0,0 +1,117 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 1999, 2000, 2001 Ralf Baechle + * Copyright (C) 2000, 2001 Silicon Graphics, Inc. + */ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +#include + +/* + * For setsockopt(2) + * + * This defines are ABI conformant as far as Linux supports these ... + */ +#define SOL_SOCKET 0xffff + +#define SO_DEBUG 0x0001 /* Record debugging information. */ +#define SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */ +#define SO_KEEPALIVE 0x0008 /* Keep connections alive and send + SIGPIPE when they die. */ +#define SO_DONTROUTE 0x0010 /* Don't do local routing. */ +#define SO_BROADCAST 0x0020 /* Allow transmission of + broadcast messages. */ +#define SO_LINGER 0x0080 /* Block on close of a reliable + socket to transmit pending data. */ +#define SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */ +#if 0 +To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ +#endif + +#define SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ +#define SO_STYLE SO_TYPE /* Synonym */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_SNDBUF 0x1001 /* Send buffer size. */ +#define SO_RCVBUF 0x1002 /* Receive buffer. */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ACCEPTCONN 0x1009 + +/* linux-specific, might as well be the same as on i386 */ +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_BSDCOMPAT 14 + +#define SO_PASSCRED 17 +#define SO_PEERCRED 18 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_PEERSEC 30 +#define SO_SNDBUFFORCE 31 +#define SO_RCVBUFFORCE 33 +#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS + +#define SO_MARK 36 + +#ifdef __KERNEL__ + +/** sock_type - Socket types + * + * Please notice that for binary compat reasons MIPS has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user level. + */ +enum sock_type { + SOCK_DGRAM = 1, + SOCK_STREAM = 2, + SOCK_RAW = 3, + SOCK_RDM = 4, + SOCK_SEQPACKET = 5, + SOCK_DCCP = 6, + SOCK_PACKET = 10, +}; + +#define SOCK_MAX (SOCK_PACKET + 1) +/* Mask which covers at least up to SOCK_MASK-1. The + * * remaining bits are used as flags. */ +#define SOCK_TYPE_MASK 0xf + +/* Flags for socket, socketpair, paccept */ +#define SOCK_CLOEXEC O_CLOEXEC +#define SOCK_NONBLOCK O_NONBLOCK + +#define ARCH_HAS_SOCKET_TYPES 1 + +#endif /* __KERNEL__ */ + +#endif /* _ASM_SOCKET_H */ diff --git a/arch/mips/include/asm/sockios.h b/arch/mips/include/asm/sockios.h new file mode 100644 index 00000000000..ed1a5f78d22 --- /dev/null +++ b/arch/mips/include/asm/sockios.h @@ -0,0 +1,26 @@ +/* + * Socket-level I/O control calls. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995 by Ralf Baechle + */ +#ifndef _ASM_SOCKIOS_H +#define _ASM_SOCKIOS_H + +#include + +/* Socket-level I/O control calls. */ +#define FIOGETOWN _IOR('f', 123, int) +#define FIOSETOWN _IOW('f', 124, int) + +#define SIOCATMARK _IOR('s', 7, int) +#define SIOCSPGRP _IOW('s', 8, pid_t) +#define SIOCGPGRP _IOR('s', 9, pid_t) + +#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ +#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ + +#endif /* _ASM_SOCKIOS_H */ diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h new file mode 100644 index 00000000000..795ac6c2320 --- /dev/null +++ b/arch/mips/include/asm/sparsemem.h @@ -0,0 +1,14 @@ +#ifndef _MIPS_SPARSEMEM_H +#define _MIPS_SPARSEMEM_H +#ifdef CONFIG_SPARSEMEM + +/* + * SECTION_SIZE_BITS 2^N: how big each section will be + * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space + */ +#define SECTION_SIZE_BITS 28 +#define MAX_PHYSMEM_BITS 35 + +#endif /* CONFIG_SPARSEMEM */ +#endif /* _MIPS_SPARSEMEM_H */ + diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h new file mode 100644 index 00000000000..bb897016c49 --- /dev/null +++ b/arch/mips/include/asm/spinlock.h @@ -0,0 +1,376 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999, 2000, 06 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_SPINLOCK_H +#define _ASM_SPINLOCK_H + +#include +#include + +/* + * Your basic SMP spinlocks, allowing only a single CPU anywhere + */ + +#define __raw_spin_is_locked(x) ((x)->lock != 0) +#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) +#define __raw_spin_unlock_wait(x) \ + do { cpu_relax(); } while ((x)->lock) + +/* + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * We make no fairness assumptions. They have a cost. + */ + +static inline void __raw_spin_lock(raw_spinlock_t *lock) +{ + unsigned int tmp; + + if (R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set noreorder # __raw_spin_lock \n" + "1: ll %1, %2 \n" + " bnez %1, 1b \n" + " li %1, 1 \n" + " sc %1, %0 \n" + " beqzl %1, 1b \n" + " nop \n" + " .set reorder \n" + : "=m" (lock->lock), "=&r" (tmp) + : "m" (lock->lock) + : "memory"); + } else { + __asm__ __volatile__( + " .set noreorder # __raw_spin_lock \n" + "1: ll %1, %2 \n" + " bnez %1, 2f \n" + " li %1, 1 \n" + " sc %1, %0 \n" + " beqz %1, 2f \n" + " nop \n" + " .subsection 2 \n" + "2: ll %1, %2 \n" + " bnez %1, 2b \n" + " li %1, 1 \n" + " b 1b \n" + " nop \n" + " .previous \n" + " .set reorder \n" + : "=m" (lock->lock), "=&r" (tmp) + : "m" (lock->lock) + : "memory"); + } + + smp_llsc_mb(); +} + +static inline void __raw_spin_unlock(raw_spinlock_t *lock) +{ + smp_mb(); + + __asm__ __volatile__( + " .set noreorder # __raw_spin_unlock \n" + " sw $0, %0 \n" + " .set\treorder \n" + : "=m" (lock->lock) + : "m" (lock->lock) + : "memory"); +} + +static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock) +{ + unsigned int temp, res; + + if (R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set noreorder # __raw_spin_trylock \n" + "1: ll %0, %3 \n" + " ori %2, %0, 1 \n" + " sc %2, %1 \n" + " beqzl %2, 1b \n" + " nop \n" + " andi %2, %0, 1 \n" + " .set reorder" + : "=&r" (temp), "=m" (lock->lock), "=&r" (res) + : "m" (lock->lock) + : "memory"); + } else { + __asm__ __volatile__( + " .set noreorder # __raw_spin_trylock \n" + "1: ll %0, %3 \n" + " ori %2, %0, 1 \n" + " sc %2, %1 \n" + " beqz %2, 2f \n" + " andi %2, %0, 1 \n" + " .subsection 2 \n" + "2: b 1b \n" + " nop \n" + " .previous \n" + " .set reorder" + : "=&r" (temp), "=m" (lock->lock), "=&r" (res) + : "m" (lock->lock) + : "memory"); + } + + smp_llsc_mb(); + + return res == 0; +} + +/* + * Read-write spinlocks, allowing multiple readers but only one writer. + * + * NOTE! it is quite common to have readers in interrupts but no interrupt + * writers. For those circumstances we can "mix" irq-safe locks - any writer + * needs to get a irq-safe write-lock, but readers can get non-irqsafe + * read-locks. + */ + +/* + * read_can_lock - would read_trylock() succeed? + * @lock: the rwlock in question. + */ +#define __raw_read_can_lock(rw) ((rw)->lock >= 0) + +/* + * write_can_lock - would write_trylock() succeed? + * @lock: the rwlock in question. + */ +#define __raw_write_can_lock(rw) (!(rw)->lock) + +static inline void __raw_read_lock(raw_rwlock_t *rw) +{ + unsigned int tmp; + + if (R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set noreorder # __raw_read_lock \n" + "1: ll %1, %2 \n" + " bltz %1, 1b \n" + " addu %1, 1 \n" + " sc %1, %0 \n" + " beqzl %1, 1b \n" + " nop \n" + " .set reorder \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } else { + __asm__ __volatile__( + " .set noreorder # __raw_read_lock \n" + "1: ll %1, %2 \n" + " bltz %1, 2f \n" + " addu %1, 1 \n" + " sc %1, %0 \n" + " beqz %1, 1b \n" + " nop \n" + " .subsection 2 \n" + "2: ll %1, %2 \n" + " bltz %1, 2b \n" + " addu %1, 1 \n" + " b 1b \n" + " nop \n" + " .previous \n" + " .set reorder \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } + + smp_llsc_mb(); +} + +/* Note the use of sub, not subu which will make the kernel die with an + overflow exception if we ever try to unlock an rwlock that is already + unlocked or is being held by a writer. */ +static inline void __raw_read_unlock(raw_rwlock_t *rw) +{ + unsigned int tmp; + + smp_llsc_mb(); + + if (R10000_LLSC_WAR) { + __asm__ __volatile__( + "1: ll %1, %2 # __raw_read_unlock \n" + " sub %1, 1 \n" + " sc %1, %0 \n" + " beqzl %1, 1b \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } else { + __asm__ __volatile__( + " .set noreorder # __raw_read_unlock \n" + "1: ll %1, %2 \n" + " sub %1, 1 \n" + " sc %1, %0 \n" + " beqz %1, 2f \n" + " nop \n" + " .subsection 2 \n" + "2: b 1b \n" + " nop \n" + " .previous \n" + " .set reorder \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } +} + +static inline void __raw_write_lock(raw_rwlock_t *rw) +{ + unsigned int tmp; + + if (R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set noreorder # __raw_write_lock \n" + "1: ll %1, %2 \n" + " bnez %1, 1b \n" + " lui %1, 0x8000 \n" + " sc %1, %0 \n" + " beqzl %1, 1b \n" + " nop \n" + " .set reorder \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } else { + __asm__ __volatile__( + " .set noreorder # __raw_write_lock \n" + "1: ll %1, %2 \n" + " bnez %1, 2f \n" + " lui %1, 0x8000 \n" + " sc %1, %0 \n" + " beqz %1, 2f \n" + " nop \n" + " .subsection 2 \n" + "2: ll %1, %2 \n" + " bnez %1, 2b \n" + " lui %1, 0x8000 \n" + " b 1b \n" + " nop \n" + " .previous \n" + " .set reorder \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } + + smp_llsc_mb(); +} + +static inline void __raw_write_unlock(raw_rwlock_t *rw) +{ + smp_mb(); + + __asm__ __volatile__( + " # __raw_write_unlock \n" + " sw $0, %0 \n" + : "=m" (rw->lock) + : "m" (rw->lock) + : "memory"); +} + +static inline int __raw_read_trylock(raw_rwlock_t *rw) +{ + unsigned int tmp; + int ret; + + if (R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set noreorder # __raw_read_trylock \n" + " li %2, 0 \n" + "1: ll %1, %3 \n" + " bltz %1, 2f \n" + " addu %1, 1 \n" + " sc %1, %0 \n" + " .set reorder \n" + " beqzl %1, 1b \n" + " nop \n" + __WEAK_LLSC_MB + " li %2, 1 \n" + "2: \n" + : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) + : "m" (rw->lock) + : "memory"); + } else { + __asm__ __volatile__( + " .set noreorder # __raw_read_trylock \n" + " li %2, 0 \n" + "1: ll %1, %3 \n" + " bltz %1, 2f \n" + " addu %1, 1 \n" + " sc %1, %0 \n" + " beqz %1, 1b \n" + " nop \n" + " .set reorder \n" + __WEAK_LLSC_MB + " li %2, 1 \n" + "2: \n" + : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) + : "m" (rw->lock) + : "memory"); + } + + return ret; +} + +static inline int __raw_write_trylock(raw_rwlock_t *rw) +{ + unsigned int tmp; + int ret; + + if (R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set noreorder # __raw_write_trylock \n" + " li %2, 0 \n" + "1: ll %1, %3 \n" + " bnez %1, 2f \n" + " lui %1, 0x8000 \n" + " sc %1, %0 \n" + " beqzl %1, 1b \n" + " nop \n" + __WEAK_LLSC_MB + " li %2, 1 \n" + " .set reorder \n" + "2: \n" + : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) + : "m" (rw->lock) + : "memory"); + } else { + __asm__ __volatile__( + " .set noreorder # __raw_write_trylock \n" + " li %2, 0 \n" + "1: ll %1, %3 \n" + " bnez %1, 2f \n" + " lui %1, 0x8000 \n" + " sc %1, %0 \n" + " beqz %1, 3f \n" + " li %2, 1 \n" + "2: \n" + __WEAK_LLSC_MB + " .subsection 2 \n" + "3: b 1b \n" + " li %2, 0 \n" + " .previous \n" + " .set reorder \n" + : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) + : "m" (rw->lock) + : "memory"); + } + + return ret; +} + + +#define _raw_spin_relax(lock) cpu_relax() +#define _raw_read_relax(lock) cpu_relax() +#define _raw_write_relax(lock) cpu_relax() + +#endif /* _ASM_SPINLOCK_H */ diff --git a/arch/mips/include/asm/spinlock_types.h b/arch/mips/include/asm/spinlock_types.h new file mode 100644 index 00000000000..ce26c5048b1 --- /dev/null +++ b/arch/mips/include/asm/spinlock_types.h @@ -0,0 +1,20 @@ +#ifndef _ASM_SPINLOCK_TYPES_H +#define _ASM_SPINLOCK_TYPES_H + +#ifndef __LINUX_SPINLOCK_TYPES_H +# error "please don't include this file directly" +#endif + +typedef struct { + volatile unsigned int lock; +} raw_spinlock_t; + +#define __RAW_SPIN_LOCK_UNLOCKED { 0 } + +typedef struct { + volatile unsigned int lock; +} raw_rwlock_t; + +#define __RAW_RW_LOCK_UNLOCKED { 0 } + +#endif diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h new file mode 100644 index 00000000000..4c37c4e5f72 --- /dev/null +++ b/arch/mips/include/asm/stackframe.h @@ -0,0 +1,574 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 99, 2001 Ralf Baechle + * Copyright (C) 1994, 1995, 1996 Paul M. Antoine. + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2007 Maciej W. Rozycki + */ +#ifndef _ASM_STACKFRAME_H +#define _ASM_STACKFRAME_H + +#include + +#include +#include +#include +#include + +/* + * For SMTC kernel, global IE should be left set, and interrupts + * controlled exclusively via IXMT. + */ +#ifdef CONFIG_MIPS_MT_SMTC +#define STATMASK 0x1e +#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) +#define STATMASK 0x3f +#else +#define STATMASK 0x1f +#endif + +#ifdef CONFIG_MIPS_MT_SMTC +#include +#endif /* CONFIG_MIPS_MT_SMTC */ + + .macro SAVE_AT + .set push + .set noat + LONG_S $1, PT_R1(sp) + .set pop + .endm + + .macro SAVE_TEMP +#ifdef CONFIG_CPU_HAS_SMARTMIPS + mflhxu v1 + LONG_S v1, PT_LO(sp) + mflhxu v1 + LONG_S v1, PT_HI(sp) + mflhxu v1 + LONG_S v1, PT_ACX(sp) +#else + mfhi v1 + LONG_S v1, PT_HI(sp) + mflo v1 + LONG_S v1, PT_LO(sp) +#endif +#ifdef CONFIG_32BIT + LONG_S $8, PT_R8(sp) + LONG_S $9, PT_R9(sp) +#endif + LONG_S $10, PT_R10(sp) + LONG_S $11, PT_R11(sp) + LONG_S $12, PT_R12(sp) + LONG_S $13, PT_R13(sp) + LONG_S $14, PT_R14(sp) + LONG_S $15, PT_R15(sp) + LONG_S $24, PT_R24(sp) + .endm + + .macro SAVE_STATIC + LONG_S $16, PT_R16(sp) + LONG_S $17, PT_R17(sp) + LONG_S $18, PT_R18(sp) + LONG_S $19, PT_R19(sp) + LONG_S $20, PT_R20(sp) + LONG_S $21, PT_R21(sp) + LONG_S $22, PT_R22(sp) + LONG_S $23, PT_R23(sp) + LONG_S $30, PT_R30(sp) + .endm + +#ifdef CONFIG_SMP +#ifdef CONFIG_MIPS_MT_SMTC +#define PTEBASE_SHIFT 19 /* TCBIND */ +#else +#define PTEBASE_SHIFT 23 /* CONTEXT */ +#endif + .macro get_saved_sp /* SMP variation */ +#ifdef CONFIG_MIPS_MT_SMTC + mfc0 k0, CP0_TCBIND +#else + MFC0 k0, CP0_CONTEXT +#endif +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) + lui k1, %hi(kernelsp) +#else + lui k1, %highest(kernelsp) + daddiu k1, %higher(kernelsp) + dsll k1, 16 + daddiu k1, %hi(kernelsp) + dsll k1, 16 +#endif + LONG_SRL k0, PTEBASE_SHIFT + LONG_ADDU k1, k0 + LONG_L k1, %lo(kernelsp)(k1) + .endm + + .macro set_saved_sp stackp temp temp2 +#ifdef CONFIG_MIPS_MT_SMTC + mfc0 \temp, CP0_TCBIND +#else + MFC0 \temp, CP0_CONTEXT +#endif + LONG_SRL \temp, PTEBASE_SHIFT + LONG_S \stackp, kernelsp(\temp) + .endm +#else + .macro get_saved_sp /* Uniprocessor variation */ +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) + lui k1, %hi(kernelsp) +#else + lui k1, %highest(kernelsp) + daddiu k1, %higher(kernelsp) + dsll k1, k1, 16 + daddiu k1, %hi(kernelsp) + dsll k1, k1, 16 +#endif + LONG_L k1, %lo(kernelsp)(k1) + .endm + + .macro set_saved_sp stackp temp temp2 + LONG_S \stackp, kernelsp + .endm +#endif + + .macro SAVE_SOME + .set push + .set noat + .set reorder + mfc0 k0, CP0_STATUS + sll k0, 3 /* extract cu0 bit */ + .set noreorder + bltz k0, 8f + move k1, sp + .set reorder + /* Called from user mode, new stack. */ + get_saved_sp +#ifndef CONFIG_CPU_DADDI_WORKAROUNDS +8: move k0, sp + PTR_SUBU sp, k1, PT_SIZE +#else + .set at=k0 +8: PTR_SUBU k1, PT_SIZE + .set noat + move k0, sp + move sp, k1 +#endif + LONG_S k0, PT_R29(sp) + LONG_S $3, PT_R3(sp) + /* + * You might think that you don't need to save $0, + * but the FPU emulator and gdb remote debug stub + * need it to operate correctly + */ + LONG_S $0, PT_R0(sp) + mfc0 v1, CP0_STATUS + LONG_S $2, PT_R2(sp) + LONG_S v1, PT_STATUS(sp) +#ifdef CONFIG_MIPS_MT_SMTC + /* + * Ideally, these instructions would be shuffled in + * to cover the pipeline delay. + */ + .set mips32 + mfc0 v1, CP0_TCSTATUS + .set mips0 + LONG_S v1, PT_TCSTATUS(sp) +#endif /* CONFIG_MIPS_MT_SMTC */ + LONG_S $4, PT_R4(sp) + mfc0 v1, CP0_CAUSE + LONG_S $5, PT_R5(sp) + LONG_S v1, PT_CAUSE(sp) + LONG_S $6, PT_R6(sp) + MFC0 v1, CP0_EPC + LONG_S $7, PT_R7(sp) +#ifdef CONFIG_64BIT + LONG_S $8, PT_R8(sp) + LONG_S $9, PT_R9(sp) +#endif + LONG_S v1, PT_EPC(sp) + LONG_S $25, PT_R25(sp) + LONG_S $28, PT_R28(sp) + LONG_S $31, PT_R31(sp) + ori $28, sp, _THREAD_MASK + xori $28, _THREAD_MASK + .set pop + .endm + + .macro SAVE_ALL + SAVE_SOME + SAVE_AT + SAVE_TEMP + SAVE_STATIC + .endm + + .macro RESTORE_AT + .set push + .set noat + LONG_L $1, PT_R1(sp) + .set pop + .endm + + .macro RESTORE_TEMP +#ifdef CONFIG_CPU_HAS_SMARTMIPS + LONG_L $24, PT_ACX(sp) + mtlhx $24 + LONG_L $24, PT_HI(sp) + mtlhx $24 + LONG_L $24, PT_LO(sp) + mtlhx $24 +#else + LONG_L $24, PT_LO(sp) + mtlo $24 + LONG_L $24, PT_HI(sp) + mthi $24 +#endif +#ifdef CONFIG_32BIT + LONG_L $8, PT_R8(sp) + LONG_L $9, PT_R9(sp) +#endif + LONG_L $10, PT_R10(sp) + LONG_L $11, PT_R11(sp) + LONG_L $12, PT_R12(sp) + LONG_L $13, PT_R13(sp) + LONG_L $14, PT_R14(sp) + LONG_L $15, PT_R15(sp) + LONG_L $24, PT_R24(sp) + .endm + + .macro RESTORE_STATIC + LONG_L $16, PT_R16(sp) + LONG_L $17, PT_R17(sp) + LONG_L $18, PT_R18(sp) + LONG_L $19, PT_R19(sp) + LONG_L $20, PT_R20(sp) + LONG_L $21, PT_R21(sp) + LONG_L $22, PT_R22(sp) + LONG_L $23, PT_R23(sp) + LONG_L $30, PT_R30(sp) + .endm + +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + + .macro RESTORE_SOME + .set push + .set reorder + .set noat + mfc0 a0, CP0_STATUS + li v1, 0xff00 + ori a0, STATMASK + xori a0, STATMASK + mtc0 a0, CP0_STATUS + and a0, v1 + LONG_L v0, PT_STATUS(sp) + nor v1, $0, v1 + and v0, v1 + or v0, a0 + mtc0 v0, CP0_STATUS + LONG_L $31, PT_R31(sp) + LONG_L $28, PT_R28(sp) + LONG_L $25, PT_R25(sp) + LONG_L $7, PT_R7(sp) + LONG_L $6, PT_R6(sp) + LONG_L $5, PT_R5(sp) + LONG_L $4, PT_R4(sp) + LONG_L $3, PT_R3(sp) + LONG_L $2, PT_R2(sp) + .set pop + .endm + + .macro RESTORE_SP_AND_RET + .set push + .set noreorder + LONG_L k0, PT_EPC(sp) + LONG_L sp, PT_R29(sp) + jr k0 + rfe + .set pop + .endm + +#else + .macro RESTORE_SOME + .set push + .set reorder + .set noat +#ifdef CONFIG_MIPS_MT_SMTC + .set mips32r2 + /* + * We need to make sure the read-modify-write + * of Status below isn't perturbed by an interrupt + * or cross-TC access, so we need to do at least a DMT, + * protected by an interrupt-inhibit. But setting IXMT + * also creates a few-cycle window where an IPI could + * be queued and not be detected before potentially + * returning to a WAIT or user-mode loop. It must be + * replayed. + * + * We're in the middle of a context switch, and + * we can't dispatch it directly without trashing + * some registers, so we'll try to detect this unlikely + * case and program a software interrupt in the VPE, + * as would be done for a cross-VPE IPI. To accomodate + * the handling of that case, we're doing a DVPE instead + * of just a DMT here to protect against other threads. + * This is a lot of cruft to cover a tiny window. + * If you can find a better design, implement it! + * + */ + mfc0 v0, CP0_TCSTATUS + ori v0, TCSTATUS_IXMT + mtc0 v0, CP0_TCSTATUS + _ehb + DVPE 5 # dvpe a1 + jal mips_ihb +#endif /* CONFIG_MIPS_MT_SMTC */ + mfc0 a0, CP0_STATUS + ori a0, STATMASK + xori a0, STATMASK + mtc0 a0, CP0_STATUS + li v1, 0xff00 + and a0, v1 + LONG_L v0, PT_STATUS(sp) + nor v1, $0, v1 + and v0, v1 + or v0, a0 + mtc0 v0, CP0_STATUS +#ifdef CONFIG_MIPS_MT_SMTC +/* + * Only after EXL/ERL have been restored to status can we + * restore TCStatus.IXMT. + */ + LONG_L v1, PT_TCSTATUS(sp) + _ehb + mfc0 a0, CP0_TCSTATUS + andi v1, TCSTATUS_IXMT + bnez v1, 0f + +/* + * We'd like to detect any IPIs queued in the tiny window + * above and request an software interrupt to service them + * when we ERET. + * + * Computing the offset into the IPIQ array of the executing + * TC's IPI queue in-line would be tedious. We use part of + * the TCContext register to hold 16 bits of offset that we + * can add in-line to find the queue head. + */ + mfc0 v0, CP0_TCCONTEXT + la a2, IPIQ + srl v0, v0, 16 + addu a2, a2, v0 + LONG_L v0, 0(a2) + beqz v0, 0f +/* + * If we have a queue, provoke dispatch within the VPE by setting C_SW1 + */ + mfc0 v0, CP0_CAUSE + ori v0, v0, C_SW1 + mtc0 v0, CP0_CAUSE +0: + /* + * This test should really never branch but + * let's be prudent here. Having atomized + * the shared register modifications, we can + * now EVPE, and must do so before interrupts + * are potentially re-enabled. + */ + andi a1, a1, MVPCONTROL_EVP + beqz a1, 1f + evpe +1: + /* We know that TCStatua.IXMT should be set from above */ + xori a0, a0, TCSTATUS_IXMT + or a0, a0, v1 + mtc0 a0, CP0_TCSTATUS + _ehb + + .set mips0 +#endif /* CONFIG_MIPS_MT_SMTC */ + LONG_L v1, PT_EPC(sp) + MTC0 v1, CP0_EPC + LONG_L $31, PT_R31(sp) + LONG_L $28, PT_R28(sp) + LONG_L $25, PT_R25(sp) +#ifdef CONFIG_64BIT + LONG_L $8, PT_R8(sp) + LONG_L $9, PT_R9(sp) +#endif + LONG_L $7, PT_R7(sp) + LONG_L $6, PT_R6(sp) + LONG_L $5, PT_R5(sp) + LONG_L $4, PT_R4(sp) + LONG_L $3, PT_R3(sp) + LONG_L $2, PT_R2(sp) + .set pop + .endm + + .macro RESTORE_SP_AND_RET + LONG_L sp, PT_R29(sp) + .set mips3 + eret + .set mips0 + .endm + +#endif + + .macro RESTORE_SP + LONG_L sp, PT_R29(sp) + .endm + + .macro RESTORE_ALL + RESTORE_TEMP + RESTORE_STATIC + RESTORE_AT + RESTORE_SOME + RESTORE_SP + .endm + + .macro RESTORE_ALL_AND_RET + RESTORE_TEMP + RESTORE_STATIC + RESTORE_AT + RESTORE_SOME + RESTORE_SP_AND_RET + .endm + +/* + * Move to kernel mode and disable interrupts. + * Set cp0 enable bit as sign that we're running on the kernel stack + */ + .macro CLI +#if !defined(CONFIG_MIPS_MT_SMTC) + mfc0 t0, CP0_STATUS + li t1, ST0_CU0 | STATMASK + or t0, t1 + xori t0, STATMASK + mtc0 t0, CP0_STATUS +#else /* CONFIG_MIPS_MT_SMTC */ + /* + * For SMTC, we need to set privilege + * and disable interrupts only for the + * current TC, using the TCStatus register. + */ + mfc0 t0, CP0_TCSTATUS + /* Fortunately CU 0 is in the same place in both registers */ + /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */ + li t1, ST0_CU0 | 0x08001c00 + or t0, t1 + /* Clear TKSU, leave IXMT */ + xori t0, 0x00001800 + mtc0 t0, CP0_TCSTATUS + _ehb + /* We need to leave the global IE bit set, but clear EXL...*/ + mfc0 t0, CP0_STATUS + ori t0, ST0_EXL | ST0_ERL + xori t0, ST0_EXL | ST0_ERL + mtc0 t0, CP0_STATUS +#endif /* CONFIG_MIPS_MT_SMTC */ + irq_disable_hazard + .endm + +/* + * Move to kernel mode and enable interrupts. + * Set cp0 enable bit as sign that we're running on the kernel stack + */ + .macro STI +#if !defined(CONFIG_MIPS_MT_SMTC) + mfc0 t0, CP0_STATUS + li t1, ST0_CU0 | STATMASK + or t0, t1 + xori t0, STATMASK & ~1 + mtc0 t0, CP0_STATUS +#else /* CONFIG_MIPS_MT_SMTC */ + /* + * For SMTC, we need to set privilege + * and enable interrupts only for the + * current TC, using the TCStatus register. + */ + _ehb + mfc0 t0, CP0_TCSTATUS + /* Fortunately CU 0 is in the same place in both registers */ + /* Set TCU0, TKSU (for later inversion) and IXMT */ + li t1, ST0_CU0 | 0x08001c00 + or t0, t1 + /* Clear TKSU *and* IXMT */ + xori t0, 0x00001c00 + mtc0 t0, CP0_TCSTATUS + _ehb + /* We need to leave the global IE bit set, but clear EXL...*/ + mfc0 t0, CP0_STATUS + ori t0, ST0_EXL + xori t0, ST0_EXL + mtc0 t0, CP0_STATUS + /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */ +#endif /* CONFIG_MIPS_MT_SMTC */ + irq_enable_hazard + .endm + +/* + * Just move to kernel mode and leave interrupts as they are. Note + * for the R3000 this means copying the previous enable from IEp. + * Set cp0 enable bit as sign that we're running on the kernel stack + */ + .macro KMODE +#ifdef CONFIG_MIPS_MT_SMTC + /* + * This gets baroque in SMTC. We want to + * protect the non-atomic clearing of EXL + * with DMT/EMT, but we don't want to take + * an interrupt while DMT is still in effect. + */ + + /* KMODE gets invoked from both reorder and noreorder code */ + .set push + .set mips32r2 + .set noreorder + mfc0 v0, CP0_TCSTATUS + andi v1, v0, TCSTATUS_IXMT + ori v0, TCSTATUS_IXMT + mtc0 v0, CP0_TCSTATUS + _ehb + DMT 2 # dmt v0 + /* + * We don't know a priori if ra is "live" + */ + move t0, ra + jal mips_ihb + nop /* delay slot */ + move ra, t0 +#endif /* CONFIG_MIPS_MT_SMTC */ + mfc0 t0, CP0_STATUS + li t1, ST0_CU0 | (STATMASK & ~1) +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + andi t2, t0, ST0_IEP + srl t2, 2 + or t0, t2 +#endif + or t0, t1 + xori t0, STATMASK & ~1 + mtc0 t0, CP0_STATUS +#ifdef CONFIG_MIPS_MT_SMTC + _ehb + andi v0, v0, VPECONTROL_TE + beqz v0, 2f + nop /* delay slot */ + emt +2: + mfc0 v0, CP0_TCSTATUS + /* Clear IXMT, then OR in previous value */ + ori v0, TCSTATUS_IXMT + xori v0, TCSTATUS_IXMT + or v0, v1, v0 + mtc0 v0, CP0_TCSTATUS + /* + * irq_disable_hazard below should expand to EHB + * on 24K/34K CPUS + */ + .set pop +#endif /* CONFIG_MIPS_MT_SMTC */ + irq_disable_hazard + .endm + +#endif /* _ASM_STACKFRAME_H */ diff --git a/arch/mips/include/asm/stacktrace.h b/arch/mips/include/asm/stacktrace.h new file mode 100644 index 00000000000..0bf82818aa5 --- /dev/null +++ b/arch/mips/include/asm/stacktrace.h @@ -0,0 +1,48 @@ +#ifndef _ASM_STACKTRACE_H +#define _ASM_STACKTRACE_H + +#include + +#ifdef CONFIG_KALLSYMS +extern int raw_show_trace; +extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, + unsigned long pc, unsigned long *ra); +#else +#define raw_show_trace 1 +static inline unsigned long unwind_stack(struct task_struct *task, + unsigned long *sp, unsigned long pc, unsigned long *ra) +{ + return 0; +} +#endif + +static __always_inline void prepare_frametrace(struct pt_regs *regs) +{ +#ifndef CONFIG_KALLSYMS + /* + * Remove any garbage that may be in regs (specially func + * addresses) to avoid show_raw_backtrace() to report them + */ + memset(regs, 0, sizeof(*regs)); +#endif + __asm__ __volatile__( + ".set push\n\t" + ".set noat\n\t" +#ifdef CONFIG_64BIT + "1: dla $1, 1b\n\t" + "sd $1, %0\n\t" + "sd $29, %1\n\t" + "sd $31, %2\n\t" +#else + "1: la $1, 1b\n\t" + "sw $1, %0\n\t" + "sw $29, %1\n\t" + "sw $31, %2\n\t" +#endif + ".set pop\n\t" + : "=m" (regs->cp0_epc), + "=m" (regs->regs[29]), "=m" (regs->regs[31]) + : : "memory"); +} + +#endif /* _ASM_STACKTRACE_H */ diff --git a/arch/mips/include/asm/stat.h b/arch/mips/include/asm/stat.h new file mode 100644 index 00000000000..6e00f751ab6 --- /dev/null +++ b/arch/mips/include/asm/stat.h @@ -0,0 +1,132 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999, 2000 Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_STAT_H +#define _ASM_STAT_H + +#include + +#include + +#if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) + +struct stat { + unsigned st_dev; + long st_pad1[3]; /* Reserved for network id */ + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + unsigned st_rdev; + long st_pad2[2]; + off_t st_size; + long st_pad3; + /* + * Actually this should be timestruc_t st_atime, st_mtime and st_ctime + * but we don't have it under Linux. + */ + time_t st_atime; + long st_atime_nsec; + time_t st_mtime; + long st_mtime_nsec; + time_t st_ctime; + long st_ctime_nsec; + long st_blksize; + long st_blocks; + long st_pad4[14]; +}; + +/* + * This matches struct stat64 in glibc2.1, hence the absolutely insane + * amounts of padding around dev_t's. The memory layout is the same as of + * struct stat of the 64-bit kernel. + */ + +struct stat64 { + unsigned long st_dev; + unsigned long st_pad0[3]; /* Reserved for st_dev expansion */ + + unsigned long long st_ino; + + mode_t st_mode; + nlink_t st_nlink; + + uid_t st_uid; + gid_t st_gid; + + unsigned long st_rdev; + unsigned long st_pad1[3]; /* Reserved for st_rdev expansion */ + + long long st_size; + + /* + * Actually this should be timestruc_t st_atime, st_mtime and st_ctime + * but we don't have it under Linux. + */ + time_t st_atime; + unsigned long st_atime_nsec; /* Reserved for st_atime expansion */ + + time_t st_mtime; + unsigned long st_mtime_nsec; /* Reserved for st_mtime expansion */ + + time_t st_ctime; + unsigned long st_ctime_nsec; /* Reserved for st_ctime expansion */ + + unsigned long st_blksize; + unsigned long st_pad2; + + long long st_blocks; +}; + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ + +#if _MIPS_SIM == _MIPS_SIM_ABI64 + +/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +struct stat { + unsigned int st_dev; + unsigned int st_pad0[3]; /* Reserved for st_dev expansion */ + + unsigned long st_ino; + + mode_t st_mode; + nlink_t st_nlink; + + uid_t st_uid; + gid_t st_gid; + + unsigned int st_rdev; + unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */ + + off_t st_size; + + /* + * Actually this should be timestruc_t st_atime, st_mtime and st_ctime + * but we don't have it under Linux. + */ + unsigned int st_atime; + unsigned int st_atime_nsec; + + unsigned int st_mtime; + unsigned int st_mtime_nsec; + + unsigned int st_ctime; + unsigned int st_ctime_nsec; + + unsigned int st_blksize; + unsigned int st_pad2; + + unsigned long st_blocks; +}; + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ + +#define STAT_HAVE_NSEC 1 + +#endif /* _ASM_STAT_H */ diff --git a/arch/mips/include/asm/statfs.h b/arch/mips/include/asm/statfs.h new file mode 100644 index 00000000000..c3ddf973c1c --- /dev/null +++ b/arch/mips/include/asm/statfs.h @@ -0,0 +1,96 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 by Ralf Baechle + */ +#ifndef _ASM_STATFS_H +#define _ASM_STATFS_H + +#include +#include + +#ifndef __KERNEL_STRICT_NAMES + +#include + +typedef __kernel_fsid_t fsid_t; + +#endif + +struct statfs { + long f_type; +#define f_fstyp f_type + long f_bsize; + long f_frsize; /* Fragment size - unsupported */ + long f_blocks; + long f_bfree; + long f_files; + long f_ffree; + long f_bavail; + + /* Linux specials */ + __kernel_fsid_t f_fsid; + long f_namelen; + long f_spare[6]; +}; + +#if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) + +/* + * Unlike the traditional version the LFAPI version has none of the ABI junk + */ +struct statfs64 { + __u32 f_type; + __u32 f_bsize; + __u32 f_frsize; /* Fragment size - unsupported */ + __u32 __pad; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_files; + __u64 f_ffree; + __u64 f_bavail; + __kernel_fsid_t f_fsid; + __u32 f_namelen; + __u32 f_spare[6]; +}; + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ + +#if _MIPS_SIM == _MIPS_SIM_ABI64 + +struct statfs64 { /* Same as struct statfs */ + long f_type; + long f_bsize; + long f_frsize; /* Fragment size - unsupported */ + long f_blocks; + long f_bfree; + long f_files; + long f_ffree; + long f_bavail; + + /* Linux specials */ + __kernel_fsid_t f_fsid; + long f_namelen; + long f_spare[6]; +}; + +struct compat_statfs64 { + __u32 f_type; + __u32 f_bsize; + __u32 f_frsize; /* Fragment size - unsupported */ + __u32 __pad; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_files; + __u64 f_ffree; + __u64 f_bavail; + __kernel_fsid_t f_fsid; + __u32 f_namelen; + __u32 f_spare[6]; +}; + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ + +#endif /* _ASM_STATFS_H */ diff --git a/arch/mips/include/asm/string.h b/arch/mips/include/asm/string.h new file mode 100644 index 00000000000..436e3ad352d --- /dev/null +++ b/arch/mips/include/asm/string.h @@ -0,0 +1,143 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1994, 95, 96, 97, 98, 2000, 01 Ralf Baechle + * Copyright (c) 2000 by Silicon Graphics, Inc. + * Copyright (c) 2001 MIPS Technologies, Inc. + */ +#ifndef _ASM_STRING_H +#define _ASM_STRING_H + + +/* + * Most of the inline functions are rather naive implementations so I just + * didn't bother updating them for 64-bit ... + */ +#ifdef CONFIG_32BIT + +#ifndef IN_STRING_C + +#define __HAVE_ARCH_STRCPY +static __inline__ char *strcpy(char *__dest, __const__ char *__src) +{ + char *__xdest = __dest; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tlbu\t$1,(%1)\n\t" + "addiu\t%1,1\n\t" + "sb\t$1,(%0)\n\t" + "bnez\t$1,1b\n\t" + "addiu\t%0,1\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (__dest), "=r" (__src) + : "0" (__dest), "1" (__src) + : "memory"); + + return __xdest; +} + +#define __HAVE_ARCH_STRNCPY +static __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n) +{ + char *__xdest = __dest; + + if (__n == 0) + return __xdest; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tlbu\t$1,(%1)\n\t" + "subu\t%2,1\n\t" + "sb\t$1,(%0)\n\t" + "beqz\t$1,2f\n\t" + "addiu\t%0,1\n\t" + "bnez\t%2,1b\n\t" + "addiu\t%1,1\n" + "2:\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (__dest), "=r" (__src), "=r" (__n) + : "0" (__dest), "1" (__src), "2" (__n) + : "memory"); + + return __xdest; +} + +#define __HAVE_ARCH_STRCMP +static __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct) +{ + int __res; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "lbu\t%2,(%0)\n" + "1:\tlbu\t$1,(%1)\n\t" + "addiu\t%0,1\n\t" + "bne\t$1,%2,2f\n\t" + "addiu\t%1,1\n\t" + "bnez\t%2,1b\n\t" + "lbu\t%2,(%0)\n\t" +#if defined(CONFIG_CPU_R3000) + "nop\n\t" +#endif + "move\t%2,$1\n" + "2:\tsubu\t%2,$1\n" + "3:\t.set\tat\n\t" + ".set\treorder" + : "=r" (__cs), "=r" (__ct), "=r" (__res) + : "0" (__cs), "1" (__ct)); + + return __res; +} + +#endif /* !defined(IN_STRING_C) */ + +#define __HAVE_ARCH_STRNCMP +static __inline__ int +strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count) +{ + int __res; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tlbu\t%3,(%0)\n\t" + "beqz\t%2,2f\n\t" + "lbu\t$1,(%1)\n\t" + "subu\t%2,1\n\t" + "bne\t$1,%3,3f\n\t" + "addiu\t%0,1\n\t" + "bnez\t%3,1b\n\t" + "addiu\t%1,1\n" + "2:\n\t" +#if defined(CONFIG_CPU_R3000) + "nop\n\t" +#endif + "move\t%3,$1\n" + "3:\tsubu\t%3,$1\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res) + : "0" (__cs), "1" (__ct), "2" (__count)); + + return __res; +} +#endif /* CONFIG_32BIT */ + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *__s, int __c, size_t __count); + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *__to, __const__ void *__from, size_t __n); + +#define __HAVE_ARCH_MEMMOVE +extern void *memmove(void *__dest, __const__ void *__src, size_t __n); + +#endif /* _ASM_STRING_H */ diff --git a/arch/mips/include/asm/suspend.h b/arch/mips/include/asm/suspend.h new file mode 100644 index 00000000000..2562f8f9be0 --- /dev/null +++ b/arch/mips/include/asm/suspend.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SUSPEND_H +#define __ASM_SUSPEND_H + +/* Somewhen... Maybe :-) */ + +#endif /* __ASM_SUSPEND_H */ diff --git a/arch/mips/include/asm/sysmips.h b/arch/mips/include/asm/sysmips.h new file mode 100644 index 00000000000..4f47b7d6a5f --- /dev/null +++ b/arch/mips/include/asm/sysmips.h @@ -0,0 +1,25 @@ +/* + * Definitions for the MIPS sysmips(2) call + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995 by Ralf Baechle + */ +#ifndef _ASM_SYSMIPS_H +#define _ASM_SYSMIPS_H + +/* + * Commands for the sysmips(2) call + * + * sysmips(2) is deprecated - though some existing software uses it. + * We only support the following commands. + */ +#define SETNAME 1 /* set hostname */ +#define FLUSH_CACHE 3 /* writeback and invalidate caches */ +#define MIPS_FIXADE 7 /* control address error fixing */ +#define MIPS_RDNVRAM 10 /* read NVRAM */ +#define MIPS_ATOMIC_SET 2001 /* atomically set variable */ + +#endif /* _ASM_SYSMIPS_H */ diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h new file mode 100644 index 00000000000..a944eda4faf --- /dev/null +++ b/arch/mips/include/asm/system.h @@ -0,0 +1,220 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle + * Copyright (C) 1996 by Paul M. Antoine + * Copyright (C) 1999 Silicon Graphics + * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#ifndef _ASM_SYSTEM_H +#define _ASM_SYSTEM_H + +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* + * switch_to(n) should switch tasks to task nr n, first + * checking that n isn't the current task, in which case it does nothing. + */ +extern asmlinkage void *resume(void *last, void *next, void *next_ti); + +struct task_struct; + +#ifdef CONFIG_MIPS_MT_FPAFF + +/* + * Handle the scheduler resume end of FPU affinity management. We do this + * inline to try to keep the overhead down. If we have been forced to run on + * a "CPU" with an FPU because of a previous high level of FP computation, + * but did not actually use the FPU during the most recent time-slice (CU1 + * isn't set), we undo the restriction on cpus_allowed. + * + * We're not calling set_cpus_allowed() here, because we have no need to + * force prompt migration - we're already switching the current CPU to a + * different thread. + */ + +#define __mips_mt_fpaff_switch_to(prev) \ +do { \ + struct thread_info *__prev_ti = task_thread_info(prev); \ + \ + if (cpu_has_fpu && \ + test_ti_thread_flag(__prev_ti, TIF_FPUBOUND) && \ + (!(KSTK_STATUS(prev) & ST0_CU1))) { \ + clear_ti_thread_flag(__prev_ti, TIF_FPUBOUND); \ + prev->cpus_allowed = prev->thread.user_cpus_allowed; \ + } \ + next->thread.emulated_fp = 0; \ +} while(0) + +#else +#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0) +#endif + +#define switch_to(prev, next, last) \ +do { \ + __mips_mt_fpaff_switch_to(prev); \ + if (cpu_has_dsp) \ + __save_dsp(prev); \ + (last) = resume(prev, next, task_thread_info(next)); \ +} while (0) + +#define finish_arch_switch(prev) \ +do { \ + if (cpu_has_dsp) \ + __restore_dsp(current); \ + if (cpu_has_userlocal) \ + write_c0_userlocal(current_thread_info()->tp_value); \ +} while (0) + +static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) +{ + __u32 retval; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long dummy; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %3 # xchg_u32 \n" + " .set mips0 \n" + " move %2, %z4 \n" + " .set mips3 \n" + " sc %2, %1 \n" + " beqzl %2, 1b \n" + " .set mips0 \n" + : "=&r" (retval), "=m" (*m), "=&r" (dummy) + : "R" (*m), "Jr" (val) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long dummy; + + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %3 # xchg_u32 \n" + " .set mips0 \n" + " move %2, %z4 \n" + " .set mips3 \n" + " sc %2, %1 \n" + " beqz %2, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (retval), "=m" (*m), "=&r" (dummy) + : "R" (*m), "Jr" (val) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + retval = *m; + *m = val; + raw_local_irq_restore(flags); /* implies memory barrier */ + } + + smp_llsc_mb(); + + return retval; +} + +#ifdef CONFIG_64BIT +static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val) +{ + __u64 retval; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + unsigned long dummy; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %3 # xchg_u64 \n" + " move %2, %z4 \n" + " scd %2, %1 \n" + " beqzl %2, 1b \n" + " .set mips0 \n" + : "=&r" (retval), "=m" (*m), "=&r" (dummy) + : "R" (*m), "Jr" (val) + : "memory"); + } else if (cpu_has_llsc) { + unsigned long dummy; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %3 # xchg_u64 \n" + " move %2, %z4 \n" + " scd %2, %1 \n" + " beqz %2, 2f \n" + " .subsection 2 \n" + "2: b 1b \n" + " .previous \n" + " .set mips0 \n" + : "=&r" (retval), "=m" (*m), "=&r" (dummy) + : "R" (*m), "Jr" (val) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + retval = *m; + *m = val; + raw_local_irq_restore(flags); /* implies memory barrier */ + } + + smp_llsc_mb(); + + return retval; +} +#else +extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val); +#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels +#endif + +/* This function doesn't exist, so you'll get a linker error + if something tries to do an invalid xchg(). */ +extern void __xchg_called_with_bad_pointer(void); + +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +{ + switch (size) { + case 4: + return __xchg_u32(ptr, x); + case 8: + return __xchg_u64(ptr, x); + } + __xchg_called_with_bad_pointer(); + return x; +} + +#define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) + +extern void set_handler(unsigned long offset, void *addr, unsigned long len); +extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len); + +typedef void (*vi_handler_t)(void); +extern void *set_vi_handler(int n, vi_handler_t addr); + +extern void *set_except_vector(int n, void *addr); +extern unsigned long ebase; +extern void per_cpu_trap_init(void); + +/* + * See include/asm-ia64/system.h; prevents deadlock on SMP + * systems. + */ +#define __ARCH_WANT_UNLOCKED_CTXSW + +extern unsigned long arch_align_stack(unsigned long sp); + +#endif /* _ASM_SYSTEM_H */ diff --git a/arch/mips/include/asm/termbits.h b/arch/mips/include/asm/termbits.h new file mode 100644 index 00000000000..c83c68444e8 --- /dev/null +++ b/arch/mips/include/asm/termbits.h @@ -0,0 +1,226 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 99, 2001, 06 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef _ASM_TERMBITS_H +#define _ASM_TERMBITS_H + +#include + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +/* + * The ABI says nothing about NCC but seems to use NCCS as + * replacement for it in struct termio + */ +#define NCCS 23 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ +}; + +struct termios2 { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +/* c_cc characters */ +#define VINTR 0 /* Interrupt character [ISIG]. */ +#define VQUIT 1 /* Quit character [ISIG]. */ +#define VERASE 2 /* Erase character [ICANON]. */ +#define VKILL 3 /* Kill-line character [ICANON]. */ +#define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */ +#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */ +#define VEOL2 6 /* Second EOL character [ICANON]. */ +#define VSWTC 7 /* ??? */ +#define VSWTCH VSWTC +#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */ +#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */ +#define VSUSP 10 /* Suspend character [ISIG]. */ +#if 0 +/* + * VDSUSP is not supported + */ +#define VDSUSP 11 /* Delayed suspend character [ISIG]. */ +#endif +#define VREPRINT 12 /* Reprint-line character [ICANON]. */ +#define VDISCARD 13 /* Discard character [IEXTEN]. */ +#define VWERASE 14 /* Word-erase character [ICANON]. */ +#define VLNEXT 15 /* Literal-next character [IEXTEN]. */ +#define VEOF 16 /* End-of-file character [ICANON]. */ +#define VEOL 17 /* End-of-line character [ICANON]. */ + +/* c_iflag bits */ +#define IGNBRK 0000001 /* Ignore break condition. */ +#define BRKINT 0000002 /* Signal interrupt on break. */ +#define IGNPAR 0000004 /* Ignore characters with parity errors. */ +#define PARMRK 0000010 /* Mark parity and framing errors. */ +#define INPCK 0000020 /* Enable input parity check. */ +#define ISTRIP 0000040 /* Strip 8th bit off characters. */ +#define INLCR 0000100 /* Map NL to CR on input. */ +#define IGNCR 0000200 /* Ignore CR. */ +#define ICRNL 0000400 /* Map CR to NL on input. */ +#define IUCLC 0001000 /* Map upper case to lower case on input. */ +#define IXON 0002000 /* Enable start/stop output control. */ +#define IXANY 0004000 /* Any character will restart after stop. */ +#define IXOFF 0010000 /* Enable start/stop input control. */ +#define IMAXBEL 0020000 /* Ring bell when input queue is full. */ +#define IUTF8 0040000 /* Input is UTF-8 */ + +/* c_oflag bits */ +#define OPOST 0000001 /* Perform output processing. */ +#define OLCUC 0000002 /* Map lower case to upper case on output. */ +#define ONLCR 0000004 /* Map NL to CR-NL on output. */ +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#define NLDLY 0000400 +#define NL0 0000000 +#define NL1 0000400 +#define CRDLY 0003000 +#define CR0 0000000 +#define CR1 0001000 +#define CR2 0002000 +#define CR3 0003000 +#define TABDLY 0014000 +#define TAB0 0000000 +#define TAB1 0004000 +#define TAB2 0010000 +#define TAB3 0014000 +#define XTABS 0014000 +#define BSDLY 0020000 +#define BS0 0000000 +#define BS1 0020000 +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 +#define FFDLY 0100000 +#define FF0 0000000 +#define FF1 0100000 +/* +#define PAGEOUT ??? +#define WRAP ??? + */ + +/* c_cflag bit meaning */ +#define CBAUD 0010017 +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#define EXTA B19200 +#define EXTB B38400 +#define CSIZE 0000060 /* Number of bits per byte (mask). */ +#define CS5 0000000 /* 5 bits per byte. */ +#define CS6 0000020 /* 6 bits per byte. */ +#define CS7 0000040 /* 7 bits per byte. */ +#define CS8 0000060 /* 8 bits per byte. */ +#define CSTOPB 0000100 /* Two stop bits instead of one. */ +#define CREAD 0000200 /* Enable receiver. */ +#define PARENB 0000400 /* Parity enable. */ +#define PARODD 0001000 /* Odd parity instead of even. */ +#define HUPCL 0002000 /* Hang up on last close. */ +#define CLOCAL 0004000 /* Ignore modem status lines. */ +#define CBAUDEX 0010000 +#define BOTHER 0010000 +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define CIBAUD 002003600000 /* input baud rate */ +#define CMSPAR 010000000000 /* mark or space (stick) parity */ +#define CRTSCTS 020000000000 /* flow control */ + +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + +/* c_lflag bits */ +#define ISIG 0000001 /* Enable signals. */ +#define ICANON 0000002 /* Do erase and kill processing. */ +#define XCASE 0000004 +#define ECHO 0000010 /* Enable echo. */ +#define ECHOE 0000020 /* Visual erase for ERASE. */ +#define ECHOK 0000040 /* Echo NL after KILL. */ +#define ECHONL 0000100 /* Echo NL even if ECHO is off. */ +#define NOFLSH 0000200 /* Disable flush after interrupt. */ +#define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */ +#define ECHOCTL 0001000 /* Echo control characters as ^X. */ +#define ECHOPRT 0002000 /* Hardcopy visual erase. */ +#define ECHOKE 0004000 /* Visual erase for KILL. */ +#define FLUSHO 0020000 +#define PENDIN 0040000 /* Retype pending input (state). */ +#define TOSTOP 0100000 /* Send SIGTTOU for background output. */ +#define ITOSTOP TOSTOP + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 /* Suspend output. */ +#define TCOON 1 /* Restart suspended output. */ +#define TCIOFF 2 /* Send a STOP character. */ +#define TCION 3 /* Send a START character. */ + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 /* Discard data received but not yet read. */ +#define TCOFLUSH 1 /* Discard data written but not yet sent. */ +#define TCIOFLUSH 2 /* Discard all pending data. */ + +/* tcsetattr uses these */ +#define TCSANOW TCSETS /* Change immediately. */ +#define TCSADRAIN TCSETSW /* Change when pending output is written. */ +#define TCSAFLUSH TCSETSF /* Flush pending input before changing. */ + +#endif /* _ASM_TERMBITS_H */ diff --git a/arch/mips/include/asm/termios.h b/arch/mips/include/asm/termios.h new file mode 100644 index 00000000000..a275661fa7e --- /dev/null +++ b/arch/mips/include/asm/termios.h @@ -0,0 +1,132 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000, 2001 Silicon Graphics, Inc. + */ +#ifndef _ASM_TERMIOS_H +#define _ASM_TERMIOS_H + +#include +#include + +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + int sg_flags; /* SGI special - int, not short */ +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; /* stop process signal */ + char t_dsuspc; /* delayed stop process signal */ + char t_rprntc; /* reprint line */ + char t_flushc; /* flush output (toggles) */ + char t_werasc; /* word erase */ + char t_lnextc; /* literal next character */ +}; + +/* TIOCGSIZE, TIOCSSIZE not defined yet. Only needed for SunOS source + compatibility anyway ... */ + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + char c_line; /* line discipline */ + unsigned char c_cc[NCCS]; /* control characters */ +}; + +#ifdef __KERNEL__ +#include + +/* + * intr=^C quit=^\ erase=del kill=^U + * vmin=\1 vtime=\0 eol2=\0 swtc=\0 + * start=^Q stop=^S susp=^Z vdsusp= + * reprint=^R discard=^U werase=^W lnext=^V + * eof=^D eol=\0 + */ +#define INIT_C_CC "\003\034\177\025\1\0\0\0\021\023\032\0\022\017\027\026\004\0" +#endif + +/* modem lines */ +#define TIOCM_LE 0x001 /* line enable */ +#define TIOCM_DTR 0x002 /* data terminal ready */ +#define TIOCM_RTS 0x004 /* request to send */ +#define TIOCM_ST 0x010 /* secondary transmit */ +#define TIOCM_SR 0x020 /* secondary receive */ +#define TIOCM_CTS 0x040 /* clear to send */ +#define TIOCM_CAR 0x100 /* carrier detect */ +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RNG 0x200 /* ring */ +#define TIOCM_RI TIOCM_RNG +#define TIOCM_DSR 0x400 /* data set ready */ +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +#ifdef __KERNEL__ + +#include + +/* + * Translate a "termio" structure into a "termios". Ugh. + */ +#define user_termio_to_kernel_termios(termios, termio) \ +({ \ + unsigned short tmp; \ + get_user(tmp, &(termio)->c_iflag); \ + (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \ + get_user(tmp, &(termio)->c_oflag); \ + (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \ + get_user(tmp, &(termio)->c_cflag); \ + (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \ + get_user(tmp, &(termio)->c_lflag); \ + (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \ + get_user((termios)->c_line, &(termio)->c_line); \ + copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ +}) + +/* + * Translate a "termios" structure into a "termio". Ugh. + */ +#define kernel_termios_to_user_termio(termio, termios) \ +({ \ + put_user((termios)->c_iflag, &(termio)->c_iflag); \ + put_user((termios)->c_oflag, &(termio)->c_oflag); \ + put_user((termios)->c_cflag, &(termio)->c_cflag); \ + put_user((termios)->c_lflag, &(termio)->c_lflag); \ + put_user((termios)->c_line, &(termio)->c_line); \ + copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ +}) + +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) + +#endif /* defined(__KERNEL__) */ + +#endif /* _ASM_TERMIOS_H */ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h new file mode 100644 index 00000000000..bb3060699df --- /dev/null +++ b/arch/mips/include/asm/thread_info.h @@ -0,0 +1,151 @@ +/* thread_info.h: MIPS low-level thread information + * + * Copyright (C) 2002 David Howells (dhowells@redhat.com) + * - Incorporating suggestions made by Linus Torvalds and Dave Miller + */ + +#ifndef _ASM_THREAD_INFO_H +#define _ASM_THREAD_INFO_H + +#ifdef __KERNEL__ + + +#ifndef __ASSEMBLY__ + +#include + +/* + * low level task data that entry.S needs immediate access to + * - this struct should fit entirely inside of one cache line + * - this struct shares the supervisor stack pages + * - if the contents of this structure are changed, the assembly constants + * must also be changed + */ +struct thread_info { + struct task_struct *task; /* main task structure */ + struct exec_domain *exec_domain; /* execution domain */ + unsigned long flags; /* low level flags */ + unsigned long tp_value; /* thread pointer */ + __u32 cpu; /* current CPU */ + int preempt_count; /* 0 => preemptable, <0 => BUG */ + + mm_segment_t addr_limit; /* thread address space: + 0-0xBFFFFFFF for user-thead + 0-0xFFFFFFFF for kernel-thread + */ + struct restart_block restart_block; + struct pt_regs *regs; +}; + +/* + * macros/functions for gaining access to the thread information structure + * + * preempt_count needs to be 1 initially, until the scheduler is functional. + */ +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .flags = _TIF_FIXADE, \ + .cpu = 0, \ + .preempt_count = 1, \ + .addr_limit = KERNEL_DS, \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ +} + +#define init_thread_info (init_thread_union.thread_info) +#define init_stack (init_thread_union.stack) + +/* How to get the thread information struct from C. */ +register struct thread_info *__current_thread_info __asm__("$28"); +#define current_thread_info() __current_thread_info + +/* thread information allocation */ +#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT) +#define THREAD_SIZE_ORDER (1) +#endif +#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_64BIT) +#define THREAD_SIZE_ORDER (2) +#endif +#ifdef CONFIG_PAGE_SIZE_8KB +#define THREAD_SIZE_ORDER (1) +#endif +#ifdef CONFIG_PAGE_SIZE_16KB +#define THREAD_SIZE_ORDER (0) +#endif +#ifdef CONFIG_PAGE_SIZE_64KB +#define THREAD_SIZE_ORDER (0) +#endif + +#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) +#define THREAD_MASK (THREAD_SIZE - 1UL) + +#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR + +#ifdef CONFIG_DEBUG_STACK_USAGE +#define alloc_thread_info(tsk) \ +({ \ + struct thread_info *ret; \ + \ + ret = kzalloc(THREAD_SIZE, GFP_KERNEL); \ + \ + ret; \ +}) +#else +#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) +#endif + +#define free_thread_info(info) kfree(info) + +#endif /* !__ASSEMBLY__ */ + +#define PREEMPT_ACTIVE 0x10000000 + +/* + * thread information flags + * - these are process state flags that various assembly files may need to + * access + * - pending work-to-be-done flags are in LSW + * - other flags in MSW + */ +#define TIF_SIGPENDING 1 /* signal pending */ +#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ +#define TIF_SYSCALL_AUDIT 3 /* syscall auditing active */ +#define TIF_SECCOMP 4 /* secure computing */ +#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ +#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ +#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_MEMDIE 18 +#define TIF_FREEZE 19 +#define TIF_FIXADE 20 /* Fix address errors in software */ +#define TIF_LOGADE 21 /* Log address errors to syslog */ +#define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */ +#define TIF_32BIT_ADDR 23 /* 32-bit address space (o32/n32) */ +#define TIF_FPUBOUND 24 /* thread bound to FPU-full CPU set */ +#define TIF_SYSCALL_TRACE 31 /* syscall trace active */ + +#define _TIF_SYSCALL_TRACE (1< +#include +#include +#include + +extern spinlock_t rtc_lock; + +/* + * RTC ops. By default, they point to weak no-op RTC functions. + * rtc_mips_set_time - reverse the above translation and set time to RTC. + * rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need + * to be set. Used by RTC sync-up. + */ +extern int rtc_mips_set_time(unsigned long); +extern int rtc_mips_set_mmss(unsigned long); + +/* + * board specific routines required by time_init(). + */ +extern void plat_time_init(void); + +/* + * mips_hpt_frequency - must be set if you intend to use an R4k-compatible + * counter as a timer interrupt source. + */ +extern unsigned int mips_hpt_frequency; + +/* + * The performance counter IRQ on MIPS is a close relative to the timer IRQ + * so it lives here. + */ +extern int (*perf_irq)(void); + +/* + * Initialize the calling CPU's compare interrupt as clockevent device + */ +#ifdef CONFIG_CEVT_R4K +extern int mips_clockevent_init(void); +extern unsigned int __weak get_c0_compare_int(void); +#else +static inline int mips_clockevent_init(void) +{ + return -ENXIO; +} +#endif + +/* + * Initialize the count register as a clocksource + */ +#ifdef CONFIG_CEVT_R4K +extern int init_mips_clocksource(void); +#else +static inline int init_mips_clocksource(void) +{ + return 0; +} +#endif + +extern void clocksource_set_clock(struct clocksource *cs, unsigned int clock); +extern void clockevent_set_clock(struct clock_event_device *cd, + unsigned int clock); + +#endif /* _ASM_TIME_H */ diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h new file mode 100644 index 00000000000..6529704aa73 --- /dev/null +++ b/arch/mips/include/asm/timex.h @@ -0,0 +1,43 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 1999, 2003 by Ralf Baechle + */ +#ifndef _ASM_TIMEX_H +#define _ASM_TIMEX_H + +#ifdef __KERNEL__ + +#include + +/* + * This is the clock rate of the i8253 PIT. A MIPS system may not have + * a PIT by the symbol is used all over the kernel including some APIs. + * So keeping it defined to the number for the PIT is the only sane thing + * for now. + */ +#define CLOCK_TICK_RATE 1193182 + +/* + * Standard way to access the cycle counter. + * Currently only used on SMP for scheduling. + * + * Only the low 32 bits are available as a continuously counting entity. + * But this only means we'll force a reschedule every 8 seconds or so, + * which isn't an evil thing. + * + * We know that all SMP capable CPUs have cycle counters. + */ + +typedef unsigned int cycles_t; + +static inline cycles_t get_cycles(void) +{ + return 0; +} + +#endif /* __KERNEL__ */ + +#endif /* _ASM_TIMEX_H */ diff --git a/arch/mips/include/asm/titan_dep.h b/arch/mips/include/asm/titan_dep.h new file mode 100644 index 00000000000..fee1908c65d --- /dev/null +++ b/arch/mips/include/asm/titan_dep.h @@ -0,0 +1,231 @@ +/* + * Copyright 2003 PMC-Sierra + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * Board specific definititions for the PMC-Sierra Yosemite + * + * 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. + */ + +#ifndef __TITAN_DEP_H__ +#define __TITAN_DEP_H__ + +#include /* for KSEG1ADDR() */ +#include /* for cpu_to_le32() */ + +#define TITAN_READ(ofs) \ + (*(volatile u32 *)(ocd_base+(ofs))) +#define TITAN_READ_16(ofs) \ + (*(volatile u16 *)(ocd_base+(ofs))) +#define TITAN_READ_8(ofs) \ + (*(volatile u8 *)(ocd_base+(ofs))) + +#define TITAN_WRITE(ofs, data) \ + do { *(volatile u32 *)(ocd_base+(ofs)) = (data); } while (0) +#define TITAN_WRITE_16(ofs, data) \ + do { *(volatile u16 *)(ocd_base+(ofs)) = (data); } while (0) +#define TITAN_WRITE_8(ofs, data) \ + do { *(volatile u8 *)(ocd_base+(ofs)) = (data); } while (0) + +/* + * PCI specific defines + */ +#define TITAN_PCI_0_CONFIG_ADDRESS 0x780 +#define TITAN_PCI_0_CONFIG_DATA 0x784 + +/* + * HT specific defines + */ +#define RM9000x2_HTLINK_REG 0xbb000644 +#define RM9000x2_BASE_ADDR 0xbb000000 + +#define OCD_BASE 0xfb000000UL +#define OCD_SIZE 0x3000UL + +extern unsigned long ocd_base; + +/* + * OCD Registers + */ +#define RM9000x2_OCD_LKB5 0x0128 /* Ethernet */ +#define RM9000x2_OCD_LKM5 0x012c + +#define RM9000x2_OCD_LKB7 0x0138 /* HT Region 0 */ +#define RM9000x2_OCD_LKM7 0x013c +#define RM9000x2_OCD_LKB8 0x0140 /* HT Region 1 */ +#define RM9000x2_OCD_LKM8 0x0144 + +#define RM9000x2_OCD_LKB9 0x0148 /* Local Bus */ +#define RM9000x2_OCD_LKM9 0x014c +#define RM9000x2_OCD_LKB10 0x0150 +#define RM9000x2_OCD_LKM10 0x0154 +#define RM9000x2_OCD_LKB11 0x0158 +#define RM9000x2_OCD_LKM11 0x015c +#define RM9000x2_OCD_LKB12 0x0160 +#define RM9000x2_OCD_LKM12 0x0164 + +#define RM9000x2_OCD_LKB13 0x0168 /* Scratch RAM */ +#define RM9000x2_OCD_LKM13 0x016c + +#define RM9000x2_OCD_LPD0 0x0200 /* Local Bus */ +#define RM9000x2_OCD_LPD1 0x0210 +#define RM9000x2_OCD_LPD2 0x0220 +#define RM9000x2_OCD_LPD3 0x0230 + +#define RM9000x2_OCD_HTDVID 0x0600 /* HT Device Header */ +#define RM9000x2_OCD_HTSC 0x0604 +#define RM9000x2_OCD_HTCCR 0x0608 +#define RM9000x2_OCD_HTBHL 0x060c +#define RM9000x2_OCD_HTBAR0 0x0610 +#define RM9000x2_OCD_HTBAR1 0x0614 +#define RM9000x2_OCD_HTBAR2 0x0618 +#define RM9000x2_OCD_HTBAR3 0x061c +#define RM9000x2_OCD_HTBAR4 0x0620 +#define RM9000x2_OCD_HTBAR5 0x0624 +#define RM9000x2_OCD_HTCBCPT 0x0628 +#define RM9000x2_OCD_HTSDVID 0x062c +#define RM9000x2_OCD_HTXRA 0x0630 +#define RM9000x2_OCD_HTCAP1 0x0634 +#define RM9000x2_OCD_HTIL 0x063c + +#define RM9000x2_OCD_HTLCC 0x0640 /* HT Capability Block */ +#define RM9000x2_OCD_HTLINK 0x0644 +#define RM9000x2_OCD_HTFQREV 0x0648 + +#define RM9000x2_OCD_HTERCTL 0x0668 /* HT Controller */ +#define RM9000x2_OCD_HTRXDB 0x066c +#define RM9000x2_OCD_HTIMPED 0x0670 +#define RM9000x2_OCD_HTSWIMP 0x0674 +#define RM9000x2_OCD_HTCAL 0x0678 + +#define RM9000x2_OCD_HTBAA30 0x0680 +#define RM9000x2_OCD_HTBAA54 0x0684 +#define RM9000x2_OCD_HTMASK0 0x0688 +#define RM9000x2_OCD_HTMASK1 0x068c +#define RM9000x2_OCD_HTMASK2 0x0690 +#define RM9000x2_OCD_HTMASK3 0x0694 +#define RM9000x2_OCD_HTMASK4 0x0698 +#define RM9000x2_OCD_HTMASK5 0x069c + +#define RM9000x2_OCD_HTIFCTL 0x06a0 +#define RM9000x2_OCD_HTPLL 0x06a4 + +#define RM9000x2_OCD_HTSRI 0x06b0 +#define RM9000x2_OCD_HTRXNUM 0x06b4 +#define RM9000x2_OCD_HTTXNUM 0x06b8 + +#define RM9000x2_OCD_HTTXCNT 0x06c8 + +#define RM9000x2_OCD_HTERROR 0x06d8 +#define RM9000x2_OCD_HTRCRCE 0x06dc +#define RM9000x2_OCD_HTEOI 0x06e0 + +#define RM9000x2_OCD_CRCR 0x06f0 + +#define RM9000x2_OCD_HTCFGA 0x06f8 +#define RM9000x2_OCD_HTCFGD 0x06fc + +#define RM9000x2_OCD_INTMSG 0x0a00 + +#define RM9000x2_OCD_INTPIN0 0x0a40 +#define RM9000x2_OCD_INTPIN1 0x0a44 +#define RM9000x2_OCD_INTPIN2 0x0a48 +#define RM9000x2_OCD_INTPIN3 0x0a4c +#define RM9000x2_OCD_INTPIN4 0x0a50 +#define RM9000x2_OCD_INTPIN5 0x0a54 +#define RM9000x2_OCD_INTPIN6 0x0a58 +#define RM9000x2_OCD_INTPIN7 0x0a5c +#define RM9000x2_OCD_SEM 0x0a60 +#define RM9000x2_OCD_SEMSET 0x0a64 +#define RM9000x2_OCD_SEMCLR 0x0a68 + +#define RM9000x2_OCD_TKT 0x0a70 +#define RM9000x2_OCD_TKTINC 0x0a74 + +#define RM9000x2_OCD_NMICONFIG 0x0ac0 /* Interrupts */ +#define RM9000x2_OCD_INTP0PRI 0x1a80 +#define RM9000x2_OCD_INTP1PRI 0x1a80 +#define RM9000x2_OCD_INTP0STATUS0 0x1b00 +#define RM9000x2_OCD_INTP0MASK0 0x1b04 +#define RM9000x2_OCD_INTP0SET0 0x1b08 +#define RM9000x2_OCD_INTP0CLEAR0 0x1b0c +#define RM9000x2_OCD_INTP0STATUS1 0x1b10 +#define RM9000x2_OCD_INTP0MASK1 0x1b14 +#define RM9000x2_OCD_INTP0SET1 0x1b18 +#define RM9000x2_OCD_INTP0CLEAR1 0x1b1c +#define RM9000x2_OCD_INTP0STATUS2 0x1b20 +#define RM9000x2_OCD_INTP0MASK2 0x1b24 +#define RM9000x2_OCD_INTP0SET2 0x1b28 +#define RM9000x2_OCD_INTP0CLEAR2 0x1b2c +#define RM9000x2_OCD_INTP0STATUS3 0x1b30 +#define RM9000x2_OCD_INTP0MASK3 0x1b34 +#define RM9000x2_OCD_INTP0SET3 0x1b38 +#define RM9000x2_OCD_INTP0CLEAR3 0x1b3c +#define RM9000x2_OCD_INTP0STATUS4 0x1b40 +#define RM9000x2_OCD_INTP0MASK4 0x1b44 +#define RM9000x2_OCD_INTP0SET4 0x1b48 +#define RM9000x2_OCD_INTP0CLEAR4 0x1b4c +#define RM9000x2_OCD_INTP0STATUS5 0x1b50 +#define RM9000x2_OCD_INTP0MASK5 0x1b54 +#define RM9000x2_OCD_INTP0SET5 0x1b58 +#define RM9000x2_OCD_INTP0CLEAR5 0x1b5c +#define RM9000x2_OCD_INTP0STATUS6 0x1b60 +#define RM9000x2_OCD_INTP0MASK6 0x1b64 +#define RM9000x2_OCD_INTP0SET6 0x1b68 +#define RM9000x2_OCD_INTP0CLEAR6 0x1b6c +#define RM9000x2_OCD_INTP0STATUS7 0x1b70 +#define RM9000x2_OCD_INTP0MASK7 0x1b74 +#define RM9000x2_OCD_INTP0SET7 0x1b78 +#define RM9000x2_OCD_INTP0CLEAR7 0x1b7c +#define RM9000x2_OCD_INTP1STATUS0 0x2b00 +#define RM9000x2_OCD_INTP1MASK0 0x2b04 +#define RM9000x2_OCD_INTP1SET0 0x2b08 +#define RM9000x2_OCD_INTP1CLEAR0 0x2b0c +#define RM9000x2_OCD_INTP1STATUS1 0x2b10 +#define RM9000x2_OCD_INTP1MASK1 0x2b14 +#define RM9000x2_OCD_INTP1SET1 0x2b18 +#define RM9000x2_OCD_INTP1CLEAR1 0x2b1c +#define RM9000x2_OCD_INTP1STATUS2 0x2b20 +#define RM9000x2_OCD_INTP1MASK2 0x2b24 +#define RM9000x2_OCD_INTP1SET2 0x2b28 +#define RM9000x2_OCD_INTP1CLEAR2 0x2b2c +#define RM9000x2_OCD_INTP1STATUS3 0x2b30 +#define RM9000x2_OCD_INTP1MASK3 0x2b34 +#define RM9000x2_OCD_INTP1SET3 0x2b38 +#define RM9000x2_OCD_INTP1CLEAR3 0x2b3c +#define RM9000x2_OCD_INTP1STATUS4 0x2b40 +#define RM9000x2_OCD_INTP1MASK4 0x2b44 +#define RM9000x2_OCD_INTP1SET4 0x2b48 +#define RM9000x2_OCD_INTP1CLEAR4 0x2b4c +#define RM9000x2_OCD_INTP1STATUS5 0x2b50 +#define RM9000x2_OCD_INTP1MASK5 0x2b54 +#define RM9000x2_OCD_INTP1SET5 0x2b58 +#define RM9000x2_OCD_INTP1CLEAR5 0x2b5c +#define RM9000x2_OCD_INTP1STATUS6 0x2b60 +#define RM9000x2_OCD_INTP1MASK6 0x2b64 +#define RM9000x2_OCD_INTP1SET6 0x2b68 +#define RM9000x2_OCD_INTP1CLEAR6 0x2b6c +#define RM9000x2_OCD_INTP1STATUS7 0x2b70 +#define RM9000x2_OCD_INTP1MASK7 0x2b74 +#define RM9000x2_OCD_INTP1SET7 0x2b78 +#define RM9000x2_OCD_INTP1CLEAR7 0x2b7c + +#define OCD_READ(reg) (*(volatile unsigned int *)(ocd_base + (reg))) +#define OCD_WRITE(reg, val) \ + do { *(volatile unsigned int *)(ocd_base + (reg)) = (val); } while (0) + +/* + * Hypertransport specific macros + */ +#define RM9K_WRITE(ofs, data) *(volatile u_int32_t *)(RM9000x2_BASE_ADDR+ofs) = data +#define RM9K_WRITE_8(ofs, data) *(volatile u8 *)(RM9000x2_BASE_ADDR+ofs) = data +#define RM9K_WRITE_16(ofs, data) *(volatile u16 *)(RM9000x2_BASE_ADDR+ofs) = data + +#define RM9K_READ(ofs, val) *(val) = *(volatile u_int32_t *)(RM9000x2_BASE_ADDR+ofs) +#define RM9K_READ_8(ofs, val) *(val) = *(volatile u8 *)(RM9000x2_BASE_ADDR+ofs) +#define RM9K_READ_16(ofs, val) *(val) = *(volatile u16 *)(RM9000x2_BASE_ADDR+ofs) + +#endif diff --git a/arch/mips/include/asm/tlb.h b/arch/mips/include/asm/tlb.h new file mode 100644 index 00000000000..80d9dfcf1e8 --- /dev/null +++ b/arch/mips/include/asm/tlb.h @@ -0,0 +1,23 @@ +#ifndef __ASM_TLB_H +#define __ASM_TLB_H + +/* + * MIPS doesn't need any special per-pte or per-vma handling, except + * we need to flush cache for area to be unmapped. + */ +#define tlb_start_vma(tlb, vma) \ + do { \ + if (!tlb->fullmm) \ + flush_cache_range(vma, vma->vm_start, vma->vm_end); \ + } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) +#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) + +/* + * .. because we flush the whole mm when it fills up. + */ +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +#include + +#endif /* __ASM_TLB_H */ diff --git a/arch/mips/include/asm/tlbdebug.h b/arch/mips/include/asm/tlbdebug.h new file mode 100644 index 00000000000..bb8f5c29c3d --- /dev/null +++ b/arch/mips/include/asm/tlbdebug.h @@ -0,0 +1,16 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002 by Ralf Baechle + */ +#ifndef __ASM_TLBDEBUG_H +#define __ASM_TLBDEBUG_H + +/* + * TLB debugging functions: + */ +extern void dump_tlb_all(void); + +#endif /* __ASM_TLBDEBUG_H */ diff --git a/arch/mips/include/asm/tlbflush.h b/arch/mips/include/asm/tlbflush.h new file mode 100644 index 00000000000..86b21de12e9 --- /dev/null +++ b/arch/mips/include/asm/tlbflush.h @@ -0,0 +1,47 @@ +#ifndef __ASM_TLBFLUSH_H +#define __ASM_TLBFLUSH_H + +#include + +/* + * TLB flushing: + * + * - flush_tlb_all() flushes all processes TLB entries + * - flush_tlb_mm(mm) flushes the specified mm context TLB entries + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(vma, start, end) flushes a range of pages + * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages + */ +extern void local_flush_tlb_all(void); +extern void local_flush_tlb_mm(struct mm_struct *mm); +extern void local_flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end); +extern void local_flush_tlb_kernel_range(unsigned long start, + unsigned long end); +extern void local_flush_tlb_page(struct vm_area_struct *vma, + unsigned long page); +extern void local_flush_tlb_one(unsigned long vaddr); + +#ifdef CONFIG_SMP + +extern void flush_tlb_all(void); +extern void flush_tlb_mm(struct mm_struct *); +extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long, + unsigned long); +extern void flush_tlb_kernel_range(unsigned long, unsigned long); +extern void flush_tlb_page(struct vm_area_struct *, unsigned long); +extern void flush_tlb_one(unsigned long vaddr); + +#else /* CONFIG_SMP */ + +#define flush_tlb_all() local_flush_tlb_all() +#define flush_tlb_mm(mm) local_flush_tlb_mm(mm) +#define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, end) +#define flush_tlb_kernel_range(vmaddr,end) \ + local_flush_tlb_kernel_range(vmaddr, end) +#define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) +#define flush_tlb_one(vaddr) local_flush_tlb_one(vaddr) + +#endif /* CONFIG_SMP */ + +#endif /* __ASM_TLBFLUSH_H */ diff --git a/arch/mips/include/asm/topology.h b/arch/mips/include/asm/topology.h new file mode 100644 index 00000000000..259145e07e9 --- /dev/null +++ b/arch/mips/include/asm/topology.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle + */ +#ifndef __ASM_TOPOLOGY_H +#define __ASM_TOPOLOGY_H + +#include + +#ifdef CONFIG_SMP +#define smt_capable() (smp_num_siblings > 1) +#endif + +#endif /* __ASM_TOPOLOGY_H */ diff --git a/arch/mips/include/asm/traps.h b/arch/mips/include/asm/traps.h new file mode 100644 index 00000000000..90ff2f497c5 --- /dev/null +++ b/arch/mips/include/asm/traps.h @@ -0,0 +1,28 @@ +/* + * Trap handling definitions. + * + * Copyright (C) 2002, 2003 Maciej W. Rozycki + * + * 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. + */ +#ifndef _ASM_TRAPS_H +#define _ASM_TRAPS_H + +/* + * Possible status responses for a board_be_handler backend. + */ +#define MIPS_BE_DISCARD 0 /* return with no action */ +#define MIPS_BE_FIXUP 1 /* return to the fixup code */ +#define MIPS_BE_FATAL 2 /* treat as an unrecoverable error */ + +extern void (*board_be_init)(void); +extern int (*board_be_handler)(struct pt_regs *regs, int is_fixup); + +extern void (*board_nmi_handler_setup)(void); +extern void (*board_ejtag_handler_setup)(void); +extern void (*board_bind_eic_interrupt)(int irq, int regset); + +#endif /* _ASM_TRAPS_H */ diff --git a/arch/mips/include/asm/txx9/boards.h b/arch/mips/include/asm/txx9/boards.h new file mode 100644 index 00000000000..cbe9476d963 --- /dev/null +++ b/arch/mips/include/asm/txx9/boards.h @@ -0,0 +1,13 @@ +#ifdef CONFIG_TOSHIBA_JMR3927 +BOARD_VEC(jmr3927_vec) +#endif +#ifdef CONFIG_TOSHIBA_RBTX4927 +BOARD_VEC(rbtx4927_vec) +BOARD_VEC(rbtx4937_vec) +#endif +#ifdef CONFIG_TOSHIBA_RBTX4938 +BOARD_VEC(rbtx4938_vec) +#endif +#ifdef CONFIG_TOSHIBA_RBTX4939 +BOARD_VEC(rbtx4939_vec) +#endif diff --git a/arch/mips/include/asm/txx9/generic.h b/arch/mips/include/asm/txx9/generic.h new file mode 100644 index 00000000000..4316a3e5767 --- /dev/null +++ b/arch/mips/include/asm/txx9/generic.h @@ -0,0 +1,89 @@ +/* + * linux/include/asm-mips/txx9/generic.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_TXX9_GENERIC_H +#define __ASM_TXX9_GENERIC_H + +#include +#include /* for struct resource */ + +extern struct resource txx9_ce_res[]; +#define TXX9_CE(n) (unsigned long)(txx9_ce_res[(n)].start) +extern unsigned int txx9_pcode; +extern char txx9_pcode_str[8]; +void txx9_reg_res_init(unsigned int pcode, unsigned long base, + unsigned long size); + +extern unsigned int txx9_master_clock; +extern unsigned int txx9_cpu_clock; +extern unsigned int txx9_gbus_clock; +#define TXX9_IMCLK (txx9_gbus_clock / 2) + +extern int txx9_ccfg_toeon; +struct uart_port; +int early_serial_txx9_setup(struct uart_port *port); + +struct pci_dev; +struct txx9_board_vec { + const char *system; + void (*prom_init)(void); + void (*mem_setup)(void); + void (*irq_setup)(void); + void (*time_init)(void); + void (*arch_init)(void); + void (*device_init)(void); +#ifdef CONFIG_PCI + int (*pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); +#endif +}; +extern struct txx9_board_vec *txx9_board_vec; +extern int (*txx9_irq_dispatch)(int pending); +char *prom_getcmdline(void); +const char *prom_getenv(const char *name); +void txx9_wdt_init(unsigned long base); +void txx9_wdt_now(unsigned long base); +void txx9_spi_init(int busid, unsigned long base, int irq); +void txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr); +void txx9_sio_init(unsigned long baseaddr, int irq, + unsigned int line, unsigned int sclk, int nocts); +void prom_putchar(char c); +#ifdef CONFIG_EARLY_PRINTK +extern void (*txx9_prom_putchar)(char c); +void txx9_sio_putchar_init(unsigned long baseaddr); +#else +static inline void txx9_sio_putchar_init(unsigned long baseaddr) +{ +} +#endif + +struct physmap_flash_data; +void txx9_physmap_flash_init(int no, unsigned long addr, unsigned long size, + const struct physmap_flash_data *pdata); + +/* 8 bit version of __fls(): find first bit set (returns 0..7) */ +static inline unsigned int __fls8(unsigned char x) +{ + int r = 7; + + if (!(x & 0xf0)) { + r -= 4; + x <<= 4; + } + if (!(x & 0xc0)) { + r -= 2; + x <<= 2; + } + if (!(x & 0x80)) + r -= 1; + return r; +} + +void txx9_iocled_init(unsigned long baseaddr, + int basenum, unsigned int num, int lowactive, + const char *color, char **deftriggers); + +#endif /* __ASM_TXX9_GENERIC_H */ diff --git a/arch/mips/include/asm/txx9/jmr3927.h b/arch/mips/include/asm/txx9/jmr3927.h new file mode 100644 index 00000000000..a409c446bf1 --- /dev/null +++ b/arch/mips/include/asm/txx9/jmr3927.h @@ -0,0 +1,180 @@ +/* + * Defines for the TJSYS JMR-TX3927 + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000-2001 Toshiba Corporation + */ +#ifndef __ASM_TXX9_JMR3927_H +#define __ASM_TXX9_JMR3927_H + +#include +#include +#include +#include + +/* CS */ +#define JMR3927_ROMCE0 0x1fc00000 /* 4M */ +#define JMR3927_ROMCE1 0x1e000000 /* 4M */ +#define JMR3927_ROMCE2 0x14000000 /* 16M */ +#define JMR3927_ROMCE3 0x10000000 /* 64M */ +#define JMR3927_ROMCE5 0x1d000000 /* 4M */ +#define JMR3927_SDCS0 0x00000000 /* 32M */ +#define JMR3927_SDCS1 0x02000000 /* 32M */ +/* PCI Direct Mappings */ + +#define JMR3927_PCIMEM 0x08000000 +#define JMR3927_PCIMEM_SIZE 0x08000000 /* 128M */ +#define JMR3927_PCIIO 0x15000000 +#define JMR3927_PCIIO_SIZE 0x01000000 /* 16M */ + +#define JMR3927_SDRAM_SIZE 0x02000000 /* 32M */ +#define JMR3927_PORT_BASE KSEG1 + +/* Address map (virtual address) */ +#define JMR3927_ROM0_BASE (KSEG1 + JMR3927_ROMCE0) +#define JMR3927_ROM1_BASE (KSEG1 + JMR3927_ROMCE1) +#define JMR3927_IOC_BASE (KSEG1 + JMR3927_ROMCE2) +#define JMR3927_PCIMEM_BASE (KSEG1 + JMR3927_PCIMEM) +#define JMR3927_PCIIO_BASE (KSEG1 + JMR3927_PCIIO) + +#define JMR3927_IOC_REV_ADDR (JMR3927_IOC_BASE + 0x00000000) +#define JMR3927_IOC_NVRAMB_ADDR (JMR3927_IOC_BASE + 0x00010000) +#define JMR3927_IOC_LED_ADDR (JMR3927_IOC_BASE + 0x00020000) +#define JMR3927_IOC_DIPSW_ADDR (JMR3927_IOC_BASE + 0x00030000) +#define JMR3927_IOC_BREV_ADDR (JMR3927_IOC_BASE + 0x00040000) +#define JMR3927_IOC_DTR_ADDR (JMR3927_IOC_BASE + 0x00050000) +#define JMR3927_IOC_INTS1_ADDR (JMR3927_IOC_BASE + 0x00080000) +#define JMR3927_IOC_INTS2_ADDR (JMR3927_IOC_BASE + 0x00090000) +#define JMR3927_IOC_INTM_ADDR (JMR3927_IOC_BASE + 0x000a0000) +#define JMR3927_IOC_INTP_ADDR (JMR3927_IOC_BASE + 0x000b0000) +#define JMR3927_IOC_RESET_ADDR (JMR3927_IOC_BASE + 0x000f0000) + +/* Flash ROM */ +#define JMR3927_FLASH_BASE (JMR3927_ROM0_BASE) +#define JMR3927_FLASH_SIZE 0x00400000 + +/* bits for IOC_REV/IOC_BREV (high byte) */ +#define JMR3927_IDT_MASK 0xfc +#define JMR3927_REV_MASK 0x03 +#define JMR3927_IOC_IDT 0xe0 + +/* bits for IOC_INTS1/IOC_INTS2/IOC_INTM/IOC_INTP (high byte) */ +#define JMR3927_IOC_INTB_PCIA 0 +#define JMR3927_IOC_INTB_PCIB 1 +#define JMR3927_IOC_INTB_PCIC 2 +#define JMR3927_IOC_INTB_PCID 3 +#define JMR3927_IOC_INTB_MODEM 4 +#define JMR3927_IOC_INTB_INT6 5 +#define JMR3927_IOC_INTB_INT7 6 +#define JMR3927_IOC_INTB_SOFT 7 +#define JMR3927_IOC_INTF_PCIA (1 << JMR3927_IOC_INTF_PCIA) +#define JMR3927_IOC_INTF_PCIB (1 << JMR3927_IOC_INTB_PCIB) +#define JMR3927_IOC_INTF_PCIC (1 << JMR3927_IOC_INTB_PCIC) +#define JMR3927_IOC_INTF_PCID (1 << JMR3927_IOC_INTB_PCID) +#define JMR3927_IOC_INTF_MODEM (1 << JMR3927_IOC_INTB_MODEM) +#define JMR3927_IOC_INTF_INT6 (1 << JMR3927_IOC_INTB_INT6) +#define JMR3927_IOC_INTF_INT7 (1 << JMR3927_IOC_INTB_INT7) +#define JMR3927_IOC_INTF_SOFT (1 << JMR3927_IOC_INTB_SOFT) + +/* bits for IOC_RESET (high byte) */ +#define JMR3927_IOC_RESET_CPU 1 +#define JMR3927_IOC_RESET_PCI 2 + +#if defined(__BIG_ENDIAN) +#define jmr3927_ioc_reg_out(d, a) ((*(volatile unsigned char *)(a)) = (d)) +#define jmr3927_ioc_reg_in(a) (*(volatile unsigned char *)(a)) +#elif defined(__LITTLE_ENDIAN) +#define jmr3927_ioc_reg_out(d, a) ((*(volatile unsigned char *)((a)^1)) = (d)) +#define jmr3927_ioc_reg_in(a) (*(volatile unsigned char *)((a)^1)) +#else +#error "No Endian" +#endif + +/* LED macro */ +#define jmr3927_led_set(n/*0-16*/) jmr3927_ioc_reg_out(~(n), JMR3927_IOC_LED_ADDR) + +#define jmr3927_led_and_set(n/*0-16*/) jmr3927_ioc_reg_out((~(n)) & jmr3927_ioc_reg_in(JMR3927_IOC_LED_ADDR), JMR3927_IOC_LED_ADDR) + +/* DIPSW4 macro */ +#define jmr3927_dipsw1() (gpio_get_value(11) == 0) +#define jmr3927_dipsw2() (gpio_get_value(10) == 0) +#define jmr3927_dipsw3() ((jmr3927_ioc_reg_in(JMR3927_IOC_DIPSW_ADDR) & 2) == 0) +#define jmr3927_dipsw4() ((jmr3927_ioc_reg_in(JMR3927_IOC_DIPSW_ADDR) & 1) == 0) + +/* + * IRQ mappings + */ + +/* These are the virtual IRQ numbers, we divide all IRQ's into + * 'spaces', the 'space' determines where and how to enable/disable + * that particular IRQ on an JMR machine. Add new 'spaces' as new + * IRQ hardware is supported. + */ +#define JMR3927_NR_IRQ_IRC 16 /* On-Chip IRC */ +#define JMR3927_NR_IRQ_IOC 8 /* PCI/MODEM/INT[6:7] */ + +#define JMR3927_IRQ_IRC TXX9_IRQ_BASE +#define JMR3927_IRQ_IOC (JMR3927_IRQ_IRC + JMR3927_NR_IRQ_IRC) +#define JMR3927_IRQ_END (JMR3927_IRQ_IOC + JMR3927_NR_IRQ_IOC) + +#define JMR3927_IRQ_IRC_INT0 (JMR3927_IRQ_IRC + TX3927_IR_INT0) +#define JMR3927_IRQ_IRC_INT1 (JMR3927_IRQ_IRC + TX3927_IR_INT1) +#define JMR3927_IRQ_IRC_INT2 (JMR3927_IRQ_IRC + TX3927_IR_INT2) +#define JMR3927_IRQ_IRC_INT3 (JMR3927_IRQ_IRC + TX3927_IR_INT3) +#define JMR3927_IRQ_IRC_INT4 (JMR3927_IRQ_IRC + TX3927_IR_INT4) +#define JMR3927_IRQ_IRC_INT5 (JMR3927_IRQ_IRC + TX3927_IR_INT5) +#define JMR3927_IRQ_IRC_SIO0 (JMR3927_IRQ_IRC + TX3927_IR_SIO0) +#define JMR3927_IRQ_IRC_SIO1 (JMR3927_IRQ_IRC + TX3927_IR_SIO1) +#define JMR3927_IRQ_IRC_SIO(ch) (JMR3927_IRQ_IRC + TX3927_IR_SIO(ch)) +#define JMR3927_IRQ_IRC_DMA (JMR3927_IRQ_IRC + TX3927_IR_DMA) +#define JMR3927_IRQ_IRC_PIO (JMR3927_IRQ_IRC + TX3927_IR_PIO) +#define JMR3927_IRQ_IRC_PCI (JMR3927_IRQ_IRC + TX3927_IR_PCI) +#define JMR3927_IRQ_IRC_TMR(ch) (JMR3927_IRQ_IRC + TX3927_IR_TMR(ch)) +#define JMR3927_IRQ_IOC_PCIA (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIA) +#define JMR3927_IRQ_IOC_PCIB (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIB) +#define JMR3927_IRQ_IOC_PCIC (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIC) +#define JMR3927_IRQ_IOC_PCID (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCID) +#define JMR3927_IRQ_IOC_MODEM (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_MODEM) +#define JMR3927_IRQ_IOC_INT6 (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_INT6) +#define JMR3927_IRQ_IOC_INT7 (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_INT7) +#define JMR3927_IRQ_IOC_SOFT (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_SOFT) + +/* IOC (PCI, MODEM) */ +#define JMR3927_IRQ_IOCINT JMR3927_IRQ_IRC_INT1 +/* TC35815 100M Ether (JMR-TX3912:JPW4:2-3 Short) */ +#define JMR3927_IRQ_ETHER0 JMR3927_IRQ_IRC_INT3 + +/* Clocks */ +#define JMR3927_CORECLK 132710400 /* 132.7MHz */ + +/* + * TX3927 Pin Configuration: + * + * PCFG bits Avail Dead + * SELSIO[1:0]:11 RXD[1:0], TXD[1:0] PIO[6:3] + * SELSIOC[0]:1 CTS[0], RTS[0] INT[5:4] + * SELSIOC[1]:0,SELDSF:0, GSDAO[0],GPCST[3] CTS[1], RTS[1],DSF, + * GDBGE* PIO[2:1] + * SELDMA[2]:1 DMAREQ[2],DMAACK[2] PIO[13:12] + * SELTMR[2:0]:000 TIMER[1:0] + * SELCS:0,SELDMA[1]:0 PIO[11;10] SDCS_CE[7:6], + * DMAREQ[1],DMAACK[1] + * SELDMA[0]:1 DMAREQ[0],DMAACK[0] PIO[9:8] + * SELDMA[3]:1 DMAREQ[3],DMAACK[3] PIO[15:14] + * SELDONE:1 DMADONE PIO[7] + * + * Usable pins are: + * RXD[1;0],TXD[1:0],CTS[0],RTS[0], + * DMAREQ[0,2,3],DMAACK[0,2,3],DMADONE,PIO[0,10,11] + * INT[3:0] + */ + +void jmr3927_prom_init(void); +void jmr3927_irq_setup(void); +struct pci_dev; +int jmr3927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); + +#endif /* __ASM_TXX9_JMR3927_H */ diff --git a/arch/mips/include/asm/txx9/pci.h b/arch/mips/include/asm/txx9/pci.h new file mode 100644 index 00000000000..3d32529060a --- /dev/null +++ b/arch/mips/include/asm/txx9/pci.h @@ -0,0 +1,39 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_TXX9_PCI_H +#define __ASM_TXX9_PCI_H + +#include + +extern struct pci_controller txx9_primary_pcic; +struct pci_controller * +txx9_alloc_pci_controller(struct pci_controller *pcic, + unsigned long mem_base, unsigned long mem_size, + unsigned long io_base, unsigned long io_size); + +int txx9_pci66_check(struct pci_controller *hose, int top_bus, + int current_bus); +extern int txx9_pci_mem_high __initdata; + +extern int txx9_pci_option; +#define TXX9_PCI_OPT_PICMG 0x0002 +#define TXX9_PCI_OPT_CLK_33 0x0008 +#define TXX9_PCI_OPT_CLK_66 0x0010 +#define TXX9_PCI_OPT_CLK_MASK \ + (TXX9_PCI_OPT_CLK_33 | TXX9_PCI_OPT_CLK_66) +#define TXX9_PCI_OPT_CLK_AUTO TXX9_PCI_OPT_CLK_MASK + +enum txx9_pci_err_action { + TXX9_PCI_ERR_REPORT, + TXX9_PCI_ERR_IGNORE, + TXX9_PCI_ERR_PANIC, +}; +extern enum txx9_pci_err_action txx9_pci_err_action; + +extern char * (*txx9_board_pcibios_setup)(char *str); +char *txx9_pcibios_setup(char *str); + +#endif /* __ASM_TXX9_PCI_H */ diff --git a/arch/mips/include/asm/txx9/rbtx4927.h b/arch/mips/include/asm/txx9/rbtx4927.h new file mode 100644 index 00000000000..b2adab3d1ac --- /dev/null +++ b/arch/mips/include/asm/txx9/rbtx4927.h @@ -0,0 +1,92 @@ +/* + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __ASM_TXX9_RBTX4927_H +#define __ASM_TXX9_RBTX4927_H + +#include + +#define RBTX4927_PCIMEM 0x08000000 +#define RBTX4927_PCIMEM_SIZE 0x08000000 +#define RBTX4927_PCIIO 0x16000000 +#define RBTX4927_PCIIO_SIZE 0x01000000 + +#define RBTX4927_LED_ADDR (IO_BASE + TXX9_CE(2) + 0x00001000) +#define RBTX4927_IMASK_ADDR (IO_BASE + TXX9_CE(2) + 0x00002000) +#define RBTX4927_IMSTAT_ADDR (IO_BASE + TXX9_CE(2) + 0x00002006) +#define RBTX4927_SOFTINT_ADDR (IO_BASE + TXX9_CE(2) + 0x00003000) +#define RBTX4927_SOFTRESET_ADDR (IO_BASE + TXX9_CE(2) + 0x0000f000) +#define RBTX4927_SOFTRESETLOCK_ADDR (IO_BASE + TXX9_CE(2) + 0x0000f002) +#define RBTX4927_PCIRESET_ADDR (IO_BASE + TXX9_CE(2) + 0x0000f006) +#define RBTX4927_BRAMRTC_BASE (IO_BASE + TXX9_CE(2) + 0x00010000) +#define RBTX4927_ETHER_BASE (IO_BASE + TXX9_CE(2) + 0x00020000) + +/* Ethernet port address */ +#define RBTX4927_ETHER_ADDR (RBTX4927_ETHER_BASE + 0x280) + +#define rbtx4927_imask_addr ((__u8 __iomem *)RBTX4927_IMASK_ADDR) +#define rbtx4927_imstat_addr ((__u8 __iomem *)RBTX4927_IMSTAT_ADDR) +#define rbtx4927_softint_addr ((__u8 __iomem *)RBTX4927_SOFTINT_ADDR) +#define rbtx4927_softreset_addr ((__u8 __iomem *)RBTX4927_SOFTRESET_ADDR) +#define rbtx4927_softresetlock_addr \ + ((__u8 __iomem *)RBTX4927_SOFTRESETLOCK_ADDR) +#define rbtx4927_pcireset_addr ((__u8 __iomem *)RBTX4927_PCIRESET_ADDR) + +/* bits for ISTAT/IMASK/IMSTAT */ +#define RBTX4927_INTB_PCID 0 +#define RBTX4927_INTB_PCIC 1 +#define RBTX4927_INTB_PCIB 2 +#define RBTX4927_INTB_PCIA 3 +#define RBTX4927_INTF_PCID (1 << RBTX4927_INTB_PCID) +#define RBTX4927_INTF_PCIC (1 << RBTX4927_INTB_PCIC) +#define RBTX4927_INTF_PCIB (1 << RBTX4927_INTB_PCIB) +#define RBTX4927_INTF_PCIA (1 << RBTX4927_INTB_PCIA) + +#define RBTX4927_NR_IRQ_IOC 8 /* IOC */ + +#define RBTX4927_IRQ_IOC (TXX9_IRQ_BASE + TX4927_NUM_IR) +#define RBTX4927_IRQ_IOC_PCID (RBTX4927_IRQ_IOC + RBTX4927_INTB_PCID) +#define RBTX4927_IRQ_IOC_PCIC (RBTX4927_IRQ_IOC + RBTX4927_INTB_PCIC) +#define RBTX4927_IRQ_IOC_PCIB (RBTX4927_IRQ_IOC + RBTX4927_INTB_PCIB) +#define RBTX4927_IRQ_IOC_PCIA (RBTX4927_IRQ_IOC + RBTX4927_INTB_PCIA) + +#define RBTX4927_IRQ_IOCINT (TXX9_IRQ_BASE + TX4927_IR_INT(1)) + +#ifdef CONFIG_PCI +#define RBTX4927_ISA_IO_OFFSET RBTX4927_PCIIO +#else +#define RBTX4927_ISA_IO_OFFSET 0 +#endif + +#define RBTX4927_RTL_8019_BASE (RBTX4927_ETHER_ADDR - mips_io_port_base) +#define RBTX4927_RTL_8019_IRQ (TXX9_IRQ_BASE + TX4927_IR_INT(3)) + +void rbtx4927_prom_init(void); +void rbtx4927_irq_setup(void); +struct pci_dev; +int rbtx4927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); + +#endif /* __ASM_TXX9_RBTX4927_H */ diff --git a/arch/mips/include/asm/txx9/rbtx4938.h b/arch/mips/include/asm/txx9/rbtx4938.h new file mode 100644 index 00000000000..9f0441a2812 --- /dev/null +++ b/arch/mips/include/asm/txx9/rbtx4938.h @@ -0,0 +1,145 @@ +/* + * Definitions for TX4937/TX4938 + * + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) + */ +#ifndef __ASM_TXX9_RBTX4938_H +#define __ASM_TXX9_RBTX4938_H + +#include +#include +#include + +/* Address map */ +#define RBTX4938_FPGA_REG_ADDR (IO_BASE + TXX9_CE(2) + 0x00000000) +#define RBTX4938_FPGA_REV_ADDR (IO_BASE + TXX9_CE(2) + 0x00000002) +#define RBTX4938_CONFIG1_ADDR (IO_BASE + TXX9_CE(2) + 0x00000004) +#define RBTX4938_CONFIG2_ADDR (IO_BASE + TXX9_CE(2) + 0x00000006) +#define RBTX4938_CONFIG3_ADDR (IO_BASE + TXX9_CE(2) + 0x00000008) +#define RBTX4938_LED_ADDR (IO_BASE + TXX9_CE(2) + 0x00001000) +#define RBTX4938_DIPSW_ADDR (IO_BASE + TXX9_CE(2) + 0x00001002) +#define RBTX4938_BDIPSW_ADDR (IO_BASE + TXX9_CE(2) + 0x00001004) +#define RBTX4938_IMASK_ADDR (IO_BASE + TXX9_CE(2) + 0x00002000) +#define RBTX4938_IMASK2_ADDR (IO_BASE + TXX9_CE(2) + 0x00002002) +#define RBTX4938_INTPOL_ADDR (IO_BASE + TXX9_CE(2) + 0x00002004) +#define RBTX4938_ISTAT_ADDR (IO_BASE + TXX9_CE(2) + 0x00002006) +#define RBTX4938_ISTAT2_ADDR (IO_BASE + TXX9_CE(2) + 0x00002008) +#define RBTX4938_IMSTAT_ADDR (IO_BASE + TXX9_CE(2) + 0x0000200a) +#define RBTX4938_IMSTAT2_ADDR (IO_BASE + TXX9_CE(2) + 0x0000200c) +#define RBTX4938_SOFTINT_ADDR (IO_BASE + TXX9_CE(2) + 0x00003000) +#define RBTX4938_PIOSEL_ADDR (IO_BASE + TXX9_CE(2) + 0x00005000) +#define RBTX4938_SPICS_ADDR (IO_BASE + TXX9_CE(2) + 0x00005002) +#define RBTX4938_SFPWR_ADDR (IO_BASE + TXX9_CE(2) + 0x00005008) +#define RBTX4938_SFVOL_ADDR (IO_BASE + TXX9_CE(2) + 0x0000500a) +#define RBTX4938_SOFTRESET_ADDR (IO_BASE + TXX9_CE(2) + 0x00007000) +#define RBTX4938_SOFTRESETLOCK_ADDR (IO_BASE + TXX9_CE(2) + 0x00007002) +#define RBTX4938_PCIRESET_ADDR (IO_BASE + TXX9_CE(2) + 0x00007004) +#define RBTX4938_ETHER_BASE (IO_BASE + TXX9_CE(2) + 0x00020000) + +/* Ethernet port address (Jumperless Mode (W12:Open)) */ +#define RBTX4938_ETHER_ADDR (RBTX4938_ETHER_BASE + 0x280) + +/* bits for ISTAT/IMASK/IMSTAT */ +#define RBTX4938_INTB_PCID 0 +#define RBTX4938_INTB_PCIC 1 +#define RBTX4938_INTB_PCIB 2 +#define RBTX4938_INTB_PCIA 3 +#define RBTX4938_INTB_RTC 4 +#define RBTX4938_INTB_ATA 5 +#define RBTX4938_INTB_MODEM 6 +#define RBTX4938_INTB_SWINT 7 +#define RBTX4938_INTF_PCID (1 << RBTX4938_INTB_PCID) +#define RBTX4938_INTF_PCIC (1 << RBTX4938_INTB_PCIC) +#define RBTX4938_INTF_PCIB (1 << RBTX4938_INTB_PCIB) +#define RBTX4938_INTF_PCIA (1 << RBTX4938_INTB_PCIA) +#define RBTX4938_INTF_RTC (1 << RBTX4938_INTB_RTC) +#define RBTX4938_INTF_ATA (1 << RBTX4938_INTB_ATA) +#define RBTX4938_INTF_MODEM (1 << RBTX4938_INTB_MODEM) +#define RBTX4938_INTF_SWINT (1 << RBTX4938_INTB_SWINT) + +#define rbtx4938_fpga_rev_addr ((__u8 __iomem *)RBTX4938_FPGA_REV_ADDR) +#define rbtx4938_led_addr ((__u8 __iomem *)RBTX4938_LED_ADDR) +#define rbtx4938_dipsw_addr ((__u8 __iomem *)RBTX4938_DIPSW_ADDR) +#define rbtx4938_bdipsw_addr ((__u8 __iomem *)RBTX4938_BDIPSW_ADDR) +#define rbtx4938_imask_addr ((__u8 __iomem *)RBTX4938_IMASK_ADDR) +#define rbtx4938_imask2_addr ((__u8 __iomem *)RBTX4938_IMASK2_ADDR) +#define rbtx4938_intpol_addr ((__u8 __iomem *)RBTX4938_INTPOL_ADDR) +#define rbtx4938_istat_addr ((__u8 __iomem *)RBTX4938_ISTAT_ADDR) +#define rbtx4938_istat2_addr ((__u8 __iomem *)RBTX4938_ISTAT2_ADDR) +#define rbtx4938_imstat_addr ((__u8 __iomem *)RBTX4938_IMSTAT_ADDR) +#define rbtx4938_imstat2_addr ((__u8 __iomem *)RBTX4938_IMSTAT2_ADDR) +#define rbtx4938_softint_addr ((__u8 __iomem *)RBTX4938_SOFTINT_ADDR) +#define rbtx4938_piosel_addr ((__u8 __iomem *)RBTX4938_PIOSEL_ADDR) +#define rbtx4938_spics_addr ((__u8 __iomem *)RBTX4938_SPICS_ADDR) +#define rbtx4938_sfpwr_addr ((__u8 __iomem *)RBTX4938_SFPWR_ADDR) +#define rbtx4938_sfvol_addr ((__u8 __iomem *)RBTX4938_SFVOL_ADDR) +#define rbtx4938_softreset_addr ((__u8 __iomem *)RBTX4938_SOFTRESET_ADDR) +#define rbtx4938_softresetlock_addr \ + ((__u8 __iomem *)RBTX4938_SOFTRESETLOCK_ADDR) +#define rbtx4938_pcireset_addr ((__u8 __iomem *)RBTX4938_PCIRESET_ADDR) + +/* + * IRQ mappings + */ + +#define RBTX4938_SOFT_INT0 0 /* not used */ +#define RBTX4938_SOFT_INT1 1 /* not used */ +#define RBTX4938_IRC_INT 2 +#define RBTX4938_TIMER_INT 7 + +/* These are the virtual IRQ numbers, we divide all IRQ's into + * 'spaces', the 'space' determines where and how to enable/disable + * that particular IRQ on an RBTX4938 machine. Add new 'spaces' as new + * IRQ hardware is supported. + */ +#define RBTX4938_NR_IRQ_IOC 8 + +#define RBTX4938_IRQ_IRC TXX9_IRQ_BASE +#define RBTX4938_IRQ_IOC (TXX9_IRQ_BASE + TX4938_NUM_IR) +#define RBTX4938_IRQ_END (RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC) + +#define RBTX4938_IRQ_IRC_ECCERR (RBTX4938_IRQ_IRC + TX4938_IR_ECCERR) +#define RBTX4938_IRQ_IRC_WTOERR (RBTX4938_IRQ_IRC + TX4938_IR_WTOERR) +#define RBTX4938_IRQ_IRC_INT(n) (RBTX4938_IRQ_IRC + TX4938_IR_INT(n)) +#define RBTX4938_IRQ_IRC_SIO(n) (RBTX4938_IRQ_IRC + TX4938_IR_SIO(n)) +#define RBTX4938_IRQ_IRC_DMA(ch, n) (RBTX4938_IRQ_IRC + TX4938_IR_DMA(ch, n)) +#define RBTX4938_IRQ_IRC_PIO (RBTX4938_IRQ_IRC + TX4938_IR_PIO) +#define RBTX4938_IRQ_IRC_PDMAC (RBTX4938_IRQ_IRC + TX4938_IR_PDMAC) +#define RBTX4938_IRQ_IRC_PCIC (RBTX4938_IRQ_IRC + TX4938_IR_PCIC) +#define RBTX4938_IRQ_IRC_TMR(n) (RBTX4938_IRQ_IRC + TX4938_IR_TMR(n)) +#define RBTX4938_IRQ_IRC_NDFMC (RBTX4938_IRQ_IRC + TX4938_IR_NDFMC) +#define RBTX4938_IRQ_IRC_PCIERR (RBTX4938_IRQ_IRC + TX4938_IR_PCIERR) +#define RBTX4938_IRQ_IRC_PCIPME (RBTX4938_IRQ_IRC + TX4938_IR_PCIPME) +#define RBTX4938_IRQ_IRC_ACLC (RBTX4938_IRQ_IRC + TX4938_IR_ACLC) +#define RBTX4938_IRQ_IRC_ACLCPME (RBTX4938_IRQ_IRC + TX4938_IR_ACLCPME) +#define RBTX4938_IRQ_IRC_PCIC1 (RBTX4938_IRQ_IRC + TX4938_IR_PCIC1) +#define RBTX4938_IRQ_IRC_SPI (RBTX4938_IRQ_IRC + TX4938_IR_SPI) +#define RBTX4938_IRQ_IOC_PCID (RBTX4938_IRQ_IOC + RBTX4938_INTB_PCID) +#define RBTX4938_IRQ_IOC_PCIC (RBTX4938_IRQ_IOC + RBTX4938_INTB_PCIC) +#define RBTX4938_IRQ_IOC_PCIB (RBTX4938_IRQ_IOC + RBTX4938_INTB_PCIB) +#define RBTX4938_IRQ_IOC_PCIA (RBTX4938_IRQ_IOC + RBTX4938_INTB_PCIA) +#define RBTX4938_IRQ_IOC_RTC (RBTX4938_IRQ_IOC + RBTX4938_INTB_RTC) +#define RBTX4938_IRQ_IOC_ATA (RBTX4938_IRQ_IOC + RBTX4938_INTB_ATA) +#define RBTX4938_IRQ_IOC_MODEM (RBTX4938_IRQ_IOC + RBTX4938_INTB_MODEM) +#define RBTX4938_IRQ_IOC_SWINT (RBTX4938_IRQ_IOC + RBTX4938_INTB_SWINT) + + +/* IOC (PCI, etc) */ +#define RBTX4938_IRQ_IOCINT (TXX9_IRQ_BASE + TX4938_IR_INT(0)) +/* Onboard 10M Ether */ +#define RBTX4938_IRQ_ETHER (TXX9_IRQ_BASE + TX4938_IR_INT(1)) + +#define RBTX4938_RTL_8019_BASE (RBTX4938_ETHER_ADDR - mips_io_port_base) +#define RBTX4938_RTL_8019_IRQ (RBTX4938_IRQ_ETHER) + +void rbtx4938_prom_init(void); +void rbtx4938_irq_setup(void); +struct pci_dev; +int rbtx4938_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); + +#endif /* __ASM_TXX9_RBTX4938_H */ diff --git a/arch/mips/include/asm/txx9/rbtx4939.h b/arch/mips/include/asm/txx9/rbtx4939.h new file mode 100644 index 00000000000..1acf428c0b4 --- /dev/null +++ b/arch/mips/include/asm/txx9/rbtx4939.h @@ -0,0 +1,133 @@ +/* + * Definitions for RBTX4939 + * + * (C) Copyright TOSHIBA CORPORATION 2005-2006 + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ASM_TXX9_RBTX4939_H +#define __ASM_TXX9_RBTX4939_H + +#include +#include +#include +#include + +/* Address map */ +#define RBTX4939_IOC_REG_ADDR (IO_BASE + TXX9_CE(1) + 0x00000000) +#define RBTX4939_BOARD_REV_ADDR (IO_BASE + TXX9_CE(1) + 0x00000000) +#define RBTX4939_IOC_REV_ADDR (IO_BASE + TXX9_CE(1) + 0x00000002) +#define RBTX4939_CONFIG1_ADDR (IO_BASE + TXX9_CE(1) + 0x00000004) +#define RBTX4939_CONFIG2_ADDR (IO_BASE + TXX9_CE(1) + 0x00000006) +#define RBTX4939_CONFIG3_ADDR (IO_BASE + TXX9_CE(1) + 0x00000008) +#define RBTX4939_CONFIG4_ADDR (IO_BASE + TXX9_CE(1) + 0x0000000a) +#define RBTX4939_USTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00001000) +#define RBTX4939_UDIPSW_ADDR (IO_BASE + TXX9_CE(1) + 0x00001002) +#define RBTX4939_BDIPSW_ADDR (IO_BASE + TXX9_CE(1) + 0x00001004) +#define RBTX4939_IEN_ADDR (IO_BASE + TXX9_CE(1) + 0x00002000) +#define RBTX4939_IPOL_ADDR (IO_BASE + TXX9_CE(1) + 0x00002002) +#define RBTX4939_IFAC1_ADDR (IO_BASE + TXX9_CE(1) + 0x00002004) +#define RBTX4939_IFAC2_ADDR (IO_BASE + TXX9_CE(1) + 0x00002006) +#define RBTX4939_SOFTINT_ADDR (IO_BASE + TXX9_CE(1) + 0x00003000) +#define RBTX4939_ISASTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00004000) +#define RBTX4939_PCISTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00004002) +#define RBTX4939_ROME_ADDR (IO_BASE + TXX9_CE(1) + 0x00004004) +#define RBTX4939_SPICS_ADDR (IO_BASE + TXX9_CE(1) + 0x00004006) +#define RBTX4939_AUDI_ADDR (IO_BASE + TXX9_CE(1) + 0x00004008) +#define RBTX4939_ISAGPIO_ADDR (IO_BASE + TXX9_CE(1) + 0x0000400a) +#define RBTX4939_PE1_ADDR (IO_BASE + TXX9_CE(1) + 0x00005000) +#define RBTX4939_PE2_ADDR (IO_BASE + TXX9_CE(1) + 0x00005002) +#define RBTX4939_PE3_ADDR (IO_BASE + TXX9_CE(1) + 0x00005004) +#define RBTX4939_VP_ADDR (IO_BASE + TXX9_CE(1) + 0x00005006) +#define RBTX4939_VPRESET_ADDR (IO_BASE + TXX9_CE(1) + 0x00005008) +#define RBTX4939_VPSOUT_ADDR (IO_BASE + TXX9_CE(1) + 0x0000500a) +#define RBTX4939_VPSIN_ADDR (IO_BASE + TXX9_CE(1) + 0x0000500c) +#define RBTX4939_7SEG_ADDR(s, ch) \ + (IO_BASE + TXX9_CE(1) + 0x00006000 + (s) * 16 + ((ch) & 3) * 2) +#define RBTX4939_SOFTRESET_ADDR (IO_BASE + TXX9_CE(1) + 0x00007000) +#define RBTX4939_RESETEN_ADDR (IO_BASE + TXX9_CE(1) + 0x00007002) +#define RBTX4939_RESETSTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00007004) +#define RBTX4939_ETHER_BASE (IO_BASE + TXX9_CE(1) + 0x00020000) + +/* Ethernet port address */ +#define RBTX4939_ETHER_ADDR (RBTX4939_ETHER_BASE + 0x300) + +/* bits for IEN/IPOL/IFAC */ +#define RBTX4938_INTB_ISA0 0 +#define RBTX4938_INTB_ISA11 1 +#define RBTX4938_INTB_ISA12 2 +#define RBTX4938_INTB_ISA15 3 +#define RBTX4938_INTB_I2S 4 +#define RBTX4938_INTB_SW 5 +#define RBTX4938_INTF_ISA0 (1 << RBTX4938_INTB_ISA0) +#define RBTX4938_INTF_ISA11 (1 << RBTX4938_INTB_ISA11) +#define RBTX4938_INTF_ISA12 (1 << RBTX4938_INTB_ISA12) +#define RBTX4938_INTF_ISA15 (1 << RBTX4938_INTB_ISA15) +#define RBTX4938_INTF_I2S (1 << RBTX4938_INTB_I2S) +#define RBTX4938_INTF_SW (1 << RBTX4938_INTB_SW) + +/* bits for PE1,PE2,PE3 */ +#define RBTX4939_PE1_ATA(ch) (0x01 << (ch)) +#define RBTX4939_PE1_RMII(ch) (0x04 << (ch)) +#define RBTX4939_PE2_SIO0 0x01 +#define RBTX4939_PE2_SIO2 0x02 +#define RBTX4939_PE2_SIO3 0x04 +#define RBTX4939_PE2_CIR 0x08 +#define RBTX4939_PE2_SPI 0x10 +#define RBTX4939_PE2_GPIO 0x20 +#define RBTX4939_PE3_VP 0x01 +#define RBTX4939_PE3_VP_P 0x02 +#define RBTX4939_PE3_VP_S 0x04 + +#define rbtx4939_board_rev_addr ((u8 __iomem *)RBTX4939_BOARD_REV_ADDR) +#define rbtx4939_ioc_rev_addr ((u8 __iomem *)RBTX4939_IOC_REV_ADDR) +#define rbtx4939_config1_addr ((u8 __iomem *)RBTX4939_CONFIG1_ADDR) +#define rbtx4939_config2_addr ((u8 __iomem *)RBTX4939_CONFIG2_ADDR) +#define rbtx4939_config3_addr ((u8 __iomem *)RBTX4939_CONFIG3_ADDR) +#define rbtx4939_config4_addr ((u8 __iomem *)RBTX4939_CONFIG4_ADDR) +#define rbtx4939_ustat_addr ((u8 __iomem *)RBTX4939_USTAT_ADDR) +#define rbtx4939_udipsw_addr ((u8 __iomem *)RBTX4939_UDIPSW_ADDR) +#define rbtx4939_bdipsw_addr ((u8 __iomem *)RBTX4939_BDIPSW_ADDR) +#define rbtx4939_ien_addr ((u8 __iomem *)RBTX4939_IEN_ADDR) +#define rbtx4939_ipol_addr ((u8 __iomem *)RBTX4939_IPOL_ADDR) +#define rbtx4939_ifac1_addr ((u8 __iomem *)RBTX4939_IFAC1_ADDR) +#define rbtx4939_ifac2_addr ((u8 __iomem *)RBTX4939_IFAC2_ADDR) +#define rbtx4939_softint_addr ((u8 __iomem *)RBTX4939_SOFTINT_ADDR) +#define rbtx4939_isastat_addr ((u8 __iomem *)RBTX4939_ISASTAT_ADDR) +#define rbtx4939_pcistat_addr ((u8 __iomem *)RBTX4939_PCISTAT_ADDR) +#define rbtx4939_rome_addr ((u8 __iomem *)RBTX4939_ROME_ADDR) +#define rbtx4939_spics_addr ((u8 __iomem *)RBTX4939_SPICS_ADDR) +#define rbtx4939_audi_addr ((u8 __iomem *)RBTX4939_AUDI_ADDR) +#define rbtx4939_isagpio_addr ((u8 __iomem *)RBTX4939_ISAGPIO_ADDR) +#define rbtx4939_pe1_addr ((u8 __iomem *)RBTX4939_PE1_ADDR) +#define rbtx4939_pe2_addr ((u8 __iomem *)RBTX4939_PE2_ADDR) +#define rbtx4939_pe3_addr ((u8 __iomem *)RBTX4939_PE3_ADDR) +#define rbtx4939_vp_addr ((u8 __iomem *)RBTX4939_VP_ADDR) +#define rbtx4939_vpreset_addr ((u8 __iomem *)RBTX4939_VPRESET_ADDR) +#define rbtx4939_vpsout_addr ((u8 __iomem *)RBTX4939_VPSOUT_ADDR) +#define rbtx4939_vpsin_addr ((u8 __iomem *)RBTX4939_VPSIN_ADDR) +#define rbtx4939_7seg_addr(s, ch) \ + ((u8 __iomem *)RBTX4939_7SEG_ADDR(s, ch)) +#define rbtx4939_softreset_addr ((u8 __iomem *)RBTX4939_SOFTRESET_ADDR) +#define rbtx4939_reseten_addr ((u8 __iomem *)RBTX4939_RESETEN_ADDR) +#define rbtx4939_resetstat_addr ((u8 __iomem *)RBTX4939_RESETSTAT_ADDR) + +/* + * IRQ mappings + */ +#define RBTX4939_NR_IRQ_IOC 8 + +#define RBTX4939_IRQ_IOC (TXX9_IRQ_BASE + TX4939_NUM_IR) +#define RBTX4939_IRQ_END (RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC) + +/* IOC (ISA, etc) */ +#define RBTX4939_IRQ_IOCINT (TXX9_IRQ_BASE + TX4939_IR_INT(0)) +/* Onboard 10M Ether */ +#define RBTX4939_IRQ_ETHER (TXX9_IRQ_BASE + TX4939_IR_INT(1)) + +void rbtx4939_prom_init(void); +void rbtx4939_irq_setup(void); + +#endif /* __ASM_TXX9_RBTX4939_H */ diff --git a/arch/mips/include/asm/txx9/smsc_fdc37m81x.h b/arch/mips/include/asm/txx9/smsc_fdc37m81x.h new file mode 100644 index 00000000000..d1d6332b4ca --- /dev/null +++ b/arch/mips/include/asm/txx9/smsc_fdc37m81x.h @@ -0,0 +1,68 @@ +/* + * Interface for smsc fdc48m81x Super IO chip + * + * Author: MontaVista Software, Inc. source@mvista.com + * + * 2001-2003 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Copyright (C) 2004 MontaVista Software Inc. + * Manish Lachwani, mlachwani@mvista.com + */ + +#ifndef _SMSC_FDC37M81X_H_ +#define _SMSC_FDC37M81X_H_ + +/* Common Registers */ +#define SMSC_FDC37M81X_CONFIG_INDEX 0x00 +#define SMSC_FDC37M81X_CONFIG_DATA 0x01 +#define SMSC_FDC37M81X_CONF 0x02 +#define SMSC_FDC37M81X_INDEX 0x03 +#define SMSC_FDC37M81X_DNUM 0x07 +#define SMSC_FDC37M81X_DID 0x20 +#define SMSC_FDC37M81X_DREV 0x21 +#define SMSC_FDC37M81X_PCNT 0x22 +#define SMSC_FDC37M81X_PMGT 0x23 +#define SMSC_FDC37M81X_OSC 0x24 +#define SMSC_FDC37M81X_CONFPA0 0x26 +#define SMSC_FDC37M81X_CONFPA1 0x27 +#define SMSC_FDC37M81X_TEST4 0x2B +#define SMSC_FDC37M81X_TEST5 0x2C +#define SMSC_FDC37M81X_TEST1 0x2D +#define SMSC_FDC37M81X_TEST2 0x2E +#define SMSC_FDC37M81X_TEST3 0x2F + +/* Logical device numbers */ +#define SMSC_FDC37M81X_FDD 0x00 +#define SMSC_FDC37M81X_PARALLEL 0x03 +#define SMSC_FDC37M81X_SERIAL1 0x04 +#define SMSC_FDC37M81X_SERIAL2 0x05 +#define SMSC_FDC37M81X_KBD 0x07 +#define SMSC_FDC37M81X_AUXIO 0x08 +#define SMSC_FDC37M81X_NONE 0xff + +/* Logical device Config Registers */ +#define SMSC_FDC37M81X_ACTIVE 0x30 +#define SMSC_FDC37M81X_BASEADDR0 0x60 +#define SMSC_FDC37M81X_BASEADDR1 0x61 +#define SMSC_FDC37M81X_INT 0x70 +#define SMSC_FDC37M81X_INT2 0x72 +#define SMSC_FDC37M81X_LDCR_F0 0xF0 + +/* Chip Config Values */ +#define SMSC_FDC37M81X_CONFIG_ENTER 0x55 +#define SMSC_FDC37M81X_CONFIG_EXIT 0xaa +#define SMSC_FDC37M81X_CHIP_ID 0x4d + +unsigned long smsc_fdc37m81x_init(unsigned long port); + +void smsc_fdc37m81x_config_beg(void); + +void smsc_fdc37m81x_config_end(void); + +u8 smsc_fdc37m81x_config_get(u8 reg); +void smsc_fdc37m81x_config_set(u8 reg, u8 val); + +#endif diff --git a/arch/mips/include/asm/txx9/spi.h b/arch/mips/include/asm/txx9/spi.h new file mode 100644 index 00000000000..0d727f35455 --- /dev/null +++ b/arch/mips/include/asm/txx9/spi.h @@ -0,0 +1,34 @@ +/* + * Definitions for TX4937/TX4938 SPI + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) + */ +#ifndef __ASM_TXX9_SPI_H +#define __ASM_TXX9_SPI_H + +#include + +#ifdef CONFIG_SPI +int spi_eeprom_register(int busid, int chipid, int size); +int spi_eeprom_read(int busid, int chipid, + int address, unsigned char *buf, int len); +#else +static inline int spi_eeprom_register(int busid, int chipid, int size) +{ + return -ENODEV; +} +static inline int spi_eeprom_read(int busid, int chipid, + int address, unsigned char *buf, int len) +{ + return -ENODEV; +} +#endif + +#endif /* __ASM_TXX9_SPI_H */ diff --git a/arch/mips/include/asm/txx9/tx3927.h b/arch/mips/include/asm/txx9/tx3927.h new file mode 100644 index 00000000000..dc30c8d4206 --- /dev/null +++ b/arch/mips/include/asm/txx9/tx3927.h @@ -0,0 +1,341 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Toshiba Corporation + */ +#ifndef __ASM_TXX9_TX3927_H +#define __ASM_TXX9_TX3927_H + +#define TX3927_REG_BASE 0xfffe0000UL +#define TX3927_REG_SIZE 0x00010000 +#define TX3927_SDRAMC_REG (TX3927_REG_BASE + 0x8000) +#define TX3927_ROMC_REG (TX3927_REG_BASE + 0x9000) +#define TX3927_DMA_REG (TX3927_REG_BASE + 0xb000) +#define TX3927_IRC_REG (TX3927_REG_BASE + 0xc000) +#define TX3927_PCIC_REG (TX3927_REG_BASE + 0xd000) +#define TX3927_CCFG_REG (TX3927_REG_BASE + 0xe000) +#define TX3927_NR_TMR 3 +#define TX3927_TMR_REG(ch) (TX3927_REG_BASE + 0xf000 + (ch) * 0x100) +#define TX3927_NR_SIO 2 +#define TX3927_SIO_REG(ch) (TX3927_REG_BASE + 0xf300 + (ch) * 0x100) +#define TX3927_PIO_REG (TX3927_REG_BASE + 0xf500) + +struct tx3927_sdramc_reg { + volatile unsigned long cr[8]; + volatile unsigned long tr[3]; + volatile unsigned long cmd; + volatile unsigned long smrs[2]; +}; + +struct tx3927_romc_reg { + volatile unsigned long cr[8]; +}; + +struct tx3927_dma_reg { + struct tx3927_dma_ch_reg { + volatile unsigned long cha; + volatile unsigned long sar; + volatile unsigned long dar; + volatile unsigned long cntr; + volatile unsigned long sair; + volatile unsigned long dair; + volatile unsigned long ccr; + volatile unsigned long csr; + } ch[4]; + volatile unsigned long dbr[8]; + volatile unsigned long tdhr; + volatile unsigned long mcr; + volatile unsigned long unused0; +}; + +#include + +#ifdef __BIG_ENDIAN +#define endian_def_s2(e1, e2) \ + volatile unsigned short e1, e2 +#define endian_def_sb2(e1, e2, e3) \ + volatile unsigned short e1;volatile unsigned char e2, e3 +#define endian_def_b2s(e1, e2, e3) \ + volatile unsigned char e1, e2;volatile unsigned short e3 +#define endian_def_b4(e1, e2, e3, e4) \ + volatile unsigned char e1, e2, e3, e4 +#else +#define endian_def_s2(e1, e2) \ + volatile unsigned short e2, e1 +#define endian_def_sb2(e1, e2, e3) \ + volatile unsigned char e3, e2;volatile unsigned short e1 +#define endian_def_b2s(e1, e2, e3) \ + volatile unsigned short e3;volatile unsigned char e2, e1 +#define endian_def_b4(e1, e2, e3, e4) \ + volatile unsigned char e4, e3, e2, e1 +#endif + +struct tx3927_pcic_reg { + endian_def_s2(did, vid); + endian_def_s2(pcistat, pcicmd); + endian_def_b4(cc, scc, rpli, rid); + endian_def_b4(unused0, ht, mlt, cls); + volatile unsigned long ioba; /* +10 */ + volatile unsigned long mba; + volatile unsigned long unused1[5]; + endian_def_s2(svid, ssvid); + volatile unsigned long unused2; /* +30 */ + endian_def_sb2(unused3, unused4, capptr); + volatile unsigned long unused5; + endian_def_b4(ml, mg, ip, il); + volatile unsigned long unused6; /* +40 */ + volatile unsigned long istat; + volatile unsigned long iim; + volatile unsigned long rrt; + volatile unsigned long unused7[3]; /* +50 */ + volatile unsigned long ipbmma; + volatile unsigned long ipbioma; /* +60 */ + volatile unsigned long ilbmma; + volatile unsigned long ilbioma; + volatile unsigned long unused8[9]; + volatile unsigned long tc; /* +90 */ + volatile unsigned long tstat; + volatile unsigned long tim; + volatile unsigned long tccmd; + volatile unsigned long pcirrt; /* +a0 */ + volatile unsigned long pcirrt_cmd; + volatile unsigned long pcirrdt; + volatile unsigned long unused9[3]; + volatile unsigned long tlboap; + volatile unsigned long tlbiap; + volatile unsigned long tlbmma; /* +c0 */ + volatile unsigned long tlbioma; + volatile unsigned long sc_msg; + volatile unsigned long sc_be; + volatile unsigned long tbl; /* +d0 */ + volatile unsigned long unused10[3]; + volatile unsigned long pwmng; /* +e0 */ + volatile unsigned long pwmngs; + volatile unsigned long unused11[6]; + volatile unsigned long req_trace; /* +100 */ + volatile unsigned long pbapmc; + volatile unsigned long pbapms; + volatile unsigned long pbapmim; + volatile unsigned long bm; /* +110 */ + volatile unsigned long cpcibrs; + volatile unsigned long cpcibgs; + volatile unsigned long pbacs; + volatile unsigned long iobas; /* +120 */ + volatile unsigned long mbas; + volatile unsigned long lbc; + volatile unsigned long lbstat; + volatile unsigned long lbim; /* +130 */ + volatile unsigned long pcistatim; + volatile unsigned long ica; + volatile unsigned long icd; + volatile unsigned long iiadp; /* +140 */ + volatile unsigned long iscdp; + volatile unsigned long mmas; + volatile unsigned long iomas; + volatile unsigned long ipciaddr; /* +150 */ + volatile unsigned long ipcidata; + volatile unsigned long ipcibe; +}; + +struct tx3927_ccfg_reg { + volatile unsigned long ccfg; + volatile unsigned long crir; + volatile unsigned long pcfg; + volatile unsigned long tear; + volatile unsigned long pdcr; +}; + +/* + * SDRAMC + */ + +/* + * ROMC + */ + +/* + * DMA + */ +/* bits for MCR */ +#define TX3927_DMA_MCR_EIS(ch) (0x10000000<<(ch)) +#define TX3927_DMA_MCR_DIS(ch) (0x01000000<<(ch)) +#define TX3927_DMA_MCR_RSFIF 0x00000080 +#define TX3927_DMA_MCR_FIFUM(ch) (0x00000008<<(ch)) +#define TX3927_DMA_MCR_LE 0x00000004 +#define TX3927_DMA_MCR_RPRT 0x00000002 +#define TX3927_DMA_MCR_MSTEN 0x00000001 + +/* bits for CCRn */ +#define TX3927_DMA_CCR_DBINH 0x04000000 +#define TX3927_DMA_CCR_SBINH 0x02000000 +#define TX3927_DMA_CCR_CHRST 0x01000000 +#define TX3927_DMA_CCR_RVBYTE 0x00800000 +#define TX3927_DMA_CCR_ACKPOL 0x00400000 +#define TX3927_DMA_CCR_REQPL 0x00200000 +#define TX3927_DMA_CCR_EGREQ 0x00100000 +#define TX3927_DMA_CCR_CHDN 0x00080000 +#define TX3927_DMA_CCR_DNCTL 0x00060000 +#define TX3927_DMA_CCR_EXTRQ 0x00010000 +#define TX3927_DMA_CCR_INTRQD 0x0000e000 +#define TX3927_DMA_CCR_INTENE 0x00001000 +#define TX3927_DMA_CCR_INTENC 0x00000800 +#define TX3927_DMA_CCR_INTENT 0x00000400 +#define TX3927_DMA_CCR_CHNEN 0x00000200 +#define TX3927_DMA_CCR_XFACT 0x00000100 +#define TX3927_DMA_CCR_SNOP 0x00000080 +#define TX3927_DMA_CCR_DSTINC 0x00000040 +#define TX3927_DMA_CCR_SRCINC 0x00000020 +#define TX3927_DMA_CCR_XFSZ(order) (((order) << 2) & 0x0000001c) +#define TX3927_DMA_CCR_XFSZ_1W TX3927_DMA_CCR_XFSZ(2) +#define TX3927_DMA_CCR_XFSZ_4W TX3927_DMA_CCR_XFSZ(4) +#define TX3927_DMA_CCR_XFSZ_8W TX3927_DMA_CCR_XFSZ(5) +#define TX3927_DMA_CCR_XFSZ_16W TX3927_DMA_CCR_XFSZ(6) +#define TX3927_DMA_CCR_XFSZ_32W TX3927_DMA_CCR_XFSZ(7) +#define TX3927_DMA_CCR_MEMIO 0x00000002 +#define TX3927_DMA_CCR_ONEAD 0x00000001 + +/* bits for CSRn */ +#define TX3927_DMA_CSR_CHNACT 0x00000100 +#define TX3927_DMA_CSR_ABCHC 0x00000080 +#define TX3927_DMA_CSR_NCHNC 0x00000040 +#define TX3927_DMA_CSR_NTRNFC 0x00000020 +#define TX3927_DMA_CSR_EXTDN 0x00000010 +#define TX3927_DMA_CSR_CFERR 0x00000008 +#define TX3927_DMA_CSR_CHERR 0x00000004 +#define TX3927_DMA_CSR_DESERR 0x00000002 +#define TX3927_DMA_CSR_SORERR 0x00000001 + +/* + * IRC + */ +#define TX3927_IR_INT0 0 +#define TX3927_IR_INT1 1 +#define TX3927_IR_INT2 2 +#define TX3927_IR_INT3 3 +#define TX3927_IR_INT4 4 +#define TX3927_IR_INT5 5 +#define TX3927_IR_SIO0 6 +#define TX3927_IR_SIO1 7 +#define TX3927_IR_SIO(ch) (6 + (ch)) +#define TX3927_IR_DMA 8 +#define TX3927_IR_PIO 9 +#define TX3927_IR_PCI 10 +#define TX3927_IR_TMR(ch) (13 + (ch)) +#define TX3927_NUM_IR 16 + +/* + * PCIC + */ +/* bits for PCICMD */ +/* see PCI_COMMAND_XXX in linux/pci.h */ + +/* bits for PCISTAT */ +/* see PCI_STATUS_XXX in linux/pci.h */ +#define PCI_STATUS_NEW_CAP 0x0010 + +/* bits for ISTAT/IIM */ +#define TX3927_PCIC_IIM_ALL 0x00001600 + +/* bits for TC */ +#define TX3927_PCIC_TC_OF16E 0x00000020 +#define TX3927_PCIC_TC_IF8E 0x00000010 +#define TX3927_PCIC_TC_OF8E 0x00000008 + +/* bits for TSTAT/TIM */ +#define TX3927_PCIC_TIM_ALL 0x0003ffff + +/* bits for IOBA/MBA */ +/* see PCI_BASE_ADDRESS_XXX in linux/pci.h */ + +/* bits for PBAPMC */ +#define TX3927_PCIC_PBAPMC_RPBA 0x00000004 +#define TX3927_PCIC_PBAPMC_PBAEN 0x00000002 +#define TX3927_PCIC_PBAPMC_BMCEN 0x00000001 + +/* bits for LBSTAT/LBIM */ +#define TX3927_PCIC_LBIM_ALL 0x0000003e + +/* bits for PCISTATIM (see also PCI_STATUS_XXX in linux/pci.h */ +#define TX3927_PCIC_PCISTATIM_ALL 0x0000f900 + +/* bits for LBC */ +#define TX3927_PCIC_LBC_IBSE 0x00004000 +#define TX3927_PCIC_LBC_TIBSE 0x00002000 +#define TX3927_PCIC_LBC_TMFBSE 0x00001000 +#define TX3927_PCIC_LBC_HRST 0x00000800 +#define TX3927_PCIC_LBC_SRST 0x00000400 +#define TX3927_PCIC_LBC_EPCAD 0x00000200 +#define TX3927_PCIC_LBC_MSDSE 0x00000100 +#define TX3927_PCIC_LBC_CRR 0x00000080 +#define TX3927_PCIC_LBC_ILMDE 0x00000040 +#define TX3927_PCIC_LBC_ILIDE 0x00000020 + +#define TX3927_PCIC_IDSEL_AD_TO_SLOT(ad) ((ad) - 11) +#define TX3927_PCIC_MAX_DEVNU TX3927_PCIC_IDSEL_AD_TO_SLOT(32) + +/* + * CCFG + */ +/* CCFG : Chip Configuration */ +#define TX3927_CCFG_TLBOFF 0x00020000 +#define TX3927_CCFG_BEOW 0x00010000 +#define TX3927_CCFG_WR 0x00008000 +#define TX3927_CCFG_TOE 0x00004000 +#define TX3927_CCFG_PCIXARB 0x00002000 +#define TX3927_CCFG_PCI3 0x00001000 +#define TX3927_CCFG_PSNP 0x00000800 +#define TX3927_CCFG_PPRI 0x00000400 +#define TX3927_CCFG_PLLM 0x00000030 +#define TX3927_CCFG_ENDIAN 0x00000004 +#define TX3927_CCFG_HALT 0x00000002 +#define TX3927_CCFG_ACEHOLD 0x00000001 + +/* PCFG : Pin Configuration */ +#define TX3927_PCFG_SYSCLKEN 0x08000000 +#define TX3927_PCFG_SDRCLKEN_ALL 0x07c00000 +#define TX3927_PCFG_SDRCLKEN(ch) (0x00400000<<(ch)) +#define TX3927_PCFG_PCICLKEN_ALL 0x003c0000 +#define TX3927_PCFG_PCICLKEN(ch) (0x00040000<<(ch)) +#define TX3927_PCFG_SELALL 0x0003ffff +#define TX3927_PCFG_SELCS 0x00020000 +#define TX3927_PCFG_SELDSF 0x00010000 +#define TX3927_PCFG_SELSIOC_ALL 0x0000c000 +#define TX3927_PCFG_SELSIOC(ch) (0x00004000<<(ch)) +#define TX3927_PCFG_SELSIO_ALL 0x00003000 +#define TX3927_PCFG_SELSIO(ch) (0x00001000<<(ch)) +#define TX3927_PCFG_SELTMR_ALL 0x00000e00 +#define TX3927_PCFG_SELTMR(ch) (0x00000200<<(ch)) +#define TX3927_PCFG_SELDONE 0x00000100 +#define TX3927_PCFG_INTDMA_ALL 0x000000f0 +#define TX3927_PCFG_INTDMA(ch) (0x00000010<<(ch)) +#define TX3927_PCFG_SELDMA_ALL 0x0000000f +#define TX3927_PCFG_SELDMA(ch) (0x00000001<<(ch)) + +#define tx3927_sdramcptr ((struct tx3927_sdramc_reg *)TX3927_SDRAMC_REG) +#define tx3927_romcptr ((struct tx3927_romc_reg *)TX3927_ROMC_REG) +#define tx3927_dmaptr ((struct tx3927_dma_reg *)TX3927_DMA_REG) +#define tx3927_pcicptr ((struct tx3927_pcic_reg *)TX3927_PCIC_REG) +#define tx3927_ccfgptr ((struct tx3927_ccfg_reg *)TX3927_CCFG_REG) +#define tx3927_sioptr(ch) ((struct txx927_sio_reg *)TX3927_SIO_REG(ch)) +#define tx3927_pioptr ((struct txx9_pio_reg __iomem *)TX3927_PIO_REG) + +#define TX3927_REV_PCODE() (tx3927_ccfgptr->crir >> 16) +#define TX3927_ROMC_BA(ch) (tx3927_romcptr->cr[(ch)] & 0xfff00000) +#define TX3927_ROMC_SIZE(ch) \ + (0x00100000 << ((tx3927_romcptr->cr[(ch)] >> 8) & 0xf)) +#define TX3927_ROMC_WIDTH(ch) (32 >> ((tx3927_romcptr->cr[(ch)] >> 7) & 0x1)) + +void tx3927_wdt_init(void); +void tx3927_setup(void); +void tx3927_time_init(unsigned int evt_tmrnr, unsigned int src_tmrnr); +void tx3927_sio_init(unsigned int sclk, unsigned int cts_mask); +struct pci_controller; +void tx3927_pcic_setup(struct pci_controller *channel, + unsigned long sdram_size, int extarb); +void tx3927_setup_pcierr_irq(void); +void tx3927_irq_init(void); +void tx3927_mtd_init(int ch); + +#endif /* __ASM_TXX9_TX3927_H */ diff --git a/arch/mips/include/asm/txx9/tx4927.h b/arch/mips/include/asm/txx9/tx4927.h new file mode 100644 index 00000000000..7d813f1cb98 --- /dev/null +++ b/arch/mips/include/asm/txx9/tx4927.h @@ -0,0 +1,269 @@ +/* + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2006 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __ASM_TXX9_TX4927_H +#define __ASM_TXX9_TX4927_H + +#include +#include +#include +#include + +#ifdef CONFIG_64BIT +#define TX4927_REG_BASE 0xffffffffff1f0000UL +#else +#define TX4927_REG_BASE 0xff1f0000UL +#endif +#define TX4927_REG_SIZE 0x00010000 + +#define TX4927_SDRAMC_REG (TX4927_REG_BASE + 0x8000) +#define TX4927_EBUSC_REG (TX4927_REG_BASE + 0x9000) +#define TX4927_PCIC_REG (TX4927_REG_BASE + 0xd000) +#define TX4927_CCFG_REG (TX4927_REG_BASE + 0xe000) +#define TX4927_IRC_REG (TX4927_REG_BASE + 0xf600) +#define TX4927_NR_TMR 3 +#define TX4927_TMR_REG(ch) (TX4927_REG_BASE + 0xf000 + (ch) * 0x100) +#define TX4927_NR_SIO 2 +#define TX4927_SIO_REG(ch) (TX4927_REG_BASE + 0xf300 + (ch) * 0x100) +#define TX4927_PIO_REG (TX4927_REG_BASE + 0xf500) + +#define TX4927_IR_ECCERR 0 +#define TX4927_IR_WTOERR 1 +#define TX4927_NUM_IR_INT 6 +#define TX4927_IR_INT(n) (2 + (n)) +#define TX4927_NUM_IR_SIO 2 +#define TX4927_IR_SIO(n) (8 + (n)) +#define TX4927_NUM_IR_DMA 4 +#define TX4927_IR_DMA(n) (10 + (n)) +#define TX4927_IR_PIO 14 +#define TX4927_IR_PDMAC 15 +#define TX4927_IR_PCIC 16 +#define TX4927_NUM_IR_TMR 3 +#define TX4927_IR_TMR(n) (17 + (n)) +#define TX4927_IR_PCIERR 22 +#define TX4927_IR_PCIPME 23 +#define TX4927_IR_ACLC 24 +#define TX4927_IR_ACLCPME 25 +#define TX4927_NUM_IR 32 + +#define TX4927_IRC_INT 2 /* IP[2] in Status register */ + +#define TX4927_NUM_PIO 16 + +struct tx4927_sdramc_reg { + u64 cr[4]; + u64 unused0[4]; + u64 tr; + u64 unused1[2]; + u64 cmd; +}; + +struct tx4927_ebusc_reg { + u64 cr[8]; +}; + +struct tx4927_ccfg_reg { + u64 ccfg; + u64 crir; + u64 pcfg; + u64 toea; + u64 clkctr; + u64 unused0; + u64 garbc; + u64 unused1; + u64 unused2; + u64 ramp; +}; + +/* + * CCFG + */ +/* CCFG : Chip Configuration */ +#define TX4927_CCFG_WDRST 0x0000020000000000ULL +#define TX4927_CCFG_WDREXEN 0x0000010000000000ULL +#define TX4927_CCFG_BCFG_MASK 0x000000ff00000000ULL +#define TX4927_CCFG_TINTDIS 0x01000000 +#define TX4927_CCFG_PCI66 0x00800000 +#define TX4927_CCFG_PCIMODE 0x00400000 +#define TX4927_CCFG_DIVMODE_MASK 0x000e0000 +#define TX4927_CCFG_DIVMODE_8 (0x0 << 17) +#define TX4927_CCFG_DIVMODE_12 (0x1 << 17) +#define TX4927_CCFG_DIVMODE_16 (0x2 << 17) +#define TX4927_CCFG_DIVMODE_10 (0x3 << 17) +#define TX4927_CCFG_DIVMODE_2 (0x4 << 17) +#define TX4927_CCFG_DIVMODE_3 (0x5 << 17) +#define TX4927_CCFG_DIVMODE_4 (0x6 << 17) +#define TX4927_CCFG_DIVMODE_2_5 (0x7 << 17) +#define TX4927_CCFG_BEOW 0x00010000 +#define TX4927_CCFG_WR 0x00008000 +#define TX4927_CCFG_TOE 0x00004000 +#define TX4927_CCFG_PCIARB 0x00002000 +#define TX4927_CCFG_PCIDIVMODE_MASK 0x00001800 +#define TX4927_CCFG_PCIDIVMODE_2_5 0x00000000 +#define TX4927_CCFG_PCIDIVMODE_3 0x00000800 +#define TX4927_CCFG_PCIDIVMODE_5 0x00001000 +#define TX4927_CCFG_PCIDIVMODE_6 0x00001800 +#define TX4927_CCFG_SYSSP_MASK 0x000000c0 +#define TX4927_CCFG_ENDIAN 0x00000004 +#define TX4927_CCFG_HALT 0x00000002 +#define TX4927_CCFG_ACEHOLD 0x00000001 +#define TX4927_CCFG_W1CBITS (TX4927_CCFG_WDRST | TX4927_CCFG_BEOW) + +/* PCFG : Pin Configuration */ +#define TX4927_PCFG_SDCLKDLY_MASK 0x30000000 +#define TX4927_PCFG_SDCLKDLY(d) ((d)<<28) +#define TX4927_PCFG_SYSCLKEN 0x08000000 +#define TX4927_PCFG_SDCLKEN_ALL 0x07800000 +#define TX4927_PCFG_SDCLKEN(ch) (0x00800000<<(ch)) +#define TX4927_PCFG_PCICLKEN_ALL 0x003f0000 +#define TX4927_PCFG_PCICLKEN(ch) (0x00010000<<(ch)) +#define TX4927_PCFG_SEL2 0x00000200 +#define TX4927_PCFG_SEL1 0x00000100 +#define TX4927_PCFG_DMASEL_ALL 0x000000ff +#define TX4927_PCFG_DMASEL0_MASK 0x00000003 +#define TX4927_PCFG_DMASEL1_MASK 0x0000000c +#define TX4927_PCFG_DMASEL2_MASK 0x00000030 +#define TX4927_PCFG_DMASEL3_MASK 0x000000c0 +#define TX4927_PCFG_DMASEL0_DRQ0 0x00000000 +#define TX4927_PCFG_DMASEL0_SIO1 0x00000001 +#define TX4927_PCFG_DMASEL0_ACL0 0x00000002 +#define TX4927_PCFG_DMASEL0_ACL2 0x00000003 +#define TX4927_PCFG_DMASEL1_DRQ1 0x00000000 +#define TX4927_PCFG_DMASEL1_SIO1 0x00000004 +#define TX4927_PCFG_DMASEL1_ACL1 0x00000008 +#define TX4927_PCFG_DMASEL1_ACL3 0x0000000c +#define TX4927_PCFG_DMASEL2_DRQ2 0x00000000 /* SEL2=0 */ +#define TX4927_PCFG_DMASEL2_SIO0 0x00000010 /* SEL2=0 */ +#define TX4927_PCFG_DMASEL2_ACL1 0x00000000 /* SEL2=1 */ +#define TX4927_PCFG_DMASEL2_ACL2 0x00000020 /* SEL2=1 */ +#define TX4927_PCFG_DMASEL2_ACL0 0x00000030 /* SEL2=1 */ +#define TX4927_PCFG_DMASEL3_DRQ3 0x00000000 +#define TX4927_PCFG_DMASEL3_SIO0 0x00000040 +#define TX4927_PCFG_DMASEL3_ACL3 0x00000080 +#define TX4927_PCFG_DMASEL3_ACL1 0x000000c0 + +/* CLKCTR : Clock Control */ +#define TX4927_CLKCTR_ACLCKD 0x02000000 +#define TX4927_CLKCTR_PIOCKD 0x01000000 +#define TX4927_CLKCTR_DMACKD 0x00800000 +#define TX4927_CLKCTR_PCICKD 0x00400000 +#define TX4927_CLKCTR_TM0CKD 0x00100000 +#define TX4927_CLKCTR_TM1CKD 0x00080000 +#define TX4927_CLKCTR_TM2CKD 0x00040000 +#define TX4927_CLKCTR_SIO0CKD 0x00020000 +#define TX4927_CLKCTR_SIO1CKD 0x00010000 +#define TX4927_CLKCTR_ACLRST 0x00000200 +#define TX4927_CLKCTR_PIORST 0x00000100 +#define TX4927_CLKCTR_DMARST 0x00000080 +#define TX4927_CLKCTR_PCIRST 0x00000040 +#define TX4927_CLKCTR_TM0RST 0x00000010 +#define TX4927_CLKCTR_TM1RST 0x00000008 +#define TX4927_CLKCTR_TM2RST 0x00000004 +#define TX4927_CLKCTR_SIO0RST 0x00000002 +#define TX4927_CLKCTR_SIO1RST 0x00000001 + +#define tx4927_sdramcptr \ + ((struct tx4927_sdramc_reg __iomem *)TX4927_SDRAMC_REG) +#define tx4927_pcicptr \ + ((struct tx4927_pcic_reg __iomem *)TX4927_PCIC_REG) +#define tx4927_ccfgptr \ + ((struct tx4927_ccfg_reg __iomem *)TX4927_CCFG_REG) +#define tx4927_ebuscptr \ + ((struct tx4927_ebusc_reg __iomem *)TX4927_EBUSC_REG) +#define tx4927_pioptr ((struct txx9_pio_reg __iomem *)TX4927_PIO_REG) + +#define TX4927_REV_PCODE() \ + ((__u32)__raw_readq(&tx4927_ccfgptr->crir) >> 16) + +#define TX4927_SDRAMC_CR(ch) __raw_readq(&tx4927_sdramcptr->cr[(ch)]) +#define TX4927_SDRAMC_BA(ch) ((TX4927_SDRAMC_CR(ch) >> 49) << 21) +#define TX4927_SDRAMC_SIZE(ch) \ + ((((TX4927_SDRAMC_CR(ch) >> 33) & 0x7fff) + 1) << 21) + +#define TX4927_EBUSC_CR(ch) __raw_readq(&tx4927_ebuscptr->cr[(ch)]) +#define TX4927_EBUSC_BA(ch) ((TX4927_EBUSC_CR(ch) >> 48) << 20) +#define TX4927_EBUSC_SIZE(ch) \ + (0x00100000 << ((unsigned long)(TX4927_EBUSC_CR(ch) >> 8) & 0xf)) +#define TX4927_EBUSC_WIDTH(ch) \ + (64 >> ((__u32)(TX4927_EBUSC_CR(ch) >> 20) & 0x3)) + +/* utilities */ +static inline void txx9_clear64(__u64 __iomem *adr, __u64 bits) +{ +#ifdef CONFIG_32BIT + unsigned long flags; + local_irq_save(flags); +#endif + ____raw_writeq(____raw_readq(adr) & ~bits, adr); +#ifdef CONFIG_32BIT + local_irq_restore(flags); +#endif +} +static inline void txx9_set64(__u64 __iomem *adr, __u64 bits) +{ +#ifdef CONFIG_32BIT + unsigned long flags; + local_irq_save(flags); +#endif + ____raw_writeq(____raw_readq(adr) | bits, adr); +#ifdef CONFIG_32BIT + local_irq_restore(flags); +#endif +} + +/* These functions are not interrupt safe. */ +static inline void tx4927_ccfg_clear(__u64 bits) +{ + ____raw_writeq(____raw_readq(&tx4927_ccfgptr->ccfg) + & ~(TX4927_CCFG_W1CBITS | bits), + &tx4927_ccfgptr->ccfg); +} +static inline void tx4927_ccfg_set(__u64 bits) +{ + ____raw_writeq((____raw_readq(&tx4927_ccfgptr->ccfg) + & ~TX4927_CCFG_W1CBITS) | bits, + &tx4927_ccfgptr->ccfg); +} +static inline void tx4927_ccfg_change(__u64 change, __u64 new) +{ + ____raw_writeq((____raw_readq(&tx4927_ccfgptr->ccfg) + & ~(TX4927_CCFG_W1CBITS | change)) | + new, + &tx4927_ccfgptr->ccfg); +} + +unsigned int tx4927_get_mem_size(void); +void tx4927_wdt_init(void); +void tx4927_setup(void); +void tx4927_time_init(unsigned int tmrnr); +void tx4927_sio_init(unsigned int sclk, unsigned int cts_mask); +int tx4927_report_pciclk(void); +int tx4927_pciclk66_setup(void); +void tx4927_setup_pcierr_irq(void); +void tx4927_irq_init(void); +void tx4927_mtd_init(int ch); + +#endif /* __ASM_TXX9_TX4927_H */ diff --git a/arch/mips/include/asm/txx9/tx4927pcic.h b/arch/mips/include/asm/txx9/tx4927pcic.h new file mode 100644 index 00000000000..c470b8a5fe5 --- /dev/null +++ b/arch/mips/include/asm/txx9/tx4927pcic.h @@ -0,0 +1,203 @@ +/* + * include/asm-mips/txx9/tx4927pcic.h + * TX4927 PCI controller definitions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_TXX9_TX4927PCIC_H +#define __ASM_TXX9_TX4927PCIC_H + +#include +#include + +struct tx4927_pcic_reg { + u32 pciid; + u32 pcistatus; + u32 pciccrev; + u32 pcicfg1; + u32 p2gm0plbase; /* +10 */ + u32 p2gm0pubase; + u32 p2gm1plbase; + u32 p2gm1pubase; + u32 p2gm2pbase; /* +20 */ + u32 p2giopbase; + u32 unused0; + u32 pcisid; + u32 unused1; /* +30 */ + u32 pcicapptr; + u32 unused2; + u32 pcicfg2; + u32 g2ptocnt; /* +40 */ + u32 unused3[15]; + u32 g2pstatus; /* +80 */ + u32 g2pmask; + u32 pcisstatus; + u32 pcimask; + u32 p2gcfg; /* +90 */ + u32 p2gstatus; + u32 p2gmask; + u32 p2gccmd; + u32 unused4[24]; /* +a0 */ + u32 pbareqport; /* +100 */ + u32 pbacfg; + u32 pbastatus; + u32 pbamask; + u32 pbabm; /* +110 */ + u32 pbacreq; + u32 pbacgnt; + u32 pbacstate; + u64 g2pmgbase[3]; /* +120 */ + u64 g2piogbase; + u32 g2pmmask[3]; /* +140 */ + u32 g2piomask; + u64 g2pmpbase[3]; /* +150 */ + u64 g2piopbase; + u32 pciccfg; /* +170 */ + u32 pcicstatus; + u32 pcicmask; + u32 unused5; + u64 p2gmgbase[3]; /* +180 */ + u64 p2giogbase; + u32 g2pcfgadrs; /* +1a0 */ + u32 g2pcfgdata; + u32 unused6[8]; + u32 g2pintack; + u32 g2pspc; + u32 unused7[12]; /* +1d0 */ + u64 pdmca; /* +200 */ + u64 pdmga; + u64 pdmpa; + u64 pdmctr; + u64 pdmcfg; /* +220 */ + u64 pdmsts; +}; + +/* bits for PCICMD */ +/* see PCI_COMMAND_XXX in linux/pci_regs.h */ + +/* bits for PCISTAT */ +/* see PCI_STATUS_XXX in linux/pci_regs.h */ + +/* bits for IOBA/MBA */ +/* see PCI_BASE_ADDRESS_XXX in linux/pci_regs.h */ + +/* bits for G2PSTATUS/G2PMASK */ +#define TX4927_PCIC_G2PSTATUS_ALL 0x00000003 +#define TX4927_PCIC_G2PSTATUS_TTOE 0x00000002 +#define TX4927_PCIC_G2PSTATUS_RTOE 0x00000001 + +/* bits for PCIMASK (see also PCI_STATUS_XXX in linux/pci_regs.h */ +#define TX4927_PCIC_PCISTATUS_ALL 0x0000f900 + +/* bits for PBACFG */ +#define TX4927_PCIC_PBACFG_FIXPA 0x00000008 +#define TX4927_PCIC_PBACFG_RPBA 0x00000004 +#define TX4927_PCIC_PBACFG_PBAEN 0x00000002 +#define TX4927_PCIC_PBACFG_BMCEN 0x00000001 + +/* bits for PBASTATUS/PBAMASK */ +#define TX4927_PCIC_PBASTATUS_ALL 0x00000001 +#define TX4927_PCIC_PBASTATUS_BM 0x00000001 + +/* bits for G2PMnGBASE */ +#define TX4927_PCIC_G2PMnGBASE_BSDIS 0x0000002000000000ULL +#define TX4927_PCIC_G2PMnGBASE_ECHG 0x0000001000000000ULL + +/* bits for G2PIOGBASE */ +#define TX4927_PCIC_G2PIOGBASE_BSDIS 0x0000002000000000ULL +#define TX4927_PCIC_G2PIOGBASE_ECHG 0x0000001000000000ULL + +/* bits for PCICSTATUS/PCICMASK */ +#define TX4927_PCIC_PCICSTATUS_ALL 0x000007b8 +#define TX4927_PCIC_PCICSTATUS_PME 0x00000400 +#define TX4927_PCIC_PCICSTATUS_TLB 0x00000200 +#define TX4927_PCIC_PCICSTATUS_NIB 0x00000100 +#define TX4927_PCIC_PCICSTATUS_ZIB 0x00000080 +#define TX4927_PCIC_PCICSTATUS_PERR 0x00000020 +#define TX4927_PCIC_PCICSTATUS_SERR 0x00000010 +#define TX4927_PCIC_PCICSTATUS_GBE 0x00000008 +#define TX4927_PCIC_PCICSTATUS_IWB 0x00000002 +#define TX4927_PCIC_PCICSTATUS_E2PDONE 0x00000001 + +/* bits for PCICCFG */ +#define TX4927_PCIC_PCICCFG_GBWC_MASK 0x0fff0000 +#define TX4927_PCIC_PCICCFG_HRST 0x00000800 +#define TX4927_PCIC_PCICCFG_SRST 0x00000400 +#define TX4927_PCIC_PCICCFG_IRBER 0x00000200 +#define TX4927_PCIC_PCICCFG_G2PMEN(ch) (0x00000100>>(ch)) +#define TX4927_PCIC_PCICCFG_G2PM0EN 0x00000100 +#define TX4927_PCIC_PCICCFG_G2PM1EN 0x00000080 +#define TX4927_PCIC_PCICCFG_G2PM2EN 0x00000040 +#define TX4927_PCIC_PCICCFG_G2PIOEN 0x00000020 +#define TX4927_PCIC_PCICCFG_TCAR 0x00000010 +#define TX4927_PCIC_PCICCFG_ICAEN 0x00000008 + +/* bits for P2GMnGBASE */ +#define TX4927_PCIC_P2GMnGBASE_TMEMEN 0x0000004000000000ULL +#define TX4927_PCIC_P2GMnGBASE_TBSDIS 0x0000002000000000ULL +#define TX4927_PCIC_P2GMnGBASE_TECHG 0x0000001000000000ULL + +/* bits for P2GIOGBASE */ +#define TX4927_PCIC_P2GIOGBASE_TIOEN 0x0000004000000000ULL +#define TX4927_PCIC_P2GIOGBASE_TBSDIS 0x0000002000000000ULL +#define TX4927_PCIC_P2GIOGBASE_TECHG 0x0000001000000000ULL + +#define TX4927_PCIC_IDSEL_AD_TO_SLOT(ad) ((ad) - 11) +#define TX4927_PCIC_MAX_DEVNU TX4927_PCIC_IDSEL_AD_TO_SLOT(32) + +/* bits for PDMCFG */ +#define TX4927_PCIC_PDMCFG_RSTFIFO 0x00200000 +#define TX4927_PCIC_PDMCFG_EXFER 0x00100000 +#define TX4927_PCIC_PDMCFG_REQDLY_MASK 0x00003800 +#define TX4927_PCIC_PDMCFG_REQDLY_NONE (0 << 11) +#define TX4927_PCIC_PDMCFG_REQDLY_16 (1 << 11) +#define TX4927_PCIC_PDMCFG_REQDLY_32 (2 << 11) +#define TX4927_PCIC_PDMCFG_REQDLY_64 (3 << 11) +#define TX4927_PCIC_PDMCFG_REQDLY_128 (4 << 11) +#define TX4927_PCIC_PDMCFG_REQDLY_256 (5 << 11) +#define TX4927_PCIC_PDMCFG_REQDLY_512 (6 << 11) +#define TX4927_PCIC_PDMCFG_REQDLY_1024 (7 << 11) +#define TX4927_PCIC_PDMCFG_ERRIE 0x00000400 +#define TX4927_PCIC_PDMCFG_NCCMPIE 0x00000200 +#define TX4927_PCIC_PDMCFG_NTCMPIE 0x00000100 +#define TX4927_PCIC_PDMCFG_CHNEN 0x00000080 +#define TX4927_PCIC_PDMCFG_XFRACT 0x00000040 +#define TX4927_PCIC_PDMCFG_BSWAP 0x00000020 +#define TX4927_PCIC_PDMCFG_XFRSIZE_MASK 0x0000000c +#define TX4927_PCIC_PDMCFG_XFRSIZE_1DW 0x00000000 +#define TX4927_PCIC_PDMCFG_XFRSIZE_1QW 0x00000004 +#define TX4927_PCIC_PDMCFG_XFRSIZE_4QW 0x00000008 +#define TX4927_PCIC_PDMCFG_XFRDIRC 0x00000002 +#define TX4927_PCIC_PDMCFG_CHRST 0x00000001 + +/* bits for PDMSTS */ +#define TX4927_PCIC_PDMSTS_REQCNT_MASK 0x3f000000 +#define TX4927_PCIC_PDMSTS_FIFOCNT_MASK 0x00f00000 +#define TX4927_PCIC_PDMSTS_FIFOWP_MASK 0x000c0000 +#define TX4927_PCIC_PDMSTS_FIFORP_MASK 0x00030000 +#define TX4927_PCIC_PDMSTS_ERRINT 0x00000800 +#define TX4927_PCIC_PDMSTS_DONEINT 0x00000400 +#define TX4927_PCIC_PDMSTS_CHNEN 0x00000200 +#define TX4927_PCIC_PDMSTS_XFRACT 0x00000100 +#define TX4927_PCIC_PDMSTS_ACCMP 0x00000080 +#define TX4927_PCIC_PDMSTS_NCCMP 0x00000040 +#define TX4927_PCIC_PDMSTS_NTCMP 0x00000020 +#define TX4927_PCIC_PDMSTS_CFGERR 0x00000008 +#define TX4927_PCIC_PDMSTS_PCIERR 0x00000004 +#define TX4927_PCIC_PDMSTS_CHNERR 0x00000002 +#define TX4927_PCIC_PDMSTS_DATAERR 0x00000001 +#define TX4927_PCIC_PDMSTS_ALL_CMP 0x000000e0 +#define TX4927_PCIC_PDMSTS_ALL_ERR 0x0000000f + +struct tx4927_pcic_reg __iomem *get_tx4927_pcicptr( + struct pci_controller *channel); +void tx4927_pcic_setup(struct tx4927_pcic_reg __iomem *pcicptr, + struct pci_controller *channel, int extarb); +void tx4927_report_pcic_status(void); +char *tx4927_pcibios_setup(char *str); +void tx4927_dump_pcic_settings(void); +irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id); + +#endif /* __ASM_TXX9_TX4927PCIC_H */ diff --git a/arch/mips/include/asm/txx9/tx4938.h b/arch/mips/include/asm/txx9/tx4938.h new file mode 100644 index 00000000000..989e7751135 --- /dev/null +++ b/arch/mips/include/asm/txx9/tx4938.h @@ -0,0 +1,295 @@ +/* + * Definitions for TX4937/TX4938 + * Copyright (C) 2000-2001 Toshiba Corporation + * + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) + */ +#ifndef __ASM_TXX9_TX4938_H +#define __ASM_TXX9_TX4938_H + +/* some controllers are compatible with 4927 */ +#include + +#ifdef CONFIG_64BIT +#define TX4938_REG_BASE 0xffffffffff1f0000UL /* == TX4937_REG_BASE */ +#else +#define TX4938_REG_BASE 0xff1f0000UL /* == TX4937_REG_BASE */ +#endif +#define TX4938_REG_SIZE 0x00010000 /* == TX4937_REG_SIZE */ + +/* NDFMC, SRAMC, PCIC1, SPIC: TX4938 only */ +#define TX4938_NDFMC_REG (TX4938_REG_BASE + 0x5000) +#define TX4938_SRAMC_REG (TX4938_REG_BASE + 0x6000) +#define TX4938_PCIC1_REG (TX4938_REG_BASE + 0x7000) +#define TX4938_SDRAMC_REG (TX4938_REG_BASE + 0x8000) +#define TX4938_EBUSC_REG (TX4938_REG_BASE + 0x9000) +#define TX4938_DMA_REG(ch) (TX4938_REG_BASE + 0xb000 + (ch) * 0x800) +#define TX4938_PCIC_REG (TX4938_REG_BASE + 0xd000) +#define TX4938_CCFG_REG (TX4938_REG_BASE + 0xe000) +#define TX4938_NR_TMR 3 +#define TX4938_TMR_REG(ch) ((TX4938_REG_BASE + 0xf000) + (ch) * 0x100) +#define TX4938_NR_SIO 2 +#define TX4938_SIO_REG(ch) ((TX4938_REG_BASE + 0xf300) + (ch) * 0x100) +#define TX4938_PIO_REG (TX4938_REG_BASE + 0xf500) +#define TX4938_IRC_REG (TX4938_REG_BASE + 0xf600) +#define TX4938_ACLC_REG (TX4938_REG_BASE + 0xf700) +#define TX4938_SPI_REG (TX4938_REG_BASE + 0xf800) + +struct tx4938_sramc_reg { + u64 cr; +}; + +struct tx4938_ccfg_reg { + u64 ccfg; + u64 crir; + u64 pcfg; + u64 toea; + u64 clkctr; + u64 unused0; + u64 garbc; + u64 unused1; + u64 unused2; + u64 ramp; + u64 unused3; + u64 jmpadr; +}; + +/* + * IRC + */ + +#define TX4938_IR_ECCERR 0 +#define TX4938_IR_WTOERR 1 +#define TX4938_NUM_IR_INT 6 +#define TX4938_IR_INT(n) (2 + (n)) +#define TX4938_NUM_IR_SIO 2 +#define TX4938_IR_SIO(n) (8 + (n)) +#define TX4938_NUM_IR_DMA 4 +#define TX4938_IR_DMA(ch, n) ((ch ? 27 : 10) + (n)) /* 10-13, 27-30 */ +#define TX4938_IR_PIO 14 +#define TX4938_IR_PDMAC 15 +#define TX4938_IR_PCIC 16 +#define TX4938_NUM_IR_TMR 3 +#define TX4938_IR_TMR(n) (17 + (n)) +#define TX4938_IR_NDFMC 21 +#define TX4938_IR_PCIERR 22 +#define TX4938_IR_PCIPME 23 +#define TX4938_IR_ACLC 24 +#define TX4938_IR_ACLCPME 25 +#define TX4938_IR_PCIC1 26 +#define TX4938_IR_SPI 31 +#define TX4938_NUM_IR 32 +/* multiplex */ +#define TX4938_IR_ETH0 TX4938_IR_INT(4) +#define TX4938_IR_ETH1 TX4938_IR_INT(3) + +#define TX4938_IRC_INT 2 /* IP[2] in Status register */ + +#define TX4938_NUM_PIO 16 + +/* + * CCFG + */ +/* CCFG : Chip Configuration */ +#define TX4938_CCFG_WDRST 0x0000020000000000ULL +#define TX4938_CCFG_WDREXEN 0x0000010000000000ULL +#define TX4938_CCFG_BCFG_MASK 0x000000ff00000000ULL +#define TX4938_CCFG_TINTDIS 0x01000000 +#define TX4938_CCFG_PCI66 0x00800000 +#define TX4938_CCFG_PCIMODE 0x00400000 +#define TX4938_CCFG_PCI1_66 0x00200000 +#define TX4938_CCFG_DIVMODE_MASK 0x001e0000 +#define TX4938_CCFG_DIVMODE_2 (0x4 << 17) +#define TX4938_CCFG_DIVMODE_2_5 (0xf << 17) +#define TX4938_CCFG_DIVMODE_3 (0x5 << 17) +#define TX4938_CCFG_DIVMODE_4 (0x6 << 17) +#define TX4938_CCFG_DIVMODE_4_5 (0xd << 17) +#define TX4938_CCFG_DIVMODE_8 (0x0 << 17) +#define TX4938_CCFG_DIVMODE_10 (0xb << 17) +#define TX4938_CCFG_DIVMODE_12 (0x1 << 17) +#define TX4938_CCFG_DIVMODE_16 (0x2 << 17) +#define TX4938_CCFG_DIVMODE_18 (0x9 << 17) +#define TX4938_CCFG_BEOW 0x00010000 +#define TX4938_CCFG_WR 0x00008000 +#define TX4938_CCFG_TOE 0x00004000 +#define TX4938_CCFG_PCIARB 0x00002000 +#define TX4938_CCFG_PCIDIVMODE_MASK 0x00001c00 +#define TX4938_CCFG_PCIDIVMODE_4 (0x1 << 10) +#define TX4938_CCFG_PCIDIVMODE_4_5 (0x3 << 10) +#define TX4938_CCFG_PCIDIVMODE_5 (0x5 << 10) +#define TX4938_CCFG_PCIDIVMODE_5_5 (0x7 << 10) +#define TX4938_CCFG_PCIDIVMODE_8 (0x0 << 10) +#define TX4938_CCFG_PCIDIVMODE_9 (0x2 << 10) +#define TX4938_CCFG_PCIDIVMODE_10 (0x4 << 10) +#define TX4938_CCFG_PCIDIVMODE_11 (0x6 << 10) +#define TX4938_CCFG_PCI1DMD 0x00000100 +#define TX4938_CCFG_SYSSP_MASK 0x000000c0 +#define TX4938_CCFG_ENDIAN 0x00000004 +#define TX4938_CCFG_HALT 0x00000002 +#define TX4938_CCFG_ACEHOLD 0x00000001 + +/* PCFG : Pin Configuration */ +#define TX4938_PCFG_ETH0_SEL 0x8000000000000000ULL +#define TX4938_PCFG_ETH1_SEL 0x4000000000000000ULL +#define TX4938_PCFG_ATA_SEL 0x2000000000000000ULL +#define TX4938_PCFG_ISA_SEL 0x1000000000000000ULL +#define TX4938_PCFG_SPI_SEL 0x0800000000000000ULL +#define TX4938_PCFG_NDF_SEL 0x0400000000000000ULL +#define TX4938_PCFG_SDCLKDLY_MASK 0x30000000 +#define TX4938_PCFG_SDCLKDLY(d) ((d)<<28) +#define TX4938_PCFG_SYSCLKEN 0x08000000 +#define TX4938_PCFG_SDCLKEN_ALL 0x07800000 +#define TX4938_PCFG_SDCLKEN(ch) (0x00800000<<(ch)) +#define TX4938_PCFG_PCICLKEN_ALL 0x003f0000 +#define TX4938_PCFG_PCICLKEN(ch) (0x00010000<<(ch)) +#define TX4938_PCFG_SEL2 0x00000200 +#define TX4938_PCFG_SEL1 0x00000100 +#define TX4938_PCFG_DMASEL_ALL 0x0000000f +#define TX4938_PCFG_DMASEL0_DRQ0 0x00000000 +#define TX4938_PCFG_DMASEL0_SIO1 0x00000001 +#define TX4938_PCFG_DMASEL1_DRQ1 0x00000000 +#define TX4938_PCFG_DMASEL1_SIO1 0x00000002 +#define TX4938_PCFG_DMASEL2_DRQ2 0x00000000 +#define TX4938_PCFG_DMASEL2_SIO0 0x00000004 +#define TX4938_PCFG_DMASEL3_DRQ3 0x00000000 +#define TX4938_PCFG_DMASEL3_SIO0 0x00000008 + +/* CLKCTR : Clock Control */ +#define TX4938_CLKCTR_NDFCKD 0x0001000000000000ULL +#define TX4938_CLKCTR_NDFRST 0x0000000100000000ULL +#define TX4938_CLKCTR_ETH1CKD 0x80000000 +#define TX4938_CLKCTR_ETH0CKD 0x40000000 +#define TX4938_CLKCTR_SPICKD 0x20000000 +#define TX4938_CLKCTR_SRAMCKD 0x10000000 +#define TX4938_CLKCTR_PCIC1CKD 0x08000000 +#define TX4938_CLKCTR_DMA1CKD 0x04000000 +#define TX4938_CLKCTR_ACLCKD 0x02000000 +#define TX4938_CLKCTR_PIOCKD 0x01000000 +#define TX4938_CLKCTR_DMACKD 0x00800000 +#define TX4938_CLKCTR_PCICKD 0x00400000 +#define TX4938_CLKCTR_TM0CKD 0x00100000 +#define TX4938_CLKCTR_TM1CKD 0x00080000 +#define TX4938_CLKCTR_TM2CKD 0x00040000 +#define TX4938_CLKCTR_SIO0CKD 0x00020000 +#define TX4938_CLKCTR_SIO1CKD 0x00010000 +#define TX4938_CLKCTR_ETH1RST 0x00008000 +#define TX4938_CLKCTR_ETH0RST 0x00004000 +#define TX4938_CLKCTR_SPIRST 0x00002000 +#define TX4938_CLKCTR_SRAMRST 0x00001000 +#define TX4938_CLKCTR_PCIC1RST 0x00000800 +#define TX4938_CLKCTR_DMA1RST 0x00000400 +#define TX4938_CLKCTR_ACLRST 0x00000200 +#define TX4938_CLKCTR_PIORST 0x00000100 +#define TX4938_CLKCTR_DMARST 0x00000080 +#define TX4938_CLKCTR_PCIRST 0x00000040 +#define TX4938_CLKCTR_TM0RST 0x00000010 +#define TX4938_CLKCTR_TM1RST 0x00000008 +#define TX4938_CLKCTR_TM2RST 0x00000004 +#define TX4938_CLKCTR_SIO0RST 0x00000002 +#define TX4938_CLKCTR_SIO1RST 0x00000001 + +/* + * DMA + */ +/* bits for MCR */ +#define TX4938_DMA_MCR_EIS(ch) (0x10000000<<(ch)) +#define TX4938_DMA_MCR_DIS(ch) (0x01000000<<(ch)) +#define TX4938_DMA_MCR_RSFIF 0x00000080 +#define TX4938_DMA_MCR_FIFUM(ch) (0x00000008<<(ch)) +#define TX4938_DMA_MCR_RPRT 0x00000002 +#define TX4938_DMA_MCR_MSTEN 0x00000001 + +/* bits for CCRn */ +#define TX4938_DMA_CCR_IMMCHN 0x20000000 +#define TX4938_DMA_CCR_USEXFSZ 0x10000000 +#define TX4938_DMA_CCR_LE 0x08000000 +#define TX4938_DMA_CCR_DBINH 0x04000000 +#define TX4938_DMA_CCR_SBINH 0x02000000 +#define TX4938_DMA_CCR_CHRST 0x01000000 +#define TX4938_DMA_CCR_RVBYTE 0x00800000 +#define TX4938_DMA_CCR_ACKPOL 0x00400000 +#define TX4938_DMA_CCR_REQPL 0x00200000 +#define TX4938_DMA_CCR_EGREQ 0x00100000 +#define TX4938_DMA_CCR_CHDN 0x00080000 +#define TX4938_DMA_CCR_DNCTL 0x00060000 +#define TX4938_DMA_CCR_EXTRQ 0x00010000 +#define TX4938_DMA_CCR_INTRQD 0x0000e000 +#define TX4938_DMA_CCR_INTENE 0x00001000 +#define TX4938_DMA_CCR_INTENC 0x00000800 +#define TX4938_DMA_CCR_INTENT 0x00000400 +#define TX4938_DMA_CCR_CHNEN 0x00000200 +#define TX4938_DMA_CCR_XFACT 0x00000100 +#define TX4938_DMA_CCR_SMPCHN 0x00000020 +#define TX4938_DMA_CCR_XFSZ(order) (((order) << 2) & 0x0000001c) +#define TX4938_DMA_CCR_XFSZ_1W TX4938_DMA_CCR_XFSZ(2) +#define TX4938_DMA_CCR_XFSZ_2W TX4938_DMA_CCR_XFSZ(3) +#define TX4938_DMA_CCR_XFSZ_4W TX4938_DMA_CCR_XFSZ(4) +#define TX4938_DMA_CCR_XFSZ_8W TX4938_DMA_CCR_XFSZ(5) +#define TX4938_DMA_CCR_XFSZ_16W TX4938_DMA_CCR_XFSZ(6) +#define TX4938_DMA_CCR_XFSZ_32W TX4938_DMA_CCR_XFSZ(7) +#define TX4938_DMA_CCR_MEMIO 0x00000002 +#define TX4938_DMA_CCR_SNGAD 0x00000001 + +/* bits for CSRn */ +#define TX4938_DMA_CSR_CHNEN 0x00000400 +#define TX4938_DMA_CSR_STLXFER 0x00000200 +#define TX4938_DMA_CSR_CHNACT 0x00000100 +#define TX4938_DMA_CSR_ABCHC 0x00000080 +#define TX4938_DMA_CSR_NCHNC 0x00000040 +#define TX4938_DMA_CSR_NTRNFC 0x00000020 +#define TX4938_DMA_CSR_EXTDN 0x00000010 +#define TX4938_DMA_CSR_CFERR 0x00000008 +#define TX4938_DMA_CSR_CHERR 0x00000004 +#define TX4938_DMA_CSR_DESERR 0x00000002 +#define TX4938_DMA_CSR_SORERR 0x00000001 + +#define tx4938_sdramcptr tx4927_sdramcptr +#define tx4938_ebuscptr tx4927_ebuscptr +#define tx4938_pcicptr tx4927_pcicptr +#define tx4938_pcic1ptr \ + ((struct tx4927_pcic_reg __iomem *)TX4938_PCIC1_REG) +#define tx4938_ccfgptr \ + ((struct tx4938_ccfg_reg __iomem *)TX4938_CCFG_REG) +#define tx4938_pioptr ((struct txx9_pio_reg __iomem *)TX4938_PIO_REG) +#define tx4938_sramcptr \ + ((struct tx4938_sramc_reg __iomem *)TX4938_SRAMC_REG) + + +#define TX4938_REV_PCODE() \ + ((__u32)__raw_readq(&tx4938_ccfgptr->crir) >> 16) + +#define tx4938_ccfg_clear(bits) tx4927_ccfg_clear(bits) +#define tx4938_ccfg_set(bits) tx4927_ccfg_set(bits) +#define tx4938_ccfg_change(change, new) tx4927_ccfg_change(change, new) + +#define TX4938_SDRAMC_CR(ch) TX4927_SDRAMC_CR(ch) +#define TX4938_SDRAMC_BA(ch) TX4927_SDRAMC_BA(ch) +#define TX4938_SDRAMC_SIZE(ch) TX4927_SDRAMC_SIZE(ch) + +#define TX4938_EBUSC_CR(ch) TX4927_EBUSC_CR(ch) +#define TX4938_EBUSC_BA(ch) TX4927_EBUSC_BA(ch) +#define TX4938_EBUSC_SIZE(ch) TX4927_EBUSC_SIZE(ch) +#define TX4938_EBUSC_WIDTH(ch) TX4927_EBUSC_WIDTH(ch) + +#define tx4938_get_mem_size() tx4927_get_mem_size() +void tx4938_wdt_init(void); +void tx4938_setup(void); +void tx4938_time_init(unsigned int tmrnr); +void tx4938_sio_init(unsigned int sclk, unsigned int cts_mask); +void tx4938_spi_init(int busid); +void tx4938_ethaddr_init(unsigned char *addr0, unsigned char *addr1); +int tx4938_report_pciclk(void); +void tx4938_report_pci1clk(void); +int tx4938_pciclk66_setup(void); +struct pci_dev; +int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot); +void tx4938_setup_pcierr_irq(void); +void tx4938_irq_init(void); +void tx4938_mtd_init(int ch); + +#endif diff --git a/arch/mips/include/asm/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h new file mode 100644 index 00000000000..7ce2dff3b7c --- /dev/null +++ b/arch/mips/include/asm/txx9/tx4939.h @@ -0,0 +1,544 @@ +/* + * Definitions for TX4939 + * + * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ASM_TXX9_TX4939_H +#define __ASM_TXX9_TX4939_H + +/* some controllers are compatible with 4927/4938 */ +#include + +#ifdef CONFIG_64BIT +#define TX4939_REG_BASE 0xffffffffff1f0000UL /* == TX4938_REG_BASE */ +#else +#define TX4939_REG_BASE 0xff1f0000UL /* == TX4938_REG_BASE */ +#endif +#define TX4939_REG_SIZE 0x00010000 /* == TX4938_REG_SIZE */ + +#define TX4939_ATA_REG(ch) (TX4939_REG_BASE + 0x3000 + (ch) * 0x1000) +#define TX4939_NDFMC_REG (TX4939_REG_BASE + 0x5000) +#define TX4939_SRAMC_REG (TX4939_REG_BASE + 0x6000) +#define TX4939_CRYPTO_REG (TX4939_REG_BASE + 0x6800) +#define TX4939_PCIC1_REG (TX4939_REG_BASE + 0x7000) +#define TX4939_DDRC_REG (TX4939_REG_BASE + 0x8000) +#define TX4939_EBUSC_REG (TX4939_REG_BASE + 0x9000) +#define TX4939_VPC_REG (TX4939_REG_BASE + 0xa000) +#define TX4939_DMA_REG(ch) (TX4939_REG_BASE + 0xb000 + (ch) * 0x800) +#define TX4939_PCIC_REG (TX4939_REG_BASE + 0xd000) +#define TX4939_CCFG_REG (TX4939_REG_BASE + 0xe000) +#define TX4939_IRC_REG (TX4939_REG_BASE + 0xe800) +#define TX4939_NR_TMR 6 /* 0xf000,0xf100,0xf200,0xfd00,0xfe00,0xff00 */ +#define TX4939_TMR_REG(ch) \ + (TX4939_REG_BASE + 0xf000 + ((ch) + ((ch) >= 3) * 10) * 0x100) +#define TX4939_NR_SIO 4 /* 0xf300, 0xf400, 0xf380, 0xf480 */ +#define TX4939_SIO_REG(ch) \ + (TX4939_REG_BASE + 0xf300 + (((ch) & 1) << 8) + (((ch) & 2) << 6)) +#define TX4939_ACLC_REG (TX4939_REG_BASE + 0xf700) +#define TX4939_SPI_REG (TX4939_REG_BASE + 0xf800) +#define TX4939_I2C_REG (TX4939_REG_BASE + 0xf900) +#define TX4939_I2S_REG (TX4939_REG_BASE + 0xfa00) +#define TX4939_RTC_REG (TX4939_REG_BASE + 0xfb00) +#define TX4939_CIR_REG (TX4939_REG_BASE + 0xfc00) + +struct tx4939_le_reg { + __u32 r; + __u32 unused; +}; + +struct tx4939_ddrc_reg { + struct tx4939_le_reg ctl[47]; + __u64 unused0[17]; + __u64 winen; + __u64 win[4]; +}; + +struct tx4939_ccfg_reg { + __u64 ccfg; + __u64 crir; + __u64 pcfg; + __u64 toea; + __u64 clkctr; + __u64 unused0; + __u64 garbc; + __u64 unused1[2]; + __u64 ramp; + __u64 unused2[2]; + __u64 dskwctrl; + __u64 mclkosc; + __u64 mclkctl; + __u64 unused3[17]; + struct { + __u64 mr; + __u64 dr; + } gpio[2]; +}; + +struct tx4939_irc_reg { + struct tx4939_le_reg den; + struct tx4939_le_reg scipb; + struct tx4939_le_reg dm[2]; + struct tx4939_le_reg lvl[16]; + struct tx4939_le_reg msk; + struct tx4939_le_reg edc; + struct tx4939_le_reg pnd0; + struct tx4939_le_reg cs; + struct tx4939_le_reg pnd1; + struct tx4939_le_reg dm2[2]; + struct tx4939_le_reg dbr[2]; + struct tx4939_le_reg dben; + struct tx4939_le_reg unused0[2]; + struct tx4939_le_reg flag[2]; + struct tx4939_le_reg pol; + struct tx4939_le_reg cnt; + struct tx4939_le_reg maskint; + struct tx4939_le_reg maskext; +}; + +struct tx4939_rtc_reg { + __u32 ctl; + __u32 adr; + __u32 dat; + __u32 tbc; +}; + +struct tx4939_crypto_reg { + struct tx4939_le_reg csr; + struct tx4939_le_reg idesptr; + struct tx4939_le_reg cdesptr; + struct tx4939_le_reg buserr; + struct tx4939_le_reg cip_tout; + struct tx4939_le_reg cir; + union { + struct { + struct tx4939_le_reg data[8]; + struct tx4939_le_reg ctrl; + } gen; + struct { + struct { + struct tx4939_le_reg l; + struct tx4939_le_reg u; + } key[3], ini; + struct tx4939_le_reg ctrl; + } des; + struct { + struct tx4939_le_reg key[4]; + struct tx4939_le_reg ini[4]; + struct tx4939_le_reg ctrl; + } aes; + struct { + struct { + struct tx4939_le_reg l; + struct tx4939_le_reg u; + } cnt; + struct tx4939_le_reg ini[5]; + struct tx4939_le_reg unused; + struct tx4939_le_reg ctrl; + } hash; + } cdr; + struct tx4939_le_reg unused0[7]; + struct tx4939_le_reg rcsr; + struct tx4939_le_reg rpr; + __u64 rdr; + __u64 ror[3]; + struct tx4939_le_reg unused1[2]; + struct tx4939_le_reg xorslr; + struct tx4939_le_reg xorsur; +}; + +struct tx4939_crypto_desc { + __u32 src; + __u32 dst; + __u32 next; + __u32 ctrl; + __u32 index; + __u32 xor; +}; + +struct tx4939_vpc_reg { + struct tx4939_le_reg csr; + struct { + struct tx4939_le_reg ctrlA; + struct tx4939_le_reg ctrlB; + struct tx4939_le_reg idesptr; + struct tx4939_le_reg cdesptr; + } port[3]; + struct tx4939_le_reg buserr; +}; + +struct tx4939_vpc_desc { + __u32 src; + __u32 next; + __u32 ctrl1; + __u32 ctrl2; +}; + +/* + * IRC + */ +#define TX4939_IR_NONE 0 +#define TX4939_IR_DDR 1 +#define TX4939_IR_WTOERR 2 +#define TX4939_NUM_IR_INT 3 +#define TX4939_IR_INT(n) (3 + (n)) +#define TX4939_NUM_IR_ETH 2 +#define TX4939_IR_ETH(n) ((n) ? 43 : 6) +#define TX4939_IR_VIDEO 7 +#define TX4939_IR_CIR 8 +#define TX4939_NUM_IR_SIO 4 +#define TX4939_IR_SIO(n) ((n) ? 43 + (n) : 9) /* 9,44-46 */ +#define TX4939_NUM_IR_DMA 4 +#define TX4939_IR_DMA(ch, n) (((ch) ? 22 : 10) + (n)) /* 10-13,22-25 */ +#define TX4939_IR_IRC 14 +#define TX4939_IR_PDMAC 15 +#define TX4939_NUM_IR_TMR 6 +#define TX4939_IR_TMR(n) (((n) >= 3 ? 45 : 16) + (n)) /* 16-18,48-50 */ +#define TX4939_NUM_IR_ATA 2 +#define TX4939_IR_ATA(n) (19 + (n)) +#define TX4939_IR_ACLC 21 +#define TX4939_IR_CIPHER 26 +#define TX4939_IR_INTA 27 +#define TX4939_IR_INTB 28 +#define TX4939_IR_INTC 29 +#define TX4939_IR_INTD 30 +#define TX4939_IR_I2C 33 +#define TX4939_IR_SPI 34 +#define TX4939_IR_PCIC 35 +#define TX4939_IR_PCIC1 36 +#define TX4939_IR_PCIERR 37 +#define TX4939_IR_PCIPME 38 +#define TX4939_IR_NDFMC 39 +#define TX4939_IR_ACLCPME 40 +#define TX4939_IR_RTC 41 +#define TX4939_IR_RND 42 +#define TX4939_IR_I2S 47 +#define TX4939_NUM_IR 64 + +#define TX4939_IRC_INT 2 /* IP[2] in Status register */ + +/* + * CCFG + */ +/* CCFG : Chip Configuration */ +#define TX4939_CCFG_PCIBOOT 0x0000040000000000ULL +#define TX4939_CCFG_WDRST 0x0000020000000000ULL +#define TX4939_CCFG_WDREXEN 0x0000010000000000ULL +#define TX4939_CCFG_BCFG_MASK 0x000000ff00000000ULL +#define TX4939_CCFG_GTOT_MASK 0x06000000 +#define TX4939_CCFG_GTOT_4096 0x06000000 +#define TX4939_CCFG_GTOT_2048 0x04000000 +#define TX4939_CCFG_GTOT_1024 0x02000000 +#define TX4939_CCFG_GTOT_512 0x00000000 +#define TX4939_CCFG_TINTDIS 0x01000000 +#define TX4939_CCFG_PCI66 0x00800000 +#define TX4939_CCFG_PCIMODE 0x00400000 +#define TX4939_CCFG_SSCG 0x00100000 +#define TX4939_CCFG_MULCLK_MASK 0x000e0000 +#define TX4939_CCFG_MULCLK_8 (0x7 << 17) +#define TX4939_CCFG_MULCLK_9 (0x0 << 17) +#define TX4939_CCFG_MULCLK_10 (0x1 << 17) +#define TX4939_CCFG_MULCLK_11 (0x2 << 17) +#define TX4939_CCFG_MULCLK_12 (0x3 << 17) +#define TX4939_CCFG_MULCLK_13 (0x4 << 17) +#define TX4939_CCFG_MULCLK_14 (0x5 << 17) +#define TX4939_CCFG_MULCLK_15 (0x6 << 17) +#define TX4939_CCFG_BEOW 0x00010000 +#define TX4939_CCFG_WR 0x00008000 +#define TX4939_CCFG_TOE 0x00004000 +#define TX4939_CCFG_PCIARB 0x00002000 +#define TX4939_CCFG_YDIVMODE_MASK 0x00001c00 +#define TX4939_CCFG_YDIVMODE_2 (0x0 << 10) +#define TX4939_CCFG_YDIVMODE_3 (0x1 << 10) +#define TX4939_CCFG_YDIVMODE_5 (0x6 << 10) +#define TX4939_CCFG_YDIVMODE_6 (0x7 << 10) +#define TX4939_CCFG_PTSEL 0x00000200 +#define TX4939_CCFG_BESEL 0x00000100 +#define TX4939_CCFG_SYSSP_MASK 0x000000c0 +#define TX4939_CCFG_ACKSEL 0x00000020 +#define TX4939_CCFG_ROMW 0x00000010 +#define TX4939_CCFG_ENDIAN 0x00000004 +#define TX4939_CCFG_ARMODE 0x00000002 +#define TX4939_CCFG_ACEHOLD 0x00000001 + +/* PCFG : Pin Configuration */ +#define TX4939_PCFG_SIO2MODE_MASK 0xc000000000000000ULL +#define TX4939_PCFG_SIO2MODE_GPIO 0x8000000000000000ULL +#define TX4939_PCFG_SIO2MODE_SIO2 0x4000000000000000ULL +#define TX4939_PCFG_SIO2MODE_SIO0 0x0000000000000000ULL +#define TX4939_PCFG_SPIMODE 0x2000000000000000ULL +#define TX4939_PCFG_I2CMODE 0x1000000000000000ULL +#define TX4939_PCFG_I2SMODE_MASK 0x0c00000000000000ULL +#define TX4939_PCFG_I2SMODE_GPIO 0x0c00000000000000ULL +#define TX4939_PCFG_I2SMODE_I2S 0x0800000000000000ULL +#define TX4939_PCFG_I2SMODE_I2S_ALT 0x0400000000000000ULL +#define TX4939_PCFG_I2SMODE_ACLC 0x0000000000000000ULL +#define TX4939_PCFG_SIO3MODE 0x0200000000000000ULL +#define TX4939_PCFG_DMASEL3 0x0004000000000000ULL +#define TX4939_PCFG_DMASEL3_SIO0 0x0004000000000000ULL +#define TX4939_PCFG_DMASEL3_NDFC 0x0000000000000000ULL +#define TX4939_PCFG_VSSMODE 0x0000200000000000ULL +#define TX4939_PCFG_VPSMODE 0x0000100000000000ULL +#define TX4939_PCFG_ET1MODE 0x0000080000000000ULL +#define TX4939_PCFG_ET0MODE 0x0000040000000000ULL +#define TX4939_PCFG_ATA1MODE 0x0000020000000000ULL +#define TX4939_PCFG_ATA0MODE 0x0000010000000000ULL +#define TX4939_PCFG_BP_PLL 0x0000000100000000ULL + +#define TX4939_PCFG_SYSCLKEN 0x08000000 +#define TX4939_PCFG_PCICLKEN_ALL 0x000f0000 +#define TX4939_PCFG_PCICLKEN(ch) (0x00010000<<(ch)) +#define TX4939_PCFG_SPEED1 0x00002000 +#define TX4939_PCFG_SPEED0 0x00001000 +#define TX4939_PCFG_ITMODE 0x00000300 +#define TX4939_PCFG_DMASEL_ALL (0x00000007 | TX4939_PCFG_DMASEL3) +#define TX4939_PCFG_DMASEL2 0x00000004 +#define TX4939_PCFG_DMASEL2_DRQ2 0x00000000 +#define TX4939_PCFG_DMASEL2_SIO0 0x00000004 +#define TX4939_PCFG_DMASEL1 0x00000002 +#define TX4939_PCFG_DMASEL1_DRQ1 0x00000000 +#define TX4939_PCFG_DMASEL0 0x00000001 +#define TX4939_PCFG_DMASEL0_DRQ0 0x00000000 + +/* CLKCTR : Clock Control */ +#define TX4939_CLKCTR_IOSCKD 0x8000000000000000ULL +#define TX4939_CLKCTR_SYSCKD 0x4000000000000000ULL +#define TX4939_CLKCTR_TM5CKD 0x2000000000000000ULL +#define TX4939_CLKCTR_TM4CKD 0x1000000000000000ULL +#define TX4939_CLKCTR_TM3CKD 0x0800000000000000ULL +#define TX4939_CLKCTR_CIRCKD 0x0400000000000000ULL +#define TX4939_CLKCTR_SIO3CKD 0x0200000000000000ULL +#define TX4939_CLKCTR_SIO2CKD 0x0100000000000000ULL +#define TX4939_CLKCTR_SIO1CKD 0x0080000000000000ULL +#define TX4939_CLKCTR_VPCCKD 0x0040000000000000ULL +#define TX4939_CLKCTR_EPCICKD 0x0020000000000000ULL +#define TX4939_CLKCTR_ETH1CKD 0x0008000000000000ULL +#define TX4939_CLKCTR_ATA1CKD 0x0004000000000000ULL +#define TX4939_CLKCTR_BROMCKD 0x0002000000000000ULL +#define TX4939_CLKCTR_NDCCKD 0x0001000000000000ULL +#define TX4939_CLKCTR_I2CCKD 0x0000800000000000ULL +#define TX4939_CLKCTR_ETH0CKD 0x0000400000000000ULL +#define TX4939_CLKCTR_SPICKD 0x0000200000000000ULL +#define TX4939_CLKCTR_SRAMCKD 0x0000100000000000ULL +#define TX4939_CLKCTR_PCI1CKD 0x0000080000000000ULL +#define TX4939_CLKCTR_DMA1CKD 0x0000040000000000ULL +#define TX4939_CLKCTR_ACLCKD 0x0000020000000000ULL +#define TX4939_CLKCTR_ATA0CKD 0x0000010000000000ULL +#define TX4939_CLKCTR_DMA0CKD 0x0000008000000000ULL +#define TX4939_CLKCTR_PCICCKD 0x0000004000000000ULL +#define TX4939_CLKCTR_I2SCKD 0x0000002000000000ULL +#define TX4939_CLKCTR_TM0CKD 0x0000001000000000ULL +#define TX4939_CLKCTR_TM1CKD 0x0000000800000000ULL +#define TX4939_CLKCTR_TM2CKD 0x0000000400000000ULL +#define TX4939_CLKCTR_SIO0CKD 0x0000000200000000ULL +#define TX4939_CLKCTR_CYPCKD 0x0000000100000000ULL +#define TX4939_CLKCTR_IOSRST 0x80000000 +#define TX4939_CLKCTR_SYSRST 0x40000000 +#define TX4939_CLKCTR_TM5RST 0x20000000 +#define TX4939_CLKCTR_TM4RST 0x10000000 +#define TX4939_CLKCTR_TM3RST 0x08000000 +#define TX4939_CLKCTR_CIRRST 0x04000000 +#define TX4939_CLKCTR_SIO3RST 0x02000000 +#define TX4939_CLKCTR_SIO2RST 0x01000000 +#define TX4939_CLKCTR_SIO1RST 0x00800000 +#define TX4939_CLKCTR_VPCRST 0x00400000 +#define TX4939_CLKCTR_EPCIRST 0x00200000 +#define TX4939_CLKCTR_ETH1RST 0x00080000 +#define TX4939_CLKCTR_ATA1RST 0x00040000 +#define TX4939_CLKCTR_BROMRST 0x00020000 +#define TX4939_CLKCTR_NDCRST 0x00010000 +#define TX4939_CLKCTR_I2CRST 0x00008000 +#define TX4939_CLKCTR_ETH0RST 0x00004000 +#define TX4939_CLKCTR_SPIRST 0x00002000 +#define TX4939_CLKCTR_SRAMRST 0x00001000 +#define TX4939_CLKCTR_PCI1RST 0x00000800 +#define TX4939_CLKCTR_DMA1RST 0x00000400 +#define TX4939_CLKCTR_ACLRST 0x00000200 +#define TX4939_CLKCTR_ATA0RST 0x00000100 +#define TX4939_CLKCTR_DMA0RST 0x00000080 +#define TX4939_CLKCTR_PCICRST 0x00000040 +#define TX4939_CLKCTR_I2SRST 0x00000020 +#define TX4939_CLKCTR_TM0RST 0x00000010 +#define TX4939_CLKCTR_TM1RST 0x00000008 +#define TX4939_CLKCTR_TM2RST 0x00000004 +#define TX4939_CLKCTR_SIO0RST 0x00000002 +#define TX4939_CLKCTR_CYPRST 0x00000001 + +/* + * RTC + */ +#define TX4939_RTCCTL_ALME 0x00000080 +#define TX4939_RTCCTL_ALMD 0x00000040 +#define TX4939_RTCCTL_BUSY 0x00000020 + +#define TX4939_RTCCTL_COMMAND 0x00000007 +#define TX4939_RTCCTL_COMMAND_NOP 0x00000000 +#define TX4939_RTCCTL_COMMAND_GETTIME 0x00000001 +#define TX4939_RTCCTL_COMMAND_SETTIME 0x00000002 +#define TX4939_RTCCTL_COMMAND_GETALARM 0x00000003 +#define TX4939_RTCCTL_COMMAND_SETALARM 0x00000004 + +#define TX4939_RTCTBC_PM 0x00000080 +#define TX4939_RTCTBC_COMP 0x0000007f + +#define TX4939_RTC_REG_RAMSIZE 0x00000100 +#define TX4939_RTC_REG_RWBSIZE 0x00000006 + +/* + * CRYPTO + */ +#define TX4939_CRYPTO_CSR_SAESO 0x08000000 +#define TX4939_CRYPTO_CSR_SAESI 0x04000000 +#define TX4939_CRYPTO_CSR_SDESO 0x02000000 +#define TX4939_CRYPTO_CSR_SDESI 0x01000000 +#define TX4939_CRYPTO_CSR_INDXBST_MASK 0x00700000 +#define TX4939_CRYPTO_CSR_INDXBST(n) ((n) << 20) +#define TX4939_CRYPTO_CSR_TOINT 0x00080000 +#define TX4939_CRYPTO_CSR_DCINT 0x00040000 +#define TX4939_CRYPTO_CSR_GBINT 0x00010000 +#define TX4939_CRYPTO_CSR_INDXAST_MASK 0x0000e000 +#define TX4939_CRYPTO_CSR_INDXAST(n) ((n) << 13) +#define TX4939_CRYPTO_CSR_CSWAP_MASK 0x00001800 +#define TX4939_CRYPTO_CSR_CSWAP_NONE 0x00000000 +#define TX4939_CRYPTO_CSR_CSWAP_IN 0x00000800 +#define TX4939_CRYPTO_CSR_CSWAP_OUT 0x00001000 +#define TX4939_CRYPTO_CSR_CSWAP_BOTH 0x00001800 +#define TX4939_CRYPTO_CSR_CDIV_MASK 0x00000600 +#define TX4939_CRYPTO_CSR_CDIV_DIV2 0x00000000 +#define TX4939_CRYPTO_CSR_CDIV_DIV1 0x00000200 +#define TX4939_CRYPTO_CSR_CDIV_DIV2ALT 0x00000400 +#define TX4939_CRYPTO_CSR_CDIV_DIV1ALT 0x00000600 +#define TX4939_CRYPTO_CSR_PDINT_MASK 0x000000c0 +#define TX4939_CRYPTO_CSR_PDINT_ALL 0x00000000 +#define TX4939_CRYPTO_CSR_PDINT_END 0x00000040 +#define TX4939_CRYPTO_CSR_PDINT_NEXT 0x00000080 +#define TX4939_CRYPTO_CSR_PDINT_NONE 0x000000c0 +#define TX4939_CRYPTO_CSR_GINTE 0x00000008 +#define TX4939_CRYPTO_CSR_RSTD 0x00000004 +#define TX4939_CRYPTO_CSR_RSTC 0x00000002 +#define TX4939_CRYPTO_CSR_ENCR 0x00000001 + +/* bits for tx4939_crypto_reg.cdr.gen.ctrl */ +#define TX4939_CRYPTO_CTX_ENGINE_MASK 0x00000003 +#define TX4939_CRYPTO_CTX_ENGINE_DES 0x00000000 +#define TX4939_CRYPTO_CTX_ENGINE_AES 0x00000001 +#define TX4939_CRYPTO_CTX_ENGINE_MD5 0x00000002 +#define TX4939_CRYPTO_CTX_ENGINE_SHA1 0x00000003 +#define TX4939_CRYPTO_CTX_TDMS 0x00000010 +#define TX4939_CRYPTO_CTX_CMS 0x00000020 +#define TX4939_CRYPTO_CTX_DMS 0x00000040 +#define TX4939_CRYPTO_CTX_UPDATE 0x00000080 + +/* bits for tx4939_crypto_desc.ctrl */ +#define TX4939_CRYPTO_DESC_OB_CNT_MASK 0xffe00000 +#define TX4939_CRYPTO_DESC_OB_CNT(cnt) ((cnt) << 21) +#define TX4939_CRYPTO_DESC_IB_CNT_MASK 0x001ffc00 +#define TX4939_CRYPTO_DESC_IB_CNT(cnt) ((cnt) << 10) +#define TX4939_CRYPTO_DESC_START 0x00000200 +#define TX4939_CRYPTO_DESC_END 0x00000100 +#define TX4939_CRYPTO_DESC_XOR 0x00000010 +#define TX4939_CRYPTO_DESC_LAST 0x00000008 +#define TX4939_CRYPTO_DESC_ERR_MASK 0x00000006 +#define TX4939_CRYPTO_DESC_ERR_NONE 0x00000000 +#define TX4939_CRYPTO_DESC_ERR_TOUT 0x00000002 +#define TX4939_CRYPTO_DESC_ERR_DIGEST 0x00000004 +#define TX4939_CRYPTO_DESC_OWN 0x00000001 + +/* bits for tx4939_crypto_desc.index */ +#define TX4939_CRYPTO_DESC_HASH_IDX_MASK 0x00000070 +#define TX4939_CRYPTO_DESC_HASH_IDX(idx) ((idx) << 4) +#define TX4939_CRYPTO_DESC_ENCRYPT_IDX_MASK 0x00000007 +#define TX4939_CRYPTO_DESC_ENCRYPT_IDX(idx) ((idx) << 0) + +#define TX4939_CRYPTO_NR_SET 6 + +#define TX4939_CRYPTO_RCSR_INTE 0x00000008 +#define TX4939_CRYPTO_RCSR_RST 0x00000004 +#define TX4939_CRYPTO_RCSR_FIN 0x00000002 +#define TX4939_CRYPTO_RCSR_ST 0x00000001 + +/* + * VPC + */ +#define TX4939_VPC_CSR_GBINT 0x00010000 +#define TX4939_VPC_CSR_SWAPO 0x00000020 +#define TX4939_VPC_CSR_SWAPI 0x00000010 +#define TX4939_VPC_CSR_GINTE 0x00000008 +#define TX4939_VPC_CSR_RSTD 0x00000004 +#define TX4939_VPC_CSR_RSTVPC 0x00000002 + +#define TX4939_VPC_CTRLA_VDPSN 0x00000200 +#define TX4939_VPC_CTRLA_PBUSY 0x00000100 +#define TX4939_VPC_CTRLA_DCINT 0x00000080 +#define TX4939_VPC_CTRLA_UOINT 0x00000040 +#define TX4939_VPC_CTRLA_PDINT_MASK 0x00000030 +#define TX4939_VPC_CTRLA_PDINT_ALL 0x00000000 +#define TX4939_VPC_CTRLA_PDINT_NEXT 0x00000010 +#define TX4939_VPC_CTRLA_PDINT_NONE 0x00000030 +#define TX4939_VPC_CTRLA_VDVLDP 0x00000008 +#define TX4939_VPC_CTRLA_VDMODE 0x00000004 +#define TX4939_VPC_CTRLA_VDFOR 0x00000002 +#define TX4939_VPC_CTRLA_ENVPC 0x00000001 + +/* bits for tx4939_vpc_desc.ctrl1 */ +#define TX4939_VPC_DESC_CTRL1_ERR_MASK 0x00000006 +#define TX4939_VPC_DESC_CTRL1_OWN 0x00000001 + +#define tx4939_ddrcptr ((struct tx4939_ddrc_reg __iomem *)TX4939_DDRC_REG) +#define tx4939_ebuscptr tx4938_ebuscptr +#define tx4939_ircptr \ + ((struct tx4939_irc_reg __iomem *)TX4939_IRC_REG) +#define tx4939_pcicptr tx4938_pcicptr +#define tx4939_pcic1ptr tx4938_pcic1ptr +#define tx4939_ccfgptr \ + ((struct tx4939_ccfg_reg __iomem *)TX4939_CCFG_REG) +#define tx4939_sramcptr tx4938_sramcptr +#define tx4939_rtcptr \ + ((struct tx4939_rtc_reg __iomem *)TX4939_RTC_REG) +#define tx4939_cryptoptr \ + ((struct tx4939_crypto_reg __iomem *)TX4939_CRYPTO_REG) +#define tx4939_vpcptr ((struct tx4939_vpc_reg __iomem *)TX4939_VPC_REG) + +#define TX4939_REV_MAJ_MIN() \ + ((__u32)__raw_readq(&tx4939_ccfgptr->crir) & 0x00ff) +#define TX4939_REV_PCODE() \ + ((__u32)__raw_readq(&tx4939_ccfgptr->crir) >> 16) +#define TX4939_CCFG_BCFG() \ + ((__u32)((__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_BCFG_MASK) \ + >> 32)) + +#define tx4939_ccfg_clear(bits) tx4938_ccfg_clear(bits) +#define tx4939_ccfg_set(bits) tx4938_ccfg_set(bits) +#define tx4939_ccfg_change(change, new) tx4938_ccfg_change(change, new) + +#define TX4939_EBUSC_CR(ch) TX4927_EBUSC_CR(ch) +#define TX4939_EBUSC_BA(ch) TX4927_EBUSC_BA(ch) +#define TX4939_EBUSC_SIZE(ch) TX4927_EBUSC_SIZE(ch) +#define TX4939_EBUSC_WIDTH(ch) \ + (16 >> ((__u32)(TX4939_EBUSC_CR(ch) >> 20) & 0x1)) + +/* SCLK0 = MSTCLK * 429/19 * 16/245 / 2 (14.745MHz for MST 20MHz) */ +#define TX4939_SCLK0(mst) \ + ((((mst) + 245/2) / 245UL * 429 * 16 + 19) / 19 / 2) + +void tx4939_wdt_init(void); +void tx4939_add_memory_regions(void); +void tx4939_setup(void); +void tx4939_time_init(unsigned int tmrnr); +void tx4939_sio_init(unsigned int sclk, unsigned int cts_mask); +void tx4939_spi_init(int busid); +void tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1); +int tx4939_report_pciclk(void); +void tx4939_report_pci1clk(void); +struct pci_dev; +int tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot); +int tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); +void tx4939_setup_pcierr_irq(void); +void tx4939_irq_init(void); +int tx4939_irq(void); +void tx4939_mtd_init(int ch); + +#endif /* __ASM_TXX9_TX4939_H */ diff --git a/arch/mips/include/asm/txx9irq.h b/arch/mips/include/asm/txx9irq.h new file mode 100644 index 00000000000..5620879be37 --- /dev/null +++ b/arch/mips/include/asm/txx9irq.h @@ -0,0 +1,34 @@ +/* + * include/asm-mips/txx9irq.h + * TX39/TX49 interrupt controller definitions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_TXX9IRQ_H +#define __ASM_TXX9IRQ_H + +#include + +#ifdef CONFIG_IRQ_CPU +#define TXX9_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) +#else +#ifdef CONFIG_I8259 +#define TXX9_IRQ_BASE (I8259A_IRQ_BASE + 16) +#else +#define TXX9_IRQ_BASE 0 +#endif +#endif + +#ifdef CONFIG_CPU_TX39XX +#define TXx9_MAX_IR 16 +#else +#define TXx9_MAX_IR 32 +#endif + +void txx9_irq_init(unsigned long baseaddr); +int txx9_irq(void); +int txx9_irq_set_pri(int irc_irq, int new_pri); + +#endif /* __ASM_TXX9IRQ_H */ diff --git a/arch/mips/include/asm/txx9pio.h b/arch/mips/include/asm/txx9pio.h new file mode 100644 index 00000000000..3d6fa9f8d51 --- /dev/null +++ b/arch/mips/include/asm/txx9pio.h @@ -0,0 +1,29 @@ +/* + * include/asm-mips/txx9pio.h + * TX39/TX49 PIO controller definitions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_TXX9PIO_H +#define __ASM_TXX9PIO_H + +#include + +struct txx9_pio_reg { + __u32 dout; + __u32 din; + __u32 dir; + __u32 od; + __u32 flag[2]; + __u32 pol; + __u32 intc; + __u32 maskcpu; + __u32 maskext; +}; + +int txx9_gpio_init(unsigned long baseaddr, + unsigned int base, unsigned int num); + +#endif /* __ASM_TXX9PIO_H */ diff --git a/arch/mips/include/asm/txx9tmr.h b/arch/mips/include/asm/txx9tmr.h new file mode 100644 index 00000000000..67f70a8f09b --- /dev/null +++ b/arch/mips/include/asm/txx9tmr.h @@ -0,0 +1,67 @@ +/* + * include/asm-mips/txx9tmr.h + * TX39/TX49 timer controller definitions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_TXX9TMR_H +#define __ASM_TXX9TMR_H + +#include + +struct txx9_tmr_reg { + u32 tcr; + u32 tisr; + u32 cpra; + u32 cprb; + u32 itmr; + u32 unused0[3]; + u32 ccdr; + u32 unused1[3]; + u32 pgmr; + u32 unused2[3]; + u32 wtmr; + u32 unused3[43]; + u32 trr; +}; + +/* TMTCR : Timer Control */ +#define TXx9_TMTCR_TCE 0x00000080 +#define TXx9_TMTCR_CCDE 0x00000040 +#define TXx9_TMTCR_CRE 0x00000020 +#define TXx9_TMTCR_ECES 0x00000008 +#define TXx9_TMTCR_CCS 0x00000004 +#define TXx9_TMTCR_TMODE_MASK 0x00000003 +#define TXx9_TMTCR_TMODE_ITVL 0x00000000 +#define TXx9_TMTCR_TMODE_PGEN 0x00000001 +#define TXx9_TMTCR_TMODE_WDOG 0x00000002 + +/* TMTISR : Timer Int. Status */ +#define TXx9_TMTISR_TPIBS 0x00000004 +#define TXx9_TMTISR_TPIAS 0x00000002 +#define TXx9_TMTISR_TIIS 0x00000001 + +/* TMITMR : Interval Timer Mode */ +#define TXx9_TMITMR_TIIE 0x00008000 +#define TXx9_TMITMR_TZCE 0x00000001 + +/* TMWTMR : Watchdog Timer Mode */ +#define TXx9_TMWTMR_TWIE 0x00008000 +#define TXx9_TMWTMR_WDIS 0x00000080 +#define TXx9_TMWTMR_TWC 0x00000001 + +void txx9_clocksource_init(unsigned long baseaddr, + unsigned int imbusclk); +void txx9_clockevent_init(unsigned long baseaddr, int irq, + unsigned int imbusclk); +void txx9_tmr_init(unsigned long baseaddr); + +#ifdef CONFIG_CPU_TX39XX +#define TXX9_TIMER_BITS 24 +#else +#define TXX9_TIMER_BITS 32 +#endif + +#endif /* __ASM_TXX9TMR_H */ diff --git a/arch/mips/include/asm/types.h b/arch/mips/include/asm/types.h new file mode 100644 index 00000000000..bcbb8d675af --- /dev/null +++ b/arch/mips/include/asm/types.h @@ -0,0 +1,54 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_TYPES_H +#define _ASM_TYPES_H + +#if _MIPS_SZLONG == 64 +# include +#else +# include +#endif + +#ifndef __ASSEMBLY__ + +typedef unsigned short umode_t; + +#endif /* __ASSEMBLY__ */ + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +#define BITS_PER_LONG _MIPS_SZLONG + +#ifndef __ASSEMBLY__ + +#if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \ + || defined(CONFIG_64BIT) +typedef u64 dma_addr_t; +#else +typedef u32 dma_addr_t; +#endif +typedef u64 dma64_addr_t; + +/* + * Don't use phys_t. You've been warned. + */ +#ifdef CONFIG_64BIT_PHYS_ADDR +typedef unsigned long long phys_t; +#else +typedef unsigned long phys_t; +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* _ASM_TYPES_H */ diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h new file mode 100644 index 00000000000..b895144d577 --- /dev/null +++ b/arch/mips/include/asm/uaccess.h @@ -0,0 +1,852 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2007 Maciej W. Rozycki + */ +#ifndef _ASM_UACCESS_H +#define _ASM_UACCESS_H + +#include +#include +#include +#include + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons, these macros are grossly misnamed. + */ +#ifdef CONFIG_32BIT + +#define __UA_LIMIT 0x80000000UL + +#define __UA_ADDR ".word" +#define __UA_LA "la" +#define __UA_ADDU "addu" +#define __UA_t0 "$8" +#define __UA_t1 "$9" + +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT + +#define __UA_LIMIT (- TASK_SIZE) + +#define __UA_ADDR ".dword" +#define __UA_LA "dla" +#define __UA_ADDU "daddu" +#define __UA_t0 "$12" +#define __UA_t1 "$13" + +#endif /* CONFIG_64BIT */ + +/* + * USER_DS is a bitmask that has the bits set that may not be set in a valid + * userspace address. Note that we limit 32-bit userspace to 0x7fff8000 but + * the arithmetic we're doing only works if the limit is a power of two, so + * we use 0x80000000 here on 32-bit kernels. If a process passes an invalid + * address in this range it's the process's problem, not ours :-) + */ + +#define KERNEL_DS ((mm_segment_t) { 0UL }) +#define USER_DS ((mm_segment_t) { __UA_LIMIT }) + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +#define get_ds() (KERNEL_DS) +#define get_fs() (current_thread_info()->addr_limit) +#define set_fs(x) (current_thread_info()->addr_limit = (x)) + +#define segment_eq(a, b) ((a).seg == (b).seg) + + +/* + * Is a address valid? This does a straighforward calculation rather + * than tests. + * + * Address valid if: + * - "addr" doesn't have any high-bits set + * - AND "size" doesn't have any high-bits set + * - AND "addr+size" doesn't have any high-bits set + * - OR we are in kernel mode. + * + * __ua_size() is a trick to avoid runtime checking of positive constant + * sizes; for those we already know at compile time that the size is ok. + */ +#define __ua_size(size) \ + ((__builtin_constant_p(size) && (signed long) (size) > 0) ? 0 : (size)) + +/* + * access_ok: - Checks if a user space pointer is valid + * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that + * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe + * to write to a block, it is always safe to read from it. + * @addr: User space pointer to start of block to check + * @size: Size of block to check + * + * Context: User context only. This function may sleep. + * + * Checks if a pointer to a block of memory in user space is valid. + * + * Returns true (nonzero) if the memory block may be valid, false (zero) + * if it is definitely invalid. + * + * Note that, depending on architecture, this function probably just + * checks that the pointer is in the user space range - after calling + * this function, memory access functions may still return -EFAULT. + */ + +#define __access_mask get_fs().seg + +#define __access_ok(addr, size, mask) \ + (((signed long)((mask) & ((addr) | ((addr) + (size)) | __ua_size(size)))) == 0) + +#define access_ok(type, addr, size) \ + likely(__access_ok((unsigned long)(addr), (size), __access_mask)) + +/* + * put_user: - Write a simple value into user space. + * @x: Value to copy to user space. + * @ptr: Destination address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple value from kernel space to user + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and @x must be assignable + * to the result of dereferencing @ptr. + * + * Returns zero on success, or -EFAULT on error. + */ +#define put_user(x,ptr) \ + __put_user_check((x), (ptr), sizeof(*(ptr))) + +/* + * get_user: - Get a simple variable from user space. + * @x: Variable to store result. + * @ptr: Source address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple variable from user space to kernel + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and the result of + * dereferencing @ptr must be assignable to @x without a cast. + * + * Returns zero on success, or -EFAULT on error. + * On error, the variable @x is set to zero. + */ +#define get_user(x,ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr))) + +/* + * __put_user: - Write a simple value into user space, with less checking. + * @x: Value to copy to user space. + * @ptr: Destination address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple value from kernel space to user + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and @x must be assignable + * to the result of dereferencing @ptr. + * + * Caller must check the pointer with access_ok() before calling this + * function. + * + * Returns zero on success, or -EFAULT on error. + */ +#define __put_user(x,ptr) \ + __put_user_nocheck((x), (ptr), sizeof(*(ptr))) + +/* + * __get_user: - Get a simple variable from user space, with less checking. + * @x: Variable to store result. + * @ptr: Source address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple variable from user space to kernel + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and the result of + * dereferencing @ptr must be assignable to @x without a cast. + * + * Caller must check the pointer with access_ok() before calling this + * function. + * + * Returns zero on success, or -EFAULT on error. + * On error, the variable @x is set to zero. + */ +#define __get_user(x,ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) + +struct __large_struct { unsigned long buf[100]; }; +#define __m(x) (*(struct __large_struct __user *)(x)) + +/* + * Yuck. We need two variants, one for 64bit operation and one + * for 32 bit mode and old iron. + */ +#ifdef CONFIG_32BIT +#define __GET_USER_DW(val, ptr) __get_user_asm_ll32(val, ptr) +#endif +#ifdef CONFIG_64BIT +#define __GET_USER_DW(val, ptr) __get_user_asm(val, "ld", ptr) +#endif + +extern void __get_user_unknown(void); + +#define __get_user_common(val, size, ptr) \ +do { \ + switch (size) { \ + case 1: __get_user_asm(val, "lb", ptr); break; \ + case 2: __get_user_asm(val, "lh", ptr); break; \ + case 4: __get_user_asm(val, "lw", ptr); break; \ + case 8: __GET_USER_DW(val, ptr); break; \ + default: __get_user_unknown(); break; \ + } \ +} while (0) + +#define __get_user_nocheck(x, ptr, size) \ +({ \ + int __gu_err; \ + \ + __get_user_common((x), size, ptr); \ + __gu_err; \ +}) + +#define __get_user_check(x, ptr, size) \ +({ \ + int __gu_err = -EFAULT; \ + const __typeof__(*(ptr)) __user * __gu_ptr = (ptr); \ + \ + if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \ + __get_user_common((x), size, __gu_ptr); \ + \ + __gu_err; \ +}) + +#define __get_user_asm(val, insn, addr) \ +{ \ + long __gu_tmp; \ + \ + __asm__ __volatile__( \ + "1: " insn " %1, %3 \n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + "3: li %0, %4 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " "__UA_ADDR "\t1b, 3b \n" \ + " .previous \n" \ + : "=r" (__gu_err), "=r" (__gu_tmp) \ + : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \ + \ + (val) = (__typeof__(*(addr))) __gu_tmp; \ +} + +/* + * Get a long long 64 using 32 bit registers. + */ +#define __get_user_asm_ll32(val, addr) \ +{ \ + union { \ + unsigned long long l; \ + __typeof__(*(addr)) t; \ + } __gu_tmp; \ + \ + __asm__ __volatile__( \ + "1: lw %1, (%3) \n" \ + "2: lw %D1, 4(%3) \n" \ + "3: .section .fixup,\"ax\" \n" \ + "4: li %0, %4 \n" \ + " move %1, $0 \n" \ + " move %D1, $0 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 4b \n" \ + " " __UA_ADDR " 2b, 4b \n" \ + " .previous \n" \ + : "=r" (__gu_err), "=&r" (__gu_tmp.l) \ + : "0" (0), "r" (addr), "i" (-EFAULT)); \ + \ + (val) = __gu_tmp.t; \ +} + +/* + * Yuck. We need two variants, one for 64bit operation and one + * for 32 bit mode and old iron. + */ +#ifdef CONFIG_32BIT +#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr) +#endif +#ifdef CONFIG_64BIT +#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr) +#endif + +#define __put_user_nocheck(x, ptr, size) \ +({ \ + __typeof__(*(ptr)) __pu_val; \ + int __pu_err = 0; \ + \ + __pu_val = (x); \ + switch (size) { \ + case 1: __put_user_asm("sb", ptr); break; \ + case 2: __put_user_asm("sh", ptr); break; \ + case 4: __put_user_asm("sw", ptr); break; \ + case 8: __PUT_USER_DW(ptr); break; \ + default: __put_user_unknown(); break; \ + } \ + __pu_err; \ +}) + +#define __put_user_check(x, ptr, size) \ +({ \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + int __pu_err = -EFAULT; \ + \ + if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \ + switch (size) { \ + case 1: __put_user_asm("sb", __pu_addr); break; \ + case 2: __put_user_asm("sh", __pu_addr); break; \ + case 4: __put_user_asm("sw", __pu_addr); break; \ + case 8: __PUT_USER_DW(__pu_addr); break; \ + default: __put_user_unknown(); break; \ + } \ + } \ + __pu_err; \ +}) + +#define __put_user_asm(insn, ptr) \ +{ \ + __asm__ __volatile__( \ + "1: " insn " %z2, %3 # __put_user_asm\n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + "3: li %0, %4 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 3b \n" \ + " .previous \n" \ + : "=r" (__pu_err) \ + : "0" (0), "Jr" (__pu_val), "o" (__m(ptr)), \ + "i" (-EFAULT)); \ +} + +#define __put_user_asm_ll32(ptr) \ +{ \ + __asm__ __volatile__( \ + "1: sw %2, (%3) # __put_user_asm_ll32 \n" \ + "2: sw %D2, 4(%3) \n" \ + "3: \n" \ + " .section .fixup,\"ax\" \n" \ + "4: li %0, %4 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 4b \n" \ + " " __UA_ADDR " 2b, 4b \n" \ + " .previous" \ + : "=r" (__pu_err) \ + : "0" (0), "r" (__pu_val), "r" (ptr), \ + "i" (-EFAULT)); \ +} + +extern void __put_user_unknown(void); + +/* + * We're generating jump to subroutines which will be outside the range of + * jump instructions + */ +#ifdef MODULE +#define __MODULE_JAL(destination) \ + ".set\tnoat\n\t" \ + __UA_LA "\t$1, " #destination "\n\t" \ + "jalr\t$1\n\t" \ + ".set\tat\n\t" +#else +#define __MODULE_JAL(destination) \ + "jal\t" #destination "\n\t" +#endif + +#ifndef CONFIG_CPU_DADDI_WORKAROUNDS +#define DADDI_SCRATCH "$0" +#else +#define DADDI_SCRATCH "$3" +#endif + +extern size_t __copy_user(void *__to, const void *__from, size_t __n); + +#define __invoke_copy_to_user(to, from, n) \ +({ \ + register void __user *__cu_to_r __asm__("$4"); \ + register const void *__cu_from_r __asm__("$5"); \ + register long __cu_len_r __asm__("$6"); \ + \ + __cu_to_r = (to); \ + __cu_from_r = (from); \ + __cu_len_r = (n); \ + __asm__ __volatile__( \ + __MODULE_JAL(__copy_user) \ + : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ + : \ + : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ + DADDI_SCRATCH, "memory"); \ + __cu_len_r; \ +}) + +/* + * __copy_to_user: - Copy a block of data into user space, with less checking. + * @to: Destination address, in user space. + * @from: Source address, in kernel space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from kernel space to user space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +#define __copy_to_user(to, from, n) \ +({ \ + void __user *__cu_to; \ + const void *__cu_from; \ + long __cu_len; \ + \ + might_sleep(); \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len); \ + __cu_len; \ +}) + +extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); + +#define __copy_to_user_inatomic(to, from, n) \ +({ \ + void __user *__cu_to; \ + const void *__cu_from; \ + long __cu_len; \ + \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len); \ + __cu_len; \ +}) + +#define __copy_from_user_inatomic(to, from, n) \ +({ \ + void *__cu_to; \ + const void __user *__cu_from; \ + long __cu_len; \ + \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + __cu_len = __invoke_copy_from_user_inatomic(__cu_to, __cu_from, \ + __cu_len); \ + __cu_len; \ +}) + +/* + * copy_to_user: - Copy a block of data into user space. + * @to: Destination address, in user space. + * @from: Source address, in kernel space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from kernel space to user space. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +#define copy_to_user(to, from, n) \ +({ \ + void __user *__cu_to; \ + const void *__cu_from; \ + long __cu_len; \ + \ + might_sleep(); \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) \ + __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, \ + __cu_len); \ + __cu_len; \ +}) + +#define __invoke_copy_from_user(to, from, n) \ +({ \ + register void *__cu_to_r __asm__("$4"); \ + register const void __user *__cu_from_r __asm__("$5"); \ + register long __cu_len_r __asm__("$6"); \ + \ + __cu_to_r = (to); \ + __cu_from_r = (from); \ + __cu_len_r = (n); \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + __MODULE_JAL(__copy_user) \ + ".set\tnoat\n\t" \ + __UA_ADDU "\t$1, %1, %2\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ + : \ + : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ + DADDI_SCRATCH, "memory"); \ + __cu_len_r; \ +}) + +#define __invoke_copy_from_user_inatomic(to, from, n) \ +({ \ + register void *__cu_to_r __asm__("$4"); \ + register const void __user *__cu_from_r __asm__("$5"); \ + register long __cu_len_r __asm__("$6"); \ + \ + __cu_to_r = (to); \ + __cu_from_r = (from); \ + __cu_len_r = (n); \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + __MODULE_JAL(__copy_user_inatomic) \ + ".set\tnoat\n\t" \ + __UA_ADDU "\t$1, %1, %2\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ + : \ + : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ + DADDI_SCRATCH, "memory"); \ + __cu_len_r; \ +}) + +/* + * __copy_from_user: - Copy a block of data from user space, with less checking. + * @to: Destination address, in kernel space. + * @from: Source address, in user space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from user space to kernel space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + * + * If some data could not be copied, this function will pad the copied + * data to the requested size using zero bytes. + */ +#define __copy_from_user(to, from, n) \ +({ \ + void *__cu_to; \ + const void __user *__cu_from; \ + long __cu_len; \ + \ + might_sleep(); \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \ + __cu_len); \ + __cu_len; \ +}) + +/* + * copy_from_user: - Copy a block of data from user space. + * @to: Destination address, in kernel space. + * @from: Source address, in user space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from user space to kernel space. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + * + * If some data could not be copied, this function will pad the copied + * data to the requested size using zero bytes. + */ +#define copy_from_user(to, from, n) \ +({ \ + void *__cu_to; \ + const void __user *__cu_from; \ + long __cu_len; \ + \ + might_sleep(); \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + if (access_ok(VERIFY_READ, __cu_from, __cu_len)) \ + __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \ + __cu_len); \ + __cu_len; \ +}) + +#define __copy_in_user(to, from, n) __copy_from_user(to, from, n) + +#define copy_in_user(to, from, n) \ +({ \ + void __user *__cu_to; \ + const void __user *__cu_from; \ + long __cu_len; \ + \ + might_sleep(); \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + if (likely(access_ok(VERIFY_READ, __cu_from, __cu_len) && \ + access_ok(VERIFY_WRITE, __cu_to, __cu_len))) \ + __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \ + __cu_len); \ + __cu_len; \ +}) + +/* + * __clear_user: - Zero a block of memory in user space, with less checking. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ +static inline __kernel_size_t +__clear_user(void __user *addr, __kernel_size_t size) +{ + __kernel_size_t res; + + might_sleep(); + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, $0\n\t" + "move\t$6, %2\n\t" + __MODULE_JAL(__bzero) + "move\t%0, $6" + : "=r" (res) + : "r" (addr), "r" (size) + : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31"); + + return res; +} + +#define clear_user(addr,n) \ +({ \ + void __user * __cl_addr = (addr); \ + unsigned long __cl_size = (n); \ + if (__cl_size && access_ok(VERIFY_WRITE, \ + ((unsigned long)(__cl_addr)), __cl_size)) \ + __cl_size = __clear_user(__cl_addr, __cl_size); \ + __cl_size; \ +}) + +/* + * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * Caller must check the specified block with access_ok() before calling + * this function. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +static inline long +__strncpy_from_user(char *__to, const char __user *__from, long __len) +{ + long res; + + might_sleep(); + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, %2\n\t" + "move\t$6, %3\n\t" + __MODULE_JAL(__strncpy_from_user_nocheck_asm) + "move\t%0, $2" + : "=r" (res) + : "r" (__to), "r" (__from), "r" (__len) + : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory"); + + return res; +} + +/* + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +static inline long +strncpy_from_user(char *__to, const char __user *__from, long __len) +{ + long res; + + might_sleep(); + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, %2\n\t" + "move\t$6, %3\n\t" + __MODULE_JAL(__strncpy_from_user_asm) + "move\t%0, $2" + : "=r" (res) + : "r" (__to), "r" (__from), "r" (__len) + : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory"); + + return res; +} + +/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ +static inline long __strlen_user(const char __user *s) +{ + long res; + + might_sleep(); + __asm__ __volatile__( + "move\t$4, %1\n\t" + __MODULE_JAL(__strlen_user_nocheck_asm) + "move\t%0, $2" + : "=r" (res) + : "r" (s) + : "$2", "$4", __UA_t0, "$31"); + + return res; +} + +/* + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * + * If there is a limit on the length of a valid string, you may wish to + * consider using strnlen_user() instead. + */ +static inline long strlen_user(const char __user *s) +{ + long res; + + might_sleep(); + __asm__ __volatile__( + "move\t$4, %1\n\t" + __MODULE_JAL(__strlen_user_asm) + "move\t%0, $2" + : "=r" (res) + : "r" (s) + : "$2", "$4", __UA_t0, "$31"); + + return res; +} + +/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ +static inline long __strnlen_user(const char __user *s, long n) +{ + long res; + + might_sleep(); + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, %2\n\t" + __MODULE_JAL(__strnlen_user_nocheck_asm) + "move\t%0, $2" + : "=r" (res) + : "r" (s), "r" (n) + : "$2", "$4", "$5", __UA_t0, "$31"); + + return res; +} + +/* + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * + * If there is a limit on the length of a valid string, you may wish to + * consider using strnlen_user() instead. + */ +static inline long strnlen_user(const char __user *s, long n) +{ + long res; + + might_sleep(); + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, %2\n\t" + __MODULE_JAL(__strnlen_user_asm) + "move\t%0, $2" + : "=r" (res) + : "r" (s), "r" (n) + : "$2", "$4", "$5", __UA_t0, "$31"); + + return res; +} + +struct exception_table_entry +{ + unsigned long insn; + unsigned long nextinsn; +}; + +extern int fixup_exception(struct pt_regs *regs); + +#endif /* _ASM_UACCESS_H */ diff --git a/arch/mips/include/asm/ucontext.h b/arch/mips/include/asm/ucontext.h new file mode 100644 index 00000000000..8a4b20e88b8 --- /dev/null +++ b/arch/mips/include/asm/ucontext.h @@ -0,0 +1,21 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Low level exception handling + * + * Copyright (C) 1998, 1999 by Ralf Baechle + */ +#ifndef _ASM_UCONTEXT_H +#define _ASM_UCONTEXT_H + +struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +#endif /* _ASM_UCONTEXT_H */ diff --git a/arch/mips/include/asm/unaligned.h b/arch/mips/include/asm/unaligned.h new file mode 100644 index 00000000000..79240494857 --- /dev/null +++ b/arch/mips/include/asm/unaligned.h @@ -0,0 +1,28 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef _ASM_MIPS_UNALIGNED_H +#define _ASM_MIPS_UNALIGNED_H + +#include +#if defined(__MIPSEB__) +# include +# include +# include +# define get_unaligned __get_unaligned_be +# define put_unaligned __put_unaligned_be +#elif defined(__MIPSEL__) +# include +# include +# include +# define get_unaligned __get_unaligned_le +# define put_unaligned __put_unaligned_le +#else +# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" +#endif + +#endif /* _ASM_MIPS_UNALIGNED_H */ diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h new file mode 100644 index 00000000000..a73e1531e15 --- /dev/null +++ b/arch/mips/include/asm/unistd.h @@ -0,0 +1,1037 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * + * Changed system calls macros _syscall5 - _syscall7 to push args 5 to 7 onto + * the stack. Robin Farine for ACN S.A, Copyright (C) 1996 by ACN S.A + */ +#ifndef _ASM_UNISTD_H +#define _ASM_UNISTD_H + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + +/* + * Linux o32 style syscalls are in the range from 4000 to 4999. + */ +#define __NR_Linux 4000 +#define __NR_syscall (__NR_Linux + 0) +#define __NR_exit (__NR_Linux + 1) +#define __NR_fork (__NR_Linux + 2) +#define __NR_read (__NR_Linux + 3) +#define __NR_write (__NR_Linux + 4) +#define __NR_open (__NR_Linux + 5) +#define __NR_close (__NR_Linux + 6) +#define __NR_waitpid (__NR_Linux + 7) +#define __NR_creat (__NR_Linux + 8) +#define __NR_link (__NR_Linux + 9) +#define __NR_unlink (__NR_Linux + 10) +#define __NR_execve (__NR_Linux + 11) +#define __NR_chdir (__NR_Linux + 12) +#define __NR_time (__NR_Linux + 13) +#define __NR_mknod (__NR_Linux + 14) +#define __NR_chmod (__NR_Linux + 15) +#define __NR_lchown (__NR_Linux + 16) +#define __NR_break (__NR_Linux + 17) +#define __NR_unused18 (__NR_Linux + 18) +#define __NR_lseek (__NR_Linux + 19) +#define __NR_getpid (__NR_Linux + 20) +#define __NR_mount (__NR_Linux + 21) +#define __NR_umount (__NR_Linux + 22) +#define __NR_setuid (__NR_Linux + 23) +#define __NR_getuid (__NR_Linux + 24) +#define __NR_stime (__NR_Linux + 25) +#define __NR_ptrace (__NR_Linux + 26) +#define __NR_alarm (__NR_Linux + 27) +#define __NR_unused28 (__NR_Linux + 28) +#define __NR_pause (__NR_Linux + 29) +#define __NR_utime (__NR_Linux + 30) +#define __NR_stty (__NR_Linux + 31) +#define __NR_gtty (__NR_Linux + 32) +#define __NR_access (__NR_Linux + 33) +#define __NR_nice (__NR_Linux + 34) +#define __NR_ftime (__NR_Linux + 35) +#define __NR_sync (__NR_Linux + 36) +#define __NR_kill (__NR_Linux + 37) +#define __NR_rename (__NR_Linux + 38) +#define __NR_mkdir (__NR_Linux + 39) +#define __NR_rmdir (__NR_Linux + 40) +#define __NR_dup (__NR_Linux + 41) +#define __NR_pipe (__NR_Linux + 42) +#define __NR_times (__NR_Linux + 43) +#define __NR_prof (__NR_Linux + 44) +#define __NR_brk (__NR_Linux + 45) +#define __NR_setgid (__NR_Linux + 46) +#define __NR_getgid (__NR_Linux + 47) +#define __NR_signal (__NR_Linux + 48) +#define __NR_geteuid (__NR_Linux + 49) +#define __NR_getegid (__NR_Linux + 50) +#define __NR_acct (__NR_Linux + 51) +#define __NR_umount2 (__NR_Linux + 52) +#define __NR_lock (__NR_Linux + 53) +#define __NR_ioctl (__NR_Linux + 54) +#define __NR_fcntl (__NR_Linux + 55) +#define __NR_mpx (__NR_Linux + 56) +#define __NR_setpgid (__NR_Linux + 57) +#define __NR_ulimit (__NR_Linux + 58) +#define __NR_unused59 (__NR_Linux + 59) +#define __NR_umask (__NR_Linux + 60) +#define __NR_chroot (__NR_Linux + 61) +#define __NR_ustat (__NR_Linux + 62) +#define __NR_dup2 (__NR_Linux + 63) +#define __NR_getppid (__NR_Linux + 64) +#define __NR_getpgrp (__NR_Linux + 65) +#define __NR_setsid (__NR_Linux + 66) +#define __NR_sigaction (__NR_Linux + 67) +#define __NR_sgetmask (__NR_Linux + 68) +#define __NR_ssetmask (__NR_Linux + 69) +#define __NR_setreuid (__NR_Linux + 70) +#define __NR_setregid (__NR_Linux + 71) +#define __NR_sigsuspend (__NR_Linux + 72) +#define __NR_sigpending (__NR_Linux + 73) +#define __NR_sethostname (__NR_Linux + 74) +#define __NR_setrlimit (__NR_Linux + 75) +#define __NR_getrlimit (__NR_Linux + 76) +#define __NR_getrusage (__NR_Linux + 77) +#define __NR_gettimeofday (__NR_Linux + 78) +#define __NR_settimeofday (__NR_Linux + 79) +#define __NR_getgroups (__NR_Linux + 80) +#define __NR_setgroups (__NR_Linux + 81) +#define __NR_reserved82 (__NR_Linux + 82) +#define __NR_symlink (__NR_Linux + 83) +#define __NR_unused84 (__NR_Linux + 84) +#define __NR_readlink (__NR_Linux + 85) +#define __NR_uselib (__NR_Linux + 86) +#define __NR_swapon (__NR_Linux + 87) +#define __NR_reboot (__NR_Linux + 88) +#define __NR_readdir (__NR_Linux + 89) +#define __NR_mmap (__NR_Linux + 90) +#define __NR_munmap (__NR_Linux + 91) +#define __NR_truncate (__NR_Linux + 92) +#define __NR_ftruncate (__NR_Linux + 93) +#define __NR_fchmod (__NR_Linux + 94) +#define __NR_fchown (__NR_Linux + 95) +#define __NR_getpriority (__NR_Linux + 96) +#define __NR_setpriority (__NR_Linux + 97) +#define __NR_profil (__NR_Linux + 98) +#define __NR_statfs (__NR_Linux + 99) +#define __NR_fstatfs (__NR_Linux + 100) +#define __NR_ioperm (__NR_Linux + 101) +#define __NR_socketcall (__NR_Linux + 102) +#define __NR_syslog (__NR_Linux + 103) +#define __NR_setitimer (__NR_Linux + 104) +#define __NR_getitimer (__NR_Linux + 105) +#define __NR_stat (__NR_Linux + 106) +#define __NR_lstat (__NR_Linux + 107) +#define __NR_fstat (__NR_Linux + 108) +#define __NR_unused109 (__NR_Linux + 109) +#define __NR_iopl (__NR_Linux + 110) +#define __NR_vhangup (__NR_Linux + 111) +#define __NR_idle (__NR_Linux + 112) +#define __NR_vm86 (__NR_Linux + 113) +#define __NR_wait4 (__NR_Linux + 114) +#define __NR_swapoff (__NR_Linux + 115) +#define __NR_sysinfo (__NR_Linux + 116) +#define __NR_ipc (__NR_Linux + 117) +#define __NR_fsync (__NR_Linux + 118) +#define __NR_sigreturn (__NR_Linux + 119) +#define __NR_clone (__NR_Linux + 120) +#define __NR_setdomainname (__NR_Linux + 121) +#define __NR_uname (__NR_Linux + 122) +#define __NR_modify_ldt (__NR_Linux + 123) +#define __NR_adjtimex (__NR_Linux + 124) +#define __NR_mprotect (__NR_Linux + 125) +#define __NR_sigprocmask (__NR_Linux + 126) +#define __NR_create_module (__NR_Linux + 127) +#define __NR_init_module (__NR_Linux + 128) +#define __NR_delete_module (__NR_Linux + 129) +#define __NR_get_kernel_syms (__NR_Linux + 130) +#define __NR_quotactl (__NR_Linux + 131) +#define __NR_getpgid (__NR_Linux + 132) +#define __NR_fchdir (__NR_Linux + 133) +#define __NR_bdflush (__NR_Linux + 134) +#define __NR_sysfs (__NR_Linux + 135) +#define __NR_personality (__NR_Linux + 136) +#define __NR_afs_syscall (__NR_Linux + 137) /* Syscall for Andrew File System */ +#define __NR_setfsuid (__NR_Linux + 138) +#define __NR_setfsgid (__NR_Linux + 139) +#define __NR__llseek (__NR_Linux + 140) +#define __NR_getdents (__NR_Linux + 141) +#define __NR__newselect (__NR_Linux + 142) +#define __NR_flock (__NR_Linux + 143) +#define __NR_msync (__NR_Linux + 144) +#define __NR_readv (__NR_Linux + 145) +#define __NR_writev (__NR_Linux + 146) +#define __NR_cacheflush (__NR_Linux + 147) +#define __NR_cachectl (__NR_Linux + 148) +#define __NR_sysmips (__NR_Linux + 149) +#define __NR_unused150 (__NR_Linux + 150) +#define __NR_getsid (__NR_Linux + 151) +#define __NR_fdatasync (__NR_Linux + 152) +#define __NR__sysctl (__NR_Linux + 153) +#define __NR_mlock (__NR_Linux + 154) +#define __NR_munlock (__NR_Linux + 155) +#define __NR_mlockall (__NR_Linux + 156) +#define __NR_munlockall (__NR_Linux + 157) +#define __NR_sched_setparam (__NR_Linux + 158) +#define __NR_sched_getparam (__NR_Linux + 159) +#define __NR_sched_setscheduler (__NR_Linux + 160) +#define __NR_sched_getscheduler (__NR_Linux + 161) +#define __NR_sched_yield (__NR_Linux + 162) +#define __NR_sched_get_priority_max (__NR_Linux + 163) +#define __NR_sched_get_priority_min (__NR_Linux + 164) +#define __NR_sched_rr_get_interval (__NR_Linux + 165) +#define __NR_nanosleep (__NR_Linux + 166) +#define __NR_mremap (__NR_Linux + 167) +#define __NR_accept (__NR_Linux + 168) +#define __NR_bind (__NR_Linux + 169) +#define __NR_connect (__NR_Linux + 170) +#define __NR_getpeername (__NR_Linux + 171) +#define __NR_getsockname (__NR_Linux + 172) +#define __NR_getsockopt (__NR_Linux + 173) +#define __NR_listen (__NR_Linux + 174) +#define __NR_recv (__NR_Linux + 175) +#define __NR_recvfrom (__NR_Linux + 176) +#define __NR_recvmsg (__NR_Linux + 177) +#define __NR_send (__NR_Linux + 178) +#define __NR_sendmsg (__NR_Linux + 179) +#define __NR_sendto (__NR_Linux + 180) +#define __NR_setsockopt (__NR_Linux + 181) +#define __NR_shutdown (__NR_Linux + 182) +#define __NR_socket (__NR_Linux + 183) +#define __NR_socketpair (__NR_Linux + 184) +#define __NR_setresuid (__NR_Linux + 185) +#define __NR_getresuid (__NR_Linux + 186) +#define __NR_query_module (__NR_Linux + 187) +#define __NR_poll (__NR_Linux + 188) +#define __NR_nfsservctl (__NR_Linux + 189) +#define __NR_setresgid (__NR_Linux + 190) +#define __NR_getresgid (__NR_Linux + 191) +#define __NR_prctl (__NR_Linux + 192) +#define __NR_rt_sigreturn (__NR_Linux + 193) +#define __NR_rt_sigaction (__NR_Linux + 194) +#define __NR_rt_sigprocmask (__NR_Linux + 195) +#define __NR_rt_sigpending (__NR_Linux + 196) +#define __NR_rt_sigtimedwait (__NR_Linux + 197) +#define __NR_rt_sigqueueinfo (__NR_Linux + 198) +#define __NR_rt_sigsuspend (__NR_Linux + 199) +#define __NR_pread64 (__NR_Linux + 200) +#define __NR_pwrite64 (__NR_Linux + 201) +#define __NR_chown (__NR_Linux + 202) +#define __NR_getcwd (__NR_Linux + 203) +#define __NR_capget (__NR_Linux + 204) +#define __NR_capset (__NR_Linux + 205) +#define __NR_sigaltstack (__NR_Linux + 206) +#define __NR_sendfile (__NR_Linux + 207) +#define __NR_getpmsg (__NR_Linux + 208) +#define __NR_putpmsg (__NR_Linux + 209) +#define __NR_mmap2 (__NR_Linux + 210) +#define __NR_truncate64 (__NR_Linux + 211) +#define __NR_ftruncate64 (__NR_Linux + 212) +#define __NR_stat64 (__NR_Linux + 213) +#define __NR_lstat64 (__NR_Linux + 214) +#define __NR_fstat64 (__NR_Linux + 215) +#define __NR_pivot_root (__NR_Linux + 216) +#define __NR_mincore (__NR_Linux + 217) +#define __NR_madvise (__NR_Linux + 218) +#define __NR_getdents64 (__NR_Linux + 219) +#define __NR_fcntl64 (__NR_Linux + 220) +#define __NR_reserved221 (__NR_Linux + 221) +#define __NR_gettid (__NR_Linux + 222) +#define __NR_readahead (__NR_Linux + 223) +#define __NR_setxattr (__NR_Linux + 224) +#define __NR_lsetxattr (__NR_Linux + 225) +#define __NR_fsetxattr (__NR_Linux + 226) +#define __NR_getxattr (__NR_Linux + 227) +#define __NR_lgetxattr (__NR_Linux + 228) +#define __NR_fgetxattr (__NR_Linux + 229) +#define __NR_listxattr (__NR_Linux + 230) +#define __NR_llistxattr (__NR_Linux + 231) +#define __NR_flistxattr (__NR_Linux + 232) +#define __NR_removexattr (__NR_Linux + 233) +#define __NR_lremovexattr (__NR_Linux + 234) +#define __NR_fremovexattr (__NR_Linux + 235) +#define __NR_tkill (__NR_Linux + 236) +#define __NR_sendfile64 (__NR_Linux + 237) +#define __NR_futex (__NR_Linux + 238) +#define __NR_sched_setaffinity (__NR_Linux + 239) +#define __NR_sched_getaffinity (__NR_Linux + 240) +#define __NR_io_setup (__NR_Linux + 241) +#define __NR_io_destroy (__NR_Linux + 242) +#define __NR_io_getevents (__NR_Linux + 243) +#define __NR_io_submit (__NR_Linux + 244) +#define __NR_io_cancel (__NR_Linux + 245) +#define __NR_exit_group (__NR_Linux + 246) +#define __NR_lookup_dcookie (__NR_Linux + 247) +#define __NR_epoll_create (__NR_Linux + 248) +#define __NR_epoll_ctl (__NR_Linux + 249) +#define __NR_epoll_wait (__NR_Linux + 250) +#define __NR_remap_file_pages (__NR_Linux + 251) +#define __NR_set_tid_address (__NR_Linux + 252) +#define __NR_restart_syscall (__NR_Linux + 253) +#define __NR_fadvise64 (__NR_Linux + 254) +#define __NR_statfs64 (__NR_Linux + 255) +#define __NR_fstatfs64 (__NR_Linux + 256) +#define __NR_timer_create (__NR_Linux + 257) +#define __NR_timer_settime (__NR_Linux + 258) +#define __NR_timer_gettime (__NR_Linux + 259) +#define __NR_timer_getoverrun (__NR_Linux + 260) +#define __NR_timer_delete (__NR_Linux + 261) +#define __NR_clock_settime (__NR_Linux + 262) +#define __NR_clock_gettime (__NR_Linux + 263) +#define __NR_clock_getres (__NR_Linux + 264) +#define __NR_clock_nanosleep (__NR_Linux + 265) +#define __NR_tgkill (__NR_Linux + 266) +#define __NR_utimes (__NR_Linux + 267) +#define __NR_mbind (__NR_Linux + 268) +#define __NR_get_mempolicy (__NR_Linux + 269) +#define __NR_set_mempolicy (__NR_Linux + 270) +#define __NR_mq_open (__NR_Linux + 271) +#define __NR_mq_unlink (__NR_Linux + 272) +#define __NR_mq_timedsend (__NR_Linux + 273) +#define __NR_mq_timedreceive (__NR_Linux + 274) +#define __NR_mq_notify (__NR_Linux + 275) +#define __NR_mq_getsetattr (__NR_Linux + 276) +#define __NR_vserver (__NR_Linux + 277) +#define __NR_waitid (__NR_Linux + 278) +/* #define __NR_sys_setaltroot (__NR_Linux + 279) */ +#define __NR_add_key (__NR_Linux + 280) +#define __NR_request_key (__NR_Linux + 281) +#define __NR_keyctl (__NR_Linux + 282) +#define __NR_set_thread_area (__NR_Linux + 283) +#define __NR_inotify_init (__NR_Linux + 284) +#define __NR_inotify_add_watch (__NR_Linux + 285) +#define __NR_inotify_rm_watch (__NR_Linux + 286) +#define __NR_migrate_pages (__NR_Linux + 287) +#define __NR_openat (__NR_Linux + 288) +#define __NR_mkdirat (__NR_Linux + 289) +#define __NR_mknodat (__NR_Linux + 290) +#define __NR_fchownat (__NR_Linux + 291) +#define __NR_futimesat (__NR_Linux + 292) +#define __NR_fstatat64 (__NR_Linux + 293) +#define __NR_unlinkat (__NR_Linux + 294) +#define __NR_renameat (__NR_Linux + 295) +#define __NR_linkat (__NR_Linux + 296) +#define __NR_symlinkat (__NR_Linux + 297) +#define __NR_readlinkat (__NR_Linux + 298) +#define __NR_fchmodat (__NR_Linux + 299) +#define __NR_faccessat (__NR_Linux + 300) +#define __NR_pselect6 (__NR_Linux + 301) +#define __NR_ppoll (__NR_Linux + 302) +#define __NR_unshare (__NR_Linux + 303) +#define __NR_splice (__NR_Linux + 304) +#define __NR_sync_file_range (__NR_Linux + 305) +#define __NR_tee (__NR_Linux + 306) +#define __NR_vmsplice (__NR_Linux + 307) +#define __NR_move_pages (__NR_Linux + 308) +#define __NR_set_robust_list (__NR_Linux + 309) +#define __NR_get_robust_list (__NR_Linux + 310) +#define __NR_kexec_load (__NR_Linux + 311) +#define __NR_getcpu (__NR_Linux + 312) +#define __NR_epoll_pwait (__NR_Linux + 313) +#define __NR_ioprio_set (__NR_Linux + 314) +#define __NR_ioprio_get (__NR_Linux + 315) +#define __NR_utimensat (__NR_Linux + 316) +#define __NR_signalfd (__NR_Linux + 317) +#define __NR_timerfd (__NR_Linux + 318) +#define __NR_eventfd (__NR_Linux + 319) +#define __NR_fallocate (__NR_Linux + 320) +#define __NR_timerfd_create (__NR_Linux + 321) +#define __NR_timerfd_gettime (__NR_Linux + 322) +#define __NR_timerfd_settime (__NR_Linux + 323) +#define __NR_signalfd4 (__NR_Linux + 324) +#define __NR_eventfd2 (__NR_Linux + 325) +#define __NR_epoll_create1 (__NR_Linux + 326) +#define __NR_dup3 (__NR_Linux + 327) +#define __NR_pipe2 (__NR_Linux + 328) +#define __NR_inotify_init1 (__NR_Linux + 329) + +/* + * Offset of the last Linux o32 flavoured syscall + */ +#define __NR_Linux_syscalls 329 + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ + +#define __NR_O32_Linux 4000 +#define __NR_O32_Linux_syscalls 329 + +#if _MIPS_SIM == _MIPS_SIM_ABI64 + +/* + * Linux 64-bit syscalls are in the range from 5000 to 5999. + */ +#define __NR_Linux 5000 +#define __NR_read (__NR_Linux + 0) +#define __NR_write (__NR_Linux + 1) +#define __NR_open (__NR_Linux + 2) +#define __NR_close (__NR_Linux + 3) +#define __NR_stat (__NR_Linux + 4) +#define __NR_fstat (__NR_Linux + 5) +#define __NR_lstat (__NR_Linux + 6) +#define __NR_poll (__NR_Linux + 7) +#define __NR_lseek (__NR_Linux + 8) +#define __NR_mmap (__NR_Linux + 9) +#define __NR_mprotect (__NR_Linux + 10) +#define __NR_munmap (__NR_Linux + 11) +#define __NR_brk (__NR_Linux + 12) +#define __NR_rt_sigaction (__NR_Linux + 13) +#define __NR_rt_sigprocmask (__NR_Linux + 14) +#define __NR_ioctl (__NR_Linux + 15) +#define __NR_pread64 (__NR_Linux + 16) +#define __NR_pwrite64 (__NR_Linux + 17) +#define __NR_readv (__NR_Linux + 18) +#define __NR_writev (__NR_Linux + 19) +#define __NR_access (__NR_Linux + 20) +#define __NR_pipe (__NR_Linux + 21) +#define __NR__newselect (__NR_Linux + 22) +#define __NR_sched_yield (__NR_Linux + 23) +#define __NR_mremap (__NR_Linux + 24) +#define __NR_msync (__NR_Linux + 25) +#define __NR_mincore (__NR_Linux + 26) +#define __NR_madvise (__NR_Linux + 27) +#define __NR_shmget (__NR_Linux + 28) +#define __NR_shmat (__NR_Linux + 29) +#define __NR_shmctl (__NR_Linux + 30) +#define __NR_dup (__NR_Linux + 31) +#define __NR_dup2 (__NR_Linux + 32) +#define __NR_pause (__NR_Linux + 33) +#define __NR_nanosleep (__NR_Linux + 34) +#define __NR_getitimer (__NR_Linux + 35) +#define __NR_setitimer (__NR_Linux + 36) +#define __NR_alarm (__NR_Linux + 37) +#define __NR_getpid (__NR_Linux + 38) +#define __NR_sendfile (__NR_Linux + 39) +#define __NR_socket (__NR_Linux + 40) +#define __NR_connect (__NR_Linux + 41) +#define __NR_accept (__NR_Linux + 42) +#define __NR_sendto (__NR_Linux + 43) +#define __NR_recvfrom (__NR_Linux + 44) +#define __NR_sendmsg (__NR_Linux + 45) +#define __NR_recvmsg (__NR_Linux + 46) +#define __NR_shutdown (__NR_Linux + 47) +#define __NR_bind (__NR_Linux + 48) +#define __NR_listen (__NR_Linux + 49) +#define __NR_getsockname (__NR_Linux + 50) +#define __NR_getpeername (__NR_Linux + 51) +#define __NR_socketpair (__NR_Linux + 52) +#define __NR_setsockopt (__NR_Linux + 53) +#define __NR_getsockopt (__NR_Linux + 54) +#define __NR_clone (__NR_Linux + 55) +#define __NR_fork (__NR_Linux + 56) +#define __NR_execve (__NR_Linux + 57) +#define __NR_exit (__NR_Linux + 58) +#define __NR_wait4 (__NR_Linux + 59) +#define __NR_kill (__NR_Linux + 60) +#define __NR_uname (__NR_Linux + 61) +#define __NR_semget (__NR_Linux + 62) +#define __NR_semop (__NR_Linux + 63) +#define __NR_semctl (__NR_Linux + 64) +#define __NR_shmdt (__NR_Linux + 65) +#define __NR_msgget (__NR_Linux + 66) +#define __NR_msgsnd (__NR_Linux + 67) +#define __NR_msgrcv (__NR_Linux + 68) +#define __NR_msgctl (__NR_Linux + 69) +#define __NR_fcntl (__NR_Linux + 70) +#define __NR_flock (__NR_Linux + 71) +#define __NR_fsync (__NR_Linux + 72) +#define __NR_fdatasync (__NR_Linux + 73) +#define __NR_truncate (__NR_Linux + 74) +#define __NR_ftruncate (__NR_Linux + 75) +#define __NR_getdents (__NR_Linux + 76) +#define __NR_getcwd (__NR_Linux + 77) +#define __NR_chdir (__NR_Linux + 78) +#define __NR_fchdir (__NR_Linux + 79) +#define __NR_rename (__NR_Linux + 80) +#define __NR_mkdir (__NR_Linux + 81) +#define __NR_rmdir (__NR_Linux + 82) +#define __NR_creat (__NR_Linux + 83) +#define __NR_link (__NR_Linux + 84) +#define __NR_unlink (__NR_Linux + 85) +#define __NR_symlink (__NR_Linux + 86) +#define __NR_readlink (__NR_Linux + 87) +#define __NR_chmod (__NR_Linux + 88) +#define __NR_fchmod (__NR_Linux + 89) +#define __NR_chown (__NR_Linux + 90) +#define __NR_fchown (__NR_Linux + 91) +#define __NR_lchown (__NR_Linux + 92) +#define __NR_umask (__NR_Linux + 93) +#define __NR_gettimeofday (__NR_Linux + 94) +#define __NR_getrlimit (__NR_Linux + 95) +#define __NR_getrusage (__NR_Linux + 96) +#define __NR_sysinfo (__NR_Linux + 97) +#define __NR_times (__NR_Linux + 98) +#define __NR_ptrace (__NR_Linux + 99) +#define __NR_getuid (__NR_Linux + 100) +#define __NR_syslog (__NR_Linux + 101) +#define __NR_getgid (__NR_Linux + 102) +#define __NR_setuid (__NR_Linux + 103) +#define __NR_setgid (__NR_Linux + 104) +#define __NR_geteuid (__NR_Linux + 105) +#define __NR_getegid (__NR_Linux + 106) +#define __NR_setpgid (__NR_Linux + 107) +#define __NR_getppid (__NR_Linux + 108) +#define __NR_getpgrp (__NR_Linux + 109) +#define __NR_setsid (__NR_Linux + 110) +#define __NR_setreuid (__NR_Linux + 111) +#define __NR_setregid (__NR_Linux + 112) +#define __NR_getgroups (__NR_Linux + 113) +#define __NR_setgroups (__NR_Linux + 114) +#define __NR_setresuid (__NR_Linux + 115) +#define __NR_getresuid (__NR_Linux + 116) +#define __NR_setresgid (__NR_Linux + 117) +#define __NR_getresgid (__NR_Linux + 118) +#define __NR_getpgid (__NR_Linux + 119) +#define __NR_setfsuid (__NR_Linux + 120) +#define __NR_setfsgid (__NR_Linux + 121) +#define __NR_getsid (__NR_Linux + 122) +#define __NR_capget (__NR_Linux + 123) +#define __NR_capset (__NR_Linux + 124) +#define __NR_rt_sigpending (__NR_Linux + 125) +#define __NR_rt_sigtimedwait (__NR_Linux + 126) +#define __NR_rt_sigqueueinfo (__NR_Linux + 127) +#define __NR_rt_sigsuspend (__NR_Linux + 128) +#define __NR_sigaltstack (__NR_Linux + 129) +#define __NR_utime (__NR_Linux + 130) +#define __NR_mknod (__NR_Linux + 131) +#define __NR_personality (__NR_Linux + 132) +#define __NR_ustat (__NR_Linux + 133) +#define __NR_statfs (__NR_Linux + 134) +#define __NR_fstatfs (__NR_Linux + 135) +#define __NR_sysfs (__NR_Linux + 136) +#define __NR_getpriority (__NR_Linux + 137) +#define __NR_setpriority (__NR_Linux + 138) +#define __NR_sched_setparam (__NR_Linux + 139) +#define __NR_sched_getparam (__NR_Linux + 140) +#define __NR_sched_setscheduler (__NR_Linux + 141) +#define __NR_sched_getscheduler (__NR_Linux + 142) +#define __NR_sched_get_priority_max (__NR_Linux + 143) +#define __NR_sched_get_priority_min (__NR_Linux + 144) +#define __NR_sched_rr_get_interval (__NR_Linux + 145) +#define __NR_mlock (__NR_Linux + 146) +#define __NR_munlock (__NR_Linux + 147) +#define __NR_mlockall (__NR_Linux + 148) +#define __NR_munlockall (__NR_Linux + 149) +#define __NR_vhangup (__NR_Linux + 150) +#define __NR_pivot_root (__NR_Linux + 151) +#define __NR__sysctl (__NR_Linux + 152) +#define __NR_prctl (__NR_Linux + 153) +#define __NR_adjtimex (__NR_Linux + 154) +#define __NR_setrlimit (__NR_Linux + 155) +#define __NR_chroot (__NR_Linux + 156) +#define __NR_sync (__NR_Linux + 157) +#define __NR_acct (__NR_Linux + 158) +#define __NR_settimeofday (__NR_Linux + 159) +#define __NR_mount (__NR_Linux + 160) +#define __NR_umount2 (__NR_Linux + 161) +#define __NR_swapon (__NR_Linux + 162) +#define __NR_swapoff (__NR_Linux + 163) +#define __NR_reboot (__NR_Linux + 164) +#define __NR_sethostname (__NR_Linux + 165) +#define __NR_setdomainname (__NR_Linux + 166) +#define __NR_create_module (__NR_Linux + 167) +#define __NR_init_module (__NR_Linux + 168) +#define __NR_delete_module (__NR_Linux + 169) +#define __NR_get_kernel_syms (__NR_Linux + 170) +#define __NR_query_module (__NR_Linux + 171) +#define __NR_quotactl (__NR_Linux + 172) +#define __NR_nfsservctl (__NR_Linux + 173) +#define __NR_getpmsg (__NR_Linux + 174) +#define __NR_putpmsg (__NR_Linux + 175) +#define __NR_afs_syscall (__NR_Linux + 176) +#define __NR_reserved177 (__NR_Linux + 177) +#define __NR_gettid (__NR_Linux + 178) +#define __NR_readahead (__NR_Linux + 179) +#define __NR_setxattr (__NR_Linux + 180) +#define __NR_lsetxattr (__NR_Linux + 181) +#define __NR_fsetxattr (__NR_Linux + 182) +#define __NR_getxattr (__NR_Linux + 183) +#define __NR_lgetxattr (__NR_Linux + 184) +#define __NR_fgetxattr (__NR_Linux + 185) +#define __NR_listxattr (__NR_Linux + 186) +#define __NR_llistxattr (__NR_Linux + 187) +#define __NR_flistxattr (__NR_Linux + 188) +#define __NR_removexattr (__NR_Linux + 189) +#define __NR_lremovexattr (__NR_Linux + 190) +#define __NR_fremovexattr (__NR_Linux + 191) +#define __NR_tkill (__NR_Linux + 192) +#define __NR_reserved193 (__NR_Linux + 193) +#define __NR_futex (__NR_Linux + 194) +#define __NR_sched_setaffinity (__NR_Linux + 195) +#define __NR_sched_getaffinity (__NR_Linux + 196) +#define __NR_cacheflush (__NR_Linux + 197) +#define __NR_cachectl (__NR_Linux + 198) +#define __NR_sysmips (__NR_Linux + 199) +#define __NR_io_setup (__NR_Linux + 200) +#define __NR_io_destroy (__NR_Linux + 201) +#define __NR_io_getevents (__NR_Linux + 202) +#define __NR_io_submit (__NR_Linux + 203) +#define __NR_io_cancel (__NR_Linux + 204) +#define __NR_exit_group (__NR_Linux + 205) +#define __NR_lookup_dcookie (__NR_Linux + 206) +#define __NR_epoll_create (__NR_Linux + 207) +#define __NR_epoll_ctl (__NR_Linux + 208) +#define __NR_epoll_wait (__NR_Linux + 209) +#define __NR_remap_file_pages (__NR_Linux + 210) +#define __NR_rt_sigreturn (__NR_Linux + 211) +#define __NR_set_tid_address (__NR_Linux + 212) +#define __NR_restart_syscall (__NR_Linux + 213) +#define __NR_semtimedop (__NR_Linux + 214) +#define __NR_fadvise64 (__NR_Linux + 215) +#define __NR_timer_create (__NR_Linux + 216) +#define __NR_timer_settime (__NR_Linux + 217) +#define __NR_timer_gettime (__NR_Linux + 218) +#define __NR_timer_getoverrun (__NR_Linux + 219) +#define __NR_timer_delete (__NR_Linux + 220) +#define __NR_clock_settime (__NR_Linux + 221) +#define __NR_clock_gettime (__NR_Linux + 222) +#define __NR_clock_getres (__NR_Linux + 223) +#define __NR_clock_nanosleep (__NR_Linux + 224) +#define __NR_tgkill (__NR_Linux + 225) +#define __NR_utimes (__NR_Linux + 226) +#define __NR_mbind (__NR_Linux + 227) +#define __NR_get_mempolicy (__NR_Linux + 228) +#define __NR_set_mempolicy (__NR_Linux + 229) +#define __NR_mq_open (__NR_Linux + 230) +#define __NR_mq_unlink (__NR_Linux + 231) +#define __NR_mq_timedsend (__NR_Linux + 232) +#define __NR_mq_timedreceive (__NR_Linux + 233) +#define __NR_mq_notify (__NR_Linux + 234) +#define __NR_mq_getsetattr (__NR_Linux + 235) +#define __NR_vserver (__NR_Linux + 236) +#define __NR_waitid (__NR_Linux + 237) +/* #define __NR_sys_setaltroot (__NR_Linux + 238) */ +#define __NR_add_key (__NR_Linux + 239) +#define __NR_request_key (__NR_Linux + 240) +#define __NR_keyctl (__NR_Linux + 241) +#define __NR_set_thread_area (__NR_Linux + 242) +#define __NR_inotify_init (__NR_Linux + 243) +#define __NR_inotify_add_watch (__NR_Linux + 244) +#define __NR_inotify_rm_watch (__NR_Linux + 245) +#define __NR_migrate_pages (__NR_Linux + 246) +#define __NR_openat (__NR_Linux + 247) +#define __NR_mkdirat (__NR_Linux + 248) +#define __NR_mknodat (__NR_Linux + 249) +#define __NR_fchownat (__NR_Linux + 250) +#define __NR_futimesat (__NR_Linux + 251) +#define __NR_newfstatat (__NR_Linux + 252) +#define __NR_unlinkat (__NR_Linux + 253) +#define __NR_renameat (__NR_Linux + 254) +#define __NR_linkat (__NR_Linux + 255) +#define __NR_symlinkat (__NR_Linux + 256) +#define __NR_readlinkat (__NR_Linux + 257) +#define __NR_fchmodat (__NR_Linux + 258) +#define __NR_faccessat (__NR_Linux + 259) +#define __NR_pselect6 (__NR_Linux + 260) +#define __NR_ppoll (__NR_Linux + 261) +#define __NR_unshare (__NR_Linux + 262) +#define __NR_splice (__NR_Linux + 263) +#define __NR_sync_file_range (__NR_Linux + 264) +#define __NR_tee (__NR_Linux + 265) +#define __NR_vmsplice (__NR_Linux + 266) +#define __NR_move_pages (__NR_Linux + 267) +#define __NR_set_robust_list (__NR_Linux + 268) +#define __NR_get_robust_list (__NR_Linux + 269) +#define __NR_kexec_load (__NR_Linux + 270) +#define __NR_getcpu (__NR_Linux + 271) +#define __NR_epoll_pwait (__NR_Linux + 272) +#define __NR_ioprio_set (__NR_Linux + 273) +#define __NR_ioprio_get (__NR_Linux + 274) +#define __NR_utimensat (__NR_Linux + 275) +#define __NR_signalfd (__NR_Linux + 276) +#define __NR_timerfd (__NR_Linux + 277) +#define __NR_eventfd (__NR_Linux + 278) +#define __NR_fallocate (__NR_Linux + 279) +#define __NR_timerfd_create (__NR_Linux + 280) +#define __NR_timerfd_gettime (__NR_Linux + 281) +#define __NR_timerfd_settime (__NR_Linux + 282) +#define __NR_signalfd4 (__NR_Linux + 283) +#define __NR_eventfd2 (__NR_Linux + 284) +#define __NR_epoll_create1 (__NR_Linux + 285) +#define __NR_dup3 (__NR_Linux + 286) +#define __NR_pipe2 (__NR_Linux + 287) +#define __NR_inotify_init1 (__NR_Linux + 288) + +/* + * Offset of the last Linux 64-bit flavoured syscall + */ +#define __NR_Linux_syscalls 288 + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ + +#define __NR_64_Linux 5000 +#define __NR_64_Linux_syscalls 288 + +#if _MIPS_SIM == _MIPS_SIM_NABI32 + +/* + * Linux N32 syscalls are in the range from 6000 to 6999. + */ +#define __NR_Linux 6000 +#define __NR_read (__NR_Linux + 0) +#define __NR_write (__NR_Linux + 1) +#define __NR_open (__NR_Linux + 2) +#define __NR_close (__NR_Linux + 3) +#define __NR_stat (__NR_Linux + 4) +#define __NR_fstat (__NR_Linux + 5) +#define __NR_lstat (__NR_Linux + 6) +#define __NR_poll (__NR_Linux + 7) +#define __NR_lseek (__NR_Linux + 8) +#define __NR_mmap (__NR_Linux + 9) +#define __NR_mprotect (__NR_Linux + 10) +#define __NR_munmap (__NR_Linux + 11) +#define __NR_brk (__NR_Linux + 12) +#define __NR_rt_sigaction (__NR_Linux + 13) +#define __NR_rt_sigprocmask (__NR_Linux + 14) +#define __NR_ioctl (__NR_Linux + 15) +#define __NR_pread64 (__NR_Linux + 16) +#define __NR_pwrite64 (__NR_Linux + 17) +#define __NR_readv (__NR_Linux + 18) +#define __NR_writev (__NR_Linux + 19) +#define __NR_access (__NR_Linux + 20) +#define __NR_pipe (__NR_Linux + 21) +#define __NR__newselect (__NR_Linux + 22) +#define __NR_sched_yield (__NR_Linux + 23) +#define __NR_mremap (__NR_Linux + 24) +#define __NR_msync (__NR_Linux + 25) +#define __NR_mincore (__NR_Linux + 26) +#define __NR_madvise (__NR_Linux + 27) +#define __NR_shmget (__NR_Linux + 28) +#define __NR_shmat (__NR_Linux + 29) +#define __NR_shmctl (__NR_Linux + 30) +#define __NR_dup (__NR_Linux + 31) +#define __NR_dup2 (__NR_Linux + 32) +#define __NR_pause (__NR_Linux + 33) +#define __NR_nanosleep (__NR_Linux + 34) +#define __NR_getitimer (__NR_Linux + 35) +#define __NR_setitimer (__NR_Linux + 36) +#define __NR_alarm (__NR_Linux + 37) +#define __NR_getpid (__NR_Linux + 38) +#define __NR_sendfile (__NR_Linux + 39) +#define __NR_socket (__NR_Linux + 40) +#define __NR_connect (__NR_Linux + 41) +#define __NR_accept (__NR_Linux + 42) +#define __NR_sendto (__NR_Linux + 43) +#define __NR_recvfrom (__NR_Linux + 44) +#define __NR_sendmsg (__NR_Linux + 45) +#define __NR_recvmsg (__NR_Linux + 46) +#define __NR_shutdown (__NR_Linux + 47) +#define __NR_bind (__NR_Linux + 48) +#define __NR_listen (__NR_Linux + 49) +#define __NR_getsockname (__NR_Linux + 50) +#define __NR_getpeername (__NR_Linux + 51) +#define __NR_socketpair (__NR_Linux + 52) +#define __NR_setsockopt (__NR_Linux + 53) +#define __NR_getsockopt (__NR_Linux + 54) +#define __NR_clone (__NR_Linux + 55) +#define __NR_fork (__NR_Linux + 56) +#define __NR_execve (__NR_Linux + 57) +#define __NR_exit (__NR_Linux + 58) +#define __NR_wait4 (__NR_Linux + 59) +#define __NR_kill (__NR_Linux + 60) +#define __NR_uname (__NR_Linux + 61) +#define __NR_semget (__NR_Linux + 62) +#define __NR_semop (__NR_Linux + 63) +#define __NR_semctl (__NR_Linux + 64) +#define __NR_shmdt (__NR_Linux + 65) +#define __NR_msgget (__NR_Linux + 66) +#define __NR_msgsnd (__NR_Linux + 67) +#define __NR_msgrcv (__NR_Linux + 68) +#define __NR_msgctl (__NR_Linux + 69) +#define __NR_fcntl (__NR_Linux + 70) +#define __NR_flock (__NR_Linux + 71) +#define __NR_fsync (__NR_Linux + 72) +#define __NR_fdatasync (__NR_Linux + 73) +#define __NR_truncate (__NR_Linux + 74) +#define __NR_ftruncate (__NR_Linux + 75) +#define __NR_getdents (__NR_Linux + 76) +#define __NR_getcwd (__NR_Linux + 77) +#define __NR_chdir (__NR_Linux + 78) +#define __NR_fchdir (__NR_Linux + 79) +#define __NR_rename (__NR_Linux + 80) +#define __NR_mkdir (__NR_Linux + 81) +#define __NR_rmdir (__NR_Linux + 82) +#define __NR_creat (__NR_Linux + 83) +#define __NR_link (__NR_Linux + 84) +#define __NR_unlink (__NR_Linux + 85) +#define __NR_symlink (__NR_Linux + 86) +#define __NR_readlink (__NR_Linux + 87) +#define __NR_chmod (__NR_Linux + 88) +#define __NR_fchmod (__NR_Linux + 89) +#define __NR_chown (__NR_Linux + 90) +#define __NR_fchown (__NR_Linux + 91) +#define __NR_lchown (__NR_Linux + 92) +#define __NR_umask (__NR_Linux + 93) +#define __NR_gettimeofday (__NR_Linux + 94) +#define __NR_getrlimit (__NR_Linux + 95) +#define __NR_getrusage (__NR_Linux + 96) +#define __NR_sysinfo (__NR_Linux + 97) +#define __NR_times (__NR_Linux + 98) +#define __NR_ptrace (__NR_Linux + 99) +#define __NR_getuid (__NR_Linux + 100) +#define __NR_syslog (__NR_Linux + 101) +#define __NR_getgid (__NR_Linux + 102) +#define __NR_setuid (__NR_Linux + 103) +#define __NR_setgid (__NR_Linux + 104) +#define __NR_geteuid (__NR_Linux + 105) +#define __NR_getegid (__NR_Linux + 106) +#define __NR_setpgid (__NR_Linux + 107) +#define __NR_getppid (__NR_Linux + 108) +#define __NR_getpgrp (__NR_Linux + 109) +#define __NR_setsid (__NR_Linux + 110) +#define __NR_setreuid (__NR_Linux + 111) +#define __NR_setregid (__NR_Linux + 112) +#define __NR_getgroups (__NR_Linux + 113) +#define __NR_setgroups (__NR_Linux + 114) +#define __NR_setresuid (__NR_Linux + 115) +#define __NR_getresuid (__NR_Linux + 116) +#define __NR_setresgid (__NR_Linux + 117) +#define __NR_getresgid (__NR_Linux + 118) +#define __NR_getpgid (__NR_Linux + 119) +#define __NR_setfsuid (__NR_Linux + 120) +#define __NR_setfsgid (__NR_Linux + 121) +#define __NR_getsid (__NR_Linux + 122) +#define __NR_capget (__NR_Linux + 123) +#define __NR_capset (__NR_Linux + 124) +#define __NR_rt_sigpending (__NR_Linux + 125) +#define __NR_rt_sigtimedwait (__NR_Linux + 126) +#define __NR_rt_sigqueueinfo (__NR_Linux + 127) +#define __NR_rt_sigsuspend (__NR_Linux + 128) +#define __NR_sigaltstack (__NR_Linux + 129) +#define __NR_utime (__NR_Linux + 130) +#define __NR_mknod (__NR_Linux + 131) +#define __NR_personality (__NR_Linux + 132) +#define __NR_ustat (__NR_Linux + 133) +#define __NR_statfs (__NR_Linux + 134) +#define __NR_fstatfs (__NR_Linux + 135) +#define __NR_sysfs (__NR_Linux + 136) +#define __NR_getpriority (__NR_Linux + 137) +#define __NR_setpriority (__NR_Linux + 138) +#define __NR_sched_setparam (__NR_Linux + 139) +#define __NR_sched_getparam (__NR_Linux + 140) +#define __NR_sched_setscheduler (__NR_Linux + 141) +#define __NR_sched_getscheduler (__NR_Linux + 142) +#define __NR_sched_get_priority_max (__NR_Linux + 143) +#define __NR_sched_get_priority_min (__NR_Linux + 144) +#define __NR_sched_rr_get_interval (__NR_Linux + 145) +#define __NR_mlock (__NR_Linux + 146) +#define __NR_munlock (__NR_Linux + 147) +#define __NR_mlockall (__NR_Linux + 148) +#define __NR_munlockall (__NR_Linux + 149) +#define __NR_vhangup (__NR_Linux + 150) +#define __NR_pivot_root (__NR_Linux + 151) +#define __NR__sysctl (__NR_Linux + 152) +#define __NR_prctl (__NR_Linux + 153) +#define __NR_adjtimex (__NR_Linux + 154) +#define __NR_setrlimit (__NR_Linux + 155) +#define __NR_chroot (__NR_Linux + 156) +#define __NR_sync (__NR_Linux + 157) +#define __NR_acct (__NR_Linux + 158) +#define __NR_settimeofday (__NR_Linux + 159) +#define __NR_mount (__NR_Linux + 160) +#define __NR_umount2 (__NR_Linux + 161) +#define __NR_swapon (__NR_Linux + 162) +#define __NR_swapoff (__NR_Linux + 163) +#define __NR_reboot (__NR_Linux + 164) +#define __NR_sethostname (__NR_Linux + 165) +#define __NR_setdomainname (__NR_Linux + 166) +#define __NR_create_module (__NR_Linux + 167) +#define __NR_init_module (__NR_Linux + 168) +#define __NR_delete_module (__NR_Linux + 169) +#define __NR_get_kernel_syms (__NR_Linux + 170) +#define __NR_query_module (__NR_Linux + 171) +#define __NR_quotactl (__NR_Linux + 172) +#define __NR_nfsservctl (__NR_Linux + 173) +#define __NR_getpmsg (__NR_Linux + 174) +#define __NR_putpmsg (__NR_Linux + 175) +#define __NR_afs_syscall (__NR_Linux + 176) +#define __NR_reserved177 (__NR_Linux + 177) +#define __NR_gettid (__NR_Linux + 178) +#define __NR_readahead (__NR_Linux + 179) +#define __NR_setxattr (__NR_Linux + 180) +#define __NR_lsetxattr (__NR_Linux + 181) +#define __NR_fsetxattr (__NR_Linux + 182) +#define __NR_getxattr (__NR_Linux + 183) +#define __NR_lgetxattr (__NR_Linux + 184) +#define __NR_fgetxattr (__NR_Linux + 185) +#define __NR_listxattr (__NR_Linux + 186) +#define __NR_llistxattr (__NR_Linux + 187) +#define __NR_flistxattr (__NR_Linux + 188) +#define __NR_removexattr (__NR_Linux + 189) +#define __NR_lremovexattr (__NR_Linux + 190) +#define __NR_fremovexattr (__NR_Linux + 191) +#define __NR_tkill (__NR_Linux + 192) +#define __NR_reserved193 (__NR_Linux + 193) +#define __NR_futex (__NR_Linux + 194) +#define __NR_sched_setaffinity (__NR_Linux + 195) +#define __NR_sched_getaffinity (__NR_Linux + 196) +#define __NR_cacheflush (__NR_Linux + 197) +#define __NR_cachectl (__NR_Linux + 198) +#define __NR_sysmips (__NR_Linux + 199) +#define __NR_io_setup (__NR_Linux + 200) +#define __NR_io_destroy (__NR_Linux + 201) +#define __NR_io_getevents (__NR_Linux + 202) +#define __NR_io_submit (__NR_Linux + 203) +#define __NR_io_cancel (__NR_Linux + 204) +#define __NR_exit_group (__NR_Linux + 205) +#define __NR_lookup_dcookie (__NR_Linux + 206) +#define __NR_epoll_create (__NR_Linux + 207) +#define __NR_epoll_ctl (__NR_Linux + 208) +#define __NR_epoll_wait (__NR_Linux + 209) +#define __NR_remap_file_pages (__NR_Linux + 210) +#define __NR_rt_sigreturn (__NR_Linux + 211) +#define __NR_fcntl64 (__NR_Linux + 212) +#define __NR_set_tid_address (__NR_Linux + 213) +#define __NR_restart_syscall (__NR_Linux + 214) +#define __NR_semtimedop (__NR_Linux + 215) +#define __NR_fadvise64 (__NR_Linux + 216) +#define __NR_statfs64 (__NR_Linux + 217) +#define __NR_fstatfs64 (__NR_Linux + 218) +#define __NR_sendfile64 (__NR_Linux + 219) +#define __NR_timer_create (__NR_Linux + 220) +#define __NR_timer_settime (__NR_Linux + 221) +#define __NR_timer_gettime (__NR_Linux + 222) +#define __NR_timer_getoverrun (__NR_Linux + 223) +#define __NR_timer_delete (__NR_Linux + 224) +#define __NR_clock_settime (__NR_Linux + 225) +#define __NR_clock_gettime (__NR_Linux + 226) +#define __NR_clock_getres (__NR_Linux + 227) +#define __NR_clock_nanosleep (__NR_Linux + 228) +#define __NR_tgkill (__NR_Linux + 229) +#define __NR_utimes (__NR_Linux + 230) +#define __NR_mbind (__NR_Linux + 231) +#define __NR_get_mempolicy (__NR_Linux + 232) +#define __NR_set_mempolicy (__NR_Linux + 233) +#define __NR_mq_open (__NR_Linux + 234) +#define __NR_mq_unlink (__NR_Linux + 235) +#define __NR_mq_timedsend (__NR_Linux + 236) +#define __NR_mq_timedreceive (__NR_Linux + 237) +#define __NR_mq_notify (__NR_Linux + 238) +#define __NR_mq_getsetattr (__NR_Linux + 239) +#define __NR_vserver (__NR_Linux + 240) +#define __NR_waitid (__NR_Linux + 241) +/* #define __NR_sys_setaltroot (__NR_Linux + 242) */ +#define __NR_add_key (__NR_Linux + 243) +#define __NR_request_key (__NR_Linux + 244) +#define __NR_keyctl (__NR_Linux + 245) +#define __NR_set_thread_area (__NR_Linux + 246) +#define __NR_inotify_init (__NR_Linux + 247) +#define __NR_inotify_add_watch (__NR_Linux + 248) +#define __NR_inotify_rm_watch (__NR_Linux + 249) +#define __NR_migrate_pages (__NR_Linux + 250) +#define __NR_openat (__NR_Linux + 251) +#define __NR_mkdirat (__NR_Linux + 252) +#define __NR_mknodat (__NR_Linux + 253) +#define __NR_fchownat (__NR_Linux + 254) +#define __NR_futimesat (__NR_Linux + 255) +#define __NR_newfstatat (__NR_Linux + 256) +#define __NR_unlinkat (__NR_Linux + 257) +#define __NR_renameat (__NR_Linux + 258) +#define __NR_linkat (__NR_Linux + 259) +#define __NR_symlinkat (__NR_Linux + 260) +#define __NR_readlinkat (__NR_Linux + 261) +#define __NR_fchmodat (__NR_Linux + 262) +#define __NR_faccessat (__NR_Linux + 263) +#define __NR_pselect6 (__NR_Linux + 264) +#define __NR_ppoll (__NR_Linux + 265) +#define __NR_unshare (__NR_Linux + 266) +#define __NR_splice (__NR_Linux + 267) +#define __NR_sync_file_range (__NR_Linux + 268) +#define __NR_tee (__NR_Linux + 269) +#define __NR_vmsplice (__NR_Linux + 270) +#define __NR_move_pages (__NR_Linux + 271) +#define __NR_set_robust_list (__NR_Linux + 272) +#define __NR_get_robust_list (__NR_Linux + 273) +#define __NR_kexec_load (__NR_Linux + 274) +#define __NR_getcpu (__NR_Linux + 275) +#define __NR_epoll_pwait (__NR_Linux + 276) +#define __NR_ioprio_set (__NR_Linux + 277) +#define __NR_ioprio_get (__NR_Linux + 278) +#define __NR_utimensat (__NR_Linux + 279) +#define __NR_signalfd (__NR_Linux + 280) +#define __NR_timerfd (__NR_Linux + 281) +#define __NR_eventfd (__NR_Linux + 282) +#define __NR_fallocate (__NR_Linux + 283) +#define __NR_timerfd_create (__NR_Linux + 284) +#define __NR_timerfd_gettime (__NR_Linux + 285) +#define __NR_timerfd_settime (__NR_Linux + 286) +#define __NR_signalfd4 (__NR_Linux + 287) +#define __NR_eventfd2 (__NR_Linux + 288) +#define __NR_epoll_create1 (__NR_Linux + 289) +#define __NR_dup3 (__NR_Linux + 290) +#define __NR_pipe2 (__NR_Linux + 291) +#define __NR_inotify_init1 (__NR_Linux + 292) + +/* + * Offset of the last N32 flavoured syscall + */ +#define __NR_Linux_syscalls 292 + +#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ + +#define __NR_N32_Linux 6000 +#define __NR_N32_Linux_syscalls 292 + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 +#define __ARCH_WANT_IPC_PARSE_VERSION +#define __ARCH_WANT_OLD_READDIR +#define __ARCH_WANT_SYS_ALARM +#define __ARCH_WANT_SYS_GETHOSTNAME +#define __ARCH_WANT_SYS_PAUSE +#define __ARCH_WANT_SYS_SGETMASK +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_WAITPID +#define __ARCH_WANT_SYS_SOCKETCALL +#define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_SYS_NICE +#define __ARCH_WANT_SYS_OLD_GETRLIMIT +#define __ARCH_WANT_SYS_OLDUMOUNT +#define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_RT_SIGACTION +# ifdef CONFIG_32BIT +# define __ARCH_WANT_STAT64 +# define __ARCH_WANT_SYS_TIME +# endif +# ifdef CONFIG_MIPS32_O32 +# define __ARCH_WANT_COMPAT_SYS_TIME +# endif + +/* whitelists for checksyscalls */ +#define __IGNORE_select +#define __IGNORE_vfork +#define __IGNORE_time +#define __IGNORE_uselib +#define __IGNORE_fadvise64_64 +#define __IGNORE_getdents64 +#if _MIPS_SIM == _MIPS_SIM_NABI32 +#define __IGNORE_truncate64 +#define __IGNORE_ftruncate64 +#define __IGNORE_stat64 +#define __IGNORE_lstat64 +#define __IGNORE_fstat64 +#define __IGNORE_fstatat64 +#endif + +#endif /* !__ASSEMBLY__ */ + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall") + +#endif /* __KERNEL__ */ +#endif /* _ASM_UNISTD_H */ diff --git a/arch/mips/include/asm/user.h b/arch/mips/include/asm/user.h new file mode 100644 index 00000000000..afa83a4c188 --- /dev/null +++ b/arch/mips/include/asm/user.h @@ -0,0 +1,58 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle + */ +#ifndef _ASM_USER_H +#define _ASM_USER_H + +#include +#include + +/* + * Core file format: The core file is written in such a way that gdb + * can understand it and provide useful information to the user (under + * linux we use the `trad-core' bfd, NOT the irix-core). The file + * contents are as follows: + * + * upage: 1 page consisting of a user struct that tells gdb + * what is present in the file. Directly after this is a + * copy of the task_struct, which is currently not used by gdb, + * but it may come in handy at some point. All of the registers + * are stored as part of the upage. The upage should always be + * only one page long. + * data: The data segment follows next. We use current->end_text to + * current->brk to pick up all of the user variables, plus any memory + * that may have been sbrk'ed. No attempt is made to determine if a + * page is demand-zero or if a page is totally unused, we just cover + * the entire range. All of the addresses are rounded in such a way + * that an integral number of pages is written. + * stack: We need the stack information in order to get a meaningful + * backtrace. We need to write the data from usp to + * current->start_stack, so we round each of these in order to be able + * to write an integer number of pages. + */ +struct user { + unsigned long regs[EF_SIZE / /* integer and fp regs */ + sizeof(unsigned long) + 64]; + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + unsigned long u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _ASM_USER_H */ diff --git a/arch/mips/include/asm/vga.h b/arch/mips/include/asm/vga.h new file mode 100644 index 00000000000..f4cff7e4fa8 --- /dev/null +++ b/arch/mips/include/asm/vga.h @@ -0,0 +1,47 @@ +/* + * Access to VGA videoram + * + * (c) 1998 Martin Mares + */ +#ifndef _ASM_VGA_H +#define _ASM_VGA_H + +#include + +/* + * On the PC, we can just recalculate addresses and then + * access the videoram directly without any black magic. + */ + +#define VGA_MAP_MEM(x, s) (0xb0000000L + (unsigned long)(x)) + +#define vga_readb(x) (*(x)) +#define vga_writeb(x, y) (*(y) = (x)) + +#define VT_BUF_HAVE_RW +/* + * These are only needed for supporting VGA or MDA text mode, which use little + * endian byte ordering. + * In other cases, we can optimize by using native byte ordering and + * has already done the right job for us. + */ + +#undef scr_writew +#undef scr_readw + +static inline void scr_writew(u16 val, volatile u16 *addr) +{ + *addr = cpu_to_le16(val); +} + +static inline u16 scr_readw(volatile const u16 *addr) +{ + return le16_to_cpu(*addr); +} + +#define scr_memcpyw(d, s, c) memcpy(d, s, c) +#define scr_memmovew(d, s, c) memmove(d, s, c) +#define VT_BUF_HAVE_MEMCPYW +#define VT_BUF_HAVE_MEMMOVEW + +#endif /* _ASM_VGA_H */ diff --git a/arch/mips/include/asm/vpe.h b/arch/mips/include/asm/vpe.h new file mode 100644 index 00000000000..c6e1b961537 --- /dev/null +++ b/arch/mips/include/asm/vpe.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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_VPE_H +#define _ASM_VPE_H + +struct vpe_notifications { + void (*start)(int vpe); + void (*stop)(int vpe); + + struct list_head list; +}; + + +extern int vpe_notify(int index, struct vpe_notifications *notify); + +extern void *vpe_get_shared(int index); +extern int vpe_getuid(int index); +extern int vpe_getgid(int index); +extern char *vpe_getcwd(int index); + +#endif /* _ASM_VPE_H */ diff --git a/arch/mips/include/asm/vr41xx/capcella.h b/arch/mips/include/asm/vr41xx/capcella.h new file mode 100644 index 00000000000..e0ee05a3dfc --- /dev/null +++ b/arch/mips/include/asm/vr41xx/capcella.h @@ -0,0 +1,43 @@ +/* + * capcella.h, Include file for ZAO Networks Capcella. + * + * Copyright (C) 2002-2004 Yoichi Yuasa + * + * 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 __ZAO_CAPCELLA_H +#define __ZAO_CAPCELLA_H + +#include + +/* + * General-Purpose I/O Pin Number + */ +#define PC104PLUS_INTA_PIN 2 +#define PC104PLUS_INTB_PIN 3 +#define PC104PLUS_INTC_PIN 4 +#define PC104PLUS_INTD_PIN 5 + +/* + * Interrupt Number + */ +#define RTL8139_1_IRQ GIU_IRQ(PC104PLUS_INTC_PIN) +#define RTL8139_2_IRQ GIU_IRQ(PC104PLUS_INTD_PIN) +#define PC104PLUS_INTA_IRQ GIU_IRQ(PC104PLUS_INTA_PIN) +#define PC104PLUS_INTB_IRQ GIU_IRQ(PC104PLUS_INTB_PIN) +#define PC104PLUS_INTC_IRQ GIU_IRQ(PC104PLUS_INTC_PIN) +#define PC104PLUS_INTD_IRQ GIU_IRQ(PC104PLUS_INTD_PIN) + +#endif /* __ZAO_CAPCELLA_H */ diff --git a/arch/mips/include/asm/vr41xx/giu.h b/arch/mips/include/asm/vr41xx/giu.h new file mode 100644 index 00000000000..0bcdd3a5c25 --- /dev/null +++ b/arch/mips/include/asm/vr41xx/giu.h @@ -0,0 +1,78 @@ +/* + * Include file for NEC VR4100 series General-purpose I/O Unit. + * + * Copyright (C) 2005 Yoichi Yuasa + * + * 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 __NEC_VR41XX_GIU_H +#define __NEC_VR41XX_GIU_H + +/* + * NEC VR4100 series GIU platform device IDs. + */ +enum { + GPIO_50PINS_PULLUPDOWN, + GPIO_36PINS, + GPIO_48PINS_EDGE_SELECT, +}; + +typedef enum { + IRQ_TRIGGER_LEVEL, + IRQ_TRIGGER_EDGE, + IRQ_TRIGGER_EDGE_FALLING, + IRQ_TRIGGER_EDGE_RISING, +} irq_trigger_t; + +typedef enum { + IRQ_SIGNAL_THROUGH, + IRQ_SIGNAL_HOLD, +} irq_signal_t; + +extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal); + +typedef enum { + IRQ_LEVEL_LOW, + IRQ_LEVEL_HIGH, +} irq_level_t; + +extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level); + +typedef enum { + GPIO_DATA_LOW, + GPIO_DATA_HIGH, + GPIO_DATA_INVAL, +} gpio_data_t; + +extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin); +extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data); + +typedef enum { + GPIO_INPUT, + GPIO_OUTPUT, + GPIO_OUTPUT_DISABLE, +} gpio_direction_t; + +extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir); + +typedef enum { + GPIO_PULL_DOWN, + GPIO_PULL_UP, + GPIO_PULL_DISABLE, +} gpio_pull_t; + +extern int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull); + +#endif /* __NEC_VR41XX_GIU_H */ diff --git a/arch/mips/include/asm/vr41xx/irq.h b/arch/mips/include/asm/vr41xx/irq.h new file mode 100644 index 00000000000..d315dfbc08f --- /dev/null +++ b/arch/mips/include/asm/vr41xx/irq.h @@ -0,0 +1,101 @@ +/* + * include/asm-mips/vr41xx/irq.h + * + * Interrupt numbers for NEC VR4100 series. + * + * Copyright (C) 1999 Michael Klar + * Copyright (C) 2001, 2002 Paul Mundt + * Copyright (C) 2002 MontaVista Software, Inc. + * Copyright (C) 2002 TimeSys Corp. + * Copyright (C) 2003-2006 Yoichi Yuasa + * + * 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. + */ +#ifndef __NEC_VR41XX_IRQ_H +#define __NEC_VR41XX_IRQ_H + +/* + * CPU core Interrupt Numbers + */ +#define MIPS_CPU_IRQ_BASE 0 +#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x)) +#define MIPS_SOFTINT0_IRQ MIPS_CPU_IRQ(0) +#define MIPS_SOFTINT1_IRQ MIPS_CPU_IRQ(1) +#define INT0_IRQ MIPS_CPU_IRQ(2) +#define INT1_IRQ MIPS_CPU_IRQ(3) +#define INT2_IRQ MIPS_CPU_IRQ(4) +#define INT3_IRQ MIPS_CPU_IRQ(5) +#define INT4_IRQ MIPS_CPU_IRQ(6) +#define TIMER_IRQ MIPS_CPU_IRQ(7) + +/* + * SYINT1 Interrupt Numbers + */ +#define SYSINT1_IRQ_BASE 8 +#define SYSINT1_IRQ(x) (SYSINT1_IRQ_BASE + (x)) +#define BATTRY_IRQ SYSINT1_IRQ(0) +#define POWER_IRQ SYSINT1_IRQ(1) +#define RTCLONG1_IRQ SYSINT1_IRQ(2) +#define ELAPSEDTIME_IRQ SYSINT1_IRQ(3) +/* RFU */ +#define PIU_IRQ SYSINT1_IRQ(5) +#define AIU_IRQ SYSINT1_IRQ(6) +#define KIU_IRQ SYSINT1_IRQ(7) +#define GIUINT_IRQ SYSINT1_IRQ(8) +#define SIU_IRQ SYSINT1_IRQ(9) +#define BUSERR_IRQ SYSINT1_IRQ(10) +#define SOFTINT_IRQ SYSINT1_IRQ(11) +#define CLKRUN_IRQ SYSINT1_IRQ(12) +#define DOZEPIU_IRQ SYSINT1_IRQ(13) +#define SYSINT1_IRQ_LAST DOZEPIU_IRQ + +/* + * SYSINT2 Interrupt Numbers + */ +#define SYSINT2_IRQ_BASE 24 +#define SYSINT2_IRQ(x) (SYSINT2_IRQ_BASE + (x)) +#define RTCLONG2_IRQ SYSINT2_IRQ(0) +#define LED_IRQ SYSINT2_IRQ(1) +#define HSP_IRQ SYSINT2_IRQ(2) +#define TCLOCK_IRQ SYSINT2_IRQ(3) +#define FIR_IRQ SYSINT2_IRQ(4) +#define CEU_IRQ SYSINT2_IRQ(4) /* same number as FIR_IRQ */ +#define DSIU_IRQ SYSINT2_IRQ(5) +#define PCI_IRQ SYSINT2_IRQ(6) +#define SCU_IRQ SYSINT2_IRQ(7) +#define CSI_IRQ SYSINT2_IRQ(8) +#define BCU_IRQ SYSINT2_IRQ(9) +#define ETHERNET_IRQ SYSINT2_IRQ(10) +#define SYSINT2_IRQ_LAST ETHERNET_IRQ + +/* + * GIU Interrupt Numbers + */ +#define GIU_IRQ_BASE 40 +#define GIU_IRQ(x) (GIU_IRQ_BASE + (x)) /* IRQ 40-71 */ +#define GIU_IRQ_LAST GIU_IRQ(31) + +/* + * VRC4173 Interrupt Numbers + */ +#define VRC4173_IRQ_BASE 72 +#define VRC4173_IRQ(x) (VRC4173_IRQ_BASE + (x)) +#define VRC4173_USB_IRQ VRC4173_IRQ(0) +#define VRC4173_PCMCIA2_IRQ VRC4173_IRQ(1) +#define VRC4173_PCMCIA1_IRQ VRC4173_IRQ(2) +#define VRC4173_PS2CH2_IRQ VRC4173_IRQ(3) +#define VRC4173_PS2CH1_IRQ VRC4173_IRQ(4) +#define VRC4173_PIU_IRQ VRC4173_IRQ(5) +#define VRC4173_AIU_IRQ VRC4173_IRQ(6) +#define VRC4173_KIU_IRQ VRC4173_IRQ(7) +#define VRC4173_GIU_IRQ VRC4173_IRQ(8) +#define VRC4173_AC97_IRQ VRC4173_IRQ(9) +#define VRC4173_AC97INT1_IRQ VRC4173_IRQ(10) +/* RFU */ +#define VRC4173_DOZEPIU_IRQ VRC4173_IRQ(13) +#define VRC4173_IRQ_LAST VRC4173_DOZEPIU_IRQ + +#endif /* __NEC_VR41XX_IRQ_H */ diff --git a/arch/mips/include/asm/vr41xx/mpc30x.h b/arch/mips/include/asm/vr41xx/mpc30x.h new file mode 100644 index 00000000000..1d67df843dc --- /dev/null +++ b/arch/mips/include/asm/vr41xx/mpc30x.h @@ -0,0 +1,37 @@ +/* + * mpc30x.h, Include file for Victor MP-C303/304. + * + * Copyright (C) 2002-2004 Yoichi Yuasa + * + * 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 __VICTOR_MPC30X_H +#define __VICTOR_MPC30X_H + +#include + +/* + * General-Purpose I/O Pin Number + */ +#define VRC4173_PIN 1 +#define MQ200_PIN 4 + +/* + * Interrupt Number + */ +#define VRC4173_CASCADE_IRQ GIU_IRQ(VRC4173_PIN) +#define MQ200_IRQ GIU_IRQ(MQ200_PIN) + +#endif /* __VICTOR_MPC30X_H */ diff --git a/arch/mips/include/asm/vr41xx/pci.h b/arch/mips/include/asm/vr41xx/pci.h new file mode 100644 index 00000000000..6fc01ce1977 --- /dev/null +++ b/arch/mips/include/asm/vr41xx/pci.h @@ -0,0 +1,90 @@ +/* + * Include file for NEC VR4100 series PCI Control Unit. + * + * Copyright (C) 2004-2005 Yoichi Yuasa + * + * 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 __NEC_VR41XX_PCI_H +#define __NEC_VR41XX_PCI_H + +#define PCI_MASTER_ADDRESS_MASK 0x7fffffffU + +struct pci_master_address_conversion { + uint32_t bus_base_address; + uint32_t address_mask; + uint32_t pci_base_address; +}; + +struct pci_target_address_conversion { + uint32_t address_mask; + uint32_t bus_base_address; +}; + +typedef enum { + CANNOT_LOCK_FROM_DEVICE, + CAN_LOCK_FROM_DEVICE, +} pci_exclusive_access_t; + +struct pci_mailbox_address { + uint32_t base_address; +}; + +struct pci_target_address_window { + uint32_t base_address; +}; + +typedef enum { + PCI_ARBITRATION_MODE_FAIR, + PCI_ARBITRATION_MODE_ALTERNATE_0, + PCI_ARBITRATION_MODE_ALTERNATE_B, +} pci_arbiter_priority_control_t; + +typedef enum { + PCI_TAKE_AWAY_GNT_DISABLE, + PCI_TAKE_AWAY_GNT_ENABLE, +} pci_take_away_gnt_mode_t; + +struct pci_controller_unit_setup { + struct pci_master_address_conversion *master_memory1; + struct pci_master_address_conversion *master_memory2; + + struct pci_target_address_conversion *target_memory1; + struct pci_target_address_conversion *target_memory2; + + struct pci_master_address_conversion *master_io; + + pci_exclusive_access_t exclusive_access; + + uint32_t pci_clock_max; + uint8_t wait_time_limit_from_irdy_to_trdy; /* Only VR4122 is supported */ + + struct pci_mailbox_address *mailbox; + struct pci_target_address_window *target_window1; + struct pci_target_address_window *target_window2; + + uint8_t master_latency_timer; + uint8_t retry_limit; + + pci_arbiter_priority_control_t arbiter_priority_control; + pci_take_away_gnt_mode_t take_away_gnt_mode; + + struct resource *mem_resource; + struct resource *io_resource; +}; + +extern void vr41xx_pciu_setup(struct pci_controller_unit_setup *setup); + +#endif /* __NEC_VR41XX_PCI_H */ diff --git a/arch/mips/include/asm/vr41xx/siu.h b/arch/mips/include/asm/vr41xx/siu.h new file mode 100644 index 00000000000..da9f6e37340 --- /dev/null +++ b/arch/mips/include/asm/vr41xx/siu.h @@ -0,0 +1,58 @@ +/* + * Include file for NEC VR4100 series Serial Interface Unit. + * + * Copyright (C) 2005-2008 Yoichi Yuasa + * + * 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 __NEC_VR41XX_SIU_H +#define __NEC_VR41XX_SIU_H + +#define SIU_PORTS_MAX 2 + +typedef enum { + SIU_INTERFACE_RS232C, + SIU_INTERFACE_IRDA, +} siu_interface_t; + +extern void vr41xx_select_siu_interface(siu_interface_t interface); + +typedef enum { + SIU_USE_IRDA, + FIR_USE_IRDA, +} irda_use_t; + +extern void vr41xx_use_irda(irda_use_t use); + +typedef enum { + SHARP_IRDA, + TEMIC_IRDA, + HP_IRDA, +} irda_module_t; + +typedef enum { + IRDA_TX_1_5MBPS, + IRDA_TX_4MBPS, +} irda_speed_t; + +extern void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed); + +#ifdef CONFIG_SERIAL_VR41XX_CONSOLE +extern void vr41xx_siu_early_setup(struct uart_port *port); +#else +static inline void vr41xx_siu_early_setup(struct uart_port *port) {} +#endif + +#endif /* __NEC_VR41XX_SIU_H */ diff --git a/arch/mips/include/asm/vr41xx/tb0219.h b/arch/mips/include/asm/vr41xx/tb0219.h new file mode 100644 index 00000000000..dc981b4be0a --- /dev/null +++ b/arch/mips/include/asm/vr41xx/tb0219.h @@ -0,0 +1,42 @@ +/* + * tb0219.h, Include file for TANBAC TB0219. + * + * Copyright (C) 2002-2004 Yoichi Yuasa + * + * Modified for TANBAC TB0219: + * Copyright (C) 2003 Megasolution Inc. + * + * 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 __TANBAC_TB0219_H +#define __TANBAC_TB0219_H + +#include + +/* + * General-Purpose I/O Pin Number + */ +#define TB0219_PCI_SLOT1_PIN 2 +#define TB0219_PCI_SLOT2_PIN 3 +#define TB0219_PCI_SLOT3_PIN 4 + +/* + * Interrupt Number + */ +#define TB0219_PCI_SLOT1_IRQ GIU_IRQ(TB0219_PCI_SLOT1_PIN) +#define TB0219_PCI_SLOT2_IRQ GIU_IRQ(TB0219_PCI_SLOT2_PIN) +#define TB0219_PCI_SLOT3_IRQ GIU_IRQ(TB0219_PCI_SLOT3_PIN) + +#endif /* __TANBAC_TB0219_H */ diff --git a/arch/mips/include/asm/vr41xx/tb0226.h b/arch/mips/include/asm/vr41xx/tb0226.h new file mode 100644 index 00000000000..de527dcfa5f --- /dev/null +++ b/arch/mips/include/asm/vr41xx/tb0226.h @@ -0,0 +1,43 @@ +/* + * tb0226.h, Include file for TANBAC TB0226. + * + * Copyright (C) 2002-2004 Yoichi Yuasa + * + * 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 __TANBAC_TB0226_H +#define __TANBAC_TB0226_H + +#include + +/* + * General-Purpose I/O Pin Number + */ +#define GD82559_1_PIN 2 +#define GD82559_2_PIN 3 +#define UPD720100_INTA_PIN 4 +#define UPD720100_INTB_PIN 8 +#define UPD720100_INTC_PIN 13 + +/* + * Interrupt Number + */ +#define GD82559_1_IRQ GIU_IRQ(GD82559_1_PIN) +#define GD82559_2_IRQ GIU_IRQ(GD82559_2_PIN) +#define UPD720100_INTA_IRQ GIU_IRQ(UPD720100_INTA_PIN) +#define UPD720100_INTB_IRQ GIU_IRQ(UPD720100_INTB_PIN) +#define UPD720100_INTC_IRQ GIU_IRQ(UPD720100_INTC_PIN) + +#endif /* __TANBAC_TB0226_H */ diff --git a/arch/mips/include/asm/vr41xx/tb0287.h b/arch/mips/include/asm/vr41xx/tb0287.h new file mode 100644 index 00000000000..61bead68abf --- /dev/null +++ b/arch/mips/include/asm/vr41xx/tb0287.h @@ -0,0 +1,43 @@ +/* + * tb0287.h, Include file for TANBAC TB0287 mini-ITX board. + * + * Copyright (C) 2005 Media Lab Inc. + * + * This code is largely based on tb0219.h. + * + * 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 __TANBAC_TB0287_H +#define __TANBAC_TB0287_H + +#include + +/* + * General-Purpose I/O Pin Number + */ +#define TB0287_PCI_SLOT_PIN 2 +#define TB0287_SM501_PIN 3 +#define TB0287_SIL680A_PIN 8 +#define TB0287_RTL8110_PIN 13 + +/* + * Interrupt Number + */ +#define TB0287_PCI_SLOT_IRQ GIU_IRQ(TB0287_PCI_SLOT_PIN) +#define TB0287_SM501_IRQ GIU_IRQ(TB0287_SM501_PIN) +#define TB0287_SIL680A_IRQ GIU_IRQ(TB0287_SIL680A_PIN) +#define TB0287_RTL8110_IRQ GIU_IRQ(TB0287_RTL8110_PIN) + +#endif /* __TANBAC_TB0287_H */ diff --git a/arch/mips/include/asm/vr41xx/vr41xx.h b/arch/mips/include/asm/vr41xx/vr41xx.h new file mode 100644 index 00000000000..22be64971cc --- /dev/null +++ b/arch/mips/include/asm/vr41xx/vr41xx.h @@ -0,0 +1,152 @@ +/* + * include/asm-mips/vr41xx/vr41xx.h + * + * Include file for NEC VR4100 series. + * + * Copyright (C) 1999 Michael Klar + * Copyright (C) 2001, 2002 Paul Mundt + * Copyright (C) 2002 MontaVista Software, Inc. + * Copyright (C) 2002 TimeSys Corp. + * Copyright (C) 2003-2008 Yoichi Yuasa + * + * 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. + */ +#ifndef __NEC_VR41XX_H +#define __NEC_VR41XX_H + +#include + +/* + * CPU Revision + */ +/* VR4122 0x00000c70-0x00000c72 */ +#define PRID_VR4122_REV1_0 0x00000c70 +#define PRID_VR4122_REV2_0 0x00000c70 +#define PRID_VR4122_REV2_1 0x00000c70 +#define PRID_VR4122_REV3_0 0x00000c71 +#define PRID_VR4122_REV3_1 0x00000c72 + +/* VR4181A 0x00000c73-0x00000c7f */ +#define PRID_VR4181A_REV1_0 0x00000c73 +#define PRID_VR4181A_REV1_1 0x00000c74 + +/* VR4131 0x00000c80-0x00000c83 */ +#define PRID_VR4131_REV1_2 0x00000c80 +#define PRID_VR4131_REV2_0 0x00000c81 +#define PRID_VR4131_REV2_1 0x00000c82 +#define PRID_VR4131_REV2_2 0x00000c83 + +/* VR4133 0x00000c84- */ +#define PRID_VR4133 0x00000c84 + +/* + * Bus Control Uint + */ +extern unsigned long vr41xx_calculate_clock_frequency(void); +extern unsigned long vr41xx_get_vtclock_frequency(void); +extern unsigned long vr41xx_get_tclock_frequency(void); + +/* + * Clock Mask Unit + */ +typedef enum { + PIU_CLOCK, + SIU_CLOCK, + AIU_CLOCK, + KIU_CLOCK, + FIR_CLOCK, + DSIU_CLOCK, + CSI_CLOCK, + PCIU_CLOCK, + HSP_CLOCK, + PCI_CLOCK, + CEU_CLOCK, + ETHER0_CLOCK, + ETHER1_CLOCK +} vr41xx_clock_t; + +extern void vr41xx_supply_clock(vr41xx_clock_t clock); +extern void vr41xx_mask_clock(vr41xx_clock_t clock); + +/* + * Interrupt Control Unit + */ +extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign); +extern int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int)); + +#define PIUINT_COMMAND 0x0040 +#define PIUINT_DATA 0x0020 +#define PIUINT_PAGE1 0x0010 +#define PIUINT_PAGE0 0x0008 +#define PIUINT_DATALOST 0x0004 +#define PIUINT_STATUSCHANGE 0x0001 + +extern void vr41xx_enable_piuint(uint16_t mask); +extern void vr41xx_disable_piuint(uint16_t mask); + +#define AIUINT_INPUT_DMAEND 0x0800 +#define AIUINT_INPUT_DMAHALT 0x0400 +#define AIUINT_INPUT_DATALOST 0x0200 +#define AIUINT_INPUT_DATA 0x0100 +#define AIUINT_OUTPUT_DMAEND 0x0008 +#define AIUINT_OUTPUT_DMAHALT 0x0004 +#define AIUINT_OUTPUT_NODATA 0x0002 + +extern void vr41xx_enable_aiuint(uint16_t mask); +extern void vr41xx_disable_aiuint(uint16_t mask); + +#define KIUINT_DATALOST 0x0004 +#define KIUINT_DATAREADY 0x0002 +#define KIUINT_SCAN 0x0001 + +extern void vr41xx_enable_kiuint(uint16_t mask); +extern void vr41xx_disable_kiuint(uint16_t mask); + +#define DSIUINT_CTS 0x0800 +#define DSIUINT_RXERR 0x0400 +#define DSIUINT_RX 0x0200 +#define DSIUINT_TX 0x0100 +#define DSIUINT_ALL 0x0f00 + +extern void vr41xx_enable_dsiuint(uint16_t mask); +extern void vr41xx_disable_dsiuint(uint16_t mask); + +#define FIRINT_UNIT 0x0010 +#define FIRINT_RX_DMAEND 0x0008 +#define FIRINT_RX_DMAHALT 0x0004 +#define FIRINT_TX_DMAEND 0x0002 +#define FIRINT_TX_DMAHALT 0x0001 + +extern void vr41xx_enable_firint(uint16_t mask); +extern void vr41xx_disable_firint(uint16_t mask); + +extern void vr41xx_enable_pciint(void); +extern void vr41xx_disable_pciint(void); + +extern void vr41xx_enable_scuint(void); +extern void vr41xx_disable_scuint(void); + +#define CSIINT_TX_DMAEND 0x0040 +#define CSIINT_TX_DMAHALT 0x0020 +#define CSIINT_TX_DATA 0x0010 +#define CSIINT_TX_FIFOEMPTY 0x0008 +#define CSIINT_RX_DMAEND 0x0004 +#define CSIINT_RX_DMAHALT 0x0002 +#define CSIINT_RX_FIFOEMPTY 0x0001 + +extern void vr41xx_enable_csiint(uint16_t mask); +extern void vr41xx_disable_csiint(uint16_t mask); + +extern void vr41xx_enable_bcuint(void); +extern void vr41xx_disable_bcuint(void); + +#ifdef CONFIG_SERIAL_VR41XX_CONSOLE +extern void vr41xx_siu_setup(void); +#else +static inline void vr41xx_siu_setup(void) {} +#endif + +#endif /* __NEC_VR41XX_H */ diff --git a/arch/mips/include/asm/war.h b/arch/mips/include/asm/war.h new file mode 100644 index 00000000000..22361d5e3bf --- /dev/null +++ b/arch/mips/include/asm/war.h @@ -0,0 +1,244 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + * Copyright (C) 2007 Maciej W. Rozycki + */ +#ifndef _ASM_WAR_H +#define _ASM_WAR_H + +#include + +/* + * Work around certain R4000 CPU errata (as implemented by GCC): + * + * - A double-word or a variable shift may give an incorrect result + * if executed immediately after starting an integer division: + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #28 + * "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum + * #19 + * + * - A double-word or a variable shift may give an incorrect result + * if executed while an integer multiplication is in progress: + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * errata #16 & #28 + * + * - An integer division may give an incorrect result if started in + * a delay slot of a taken branch or a jump: + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #52 + */ +#ifdef CONFIG_CPU_R4000_WORKAROUNDS +#define R4000_WAR 1 +#else +#define R4000_WAR 0 +#endif + +/* + * Work around certain R4400 CPU errata (as implemented by GCC): + * + * - A double-word or a variable shift may give an incorrect result + * if executed immediately after starting an integer division: + * "MIPS R4400MC Errata, Processor Revision 1.0", erratum #10 + * "MIPS R4400MC Errata, Processor Revision 2.0 & 3.0", erratum #4 + */ +#ifdef CONFIG_CPU_R4400_WORKAROUNDS +#define R4400_WAR 1 +#else +#define R4400_WAR 0 +#endif + +/* + * Work around the "daddi" and "daddiu" CPU errata: + * + * - The `daddi' instruction fails to trap on overflow. + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #23 + * + * - The `daddiu' instruction can produce an incorrect result. + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #41 + * "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum + * #15 + * "MIPS R4400PC/SC Errata, Processor Revision 1.0", erratum #7 + * "MIPS R4400MC Errata, Processor Revision 1.0", erratum #5 + */ +#ifdef CONFIG_CPU_DADDI_WORKAROUNDS +#define DADDI_WAR 1 +#else +#define DADDI_WAR 0 +#endif + +/* + * Another R4600 erratum. Due to the lack of errata information the exact + * technical details aren't known. I've experimentally found that disabling + * interrupts during indexed I-cache flushes seems to be sufficient to deal + * with the issue. + */ +#ifndef R4600_V1_INDEX_ICACHEOP_WAR +#error Check setting of R4600_V1_INDEX_ICACHEOP_WAR for your platform +#endif + +/* + * Pleasures of the R4600 V1.x. Cite from the IDT R4600 V1.7 errata: + * + * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D, + * Hit_Invalidate_D and Create_Dirty_Excl_D should only be + * executed if there is no other dcache activity. If the dcache is + * accessed for another instruction immeidately preceding when these + * cache instructions are executing, it is possible that the dcache + * tag match outputs used by these cache instructions will be + * incorrect. These cache instructions should be preceded by at least + * four instructions that are not any kind of load or store + * instruction. + * + * This is not allowed: lw + * nop + * nop + * nop + * cache Hit_Writeback_Invalidate_D + * + * This is allowed: lw + * nop + * nop + * nop + * nop + * cache Hit_Writeback_Invalidate_D + */ +#ifndef R4600_V1_HIT_CACHEOP_WAR +#error Check setting of R4600_V1_HIT_CACHEOP_WAR for your platform +#endif + + +/* + * Writeback and invalidate the primary cache dcache before DMA. + * + * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D, + * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Exclusive_D will only + * operate correctly if the internal data cache refill buffer is empty. These + * CACHE instructions should be separated from any potential data cache miss + * by a load instruction to an uncached address to empty the response buffer." + * (Revision 2.0 device errata from IDT available on http://www.idt.com/ + * in .pdf format.) + */ +#ifndef R4600_V2_HIT_CACHEOP_WAR +#error Check setting of R4600_V2_HIT_CACHEOP_WAR for your platform +#endif + +/* + * When an interrupt happens on a CP0 register read instruction, CPU may + * lock up or read corrupted values of CP0 registers after it enters + * the exception handler. + * + * This workaround makes sure that we read a "safe" CP0 register as the + * first thing in the exception handler, which breaks one of the + * pre-conditions for this problem. + */ +#ifndef R5432_CP0_INTERRUPT_WAR +#error Check setting of R5432_CP0_INTERRUPT_WAR for your platform +#endif + +/* + * Workaround for the Sibyte M3 errata the text of which can be found at + * + * http://sibyte.broadcom.com/hw/bcm1250/docs/pass2errata.txt + * + * This will enable the use of a special TLB refill handler which does a + * consistency check on the information in c0_badvaddr and c0_entryhi and + * will just return and take the exception again if the information was + * found to be inconsistent. + */ +#ifndef BCM1250_M3_WAR +#error Check setting of BCM1250_M3_WAR for your platform +#endif + +/* + * This is a DUART workaround related to glitches around register accesses + */ +#ifndef SIBYTE_1956_WAR +#error Check setting of SIBYTE_1956_WAR for your platform +#endif + +/* + * Fill buffers not flushed on CACHE instructions + * + * Hit_Invalidate_I cacheops invalidate an icache line but the refill + * for that line can get stale data from the fill buffer instead of + * accessing memory if the previous icache miss was also to that line. + * + * Workaround: generate an icache refill from a different line + * + * Affects: + * MIPS 4K RTL revision <3.0, PRID revision <4 + */ +#ifndef MIPS4K_ICACHE_REFILL_WAR +#error Check setting of MIPS4K_ICACHE_REFILL_WAR for your platform +#endif + +/* + * Missing implicit forced flush of evictions caused by CACHE + * instruction + * + * Evictions caused by a CACHE instructions are not forced on to the + * bus. The BIU gives higher priority to fetches than to the data from + * the eviction buffer and no collision detection is performed between + * fetches and pending data from the eviction buffer. + * + * Workaround: Execute a SYNC instruction after the cache instruction + * + * Affects: + * MIPS 5Kc,5Kf RTL revision <2.3, PRID revision <8 + * MIPS 20Kc RTL revision <4.0, PRID revision diff --git a/arch/mips/include/asm/xtalk/xtalk.h b/arch/mips/include/asm/xtalk/xtalk.h new file mode 100644 index 00000000000..79bac882a73 --- /dev/null +++ b/arch/mips/include/asm/xtalk/xtalk.h @@ -0,0 +1,52 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * xtalk.h -- platform-independent crosstalk interface, derived from + * IRIX , revision 1.38. + * + * Copyright (C) 1995 - 1997, 1999 Silcon Graphics, Inc. + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + */ +#ifndef _ASM_XTALK_XTALK_H +#define _ASM_XTALK_XTALK_H + +#ifndef __ASSEMBLY__ +/* + * User-level device driver visible types + */ +typedef char xwidgetnum_t; /* xtalk widget number (0..15) */ + +#define XWIDGET_NONE -1 + +typedef int xwidget_part_num_t; /* xtalk widget part number */ + +#define XWIDGET_PART_NUM_NONE -1 + +typedef int xwidget_rev_num_t; /* xtalk widget revision number */ + +#define XWIDGET_REV_NUM_NONE -1 + +typedef int xwidget_mfg_num_t; /* xtalk widget manufacturing ID */ + +#define XWIDGET_MFG_NUM_NONE -1 + +typedef struct xtalk_piomap_s *xtalk_piomap_t; + +/* It is often convenient to fold the XIO target port + * number into the XIO address. + */ +#define XIO_NOWHERE (0xFFFFFFFFFFFFFFFFull) +#define XIO_ADDR_BITS (0x0000FFFFFFFFFFFFull) +#define XIO_PORT_BITS (0xF000000000000000ull) +#define XIO_PORT_SHIFT (60) + +#define XIO_PACKED(x) (((x)&XIO_PORT_BITS) != 0) +#define XIO_ADDR(x) ((x)&XIO_ADDR_BITS) +#define XIO_PORT(x) ((xwidgetnum_t)(((x)&XIO_PORT_BITS) >> XIO_PORT_SHIFT)) +#define XIO_PACK(p, o) ((((uint64_t)(p))<, revision 1.32. + * + * Copyright (C) 1996, 1999 Silcon Graphics, Inc. + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + */ +#ifndef _ASM_XTALK_XWIDGET_H +#define _ASM_XTALK_XWIDGET_H + +#include +#include + +#define WIDGET_ID 0x04 +#define WIDGET_STATUS 0x0c +#define WIDGET_ERR_UPPER_ADDR 0x14 +#define WIDGET_ERR_LOWER_ADDR 0x1c +#define WIDGET_CONTROL 0x24 +#define WIDGET_REQ_TIMEOUT 0x2c +#define WIDGET_INTDEST_UPPER_ADDR 0x34 +#define WIDGET_INTDEST_LOWER_ADDR 0x3c +#define WIDGET_ERR_CMD_WORD 0x44 +#define WIDGET_LLP_CFG 0x4c +#define WIDGET_TFLUSH 0x54 + +/* WIDGET_ID */ +#define WIDGET_REV_NUM 0xf0000000 +#define WIDGET_PART_NUM 0x0ffff000 +#define WIDGET_MFG_NUM 0x00000ffe +#define WIDGET_REV_NUM_SHFT 28 +#define WIDGET_PART_NUM_SHFT 12 +#define WIDGET_MFG_NUM_SHFT 1 + +#define XWIDGET_PART_NUM(widgetid) (((widgetid) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT) +#define XWIDGET_REV_NUM(widgetid) (((widgetid) & WIDGET_REV_NUM) >> WIDGET_REV_NUM_SHFT) +#define XWIDGET_MFG_NUM(widgetid) (((widgetid) & WIDGET_MFG_NUM) >> WIDGET_MFG_NUM_SHFT) + +/* WIDGET_STATUS */ +#define WIDGET_LLP_REC_CNT 0xff000000 +#define WIDGET_LLP_TX_CNT 0x00ff0000 +#define WIDGET_PENDING 0x0000001f + +/* WIDGET_ERR_UPPER_ADDR */ +#define WIDGET_ERR_UPPER_ADDR_ONLY 0x0000ffff + +/* WIDGET_CONTROL */ +#define WIDGET_F_BAD_PKT 0x00010000 +#define WIDGET_LLP_XBAR_CRD 0x0000f000 +#define WIDGET_LLP_XBAR_CRD_SHFT 12 +#define WIDGET_CLR_RLLP_CNT 0x00000800 +#define WIDGET_CLR_TLLP_CNT 0x00000400 +#define WIDGET_SYS_END 0x00000200 +#define WIDGET_MAX_TRANS 0x000001f0 +#define WIDGET_WIDGET_ID 0x0000000f + +/* WIDGET_INTDEST_UPPER_ADDR */ +#define WIDGET_INT_VECTOR 0xff000000 +#define WIDGET_INT_VECTOR_SHFT 24 +#define WIDGET_TARGET_ID 0x000f0000 +#define WIDGET_TARGET_ID_SHFT 16 +#define WIDGET_UPP_ADDR 0x0000ffff + +/* WIDGET_ERR_CMD_WORD */ +#define WIDGET_DIDN 0xf0000000 +#define WIDGET_SIDN 0x0f000000 +#define WIDGET_PACTYP 0x00f00000 +#define WIDGET_TNUM 0x000f8000 +#define WIDGET_COHERENT 0x00004000 +#define WIDGET_DS 0x00003000 +#define WIDGET_GBR 0x00000800 +#define WIDGET_VBPM 0x00000400 +#define WIDGET_ERROR 0x00000200 +#define WIDGET_BARRIER 0x00000100 + +/* WIDGET_LLP_CFG */ +#define WIDGET_LLP_MAXRETRY 0x03ff0000 +#define WIDGET_LLP_MAXRETRY_SHFT 16 +#define WIDGET_LLP_NULLTIMEOUT 0x0000fc00 +#define WIDGET_LLP_NULLTIMEOUT_SHFT 10 +#define WIDGET_LLP_MAXBURST 0x000003ff +#define WIDGET_LLP_MAXBURST_SHFT 0 + +/* + * according to the crosstalk spec, only 32-bits access to the widget + * configuration registers is allowed. some widgets may allow 64-bits + * access but software should not depend on it. registers beyond the + * widget target flush register are widget dependent thus will not be + * defined here + */ +#ifndef __ASSEMBLY__ +typedef u32 widgetreg_t; + +/* widget configuration registers */ +typedef volatile struct widget_cfg { + widgetreg_t w_pad_0; /* 0x00 */ + widgetreg_t w_id; /* 0x04 */ + widgetreg_t w_pad_1; /* 0x08 */ + widgetreg_t w_status; /* 0x0c */ + widgetreg_t w_pad_2; /* 0x10 */ + widgetreg_t w_err_upper_addr; /* 0x14 */ + widgetreg_t w_pad_3; /* 0x18 */ + widgetreg_t w_err_lower_addr; /* 0x1c */ + widgetreg_t w_pad_4; /* 0x20 */ + widgetreg_t w_control; /* 0x24 */ + widgetreg_t w_pad_5; /* 0x28 */ + widgetreg_t w_req_timeout; /* 0x2c */ + widgetreg_t w_pad_6; /* 0x30 */ + widgetreg_t w_intdest_upper_addr; /* 0x34 */ + widgetreg_t w_pad_7; /* 0x38 */ + widgetreg_t w_intdest_lower_addr; /* 0x3c */ + widgetreg_t w_pad_8; /* 0x40 */ + widgetreg_t w_err_cmd_word; /* 0x44 */ + widgetreg_t w_pad_9; /* 0x48 */ + widgetreg_t w_llp_cfg; /* 0x4c */ + widgetreg_t w_pad_10; /* 0x50 */ + widgetreg_t w_tflush; /* 0x54 */ +} widget_cfg_t; + +typedef struct { + unsigned didn:4; + unsigned sidn:4; + unsigned pactyp:4; + unsigned tnum:5; + unsigned ct:1; + unsigned ds:2; + unsigned gbr:1; + unsigned vbpm:1; + unsigned error:1; + unsigned bo:1; + unsigned other:8; +} w_err_cmd_word_f; + +typedef union { + widgetreg_t r; + w_err_cmd_word_f f; +} w_err_cmd_word_u; + +typedef struct xwidget_info_s *xwidget_info_t; + +/* + * Crosstalk Widget Hardware Identification, as defined in the Crosstalk spec. + */ +typedef struct xwidget_hwid_s { + xwidget_part_num_t part_num; + xwidget_rev_num_t rev_num; + xwidget_mfg_num_t mfg_num; +} *xwidget_hwid_t; + + +/* + * Returns 1 if a driver that handles devices described by hwid1 is able + * to manage a device with hardwareid hwid2. NOTE: We don't check rev + * numbers at all. + */ +#define XWIDGET_HARDWARE_ID_MATCH(hwid1, hwid2) \ + (((hwid1)->part_num == (hwid2)->part_num) && \ + (((hwid1)->mfg_num == XWIDGET_MFG_NUM_NONE) || \ + ((hwid2)->mfg_num == XWIDGET_MFG_NUM_NONE) || \ + ((hwid1)->mfg_num == (hwid2)->mfg_num))) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_XTALK_XWIDGET_H */ -- cgit v1.2.3 From d86a8123b11a9a40d850f6e88b89c948c2477da3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:53 +0100 Subject: MIPS: IP checksums: Remove unncessary folding of sum to 16 bit. Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch') diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index edac9892c51..201d82ee4c7 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -276,11 +276,6 @@ LEAF(csum_partial) dsra32 sum, sum, 0 addu sum, v1 #endif - sll v1, sum, 16 - addu sum, v1 - sltu v1, sum, v1 - srl sum, sum, 16 - addu sum, v1 /* odd buffer alignment? */ beqz t7, 1f @@ -678,11 +673,6 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) dsra32 sum, sum, 0 addu sum, v1 #endif - sll v1, sum, 16 - addu sum, v1 - sltu v1, sum, v1 - srl sum, sum, 16 - addu sum, v1 /* odd buffer alignment? */ beqz odd, 1f -- cgit v1.2.3 From 60724ca59eda766a30be57aec6b49bc3e2bead91 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:53 +0100 Subject: MIPS: IP checksums: Remove unncessary .set pseudos They possibly silence meaningful warnings ... Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch') diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 201d82ee4c7..84d5e6a1e76 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -55,20 +55,14 @@ #define UNIT(unit) ((unit)*NBYTES) #define ADDC(sum,reg) \ - .set push; \ - .set noat; \ ADD sum, reg; \ sltu v1, sum, reg; \ ADD sum, v1; \ - .set pop #define ADDC32(sum,reg) \ - .set push; \ - .set noat; \ addu sum, reg; \ sltu v1, sum, reg; \ addu sum, v1; \ - .set pop #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ LOAD _t0, (offset + UNIT(0))(src); \ @@ -267,8 +261,6 @@ LEAF(csum_partial) 1: ADDC(sum, t1) /* fold checksum */ - .set push - .set noat #ifdef USE_DOUBLE dsll32 v1, sum, 0 daddu sum, v1 @@ -284,7 +276,6 @@ LEAF(csum_partial) srl sum, sum, 8 or sum, v1 andi sum, 0xffff - .set pop 1: .set reorder /* Add the passed partial csum. */ @@ -664,8 +655,6 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) ADDC(sum, t2) .Ldone: /* fold checksum */ - .set push - .set noat #ifdef USE_DOUBLE dsll32 v1, sum, 0 daddu sum, v1 @@ -681,7 +670,6 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) srl sum, sum, 8 or sum, v1 andi sum, 0xffff - .set pop 1: .set reorder ADDC32(sum, psum) -- cgit v1.2.3 From b65a75b8c91c0f05047399401407371678fe9549 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:53 +0100 Subject: MIPS: IP checksums: Optimize adjust of sum on buffers of odd alignment. Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 84d5e6a1e76..6b876ca299e 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -270,13 +270,20 @@ LEAF(csum_partial) #endif /* odd buffer alignment? */ - beqz t7, 1f - nop - sll v1, sum, 8 +#ifdef CPU_MIPSR2 + wsbh v1, sum + movn sum, v1, t7 +#else + beqz t7, 1f /* odd buffer alignment? */ + lui v1, 0x00ff + addu v1, 0x00ff + and t0, sum, v1 + sll t0, t0, 8 srl sum, sum, 8 - or sum, v1 - andi sum, 0xffff + and sum, sum, v1 + or sum, sum, t0 1: +#endif .set reorder /* Add the passed partial csum. */ ADDC32(sum, a2) @@ -663,14 +670,20 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) addu sum, v1 #endif - /* odd buffer alignment? */ - beqz odd, 1f - nop - sll v1, sum, 8 +#ifdef CPU_MIPSR2 + wsbh v1, sum + movn sum, v1, odd +#else + beqz odd, 1f /* odd buffer alignment? */ + lui v1, 0x00ff + addu v1, 0x00ff + and t0, sum, v1 + sll t0, t0, 8 srl sum, sum, 8 - or sum, v1 - andi sum, 0xffff + and sum, sum, v1 + or sum, sum, t0 1: +#endif .set reorder ADDC32(sum, psum) jr ra -- cgit v1.2.3 From 2a31b03335e570dce5fdd082e0d71d48b2cb4290 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 28 Aug 2008 15:17:49 +0100 Subject: MIPS: Rewrite spinlocks to ticket locks. Based on patch by Chad Reese of Cavium Networks. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 5 - arch/mips/include/asm/spinlock.h | 253 ++++++++++++++++++++++++--------- arch/mips/include/asm/spinlock_types.h | 7 +- 3 files changed, 188 insertions(+), 77 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c15416c2e89..16097a8f5c5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -610,11 +610,6 @@ source "arch/mips/vr41xx/Kconfig" endmenu -config GENERIC_LOCKBREAK - bool - default y - depends on SMP && PREEMPT - config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h index bb897016c49..5d98a3cb85b 100644 --- a/arch/mips/include/asm/spinlock.h +++ b/arch/mips/include/asm/spinlock.h @@ -9,62 +9,125 @@ #ifndef _ASM_SPINLOCK_H #define _ASM_SPINLOCK_H +#include + #include #include /* * Your basic SMP spinlocks, allowing only a single CPU anywhere + * + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * These are fair FIFO ticket locks + * + * (the type definitions are in asm/spinlock_types.h) */ -#define __raw_spin_is_locked(x) ((x)->lock != 0) -#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) -#define __raw_spin_unlock_wait(x) \ - do { cpu_relax(); } while ((x)->lock) /* - * Simple spin lock operations. There are two variants, one clears IRQ's - * on the local processor, one does not. - * - * We make no fairness assumptions. They have a cost. + * Ticket locks are conceptually two parts, one indicating the current head of + * the queue, and the other indicating the current tail. The lock is acquired + * by atomically noting the tail and incrementing it by one (thus adding + * ourself to the queue and noting our position), then waiting until the head + * becomes equal to the the initial value of the tail. */ +static inline int __raw_spin_is_locked(raw_spinlock_t *lock) +{ + unsigned int counters = ACCESS_ONCE(lock->lock); + + return ((counters >> 14) ^ counters) & 0x1fff; +} + +#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) +#define __raw_spin_unlock_wait(x) \ + while (__raw_spin_is_locked(x)) { cpu_relax(); } + +static inline int __raw_spin_is_contended(raw_spinlock_t *lock) +{ + unsigned int counters = ACCESS_ONCE(lock->lock); + + return (((counters >> 14) - counters) & 0x1fff) > 1; +} + static inline void __raw_spin_lock(raw_spinlock_t *lock) { - unsigned int tmp; + int my_ticket; + int tmp; if (R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set noreorder # __raw_spin_lock \n" - "1: ll %1, %2 \n" - " bnez %1, 1b \n" - " li %1, 1 \n" - " sc %1, %0 \n" - " beqzl %1, 1b \n" + __asm__ __volatile__ ( + " .set push # __raw_spin_lock \n" + " .set noreorder \n" + " \n" + "1: ll %[ticket], %[ticket_ptr] \n" + " addiu %[my_ticket], %[ticket], 0x4000 \n" + " sc %[my_ticket], %[ticket_ptr] \n" + " beqzl %[my_ticket], 1b \n" " nop \n" - " .set reorder \n" - : "=m" (lock->lock), "=&r" (tmp) - : "m" (lock->lock) - : "memory"); + " srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " bne %[ticket], %[my_ticket], 4f \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + "2: \n" + " .subsection 2 \n" + "4: andi %[ticket], %[ticket], 0x1fff \n" + "5: sll %[ticket], 5 \n" + " \n" + "6: bnez %[ticket], 6b \n" + " subu %[ticket], 1 \n" + " \n" + " lw %[ticket], %[ticket_ptr] \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " beq %[ticket], %[my_ticket], 2b \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + " b 5b \n" + " subu %[ticket], %[ticket], 1 \n" + " .previous \n" + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (my_ticket)); } else { - __asm__ __volatile__( - " .set noreorder # __raw_spin_lock \n" - "1: ll %1, %2 \n" - " bnez %1, 2f \n" - " li %1, 1 \n" - " sc %1, %0 \n" - " beqz %1, 2f \n" + __asm__ __volatile__ ( + " .set push # __raw_spin_lock \n" + " .set noreorder \n" + " \n" + " ll %[ticket], %[ticket_ptr] \n" + "1: addiu %[my_ticket], %[ticket], 0x4000 \n" + " sc %[my_ticket], %[ticket_ptr] \n" + " beqz %[my_ticket], 3f \n" " nop \n" + " srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " bne %[ticket], %[my_ticket], 4f \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + "2: \n" " .subsection 2 \n" - "2: ll %1, %2 \n" - " bnez %1, 2b \n" - " li %1, 1 \n" - " b 1b \n" - " nop \n" + "3: b 1b \n" + " ll %[ticket], %[ticket_ptr] \n" + " \n" + "4: andi %[ticket], %[ticket], 0x1fff \n" + "5: sll %[ticket], 5 \n" + " \n" + "6: bnez %[ticket], 6b \n" + " subu %[ticket], 1 \n" + " \n" + " lw %[ticket], %[ticket_ptr] \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " beq %[ticket], %[my_ticket], 2b \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + " b 5b \n" + " subu %[ticket], %[ticket], 1 \n" " .previous \n" - " .set reorder \n" - : "=m" (lock->lock), "=&r" (tmp) - : "m" (lock->lock) - : "memory"); + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (my_ticket)); } smp_llsc_mb(); @@ -72,55 +135,103 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) static inline void __raw_spin_unlock(raw_spinlock_t *lock) { - smp_mb(); + int tmp; - __asm__ __volatile__( - " .set noreorder # __raw_spin_unlock \n" - " sw $0, %0 \n" - " .set\treorder \n" - : "=m" (lock->lock) - : "m" (lock->lock) - : "memory"); + smp_llsc_mb(); + + if (R10000_LLSC_WAR) { + __asm__ __volatile__ ( + " # __raw_spin_unlock \n" + "1: ll %[ticket], %[ticket_ptr] \n" + " addiu %[ticket], %[ticket], 1 \n" + " ori %[ticket], %[ticket], 0x2000 \n" + " xori %[ticket], %[ticket], 0x2000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqzl %[ticket], 2f \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp)); + } else { + __asm__ __volatile__ ( + " .set push # __raw_spin_unlock \n" + " .set noreorder \n" + " \n" + " ll %[ticket], %[ticket_ptr] \n" + "1: addiu %[ticket], %[ticket], 1 \n" + " ori %[ticket], %[ticket], 0x2000 \n" + " xori %[ticket], %[ticket], 0x2000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqz %[ticket], 2f \n" + " nop \n" + " \n" + " .subsection 2 \n" + "2: b 1b \n" + " ll %[ticket], %[ticket_ptr] \n" + " .previous \n" + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp)); + } } static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock) { - unsigned int temp, res; + int tmp, tmp2, tmp3; if (R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set noreorder # __raw_spin_trylock \n" - "1: ll %0, %3 \n" - " ori %2, %0, 1 \n" - " sc %2, %1 \n" - " beqzl %2, 1b \n" - " nop \n" - " andi %2, %0, 1 \n" - " .set reorder" - : "=&r" (temp), "=m" (lock->lock), "=&r" (res) - : "m" (lock->lock) - : "memory"); + __asm__ __volatile__ ( + " .set push # __raw_spin_trylock \n" + " .set noreorder \n" + " \n" + "1: ll %[ticket], %[ticket_ptr] \n" + " srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[now_serving], %[ticket], 0x1fff \n" + " bne %[my_ticket], %[now_serving], 3f \n" + " addiu %[ticket], %[ticket], 0x4000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqzl %[ticket], 1b \n" + " li %[ticket], 1 \n" + "2: \n" + " .subsection 2 \n" + "3: b 2b \n" + " li %[ticket], 0 \n" + " .previous \n" + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (tmp2), + [now_serving] "=&r" (tmp3)); } else { - __asm__ __volatile__( - " .set noreorder # __raw_spin_trylock \n" - "1: ll %0, %3 \n" - " ori %2, %0, 1 \n" - " sc %2, %1 \n" - " beqz %2, 2f \n" - " andi %2, %0, 1 \n" + __asm__ __volatile__ ( + " .set push # __raw_spin_trylock \n" + " .set noreorder \n" + " \n" + " ll %[ticket], %[ticket_ptr] \n" + "1: srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[now_serving], %[ticket], 0x1fff \n" + " bne %[my_ticket], %[now_serving], 3f \n" + " addiu %[ticket], %[ticket], 0x4000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqz %[ticket], 4f \n" + " li %[ticket], 1 \n" + "2: \n" " .subsection 2 \n" - "2: b 1b \n" - " nop \n" + "3: b 2b \n" + " li %[ticket], 0 \n" + "4: b 1b \n" + " ll %[ticket], %[ticket_ptr] \n" " .previous \n" - " .set reorder" - : "=&r" (temp), "=m" (lock->lock), "=&r" (res) - : "m" (lock->lock) - : "memory"); + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (tmp2), + [now_serving] "=&r" (tmp3)); } smp_llsc_mb(); - return res == 0; + return tmp; } /* diff --git a/arch/mips/include/asm/spinlock_types.h b/arch/mips/include/asm/spinlock_types.h index ce26c5048b1..adeedaa116c 100644 --- a/arch/mips/include/asm/spinlock_types.h +++ b/arch/mips/include/asm/spinlock_types.h @@ -6,7 +6,12 @@ #endif typedef struct { - volatile unsigned int lock; + /* + * bits 0..13: serving_now + * bits 14 : junk data + * bits 15..28: ticket + */ + unsigned int lock; } raw_spinlock_t; #define __RAW_SPIN_LOCK_UNLOCKED { 0 } -- cgit v1.2.3 From 4bacc68766b11c191ee1567f54103f109c002f4f Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 18 Sep 2008 00:13:58 +0900 Subject: MIPS: TXx9: Add TX4939 ATA support (v2) Add a helper routine to register tx4939ide driver and use it on RBTX4939 board. Signed-off-by: Atsushi Nemoto Acked-by: Sergei Shtylyov Signed-off-by: Ralf Baechle --- arch/mips/include/asm/txx9/tx4939.h | 1 + arch/mips/txx9/generic/setup_tx4939.c | 46 +++++++++++++++++++++++++++++++++++ arch/mips/txx9/rbtx4939/setup.c | 1 + 3 files changed, 48 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h index 7ce2dff3b7c..88badb42301 100644 --- a/arch/mips/include/asm/txx9/tx4939.h +++ b/arch/mips/include/asm/txx9/tx4939.h @@ -540,5 +540,6 @@ void tx4939_setup_pcierr_irq(void); void tx4939_irq_init(void); int tx4939_irq(void); void tx4939_mtd_init(int ch); +void tx4939_ata_init(void); #endif /* __ASM_TXX9_TX4939_H */ diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index f14a497077d..6c0049a5bbc 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -389,6 +390,51 @@ void __init tx4939_mtd_init(int ch) txx9_physmap_flash_init(ch, start, size, &pdata); } +#define TX4939_ATA_REG_PHYS(ch) (TX4939_ATA_REG(ch) & 0xfffffffffULL) +void __init tx4939_ata_init(void) +{ + static struct resource ata0_res[] = { + { + .start = TX4939_ATA_REG_PHYS(0), + .end = TX4939_ATA_REG_PHYS(0) + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = TXX9_IRQ_BASE + TX4939_IR_ATA(0), + .flags = IORESOURCE_IRQ, + }, + }; + static struct resource ata1_res[] = { + { + .start = TX4939_ATA_REG_PHYS(1), + .end = TX4939_ATA_REG_PHYS(1) + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = TXX9_IRQ_BASE + TX4939_IR_ATA(1), + .flags = IORESOURCE_IRQ, + }, + }; + static struct platform_device ata0_dev = { + .name = "tx4939ide", + .id = 0, + .num_resources = ARRAY_SIZE(ata0_res), + .resource = ata0_res, + }; + static struct platform_device ata1_dev = { + .name = "tx4939ide", + .id = 1, + .num_resources = ARRAY_SIZE(ata1_res), + .resource = ata1_res, + }; + __u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); + + if (pcfg & TX4939_PCFG_ATA0MODE) + platform_device_register(&ata0_dev); + if ((pcfg & (TX4939_PCFG_ATA1MODE | + TX4939_PCFG_ET1MODE | + TX4939_PCFG_ET0MODE)) == TX4939_PCFG_ATA1MODE) + platform_device_register(&ata1_dev); +} + static void __init tx4939_stop_unused_modules(void) { __u64 pcfg, rst = 0, ckd = 0; diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c index 277864d5e77..9855d7bccc2 100644 --- a/arch/mips/txx9/rbtx4939/setup.c +++ b/arch/mips/txx9/rbtx4939/setup.c @@ -264,6 +264,7 @@ static void __init rbtx4939_device_init(void) #endif rbtx4939_led_setup(); tx4939_wdt_init(); + tx4939_ata_init(); } static void __init rbtx4939_setup(void) -- cgit v1.2.3 From 71ec6ccfdc2706e767189d40016fc802305067bb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 02:52:56 +0000 Subject: MIPS: Replace use of with native implementations. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/uaccess.h | 264 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 263 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index b895144d577..09ff5bb1744 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -13,7 +13,6 @@ #include #include #include -#include /* * The fs value determines whether argument validity checking should be @@ -373,6 +372,269 @@ do { \ extern void __put_user_unknown(void); +/* + * put_user_unaligned: - Write a simple value into user space. + * @x: Value to copy to user space. + * @ptr: Destination address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple value from kernel space to user + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and @x must be assignable + * to the result of dereferencing @ptr. + * + * Returns zero on success, or -EFAULT on error. + */ +#define put_user_unaligned(x,ptr) \ + __put_user_unaligned_check((x),(ptr),sizeof(*(ptr))) + +/* + * get_user_unaligned: - Get a simple variable from user space. + * @x: Variable to store result. + * @ptr: Source address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple variable from user space to kernel + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and the result of + * dereferencing @ptr must be assignable to @x without a cast. + * + * Returns zero on success, or -EFAULT on error. + * On error, the variable @x is set to zero. + */ +#define get_user_unaligned(x,ptr) \ + __get_user_unaligned_check((x),(ptr),sizeof(*(ptr))) + +/* + * __put_user_unaligned: - Write a simple value into user space, with less checking. + * @x: Value to copy to user space. + * @ptr: Destination address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple value from kernel space to user + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and @x must be assignable + * to the result of dereferencing @ptr. + * + * Caller must check the pointer with access_ok() before calling this + * function. + * + * Returns zero on success, or -EFAULT on error. + */ +#define __put_user_unaligned(x,ptr) \ + __put_user_unaligned_nocheck((x),(ptr),sizeof(*(ptr))) + +/* + * __get_user_unaligned: - Get a simple variable from user space, with less checking. + * @x: Variable to store result. + * @ptr: Source address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple variable from user space to kernel + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and the result of + * dereferencing @ptr must be assignable to @x without a cast. + * + * Caller must check the pointer with access_ok() before calling this + * function. + * + * Returns zero on success, or -EFAULT on error. + * On error, the variable @x is set to zero. + */ +#define __get_user_unaligned(x,ptr) \ + __get_user__unalignednocheck((x),(ptr),sizeof(*(ptr))) + +/* + * Yuck. We need two variants, one for 64bit operation and one + * for 32 bit mode and old iron. + */ +#ifdef CONFIG_32BIT +#define __GET_USER_UNALIGNED_DW(val, ptr) \ + __get_user_unaligned_asm_ll32(val, ptr) +#endif +#ifdef CONFIG_64BIT +#define __GET_USER_UNALIGNED_DW(val, ptr) \ + __get_user_unaligned_asm(val, "uld", ptr) +#endif + +extern void __get_user_unaligned_unknown(void); + +#define __get_user_unaligned_common(val, size, ptr) \ +do { \ + switch (size) { \ + case 1: __get_user_asm(val, "lb", ptr); break; \ + case 2: __get_user_unaligned_asm(val, "ulh", ptr); break; \ + case 4: __get_user_unaligned_asm(val, "ulw", ptr); break; \ + case 8: __GET_USER_UNALIGNED_DW(val, ptr); break; \ + default: __get_user_unaligned_unknown(); break; \ + } \ +} while (0) + +#define __get_user_unaligned_nocheck(x,ptr,size) \ +({ \ + int __gu_err; \ + \ + __get_user_unaligned_common((x), size, ptr); \ + __gu_err; \ +}) + +#define __get_user_unaligned_check(x,ptr,size) \ +({ \ + int __gu_err = -EFAULT; \ + const __typeof__(*(ptr)) __user * __gu_ptr = (ptr); \ + \ + if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \ + __get_user_unaligned_common((x), size, __gu_ptr); \ + \ + __gu_err; \ +}) + +#define __get_user_unaligned_asm(val, insn, addr) \ +{ \ + long __gu_tmp; \ + \ + __asm__ __volatile__( \ + "1: " insn " %1, %3 \n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + "3: li %0, %4 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " "__UA_ADDR "\t1b, 3b \n" \ + " "__UA_ADDR "\t1b + 4, 3b \n" \ + " .previous \n" \ + : "=r" (__gu_err), "=r" (__gu_tmp) \ + : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \ + \ + (val) = (__typeof__(*(addr))) __gu_tmp; \ +} + +/* + * Get a long long 64 using 32 bit registers. + */ +#define __get_user_unaligned_asm_ll32(val, addr) \ +{ \ + unsigned long long __gu_tmp; \ + \ + __asm__ __volatile__( \ + "1: ulw %1, (%3) \n" \ + "2: ulw %D1, 4(%3) \n" \ + " move %0, $0 \n" \ + "3: .section .fixup,\"ax\" \n" \ + "4: li %0, %4 \n" \ + " move %1, $0 \n" \ + " move %D1, $0 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 4b \n" \ + " " __UA_ADDR " 1b + 4, 4b \n" \ + " " __UA_ADDR " 2b, 4b \n" \ + " " __UA_ADDR " 2b + 4, 4b \n" \ + " .previous \n" \ + : "=r" (__gu_err), "=&r" (__gu_tmp) \ + : "0" (0), "r" (addr), "i" (-EFAULT)); \ + (val) = (__typeof__(*(addr))) __gu_tmp; \ +} + +/* + * Yuck. We need two variants, one for 64bit operation and one + * for 32 bit mode and old iron. + */ +#ifdef CONFIG_32BIT +#define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm_ll32(ptr) +#endif +#ifdef CONFIG_64BIT +#define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm("usd", ptr) +#endif + +#define __put_user_unaligned_nocheck(x,ptr,size) \ +({ \ + __typeof__(*(ptr)) __pu_val; \ + int __pu_err = 0; \ + \ + __pu_val = (x); \ + switch (size) { \ + case 1: __put_user_asm("sb", ptr); break; \ + case 2: __put_user_unaligned_asm("ush", ptr); break; \ + case 4: __put_user_unaligned_asm("usw", ptr); break; \ + case 8: __PUT_USER_UNALIGNED_DW(ptr); break; \ + default: __put_user_unaligned_unknown(); break; \ + } \ + __pu_err; \ +}) + +#define __put_user_unaligned_check(x,ptr,size) \ +({ \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + int __pu_err = -EFAULT; \ + \ + if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \ + switch (size) { \ + case 1: __put_user_asm("sb", __pu_addr); break; \ + case 2: __put_user_unaligned_asm("ush", __pu_addr); break; \ + case 4: __put_user_unaligned_asm("usw", __pu_addr); break; \ + case 8: __PUT_USER_UNALGINED_DW(__pu_addr); break; \ + default: __put_user_unaligned_unknown(); break; \ + } \ + } \ + __pu_err; \ +}) + +#define __put_user_unaligned_asm(insn, ptr) \ +{ \ + __asm__ __volatile__( \ + "1: " insn " %z2, %3 # __put_user_unaligned_asm\n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + "3: li %0, %4 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 3b \n" \ + " .previous \n" \ + : "=r" (__pu_err) \ + : "0" (0), "Jr" (__pu_val), "o" (__m(ptr)), \ + "i" (-EFAULT)); \ +} + +#define __put_user_unaligned_asm_ll32(ptr) \ +{ \ + __asm__ __volatile__( \ + "1: sw %2, (%3) # __put_user_unaligned_asm_ll32 \n" \ + "2: sw %D2, 4(%3) \n" \ + "3: \n" \ + " .section .fixup,\"ax\" \n" \ + "4: li %0, %4 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 4b \n" \ + " " __UA_ADDR " 1b + 4, 4b \n" \ + " " __UA_ADDR " 2b, 4b \n" \ + " " __UA_ADDR " 2b + 4, 4b \n" \ + " .previous" \ + : "=r" (__pu_err) \ + : "0" (0), "r" (__pu_val), "r" (ptr), \ + "i" (-EFAULT)); \ +} + +extern void __put_user_unaligned_unknown(void); + /* * We're generating jump to subroutines which will be outside the range of * jump instructions -- cgit v1.2.3 From 8192c9ea9ac44213d1266ecb64615519443979b3 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:04:26 -0700 Subject: MIPS: Add HARDWARE_WATCHPOINTS configure option. This is automatically set for all MIPS32 and MIPS64 processors. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 16097a8f5c5..cd5fbf6f078 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1268,6 +1268,13 @@ config CPU_SUPPORTS_32BIT_KERNEL config CPU_SUPPORTS_64BIT_KERNEL bool +# +# Set to y for ptrace access to watch registers. +# +config HARDWARE_WATCHPOINTS + bool + default y if CPU_MIPS32 || CPU_MIPS64 + menu "Kernel type" choice -- cgit v1.2.3 From 6aa3524c182c01b8b8b7c21c4da20c742a9b4d86 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:05:54 -0700 Subject: MIPS: Add HARDWARE_WATCHPOINTS definitions and support code. This is the main support code for the patch. Here we just add the code, the following patches hook it up. Signed-off-by: David Daney Signed-off-by: Ralf Baechle create mode 100644 arch/mips/include/asm/watch.h create mode 100644 arch/mips/kernel/watch.c --- arch/mips/include/asm/cpu-info.h | 6 ++ arch/mips/include/asm/processor.h | 20 ++++ arch/mips/include/asm/thread_info.h | 2 + arch/mips/include/asm/watch.h | 32 ++++++ arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/watch.c | 188 ++++++++++++++++++++++++++++++++++++ 6 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 arch/mips/include/asm/watch.h create mode 100644 arch/mips/kernel/watch.c (limited to 'arch') diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 2de73dbb2e9..744cd8fb107 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -12,6 +12,8 @@ #ifndef __ASM_CPU_INFO_H #define __ASM_CPU_INFO_H +#include + #include /* @@ -69,6 +71,10 @@ struct cpuinfo_mips { int tc_id; /* Thread Context number */ #endif void *data; /* Additional data */ + unsigned int watch_reg_count; /* Number that exist */ + unsigned int watch_reg_use_cnt; /* Usable by ptrace */ +#define NUM_WATCH_REGS 4 + u16 watch_reg_masks[NUM_WATCH_REGS]; } __attribute__((aligned(SMP_CACHE_BYTES))); extern struct cpuinfo_mips cpu_data[]; diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index a1e4453469f..18ee58e3944 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -105,6 +105,19 @@ struct mips_dsp_state { {0,} \ } +struct mips3264_watch_reg_state { + /* The width of watchlo is 32 in a 32 bit kernel and 64 in a + 64 bit kernel. We use unsigned long as it has the same + property. */ + unsigned long watchlo[NUM_WATCH_REGS]; + /* Only the mask and IRW bits from watchhi. */ + u16 watchhi[NUM_WATCH_REGS]; +}; + +union mips_watch_reg_state { + struct mips3264_watch_reg_state mips3264; +}; + typedef struct { unsigned long seg; } mm_segment_t; @@ -137,6 +150,9 @@ struct thread_struct { /* Saved state of the DSP ASE, if available. */ struct mips_dsp_state dsp; + /* Saved watch register state, if available. */ + union mips_watch_reg_state watch; + /* Other stuff associated with the thread. */ unsigned long cp0_badvaddr; /* Last user fault */ unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ @@ -192,6 +208,10 @@ struct thread_struct { .dspr = {0, }, \ .dspcontrol = 0, \ }, \ + /* \ + * saved watch register stuff \ + */ \ + .watch = {{{0,},},}, \ /* \ * Other stuff associated with the process \ */ \ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index bb3060699df..3f76de73c94 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -124,6 +124,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */ #define TIF_32BIT_ADDR 23 /* 32-bit address space (o32/n32) */ #define TIF_FPUBOUND 24 /* thread bound to FPU-full CPU set */ +#define TIF_LOAD_WATCH 25 /* If set, load watch registers */ #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ #define _TIF_SYSCALL_TRACE (1< + +#include + +void mips_install_watch_registers(void); +void mips_read_watch_registers(void); +void mips_clear_watch_registers(void); +void mips_probe_watch_registers(struct cpuinfo_mips *c); + +#ifdef CONFIG_HARDWARE_WATCHPOINTS +#define __restore_watch() do { \ + if (unlikely(test_bit(TIF_LOAD_WATCH, \ + ¤t_thread_info()->flags))) { \ + mips_install_watch_registers(); \ + } \ +} while (0) + +#else +#define __restore_watch() do {} while (0) +#endif + +#endif /* _ASM_WATCH_H */ diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 25775cb5400..d9da7112aaf 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ ptrace.o reset.o setup.o signal.o syscall.o \ - time.o topology.o traps.o unaligned.o + time.o topology.o traps.o unaligned.o watch.o obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c new file mode 100644 index 00000000000..c1540696803 --- /dev/null +++ b/arch/mips/kernel/watch.c @@ -0,0 +1,188 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2008 David Daney + */ + +#include + +#include +#include + +/* + * Install the watch registers for the current thread. A maximum of + * four registers are installed although the machine may have more. + */ +void mips_install_watch_registers(void) +{ + struct mips3264_watch_reg_state *watches = + ¤t->thread.watch.mips3264; + switch (current_cpu_data.watch_reg_use_cnt) { + default: + BUG(); + case 4: + write_c0_watchlo3(watches->watchlo[3]); + /* Write 1 to the I, R, and W bits to clear them, and + 1 to G so all ASIDs are trapped. */ + write_c0_watchhi3(0x40000007 | watches->watchhi[3]); + case 3: + write_c0_watchlo2(watches->watchlo[2]); + write_c0_watchhi2(0x40000007 | watches->watchhi[2]); + case 2: + write_c0_watchlo1(watches->watchlo[1]); + write_c0_watchhi1(0x40000007 | watches->watchhi[1]); + case 1: + write_c0_watchlo0(watches->watchlo[0]); + write_c0_watchhi0(0x40000007 | watches->watchhi[0]); + } +} + +/* + * Read back the watchhi registers so the user space debugger has + * access to the I, R, and W bits. A maximum of four registers are + * read although the machine may have more. + */ +void mips_read_watch_registers(void) +{ + struct mips3264_watch_reg_state *watches = + ¤t->thread.watch.mips3264; + switch (current_cpu_data.watch_reg_use_cnt) { + default: + BUG(); + case 4: + watches->watchhi[3] = (read_c0_watchhi3() & 0x0fff); + case 3: + watches->watchhi[2] = (read_c0_watchhi2() & 0x0fff); + case 2: + watches->watchhi[1] = (read_c0_watchhi1() & 0x0fff); + case 1: + watches->watchhi[0] = (read_c0_watchhi0() & 0x0fff); + } + if (current_cpu_data.watch_reg_use_cnt == 1 && + (watches->watchhi[0] & 7) == 0) { + /* Pathological case of release 1 architecture that + * doesn't set the condition bits. We assume that + * since we got here, the watch condition was met and + * signal that the conditions requested in watchlo + * were met. */ + watches->watchhi[0] |= (watches->watchlo[0] & 7); + } + } + +/* + * Disable all watch registers. Although only four registers are + * installed, all are cleared to eliminate the possibility of endless + * looping in the watch handler. + */ +void mips_clear_watch_registers(void) +{ + switch (current_cpu_data.watch_reg_count) { + default: + BUG(); + case 8: + write_c0_watchlo7(0); + case 7: + write_c0_watchlo6(0); + case 6: + write_c0_watchlo5(0); + case 5: + write_c0_watchlo4(0); + case 4: + write_c0_watchlo3(0); + case 3: + write_c0_watchlo2(0); + case 2: + write_c0_watchlo1(0); + case 1: + write_c0_watchlo0(0); + } +} + +__cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) +{ + unsigned int t; + + if ((c->options & MIPS_CPU_WATCH) == 0) + return; + /* + * Check which of the I,R and W bits are supported, then + * disable the register. + */ + write_c0_watchlo0(7); + t = read_c0_watchlo0(); + write_c0_watchlo0(0); + c->watch_reg_masks[0] = t & 7; + + /* Write the mask bits and read them back to determine which + * can be used. */ + c->watch_reg_count = 1; + c->watch_reg_use_cnt = 1; + t = read_c0_watchhi0(); + write_c0_watchhi0(t | 0xff8); + t = read_c0_watchhi0(); + c->watch_reg_masks[0] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + write_c0_watchlo1(7); + t = read_c0_watchlo1(); + write_c0_watchlo1(0); + c->watch_reg_masks[1] = t & 7; + + c->watch_reg_count = 2; + c->watch_reg_use_cnt = 2; + t = read_c0_watchhi1(); + write_c0_watchhi1(t | 0xff8); + t = read_c0_watchhi1(); + c->watch_reg_masks[1] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + write_c0_watchlo2(7); + t = read_c0_watchlo2(); + write_c0_watchlo2(0); + c->watch_reg_masks[2] = t & 7; + + c->watch_reg_count = 3; + c->watch_reg_use_cnt = 3; + t = read_c0_watchhi2(); + write_c0_watchhi2(t | 0xff8); + t = read_c0_watchhi2(); + c->watch_reg_masks[2] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + write_c0_watchlo3(7); + t = read_c0_watchlo3(); + write_c0_watchlo3(0); + c->watch_reg_masks[3] = t & 7; + + c->watch_reg_count = 4; + c->watch_reg_use_cnt = 4; + t = read_c0_watchhi3(); + write_c0_watchhi3(t | 0xff8); + t = read_c0_watchhi3(); + c->watch_reg_masks[3] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + /* We use at most 4, but probe and report up to 8. */ + c->watch_reg_count = 5; + t = read_c0_watchhi4(); + if ((t & 0x80000000) == 0) + return; + + c->watch_reg_count = 6; + t = read_c0_watchhi5(); + if ((t & 0x80000000) == 0) + return; + + c->watch_reg_count = 7; + t = read_c0_watchhi6(); + if ((t & 0x80000000) == 0) + return; + + c->watch_reg_count = 8; +} -- cgit v1.2.3 From 654f57bfb467996fb730eae96dc30ea4de989fdc Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:07:16 -0700 Subject: MIPS: Probe watch registers and report configuration. Probe for watch register characteristics, and report them in /proc/cpuinfo. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 2 ++ arch/mips/kernel/proc.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e621fda8ab3..0cf15457eca 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, @@ -677,6 +678,7 @@ static inline void spram_config(void) {} static inline void cpu_probe_mips(struct cpuinfo_mips *c) { decode_configs(c); + mips_probe_watch_registers(c); switch (c->processor_id & 0xff00) { case PRID_IMP_4KC: c->cputype = CPU_4KC; diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 36f06539824..75bb1300dd7 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -23,6 +23,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) unsigned int version = cpu_data[n].processor_id; unsigned int fp_vers = cpu_data[n].fpu_id; char fmt [64]; + int i; #ifdef CONFIG_SMP if (!cpu_isset(n, cpu_online_map)) @@ -50,8 +51,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize); seq_printf(m, "extra interrupt vector\t: %s\n", cpu_has_divec ? "yes" : "no"); - seq_printf(m, "hardware watchpoint\t: %s\n", - cpu_has_watch ? "yes" : "no"); + seq_printf(m, "hardware watchpoint\t: %s", + cpu_has_watch ? "yes, " : "no\n"); + if (cpu_has_watch) { + seq_printf(m, "count: %d, address/irw mask: [", + cpu_data[n].watch_reg_count); + for (i = 0; i < cpu_data[n].watch_reg_count; i++) + seq_printf(m, "%s0x%04x", i ? ", " : "" , + cpu_data[n].watch_reg_masks[i]); + seq_printf(m, "]\n"); + } seq_printf(m, "ASEs implemented\t:%s%s%s%s%s%s\n", cpu_has_mips16 ? " mips16" : "", cpu_has_mdmx ? " mdmx" : "", -- cgit v1.2.3 From b67b2b703047bfaf62687ca64c9486599b609ef0 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:08:45 -0700 Subject: MIPS: Watch exception handling for HARDWARE_WATCHPOINTS. Here we hook up the watch exception handler so that it sends SIGTRAP when the hardware watch registers are triggered. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/kernel/genex.S | 4 ++++ arch/mips/kernel/traps.c | 24 +++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 01dcbe38fa0..757d48f0d80 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -453,7 +453,11 @@ NESTED(nmi_handler, PT_SIZE, sp) BUILD_HANDLER tr tr sti silent /* #13 */ BUILD_HANDLER fpe fpe fpe silent /* #15 */ BUILD_HANDLER mdmx mdmx sti silent /* #22 */ +#ifdef CONFIG_HARDWARE_WATCHPOINTS + BUILD_HANDLER watch watch sti silent /* #23 */ +#else BUILD_HANDLER watch watch sti verbose /* #23 */ +#endif BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ BUILD_HANDLER mt mt sti silent /* #25 */ BUILD_HANDLER dsp dsp sti silent /* #26 */ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b602ac6eb47..80b9e070c20 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -912,13 +913,26 @@ asmlinkage void do_mdmx(struct pt_regs *regs) asmlinkage void do_watch(struct pt_regs *regs) { + u32 cause; + /* - * We use the watch exception where available to detect stack - * overflows. + * Clear WP (bit 22) bit of cause register so we don't loop + * forever. */ - dump_tlb_all(); - show_regs(regs); - panic("Caught WATCH exception - probably caused by stack overflow."); + cause = read_c0_cause(); + cause &= ~(1 << 22); + write_c0_cause(cause); + + /* + * If the current thread has the watch registers loaded, save + * their values and send SIGTRAP. Otherwise another thread + * left the registers set, clear them and continue. + */ + if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { + mips_read_watch_registers(); + force_sig(SIGTRAP, current); + } else + mips_clear_watch_registers(); } asmlinkage void do_mcheck(struct pt_regs *regs) -- cgit v1.2.3 From 2c708cbaa6031b73be6b992adb3ec1811f91cdb1 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:09:51 -0700 Subject: MIPS: Scheduler support for HARDWARE_WATCHPOINTS. Here we hook up the scheduler. Whenever we switch to a new process, we check to see if the watch registers should be installed, and do it if needed. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/include/asm/system.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h index a944eda4faf..cd30f83235b 100644 --- a/arch/mips/include/asm/system.h +++ b/arch/mips/include/asm/system.h @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -76,6 +77,7 @@ do { \ __restore_dsp(current); \ if (cpu_has_userlocal) \ write_c0_userlocal(current_thread_info()->tp_value); \ + __restore_watch(); \ } while (0) static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) -- cgit v1.2.3 From 0926bf953ee79b8f139741b442e5a18520f81705 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:11:26 -0700 Subject: MIPS: Ptrace support for HARDWARE_WATCHPOINTS This is the final part of the watch register patch. Here we hook up ptrace so that the user space debugger (gdb), can set and read the registers. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/include/asm/ptrace.h | 46 +++++++++++++++++++ arch/mips/kernel/ptrace.c | 100 ++++++++++++++++++++++++++++++++++++++++- arch/mips/kernel/ptrace32.c | 10 +++++ 3 files changed, 155 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index c00cca24dae..cd5e8a47812 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -74,11 +74,57 @@ struct pt_regs { #define PTRACE_POKEDATA_3264 0xc3 #define PTRACE_GET_THREAD_AREA_3264 0xc4 +/* Read and write watchpoint registers. */ +enum pt_watch_style { + pt_watch_style_mips32, + pt_watch_style_mips64 +}; +struct mips32_watch_regs { + uint32_t watchlo[8]; + /* Lower 16 bits of watchhi. */ + uint16_t watchhi[8]; + /* Valid mask and I R W bits. + * bit 0 -- 1 if W bit is usable. + * bit 1 -- 1 if R bit is usable. + * bit 2 -- 1 if I bit is usable. + * bits 3 - 11 -- Valid watchhi mask bits. + */ + uint16_t watch_masks[8]; + /* The number of valid watch register pairs. */ + uint32_t num_valid; +} __attribute__((aligned(8))); + +struct mips64_watch_regs { + uint64_t watchlo[8]; + uint16_t watchhi[8]; + uint16_t watch_masks[8]; + uint32_t num_valid; +} __attribute__((aligned(8))); + +struct pt_watch_regs { + enum pt_watch_style style; + union { + struct mips32_watch_regs mips32; + struct mips32_watch_regs mips64; + }; +}; + +#define PTRACE_GET_WATCH_REGS 0xd0 +#define PTRACE_SET_WATCH_REGS 0xd1 + #ifdef __KERNEL__ +#include #include #include +struct task_struct; + +extern int ptrace_get_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr); +extern int ptrace_set_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr); + /* * Does the process account for user or for system time? */ diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 96ffc9c6d19..054861ccb4d 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -46,7 +46,8 @@ */ void ptrace_disable(struct task_struct *child) { - /* Nothing to do.. */ + /* Don't load the watchpoint registers for the ex-child. */ + clear_tsk_thread_flag(child, TIF_LOAD_WATCH); } /* @@ -167,6 +168,93 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) return 0; } +int ptrace_get_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr) +{ + enum pt_watch_style style; + int i; + + if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + return -EIO; + if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs))) + return -EIO; + +#ifdef CONFIG_32BIT + style = pt_watch_style_mips32; +#define WATCH_STYLE mips32 +#else + style = pt_watch_style_mips64; +#define WATCH_STYLE mips64 +#endif + + __put_user(style, &addr->style); + __put_user(current_cpu_data.watch_reg_use_cnt, + &addr->WATCH_STYLE.num_valid); + for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + __put_user(child->thread.watch.mips3264.watchlo[i], + &addr->WATCH_STYLE.watchlo[i]); + __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff, + &addr->WATCH_STYLE.watchhi[i]); + __put_user(current_cpu_data.watch_reg_masks[i], + &addr->WATCH_STYLE.watch_masks[i]); + } + for (; i < 8; i++) { + __put_user(0, &addr->WATCH_STYLE.watchlo[i]); + __put_user(0, &addr->WATCH_STYLE.watchhi[i]); + __put_user(0, &addr->WATCH_STYLE.watch_masks[i]); + } + + return 0; +} + +int ptrace_set_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr) +{ + int i; + int watch_active = 0; + unsigned long lt[NUM_WATCH_REGS]; + u16 ht[NUM_WATCH_REGS]; + + if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + return -EIO; + if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs))) + return -EIO; + /* Check the values. */ + for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]); +#ifdef CONFIG_32BIT + if (lt[i] & __UA_LIMIT) + return -EINVAL; +#else + if (test_tsk_thread_flag(child, TIF_32BIT_ADDR)) { + if (lt[i] & 0xffffffff80000000UL) + return -EINVAL; + } else { + if (lt[i] & __UA_LIMIT) + return -EINVAL; + } +#endif + __get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]); + if (ht[i] & ~0xff8) + return -EINVAL; + } + /* Install them. */ + for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + if (lt[i] & 7) + watch_active = 1; + child->thread.watch.mips3264.watchlo[i] = lt[i]; + /* Set the G bit. */ + child->thread.watch.mips3264.watchhi[i] = ht[i]; + } + + if (watch_active) + set_tsk_thread_flag(child, TIF_LOAD_WATCH); + else + clear_tsk_thread_flag(child, TIF_LOAD_WATCH); + + return 0; +} + long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; @@ -440,6 +528,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) (unsigned long __user *) data); break; + case PTRACE_GET_WATCH_REGS: + ret = ptrace_get_watch_regs(child, + (struct pt_watch_regs __user *) addr); + break; + + case PTRACE_SET_WATCH_REGS: + ret = ptrace_set_watch_regs(child, + (struct pt_watch_regs __user *) addr); + break; + default: ret = ptrace_request(child, request, addr, data); break; diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index cac56a8c867..e45105e3ef0 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -387,6 +387,16 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, (unsigned long __user *) (unsigned long) data); break; + case PTRACE_GET_WATCH_REGS: + ret = ptrace_get_watch_regs(child, + (struct pt_watch_regs __user *) (unsigned long) addr); + break; + + case PTRACE_SET_WATCH_REGS: + ret = ptrace_set_watch_regs(child, + (struct pt_watch_regs __user *) (unsigned long) addr); + break; + default: ret = ptrace_request(child, request, addr, data); break; -- cgit v1.2.3 From d302d05cf4d25f4fbbec0f9338fac13ee0c0ad89 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:57 +0100 Subject: MIPS: Move ptrace prototypes to ptrace.h Signed-off-by: Ralf Baechle --- arch/mips/include/asm/ptrace.h | 6 ++++++ arch/mips/kernel/ptrace32.c | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index cd5e8a47812..9c22571b160 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -120,6 +120,12 @@ struct pt_watch_regs { struct task_struct; +extern int ptrace_getregs(struct task_struct *child, __s64 __user *data); +extern int ptrace_setregs(struct task_struct *child, __s64 __user *data); + +extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data); +extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data); + extern int ptrace_get_watch_regs(struct task_struct *child, struct pt_watch_regs __user *addr); extern int ptrace_set_watch_regs(struct task_struct *child, diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index e45105e3ef0..1ca34104e59 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -37,12 +37,6 @@ #include #include -int ptrace_getregs(struct task_struct *child, __s64 __user *data); -int ptrace_setregs(struct task_struct *child, __s64 __user *data); - -int ptrace_getfpregs(struct task_struct *child, __u32 __user *data); -int ptrace_setfpregs(struct task_struct *child, __u32 __user *data); - /* * Tracing a 32-bit process with a 64-bit strace and vice versa will not * work. I don't know how to fix this. -- cgit v1.2.3 From 9609e74093abd9f61fb1d20a8915a8ea87c77d5a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 11 Sep 2008 17:48:00 +0200 Subject: MIPS: RB532: provide GPIO_BUILTIN_NR and irq_to_gpio/gpio_to_irq This patchs defines the number of built-in the GPIOs present on the SoC as Documentation/gpio.txt recommends to do. Define irq_to_gpio/gpio_to_irq to return the right values so that it fixes a compilation error on drivers/gpio/gpiolib.c when enabling debugfs. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-rc32434/gpio.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h index 3a70b41cd7a..c8e554eafce 100644 --- a/arch/mips/include/asm/mach-rc32434/gpio.h +++ b/arch/mips/include/asm/mach-rc32434/gpio.h @@ -14,16 +14,16 @@ #define _RC32434_GPIO_H_ #include +#include -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value - -#define gpio_cansleep __gpio_cansleep +#define NR_BUILTIN_GPIO 32 -#define gpio_to_irq(gpio) IRQ_GPIO(gpio) -#define irq_to_gpio(irq) IRQ_TO_GPIO(irq) +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep -#include +#define gpio_to_irq(gpio) (8 + 4 * 32 + gpio) +#define irq_to_gpio(irq) (irq - (8 + 4 * 32)) struct rb532_gpio_reg { u32 gpiofunc; /* GPIO Function Register -- cgit v1.2.3 From e1e23bb0513520035ec934fa3483507cb6648b7c Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 7 Oct 2008 14:15:11 -0700 Subject: x86: avoid dereferencing beyond stack + THREAD_SIZE It's possible for get_wchan() to dereference past task->stack + THREAD_SIZE while iterating through instruction pointers if fp equals the upper boundary, causing a kernel panic. Signed-off-by: David Rientjes Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 2a8ccb9238b..b6b508ea711 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -754,12 +754,12 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); - if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) + if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); do { if (fp < (unsigned long)stack || - fp > (unsigned long)stack+THREAD_SIZE) + fp >= (unsigned long)stack+THREAD_SIZE) return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) -- cgit v1.2.3 From c613ec1a7ff3714da11c7c48a13bab03beb5c376 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 10 Oct 2008 10:46:45 +0100 Subject: x86, early_ioremap: fix fencepost error The x86 implementation of early_ioremap has an off by one error. If we get an object which ends on the first byte of a page we undermap by one page and this causes a crash on boot with the ASUS P5QL whose DMI table happens to fit this alignment. The size computation is currently last_addr = phys_addr + size - 1; npages = (PAGE_ALIGN(last_addr) - phys_addr) (Consider a request for 1 byte at alignment 0...) Closes #11693 Debugging work by Ian Campbell/Felix Geyer Signed-off-by: Alan Cox Cc: Signed-off-by: Ingo Molnar --- arch/x86/mm/ioremap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 6ab3196d12b..10b52309aef 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -614,7 +614,7 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size) */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; /* * Mappings have to fit in the FIX_BTMAP area. -- cgit v1.2.3 From cb58ffc3889f0545628f138f849e759a331b8ddc Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Sun, 12 Oct 2008 10:51:03 +0200 Subject: x86: fix early panic on amd64 due to typo in supported CPU section Do not crash when enumerating supported CPU architectures SECURITY_INIT somehow ended up in x86_cpu_dev.init section. That caused printk in code which prints supported architectures to hit #GP due to non-canonical address being used. Signed-off-by: Petr Vandrovec Cc: thomas.petazzoni@free-electrons.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/vmlinux_64.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 201e81a91a9..46e05447405 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -172,8 +172,8 @@ SECTIONS .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { *(.x86_cpu_dev.init) } - SECURITY_INIT __x86_cpu_dev_end = .; + SECURITY_INIT . = ALIGN(8); .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { -- cgit v1.2.3 From 325af5fb1418c79953db0954556de048e061d8b6 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 8 Aug 2008 15:58:39 -0700 Subject: x86: ioperm user_regset This adds a user_regset type for the x86 io permissions bitmap. This makes it appear in core dumps (when ioperm has been used). It will also make it visible to debuggers in the future. Signed-off-by: Roland McGrath Signed-off-by: H. Peter Anvin [conflict resolutions: Signed-off-by: Ingo Molnar ] --- arch/x86/kernel/ptrace.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e375b658efc..4e1ef66c2ea 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -40,7 +40,9 @@ enum x86_regset { REGSET_GENERAL, REGSET_FP, REGSET_XFP, + REGSET_IOPERM64 = REGSET_XFP, REGSET_TLS, + REGSET_IOPERM32, }; /* @@ -555,6 +557,29 @@ static int ptrace_set_debugreg(struct task_struct *child, return 0; } +/* + * These access the current or another (stopped) task's io permission + * bitmap for debugging or core dump. + */ +static int ioperm_active(struct task_struct *target, + const struct user_regset *regset) +{ + return target->thread.io_bitmap_max / regset->size; +} + +static int ioperm_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + if (!target->thread.io_bitmap_ptr) + return -ENXIO; + + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + target->thread.io_bitmap_ptr, + 0, IO_BITMAP_BYTES); +} + #ifdef CONFIG_X86_PTRACE_BTS /* * The configuration for a particular BTS hardware implementation. @@ -1385,6 +1410,12 @@ static const struct user_regset x86_64_regsets[] = { .size = sizeof(long), .align = sizeof(long), .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set }, + [REGSET_IOPERM64] = { + .core_note_type = NT_386_IOPERM, + .n = IO_BITMAP_LONGS, + .size = sizeof(long), .align = sizeof(long), + .active = ioperm_active, .get = ioperm_get + }, }; static const struct user_regset_view user_x86_64_view = { @@ -1431,6 +1462,12 @@ static const struct user_regset x86_32_regsets[] = { .active = regset_tls_active, .get = regset_tls_get, .set = regset_tls_set }, + [REGSET_IOPERM32] = { + .core_note_type = NT_386_IOPERM, + .n = IO_BITMAP_BYTES / sizeof(u32), + .size = sizeof(u32), .align = sizeof(u32), + .active = ioperm_active, .get = ioperm_get + }, }; static const struct user_regset_view user_x86_32_view = { -- cgit v1.2.3 From 81034663159f39d005316b5c139038459cd16721 Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier Date: Thu, 14 Aug 2008 12:04:11 -0300 Subject: V4L/DVB (8687): soc-camera: Move .power and .reset from soc_camera host to sensor driver Make .power and .reset callbacks per camera instead of per host, also move their invocation to camera drivers. .arch/arm/mach-pxa/include/mach/camera.h | 2 - Signed-off-by: Stefan Herbrechtsmeier Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-pxa/include/mach/camera.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/include/mach/camera.h b/arch/arm/mach-pxa/include/mach/camera.h index 39516ced8b1..31abe6d514b 100644 --- a/arch/arm/mach-pxa/include/mach/camera.h +++ b/arch/arm/mach-pxa/include/mach/camera.h @@ -36,8 +36,6 @@ struct pxacamera_platform_data { int (*init)(struct device *); - int (*power)(struct device *, int); - int (*reset)(struct device *, int); unsigned long flags; unsigned long mclk_10khz; -- cgit v1.2.3 From 46eaa6702016e3ac9a188172a2c309d6ca1be1cd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:06:29 +0200 Subject: x86: memory corruption check - cleanup Move the prototypes from the generic kernel.h header to the more appropriate include/asm-x86/bios_ebda.h header file. Also, remove the check from the power management code - this is a pure x86 matter for now. Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 1 + arch/x86/mm/init_64.c | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 7e05462ffb1..bbe044dbe01 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index d84d3e91d34..3e10054c573 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From 9f482807a6bd7e2aa1ed0d8cfc48463ec4ca3568 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 18 Aug 2008 12:59:32 +0200 Subject: x86, fpu: check __clear_user() return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix warning: arch/x86/kernel/xsave.c: In function ‘save_i387_xstate’: arch/x86/kernel/xsave.c:98: warning: ignoring return value of ‘__clear_user’, declared with attribute warn_unused_result check the return value and act on it. We should not be ignoring faults at this point. Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 2f98323716d..9abac8a9d82 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -95,7 +95,9 @@ int save_i387_xstate(void __user *buf) * Start with clearing the user buffer. This will present a * clean context for the bytes not touched by the fxsave/xsave. */ - __clear_user(buf, sig_xstate_size); + err = __clear_user(buf, sig_xstate_size); + if (err) + return err; if (task_thread_info(tsk)->status & TS_XSAVE) err = xsave_user(buf); -- cgit v1.2.3 From 45e96f26f257bd873017c6244a6cafd27f6f5439 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 27 Aug 2008 10:37:14 +0200 Subject: warnings: fix arch/x86/kernel/early_printk.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix warning: arch/x86/kernel/early_printk.c:993: warning: ‘enable_debug_console’ defined but not used Eliminate dead code. Signed-off-by: Ingo Molnar --- arch/x86/kernel/early_printk.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 02fc5b40c14..34ad997d383 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -989,22 +989,4 @@ static int __init setup_early_printk(char *buf) return 0; } -static void __init enable_debug_console(char *buf) -{ -#ifdef DBGP_DEBUG - struct console *old_early_console = NULL; - - if (early_console_initialized && early_console) { - old_early_console = early_console; - unregister_console(early_console); - early_console_initialized = 0; - } - - setup_early_printk(buf); - - if (early_console == old_early_console && old_early_console) - register_console(old_early_console); -#endif -} - early_param("earlyprintk", setup_early_printk); -- cgit v1.2.3 From d562353a4533c4671af683499191707c9a77c406 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:22:22 +0200 Subject: warnings: fix arch/x86/kernel/io_apic_64.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/io_apic_64.c: In function ‘print_local_APIC’: arch/x86/kernel/io_apic_64.c:1284: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 2 has type ‘long unsigned int’ arch/x86/kernel/io_apic_64.c:1285: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 2 has type ‘long unsigned int’ We want to print the two halves of 'icr' at 32 bit width. Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index a1bec2969c6..02063ae042f 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -1281,8 +1281,8 @@ __apicdebuginit(void) print_local_APIC(void *dummy) printk(KERN_DEBUG "... APIC ESR: %08x\n", v); icr = apic_icr_read(); - printk(KERN_DEBUG "... APIC ICR: %08x\n", icr); - printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32); + printk(KERN_DEBUG "... APIC ICR: %08x\n", (u32)icr); + printk(KERN_DEBUG "... APIC ICR2: %08x\n", (u32)(icr >> 32)); v = apic_read(APIC_LVTT); printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); -- cgit v1.2.3 From 8a66712ba0969aea5580b9e312badfc2490fc614 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:24:53 +0200 Subject: x86, amd-iommu: propagate PCI device enabling error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit propagate an error in enabling the PCI device. Also eliminates this warning: arch/x86/kernel/amd_iommu_init.c: In function ‘init_iommu_one’: arch/x86/kernel/amd_iommu_init.c:726: warning: ignoring return value of ‘pci_enable_device’, declared with attribute warn_unused_result Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 148fcfe22f1..4cd8083c58b 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -723,9 +723,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); - pci_enable_device(iommu->dev); - - return 0; + return pci_enable_device(iommu->dev); } /* -- cgit v1.2.3 From b7b3a42533e1e41297fe517533375f9f8f7b92d0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:36:24 +0200 Subject: x86: extend processor type select help text extend the help text of the CONFIG_CPU_SUP_* config options to express what it does and what effects it has. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 63 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index f8843c3ae77..a2ea1488b37 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -430,48 +430,97 @@ config CPU_SUP_INTEL default y bool "Support Intel processors" if PROCESSOR_SELECT help - This enables extended support for Intel processors + This enables detection, tunings and quirks for Intel processors + + You need this enabled if you want your kernel to run on an + Intel CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on an Intel + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_CYRIX_32 default y bool "Support Cyrix processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for Cyrix processors + This enables detection, tunings and quirks for Cyrix processors + + You need this enabled if you want your kernel to run on a + Cyrix CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Cyrix + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_AMD default y bool "Support AMD processors" if PROCESSOR_SELECT help - This enables extended support for AMD processors + This enables detection, tunings and quirks for AMD processors + + You need this enabled if you want your kernel to run on an + AMD CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on an AMD + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_CENTAUR_32 default y bool "Support Centaur processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for Centaur processors + This enables detection, tunings and quirks for Centaur processors + + You need this enabled if you want your kernel to run on a + Centaur CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Centaur + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_CENTAUR_64 default y bool "Support Centaur processors" if PROCESSOR_SELECT depends on 64BIT help - This enables extended support for Centaur processors + This enables detection, tunings and quirks for Centaur processors + + You need this enabled if you want your kernel to run on a + Centaur CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Centaur + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_TRANSMETA_32 default y bool "Support Transmeta processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for Transmeta processors + This enables detection, tunings and quirks for Transmeta processors + + You need this enabled if you want your kernel to run on a + Transmeta CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Transmeta + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_UMC_32 default y bool "Support UMC processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for UMC processors + This enables detection, tunings and quirks for UMC processors + + You need this enabled if you want your kernel to run on a + UMC CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a UMC + CPU might render the kernel unbootable. + + If unsure, say N. config X86_DS bool "Debug Store support" -- cgit v1.2.3 From 1db5fff9aeab18566eb380e354629fdbbe7792f0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:40:45 +0200 Subject: x86: make processor type select depend on CONFIG_EMBEDDED deselecting one of the CPU type CONFIG_CPU_SUP_* config options can render a kernel unbootable. Make sure this option is only available if CONFIG_EMBEDDED is enabled. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index a2ea1488b37..c5f10136052 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -420,7 +420,6 @@ config X86_DEBUGCTLMSR depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) menuconfig PROCESSOR_SELECT - default y bool "Supported processor vendors" if EMBEDDED help This lets you choose what x86 vendor support code your kernel -- cgit v1.2.3 From caf18f19eefc0cf5539b4e82b8aa8df6a78391a6 Mon Sep 17 00:00:00 2001 From: Julien May Date: Wed, 24 Sep 2008 10:30:47 +0200 Subject: avr32: Allow selecting multiple pins at once at32_select_periph() now takes an u32 bitmask rather than a single pin. This allows to set multiple pins at once. Signed-off-by: Alex Raimondi Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atngw100/setup.c | 2 +- arch/avr32/boards/atstk1000/atstk1002.c | 2 +- arch/avr32/boards/atstk1000/atstk1003.c | 2 +- arch/avr32/boards/atstk1000/atstk1004.c | 2 +- arch/avr32/mach-at32ap/at32ap700x.c | 307 +++++++++++++++----------- arch/avr32/mach-at32ap/include/mach/portmux.h | 4 +- arch/avr32/mach-at32ap/pio.c | 41 ++-- 7 files changed, 212 insertions(+), 148 deletions(-) (limited to 'arch') diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index 65db3d26696..6c54580a66d 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -194,7 +194,7 @@ static int __init atngw100_init(void) * PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus), * but it's not available off-board. */ - at32_select_periph(GPIO_PIN_PB(28), 0, AT32_GPIOF_PULLUP); + at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP); at32_select_gpio(i2c_gpio_data.sda_pin, AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); at32_select_gpio(i2c_gpio_data.scl_pin, diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 32aceec0ae7..2bcea80b274 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -232,7 +232,7 @@ static void __init atstk1002_setup_extdac(void) goto err_set_clk; } - at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); + at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); at73c213_data.dac_clk = gclk; err_set_clk: diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c index acc61235b89..2bc300c3471 100644 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ b/arch/avr32/boards/atstk1000/atstk1003.c @@ -94,7 +94,7 @@ static void __init atstk1003_setup_extdac(void) goto err_set_clk; } - at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); + at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); at73c213_data.dac_clk = gclk; err_set_clk: diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index 949c13ec51e..5d485597171 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -99,7 +99,7 @@ static void __init atstk1004_setup_extdac(void) goto err_set_clk; } - at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); + at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); at73c213_data.dac_clk = gclk; err_set_clk: diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 5d00bb8d3cc..813b6844cdf 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -82,8 +82,9 @@ static struct platform_device _name##_id##_device = { \ .num_resources = ARRAY_SIZE(_name##_id##_resource), \ } -#define select_peripheral(pin, periph, flags) \ - at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags) +#define select_peripheral(port, pin_mask, periph, flags) \ + at32_select_periph(GPIO_##port##_BASE, pin_mask, \ + GPIO_##periph, flags) #define DEV_CLK(_name, devname, bus, _index) \ static struct clk devname##_##_name = { \ @@ -871,6 +872,7 @@ static struct clk atmel_psif1_pclk = { struct platform_device *__init at32_add_device_psif(unsigned int id) { struct platform_device *pdev; + u32 pin_mask; if (!(id == 0 || id == 1)) return NULL; @@ -881,20 +883,22 @@ struct platform_device *__init at32_add_device_psif(unsigned int id) switch (id) { case 0: + pin_mask = (1 << 8) | (1 << 9); /* CLOCK & DATA */ + if (platform_device_add_resources(pdev, atmel_psif0_resource, ARRAY_SIZE(atmel_psif0_resource))) goto err_add_resources; atmel_psif0_pclk.dev = &pdev->dev; - select_peripheral(PA(8), PERIPH_A, 0); /* CLOCK */ - select_peripheral(PA(9), PERIPH_A, 0); /* DATA */ + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); break; case 1: + pin_mask = (1 << 11) | (1 << 12); /* CLOCK & DATA */ + if (platform_device_add_resources(pdev, atmel_psif1_resource, ARRAY_SIZE(atmel_psif1_resource))) goto err_add_resources; atmel_psif1_pclk.dev = &pdev->dev; - select_peripheral(PB(11), PERIPH_A, 0); /* CLOCK */ - select_peripheral(PB(12), PERIPH_A, 0); /* DATA */ + select_peripheral(PIOB, pin_mask, PERIPH_A, 0); break; default: return NULL; @@ -958,26 +962,30 @@ DEV_CLK(usart, atmel_usart3, pba, 6); static inline void configure_usart0_pins(void) { - select_peripheral(PA(8), PERIPH_B, 0); /* RXD */ - select_peripheral(PA(9), PERIPH_B, 0); /* TXD */ + u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */ + + select_peripheral(PIOA, pin_mask, PERIPH_B, 0); } static inline void configure_usart1_pins(void) { - select_peripheral(PA(17), PERIPH_A, 0); /* RXD */ - select_peripheral(PA(18), PERIPH_A, 0); /* TXD */ + u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */ + + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); } static inline void configure_usart2_pins(void) { - select_peripheral(PB(26), PERIPH_B, 0); /* RXD */ - select_peripheral(PB(27), PERIPH_B, 0); /* TXD */ + u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */ + + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); } static inline void configure_usart3_pins(void) { - select_peripheral(PB(18), PERIPH_B, 0); /* RXD */ - select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ + u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */ + + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); } static struct platform_device *__initdata at32_usarts[4]; @@ -1057,59 +1065,69 @@ struct platform_device *__init at32_add_device_eth(unsigned int id, struct eth_platform_data *data) { struct platform_device *pdev; + u32 pin_mask; switch (id) { case 0: pdev = &macb0_device; - select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */ - select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */ - select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */ - select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */ - select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */ - select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */ - select_peripheral(PC(13), PERIPH_A, 0); /* RXER */ - select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */ - select_peripheral(PC(16), PERIPH_A, 0); /* MDC */ - select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */ + pin_mask = (1 << 3); /* TXD0 */ + pin_mask |= (1 << 4); /* TXD1 */ + pin_mask |= (1 << 7); /* TXEN */ + pin_mask |= (1 << 8); /* TXCK */ + pin_mask |= (1 << 9); /* RXD0 */ + pin_mask |= (1 << 10); /* RXD1 */ + pin_mask |= (1 << 13); /* RXER */ + pin_mask |= (1 << 15); /* RXDV */ + pin_mask |= (1 << 16); /* MDC */ + pin_mask |= (1 << 17); /* MDIO */ if (!data->is_rmii) { - select_peripheral(PC(0), PERIPH_A, 0); /* COL */ - select_peripheral(PC(1), PERIPH_A, 0); /* CRS */ - select_peripheral(PC(2), PERIPH_A, 0); /* TXER */ - select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */ - select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */ - select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */ - select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */ - select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */ - select_peripheral(PC(18), PERIPH_A, 0); /* SPD */ + pin_mask |= (1 << 0); /* COL */ + pin_mask |= (1 << 1); /* CRS */ + pin_mask |= (1 << 2); /* TXER */ + pin_mask |= (1 << 5); /* TXD2 */ + pin_mask |= (1 << 6); /* TXD3 */ + pin_mask |= (1 << 11); /* RXD2 */ + pin_mask |= (1 << 12); /* RXD3 */ + pin_mask |= (1 << 14); /* RXCK */ + pin_mask |= (1 << 18); /* SPD */ } + + select_peripheral(PIOC, pin_mask, PERIPH_A, 0); + break; case 1: pdev = &macb1_device; - select_peripheral(PD(13), PERIPH_B, 0); /* TXD0 */ - select_peripheral(PD(14), PERIPH_B, 0); /* TXD1 */ - select_peripheral(PD(11), PERIPH_B, 0); /* TXEN */ - select_peripheral(PD(12), PERIPH_B, 0); /* TXCK */ - select_peripheral(PD(10), PERIPH_B, 0); /* RXD0 */ - select_peripheral(PD(6), PERIPH_B, 0); /* RXD1 */ - select_peripheral(PD(5), PERIPH_B, 0); /* RXER */ - select_peripheral(PD(4), PERIPH_B, 0); /* RXDV */ - select_peripheral(PD(3), PERIPH_B, 0); /* MDC */ - select_peripheral(PD(2), PERIPH_B, 0); /* MDIO */ + pin_mask = (1 << 13); /* TXD0 */ + pin_mask |= (1 << 14); /* TXD1 */ + pin_mask |= (1 << 11); /* TXEN */ + pin_mask |= (1 << 12); /* TXCK */ + pin_mask |= (1 << 10); /* RXD0 */ + pin_mask |= (1 << 6); /* RXD1 */ + pin_mask |= (1 << 5); /* RXER */ + pin_mask |= (1 << 4); /* RXDV */ + pin_mask |= (1 << 3); /* MDC */ + pin_mask |= (1 << 2); /* MDIO */ + + if (!data->is_rmii) + pin_mask |= (1 << 15); /* SPD */ + + select_peripheral(PIOD, pin_mask, PERIPH_B, 0); if (!data->is_rmii) { - select_peripheral(PC(19), PERIPH_B, 0); /* COL */ - select_peripheral(PC(23), PERIPH_B, 0); /* CRS */ - select_peripheral(PC(26), PERIPH_B, 0); /* TXER */ - select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */ - select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */ - select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */ - select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */ - select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */ - select_peripheral(PD(15), PERIPH_B, 0); /* SPD */ + pin_mask = (1 << 19); /* COL */ + pin_mask |= (1 << 23); /* CRS */ + pin_mask |= (1 << 26); /* TXER */ + pin_mask |= (1 << 27); /* TXD2 */ + pin_mask |= (1 << 28); /* TXD3 */ + pin_mask |= (1 << 29); /* RXD2 */ + pin_mask |= (1 << 30); /* RXD3 */ + pin_mask |= (1 << 24); /* RXCK */ + + select_peripheral(PIOC, pin_mask, PERIPH_B, 0); } break; @@ -1177,23 +1195,28 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) { GPIO_PIN_PB(2), GPIO_PIN_PB(3), GPIO_PIN_PB(4), GPIO_PIN_PA(27), }; struct platform_device *pdev; + u32 pin_mask; switch (id) { case 0: pdev = &atmel_spi0_device; + pin_mask = (1 << 1) | (1 << 2); /* MOSI & SCK */ + /* pullup MISO so a level is always defined */ - select_peripheral(PA(0), PERIPH_A, AT32_GPIOF_PULLUP); - select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ - select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ + select_peripheral(PIOA, (1 << 0), PERIPH_A, AT32_GPIOF_PULLUP); + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); + at32_spi_setup_slaves(0, b, n, spi0_pins); break; case 1: pdev = &atmel_spi1_device; + pin_mask = (1 << 1) | (1 << 5); /* MOSI */ + /* pullup MISO so a level is always defined */ - select_peripheral(PB(0), PERIPH_B, AT32_GPIOF_PULLUP); - select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ - select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ + select_peripheral(PIOB, (1 << 0), PERIPH_B, AT32_GPIOF_PULLUP); + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); + at32_spi_setup_slaves(1, b, n, spi1_pins); break; @@ -1226,6 +1249,7 @@ struct platform_device *__init at32_add_device_twi(unsigned int id, unsigned int n) { struct platform_device *pdev; + u32 pin_mask; if (id != 0) return NULL; @@ -1238,8 +1262,9 @@ struct platform_device *__init at32_add_device_twi(unsigned int id, ARRAY_SIZE(atmel_twi0_resource))) goto err_add_resources; - select_peripheral(PA(6), PERIPH_A, 0); /* SDA */ - select_peripheral(PA(7), PERIPH_A, 0); /* SDL */ + pin_mask = (1 << 6) | (1 << 7); /* SDA & SDL */ + + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); atmel_twi0_pclk.dev = &pdev->dev; @@ -1274,6 +1299,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { struct platform_device *pdev; struct dw_dma_slave *dws; + u32 pioa_mask; + u32 piob_mask; if (id != 0 || !data) return NULL; @@ -1311,17 +1338,17 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) goto fail; /* CLK line is common to both slots */ - select_peripheral(PA(10), PERIPH_A, 0); + pioa_mask = 1 << 10; switch (data->slot[0].bus_width) { case 4: - select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ - select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ - select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ + pioa_mask |= 1 << 13; /* DATA1 */ + pioa_mask |= 1 << 14; /* DATA2 */ + pioa_mask |= 1 << 15; /* DATA3 */ /* fall through */ case 1: - select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ - select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */ + pioa_mask |= 1 << 11; /* CMD */ + pioa_mask |= 1 << 12; /* DATA0 */ if (gpio_is_valid(data->slot[0].detect_pin)) at32_select_gpio(data->slot[0].detect_pin, 0); @@ -1335,15 +1362,19 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) goto fail; } + select_peripheral(PIOA, pioa_mask, PERIPH_A, 0); + piob_mask = 0; + switch (data->slot[1].bus_width) { case 4: - select_peripheral(PB(8), PERIPH_B, 0); /* DATA1 */ - select_peripheral(PB(9), PERIPH_B, 0); /* DATA2 */ - select_peripheral(PB(10), PERIPH_B, 0); /* DATA3 */ + piob_mask |= 1 << 8; /* DATA1 */ + piob_mask |= 1 << 9; /* DATA2 */ + piob_mask |= 1 << 10; /* DATA3 */ /* fall through */ case 1: - select_peripheral(PB(6), PERIPH_B, 0); /* CMD */ - select_peripheral(PB(7), PERIPH_B, 0); /* DATA0 */ + piob_mask |= 1 << 6; /* CMD */ + piob_mask |= 1 << 7; /* DATA0 */ + select_peripheral(PIOB, piob_mask, PERIPH_B, 0); if (gpio_is_valid(data->slot[1].detect_pin)) at32_select_gpio(data->slot[1].detect_pin, 0); @@ -1412,7 +1443,7 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, struct fb_monspecs *monspecs; struct fb_videomode *modedb; unsigned int modedb_size; - int i; + u32 portc_mask, portd_mask, porte_mask; /* * Do a deep copy of the fb data, monspecs and modedb. Make @@ -1439,25 +1470,16 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, pin_mask = ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL; /* LCDC on port C */ - for (i = 19; i < 32; i++) { - if (pin_mask & (1ULL << i)) - at32_select_periph(GPIO_PIOC_BASE + i, - GPIO_PERIPH_A, 0); - } + portc_mask = (pin_mask & 0xfff80000) >> 19; + select_peripheral(PIOC, portc_mask, PERIPH_A, 0); /* LCDC on port D */ - for (i = 0; i < 18; i++) { - if (pin_mask & (1ULL << i)) - at32_select_periph(GPIO_PIOD_BASE + i, - GPIO_PERIPH_A, 0); - } + portd_mask = pin_mask & 0x0003ffff; + select_peripheral(PIOD, portd_mask, PERIPH_A, 0); /* LCDC on port E */ - for (i = 0; i < 19; i++) { - if (pin_mask & (1ULL << (i + 32))) - at32_select_periph(GPIO_PIOE_BASE + i, - GPIO_PERIPH_B, 0); - } + porte_mask = (pin_mask >> 32) & 0x0007ffff; + select_peripheral(PIOE, porte_mask, PERIPH_B, 0); clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); @@ -1506,6 +1528,7 @@ static struct clk atmel_pwm0_mck = { struct platform_device *__init at32_add_device_pwm(u32 mask) { struct platform_device *pdev; + u32 pin_mask; if (!mask) return NULL; @@ -1521,14 +1544,21 @@ struct platform_device *__init at32_add_device_pwm(u32 mask) if (platform_device_add_data(pdev, &mask, sizeof(mask))) goto out_free_pdev; + pin_mask = 0; if (mask & (1 << 0)) - select_peripheral(PA(28), PERIPH_A, 0); + pin_mask |= (1 << 28); if (mask & (1 << 1)) - select_peripheral(PA(29), PERIPH_A, 0); + pin_mask |= (1 << 29); + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); + + pin_mask = 0; if (mask & (1 << 2)) - select_peripheral(PA(21), PERIPH_B, 0); + pin_mask |= (1 << 21); if (mask & (1 << 3)) - select_peripheral(PA(22), PERIPH_B, 0); + pin_mask |= (1 << 22); + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_B, 0); atmel_pwm0_mck.dev = &pdev->dev; @@ -1569,52 +1599,65 @@ struct platform_device *__init at32_add_device_ssc(unsigned int id, unsigned int flags) { struct platform_device *pdev; + u32 pin_mask = 0; switch (id) { case 0: pdev = &ssc0_device; if (flags & ATMEL_SSC_RF) - select_peripheral(PA(21), PERIPH_A, 0); /* RF */ + pin_mask |= (1 << 21); /* RF */ if (flags & ATMEL_SSC_RK) - select_peripheral(PA(22), PERIPH_A, 0); /* RK */ + pin_mask |= (1 << 22); /* RK */ if (flags & ATMEL_SSC_TK) - select_peripheral(PA(23), PERIPH_A, 0); /* TK */ + pin_mask |= (1 << 23); /* TK */ if (flags & ATMEL_SSC_TF) - select_peripheral(PA(24), PERIPH_A, 0); /* TF */ + pin_mask |= (1 << 24); /* TF */ if (flags & ATMEL_SSC_TD) - select_peripheral(PA(25), PERIPH_A, 0); /* TD */ + pin_mask |= (1 << 25); /* TD */ if (flags & ATMEL_SSC_RD) - select_peripheral(PA(26), PERIPH_A, 0); /* RD */ + pin_mask |= (1 << 26); /* RD */ + + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); + break; case 1: pdev = &ssc1_device; if (flags & ATMEL_SSC_RF) - select_peripheral(PA(0), PERIPH_B, 0); /* RF */ + pin_mask |= (1 << 0); /* RF */ if (flags & ATMEL_SSC_RK) - select_peripheral(PA(1), PERIPH_B, 0); /* RK */ + pin_mask |= (1 << 1); /* RK */ if (flags & ATMEL_SSC_TK) - select_peripheral(PA(2), PERIPH_B, 0); /* TK */ + pin_mask |= (1 << 2); /* TK */ if (flags & ATMEL_SSC_TF) - select_peripheral(PA(3), PERIPH_B, 0); /* TF */ + pin_mask |= (1 << 3); /* TF */ if (flags & ATMEL_SSC_TD) - select_peripheral(PA(4), PERIPH_B, 0); /* TD */ + pin_mask |= (1 << 4); /* TD */ if (flags & ATMEL_SSC_RD) - select_peripheral(PA(5), PERIPH_B, 0); /* RD */ + pin_mask |= (1 << 5); /* RD */ + + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_B, 0); + break; case 2: pdev = &ssc2_device; if (flags & ATMEL_SSC_TD) - select_peripheral(PB(13), PERIPH_A, 0); /* TD */ + pin_mask |= (1 << 13); /* TD */ if (flags & ATMEL_SSC_RD) - select_peripheral(PB(14), PERIPH_A, 0); /* RD */ + pin_mask |= (1 << 14); /* RD */ if (flags & ATMEL_SSC_TK) - select_peripheral(PB(15), PERIPH_A, 0); /* TK */ + pin_mask |= (1 << 15); /* TK */ if (flags & ATMEL_SSC_TF) - select_peripheral(PB(16), PERIPH_A, 0); /* TF */ + pin_mask |= (1 << 16); /* TF */ if (flags & ATMEL_SSC_RF) - select_peripheral(PB(17), PERIPH_A, 0); /* RF */ + pin_mask |= (1 << 17); /* RF */ if (flags & ATMEL_SSC_RK) - select_peripheral(PB(18), PERIPH_A, 0); /* RK */ + pin_mask |= (1 << 18); /* RK */ + + if (pin_mask > 0) + select_peripheral(PIOB, pin_mask, PERIPH_A, 0); + break; default: return NULL; @@ -1752,14 +1795,15 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, unsigned int cs, unsigned int extint) { static unsigned int extint_pin_map[4] __initdata = { - GPIO_PIN_PB(25), - GPIO_PIN_PB(26), - GPIO_PIN_PB(27), - GPIO_PIN_PB(28), + (1 << 25), + (1 << 26), + (1 << 27), + (1 << 28), }; static bool common_pins_initialized __initdata = false; unsigned int extint_pin; int ret; + u32 pin_mask; if (extint >= ARRAY_SIZE(extint_pin_map)) return -EINVAL; @@ -1773,7 +1817,8 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, if (ret) return ret; - select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */ + /* NCS4 -> OE_N */ + select_peripheral(PIOE, (1 << 21), PERIPH_A, 0); hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF0_ENABLE); break; case 5: @@ -1783,7 +1828,8 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, if (ret) return ret; - select_peripheral(PE(22), PERIPH_A, 0); /* NCS5 -> OE_N */ + /* NCS5 -> OE_N */ + select_peripheral(PIOE, (1 << 22), PERIPH_A, 0); hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF1_ENABLE); break; default: @@ -1791,14 +1837,17 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, } if (!common_pins_initialized) { - select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */ - select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */ - select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */ - select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */ + pin_mask = (1 << 19); /* CFCE1 -> CS0_N */ + pin_mask |= (1 << 20); /* CFCE2 -> CS1_N */ + pin_mask |= (1 << 23); /* CFRNW -> DIR */ + pin_mask |= (1 << 24); /* NWAIT <- IORDY */ + + select_peripheral(PIOE, pin_mask, PERIPH_A, 0); + common_pins_initialized = true; } - at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); + select_peripheral(PIOB, extint_pin, PERIPH_A, AT32_GPIOF_DEGLITCH); pdev->resource[1].start = EIM_IRQ_BASE + extint; pdev->resource[1].end = pdev->resource[1].start; @@ -1937,6 +1986,7 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) { struct platform_device *pdev; struct ac97c_platform_data _data; + u32 pin_mask; if (id != 0) return NULL; @@ -1963,10 +2013,10 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) sizeof(struct ac97c_platform_data))) goto fail; - select_peripheral(PB(20), PERIPH_B, 0); /* SDO */ - select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */ - select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */ - select_peripheral(PB(23), PERIPH_B, 0); /* SDI */ + pin_mask = (1 << 20) | (1 << 21); /* SDO & SYNC */ + pin_mask |= (1 << 22) | (1 << 23); /* SCLK & SDI */ + + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ if (data->reset_pin != GPIO_PIN_NONE) @@ -2008,6 +2058,7 @@ static struct clk abdac0_sample_clk = { struct platform_device *__init at32_add_device_abdac(unsigned int id) { struct platform_device *pdev; + u32 pin_mask; if (id != 0) return NULL; @@ -2020,10 +2071,10 @@ struct platform_device *__init at32_add_device_abdac(unsigned int id) ARRAY_SIZE(abdac0_resource))) goto err_add_resources; - select_peripheral(PB(20), PERIPH_A, 0); /* DATA1 */ - select_peripheral(PB(21), PERIPH_A, 0); /* DATA0 */ - select_peripheral(PB(22), PERIPH_A, 0); /* DATAN1 */ - select_peripheral(PB(23), PERIPH_A, 0); /* DATAN0 */ + pin_mask = (1 << 20) | (1 << 22); /* DATA1 & DATAN1 */ + pin_mask |= (1 << 21) | (1 << 23); /* DATA0 & DATAN0 */ + + select_peripheral(PIOB, pin_mask, PERIPH_A, 0); abdac0_pclk.dev = &pdev->dev; abdac0_sample_clk.dev = &pdev->dev; diff --git a/arch/avr32/mach-at32ap/include/mach/portmux.h b/arch/avr32/mach-at32ap/include/mach/portmux.h index 4bbf99ec2c4..21c79373b53 100644 --- a/arch/avr32/mach-at32ap/include/mach/portmux.h +++ b/arch/avr32/mach-at32ap/include/mach/portmux.h @@ -21,8 +21,8 @@ #define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */ #define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */ -void at32_select_periph(unsigned int pin, unsigned int periph, - unsigned long flags); +void at32_select_periph(unsigned int port, unsigned int pin, + unsigned int periph, unsigned long flags); void at32_select_gpio(unsigned int pin, unsigned long flags); void at32_deselect_pin(unsigned int pin); void at32_reserve_pin(unsigned int pin); diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index ef2561e1539..ed81a8bcb22 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -50,35 +50,48 @@ static struct pio_device *gpio_to_pio(unsigned int gpio) } /* Pin multiplexing API */ +static DEFINE_SPINLOCK(pio_lock); -void __init at32_select_periph(unsigned int pin, unsigned int periph, - unsigned long flags) +void __init at32_select_periph(unsigned int port, u32 pin_mask, + unsigned int periph, unsigned long flags) { struct pio_device *pio; - unsigned int pin_index = pin & 0x1f; - u32 mask = 1 << pin_index; - pio = gpio_to_pio(pin); + /* assign and verify pio */ + pio = gpio_to_pio(port); if (unlikely(!pio)) { - printk("pio: invalid pin %u\n", pin); + printk(KERN_WARNING "pio: invalid port %u\n", port); goto fail; } - if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask) - || gpiochip_is_requested(&pio->chip, pin_index))) { - printk("%s: pin %u is busy\n", pio->name, pin_index); + /* Test if any of the requested pins is already muxed */ + spin_lock(&pio_lock); + if (unlikely(pio->pinmux_mask & pin_mask)) { + printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n", + pio->name, pin_mask, pio->pinmux_mask & pin_mask); + spin_unlock(&pio_lock); goto fail; } - pio_writel(pio, PUER, mask); + pio->pinmux_mask |= pin_mask; + + /* enable pull ups */ + pio_writel(pio, PUER, pin_mask); + + /* select either peripheral A or B */ if (periph) - pio_writel(pio, BSR, mask); + pio_writel(pio, BSR, pin_mask); else - pio_writel(pio, ASR, mask); + pio_writel(pio, ASR, pin_mask); + + /* enable peripheral control */ + pio_writel(pio, PDR, pin_mask); - pio_writel(pio, PDR, mask); + /* Disable pull ups if not requested. */ if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, mask); + pio_writel(pio, PUDR, pin_mask); + + spin_unlock(&pio_lock); return; -- cgit v1.2.3 From 6eb3ebe04da4c8f31d776217b0b76ca3d00f20b1 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Sun, 12 Oct 2008 16:02:46 +0200 Subject: avr32: Fix build failures in board code Fix a few instances of board code breakage introduced by the atmel-mci platform interface changes. Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/atstk1002.c | 2 +- arch/avr32/boards/atstk1000/atstk1003.c | 1 + arch/avr32/boards/atstk1000/atstk1004.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 2bcea80b274..29e5b51a7fd 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -330,7 +330,7 @@ static int __init atstk1002_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, &mci0_pdata); + at32_add_device_mci(0, &mci0_data); #endif #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM set_hw_addr(at32_add_device_eth(1, ð_data[1])); diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c index 2bc300c3471..be089d7f37e 100644 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ b/arch/avr32/boards/atstk1000/atstk1003.c @@ -19,6 +19,7 @@ #include #include +#include #include #include diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index 5d485597171..248ef237c16 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -21,6 +21,7 @@ #include