summaryrefslogtreecommitdiff
path: root/arch/arm/mach-msm
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-01-12 04:11:43 (GMT)
committerPaul Mundt <lethal@linux-sh.org>2012-01-12 04:11:43 (GMT)
commitb1bdd255661369cb6eb90b6e181169b5e6d0f9b6 (patch)
tree17d15f3a6dc5bdd6205070dbef0e339421b13d25 /arch/arm/mach-msm
parent9d14070f656addddce3d63fd483de46930b51850 (diff)
parentc1537b4863da620f12f5b42ece61bf65314148ed (diff)
downloadlinux-fsl-qoriq-b1bdd255661369cb6eb90b6e181169b5e6d0f9b6.tar.xz
Merge branch 'sh/nommu' into sh-latest
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r--arch/arm/mach-msm/Kconfig35
-rw-r--r--arch/arm/mach-msm/include/mach/debug-macro.S51
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-7x00.h12
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-7x30.h12
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-8960.h5
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-8x50.h12
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-8x60.h5
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap.h12
-rw-r--r--arch/arm/mach-msm/include/mach/uncompress.h39
-rw-r--r--arch/arm/mach-msm/io.c15
-rw-r--r--arch/arm/mach-msm/platsmp.c2
-rw-r--r--arch/arm/mach-msm/timer.c347
12 files changed, 225 insertions, 322 deletions
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index e6beaff..1cd40ad 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -13,7 +13,6 @@ config ARCH_MSM7X00A
select CPU_V6
select GPIO_MSM_V1
select MSM_PROC_COMM
- select HAS_MSM_DEBUG_UART_PHYS
config ARCH_MSM7X30
bool "MSM7x30"
@@ -25,7 +24,6 @@ config ARCH_MSM7X30
select MSM_GPIOMUX
select GPIO_MSM_V1
select MSM_PROC_COMM
- select HAS_MSM_DEBUG_UART_PHYS
config ARCH_QSD8X50
bool "QSD8X50"
@@ -37,7 +35,6 @@ config ARCH_QSD8X50
select MSM_GPIOMUX
select GPIO_MSM_V1
select MSM_PROC_COMM
- select HAS_MSM_DEBUG_UART_PHYS
config ARCH_MSM8X60
bool "MSM8X60"
@@ -63,6 +60,9 @@ config ARCH_MSM8960
endchoice
+config MSM_HAS_DEBUG_UART_HS
+ bool
+
config MSM_SOC_REV_A
bool
config ARCH_MSM_SCORPIONMP
@@ -74,9 +74,6 @@ config ARCH_MSM_ARM11
config ARCH_MSM_SCORPION
bool
-config HAS_MSM_DEBUG_UART_PHYS
- bool
-
config MSM_VIC
bool
@@ -153,32 +150,6 @@ config MACH_MSM8960_RUMI3
endmenu
-config MSM_DEBUG_UART
- int
- default 1 if MSM_DEBUG_UART1
- default 2 if MSM_DEBUG_UART2
- default 3 if MSM_DEBUG_UART3
-
-if HAS_MSM_DEBUG_UART_PHYS
-choice
- prompt "Debug UART"
-
- default MSM_DEBUG_UART_NONE
-
- config MSM_DEBUG_UART_NONE
- bool "None"
-
- config MSM_DEBUG_UART1
- bool "UART1"
-
- config MSM_DEBUG_UART2
- bool "UART2"
-
- config MSM_DEBUG_UART3
- bool "UART3"
-endchoice
-endif
-
config MSM_SMD_PKG3
bool
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 2dc73cc..3ffd866 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -1,6 +1,7 @@
-/* arch/arm/mach-msm7200/include/mach/debug-macro.S
+/*
*
* Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -14,40 +15,52 @@
*
*/
-
-
#include <mach/hardware.h>
#include <mach/msm_iomap.h>
-#if defined(CONFIG_HAS_MSM_DEBUG_UART_PHYS) && !defined(CONFIG_MSM_DEBUG_UART_NONE)
.macro addruart, rp, rv, tmp
+#ifdef MSM_DEBUG_UART_PHYS
ldr \rp, =MSM_DEBUG_UART_PHYS
ldr \rv, =MSM_DEBUG_UART_BASE
+#endif
.endm
- .macro senduart,rd,rx
+ .macro senduart, rd, rx
+#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
+ @ Write the 1 character to UARTDM_TF
+ str \rd, [\rx, #0x70]
+#else
teq \rx, #0
strne \rd, [\rx, #0x0C]
+#endif
.endm
- .macro waituart,rd,rx
+ .macro waituart, rd, rx
+#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
+ @ check for TX_EMT in UARTDM_SR
+ ldr \rd, [\rx, #0x08]
+ tst \rd, #0x08
+ bne 1002f
+ @ wait for TXREADY in UARTDM_ISR
+1001: ldr \rd, [\rx, #0x14]
+ tst \rd, #0x80
+ beq 1001b
+1002:
+ @ Clear TX_READY by writing to the UARTDM_CR register
+ mov \rd, #0x300
+ str \rd, [\rx, #0x10]
+ @ Write 0x1 to NCF register
+ mov \rd, #0x1
+ str \rd, [\rx, #0x40]
+ @ UARTDM reg. Read to induce delay
+ ldr \rd, [\rx, #0x08]
+#else
@ wait for TX_READY
1001: ldr \rd, [\rx, #0x08]
tst \rd, #0x04
beq 1001b
- .endm
-#else
- .macro addruart, rp, rv, tmp
- mov \rv, #0xff000000
- orr \rv, \rv, #0x00f00000
- .endm
-
- .macro senduart,rd,rx
- .endm
-
- .macro waituart,rd,rx
- .endm
#endif
+ .endm
- .macro busyuart,rd,rx
+ .macro busyuart, rd, rx
.endm
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
index 94fe9fe..8af4612 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
@@ -78,18 +78,6 @@
#define MSM_UART3_PHYS 0xA9C00000
#define MSM_UART3_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xE1000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#define MSM_SDC1_PHYS 0xA0400000
#define MSM_SDC1_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index 3769444..198202c 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -89,18 +89,6 @@
#define MSM_UART3_PHYS 0xACC00000
#define MSM_UART3_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xE1000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#define MSM_MDC_BASE IOMEM(0xE0200000)
#define MSM_MDC_PHYS 0xAA500000
#define MSM_MDC_SIZE SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
index 3c9d960..800b557 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
@@ -45,4 +45,9 @@
#define MSM8960_TMR0_PHYS 0x0208A000
#define MSM8960_TMR0_SIZE SZ_4K
+#ifdef CONFIG_DEBUG_MSM8960_UART
+#define MSM_DEBUG_UART_BASE 0xE1040000
+#define MSM_DEBUG_UART_PHYS 0x16440000
+#endif
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
index d67cd73..0faa894 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
@@ -83,18 +83,6 @@
#define MSM_UART3_PHYS 0xA9C00000
#define MSM_UART3_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xE1000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#define MSM_MDC_BASE IOMEM(0xE0200000)
#define MSM_MDC_PHYS 0xAA500000
#define MSM_MDC_SIZE SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index 3b19b8f..54e12ca 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -62,4 +62,9 @@
#define MSM8X60_TMR0_PHYS 0x02040000
#define MSM8X60_TMR0_SIZE SZ_4K
+#ifdef CONFIG_DEBUG_MSM8660_UART
+#define MSM_DEBUG_UART_BASE 0xE1040000
+#define MSM_DEBUG_UART_PHYS 0x19C40000
+#endif
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 4ded152..90682f4 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -55,6 +55,18 @@
#include "msm_iomap-8960.h"
+#define MSM_DEBUG_UART_SIZE SZ_4K
+#if defined(CONFIG_DEBUG_MSM_UART1)
+#define MSM_DEBUG_UART_BASE 0xE1000000
+#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART2)
+#define MSM_DEBUG_UART_BASE 0xE1000000
+#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART3)
+#define MSM_DEBUG_UART_BASE 0xE1000000
+#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
+#endif
+
/* Virtual addresses shared across all MSM targets. */
#define MSM_CSR_BASE IOMEM(0xE0001000)
#define MSM_QGIC_DIST_BASE IOMEM(0xF0000000)
diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h
index d94292c..169a840 100644
--- a/arch/arm/mach-msm/include/mach/uncompress.h
+++ b/arch/arm/mach-msm/include/mach/uncompress.h
@@ -1,6 +1,6 @@
-/* arch/arm/mach-msm/include/mach/uncompress.h
- *
+/*
* Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -14,17 +14,40 @@
*/
#ifndef __ASM_ARCH_MSM_UNCOMPRESS_H
+#define __ASM_ARCH_MSM_UNCOMPRESS_H
+
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+
+#define UART_CSR (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x08))
+#define UART_TF (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x0c))
-#include "hardware.h"
-#include "linux/io.h"
-#include "mach/msm_iomap.h"
+#define UART_DM_SR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x08)))
+#define UART_DM_CR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x10)))
+#define UART_DM_ISR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x14)))
+#define UART_DM_NCHAR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x40)))
+#define UART_DM_TF (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x70)))
static void putc(int c)
{
#if defined(MSM_DEBUG_UART_PHYS)
- unsigned base = MSM_DEBUG_UART_PHYS;
- while (!(readl(base + 0x08) & 0x04)) ;
- writel(c, base + 0x0c);
+#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
+ /*
+ * Wait for TX_READY to be set; but skip it if we have a
+ * TX underrun.
+ */
+ if (UART_DM_SR & 0x08)
+ while (!(UART_DM_ISR & 0x80))
+ cpu_relax();
+
+ UART_DM_CR = 0x300;
+ UART_DM_NCHAR = 0x1;
+ UART_DM_TF = c;
+#else
+ while (!(UART_CSR & 0x04))
+ cpu_relax();
+ UART_TF = c;
+#endif
#endif
}
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 8759ecf..578b04e 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -47,7 +47,8 @@ static struct map_desc msm_io_desc[] __initdata = {
MSM_CHIP_DEVICE(GPIO1, MSM7X00),
MSM_CHIP_DEVICE(GPIO2, MSM7X00),
MSM_DEVICE(CLK_CTL),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+ defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
#endif
#ifdef CONFIG_ARCH_MSM7X30
@@ -84,7 +85,8 @@ static struct map_desc qsd8x50_io_desc[] __initdata = {
MSM_DEVICE(SCPLL),
MSM_DEVICE(AD5),
MSM_DEVICE(MDC),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+ defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
#endif
{
@@ -109,6 +111,9 @@ static struct map_desc msm8x60_io_desc[] __initdata = {
MSM_CHIP_DEVICE(TMR0, MSM8X60),
MSM_DEVICE(ACC),
MSM_DEVICE(GCC),
+#ifdef CONFIG_DEBUG_MSM8660_UART
+ MSM_DEVICE(DEBUG_UART),
+#endif
};
void __init msm_map_msm8x60_io(void)
@@ -123,6 +128,9 @@ static struct map_desc msm8960_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_CPU, MSM8960),
MSM_CHIP_DEVICE(TMR, MSM8960),
MSM_CHIP_DEVICE(TMR0, MSM8960),
+#ifdef CONFIG_DEBUG_MSM8960_UART
+ MSM_DEVICE(DEBUG_UART),
+#endif
};
void __init msm_map_msm8960_io(void)
@@ -146,7 +154,8 @@ static struct map_desc msm7x30_io_desc[] __initdata = {
MSM_DEVICE(SAW),
MSM_DEVICE(GCC),
MSM_DEVICE(TCSR),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+ defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
#endif
{
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index fdec58a..0b3e357 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -79,7 +79,7 @@ static __cpuinit void prepare_cold_cpu(unsigned int cpu)
ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup),
SCM_FLAG_COLDBOOT_CPU1);
if (ret == 0) {
- void *sc1_base_ptr;
+ void __iomem *sc1_base_ptr;
sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
if (sc1_base_ptr) {
writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index afeeca5..11d0d8f 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -1,6 +1,7 @@
-/* linux/arch/arm/mach-msm/timer.c
+/*
*
* Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -13,306 +14,207 @@
*
*/
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <linux/init.h>
-#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/delay.h>
#include <linux/io.h>
#include <asm/mach/time.h>
#include <asm/hardware/gic.h>
+#include <asm/localtimer.h>
#include <mach/msm_iomap.h>
#include <mach/cpu.h>
+#include <mach/board.h>
#define TIMER_MATCH_VAL 0x0000
#define TIMER_COUNT_VAL 0x0004
#define TIMER_ENABLE 0x0008
-#define TIMER_ENABLE_CLR_ON_MATCH_EN 2
-#define TIMER_ENABLE_EN 1
+#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1)
+#define TIMER_ENABLE_EN BIT(0)
#define TIMER_CLEAR 0x000C
#define DGT_CLK_CTL 0x0034
-enum {
- DGT_CLK_CTL_DIV_1 = 0,
- DGT_CLK_CTL_DIV_2 = 1,
- DGT_CLK_CTL_DIV_3 = 2,
- DGT_CLK_CTL_DIV_4 = 3,
-};
-#define CSR_PROTECTION 0x0020
-#define CSR_PROTECTION_EN 1
+#define DGT_CLK_CTL_DIV_4 0x3
#define GPT_HZ 32768
-enum timer_location {
- LOCAL_TIMER = 0,
- GLOBAL_TIMER = 1,
-};
-
-#define MSM_GLOBAL_TIMER MSM_CLOCK_DGT
-
-/* TODO: Remove these ifdefs */
-#if defined(CONFIG_ARCH_QSD8X50)
-#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
-#define MSM_DGT_SHIFT (0)
-#elif defined(CONFIG_ARCH_MSM7X30)
-#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
-#define MSM_DGT_SHIFT (0)
-#elif defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960)
-#define DGT_HZ (27000000 / 4) /* 27 MHz (PXO) / 4 by default */
-#define MSM_DGT_SHIFT (0)
-#else
-#define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
-#define MSM_DGT_SHIFT (5)
-#endif
+#define MSM_DGT_SHIFT 5
-struct msm_clock {
- struct clock_event_device clockevent;
- struct clocksource clocksource;
- unsigned int irq;
- void __iomem *regbase;
- uint32_t freq;
- uint32_t shift;
- void __iomem *global_counter;
- void __iomem *local_counter;
- union {
- struct clock_event_device *evt;
- struct clock_event_device __percpu **percpu_evt;
- };
-};
-
-enum {
- MSM_CLOCK_GPT,
- MSM_CLOCK_DGT,
- NR_TIMERS,
-};
-
-
-static struct msm_clock msm_clocks[];
+static void __iomem *event_base;
static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
- if (evt->event_handler == NULL)
- return IRQ_HANDLED;
+ /* Stop the timer tick */
+ if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
+ u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
+ ctrl &= ~TIMER_ENABLE_EN;
+ writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+ }
evt->event_handler(evt);
return IRQ_HANDLED;
}
-static cycle_t msm_read_timer_count(struct clocksource *cs)
-{
- struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource);
-
- /*
- * Shift timer count down by a constant due to unreliable lower bits
- * on some targets.
- */
- return readl(clk->global_counter) >> clk->shift;
-}
-
-static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt)
-{
-#ifdef CONFIG_SMP
- int i;
- for (i = 0; i < NR_TIMERS; i++)
- if (evt == &(msm_clocks[i].clockevent))
- return &msm_clocks[i];
- return &msm_clocks[MSM_GLOBAL_TIMER];
-#else
- return container_of(evt, struct msm_clock, clockevent);
-#endif
-}
-
static int msm_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- struct msm_clock *clock = clockevent_to_clock(evt);
- uint32_t now = readl(clock->local_counter);
- uint32_t alarm = now + (cycles << clock->shift);
+ u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
- writel(alarm, clock->regbase + TIMER_MATCH_VAL);
+ writel_relaxed(0, event_base + TIMER_CLEAR);
+ writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
+ writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
return 0;
}
static void msm_timer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- struct msm_clock *clock = clockevent_to_clock(evt);
+ u32 ctrl;
+
+ ctrl = readl_relaxed(event_base + TIMER_ENABLE);
+ ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
switch (mode) {
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_PERIODIC:
break;
case CLOCK_EVT_MODE_ONESHOT:
- writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
+ /* Timer is enabled in set_next_event */
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
- writel(0, clock->regbase + TIMER_ENABLE);
break;
}
+ writel_relaxed(ctrl, event_base + TIMER_ENABLE);
}
-static struct msm_clock msm_clocks[] = {
- [MSM_CLOCK_GPT] = {
- .clockevent = {
- .name = "gp_timer",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .shift = 32,
- .rating = 200,
- .set_next_event = msm_timer_set_next_event,
- .set_mode = msm_timer_set_mode,
- },
- .clocksource = {
- .name = "gp_timer",
- .rating = 200,
- .read = msm_read_timer_count,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- },
- .irq = INT_GP_TIMER_EXP,
- .freq = GPT_HZ,
- },
- [MSM_CLOCK_DGT] = {
- .clockevent = {
- .name = "dg_timer",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .shift = 32 + MSM_DGT_SHIFT,
- .rating = 300,
- .set_next_event = msm_timer_set_next_event,
- .set_mode = msm_timer_set_mode,
- },
- .clocksource = {
- .name = "dg_timer",
- .rating = 300,
- .read = msm_read_timer_count,
- .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- },
- .irq = INT_DEBUG_TIMER_EXP,
- .freq = DGT_HZ >> MSM_DGT_SHIFT,
- .shift = MSM_DGT_SHIFT,
- }
+static struct clock_event_device msm_clockevent = {
+ .name = "gp_timer",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 200,
+ .set_next_event = msm_timer_set_next_event,
+ .set_mode = msm_timer_set_mode,
+};
+
+static union {
+ struct clock_event_device *evt;
+ struct clock_event_device __percpu **percpu_evt;
+} msm_evt;
+
+static void __iomem *source_base;
+
+static cycle_t msm_read_timer_count(struct clocksource *cs)
+{
+ return readl_relaxed(source_base + TIMER_COUNT_VAL);
+}
+
+static cycle_t msm_read_timer_count_shift(struct clocksource *cs)
+{
+ /*
+ * Shift timer count down by a constant due to unreliable lower bits
+ * on some targets.
+ */
+ return msm_read_timer_count(cs) >> MSM_DGT_SHIFT;
+}
+
+static struct clocksource msm_clocksource = {
+ .name = "dg_timer",
+ .rating = 300,
+ .read = msm_read_timer_count,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static void __init msm_timer_init(void)
{
- int i;
+ struct clock_event_device *ce = &msm_clockevent;
+ struct clocksource *cs = &msm_clocksource;
int res;
- int global_offset = 0;
+ u32 dgt_hz;
if (cpu_is_msm7x01()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+ event_base = MSM_CSR_BASE;
+ source_base = MSM_CSR_BASE + 0x10;
+ dgt_hz = 19200000 >> MSM_DGT_SHIFT; /* 600 KHz */
+ cs->read = msm_read_timer_count_shift;
+ cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
} else if (cpu_is_msm7x30()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE + 0x04;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x24;
+ event_base = MSM_CSR_BASE + 0x04;
+ source_base = MSM_CSR_BASE + 0x24;
+ dgt_hz = 24576000 / 4;
} else if (cpu_is_qsd8x50()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+ event_base = MSM_CSR_BASE;
+ source_base = MSM_CSR_BASE + 0x10;
+ dgt_hz = 19200000 / 4;
} else if (cpu_is_msm8x60() || cpu_is_msm8960()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_TMR_BASE + 0x04;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_TMR_BASE + 0x24;
-
- /* Use CPU0's timer as the global timer. */
- global_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
+ event_base = MSM_TMR_BASE + 0x04;
+ /* Use CPU0's timer as the global clock source. */
+ source_base = MSM_TMR0_BASE + 0x24;
+ dgt_hz = 27000000 / 4;
+ writel_relaxed(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
} else
BUG();
-#ifdef CONFIG_ARCH_MSM_SCORPIONMP
- writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
-#endif
-
- for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
- struct msm_clock *clock = &msm_clocks[i];
- struct clock_event_device *ce = &clock->clockevent;
- struct clocksource *cs = &clock->clocksource;
-
- clock->local_counter = clock->regbase + TIMER_COUNT_VAL;
- clock->global_counter = clock->local_counter + global_offset;
-
- writel(0, clock->regbase + TIMER_ENABLE);
- writel(0, clock->regbase + TIMER_CLEAR);
- writel(~0, clock->regbase + TIMER_MATCH_VAL);
-
- ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift);
- /* allow at least 10 seconds to notice that the timer wrapped */
- ce->max_delta_ns =
- clockevent_delta2ns(0xf0000000 >> clock->shift, ce);
- /* 4 gets rounded down to 3 */
- ce->min_delta_ns = clockevent_delta2ns(4, ce);
- ce->cpumask = cpumask_of(0);
-
- res = clocksource_register_hz(cs, clock->freq);
- if (res)
- printk(KERN_ERR "msm_timer_init: clocksource_register "
- "failed for %s\n", cs->name);
-
- ce->irq = clock->irq;
- if (cpu_is_msm8x60() || cpu_is_msm8960()) {
- clock->percpu_evt = alloc_percpu(struct clock_event_device *);
- if (!clock->percpu_evt) {
- pr_err("msm_timer_init: memory allocation "
- "failed for %s\n", ce->name);
- continue;
- }
-
- *__this_cpu_ptr(clock->percpu_evt) = ce;
- res = request_percpu_irq(ce->irq, msm_timer_interrupt,
- ce->name, clock->percpu_evt);
- if (!res)
- enable_percpu_irq(ce->irq, 0);
- } else {
- clock->evt = ce;
- res = request_irq(ce->irq, msm_timer_interrupt,
- IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
- ce->name, &clock->evt);
+ writel_relaxed(0, event_base + TIMER_ENABLE);
+ writel_relaxed(0, event_base + TIMER_CLEAR);
+ writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
+ ce->cpumask = cpumask_of(0);
+
+ ce->irq = INT_GP_TIMER_EXP;
+ clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff);
+ if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+ msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *);
+ if (!msm_evt.percpu_evt) {
+ pr_err("memory allocation failed for %s\n", ce->name);
+ goto err;
}
-
- if (res)
- pr_err("msm_timer_init: request_irq failed for %s\n",
- ce->name);
-
- clockevents_register_device(ce);
+ *__this_cpu_ptr(msm_evt.percpu_evt) = ce;
+ res = request_percpu_irq(ce->irq, msm_timer_interrupt,
+ ce->name, msm_evt.percpu_evt);
+ if (!res)
+ enable_percpu_irq(ce->irq, 0);
+ } else {
+ msm_evt.evt = ce;
+ res = request_irq(ce->irq, msm_timer_interrupt,
+ IRQF_TIMER | IRQF_NOBALANCING |
+ IRQF_TRIGGER_RISING, ce->name, &msm_evt.evt);
}
+
+ if (res)
+ pr_err("request_irq failed for %s\n", ce->name);
+err:
+ writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE);
+ res = clocksource_register_hz(cs, dgt_hz);
+ if (res)
+ pr_err("clocksource_register failed\n");
}
-#ifdef CONFIG_SMP
+#ifdef CONFIG_LOCAL_TIMERS
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
- static bool local_timer_inited;
- struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
-
/* Use existing clock_event for cpu 0 */
if (!smp_processor_id())
return 0;
- writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
-
- if (!local_timer_inited) {
- writel(0, clock->regbase + TIMER_ENABLE);
- writel(0, clock->regbase + TIMER_CLEAR);
- writel(~0, clock->regbase + TIMER_MATCH_VAL);
- local_timer_inited = true;
- }
- evt->irq = clock->irq;
+ writel_relaxed(0, event_base + TIMER_ENABLE);
+ writel_relaxed(0, event_base + TIMER_CLEAR);
+ writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
+ evt->irq = msm_clockevent.irq;
evt->name = "local_timer";
- evt->features = CLOCK_EVT_FEAT_ONESHOT;
- evt->rating = clock->clockevent.rating;
+ evt->features = msm_clockevent.features;
+ evt->rating = msm_clockevent.rating;
evt->set_mode = msm_timer_set_mode;
evt->set_next_event = msm_timer_set_next_event;
- evt->shift = clock->clockevent.shift;
- evt->mult = div_sc(clock->freq, NSEC_PER_SEC, evt->shift);
- evt->max_delta_ns =
- clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
+ evt->shift = msm_clockevent.shift;
+ evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift);
+ evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt);
evt->min_delta_ns = clockevent_delta2ns(4, evt);
- *__this_cpu_ptr(clock->percpu_evt) = evt;
- enable_percpu_irq(evt->irq, 0);
-
+ *__this_cpu_ptr(msm_evt.percpu_evt) = evt;
clockevents_register_device(evt);
+ enable_percpu_irq(evt->irq, 0);
return 0;
}
@@ -321,8 +223,7 @@ void local_timer_stop(struct clock_event_device *evt)
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
disable_percpu_irq(evt->irq);
}
-
-#endif
+#endif /* CONFIG_LOCAL_TIMERS */
struct sys_timer msm_timer = {
.init = msm_timer_init