arm: move nomadik timer to drivers/clocksource
as this timer is shared with multiple arch Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
This commit is contained in:
parent
0228863348
commit
ebf6e1d052
|
@ -54,6 +54,7 @@ config ARCH_NETX
|
|||
config ARCH_NOMADIK
|
||||
bool "STMicroelectronics Nomadik"
|
||||
select CPU_ARM926T
|
||||
select CLOCKSOURCE_NOMADIK
|
||||
help
|
||||
Support for the Nomadik platform by ST-Ericsson
|
||||
|
||||
|
|
|
@ -29,6 +29,10 @@ static struct clk st8815_clk_48 = {
|
|||
.rate = 48 * 1000 * 1000,
|
||||
};
|
||||
|
||||
static struct clk st8815_clk_2_4 = {
|
||||
.rate = 2400000,
|
||||
};
|
||||
|
||||
static struct clk st8815_dummy;
|
||||
|
||||
void st8815_add_device_sdram(u32 size)
|
||||
|
@ -38,6 +42,7 @@ void st8815_add_device_sdram(u32 size)
|
|||
|
||||
static struct clk_lookup clocks_lookups[] = {
|
||||
CLKDEV_CON_ID("apb_pclk", &st8815_dummy),
|
||||
CLKDEV_CON_ID("nomadik_mtu", &st8815_clk_2_4),
|
||||
CLKDEV_DEV_ID("uart-pl0110", &st8815_clk_48),
|
||||
CLKDEV_DEV_ID("uart-pl0111", &st8815_clk_48),
|
||||
};
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
#ifndef __ASM_ARCH_MTU_H
|
||||
#define __ASM_ARCH_MTU_H
|
||||
|
||||
/*
|
||||
* The MTU device hosts four different counters, with 4 set of
|
||||
* registers. These are register names.
|
||||
*/
|
||||
|
||||
#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
|
||||
#define MTU_RIS 0x04 /* Raw interrupt status */
|
||||
#define MTU_MIS 0x08 /* Masked interrupt status */
|
||||
#define MTU_ICR 0x0C /* Interrupt clear register */
|
||||
|
||||
/* per-timer registers take 0..3 as argument */
|
||||
#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
|
||||
#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
|
||||
|
||||
#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
|
||||
#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
|
||||
|
||||
|
||||
/* bits for the control register */
|
||||
#define MTU_CRn_ENA 0x80
|
||||
#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
|
||||
#define MTU_CRn_PRESCALE_MASK 0x0c
|
||||
#define MTU_CRn_PRESCALE_1 0x00
|
||||
#define MTU_CRn_PRESCALE_16 0x04
|
||||
#define MTU_CRn_PRESCALE_256 0x08
|
||||
#define MTU_CRn_32BITS 0x02
|
||||
#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
|
||||
|
||||
/* Other registers are usual amba/primecell registers, currently not used */
|
||||
#define MTU_ITCR 0xff0
|
||||
#define MTU_ITOP 0xff4
|
||||
|
||||
#define MTU_PERIPH_ID0 0xfe0
|
||||
#define MTU_PERIPH_ID1 0xfe4
|
||||
#define MTU_PERIPH_ID2 0xfe8
|
||||
#define MTU_PERIPH_ID3 0xfeC
|
||||
|
||||
#define MTU_PCELL0 0xff0
|
||||
#define MTU_PCELL1 0xff4
|
||||
#define MTU_PCELL2 0xff8
|
||||
#define MTU_PCELL3 0xffC
|
||||
|
||||
#endif /* __ASM_ARCH_MTU_H */
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef __ASM_ARCH_TIMEX_H
|
||||
#define __ASM_ARCH_TIMEX_H
|
||||
|
||||
#define CLOCK_TICK_RATE 2400000
|
||||
|
||||
#endif
|
|
@ -10,55 +10,16 @@
|
|||
*/
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <clock.h>
|
||||
#include <io.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/mtu.h>
|
||||
#include <mach/timex.h>
|
||||
|
||||
/* Initial value for SRC control register: all timers use MXTAL/8 source */
|
||||
#define SRC_CR_INIT_MASK 0x00007fff
|
||||
#define SRC_CR_INIT_VAL 0x2aaa8000
|
||||
|
||||
static u32 nmdk_cycle; /* write-once */
|
||||
static __iomem void *mtu_base;
|
||||
|
||||
/*
|
||||
* clocksource: the MTU device is a decrementing counters, so we negate
|
||||
* the value being read.
|
||||
*/
|
||||
static uint64_t nmdk_read_timer(void)
|
||||
{
|
||||
return nmdk_cycle - readl(mtu_base + MTU_VAL(0));
|
||||
}
|
||||
|
||||
static struct clocksource nmdk_clksrc = {
|
||||
.read = nmdk_read_timer,
|
||||
.shift = 20,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
};
|
||||
|
||||
static void nmdk_timer_reset(void)
|
||||
{
|
||||
u32 cr;
|
||||
|
||||
writel(0, mtu_base + MTU_CR(0)); /* off */
|
||||
|
||||
/* configure load and background-load, and fire it up */
|
||||
writel(nmdk_cycle, mtu_base + MTU_LR(0));
|
||||
writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
|
||||
cr = MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS;
|
||||
writel(cr, mtu_base + MTU_CR(0));
|
||||
writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
|
||||
}
|
||||
|
||||
static int nmdk_timer_init(void)
|
||||
static int st8815_timer_init(void)
|
||||
{
|
||||
u32 src_cr;
|
||||
unsigned long rate;
|
||||
|
||||
rate = CLOCK_TICK_RATE; /* 2.4MHz */
|
||||
nmdk_cycle = (rate + 1000 / 2) / 1000;
|
||||
|
||||
/* Configure timer sources in "system reset controller" ctrl reg */
|
||||
src_cr = readl(NOMADIK_SRC_BASE);
|
||||
|
@ -66,16 +27,7 @@ static int nmdk_timer_init(void)
|
|||
src_cr |= SRC_CR_INIT_VAL;
|
||||
writel(src_cr, NOMADIK_SRC_BASE);
|
||||
|
||||
/* Save global pointer to mtu, used by functions above */
|
||||
mtu_base = (void *)NOMADIK_MTU0_BASE;
|
||||
|
||||
/* Init the timer and register clocksource */
|
||||
nmdk_timer_reset();
|
||||
|
||||
nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift);
|
||||
|
||||
init_clock(&nmdk_clksrc);
|
||||
|
||||
add_generic_device("nomadik_mtu", DEVICE_ID_SINGLE, NULL, NOMADIK_MTU0_BASE, 0x1000, IORESOURCE_MEM, NULL);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(nmdk_timer_init);
|
||||
coredevice_initcall(st8815_timer_init);
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
config ARM_SMP_TWD
|
||||
bool
|
||||
depends on ARM && CPU_V7
|
||||
|
||||
config CLOCKSOURCE_NOMADIK
|
||||
bool
|
||||
depends on ARM
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
|
||||
obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-nomadik/timer.c
|
||||
*
|
||||
* Copyright (C) 2008 STMicroelectronics
|
||||
* Copyright (C) 2009 Alessandro Rubini, somewhat based on at91sam926x
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <clock.h>
|
||||
#include <io.h>
|
||||
#include <init.h>
|
||||
#include <driver.h>
|
||||
#include <errno.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* The MTU device hosts four different counters, with 4 set of
|
||||
* registers. These are register names.
|
||||
*/
|
||||
|
||||
#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
|
||||
#define MTU_RIS 0x04 /* Raw interrupt status */
|
||||
#define MTU_MIS 0x08 /* Masked interrupt status */
|
||||
#define MTU_ICR 0x0C /* Interrupt clear register */
|
||||
|
||||
/* per-timer registers take 0..3 as argument */
|
||||
#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
|
||||
#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
|
||||
#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
|
||||
#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
|
||||
|
||||
/* bits for the control register */
|
||||
#define MTU_CRn_ENA 0x80
|
||||
#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
|
||||
#define MTU_CRn_PRESCALE_MASK 0x0c
|
||||
#define MTU_CRn_PRESCALE_1 0x00
|
||||
#define MTU_CRn_PRESCALE_16 0x04
|
||||
#define MTU_CRn_PRESCALE_256 0x08
|
||||
#define MTU_CRn_32BITS 0x02
|
||||
#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
|
||||
|
||||
/* Other registers are usual amba/primecell registers, currently not used */
|
||||
#define MTU_ITCR 0xff0
|
||||
#define MTU_ITOP 0xff4
|
||||
|
||||
#define MTU_PERIPH_ID0 0xfe0
|
||||
#define MTU_PERIPH_ID1 0xfe4
|
||||
#define MTU_PERIPH_ID2 0xfe8
|
||||
#define MTU_PERIPH_ID3 0xfeC
|
||||
|
||||
#define MTU_PCELL0 0xff0
|
||||
#define MTU_PCELL1 0xff4
|
||||
#define MTU_PCELL2 0xff8
|
||||
#define MTU_PCELL3 0xffC
|
||||
|
||||
static __iomem void *mtu_base;
|
||||
static u32 clk_prescale;
|
||||
static u32 nmdk_cycle; /* write-once */
|
||||
|
||||
/*
|
||||
* clocksource: the MTU device is a decrementing counters, so we negate
|
||||
* the value being read.
|
||||
*/
|
||||
static uint64_t nmdk_read_timer(void)
|
||||
{
|
||||
return nmdk_cycle - readl(mtu_base + MTU_VAL(0));
|
||||
}
|
||||
|
||||
static struct clocksource nmdk_clksrc = {
|
||||
.read = nmdk_read_timer,
|
||||
.shift = 20,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
};
|
||||
|
||||
static void nmdk_timer_reset(void)
|
||||
{
|
||||
u32 cr;
|
||||
|
||||
/* Disable */
|
||||
writel(0, mtu_base + MTU_CR(0)); /* off */
|
||||
|
||||
/* configure load and background-load, and fire it up */
|
||||
writel(nmdk_cycle, mtu_base + MTU_LR(0));
|
||||
writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
|
||||
|
||||
cr = clk_prescale | MTU_CRn_32BITS;
|
||||
writel(cr, mtu_base + MTU_CR(0));
|
||||
writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
|
||||
}
|
||||
|
||||
static int nmdk_mtu_probe(struct device_d *dev)
|
||||
{
|
||||
static struct clk *mtu_clk;
|
||||
u32 rate;
|
||||
int ret;
|
||||
|
||||
mtu_clk = clk_get(dev, NULL);
|
||||
if (IS_ERR(mtu_clk)) {
|
||||
ret = PTR_ERR(mtu_clk);
|
||||
dev_err(dev, "clock not found: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(mtu_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "clock failed to enable: %d\n", ret);
|
||||
clk_put(mtu_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rate = clk_get_rate(mtu_clk);
|
||||
if (rate > 32000000) {
|
||||
rate /= 16;
|
||||
clk_prescale = MTU_CRn_PRESCALE_16;
|
||||
} else {
|
||||
clk_prescale = MTU_CRn_PRESCALE_1;
|
||||
}
|
||||
|
||||
nmdk_cycle = (rate + 1000 / 2) / 1000;
|
||||
|
||||
/* Save global pointer to mtu, used by functions above */
|
||||
mtu_base = dev_request_mem_region(dev, 0);
|
||||
|
||||
/* Init the timer and register clocksource */
|
||||
nmdk_timer_reset();
|
||||
|
||||
nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift);
|
||||
|
||||
init_clock(&nmdk_clksrc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct driver_d nmdk_mtu_driver = {
|
||||
.name = "nomadik_mtu",
|
||||
.probe = nmdk_mtu_probe,
|
||||
};
|
||||
|
||||
static int nmdk_mtu_init(void)
|
||||
{
|
||||
return platform_driver_register(&nmdk_mtu_driver);
|
||||
}
|
||||
coredevice_initcall(nmdk_mtu_init);
|
Loading…
Reference in New Issue