diff options
Diffstat (limited to 'arch/arm/mach-imx/clocksource.c')
-rw-r--r-- | arch/arm/mach-imx/clocksource.c | 89 |
1 files changed, 80 insertions, 9 deletions
diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c index 4e77ece7f3..c725f8c23a 100644 --- a/arch/arm/mach-imx/clocksource.c +++ b/arch/arm/mach-imx/clocksource.c @@ -32,17 +32,45 @@ #include <common.h> #include <init.h> #include <clock.h> +#include <errno.h> #include <notifier.h> #include <mach/imx-regs.h> #include <mach/clock.h> #include <io.h> -#define GPT(x) __REG(IMX_TIM1_BASE + (x)) -#define timer_base IOMEM(IMX_TIM1_BASE) +/* Part 1: Registers */ +# define GPT_TCTL 0x00 +# define GPT_TPRER 0x04 + +/* Part 2: Bitfields */ +#define TCTL_SWR (1 << 15) /* Software reset */ +#define IMX1_TCTL_FRR (1 << 8) /* Freerun / restart */ +#define IMX31_TCTL_FRR (1 << 9) /* Freerun / restart */ +#define IMX1_TCTL_CLKSOURCE_IPG (1 << 1) /* Clock source bit position */ +#define IMX31_TCTL_CLKSOURCE_IPG (1 << 6) /* Clock source bit position */ +#define TCTL_TEN (1 << 0) /* Timer enable */ + +struct imx_gpt_regs { + unsigned int tcn; + uint32_t tctl_val; +}; + +static struct imx_gpt_regs regs_imx1 = { + .tcn = 0x10, + .tctl_val = IMX1_TCTL_FRR | IMX1_TCTL_CLKSOURCE_IPG | TCTL_TEN, +}; + +static struct imx_gpt_regs regs_imx31 = { + .tcn = 0x24, + .tctl_val = IMX31_TCTL_FRR | IMX31_TCTL_CLKSOURCE_IPG | TCTL_TEN, +}; + +static struct imx_gpt_regs *regs; +static void __iomem *timer_base; static uint64_t imx_clocksource_read(void) { - return readl(timer_base + GPT_TCN); + return readl(timer_base + regs->tcn); } static struct clocksource cs = { @@ -61,10 +89,20 @@ static struct notifier_block imx_clock_notifier = { .notifier_call = imx_clocksource_clock_change, }; -static int clocksource_init (void) +static int imx_gpt_probe(struct device_d *dev) { int i; - uint32_t val; + int ret; + + /* one timer is enough */ + if (timer_base) + return -EBUSY; + + ret = dev_get_drvdata(dev, (unsigned long *)®s); + if (ret) + return ret; + + timer_base = dev_request_mem_region(dev, 0); /* setup GP Timer 1 */ writel(TCTL_SWR, timer_base + GPT_TCTL); @@ -85,9 +123,7 @@ static int clocksource_init (void) writel(0, timer_base + GPT_TCTL); /* We have no udelay by now */ writel(0, timer_base + GPT_TPRER); - val = readl(timer_base + GPT_TCTL); - val |= TCTL_FRR | (1 << TCTL_CLKSOURCE) | TCTL_TEN; /* Freerun Mode, PERCLK1 input */ - writel(val, timer_base + GPT_TCTL); + writel(regs->tctl_val, timer_base + GPT_TCTL); cs.mult = clocksource_hz2mult(imx_get_gptclk(), cs.shift); @@ -98,7 +134,42 @@ static int clocksource_init (void) return 0; } -core_initcall(clocksource_init); +static __maybe_unused struct of_device_id imx_gpt_dt_ids[] = { + { + .compatible = "fsl,imx1-gpt", + .data = (unsigned long)®s_imx1, + }, { + .compatible = "fsl,imx31-gpt", + .data = (unsigned long)®s_imx31, + }, { + /* sentinel */ + } +}; + +static struct platform_device_id imx_gpt_ids[] = { + { + .name = "imx1-gpt", + .driver_data = (unsigned long)®s_imx1, + }, { + .name = "imx31-gpt", + .driver_data = (unsigned long)®s_imx31, + }, { + /* sentinel */ + }, +}; + +static struct driver_d imx_gpt_driver = { + .name = "imx-gpt", + .probe = imx_gpt_probe, + .of_compatible = DRV_OF_COMPAT(imx_gpt_dt_ids), + .id_table = imx_gpt_ids, +}; + +static int imx_gpt_init(void) +{ + return register_driver(&imx_gpt_driver); +} +coredevice_initcall(imx_gpt_init); /* * Watchdog Registers |