diff options
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_dma_5xx.c | 26 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 35 | ||||
-rw-r--r-- | arch/blackfin/kernel/gptimers.c | 250 | ||||
-rw-r--r-- | arch/blackfin/kernel/reboot.c | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 116 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 2 |
7 files changed, 388 insertions, 44 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 8aeb6066b19b..8a4cfb293b27 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -9,6 +9,7 @@ obj-y := \ sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \ fixed_code.o cplbinit.o cacheinit.o reboot.o bfin_gpio.o +obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index e19164fb4cd1..503eef4c7fec 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -420,6 +420,32 @@ unsigned short get_dma_curr_ycount(unsigned int channel) } EXPORT_SYMBOL(get_dma_curr_ycount); +unsigned long get_dma_next_desc_ptr(unsigned int channel) +{ + BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE + && channel < MAX_BLACKFIN_DMA_CHANNEL)); + + return dma_ch[channel].regs->next_desc_ptr; +} +EXPORT_SYMBOL(get_dma_next_desc_ptr); + +unsigned long get_dma_curr_desc_ptr(unsigned int channel) +{ + BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE + && channel < MAX_BLACKFIN_DMA_CHANNEL)); + + return dma_ch[channel].regs->curr_desc_ptr; +} + +unsigned long get_dma_curr_addr(unsigned int channel) +{ + BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE + && channel < MAX_BLACKFIN_DMA_CHANNEL)); + + return dma_ch[channel].regs->curr_addr_ptr; +} +EXPORT_SYMBOL(get_dma_curr_addr); + static void *__dma_memcpy(void *dest, const void *src, size_t size) { int direction; /* 1 - address decrease, 0 - address increase */ diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 3fe0cd49e8db..ce85d4bf34ca 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -124,7 +124,7 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { }; #endif -#ifdef BF537_FAMILY +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { (struct gpio_port_t *) PORTFIO, (struct gpio_port_t *) PORTGIO, @@ -139,6 +139,21 @@ static unsigned short *port_fer[gpio_bank(MAX_BLACKFIN_GPIOS)] = { #endif +#ifdef BF527_FAMILY +static unsigned short *port_mux[gpio_bank(MAX_BLACKFIN_GPIOS)] = { + (unsigned short *) PORTF_MUX, + (unsigned short *) PORTG_MUX, + (unsigned short *) PORTH_MUX, +}; + +static const +u8 pmux_offset[][16] = + {{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ + { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ + }; +#endif + #ifdef BF561_FAMILY static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { (struct gpio_port_t *) FIO0_FLAG_D, @@ -186,6 +201,10 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX}; #endif +#ifdef BF527_FAMILY +static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB}; +#endif + #ifdef BF561_FAMILY static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; #endif @@ -238,7 +257,7 @@ static int cmp_label(unsigned short ident, const char *label) return -EINVAL; } -#ifdef BF537_FAMILY +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) static void port_setup(unsigned short gpio, unsigned short usage) { if (!check_gpio(gpio)) { @@ -354,6 +373,18 @@ inline u16 get_portmux(unsigned short portno) return (pmux >> (2 * gpio_sub_n(portno)) & 0x3); } +#elif defined(BF527_FAMILY) +inline void portmux_setup(unsigned short portno, unsigned short function) +{ + u16 pmux, ident = P_IDENT(portno); + u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; + + pmux = *port_mux[gpio_bank(ident)]; + pmux &= ~(3 << offset); + pmux |= (function & 3) << offset; + *port_mux[gpio_bank(ident)] = pmux; + SSYNC(); +} #else # define portmux_setup(...) do { } while (0) #endif diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c new file mode 100644 index 000000000000..cb7ba9bfc79c --- /dev/null +++ b/arch/blackfin/kernel/gptimers.c @@ -0,0 +1,250 @@ +/* + * bfin_gptimers.c - derived from bf53x_timers.c + * Driver for General Purpose Timer functions on the Blackfin processor + * + * Copyright (C) 2005 John DeHority + * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de) + * + * Licensed under the GPLv2. + */ + +#include <linux/kernel.h> +#include <linux/module.h> + +#include <asm/io.h> +#include <asm/blackfin.h> +#include <asm/gptimers.h> + +#ifdef DEBUG +# define tassert(expr) +#else +# define tassert(expr) \ + if (!(expr)) \ + 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) + +typedef struct { + uint16_t config; + uint16_t __pad; + uint32_t counter; + uint32_t period; + uint32_t width; +} GPTIMER_timer_regs; + +typedef struct { + uint16_t enable; + uint16_t __pad0; + uint16_t disable; + uint16_t __pad1; + uint32_t status; +} GPTIMER_group_regs; + +static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] = +{ + (GPTIMER_timer_regs *)TIMER0_CONFIG, + (GPTIMER_timer_regs *)TIMER1_CONFIG, + (GPTIMER_timer_regs *)TIMER2_CONFIG, +#if (MAX_BLACKFIN_GPTIMERS > 3) + (GPTIMER_timer_regs *)TIMER3_CONFIG, + (GPTIMER_timer_regs *)TIMER4_CONFIG, + (GPTIMER_timer_regs *)TIMER5_CONFIG, + (GPTIMER_timer_regs *)TIMER6_CONFIG, + (GPTIMER_timer_regs *)TIMER7_CONFIG, +#endif +#if (MAX_BLACKFIN_GPTIMERS > 8) + (GPTIMER_timer_regs *)TIMER8_CONFIG, + (GPTIMER_timer_regs *)TIMER9_CONFIG, + (GPTIMER_timer_regs *)TIMER10_CONFIG, + (GPTIMER_timer_regs *)TIMER11_CONFIG, +#endif +}; + +static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] = +{ + (GPTIMER_group_regs *)TIMER0_GROUP_REG, +#if (MAX_BLACKFIN_GPTIMERS > 8) + (GPTIMER_group_regs *)TIMER8_GROUP_REG, +#endif +}; + +static uint32_t const dis_mask[MAX_BLACKFIN_GPTIMERS] = +{ + TIMER_STATUS_TRUN0, + TIMER_STATUS_TRUN1, + TIMER_STATUS_TRUN2, +#if (MAX_BLACKFIN_GPTIMERS > 3) + TIMER_STATUS_TRUN3, + TIMER_STATUS_TRUN4, + TIMER_STATUS_TRUN5, + TIMER_STATUS_TRUN6, + TIMER_STATUS_TRUN7, +#endif +#if (MAX_BLACKFIN_GPTIMERS > 8) + TIMER_STATUS_TRUN8, + TIMER_STATUS_TRUN9, + TIMER_STATUS_TRUN10, + TIMER_STATUS_TRUN11, +#endif +}; + +static uint32_t const irq_mask[MAX_BLACKFIN_GPTIMERS] = +{ + TIMER_STATUS_TIMIL0, + TIMER_STATUS_TIMIL1, + TIMER_STATUS_TIMIL2, +#if (MAX_BLACKFIN_GPTIMERS > 3) + TIMER_STATUS_TIMIL3, + TIMER_STATUS_TIMIL4, + TIMER_STATUS_TIMIL5, + TIMER_STATUS_TIMIL6, + TIMER_STATUS_TIMIL7, +#endif +#if (MAX_BLACKFIN_GPTIMERS > 8) + TIMER_STATUS_TIMIL8, + TIMER_STATUS_TIMIL9, + TIMER_STATUS_TIMIL10, + TIMER_STATUS_TIMIL11, +#endif +}; + +void set_gptimer_pwidth(int timer_id, uint32_t value) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->width = value; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_pwidth); + +uint32_t get_gptimer_pwidth(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->width; +} +EXPORT_SYMBOL(get_gptimer_pwidth); + +void set_gptimer_period(int timer_id, uint32_t period) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->period = period; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_period); + +uint32_t get_gptimer_period(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->period; +} +EXPORT_SYMBOL(get_gptimer_period); + +uint32_t get_gptimer_count(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->counter; +} +EXPORT_SYMBOL(get_gptimer_count); + +uint32_t get_gptimer_status(int group) +{ + tassert(group < BFIN_TIMER_NUM_GROUP); + return group_regs[group]->status; +} +EXPORT_SYMBOL(get_gptimer_status); + +void set_gptimer_status(int group, uint32_t value) +{ + tassert(group < BFIN_TIMER_NUM_GROUP); + group_regs[group]->status = value; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_status); + +uint16_t get_gptimer_intr(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & irq_mask[timer_id]) ? 1 : 0; +} +EXPORT_SYMBOL(get_gptimer_intr); + +void clear_gptimer_intr(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + group_regs[BFIN_TIMER_OCTET(timer_id)]->status = irq_mask[timer_id]; +} +EXPORT_SYMBOL(clear_gptimer_intr); + +void set_gptimer_config(int timer_id, uint16_t config) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->config = config; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_config); + +uint16_t get_gptimer_config(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->config; +} +EXPORT_SYMBOL(get_gptimer_config); + +void enable_gptimers(uint16_t mask) +{ + int i; + tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0); + for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) { + group_regs[i]->enable = mask & 0xFF; + mask >>= 8; + } + SSYNC(); +} +EXPORT_SYMBOL(enable_gptimers); + +void disable_gptimers(uint16_t mask) +{ + int i; + uint16_t m = mask; + tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0); + for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) { + group_regs[i]->disable = m & 0xFF; + m >>= 8; + } + for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) + if (mask & (1 << i)) + group_regs[BFIN_TIMER_OCTET(i)]->status |= dis_mask[i]; + SSYNC(); +} +EXPORT_SYMBOL(disable_gptimers); + +void set_gptimer_pulse_hi(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->config |= TIMER_PULSE_HI; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_pulse_hi); + +void clear_gptimer_pulse_hi(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->config &= ~TIMER_PULSE_HI; + SSYNC(); +} +EXPORT_SYMBOL(clear_gptimer_pulse_hi); + +uint16_t get_enabled_gptimers(void) +{ + int i; + uint16_t result = 0; + for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) + result |= (group_regs[i]->enable << (i << 3)); + return result; +} +EXPORT_SYMBOL(get_enabled_gptimers); + +MODULE_AUTHOR("Axel Weiss (awe@aglaia-gmbh.de)"); +MODULE_DESCRIPTION("Blackfin General Purpose Timers API"); +MODULE_LICENSE("GPL"); diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index 356078ec462b..ae28aac6fec1 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -11,7 +11,7 @@ #include <asm/reboot.h> #include <asm/system.h> -#if defined(BF537_FAMILY) || defined(BF533_FAMILY) +#if defined(BF537_FAMILY) || defined(BF533_FAMILY) || defined(BF527_FAMILY) #define SYSCR_VAL 0x0 #elif defined(BF561_FAMILY) #define SYSCR_VAL 0x20 diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 8dcd76e87ed5..0e746449c29b 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -459,7 +459,7 @@ static u_long get_vco(void) return vco; } -/*Get the Core clock*/ +/* Get the Core clock */ u_long get_cclk(void) { u_long csel, ssel; @@ -493,12 +493,24 @@ u_long get_sclk(void) } EXPORT_SYMBOL(get_sclk); +unsigned long sclk_to_usecs(unsigned long sclk) +{ + return (USEC_PER_SEC * (u64)sclk) / get_sclk(); +} +EXPORT_SYMBOL(sclk_to_usecs); + +unsigned long usecs_to_sclk(unsigned long usecs) +{ + return get_sclk() / (USEC_PER_SEC * (u64)usecs); +} +EXPORT_SYMBOL(usecs_to_sclk); + /* * Get CPU information for use by the procfs. */ static int show_cpuinfo(struct seq_file *m, void *v) { - char *cpu, *mmu, *fpu, *name; + char *cpu, *mmu, *fpu, *vendor, *cache; uint32_t revid; u_long cclk = 0, sclk = 0; @@ -508,70 +520,83 @@ static int show_cpuinfo(struct seq_file *m, void *v) mmu = "none"; fpu = "none"; revid = bfin_revid(); - name = bfin_board_name; cclk = get_cclk(); sclk = get_sclk(); - seq_printf(m, "CPU:\t\tADSP-%s Rev. 0.%d\n" - "MMU:\t\t%s\n" - "FPU:\t\t%s\n" - "Core Clock:\t%9lu Hz\n" - "System Clock:\t%9lu Hz\n" - "BogoMips:\t%lu.%02lu\n" - "Calibration:\t%lu loops\n", - cpu, revid, mmu, fpu, - cclk, - sclk, - (loops_per_jiffy * HZ) / 500000, - ((loops_per_jiffy * HZ) / 5000) % 100, - (loops_per_jiffy * HZ)); - seq_printf(m, "Board Name:\t%s\n", name); - seq_printf(m, "Board Memory:\t%ld MB\n", physical_mem_end >> 20); - seq_printf(m, "Kernel Memory:\t%ld MB\n", (unsigned long)_ramend >> 20); - if (bfin_read_IMEM_CONTROL() & (ENICPLB | IMC)) - seq_printf(m, "I-CACHE:\tON\n"); - else - seq_printf(m, "I-CACHE:\tOFF\n"); - if ((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE)) - seq_printf(m, "D-CACHE:\tON" -#if defined CONFIG_BFIN_WB - " (write-back)" -#elif defined CONFIG_BFIN_WT - " (write-through)" -#endif - "\n"); - else - seq_printf(m, "D-CACHE:\tOFF\n"); - + switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) { + case 0xca: + vendor = "Analog Devices"; + break; + default: + vendor = "unknown"; + break; + } + seq_printf(m, "processor\t: %d\n" + "vendor_id\t: %s\n" + "cpu family\t: 0x%x\n" + "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK)\n" + "stepping\t: %d\n", + 0, + vendor, + (bfin_read_CHIPID() & CHIPID_FAMILY), + cpu, cclk/1000000, sclk/1000000, + revid); + + seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", + cclk/1000000, cclk%1000000, + sclk/1000000, sclk%1000000); + seq_printf(m, "bogomips\t: %lu.%02lu\n" + "Calibration\t: %lu loops\n", + (loops_per_jiffy * HZ) / 500000, + ((loops_per_jiffy * HZ) / 5000) % 100, + (loops_per_jiffy * HZ)); + + /* Check Cache configutation */ switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) { case ACACHE_BSRAM: - seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n"); + cache = "dbank-A/B\t: cache/sram"; dcache_size = 16; dsup_banks = 1; break; case ACACHE_BCACHE: - seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n"); + cache = "dbank-A/B\t: cache/cache"; dcache_size = 32; dsup_banks = 2; break; case ASRAM_BSRAM: - seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n"); + cache = "dbank-A/B\t: sram/sram"; dcache_size = 0; dsup_banks = 0; break; default: + cache = "unknown"; + dcache_size = 0; + dsup_banks = 0; break; } + /* Is it turned on? */ + if (!((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE))) + dcache_size = 0; - seq_printf(m, "I-CACHE Size:\t%dKB\n", BFIN_ICACHESIZE / 1024); - seq_printf(m, "D-CACHE Size:\t%dKB\n", dcache_size); - seq_printf(m, "I-CACHE Setup:\t%d Sub-banks/%d Ways, %d Lines/Way\n", + seq_printf(m, "cache size\t: %d KB(L1 icache) " + "%d KB(L1 dcache-%s) %d KB(L2 cache)\n", + BFIN_ICACHESIZE / 1024, dcache_size, +#if defined CONFIG_BFIN_WB + "wb" +#elif defined CONFIG_BFIN_WT + "wt" +#endif + , 0); + + seq_printf(m, "%s\n", cache); + + seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n", BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES); seq_printf(m, - "D-CACHE Setup:\t%d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", + "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, BFIN_DLINES); #ifdef CONFIG_BFIN_ICACHE_LOCK @@ -625,6 +650,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "No Ways are locked\n"); } #endif + + seq_printf(m, "board name\t: %s\n", bfin_board_name); + seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", + physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); + seq_printf(m, "kernel memory\t: %d kB (0x%p -> 0x%p)\n", + ((int)memory_end - (int)_stext) >> 10, + _stext, + (void *)memory_end); + return 0; } diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 8823e9ade584..afd044e78af6 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -118,12 +118,14 @@ static int printk_address(unsigned long address) offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); write_unlock_irq(&tasklist_lock); + mmput(mm); return printk("<0x%p> [ %s + 0x%lx ]", (void *)address, name, offset); } vml = vml->next; } + mmput(mm); } write_unlock_irq(&tasklist_lock); |