From 26bfeea38a4a5daf52c8f01c986ca8680bf1f6a1 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Mon, 19 Jul 2010 15:40:03 -0500 Subject: [PATCH 01/51] 9p: Pass the correct end of buffer to p9stat_read Pass the correct end of the buffer to p9stat_read. Signed-off-by: Latchesar Ionkov Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index d61e3b28ce37..36d961f342af 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -146,7 +146,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) while (rdir->head < rdir->tail) { p9stat_init(&st); err = p9stat_read(rdir->buf + rdir->head, - buflen - rdir->head, &st, + rdir->tail - rdir->head, &st, fid->clnt->proto_version); if (err) { P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); From 60dbd6633178a8625ed71329da0167c6d50c559c Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Fri, 30 Jul 2010 17:33:07 +0200 Subject: [PATCH 02/51] CRIS: GENERIC_TIME fixes GENERIC_TIME was not functional for CRIS, giving random backward time jumps. For CRISv32 implement a new clocksource using the free running counter and ditch the arch_gettimeoffset. The random time jumps still existed, but turned out to be the write_seqlock which was missing around our do_timer() call. So switch over to GENERIC_TIME using the clocksource for CRISv32. CRISv10 doesn't have the free running counter needed for the clocksource trick, but we can still use GENERIC_TIME with arch_gettimeoffset. Unfortunately, there were problems in using the prescaler register to timer0 for the gettimeoffset calculation, so it is now ignored, making our resolution worse by the tune of 40usec (0.4%) worst case. At the same time, clean up some formatting and use NSEC_PER_SEC instead of 1000000000. Signed-off-by: Jesper Nilsson --- arch/cris/Kconfig | 5 +- arch/cris/arch-v10/kernel/time.c | 54 +------------------- arch/cris/arch-v32/kernel/time.c | 85 +++++++++++++------------------- arch/cris/kernel/time.c | 7 ++- 4 files changed, 45 insertions(+), 106 deletions(-) diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index e25bf4440b51..4827c72b9634 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -27,7 +27,7 @@ config GENERIC_CMOS_UPDATE def_bool y config ARCH_USES_GETTIMEOFFSET - def_bool y + def_bool n config GENERIC_IOMAP bool @@ -131,16 +131,19 @@ choice config ETRAX100LX bool "ETRAX-100LX-v1" + select ARCH_USES_GETTIMEOFFSET help Support version 1 of the ETRAX 100LX. config ETRAX100LX_V2 bool "ETRAX-100LX-v2" + select ARCH_USES_GETTIMEOFFSET help Support version 2 of the ETRAX 100LX. config SVINTO_SIM bool "ETRAX-100LX-for-xsim-simulator" + select ARCH_USES_GETTIMEOFFSET help Support the xsim ETRAX Simulator. diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c index 30adae594aef..00eb36f8debf 100644 --- a/arch/cris/arch-v10/kernel/time.c +++ b/arch/cris/arch-v10/kernel/time.c @@ -61,66 +61,16 @@ unsigned long get_ns_in_jiffie(void) unsigned long do_slow_gettimeoffset(void) { - unsigned long count, t1; - unsigned long usec_count = 0; - unsigned short presc_count; - - static unsigned long count_p = TIMER0_DIV;/* for the first call after boot */ - static unsigned long jiffies_p = 0; - - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; + unsigned long count; /* The timer interrupt comes from Etrax timer 0. In order to get * better precision, we check the current value. It might have * underflowed already though. */ - -#ifndef CONFIG_SVINTO_SIM - /* Not available in the xsim simulator. */ count = *R_TIMER0_DATA; - presc_count = *R_TIM_PRESC_STATUS; - /* presc_count might be wrapped */ - t1 = *R_TIMER0_DATA; - if (count != t1){ - /* it wrapped, read prescaler again... */ - presc_count = *R_TIM_PRESC_STATUS; - count = t1; - } -#else - count = 0; - presc_count = 0; -#endif - jiffies_t = jiffies; - - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there are one problem that must be avoided here: - * 1. the timer counter underflows - */ - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* Timer wrapped, use new count and prescale - * increase the time corresponding to one jiffie - */ - usec_count = 1000000/HZ; - } - } else - jiffies_p = jiffies_t; - count_p = count; - if (presc_count >= PRESCALE_VALUE/2 ){ - presc_count = PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2; - } else { - presc_count = PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2; - } /* Convert timer value to usec */ - usec_count += ( (TIMER0_DIV - count) * (1000000/HZ)/TIMER0_DIV ) + - (( (presc_count) * (1000000000/PRESCALE_FREQ))/1000); - - return usec_count; + return (TIMER0_DIV - count) * ((NSEC_PER_SEC/1000)/HZ)/TIMER0_DIV; } /* Excerpt from the Etrax100 HSDD about the built-in watchdog: diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c index 1ee0e1010228..a545211e999d 100644 --- a/arch/cris/arch-v32/kernel/time.c +++ b/arch/cris/arch-v32/kernel/time.c @@ -1,13 +1,13 @@ /* * linux/arch/cris/arch-v32/kernel/time.c * - * Copyright (C) 2003-2007 Axis Communications AB + * Copyright (C) 2003-2010 Axis Communications AB * */ #include #include -#include +#include #include #include #include @@ -36,6 +36,30 @@ /* Number of 763 counts before watchdog bites */ #define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) +/* Register the continuos readonly timer available in FS and ARTPEC-3. */ +static cycle_t read_cont_rotime(struct clocksource *cs) +{ + return (u32)REG_RD(timer, regi_timer0, r_time); +} + +static struct clocksource cont_rotime = { + .name = "crisv32_rotime", + .rating = 300, + .read = read_cont_rotime, + .mask = CLOCKSOURCE_MASK(32), + .shift = 10, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int __init etrax_init_cont_rotime(void) +{ + cont_rotime.mult = clocksource_khz2mult(100000, cont_rotime.shift); + clocksource_register(&cont_rotime); + return 0; +} +arch_initcall(etrax_init_cont_rotime); + + unsigned long timer_regs[NR_CPUS] = { regi_timer0, @@ -67,43 +91,6 @@ unsigned long get_ns_in_jiffie(void) return ns; } -unsigned long do_slow_gettimeoffset(void) -{ - unsigned long count; - unsigned long usec_count = 0; - - /* For the first call after boot */ - static unsigned long count_p = TIMER0_DIV; - static unsigned long jiffies_p = 0; - - /* Cache volatile jiffies temporarily; we have IRQs turned off. */ - unsigned long jiffies_t; - - /* The timer interrupt comes from Etrax timer 0. In order to get - * better precision, we check the current value. It might have - * underflowed already though. */ - count = REG_RD(timer, regi_timer0, r_tmr0_data); - jiffies_t = jiffies; - - /* Avoiding timer inconsistencies (they are rare, but they happen) - * There is one problem that must be avoided here: - * 1. the timer counter underflows - */ - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* Timer wrapped, use new count and prescale. - * Increase the time corresponding to one jiffy. - */ - usec_count = 1000000/HZ; - } - } else - jiffies_p = jiffies_t; - count_p = count; - /* Convert timer value to usec */ - /* 100 MHz timer, divide by 100 to get usec */ - usec_count += (TIMER0_DIV - count) / 100; - return usec_count; -} /* From timer MDS describing the hardware watchdog: * 4.3.1 Watchdog Operation @@ -126,8 +113,7 @@ static short int watchdog_key = 42; /* arbitrary 7 bit number */ * is used though, so set this really low. */ #define WATCHDOG_MIN_FREE_PAGES 8 -void -reset_watchdog(void) +void reset_watchdog(void) { #if defined(CONFIG_ETRAX_WATCHDOG) reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; @@ -147,8 +133,7 @@ reset_watchdog(void) /* stop the watchdog - we still need the correct key */ -void -stop_watchdog(void) +void stop_watchdog(void) { #if defined(CONFIG_ETRAX_WATCHDOG) reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; @@ -162,8 +147,7 @@ stop_watchdog(void) extern void show_registers(struct pt_regs *regs); -void -handle_watchdog_bite(struct pt_regs* regs) +void handle_watchdog_bite(struct pt_regs *regs) { #if defined(CONFIG_ETRAX_WATCHDOG) extern int cause_of_death; @@ -203,8 +187,7 @@ handle_watchdog_bite(struct pt_regs* regs) */ extern void cris_do_profile(struct pt_regs *regs); -static inline irqreturn_t -timer_interrupt(int irq, void *dev_id) +static inline irqreturn_t timer_interrupt(int irq, void *dev_id) { struct pt_regs *regs = get_irq_regs(); int cpu = smp_processor_id(); @@ -233,7 +216,9 @@ timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; /* Call the real timer interrupt handler */ + write_seqlock(&xtime_lock); do_timer(1); + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } @@ -246,8 +231,7 @@ static struct irqaction irq_timer = { .name = "timer" }; -void __init -cris_timer_init(void) +void __init cris_timer_init(void) { int cpu = smp_processor_id(); reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 }; @@ -273,8 +257,7 @@ cris_timer_init(void) REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask); } -void __init -time_init(void) +void __init time_init(void) { reg_intr_vect_rw_mask intr_mask; diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c index c72730d20ef6..b5096430ce1c 100644 --- a/arch/cris/kernel/time.c +++ b/arch/cris/kernel/time.c @@ -39,13 +39,16 @@ int have_rtc; /* used to remember if we have an RTC or not */; extern unsigned long loops_per_jiffy; /* init/main.c */ unsigned long loops_per_usec; + +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET extern unsigned long do_slow_gettimeoffset(void); static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; u32 arch_gettimeoffset(void) { - return do_gettimeoffset() * 1000; + return do_gettimeoffset() * 1000; } +#endif /* * BUG: This routine does not handle hour overflow properly; it just @@ -151,7 +154,7 @@ cris_do_profile(struct pt_regs* regs) unsigned long long sched_clock(void) { - return (unsigned long long)jiffies * (1000000000 / HZ) + + return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ) + get_ns_in_jiffie(); } From 3648bdf79f7e020c3a28c9c842111879d8e506c0 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Fri, 30 Jul 2010 18:34:16 +0200 Subject: [PATCH 03/51] CRIS: invoke oom-killer from page fault As explained in commit 1c0fe6e3bd, we want to call the architecture independent oom killer when getting an unexplained OOM from handle_mm_fault, rather than simply killing current. Signed-off-by: Nick Piggin Acked-by: David Rientjes Signed-off-by: Jesper Nilsson Signed-off-by: Mikael Starvik --- arch/cris/mm/fault.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index 380df1a73a6e..52b32b092603 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -245,10 +245,10 @@ do_page_fault(unsigned long address, struct pt_regs *regs, out_of_memory: up_read(&mm->mmap_sem); - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_exit(SIGKILL); - goto no_context; + if (!user_mode(regs)) + goto no_context; + pagefault_out_of_memory(); + return; do_sigbus: up_read(&mm->mmap_sem); From 90276a1a64e2ab732e26e3ac68febbf3ad04c517 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Fri, 30 Jul 2010 19:04:37 +0200 Subject: [PATCH 04/51] cris: Pushdown the bkl from ioctl From: Frederic Weisbecker Pushdown the bkl to the remaining drivers using the deprecated .ioctl. Signed-off-by: Frederic Weisbecker Signed-off-by: Arnd Bergmann Signed-off-by: Jesper Nilsson Cc: Thomas Gleixner Cc: John Kacur --- arch/cris/arch-v10/drivers/gpio.c | 30 ++++++++++++++------- arch/cris/arch-v10/drivers/i2c.c | 22 +++++++++++----- arch/cris/arch-v10/drivers/sync_serial.c | 30 ++++++++++++++------- arch/cris/arch-v32/drivers/cryptocop.c | 26 +++++++++++++----- arch/cris/arch-v32/drivers/mach-a3/gpio.c | 28 +++++++++++++------- arch/cris/arch-v32/drivers/mach-fs/gpio.c | 32 ++++++++++++++--------- arch/cris/arch-v32/drivers/sync_serial.c | 30 ++++++++++++++------- 7 files changed, 137 insertions(+), 61 deletions(-) diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c index 4b0f65fac8e8..080927ffe63b 100644 --- a/arch/cris/arch-v10/drivers/gpio.c +++ b/arch/cris/arch-v10/drivers/gpio.c @@ -46,8 +46,7 @@ static char gpio_name[] = "etrax gpio"; static wait_queue_head_t *gpio_wq; #endif -static int gpio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static int gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static ssize_t gpio_write(struct file *file, const char __user *buf, size_t count, loff_t *off); static int gpio_open(struct inode *inode, struct file *filp); @@ -505,8 +504,7 @@ static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg); static int -gpio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { unsigned long flags; unsigned long val; @@ -683,6 +681,18 @@ gpio_ioctl(struct inode *inode, struct file *file, return ret; } +static int +gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = gpio_ioctl_unlocked(file, cmd, arg); + unlock_kernel(); + + return ret; +} + static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg) { @@ -713,12 +723,12 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg) } static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .poll = gpio_poll, - .ioctl = gpio_ioctl, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, + .owner = THIS_MODULE, + .poll = gpio_poll, + .unlocked_ioctl = gpio_ioctl, + .write = gpio_write, + .open = gpio_open, + .release = gpio_release, }; static void ioif_watcher(const unsigned int gpio_in_available, diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index a8737a8eb229..399e089bed7a 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c @@ -580,8 +580,7 @@ i2c_release(struct inode *inode, struct file *filp) */ static int -i2c_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +i2c_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { return -EINVAL; @@ -617,11 +616,22 @@ i2c_ioctl(struct inode *inode, struct file *file, return 0; } +static long i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = i2c_ioctl_unlocked(file, cmd, arg); + unlock_kernel(); + + return ret; +} + static const struct file_operations i2c_fops = { - .owner = THIS_MODULE, - .ioctl = i2c_ioctl, - .open = i2c_open, - .release = i2c_release, + .owner = THIS_MODULE, + .unlocked_ioctl = i2c_ioctl, + .open = i2c_open, + .release = i2c_release, }; int __init diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c index 109dcd826d17..ee2dd4323daf 100644 --- a/arch/cris/arch-v10/drivers/sync_serial.c +++ b/arch/cris/arch-v10/drivers/sync_serial.c @@ -157,7 +157,7 @@ static int sync_serial_open(struct inode *inode, struct file *file); static int sync_serial_release(struct inode *inode, struct file *file); static unsigned int sync_serial_poll(struct file *filp, poll_table *wait); -static int sync_serial_ioctl(struct inode *inode, struct file *file, +static int sync_serial_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static ssize_t sync_serial_write(struct file *file, const char *buf, size_t count, loff_t *ppos); @@ -244,13 +244,13 @@ static unsigned sync_serial_prescale_shadow; #define NUMBER_OF_PORTS 2 static const struct file_operations sync_serial_fops = { - .owner = THIS_MODULE, - .write = sync_serial_write, - .read = sync_serial_read, - .poll = sync_serial_poll, - .ioctl = sync_serial_ioctl, - .open = sync_serial_open, - .release = sync_serial_release + .owner = THIS_MODULE, + .write = sync_serial_write, + .read = sync_serial_read, + .poll = sync_serial_poll, + .unlocked_ioctl = sync_serial_ioctl, + .open = sync_serial_open, + .release = sync_serial_release }; static int __init etrax_sync_serial_init(void) @@ -678,7 +678,7 @@ static unsigned int sync_serial_poll(struct file *file, poll_table *wait) return mask; } -static int sync_serial_ioctl(struct inode *inode, struct file *file, +static int sync_serial_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { int return_val = 0; @@ -956,6 +956,18 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, return return_val; } +static long sync_serial_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = sync_serial_ioctl_unlocked(file, cmd, arg); + unlock_kernel(); + + return ret; +} + static ssize_t sync_serial_write(struct file *file, const char *buf, size_t count, loff_t *ppos) diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index b70fb34939d9..9cfbfae107c7 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -217,7 +217,7 @@ static int cryptocop_open(struct inode *, struct file *); static int cryptocop_release(struct inode *, struct file *); -static int cryptocop_ioctl(struct inode *inode, struct file *file, +static long cryptocop_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static void cryptocop_start_job(void); @@ -279,10 +279,10 @@ static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op); const struct file_operations cryptocop_fops = { - .owner = THIS_MODULE, - .open = cryptocop_open, - .release = cryptocop_release, - .ioctl = cryptocop_ioctl + .owner = THIS_MODULE, + .open = cryptocop_open, + .release = cryptocop_release, + .unlocked_ioctl = cryptocop_ioctl }; @@ -3102,7 +3102,8 @@ static int cryptocop_ioctl_create_session(struct inode *inode, struct file *filp return 0; } -static int cryptocop_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +static long cryptocop_ioctl_unlocked(struct inode *inode, + struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; if (_IOC_TYPE(cmd) != ETRAXCRYPTOCOP_IOCTYPE) { @@ -3134,6 +3135,19 @@ static int cryptocop_ioctl(struct inode *inode, struct file *filp, unsigned int return 0; } +static long +cryptocop_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file->f_path.dentry->d_inode; + long ret; + + lock_kernel(); + ret = cryptocop_ioctl_unlocked(inode, filp, cmd, arg); + unlock_kernel(); + + return ret; +} + #ifdef LDEBUG static void print_dma_descriptors(struct cryptocop_int_operation *iop) diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c index 97357cfd17bb..2dcd27adbad4 100644 --- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c +++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c @@ -72,8 +72,7 @@ static char gpio_name[] = "etrax gpio"; static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); #endif -static int gpio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static ssize_t gpio_write(struct file *file, const char __user *buf, size_t count, loff_t *off); static int gpio_open(struct inode *inode, struct file *filp); @@ -521,7 +520,7 @@ static inline unsigned long setget_output(struct gpio_private *priv, return dir_shadow; } /* setget_output */ -static int gpio_ioctl(struct inode *inode, struct file *file, +static long gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { unsigned long flags; @@ -664,6 +663,17 @@ static int gpio_ioctl(struct inode *inode, struct file *file, return 0; } +static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = gpio_ioctl_unlocked(file, cmd, arg); + unlock_kernel(); + + return ret; +} + #ifdef CONFIG_ETRAX_VIRTUAL_GPIO static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -877,12 +887,12 @@ static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, } static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .poll = gpio_poll, - .ioctl = gpio_ioctl, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, + .owner = THIS_MODULE, + .poll = gpio_poll, + .unlocked_ioctl = gpio_ioctl, + .write = gpio_write, + .open = gpio_open, + .release = gpio_release, }; #ifdef CONFIG_ETRAX_VIRTUAL_GPIO diff --git a/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c index d89ab80498ed..3a12ce309e3b 100644 --- a/arch/cris/arch-v32/drivers/mach-fs/gpio.c +++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c @@ -74,8 +74,7 @@ static wait_queue_head_t *gpio_wq; static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); #endif -static int gpio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static ssize_t gpio_write(struct file *file, const char *buf, size_t count, loff_t *off); static int gpio_open(struct inode *inode, struct file *filp); @@ -557,12 +556,10 @@ inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg) return dir_shadow; } /* setget_output */ -static int -gpio_leds_ioctl(unsigned int cmd, unsigned long arg); +static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg); static int -gpio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { unsigned long flags; unsigned long val; @@ -707,6 +704,17 @@ gpio_ioctl(struct inode *inode, struct file *file, return 0; } +static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = gpio_ioctl_unlocked(file, cmd, arg); + unlock_kernel(); + + return ret; +} + #ifdef CONFIG_ETRAX_VIRTUAL_GPIO static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -856,12 +864,12 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg) } static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .poll = gpio_poll, - .ioctl = gpio_ioctl, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, + .owner = THIS_MODULE, + .poll = gpio_poll, + .unlocked_ioctl = gpio_ioctl, + .write = gpio_write, + .open = gpio_open, + .release = gpio_release, }; #ifdef CONFIG_ETRAX_VIRTUAL_GPIO diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index 4889f196ecd6..ca248f3adb80 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c @@ -153,7 +153,7 @@ static int sync_serial_open(struct inode *, struct file*); static int sync_serial_release(struct inode*, struct file*); static unsigned int sync_serial_poll(struct file *filp, poll_table *wait); -static int sync_serial_ioctl(struct inode*, struct file*, +static int sync_serial_ioctl(struct file *, unsigned int cmd, unsigned long arg); static ssize_t sync_serial_write(struct file * file, const char * buf, size_t count, loff_t *ppos); @@ -241,13 +241,13 @@ static struct sync_port ports[]= #define NBR_PORTS ARRAY_SIZE(ports) static const struct file_operations sync_serial_fops = { - .owner = THIS_MODULE, - .write = sync_serial_write, - .read = sync_serial_read, - .poll = sync_serial_poll, - .ioctl = sync_serial_ioctl, - .open = sync_serial_open, - .release = sync_serial_release + .owner = THIS_MODULE, + .write = sync_serial_write, + .read = sync_serial_read, + .poll = sync_serial_poll, + .unlocked_ioctl = sync_serial_ioctl, + .open = sync_serial_open, + .release = sync_serial_release }; static int __init etrax_sync_serial_init(void) @@ -650,7 +650,7 @@ static unsigned int sync_serial_poll(struct file *file, poll_table *wait) return mask; } -static int sync_serial_ioctl(struct inode *inode, struct file *file, +static int sync_serial_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int return_val = 0; @@ -961,6 +961,18 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, return return_val; } +static long sync_serial_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = sync_serial_ioctl_unlocked(file, cmd, arg); + unlock_kernel(); + + return ret; +} + /* NOTE: sync_serial_write does not support concurrency */ static ssize_t sync_serial_write(struct file *file, const char *buf, size_t count, loff_t *ppos) From 096b7bdc8663c16417ff5fbec42622302e6886e1 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Fri, 30 Jul 2010 19:15:24 +0200 Subject: [PATCH 05/51] cris: autoconvert trivial BKL users to private mutex All these files use the big kernel lock in a trivial way to serialize their private file operations, typically resulting from an earlier semi-automatic pushdown from VFS. None of these drivers appears to want to lock against other code, and they all use the BKL as the top-level lock in their file operations, meaning that there is no lock-order inversion problem. Consequently, we can remove the BKL completely, replacing it with a per-file mutex in every case. Using a scripted approach means we can avoid typos. file=$1 name=$2 if grep -q lock_kernel ${file} ; then if grep -q 'include.*linux.mutex.h' ${file} ; then sed -i '/include.*/d' ${file} else sed -i 's/include.*.*$/include /g' ${file} fi sed -i ${file} \ -e "/^#include.*linux.mutex.h/,$ { 1,/^\(static\|int\|long\)/ { /^\(static\|int\|long\)/istatic DEFINE_MUTEX(${name}_mutex); } }" \ -e "s/\(un\)*lock_kernel\>[ ]*()/mutex_\1lock(\&${name}_mutex)/g" \ -e '/[ ]*cycle_kernel_lock();/d' else sed -i -e '/include.*\/d' ${file} \ -e '/cycle_kernel_lock()/d' fi Signed-off-by: Arnd Bergmann Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/drivers/eeprom.c | 2 -- arch/cris/arch-v10/drivers/i2c.c | 2 -- arch/cris/arch-v32/drivers/cryptocop.c | 2 -- arch/cris/arch-v32/drivers/i2c.c | 12 ++++++------ 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c index c3405507a3d1..5047a33043bd 100644 --- a/arch/cris/arch-v10/drivers/eeprom.c +++ b/arch/cris/arch-v10/drivers/eeprom.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include "i2c.h" @@ -376,7 +375,6 @@ int __init eeprom_init(void) /* Opens the device. */ static int eeprom_open(struct inode * inode, struct file * file) { - cycle_kernel_lock(); if(iminor(inode) != EEPROM_MINOR_NR) return -ENXIO; if(imajor(inode) != EEPROM_MAJOR_NR) diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index 399e089bed7a..54e2e1adf085 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -566,7 +565,6 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) static int i2c_open(struct inode *inode, struct file *filp) { - cycle_kernel_lock(); return 0; } diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index 9cfbfae107c7..b07646a30509 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -2307,7 +2306,6 @@ static int cryptocop_open(struct inode *inode, struct file *filp) { int p = iminor(inode); - cycle_kernel_lock(); if (p != CRYPTOCOP_MINOR) return -EINVAL; filp->private_data = NULL; diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c index 2fd6a740d895..5a3e900c9a78 100644 --- a/arch/cris/arch-v32/drivers/i2c.c +++ b/arch/cris/arch-v32/drivers/i2c.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include @@ -47,6 +47,7 @@ #define D(x) #define I2C_MAJOR 123 /* LOCAL/EXPERIMENTAL */ +static DEFINE_MUTEX(i2c_mutex); static const char i2c_name[] = "i2c"; #define CLOCK_LOW_TIME 8 @@ -636,7 +637,6 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) static int i2c_open(struct inode *inode, struct file *filp) { - cycle_kernel_lock(); return 0; } @@ -665,11 +665,11 @@ i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) I2C_ARGREG(arg), I2C_ARGVALUE(arg))); - lock_kernel(); + mutex_lock(&i2c_mutex); ret = i2c_writereg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg), I2C_ARGVALUE(arg)); - unlock_kernel(); + mutex_unlock(&i2c_mutex); return ret; case I2C_READREG: @@ -679,9 +679,9 @@ i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) D(printk("i2cr %d %d ", I2C_ARGSLAVE(arg), I2C_ARGREG(arg))); - lock_kernel(); + mutex_lock(&i2c_mutex); val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg)); - unlock_kernel(); + mutex_unlock(&i2c_mutex); D(printk("= %d\n", val)); return val; } From 16bc0fe5ce84df89c8e802be210af88721d4cc4f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 12 Jul 2010 22:49:53 +0200 Subject: [PATCH 06/51] arch/cris: Remove unnecessary casts of private_data Signed-off-by: Joe Perches Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/drivers/mach-fs/gpio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c index 3a12ce309e3b..5ec8a7d4e7d7 100644 --- a/arch/cris/arch-v32/drivers/mach-fs/gpio.c +++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c @@ -184,7 +184,7 @@ static volatile unsigned long *dir_oe[NUM_PORTS] = { static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait) { unsigned int mask = 0; - struct gpio_private *priv = (struct gpio_private *)file->private_data; + struct gpio_private *priv = file->private_data; unsigned long data; poll_wait(file, &priv->alarm_wq, wait); if (priv->minor == GPIO_MINOR_A) { @@ -352,7 +352,7 @@ gpio_pa_interrupt(int irq, void *dev_id) static ssize_t gpio_write(struct file *file, const char *buf, size_t count, loff_t *off) { - struct gpio_private *priv = (struct gpio_private *)file->private_data; + struct gpio_private *priv = file->private_data; unsigned char data, clk_mask, data_mask, write_msb; unsigned long flags; unsigned long shadow; @@ -467,7 +467,7 @@ gpio_release(struct inode *inode, struct file *filp) spin_lock_irq(&alarm_lock); p = alarmlist; - todel = (struct gpio_private *)filp->private_data; + todel = filp->private_data; if (p == todel) { alarmlist = todel->next; @@ -564,7 +564,7 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) unsigned long flags; unsigned long val; unsigned long shadow; - struct gpio_private *priv = (struct gpio_private *)file->private_data; + struct gpio_private *priv = file->private_data; if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) return -EINVAL; @@ -722,7 +722,7 @@ virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) unsigned long flags; unsigned short val; unsigned short shadow; - struct gpio_private *priv = (struct gpio_private *)file->private_data; + struct gpio_private *priv = file->private_data; switch (_IOC_NR(cmd)) { case IO_SETBITS: From 60362158e2419b20cc04d43a6ffa60c1845775dc Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 13:17:05 +0200 Subject: [PATCH 07/51] CRIS: gpio: don't call copy_to_user()/copy_from_user() while holding spinlocks copy_to_user()/copy_from_user() must not be used with spinlocks held. Move locks inside each case so we have better control of when the locks are held. Also, since we use spinlocks, we don't need to hold the BKL, so remove it. Reported-by: Kulikov Vasiliy Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/drivers/gpio.c | 80 ++++++++++++++++++------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c index 080927ffe63b..a07b6d25b0c7 100644 --- a/arch/cris/arch-v10/drivers/gpio.c +++ b/arch/cris/arch-v10/drivers/gpio.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -46,7 +45,7 @@ static char gpio_name[] = "etrax gpio"; static wait_queue_head_t *gpio_wq; #endif -static int gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static ssize_t gpio_write(struct file *file, const char __user *buf, size_t count, loff_t *off); static int gpio_open(struct inode *inode, struct file *filp); @@ -323,7 +322,6 @@ gpio_open(struct inode *inode, struct file *filp) if (!priv) return -ENOMEM; - lock_kernel(); priv->minor = p; /* initialize the io/alarm struct */ @@ -358,7 +356,6 @@ gpio_open(struct inode *inode, struct file *filp) alarmlist = priv; spin_unlock_irqrestore(&gpio_lock, flags); - unlock_kernel(); return 0; } @@ -503,8 +500,7 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg) static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg); -static int -gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) +static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned long flags; unsigned long val; @@ -514,54 +510,65 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) return -EINVAL; - spin_lock_irqsave(&gpio_lock, flags); - switch (_IOC_NR(cmd)) { case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ // read the port + spin_lock_irqsave(&gpio_lock, flags); if (USE_PORTS(priv)) { ret = *priv->port; } else if (priv->minor == GPIO_MINOR_G) { ret = (*R_PORT_G_DATA) & 0x7FFFFFFF; } + spin_unlock_irqrestore(&gpio_lock, flags); + break; case IO_SETBITS: // set changeable bits with a 1 in arg + spin_lock_irqsave(&gpio_lock, flags); + if (USE_PORTS(priv)) { - *priv->port = *priv->shadow |= + *priv->port = *priv->shadow |= ((unsigned char)arg & priv->changeable_bits); } else if (priv->minor == GPIO_MINOR_G) { *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits); } + spin_unlock_irqrestore(&gpio_lock, flags); + break; case IO_CLRBITS: // clear changeable bits with a 1 in arg + spin_lock_irqsave(&gpio_lock, flags); if (USE_PORTS(priv)) { - *priv->port = *priv->shadow &= + *priv->port = *priv->shadow &= ~((unsigned char)arg & priv->changeable_bits); } else if (priv->minor == GPIO_MINOR_G) { *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits); } + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_HIGHALARM: // set alarm when bits with 1 in arg go high + spin_lock_irqsave(&gpio_lock, flags); priv->highalarm |= arg; gpio_some_alarms = 1; + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_LOWALARM: // set alarm when bits with 1 in arg go low + spin_lock_irqsave(&gpio_lock, flags); priv->lowalarm |= arg; gpio_some_alarms = 1; + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_CLRALARM: - // clear alarm for bits with 1 in arg + /* clear alarm for bits with 1 in arg */ + spin_lock_irqsave(&gpio_lock, flags); priv->highalarm &= ~arg; priv->lowalarm &= ~arg; { /* Must update gpio_some_alarms */ struct gpio_private *p = alarmlist; int some_alarms; - spin_lock_irq(&gpio_lock); p = alarmlist; some_alarms = 0; while (p) { @@ -572,11 +579,12 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) p = p->next; } gpio_some_alarms = some_alarms; - spin_unlock_irq(&gpio_lock); } + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ /* Read direction 0=input 1=output */ + spin_lock_irqsave(&gpio_lock, flags); if (USE_PORTS(priv)) { ret = *priv->dir_shadow; } else if (priv->minor == GPIO_MINOR_G) { @@ -585,30 +593,40 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) */ ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF; } + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ - /* Set direction 0=unchanged 1=input, - * return mask with 1=input + /* Set direction 0=unchanged 1=input, + * return mask with 1=input */ + spin_lock_irqsave(&gpio_lock, flags); ret = setget_input(priv, arg) & 0x7FFFFFFF; + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ - /* Set direction 0=unchanged 1=output, - * return mask with 1=output + /* Set direction 0=unchanged 1=output, + * return mask with 1=output */ + spin_lock_irqsave(&gpio_lock, flags); ret = setget_output(priv, arg) & 0x7FFFFFFF; + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_SHUTDOWN: + spin_lock_irqsave(&gpio_lock, flags); SOFT_SHUTDOWN(); + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_GET_PWR_BT: + spin_lock_irqsave(&gpio_lock, flags); #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN) ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT)); #else ret = 0; #endif + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_CFG_WRITE_MODE: + spin_lock_irqsave(&gpio_lock, flags); priv->clk_mask = arg & 0xFF; priv->data_mask = (arg >> 8) & 0xFF; priv->write_msb = (arg >> 16) & 0x01; @@ -624,28 +642,33 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) priv->data_mask = 0; ret = -EPERM; } + spin_unlock_irqrestore(&gpio_lock, flags); break; - case IO_READ_INBITS: + case IO_READ_INBITS: /* *arg is result of reading the input pins */ + spin_lock_irqsave(&gpio_lock, flags); if (USE_PORTS(priv)) { val = *priv->port; } else if (priv->minor == GPIO_MINOR_G) { val = *R_PORT_G_DATA; } + spin_unlock_irqrestore(&gpio_lock, flags); if (copy_to_user((void __user *)arg, &val, sizeof(val))) ret = -EFAULT; break; case IO_READ_OUTBITS: /* *arg is result of reading the output shadow */ + spin_lock_irqsave(&gpio_lock, flags); if (USE_PORTS(priv)) { val = *priv->shadow; } else if (priv->minor == GPIO_MINOR_G) { val = port_g_data_shadow; } + spin_unlock_irqrestore(&gpio_lock, flags); if (copy_to_user((void __user *)arg, &val, sizeof(val))) ret = -EFAULT; break; - case IO_SETGET_INPUT: + case IO_SETGET_INPUT: /* bits set in *arg is set to input, * *arg updated with current input pins. */ @@ -654,7 +677,9 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) ret = -EFAULT; break; } + spin_lock_irqsave(&gpio_lock, flags); val = setget_input(priv, val); + spin_unlock_irqrestore(&gpio_lock, flags); if (copy_to_user((void __user *)arg, &val, sizeof(val))) ret = -EFAULT; break; @@ -666,33 +691,24 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) ret = -EFAULT; break; } + spin_lock_irqsave(&gpio_lock, flags); val = setget_output(priv, val); + spin_unlock_irqrestore(&gpio_lock, flags); if (copy_to_user((void __user *)arg, &val, sizeof(val))) ret = -EFAULT; break; default: + spin_lock_irqsave(&gpio_lock, flags); if (priv->minor == GPIO_MINOR_LEDS) ret = gpio_leds_ioctl(cmd, arg); else ret = -EINVAL; + spin_unlock_irqrestore(&gpio_lock, flags); } /* switch */ - spin_unlock_irqrestore(&gpio_lock, flags); return ret; } -static int -gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - lock_kernel(); - ret = gpio_ioctl_unlocked(file, cmd, arg); - unlock_kernel(); - - return ret; -} - static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg) { From 0e0aff21261aba52ee37b59fcf48202230fc7377 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 13:46:12 +0200 Subject: [PATCH 08/51] CRIS: v10: remove all BKL usage We don't need to take the BKL here. Also fixes compile error after last commit (smp_lock.h was not included) Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/drivers/i2c.c | 39 +++++++++++--------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index 54e2e1adf085..77a941813819 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c @@ -59,8 +59,8 @@ static const char i2c_name[] = "i2c"; #define SDABIT CONFIG_ETRAX_I2C_DATA_PORT #define SCLBIT CONFIG_ETRAX_I2C_CLK_PORT -#define i2c_enable() -#define i2c_disable() +#define i2c_enable() +#define i2c_disable() /* enable or disable output-enable, to select output or input on the i2c bus */ @@ -90,7 +90,7 @@ static const char i2c_name[] = "i2c"; #define i2c_dir_out() \ *R_PORT_PB_I2C = (port_pb_i2c_shadow &= ~IO_MASK(R_PORT_PB_I2C, i2c_oe_)); \ - REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, 0, 1); + REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, 0, 1); #define i2c_dir_in() \ *R_PORT_PB_I2C = (port_pb_i2c_shadow |= IO_MASK(R_PORT_PB_I2C, i2c_oe_)); \ REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, 0, 0); @@ -188,7 +188,7 @@ i2c_outbyte(unsigned char x) } else { i2c_data(I2C_DATA_LOW); } - + i2c_delay(CLOCK_LOW_TIME/2); i2c_clk(I2C_CLOCK_HIGH); i2c_delay(CLOCK_HIGH_TIME); @@ -415,7 +415,7 @@ i2c_sendnack(void) *# *#--------------------------------------------------------------------------*/ int -i2c_writereg(unsigned char theSlave, unsigned char theReg, +i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue) { int error, cntr = 3; @@ -467,7 +467,7 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, * enable interrupt again */ local_irq_restore(flags); - + } while(error && cntr--); i2c_delay(CLOCK_LOW_TIME); @@ -503,7 +503,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) * generate start condition */ i2c_start(); - + /* * send slave address */ @@ -554,7 +554,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) * enable interrupt again */ local_irq_restore(flags); - + } while(error && cntr--); spin_unlock(&i2c_lock); @@ -577,8 +577,7 @@ i2c_release(struct inode *inode, struct file *filp) /* Main device API. ioctl's to write or read to/from i2c registers. */ -static int -i2c_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) +static long i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { return -EINVAL; @@ -587,7 +586,7 @@ i2c_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) switch (_IOC_NR(cmd)) { case I2C_WRITEREG: /* write to an i2c slave */ - D(printk("i2cw %d %d %d\n", + D(printk(KERN_DEBUG "i2cw %d %d %d\n", I2C_ARGSLAVE(arg), I2C_ARGREG(arg), I2C_ARGVALUE(arg))); @@ -599,32 +598,20 @@ i2c_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { unsigned char val; /* read from an i2c slave */ - D(printk("i2cr %d %d ", + D(printk(KERN_DEBUG "i2cr %d %d ", I2C_ARGSLAVE(arg), I2C_ARGREG(arg))); val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg)); - D(printk("= %d\n", val)); + D(printk(KERN_DEBUG "= %d\n", val)); return val; - } + } default: return -EINVAL; } - return 0; } -static long i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - lock_kernel(); - ret = i2c_ioctl_unlocked(file, cmd, arg); - unlock_kernel(); - - return ret; -} - static const struct file_operations i2c_fops = { .owner = THIS_MODULE, .unlocked_ioctl = i2c_ioctl, From fcb31dbb36bfaa96ceb64ed0924a828013429840 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 15:04:51 +0200 Subject: [PATCH 09/51] CRIS: Remove CVS tag. Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/drivers/i2c.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/cris/arch-v10/drivers/i2c.h b/arch/cris/arch-v10/drivers/i2c.h index 4ee91426bd40..e36c96276478 100644 --- a/arch/cris/arch-v10/drivers/i2c.h +++ b/arch/cris/arch-v10/drivers/i2c.h @@ -1,5 +1,4 @@ -/* $Id: i2c.h,v 1.3 2004/05/28 09:26:59 starvik Exp $ */ - +/* i2c.h */ int i2c_init(void); /* High level I2C actions */ From 5866d7ef9553c0107576dc1bc1d5c6acb68e8f87 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 15:09:22 +0200 Subject: [PATCH 10/51] CRIS: Better link to rs485 in help Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/drivers/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index 58f5864a6680..0d7221779923 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -383,7 +383,7 @@ config ETRAX_RS485 depends on ETRAX_SERIAL help Enables support for RS-485 serial communication. For a primer on - RS-485, see . + RS-485, see config ETRAX_RS485_ON_PA bool "RS-485 mode on PA" From d77eab8cb18dc4b8adfa82088e95b48c654c66b9 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 15:19:17 +0200 Subject: [PATCH 11/51] CRIS: Fasttimer: Remove obsolete ifdef Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/kernel/fasttimer.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index 5ff08a8695e9..8a8196ee8ce8 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c @@ -467,11 +467,7 @@ timer1_handler(int irq, void *dev_id) static void wake_up_func(unsigned long data) { -#ifdef DECLARE_WAITQUEUE - wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data; -#else - struct wait_queue **sleep_wait_p = (struct wait_queue **)data; -#endif + wait_queue_head_t *sleep_wait_p = (wait_queue_head_t *)data; wake_up(sleep_wait_p); } From b4973ae9dac3397499f5576c591d5c5bf51c68c6 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 17:48:31 +0200 Subject: [PATCH 12/51] CRIS: Correct address of the romfs in boot image The romfs should land after __init_end Signed-off-by: Jesper Nilsson --- arch/cris/arch-v10/kernel/head.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/arch-v10/kernel/head.S b/arch/cris/arch-v10/kernel/head.S index fc4577102933..a1f2014b4e3b 100644 --- a/arch/cris/arch-v10/kernel/head.S +++ b/arch/cris/arch-v10/kernel/head.S @@ -280,7 +280,7 @@ _no_romfs_in_flash: ;; the "rom fs" we'll possibly use in 2.4 if not JFFS (which does ;; not need this mechanism anyway) - move.d __vmlinux_end, $r0; the image will be after the vmlinux end address + move.d __init_end, $r0; the image will be after the end of init move.d [$r0], $r1 ; cramfs assumes same endian on host/target cmp.d CRAMFS_MAGIC, $r1; magic value in cramfs superblock bne 2f From a80a635f3d60e4aa61f96d22a122071cb061be93 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 18:05:17 +0200 Subject: [PATCH 13/51] CRIS: Add debug for assembler functions Signed-off-by: Edgar Iglesias Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/cacheflush.S | 5 +++++ arch/cris/arch-v32/kernel/entry.S | 25 ++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/arch/cris/arch-v32/kernel/cacheflush.S b/arch/cris/arch-v32/kernel/cacheflush.S index 956e8fb82f01..6fc3d95d7029 100644 --- a/arch/cris/arch-v32/kernel/cacheflush.S +++ b/arch/cris/arch-v32/kernel/cacheflush.S @@ -1,4 +1,5 @@ .global cris_flush_cache_range + .type cris_flush_cache_range, @function cris_flush_cache_range: move.d 1024, $r12 cmp.d $r11, $r12 @@ -80,8 +81,10 @@ cris_flush_1KB: addq 32, $r10 ba cris_flush_cache_range sub.d $r12, $r11 + .size cris_flush_cache_range, . - cris_flush_cache_range .global cris_flush_cache + .type cris_flush_cache, @function cris_flush_cache: moveq 0, $r10 cris_flush_line: @@ -92,3 +95,5 @@ cris_flush_line: fidxd [$r10] ret nop + .size cris_flush_cache, . - cris_flush_cache + diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 1f39861eac8c..7c14acb754a1 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -76,12 +76,15 @@ _need_resched: ; Called at exit from fork. schedule_tail must be called to drop ; spinlock if CONFIG_PREEMPT. + .type ret_from_fork,@function ret_from_fork: jsr schedule_tail nop ba ret_from_sys_call nop + .size ret_from_fork, . - ret_from_fork + .type ret_from_intr,@function ret_from_intr: ;; Check for resched if preemptive kernel, or if we're going back to ;; user-mode. This test matches the user_regs(regs) macro. Don't simply @@ -91,9 +94,10 @@ ret_from_intr: move.d [$acr], $r0 btstq 16, $r0 ; User-mode flag. bpl _resume_kernel + .size ret_from_intr, . - ret_from_intr + 2 ; +2 includes the dslot. ; Note that di below is in delay slot. - + .type _resume_userspace,@function _resume_userspace: di ; So need_resched and sigpending don't change. @@ -107,6 +111,7 @@ _resume_userspace: nop ba _Rexit nop + .size _resume_userspace, . - _resume_userspace ;; The system_call is called by a BREAK instruction, which looks pretty ;; much like any other exception. @@ -122,6 +127,7 @@ _resume_userspace: ;; non-used instructions. Only the non-common cases cause the outlined code ;; to run.. + .type system_call,@function system_call: ;; Stack-frame similar to the irq heads, which is reversed in ;; ret_from_sys_call. @@ -217,7 +223,9 @@ ret_from_sys_call: and.d _TIF_ALLWORK_MASK, $r1 bne _syscall_exit_work nop + .size system_call, . - system_call + .type _Rexit,@function _Rexit: ;; This epilogue MUST match the prologues in multiple_interrupt, irq.h ;; and ptregs.h. @@ -234,10 +242,12 @@ _Rexit: addq 8, $sp ; Skip EXS, EDA. jump $erp rfe ; Restore condition code stack in delay-slot. + .size _Rexit, . - _Rexit ;; We get here after doing a syscall if extra work might need to be done ;; perform syscall exit tracing if needed. + .type _syscall_exit_work,@function _syscall_exit_work: ;; R0 contains current at this point and irq's are disabled. @@ -253,14 +263,18 @@ _syscall_exit_work: move.d $r1, $r9 ba _resume_userspace nop + .size _syscall_exit_work, . - _syscall_exit_work + .type _work_pending,@function _work_pending: addoq +TI_flags, $r0, $acr move.d [$acr], $r10 btstq TIF_NEED_RESCHED, $r10 ; Need resched? bpl _work_notifysig ; No, must be signal/notify. nop + .size _work_pending, . - _work_pending + .type _work_resched,@function _work_resched: move.d $r9, $r1 ; Preserve R9. jsr schedule @@ -276,7 +290,9 @@ _work_resched: btstq TIF_NEED_RESCHED, $r1 bmi _work_resched ; current->work.need_resched. nop + .size _work_resched, . - _work_resched + .type _work_notifysig,@function _work_notifysig: ;; Deal with pending signals and notify-resume requests. @@ -288,6 +304,7 @@ _work_notifysig: ba _Rexit nop + .size _work_notifysig, . - _work_notifysig ;; We get here as a sidetrack when we've entered a syscall with the ;; trace-bit set. We need to call do_syscall_trace and then continue @@ -329,6 +346,7 @@ _syscall_trace_entry: ;; ;; Returns old current in R10. + .type resume,@function resume: subq 4, $sp move $srp, [$sp] ; Keep old/new PC on the stack. @@ -364,6 +382,7 @@ resume: move.d [$sp+], $acr jump $acr ; Restore PC. nop + .size resume, . - resume nmi_interrupt: @@ -426,6 +445,7 @@ spurious_interrupt: ;; time. Jump to the first set interrupt bit in a priotiry fashion. The ;; hardware will call the unserved interrupts after the handler ;; finishes. + .type multiple_interrupt, @function multiple_interrupt: ;; This prologue MUST match the one in irq.h and the struct in ptregs.h! subq 12, $sp ; Skip EXS, EDA. @@ -458,6 +478,7 @@ multiple_interrupt: move.d $sp, $r10 jump ret_from_intr nop + .size multiple_interrupt, . - multiple_interrupt do_sigtrap: ;; Sigtraps the process that executed the BREAK instruction. Creates a @@ -514,11 +535,13 @@ _ugdb_handle_exception: move.d [$sp+], $r0 ; Restore R0 in delay slot. .global kernel_execve + .type kernel_execve,@function kernel_execve: move.d __NR_execve, $r9 break 13 ret nop + .size kernel_execve, . - kernel_execve .data From 43f6cdd7693ddddb4db17a1ab591d506cb1fc110 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 18:09:56 +0200 Subject: [PATCH 14/51] CRIS: Simple insn reschedule to avoid interlocks. Brings down the CPI from ~1.5 to ~1.1. Signed-off-by: Edgar Iglesias Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/entry.S | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 7c14acb754a1..ce121df3aaef 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -348,40 +348,40 @@ _syscall_trace_entry: .type resume,@function resume: - subq 4, $sp - move $srp, [$sp] ; Keep old/new PC on the stack. + subq 4, $sp ; Make space for srp. + add.d $r12, $r10 ; R10 = current tasks tss. addoq +THREAD_ccs, $r10, $acr + move $srp, [$sp] ; Keep old/new PC on the stack. move $ccs, [$acr] ; Save IRQ enable state. di addoq +THREAD_usp, $r10, $acr + subq 10*4, $sp ; Make room for R9. move $usp, [$acr] ; Save user-mode stackpointer. ;; See copy_thread for the reason why register R9 is saved. - subq 10*4, $sp movem $r9, [$sp] ; Save non-scratch registers and R9. addoq +THREAD_ksp, $r10, $acr + move.d $sp, $r10 ; Return last running task in R10. move.d $sp, [$acr] ; Save kernel SP for old task. - move.d $sp, $r10 ; Return last running task in R10. and.d -8192, $r10 ; Get thread_info from stackpointer. addoq +TI_task, $r10, $acr - move.d [$acr], $r10 ; Get task. add.d $r12, $r11 ; Find the new tasks tss. + move.d [$acr], $r10 ; Get task. addoq +THREAD_ksp, $r11, $acr move.d [$acr], $sp ; Switch to new stackframe. + addoq +THREAD_usp, $r11, $acr movem [$sp+], $r9 ; Restore non-scratch registers and R9. - addoq +THREAD_usp, $r11, $acr move [$acr], $usp ; Restore user-mode stackpointer. addoq +THREAD_ccs, $r11, $acr + move.d [$sp+], $r11 + jump $r11 ; Restore PC. move [$acr], $ccs ; Restore IRQ enable status. - move.d [$sp+], $acr - jump $acr ; Restore PC. - nop .size resume, . - resume nmi_interrupt: From cd4f20110cf46ab7ca35ea32d601576b31abd9bb Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 18:13:45 +0200 Subject: [PATCH 15/51] CRIS: Faster syscall entry for CRISv32. Signed-off-by: Edgar Iglesias Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/entry.S | 37 ++++++++++++++----------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index ce121df3aaef..0ecb50b8f0d9 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -131,27 +131,24 @@ _resume_userspace: system_call: ;; Stack-frame similar to the irq heads, which is reversed in ;; ret_from_sys_call. - subq 12, $sp ; Skip EXS, EDA. - move $erp, [$sp] - subq 4, $sp - move $srp, [$sp] - subq 4, $sp - move $ccs, [$sp] - subq 4, $sp - ei ; Allow IRQs while handling system call - move $spc, [$sp] - subq 4, $sp - move $mof, [$sp] - subq 4, $sp - move $srs, [$sp] - subq 4, $sp - move.d $acr, [$sp] - subq 14*4, $sp ; Make room for R0-R13. - movem $r13, [$sp] ; Push R0-R13 - subq 4, $sp - move.d $r10, [$sp] ; Push orig_r10. -; Set S-bit when kernel debugging to keep hardware breakpoints active. + sub.d 92, $sp ; Skip EXS and EDA. + movem $r13, [$sp] + move.d $sp, $r8 + addq 14*4, $r8 + move.d $acr, $r0 + move $srs, $r1 + move $mof, $r2 + move $spc, $r3 + move $ccs, $r4 + move $srp, $r5 + move $erp, $r6 + subq 4, $sp + movem $r6, [$r8] + ei ; Enable interrupts while processing syscalls. + move.d $r10, [$sp] + + ; Set S-bit when kernel debugging to keep hardware breakpoints active. #ifdef CONFIG_ETRAX_KGDB move $ccs, $r0 or.d (1<<9), $r0 From 345c52e079001354809c17f84e164827e99f2aaa Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 18:22:09 +0200 Subject: [PATCH 16/51] CRIS: Additional mmu settings for ARTPEC-3 Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/head.S | 42 ++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S index 76266f80a5f1..5fe1513e447a 100644 --- a/arch/cris/arch-v32/kernel/head.S +++ b/arch/cris/arch-v32/kernel/head.S @@ -69,7 +69,13 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */ ;; ;; Note; 3 cycles is needed for a bank-select to take effect. Further; ;; bank 1 is the instruction MMU, bank 2 is the data MMU. -#ifndef CONFIG_ETRAX_VCS_SIM + +#ifdef CONFIG_CRIS_MACH_ARTPEC3 + move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ + | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ + | REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5) \ + | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 +#elif !defined(CONFIG_ETRAX_VCS_SIM) move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 @@ -88,7 +94,39 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */ ;; Enable certain page protections and setup linear mapping ;; for f,e,c,b,4,0. -#ifndef CONFIG_ETRAX_VCS_SIM + + ;; ARTPEC-3: + ;; c,d used for linear kernel mapping, up to 512 MB + ;; e used for vmalloc + ;; f unused, but page mapped to get page faults + + ;; ETRAX FS: + ;; c used for linear kernel mapping, up to 256 MB + ;; d used for vmalloc + ;; e,f used for memory-mapped NOR flash + +#ifdef CONFIG_CRIS_MACH_ARTPEC3 + move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ + | REG_STATE(mmu, rw_mm_cfg, acc, on) \ + | REG_STATE(mmu, rw_mm_cfg, ex, on) \ + | REG_STATE(mmu, rw_mm_cfg, inv, on) \ + | REG_STATE(mmu, rw_mm_cfg, seg_f, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_e, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_d, linear) \ + | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \ + | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \ + | REG_STATE(mmu, rw_mm_cfg, seg_a, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \ + | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \ + | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2 +#elif !defined(CONFIG_ETRAX_VCS_SIM) move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ | REG_STATE(mmu, rw_mm_cfg, acc, on) \ | REG_STATE(mmu, rw_mm_cfg, ex, on) \ From 403a1c4f1380b4ec842df5f4aa86e86ba02904f3 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Mon, 2 Aug 2010 18:23:39 +0200 Subject: [PATCH 17/51] CRIS: v32: Correct address for romfs in the image Is after __bss_start, not __vmlinux_end Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/head.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S index 5fe1513e447a..5d502b9ab56d 100644 --- a/arch/cris/arch-v32/kernel/head.S +++ b/arch/cris/arch-v32/kernel/head.S @@ -367,7 +367,7 @@ _no_romfs_in_flash: ;; For jffs2, a jhead is prepended which contains with magic and length. ;; The jhead is not part of the jffs2 partition however. #ifndef CONFIG_ETRAXFS_SIM - move.d __vmlinux_end, $r0 + move.d __bss_start, $r0 #else move.d __end, $r0 #endif From e75a320edab4170f28f6cce22d4ea5c15f13ecfa Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 13:52:45 +0200 Subject: [PATCH 18/51] CRIS: v32: Better irq mapping code Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/irq.c | 47 +++++++++++++++------------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c index 0b1febe44aa3..2ed48ae3d313 100644 --- a/arch/cris/arch-v32/kernel/irq.c +++ b/arch/cris/arch-v32/kernel/irq.c @@ -97,7 +97,11 @@ extern void breakh_BUG(void); /* * Build the IRQ handler stubs using macros from irq.h. */ +#ifdef CONFIG_CRIS_MACH_ARTPEC3 +BUILD_TIMER_IRQ(0x31, 0) +#else BUILD_IRQ(0x31) +#endif BUILD_IRQ(0x32) BUILD_IRQ(0x33) BUILD_IRQ(0x34) @@ -123,7 +127,11 @@ BUILD_IRQ(0x47) BUILD_IRQ(0x48) BUILD_IRQ(0x49) BUILD_IRQ(0x4a) +#ifdef CONFIG_ETRAXFS +BUILD_TIMER_IRQ(0x4b, 0) +#else BUILD_IRQ(0x4b) +#endif BUILD_IRQ(0x4c) BUILD_IRQ(0x4d) BUILD_IRQ(0x4e) @@ -199,25 +207,20 @@ block_irq(int irq, int cpu) unsigned long flags; spin_lock_irqsave(&irq_lock, flags); - if (irq - FIRST_IRQ < 32) + /* Remember, 1 let thru, 0 block. */ + if (irq - FIRST_IRQ < 32) { intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, 0); - else - intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], - rw_mask, 1); - - /* Remember; 1 let thru, 0 block. */ - if (irq - FIRST_IRQ < 32) intr_mask &= ~(1 << (irq - FIRST_IRQ)); - else - intr_mask &= ~(1 << (irq - FIRST_IRQ - 32)); - - if (irq - FIRST_IRQ < 32) REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, 0, intr_mask); - else + } else { + intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], + rw_mask, 1); + intr_mask &= ~(1 << (irq - FIRST_IRQ - 32)); REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, 1, intr_mask); + } spin_unlock_irqrestore(&irq_lock, flags); } @@ -228,26 +231,20 @@ unblock_irq(int irq, int cpu) unsigned long flags; spin_lock_irqsave(&irq_lock, flags); - if (irq - FIRST_IRQ < 32) + /* Remember, 1 let thru, 0 block. */ + if (irq - FIRST_IRQ < 32) { intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, 0); - else - intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], - rw_mask, 1); - - /* Remember; 1 let thru, 0 block. */ - if (irq - FIRST_IRQ < 32) intr_mask |= (1 << (irq - FIRST_IRQ)); - else - intr_mask |= (1 << (irq - FIRST_IRQ - 32)); - - if (irq - FIRST_IRQ < 32) REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, 0, intr_mask); - else + } else { + intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], + rw_mask, 1); + intr_mask |= (1 << (irq - FIRST_IRQ - 32)); REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, 1, intr_mask); - + } spin_unlock_irqrestore(&irq_lock, flags); } From e336285db2593bf443b53647d8f6d8006e471d89 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 14:17:20 +0200 Subject: [PATCH 19/51] CRIS: v32: Correct path for intr_vect.h Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/kgdb_asm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/arch-v32/kernel/kgdb_asm.S b/arch/cris/arch-v32/kernel/kgdb_asm.S index eba93e7e4aad..f3a47605902a 100644 --- a/arch/cris/arch-v32/kernel/kgdb_asm.S +++ b/arch/cris/arch-v32/kernel/kgdb_asm.S @@ -5,7 +5,7 @@ * port exceptions for kernel debugging purposes. */ -#include +#include ;; Exported functions. .globl kgdb_handle_exception From ab43d14dab1c112b74aae1c2d684a19a26c34c43 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 14:45:55 +0200 Subject: [PATCH 20/51] CRIS: kgdb: Fix compilation errors Paths were not correct and pack_hex_byte() takes two arguments. Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/kgdb.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c index c981fd663323..6b653323d796 100644 --- a/arch/cris/arch-v32/kernel/kgdb.c +++ b/arch/cris/arch-v32/kernel/kgdb.c @@ -174,10 +174,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include /* From entry.S. */ extern void gdb_handle_exception(void); @@ -988,26 +988,26 @@ stub_is_stopped(int sigval) } /* Only send PC, frame and stack pointer. */ read_register(PC, ®_cont); - ptr = pack_hex_byte(PC); + ptr = pack_hex_byte(ptr, PC); *ptr++ = ':'; ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[PC]); *ptr++ = ';'; read_register(R8, ®_cont); - ptr = pack_hex_byte(R8); + ptr = pack_hex_byte(ptr, R8); *ptr++ = ':'; ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[R8]); *ptr++ = ';'; read_register(SP, ®_cont); - ptr = pack_hex_byte(SP); + ptr = pack_hex_byte(ptr, SP); *ptr++ = ':'; ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[SP]); *ptr++ = ';'; /* Send ERP as well; this will save us an entire register fetch in some cases. */ read_register(ERP, ®_cont); - ptr = pack_hex_byte(ERP); + ptr = pack_hex_byte(ptr, ERP); *ptr++ = ':'; ptr = mem2hex(ptr, (unsigned char *)®_cont, register_size[ERP]); *ptr++ = ';'; From c9cbf097b79b9bde32f4e5aaa0bbc16212be3016 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 14:49:12 +0200 Subject: [PATCH 21/51] CRIS: Remove obsolete pinmux.c, now machine dependent. Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/pinmux.c | 229 ----------------------------- 1 file changed, 229 deletions(-) delete mode 100644 arch/cris/arch-v32/kernel/pinmux.c diff --git a/arch/cris/arch-v32/kernel/pinmux.c b/arch/cris/arch-v32/kernel/pinmux.c deleted file mode 100644 index f6f3637a4194..000000000000 --- a/arch/cris/arch-v32/kernel/pinmux.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Allocator for I/O pins. All pins are allocated to GPIO at bootup. - * Unassigned pins and GPIO pins can be allocated to a fixed interface - * or the I/O processor instead. - * - * Copyright (c) 2004 Axis Communications AB. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG - -#define PORT_PINS 18 -#define PORTS 4 - -static char pins[PORTS][PORT_PINS]; -static DEFINE_SPINLOCK(pinmux_lock); - -static void crisv32_pinmux_set(int port); - -int -crisv32_pinmux_init(void) -{ - static int initialized = 0; - - if (!initialized) { - reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa); - initialized = 1; - pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 = - pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes; - REG_WR(pinmux, regi_pinmux, rw_pa, pa); - crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio); - crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio); - crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio); - crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio); - } - - return 0; -} - -int -crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode) -{ - int i; - unsigned long flags; - - crisv32_pinmux_init(); - - if (port > PORTS || port < 0) - return -EINVAL; - - spin_lock_irqsave(&pinmux_lock, flags); - - for (i = first_pin; i <= last_pin; i++) - { - if ((pins[port][i] != pinmux_none) && (pins[port][i] != pinmux_gpio) && - (pins[port][i] != mode)) - { - spin_unlock_irqrestore(&pinmux_lock, flags); -#ifdef DEBUG - panic("Pinmux alloc failed!\n"); -#endif - return -EPERM; - } - } - - for (i = first_pin; i <= last_pin; i++) - pins[port][i] = mode; - - crisv32_pinmux_set(port); - - spin_unlock_irqrestore(&pinmux_lock, flags); - - return 0; -} - -int -crisv32_pinmux_alloc_fixed(enum fixed_function function) -{ - int ret = -EINVAL; - char saved[sizeof pins]; - unsigned long flags; - - spin_lock_irqsave(&pinmux_lock, flags); - - /* Save internal data for recovery */ - memcpy(saved, pins, sizeof pins); - - reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); - - switch(function) - { - case pinmux_ser1: - ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed); - hwprot.ser1 = regk_pinmux_yes; - break; - case pinmux_ser2: - ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed); - hwprot.ser2 = regk_pinmux_yes; - break; - case pinmux_ser3: - ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed); - hwprot.ser3 = regk_pinmux_yes; - break; - case pinmux_sser0: - ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed); - ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); - hwprot.sser0 = regk_pinmux_yes; - break; - case pinmux_sser1: - ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); - hwprot.sser1 = regk_pinmux_yes; - break; - case pinmux_ata0: - ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed); - ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed); - hwprot.ata0 = regk_pinmux_yes; - break; - case pinmux_ata1: - ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); - ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed); - hwprot.ata1 = regk_pinmux_yes; - break; - case pinmux_ata2: - ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed); - ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed); - hwprot.ata2 = regk_pinmux_yes; - break; - case pinmux_ata3: - ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed); - ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed); - hwprot.ata2 = regk_pinmux_yes; - break; - case pinmux_ata: - ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed); - ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed); - hwprot.ata = regk_pinmux_yes; - break; - case pinmux_eth1: - ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed); - hwprot.eth1 = regk_pinmux_yes; - hwprot.eth1_mgm = regk_pinmux_yes; - break; - case pinmux_timer: - ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); - hwprot.timer = regk_pinmux_yes; - spin_unlock_irqrestore(&pinmux_lock, flags); - return ret; - } - - if (!ret) - REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot); - else - memcpy(pins, saved, sizeof pins); - - spin_unlock_irqrestore(&pinmux_lock, flags); - - return ret; -} - -void -crisv32_pinmux_set(int port) -{ - int i; - int gpio_val = 0; - int iop_val = 0; - - for (i = 0; i < PORT_PINS; i++) - { - if (pins[port][i] == pinmux_gpio) - gpio_val |= (1 << i); - else if (pins[port][i] == pinmux_iop) - iop_val |= (1 << i); - } - - REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_gio + 8*port, gpio_val); - REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_iop + 8*port, iop_val); - -#ifdef DEBUG - crisv32_pinmux_dump(); -#endif -} - -int -crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) -{ - int i; - unsigned long flags; - - crisv32_pinmux_init(); - - if (port > PORTS || port < 0) - return -EINVAL; - - spin_lock_irqsave(&pinmux_lock, flags); - - for (i = first_pin; i <= last_pin; i++) - pins[port][i] = pinmux_none; - - crisv32_pinmux_set(port); - spin_unlock_irqrestore(&pinmux_lock, flags); - - return 0; -} - -void -crisv32_pinmux_dump(void) -{ - int i, j; - - crisv32_pinmux_init(); - - for (i = 0; i < PORTS; i++) - { - printk("Port %c\n", 'B'+i); - for (j = 0; j < PORT_PINS; j++) - printk(" Pin %d = %d\n", j, pins[i][j]); - } -} - -__initcall(crisv32_pinmux_init); From e281a31e1c08e02d05c6fa1c11968c9369e4d809 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 14:59:22 +0200 Subject: [PATCH 22/51] CRIS: More ARTPEC-3 support and i2c-boardinfo. Add standard i2d-devices. Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/setup.c | 74 +++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/arch/cris/arch-v32/kernel/setup.c b/arch/cris/arch-v32/kernel/setup.c index 72e9e8331f63..61e10ae65296 100644 --- a/arch/cris/arch-v32/kernel/setup.c +++ b/arch/cris/arch-v32/kernel/setup.c @@ -9,6 +9,9 @@ #include #include +#include +#include + #ifdef CONFIG_PROC_FS #define HAS_FPU 0x0001 @@ -43,14 +46,15 @@ static struct cpu_info cpinfo[] = { {"ETRAX 100LX v2", 11, 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU}, - +#ifdef CONFIG_ETRAXFS {"ETRAX FS", 32, 32, HAS_ETHERNET100 | HAS_ATA | HAS_MMU}, - +#else + {"ARTPEC-3", 32, 32, HAS_ETHERNET100 | HAS_MMU}, +#endif {"Unknown", 0, 0, 0} }; -int -show_cpuinfo(struct seq_file *m, void *v) +int show_cpuinfo(struct seq_file *m, void *v) { int i; int cpu = (int)v - 1; @@ -107,9 +111,63 @@ show_cpuinfo(struct seq_file *m, void *v) #endif /* CONFIG_PROC_FS */ -void -show_etrax_copyright(void) +void show_etrax_copyright(void) { - printk(KERN_INFO - "Linux/CRISv32 port on ETRAX FS (C) 2003, 2004 Axis Communications AB\n"); +#ifdef CONFIG_ETRAXFS + printk(KERN_INFO "Linux/CRISv32 port on ETRAX FS " + "(C) 2003, 2004 Axis Communications AB\n"); +#else + printk(KERN_INFO "Linux/CRISv32 port on ARTPEC-3 " + "(C) 2003-2009 Axis Communications AB\n"); +#endif } + +static struct i2c_board_info __initdata i2c_info[] = { + {I2C_BOARD_INFO("camblock", 0x43)}, + {I2C_BOARD_INFO("tmp100", 0x48)}, + {I2C_BOARD_INFO("tmp100", 0x4A)}, + {I2C_BOARD_INFO("tmp100", 0x4C)}, + {I2C_BOARD_INFO("tmp100", 0x4D)}, + {I2C_BOARD_INFO("tmp100", 0x4E)}, +#ifdef CONFIG_RTC_DRV_PCF8563 + {I2C_BOARD_INFO("pcf8563", 0x51)}, +#endif +#ifdef CONFIG_ETRAX_VIRTUAL_GPIO + {I2C_BOARD_INFO("vgpio", 0x20)}, + {I2C_BOARD_INFO("vgpio", 0x21)}, +#endif + {I2C_BOARD_INFO("pca9536", 0x41)}, + {I2C_BOARD_INFO("fnp300", 0x40)}, + {I2C_BOARD_INFO("fnp300", 0x42)}, + {I2C_BOARD_INFO("adc101", 0x54)}, +}; + +static struct i2c_board_info __initdata i2c_info2[] = { + {I2C_BOARD_INFO("camblock", 0x43)}, + {I2C_BOARD_INFO("tmp100", 0x48)}, + {I2C_BOARD_INFO("tmp100", 0x4A)}, + {I2C_BOARD_INFO("tmp100", 0x4C)}, + {I2C_BOARD_INFO("tmp100", 0x4D)}, + {I2C_BOARD_INFO("tmp100", 0x4E)}, +#ifdef CONFIG_ETRAX_VIRTUAL_GPIO + {I2C_BOARD_INFO("vgpio", 0x20)}, + {I2C_BOARD_INFO("vgpio", 0x21)}, +#endif + {I2C_BOARD_INFO("pca9536", 0x41)}, + {I2C_BOARD_INFO("fnp300", 0x40)}, + {I2C_BOARD_INFO("fnp300", 0x42)}, + {I2C_BOARD_INFO("adc101", 0x54)}, +}; + +static struct i2c_board_info __initdata i2c_info3[] = { + {I2C_BOARD_INFO("adc101", 0x54)}, +}; + +static int __init etrax_init(void) +{ + i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); + i2c_register_board_info(1, i2c_info2, ARRAY_SIZE(i2c_info2)); + i2c_register_board_info(2, i2c_info3, ARRAY_SIZE(i2c_info3)); + return 0; +} +arch_initcall(etrax_init); From 399233265c2ce805cf19a4f56f79836faad6a034 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 15:55:48 +0200 Subject: [PATCH 23/51] CRIS: v32: Correct auto-restart of syscalls Register number was incorrect in syscalls that go via the restartblock (e.g, poll). Signed-off-by: Edgar Iglesias Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index 0b7e3f143281..b3a05ae56214 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -587,7 +587,7 @@ do_signal(int canrestart, struct pt_regs *regs) } if (regs->r10 == -ERESTART_RESTARTBLOCK){ - regs->r10 = __NR_restart_syscall; + regs->r9 = __NR_restart_syscall; regs->erp -= 2; } } From e2ee9bb2253c50a40a659f5c6daf3da1e77d9308 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 15:59:26 +0200 Subject: [PATCH 24/51] CRIS: Minor formatting fix in traps.c Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/kernel/traps.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/cris/arch-v32/kernel/traps.c b/arch/cris/arch-v32/kernel/traps.c index 9003e382cada..8bbe09c93132 100644 --- a/arch/cris/arch-v32/kernel/traps.c +++ b/arch/cris/arch-v32/kernel/traps.c @@ -9,8 +9,7 @@ #include #include -void -show_registers(struct pt_regs *regs) +void show_registers(struct pt_regs *regs) { /* * It's possible to use either the USP register or current->thread.usp. @@ -101,8 +100,7 @@ show_registers(struct pt_regs *regs) } } -void -arch_enable_nmi(void) +void arch_enable_nmi(void) { unsigned long flags; From 5f9ac92f3d21ed5a2afdc88c97ad7d9289be373c Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 16:13:37 +0200 Subject: [PATCH 25/51] CRIS: Add debug symbols for assembler code Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/lib/checksumcopy.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/cris/arch-v32/lib/checksumcopy.S b/arch/cris/arch-v32/lib/checksumcopy.S index 21aabe91489b..54e209f18b06 100644 --- a/arch/cris/arch-v32/lib/checksumcopy.S +++ b/arch/cris/arch-v32/lib/checksumcopy.S @@ -9,6 +9,7 @@ */ .globl csum_partial_copy_nocheck + .type csum_partial_copy_nocheck,@function csum_partial_copy_nocheck: ;; r10 - src @@ -89,3 +90,5 @@ _do_byte: move.b $r9,[$r11] ret move.d $r13,$r10 + + .size csum_partial_copy_nocheck, . - csum_partial_copy_nocheck From 3a38125d3eda41972caee512d9823b964e0c16fc Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 16:16:45 +0200 Subject: [PATCH 26/51] CRIS: Add debug info for assembler code Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/lib/checksum.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/cris/arch-v32/lib/checksum.S b/arch/cris/arch-v32/lib/checksum.S index 87f3fd71ab10..4a72a94a49ad 100644 --- a/arch/cris/arch-v32/lib/checksum.S +++ b/arch/cris/arch-v32/lib/checksum.S @@ -6,6 +6,7 @@ */ .globl csum_partial + .type csum_partial,@function csum_partial: ;; r10 - src @@ -83,3 +84,5 @@ _do_byte: addu.b [$r10],$r12 ret move.d $r12,$r10 + + .size csum_partial, .-csum_partial From 2d0503d1a6816e920e5b827bbe4eea7370c8130e Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 16:18:22 +0200 Subject: [PATCH 27/51] CRIS: Add debug info for assembler code Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/lib/spinlock.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/cris/arch-v32/lib/spinlock.S b/arch/cris/arch-v32/lib/spinlock.S index 79087ef59a1c..fe610b9d775f 100644 --- a/arch/cris/arch-v32/lib/spinlock.S +++ b/arch/cris/arch-v32/lib/spinlock.S @@ -6,7 +6,9 @@ .global cris_spin_lock + .type cris_spin_lock,@function .global cris_spin_trylock + .type cris_spin_trylock,@function .text @@ -22,6 +24,8 @@ cris_spin_lock: ret nop + .size cris_spin_lock, . - cris_spin_lock + cris_spin_trylock: clearf p 1: move.b [$r10], $r11 @@ -31,3 +35,6 @@ cris_spin_trylock: clearf p ret movu.b $r11,$r10 + + .size cris_spin_trylock, . - cris_spin_trylock + From 98560bd83e73b5c0cf38e3d984892f46a405a172 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 17:34:28 +0200 Subject: [PATCH 28/51] CRIS: Add more delays in DDR setup Also, make DDR latency configurable. Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/mach-a3/Kconfig | 4 ++++ arch/cris/arch-v32/mach-a3/dram_init.S | 16 +++++++++++++++- arch/cris/arch-v32/mach-a3/hw_settings.S | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/cris/arch-v32/mach-a3/Kconfig b/arch/cris/arch-v32/mach-a3/Kconfig index a4df06d5997a..7796aafc711e 100644 --- a/arch/cris/arch-v32/mach-a3/Kconfig +++ b/arch/cris/arch-v32/mach-a3/Kconfig @@ -33,6 +33,10 @@ config ETRAX_DDR2_CONFIG hex "DDR2 config" default "0" +config ETRAX_DDR2_LATENCY + hex "DDR2 latency" + default "0" + config ETRAX_PIO_CE0_CFG hex "PIO CE0 configuration" default "0" diff --git a/arch/cris/arch-v32/mach-a3/dram_init.S b/arch/cris/arch-v32/mach-a3/dram_init.S index 94d6b41cb299..ec8648be32d3 100644 --- a/arch/cris/arch-v32/mach-a3/dram_init.S +++ b/arch/cris/arch-v32/mach-a3/dram_init.S @@ -24,11 +24,21 @@ ;; Refer to ddr2 MDS for initialization sequence + ; 2. Wait 200us + move.d 10000, $r2 +1: bne 1b + subq 1, $r2 + ; Start clock move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_phy_cfg), $r0 move.d REG_STATE(ddr2, rw_phy_cfg, en, yes), $r1 move.d $r1, [$r0] + ; 2. Wait 200us + move.d 10000, $r2 +1: bne 1b + subq 1, $r2 + ; Reset phy and start calibration move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_phy_ctrl), $r0 move.d REG_STATE(ddr2, rw_phy_ctrl, rst, yes) | \ @@ -52,6 +62,10 @@ do_cmd: lslq 16, $r1 or.d $r3, $r1 move.d $r1, [$r0] + ; 2. Wait 200us + move.d 10000, $r4 +1: bne 1b + subq 1, $r4 cmp.d sdram_commands_end, $r2 blo command_loop nop @@ -63,7 +77,7 @@ do_cmd: ; Set latency move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_latency), $r0 - move.d 0x13, $r1 + move.d CONFIG_ETRAX_DDR2_LATENCY, $r1 move.d $r1, [$r0] ; Set configuration diff --git a/arch/cris/arch-v32/mach-a3/hw_settings.S b/arch/cris/arch-v32/mach-a3/hw_settings.S index 258a6329cd4a..0145725a1ce5 100644 --- a/arch/cris/arch-v32/mach-a3/hw_settings.S +++ b/arch/cris/arch-v32/mach-a3/hw_settings.S @@ -31,6 +31,8 @@ ; Register values .dword REG_ADDR(ddr2, regi_ddr2_ctrl, rw_cfg) .dword CONFIG_ETRAX_DDR2_CONFIG + .dword REG_ADDR(ddr2, regi_ddr2_ctrl, rw_latency) + .dword CONFIG_ETRAX_DDR2_LATENCY .dword REG_ADDR(ddr2, regi_ddr2_ctrl, rw_timing) .dword CONFIG_ETRAX_DDR2_TIMING .dword CONFIG_ETRAX_DDR2_MRS From 7ec280c52ca5aa1448cd16ae77dd44755413db2b Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:01:06 +0200 Subject: [PATCH 29/51] CRIS: Update for ARTPEC-3 Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/mm/init.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/arch/cris/arch-v32/mm/init.c b/arch/cris/arch-v32/mm/init.c index caeb921a92ea..0768bc409ca8 100644 --- a/arch/cris/arch-v32/mm/init.c +++ b/arch/cris/arch-v32/mm/init.c @@ -27,8 +27,7 @@ extern void tlb_init(void); * at kseg_4 thus the ksegs are set up again. Also clear the TLB and do various * other paging stuff. */ -void __init -cris_mmu_init(void) +void __init cris_mmu_init(void) { unsigned long mmu_config; unsigned long mmu_kbase_hi; @@ -55,14 +54,23 @@ cris_mmu_init(void) /* Initialise the TLB. Function found in tlb.c. */ tlb_init(); - /* Enable exceptions and initialize the kernel segments. */ + /* + * Enable exceptions and initialize the kernel segments. + * See head.S for differences between ARTPEC-3 and ETRAX FS. + */ mmu_config = ( REG_STATE(mmu, rw_mm_cfg, we, on) | REG_STATE(mmu, rw_mm_cfg, acc, on) | REG_STATE(mmu, rw_mm_cfg, ex, on) | REG_STATE(mmu, rw_mm_cfg, inv, on) | +#ifdef CONFIG_CRIS_MACH_ARTPEC3 + REG_STATE(mmu, rw_mm_cfg, seg_f, page) | + REG_STATE(mmu, rw_mm_cfg, seg_e, page) | + REG_STATE(mmu, rw_mm_cfg, seg_d, linear) | +#else REG_STATE(mmu, rw_mm_cfg, seg_f, linear) | REG_STATE(mmu, rw_mm_cfg, seg_e, linear) | REG_STATE(mmu, rw_mm_cfg, seg_d, page) | +#endif REG_STATE(mmu, rw_mm_cfg, seg_c, linear) | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) | #ifndef CONFIG_ETRAX_VCS_SIM @@ -81,9 +89,15 @@ cris_mmu_init(void) REG_STATE(mmu, rw_mm_cfg, seg_1, page) | REG_STATE(mmu, rw_mm_cfg, seg_0, page)); + /* See head.S for differences between ARTPEC-3 and ETRAX FS. */ mmu_kbase_hi = ( REG_FIELD(mmu, rw_mm_kbase_hi, base_f, 0x0) | +#ifdef CONFIG_CRIS_MACH_ARTPEC3 + REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 0x0) | + REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 0x5) | +#else REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 0x8) | REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 0x0) | +#endif REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0x4) | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) | #ifndef CONFIG_ETRAX_VCS_SIM @@ -129,8 +143,7 @@ cris_mmu_init(void) SUPP_REG_WR(RW_GC_CFG, 0xf); /* IMMU, DMMU, ICache, DCache on */ } -void __init -paging_init(void) +void __init paging_init(void) { int i; unsigned long zones_size[MAX_NR_ZONES]; From ac93f62179ecb82739ab7c76857c4ae44e0cb83f Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:10:12 +0200 Subject: [PATCH 30/51] CRIS: Add debug for assembler macros Signed-off-by: Jesper Nilsson --- arch/cris/arch-v32/mm/mmu.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/cris/arch-v32/mm/mmu.S b/arch/cris/arch-v32/mm/mmu.S index f125d912e140..72727c1d8e60 100644 --- a/arch/cris/arch-v32/mm/mmu.S +++ b/arch/cris/arch-v32/mm/mmu.S @@ -38,6 +38,7 @@ ; to handle the fault. .macro MMU_BUS_FAULT_HANDLER handler, mmu, we, ex .globl \handler + .type \handler,"function" \handler: SAVE_ALL move \mmu, $srs ; Select MMU support register bank @@ -52,6 +53,7 @@ nop ba ret_from_intr nop + .size \handler, . - \handler .endm ; Refill handler. Three cases may occur: @@ -84,6 +86,7 @@ 2: .dword 0 ; last_refill_cause .text .globl \handler + .type \handler, "function" \handler: subq 4, $sp ; (The pipeline stalls for one cycle; $sp used as address in the next cycle.) @@ -196,6 +199,7 @@ ; Return ba ret_from_intr nop + .size \handler, . - \handler .endm ; This is the MMU bus fault handlers. From 76fdf67bb5415a8e97bfecf81bf0c0d64bf7a552 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:12:47 +0200 Subject: [PATCH 31/51] CRIS: Avoid compilation warning for puts Rename to aputs. Also, simplify code by moving some common code out to macros. Signed-off-by: Jesper Nilsson --- arch/cris/boot/compressed/misc.c | 65 ++++++++++++-------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/arch/cris/boot/compressed/misc.c b/arch/cris/boot/compressed/misc.c index 47bc190ba6d4..548d886b03d3 100644 --- a/arch/cris/boot/compressed/misc.c +++ b/arch/cris/boot/compressed/misc.c @@ -106,7 +106,7 @@ static unsigned outcnt = 0; /* bytes in output buffer */ static void flush_window(void); static void error(char *m); -static void puts(const char *); +static void aputs(const char *s); extern char *input_data; /* lives in head.S */ @@ -137,52 +137,37 @@ static inline void serout(const char *s, reg_scope_instances regi_ser) REG_WR(ser, regi_ser, rw_dout, dout); } +#define SEROUT(S, N) \ + do { \ + serout(S, regi_ser ## N); \ + s++; \ + } while (0) +#else +#define SEROUT(S, N) do { \ + while (!(*R_SERIAL ## N ## _STATUS & (1 << 5))) \ + ; \ + *R_SERIAL ## N ## _TR_DATA = *s++; \ + } while (0) #endif -static void puts(const char *s) +static void aputs(const char *s) { #ifndef CONFIG_ETRAX_DEBUG_PORT_NULL while (*s) { #ifdef CONFIG_ETRAX_DEBUG_PORT0 -#ifdef CONFIG_ETRAX_ARCH_V32 - serout(s, regi_ser0); -#else - while (!(*R_SERIAL0_STATUS & (1 << 5))) - ; - *R_SERIAL0_TR_DATA = *s++; -#endif + SEROUT(s, 0); #endif #ifdef CONFIG_ETRAX_DEBUG_PORT1 -#ifdef CONFIG_ETRAX_ARCH_V32 - serout(s, regi_ser1); -#else - while (!(*R_SERIAL1_STATUS & (1 << 5))) - ; - *R_SERIAL1_TR_DATA = *s++; -#endif + SEROUT(s, 1); #endif #ifdef CONFIG_ETRAX_DEBUG_PORT2 -#ifdef CONFIG_ETRAX_ARCH_V32 - serout(s, regi_ser2); -#else - while (!(*R_SERIAL2_STATUS & (1 << 5))) - ; - *R_SERIAL2_TR_DATA = *s++; -#endif + SEROUT(s, 2); #endif #ifdef CONFIG_ETRAX_DEBUG_PORT3 -#ifdef CONFIG_ETRAX_ARCH_V32 - serout(s, regi_ser3); -#else - while (!(*R_SERIAL3_STATUS & (1 << 5))) - ; - *R_SERIAL3_TR_DATA = *s++; + SEROUT(s, 3); #endif -#endif - *s++; } -/* CONFIG_ETRAX_DEBUG_PORT_NULL */ -#endif +#endif /* CONFIG_ETRAX_DEBUG_PORT_NULL */ } void *memset(void *s, int c, size_t n) @@ -233,9 +218,9 @@ static void flush_window(void) static void error(char *x) { - puts("\n\n"); - puts(x); - puts("\n\n -- System halted\n"); + aputs("\n\n"); + aputs(x); + aputs("\n\n -- System halted\n"); while(1); /* Halt */ } @@ -378,14 +363,14 @@ void decompress_kernel(void) __asm__ volatile ("move $vr,%0" : "=rm" (revision)); if (revision < compile_rev) { #ifdef CONFIG_ETRAX_ARCH_V32 - puts("You need an ETRAX FS to run Linux 2.6/crisv32\n"); + aputs("You need at least ETRAX FS to run Linux 2.6/crisv32\n"); #else - puts("You need an ETRAX 100LX to run linux 2.6\n"); + aputs("You need an ETRAX 100LX to run linux 2.6/crisv10\n"); #endif while(1); } - puts("Uncompressing Linux...\n"); + aputs("Uncompressing Linux...\n"); gunzip(); - puts("Done. Now booting the kernel\n"); + aputs("Done. Now booting the kernel\n"); } From d717809bcef50658092c8e18d7576475b6484a4c Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:27:23 +0200 Subject: [PATCH 32/51] CRIS: Discard .note.gnu.build-id section Signed-off-by: Jesper Nilsson --- arch/cris/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/boot/Makefile b/arch/cris/boot/Makefile index 144f3afa0119..6e3b509fd7fc 100644 --- a/arch/cris/boot/Makefile +++ b/arch/cris/boot/Makefile @@ -3,7 +3,7 @@ # objcopyflags-$(CONFIG_ETRAX_ARCH_V10) += -R .note -R .comment -objcopyflags-$(CONFIG_ETRAX_ARCH_V32) += --remove-section=.bss +objcopyflags-$(CONFIG_ETRAX_ARCH_V32) += --remove-section=.bss --remove-section=.note.gnu.build-id OBJCOPYFLAGS = -O binary $(objcopyflags-y) From 6fdf581e9df53ee4f8b46487a046fff7613a0fa0 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:29:07 +0200 Subject: [PATCH 33/51] CRIS: Define __read_mostly for CRISv32 Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/arch/cache.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/cris/include/arch-v32/arch/cache.h b/arch/cris/include/arch-v32/arch/cache.h index dfc73050e6b4..1de779f4f240 100644 --- a/arch/cris/include/arch-v32/arch/cache.h +++ b/arch/cris/include/arch-v32/arch/cache.h @@ -7,6 +7,8 @@ #define L1_CACHE_BYTES 32 #define L1_CACHE_SHIFT 5 +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) + void flush_dma_list(dma_descr_data *descr); void flush_dma_descr(dma_descr_data *descr, int flush_buf); From a3af54ffa9fb0e3ce66904bd316f079cafad1bd5 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:40:39 +0200 Subject: [PATCH 34/51] CRIS: Machine dependent dma.h Move the old one to mach-fs and replace with a new one that only include the correct one for the machine architecture. Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/arch/dma.h | 80 +------------------ arch/cris/include/arch-v32/mach-fs/mach/dma.h | 79 ++++++++++++++++++ 2 files changed, 80 insertions(+), 79 deletions(-) create mode 100644 arch/cris/include/arch-v32/mach-fs/mach/dma.h diff --git a/arch/cris/include/arch-v32/arch/dma.h b/arch/cris/include/arch-v32/arch/dma.h index 3674081389fd..61906153a9af 100644 --- a/arch/cris/include/arch-v32/arch/dma.h +++ b/arch/cris/include/arch-v32/arch/dma.h @@ -1,79 +1 @@ -#ifndef _ASM_ARCH_CRIS_DMA_H -#define _ASM_ARCH_CRIS_DMA_H - -/* Defines for using and allocating dma channels. */ - -#define MAX_DMA_CHANNELS 10 - -#define NETWORK_ETH0_TX_DMA_NBR 0 /* Ethernet 0 out. */ -#define NETWORK_ETH0 RX_DMA_NBR 1 /* Ethernet 0 in. */ - -#define IO_PROC_DMA0_TX_DMA_NBR 2 /* IO processor DMA0 out. */ -#define IO_PROC_DMA0_RX_DMA_NBR 3 /* IO processor DMA0 in. */ - -#define ATA_TX_DMA_NBR 2 /* ATA interface out. */ -#define ATA_RX_DMA_NBR 3 /* ATA interface in. */ - -#define ASYNC_SER2_TX_DMA_NBR 2 /* Asynchronous serial port 2 out. */ -#define ASYNC_SER2_RX_DMA_NBR 3 /* Asynchronous serial port 2 in. */ - -#define IO_PROC_DMA1_TX_DMA_NBR 4 /* IO processor DMA1 out. */ -#define IO_PROC_DMA1_RX_DMA_NBR 5 /* IO processor DMA1 in. */ - -#define ASYNC_SER1_TX_DMA_NBR 4 /* Asynchronous serial port 1 out. */ -#define ASYNC_SER1_RX_DMA_NBR 5 /* Asynchronous serial port 1 in. */ - -#define SYNC_SER0_TX_DMA_NBR 4 /* Synchronous serial port 0 out. */ -#define SYNC_SER0_RX_DMA_NBR 5 /* Synchronous serial port 0 in. */ - -#define EXTDMA0_TX_DMA_NBR 6 /* External DMA 0 out. */ -#define EXTDMA1_RX_DMA_NBR 7 /* External DMA 1 in. */ - -#define ASYNC_SER0_TX_DMA_NBR 6 /* Asynchronous serial port 0 out. */ -#define ASYNC_SER0_RX_DMA_NBR 7 /* Asynchronous serial port 0 in. */ - -#define SYNC_SER1_TX_DMA_NBR 6 /* Synchronous serial port 1 out. */ -#define SYNC_SER1_RX_DMA_NBR 7 /* Synchronous serial port 1 in. */ - -#define NETWORK_ETH1_TX_DMA_NBR 6 /* Ethernet 1 out. */ -#define NETWORK_ETH1_RX_DMA_NBR 7 /* Ethernet 1 in. */ - -#define EXTDMA2_TX_DMA_NBR 8 /* External DMA 2 out. */ -#define EXTDMA3_RX_DMA_NBR 9 /* External DMA 3 in. */ - -#define STRCOP_TX_DMA_NBR 8 /* Stream co-processor out. */ -#define STRCOP_RX_DMA_NBR 9 /* Stream co-processor in. */ - -#define ASYNC_SER3_TX_DMA_NBR 8 /* Asynchronous serial port 3 out. */ -#define ASYNC_SER3_RX_DMA_NBR 9 /* Asynchronous serial port 3 in. */ - -enum dma_owner -{ - dma_eth0, - dma_eth1, - dma_iop0, - dma_iop1, - dma_ser0, - dma_ser1, - dma_ser2, - dma_ser3, - dma_sser0, - dma_sser1, - dma_ata, - dma_strp, - dma_ext0, - dma_ext1, - dma_ext2, - dma_ext3 -}; - -int crisv32_request_dma(unsigned int dmanr, const char * device_id, - unsigned options, unsigned bandwidth, enum dma_owner owner); -void crisv32_free_dma(unsigned int dmanr); - -/* Masks used by crisv32_request_dma options: */ -#define DMA_VERBOSE_ON_ERROR 1 -#define DMA_PANIC_ON_ERROR (2|DMA_VERBOSE_ON_ERROR) -#define DMA_INT_MEM 4 - -#endif /* _ASM_ARCH_CRIS_DMA_H */ +#include "mach/dma.h" diff --git a/arch/cris/include/arch-v32/mach-fs/mach/dma.h b/arch/cris/include/arch-v32/mach-fs/mach/dma.h new file mode 100644 index 000000000000..a8c59292586a --- /dev/null +++ b/arch/cris/include/arch-v32/mach-fs/mach/dma.h @@ -0,0 +1,79 @@ +#ifndef _ASM_ARCH_CRIS_DMA_H +#define _ASM_ARCH_CRIS_DMA_H + +/* Defines for using and allocating dma channels. */ + +#define MAX_DMA_CHANNELS 10 + +#define NETWORK_ETH0_TX_DMA_NBR 0 /* Ethernet 0 out. */ +#define NETWORK_ETH0 RX_DMA_NBR 1 /* Ethernet 0 in. */ + +#define IO_PROC_DMA0_TX_DMA_NBR 2 /* IO processor DMA0 out. */ +#define IO_PROC_DMA0_RX_DMA_NBR 3 /* IO processor DMA0 in. */ + +#define ATA_TX_DMA_NBR 2 /* ATA interface out. */ +#define ATA_RX_DMA_NBR 3 /* ATA interface in. */ + +#define ASYNC_SER2_TX_DMA_NBR 2 /* Asynchronous serial port 2 out. */ +#define ASYNC_SER2_RX_DMA_NBR 3 /* Asynchronous serial port 2 in. */ + +#define IO_PROC_DMA1_TX_DMA_NBR 4 /* IO processor DMA1 out. */ +#define IO_PROC_DMA1_RX_DMA_NBR 5 /* IO processor DMA1 in. */ + +#define ASYNC_SER1_TX_DMA_NBR 4 /* Asynchronous serial port 1 out. */ +#define ASYNC_SER1_RX_DMA_NBR 5 /* Asynchronous serial port 1 in. */ + +#define SYNC_SER0_TX_DMA_NBR 4 /* Synchronous serial port 0 out. */ +#define SYNC_SER0_RX_DMA_NBR 5 /* Synchronous serial port 0 in. */ + +#define EXTDMA0_TX_DMA_NBR 6 /* External DMA 0 out. */ +#define EXTDMA1_RX_DMA_NBR 7 /* External DMA 1 in. */ + +#define ASYNC_SER0_TX_DMA_NBR 6 /* Asynchronous serial port 0 out. */ +#define ASYNC_SER0_RX_DMA_NBR 7 /* Asynchronous serial port 0 in. */ + +#define SYNC_SER1_TX_DMA_NBR 6 /* Synchronous serial port 1 out. */ +#define SYNC_SER1_RX_DMA_NBR 7 /* Synchronous serial port 1 in. */ + +#define NETWORK_ETH1_TX_DMA_NBR 6 /* Ethernet 1 out. */ +#define NETWORK_ETH1_RX_DMA_NBR 7 /* Ethernet 1 in. */ + +#define EXTDMA2_TX_DMA_NBR 8 /* External DMA 2 out. */ +#define EXTDMA3_RX_DMA_NBR 9 /* External DMA 3 in. */ + +#define STRCOP_TX_DMA_NBR 8 /* Stream co-processor out. */ +#define STRCOP_RX_DMA_NBR 9 /* Stream co-processor in. */ + +#define ASYNC_SER3_TX_DMA_NBR 8 /* Asynchronous serial port 3 out. */ +#define ASYNC_SER3_RX_DMA_NBR 9 /* Asynchronous serial port 3 in. */ + +enum dma_owner { + dma_eth0, + dma_eth1, + dma_iop0, + dma_iop1, + dma_ser0, + dma_ser1, + dma_ser2, + dma_ser3, + dma_sser0, + dma_sser1, + dma_ata, + dma_strp, + dma_ext0, + dma_ext1, + dma_ext2, + dma_ext3 +}; + +int crisv32_request_dma(unsigned int dmanr, const char *device_id, + unsigned options, unsigned bandwidth, + enum dma_owner owner); +void crisv32_free_dma(unsigned int dmanr); + +/* Masks used by crisv32_request_dma options: */ +#define DMA_VERBOSE_ON_ERROR 1 +#define DMA_PANIC_ON_ERROR (2|DMA_VERBOSE_ON_ERROR) +#define DMA_INT_MEM 4 + +#endif /* _ASM_ARCH_CRIS_DMA_H */ From 243ba2fa461a22e01e5905dd299babeaeeb418e2 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:50:06 +0200 Subject: [PATCH 35/51] CRIS: Check if pointer is set before using it Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/arch/io.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/cris/include/arch-v32/arch/io.h b/arch/cris/include/arch-v32/arch/io.h index 72024452cea9..adc5484351bf 100644 --- a/arch/cris/include/arch-v32/arch/io.h +++ b/arch/cris/include/arch-v32/arch/io.h @@ -46,10 +46,12 @@ static inline void crisv32_io_set(struct crisv32_iopin *iopin, int val) unsigned long flags; spin_lock_irqsave(&iopin->port->lock, flags); - if (val) - *iopin->port->data |= iopin->bit; - else - *iopin->port->data &= ~iopin->bit; + if (iopin->port->data) { + if (val) + *iopin->port->data |= iopin->bit; + else + *iopin->port->data &= ~iopin->bit; + } spin_unlock_irqrestore(&iopin->port->lock, flags); } @@ -60,10 +62,12 @@ static inline void crisv32_io_set_dir(struct crisv32_iopin* iopin, unsigned long flags; spin_lock_irqsave(&iopin->port->lock, flags); - if (dir == crisv32_io_dir_in) - *iopin->port->oe &= ~iopin->bit; - else - *iopin->port->oe |= iopin->bit; + if (iopin->port->oe) { + if (dir == crisv32_io_dir_in) + *iopin->port->oe &= ~iopin->bit; + else + *iopin->port->oe |= iopin->bit; + } spin_unlock_irqrestore(&iopin->port->lock, flags); } From 32e7a8ba8d435d03752be818a82748c5e3eadc36 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:53:50 +0200 Subject: [PATCH 36/51] CRIS: Machine dependent memmap.h Move the old one to mach-fs and replace with a new one that only include the correct one for the machine architecture. Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/arch/memmap.h | 25 +------------------ .../include/arch-v32/mach-fs/mach/memmap.h | 24 ++++++++++++++++++ 2 files changed, 25 insertions(+), 24 deletions(-) create mode 100644 arch/cris/include/arch-v32/mach-fs/mach/memmap.h diff --git a/arch/cris/include/arch-v32/arch/memmap.h b/arch/cris/include/arch-v32/arch/memmap.h index d29df5644d3e..81985c0a6789 100644 --- a/arch/cris/include/arch-v32/arch/memmap.h +++ b/arch/cris/include/arch-v32/arch/memmap.h @@ -1,24 +1 @@ -#ifndef _ASM_ARCH_MEMMAP_H -#define _ASM_ARCH_MEMMAP_H - -#define MEM_CSE0_START (0x00000000) -#define MEM_CSE0_SIZE (0x04000000) -#define MEM_CSE1_START (0x04000000) -#define MEM_CSE1_SIZE (0x04000000) -#define MEM_CSR0_START (0x08000000) -#define MEM_CSR1_START (0x0c000000) -#define MEM_CSP0_START (0x10000000) -#define MEM_CSP1_START (0x14000000) -#define MEM_CSP2_START (0x18000000) -#define MEM_CSP3_START (0x1c000000) -#define MEM_CSP4_START (0x20000000) -#define MEM_CSP5_START (0x24000000) -#define MEM_CSP6_START (0x28000000) -#define MEM_CSP7_START (0x2c000000) -#define MEM_INTMEM_START (0x38000000) -#define MEM_INTMEM_SIZE (0x00020000) -#define MEM_DRAM_START (0x40000000) - -#define MEM_NON_CACHEABLE (0x80000000) - -#endif +#include diff --git a/arch/cris/include/arch-v32/mach-fs/mach/memmap.h b/arch/cris/include/arch-v32/mach-fs/mach/memmap.h new file mode 100644 index 000000000000..d29df5644d3e --- /dev/null +++ b/arch/cris/include/arch-v32/mach-fs/mach/memmap.h @@ -0,0 +1,24 @@ +#ifndef _ASM_ARCH_MEMMAP_H +#define _ASM_ARCH_MEMMAP_H + +#define MEM_CSE0_START (0x00000000) +#define MEM_CSE0_SIZE (0x04000000) +#define MEM_CSE1_START (0x04000000) +#define MEM_CSE1_SIZE (0x04000000) +#define MEM_CSR0_START (0x08000000) +#define MEM_CSR1_START (0x0c000000) +#define MEM_CSP0_START (0x10000000) +#define MEM_CSP1_START (0x14000000) +#define MEM_CSP2_START (0x18000000) +#define MEM_CSP3_START (0x1c000000) +#define MEM_CSP4_START (0x20000000) +#define MEM_CSP5_START (0x24000000) +#define MEM_CSP6_START (0x28000000) +#define MEM_CSP7_START (0x2c000000) +#define MEM_INTMEM_START (0x38000000) +#define MEM_INTMEM_SIZE (0x00020000) +#define MEM_DRAM_START (0x40000000) + +#define MEM_NON_CACHEABLE (0x80000000) + +#endif From 2dc1c40c6e81ba406f2f6b00fe5eecb4c7cf1197 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 18:58:29 +0200 Subject: [PATCH 37/51] CRIS: Pagetable for ARTPEC-3 Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/arch/pgtable.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/cris/include/arch-v32/arch/pgtable.h b/arch/cris/include/arch-v32/arch/pgtable.h index 08cb7ff7e4e7..c1051a8da33d 100644 --- a/arch/cris/include/arch-v32/arch/pgtable.h +++ b/arch/cris/include/arch-v32/arch/pgtable.h @@ -2,8 +2,16 @@ #define _ASM_CRIS_ARCH_PGTABLE_H /* Define the kernels virtual memory area. */ + +/* See head.S for differences between ARTPEC-3 and ETRAX FS. */ +#ifdef CONFIG_CRIS_MACH_ARTPEC3 +#define VMALLOC_START KSEG_E +#define VMALLOC_END KSEG_F +#else #define VMALLOC_START KSEG_D #define VMALLOC_END KSEG_E +#endif + #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #endif /* _ASM_CRIS_ARCH_PGTABLE_H */ From da2af0a771caa8f8cff9c7bfc979f0510eb0faea Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 3 Aug 2010 19:14:29 +0200 Subject: [PATCH 38/51] CRIS: __do_strncpy_from_user: Don't read the byte beyond the nil Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/arch/uaccess.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/cris/include/arch-v32/arch/uaccess.h b/arch/cris/include/arch-v32/arch/uaccess.h index 6b207f1b6622..3196019706cb 100644 --- a/arch/cris/include/arch-v32/arch/uaccess.h +++ b/arch/cris/include/arch-v32/arch/uaccess.h @@ -122,14 +122,14 @@ __do_strncpy_from_user(char *dst, const char *src, long count) __asm__ __volatile__ ( " move.d %3,%0\n" "5: move.b [%2+],$acr\n" - "1: beq 2f\n" + "1: beq 6f\n" " move.b $acr,[%1+]\n" " subq 1,%0\n" "2: bne 1b\n" " move.b [%2+],$acr\n" - " sub.d %3,%0\n" + "6: sub.d %3,%0\n" " neg.d %0,%0\n" "3:\n" " .section .fixup,\"ax\"\n" @@ -140,8 +140,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) /* The address for a fault at the first move is trivial. The address for a fault at the second move is that of the preceding branch insn, since the move insn is in - its delay-slot. That address is also a branch - target. Just so you don't get confused... */ + its delay-slot. Just so you don't get confused... */ " .previous\n" " .section __ex_table,\"a\"\n" " .dword 5b,4b\n" From 6f09963caf5ff7cb4b8de600caee3ff016e97139 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 10:49:17 +0200 Subject: [PATCH 39/51] CRIS: New DMA defines for ARTPEC-3 Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/mach-a3/mach/dma.h | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/cris/include/arch-v32/mach-a3/mach/dma.h b/arch/cris/include/arch-v32/mach-a3/mach/dma.h index 9e8eb13b601d..f01dca1ad108 100644 --- a/arch/cris/include/arch-v32/mach-a3/mach/dma.h +++ b/arch/cris/include/arch-v32/mach-a3/mach/dma.h @@ -5,6 +5,33 @@ #define MAX_DMA_CHANNELS 12 /* 8 and 10 not used. */ +#define NETWORK_ETH_TX_DMA_NBR 0 /* Ethernet 0 out. */ +#define NETWORK_ETH_RX_DMA_NBR 1 /* Ethernet 0 in. */ + +#define IO_PROC_DMA_TX_DMA_NBR 4 /* IO processor DMA0 out. */ +#define IO_PROC_DMA_RX_DMA_NBR 5 /* IO processor DMA0 in. */ + +#define ASYNC_SER3_TX_DMA_NBR 2 /* Asynchronous serial port 3 out. */ +#define ASYNC_SER3_RX_DMA_NBR 3 /* Asynchronous serial port 3 in. */ + +#define ASYNC_SER2_TX_DMA_NBR 6 /* Asynchronous serial port 2 out. */ +#define ASYNC_SER2_RX_DMA_NBR 7 /* Asynchronous serial port 2 in. */ + +#define ASYNC_SER1_TX_DMA_NBR 4 /* Asynchronous serial port 1 out. */ +#define ASYNC_SER1_RX_DMA_NBR 5 /* Asynchronous serial port 1 in. */ + +#define SYNC_SER_TX_DMA_NBR 6 /* Synchronous serial port 0 out. */ +#define SYNC_SER_RX_DMA_NBR 7 /* Synchronous serial port 0 in. */ + +#define ASYNC_SER0_TX_DMA_NBR 0 /* Asynchronous serial port 0 out. */ +#define ASYNC_SER0_RX_DMA_NBR 1 /* Asynchronous serial port 0 in. */ + +#define STRCOP_TX_DMA_NBR 2 /* Stream co-processor out. */ +#define STRCOP_RX_DMA_NBR 3 /* Stream co-processor in. */ + +#define dma_eth0 dma_eth +#define dma_eth1 dma_eth + enum dma_owner { dma_eth, dma_ser0, From 0c07d3abc8d76120317c108062cc7aa81fbd96d6 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 11:03:57 +0200 Subject: [PATCH 40/51] CRIS: Better handling of pinmux settings Depending on eth, eth_mido and geth fields in wr_hwprot, don't set corresponding pins on gpio port b to gpio mode. This avoids re-resetting the ethernet PHY should this already have been done. Signed-off-by: Jesper Nilsson --- .../include/arch-v32/mach-a3/mach/startup.inc | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/cris/include/arch-v32/mach-a3/mach/startup.inc b/arch/cris/include/arch-v32/mach-a3/mach/startup.inc index 2f23e5e16f4a..2d52bcc96ed5 100644 --- a/arch/cris/include/arch-v32/mach-a3/mach/startup.inc +++ b/arch/cris/include/arch-v32/mach-a3/mach/startup.inc @@ -1,9 +1,19 @@ +#ifndef STARTUP_INC_INCLUDED +#define STARTUP_INC_INCLUDED + #include #include #include #include #include + .macro GIO_SET_P BITS, OUTREG + bmi 1f ; btstq: bit -> N flag + nop + or.d \BITS, \OUTREG +1: + .endm + .macro GIO_INIT move.d CONFIG_ETRAX_DEF_GIO_PA_OUT, $r0 move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r1 @@ -32,10 +42,23 @@ move.d 0xFFFFFFFF, $r0 move.d REG_ADDR(pinmux, regi_pinmux, rw_gio_pa), $r1 move.d $r0, [$r1] - move.d REG_ADDR(pinmux, regi_pinmux, rw_gio_pb), $r1 - move.d $r0, [$r1] move.d REG_ADDR(pinmux, regi_pinmux, rw_gio_pc), $r1 move.d $r0, [$r1] + + ;; If eth_mdio, eth, geth bits are set in hwprot, don't + ;; set them to gpio, as this means they have been configured + ;; earlier and shouldn't be changed. + move.d 0xFC000000, $r2 ; pins 25..0 are eth_mdio, eth, geth + move.d REG_ADDR(pinmux, regi_pinmux, rw_hwprot), $r1 + move.d [$r1], $r0 + btstq REG_BIT(pinmux, rw_hwprot, eth), $r0 + GIO_SET_P 0x00FFFF00, $r2 ;; pins 8..23 are eth + btstq REG_BIT(pinmux, rw_hwprot, eth_mdio), $r0 + GIO_SET_P 0x03000000, $r2 ;; pins 24..25 are eth_mdio + btstq REG_BIT(pinmux, rw_hwprot, geth), $r0 + GIO_SET_P 0x000000FF, $r2 ;; pins 0..7 are geth + move.d REG_ADDR(pinmux, regi_pinmux, rw_gio_pb), $r1 + move.d $r2, [$r1] .endm .macro START_CLOCKS @@ -58,3 +81,4 @@ move.d CONFIG_ETRAX_PIO_CE2_CFG, $r1 move.d $r1, [$r0] .endm +#endif From 97a644461d9f47a0b2085d79783017d45b575325 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 11:18:47 +0200 Subject: [PATCH 41/51] CRIS: Add include guard Signed-off-by: Jesper Nilsson --- arch/cris/include/arch-v32/mach-fs/mach/startup.inc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/cris/include/arch-v32/mach-fs/mach/startup.inc b/arch/cris/include/arch-v32/mach-fs/mach/startup.inc index 4a10ccbd6cc1..dd1abbdcbc7a 100644 --- a/arch/cris/include/arch-v32/mach-fs/mach/startup.inc +++ b/arch/cris/include/arch-v32/mach-fs/mach/startup.inc @@ -1,3 +1,6 @@ +#ifndef STARTUP_INC_INCLUDED +#define STARTUP_INC_INCLUDED + #include #include #include @@ -75,3 +78,5 @@ move.d $r10, [$r11] #endif .endm + +#endif From 4f248d1cea12afd2d961509eb2ba19bd0939033f Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 11:25:13 +0200 Subject: [PATCH 42/51] CRIS: Better ARTPEC-3 support for gpio Add PWM support, correct comment for ARTPEC-3. Signed-off-by: Jesper Nilsson --- arch/cris/include/asm/etraxgpio.h | 96 +++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/arch/cris/include/asm/etraxgpio.h b/arch/cris/include/asm/etraxgpio.h index 38f1c8e1770c..d474818a537e 100644 --- a/arch/cris/include/asm/etraxgpio.h +++ b/arch/cris/include/asm/etraxgpio.h @@ -21,31 +21,35 @@ * /dev/leds minor 2, Access to leds depending on kernelconfig * * For ARTPEC-3 (CONFIG_CRIS_MACH_ARTPEC3): - * /dev/gpioa minor 0, 8 bit GPIO, each bit can change direction - * /dev/gpiob minor 1, 18 bit GPIO, each bit can change direction - * /dev/gpioc minor 3, 18 bit GPIO, each bit can change direction - * /dev/gpiod minor 4, 18 bit GPIO, each bit can change direction + * /dev/gpioa minor 0, 32 bit GPIO, each bit can change direction + * /dev/gpiob minor 1, 32 bit GPIO, each bit can change direction + * /dev/gpioc minor 3, 16 bit GPIO, each bit can change direction + * /dev/gpiod minor 4, 32 bit GPIO, input only * /dev/leds minor 2, Access to leds depending on kernelconfig * /dev/pwm0 minor 16, PWM channel 0 on PA30 * /dev/pwm1 minor 17, PWM channel 1 on PA31 * /dev/pwm2 minor 18, PWM channel 2 on PB26 + * /dev/ppwm minor 19, PPWM channel * */ #ifndef _ASM_ETRAXGPIO_H #define _ASM_ETRAXGPIO_H +#define GPIO_MINOR_FIRST 0 + +#define ETRAXGPIO_IOCTYPE 43 + /* etraxgpio _IOC_TYPE, bits 8 to 15 in ioctl cmd */ #ifdef CONFIG_ETRAX_ARCH_V10 -#define ETRAXGPIO_IOCTYPE 43 #define GPIO_MINOR_A 0 #define GPIO_MINOR_B 1 #define GPIO_MINOR_LEDS 2 #define GPIO_MINOR_G 3 #define GPIO_MINOR_LAST 3 +#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST #endif #ifdef CONFIG_ETRAXFS -#define ETRAXGPIO_IOCTYPE 43 #define GPIO_MINOR_A 0 #define GPIO_MINOR_B 1 #define GPIO_MINOR_LEDS 2 @@ -58,10 +62,10 @@ #else #define GPIO_MINOR_LAST 5 #endif +#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST #endif #ifdef CONFIG_CRIS_MACH_ARTPEC3 -#define ETRAXGPIO_IOCTYPE 43 #define GPIO_MINOR_A 0 #define GPIO_MINOR_B 1 #define GPIO_MINOR_LEDS 2 @@ -73,12 +77,17 @@ #else #define GPIO_MINOR_LAST 4 #endif -#define GPIO_MINOR_PWM0 16 -#define GPIO_MINOR_PWM1 17 -#define GPIO_MINOR_PWM2 18 -#define GPIO_MINOR_LAST_PWM GPIO_MINOR_PWM2 +#define GPIO_MINOR_FIRST_PWM 16 +#define GPIO_MINOR_PWM0 (GPIO_MINOR_FIRST_PWM+0) +#define GPIO_MINOR_PWM1 (GPIO_MINOR_FIRST_PWM+1) +#define GPIO_MINOR_PWM2 (GPIO_MINOR_FIRST_PWM+2) +#define GPIO_MINOR_PPWM (GPIO_MINOR_FIRST_PWM+3) +#define GPIO_MINOR_LAST_PWM GPIO_MINOR_PPWM +#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST_PWM #endif + + /* supported ioctl _IOC_NR's */ #define IO_READBITS 0x1 /* read and return current port bits (obsolete) */ @@ -125,12 +134,10 @@ */ #define IO_READ_INBITS 0x10 /* *arg is result of reading the input pins */ #define IO_READ_OUTBITS 0x11 /* *arg is result of reading the output shadow */ -#define IO_SETGET_INPUT 0x12 /* bits set in *arg is set to input, - * *arg updated with current input pins. - */ -#define IO_SETGET_OUTPUT 0x13 /* bits set in *arg is set to output, - * *arg updated with current output pins. - */ +#define IO_SETGET_INPUT 0x12 /* bits set in *arg is set to input, */ + /* *arg updated with current input pins. */ +#define IO_SETGET_OUTPUT 0x13 /* bits set in *arg is set to output, */ + /* *arg updated with current output pins. */ /* The following ioctl's are applicable to the PWM channels only */ @@ -140,7 +147,8 @@ enum io_pwm_mode { PWM_OFF = 0, /* disabled, deallocated */ PWM_STANDARD = 1, /* 390 kHz, duty cycle 0..255/256 */ PWM_FAST = 2, /* variable freq, w/ 10ns active pulse len */ - PWM_VARFREQ = 3 /* individually configurable high/low periods */ + PWM_VARFREQ = 3, /* individually configurable high/low periods */ + PWM_SOFT = 4 /* software generated */ }; struct io_pwm_set_mode { @@ -176,4 +184,56 @@ struct io_pwm_set_duty { int duty; /* 0..255 */ }; +/* Returns information about the latest PWM pulse. + * lo: Length of the latest low period, in units of 10ns. + * hi: Length of the latest high period, in units of 10ns. + * cnt: Time since last detected edge, in units of 10ns. + * + * The input source to PWM is decied by IO_PWM_SET_INPUT_SRC. + * + * NOTE: All PWM devices is connected to the same input source. + */ +#define IO_PWM_GET_PERIOD 0x23 + +struct io_pwm_get_period { + unsigned int lo; + unsigned int hi; + unsigned int cnt; +}; + +/* Sets the input source for the PWM input. For the src value see the + * register description for gio:rw_pwm_in_cfg. + * + * NOTE: All PWM devices is connected to the same input source. + */ +#define IO_PWM_SET_INPUT_SRC 0x24 +struct io_pwm_set_input_src { + unsigned int src; /* 0..7 */ +}; + +/* Sets the duty cycles in steps of 1/256, 0 = 0%, 255 = 100% duty cycle */ +#define IO_PPWM_SET_DUTY 0x25 + +struct io_ppwm_set_duty { + int duty; /* 0..255 */ +}; + +/* Configuraton struct for the IO_PWMCLK_SET_CONFIG ioctl to configure + * PWM capable gpio pins: + */ +#define IO_PWMCLK_SETGET_CONFIG 0x26 +struct gpio_pwmclk_conf { + unsigned int gpiopin; /* The pin number based on the opened device */ + unsigned int baseclk; /* The base clock to use, or sw will select one close*/ + unsigned int low; /* The number of low periods of the baseclk */ + unsigned int high; /* The number of high periods of the baseclk */ +}; + +/* Examples: + * To get a symmetric 12 MHz clock without knowing anything about the hardware: + * baseclk = 12000000, low = 0, high = 0 + * To just get info of current setting: + * baseclk = 0, low = 0, high = 0, the values will be updated by driver. + */ + #endif From 72e08db187cbbfca00583c28b64ae81a35f4a287 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 11:30:41 +0200 Subject: [PATCH 43/51] CRIS: Add ARTPEC-3 and timestamps for sync-serial Signed-off-by: Jesper Nilsson --- arch/cris/include/asm/sync_serial.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/cris/include/asm/sync_serial.h b/arch/cris/include/asm/sync_serial.h index d87c24df2b38..7f827fea30e7 100644 --- a/arch/cris/include/asm/sync_serial.h +++ b/arch/cris/include/asm/sync_serial.h @@ -19,6 +19,7 @@ #define SSP_OPOLARITY _IOR('S', 4, unsigned int) #define SSP_SPI _IOR('S', 5, unsigned int) #define SSP_INBUFCHUNK _IOR('S', 6, unsigned int) +#define SSP_INPUT _IOR('S', 7, unsigned int) /* Values for SSP_SPEED */ #define SSP150 0 @@ -37,6 +38,7 @@ #define SSP921600 13 #define SSP3125000 14 #define CODEC 15 +#define CODEC_f32768 16 #define FREQ_4MHz 0 #define FREQ_2MHz 1 @@ -46,9 +48,14 @@ #define FREQ_128kHz 5 #define FREQ_64kHz 6 #define FREQ_32kHz 7 +/* FREQ_* with values where bit (value & 0x10) is set are */ +/* used for CODEC_f32768 */ +#define FREQ_4096kHz 16 /* CODEC_f32768 */ /* Used by application to set CODEC divider, word rate and frame rate */ -#define CODEC_VAL(freq, clk_per_sync, sync_per_frame) (CODEC | (freq << 8) | (clk_per_sync << 16) | (sync_per_frame << 28)) +#define CODEC_VAL(freq, clk_per_sync, sync_per_frame) \ + ((CODEC + ((freq & 0x10) >> 4)) | (freq << 8) | \ + (clk_per_sync << 16) | (sync_per_frame << 28)) /* Used by driver to extract speed */ #define GET_SPEED(x) (x & 0xff) @@ -68,6 +75,7 @@ #define NORMAL_SYNC 1 #define EARLY_SYNC 2 #define SECOND_WORD_SYNC 0x40000 +#define LATE_SYNC 0x80000 #define BIT_SYNC 4 #define WORD_SYNC 8 @@ -104,4 +112,21 @@ /* Values for SSP_INBUFCHUNK */ /* plain integer with the size of DMA chunks */ +/* To ensure that the timestamps are aligned with the data being read + * the read length MUST be a multiple of the length of the DMA buffers. + * + * Use a multiple of SSP_INPUT_CHUNK_SIZE defined below. + */ +#define SSP_INPUT_CHUNK_SIZE 256 + +/* Request struct to pass through the ioctl interface to read + * data with timestamps. + */ +struct ssp_request { + char __user *buf; /* Where to put the data. */ + size_t len; /* Size of buf. MUST be a multiple of */ + /* SSP_INPUT_CHUNK_SIZE! */ + struct timespec ts; /* The time the data was sampled. */ +}; + #endif From c1c8f558749cbf2a7ed16b6ae6e19a4238b6fa33 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 11:44:08 +0200 Subject: [PATCH 44/51] CRIS: Return something from profile write Even if it doesn't matter, we should return something. Also, clean up some formatting. Signed-off-by: Jesper Nilsson --- arch/cris/kernel/profile.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c index b917549a7d94..195ec5fa0dd2 100644 --- a/arch/cris/kernel/profile.c +++ b/arch/cris/kernel/profile.c @@ -9,12 +9,11 @@ #define SAMPLE_BUFFER_SIZE 8192 -static char* sample_buffer; -static char* sample_buffer_pos; +static char *sample_buffer; +static char *sample_buffer_pos; static int prof_running = 0; -void -cris_profile_sample(struct pt_regs* regs) +void cris_profile_sample(struct pt_regs *regs) { if (!prof_running) return; @@ -24,7 +23,7 @@ cris_profile_sample(struct pt_regs* regs) else *(unsigned int*)sample_buffer_pos = 0; - *(unsigned int*)(sample_buffer_pos + 4) = instruction_pointer(regs); + *(unsigned int *)(sample_buffer_pos + 4) = instruction_pointer(regs); sample_buffer_pos += 8; if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE) @@ -54,6 +53,7 @@ write_cris_profile(struct file *file, const char __user *buf, { sample_buffer_pos = sample_buffer; memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE); + return count < SAMPLE_BUFFER_SIZE ? count : SAMPLE_BUFFER_SIZE; } static const struct file_operations cris_proc_profile_operations = { @@ -61,8 +61,7 @@ static const struct file_operations cris_proc_profile_operations = { .write = write_cris_profile, }; -static int -__init init_cris_profile(void) +static int __init init_cris_profile(void) { struct proc_dir_entry *entry; @@ -82,5 +81,5 @@ __init init_cris_profile(void) return 0; } - __initcall(init_cris_profile); + From dcb313c23f440873a5a382e6672ad6a684193e86 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 14:01:28 +0200 Subject: [PATCH 45/51] CRIS: Add cache aligned and read mostly data sections Signed-off-by: Jesper Nilsson --- arch/cris/kernel/vmlinux.lds.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S index d49d17d2a14f..942051102bb5 100644 --- a/arch/cris/kernel/vmlinux.lds.S +++ b/arch/cris/kernel/vmlinux.lds.S @@ -58,6 +58,8 @@ SECTIONS ___data_start = . ; __Sdata = . ; .data : { /* Data */ + CACHELINE_ALIGNED_DATA(32) + READ_MOSTLY_DATA(32) DATA_DATA } __edata = . ; /* End of data section. */ From 7c8a25b544c1659ad57de2394006fdd449325161 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 14:10:04 +0200 Subject: [PATCH 46/51] CRIS: Discard exit.text and .data at runtime This allows us to handle references from __bug_table. Signed-off-by: Jesper Nilsson --- arch/cris/kernel/vmlinux.lds.S | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S index 942051102bb5..789ad35f7e08 100644 --- a/arch/cris/kernel/vmlinux.lds.S +++ b/arch/cris/kernel/vmlinux.lds.S @@ -86,6 +86,16 @@ SECTIONS } SECURITY_INIT + /* .exit.text is discarded at runtime, not link time, + * to deal with references from __bug_table + */ + .exit.text : { + EXIT_TEXT + } + .exit.data : { + EXIT_DATA + } + #ifdef CONFIG_ETRAX_ARCH_V10 #ifdef CONFIG_BLK_DEV_INITRD .init.ramfs : { From a90993c693ab7bd72bcb28b105e8dd4f0698f836 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 14:39:01 +0200 Subject: [PATCH 47/51] CRIS: Fixup lookup for delay slot faults Signed-off-by: Jesper Nilsson --- arch/cris/mm/fault.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index 52b32b092603..72dbdbf0accf 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -334,8 +334,11 @@ int find_fixup_code(struct pt_regs *regs) { const struct exception_table_entry *fixup; + /* in case of delay slot fault (v32) */ + unsigned long ip = (instruction_pointer(regs) & ~0x1); - if ((fixup = search_exception_tables(instruction_pointer(regs))) != 0) { + fixup = search_exception_tables(ip); + if (fixup != 0) { /* Adjust the instruction pointer in the stackframe. */ instruction_pointer(regs) = fixup->fixup; arch_fixup(regs); From 028c1f6817c1ef49c61641dc1ae6c629e5bb32df Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 17:23:24 +0200 Subject: [PATCH 48/51] CRIS: Don't take faults while in_atomic Signed-off-by: Jesper Nilsson --- arch/cris/mm/fault.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index 72dbdbf0accf..a2b4c0b8f0fd 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -1,10 +1,7 @@ /* - * linux/arch/cris/mm/fault.c - * - * Copyright (C) 2000-2006 Axis Communications AB - * - * Authors: Bjorn Wesen + * arch/cris/mm/fault.c * + * Copyright (C) 2000-2010 Axis Communications AB */ #include @@ -108,11 +105,11 @@ do_page_fault(unsigned long address, struct pt_regs *regs, info.si_code = SEGV_MAPERR; /* - * If we're in an interrupt or have no user - * context, we must not take the fault.. + * If we're in an interrupt or "atomic" operation or have no + * user context, we must not take the fault. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); From b4e8a1813c7d65a7c28a3536da08444c21f2c37b Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 17:42:43 +0200 Subject: [PATCH 49/51] CRIS: Add config for pausing a seg-faulting process Put it on a wait queue, so we can attach gdb to the process to debug it instead of just killing it. Signed-off-by: Jesper Nilsson --- arch/cris/Kconfig.debug | 6 ++++++ arch/cris/mm/fault.c | 13 ++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/arch/cris/Kconfig.debug b/arch/cris/Kconfig.debug index 0a1d62a23614..0b9a630dc812 100644 --- a/arch/cris/Kconfig.debug +++ b/arch/cris/Kconfig.debug @@ -32,4 +32,10 @@ config DEBUG_NMI_OOPS If the system locks up without any debug information you can say Y here to make it possible to dump an OOPS with an external NMI. +config NO_SEGFAULT_TERMINATION + bool "Keep segfaulting processes" + help + Place segfaulting user mode processes on a wait queue instead of + delivering a terminating SIGSEGV to allow debugging with gdb. + endmenu diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index a2b4c0b8f0fd..7705cd7cef36 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -7,6 +7,7 @@ #include #include #include +#include #include extern int find_fixup_code(struct pt_regs *); @@ -190,14 +191,20 @@ do_page_fault(unsigned long address, struct pt_regs *regs, /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { + printk(KERN_NOTICE "%s (pid %d) segfaults for page " + "address %08lx at pc %08lx\n", + tsk->comm, tsk->pid, + address, instruction_pointer(regs)); +#ifdef CONFIG_NO_SEGFAULT_TERMINATION + DECLARE_WAIT_QUEUE_HEAD(wq); + wait_event_interruptible(wq, 0 == 1); +#else info.si_signo = SIGSEGV; info.si_errno = 0; /* info.si_code has been set above */ info.si_addr = (void *)address; force_sig_info(SIGSEGV, &info, tsk); - printk(KERN_NOTICE "%s (pid %d) segfaults for page " - "address %08lx at pc %08lx\n", - tsk->comm, tsk->pid, address, instruction_pointer(regs)); +#endif return; } From 2d495ebc55f0d5a7ac488716230d817d43818549 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 17:48:40 +0200 Subject: [PATCH 50/51] CRIS: Always dump registers for segfaulting process. Signed-off-by: Jesper Nilsson --- arch/cris/mm/fault.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index 7705cd7cef36..9dcac8ec8fa0 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -12,6 +12,7 @@ extern int find_fixup_code(struct pt_regs *); extern void die_if_kernel(const char *, struct pt_regs *, long); +extern void show_registers(struct pt_regs *regs); /* debug of low-level TLB reload */ #undef DEBUG @@ -195,6 +196,11 @@ do_page_fault(unsigned long address, struct pt_regs *regs, "address %08lx at pc %08lx\n", tsk->comm, tsk->pid, address, instruction_pointer(regs)); + + /* With DPG on, we've already dumped registers above. */ + DPG(if (0)) + show_registers(regs); + #ifdef CONFIG_NO_SEGFAULT_TERMINATION DECLARE_WAIT_QUEUE_HEAD(wq); wait_event_interruptible(wq, 0 == 1); From 85d9865721c62a551547984e6cc8bd3ba732e294 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Wed, 4 Aug 2010 18:30:01 +0200 Subject: [PATCH 51/51] CRIS: Fix alignment problem for older ld CRISv10 uses a pretty old ld, which does not allow ALIGN(0), (It becomes . = 0;) so instead we align to 1 byte. Signed-off-by: Jesper Nilsson --- arch/cris/kernel/vmlinux.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S index 789ad35f7e08..442218980db0 100644 --- a/arch/cris/kernel/vmlinux.lds.S +++ b/arch/cris/kernel/vmlinux.lds.S @@ -124,7 +124,7 @@ SECTIONS __init_end = .; __data_end = . ; /* Move to _edata ? */ - BSS_SECTION(0, 0, 0) + BSS_SECTION(1, 1, 1) . = ALIGN (0x20); _end = .;