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: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
13e0b4059b
commit
65af666713
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue