From: Martin Date: Sat, 30 Apr 2011 20:14:23 +0000 (+0200) Subject: deubootization, added cache.c and ints.c in arch X-Git-Url: https://rtime.felk.cvut.cz/gitweb/mcf548x/linux.git/commitdiff_plain/81840381cc4d1f7903df0310021e315dc40bee87?hp=0ab340cca35a7b529f78a54e8bd2ccaa23f1855e deubootization, added cache.c and ints.c in arch --- diff --git a/arch/m68k/coldfire/cache.c b/arch/m68k/coldfire/cache.c new file mode 100644 index 000000000000..d5cdce2edaf3 --- /dev/null +++ b/arch/m68k/coldfire/cache.c @@ -0,0 +1,43 @@ +/* + * linux/arch/m68k/coldfire/cache.c + * + * Matt Waddel Matt.Waddel@freescale.com + * Kurt Mahan kmahan@freescale.com + * Copyright Freescale Semiconductor, Inc. 2007 + * + * 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 + +/* Cache Control Reg shadow reg */ +unsigned long shadow_cacr; + +/** + * cacr_set - Set the Cache Control Register + * @x Value to set + */ +void cacr_set(unsigned long x) +{ + shadow_cacr = x; + + __asm__ __volatile__ ("movec %0, %%cacr" + : /* no outputs */ + : "r" (shadow_cacr)); +} + +/** + * cacr_get - Get the current value of the Cache Control Register + * + * @return CACR value + */ +unsigned long cacr_get(void) +{ + return shadow_cacr; +} diff --git a/arch/m68k/coldfire/config.c b/arch/m68k/coldfire/config.c index a3fcb59b7dc0..ef2c4000d21e 100644 --- a/arch/m68k/coldfire/config.c +++ b/arch/m68k/coldfire/config.c @@ -21,10 +21,10 @@ #include #include #include -//#include +#include #include #include -//#include +#include #include #include #include @@ -63,18 +63,15 @@ extern int get_irq_list(struct seq_file *p, void *v); extern char _text, _end; extern char _etext, _edata, __init_begin, __init_end; extern struct console mcfrs_console; -extern char m68k_command_line[CL_SIZE]; extern unsigned long availmem; +#if CONFIG_UBOOT +extern char m68k_command_line[CL_SIZE]; +#endif + static int irq_enable[NR_IRQS]; unsigned long num_pages; -/* ethernet mac addresses from uboot */ -#ifdef CONFIG_UBOOT -unsigned char uboot_enet0[6]; -unsigned char uboot_enet1[6]; -#endif - void coldfire_sort_memrec(void) { int i, j; @@ -105,38 +102,25 @@ void coldfire_sort_memrec(void) } /* - * UBoot Handler + * Use uboot commandline if told to */ #ifdef CONFIG_UBOOT int __init uboot_commandline(char *bootargs) { + extern unsigned long uboot_init_sp; + int len = 0, cmd_line_len; - static struct uboot_record uboot_info; + unsigned long cmd_line_stop, cmd_line_start; u32 offset = PAGE_OFFSET_RAW - PHYS_OFFSET; - extern unsigned long uboot_info_stk; - - /* validate address */ - if ((uboot_info_stk < PAGE_OFFSET_RAW) || - (uboot_info_stk >= (PAGE_OFFSET_RAW + CONFIG_SDRAM_SIZE))) - return 0; - - /* Add offset to get post-remapped kernel memory location */ - uboot_info.bdi = (struct bd_info *)((*(u32 *)(uboot_info_stk)) + offset); - uboot_info.initrd_start = (*(u32 *)(uboot_info_stk+4)) + offset; - uboot_info.initrd_end = (*(u32 *)(uboot_info_stk+8)) + offset; - uboot_info.cmd_line_start = (*(u32 *)(uboot_info_stk+12)) + offset; - uboot_info.cmd_line_stop = (*(u32 *)(uboot_info_stk+16)) + offset; - - /* copy over mac addresses */ - memcpy(uboot_enet0, uboot_info.bdi->bi_enet0addr, 6); - memcpy(uboot_enet1, uboot_info.bdi->bi_enet1addr, 6); + //uboot_init_sp parameters - must add offset to them !! + cmd_line_start = uboot_init_sp + 16 + offset; + cmd_line_start = uboot_init_sp + 20 + offset; /* copy command line */ - cmd_line_len = uboot_info.cmd_line_stop - uboot_info.cmd_line_start; + cmd_line_len = cmd_line_stop - cmd_line_start; if ((cmd_line_len > 0) && (cmd_line_len < CL_SIZE-1)) - len = (int)strncpy(bootargs, (char *)uboot_info.cmd_line_start,\ - cmd_line_len); + len = (int)strncpy(bootargs, (char *)cmd_line_start,cmd_line_len); return len; } @@ -204,13 +188,9 @@ asmlinkage void __init cf_early_init(void) m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE; m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE; - #ifdef CONFIG_UBOOT if (!uboot_commandline(m68k_command_line)) strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1); -#else - //FIXME: some better way here - strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1); #endif #if defined(CONFIG_BLK_DEV_INITRD) diff --git a/arch/m68k/coldfire/head.S b/arch/m68k/coldfire/head.S index ff329b74b849..e1b53214f679 100644 --- a/arch/m68k/coldfire/head.S +++ b/arch/m68k/coldfire/head.S @@ -290,7 +290,9 @@ __INIT ENTRY(__start) movew #0x2700,%sr /* no interrupts */ #if defined(CONFIG_UBOOT) - movel %sp,uboot_init_sp /* save initial stack pointer */ + movel %sp,%a4 /* save initial stack pointer */ + addl #(PAGE_OFFSET-CONFIG_SDRAM_BASE),%a4 /* high mem offset */ + movel %a4, uboot_init_sp /*this will be used by C code after turning on MMU*/ #endif /* Setup initial stack pointer */ @@ -605,15 +607,6 @@ _loop_bss: wdebug (%a0) #endif - -#ifdef CONFIG_UBOOT - /* save the uboot structure to variable */ - mov uboot_init_sp, %a4 - addl #0x00000004,%a4 /* offset past top */ - addl #(PAGE_OFFSET-CONFIG_SDRAM_BASE),%a4 /* high mem offset */ - movel %a4,uboot_info_stk /* save uboot info to variable */ -#endif - /* Continuing in C code */ bsr cf_early_init jmp start_kernel diff --git a/arch/m68k/coldfire/ints.c b/arch/m68k/coldfire/ints.c new file mode 100644 index 000000000000..00d5dd637aa6 --- /dev/null +++ b/arch/m68k/coldfire/ints.c @@ -0,0 +1,463 @@ +/* + * linux/arch/m68k/coldfire/ints.c -- General interrupt handling code + * + * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * + * Copyright Freescale Semiconductor, Inc. 2007, 2008 + * Kurt Mahan kmahan@freescale.com + * Matt Waddel Matt.Waddel@freescale.com + * + * Based on: + * linux/arch/m68k/kernel/ints.c & + * linux/arch/m68knommu/5307/ints.c + * + * 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 + +/* + * IRQ Handler lists. + */ +static struct irq_node *irq_list[SYS_IRQS]; +static struct irq_controller *irq_controller[SYS_IRQS]; +static int irq_depth[SYS_IRQS]; + +/* + * IRQ Controller + */ +#if defined(CONFIG_M5445X) +void m5445x_irq_enable(unsigned int irq); +void m5445x_irq_disable(unsigned int irq); +static struct irq_controller m5445x_irq_controller = { + .name = "M5445X", + .lock = SPIN_LOCK_UNLOCKED, + .enable = m5445x_irq_enable, + .disable = m5445x_irq_disable, +}; +#elif defined(CONFIG_M547X_8X) +void m547x_8x_irq_enable(unsigned int irq); +void m547x_8x_irq_disable(unsigned int irq); +static struct irq_controller m547x_8x_irq_controller = { + .name = "M547X_8X", + .lock = SPIN_LOCK_UNLOCKED, + .enable = m547x_8x_irq_enable, + .disable = m547x_8x_irq_disable, +}; +#else +# error No IRQ controller defined +#endif + +#define POOL_SIZE SYS_IRQS +static struct irq_node pool[POOL_SIZE]; +static struct irq_node *get_irq_node(void); + +/* The number of spurious interrupts */ +unsigned int num_spurious; +asmlinkage void handle_badint(struct pt_regs *regs); + +/* + * void init_IRQ(void) + * + * This function should be called during kernel startup to initialize + * the IRQ handling routines. + */ +void __init init_IRQ(void) +{ + int i; + +#if defined(CONFIG_M5445X) + for (i = 0; i < SYS_IRQS; i++) + irq_controller[i] = &m5445x_irq_controller; +#elif defined(CONFIG_M547X_8X) + for (i = 0; i < SYS_IRQS; i++) + irq_controller[i] = &m547x_8x_irq_controller; +#endif +} + +/* + * process_int(unsigned long vec, struct pt_regs *fp) + * + * Process an interrupt. Called from entry.S. + */ +asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) +{ + struct pt_regs *old_regs; + struct irq_node *node; + old_regs = set_irq_regs(fp); + kstat_cpu(0).irqs[vec]++; + + node = irq_list[vec]; + if (!node) + handle_badint(fp); + else { + do { + node->handler(vec, node->dev_id); + node = node->next; + } while (node); + } + + set_irq_regs(old_regs); +} + +/* + * show_interrupts( struct seq_file *p, void *v) + * + * Called to show all the current interrupt information. + */ +int show_interrupts(struct seq_file *p, void *v) +{ + struct irq_controller *contr; + struct irq_node *node; + int i = *(loff_t *) v; + + if ((i < NR_IRQS) && (irq_list[i])) { + contr = irq_controller[i]; + node = irq_list[i]; + seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, + kstat_cpu(0).irqs[i], node->devname); + while ((node = node->next)) + seq_printf(p, ", %s", node->devname); + + seq_printf(p, "\n"); + } + + return 0; +} + +/* + * get_irq_node(void) + * + * Get an irq node from the pool. + */ +struct irq_node *get_irq_node(void) +{ + struct irq_node *p = pool; + int i; + + for (i = 0; i < POOL_SIZE; i++, p++) { + if (!p->handler) { + memset(p, 0, sizeof(struct irq_node)); + return p; + } + } + printk(KERN_INFO "%s(%s:%d): No more irq nodes, I suggest you \ + increase POOL_SIZE", __FUNCTION__, __FILE__, __LINE__); + return NULL; +} + +void init_irq_proc(void) +{ + /* Insert /proc/irq driver here */ +} + +int setup_irq(unsigned int irq, struct irq_node *node) +{ + struct irq_controller *contr; + struct irq_node **prev; + unsigned long flags; + + if (irq >= NR_IRQS || !irq_controller[irq]) { + printk("%s: Incorrect IRQ %d from %s\n", + __FUNCTION__, irq, node->devname); + return -ENXIO; + } + + contr = irq_controller[irq]; + spin_lock_irqsave(&contr->lock, flags); + + prev = irq_list + irq; + if (*prev) { + /* Can't share interrupts unless both agree to */ + if (!((*prev)->flags & node->flags & IRQF_SHARED)) { + spin_unlock_irqrestore(&contr->lock, flags); + printk(KERN_INFO "%s: -BUSY-Incorrect IRQ %d \n", + __FUNCTION__, irq); + return -EBUSY; + } + while (*prev) + prev = &(*prev)->next; + } + + if (!irq_list[irq]) { + if (contr->startup) + contr->startup(irq); + else + contr->enable(irq); + } + node->next = NULL; + *prev = node; + + spin_unlock_irqrestore(&contr->lock, flags); + + return 0; +} + +int request_irq(unsigned int irq, + irq_handler_t handler, + unsigned long flags, const char *devname, void *dev_id) +{ + struct irq_node *node = get_irq_node(); + int res; + + if (!node) { + printk(KERN_INFO "%s:get_irq_node error %x\n", + __FUNCTION__,(unsigned int) node); + return -ENOMEM; + } + node->handler = handler; + node->flags = flags; + node->dev_id = dev_id; + node->devname = devname; + + res = setup_irq(irq, node); + if (res) + node->handler = NULL; + + return res; +} +EXPORT_SYMBOL(request_irq); + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irq_controller *contr; + struct irq_node **p, *node; + unsigned long flags; + + if (irq >= NR_IRQS || !irq_controller[irq]) { + printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + + contr = irq_controller[irq]; + spin_lock_irqsave(&contr->lock, flags); + + p = irq_list + irq; + while ((node = *p)) { + if (node->dev_id == dev_id) + break; + p = &node->next; + } + + if (node) { + *p = node->next; + node->handler = NULL; + } else + printk(KERN_DEBUG "%s: Removing probably wrong IRQ %d\n", + __FUNCTION__, irq); + + if (!irq_list[irq]) { + if (contr->shutdown) + contr->shutdown(irq); + else + contr->disable(irq); + } + + spin_unlock_irqrestore(&contr->lock, flags); +} +EXPORT_SYMBOL(free_irq); + +void enable_irq(unsigned int irq) +{ + struct irq_controller *contr; + unsigned long flags; + + if (irq >= NR_IRQS || !irq_controller[irq]) { + printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + + contr = irq_controller[irq]; + spin_lock_irqsave(&contr->lock, flags); + if (irq_depth[irq]) { + if (!--irq_depth[irq]) { + if (contr->enable) + contr->enable(irq); + } + } else + WARN_ON(1); + spin_unlock_irqrestore(&contr->lock, flags); +} +EXPORT_SYMBOL(enable_irq); + +void disable_irq(unsigned int irq) +{ + struct irq_controller *contr; + unsigned long flags; + + if (irq >= NR_IRQS || !irq_controller[irq]) { + printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + + contr = irq_controller[irq]; + spin_lock_irqsave(&contr->lock, flags); + if (!irq_depth[irq]++) { + if (contr->disable) + contr->disable(irq); + } + spin_unlock_irqrestore(&contr->lock, flags); +} +EXPORT_SYMBOL(disable_irq); + +void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); +EXPORT_SYMBOL(disable_irq_nosync); + + +unsigned long probe_irq_on(void) +{ + return 0; +} +EXPORT_SYMBOL(probe_irq_on); + +int probe_irq_off(unsigned long irqs) +{ + return 0; +} +EXPORT_SYMBOL(probe_irq_off); + +asmlinkage void handle_badint(struct pt_regs *regs) +{ + kstat_cpu(0).irqs[0]++; + num_spurious++; + printk(KERN_DEBUG "unexpected interrupt from %u\n", regs->vector); +} +EXPORT_SYMBOL(handle_badint); + +#ifdef CONFIG_M5445X +/* + * M5445X Implementation + */ +void m5445x_irq_enable(unsigned int irq) +{ + /* enable the interrupt hardware */ + if (irq < 64) + return; + + /* adjust past non-hardware ints */ + irq -= 64; + + /* check for eport */ + if ((irq > 0) && (irq < 8)) { + /* enable eport */ + MCF_EPORT_EPPAR &= ~(3 << (irq*2)); /* level */ + MCF_EPORT_EPDDR &= ~(1 << irq); /* input */ + MCF_EPORT_EPIER |= 1 << irq; /* irq enabled */ + } + + if (irq < 64) { + /* controller 0 */ + MCF_INTC0_ICR(irq) = 0x02; + MCF_INTC0_CIMR = irq; + } else { + /* controller 1 */ + irq -= 64; + MCF_INTC1_ICR(irq) = 0x02; + MCF_INTC1_CIMR = irq; + } +} + +void m5445x_irq_disable(unsigned int irq) +{ + /* disable the interrupt hardware */ + if (irq < 64) + return; + + /* adjust past non-hardware ints */ + irq -= 64; + + /* check for eport */ + if ((irq > 0) && (irq < 8)) { + /* disable eport */ + MCF_EPORT_EPIER &= ~(1 << irq); + } + + if (irq < 64) { + /* controller 0 */ + MCF_INTC0_ICR(irq) = 0x00; + MCF_INTC0_SIMR = irq; + } else { + /* controller 1 */ + irq -= 64; + MCF_INTC1_ICR(irq) = 0x00; + MCF_INTC1_SIMR = irq; + } +} +#elif defined(CONFIG_M547X_8X) +/* + * M547X_8X Implementation + */ +void m547x_8x_irq_enable(unsigned int irq) +{ + /* enable the interrupt hardware */ + if (irq < 64) + return; + + /* adjust past non-hardware ints */ + irq -= 64; + +/* JKM -- re-add EPORT later */ +#if 0 + /* check for eport */ + if ((irq > 0) && (irq < 8)) { + /* enable eport */ + MCF_EPORT_EPPAR &= ~(3 << (irq*2)); /* level */ + MCF_EPORT_EPDDR &= ~(1 << irq); /* input */ + MCF_EPORT_EPIER |= 1 << irq; /* irq enabled */ + } +#endif + + if (irq < 32) { + /* *grumble* don't set low bit of IMRL */ + MCF_IMRL &= (~(1 << irq) & 0xfffffffe); + } + else { + MCF_IMRH &= ~(1 << (irq - 32)); + } +} + +void m547x_8x_irq_disable(unsigned int irq) +{ + /* disable the interrupt hardware */ + if (irq < 64) + return; + + /* adjust past non-hardware ints */ + irq -= 64; + +/* JKM -- re-add EPORT later */ +#if 0 + /* check for eport */ + if ((irq > 0) && (irq < 8)) { + /* disable eport */ + MCF_EPORT_EPIER &= ~(1 << irq); + } +#endif + + if (irq < 32) + MCF_IMRL |= (1 << irq); + else + MCF_IMRH |= (1 << (irq - 32)); +} +#endif