Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65af6667 authored by Linus Walleij's avatar Linus Walleij
Browse files

ARM: ixp4xx: Switch to use new timer driver



This augments the IXP4xx to select and use the new
timer driver in drivers/clocksource and removes the old
code in the machine.

Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 13e0b405
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -429,7 +429,6 @@ config ARCH_IXP4XX
	depends on MMU
	select ARCH_HAS_DMA_SET_COHERENT_MASK
	select ARCH_SUPPORTS_BIG_ENDIAN
	select CLKSRC_MMIO
	select CPU_XSCALE
	select DMABOUNCE if PCI
	select GENERIC_CLOCKEVENTS
@@ -438,6 +437,7 @@ config ARCH_IXP4XX
	select GPIOLIB
	select HAVE_PCI
	select IXP4XX_IRQ
	select IXP4XX_TIMER
	select NEED_MACH_IO_H
	select USB_EHCI_BIG_ENDIAN_DESC
	select USB_EHCI_BIG_ENDIAN_MMIO
+4 −149
Original line number Diff line number Diff line
@@ -22,9 +22,6 @@
#include <linux/serial_core.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/time.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/io.h>
#include <linux/export.h>
#include <linux/cpu.h>
@@ -32,6 +29,7 @@
#include <linux/sched_clock.h>
#include <linux/bitops.h>
#include <linux/irqchip/irq-ixp4xx.h>
#include <linux/platform_data/timer-ixp4xx.h>
#include <mach/udc.h>
#include <mach/hardware.h>
#include <mach/io.h>
@@ -49,19 +47,6 @@

#define IXP4XX_TIMER_FREQ 66666000

/*
 * The timer register doesn't allow to specify the two least significant bits of
 * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is
 * the best value with the two least significant bits unset.
 */
#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \
				       (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
			(IXP4XX_OST_RELOAD_MASK + 1)

static void __init ixp4xx_clocksource_init(void);
static void __init ixp4xx_clockevent_init(void);
static struct clock_event_device clockevent_ixp4xx;

/*************************************************************************
 * IXP4xx chipset I/O mapping
 *************************************************************************/
@@ -106,37 +91,11 @@ void __init ixp4xx_init_irq(void)
			(cpu_is_ixp46x() || cpu_is_ixp43x()));
}

/*************************************************************************
 * IXP4xx timer tick
 * We use OS timer1 on the CPU for the timer tick and the timestamp 
 * counter as a source of real clock ticks to account for missed jiffies.
 *************************************************************************/

static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *evt = dev_id;

	/* Clear Pending Interrupt by writing '1' to it */
	*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;

	evt->event_handler(evt);

	return IRQ_HANDLED;
}

void __init ixp4xx_timer_init(void)
{
	/* Reset/disable counter */
	*IXP4XX_OSRT1 = 0;

	/* Clear Pending Interrupt by writing '1' to it */
	*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;

	/* Reset time-stamp counter */
	*IXP4XX_OSTS = 0;

	ixp4xx_clocksource_init();
	ixp4xx_clockevent_init();
	return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS,
				  IRQ_IXP4XX_TIMER1,
				  IXP4XX_TIMER_FREQ);
}

static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
@@ -251,112 +210,8 @@ void __init ixp4xx_sys_init(void)
			ixp4xx_exp_bus_size >> 20);
}

/*
 * sched_clock()
 */
static u64 notrace ixp4xx_read_sched_clock(void)
{
	return *IXP4XX_OSTS;
}

/*
 * clocksource
 */

static u64 ixp4xx_clocksource_read(struct clocksource *c)
{
	return *IXP4XX_OSTS;
}

unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
EXPORT_SYMBOL(ixp4xx_timer_freq);
static void __init ixp4xx_clocksource_init(void)
{
	sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);

	clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32,
			ixp4xx_clocksource_read);
}

/*
 * clockevents
 */
static int ixp4xx_set_next_event(unsigned long evt,
				 struct clock_event_device *unused)
{
	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;

	*IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;

	return 0;
}

static int ixp4xx_shutdown(struct clock_event_device *evt)
{
	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
	unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;

	opts &= ~IXP4XX_OST_ENABLE;
	*IXP4XX_OSRT1 = osrt | opts;
	return 0;
}

static int ixp4xx_set_oneshot(struct clock_event_device *evt)
{
	unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
	unsigned long osrt = 0;

	/* period set by 'set next_event' */
	*IXP4XX_OSRT1 = osrt | opts;
	return 0;
}

static int ixp4xx_set_periodic(struct clock_event_device *evt)
{
	unsigned long opts = IXP4XX_OST_ENABLE;
	unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK;

	*IXP4XX_OSRT1 = osrt | opts;
	return 0;
}

static int ixp4xx_resume(struct clock_event_device *evt)
{
	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
	unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;

	opts |= IXP4XX_OST_ENABLE;
	*IXP4XX_OSRT1 = osrt | opts;
	return 0;
}

static struct clock_event_device clockevent_ixp4xx = {
	.name			= "ixp4xx timer1",
	.features		= CLOCK_EVT_FEAT_PERIODIC |
				  CLOCK_EVT_FEAT_ONESHOT,
	.rating			= 200,
	.set_state_shutdown	= ixp4xx_shutdown,
	.set_state_periodic	= ixp4xx_set_periodic,
	.set_state_oneshot	= ixp4xx_set_oneshot,
	.tick_resume		= ixp4xx_resume,
	.set_next_event		= ixp4xx_set_next_event,
};

static void __init ixp4xx_clockevent_init(void)
{
	int ret;

	clockevent_ixp4xx.cpumask = cpumask_of(0);
	clockevent_ixp4xx.irq = IRQ_IXP4XX_TIMER1;
	ret = request_irq(IRQ_IXP4XX_TIMER1, ixp4xx_timer_interrupt,
			  IRQF_TIMER, "IXP4XX-TIMER1", &clockevent_ixp4xx);
	if (ret) {
		pr_crit("no timer IRQ\n");
		return;
	}
	clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ,
					0xf, 0xfffffffe);
}

void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
{