diff options
-rw-r--r-- | arch/arm/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/configs/netx_defconfig | 6 | ||||
-rw-r--r-- | arch/arm/configs/picotux200_defconfig | 6 | ||||
-rw-r--r-- | arch/arm/kernel/ftrace.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91rm9200_time.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-netx/include/mach/netx-regs.h | 22 | ||||
-rw-r--r-- | arch/arm/mach-netx/time.c | 98 | ||||
-rw-r--r-- | arch/arm/mach-netx/xc.c | 6 |
8 files changed, 127 insertions, 25 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f1a3b10..4f87020 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -156,7 +156,6 @@ config ARCH_MTD_XIP bool config GENERIC_HARDIRQS_NO__DO_IRQ - bool def_bool y if OPROFILE @@ -288,6 +287,8 @@ config ARCH_NETX bool "Hilscher NetX based" select CPU_ARM926T select ARM_VIC + select GENERIC_CLOCKEVENTS + select GENERIC_TIME help This enables support for systems based on the Hilscher NetX Soc diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig index 0884f23..61d0fc5 100644 --- a/arch/arm/configs/netx_defconfig +++ b/arch/arm/configs/netx_defconfig @@ -728,9 +728,9 @@ CONFIG_RTC_CLASS=m # # RTC interfaces # -CONFIG_RTC_INTF_SYSFS=m -CONFIG_RTC_INTF_PROC=m -CONFIG_RTC_INTF_DEV=m +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y # # RTC drivers diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig index 14826f0..59e4463 100644 --- a/arch/arm/configs/picotux200_defconfig +++ b/arch/arm/configs/picotux200_defconfig @@ -1069,9 +1069,9 @@ CONFIG_RTC_CLASS=m # # RTC interfaces # -CONFIG_RTC_INTF_SYSFS=m -CONFIG_RTC_INTF_PROC=m -CONFIG_RTC_INTF_DEV=m +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index 6c90479..c638427 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -95,7 +95,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ret; } -/* run from kstop_machine */ +/* run from ftrace_init with irqs disabled */ int __init ftrace_dyn_arch_init(void *data) { ftrace_mcount_set(data); diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index a72e798..d140eae 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -141,6 +141,15 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) /* Use "raw" primitives so we behave correctly on RT kernels. */ raw_local_irq_save(flags); + /* + * According to Thomas Gleixner irqs are already disabled here. Simply + * removing raw_local_irq_save above (and the matching + * raw_local_irq_restore) was not accepted. See + * http://thread.gmane.org/gmane.linux.ports.arm.kernel/41174 + * So for now (2008-11-20) just warn once if irqs were not disabled ... + */ + WARN_ON_ONCE(!raw_irqs_disabled_flags(flags)); + /* The alarm IRQ uses absolute time (now+delta), not the relative * time (delta) in our calling convention. Like all clockevents * using such "match" hardware, we have a race to defend against. diff --git a/arch/arm/mach-netx/include/mach/netx-regs.h b/arch/arm/mach-netx/include/mach/netx-regs.h index 5104a00..08c60ff 100644 --- a/arch/arm/mach-netx/include/mach/netx-regs.h +++ b/arch/arm/mach-netx/include/mach/netx-regs.h @@ -328,6 +328,28 @@ #define NETX_PFIFO_FILL_LEVEL(pfifo) NETX_PFIFO_REG(0x180 + ((pfifo)<<2)) #define NETX_PFIFO_XPEC_ISR(xpec) NETX_PFIFO_REG(0x400 + ((xpec) << 2)) + +/******************************* + * Memory Controller * + *******************************/ + +/* Registers */ +#define NETX_MEMCR_REG(ofs) __io(NETX_VA_MEMCR + (ofs)) +#define NETX_MEMCR_SRAM_CTRL(cs) NETX_MEMCR_REG(0x0 + 4 * (cs)) /* SRAM for CS 0..2 */ +#define NETX_MEMCR_SDRAM_CFG_CTRL NETX_MEMCR_REG(0x40) +#define NETX_MEMCR_SDRAM_TIMING_CTRL NETX_MEMCR_REG(0x44) +#define NETX_MEMCR_SDRAM_MODE NETX_MEMCR_REG(0x48) +#define NETX_MEMCR_SDRAM_EXT_MODE NETX_MEMCR_REG(0x4c) +#define NETX_MEMCR_PRIO_TIMESLOT_CTRL NETX_MEMCR_REG(0x80) +#define NETX_MEMCR_PRIO_ACCESS_CTRL NETX_MEMCR_REG(0x84) + +/* Bits */ +#define NETX_MEMCR_SRAM_CTRL_WIDTHEXTMEM(x) (((x) & 0x3) << 24) +#define NETX_MEMCR_SRAM_CTRL_WSPOSTPAUSEEXTMEM(x) (((x) & 0x3) << 16) +#define NETX_MEMCR_SRAM_CTRL_WSPREPASEEXTMEM(x) (((x) & 0x3) << 8) +#define NETX_MEMCR_SRAM_CTRL_WSEXTMEM(x) (((x) & 0x1f) << 0) + + /******************************* * Dual Port Memory * *******************************/ diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 7c540c1..d51d627 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -21,43 +21,100 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/clocksource.h> +#include <linux/clockchips.h> #include <linux/io.h> #include <mach/hardware.h> #include <asm/mach/time.h> #include <mach/netx-regs.h> +#define TIMER_CLOCKEVENT 0 +#define TIMER_CLOCKSOURCE 1 + +static void netx_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + u32 tmode; + + /* disable timer */ + writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + writel(LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); + tmode = NETX_GPIO_COUNTER_CTRL_RST_EN | + NETX_GPIO_COUNTER_CTRL_IRQ_EN | + NETX_GPIO_COUNTER_CTRL_RUN; + break; + + case CLOCK_EVT_MODE_ONESHOT: + writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); + tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | + NETX_GPIO_COUNTER_CTRL_RUN; + break; + + default: + WARN(1, "%s: unhandled mode %d\n", __func__, mode); + /* fall through */ + + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + tmode = 0; + break; + } + + writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); +} + +static int netx_set_next_event(unsigned long evt, + struct clock_event_device *clk) +{ + writel(0 - evt, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKEVENT)); + return 0; +} + +static struct clock_event_device netx_clockevent = { + .name = "netx-timer" __stringify(TIMER_CLOCKEVENT), + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = netx_set_next_event, + .set_mode = netx_set_mode, +}; + /* * IRQ handler for the timer */ static irqreturn_t netx_timer_interrupt(int irq, void *dev_id) { - timer_tick(); + struct clock_event_device *evt = &netx_clockevent; /* acknowledge interrupt */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + evt->event_handler(evt); + return IRQ_HANDLED; } static struct irqaction netx_timer_irq = { - .name = "NetX Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = netx_timer_interrupt, + .name = "NetX Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = netx_timer_interrupt, }; cycle_t netx_get_cycles(void) { - return readl(NETX_GPIO_COUNTER_CURRENT(1)); + return readl(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE)); } static struct clocksource clocksource_netx = { - .name = "netx_timer", + .name = "netx_timer", .rating = 200, .read = netx_get_cycles, .mask = CLOCKSOURCE_MASK(32), - .shift = 20, + .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -77,24 +134,37 @@ static void __init netx_timer_init(void) /* acknowledge interrupt */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ); - /* Enable the interrupt in the specific timer register and start timer */ + /* Enable the interrupt in the specific timer + * register and start timer + */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE); writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN, - NETX_GPIO_COUNTER_CTRL(0)); + NETX_GPIO_COUNTER_CTRL(0)); setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq); /* Setup timer one for clocksource */ - writel(0, NETX_GPIO_COUNTER_CTRL(1)); - writel(0, NETX_GPIO_COUNTER_CURRENT(1)); - writel(0xFFFFFFFF, NETX_GPIO_COUNTER_MAX(1)); + writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); + writel(0, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE)); + writel(0xffffffff, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKSOURCE)); - writel(NETX_GPIO_COUNTER_CTRL_RUN, - NETX_GPIO_COUNTER_CTRL(1)); + writel(NETX_GPIO_COUNTER_CTRL_RUN, + NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); clocksource_netx.mult = clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift); clocksource_register(&clocksource_netx); + + netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, + netx_clockevent.shift); + netx_clockevent.max_delta_ns = + clockevent_delta2ns(0xfffffffe, &netx_clockevent); + /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine. + * Adding some safety ... */ + netx_clockevent.min_delta_ns = + clockevent_delta2ns(0xa00, &netx_clockevent); + netx_clockevent.cpumask = cpumask_of_cpu(0); + clockevents_register_device(&netx_clockevent); } struct sys_timer netx_timer = { diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c index 32eabf5..8fc6205 100644 --- a/arch/arm/mach-netx/xc.c +++ b/arch/arm/mach-netx/xc.c @@ -92,10 +92,10 @@ static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size) return -1; } -static int xc_patch(struct xc *x, void *patch, int count) +static int xc_patch(struct xc *x, const void *patch, int count) { unsigned int val, adr; - unsigned int *data = patch; + const unsigned int *data = patch; int i; for (i = 0; i < count; i++) { @@ -117,7 +117,7 @@ int xc_request_firmware(struct xc *x) struct fw_header *head; unsigned int size; int i; - void *src; + const void *src; unsigned long dst; sprintf(name, "xc%d.bin", x->no); |