diff options
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/asm-offsets.c | 10 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 26 | ||||
-rw-r--r-- | arch/blackfin/kernel/debug-mmrs.c | 109 | ||||
-rw-r--r-- | arch/blackfin/kernel/ftrace.c | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/gptimers.c | 93 | ||||
-rw-r--r-- | arch/blackfin/kernel/ipipe.c | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/module.c | 21 | ||||
-rw-r--r-- | arch/blackfin/kernel/nmi.c | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/process.c | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/pwm.c | 100 | ||||
-rw-r--r-- | arch/blackfin/kernel/reboot.c | 4 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 16 | ||||
-rw-r--r-- | arch/blackfin/kernel/time.c | 4 | ||||
-rw-r--r-- | arch/blackfin/kernel/vmlinux.lds.S | 1 |
15 files changed, 263 insertions, 129 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index d550b24d9e9..b7bdc42fe1a 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -21,6 +21,7 @@ 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 bd32c09b934..17e35465a41 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c @@ -138,6 +138,16 @@ int main(void) DEFINE(PDA_DF_SEQSTAT, offsetof(struct blackfin_pda, seqstat_doublefault)); DEFINE(PDA_DF_RETX, offsetof(struct blackfin_pda, retx_doublefault)); #endif + + /* PDA initial management */ + DEFINE(PDA_INIT_RETX, offsetof(struct blackfin_initial_pda, retx)); +#ifdef CONFIG_DEBUG_DOUBLEFAULT + DEFINE(PDA_INIT_DF_DCPLB, offsetof(struct blackfin_initial_pda, dcplb_doublefault_addr)); + DEFINE(PDA_INIT_DF_ICPLB, offsetof(struct blackfin_initial_pda, icplb_doublefault_addr)); + DEFINE(PDA_INIT_DF_SEQSTAT, offsetof(struct blackfin_initial_pda, seqstat_doublefault)); + DEFINE(PDA_INIT_DF_RETX, offsetof(struct blackfin_initial_pda, retx_doublefault)); +#endif + #ifdef CONFIG_SMP /* Inter-core lock (in L2 SRAM) */ DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot)); diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index bcf8cf6fe41..02796b88443 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -118,6 +118,9 @@ static struct str_ident { #if defined(CONFIG_PM) static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; +# ifdef BF538_FAMILY +static unsigned short port_fer_saved[3]; +# endif #endif static void gpio_error(unsigned gpio) @@ -604,6 +607,11 @@ void bfin_gpio_pm_hibernate_suspend(void) { int i, bank; +#ifdef BF538_FAMILY + for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i) + port_fer_saved[i] = *port_fer[i]; +#endif + for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); @@ -625,6 +633,10 @@ void bfin_gpio_pm_hibernate_suspend(void) gpio_bank_saved[bank].maska = gpio_array[bank]->maska; } +#ifdef BFIN_SPECIAL_GPIO_BANKS + bfin_special_gpio_pm_hibernate_suspend(); +#endif + AWA_DUMMY_READ(maska); } @@ -632,6 +644,11 @@ void bfin_gpio_pm_hibernate_restore(void) { int i, bank; +#ifdef BF538_FAMILY + for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i) + *port_fer[i] = port_fer_saved[i]; +#endif + for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); @@ -653,6 +670,11 @@ void bfin_gpio_pm_hibernate_restore(void) gpio_array[bank]->both = gpio_bank_saved[bank].both; gpio_array[bank]->maska = gpio_bank_saved[bank].maska; } + +#ifdef BFIN_SPECIAL_GPIO_BANKS + bfin_special_gpio_pm_hibernate_restore(); +#endif + AWA_DUMMY_READ(maska); } @@ -691,9 +713,9 @@ void bfin_gpio_pm_hibernate_restore(void) 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]->dir_set = gpio_bank_saved[bank].dir; gpio_array[bank]->data_set = gpio_bank_saved[bank].data - | gpio_bank_saved[bank].dir; + & gpio_bank_saved[bank].dir; + gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir; } } #endif diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c index fce4807ceef..92f66482628 100644 --- a/arch/blackfin/kernel/debug-mmrs.c +++ b/arch/blackfin/kernel/debug-mmrs.c @@ -27,7 +27,7 @@ #define PORT_MUX BFIN_PORT_MUX #endif -#define _d(name, bits, addr, perms) debugfs_create_x##bits(name, perms, parent, (u##bits *)addr) +#define _d(name, bits, addr, perms) debugfs_create_x##bits(name, perms, parent, (u##bits *)(addr)) #define d(name, bits, addr) _d(name, bits, addr, S_IRUSR|S_IWUSR) #define d_RO(name, bits, addr) _d(name, bits, addr, S_IRUSR) #define d_WO(name, bits, addr) _d(name, bits, addr, S_IWUSR) @@ -223,7 +223,8 @@ 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); - __DMA(PERIPHERAL_MAP, peripheral_map); + if (strcmp(pfx, "IMDMA") != 0) + __DMA(PERIPHERAL_MAP, peripheral_map); __DMA(CURR_X_COUNT, curr_x_count); __DMA(CURR_Y_COUNT, curr_y_count); } @@ -277,6 +278,32 @@ bfin_debug_mmrs_gptimer(struct dentry *parent, unsigned long base, int num) } #define GPTIMER(num) bfin_debug_mmrs_gptimer(parent, TIMER##num##_CONFIG, num) +#define GPTIMER_GROUP_OFF(mmr) REGS_OFF(gptimer_group, mmr) +#define __GPTIMER_GROUP(uname, lname) __REGS(gptimer_group, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_gptimer_group(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf; + + if (num == -1) { + _buf = buf + sprintf(buf, "TIMER_"); + __GPTIMER_GROUP(ENABLE, enable); + __GPTIMER_GROUP(DISABLE, disable); + __GPTIMER_GROUP(STATUS, status); + } else { + /* These MMRs are a bit odd as the group # is a suffix */ + _buf = buf + sprintf(buf, "TIMER_ENABLE%i", num); + d(buf, 16, base + GPTIMER_GROUP_OFF(enable)); + + _buf = buf + sprintf(buf, "TIMER_DISABLE%i", num); + d(buf, 16, base + GPTIMER_GROUP_OFF(disable)); + + _buf = buf + sprintf(buf, "TIMER_STATUS%i", num); + d(buf, 32, base + GPTIMER_GROUP_OFF(status)); + } +} +#define GPTIMER_GROUP(mmr, num) bfin_debug_mmrs_gptimer_group(parent, mmr, num) + /* * Handshake MDMA */ @@ -296,6 +323,29 @@ bfin_debug_mmrs_hmdma(struct dentry *parent, unsigned long base, int num) #define HMDMA(num) bfin_debug_mmrs_hmdma(parent, HMDMA##num##_CONTROL, num) /* + * Peripheral Interrupts (PINT/GPIO) + */ +#ifdef PINT0_MASK_SET +#define __PINT(uname, lname) __REGS(pint, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_pint(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, PINT, num); + __PINT(MASK_SET, mask_set); + __PINT(MASK_CLEAR, mask_clear); + __PINT(REQUEST, request); + __PINT(ASSIGN, assign); + __PINT(EDGE_SET, edge_set); + __PINT(EDGE_CLEAR, edge_clear); + __PINT(INVERT_SET, invert_set); + __PINT(INVERT_CLEAR, invert_clear); + __PINT(PINSTATE, pinstate); + __PINT(LATCH, latch); +} +#define PINT(num) bfin_debug_mmrs_pint(parent, PINT##num##_MASK_SET, num) +#endif + +/* * Port/GPIO */ #define bfin_gpio_regs gpio_port_t @@ -747,7 +797,7 @@ static int __init bfin_debug_mmrs_init(void) #endif parent = debugfs_create_dir("dmac", top); -#ifdef DMA_TC_CNT +#ifdef DMAC_TC_CNT D16(DMAC_TC_CNT); D16(DMAC_TC_PER); #endif @@ -1005,29 +1055,19 @@ static int __init bfin_debug_mmrs_init(void) #endif parent = debugfs_create_dir("gptimer", top); -#ifdef TIMER_DISABLE - D16(TIMER_DISABLE); - D16(TIMER_ENABLE); - D32(TIMER_STATUS); +#ifdef TIMER_ENABLE + GPTIMER_GROUP(TIMER_ENABLE, -1); #endif -#ifdef TIMER_DISABLE0 - D16(TIMER_DISABLE0); - D16(TIMER_ENABLE0); - D32(TIMER_STATUS0); +#ifdef TIMER_ENABLE0 + GPTIMER_GROUP(TIMER_ENABLE0, 0); #endif -#ifdef TIMER_DISABLE1 - D16(TIMER_DISABLE1); - D16(TIMER_ENABLE1); - D32(TIMER_STATUS1); +#ifdef TIMER_ENABLE1 + GPTIMER_GROUP(TIMER_ENABLE1, 1); #endif /* XXX: Should convert BF561 MMR names */ #ifdef TMRS4_DISABLE - D16(TMRS4_DISABLE); - D16(TMRS4_ENABLE); - D32(TMRS4_STATUS); - D16(TMRS8_DISABLE); - D16(TMRS8_ENABLE); - D32(TMRS8_STATUS); + GPTIMER_GROUP(TMRS4_ENABLE, 0); + GPTIMER_GROUP(TMRS8_ENABLE, 1); #endif GPTIMER(0); GPTIMER(1); @@ -1253,6 +1293,14 @@ static int __init bfin_debug_mmrs_init(void) D32(OTP_DATA3); #endif +#ifdef PINT0_MASK_SET + parent = debugfs_create_dir("pint", top); + PINT(0); + PINT(1); + PINT(2); + PINT(3); +#endif + #ifdef PIXC_CTL parent = debugfs_create_dir("pixc", top); D16(PIXC_CTL); @@ -1816,7 +1864,6 @@ static int __init bfin_debug_mmrs_init(void) { int num; unsigned long base; - char *_buf, buf[32]; base = PORTA_FER; for (num = 0; num < 10; ++num) { @@ -1824,24 +1871,6 @@ static int __init bfin_debug_mmrs_init(void) base += sizeof(struct bfin_gpio_regs); } -#define __PINT(uname, lname) __REGS(pint, #uname, lname) - parent = debugfs_create_dir("pint", top); - base = PINT0_MASK_SET; - for (num = 0; num < 4; ++num) { - _buf = REGS_STR_PFX(buf, PINT, num); - __PINT(MASK_SET, mask_set); - __PINT(MASK_CLEAR, mask_clear); - __PINT(IRQ, irq); - __PINT(ASSIGN, assign); - __PINT(EDGE_SET, edge_set); - __PINT(EDGE_CLEAR, edge_clear); - __PINT(INVERT_SET, invert_set); - __PINT(INVERT_CLEAR, invert_clear); - __PINT(PINSTATE, pinstate); - __PINT(LATCH, latch); - base += sizeof(struct bfin_pint_regs); - } - } #endif /* BF54x */ diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c index 48808a12b42..9277905b82c 100644 --- a/arch/blackfin/kernel/ftrace.c +++ b/arch/blackfin/kernel/ftrace.c @@ -9,7 +9,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/cacheflush.h> #ifdef CONFIG_DYNAMIC_FTRACE diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c index 8b81dc04488..06459f4bf43 100644 --- a/arch/blackfin/kernel/gptimers.c +++ b/arch/blackfin/kernel/gptimers.c @@ -25,49 +25,33 @@ #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] = +static struct bfin_gptimer_regs * const timer_regs[MAX_BLACKFIN_GPTIMERS] = { - (GPTIMER_timer_regs *)TIMER0_CONFIG, - (GPTIMER_timer_regs *)TIMER1_CONFIG, - (GPTIMER_timer_regs *)TIMER2_CONFIG, + (void *)TIMER0_CONFIG, + (void *)TIMER1_CONFIG, + (void *)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, + (void *)TIMER3_CONFIG, + (void *)TIMER4_CONFIG, + (void *)TIMER5_CONFIG, + (void *)TIMER6_CONFIG, + (void *)TIMER7_CONFIG, # if (MAX_BLACKFIN_GPTIMERS > 8) - (GPTIMER_timer_regs *)TIMER8_CONFIG, - (GPTIMER_timer_regs *)TIMER9_CONFIG, - (GPTIMER_timer_regs *)TIMER10_CONFIG, + (void *)TIMER8_CONFIG, + (void *)TIMER9_CONFIG, + (void *)TIMER10_CONFIG, # if (MAX_BLACKFIN_GPTIMERS > 11) - (GPTIMER_timer_regs *)TIMER11_CONFIG, + (void *)TIMER11_CONFIG, # endif # endif #endif }; -static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] = +static struct bfin_gptimer_group_regs * const group_regs[BFIN_TIMER_NUM_GROUP] = { - (GPTIMER_group_regs *)TIMER0_GROUP_REG, + (void *)TIMER0_GROUP_REG, #if (MAX_BLACKFIN_GPTIMERS > 8) - (GPTIMER_group_regs *)TIMER8_GROUP_REG, + (void *)TIMER8_GROUP_REG, #endif }; @@ -140,7 +124,7 @@ static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] = void set_gptimer_pwidth(unsigned int timer_id, uint32_t value) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - timer_regs[timer_id]->width = value; + bfin_write(&timer_regs[timer_id]->width, value); SSYNC(); } EXPORT_SYMBOL(set_gptimer_pwidth); @@ -148,14 +132,14 @@ EXPORT_SYMBOL(set_gptimer_pwidth); uint32_t get_gptimer_pwidth(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return timer_regs[timer_id]->width; + return bfin_read(&timer_regs[timer_id]->width); } EXPORT_SYMBOL(get_gptimer_pwidth); void set_gptimer_period(unsigned int timer_id, uint32_t period) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - timer_regs[timer_id]->period = period; + bfin_write(&timer_regs[timer_id]->period, period); SSYNC(); } EXPORT_SYMBOL(set_gptimer_period); @@ -163,71 +147,76 @@ EXPORT_SYMBOL(set_gptimer_period); uint32_t get_gptimer_period(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return timer_regs[timer_id]->period; + return bfin_read(&timer_regs[timer_id]->period); } EXPORT_SYMBOL(get_gptimer_period); uint32_t get_gptimer_count(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return timer_regs[timer_id]->counter; + return bfin_read(&timer_regs[timer_id]->counter); } EXPORT_SYMBOL(get_gptimer_count); uint32_t get_gptimer_status(unsigned int group) { tassert(group < BFIN_TIMER_NUM_GROUP); - return group_regs[group]->status; + return bfin_read(&group_regs[group]->status); } EXPORT_SYMBOL(get_gptimer_status); void set_gptimer_status(unsigned int group, uint32_t value) { tassert(group < BFIN_TIMER_NUM_GROUP); - group_regs[group]->status = value; + bfin_write(&group_regs[group]->status, value); SSYNC(); } EXPORT_SYMBOL(set_gptimer_status); +static uint32_t read_gptimer_status(unsigned int timer_id) +{ + return bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status); +} + int get_gptimer_intr(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]); + return !!(read_gptimer_status(timer_id) & timil_mask[timer_id]); } EXPORT_SYMBOL(get_gptimer_intr); void clear_gptimer_intr(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id]; + bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status, timil_mask[timer_id]); } EXPORT_SYMBOL(clear_gptimer_intr); int get_gptimer_over(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]); + return !!(read_gptimer_status(timer_id) & tovf_mask[timer_id]); } EXPORT_SYMBOL(get_gptimer_over); void clear_gptimer_over(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id]; + bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status, tovf_mask[timer_id]); } EXPORT_SYMBOL(clear_gptimer_over); int get_gptimer_run(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]); + return !!(read_gptimer_status(timer_id) & trun_mask[timer_id]); } EXPORT_SYMBOL(get_gptimer_run); void set_gptimer_config(unsigned int timer_id, uint16_t config) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - timer_regs[timer_id]->config = config; + bfin_write(&timer_regs[timer_id]->config, config); SSYNC(); } EXPORT_SYMBOL(set_gptimer_config); @@ -235,7 +224,7 @@ EXPORT_SYMBOL(set_gptimer_config); uint16_t get_gptimer_config(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return timer_regs[timer_id]->config; + return bfin_read(&timer_regs[timer_id]->config); } EXPORT_SYMBOL(get_gptimer_config); @@ -244,7 +233,7 @@ 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; + bfin_write(&group_regs[i]->enable, mask & 0xFF); mask >>= 8; } SSYNC(); @@ -257,7 +246,7 @@ static void _disable_gptimers(uint16_t mask) 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; + bfin_write(&group_regs[i]->disable, m & 0xFF); m >>= 8; } } @@ -268,7 +257,7 @@ void disable_gptimers(uint16_t mask) _disable_gptimers(mask); for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) if (mask & (1 << i)) - group_regs[BFIN_TIMER_OCTET(i)]->status = trun_mask[i]; + bfin_write(&group_regs[BFIN_TIMER_OCTET(i)]->status, trun_mask[i]); SSYNC(); } EXPORT_SYMBOL(disable_gptimers); @@ -283,7 +272,7 @@ EXPORT_SYMBOL(disable_gptimers_sync); void set_gptimer_pulse_hi(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - timer_regs[timer_id]->config |= TIMER_PULSE_HI; + bfin_write_or(&timer_regs[timer_id]->config, TIMER_PULSE_HI); SSYNC(); } EXPORT_SYMBOL(set_gptimer_pulse_hi); @@ -291,7 +280,7 @@ EXPORT_SYMBOL(set_gptimer_pulse_hi); void clear_gptimer_pulse_hi(unsigned int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - timer_regs[timer_id]->config &= ~TIMER_PULSE_HI; + bfin_write_and(&timer_regs[timer_id]->config, ~TIMER_PULSE_HI); SSYNC(); } EXPORT_SYMBOL(clear_gptimer_pulse_hi); @@ -301,7 +290,7 @@ 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)); + result |= (bfin_read(&group_regs[i]->enable) << (i << 3)); return result; } EXPORT_SYMBOL(get_enabled_gptimers); diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index 486426f8a0d..dbe11220cc5 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -32,7 +32,7 @@ #include <linux/unistd.h> #include <linux/io.h> #include <asm/system.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/irq_handler.h> DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs); diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index 35e350cad9d..4489efc5288 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c @@ -16,19 +16,6 @@ #include <asm/cacheflush.h> #include <asm/uaccess.h> -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - return vmalloc(size); -} - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); -} - /* Transfer the section to the L1 memory */ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, @@ -150,14 +137,6 @@ module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, return 0; } -int -apply_relocate(Elf_Shdr * sechdrs, const char *strtab, - unsigned int symindex, unsigned int relsec, struct module *mod) -{ - pr_err(".rel unsupported\n"); - return -ENOEXEC; -} - /*************************************************************************/ /* FUNCTION : apply_relocate_add */ /* ABSTRACT : Blackfin specific relocation handling for the loadable */ diff --git a/arch/blackfin/kernel/nmi.c b/arch/blackfin/kernel/nmi.c index 679d0db3525..9919d29287d 100644 --- a/arch/blackfin/kernel/nmi.c +++ b/arch/blackfin/kernel/nmi.c @@ -18,7 +18,7 @@ #include <linux/smp.h> #include <linux/timer.h> #include <asm/blackfin.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/cacheflush.h> #include <asm/bfin_watchdog.h> diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 6a660fa921b..6a80a9e9fc4 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -140,7 +140,6 @@ EXPORT_SYMBOL(kernel_thread); */ void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { - set_fs(USER_DS); regs->pc = new_ip; if (current->mm) regs->p5 = current->mm->start_data; diff --git a/arch/blackfin/kernel/pwm.c b/arch/blackfin/kernel/pwm.c new file mode 100644 index 00000000000..33f5942733b --- /dev/null +++ b/arch/blackfin/kernel/pwm.c @@ -0,0 +1,100 @@ +/* + * 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 488bdc51aaa..c4c0081b199 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -54,7 +54,9 @@ static void bfin_reset(void) /* The BF526 ROM will crash during reset */ #if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) - bfin_read_SWRST(); + /* Seems to be fixed with newer parts though ... */ + if (__SILICON_REVISION__ < 1 && bfin_revid() < 1) + bfin_read_SWRST(); #endif /* Wait for the SWRST write to complete. Cannot rely on SSYNC diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 536bd9d7e0c..dfa2525a442 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -54,8 +54,7 @@ EXPORT_SYMBOL(mtd_size); #endif char __initdata command_line[COMMAND_LINE_SIZE]; -void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat, - *init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr; +struct blackfin_initial_pda __initdata initial_pda; /* boot memmap, for parsing "memmap=" */ #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ @@ -957,13 +956,16 @@ void __init setup_arch(char **cmdline_p) printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); #ifdef CONFIG_DEBUG_DOUBLEFAULT /* We assume the crashing kernel, and the current symbol table match */ - printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n", - (int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx); - printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr); - printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr); + printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF\n", + initial_pda.seqstat_doublefault & SEQSTAT_EXCAUSE, + initial_pda.retx_doublefault); + printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", + initial_pda.dcplb_doublefault_addr); + printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", + initial_pda.icplb_doublefault_addr); #endif printk(KERN_NOTICE " The instruction at %pF caused a double exception\n", - init_retx); + initial_pda.retx); } else if (_bfin_swrst & RESET_WDOG) printk(KERN_INFO "Recovering from Watchdog event\n"); else if (_bfin_swrst & RESET_SOFTWARE) diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index 8d73724c009..ceb2bf63dfe 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -51,7 +51,7 @@ void __init setup_core_timer(void) u32 tcount; /* power up the timer, but don't enable it just yet */ - bfin_write_TCNTL(1); + bfin_write_TCNTL(TMPWR); CSYNC(); /* the TSCALE prescaler counter */ @@ -64,7 +64,7 @@ void __init setup_core_timer(void) /* now enable the timer */ CSYNC(); - bfin_write_TCNTL(7); + bfin_write_TCNTL(TAUTORLD | TMREN | TMPWR); } #endif diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 3ac5b66d14a..ba35864b2b7 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -155,6 +155,7 @@ SECTIONS SECURITY_INITCALL INIT_RAM_FS + . = ALIGN(PAGE_SIZE); ___per_cpu_load = .; PERCPU_INPUT(32) |