* [PATCH 03/11] m68k: set arch_gettimeoffset directly
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
remove m68k's mach_gettimeoffset function pointer, and instead directly
set the arch_gettimeoffset function pointer. This requires multiplying
all function results by 1000, since the removed m68k_gettimeoffset() did
this. Also, s/unsigned long/u32/ just to make the function prototypes
exactly match that of arch_gettimeoffset.
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Philip Blundell <philb@gnu.org>
Cc: Joshua Thompson <funaho@jurai.org>
Cc: Sam Creasey <sammy@sammy.net>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/m68k/amiga/config.c | 10 +++++-----
arch/m68k/apollo/config.c | 9 ++++-----
arch/m68k/atari/config.c | 4 ++--
arch/m68k/atari/time.c | 6 +++---
arch/m68k/bvme6000/config.c | 10 +++++-----
arch/m68k/hp300/config.c | 2 +-
arch/m68k/hp300/time.c | 4 ++--
arch/m68k/hp300/time.h | 2 +-
arch/m68k/include/asm/machdep.h | 2 +-
arch/m68k/kernel/setup_mm.c | 1 -
arch/m68k/kernel/time.c | 9 ---------
arch/m68k/mac/config.c | 4 ++--
arch/m68k/mac/via.c | 4 ++--
arch/m68k/mvme147/config.c | 8 ++++----
arch/m68k/mvme16x/config.c | 8 ++++----
arch/m68k/q40/config.c | 8 ++++----
arch/m68k/sun3/config.c | 4 ++--
arch/m68k/sun3/intersil.c | 4 ++--
arch/m68k/sun3x/config.c | 2 +-
arch/m68k/sun3x/time.c | 2 +-
arch/m68k/sun3x/time.h | 2 +-
21 files changed, 47 insertions(+), 58 deletions(-)
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index ee01b7a..b819390 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -95,7 +95,7 @@ static void amiga_sched_init(irq_handler_t handler);
static void amiga_get_model(char *model);
static void amiga_get_hardware_list(struct seq_file *m);
/* amiga specific timer functions */
-static unsigned long amiga_gettimeoffset(void);
+static u32 amiga_gettimeoffset(void);
extern void amiga_mksound(unsigned int count, unsigned int ticks);
static void amiga_reset(void);
extern void amiga_init_sound(void);
@@ -377,7 +377,7 @@ void __init config_amiga(void)
mach_init_IRQ = amiga_init_IRQ;
mach_get_model = amiga_get_model;
mach_get_hardware_list = amiga_get_hardware_list;
- mach_gettimeoffset = amiga_gettimeoffset;
+ arch_gettimeoffset = amiga_gettimeoffset;
/*
* default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI
@@ -482,10 +482,10 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
#define TICK_SIZE 10000
/* This is always executed with interrupts disabled. */
-static unsigned long amiga_gettimeoffset(void)
+static u32 amiga_gettimeoffset(void)
{
unsigned short hi, lo, hi2;
- unsigned long ticks, offset = 0;
+ u32 ticks, offset = 0;
/* read CIA B timer A current value */
hi = ciab.tahi;
@@ -507,7 +507,7 @@ static unsigned long amiga_gettimeoffset(void)
ticks = jiffy_ticks - ticks;
ticks = (10000 * ticks) / jiffy_ticks;
- return ticks + offset;
+ return (ticks + offset) * 1000;
}
static void amiga_reset(void) __noreturn;
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index f5565d6..3ea56b9 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -26,7 +26,7 @@ u_long apollo_model;
extern void dn_sched_init(irq_handler_t handler);
extern void dn_init_IRQ(void);
-extern unsigned long dn_gettimeoffset(void);
+extern u32 dn_gettimeoffset(void);
extern int dn_dummy_hwclk(int, struct rtc_time *);
extern int dn_dummy_set_clock_mmss(unsigned long);
extern void dn_dummy_reset(void);
@@ -151,7 +151,7 @@ void __init config_apollo(void)
mach_sched_init=dn_sched_init; /* */
mach_init_IRQ=dn_init_IRQ;
- mach_gettimeoffset = dn_gettimeoffset;
+ arch_gettimeoffset = dn_gettimeoffset;
mach_max_dma_address = 0xffffffff;
mach_hwclk = dn_dummy_hwclk; /* */
mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */
@@ -203,10 +203,9 @@ void dn_sched_init(irq_handler_t timer_routine)
pr_err("Couldn't register timer interrupt\n");
}
-unsigned long dn_gettimeoffset(void) {
-
+u32 dn_gettimeoffset(void)
+{
return 0xdeadbeef;
-
}
int dn_dummy_hwclk(int op, struct rtc_time *t) {
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index d8eb327..037c11c 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -74,7 +74,7 @@ static void atari_heartbeat(int on);
/* atari specific timer functions (in time.c) */
extern void atari_sched_init(irq_handler_t);
-extern unsigned long atari_gettimeoffset (void);
+extern u32 atari_gettimeoffset(void);
extern int atari_mste_hwclk (int, struct rtc_time *);
extern int atari_tt_hwclk (int, struct rtc_time *);
extern int atari_mste_set_clock_mmss (unsigned long);
@@ -204,7 +204,7 @@ void __init config_atari(void)
mach_init_IRQ = atari_init_IRQ;
mach_get_model = atari_get_model;
mach_get_hardware_list = atari_get_hardware_list;
- mach_gettimeoffset = atari_gettimeoffset;
+ arch_gettimeoffset = atari_gettimeoffset;
mach_reset = atari_reset;
mach_max_dma_address = 0xffffff;
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index c0cc68a..da8f981 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -42,9 +42,9 @@ atari_sched_init(irq_handler_t timer_routine)
#define TICK_SIZE 10000
/* This is always executed with interrupts disabled. */
-unsigned long atari_gettimeoffset (void)
+u32 atari_gettimeoffset(void)
{
- unsigned long ticks, offset = 0;
+ u32 ticks, offset = 0;
/* read MFP timer C current value */
ticks = st_mfp.tim_dt_c;
@@ -57,7 +57,7 @@ unsigned long atari_gettimeoffset (void)
ticks = INT_TICKS - ticks;
ticks = ticks * 10000L / INT_TICKS;
- return ticks + offset;
+ return (ticks + offset) * 1000;
}
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 0bf850a..8943aa4 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -38,7 +38,7 @@
static void bvme6000_get_model(char *model);
extern void bvme6000_sched_init(irq_handler_t handler);
-extern unsigned long bvme6000_gettimeoffset (void);
+extern u32 bvme6000_gettimeoffset(void);
extern int bvme6000_hwclk (int, struct rtc_time *);
extern int bvme6000_set_clock_mmss (unsigned long);
extern void bvme6000_reset (void);
@@ -110,7 +110,7 @@ void __init config_bvme6000(void)
mach_max_dma_address = 0xffffffff;
mach_sched_init = bvme6000_sched_init;
mach_init_IRQ = bvme6000_init_IRQ;
- mach_gettimeoffset = bvme6000_gettimeoffset;
+ arch_gettimeoffset = bvme6000_gettimeoffset;
mach_hwclk = bvme6000_hwclk;
mach_set_clock_mmss = bvme6000_set_clock_mmss;
mach_reset = bvme6000_reset;
@@ -216,13 +216,13 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
* results...
*/
-unsigned long bvme6000_gettimeoffset (void)
+u32 bvme6000_gettimeoffset(void)
{
volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
unsigned char msr = rtc->msr & 0xc0;
unsigned char t1int, t1op;
- unsigned long v = 800000, ov;
+ u32 v = 800000, ov;
rtc->msr = 0; /* Ensure timer registers accessible */
@@ -246,7 +246,7 @@ unsigned long bvme6000_gettimeoffset (void)
v += 10000; /* Int pending, + 10ms */
rtc->msr = msr;
- return v;
+ return v * 1000;
}
/*
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index bf16af1..b7609f7 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -251,7 +251,7 @@ void __init config_hp300(void)
mach_sched_init = hp300_sched_init;
mach_init_IRQ = hp300_init_IRQ;
mach_get_model = hp300_get_model;
- mach_gettimeoffset = hp300_gettimeoffset;
+ arch_gettimeoffset = hp300_gettimeoffset;
mach_hwclk = hp300_hwclk;
mach_get_ss = hp300_get_ss;
mach_reset = hp300_reset;
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 29a71be..749543b 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -46,7 +46,7 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
return vector(irq, NULL);
}
-unsigned long hp300_gettimeoffset(void)
+u32 hp300_gettimeoffset(void)
{
/* Read current timer 1 value */
unsigned char lsb, msb1, msb2;
@@ -59,7 +59,7 @@ unsigned long hp300_gettimeoffset(void)
/* A carry happened while we were reading. Read it again */
lsb = in_8(CLOCKBASE + 7);
ticks = INTVAL - ((msb2 << 8) | lsb);
- return (USECS_PER_JIFFY * ticks) / INTVAL;
+ return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000;
}
void __init hp300_sched_init(irq_handler_t vector)
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
index 7b98242..f5583ec 100644
--- a/arch/m68k/hp300/time.h
+++ b/arch/m68k/hp300/time.h
@@ -1,2 +1,2 @@
extern void hp300_sched_init(irq_handler_t vector);
-extern unsigned long hp300_gettimeoffset(void);
+extern u32 hp300_gettimeoffset(void);
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index 825c1c8..953ca21 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -3,6 +3,7 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
+#include <linux/time.h>
struct pt_regs;
struct mktime;
@@ -16,7 +17,6 @@ extern void (*mach_init_IRQ) (void);
extern void (*mach_get_model) (char *model);
extern void (*mach_get_hardware_list) (struct seq_file *m);
/* machine dependent timer functions */
-extern unsigned long (*mach_gettimeoffset)(void);
extern int (*mach_hwclk)(int, struct rtc_time*);
extern unsigned int (*mach_get_ss)(void);
extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index d872ce4..80cfbe5 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -84,7 +84,6 @@ void (*mach_init_IRQ) (void) __initdata = NULL;
void (*mach_get_model) (char *model);
void (*mach_get_hardware_list) (struct seq_file *m);
/* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
int (*mach_hwclk) (int, struct rtc_time*);
EXPORT_SYMBOL(mach_hwclk);
int (*mach_set_clock_mmss) (unsigned long);
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index c2994c8..bea6bcf 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -82,11 +82,6 @@ void read_persistent_clock(struct timespec *ts)
#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-static u32 m68k_gettimeoffset(void)
-{
- return mach_gettimeoffset() * 1000;
-}
-
static int __init rtc_init(void)
{
struct platform_device *pdev;
@@ -104,9 +99,5 @@ module_init(rtc_init);
void __init time_init(void)
{
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
- arch_gettimeoffset = m68k_gettimeoffset;
-#endif
-
mach_sched_init(timer_interrupt);
}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index d9f62e0..afb95d5 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -52,7 +52,7 @@ struct mac_booter_data mac_bi_data;
static unsigned long mac_orig_videoaddr;
/* Mac specific timer functions */
-extern unsigned long mac_gettimeoffset(void);
+extern u32 mac_gettimeoffset(void);
extern int mac_hwclk(int, struct rtc_time *);
extern int mac_set_clock_mmss(unsigned long);
extern void iop_preinit(void);
@@ -177,7 +177,7 @@ void __init config_mac(void)
mach_sched_init = mac_sched_init;
mach_init_IRQ = mac_init_IRQ;
mach_get_model = mac_get_model;
- mach_gettimeoffset = mac_gettimeoffset;
+ arch_gettimeoffset = mac_gettimeoffset;
mach_hwclk = mac_hwclk;
mach_set_clock_mmss = mac_set_clock_mmss;
mach_reset = mac_reset;
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 2d85662..5d1458b 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -327,7 +327,7 @@ void via_debug_dump(void)
* TBI: get time offset between scheduling timer ticks
*/
-unsigned long mac_gettimeoffset (void)
+u32 mac_gettimeoffset(void)
{
unsigned long ticks, offset = 0;
@@ -341,7 +341,7 @@ unsigned long mac_gettimeoffset (void)
ticks = MAC_CLOCK_TICK - ticks;
ticks = ticks * 10000L / MAC_CLOCK_TICK;
- return ticks + offset;
+ return (ticks + offset) * 1000;
}
/*
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index a41c091..1c62628 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -37,7 +37,7 @@
static void mvme147_get_model(char *model);
extern void mvme147_sched_init(irq_handler_t handler);
-extern unsigned long mvme147_gettimeoffset (void);
+extern u32 mvme147_gettimeoffset(void);
extern int mvme147_hwclk (int, struct rtc_time *);
extern int mvme147_set_clock_mmss (unsigned long);
extern void mvme147_reset (void);
@@ -88,7 +88,7 @@ void __init config_mvme147(void)
mach_max_dma_address = 0x01000000;
mach_sched_init = mvme147_sched_init;
mach_init_IRQ = mvme147_init_IRQ;
- mach_gettimeoffset = mvme147_gettimeoffset;
+ arch_gettimeoffset = mvme147_gettimeoffset;
mach_hwclk = mvme147_hwclk;
mach_set_clock_mmss = mvme147_set_clock_mmss;
mach_reset = mvme147_reset;
@@ -127,7 +127,7 @@ void mvme147_sched_init (irq_handler_t timer_routine)
/* This is always executed with interrupts disabled. */
/* XXX There are race hazards in this code XXX */
-unsigned long mvme147_gettimeoffset (void)
+u32 mvme147_gettimeoffset(void)
{
volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
unsigned short n;
@@ -137,7 +137,7 @@ unsigned long mvme147_gettimeoffset (void)
n = *cp;
n -= PCC_TIMER_PRELOAD;
- return (unsigned long)n * 25 / 4;
+ return ((unsigned long)n * 25 / 4) * 1000;
}
static int bcd2int (unsigned char b)
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index b6d7d8a..080a342 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -43,7 +43,7 @@ static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
static void mvme16x_get_model(char *model);
extern void mvme16x_sched_init(irq_handler_t handler);
-extern unsigned long mvme16x_gettimeoffset (void);
+extern u32 mvme16x_gettimeoffset(void);
extern int mvme16x_hwclk (int, struct rtc_time *);
extern int mvme16x_set_clock_mmss (unsigned long);
extern void mvme16x_reset (void);
@@ -289,7 +289,7 @@ void __init config_mvme16x(void)
mach_max_dma_address = 0xffffffff;
mach_sched_init = mvme16x_sched_init;
mach_init_IRQ = mvme16x_init_IRQ;
- mach_gettimeoffset = mvme16x_gettimeoffset;
+ arch_gettimeoffset = mvme16x_gettimeoffset;
mach_hwclk = mvme16x_hwclk;
mach_set_clock_mmss = mvme16x_set_clock_mmss;
mach_reset = mvme16x_reset;
@@ -405,9 +405,9 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
/* This is always executed with interrupts disabled. */
-unsigned long mvme16x_gettimeoffset (void)
+u32 mvme16x_gettimeoffset(void)
{
- return (*(volatile unsigned long *)0xfff42008);
+ return (*(volatile u32 *)0xfff42008) * 1000;
}
int bcd2int (unsigned char b)
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 1adb5b7..658542b 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -40,7 +40,7 @@ extern void q40_init_IRQ(void);
static void q40_get_model(char *model);
extern void q40_sched_init(irq_handler_t handler);
-static unsigned long q40_gettimeoffset(void);
+static u32 q40_gettimeoffset(void);
static int q40_hwclk(int, struct rtc_time *);
static unsigned int q40_get_ss(void);
static int q40_set_clock_mmss(unsigned long);
@@ -170,7 +170,7 @@ void __init config_q40(void)
mach_sched_init = q40_sched_init;
mach_init_IRQ = q40_init_IRQ;
- mach_gettimeoffset = q40_gettimeoffset;
+ arch_gettimeoffset = q40_gettimeoffset;
mach_hwclk = q40_hwclk;
mach_get_ss = q40_get_ss;
mach_get_rtc_pll = q40_get_rtc_pll;
@@ -204,9 +204,9 @@ int q40_parse_bootinfo(const struct bi_record *rec)
}
-static unsigned long q40_gettimeoffset(void)
+static u32 q40_gettimeoffset(void)
{
- return 5000 * (ql_ticks != 0);
+ return 5000 * (ql_ticks != 0) * 1000;
}
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 2ca25bd..f59ec58 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -36,7 +36,7 @@
char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
-extern unsigned long sun3_gettimeoffset(void);
+extern u32 sun3_gettimeoffset(void);
static void sun3_sched_init(irq_handler_t handler);
extern void sun3_get_model (char* model);
extern int sun3_hwclk(int set, struct rtc_time *t);
@@ -141,7 +141,7 @@ void __init config_sun3(void)
mach_sched_init = sun3_sched_init;
mach_init_IRQ = sun3_init_IRQ;
mach_reset = sun3_reboot;
- mach_gettimeoffset = sun3_gettimeoffset;
+ arch_gettimeoffset = sun3_gettimeoffset;
mach_get_model = sun3_get_model;
mach_hwclk = sun3_hwclk;
mach_halt = sun3_halt;
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
index 94fe801..889829e 100644
--- a/arch/m68k/sun3/intersil.c
+++ b/arch/m68k/sun3/intersil.c
@@ -23,9 +23,9 @@
#define START_VAL (INTERSIL_RUN | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
/* does this need to be implemented? */
-unsigned long sun3_gettimeoffset(void)
+u32 sun3_gettimeoffset(void)
{
- return 1;
+ return 1000;
}
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index dd306c8..0532d64 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -48,7 +48,7 @@ void __init config_sun3x(void)
mach_sched_init = sun3x_sched_init;
mach_init_IRQ = sun3_init_IRQ;
- mach_gettimeoffset = sun3x_gettimeoffset;
+ arch_gettimeoffset = sun3x_gettimeoffset;
mach_reset = sun3x_reboot;
mach_hwclk = sun3x_hwclk;
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index 1d0a724..c8eb08a 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -71,7 +71,7 @@ int sun3x_hwclk(int set, struct rtc_time *t)
return 0;
}
/* Not much we can do here */
-unsigned long sun3x_gettimeoffset (void)
+u32 sun3x_gettimeoffset(void)
{
return 0L;
}
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
index 6909e12..a4f9126 100644
--- a/arch/m68k/sun3x/time.h
+++ b/arch/m68k/sun3x/time.h
@@ -2,7 +2,7 @@
#define SUN3X_TIME_H
extern int sun3x_hwclk(int set, struct rtc_time *t);
-unsigned long sun3x_gettimeoffset (void);
+u32 sun3x_gettimeoffset(void);
void sun3x_sched_init(irq_handler_t vector);
struct mostek_dt {
--
1.7.0.4
^ permalink raw reply related
* [PATCH 04/11] ARM: set arch_gettimeoffset directly
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
remove ARM's struct sys_timer .offset function pointer, and instead
directly set the arch_gettimeoffset function pointer when the timer
driver is initialized. This requires multiplying all function results
by 1000, since the removed arm_gettimeoffset() did this. Also,
s/unsigned long/u32/ just to make the function prototypes exactly
match that of arch_gettimeoffset.
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Andrew Victor <linux@maxim.org.za>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Cc: Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ryan Mallon <rmallon@gmail.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/include/asm/mach/time.h | 3 ---
arch/arm/kernel/time.c | 14 --------------
arch/arm/mach-at91/at91x40_time.c | 8 +++++---
arch/arm/mach-ebsa110/core.c | 7 ++++---
arch/arm/mach-ep93xx/core.c | 23 ++++++++++++-----------
arch/arm/mach-h720x/common.c | 6 +++---
arch/arm/mach-h720x/common.h | 2 +-
arch/arm/mach-h720x/cpu-h7201.c | 3 ++-
arch/arm/mach-h720x/cpu-h7202.c | 3 ++-
arch/arm/mach-rpc/time.c | 6 +++---
arch/arm/plat-samsung/time.c | 7 ++++---
11 files changed, 36 insertions(+), 46 deletions(-)
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index 6ca945f..cac8d9c 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -35,9 +35,6 @@ struct sys_timer {
void (*init)(void);
void (*suspend)(void);
void (*resume)(void);
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
- unsigned long (*offset)(void);
-#endif
};
extern void timer_tick(void);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index b0190b4..ea36bfa 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -69,16 +69,6 @@ unsigned long profile_pc(struct pt_regs *regs)
EXPORT_SYMBOL(profile_pc);
#endif
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-static u32 arm_gettimeoffset(void)
-{
- if (system_timer->offset != NULL)
- return system_timer->offset() * 1000;
-
- return 0;
-}
-#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
-
#ifndef CONFIG_GENERIC_CLOCKEVENTS
/*
* Kernel system timer support.
@@ -164,10 +154,6 @@ device_initcall(timer_init_syscore_ops);
void __init time_init(void)
{
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
- arch_gettimeoffset = arm_gettimeoffset;
-#endif
-
system_timer = machine_desc->timer;
system_timer->init();
sched_clock_postinit();
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
index ee06d7b..eb6151e 100644
--- a/arch/arm/mach-at91/at91x40_time.c
+++ b/arch/arm/mach-at91/at91x40_time.c
@@ -41,9 +41,10 @@
#define AT91_TC_CLK1BASE 0x40
#define AT91_TC_CLK2BASE 0x80
-static unsigned long at91x40_gettimeoffset(void)
+static u32 at91x40_gettimeoffset(void)
{
- return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / (AT91X40_MASTER_CLOCK / 128));
+ return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 /
+ (AT91X40_MASTER_CLOCK / 128)) * 1000;
}
static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id)
@@ -63,6 +64,8 @@ void __init at91x40_timer_init(void)
{
unsigned int v;
+ arch_gettimeoffset = at91x40_gettimeoffset;
+
at91_tc_write(AT91_TC_BCR, 0);
v = at91_tc_read(AT91_TC_BMR);
v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE;
@@ -81,6 +84,5 @@ void __init at91x40_timer_init(void)
struct sys_timer at91x40_timer = {
.init = at91x40_timer_init,
- .offset = at91x40_gettimeoffset,
};
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index f0fe6b5..d96dd94 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -158,7 +158,7 @@ static void __init ebsa110_init_early(void)
* interrupt, then the PIT counter will roll over (ie, be negative).
* This actually works out to be convenient.
*/
-static unsigned long ebsa110_gettimeoffset(void)
+static u32 ebsa110_gettimeoffset(void)
{
unsigned long offset, count;
@@ -181,7 +181,7 @@ static unsigned long ebsa110_gettimeoffset(void)
*/
offset = offset * (1000000 / HZ) / COUNT;
- return offset;
+ return offset * 1000;
}
static irqreturn_t
@@ -215,6 +215,8 @@ static struct irqaction ebsa110_timer_irq = {
*/
static void __init ebsa110_timer_init(void)
{
+ arch_gettimeoffset = ebsa110_gettimeoffset;
+
/*
* Timer 1, mode 2, LSB/MSB
*/
@@ -227,7 +229,6 @@ static void __init ebsa110_timer_init(void)
static struct sys_timer ebsa110_timer = {
.init = ebsa110_timer_init,
- .offset = ebsa110_gettimeoffset,
};
static struct plat_serial8250_port serial_platform_data[] = {
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index e85bf17..c084acf 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -140,11 +140,23 @@ static struct irqaction ep93xx_timer_irq = {
.handler = ep93xx_timer_interrupt,
};
+static u32 ep93xx_gettimeoffset(void)
+{
+ int offset;
+
+ offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
+
+ /* Calculate (1000000 / 983040) * offset. */
+ return (offset + (53 * offset / 3072)) * 1000;
+}
+
static void __init ep93xx_timer_init(void)
{
u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
EP93XX_TIMER123_CONTROL_CLKSEL;
+ arch_gettimeoffset = ep93xx_gettimeoffset;
+
/* Enable periodic HZ timer. */
__raw_writel(tmode, EP93XX_TIMER1_CONTROL);
__raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD);
@@ -158,19 +170,8 @@ static void __init ep93xx_timer_init(void)
setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
}
-static unsigned long ep93xx_gettimeoffset(void)
-{
- int offset;
-
- offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
-
- /* Calculate (1000000 / 983040) * offset. */
- return offset + (53 * offset / 3072);
-}
-
struct sys_timer ep93xx_timer = {
.init = ep93xx_timer_init,
- .offset = ep93xx_gettimeoffset,
};
diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
index aa1331e..17ef91f 100644
--- a/arch/arm/mach-h720x/common.c
+++ b/arch/arm/mach-h720x/common.c
@@ -42,12 +42,12 @@ void __init arch_dma_init(dma_t *dma)
}
/*
- * Return usecs since last timer reload
+ * Return nsecs since last timer reload
* (timercount * (usecs perjiffie)) / (ticks per jiffie)
*/
-unsigned long h720x_gettimeoffset(void)
+u32 h720x_gettimeoffset(void)
{
- return (CPU_REG (TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH;
+ return ((CPU_REG(TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH) * 1000;
}
/*
diff --git a/arch/arm/mach-h720x/common.h b/arch/arm/mach-h720x/common.h
index 2489537..79cfb97 100644
--- a/arch/arm/mach-h720x/common.h
+++ b/arch/arm/mach-h720x/common.h
@@ -13,7 +13,7 @@
*
*/
-extern unsigned long h720x_gettimeoffset(void);
+extern u32 h720x_gettimeoffset(void);
extern void __init h720x_init_irq(void);
extern void __init h720x_map_io(void);
extern void h720x_restart(char, const char *);
diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c
index 24df2a3..ba349cf 100644
--- a/arch/arm/mach-h720x/cpu-h7201.c
+++ b/arch/arm/mach-h720x/cpu-h7201.c
@@ -46,6 +46,8 @@ static struct irqaction h7201_timer_irq = {
*/
void __init h7201_init_time(void)
{
+ arch_gettimeoffset = h720x_gettimeoffset;
+
CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
@@ -56,5 +58,4 @@ void __init h7201_init_time(void)
struct sys_timer h7201_timer = {
.init = h7201_init_time,
- .offset = h720x_gettimeoffset,
};
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
index c37d570..fb9ca76 100644
--- a/arch/arm/mach-h720x/cpu-h7202.c
+++ b/arch/arm/mach-h720x/cpu-h7202.c
@@ -180,6 +180,8 @@ static struct irqaction h7202_timer_irq = {
*/
void __init h7202_init_time(void)
{
+ arch_gettimeoffset = h720x_gettimeoffset;
+
CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
@@ -190,7 +192,6 @@ void __init h7202_init_time(void)
struct sys_timer h7202_timer = {
.init = h7202_init_time,
- .offset = h720x_gettimeoffset,
};
void __init h7202_init_irq (void)
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 581fca9..6ddccb0 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -24,7 +24,7 @@
#include <asm/mach/time.h>
-unsigned long ioc_timer_gettimeoffset(void)
+static u32 ioc_timer_gettimeoffset(void)
{
unsigned int count1, count2, status;
long offset;
@@ -56,7 +56,7 @@ unsigned long ioc_timer_gettimeoffset(void)
}
offset = (LATCH - offset) * (tick_nsec / 1000);
- return (offset + LATCH/2) / LATCH;
+ return ((offset + LATCH/2) / LATCH) * 1000;
}
void __init ioctime_init(void)
@@ -84,12 +84,12 @@ static struct irqaction ioc_timer_irq = {
*/
static void __init ioc_timer_init(void)
{
+ arch_gettimeoffset = ioc_timer_gettimeoffset;
ioctime_init();
setup_irq(IRQ_TIMER0, &ioc_timer_irq);
}
struct sys_timer ioc_timer = {
.init = ioc_timer_init,
- .offset = ioc_timer_gettimeoffset,
};
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
index 60552e2..67206df 100644
--- a/arch/arm/plat-samsung/time.c
+++ b/arch/arm/plat-samsung/time.c
@@ -95,7 +95,7 @@ static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
* IRQs are disabled before entering here from do_gettimeofday()
*/
-static unsigned long s3c2410_gettimeoffset (void)
+static u32 s3c2410_gettimeoffset(void)
{
unsigned long tdone;
unsigned long tval;
@@ -120,7 +120,7 @@ static unsigned long s3c2410_gettimeoffset (void)
tdone += timer_startval;
}
- return timer_ticks_to_usec(tdone);
+ return timer_ticks_to_usec(tdone) * 1000;
}
@@ -273,6 +273,8 @@ static void __init s3c2410_timer_resources(void)
static void __init s3c2410_timer_init(void)
{
+ arch_gettimeoffset = s3c2410_gettimeoffset;
+
s3c2410_timer_resources();
s3c2410_timer_setup();
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
@@ -280,6 +282,5 @@ static void __init s3c2410_timer_init(void)
struct sys_timer s3c24xx_timer = {
.init = s3c2410_timer_init,
- .offset = s3c2410_gettimeoffset,
.resume = s3c2410_timer_setup
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 05/11] ARM: at91: convert timer suspend/resume to clock_event_device
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
Move at91's timer suspend/resume functions from struct sys_timer
at91sam926x_timer into struct clock_event_device pit_clkevt. This
will allow the sys_timer suspend/resume fields to be removed, and
eventually lead to a complete removal of struct sys_timer.
Cc: Andrew Victor <linux@maxim.org.za>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/mach-at91/at91sam926x_time.c | 47 ++++++++++++++++++--------------
1 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index ffc0957..2794882 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -94,12 +94,38 @@ pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
}
}
+static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
+{
+ /* Disable timer */
+ pit_write(AT91_PIT_MR, 0);
+}
+
+static void at91sam926x_pit_reset(void)
+{
+ /* Disable timer and irqs */
+ pit_write(AT91_PIT_MR, 0);
+
+ /* Clear any pending interrupts, wait for PIT to stop counting */
+ while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
+ cpu_relax();
+
+ /* Start PIT but don't enable IRQ */
+ pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
+}
+
+static void at91sam926x_pit_resume(struct clock_event_device *cedev)
+{
+ at91sam926x_pit_reset();
+}
+
static struct clock_event_device pit_clkevt = {
.name = "pit",
.features = CLOCK_EVT_FEAT_PERIODIC,
.shift = 32,
.rating = 100,
.set_mode = pit_clkevt_mode,
+ .suspend = at91sam926x_pit_suspend,
+ .resume = at91sam926x_pit_resume,
};
@@ -140,19 +166,6 @@ static struct irqaction at91sam926x_pit_irq = {
.irq = NR_IRQS_LEGACY + AT91_ID_SYS,
};
-static void at91sam926x_pit_reset(void)
-{
- /* Disable timer and irqs */
- pit_write(AT91_PIT_MR, 0);
-
- /* Clear any pending interrupts, wait for PIT to stop counting */
- while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
- cpu_relax();
-
- /* Start PIT but don't enable IRQ */
- pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
-}
-
#ifdef CONFIG_OF
static struct of_device_id pit_timer_ids[] = {
{ .compatible = "atmel,at91sam9260-pit" },
@@ -240,12 +253,6 @@ static void __init at91sam926x_pit_init(void)
clockevents_register_device(&pit_clkevt);
}
-static void at91sam926x_pit_suspend(void)
-{
- /* Disable timer */
- pit_write(AT91_PIT_MR, 0);
-}
-
void __init at91sam926x_ioremap_pit(u32 addr)
{
#if defined(CONFIG_OF)
@@ -265,6 +272,4 @@ void __init at91sam926x_ioremap_pit(u32 addr)
struct sys_timer at91sam926x_timer = {
.init = at91sam926x_pit_init,
- .suspend = at91sam926x_pit_suspend,
- .resume = at91sam926x_pit_reset,
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 06/11] ARM: pxa: convert timer suspend/resume to clock_event_device
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
Move PXA's timer suspend/resume functions from struct sys_timer
pxa_timer into struct clock_event_device ckevt_pxa_osmr0. This
will allow the sys_timer suspend/resume fields to be removed, and
eventually lead to a complete removal of struct sys_timer.
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/mach-pxa/time.c | 76 +++++++++++++++++++++++-----------------------
1 files changed, 38 insertions(+), 38 deletions(-)
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 4bc47d6..ce58bc9 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -89,12 +89,50 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
}
}
+#ifdef CONFIG_PM
+static unsigned long osmr[4], oier, oscr;
+
+static void pxa_timer_suspend(struct clock_event_device *cedev)
+{
+ osmr[0] = readl_relaxed(OSMR0);
+ osmr[1] = readl_relaxed(OSMR1);
+ osmr[2] = readl_relaxed(OSMR2);
+ osmr[3] = readl_relaxed(OSMR3);
+ oier = readl_relaxed(OIER);
+ oscr = readl_relaxed(OSCR);
+}
+
+static void pxa_timer_resume(struct clock_event_device *cedev)
+{
+ /*
+ * Ensure that we have at least MIN_OSCR_DELTA between match
+ * register 0 and the OSCR, to guarantee that we will receive
+ * the one-shot timer interrupt. We adjust OSMR0 in preference
+ * to OSCR to guarantee that OSCR is monotonically incrementing.
+ */
+ if (osmr[0] - oscr < MIN_OSCR_DELTA)
+ osmr[0] += MIN_OSCR_DELTA;
+
+ writel_relaxed(osmr[0], OSMR0);
+ writel_relaxed(osmr[1], OSMR1);
+ writel_relaxed(osmr[2], OSMR2);
+ writel_relaxed(osmr[3], OSMR3);
+ writel_relaxed(oier, OIER);
+ writel_relaxed(oscr, OSCR);
+}
+#else
+#define pxa_timer_suspend NULL
+#define pxa_timer_resume NULL
+#endif
+
static struct clock_event_device ckevt_pxa_osmr0 = {
.name = "osmr0",
.features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
.set_next_event = pxa_osmr0_set_next_event,
.set_mode = pxa_osmr0_set_mode,
+ .suspend = pxa_timer_suspend,
+ .resume = pxa_timer_resume,
};
static struct irqaction pxa_ost0_irq = {
@@ -127,44 +165,6 @@ static void __init pxa_timer_init(void)
clockevents_register_device(&ckevt_pxa_osmr0);
}
-#ifdef CONFIG_PM
-static unsigned long osmr[4], oier, oscr;
-
-static void pxa_timer_suspend(void)
-{
- osmr[0] = readl_relaxed(OSMR0);
- osmr[1] = readl_relaxed(OSMR1);
- osmr[2] = readl_relaxed(OSMR2);
- osmr[3] = readl_relaxed(OSMR3);
- oier = readl_relaxed(OIER);
- oscr = readl_relaxed(OSCR);
-}
-
-static void pxa_timer_resume(void)
-{
- /*
- * Ensure that we have@least MIN_OSCR_DELTA between match
- * register 0 and the OSCR, to guarantee that we will receive
- * the one-shot timer interrupt. We adjust OSMR0 in preference
- * to OSCR to guarantee that OSCR is monotonically incrementing.
- */
- if (osmr[0] - oscr < MIN_OSCR_DELTA)
- osmr[0] += MIN_OSCR_DELTA;
-
- writel_relaxed(osmr[0], OSMR0);
- writel_relaxed(osmr[1], OSMR1);
- writel_relaxed(osmr[2], OSMR2);
- writel_relaxed(osmr[3], OSMR3);
- writel_relaxed(oier, OIER);
- writel_relaxed(oscr, OSCR);
-}
-#else
-#define pxa_timer_suspend NULL
-#define pxa_timer_resume NULL
-#endif
-
struct sys_timer pxa_timer = {
.init = pxa_timer_init,
- .suspend = pxa_timer_suspend,
- .resume = pxa_timer_resume,
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 07/11] ARM: sa1100: convert timer suspend/resume to clock_event_device
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
Move sa1100's timer suspend/resume functions from struct sys_timer
sa1100_timer into struct clock_event_device ckevt_sa1100_osmr0. This
will allow the sys_timer suspend/resume fields to be removed, and
eventually lead to a complete removal of struct sys_timer.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/mach-sa1100/time.c | 66 +++++++++++++++++++++---------------------
1 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 80702c9..164f827 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -69,12 +69,45 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
}
}
+#ifdef CONFIG_PM
+unsigned long osmr[4], oier;
+
+static void sa1100_timer_suspend(struct clock_event_device *cedev)
+{
+ osmr[0] = readl_relaxed(OSMR0);
+ osmr[1] = readl_relaxed(OSMR1);
+ osmr[2] = readl_relaxed(OSMR2);
+ osmr[3] = readl_relaxed(OSMR3);
+ oier = readl_relaxed(OIER);
+}
+
+static void sa1100_timer_resume(struct clock_event_device *cedev)
+{
+ writel_relaxed(0x0f, OSSR);
+ writel_relaxed(osmr[0], OSMR0);
+ writel_relaxed(osmr[1], OSMR1);
+ writel_relaxed(osmr[2], OSMR2);
+ writel_relaxed(osmr[3], OSMR3);
+ writel_relaxed(oier, OIER);
+
+ /*
+ * OSMR0 is the system timer: make sure OSCR is sufficiently behind
+ */
+ writel_relaxed(OSMR0 - LATCH, OSCR);
+}
+#else
+#define sa1100_timer_suspend NULL
+#define sa1100_timer_resume NULL
+#endif
+
static struct clock_event_device ckevt_sa1100_osmr0 = {
.name = "osmr0",
.features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
.set_next_event = sa1100_osmr0_set_next_event,
.set_mode = sa1100_osmr0_set_mode,
+ .suspend = sa1100_timer_suspend,
+ .resume = sa1100_timer_resume,
};
static struct irqaction sa1100_timer_irq = {
@@ -105,39 +138,6 @@ static void __init sa1100_timer_init(void)
clockevents_register_device(&ckevt_sa1100_osmr0);
}
-#ifdef CONFIG_PM
-unsigned long osmr[4], oier;
-
-static void sa1100_timer_suspend(void)
-{
- osmr[0] = readl_relaxed(OSMR0);
- osmr[1] = readl_relaxed(OSMR1);
- osmr[2] = readl_relaxed(OSMR2);
- osmr[3] = readl_relaxed(OSMR3);
- oier = readl_relaxed(OIER);
-}
-
-static void sa1100_timer_resume(void)
-{
- writel_relaxed(0x0f, OSSR);
- writel_relaxed(osmr[0], OSMR0);
- writel_relaxed(osmr[1], OSMR1);
- writel_relaxed(osmr[2], OSMR2);
- writel_relaxed(osmr[3], OSMR3);
- writel_relaxed(oier, OIER);
-
- /*
- * OSMR0 is the system timer: make sure OSCR is sufficiently behind
- */
- writel_relaxed(OSMR0 - LATCH, OSCR);
-}
-#else
-#define sa1100_timer_suspend NULL
-#define sa1100_timer_resume NULL
-#endif
-
struct sys_timer sa1100_timer = {
.init = sa1100_timer_init,
- .suspend = sa1100_timer_suspend,
- .resume = sa1100_timer_resume,
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 08/11] ARM: ux500: convert timer suspend/resume to clock_event_device
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
Move ux500's timer suspend/resume functions from struct sys_timer
ux500_timer into struct clock_event_device nmdk_clkevt. This
will allow the sys_timer suspend/resume fields to be removed, and
eventually lead to a complete removal of struct sys_timer.
Cc: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/mach-ux500/timer.c | 7 -------
drivers/clocksource/nomadik-mtu.c | 33 ++++++++++++++++++++-------------
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index 875309a..46a7244 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -100,13 +100,6 @@ dt_fail:
ux500_twd_init();
}
-static void ux500_timer_reset(void)
-{
- nmdk_clkevt_reset();
- nmdk_clksrc_reset();
-}
-
struct sys_timer ux500_timer = {
.init = ux500_timer_init,
- .resume = ux500_timer_reset,
};
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c
index 23c780b..a60b077 100644
--- a/drivers/clocksource/nomadik-mtu.c
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -134,12 +134,32 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
}
}
+void nmdk_clksrc_reset(void)
+{
+ /* Disable */
+ writel(0, mtu_base + MTU_CR(0));
+
+ /* ClockSource: 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));
+
+ writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+ mtu_base + MTU_CR(0));
+}
+
+static void nmdk_clkevt_resume(struct clock_event_device *cedev)
+{
+ nmdk_clkevt_reset();
+ nmdk_clksrc_reset();
+}
+
static struct clock_event_device nmdk_clkevt = {
.name = "mtu_1",
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
.rating = 200,
.set_mode = nmdk_clkevt_mode,
.set_next_event = nmdk_clkevt_next,
+ .resume = nmdk_clkevt_resume,
};
/*
@@ -161,19 +181,6 @@ static struct irqaction nmdk_timer_irq = {
.dev_id = &nmdk_clkevt,
};
-void nmdk_clksrc_reset(void)
-{
- /* Disable */
- writel(0, mtu_base + MTU_CR(0));
-
- /* ClockSource: 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));
-
- writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
- mtu_base + MTU_CR(0));
-}
-
void __init nmdk_timer_init(void __iomem *base, int irq)
{
unsigned long rate;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 09/11] ARM: samsung: register syscore_ops for timer resume directly
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
Instead of using struct sys_timer's resume function, register syscore_ops
directly in s3c2410_timer_init(). This will allow the sys_timer suspend/
resume fields to be removed, and eventually lead to a complete removal of
struct sys_timer.
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/plat-samsung/time.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
index 67206df..773745a 100644
--- a/arch/arm/plat-samsung/time.c
+++ b/arch/arm/plat-samsung/time.c
@@ -27,6 +27,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
#include <asm/mach-types.h>
@@ -271,6 +272,10 @@ static void __init s3c2410_timer_resources(void)
clk_enable(tin);
}
+static struct syscore_ops s3c24xx_syscore_ops = {
+ .resume = s3c2410_timer_setup,
+};
+
static void __init s3c2410_timer_init(void)
{
arch_gettimeoffset = s3c2410_gettimeoffset;
@@ -278,9 +283,9 @@ static void __init s3c2410_timer_init(void)
s3c2410_timer_resources();
s3c2410_timer_setup();
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+ register_syscore_ops(&s3c24xx_syscore_ops);
}
struct sys_timer s3c24xx_timer = {
.init = s3c2410_timer_init,
- .resume = s3c2410_timer_setup
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 10/11] ARM: remove struct sys_timer suspend and resume fields
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
These fields duplicate e.g. struct clock_event_device's suspend and
resume fields, so remove them now that nothing is using them. The aim
is to remove all fields from struct sys_timer except .init, then replace
the ARM machine descriptor's .timer field with a .init_time function
instead, and delete struct sys_timer.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/include/asm/mach/time.h | 11 -----------
arch/arm/kernel/time.c | 34 ----------------------------------
2 files changed, 0 insertions(+), 45 deletions(-)
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index cac8d9c..d316d76 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -17,15 +17,6 @@
* Initialise the kernels jiffy timer source, claim interrupt
* using setup_irq. This is called early on during initialisation
* while interrupts are still disabled on the local CPU.
- * - suspend
- * Suspend the kernel jiffy timer source, if necessary. This
- * is called with interrupts disabled, after all normal devices
- * have been suspended. If no action is required, set this to
- * NULL.
- * - resume
- * Resume the kernel jiffy timer source, if necessary. This
- * is called with interrupts disabled before any normal devices
- * are resumed. If no action is required, set this to NULL.
* - offset
* Return the timer offset in microseconds since the last timer
* interrupt. Note: this must take account of any unprocessed
@@ -33,8 +24,6 @@
*/
struct sys_timer {
void (*init)(void);
- void (*suspend)(void);
- void (*resume)(void);
};
extern void timer_tick(void);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index ea36bfa..0b51a7c 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -21,7 +21,6 @@
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/profile.h>
-#include <linux/syscore_ops.h>
#include <linux/timer.h>
#include <linux/irq.h>
@@ -119,39 +118,6 @@ int __init register_persistent_clock(clock_access_fn read_boot,
return -EINVAL;
}
-#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
-static int timer_suspend(void)
-{
- if (system_timer->suspend)
- system_timer->suspend();
-
- return 0;
-}
-
-static void timer_resume(void)
-{
- if (system_timer->resume)
- system_timer->resume();
-}
-#else
-#define timer_suspend NULL
-#define timer_resume NULL
-#endif
-
-static struct syscore_ops timer_syscore_ops = {
- .suspend = timer_suspend,
- .resume = timer_resume,
-};
-
-static int __init timer_init_syscore_ops(void)
-{
- register_syscore_ops(&timer_syscore_ops);
-
- return 0;
-}
-
-device_initcall(timer_init_syscore_ops);
-
void __init time_init(void)
{
system_timer = machine_desc->timer;
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH 11/11] ARM: delete struct sys_timer
From: Stephen Warren @ 2012-11-08 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-1-git-send-email-swarren@wwwdotorg.org>
From: Stephen Warren <swarren@nvidia.com>
Now that the only field in struct sys_timer is .init, delete the struct,
and replace the machine descriptor .timer field with the initialization
function itself.
This will enable moving timer drivers into drivers/clocksource without
having to place a public prototype of each struct sys_timer object into
include/linux; the intent is to create a single of_clocksource_init()
function that determines which timer driver to initialize by scanning
the device dtree, much like the proposed irqchip_init() at:
http://www.spinics.net/lists/arm-kernel/msg203686.html
RFC: This will be quite a large patch since it'll end up touching tens
or hundreds of ARM board files, timer drivers, etc. Perhaps it'd be
better to create patches that:
1) Add .init_time field to machine descriptor, update ARM's time_init to
use that if present, else fall back to .timer.init.
2) 1 patch per ARM sub-architecture to convert to from .timer to
.init_time.
3) Remove sys_timer and machine descriptor .timer field.
For now, this patch only converts Tegra as an example of my intent.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/include/asm/mach/arch.h | 3 +--
arch/arm/include/asm/mach/time.h | 16 ----------------
arch/arm/kernel/time.c | 9 +--------
arch/arm/mach-tegra/board-dt-tegra20.c | 2 +-
arch/arm/mach-tegra/board-dt-tegra30.c | 2 +-
arch/arm/mach-tegra/board.h | 2 +-
arch/arm/mach-tegra/timer.c | 6 +-----
7 files changed, 6 insertions(+), 34 deletions(-)
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 917d4fc..308ad7d 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -12,7 +12,6 @@
struct tag;
struct meminfo;
-struct sys_timer;
struct pt_regs;
struct smp_operations;
#ifdef CONFIG_SMP
@@ -48,7 +47,7 @@ struct machine_desc {
void (*map_io)(void);/* IO mapping function */
void (*init_early)(void);
void (*init_irq)(void);
- struct sys_timer *timer; /* system tick timer */
+ void (*init_time)(void);
void (*init_machine)(void);
void (*init_late)(void);
#ifdef CONFIG_MULTI_IRQ_HANDLER
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index d316d76..90c12e1 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -10,22 +10,6 @@
#ifndef __ASM_ARM_MACH_TIME_H
#define __ASM_ARM_MACH_TIME_H
-/*
- * This is our kernel timer structure.
- *
- * - init
- * Initialise the kernels jiffy timer source, claim interrupt
- * using setup_irq. This is called early on during initialisation
- * while interrupts are still disabled on the local CPU.
- * - offset
- * Return the timer offset in microseconds since the last timer
- * interrupt. Note: this must take account of any unprocessed
- * timer interrupt which may be pending.
- */
-struct sys_timer {
- void (*init)(void);
-};
-
extern void timer_tick(void);
struct timespec;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 0b51a7c..955d92d 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -30,11 +30,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
-/*
- * Our system timer.
- */
-static struct sys_timer *system_timer;
-
#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
/* this needs a better home */
@@ -120,8 +115,6 @@ int __init register_persistent_clock(clock_access_fn read_boot,
void __init time_init(void)
{
- system_timer = machine_desc->timer;
- system_timer->init();
+ machine_desc->init_time();
sched_clock_postinit();
}
-
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
index 22f5a9b..3777b03 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/board-dt-tegra20.c
@@ -192,7 +192,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
.init_early = tegra20_init_early,
.init_irq = tegra_dt_init_irq,
.handle_irq = gic_handle_irq,
- .timer = &tegra_sys_timer,
+ .init_time = tegra_init_timer,
.init_machine = tegra_dt_init,
.init_late = tegra_dt_init_late,
.restart = tegra_assert_system_reset,
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index cd30338..08d3b19 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -104,7 +104,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
.init_early = tegra30_init_early,
.init_irq = tegra_dt_init_irq,
.handle_irq = gic_handle_irq,
- .timer = &tegra_sys_timer,
+ .init_time = tegra_init_timer,
.init_machine = tegra30_dt_init,
.init_late = tegra_init_late,
.restart = tegra_assert_system_reset,
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 91fbe73..744cdd2 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -55,5 +55,5 @@ static inline int harmony_pcie_init(void) { return 0; }
void __init tegra_paz00_wifikill_init(void);
-extern struct sys_timer tegra_sys_timer;
+extern void tegra_init_timer(void);
#endif
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index e4863f3..b0036e5 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -168,7 +168,7 @@ static const struct of_device_id rtc_match[] __initconst = {
{}
};
-static void __init tegra_init_timer(void)
+void __init tegra_init_timer(void)
{
struct device_node *np;
struct clk *clk;
@@ -273,10 +273,6 @@ static void __init tegra_init_timer(void)
register_persistent_clock(NULL, tegra_read_persistent_clock);
}
-struct sys_timer tegra_sys_timer = {
- .init = tegra_init_timer,
-};
-
#ifdef CONFIG_PM
static u32 usec_config;
--
1.7.0.4
^ permalink raw reply related
* [PATCH] ARM: delete struct sys_timer
From: Stephen Warren @ 2012-11-08 21:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-2-git-send-email-swarren@wwwdotorg.org>
On 11/08/2012 02:01 PM, Stephen Warren wrote:
> Now that the only field in struct sys_timer is .init, delete the struct,
> and replace the machine descriptor .timer field with the initialization
> function itself.
Oops. This one patch is a duplicate of 11/11 in the series I just sent.
Sorry.
^ permalink raw reply
* [PATCH 2/4] gpio: samsung: Skip registration if pinctrl driver is present on Exynos4x12
From: Linus Walleij @ 2012-11-08 21:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0c5301cdbca2$30320240$909606c0$%kim@samsung.com>
On Wed, Nov 7, 2012 at 5:41 AM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> A commit 1b6056d6 ("pinctrl: samsung: Include bank-specific eint offset in
> bank struct") which is in your pinctrl tree (samsung branch) changed
> macro(EXYNOS_PIN_BANK_EINTG) to add offset. Eventually, this series(due to
> 3rd patch, pinctrl: samsung: Add support for Exynos4x12) breaks compilation
> without the commit. So if you don't have a plan to rebase samsung branch of
> your pinctrl tree, I'd like to merge it in my tree. Is it ok to you?
Sure tell me when you've merged it and I'll drop commit 1b6056d6
from my tree.
Yours,
Linus Walleij
^ permalink raw reply
* scheduler clock for MXS
From: Stanislav Meduna @ 2012-11-08 21:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121106224624.GR28327@n2100.arm.linux.org.uk>
On 06.11.2012 23:46, Russell King - ARM Linux wrote:
> * round_jiffies - function to round jiffies to a full second
>
> This is probably it. With mine, it's a 32.768kHz clock, so limiting
> it to 16-bit gives a wrap period of 2 seconds exactly. We take 10%
> off, so the timer would be asked to fire every 1.8s, which would be
> rounded up to 2 seconds. That's a little too close for comfort...
Confirmed.
- if I artificially change my timer code to act as a 16-bit one,
I get wrap-arounds. Not always, but there are definitely some
during the bootup (where maybe the tick is sometimes delayed
a tad more)
- if I then remove the round_jiffies and only leave jiffies +
wrap_ticks, the wrap-arounds go away
> I think in this case, we need a version of round_jiffies() which _always_
> rounds down. Unfortunately, it doesn't exist. Thomas? What are the
> options here?
What is actually the reason of round_jiffies there? The
http://kernel.org/doc/htmldocs/device-drivers/API-round-jiffies.html
mentions saving power, is it the only one?
I'd probably just leave the round_jiffies out at least for
wrap_ticks < around 16*HZ. Above that the error by possibly
rounding up can be ignored.
There is also a round_jiffies_up - unless I am too tired, as long as
we tick no faster than once per second, subtracting (HZ-1) and rounding
up should be the same as rounding down.
But: is the round_jiffies* safe at all for sub-second precision
at jiffies around 0xffffffff? From quick looking it does a modulo,
0xffffffff % say 250 is 45, the next jiffy is@0...
Regards
--
Stano
^ permalink raw reply
* [PATCH 14/26] ARM: OMAP3: clock: Add 3xxx data using common struct clk
From: Mike Turquette @ 2012-11-08 21:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1211081800210.20703@utopia.booyaka.com>
Quoting Paul Walmsley (2012-11-08 10:08:16)
> On Wed, 7 Nov 2012, Mike Turquette wrote:
>
> > From: Rajendra Nayak <rnayak@ti.com>
> >
> > The patch is the output from a python script which converts
> > from the old OMAP clk format to COMMON clk format using a
> > JSON parser in between which was developed by Paul Walmsley.
> >
> > Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> > [paul at pwsan.com: AM3517/05: dropped bogus hsotgusb "ick" and "fck"
> > clkdev aliases; added hsotgusb_fck alias; added emac_ick and emac_fck
> > aliases; replace omap2_init_clksel_parent() with
> > omap2_clksel_find_parent_index(); reflow macros and parent name
> > lists; add clkdm_name argument to DEFINE_STRUCT_CLK_HW_OMAP macros]
> > Signed-off-by: Mike Turquette <mturquette@ti.com>
>
> Am seeing warnings during the disable-unused-clocks phase of the boot
> on the OMAP3 test boards here. Log is included at the bottom of this
> E-mail, with some debugging added for extra context. The problem
> appears to be that the clock code is disabling clocks that are active
> in the hardware, but for which the clockdomain use count is 0, since
> they've never been enabled.
>
Right. The old omap2_disabled_unused_clocks code used to call
omap2_clk_enable before calling omap2_clk_disable. That approach is
sort of "cooking the books" and the generic implementation in
drivers/clk/clk.c simply disables the clocks (without first enabling),
which is why these WARNs are new.
> Ideally there would be some way for the core CCF code to indicate to the
> underlying clock hardware implementation that the disable-unused-clock
> process is a 'force disable'. The OMAP clock hardware implementation code
> could then also put the clockdomain to sleep (and skip the warning) in
> such a circumstance.
>
I'm looking at a few different ways to do that now.
Regards,
Mike
>
> - Paul
>
> [ 2.685943] disabling sys_clkout1: ec = 0
> [ 2.690277] disabling wdt1_ick: ec = 0
> [ 2.694366] disabling cam_mclk: ec = 0
> [ 2.698333] ------------[ cut here ]------------
> [ 2.703216] WARNING: at arch/arm/mach-omap2/clockdomain.c:961 _clkdm_clk_hwmod_disable+0xc4/0xd8()
> [ 2.712646] Modules linked in:
> [ 2.715911] [<c001c38c>] (unwind_backtrace+0x0/0xf0) from [<c0043cd8>] (warn_slowpath_common+0x4c/0x64)
> [ 2.725799] [<c0043cd8>] (warn_slowpath_common+0x4c/0x64) from [<c0043d0c>] (warn_slowpath_null+0x1c/0x24)
> [ 2.735961] [<c0043d0c>] (warn_slowpath_null+0x1c/0x24) from [<c003705c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8)
> [ 2.746520] [<c003705c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8) from [<c0437bd0>] (clk_disable_unused_subtree+0xb0/0xbc)
> [ 2.757781] [<c0437bd0>] (clk_disable_unused_subtree+0xb0/0xbc) from [<c0437b40>] (clk_disable_unused_subtree+0x20/0xbc)
> [ 2.769226] ---[ end trace ebefd5468131571a ]---
> [ 2.774261] disabling mspro_fck: ec = 0
> [ 2.778320] disabling ssi_ssr_fck_3430es2: ec = 0
> [ 2.783355] disabling pka_ick: ec = 0
> [ 2.787231] disabling sad2d_ick: ec = 0
> [ 2.791259] ------------[ cut here ]------------
> [ 2.796142] WARNING: at arch/arm/mach-omap2/clockdomain.c:961 _clkdm_clk_hwmod_disable+0xc4/0xd8()
> [ 2.805572] Modules linked in:
> [ 2.808807] [<c001c38c>] (unwind_backtrace+0x0/0xf0) from [<c0043cd8>] (warn_slowpath_common+0x4c/0x64)
> [ 2.818695] [<c0043cd8>] (warn_slowpath_common+0x4c/0x64) from [<c0043d0c>] (warn_slowpath_null+0x1c/0x24)
> [ 2.828857] [<c0043d0c>] (warn_slowpath_null+0x1c/0x24) from [<c003705c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8)
> [ 2.839416] [<c003705c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8) from [<c0437bd0>] (clk_disable_unused_subtree+0xb0/0xbc)
> [ 2.850677] [<c0437bd0>] (clk_disable_unused_subtree+0xb0/0xbc) from [<c0437b40>] (clk_disable_unused_subtree+0x20/0xbc)
> [ 2.862121] ---[ end trace ebefd5468131571b ]---
> [ 2.867065] disabling wdt3_ick: ec = 0
> [ 2.871032] disabling des1_ick: ec = 0
> [ 2.875030] disabling sha11_ick: ec = 0
> [ 2.879089] disabling rng_ick: ec = 0
> [ 2.882995] disabling aes1_ick: ec = 0
> [ 2.886932] disabling ssi_ick_3430es2: ec = 0
> [ 2.891601] disabling mspro_ick: ec = 0
> [ 2.895660] disabling des2_ick: ec = 0
> [ 2.899658] disabling sha12_ick: ec = 0
> [ 2.903686] disabling aes2_ick: ec = 0
> [ 2.907684] disabling icr_ick: ec = 0
> [ 2.911621] disabling wdt3_fck: ec = 0
^ permalink raw reply
* [PATCH 14/26] ARM: OMAP3: clock: Add 3xxx data using common struct clk
From: Paul Walmsley @ 2012-11-08 22:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1211081800210.20703@utopia.booyaka.com>
On Thu, 8 Nov 2012, Paul Walmsley wrote:
> Am seeing warnings during the disable-unused-clocks phase of the boot on
> the OMAP3 test boards here.
Similar problems during system suspend on 3530ES3 Beagle. Not sure
what's causing these yet. At this point the clockdomain usecounts
should be accurate.
- Paul
root at beagleboard:~# echo mem > /sys/power/state
[ 36.488800] PM: Syncing filesystems ... done.
[ 37.037841] Freezing user space processes ... (elapsed 0.01 seconds) done.
[ 37.059600] Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.
[ 37.082885] Suspending console(s) (use no_console_suspend to debug)
[ 37.222747] PM: suspend of devices complete after 129.791 msecs
[ 37.228057] PM: late suspend of devices complete after 5.310 msecs
[ 37.235412] ------------[ cut here ]------------
[ 37.235473] WARNING: at arch/arm/mach-omap2/clockdomain.c:961 _clkdm_clk_hwmod_disable+0xc4/0xd8()
[ 37.235504] Modules linked in:
[ 37.235565] [<c001c1cc>] (unwind_backtrace+0x0/0xf0) from [<c00435f8>] (warn_slowpath_common+0x4c/0x64)
[ 37.235565] [<c00435f8>] (warn_slowpath_common+0x4c/0x64) from [<c004362c>] (warn_slowpath_null+0x1c/0x24)
[ 37.235595] [<c004362c>] (warn_slowpath_null+0x1c/0x24) from [<c003697c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8)
[ 37.235626] [<c003697c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8) from [<c0437d1c>] (__clk_disable+0x70/0xa8)
[ 37.235656] [<c0437d1c>] (__clk_disable+0x70/0xa8) from [<c0437d74>] (clk_disable+0x20/0x34)
[ 37.235687] [<c0437d74>] (clk_disable+0x20/0x34) from [<c002a330>] (_disable_clocks+0x18/0x68)
[ 37.235717] [<c002a330>] (_disable_clocks+0x18/0x68) from [<c002b09c>] (_idle+0xf8/0x1b4)
[ 37.235717] [<c002b09c>] (_idle+0xf8/0x1b4) from [<c002bf08>] (omap_hwmod_idle+0x24/0x40)
[ 37.235748] [<c002bf08>] (omap_hwmod_idle+0x24/0x40) from [<c002ce34>] (omap_device_idle_hwmods+0x24/0x3c)
[ 37.235778] [<c002ce34>] (omap_device_idle_hwmods+0x24/0x3c) from [<c002d024>] (_omap_device_deactivate+0x9c/0x138)
[ 37.235778] [<c002d024>] (_omap_device_deactivate+0x9c/0x138) from [<c002d984>] (omap_device_idle+0x28/0x54)
[ 37.235809] [<c002d984>] (omap_device_idle+0x28/0x54) from [<c002da48>] (_od_suspend_noirq+0x74/0x7c)
[ 37.235839] [<c002da48>] (_od_suspend_noirq+0x74/0x7c) from [<c034cbec>] (dpm_run_callback.clone.9+0x30/0xb4)
[ 37.235870] [<c034cbec>] (dpm_run_callback.clone.9+0x30/0xb4) from [<c034d440>] (dpm_suspend_end+0x364/0x554)
[ 37.235870] [<c034d440>] (dpm_suspend_end+0x364/0x554) from [<c0084ec0>] (suspend_devices_and_enter+0xbc/0x2d0)
[ 37.235900] [<c0084ec0>] (suspend_devices_and_enter+0xbc/0x2d0) from [<c0085260>] (pm_suspend+0x18c/0x208)
[ 37.235931] [<c0085260>] (pm_suspend+0x18c/0x208) from [<c00844f4>] (state_store+0x120/0x134)
[ 37.235961] [<c00844f4>] (state_store+0x120/0x134) from [<c02d29b8>] (kobj_attr_store+0x14/0x20)
[ 37.235992] [<c02d29b8>] (kobj_attr_store+0x14/0x20) from [<c017a630>] (sysfs_write_file+0x100/0x184)
[ 37.236022] [<c017a630>] (sysfs_write_file+0x100/0x184) from [<c0116630>] (vfs_write+0xb4/0x148)
[ 37.236022] [<c0116630>] (vfs_write+0xb4/0x148) from [<c01168b4>] (sys_write+0x40/0x6c)
[ 37.236053] [<c01168b4>] (sys_write+0x40/0x6c) from [<c0013ee0>] (ret_fast_syscall+0x0/0x3c)
[ 37.236083] ---[ end trace 86835b3ee8ec9dde ]---
[ 37.236083] ------------[ cut here ]------------
[ 37.236114] WARNING: at arch/arm/mach-omap2/clockdomain.c:961 _clkdm_clk_hwmod_disable+0xc4/0xd8()
[ 37.236145] Modules linked in:
[ 37.236175] [<c001c1cc>] (unwind_backtrace+0x0/0xf0) from [<c00435f8>] (warn_slowpath_common+0x4c/0x64)
[ 37.236175] [<c00435f8>] (warn_slowpath_common+0x4c/0x64) from [<c004362c>] (warn_slowpath_null+0x1c/0x24)
[ 37.236206] [<c004362c>] (warn_slowpath_null+0x1c/0x24) from [<c003697c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8)
[ 37.236236] [<c003697c>] (_clkdm_clk_hwmod_disable+0xc4/0xd8) from [<c0437d1c>] (__clk_disable+0x70/0xa8)
[ 37.236267] [<c0437d1c>] (__clk_disable+0x70/0xa8) from [<c0437d74>] (clk_disable+0x20/0x34)
[ 37.236267] [<c0437d74>] (clk_disable+0x20/0x34) from [<c002a330>] (_disable_clocks+0x18/0x68)
[ 37.236297] [<c002a330>] (_disable_clocks+0x18/0x68) from [<c002b09c>] (_idle+0xf8/0x1b4)
[ 37.236328] [<c002b09c>] (_idle+0xf8/0x1b4) from [<c002bf08>] (omap_hwmod_idle+0x24/0x40)
[ 37.236328] [<c002bf08>] (omap_hwmod_idle+0x24/0x40) from [<c002ce34>] (omap_device_idle_hwmods+0x24/0x3c)
[ 37.236358] [<c002ce34>] (omap_device_idle_hwmods+0x24/0x3c) from [<c002d024>] (_omap_device_deactivate+0x9c/0x138)
[ 37.236389] [<c002d024>] (_omap_device_deactivate+0x9c/0x138) from [<c002d984>] (omap_device_idle+0x28/0x54)
[ 37.236389] [<c002d984>] (omap_device_idle+0x28/0x54) from [<c002da48>] (_od_suspend_noirq+0x74/0x7c)
[ 37.236419] [<c002da48>] (_od_suspend_noirq+0x74/0x7c) from [<c034cbec>] (dpm_run_callback.clone.9+0x30/0xb4)
[ 37.236450] [<c034cbec>] (dpm_run_callback.clone.9+0x30/0xb4) from [<c034d440>] (dpm_suspend_end+0x364/0x554)
[ 37.236450] [<c034d440>] (dpm_suspend_end+0x364/0x554) from [<c0084ec0>] (suspend_devices_and_enter+0xbc/0x2d0)
[ 37.236480] [<c0084ec0>] (suspend_devices_and_enter+0xbc/0x2d0) from [<c0085260>] (pm_suspend+0x18c/0x208)
[ 37.236511] [<c0085260>] (pm_suspend+0x18c/0x208) from [<c00844f4>] (state_store+0x120/0x134)
[ 37.236541] [<c00844f4>] (state_store+0x120/0x134) from [<c02d29b8>] (kobj_attr_store+0x14/0x20)
[ 37.236541] [<c02d29b8>] (kobj_attr_store+0x14/0x20) from [<c017a630>] (sysfs_write_file+0x100/0x184)
[ 37.236572] [<c017a630>] (sysfs_write_file+0x100/0x184) from [<c0116630>] (vfs_write+0xb4/0x148)
[ 37.236602] [<c0116630>] (vfs_write+0xb4/0x148) from [<c01168b4>] (sys_write+0x40/0x6c)
[ 37.236602] [<c01168b4>] (sys_write+0x40/0x6c) from [<c0013ee0>] (ret_fast_syscall+0x0/0x3c)
[ 37.236633] ---[ end trace 86835b3ee8ec9ddf ]---
[ 37.237213] PM: noirq suspend of devices complete after 9.124 msecs
[ 37.237304] Disabling non-boot CPUs ...
[ 37.237792] Successfully put all powerdomains to target state
[ 37.242034] PM: noirq resume of devices complete after 3.967 msecs
[ 37.247161] PM: early resume of devices complete after 3.570 msecs
[ 37.536956] PM: resume of devices complete after 289.550 msecs
[ 37.815185] Restarting tasks ... done.
root at beagleboard:~#
^ permalink raw reply
* scheduler clock for MXS
From: Russell King - ARM Linux @ 2012-11-08 22:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <509C23DF.1020106@meduna.org>
On Thu, Nov 08, 2012 at 10:27:59PM +0100, Stanislav Meduna wrote:
> What is actually the reason of round_jiffies there? The
> http://kernel.org/doc/htmldocs/device-drivers/API-round-jiffies.html
> mentions saving power, is it the only one?
>
> I'd probably just leave the round_jiffies out at least for
> wrap_ticks < around 16*HZ. Above that the error by possibly
> rounding up can be ignored.
>
> There is also a round_jiffies_up - unless I am too tired, as long as
> we tick no faster than once per second, subtracting (HZ-1) and rounding
> up should be the same as rounding down.
>
> But: is the round_jiffies* safe at all for sub-second precision
> at jiffies around 0xffffffff? From quick looking it does a modulo,
> 0xffffffff % say 250 is 45, the next jiffy is at 0...
Well, the idea is to avoid having yet another random thing causing yet
another wakeup from the idle modes. If you've ever watched a LED
indicating when the kernel is in the idle loop and when it isn't,
you'll know exactly what I'm talking about; your normal Linux system
sits there constantly being kicked out of idle several times a second
while... idle to service various kernel tasks.
We really don't want to add to that; if we get enough of these events
happening at random intervals, we will end up with things like cpu idle
being completely thwarted by stuff like this.
As I have said, what we want is a version of round_jiffies() which
rounds down to something, not up.
^ permalink raw reply
* [PATCH 08/13] ARM: OMAP2+: CM/clock: convert _omap2_module_wait_ready() to use SoC-independent CM functions
From: Paul Walmsley @ 2012-11-08 22:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121025232117.17558.83100.stgit@dusk.lan>
On Thu, 25 Oct 2012, Paul Walmsley wrote:
> Convert the OMAP clock code's _omap2_module_wait_ready() to use
> SoC-independent CM functions that are provided by the CM code, rather
> than using a deprecated function from mach-omap2/prcm.c.
>
> This facilitates the future conversion of the CM code to a driver, and
> also removes a mach-omap2/prcm.c user. mach-omap2/prcm.c will be removed
> by a subsequent patch.
>
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
Here's an update of this one. Further testing with the AM3517/3505 boards
resulted in a warning message being logged from _omap2_wait_module_ready()
for emac_ick. The AM3517 designers didn't integrate the IPSS IDLEST bits
into the CM as other OMAPs do. They just put them into the SCM module.
This shortcut taken during hardware integration just resulted in more time
wasted on the software side :-(
- Paul
From: Paul Walmsley <paul@pwsan.com>
Date: Mon, 29 Oct 2012 20:56:29 -0600
Subject: [PATCH] ARM: OMAP2+: CM/clock: convert _omap2_module_wait_ready() to
use SoC-independent CM functions
Convert the OMAP clock code's _omap2_module_wait_ready() to use
SoC-independent CM functions that are provided by the CM code, rather
than using a deprecated function from mach-omap2/prcm.c.
This facilitates the future conversion of the CM code to a driver, and
also removes a mach-omap2/prcm.c user. mach-omap2/prcm.c will be removed
by a subsequent patch.
Some modules have IDLEST registers that aren't in the CM module, such
as the AM3517 IDLEST bits. So we also need a fallback function for
these non-CM odd cases. Create a temporary one in mach-omap2/clock.c,
intended to exist until the SCM drivers are ready.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Tested-by: Vaibhav Hiremath <hvaibhav@ti.com>
---
arch/arm/mach-omap2/clock.c | 56 +++++++++++++++++++++++++++++++--
arch/arm/mach-omap2/cm.h | 12 ++++++-
arch/arm/mach-omap2/cm2xxx.c | 65 ++++++++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/cm2xxx.h | 4 +++
arch/arm/mach-omap2/cm3xxx.c | 66 +++++++++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/cm3xxx.h | 5 +++
arch/arm/mach-omap2/cm_common.c | 48 ++++++++++++++++++++++++++++
arch/arm/mach-omap2/io.c | 5 +++
8 files changed, 257 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 9205ea7..2fe57d6 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -33,10 +33,18 @@
#include "soc.h"
#include "clockdomain.h"
#include "clock.h"
+#include "cm.h"
#include "cm2xxx.h"
#include "cm3xxx.h"
#include "cm-regbits-24xx.h"
#include "cm-regbits-34xx.h"
+#include "common.h"
+
+/*
+ * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
+ * for a module to indicate that it is no longer in idle
+ */
+#define MAX_MODULE_ENABLE_WAIT 100000
u16 cpu_mask;
@@ -58,6 +66,40 @@ static DEFINE_SPINLOCK(clockfw_lock);
/* Private functions */
+
+/**
+ * _wait_idlest_generic - wait for a module to leave the idle state
+ * @reg: virtual address of module IDLEST register
+ * @mask: value to mask against to determine if the module is active
+ * @idlest: idle state indicator (0 or 1) for the clock
+ * @name: name of the clock (for printk)
+ *
+ * Wait for a module to leave idle, where its idle-status register is
+ * not inside the CM module. Returns 1 if the module left idle
+ * promptly, or 0 if the module did not leave idle before the timeout
+ * elapsed. XXX Deprecated - should be moved into drivers for the
+ * individual IP block that the IDLEST register exists in.
+ */
+static int _wait_idlest_generic(void __iomem *reg, u32 mask, u8 idlest,
+ const char *name)
+{
+ int i = 0, ena = 0;
+
+ ena = (idlest) ? 0 : mask;
+
+ omap_test_timeout(((__raw_readl(reg) & mask) == ena),
+ MAX_MODULE_ENABLE_WAIT, i);
+
+ if (i < MAX_MODULE_ENABLE_WAIT)
+ pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
+ name, i);
+ else
+ pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
+ name, MAX_MODULE_ENABLE_WAIT);
+
+ return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
+};
+
/**
* _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
* @clk: struct clk * belonging to the module
@@ -71,7 +113,9 @@ static DEFINE_SPINLOCK(clockfw_lock);
static void _omap2_module_wait_ready(struct clk *clk)
{
void __iomem *companion_reg, *idlest_reg;
- u8 other_bit, idlest_bit, idlest_val;
+ u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
+ s16 prcm_mod;
+ int r;
/* Not all modules have multiple clocks that their IDLEST depends on */
if (clk->ops->find_companion) {
@@ -82,8 +126,14 @@ static void _omap2_module_wait_ready(struct clk *clk)
clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
- omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), idlest_val,
- __clk_get_name(clk));
+ r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
+ if (r) {
+ /* IDLEST register not in the CM module */
+ _wait_idlest_generic(idlest_reg, (1 << idlest_bit), idlest_val,
+ clk->name);
+ } else {
+ cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
+ };
}
/* Public functions */
diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
index b3cee91..e419ecb 100644
--- a/arch/arm/mach-omap2/cm.h
+++ b/arch/arm/mach-omap2/cm.h
@@ -37,8 +37,18 @@
/**
* struct cm_ll_data - fn ptrs to per-SoC CM function implementations
+ * @split_idlest_reg: ptr to the SoC CM-specific split_idlest_reg impl
+ * @wait_module_ready: ptr to the SoC CM-specific wait_module_ready impl
*/
-struct cm_ll_data {};
+struct cm_ll_data {
+ int (*split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
+ u8 *idlest_reg_id);
+ int (*wait_module_ready)(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
+};
+
+extern int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+ u8 *idlest_reg_id);
+extern int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
extern int cm_register(struct cm_ll_data *cld);
extern int cm_unregister(struct cm_ll_data *cld);
diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c
index e96cd70..db65069 100644
--- a/arch/arm/mach-omap2/cm2xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx.c
@@ -198,6 +198,43 @@ void omap2xxx_cm_apll96_disable(void)
_omap2xxx_apll_disable(OMAP24XX_EN_96M_PLL_SHIFT);
}
+/**
+ * omap2xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
+ * @idlest_reg: CM_IDLEST* virtual address
+ * @prcm_inst: pointer to an s16 to return the PRCM instance offset
+ * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
+ *
+ * XXX This function is only needed until absolute register addresses are
+ * removed from the OMAP struct clk records.
+ */
+int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+ u8 *idlest_reg_id)
+{
+ unsigned long offs;
+ u8 idlest_offs;
+ int i;
+
+ if (idlest_reg < cm_base || idlest_reg > (cm_base + 0x0fff))
+ return -EINVAL;
+
+ idlest_offs = (unsigned long)idlest_reg & 0xff;
+ for (i = 0; i < ARRAY_SIZE(omap2xxx_cm_idlest_offs); i++) {
+ if (idlest_offs == omap2xxx_cm_idlest_offs[i]) {
+ *idlest_reg_id = i + 1;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(omap2xxx_cm_idlest_offs))
+ return -EINVAL;
+
+ offs = idlest_reg - cm_base;
+ offs &= 0xff00;
+ *prcm_inst = offs;
+
+ return 0;
+}
+
/*
*
*/
@@ -314,3 +351,31 @@ struct clkdm_ops omap2_clkdm_operations = {
.clkdm_clk_enable = omap2xxx_clkdm_clk_enable,
.clkdm_clk_disable = omap2xxx_clkdm_clk_disable,
};
+
+/*
+ *
+ */
+
+static struct cm_ll_data omap2xxx_cm_ll_data = {
+ .split_idlest_reg = &omap2xxx_cm_split_idlest_reg,
+ .wait_module_ready = &omap2xxx_cm_wait_module_ready,
+};
+
+int __init omap2xxx_cm_init(void)
+{
+ if (!cpu_is_omap24xx())
+ return 0;
+
+ return cm_register(&omap2xxx_cm_ll_data);
+}
+
+static void __exit omap2xxx_cm_exit(void)
+{
+ if (!cpu_is_omap24xx())
+ return;
+
+ /* Should never happen */
+ WARN(cm_unregister(&omap2xxx_cm_ll_data),
+ "%s: cm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap2xxx_cm_exit);
diff --git a/arch/arm/mach-omap2/cm2xxx.h b/arch/arm/mach-omap2/cm2xxx.h
index bce3c4b..4cbb39b 100644
--- a/arch/arm/mach-omap2/cm2xxx.h
+++ b/arch/arm/mach-omap2/cm2xxx.h
@@ -60,6 +60,10 @@ extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
extern bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
extern int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
u8 idlest_shift);
+extern int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+ s16 *prcm_inst, u8 *idlest_reg_id);
+
+extern int __init omap2xxx_cm_init(void);
#endif
diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c
index 8b03ec2..c2086f2 100644
--- a/arch/arm/mach-omap2/cm3xxx.c
+++ b/arch/arm/mach-omap2/cm3xxx.c
@@ -110,6 +110,44 @@ int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
}
+/**
+ * omap3xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
+ * @idlest_reg: CM_IDLEST* virtual address
+ * @prcm_inst: pointer to an s16 to return the PRCM instance offset
+ * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
+ *
+ * XXX This function is only needed until absolute register addresses are
+ * removed from the OMAP struct clk records.
+ */
+int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+ u8 *idlest_reg_id)
+{
+ unsigned long offs;
+ u8 idlest_offs;
+ int i;
+
+ if (idlest_reg < (cm_base + OMAP3430_IVA2_MOD) ||
+ idlest_reg > (cm_base + 0x1ffff))
+ return -EINVAL;
+
+ idlest_offs = (unsigned long)idlest_reg & 0xff;
+ for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
+ if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
+ *idlest_reg_id = i + 1;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
+ return -EINVAL;
+
+ offs = idlest_reg - cm_base;
+ offs &= 0xff00;
+ *prcm_inst = offs;
+
+ return 0;
+}
+
/* Clockdomain low-level operations */
static int omap3xxx_clkdm_add_sleepdep(struct clockdomain *clkdm1,
@@ -597,3 +635,31 @@ void omap3_cm_restore_context(void)
omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
OMAP3_CM_CLKOUT_CTRL_OFFSET);
}
+
+/*
+ *
+ */
+
+static struct cm_ll_data omap3xxx_cm_ll_data = {
+ .split_idlest_reg = &omap3xxx_cm_split_idlest_reg,
+ .wait_module_ready = &omap3xxx_cm_wait_module_ready,
+};
+
+int __init omap3xxx_cm_init(void)
+{
+ if (!cpu_is_omap34xx())
+ return 0;
+
+ return cm_register(&omap3xxx_cm_ll_data);
+}
+
+static void __exit omap3xxx_cm_exit(void)
+{
+ if (!cpu_is_omap34xx())
+ return;
+
+ /* Should never happen */
+ WARN(cm_unregister(&omap3xxx_cm_ll_data),
+ "%s: cm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap3xxx_cm_exit);
diff --git a/arch/arm/mach-omap2/cm3xxx.h b/arch/arm/mach-omap2/cm3xxx.h
index 4a6ac81..e8e146f 100644
--- a/arch/arm/mach-omap2/cm3xxx.h
+++ b/arch/arm/mach-omap2/cm3xxx.h
@@ -78,9 +78,14 @@ extern bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
extern int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
u8 idlest_shift);
+extern int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+ s16 *prcm_inst, u8 *idlest_reg_id);
+
extern void omap3_cm_save_context(void);
extern void omap3_cm_restore_context(void);
+extern int __init omap3xxx_cm_init(void);
+
#endif
#endif
diff --git a/arch/arm/mach-omap2/cm_common.c b/arch/arm/mach-omap2/cm_common.c
index 3246cef..561969b 100644
--- a/arch/arm/mach-omap2/cm_common.c
+++ b/arch/arm/mach-omap2/cm_common.c
@@ -26,6 +26,54 @@ static struct cm_ll_data null_cm_ll_data;
static struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
/**
+ * cm_split_idlest_reg - split CM_IDLEST reg addr into its components
+ * @idlest_reg: CM_IDLEST* virtual address
+ * @prcm_inst: pointer to an s16 to return the PRCM instance offset
+ * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
+ *
+ * Given an absolute CM_IDLEST register address @idlest_reg, passes
+ * the PRCM instance offset and IDLEST register ID back to the caller
+ * via the @prcm_inst and @idlest_reg_id. Returns -EINVAL upon error,
+ * or 0 upon success. XXX This function is only needed until absolute
+ * register addresses are removed from the OMAP struct clk records.
+ */
+int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+ u8 *idlest_reg_id)
+{
+ if (!cm_ll_data->split_idlest_reg) {
+ WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return cm_ll_data->split_idlest_reg(idlest_reg, prcm_inst,
+ idlest_reg_id);
+}
+
+/**
+ * cm_wait_module_ready - wait for a module to leave idle or standby
+ * @prcm_mod: PRCM module offset
+ * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
+ * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
+ *
+ * Wait for the PRCM to indicate that the module identified by
+ * (@prcm_mod, @idlest_id, @idlest_shift) is clocked. Return 0 upon
+ * success, -EBUSY if the module doesn't enable in time, or -EINVAL if
+ * no per-SoC wait_module_ready() function pointer has been registered
+ * or if the idlest register is unknown on the SoC.
+ */
+int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+{
+ if (!cm_ll_data->wait_module_ready) {
+ WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return cm_ll_data->wait_module_ready(prcm_mod, idlest_id, idlest_shift);
+}
+
+/**
* cm_register - register per-SoC low-level data with the CM
* @cld: low-level per-SoC OMAP CM data & function pointers to register
*
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index a204b70..772dc7e 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -45,6 +45,8 @@
#include "sdrc.h"
#include "control.h"
#include "serial.h"
+#include "cm2xxx.h"
+#include "cm3xxx.h"
/*
* The machine specific code may provide the extra mapping besides the
@@ -388,6 +390,7 @@ void __init omap2420_init_early(void)
OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE),
NULL, NULL);
omap2xxx_check_revision();
+ omap2xxx_cm_init();
omap_common_init_early();
omap2xxx_voltagedomains_init();
omap242x_powerdomains_init();
@@ -417,6 +420,7 @@ void __init omap2430_init_early(void)
OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE),
NULL, NULL);
omap2xxx_check_revision();
+ omap2xxx_cm_init();
omap_common_init_early();
omap2xxx_voltagedomains_init();
omap243x_powerdomains_init();
@@ -451,6 +455,7 @@ void __init omap3_init_early(void)
NULL, NULL);
omap3xxx_check_revision();
omap3xxx_check_features();
+ omap3xxx_cm_init();
omap_common_init_early();
omap3xxx_voltagedomains_init();
omap3xxx_powerdomains_init();
--
1.7.10.4
^ permalink raw reply related
* [RFC] arm: memtest
From: Matthieu Castet @ 2012-11-08 22:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <509C1A92.9080407@ahsoftware.de>
Note memtester is also a great userspace tool for testing memory :
http://pyropus.ca/software/memtester/
It works fine on arm and other arch (but work on malloc or /dev/mem memory)
^ permalink raw reply
* [RFC] arm: memtest
From: Yinghai Lu @ 2012-11-08 22:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <509C1A92.9080407@ahsoftware.de>
On Thu, Nov 8, 2012 at 12:48 PM, Alexander Holler <holler@ahsoftware.de> wrote:
> Hello,
>
> I've recently discovered the lack of the command line parameter memtest for
> ARM. So I've made a patch.
>
> But I have some questions:
>
> 1. arch/x86/mm/memtest.c looks platform independ.
> The only thing why I don't use it for arm, is because it uses 64bit
> pointers. Maybe it could be moved to mm/memtest.c. If so, the memtest32.c
> I'm using (basically a copy of memtest.c) could be moved there too.
>
> 2. Because the below memtest32.c is basically a copy of
> arch/x86/mm/memtest.c, I'm not sure if the mapping from physical to virtual
> locations there does fit (always) for ARM too. I know almost as much about
> the in-kernel memory organization on x86 as on ARM, which is not really that
> much (some theory about TLBs, some source code explorations, ..., but I'm
> working on it). ;)
We are using arch/x86/mm/memtest.c for x86 32bit and 64bit.
So it should be ok to use it with arm 32bit and 64bit directly.
Yinghai
^ permalink raw reply
* [PATCH] ARM: mxs: Setup scheduler clock
From: Stanislav Meduna @ 2012-11-08 22:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121106134630.GD27643@S2100-06.ap.freescale.net>
Hi,
OK, as the problem with 16-bit fast ticking timer looks to
be more complicated, I'd like to submit the patch for the 32-bit
ones.
Thanks
--
Stano
-------------- next part --------------
>From 74092cc0217a5bab6f80ee07aa188a54f5792634 Mon Sep 17 00:00:00 2001
From: Stanislav Meduna <stano@meduna.org>
Date: Mon, 8 Nov 2012 23:39:14 +0100
Subject: [PATCH] ARM: mxs: Setup scheduler clock
Setup scheduler clock on ARM MXS platforms with a 32-bit timrot
such as MX.28. This allows the scheduler to use sub-jiffy resolution.
The corresponding change for 16-bit v1 timrots is not possible
at the moment due to rounding issues with clock values wrapping
faster than once per several seconds in the common ARM platform code.
Signed-off-by: Stanislav Meduna <stano@meduna.org>
---
arch/arm/mach-mxs/timer.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
index 564a632..4b6e36c 100644
--- a/arch/arm/mach-mxs/timer.c
+++ b/arch/arm/mach-mxs/timer.c
@@ -26,6 +26,7 @@
#include <linux/clk.h>
#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
#include <mach/mxs.h>
#include <mach/common.h>
@@ -230,15 +231,22 @@ static struct clocksource clocksource_mxs = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
+static u32 notrace mxs_read_sched_clock_v2(void)
+{
+ return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
+}
+
static int __init mxs_clocksource_init(struct clk *timer_clk)
{
unsigned int c = clk_get_rate(timer_clk);
if (timrot_is_v1())
clocksource_register_hz(&clocksource_mxs, c);
- else
+ else {
clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1),
"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
+ setup_sched_clock(mxs_read_sched_clock_v2, 32, c);
+ }
return 0;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH v4 3/9] pinctrl: single: support pinconf generic
From: Tony Lindgren @ 2012-11-08 22:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352301582-12244-4-git-send-email-haojian.zhuang@gmail.com>
Hi,
Noticed few more things while playing with this.
* Haojian Zhuang <haojian.zhuang@gmail.com> [121107 07:21]:
> --- a/drivers/pinctrl/pinctrl-single.c
> +++ b/drivers/pinctrl/pinctrl-single.c
> static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
> unsigned pin, unsigned long *config)
> {
> + struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
> + enum pin_config_param param = pinconf_to_config_param(*config);
> + unsigned data;
> + u32 offset;
I suggest adding:
int res = -ENOTSUPP;
> +
> + offset = pin * (pcs->width / BITS_PER_BYTE);
> + data = pcs->read(pcs->base + offset);
> +
> + switch (param) {
> + case PIN_CONFIG_POWER_SOURCE:
> + if (pcs->psmask == PCS_OFF_DISABLED
> + || pcs->psshift == PCS_OFF_DISABLED)
> + return -ENOTSUPP;
> + data &= pcs->psmask;
> + data = data >> pcs->psshift;
> + *config = data;
> + return 0;
> + break;
then you can do:
res = 0;
break;
instead of the return 0 and break.
> + case PIN_CONFIG_BIAS_DISABLE:
> + if (pcs->bmask == PCS_OFF_DISABLED
> + || pcs->bshift == PCS_OFF_DISABLED
> + || pcs->bdis == PCS_OFF_DISABLED)
> + return -ENOTSUPP;
> + data &= pcs->bmask;
> + *config = 0;
> + if (data == pcs->bdis)
> + return 0;
> + else
> + return -EINVAL;
> + break;
> + case PIN_CONFIG_BIAS_PULL_UP:
> + if (pcs->bmask == PCS_OFF_DISABLED
> + || pcs->bshift == PCS_OFF_DISABLED
> + || pcs->bpullup == PCS_OFF_DISABLED)
> + return -ENOTSUPP;
> + data &= pcs->bmask;
> + *config = 0;
> + if (data == pcs->bpullup)
> + return 0;
> + else
> + return -EINVAL;
> + break;
> + case PIN_CONFIG_BIAS_PULL_DOWN:
> + if (pcs->bmask == PCS_OFF_DISABLED
> + || pcs->bshift == PCS_OFF_DISABLED
> + || pcs->bpulldown == PCS_OFF_DISABLED)
> + return -ENOTSUPP;
> + data &= pcs->bmask;
> + *config = 0;
> + if (data == pcs->bpulldown)
> + return 0;
> + else
> + return -EINVAL;
> + break;
> + default:
> + break;
> + }
> return -ENOTSUPP;
return res;
> }
Did you forget to add the input schmitt handling to pcs_pinconf_get()
above?
> static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
> unsigned pin, unsigned long config)
> {
> - return -ENOTSUPP;
> + struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
> + enum pin_config_param config_param = pinconf_to_config_param(config);
> + unsigned ret, mask = ~0UL;
> + u32 offset, data;
> +
> + switch (config_param) {
> + case PIN_CONFIG_POWER_SOURCE:
> + if (pcs->psmask == PCS_OFF_DISABLED
> + || pcs->psshift == PCS_OFF_DISABLED)
> + return 0;
> + mask = pcs->psmask;
> + data = (pinconf_to_config_argument(config) << pcs->psshift)
> + & pcs->psmask;
> + break;
> + case PIN_CONFIG_BIAS_DISABLE:
> + if (pcs->bmask == PCS_OFF_DISABLED
> + || pcs->bshift == PCS_OFF_DISABLED)
> + return 0;
> + mask = pcs->bmask;
> + data = (pinconf_to_config_argument(config) << pcs->bshift)
> + & pcs->bmask;
> + break;
> + default:
> + return 0;
Here we should probably return -ENOTSUPP instead for the unhandled
ones?
> + }
> + offset = pin * (pcs->width / BITS_PER_BYTE);
> + ret = pcs->read(pcs->base + offset) & ~mask;
> + pcs->write(ret | data, pcs->base + offset);
> + return 0;
> }
Then looks like pcs_pinconf_set() is also missing handling for few
of the things configured in the probe?
Regards,
Tony
^ permalink raw reply
* [PATCH 04/11] ARM: set arch_gettimeoffset directly
From: Ryan Mallon @ 2012-11-08 23:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352408516-21988-6-git-send-email-swarren@wwwdotorg.org>
On 09/11/12 08:01, Stephen Warren wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> remove ARM's struct sys_timer .offset function pointer, and instead
> directly set the arch_gettimeoffset function pointer when the timer
> driver is initialized. This requires multiplying all function results
> by 1000, since the removed arm_gettimeoffset() did this. Also,
> s/unsigned long/u32/ just to make the function prototypes exactly
> match that of arch_gettimeoffset.
>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Andrew Victor <linux@maxim.org.za>
> Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
> Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
> Cc: Hartley Sweeten <hsweeten@visionengravers.com>
> Cc: Ryan Mallon <rmallon@gmail.com>
> Cc: Ben Dooks <ben-linux@fluff.org>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> arch/arm/include/asm/mach/time.h | 3 ---
> arch/arm/kernel/time.c | 14 --------------
> arch/arm/mach-at91/at91x40_time.c | 8 +++++---
> arch/arm/mach-ebsa110/core.c | 7 ++++---
> arch/arm/mach-ep93xx/core.c | 23 ++++++++++++-----------
> arch/arm/mach-h720x/common.c | 6 +++---
> arch/arm/mach-h720x/common.h | 2 +-
> arch/arm/mach-h720x/cpu-h7201.c | 3 ++-
> arch/arm/mach-h720x/cpu-h7202.c | 3 ++-
> arch/arm/mach-rpc/time.c | 6 +++---
> arch/arm/plat-samsung/time.c | 7 ++++---
> 11 files changed, 36 insertions(+), 46 deletions(-)
<snip>
> +static u32 ep93xx_gettimeoffset(void)
> +{
> + int offset;
> +
> + offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
> +
> + /* Calculate (1000000 / 983040) * offset. */
This comment is now incorrect, it should say:
/* Calculate (1000000000 / 983040) * offset */
or perhaps to better explain what is being done:
/*
* Timer 4 is based on a 983.04 kHz reference clock,
* so dividing by 983040 gives a milli-second value.
* Refactor the calculation to avoid overflow.
*/
> + return (offset + (53 * offset / 3072)) * 1000;
> +}
~Ryan
^ permalink raw reply
* [PATCH v4 3/9] pinctrl: single: support pinconf generic
From: Tony Lindgren @ 2012-11-08 23:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121108225547.GL6801@atomide.com>
* Tony Lindgren <tony@atomide.com> [121108 15:00]:
> Hi,
>
> Noticed few more things while playing with this.
Also please run checkpatch.pl --strict on these patches,
at least this one generates some warnings.
Regards,
Tony
^ permalink raw reply
* [PATCH v2 2/5] clk: Add support for fundamental zynq clks
From: Soren Brinkmann @ 2012-11-08 23:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3569f4619a92904a40aecc9300aafe767ac736f7.1352400580.git.josh.cartwright@ni.com>
One note below:
On Wed, Oct 31, 2012 at 12:58:52PM -0600, Josh Cartwright wrote:
> Provide simplified models for the necessary clocks on the zynq-7000
> platform. Currently, the PLLs, the CPU clock network, and the basic
> peripheral clock networks (for SDIO, SMC, SPI, QSPI, UART) are modelled.
>
> OF bindings are also provided and documented.
>
> Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
> ---
> .../devicetree/bindings/clock/zynq-7000.txt | 55 +++
> drivers/clk/clk-zynq.c | 383 +++++++++++++++++++++
> include/linux/clk/zynq.h | 24 ++
> 3 files changed, 462 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/zynq-7000.txt
> create mode 100644 drivers/clk/clk-zynq.c
> create mode 100644 include/linux/clk/zynq.h
>
> diff --git a/Documentation/devicetree/bindings/clock/zynq-7000.txt b/Documentation/devicetree/bindings/clock/zynq-7000.txt
> new file mode 100644
> index 0000000..23ae1db
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/zynq-7000.txt
> @@ -0,0 +1,55 @@
> +Device Tree Clock bindings for the Zynq 7000 EPP
> +
> +The Zynq EPP has several different clk providers, each with there own bindings.
> +The purpose of this document is to document their usage.
> +
> +See clock_bindings.txt for more information on the generic clock bindings.
> +See Chapter 25 of Zynq TRM for more information about Zynq clocks.
> +
> +== PLLs ==
> +
> +Used to describe the ARM_PLL, DDR_PLL, and IO_PLL.
> +
> +Required properties:
> +- #clock-cells : shall be 0 (only one clock is output from this node)
> +- compatible : "xlnx,zynq-pll"
> +- reg : pair of u32 values, which are the address offsets within the SLCR
> + of the relevant PLL_CTRL register and PLL_CFG register respectively
> +- clocks : phandle for parent clock. should be the phandle for ps_clk
> +
> +Optional properties:
> +- clock-output-names : name of the output clock
> +
> +Example:
> + armpll: armpll {
> + #clock-cells = <0>;
> + compatible = "xlnx,zynq-pll";
> + clocks = <&ps_clk>;
> + reg = <0x100 0x110>;
> + clock-output-names = "armpll";
> + };
> +
> +== Peripheral clocks ==
> +
> +Describes clock node for the SDIO, SMC, SPI, QSPI, and UART clocks.
> +
> +Required properties:
> +- #clock-cells : shall be 1
> +- compatible : "xlnx,zynq-periph-clock"
> +- reg : a single u32 value, describing the offset within the SLCR where
> + the CLK_CTRL register is found for this peripheral
> +- clocks : phandle for parent clocks. should hold phandles for
> + the IO_PLL, ARM_PLL, and DDR_PLL in order
> +- clock-output-names : names of the output clock(s). For peripherals that have
> + two output clocks (for example, the UART), two clocks
> + should be listed.
> +
> +Example:
> + uart_clk: uart_clk {
> + #clock-cells = <1>;
> + compatible = "xlnx,zynq-periph-clock";
> + clocks = <&iopll &armpll &ddrpll>;
> + reg = <0x154>;
> + clock-output-names = "uart0_ref_clk",
> + "uart1_ref_clk";
> + };
> diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c
> new file mode 100644
> index 0000000..de8b586
> --- /dev/null
> +++ b/drivers/clk/clk-zynq.c
> @@ -0,0 +1,383 @@
> +/*
> + * Copyright (c) 2012 National Instruments
> + *
> + * Josh Cartwright <josh.cartwright@ni.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +
> +static void __iomem *slcr_base;
> +
> +struct zynq_pll_clk {
> + struct clk_hw hw;
> + void __iomem *pll_ctrl;
> + void __iomem *pll_cfg;
> +};
> +
> +#define to_zynq_pll_clk(hw) container_of(hw, struct zynq_pll_clk, hw)
> +
> +#define CTRL_PLL_FDIV(x) ((x) >> 12)
> +
> +static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
> + return parent_rate * CTRL_PLL_FDIV(ioread32(pll->pll_ctrl));
> +}
> +
> +static const struct clk_ops zynq_pll_clk_ops = {
> + .recalc_rate = zynq_pll_recalc_rate,
> +};
> +
> +static void __init zynq_pll_clk_setup(struct device_node *np)
> +{
> + struct clk_init_data init;
> + struct zynq_pll_clk *pll;
> + const char *parent_name;
> + struct clk *clk;
> + u32 regs[2];
> + int ret;
> +
> + ret = of_property_read_u32_array(np, "reg", regs, ARRAY_SIZE(regs));
> + if (WARN_ON(ret))
> + return;
> +
> + pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> + if (WARN_ON(!pll))
> + return;
> +
> + pll->pll_ctrl = slcr_base + regs[0];
> + pll->pll_cfg = slcr_base + regs[1];
> +
> + of_property_read_string(np, "clock-output-names", &init.name);
> +
> + init.ops = &zynq_pll_clk_ops;
> + parent_name = of_clk_get_parent_name(np, 0);
> + init.parent_names = &parent_name;
> + init.num_parents = 1;
> +
> + pll->hw.init = &init;
> +
> + clk = clk_register(NULL, &pll->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + return;
> +
> + ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
> + if (WARN_ON(ret))
> + return;
> +}
> +
> +struct zynq_periph_clk {
> + struct clk_hw hw;
> + struct clk_onecell_data onecell_data;
> + struct clk *gates[2];
> + void __iomem *clk_ctrl;
> + spinlock_t clkact_lock;
> +};
> +
> +#define to_zynq_periph_clk(hw) container_of(hw, struct zynq_periph_clk, hw)
> +
> +static const u8 periph_clk_parent_map[] = {
> + 0, 0, 1, 2
> +};
> +#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 3) >> 4])
I think this should be:
#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
> +#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
> +
> +static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
> + return parent_rate / PERIPH_CLK_CTRL_DIV(ioread32(periph->clk_ctrl));
> +}
> +
> +static u8 zynq_periph_get_parent(struct clk_hw *hw)
> +{
> + struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
> + return PERIPH_CLK_CTRL_SRC(ioread32(periph->clk_ctrl));
> +}
> +
> +static const struct clk_ops zynq_periph_clk_ops = {
> + .recalc_rate = zynq_periph_recalc_rate,
> + .get_parent = zynq_periph_get_parent,
> +};
> +
> +static void __init zynq_periph_clk_setup(struct device_node *np)
> +{
> + struct zynq_periph_clk *periph;
> + const char *parent_names[3];
> + struct clk_init_data init;
> + int clk_num = 0, err;
> + const char *name;
> + struct clk *clk;
> + u32 reg;
> + int i;
> +
> + err = of_property_read_u32(np, "reg", ®);
> + if (WARN_ON(err))
> + return;
> +
> + periph = kzalloc(sizeof(*periph), GFP_KERNEL);
> + if (WARN_ON(!periph))
> + return;
> +
> + periph->clk_ctrl = slcr_base + reg;
> + spin_lock_init(&periph->clkact_lock);
> +
> + init.name = np->name;
> + init.ops = &zynq_periph_clk_ops;
> + for (i = 0; i < ARRAY_SIZE(parent_names); i++)
> + parent_names[i] = of_clk_get_parent_name(np, i);
> + init.parent_names = parent_names;
> + init.num_parents = ARRAY_SIZE(parent_names);
> +
> + periph->hw.init = &init;
> +
> + clk = clk_register(NULL, &periph->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + return;
> +
> + err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
> + if (WARN_ON(err))
> + return;
> +
> + err = of_property_read_string_index(np, "clock-output-names", 0,
> + &name);
> + if (WARN_ON(err))
> + return;
> +
> + periph->gates[0] = clk_register_gate(NULL, name, np->name, 0,
> + periph->clk_ctrl, 0, 0,
> + &periph->clkact_lock);
> + if (WARN_ON(IS_ERR(periph->gates[0])))
> + return;
> + clk_num++;
> +
> + /* some periph clks have 2 downstream gates */
> + err = of_property_read_string_index(np, "clock-output-names", 1,
> + &name);
> + if (err != -ENODATA) {
> + periph->gates[1] = clk_register_gate(NULL, name, np->name, 0,
> + periph->clk_ctrl, 1, 0,
> + &periph->clkact_lock);
> + if (WARN_ON(IS_ERR(periph->gates[1])))
> + return;
> + clk_num++;
> + }
> +
> + periph->onecell_data.clks = periph->gates;
> + periph->onecell_data.clk_num = clk_num;
> +
> + err = of_clk_add_provider(np, of_clk_src_onecell_get,
> + &periph->onecell_data);
> + if (WARN_ON(err))
> + return;
> +}
> +
> +/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
> + * derivative rates depend on CLK_621_TRUE
> + */
> +
> +struct zynq_cpu_clk {
> + struct clk_hw hw;
> + struct clk_onecell_data onecell_data;
> + struct clk *subclks[4];
> + void __iomem *clk_ctrl;
> + spinlock_t clkact_lock;
> +};
> +
> +#define to_zynq_cpu_clk(hw) container_of(hw, struct zynq_cpu_clk, hw)
> +
> +static const u8 zynq_cpu_clk_parent_map[] = {
> + 1, 1, 2, 0
> +};
> +#define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
> +#define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
> +
> +static u8 zynq_cpu_clk_get_parent(struct clk_hw *hw)
> +{
> + struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
> + return CPU_CLK_SRCSEL(ioread32(cpuclk->clk_ctrl));
> +}
> +
> +static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
> + return parent_rate / CPU_CLK_CTRL_DIV(ioread32(cpuclk->clk_ctrl));
> +}
> +
> +static const struct clk_ops zynq_cpu_clk_ops = {
> + .get_parent = zynq_cpu_clk_get_parent,
> + .recalc_rate = zynq_cpu_clk_recalc_rate,
> +};
> +
> +struct zynq_cpu_subclk {
> + struct clk_hw hw;
> + void __iomem *clk_621;
> + enum {
> + CPU_SUBCLK_6X4X,
> + CPU_SUBCLK_3X2X,
> + CPU_SUBCLK_2X,
> + CPU_SUBCLK_1X,
> + } which;
> +};
> +
> +#define CLK_621_TRUE(x) ((x) & 1)
> +
> +#define to_zynq_cpu_subclk(hw) container_of(hw, struct zynq_cpu_subclk, hw);
> +
> +static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + unsigned long uninitialized_var(rate);
> + struct zynq_cpu_subclk *subclk;
> + bool is_621;
> +
> + subclk = to_zynq_cpu_subclk(hw)
> + is_621 = CLK_621_TRUE(ioread32(subclk->clk_621));
> +
> + switch (subclk->which) {
> + case CPU_SUBCLK_6X4X:
> + rate = parent_rate;
> + break;
> + case CPU_SUBCLK_3X2X:
> + rate = parent_rate / 2;
> + break;
> + case CPU_SUBCLK_2X:
> + rate = parent_rate / (is_621 ? 3 : 2);
> + break;
> + case CPU_SUBCLK_1X:
> + rate = parent_rate / (is_621 ? 6 : 4);
> + break;
> + };
> +
> + return rate;
> +}
> +
> +static const struct clk_ops zynq_cpu_subclk_ops = {
> + .recalc_rate = zynq_cpu_subclk_recalc_rate,
> +};
> +
> +static struct clk *zynq_cpu_subclk_setup(struct device_node *np, u8 which,
> + void __iomem *clk_621)
> +{
> + struct zynq_cpu_subclk *subclk;
> + struct clk_init_data init;
> + struct clk *clk;
> + int err;
> +
> + err = of_property_read_string_index(np, "clock-output-names",
> + which, &init.name);
> + if (WARN_ON(err))
> + goto err_read_output_name;
> +
> + subclk = kzalloc(sizeof(*subclk), GFP_KERNEL);
> + if (!subclk)
> + goto err_subclk_alloc;
> +
> + subclk->clk_621 = clk_621;
> + subclk->which = which;
> +
> + init.ops = &zynq_cpu_subclk_ops;
> + init.parent_names = &np->name;
> + init.num_parents = 1;
> +
> + subclk->hw.init = &init;
> +
> + clk = clk_register(NULL, &subclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + goto err_clk_register;
> +
> + return clk;
> +
> +err_clk_register:
> + kfree(subclk);
> +err_subclk_alloc:
> +err_read_output_name:
> + return ERR_PTR(-EINVAL);
> +}
> +
> +static void __init zynq_cpu_clk_setup(struct device_node *np)
> +{
> + struct zynq_cpu_clk *cpuclk;
> + const char *parent_names[3];
> + struct clk_init_data init;
> + void __iomem *clk_621;
> + struct clk *clk;
> + u32 reg[2];
> + int err;
> + int i;
> +
> + err = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
> + if (WARN_ON(err))
> + return;
> +
> + cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
> + if (WARN_ON(!cpuclk))
> + return;
> +
> + cpuclk->clk_ctrl = slcr_base + reg[0];
> + clk_621 = slcr_base + reg[1];
> + spin_lock_init(&cpuclk->clkact_lock);
> +
> + init.name = np->name;
> + init.ops = &zynq_cpu_clk_ops;
> + for (i = 0; i < ARRAY_SIZE(parent_names); i++)
> + parent_names[i] = of_clk_get_parent_name(np, i);
> + init.parent_names = parent_names;
> + init.num_parents = ARRAY_SIZE(parent_names);
> +
> + cpuclk->hw.init = &init;
> +
> + clk = clk_register(NULL, &cpuclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + return;
> +
> + err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
> + if (WARN_ON(err))
> + return;
> +
> + for (i = 0; i < 4; i++) {
> + cpuclk->subclks[i] = zynq_cpu_subclk_setup(np, i, clk_621);
> + if (WARN_ON(IS_ERR(cpuclk->subclks[i])))
> + return;
> + }
> +
> + cpuclk->onecell_data.clks = cpuclk->subclks;
> + cpuclk->onecell_data.clk_num = i;
> +
> + err = of_clk_add_provider(np, of_clk_src_onecell_get,
> + &cpuclk->onecell_data);
> + if (WARN_ON(err))
> + return;
> +}
> +
> +static const __initconst struct of_device_id zynq_clk_match[] = {
> + { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
> + { .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, },
> + { .compatible = "xlnx,zynq-periph-clock",
> + .data = zynq_periph_clk_setup, },
> + { .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, },
> + {}
> +};
> +
> +void __init xilinx_zynq_clocks_init(void __iomem *slcr)
> +{
> + slcr_base = slcr;
> + of_clk_init(zynq_clk_match);
> +}
> diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
> new file mode 100644
> index 0000000..56be7cd
> --- /dev/null
> +++ b/include/linux/clk/zynq.h
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright (C) 2012 National Instruments
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#ifndef __LINUX_CLK_ZYNQ_H_
> +#define __LINUX_CLK_ZYNQ_H_
> +
> +void __init xilinx_zynq_clocks_init(void __iomem *slcr);
> +
> +#endif
> --
> 1.8.0
Soren
^ permalink raw reply
* [PATCH] ARM: OMAP2+: clockdomain: disabling unused clks
From: Mike Turquette @ 2012-11-08 23:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1211081800210.20703@utopia.booyaka.com>
The OMAP port to the common clk framework[1] resulted in spurious WARNs
while disable unused clocks. This is due to _clkdm_clk_hwmod_disable
catching clkdm->usecount's with a value of zero. Even less desirable it
would not allow the clkdm_clk_disable function pointer to get called due
to an early return of -ERANGE.
This patch adds a check for such a corner case by skipping the WARN and
early return in the event that clkdm->usecount and clk->enable_usecount
are both zero. Presumably this could only happen during the check for
unused clocks at boot-time.
[1] http://article.gmane.org/gmane.linux.ports.arm.omap/88824
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
arch/arm/mach-omap2/clockdomain.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 64e5046..b0c0ce6 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -947,16 +947,22 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
return 0;
}
-static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
+static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm,
+ struct clk *clk)
{
unsigned long flags;
+ int clk_enable_count = 1;
if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
return -EINVAL;
spin_lock_irqsave(&clkdm->lock, flags);
- if (atomic_read(&clkdm->usecount) == 0) {
+ /* corner case: disabling unused clocks */
+ if (clk)
+ clk_enable_count = __clk_get_enable_count(clk);
+
+ if (atomic_read(&clkdm->usecount) == 0 && clk_enable_count) {
spin_unlock_irqrestore(&clkdm->lock, flags);
WARN_ON(1); /* underflow */
return -ERANGE;
@@ -1026,7 +1032,7 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
if (!clk)
return -EINVAL;
- return _clkdm_clk_hwmod_disable(clkdm);
+ return _clkdm_clk_hwmod_disable(clkdm, clk);
}
/**
@@ -1089,6 +1095,6 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
if (!oh)
return -EINVAL;
- return _clkdm_clk_hwmod_disable(clkdm);
+ return _clkdm_clk_hwmod_disable(clkdm, NULL);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 0/5] zynq clk support
From: Soren Brinkmann @ 2012-11-08 23:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352400580.git.josh.cartwright@ni.com>
Hi Josh,
did you also have a look at what is available in the Xilinx git repository?
There are also quite some patches to support common clock and port drivers over
to using it.
It would be great if we could combine our efforts instead of ending up with
competing solutions.
Thanks,
Soren
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox