diff options
Diffstat (limited to 'arch/blackfin/kernel')
33 files changed, 573 insertions, 689 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 1f88edd4572..703dc7cf2ec 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -2,12 +2,12 @@ # arch/blackfin/kernel/Makefile # -extra-y := init_task.o vmlinux.lds +extra-y := vmlinux.lds obj-y := \ entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \ sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \ - fixed_code.o reboot.o bfin_gpio.o bfin_dma_5xx.o \ + fixed_code.o reboot.o bfin_dma.o \ exception.o dumpstack.o ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y) @@ -16,12 +16,12 @@ else obj-y += time.o endif +obj-$(CONFIG_GPIO_ADI) += bfin_gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o CFLAGS_REMOVE_ftrace.o = -pg -obj-$(CONFIG_HAVE_PWM) += pwm.o obj-$(CONFIG_IPIPE) += ipipe.o obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o obj-$(CONFIG_CPLB_INFO) += cplbinfo.o diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index 17e35465a41..37fcae95021 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c @@ -14,6 +14,7 @@ #include <linux/irq.h> #include <linux/thread_info.h> #include <linux/kbuild.h> +#include <asm/pda.h> int main(void) { diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma.c index 71dbaa4a48a..4a32f2dd5dd 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma.c @@ -1,5 +1,5 @@ /* - * bfin_dma_5xx.c - Blackfin DMA implementation + * bfin_dma.c - Blackfin DMA implementation * * Copyright 2004-2008 Analog Devices Inc. * @@ -45,9 +45,15 @@ static int __init blackfin_dma_init(void) atomic_set(&dma_ch[i].chan_status, 0); dma_ch[i].regs = dma_io_base_addr[i]; } +#if defined(CH_MEM_STREAM3_SRC) && defined(CONFIG_BF60x) + /* Mark MEMDMA Channel 3 as requested since we're using it internally */ + request_dma(CH_MEM_STREAM3_DEST, "Blackfin dma_memcpy"); + request_dma(CH_MEM_STREAM3_SRC, "Blackfin dma_memcpy"); +#else /* Mark MEMDMA Channel 0 as requested since we're using it internally */ request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy"); request_dma(CH_MEM_STREAM0_SRC, "Blackfin dma_memcpy"); +#endif #if defined(CONFIG_DEB_DMA_URGENT) bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE() @@ -84,7 +90,8 @@ static const struct file_operations proc_dma_operations = { static int __init proc_dma_init(void) { - return proc_create("dma", 0, NULL, &proc_dma_operations) != NULL; + proc_create("dma", 0, NULL, &proc_dma_operations); + return 0; } late_initcall(proc_dma_init); #endif @@ -204,6 +211,7 @@ EXPORT_SYMBOL(free_dma); # ifndef MAX_DMA_SUSPEND_CHANNELS # define MAX_DMA_SUSPEND_CHANNELS MAX_DMA_CHANNELS # endif +# ifndef CONFIG_BF60x int blackfin_dma_suspend(void) { int i; @@ -213,11 +221,13 @@ int blackfin_dma_suspend(void) printk(KERN_ERR "DMA Channel %d failed to suspend\n", i); return -EBUSY; } - if (i < MAX_DMA_SUSPEND_CHANNELS) dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map; } +#if ANOMALY_05000480 + bfin_write_DMAC_TC_PER(0x0); +#endif return 0; } @@ -227,12 +237,24 @@ void blackfin_dma_resume(void) for (i = 0; i < MAX_DMA_CHANNELS; ++i) { dma_ch[i].regs->cfg = 0; - if (i < MAX_DMA_SUSPEND_CHANNELS) dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map; } +#if ANOMALY_05000480 + bfin_write_DMAC_TC_PER(0x0111); +#endif +} +# else +int blackfin_dma_suspend(void) +{ + return 0; +} + +void blackfin_dma_resume(void) +{ } #endif +#endif /** * blackfin_dma_early_init - minimal DMA init @@ -273,10 +295,10 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR; } - if (!bfin_read16(&src_ch->cfg)) + if (!DMA_MMR_READ(&src_ch->cfg)) break; - else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) { - bfin_write16(&src_ch->cfg, 0); + else if (DMA_MMR_READ(&dst_ch->irq_status) & DMA_DONE) { + DMA_MMR_WRITE(&src_ch->cfg, 0); break; } } @@ -289,22 +311,31 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) /* Destination */ bfin_write32(&dst_ch->start_addr, dst); - bfin_write16(&dst_ch->x_count, size >> 2); - bfin_write16(&dst_ch->x_modify, 1 << 2); - bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR); + DMA_MMR_WRITE(&dst_ch->x_count, size >> 2); + DMA_MMR_WRITE(&dst_ch->x_modify, 1 << 2); + DMA_MMR_WRITE(&dst_ch->irq_status, DMA_DONE | DMA_ERR); /* Source */ bfin_write32(&src_ch->start_addr, src); - bfin_write16(&src_ch->x_count, size >> 2); - bfin_write16(&src_ch->x_modify, 1 << 2); - bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR); + DMA_MMR_WRITE(&src_ch->x_count, size >> 2); + DMA_MMR_WRITE(&src_ch->x_modify, 1 << 2); + DMA_MMR_WRITE(&src_ch->irq_status, DMA_DONE | DMA_ERR); /* Enable */ - bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32); - bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32); + DMA_MMR_WRITE(&src_ch->cfg, DMAEN | WDSIZE_32); + DMA_MMR_WRITE(&dst_ch->cfg, WNR | DI_EN_X | DMAEN | WDSIZE_32); /* Since we are atomic now, don't use the workaround ssync */ __builtin_bfin_ssync(); + +#ifdef CONFIG_BF60x + /* Work around a possible MDMA anomaly. Running 2 MDMA channels to + * transfer DDR data to L1 SRAM may corrupt data. + * Should be reverted after this issue is root caused. + */ + while (!(DMA_MMR_READ(&dst_ch->irq_status) & DMA_DONE)) + continue; +#endif } void __init early_dma_memcpy_done(void) @@ -330,6 +361,42 @@ void __init early_dma_memcpy_done(void) __builtin_bfin_ssync(); } +#if defined(CH_MEM_STREAM3_SRC) && defined(CONFIG_BF60x) +#define bfin_read_MDMA_S_CONFIG bfin_read_MDMA_S3_CONFIG +#define bfin_write_MDMA_S_CONFIG bfin_write_MDMA_S3_CONFIG +#define bfin_write_MDMA_S_START_ADDR bfin_write_MDMA_S3_START_ADDR +#define bfin_write_MDMA_S_IRQ_STATUS bfin_write_MDMA_S3_IRQ_STATUS +#define bfin_write_MDMA_S_X_COUNT bfin_write_MDMA_S3_X_COUNT +#define bfin_write_MDMA_S_X_MODIFY bfin_write_MDMA_S3_X_MODIFY +#define bfin_write_MDMA_S_Y_COUNT bfin_write_MDMA_S3_Y_COUNT +#define bfin_write_MDMA_S_Y_MODIFY bfin_write_MDMA_S3_Y_MODIFY +#define bfin_write_MDMA_D_CONFIG bfin_write_MDMA_D3_CONFIG +#define bfin_write_MDMA_D_START_ADDR bfin_write_MDMA_D3_START_ADDR +#define bfin_read_MDMA_D_IRQ_STATUS bfin_read_MDMA_D3_IRQ_STATUS +#define bfin_write_MDMA_D_IRQ_STATUS bfin_write_MDMA_D3_IRQ_STATUS +#define bfin_write_MDMA_D_X_COUNT bfin_write_MDMA_D3_X_COUNT +#define bfin_write_MDMA_D_X_MODIFY bfin_write_MDMA_D3_X_MODIFY +#define bfin_write_MDMA_D_Y_COUNT bfin_write_MDMA_D3_Y_COUNT +#define bfin_write_MDMA_D_Y_MODIFY bfin_write_MDMA_D3_Y_MODIFY +#else +#define bfin_read_MDMA_S_CONFIG bfin_read_MDMA_S0_CONFIG +#define bfin_write_MDMA_S_CONFIG bfin_write_MDMA_S0_CONFIG +#define bfin_write_MDMA_S_START_ADDR bfin_write_MDMA_S0_START_ADDR +#define bfin_write_MDMA_S_IRQ_STATUS bfin_write_MDMA_S0_IRQ_STATUS +#define bfin_write_MDMA_S_X_COUNT bfin_write_MDMA_S0_X_COUNT +#define bfin_write_MDMA_S_X_MODIFY bfin_write_MDMA_S0_X_MODIFY +#define bfin_write_MDMA_S_Y_COUNT bfin_write_MDMA_S0_Y_COUNT +#define bfin_write_MDMA_S_Y_MODIFY bfin_write_MDMA_S0_Y_MODIFY +#define bfin_write_MDMA_D_CONFIG bfin_write_MDMA_D0_CONFIG +#define bfin_write_MDMA_D_START_ADDR bfin_write_MDMA_D0_START_ADDR +#define bfin_read_MDMA_D_IRQ_STATUS bfin_read_MDMA_D0_IRQ_STATUS +#define bfin_write_MDMA_D_IRQ_STATUS bfin_write_MDMA_D0_IRQ_STATUS +#define bfin_write_MDMA_D_X_COUNT bfin_write_MDMA_D0_X_COUNT +#define bfin_write_MDMA_D_X_MODIFY bfin_write_MDMA_D0_X_MODIFY +#define bfin_write_MDMA_D_Y_COUNT bfin_write_MDMA_D0_Y_COUNT +#define bfin_write_MDMA_D_Y_MODIFY bfin_write_MDMA_D0_Y_MODIFY +#endif + /** * __dma_memcpy - program the MDMA registers * @@ -352,8 +419,8 @@ static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u */ __builtin_bfin_ssync(); - if (bfin_read_MDMA_S0_CONFIG()) - while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) + if (bfin_read_MDMA_S_CONFIG()) + while (!(bfin_read_MDMA_D_IRQ_STATUS() & DMA_DONE)) continue; if (conf & DMA2D) { @@ -368,39 +435,42 @@ static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u u32 shift = abs(dmod) >> 1; size_t ycnt = cnt >> (16 - shift); cnt = 1 << (16 - shift); - bfin_write_MDMA_D0_Y_COUNT(ycnt); - bfin_write_MDMA_S0_Y_COUNT(ycnt); - bfin_write_MDMA_D0_Y_MODIFY(dmod); - bfin_write_MDMA_S0_Y_MODIFY(smod); + bfin_write_MDMA_D_Y_COUNT(ycnt); + bfin_write_MDMA_S_Y_COUNT(ycnt); + bfin_write_MDMA_D_Y_MODIFY(dmod); + bfin_write_MDMA_S_Y_MODIFY(smod); } - bfin_write_MDMA_D0_START_ADDR(daddr); - bfin_write_MDMA_D0_X_COUNT(cnt); - bfin_write_MDMA_D0_X_MODIFY(dmod); - bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); + bfin_write_MDMA_D_START_ADDR(daddr); + bfin_write_MDMA_D_X_COUNT(cnt); + bfin_write_MDMA_D_X_MODIFY(dmod); + bfin_write_MDMA_D_IRQ_STATUS(DMA_DONE | DMA_ERR); - bfin_write_MDMA_S0_START_ADDR(saddr); - bfin_write_MDMA_S0_X_COUNT(cnt); - bfin_write_MDMA_S0_X_MODIFY(smod); - bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR); + bfin_write_MDMA_S_START_ADDR(saddr); + bfin_write_MDMA_S_X_COUNT(cnt); + bfin_write_MDMA_S_X_MODIFY(smod); + bfin_write_MDMA_S_IRQ_STATUS(DMA_DONE | DMA_ERR); - bfin_write_MDMA_S0_CONFIG(DMAEN | conf); - bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | conf); + bfin_write_MDMA_S_CONFIG(DMAEN | conf); + if (conf & DMA2D) + bfin_write_MDMA_D_CONFIG(WNR | DI_EN_Y | DMAEN | conf); + else + bfin_write_MDMA_D_CONFIG(WNR | DI_EN_X | DMAEN | conf); spin_unlock_irqrestore(&mdma_lock, flags); SSYNC(); - while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) - if (bfin_read_MDMA_S0_CONFIG()) + while (!(bfin_read_MDMA_D_IRQ_STATUS() & DMA_DONE)) + if (bfin_read_MDMA_S_CONFIG()) continue; else return; - bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); + bfin_write_MDMA_D_IRQ_STATUS(DMA_DONE | DMA_ERR); - bfin_write_MDMA_S0_CONFIG(0); - bfin_write_MDMA_D0_CONFIG(0); + bfin_write_MDMA_S_CONFIG(0); + bfin_write_MDMA_D_CONFIG(0); } /** @@ -442,8 +512,10 @@ static void *_dma_memcpy(void *pdst, const void *psrc, size_t size) } size >>= shift; +#ifndef DMA_MMR_SIZE_32 if (size > 0x10000) conf |= DMA2D; +#endif __dma_memcpy(dst, mod, src, mod, size, conf); @@ -482,6 +554,9 @@ EXPORT_SYMBOL(dma_memcpy); */ void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size) { +#ifdef DMA_MMR_SIZE_32 + _dma_memcpy(pdst, psrc, size); +#else size_t bulk, rest; bulk = size & ~0xffff; @@ -489,6 +564,7 @@ void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size) if (bulk) _dma_memcpy(pdst, psrc, bulk); _dma_memcpy(pdst + bulk, psrc + bulk, rest); +#endif return pdst; } EXPORT_SYMBOL(dma_memcpy_nocache); @@ -508,14 +584,14 @@ void *safe_dma_memcpy(void *dst, const void *src, size_t size) } EXPORT_SYMBOL(safe_dma_memcpy); -static void _dma_out(unsigned long addr, unsigned long buf, unsigned short len, +static void _dma_out(unsigned long addr, unsigned long buf, unsigned DMA_MMR_SIZE_TYPE len, u16 size, u16 dma_size) { blackfin_dcache_flush_range(buf, buf + len * size); __dma_memcpy(addr, 0, buf, size, len, dma_size); } -static void _dma_in(unsigned long addr, unsigned long buf, unsigned short len, +static void _dma_in(unsigned long addr, unsigned long buf, unsigned DMA_MMR_SIZE_TYPE len, u16 size, u16 dma_size) { blackfin_dcache_invalidate_range(buf, buf + len * size); @@ -523,7 +599,7 @@ static void _dma_in(unsigned long addr, unsigned long buf, unsigned short len, } #define MAKE_DMA_IO(io, bwl, isize, dmasize, cnst) \ -void dma_##io##s##bwl(unsigned long addr, cnst void *buf, unsigned short len) \ +void dma_##io##s##bwl(unsigned long addr, cnst void *buf, unsigned DMA_MMR_SIZE_TYPE len) \ { \ _dma_##io(addr, (unsigned long)buf, len, isize, WDSIZE_##dmasize); \ } \ diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 02796b88443..a017359c182 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -11,11 +11,8 @@ #include <linux/err.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> -#include <asm/blackfin.h> -#include <asm/gpio.h> -#include <asm/portmux.h> +#include <linux/gpio.h> #include <linux/irq.h> -#include <asm/irq_handler.h> #if ANOMALY_05000311 || ANOMALY_05000323 enum { @@ -58,17 +55,6 @@ static struct gpio_port_t * const gpio_array[] = { (struct gpio_port_t *) FIO0_FLAG_D, (struct gpio_port_t *) FIO1_FLAG_D, (struct gpio_port_t *) FIO2_FLAG_D, -#elif defined(CONFIG_BF54x) - (struct gpio_port_t *)PORTA_FER, - (struct gpio_port_t *)PORTB_FER, - (struct gpio_port_t *)PORTC_FER, - (struct gpio_port_t *)PORTD_FER, - (struct gpio_port_t *)PORTE_FER, - (struct gpio_port_t *)PORTF_FER, - (struct gpio_port_t *)PORTG_FER, - (struct gpio_port_t *)PORTH_FER, - (struct gpio_port_t *)PORTI_FER, - (struct gpio_port_t *)PORTJ_FER, #else # error no gpio arrays defined #endif @@ -167,12 +153,6 @@ DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM); inline int check_gpio(unsigned gpio) { -#if defined(CONFIG_BF54x) - if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 - || gpio == GPIO_PH14 || gpio == GPIO_PH15 - || gpio == GPIO_PJ14 || gpio == GPIO_PJ15) - return -EINVAL; -#endif if (gpio >= MAX_BLACKFIN_GPIOS) return -EINVAL; return 0; @@ -210,12 +190,6 @@ static void port_setup(unsigned gpio, unsigned short usage) else *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); SSYNC(); -#elif defined(CONFIG_BF54x) - if (usage == GPIO_USAGE) - gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); - else - gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); - SSYNC(); #endif } @@ -253,7 +227,7 @@ static int portmux_group_check(unsigned short per) u16 ident = P_IDENT(per); u16 function = P_FUNCT2MUX(per); s8 offset = port_mux[ident]; - u16 m, pmux, pfunc; + u16 m, pmux, pfunc, mask; if (offset < 0) return 0; @@ -268,10 +242,12 @@ static int portmux_group_check(unsigned short per) continue; if (offset == 1) - pfunc = (pmux >> offset) & 3; + mask = 3; else - pfunc = (pmux >> offset) & 1; - if (pfunc != function) { + mask = 1; + + pfunc = (pmux >> offset) & mask; + if (pfunc != (function & mask)) { pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", ident, function, m, pfunc); return -EINVAL; @@ -286,43 +262,21 @@ static void portmux_setup(unsigned short per) u16 ident = P_IDENT(per); u16 function = P_FUNCT2MUX(per); s8 offset = port_mux[ident]; - u16 pmux; + u16 pmux, mask; if (offset == -1) return; pmux = bfin_read_PORT_MUX(); - if (offset != 1) - pmux &= ~(1 << offset); + if (offset == 1) + mask = 3; else - pmux &= ~(3 << 1); - pmux |= (function << offset); - bfin_write_PORT_MUX(pmux); -} -#elif defined(CONFIG_BF54x) -inline void portmux_setup(unsigned short per) -{ - u16 ident = P_IDENT(per); - u16 function = P_FUNCT2MUX(per); - u32 pmux; - - pmux = gpio_array[gpio_bank(ident)]->port_mux; + mask = 1; - pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); - pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); + pmux &= ~(mask << offset); + pmux |= ((function & mask) << offset); - gpio_array[gpio_bank(ident)]->port_mux = pmux; -} - -inline u16 get_portmux(unsigned short per) -{ - u16 ident = P_IDENT(per); - u32 pmux = gpio_array[gpio_bank(ident)]->port_mux; - return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); -} -static int portmux_group_check(unsigned short per) -{ - return 0; + bfin_write_PORT_MUX(pmux); } #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) static int portmux_group_check(unsigned short per) @@ -377,7 +331,6 @@ static int portmux_group_check(unsigned short per) } #endif -#ifndef CONFIG_BF54x /*********************************************************** * * FUNCTIONS: Blackfin General Purpose Ports Access Functions @@ -570,7 +523,7 @@ static const unsigned int sic_iwr_irqs[] = { ************************************************************* * MODIFICATION HISTORY : **************************************************************/ -int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) +int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) { unsigned long flags; @@ -589,7 +542,7 @@ int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) return 0; } -int bfin_pm_standby_ctrl(unsigned ctrl) +int bfin_gpio_pm_standby_ctrl(unsigned ctrl) { u16 bank, mask, i; @@ -680,53 +633,6 @@ void bfin_gpio_pm_hibernate_restore(void) #endif -#else /* CONFIG_BF54x */ -#ifdef CONFIG_PM - -int bfin_pm_standby_ctrl(unsigned ctrl) -{ - return 0; -} - -void bfin_gpio_pm_hibernate_suspend(void) -{ - int i, bank; - - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); - - gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer; - gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux; - gpio_bank_saved[bank].data = gpio_array[bank]->data; - gpio_bank_saved[bank].inen = gpio_array[bank]->inen; - gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set; - } -} - -void bfin_gpio_pm_hibernate_restore(void) -{ - int i, bank; - - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); - - gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux; - gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer; - gpio_array[bank]->inen = gpio_bank_saved[bank].inen; - gpio_array[bank]->data_set = gpio_bank_saved[bank].data - & gpio_bank_saved[bank].dir; - gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir; - } -} -#endif - -unsigned short get_gpio_dir(unsigned gpio) -{ - return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio))); -} -EXPORT_SYMBOL(get_gpio_dir); - -#endif /* CONFIG_BF54x */ /*********************************************************** * @@ -783,11 +689,7 @@ int peripheral_request(unsigned short per, const char *label) * be requested and used by several drivers */ -#ifdef CONFIG_BF54x - if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { -#else if (!(per & P_MAYSHARE)) { -#endif /* * Allow that the identical pin function can * be requested from the same driver twice @@ -936,12 +838,9 @@ int bfin_gpio_request(unsigned gpio, const char *label) if (unlikely(is_reserved(gpio_irq, gpio, 1))) { printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); - } -#ifndef CONFIG_BF54x - else { /* Reset POLAR setting when acquiring a gpio for the first time */ + } else { /* Reset POLAR setting when acquiring a gpio for the first time */ set_gpio_polar(gpio, 0); } -#endif reserve(gpio, gpio); set_label(gpio, label); @@ -1110,11 +1009,7 @@ void bfin_gpio_irq_free(unsigned gpio) static inline void __bfin_gpio_direction_input(unsigned gpio) { -#ifdef CONFIG_BF54x - gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); -#endif gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); } @@ -1138,17 +1033,7 @@ EXPORT_SYMBOL(bfin_gpio_direction_input); void bfin_gpio_irq_prepare(unsigned gpio) { -#ifdef CONFIG_BF54x - unsigned long flags; -#endif - port_setup(gpio, GPIO_USAGE); - -#ifdef CONFIG_BF54x - flags = hard_local_irq_save(); - __bfin_gpio_direction_input(gpio); - hard_local_irq_restore(flags); -#endif } void bfin_gpio_set_value(unsigned gpio, int arg) @@ -1173,11 +1058,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value) gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); gpio_set_value(gpio, value); -#ifdef CONFIG_BF54x - gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); -#endif AWA_DUMMY_READ(dir); hard_local_irq_restore(flags); @@ -1188,9 +1069,6 @@ EXPORT_SYMBOL(bfin_gpio_direction_output); int bfin_gpio_get_value(unsigned gpio) { -#ifdef CONFIG_BF54x - return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); -#else unsigned long flags; if (unlikely(get_gpio_edge(gpio))) { @@ -1203,7 +1081,6 @@ int bfin_gpio_get_value(unsigned gpio) return ret; } else return get_gpio_data(gpio); -#endif } EXPORT_SYMBOL(bfin_gpio_get_value); @@ -1263,8 +1140,8 @@ static __init int gpio_register_proc(void) { struct proc_dir_entry *proc_gpio; - proc_gpio = proc_create("gpio", S_IRUGO, NULL, &gpio_proc_ops); - return proc_gpio != NULL; + proc_gpio = proc_create("gpio", 0, NULL, &gpio_proc_ops); + return proc_gpio == NULL; } __initcall(gpio_register_proc); #endif diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 8de92299b3e..b56bd8514b7 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c @@ -120,6 +120,7 @@ MGR_ATTR static noinline int dcplb_miss(unsigned int cpu) d_data = L2_DMEMORY; } else if (addr >= physical_mem_end) { if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { +#if defined(CONFIG_ROMFS_ON_MTD) && defined(CONFIG_MTD_ROM) mask = current_rwx_mask[cpu]; if (mask) { int page = (addr - (ASYNC_BANK0_BASE - _ramend)) >> PAGE_SHIFT; @@ -129,6 +130,7 @@ MGR_ATTR static noinline int dcplb_miss(unsigned int cpu) if (mask[idx] & bit) d_data |= CPLB_USER_RD; } +#endif } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) { addr &= ~(1 * 1024 * 1024 - 1); diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c index 886e00014d7..b49a53b583d 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c @@ -30,6 +30,7 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) { int i_d, i_i; unsigned long addr; + unsigned long cplb_pageflags, cplb_pagesize; struct cplb_entry *d_tbl = dcplb_tbl[cpu]; struct cplb_entry *i_tbl = icplb_tbl[cpu]; @@ -49,21 +50,38 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) /* Cover kernel memory with 4M pages. */ addr = 0; - for (; addr < memory_start; addr += 4 * 1024 * 1024) { +#ifdef PAGE_SIZE_16MB + cplb_pageflags = PAGE_SIZE_16MB; + cplb_pagesize = SIZE_16M; +#else + cplb_pageflags = PAGE_SIZE_4MB; + cplb_pagesize = SIZE_4M; +#endif + + + for (; addr < memory_start; addr += cplb_pagesize) { d_tbl[i_d].addr = addr; - d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_4MB; + d_tbl[i_d++].data = SDRAM_DGENERIC | cplb_pageflags; i_tbl[i_i].addr = addr; - i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_4MB; + i_tbl[i_i++].data = SDRAM_IGENERIC | cplb_pageflags; } #ifdef CONFIG_ROMKERNEL /* Cover kernel XIP flash area */ +#ifdef CONFIG_BF60x + addr = CONFIG_ROM_BASE & ~(16 * 1024 * 1024 - 1); + d_tbl[i_d].addr = addr; + d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_16MB; + i_tbl[i_i].addr = addr; + i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_16MB; +#else addr = CONFIG_ROM_BASE & ~(4 * 1024 * 1024 - 1); d_tbl[i_d].addr = addr; d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_4MB; i_tbl[i_i].addr = addr; i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_4MB; #endif +#endif /* Cover L1 memory. One 4M area for code and data each is enough. */ if (cpu == 0) { @@ -139,7 +157,7 @@ void __init generate_cplb_tables_all(void) dcplb_bounds[i_d].eaddr = BOOT_ROM_START; dcplb_bounds[i_d++].data = 0; /* BootROM -- largest one should be less than 1 meg. */ - dcplb_bounds[i_d].eaddr = BOOT_ROM_START + (1 * 1024 * 1024); + dcplb_bounds[i_d].eaddr = BOOT_ROM_START + BOOT_ROM_LENGTH; dcplb_bounds[i_d++].data = SDRAM_DGENERIC; if (L2_LENGTH) { /* Addressing hole up to L2 SRAM. */ @@ -178,7 +196,7 @@ void __init generate_cplb_tables_all(void) icplb_bounds[i_i].eaddr = BOOT_ROM_START; icplb_bounds[i_i++].data = 0; /* BootROM -- largest one should be less than 1 meg. */ - icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024); + icplb_bounds[i_i].eaddr = BOOT_ROM_START + BOOT_ROM_LENGTH; icplb_bounds[i_i++].data = SDRAM_IGENERIC; if (L2_LENGTH) { diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c index 5b88861d618..79cc0f6dcdd 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c @@ -145,7 +145,7 @@ MGR_ATTR static int dcplb_miss(int cpu) unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); int status = bfin_read_DCPLB_STATUS(); int idx; - unsigned long d_data, base, addr1, eaddr; + unsigned long d_data, base, addr1, eaddr, cplb_pagesize, cplb_pageflags; nr_dcplb_miss[cpu]++; if (unlikely(status & FAULT_USERSUPV)) @@ -167,18 +167,43 @@ MGR_ATTR static int dcplb_miss(int cpu) if (unlikely(d_data == 0)) return CPLB_NO_ADDR_MATCH; - addr1 = addr & ~(SIZE_4M - 1); addr &= ~(SIZE_1M - 1); d_data |= PAGE_SIZE_1MB; - if (addr1 >= base && (addr1 + SIZE_4M) <= eaddr) { + + /* BF60x support large than 4M CPLB page size */ +#ifdef PAGE_SIZE_16MB + cplb_pageflags = PAGE_SIZE_16MB; + cplb_pagesize = SIZE_16M; +#else + cplb_pageflags = PAGE_SIZE_4MB; + cplb_pagesize = SIZE_4M; +#endif + +find_pagesize: + addr1 = addr & ~(cplb_pagesize - 1); + if (addr1 >= base && (addr1 + cplb_pagesize) <= eaddr) { /* * This works because * (PAGE_SIZE_4MB & PAGE_SIZE_1MB) == PAGE_SIZE_1MB. */ - d_data |= PAGE_SIZE_4MB; + d_data |= cplb_pageflags; addr = addr1; + goto found_pagesize; + } else { + if (cplb_pagesize > SIZE_4M) { + cplb_pageflags = PAGE_SIZE_4MB; + cplb_pagesize = SIZE_4M; + goto find_pagesize; + } } +found_pagesize: +#ifdef CONFIG_BF60x + if ((addr >= ASYNC_BANK0_BASE) + && (addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)) + d_data |= PAGE_SIZE_64MB; +#endif + /* Pick entry to evict */ idx = evict_one_dcplb(cpu); diff --git a/arch/blackfin/kernel/cplbinfo.c b/arch/blackfin/kernel/cplbinfo.c index 0bdaa517a50..5b80d59e66e 100644 --- a/arch/blackfin/kernel/cplbinfo.c +++ b/arch/blackfin/kernel/cplbinfo.c @@ -17,8 +17,13 @@ #include <asm/cplbinit.h> #include <asm/blackfin.h> -static char const page_strtbl[][3] = { "1K", "4K", "1M", "4M" }; -#define page(flags) (((flags) & 0x30000) >> 16) +static char const page_strtbl[][4] = { + "1K", "4K", "1M", "4M", +#ifdef CONFIG_BF60x + "16K", "64K", "16M", "64M", +#endif +}; +#define page(flags) (((flags) & 0x70000) >> 16) #define strpage(flags) page_strtbl[page(flags)] struct cplbinfo_data { @@ -116,14 +121,12 @@ static const struct seq_operations cplbinfo_sops = { static int cplbinfo_open(struct inode *inode, struct file *file) { - struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); char cplb_type; - unsigned int cpu; + unsigned int cpu = (unsigned long)PDE_DATA(file_inode(file)); int ret; struct seq_file *m; struct cplbinfo_data *cdata; - cpu = (unsigned int)pde->data; cplb_type = cpu & CPLBINFO_DCPLB_FLAG ? 'D' : 'I'; cpu &= ~CPLBINFO_DCPLB_FLAG; diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c index 92f66482628..947ad083233 100644 --- a/arch/blackfin/kernel/debug-mmrs.c +++ b/arch/blackfin/kernel/debug-mmrs.c @@ -10,6 +10,7 @@ #include <linux/fs.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/i2c/bfin_twi.h> #include <asm/blackfin.h> #include <asm/gpio.h> @@ -105,6 +106,7 @@ DEFINE_SYSREG(seqstat, , ); DEFINE_SYSREG(syscfg, , CSYNC()); #define D_SYSREG(sr) debugfs_create_file(#sr, S_IRUSR|S_IWUSR, parent, NULL, &fops_sysreg_##sr) +#ifndef CONFIG_BF60x /* * CAN */ @@ -223,8 +225,10 @@ bfin_debug_mmrs_dma(struct dentry *parent, unsigned long base, int num, char mdm __DMA(CURR_DESC_PTR, curr_desc_ptr); __DMA(CURR_ADDR, curr_addr); __DMA(IRQ_STATUS, irq_status); +#ifndef CONFIG_BF60x if (strcmp(pfx, "IMDMA") != 0) __DMA(PERIPHERAL_MAP, peripheral_map); +#endif __DMA(CURR_X_COUNT, curr_x_count); __DMA(CURR_Y_COUNT, curr_y_count); } @@ -568,7 +572,7 @@ bfin_debug_mmrs_uart(struct dentry *parent, unsigned long base, int num) #endif } #define UART(num) bfin_debug_mmrs_uart(parent, UART##num##_DLL, num) - +#endif /* CONFIG_BF60x */ /* * The actual debugfs generation */ @@ -740,7 +744,7 @@ static int __init bfin_debug_mmrs_init(void) D32(WPDACNT0); D32(WPDACNT1); D32(WPSTAT); - +#ifndef CONFIG_BF60x /* System MMRs */ #ifdef ATAPI_CONTROL parent = debugfs_create_dir("atapi", top); @@ -1873,7 +1877,7 @@ static int __init bfin_debug_mmrs_init(void) } #endif /* BF54x */ - +#endif /* CONFIG_BF60x */ debug_mmrs_dentry = top; return 0; diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c index f0d1118f182..df437e52d9d 100644 --- a/arch/blackfin/kernel/dma-mapping.c +++ b/arch/blackfin/kernel/dma-mapping.c @@ -13,6 +13,7 @@ #include <linux/dma-mapping.h> #include <linux/scatterlist.h> #include <linux/export.h> +#include <linux/bitmap.h> static spinlock_t dma_page_lock; static unsigned long *dma_page; @@ -46,24 +47,17 @@ static inline unsigned int get_pages(size_t size) static unsigned long __alloc_dma_pages(unsigned int pages) { unsigned long ret = 0, flags; - int i, count = 0; + unsigned long start; if (dma_initialized == 0) dma_alloc_init(_ramend - DMA_UNCACHED_REGION, _ramend); spin_lock_irqsave(&dma_page_lock, flags); - for (i = 0; i < dma_pages;) { - if (test_bit(i++, dma_page) == 0) { - if (++count == pages) { - while (count--) - __set_bit(--i, dma_page); - - ret = dma_base + (i << PAGE_SHIFT); - break; - } - } else - count = 0; + start = bitmap_find_next_zero_area(dma_page, dma_pages, 0, pages, 0); + if (start < dma_pages) { + ret = dma_base + (start << PAGE_SHIFT); + bitmap_set(dma_page, start, pages); } spin_unlock_irqrestore(&dma_page_lock, flags); return ret; @@ -73,7 +67,6 @@ static void __free_dma_pages(unsigned long addr, unsigned int pages) { unsigned long page = (addr - dma_base) >> PAGE_SHIFT; unsigned long flags; - int i; if ((page + pages) > dma_pages) { printk(KERN_ERR "%s: freeing outside range.\n", __func__); @@ -81,9 +74,7 @@ static void __free_dma_pages(unsigned long addr, unsigned int pages) } spin_lock_irqsave(&dma_page_lock, flags); - for (i = page; i < page + pages; i++) - __clear_bit(i, dma_page); - + bitmap_clear(dma_page, page, pages); spin_unlock_irqrestore(&dma_page_lock, flags); } @@ -122,12 +113,13 @@ void __dma_sync(dma_addr_t addr, size_t size, EXPORT_SYMBOL(__dma_sync); int -dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, +dma_map_sg(struct device *dev, struct scatterlist *sg_list, int nents, enum dma_data_direction direction) { + struct scatterlist *sg; int i; - for (i = 0; i < nents; i++, sg++) { + for_each_sg(sg_list, sg, nents, i) { sg->dma_address = (dma_addr_t) sg_virt(sg); __dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction); } @@ -136,12 +128,13 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, } EXPORT_SYMBOL(dma_map_sg); -void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg_list, int nelems, enum dma_data_direction direction) { + struct scatterlist *sg; int i; - for (i = 0; i < nelems; i++, sg++) { + for_each_sg(sg_list, sg, nelems, i) { sg->dma_address = (dma_addr_t) sg_virt(sg); __dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction); } diff --git a/arch/blackfin/kernel/dumpstack.c b/arch/blackfin/kernel/dumpstack.c index 5cfbaa29821..95ba6d9e9a3 100644 --- a/arch/blackfin/kernel/dumpstack.c +++ b/arch/blackfin/kernel/dumpstack.c @@ -168,6 +168,7 @@ void dump_stack(void) #endif trace_buffer_save(tflags); dump_bfin_trace_buffer(); + dump_stack_print_info(KERN_DEFAULT); show_stack(current, &stack); trace_buffer_restore(tflags); } diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 84ed8375113..61fbd2de993 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c @@ -25,8 +25,6 @@ extern struct console *bfin_earlyserial_init(unsigned int port, extern struct console *bfin_jc_early_init(void); #endif -static struct console *early_console; - /* Default console */ #define DEFAULT_PORT 0 #define DEFAULT_CFLAG CS8|B57600 diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S index 686478f5f66..4071265fc4f 100644 --- a/arch/blackfin/kernel/entry.S +++ b/arch/blackfin/kernel/entry.S @@ -46,63 +46,14 @@ ENTRY(_ret_from_fork) SP += -12; pseudo_long_call _schedule_tail, p5; SP += 12; - r0 = [sp + PT_IPEND]; - cc = bittst(r0,1); - if cc jump .Lin_kernel; + p1 = [sp++]; + r0 = [sp++]; + cc = p1 == 0; + if cc jump .Lfork; + sp += -12; + call (p1); + sp += 12; +.Lfork: RESTORE_CONTEXT rti; -.Lin_kernel: - bitclr(r0,1); - [sp + PT_IPEND] = r0; - /* do a 'fake' RTI by jumping to [RETI] - * to avoid clearing supervisor mode in child - */ - r0 = [sp + PT_PC]; - [sp + PT_P0] = r0; - - RESTORE_ALL_SYS - jump (p0); ENDPROC(_ret_from_fork) - -ENTRY(_sys_fork) - r0 = -EINVAL; -#if (ANOMALY_05000371) - nop; - nop; - nop; -#endif - rts; -ENDPROC(_sys_fork) - -ENTRY(_sys_vfork) - r0 = sp; - r0 += 24; - [--sp] = rets; - SP += -12; - pseudo_long_call _bfin_vfork, p2; - SP += 12; - rets = [sp++]; - rts; -ENDPROC(_sys_vfork) - -ENTRY(_sys_clone) - r0 = sp; - r0 += 24; - [--sp] = rets; - SP += -12; - pseudo_long_call _bfin_clone, p2; - SP += 12; - rets = [sp++]; - rts; -ENDPROC(_sys_clone) - -ENTRY(_sys_rt_sigreturn) - r0 = sp; - r0 += 24; - [--sp] = rets; - SP += -12; - pseudo_long_call _do_rt_sigreturn, p2; - SP += 12; - rets = [sp++]; - rts; -ENDPROC(_sys_rt_sigreturn) diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c index 9277905b82c..095de0fa044 100644 --- a/arch/blackfin/kernel/ftrace.c +++ b/arch/blackfin/kernel/ftrace.c @@ -65,11 +65,8 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ftrace_modify_code(ip, call, sizeof(call)); } -int __init ftrace_dyn_arch_init(void *data) +int __init ftrace_dyn_arch_init(void) { - /* return value is done indirectly via data */ - *(unsigned long *)data = 0; - return 0; } diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c index 06459f4bf43..d776773d386 100644 --- a/arch/blackfin/kernel/gptimers.c +++ b/arch/blackfin/kernel/gptimers.c @@ -23,7 +23,11 @@ printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", __FILE__, __func__, __LINE__); #endif -#define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1) +#ifndef CONFIG_BF60x +# define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1) +#else +# define BFIN_TIMER_NUM_GROUP 1 +#endif static struct bfin_gptimer_regs * const timer_regs[MAX_BLACKFIN_GPTIMERS] = { @@ -158,6 +162,74 @@ uint32_t get_gptimer_count(unsigned int timer_id) } EXPORT_SYMBOL(get_gptimer_count); +#ifdef CONFIG_BF60x +void set_gptimer_delay(unsigned int timer_id, uint32_t delay) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + bfin_write(&timer_regs[timer_id]->delay, delay); + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_delay); + +uint32_t get_gptimer_delay(unsigned int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return bfin_read(&timer_regs[timer_id]->delay); +} +EXPORT_SYMBOL(get_gptimer_delay); +#endif + +#ifdef CONFIG_BF60x +int get_gptimer_intr(unsigned int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return !!(bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->data_ilat) & timil_mask[timer_id]); +} +EXPORT_SYMBOL(get_gptimer_intr); + +void clear_gptimer_intr(unsigned int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->data_ilat, timil_mask[timer_id]); +} +EXPORT_SYMBOL(clear_gptimer_intr); + +int get_gptimer_over(unsigned int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return !!(bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->stat_ilat) & tovf_mask[timer_id]); +} +EXPORT_SYMBOL(get_gptimer_over); + +void clear_gptimer_over(unsigned int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->stat_ilat, tovf_mask[timer_id]); +} +EXPORT_SYMBOL(clear_gptimer_over); + +int get_gptimer_run(unsigned int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return !!(bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->run) & trun_mask[timer_id]); +} +EXPORT_SYMBOL(get_gptimer_run); + +uint32_t get_gptimer_status(unsigned int group) +{ + tassert(group < BFIN_TIMER_NUM_GROUP); + return bfin_read(&group_regs[group]->data_ilat); +} +EXPORT_SYMBOL(get_gptimer_status); + +void set_gptimer_status(unsigned int group, uint32_t value) +{ + tassert(group < BFIN_TIMER_NUM_GROUP); + bfin_write(&group_regs[group]->data_ilat, value); + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_status); +#else uint32_t get_gptimer_status(unsigned int group) { tassert(group < BFIN_TIMER_NUM_GROUP); @@ -212,6 +284,7 @@ int get_gptimer_run(unsigned int timer_id) return !!(read_gptimer_status(timer_id) & trun_mask[timer_id]); } EXPORT_SYMBOL(get_gptimer_run); +#endif void set_gptimer_config(unsigned int timer_id, uint16_t config) { @@ -231,6 +304,12 @@ EXPORT_SYMBOL(get_gptimer_config); void enable_gptimers(uint16_t mask) { int i; +#ifdef CONFIG_BF60x + uint16_t imask; + imask = bfin_read16(TIMER_DATA_IMSK); + imask &= ~mask; + bfin_write16(TIMER_DATA_IMSK, imask); +#endif tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0); for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) { bfin_write(&group_regs[i]->enable, mask & 0xFF); @@ -253,12 +332,16 @@ static void _disable_gptimers(uint16_t mask) void disable_gptimers(uint16_t mask) { +#ifndef CONFIG_BF60x int i; _disable_gptimers(mask); for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) if (mask & (1 << i)) bfin_write(&group_regs[BFIN_TIMER_OCTET(i)]->status, trun_mask[i]); SSYNC(); +#else + _disable_gptimers(mask); +#endif } EXPORT_SYMBOL(disable_gptimers); diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c deleted file mode 100644 index d3970e8acd1..00000000000 --- a/arch/blackfin/kernel/init_task.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2004-2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later - */ - -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/init_task.h> -#include <linux/mqueue.h> -#include <linux/fs.h> - -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -struct task_struct init_task = INIT_TASK(init_task); -EXPORT_SYMBOL(init_task); - -/* - * Initial thread structure. - * - * We need to make sure that this is 8192-byte aligned due to the - * way process stacks are handled. This is done by having a special - * "init_task" linker map entry. - */ -union thread_union init_thread_union - __init_task_data = { -INIT_THREAD_INFO(init_task)}; diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index dbe11220cc5..f657b38163e 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -31,7 +31,6 @@ #include <linux/kthread.h> #include <linux/unistd.h> #include <linux/io.h> -#include <asm/system.h> #include <linux/atomic.h> #include <asm/irq_handler.h> diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index ff3d747154a..0ba25764b8c 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -11,6 +11,7 @@ #include <linux/kallsyms.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/seq_file.h> #include <asm/irq_handler.h> #include <asm/trace.h> #include <asm/pda.h> @@ -33,37 +34,15 @@ static struct irq_desc bad_irq_desc = { #endif #ifdef CONFIG_PROC_FS -int show_interrupts(struct seq_file *p, void *v) +int arch_show_interrupts(struct seq_file *p, int prec) { - int i = *(loff_t *) v, j; - struct irqaction *action; - unsigned long flags; - - if (i < NR_IRQS) { - struct irq_desc *desc = irq_to_desc(i); - - raw_spin_lock_irqsave(&desc->lock, flags); - action = desc->action; - if (!action) - goto skip; - seq_printf(p, "%3d: ", i); - for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); - seq_printf(p, " %8s", irq_desc_get_chip(desc)->name); - seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) - seq_printf(p, " %s", action->name); - - seq_putc(p, '\n'); - skip: - raw_spin_unlock_irqrestore(&desc->lock, flags); - } else if (i == NR_IRQS) { - seq_printf(p, "NMI: "); - for_each_online_cpu(j) - seq_printf(p, "%10u ", cpu_pda[j].__nmi_count); - seq_printf(p, " CORE Non Maskable Interrupt\n"); - seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count)); - } + int j; + + seq_printf(p, "%*s: ", prec, "NMI"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_pda[j].__nmi_count); + seq_printf(p, " CORE Non Maskable Interrupt\n"); + seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); return 0; } #endif diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index 9b80b152435..fa53faeeb0e 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -9,6 +9,7 @@ #include <linux/ptrace.h> /* for linux pt_regs struct */ #include <linux/kgdb.h> #include <linux/uaccess.h> +#include <asm/irq_regs.h> void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) { @@ -329,6 +330,9 @@ static void bfin_disable_hw_debug(struct pt_regs *regs) } #ifdef CONFIG_SMP +extern void generic_exec_single(int cpu, struct call_single_data *data, int wait); +static struct call_single_data kgdb_smp_ipi_data[NR_CPUS]; + void kgdb_passive_cpu_callback(void *info) { kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); @@ -336,12 +340,18 @@ void kgdb_passive_cpu_callback(void *info) void kgdb_roundup_cpus(unsigned long flags) { - smp_call_function(kgdb_passive_cpu_callback, NULL, 0); + unsigned int cpu; + + for (cpu = cpumask_first(cpu_online_mask); cpu < nr_cpu_ids; + cpu = cpumask_next(cpu, cpu_online_mask)) { + kgdb_smp_ipi_data[cpu].func = kgdb_passive_cpu_callback; + generic_exec_single(cpu, &kgdb_smp_ipi_data[cpu], 0); + } } void kgdb_roundup_cpu(int cpu, unsigned long flags) { - smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0); + generic_exec_single(cpu, &kgdb_smp_ipi_data[cpu], 0); } #endif diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c index 4a7dcfea98a..18ab004aea1 100644 --- a/arch/blackfin/kernel/kgdb_test.c +++ b/arch/blackfin/kernel/kgdb_test.c @@ -13,7 +13,6 @@ #include <asm/current.h> #include <asm/uaccess.h> -#include <asm/system.h> #include <asm/blackfin.h> diff --git a/arch/blackfin/kernel/perf_event.c b/arch/blackfin/kernel/perf_event.c index e47d19ae3e0..974e55496db 100644 --- a/arch/blackfin/kernel/perf_event.c +++ b/arch/blackfin/kernel/perf_event.c @@ -468,7 +468,7 @@ static void bfin_pmu_setup(int cpu) memset(cpuhw, 0, sizeof(struct cpu_hw_events)); } -static int __cpuinit +static int bfin_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 8dd0416673c..4aa5545c4fd 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -19,6 +19,7 @@ #include <asm/blackfin.h> #include <asm/fixed_code.h> #include <asm/mem_map.h> +#include <asm/irq.h> asmlinkage void ret_from_fork(void); @@ -38,12 +39,6 @@ int nr_l1stack_tasks; void *l1_stack_base; unsigned long l1_stack_len; -/* - * Powermanagement idle function, if any.. - */ -void (*pm_idle)(void) = NULL; -EXPORT_SYMBOL(pm_idle); - void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); @@ -51,15 +46,14 @@ EXPORT_SYMBOL(pm_power_off); * The idle loop on BFIN */ #ifdef CONFIG_IDLE_L1 -static void default_idle(void)__attribute__((l1_text)); -void cpu_idle(void)__attribute__((l1_text)); +void arch_cpu_idle(void)__attribute__((l1_text)); #endif /* * This is our default idle handler. We need to disable * interrupts here to ensure we don't miss a wakeup call. */ -static void default_idle(void) +void arch_cpu_idle(void) { #ifdef CONFIG_IPIPE ipipe_suspend_domain(); @@ -71,68 +65,12 @@ static void default_idle(void) hard_local_irq_enable(); } -/* - * The idle thread. We try to conserve power, while trying to keep - * overall latency low. The architecture specific idle is passed - * a value to indicate the level of "idleness" of the system. - */ -void cpu_idle(void) -{ - /* endless idle loop with no priority at all */ - while (1) { - void (*idle)(void) = pm_idle; - #ifdef CONFIG_HOTPLUG_CPU - if (cpu_is_offline(smp_processor_id())) - cpu_die(); -#endif - if (!idle) - idle = default_idle; - tick_nohz_idle_enter(); - rcu_idle_enter(); - while (!need_resched()) - idle(); - rcu_idle_exit(); - tick_nohz_idle_exit(); - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } -} - -/* - * This gets run with P1 containing the - * function to call, and R1 containing - * the "args". Note P0 is clobbered on the way here. - */ -void kernel_thread_helper(void); -__asm__(".section .text\n" - ".align 4\n" - "_kernel_thread_helper:\n\t" - "\tsp += -12;\n\t" - "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous"); - -/* - * Create a kernel thread. - */ -pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) +void arch_cpu_idle_dead(void) { - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.r1 = (unsigned long)arg; - regs.p1 = (unsigned long)fn; - regs.pc = (unsigned long)kernel_thread_helper; - regs.orig_p0 = -1; - /* Set bit 2 to tell ret_from_fork we should be returning to kernel - mode. */ - regs.ipend = 0x8002; - __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):); - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, - NULL); + cpu_die(); } -EXPORT_SYMBOL(kernel_thread); +#endif /* * Do necessary setup to start up a newly executed thread. @@ -160,70 +98,48 @@ void flush_thread(void) { } -asmlinkage int bfin_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, - NULL); -} - -asmlinkage int bfin_clone(struct pt_regs *regs) +asmlinkage int bfin_clone(unsigned long clone_flags, unsigned long newsp) { - unsigned long clone_flags; - unsigned long newsp; - #ifdef __ARCH_SYNC_CORE_DCACHE - if (current->rt.nr_cpus_allowed == num_possible_cpus()) + if (current->nr_cpus_allowed == num_possible_cpus()) set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id())); #endif - - /* syscall2 puts clone_flags in r0 and usp in r1 */ - clone_flags = regs->r0; - newsp = regs->r1; - if (!newsp) - newsp = rdusp(); - else + if (newsp) newsp -= 12; - return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, 0, NULL, NULL); } int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long topstk, - struct task_struct *p, struct pt_regs *regs) + struct task_struct *p) { struct pt_regs *childregs; + unsigned long *v; childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; - *childregs = *regs; - childregs->r0 = 0; + v = ((unsigned long *)childregs) - 2; + if (unlikely(p->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + v[0] = usp; + v[1] = topstk; + childregs->orig_p0 = -1; + childregs->ipend = 0x8000; + __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):); + p->thread.usp = 0; + } else { + *childregs = *current_pt_regs(); + childregs->r0 = 0; + p->thread.usp = usp ? : rdusp(); + v[0] = v[1] = 0; + } - p->thread.usp = usp; - p->thread.ksp = (unsigned long)childregs; + p->thread.ksp = (unsigned long)v; p->thread.pc = (unsigned long)ret_from_fork; return 0; } -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char __user *name, - const char __user *const __user *argv, - const char __user *const __user *envp) -{ - int error; - char *filename; - struct pt_regs *regs = (struct pt_regs *)((&name) + 6); - - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - return error; - error = do_execve(filename, argv, envp, regs); - putname(filename); - return error; -} - unsigned long get_wchan(struct task_struct *p) { unsigned long fp, pc; @@ -330,12 +246,16 @@ int in_mem_const(unsigned long addr, unsigned long size, { return in_mem_const_off(addr, size, 0, const_addr, const_size); } +#ifdef CONFIG_BF60x +#define ASYNC_ENABLED(bnum, bctlnum) 1 +#else #define ASYNC_ENABLED(bnum, bctlnum) \ ({ \ (bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? 0 : \ bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? 0 : \ 1; \ }) +#endif /* * We can't read EBIU banks that aren't enabled or we end up hanging * on the access to the async space. Make sure we validate accesses diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 75089f80855..8b8fe671b1a 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -20,7 +20,6 @@ #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/processor.h> #include <asm/asm-offsets.h> #include <asm/dma.h> @@ -118,6 +117,7 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data) int is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len) { + bool valid; struct vm_area_struct *vma; struct sram_list_struct *sraml; @@ -125,9 +125,12 @@ is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long if (start + len < start) return -EIO; + down_read(&child->mm->mmap_sem); vma = find_vma(child->mm, start); - if (vma && start >= vma->vm_start && start + len <= vma->vm_end) - return 0; + valid = vma && start >= vma->vm_start && start + len <= vma->vm_end; + up_read(&child->mm->mmap_sem); + if (valid) + return 0; for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next) if (start >= (unsigned long)sraml->addr diff --git a/arch/blackfin/kernel/pwm.c b/arch/blackfin/kernel/pwm.c deleted file mode 100644 index 33f5942733b..00000000000 --- a/arch/blackfin/kernel/pwm.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Blackfin Pulse Width Modulation (PWM) core - * - * Copyright (c) 2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/pwm.h> -#include <linux/slab.h> - -#include <asm/gptimers.h> -#include <asm/portmux.h> - -struct pwm_device { - unsigned id; - unsigned short pin; -}; - -static const unsigned short pwm_to_gptimer_per[] = { - P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5, - P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11, -}; - -struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - struct pwm_device *pwm; - int ret; - - /* XXX: pwm_id really should be unsigned */ - if (pwm_id < 0) - return NULL; - - pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); - if (!pwm) - return pwm; - - pwm->id = pwm_id; - if (pwm->id >= ARRAY_SIZE(pwm_to_gptimer_per)) - goto err; - - pwm->pin = pwm_to_gptimer_per[pwm->id]; - ret = peripheral_request(pwm->pin, label); - if (ret) - goto err; - - return pwm; - err: - kfree(pwm); - return NULL; -} -EXPORT_SYMBOL(pwm_request); - -void pwm_free(struct pwm_device *pwm) -{ - peripheral_free(pwm->pin); - kfree(pwm); -} -EXPORT_SYMBOL(pwm_free); - -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) -{ - unsigned long period, duty; - unsigned long long val; - - if (duty_ns < 0 || duty_ns > period_ns) - return -EINVAL; - - val = (unsigned long long)get_sclk() * period_ns; - do_div(val, NSEC_PER_SEC); - period = val; - - val = (unsigned long long)period * duty_ns; - do_div(val, period_ns); - duty = period - val; - - if (duty >= period) - duty = period - 1; - - set_gptimer_config(pwm->id, TIMER_MODE_PWM | TIMER_PERIOD_CNT); - set_gptimer_pwidth(pwm->id, duty); - set_gptimer_period(pwm->id, period); - - return 0; -} -EXPORT_SYMBOL(pwm_config); - -int pwm_enable(struct pwm_device *pwm) -{ - enable_gptimer(pwm->id); - return 0; -} -EXPORT_SYMBOL(pwm_enable); - -void pwm_disable(struct pwm_device *pwm) -{ - disable_gptimer(pwm->id); -} -EXPORT_SYMBOL(pwm_disable); diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index c4c0081b199..c4f50a32850 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -9,7 +9,6 @@ #include <linux/interrupt.h> #include <asm/bfin-global.h> #include <asm/reboot.h> -#include <asm/system.h> #include <asm/bfrom.h> /* A system soft reset makes external memory unusable so force @@ -23,6 +22,7 @@ __attribute__ ((__l1_text__, __noreturn__)) static void bfin_reset(void) { +#ifndef CONFIG_BF60x if (!ANOMALY_05000353 && !ANOMALY_05000386) bfrom_SoftReset((void *)(L1_SCRATCH_START + L1_SCRATCH_LENGTH - 20)); @@ -58,7 +58,6 @@ static void bfin_reset(void) if (__SILICON_REVISION__ < 1 && bfin_revid() < 1) bfin_read_SWRST(); #endif - /* Wait for the SWRST write to complete. Cannot rely on SSYNC * though as the System state is all reset now. */ @@ -73,6 +72,10 @@ static void bfin_reset(void) while (1) /* Issue core reset */ asm("raise 1"); +#else + while (1) + bfin_write_RCU0_CTL(0x1); +#endif } __attribute__((weak)) @@ -83,7 +86,6 @@ void native_machine_restart(char *cmd) void machine_restart(char *cmd) { native_machine_restart(cmd); - local_irq_disable(); if (smp_processor_id()) smp_call_function((void *)bfin_reset, 0, 1); else diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index d6102c86d03..4f424ae3b36 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -17,7 +17,7 @@ #ifdef CONFIG_MTD_UCLINUX #include <linux/mtd/map.h> #include <linux/ext2_fs.h> -#include <linux/cramfs_fs.h> +#include <uapi/linux/cramfs_fs.h> #include <linux/romfs_fs.h> #endif @@ -25,11 +25,19 @@ #include <asm/cacheflush.h> #include <asm/blackfin.h> #include <asm/cplbinit.h> +#include <asm/clocks.h> #include <asm/div64.h> #include <asm/cpu.h> #include <asm/fixed_code.h> #include <asm/early_printk.h> #include <asm/irq_handler.h> +#include <asm/pda.h> +#ifdef CONFIG_BF60x +#include <mach/pm.h> +#endif +#ifdef CONFIG_SCB_PRIORITY +#include <asm/scb.h> +#endif u16 _bfin_swrst; EXPORT_SYMBOL(_bfin_swrst); @@ -47,7 +55,6 @@ EXPORT_SYMBOL(reserved_mem_dcache_on); #ifdef CONFIG_MTD_UCLINUX extern struct map_info uclinux_ram_map; unsigned long memory_mtd_end, memory_mtd_start, mtd_size; -unsigned long _ebss; EXPORT_SYMBOL(memory_mtd_end); EXPORT_SYMBOL(memory_mtd_start); EXPORT_SYMBOL(mtd_size); @@ -95,7 +102,7 @@ void __init generate_cplb_tables(void) } #endif -void __cpuinit bfin_setup_caches(unsigned int cpu) +void bfin_setup_caches(unsigned int cpu) { #ifdef CONFIG_BFIN_ICACHE bfin_icache_init(icplb_tbl[cpu]); @@ -161,7 +168,7 @@ void __cpuinit bfin_setup_caches(unsigned int cpu) #endif } -void __cpuinit bfin_setup_cpudata(unsigned int cpu) +void bfin_setup_cpudata(unsigned int cpu) { struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu); @@ -610,7 +617,8 @@ static __init void memory_setup(void) /* ROM_FS is XIP, so if we found it, we need to limit memory */ if (memory_end > max_mem) { - pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20); + pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", + (max_mem - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); memory_end = max_mem; } } @@ -640,7 +648,8 @@ static __init void memory_setup(void) * doesn't exist, or we don't need to - then dont. */ if (memory_end > max_mem) { - pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20); + pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", + (max_mem - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); memory_end = max_mem; } @@ -659,8 +668,8 @@ static __init void memory_setup(void) init_mm.end_data = (unsigned long)_edata; init_mm.brk = (unsigned long)0; - printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20); - printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20); + printk(KERN_INFO "Board Memory: %ldMB\n", (physical_mem_end - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); + printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", (_ramend - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); printk(KERN_INFO "Memory map:\n" " fixedcode = 0x%p-0x%p\n" @@ -703,7 +712,7 @@ void __init find_min_max_pfn(void) int i; max_pfn = 0; - min_low_pfn = memory_end; + min_low_pfn = PFN_DOWN(memory_end); for (i = 0; i < bfin_memmap.nr_map; i++) { unsigned long start, end; @@ -746,8 +755,7 @@ static __init void setup_bootmem_allocator(void) /* pfn of the first usable page frame after kernel image*/ if (min_low_pfn < memory_start >> PAGE_SHIFT) min_low_pfn = memory_start >> PAGE_SHIFT; - - start_pfn = PAGE_OFFSET >> PAGE_SHIFT; + start_pfn = CONFIG_PHY_RAM_BASE_ADDRESS >> PAGE_SHIFT; end_pfn = memory_end >> PAGE_SHIFT; /* @@ -792,8 +800,8 @@ static __init void setup_bootmem_allocator(void) } /* reserve memory before memory_start, including bootmap */ - reserve_bootmem(PAGE_OFFSET, - memory_start + bootmap_size + PAGE_SIZE - 1 - PAGE_OFFSET, + reserve_bootmem(CONFIG_PHY_RAM_BASE_ADDRESS, + memory_start + bootmap_size + PAGE_SIZE - 1 - CONFIG_PHY_RAM_BASE_ADDRESS, BOOTMEM_DEFAULT); } @@ -842,13 +850,40 @@ static inline int __init get_mem_size(void) break; } switch (ddrctl & 0x30000) { - case DEVWD_4: ret *= 2; - case DEVWD_8: ret *= 2; - case DEVWD_16: break; + case DEVWD_4: + ret *= 2; + case DEVWD_8: + ret *= 2; + case DEVWD_16: + break; } if ((ddrctl & 0xc000) == 0x4000) ret *= 2; return ret; +#elif defined(CONFIG_BF60x) + u32 ddrctl = bfin_read_DMC0_CFG(); + int ret; + switch (ddrctl & 0xf00) { + case DEVSZ_64: + ret = 64 / 8; + break; + case DEVSZ_128: + ret = 128 / 8; + break; + case DEVSZ_256: + ret = 256 / 8; + break; + case DEVSZ_512: + ret = 512 / 8; + break; + case DEVSZ_1G: + ret = 1024 / 8; + break; + case DEVSZ_2G: + ret = 2048 / 8; + break; + } + return ret; #endif BUG(); } @@ -858,6 +893,22 @@ void __init native_machine_early_platform_add_devices(void) { } +#ifdef CONFIG_BF60x +static inline u_long bfin_get_clk(char *name) +{ + struct clk *clk; + u_long clk_rate; + + clk = clk_get(NULL, name); + if (IS_ERR(clk)) + return 0; + + clk_rate = clk_get_rate(clk); + clk_put(clk); + return clk_rate; +} +#endif + void __init setup_arch(char **cmdline_p) { u32 mmr; @@ -868,6 +919,7 @@ void __init setup_arch(char **cmdline_p) enable_shadow_console(); /* Check to make sure we are running on the right processor */ + mmr = bfin_cpuid(); if (unlikely(CPUID != bfin_cpuid())) printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", CPU, bfin_cpuid(), bfin_revid()); @@ -888,6 +940,10 @@ void __init setup_arch(char **cmdline_p) memset(&bfin_memmap, 0, sizeof(bfin_memmap)); +#ifdef CONFIG_BF60x + /* Should init clock device before parse command early */ + clk_init(); +#endif /* If the user does not specify things on the command line, use * what the bootloader set things up as */ @@ -902,6 +958,7 @@ void __init setup_arch(char **cmdline_p) memory_setup(); +#ifndef CONFIG_BF60x /* Initialize Async memory banks */ bfin_write_EBIU_AMBCTL0(AMBCTL0VAL); bfin_write_EBIU_AMBCTL1(AMBCTL1VAL); @@ -911,6 +968,7 @@ void __init setup_arch(char **cmdline_p) bfin_write_EBIU_MODE(CONFIG_EBIU_MODEVAL); bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTLVAL); #endif +#endif #ifdef CONFIG_BFIN_HYSTERESIS_CONTROL bfin_write_PORTF_HYSTERESIS(HYST_PORTF_0_15); bfin_write_PORTG_HYSTERESIS(HYST_PORTG_0_15); @@ -936,7 +994,7 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Hardware Trace %s and %sabled\n", (mmr & 0x1) ? "active" : "off", (mmr & 0x2) ? "en" : "dis"); - +#ifndef CONFIG_BF60x mmr = bfin_read_SYSCR(); printk(KERN_INFO "Boot Mode: %i\n", mmr & 0xF); @@ -978,7 +1036,7 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Recovering from Watchdog event\n"); else if (_bfin_swrst & RESET_SOFTWARE) printk(KERN_NOTICE "Reset caused by Software reset\n"); - +#endif printk(KERN_INFO "Blackfin support (C) 2004-2010 Analog Devices, Inc.\n"); if (bfin_compiled_revid() == 0xffff) printk(KERN_INFO "Compiled for ADSP-%s Rev any, running on 0.%d\n", CPU, bfin_revid()); @@ -1006,8 +1064,13 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); +#ifdef CONFIG_BF60x + printk(KERN_INFO "Processor Speed: %lu MHz core clock, %lu MHz SCLk, %lu MHz SCLK0, %lu MHz SCLK1 and %lu MHz DCLK\n", + cclk / 1000000, bfin_get_clk("SYSCLK") / 1000000, get_sclk0() / 1000000, get_sclk1() / 1000000, get_dclk() / 1000000); +#else printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", cclk / 1000000, sclk / 1000000); +#endif setup_bootmem_allocator(); @@ -1041,6 +1104,9 @@ void __init setup_arch(char **cmdline_p) #endif init_exception_vectors(); bfin_cache_init(); /* Initialize caches for the boot CPU */ +#ifdef CONFIG_SCB_PRIORITY + init_scb(); +#endif } static int __init topology_init(void) @@ -1058,10 +1124,12 @@ subsys_initcall(topology_init); /* Get the input clock frequency */ static u_long cached_clkin_hz = CONFIG_CLKIN_HZ; +#ifndef CONFIG_BF60x static u_long get_clkin_hz(void) { return cached_clkin_hz; } +#endif static int __init early_init_clkin_hz(char *buf) { cached_clkin_hz = simple_strtoul(buf, NULL, 0); @@ -1073,6 +1141,7 @@ static int __init early_init_clkin_hz(char *buf) } early_param("clkin_hz=", early_init_clkin_hz); +#ifndef CONFIG_BF60x /* Get the voltage input multiplier */ static u_long get_vco(void) { @@ -1095,10 +1164,14 @@ static u_long get_vco(void) cached_vco *= msel; return cached_vco; } +#endif /* Get the Core clock */ u_long get_cclk(void) { +#ifdef CONFIG_BF60x + return bfin_get_clk("CCLK"); +#else static u_long cached_cclk_pll_div, cached_cclk; u_long csel, ssel; @@ -1118,12 +1191,39 @@ u_long get_cclk(void) else cached_cclk = get_vco() >> csel; return cached_cclk; +#endif } EXPORT_SYMBOL(get_cclk); -/* Get the System clock */ +#ifdef CONFIG_BF60x +/* Get the bf60x clock of SCLK0 domain */ +u_long get_sclk0(void) +{ + return bfin_get_clk("SCLK0"); +} +EXPORT_SYMBOL(get_sclk0); + +/* Get the bf60x clock of SCLK1 domain */ +u_long get_sclk1(void) +{ + return bfin_get_clk("SCLK1"); +} +EXPORT_SYMBOL(get_sclk1); + +/* Get the bf60x DRAM clock */ +u_long get_dclk(void) +{ + return bfin_get_clk("DCLK"); +} +EXPORT_SYMBOL(get_dclk); +#endif + +/* Get the default system clock */ u_long get_sclk(void) { +#ifdef CONFIG_BF60x + return get_sclk0(); +#else static u_long cached_sclk; u_long ssel; @@ -1144,6 +1244,7 @@ u_long get_sclk(void) cached_sclk = get_vco() / ssel; return cached_sclk; +#endif } EXPORT_SYMBOL(get_sclk); @@ -1219,7 +1320,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "(Compiled for Rev %d)", bfin_compiled_revid()); } - seq_printf(m, "\ncpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", + seq_printf(m, "\ncpu MHz\t\t: %lu.%06lu/%lu.%06lu\n", cclk/1000000, cclk%1000000, sclk/1000000, sclk%1000000); seq_printf(m, "bogomips\t: %lu.%02lu\n" diff --git a/arch/blackfin/kernel/shadow_console.c b/arch/blackfin/kernel/shadow_console.c index 557e9fef406..aeb8343eeb0 100644 --- a/arch/blackfin/kernel/shadow_console.c +++ b/arch/blackfin/kernel/shadow_console.c @@ -15,9 +15,9 @@ #include <asm/irq_handler.h> #include <asm/early_printk.h> -#define SHADOW_CONSOLE_START (0x500) -#define SHADOW_CONSOLE_END (0x1000) -#define SHADOW_CONSOLE_MAGIC_LOC (0x4F0) +#define SHADOW_CONSOLE_START (CONFIG_PHY_RAM_BASE_ADDRESS + 0x500) +#define SHADOW_CONSOLE_END (CONFIG_PHY_RAM_BASE_ADDRESS + 0x1000) +#define SHADOW_CONSOLE_MAGIC_LOC (CONFIG_PHY_RAM_BASE_ADDRESS + 0x4F0) #define SHADOW_CONSOLE_MAGIC (0xDEADBEEF) static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index d536f35d1f4..b022af6c48f 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c @@ -10,7 +10,6 @@ #include <linux/tty.h> #include <linux/personality.h> #include <linux/binfmts.h> -#include <linux/freezer.h> #include <linux/uaccess.h> #include <linux/tracehook.h> @@ -19,8 +18,6 @@ #include <asm/fixed_code.h> #include <asm/syscall.h> -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - /* Location of the trace bit in SYSCFG. */ #define TRACE_BITS 0x0001 @@ -40,11 +37,6 @@ struct rt_sigframe { struct ucontext uc; }; -asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) -{ - return do_sigaltstack(uss, uoss, rdusp()); -} - static inline int rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *pr0) { @@ -85,9 +77,9 @@ rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *p return err; } -asmlinkage int do_rt_sigreturn(unsigned long __unused) +asmlinkage int sys_rt_sigreturn(void) { - struct pt_regs *regs = (struct pt_regs *)__unused; + struct pt_regs *regs = current_pt_regs(); unsigned long usp = rdusp(); struct rt_sigframe *frame = (struct rt_sigframe *)(usp); sigset_t set; @@ -98,16 +90,12 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->usp) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; return r0; @@ -185,25 +173,27 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); - err |= - __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(rdusp()), &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= __save_altstack(&frame->uc.uc_stack, rdusp()); err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up registers for signal handler */ - wrusp((unsigned long)frame); if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor *) ka->sa.sa_handler; - __get_user(regs->pc, &funcptr->text); - __get_user(regs->p3, &funcptr->GOT); + u32 pc, p3; + err |= __get_user(pc, &funcptr->text); + err |= __get_user(p3, &funcptr->GOT); + if (err) + return -EFAULT; + regs->pc = pc; + regs->p3 = p3; } else regs->pc = (unsigned long)ka->sa.sa_handler; + wrusp((unsigned long)frame); regs->rets = SIGRETURN_STUB; regs->r0 = frame->sig; @@ -211,12 +201,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, regs->r2 = (unsigned long)(&frame->uc); return 0; - - give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); - return -EFAULT; } static inline void @@ -252,30 +236,21 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) /* * OK, we're invoking a handler */ -static int +static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, - sigset_t *oldset, struct pt_regs *regs) + struct pt_regs *regs) { - int ret; - /* are we from a system call? to see pt_regs->orig_p0 */ if (regs->orig_p0 >= 0) /* If so, check system call restarting.. */ handle_restart(regs, ka, 1); /* set up the stack frame */ - ret = setup_rt_frame(sig, ka, info, oldset, regs); - - if (ret == 0) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - return ret; + if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) + force_sigsegv(sig, current); + else + signal_delivered(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); } /* @@ -292,37 +267,16 @@ asmlinkage void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; - sigset_t *oldset; current->thread.esp0 = (unsigned long)regs; - if (try_to_freeze()) - goto no_signal; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - tracehook_signal_handler(signr, &info, &ka, regs, - test_thread_flag(TIF_SINGLESTEP)); - } - + handle_signal(signr, &info, &ka, regs); return; } - no_signal: /* Did we come from a system call? */ if (regs->orig_p0 >= 0) /* Restart the system call - no handlers present */ @@ -330,10 +284,7 @@ asmlinkage void do_signal(struct pt_regs *regs) /* if there's no signal to deliver, we just put the saved sigmask * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } + restore_saved_sigmask(); } /* @@ -341,14 +292,12 @@ asmlinkage void do_signal(struct pt_regs *regs) */ asmlinkage void do_notify_resume(struct pt_regs *regs) { - if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_RESTORE_SIGMASK)) + if (test_thread_flag(TIF_SIGPENDING)) do_signal(regs); if (test_thread_flag(TIF_NOTIFY_RESUME)) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); - if (current->replacement_session_keyring) - key_replace_session_keyring(); } } diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index d98f2d69b0c..cb0a4845339 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c @@ -66,8 +66,14 @@ void __init setup_gptimer0(void) { disable_gptimers(TIMER0bit); +#ifdef CONFIG_BF60x + bfin_write16(TIMER_DATA_IMSK, 0); + set_gptimer_config(TIMER0_id, TIMER_OUT_DIS + | TIMER_MODE_PWM_CONT | TIMER_PULSE_HI | TIMER_IRQ_PER); +#else set_gptimer_config(TIMER0_id, \ TIMER_OUT_DIS | TIMER_PERIOD_CNT | TIMER_MODE_PWM); +#endif set_gptimer_period(TIMER0_id, -1); set_gptimer_pwidth(TIMER0_id, -2); SSYNC(); @@ -135,9 +141,15 @@ static void bfin_gptmr0_set_mode(enum clock_event_mode mode, { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: { +#ifndef CONFIG_BF60x set_gptimer_config(TIMER0_id, \ TIMER_OUT_DIS | TIMER_IRQ_ENA | \ TIMER_PERIOD_CNT | TIMER_MODE_PWM); +#else + set_gptimer_config(TIMER0_id, TIMER_OUT_DIS + | TIMER_MODE_PWM_CONT | TIMER_PULSE_HI | TIMER_IRQ_PER); +#endif + set_gptimer_period(TIMER0_id, get_sclk() / HZ); set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1); enable_gptimers(TIMER0bit); @@ -145,8 +157,14 @@ static void bfin_gptmr0_set_mode(enum clock_event_mode mode, } case CLOCK_EVT_MODE_ONESHOT: disable_gptimers(TIMER0bit); +#ifndef CONFIG_BF60x set_gptimer_config(TIMER0_id, \ TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM); +#else + set_gptimer_config(TIMER0_id, TIMER_OUT_DIS | TIMER_MODE_PWM + | TIMER_PULSE_HI | TIMER_IRQ_WID_DLY); +#endif + set_gptimer_period(TIMER0_id, 0); break; case CLOCK_EVT_MODE_UNUSED: @@ -160,7 +178,7 @@ static void bfin_gptmr0_set_mode(enum clock_event_mode mode, static void bfin_gptmr0_ack(void) { - set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0); + clear_gptimer_intr(TIMER0_id); } static void __init bfin_gptmr0_init(void) @@ -197,7 +215,7 @@ static struct clock_event_device clockevent_gptmr0 = { .rating = 300, .irq = IRQ_TIMER0, .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = bfin_gptmr0_set_next_event, .set_mode = bfin_gptmr0_set_mode, }; @@ -311,7 +329,6 @@ void bfin_coretmr_clockevent_init(void) evt->broadcast = smp_timer_broadcast; #endif - evt->name = "bfin_core_timer"; evt->rating = 350; evt->irq = -1; diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index 2310b249675..3126b920a4a 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -85,7 +85,7 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *)) /* * Should return useconds since last timer tick */ -u32 arch_gettimeoffset(void) +static u32 blackfin_gettimeoffset(void) { unsigned long offset; unsigned long clocks_per_jiffy; @@ -141,6 +141,10 @@ void read_persistent_clock(struct timespec *ts) void __init time_init(void) { +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET + arch_gettimeoffset = blackfin_gettimeoffset; +#endif + #ifdef CONFIG_RTC_DRV_BFIN /* [#2663] hack to filter junk RTC values that would cause * userspace to have to deal with time values greater than diff --git a/arch/blackfin/kernel/trace.c b/arch/blackfin/kernel/trace.c index 050db44fe91..c36efa0c716 100644 --- a/arch/blackfin/kernel/trace.c +++ b/arch/blackfin/kernel/trace.c @@ -10,6 +10,8 @@ #include <linux/hardirq.h> #include <linux/thread_info.h> #include <linux/mm.h> +#include <linux/oom.h> +#include <linux/sched.h> #include <linux/uaccess.h> #include <linux/module.h> #include <linux/kallsyms.h> @@ -21,13 +23,13 @@ #include <asm/fixed_code.h> #include <asm/traps.h> #include <asm/irq_handler.h> +#include <asm/pda.h> void decode_address(char *buf, unsigned long address) { struct task_struct *p; struct mm_struct *mm; - unsigned long flags, offset; - unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); + unsigned long offset; struct rb_node *n; #ifdef CONFIG_KALLSYMS @@ -111,17 +113,17 @@ void decode_address(char *buf, unsigned long address) * mappings of all our processes and see if we can't be a whee * bit more specific */ - write_lock_irqsave(&tasklist_lock, flags); + read_lock(&tasklist_lock); for_each_process(p) { - mm = (in_atomic ? p->mm : get_task_mm(p)); - if (!mm) - continue; + struct task_struct *t; - if (!down_read_trylock(&mm->mmap_sem)) { - if (!in_atomic) - mmput(mm); + t = find_lock_task_mm(p); + if (!t) continue; - } + + mm = t->mm; + if (!down_read_trylock(&mm->mmap_sem)) + goto __continue; for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) { struct vm_area_struct *vma; @@ -130,7 +132,7 @@ void decode_address(char *buf, unsigned long address) if (address >= vma->vm_start && address < vma->vm_end) { char _tmpbuf[256]; - char *name = p->comm; + char *name = t->comm; struct file *file = vma->vm_file; if (file) { @@ -163,8 +165,7 @@ void decode_address(char *buf, unsigned long address) name, vma->vm_start, vma->vm_end); up_read(&mm->mmap_sem); - if (!in_atomic) - mmput(mm); + task_unlock(t); if (buf[0] == '\0') sprintf(buf, "[ %s ] dynamic memory", name); @@ -174,8 +175,8 @@ void decode_address(char *buf, unsigned long address) } up_read(&mm->mmap_sem); - if (!in_atomic) - mmput(mm); +__continue: + task_unlock(t); } /* @@ -185,7 +186,7 @@ void decode_address(char *buf, unsigned long address) sprintf(buf, "/* kernel dynamic memory */"); done: - write_unlock_irqrestore(&tasklist_lock, flags); + read_unlock(&tasklist_lock); } #define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1) @@ -852,6 +853,8 @@ void show_regs(struct pt_regs *fp) unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); pr_notice("\n"); + show_regs_print_info(KERN_NOTICE); + if (CPUID != bfin_cpuid()) pr_notice("Compiled for cpu family 0x%04x (Rev %d), " "but running on:0x%04x (Rev %d)\n", diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 655f25d139a..de5c2c3ebd9 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -17,6 +17,7 @@ #include <asm/trace.h> #include <asm/fixed_code.h> #include <asm/pseudo_instructions.h> +#include <asm/pda.h> #ifdef CONFIG_KGDB # include <linux/kgdb.h> diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index ba35864b2b7..c9eec84aa25 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -145,7 +145,7 @@ SECTIONS .text_l1 L1_CODE_START : AT(LOADADDR(.exit.data) + SIZEOF(.exit.data)) #else - .init.data : AT(__data_lma + __data_len) + .init.data : AT(__data_lma + __data_len + 32) { __sinitdata = .; INIT_DATA |
