From 976516404ff3fab2a8caa8bd6f5efc1437fed0b8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Aug 2018 14:02:57 +0200 Subject: y2038: remove unused time interfaces After many small patches, at least some of the deprecated interfaces have no remaining users any more and can be removed: current_kernel_time do_settimeofday get_monotonic_boottime get_monotonic_boottime64 get_monotonic_coarse get_monotonic_coarse64 getrawmonotonic64 ktime_get_real_ts timekeeping_clocktai timespec_trunc timespec_valid_strict time_to_tm For many of the remaining time functions, we are missing one or two patches that failed to make it into 4.19, they will be removed in the following merge window. The replacement functions for the removed interfaces are documented in Documentation/core-api/timekeeping.rst. Signed-off-by: Arnd Bergmann --- include/linux/time32.h | 25 ---------------------- include/linux/timekeeping.h | 12 ----------- include/linux/timekeeping32.h | 50 ------------------------------------------- kernel/time/time.c | 24 --------------------- 4 files changed, 111 deletions(-) diff --git a/include/linux/time32.h b/include/linux/time32.h index d1ae43c13e25..92c0ca092d93 100644 --- a/include/linux/time32.h +++ b/include/linux/time32.h @@ -105,16 +105,6 @@ static inline bool timespec_valid(const struct timespec *ts) return true; } -static inline bool timespec_valid_strict(const struct timespec *ts) -{ - if (!timespec_valid(ts)) - return false; - /* Disallow values that could overflow ktime_t */ - if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX) - return false; - return true; -} - /** * timespec_to_ns - Convert timespec to nanoseconds * @ts: pointer to the timespec variable to be converted @@ -149,19 +139,6 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) a->tv_nsec = ns; } -/** - * time_to_tm - converts the calendar time to local broken-down time - * - * @totalsecs the number of seconds elapsed since 00:00:00 on January 1, 1970, - * Coordinated Universal Time (UTC). - * @offset offset seconds adding to totalsecs. - * @result pointer to struct tm variable to receive broken-down time - */ -static inline void time_to_tm(time_t totalsecs, int offset, struct tm *result) -{ - time64_to_tm(totalsecs, offset, result); -} - static inline unsigned long mktime(const unsigned int year, const unsigned int mon, const unsigned int day, const unsigned int hour, const unsigned int min, @@ -183,8 +160,6 @@ static inline bool timeval_valid(const struct timeval *tv) return true; } -extern struct timespec timespec_trunc(struct timespec t, unsigned int gran); - /** * timeval_to_ns - Convert timeval to nanoseconds * @ts: pointer to the timeval variable to be converted diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 5d738804e3d6..3faba06411aa 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -266,9 +266,6 @@ extern int update_persistent_clock64(struct timespec64 now); * deprecated aliases, don't use in new code */ #define getnstimeofday64(ts) ktime_get_real_ts64(ts) -#define get_monotonic_boottime64(ts) ktime_get_boottime_ts64(ts) -#define getrawmonotonic64(ts) ktime_get_raw_ts64(ts) -#define timekeeping_clocktai64(ts) ktime_get_clocktai_ts64(ts) static inline struct timespec64 current_kernel_time64(void) { @@ -279,13 +276,4 @@ static inline struct timespec64 current_kernel_time64(void) return ts; } -static inline struct timespec64 get_monotonic_coarse64(void) -{ - struct timespec64 ts; - - ktime_get_coarse_ts64(&ts); - - return ts; -} - #endif diff --git a/include/linux/timekeeping32.h b/include/linux/timekeeping32.h index 8762c2f45f8b..a4a4991160fb 100644 --- a/include/linux/timekeeping32.h +++ b/include/linux/timekeeping32.h @@ -9,26 +9,6 @@ extern void do_gettimeofday(struct timeval *tv); unsigned long get_seconds(void); -static inline struct timespec current_kernel_time(void) -{ - struct timespec64 ts64; - - ktime_get_coarse_real_ts64(&ts64); - - return timespec64_to_timespec(ts64); -} - -/** - * Deprecated. Use do_settimeofday64(). - */ -static inline int do_settimeofday(const struct timespec *ts) -{ - struct timespec64 ts64; - - ts64 = timespec_to_timespec64(*ts); - return do_settimeofday64(&ts64); -} - static inline void getnstimeofday(struct timespec *ts) { struct timespec64 ts64; @@ -45,14 +25,6 @@ static inline void ktime_get_ts(struct timespec *ts) *ts = timespec64_to_timespec(ts64); } -static inline void ktime_get_real_ts(struct timespec *ts) -{ - struct timespec64 ts64; - - ktime_get_real_ts64(&ts64); - *ts = timespec64_to_timespec(ts64); -} - static inline void getrawmonotonic(struct timespec *ts) { struct timespec64 ts64; @@ -61,15 +33,6 @@ static inline void getrawmonotonic(struct timespec *ts) *ts = timespec64_to_timespec(ts64); } -static inline struct timespec get_monotonic_coarse(void) -{ - struct timespec64 ts64; - - ktime_get_coarse_ts64(&ts64); - - return timespec64_to_timespec(ts64); -} - static inline void getboottime(struct timespec *ts) { struct timespec64 ts64; @@ -78,19 +41,6 @@ static inline void getboottime(struct timespec *ts) *ts = timespec64_to_timespec(ts64); } -/* - * Timespec interfaces utilizing the ktime based ones - */ -static inline void get_monotonic_boottime(struct timespec *ts) -{ - *ts = ktime_to_timespec(ktime_get_boottime()); -} - -static inline void timekeeping_clocktai(struct timespec *ts) -{ - *ts = ktime_to_timespec(ktime_get_clocktai()); -} - /* * Persistent clock related interfaces */ diff --git a/kernel/time/time.c b/kernel/time/time.c index ccdb351277ee..712543011106 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -342,30 +342,6 @@ unsigned int jiffies_to_usecs(const unsigned long j) } EXPORT_SYMBOL(jiffies_to_usecs); -/** - * timespec_trunc - Truncate timespec to a granularity - * @t: Timespec - * @gran: Granularity in ns. - * - * Truncate a timespec to a granularity. Always rounds down. gran must - * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns). - */ -struct timespec timespec_trunc(struct timespec t, unsigned gran) -{ - /* Avoid division in the common cases 1 ns and 1 s. */ - if (gran == 1) { - /* nothing */ - } else if (gran == NSEC_PER_SEC) { - t.tv_nsec = 0; - } else if (gran > 1 && gran < NSEC_PER_SEC) { - t.tv_nsec -= t.tv_nsec % gran; - } else { - WARN(1, "illegal file time granularity: %u", gran); - } - return t; -} -EXPORT_SYMBOL(timespec_trunc); - /* * mktime64 - Converts date to seconds. * Converts Gregorian date to seconds since 1970-01-01 00:00:00. -- cgit v1.2.3-59-g8ed1b From 33e26418193f58d1895f2f968e1953b1caf8deb7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Aug 2018 15:18:20 +0200 Subject: y2038: make do_gettimeofday() and get_seconds() inline get_seconds() and do_gettimeofday() are only used by a few modules now any more (waiting for the respective patches to get accepted), and they are among the last holdouts of code that is not y2038 safe in the core kernel. Move the implementation into the timekeeping32.h header to clean up the core kernel and isolate the old interfaces further. Signed-off-by: Arnd Bergmann --- include/linux/timekeeping32.h | 15 +++++++++++++-- kernel/time/time.c | 15 +++++++++------ kernel/time/timekeeping.c | 24 ------------------------ 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/include/linux/timekeeping32.h b/include/linux/timekeeping32.h index a4a4991160fb..a502616f7e1c 100644 --- a/include/linux/timekeeping32.h +++ b/include/linux/timekeeping32.h @@ -6,8 +6,19 @@ * over time so we can remove the file here. */ -extern void do_gettimeofday(struct timeval *tv); -unsigned long get_seconds(void); +static inline void do_gettimeofday(struct timeval *tv) +{ + struct timespec64 now; + + ktime_get_real_ts64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec/1000; +} + +static inline unsigned long get_seconds(void) +{ + return ktime_get_real_seconds(); +} static inline void getnstimeofday(struct timespec *ts) { diff --git a/kernel/time/time.c b/kernel/time/time.c index 712543011106..de332250d6fa 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -144,9 +144,11 @@ SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv, struct timezone __user *, tz) { if (likely(tv != NULL)) { - struct timeval ktv; - do_gettimeofday(&ktv); - if (copy_to_user(tv, &ktv, sizeof(ktv))) + struct timespec64 ts; + + ktime_get_real_ts64(&ts); + if (put_user(ts.tv_sec, &tv->tv_sec) || + put_user(ts.tv_nsec / 1000, &tv->tv_usec)) return -EFAULT; } if (unlikely(tz != NULL)) { @@ -227,10 +229,11 @@ COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv, struct timezone __user *, tz) { if (tv) { - struct timeval ktv; + struct timespec64 ts; - do_gettimeofday(&ktv); - if (compat_put_timeval(&ktv, tv)) + ktime_get_real_ts64(&ts); + if (put_user(ts.tv_sec, &tv->tv_sec) || + put_user(ts.tv_nsec / 1000, &tv->tv_usec)) return -EFAULT; } if (tz) { diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index f3b22f456fac..2d110c948805 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1211,22 +1211,6 @@ int get_device_system_crosststamp(int (*get_time_fn) } EXPORT_SYMBOL_GPL(get_device_system_crosststamp); -/** - * do_gettimeofday - Returns the time of day in a timeval - * @tv: pointer to the timeval to be set - * - * NOTE: Users should be converted to using getnstimeofday() - */ -void do_gettimeofday(struct timeval *tv) -{ - struct timespec64 now; - - getnstimeofday64(&now); - tv->tv_sec = now.tv_sec; - tv->tv_usec = now.tv_nsec/1000; -} -EXPORT_SYMBOL(do_gettimeofday); - /** * do_settimeofday64 - Sets the time of day. * @ts: pointer to the timespec64 variable containing the new time @@ -2174,14 +2158,6 @@ void getboottime64(struct timespec64 *ts) } EXPORT_SYMBOL_GPL(getboottime64); -unsigned long get_seconds(void) -{ - struct timekeeper *tk = &tk_core.timekeeper; - - return tk->xtime_sec; -} -EXPORT_SYMBOL(get_seconds); - void ktime_get_coarse_real_ts64(struct timespec64 *ts) { struct timekeeper *tk = &tk_core.timekeeper; -- cgit v1.2.3-59-g8ed1b From 9afc5eee65ca7d717a99d6fe8f4adfe32a40940a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 13 Jul 2018 12:52:28 +0200 Subject: y2038: globally rename compat_time to old_time32 Christoph Hellwig suggested a slightly different path for handling backwards compatibility with the 32-bit time_t based system calls: Rather than simply reusing the compat_sys_* entry points on 32-bit architectures unchanged, we get rid of those entry points and the compat_time types by renaming them to something that makes more sense on 32-bit architectures (which don't have a compat mode otherwise), and then share the entry points under the new name with the 64-bit architectures that use them for implementing the compatibility. The following types and interfaces are renamed here, and moved from linux/compat_time.h to linux/time32.h: old new --- --- compat_time_t old_time32_t struct compat_timeval struct old_timeval32 struct compat_timespec struct old_timespec32 struct compat_itimerspec struct old_itimerspec32 ns_to_compat_timeval() ns_to_old_timeval32() get_compat_itimerspec64() get_old_itimerspec32() put_compat_itimerspec64() put_old_itimerspec32() compat_get_timespec64() get_old_timespec32() compat_put_timespec64() put_old_timespec32() As we already have aliases in place, this patch addresses only the instances that are relevant to the system call interface in particular, not those that occur in device drivers and other modules. Those will get handled separately, while providing the 64-bit version of the respective interfaces. I'm not renaming the timex, rusage and itimerval structures, as we are still debating what the new interface will look like, and whether we will need a replacement at all. This also doesn't change the names of the syscall entry points, which can be done more easily when we actually switch over the 32-bit architectures to use them, at that point we need to change COMPAT_SYSCALL_DEFINEx to SYSCALL_DEFINEx with a new name, e.g. with a _time32 suffix. Suggested-by: Christoph Hellwig Link: https://lore.kernel.org/lkml/20180705222110.GA5698@infradead.org/ Signed-off-by: Arnd Bergmann --- arch/arm64/include/asm/compat.h | 6 +-- arch/arm64/include/asm/stat.h | 2 +- arch/mips/include/asm/compat.h | 6 +-- arch/mips/kernel/binfmt_elfn32.c | 14 +++--- arch/mips/kernel/binfmt_elfo32.c | 14 +++--- arch/parisc/include/asm/compat.h | 6 +-- arch/powerpc/include/asm/compat.h | 6 +-- arch/powerpc/kernel/asm-offsets.c | 8 ++-- arch/powerpc/oprofile/backtrace.c | 2 +- arch/sparc/include/asm/compat.h | 6 +-- fs/aio.c | 8 ++-- fs/compat_binfmt_elf.c | 2 +- fs/select.c | 20 ++++---- fs/timerfd.c | 12 ++--- fs/utimes.c | 12 ++--- include/linux/compat.h | 96 +++++++++++++++++++-------------------- include/linux/compat_time.h | 32 ------------- include/linux/elfcore-compat.h | 8 ++-- include/linux/restart_block.h | 4 +- include/linux/syscalls.h | 2 +- include/linux/time32.h | 48 +++++++++++++++----- ipc/mqueue.c | 8 ++-- ipc/msg.c | 6 +-- ipc/sem.c | 10 ++-- ipc/shm.c | 6 +-- ipc/syscall.c | 2 +- ipc/util.h | 2 +- kernel/compat.c | 8 ++-- kernel/futex_compat.c | 2 +- kernel/sched/core.c | 4 +- kernel/signal.c | 2 +- kernel/time/hrtimer.c | 8 ++-- kernel/time/posix-stubs.c | 18 ++++---- kernel/time/posix-timers.c | 30 ++++++------ kernel/time/time.c | 58 +++++++++++------------ net/compat.c | 4 +- 36 files changed, 237 insertions(+), 245 deletions(-) delete mode 100644 include/linux/compat_time.h diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 1a037b94eba1..4a89007db14a 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -86,11 +86,11 @@ struct compat_stat { compat_off_t st_size; compat_off_t st_blksize; compat_off_t st_blocks; - compat_time_t st_atime; + old_time32_t st_atime; compat_ulong_t st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; compat_ulong_t st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; compat_ulong_t st_ctime_nsec; compat_ulong_t __unused4[2]; }; diff --git a/arch/arm64/include/asm/stat.h b/arch/arm64/include/asm/stat.h index eab738019707..397c6ccd04e7 100644 --- a/arch/arm64/include/asm/stat.h +++ b/arch/arm64/include/asm/stat.h @@ -20,7 +20,7 @@ #ifdef CONFIG_COMPAT -#include +#include #include /* diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 78675f19440f..7dcbd855814e 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -59,11 +59,11 @@ struct compat_stat { s32 st_pad2[2]; compat_off_t st_size; s32 st_pad3; - compat_time_t st_atime; + old_time32_t st_atime; s32 st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; s32 st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; s32 st_ctime_nsec; s32 st_blksize; s32 st_blocks; diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index 89b234844534..7a12763d553a 100644 --- a/arch/mips/kernel/binfmt_elfn32.c +++ b/arch/mips/kernel/binfmt_elfn32.c @@ -54,10 +54,10 @@ struct elf_prstatus32 pid_t pr_ppid; pid_t pr_pgrp; pid_t pr_sid; - struct compat_timeval pr_utime; /* User time */ - struct compat_timeval pr_stime; /* System time */ - struct compat_timeval pr_cutime;/* Cumulative user time */ - struct compat_timeval pr_cstime;/* Cumulative system time */ + struct old_timeval32 pr_utime; /* User time */ + struct old_timeval32 pr_stime; /* System time */ + struct old_timeval32 pr_cutime;/* Cumulative user time */ + struct old_timeval32 pr_cstime;/* Cumulative system time */ elf_gregset_t pr_reg; /* GP registers */ int pr_fpvalid; /* True if math co-processor being used. */ }; @@ -81,9 +81,9 @@ struct elf_prpsinfo32 #define elf_caddr_t u32 #define init_elf_binfmt init_elfn32_binfmt -#define jiffies_to_timeval jiffies_to_compat_timeval +#define jiffies_to_timeval jiffies_to_old_timeval32 static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value) { /* * Convert jiffies to nanoseconds and separate with @@ -101,6 +101,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) #define TASK_SIZE TASK_SIZE32 #undef ns_to_timeval -#define ns_to_timeval ns_to_compat_timeval +#define ns_to_timeval ns_to_old_timeval32 #include "../../../fs/binfmt_elf.c" diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index a88c59db3d48..e6db06a1d31a 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -59,10 +59,10 @@ struct elf_prstatus32 pid_t pr_ppid; pid_t pr_pgrp; pid_t pr_sid; - struct compat_timeval pr_utime; /* User time */ - struct compat_timeval pr_stime; /* System time */ - struct compat_timeval pr_cutime;/* Cumulative user time */ - struct compat_timeval pr_cstime;/* Cumulative system time */ + struct old_timeval32 pr_utime; /* User time */ + struct old_timeval32 pr_stime; /* System time */ + struct old_timeval32 pr_cutime;/* Cumulative user time */ + struct old_timeval32 pr_cstime;/* Cumulative system time */ elf_gregset_t pr_reg; /* GP registers */ int pr_fpvalid; /* True if math co-processor being used. */ }; @@ -86,9 +86,9 @@ struct elf_prpsinfo32 #define elf_caddr_t u32 #define init_elf_binfmt init_elf32_binfmt -#define jiffies_to_timeval jiffies_to_compat_timeval +#define jiffies_to_timeval jiffies_to_old_timeval32 static inline void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value) { /* * Convert jiffies to nanoseconds and separate with @@ -104,6 +104,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) #define TASK_SIZE TASK_SIZE32 #undef ns_to_timeval -#define ns_to_timeval ns_to_compat_timeval +#define ns_to_timeval ns_to_old_timeval32 #include "../../../fs/binfmt_elf.c" diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index ab8a54771507..32dadaf2b534 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -48,11 +48,11 @@ struct compat_stat { u16 st_reserved2; /* old st_gid */ compat_dev_t st_rdev; compat_off_t st_size; - compat_time_t st_atime; + old_time32_t st_atime; u32 st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; u32 st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; u32 st_ctime_nsec; s32 st_blksize; s32 st_blocks; diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 85c8af2bb272..93f79d1a03c3 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -55,11 +55,11 @@ struct compat_stat { compat_off_t st_size; compat_off_t st_blksize; compat_off_t st_blocks; - compat_time_t st_atime; + old_time32_t st_atime; u32 st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; u32 st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; u32 st_ctime_nsec; u32 __unused4[2]; }; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 89cf15566c4e..041a115789a1 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -387,12 +387,12 @@ int main(void) OFFSET(CFG_SYSCALL_MAP64, vdso_data, syscall_map_64); OFFSET(TVAL64_TV_SEC, timeval, tv_sec); OFFSET(TVAL64_TV_USEC, timeval, tv_usec); - OFFSET(TVAL32_TV_SEC, compat_timeval, tv_sec); - OFFSET(TVAL32_TV_USEC, compat_timeval, tv_usec); + OFFSET(TVAL32_TV_SEC, old_timeval32, tv_sec); + OFFSET(TVAL32_TV_USEC, old_timeval32, tv_usec); OFFSET(TSPC64_TV_SEC, timespec, tv_sec); OFFSET(TSPC64_TV_NSEC, timespec, tv_nsec); - OFFSET(TSPC32_TV_SEC, compat_timespec, tv_sec); - OFFSET(TSPC32_TV_NSEC, compat_timespec, tv_nsec); + OFFSET(TSPC32_TV_SEC, old_timespec32, tv_sec); + OFFSET(TSPC32_TV_NSEC, old_timespec32, tv_nsec); #else OFFSET(TVAL32_TV_SEC, timeval, tv_sec); OFFSET(TVAL32_TV_USEC, timeval, tv_usec); diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c index ad054dd0d666..5df6290d1ccc 100644 --- a/arch/powerpc/oprofile/backtrace.c +++ b/arch/powerpc/oprofile/backtrace.c @@ -7,7 +7,7 @@ * 2 of the License, or (at your option) any later version. **/ -#include +#include #include #include #include diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 4eb51d2dae98..7018cb60beef 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -47,11 +47,11 @@ struct compat_stat { __compat_gid_t st_gid; compat_dev_t st_rdev; compat_off_t st_size; - compat_time_t st_atime; + old_time32_t st_atime; compat_ulong_t st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; compat_ulong_t st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; compat_ulong_t st_ctime_nsec; compat_off_t st_blksize; compat_off_t st_blocks; diff --git a/fs/aio.c b/fs/aio.c index b9350f3360c6..301e6314183b 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -2135,12 +2135,12 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, compat_long_t, min_nr, compat_long_t, nr, struct io_event __user *, events, - struct compat_timespec __user *, timeout) + struct old_timespec32 __user *, timeout) { struct timespec64 t; int ret; - if (timeout && compat_get_timespec64(&t, timeout)) + if (timeout && get_old_timespec32(&t, timeout)) return -EFAULT; ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL); @@ -2160,7 +2160,7 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents, compat_long_t, min_nr, compat_long_t, nr, struct io_event __user *, events, - struct compat_timespec __user *, timeout, + struct old_timespec32 __user *, timeout, const struct __compat_aio_sigset __user *, usig) { struct __compat_aio_sigset ksig = { NULL, }; @@ -2168,7 +2168,7 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents, struct timespec64 t; int ret; - if (timeout && compat_get_timespec64(&t, timeout)) + if (timeout && get_old_timespec32(&t, timeout)) return -EFAULT; if (usig && copy_from_user(&ksig, usig, sizeof(ksig))) diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index 504b3c3539dc..15f6e96b3bd9 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -52,7 +52,7 @@ #define elf_prpsinfo compat_elf_prpsinfo #undef ns_to_timeval -#define ns_to_timeval ns_to_compat_timeval +#define ns_to_timeval ns_to_old_timeval32 /* * To use this file, asm/elf.h must define compat_elf_check_arch. diff --git a/fs/select.c b/fs/select.c index 4a6b6e4b21cb..22b3bf89f051 100644 --- a/fs/select.c +++ b/fs/select.c @@ -1120,7 +1120,7 @@ int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user * ts.tv_sec = ts.tv_nsec = 0; if (timeval) { - struct compat_timeval rtv; + struct old_timeval32 rtv; rtv.tv_sec = ts.tv_sec; rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC; @@ -1128,7 +1128,7 @@ int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user * if (!copy_to_user(p, &rtv, sizeof(rtv))) return ret; } else { - if (!compat_put_timespec64(&ts, p)) + if (!put_old_timespec32(&ts, p)) return ret; } /* @@ -1257,10 +1257,10 @@ out_nofds: static int do_compat_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, - struct compat_timeval __user *tvp) + struct old_timeval32 __user *tvp) { struct timespec64 end_time, *to = NULL; - struct compat_timeval tv; + struct old_timeval32 tv; int ret; if (tvp) { @@ -1282,7 +1282,7 @@ static int do_compat_select(int n, compat_ulong_t __user *inp, COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp, compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, - struct compat_timeval __user *, tvp) + struct old_timeval32 __user *, tvp) { return do_compat_select(n, inp, outp, exp, tvp); } @@ -1307,7 +1307,7 @@ COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg) static long do_compat_pselect(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, - struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, + struct old_timespec32 __user *tsp, compat_sigset_t __user *sigmask, compat_size_t sigsetsize) { sigset_t ksigmask, sigsaved; @@ -1315,7 +1315,7 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, int ret; if (tsp) { - if (compat_get_timespec64(&ts, tsp)) + if (get_old_timespec32(&ts, tsp)) return -EFAULT; to = &end_time; @@ -1355,7 +1355,7 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp, compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, - struct compat_timespec __user *, tsp, void __user *, sig) + struct old_timespec32 __user *, tsp, void __user *, sig) { compat_size_t sigsetsize = 0; compat_uptr_t up = 0; @@ -1373,7 +1373,7 @@ COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp, } COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, - unsigned int, nfds, struct compat_timespec __user *, tsp, + unsigned int, nfds, struct old_timespec32 __user *, tsp, const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize) { sigset_t ksigmask, sigsaved; @@ -1381,7 +1381,7 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, int ret; if (tsp) { - if (compat_get_timespec64(&ts, tsp)) + if (get_old_timespec32(&ts, tsp)) return -EFAULT; to = &end_time; diff --git a/fs/timerfd.c b/fs/timerfd.c index d69ad801eb80..803ca070d42e 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -561,29 +561,29 @@ SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct __kernel_itimerspec __user *, #ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, - const struct compat_itimerspec __user *, utmr, - struct compat_itimerspec __user *, otmr) + const struct old_itimerspec32 __user *, utmr, + struct old_itimerspec32 __user *, otmr) { struct itimerspec64 new, old; int ret; - if (get_compat_itimerspec64(&new, utmr)) + if (get_old_itimerspec32(&new, utmr)) return -EFAULT; ret = do_timerfd_settime(ufd, flags, &new, &old); if (ret) return ret; - if (otmr && put_compat_itimerspec64(&old, otmr)) + if (otmr && put_old_itimerspec32(&old, otmr)) return -EFAULT; return ret; } COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd, - struct compat_itimerspec __user *, otmr) + struct old_itimerspec32 __user *, otmr) { struct itimerspec64 kotmr; int ret = do_timerfd_gettime(ufd, &kotmr); if (ret) return ret; - return put_compat_itimerspec64(&kotmr, otmr) ? -EFAULT : 0; + return put_old_itimerspec32(&kotmr, otmr) ? -EFAULT : 0; } #endif diff --git a/fs/utimes.c b/fs/utimes.c index 69d4b6ba1bfb..79a65c163f40 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -245,13 +245,13 @@ COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); } -COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) +COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct old_timespec32 __user *, t, int, flags) { struct timespec64 tv[2]; if (t) { - if (compat_get_timespec64(&tv[0], &t[0]) || - compat_get_timespec64(&tv[1], &t[1])) + if (get_old_timespec32(&tv[0], &t[0]) || + get_old_timespec32(&tv[1], &t[1])) return -EFAULT; if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) @@ -261,7 +261,7 @@ COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filena } static long do_compat_futimesat(unsigned int dfd, const char __user *filename, - struct compat_timeval __user *t) + struct old_timeval32 __user *t) { struct timespec64 tv[2]; @@ -282,12 +282,12 @@ static long do_compat_futimesat(unsigned int dfd, const char __user *filename, COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, - struct compat_timeval __user *, t) + struct old_timeval32 __user *, t) { return do_compat_futimesat(dfd, filename, t); } -COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t) +COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct old_timeval32 __user *, t) { return do_compat_futimesat(AT_FDCWD, filename, t); } diff --git a/include/linux/compat.h b/include/linux/compat.h index 1a3c4f37e908..0e058792ecf6 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -7,7 +7,7 @@ */ #include -#include +#include #include #include /* for HZ */ @@ -116,13 +116,13 @@ struct compat_sel_arg_struct; struct rusage; struct compat_utimbuf { - compat_time_t actime; - compat_time_t modtime; + old_time32_t actime; + old_time32_t modtime; }; struct compat_itimerval { - struct compat_timeval it_interval; - struct compat_timeval it_value; + struct old_timeval32 it_interval; + struct old_timeval32 it_value; }; struct itimerval; @@ -146,7 +146,7 @@ struct compat_timex { compat_long_t constant; compat_long_t precision; compat_long_t tolerance; - struct compat_timeval time; + struct old_timeval32 time; compat_long_t tick; compat_long_t ppsfreq; compat_long_t jitter; @@ -307,8 +307,8 @@ struct compat_rlimit { }; struct compat_rusage { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; + struct old_timeval32 ru_utime; + struct old_timeval32 ru_stime; compat_long_t ru_maxrss; compat_long_t ru_ixrss; compat_long_t ru_idrss; @@ -457,8 +457,8 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *fr int get_compat_sigevent(struct sigevent *event, const struct compat_sigevent __user *u_event); -static inline int compat_timeval_compare(struct compat_timeval *lhs, - struct compat_timeval *rhs) +static inline int old_timeval32_compare(struct old_timeval32 *lhs, + struct old_timeval32 *rhs) { if (lhs->tv_sec < rhs->tv_sec) return -1; @@ -467,8 +467,8 @@ static inline int compat_timeval_compare(struct compat_timeval *lhs, return lhs->tv_usec - rhs->tv_usec; } -static inline int compat_timespec_compare(struct compat_timespec *lhs, - struct compat_timespec *rhs) +static inline int old_timespec32_compare(struct old_timespec32 *lhs, + struct old_timespec32 *rhs) { if (lhs->tv_sec < rhs->tv_sec) return -1; @@ -552,12 +552,12 @@ asmlinkage long compat_sys_io_getevents(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, - struct compat_timespec __user *timeout); + struct old_timespec32 __user *timeout); asmlinkage long compat_sys_io_pgetevents(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, - struct compat_timespec __user *timeout, + struct old_timespec32 __user *timeout, const struct __compat_aio_sigset __user *usig); /* fs/cookies.c */ @@ -642,11 +642,11 @@ asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd, asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, - struct compat_timespec __user *tsp, + struct old_timespec32 __user *tsp, void __user *sig); asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, - struct compat_timespec __user *tsp, + struct old_timespec32 __user *tsp, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize); @@ -671,15 +671,15 @@ asmlinkage long compat_sys_newfstat(unsigned int fd, /* fs/timerfd.c */ asmlinkage long compat_sys_timerfd_gettime(int ufd, - struct compat_itimerspec __user *otmr); + struct old_itimerspec32 __user *otmr); asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, - const struct compat_itimerspec __user *utmr, - struct compat_itimerspec __user *otmr); + const struct old_itimerspec32 __user *utmr, + struct old_itimerspec32 __user *otmr); /* fs/utimes.c */ asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, - struct compat_timespec __user *t, + struct old_timespec32 __user *t, int flags); /* kernel/exit.c */ @@ -691,7 +691,7 @@ asmlinkage long compat_sys_waitid(int, compat_pid_t, /* kernel/futex.c */ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, - struct compat_timespec __user *utime, u32 __user *uaddr2, + struct old_timespec32 __user *utime, u32 __user *uaddr2, u32 val3); asmlinkage long compat_sys_set_robust_list(struct compat_robust_list_head __user *head, @@ -701,8 +701,8 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, compat_size_t __user *len_ptr); /* kernel/hrtimer.c */ -asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, - struct compat_timespec __user *rmtp); +asmlinkage long compat_sys_nanosleep(struct old_timespec32 __user *rqtp, + struct old_timespec32 __user *rmtp); /* kernel/itimer.c */ asmlinkage long compat_sys_getitimer(int which, @@ -722,19 +722,19 @@ asmlinkage long compat_sys_timer_create(clockid_t which_clock, struct compat_sigevent __user *timer_event_spec, timer_t __user *created_timer_id); asmlinkage long compat_sys_timer_gettime(timer_t timer_id, - struct compat_itimerspec __user *setting); + struct old_itimerspec32 __user *setting); asmlinkage long compat_sys_timer_settime(timer_t timer_id, int flags, - struct compat_itimerspec __user *new, - struct compat_itimerspec __user *old); + struct old_itimerspec32 __user *new, + struct old_itimerspec32 __user *old); asmlinkage long compat_sys_clock_settime(clockid_t which_clock, - struct compat_timespec __user *tp); + struct old_timespec32 __user *tp); asmlinkage long compat_sys_clock_gettime(clockid_t which_clock, - struct compat_timespec __user *tp); + struct old_timespec32 __user *tp); asmlinkage long compat_sys_clock_getres(clockid_t which_clock, - struct compat_timespec __user *tp); + struct old_timespec32 __user *tp); asmlinkage long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, - struct compat_timespec __user *rqtp, - struct compat_timespec __user *rmtp); + struct old_timespec32 __user *rqtp, + struct old_timespec32 __user *rmtp); /* kernel/ptrace.c */ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, @@ -748,7 +748,7 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, compat_ulong_t __user *user_mask_ptr); asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, - struct compat_timespec __user *interval); + struct old_timespec32 __user *interval); /* kernel/signal.c */ asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, @@ -768,7 +768,7 @@ asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, compat_size_t sigsetsize); asmlinkage long compat_sys_rt_sigtimedwait(compat_sigset_t __user *uthese, struct compat_siginfo __user *uinfo, - struct compat_timespec __user *uts, compat_size_t sigsetsize); + struct old_timespec32 __user *uts, compat_size_t sigsetsize); asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, struct compat_siginfo __user *uinfo); /* No generic prototype for rt_sigreturn */ @@ -782,9 +782,9 @@ asmlinkage long compat_sys_setrlimit(unsigned int resource, asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru); /* kernel/time.c */ -asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, +asmlinkage long compat_sys_gettimeofday(struct old_timeval32 __user *tv, struct timezone __user *tz); -asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, +asmlinkage long compat_sys_settimeofday(struct old_timeval32 __user *tv, struct timezone __user *tz); asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); @@ -798,11 +798,11 @@ asmlinkage long compat_sys_mq_open(const char __user *u_name, asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, compat_size_t msg_len, unsigned int msg_prio, - const struct compat_timespec __user *u_abs_timeout); + const struct old_timespec32 __user *u_abs_timeout); asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, compat_size_t msg_len, unsigned int __user *u_msg_prio, - const struct compat_timespec __user *u_abs_timeout); + const struct old_timespec32 __user *u_abs_timeout); asmlinkage long compat_sys_mq_notify(mqd_t mqdes, const struct compat_sigevent __user *u_notification); asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes, @@ -819,7 +819,7 @@ asmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp, /* ipc/sem.c */ asmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg); asmlinkage long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, - unsigned nsems, const struct compat_timespec __user *timeout); + unsigned nsems, const struct old_timespec32 __user *timeout); /* ipc/shm.c */ asmlinkage long compat_sys_shmctl(int first, int second, void __user *uptr); @@ -876,7 +876,7 @@ asmlinkage long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, struct compat_siginfo __user *uinfo); asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags, - struct compat_timespec __user *timeout); + struct old_timespec32 __user *timeout); asmlinkage long compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru); @@ -928,7 +928,7 @@ asmlinkage long compat_sys_pwritev64v2(unsigned long fd, asmlinkage long compat_sys_open(const char __user *filename, int flags, umode_t mode); asmlinkage long compat_sys_utimes(const char __user *filename, - struct compat_timeval __user *t); + struct old_timeval32 __user *t); /* __ARCH_WANT_SYSCALL_NO_FLAGS */ asmlinkage long compat_sys_signalfd(int ufd, @@ -942,15 +942,15 @@ asmlinkage long compat_sys_newlstat(const char __user *filename, struct compat_stat __user *statbuf); /* __ARCH_WANT_SYSCALL_DEPRECATED */ -asmlinkage long compat_sys_time(compat_time_t __user *tloc); +asmlinkage long compat_sys_time(old_time32_t __user *tloc); asmlinkage long compat_sys_utime(const char __user *filename, struct compat_utimbuf __user *t); asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, - struct compat_timeval __user *t); + struct old_timeval32 __user *t); asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, - struct compat_timeval __user *tvp); + struct old_timeval32 __user *tvp); asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32); asmlinkage long compat_sys_recv(int fd, void __user *buf, compat_size_t len, unsigned flags); @@ -983,7 +983,7 @@ asmlinkage long compat_sys_sigaction(int sig, #endif /* obsolete: kernel/time/time.c */ -asmlinkage long compat_sys_stime(compat_time_t __user *tptr); +asmlinkage long compat_sys_stime(old_time32_t __user *tptr); /* obsolete: net/socket.c */ asmlinkage long compat_sys_socketcall(int call, u32 __user *args); @@ -1002,15 +1002,15 @@ static inline bool in_compat_syscall(void) { return is_compat_task(); } #endif /** - * ns_to_compat_timeval - Compat version of ns_to_timeval + * ns_to_old_timeval32 - Compat version of ns_to_timeval * @nsec: the nanoseconds value to be converted * - * Returns the compat_timeval representation of the nsec parameter. + * Returns the old_timeval32 representation of the nsec parameter. */ -static inline struct compat_timeval ns_to_compat_timeval(s64 nsec) +static inline struct old_timeval32 ns_to_old_timeval32(s64 nsec) { struct timeval tv; - struct compat_timeval ctv; + struct old_timeval32 ctv; tv = ns_to_timeval(nsec); ctv.tv_sec = tv.tv_sec; diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h deleted file mode 100644 index e70bfd1d2c3f..000000000000 --- a/include/linux/compat_time.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _LINUX_COMPAT_TIME_H -#define _LINUX_COMPAT_TIME_H - -#include -#include - -typedef s32 compat_time_t; - -struct compat_timespec { - compat_time_t tv_sec; - s32 tv_nsec; -}; - -struct compat_timeval { - compat_time_t tv_sec; - s32 tv_usec; -}; - -struct compat_itimerspec { - struct compat_timespec it_interval; - struct compat_timespec it_value; -}; - -extern int compat_get_timespec64(struct timespec64 *, const void __user *); -extern int compat_put_timespec64(const struct timespec64 *, void __user *); -extern int get_compat_itimerspec64(struct itimerspec64 *its, - const struct compat_itimerspec __user *uits); -extern int put_compat_itimerspec64(const struct itimerspec64 *its, - struct compat_itimerspec __user *uits); - -#endif /* _LINUX_COMPAT_TIME_H */ diff --git a/include/linux/elfcore-compat.h b/include/linux/elfcore-compat.h index b5f2efdd05e0..7a37f4ce9fd2 100644 --- a/include/linux/elfcore-compat.h +++ b/include/linux/elfcore-compat.h @@ -27,10 +27,10 @@ struct compat_elf_prstatus compat_pid_t pr_ppid; compat_pid_t pr_pgrp; compat_pid_t pr_sid; - struct compat_timeval pr_utime; - struct compat_timeval pr_stime; - struct compat_timeval pr_cutime; - struct compat_timeval pr_cstime; + struct old_timeval32 pr_utime; + struct old_timeval32 pr_stime; + struct old_timeval32 pr_cutime; + struct old_timeval32 pr_cstime; compat_elf_gregset_t pr_reg; #ifdef CONFIG_BINFMT_ELF_FDPIC compat_ulong_t pr_exec_fdpic_loadmap; diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h index 5d83d0c1d06c..bba2920e9c05 100644 --- a/include/linux/restart_block.h +++ b/include/linux/restart_block.h @@ -10,7 +10,7 @@ #include struct timespec; -struct compat_timespec; +struct old_timespec32; struct pollfd; enum timespec_type { @@ -40,7 +40,7 @@ struct restart_block { enum timespec_type type; union { struct __kernel_timespec __user *rmtp; - struct compat_timespec __user *compat_rmtp; + struct old_timespec32 __user *compat_rmtp; }; u64 expires; } nanosleep; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 2ff814c92f7f..b3e27e5ee322 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -60,7 +60,7 @@ struct tms; struct utimbuf; struct mq_attr; struct compat_stat; -struct compat_timeval; +struct old_timeval32; struct robust_list_head; struct getcpu_cache; struct old_linux_dirent; diff --git a/include/linux/time32.h b/include/linux/time32.h index 92c0ca092d93..0e0d7304d1a8 100644 --- a/include/linux/time32.h +++ b/include/linux/time32.h @@ -13,6 +13,31 @@ #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) +typedef s32 old_time32_t; + +struct old_timespec32 { + old_time32_t tv_sec; + s32 tv_nsec; +}; + +struct old_timeval32 { + old_time32_t tv_sec; + s32 tv_usec; +}; + +struct old_itimerspec32 { + struct old_timespec32 it_interval; + struct old_timespec32 it_value; +}; + +extern int get_old_timespec32(struct timespec64 *, const void __user *); +extern int put_old_timespec32(const struct timespec64 *, void __user *); +extern int get_old_itimerspec32(struct itimerspec64 *its, + const struct old_itimerspec32 __user *uits); +extern int put_old_itimerspec32(const struct itimerspec64 *its, + struct old_itimerspec32 __user *uits); + + #if __BITS_PER_LONG == 64 /* timespec64 is defined as timespec here */ @@ -183,18 +208,17 @@ extern struct timeval ns_to_timeval(const s64 nsec); extern struct __kernel_old_timeval ns_to_kernel_old_timeval(s64 nsec); /* - * New aliases for compat time functions. These will be used to replace - * the compat code so it can be shared between 32-bit and 64-bit builds - * both of which provide compatibility with old 32-bit tasks. + * Old names for the 32-bit time_t interfaces, these will be removed + * when everything uses the new names. */ -#define old_time32_t compat_time_t -#define old_timeval32 compat_timeval -#define old_timespec32 compat_timespec -#define old_itimerspec32 compat_itimerspec -#define ns_to_old_timeval32 ns_to_compat_timeval -#define get_old_itimerspec32 get_compat_itimerspec64 -#define put_old_itimerspec32 put_compat_itimerspec64 -#define get_old_timespec32 compat_get_timespec64 -#define put_old_timespec32 compat_put_timespec64 +#define compat_time_t old_time32_t +#define compat_timeval old_timeval32 +#define compat_timespec old_timespec32 +#define compat_itimerspec old_itimerspec32 +#define ns_to_compat_timeval ns_to_old_timeval32 +#define get_compat_itimerspec64 get_old_itimerspec32 +#define put_compat_itimerspec64 put_old_itimerspec32 +#define compat_get_timespec64 get_old_timespec32 +#define compat_put_timespec64 put_old_timespec32 #endif diff --git a/ipc/mqueue.c b/ipc/mqueue.c index c0d58f390c3b..db7833370351 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1461,10 +1461,10 @@ COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes, #endif #ifdef CONFIG_COMPAT_32BIT_TIME -static int compat_prepare_timeout(const struct compat_timespec __user *p, +static int compat_prepare_timeout(const struct old_timespec32 __user *p, struct timespec64 *ts) { - if (compat_get_timespec64(ts, p)) + if (get_old_timespec32(ts, p)) return -EFAULT; if (!timespec64_valid(ts)) return -EINVAL; @@ -1474,7 +1474,7 @@ static int compat_prepare_timeout(const struct compat_timespec __user *p, COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, compat_size_t, msg_len, unsigned int, msg_prio, - const struct compat_timespec __user *, u_abs_timeout) + const struct old_timespec32 __user *, u_abs_timeout) { struct timespec64 ts, *p = NULL; if (u_abs_timeout) { @@ -1489,7 +1489,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, compat_size_t, msg_len, unsigned int __user *, u_msg_prio, - const struct compat_timespec __user *, u_abs_timeout) + const struct old_timespec32 __user *, u_abs_timeout) { struct timespec64 ts, *p = NULL; if (u_abs_timeout) { diff --git a/ipc/msg.c b/ipc/msg.c index 883642cf2b27..0833c6405915 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -622,9 +622,9 @@ struct compat_msqid_ds { struct compat_ipc_perm msg_perm; compat_uptr_t msg_first; compat_uptr_t msg_last; - compat_time_t msg_stime; - compat_time_t msg_rtime; - compat_time_t msg_ctime; + old_time32_t msg_stime; + old_time32_t msg_rtime; + old_time32_t msg_ctime; compat_ulong_t msg_lcbytes; compat_ulong_t msg_lqbytes; unsigned short msg_cbytes; diff --git a/ipc/sem.c b/ipc/sem.c index 26f8e37fcdcb..745dc6187e84 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1698,8 +1698,8 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg) struct compat_semid_ds { struct compat_ipc_perm sem_perm; - compat_time_t sem_otime; - compat_time_t sem_ctime; + old_time32_t sem_otime; + old_time32_t sem_ctime; compat_uptr_t sem_base; compat_uptr_t sem_pending; compat_uptr_t sem_pending_last; @@ -2214,11 +2214,11 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, #ifdef CONFIG_COMPAT_32BIT_TIME long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, unsigned int nsops, - const struct compat_timespec __user *timeout) + const struct old_timespec32 __user *timeout) { if (timeout) { struct timespec64 ts; - if (compat_get_timespec64(&ts, timeout)) + if (get_old_timespec32(&ts, timeout)) return -EFAULT; return do_semtimedop(semid, tsems, nsops, &ts); } @@ -2227,7 +2227,7 @@ long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems, unsigned int, nsops, - const struct compat_timespec __user *, timeout) + const struct old_timespec32 __user *, timeout) { return compat_ksys_semtimedop(semid, tsems, nsops, timeout); } diff --git a/ipc/shm.c b/ipc/shm.c index b0eb3757ab89..2657692199eb 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1201,9 +1201,9 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) struct compat_shmid_ds { struct compat_ipc_perm shm_perm; int shm_segsz; - compat_time_t shm_atime; - compat_time_t shm_dtime; - compat_time_t shm_ctime; + old_time32_t shm_atime; + old_time32_t shm_dtime; + old_time32_t shm_ctime; compat_ipc_pid_t shm_cpid; compat_ipc_pid_t shm_lpid; unsigned short shm_nattch; diff --git a/ipc/syscall.c b/ipc/syscall.c index 65d405f1ba0c..1ac06e3983c0 100644 --- a/ipc/syscall.c +++ b/ipc/syscall.c @@ -35,7 +35,7 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, (const struct __kernel_timespec __user *)fifth); else if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME)) return compat_ksys_semtimedop(first, ptr, second, - (const struct compat_timespec __user *)fifth); + (const struct old_timespec32 __user *)fifth); else return -ENOSYS; diff --git a/ipc/util.h b/ipc/util.h index 0a159f69b3bb..1ee81bce25e9 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -266,7 +266,7 @@ long ksys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); /* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */ long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, unsigned int nsops, - const struct compat_timespec __user *timeout); + const struct old_timespec32 __user *timeout); #ifdef CONFIG_COMPAT long compat_ksys_semctl(int semid, int semnum, int cmd, int arg); long compat_ksys_msgctl(int msqid, int cmd, void __user *uptr); diff --git a/kernel/compat.c b/kernel/compat.c index 8e40efc2928a..089d00d0da9c 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -93,28 +93,28 @@ int compat_put_timex(struct compat_timex __user *utp, const struct timex *txc) return 0; } -static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv) +static int __compat_get_timeval(struct timeval *tv, const struct old_timeval32 __user *ctv) { return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) || __get_user(tv->tv_sec, &ctv->tv_sec) || __get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0; } -static int __compat_put_timeval(const struct timeval *tv, struct compat_timeval __user *ctv) +static int __compat_put_timeval(const struct timeval *tv, struct old_timeval32 __user *ctv) { return (!access_ok(VERIFY_WRITE, ctv, sizeof(*ctv)) || __put_user(tv->tv_sec, &ctv->tv_sec) || __put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0; } -static int __compat_get_timespec(struct timespec *ts, const struct compat_timespec __user *cts) +static int __compat_get_timespec(struct timespec *ts, const struct old_timespec32 __user *cts) { return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || __get_user(ts->tv_sec, &cts->tv_sec) || __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; } -static int __compat_put_timespec(const struct timespec *ts, struct compat_timespec __user *cts) +static int __compat_put_timespec(const struct timespec *ts, struct old_timespec32 __user *cts) { return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) || __put_user(ts->tv_sec, &cts->tv_sec) || diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 83f830acbb5f..410a77a8f6e2 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -173,7 +173,7 @@ err_unlock: } COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, - struct compat_timespec __user *, utime, u32 __user *, uaddr2, + struct old_timespec32 __user *, utime, u32 __user *, uaddr2, u32, val3) { struct timespec ts; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 625bc9897f62..8287b75ed961 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5257,13 +5257,13 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, #ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, compat_pid_t, pid, - struct compat_timespec __user *, interval) + struct old_timespec32 __user *, interval) { struct timespec64 t; int retval = sched_rr_get_interval(pid, &t); if (retval == 0) - retval = compat_put_timespec64(&t, interval); + retval = put_old_timespec32(&t, interval); return retval; } #endif diff --git a/kernel/signal.c b/kernel/signal.c index 5843c541fda9..a4db724e14c1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3173,7 +3173,7 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese, #ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, struct compat_siginfo __user *, uinfo, - struct compat_timespec __user *, uts, compat_size_t, sigsetsize) + struct old_timespec32 __user *, uts, compat_size_t, sigsetsize) { sigset_t s; struct timespec t; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index e1a549c9e399..9cdd74bd2d27 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1660,7 +1660,7 @@ int nanosleep_copyout(struct restart_block *restart, struct timespec64 *ts) switch(restart->nanosleep.type) { #ifdef CONFIG_COMPAT_32BIT_TIME case TT_COMPAT: - if (compat_put_timespec64(ts, restart->nanosleep.compat_rmtp)) + if (put_old_timespec32(ts, restart->nanosleep.compat_rmtp)) return -EFAULT; break; #endif @@ -1780,12 +1780,12 @@ SYSCALL_DEFINE2(nanosleep, struct __kernel_timespec __user *, rqtp, #ifdef CONFIG_COMPAT_32BIT_TIME -COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, - struct compat_timespec __user *, rmtp) +COMPAT_SYSCALL_DEFINE2(nanosleep, struct old_timespec32 __user *, rqtp, + struct old_timespec32 __user *, rmtp) { struct timespec64 tu; - if (compat_get_timespec64(&tu, rqtp)) + if (get_old_timespec32(&tu, rqtp)) return -EFAULT; if (!timespec64_valid(&tu)) diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c index 2c6847d5d69b..989ccf028bde 100644 --- a/kernel/time/posix-stubs.c +++ b/kernel/time/posix-stubs.c @@ -162,20 +162,20 @@ COMPAT_SYS_NI(setitimer); #ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, - struct compat_timespec __user *, tp) + struct old_timespec32 __user *, tp) { struct timespec64 new_tp; if (which_clock != CLOCK_REALTIME) return -EINVAL; - if (compat_get_timespec64(&new_tp, tp)) + if (get_old_timespec32(&new_tp, tp)) return -EFAULT; return do_sys_settimeofday64(&new_tp, NULL); } COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, - struct compat_timespec __user *, tp) + struct old_timespec32 __user *, tp) { int ret; struct timespec64 kernel_tp; @@ -184,13 +184,13 @@ COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, if (ret) return ret; - if (compat_put_timespec64(&kernel_tp, tp)) + if (put_old_timespec32(&kernel_tp, tp)) return -EFAULT; return 0; } COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, - struct compat_timespec __user *, tp) + struct old_timespec32 __user *, tp) { struct timespec64 rtn_tp = { .tv_sec = 0, @@ -201,7 +201,7 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, case CLOCK_REALTIME: case CLOCK_MONOTONIC: case CLOCK_BOOTTIME: - if (compat_put_timespec64(&rtn_tp, tp)) + if (put_old_timespec32(&rtn_tp, tp)) return -EFAULT; return 0; default: @@ -210,8 +210,8 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, } COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, - struct compat_timespec __user *, rqtp, - struct compat_timespec __user *, rmtp) + struct old_timespec32 __user *, rqtp, + struct old_timespec32 __user *, rmtp) { struct timespec64 t; @@ -224,7 +224,7 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, return -EINVAL; } - if (compat_get_timespec64(&t, rqtp)) + if (get_old_timespec32(&t, rqtp)) return -EFAULT; if (!timespec64_valid(&t)) return -EINVAL; diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 4b9127e95430..3e71921668ba 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -755,13 +755,13 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, #ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, - struct compat_itimerspec __user *, setting) + struct old_itimerspec32 __user *, setting) { struct itimerspec64 cur_setting; int ret = do_timer_gettime(timer_id, &cur_setting); if (!ret) { - if (put_compat_itimerspec64(&cur_setting, setting)) + if (put_old_itimerspec32(&cur_setting, setting)) ret = -EFAULT; } return ret; @@ -928,8 +928,8 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, #ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, - struct compat_itimerspec __user *, new, - struct compat_itimerspec __user *, old) + struct old_itimerspec32 __user *, new, + struct old_itimerspec32 __user *, old) { struct itimerspec64 new_spec, old_spec; struct itimerspec64 *rtn = old ? &old_spec : NULL; @@ -937,12 +937,12 @@ COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, if (!new) return -EINVAL; - if (get_compat_itimerspec64(&new_spec, new)) + if (get_old_itimerspec32(&new_spec, new)) return -EFAULT; error = do_timer_settime(timer_id, flags, &new_spec, rtn); if (!error && old) { - if (put_compat_itimerspec64(&old_spec, old)) + if (put_old_itimerspec32(&old_spec, old)) error = -EFAULT; } return error; @@ -1115,7 +1115,7 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, #ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock, - struct compat_timespec __user *, tp) + struct old_timespec32 __user *, tp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 ts; @@ -1123,14 +1123,14 @@ COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock, if (!kc || !kc->clock_set) return -EINVAL; - if (compat_get_timespec64(&ts, tp)) + if (get_old_timespec32(&ts, tp)) return -EFAULT; return kc->clock_set(which_clock, &ts); } COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, - struct compat_timespec __user *, tp) + struct old_timespec32 __user *, tp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 ts; @@ -1141,7 +1141,7 @@ COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, err = kc->clock_get(which_clock, &ts); - if (!err && compat_put_timespec64(&ts, tp)) + if (!err && put_old_timespec32(&ts, tp)) err = -EFAULT; return err; @@ -1180,7 +1180,7 @@ COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock, #ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, - struct compat_timespec __user *, tp) + struct old_timespec32 __user *, tp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 ts; @@ -1190,7 +1190,7 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, return -EINVAL; err = kc->clock_getres(which_clock, &ts); - if (!err && tp && compat_put_timespec64(&ts, tp)) + if (!err && tp && put_old_timespec32(&ts, tp)) return -EFAULT; return err; @@ -1237,8 +1237,8 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, #ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, - struct compat_timespec __user *, rqtp, - struct compat_timespec __user *, rmtp) + struct old_timespec32 __user *, rqtp, + struct old_timespec32 __user *, rmtp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 t; @@ -1248,7 +1248,7 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, if (!kc->nsleep) return -EOPNOTSUPP; - if (compat_get_timespec64(&t, rqtp)) + if (get_old_timespec32(&t, rqtp)) return -EFAULT; if (!timespec64_valid(&t)) diff --git a/kernel/time/time.c b/kernel/time/time.c index de332250d6fa..f1983f468fe3 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -104,12 +104,12 @@ SYSCALL_DEFINE1(stime, time_t __user *, tptr) #ifdef CONFIG_COMPAT #ifdef __ARCH_WANT_COMPAT_SYS_TIME -/* compat_time_t is a 32 bit "long" and needs to get converted. */ -COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc) +/* old_time32_t is a 32 bit "long" and needs to get converted. */ +COMPAT_SYSCALL_DEFINE1(time, old_time32_t __user *, tloc) { - compat_time_t i; + old_time32_t i; - i = (compat_time_t)ktime_get_real_seconds(); + i = (old_time32_t)ktime_get_real_seconds(); if (tloc) { if (put_user(i,tloc)) @@ -119,7 +119,7 @@ COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc) return i; } -COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr) +COMPAT_SYSCALL_DEFINE1(stime, old_time32_t __user *, tptr) { struct timespec64 tv; int err; @@ -225,7 +225,7 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv, } #ifdef CONFIG_COMPAT -COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv, +COMPAT_SYSCALL_DEFINE2(gettimeofday, struct old_timeval32 __user *, tv, struct timezone __user *, tz) { if (tv) { @@ -244,7 +244,7 @@ COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv, return 0; } -COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, +COMPAT_SYSCALL_DEFINE2(settimeofday, struct old_timeval32 __user *, tv, struct timezone __user *, tz) { struct timespec64 new_ts; @@ -863,10 +863,10 @@ int put_timespec64(const struct timespec64 *ts, } EXPORT_SYMBOL_GPL(put_timespec64); -int __compat_get_timespec64(struct timespec64 *ts64, - const struct compat_timespec __user *cts) +int __get_old_timespec32(struct timespec64 *ts64, + const struct old_timespec32 __user *cts) { - struct compat_timespec ts; + struct old_timespec32 ts; int ret; ret = copy_from_user(&ts, cts, sizeof(ts)); @@ -879,33 +879,33 @@ int __compat_get_timespec64(struct timespec64 *ts64, return 0; } -int __compat_put_timespec64(const struct timespec64 *ts64, - struct compat_timespec __user *cts) +int __put_old_timespec32(const struct timespec64 *ts64, + struct old_timespec32 __user *cts) { - struct compat_timespec ts = { + struct old_timespec32 ts = { .tv_sec = ts64->tv_sec, .tv_nsec = ts64->tv_nsec }; return copy_to_user(cts, &ts, sizeof(ts)) ? -EFAULT : 0; } -int compat_get_timespec64(struct timespec64 *ts, const void __user *uts) +int get_old_timespec32(struct timespec64 *ts, const void __user *uts) { if (COMPAT_USE_64BIT_TIME) return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0; else - return __compat_get_timespec64(ts, uts); + return __get_old_timespec32(ts, uts); } -EXPORT_SYMBOL_GPL(compat_get_timespec64); +EXPORT_SYMBOL_GPL(get_old_timespec32); -int compat_put_timespec64(const struct timespec64 *ts, void __user *uts) +int put_old_timespec32(const struct timespec64 *ts, void __user *uts) { if (COMPAT_USE_64BIT_TIME) return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0; else - return __compat_put_timespec64(ts, uts); + return __put_old_timespec32(ts, uts); } -EXPORT_SYMBOL_GPL(compat_put_timespec64); +EXPORT_SYMBOL_GPL(put_old_timespec32); int get_itimerspec64(struct itimerspec64 *it, const struct __kernel_itimerspec __user *uit) @@ -937,23 +937,23 @@ int put_itimerspec64(const struct itimerspec64 *it, } EXPORT_SYMBOL_GPL(put_itimerspec64); -int get_compat_itimerspec64(struct itimerspec64 *its, - const struct compat_itimerspec __user *uits) +int get_old_itimerspec32(struct itimerspec64 *its, + const struct old_itimerspec32 __user *uits) { - if (__compat_get_timespec64(&its->it_interval, &uits->it_interval) || - __compat_get_timespec64(&its->it_value, &uits->it_value)) + if (__get_old_timespec32(&its->it_interval, &uits->it_interval) || + __get_old_timespec32(&its->it_value, &uits->it_value)) return -EFAULT; return 0; } -EXPORT_SYMBOL_GPL(get_compat_itimerspec64); +EXPORT_SYMBOL_GPL(get_old_itimerspec32); -int put_compat_itimerspec64(const struct itimerspec64 *its, - struct compat_itimerspec __user *uits) +int put_old_itimerspec32(const struct itimerspec64 *its, + struct old_itimerspec32 __user *uits) { - if (__compat_put_timespec64(&its->it_interval, &uits->it_interval) || - __compat_put_timespec64(&its->it_value, &uits->it_value)) + if (__put_old_timespec32(&its->it_interval, &uits->it_interval) || + __put_old_timespec32(&its->it_value, &uits->it_value)) return -EFAULT; return 0; } -EXPORT_SYMBOL_GPL(put_compat_itimerspec64); +EXPORT_SYMBOL_GPL(put_old_itimerspec32); diff --git a/net/compat.c b/net/compat.c index 3b2105f6549d..2ef160876bc1 100644 --- a/net/compat.c +++ b/net/compat.c @@ -812,7 +812,7 @@ COMPAT_SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, buf, compat_size_t, len static int __compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, - struct compat_timespec __user *timeout) + struct old_timespec32 __user *timeout) { int datagrams; struct timespec ktspec; @@ -834,7 +834,7 @@ static int __compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, unsigned int, vlen, unsigned int, flags, - struct compat_timespec __user *, timeout) + struct old_timespec32 __user *, timeout) { return __compat_sys_recvmmsg(fd, mmsg, vlen, flags, timeout); } -- cgit v1.2.3-59-g8ed1b From 743f5cdb6cec33d2300922f6b1b1670a572595ad Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Wed, 29 Aug 2018 20:50:52 +0800 Subject: y2038: __get_old_timespec32() can be static The kbuild test robot reports two new warnings with the previous patch: kernel/time/time.c:866:5: sparse: symbol '__get_old_timespec32' was not declared. Should it be static? kernel/time/time.c:882:5: sparse: symbol '__put_old_timespec32' was not declared. Should it be static? These are actually older bugs, but came up now after the symbol got renamed. Fortunately, commit afef05cf238c ("time: Enable get/put_compat_itimerspec64 always") makes the two functions (__compat_get_timespec64/__compat_get_timespec64) local to time.c already, so we can mark them as 'static'. Fixes: ee16c8f415e4 ("y2038: Globally rename compat_time to old_time32") Signed-off-by: kbuild test robot [arnd: added changelog text] Signed-off-by: Arnd Bergmann --- kernel/time/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/time.c b/kernel/time/time.c index f1983f468fe3..e3a7f7fd3abc 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -863,7 +863,7 @@ int put_timespec64(const struct timespec64 *ts, } EXPORT_SYMBOL_GPL(put_timespec64); -int __get_old_timespec32(struct timespec64 *ts64, +static int __get_old_timespec32(struct timespec64 *ts64, const struct old_timespec32 __user *cts) { struct old_timespec32 ts; @@ -879,7 +879,7 @@ int __get_old_timespec32(struct timespec64 *ts64, return 0; } -int __put_old_timespec32(const struct timespec64 *ts64, +static int __put_old_timespec32(const struct timespec64 *ts64, struct old_timespec32 __user *cts) { struct old_timespec32 ts = { -- cgit v1.2.3-59-g8ed1b From 82b355d161c9525ab8838cc27d3200bc3bc9082d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 13 Apr 2018 11:50:12 +0200 Subject: y2038: Remove newstat family from default syscall set We have four generations of stat() syscalls: - the oldstat syscalls that are only used on the older architectures - the newstat family that is used on all 64-bit architectures but lacked support for large files on 32-bit architectures. - the stat64 family that is used mostly on 32-bit architectures to replace newstat - statx() to replace all of the above, adding 64-bit timestamps among other things. We already compile stat64 only on those architectures that need it, but newstat is always built, including on those that don't reference it. This adds a new __ARCH_WANT_NEW_STAT symbol along the lines of __ARCH_WANT_OLD_STAT and __ARCH_WANT_STAT64 to control compilation of newstat. All architectures that need it use an explict define, the others now get a little bit smaller, and future architecture (including 64-bit targets) won't ever see it. Acked-by: Geert Uytterhoeven Signed-off-by: Arnd Bergmann --- arch/alpha/include/asm/unistd.h | 1 + arch/arm/include/asm/unistd.h | 1 + arch/arm64/include/uapi/asm/unistd.h | 1 + arch/ia64/include/asm/unistd.h | 2 ++ arch/m68k/include/asm/unistd.h | 1 + arch/microblaze/include/asm/unistd.h | 1 + arch/mips/include/asm/unistd.h | 1 + arch/parisc/include/asm/unistd.h | 1 + arch/powerpc/include/asm/unistd.h | 1 + arch/s390/include/asm/unistd.h | 1 + arch/sh/include/asm/unistd.h | 1 + arch/sparc/include/asm/unistd.h | 1 + arch/x86/include/asm/unistd.h | 1 + arch/xtensa/include/asm/unistd.h | 1 + fs/stat.c | 3 +++ 15 files changed, 18 insertions(+) diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index d6e29a1de4cc..edc090470023 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -6,6 +6,7 @@ #define NR_SYSCALLS 523 +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 076090d2dbf5..07e58010d597 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -16,6 +16,7 @@ #include #include +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h index 5072cbd15c82..dae1584cf017 100644 --- a/arch/arm64/include/uapi/asm/unistd.h +++ b/arch/arm64/include/uapi/asm/unistd.h @@ -16,5 +16,6 @@ */ #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_NEW_STAT #include diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index ffb705dc9c13..c5b2620c4a4c 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h @@ -28,6 +28,8 @@ #define __IGNORE_vfork /* clone() */ #define __IGNORE_umount2 /* umount() */ +#define __ARCH_WANT_NEW_STAT + #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) #include diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 30d0d3fbd4ef..db22cdadc38a 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -7,6 +7,7 @@ #define NR_syscalls 380 +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index a62d09420a47..a28dc770c9b2 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -15,6 +15,7 @@ /* #define __ARCH_WANT_OLD_READDIR */ /* #define __ARCH_WANT_OLD_STAT */ +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 3c09450908aa..d7878b3e16d8 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -24,6 +24,7 @@ #ifndef __ASSEMBLY__ +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 3d507d04eb4c..b36273bacca7 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -141,6 +141,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ return K_INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \ } +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index c19379f0a32e..8b37e01817be 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -22,6 +22,7 @@ #include #include +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index fd79c0d35dc4..1d181373288a 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -15,6 +15,7 @@ #define __IGNORE_pkey_alloc #define __IGNORE_pkey_free +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h index b36200af9ce7..a845b57eac69 100644 --- a/arch/sh/include/asm/unistd.h +++ b/arch/sh/include/asm/unistd.h @@ -5,6 +5,7 @@ # include # endif +# define __ARCH_WANT_NEW_STAT # define __ARCH_WANT_OLD_READDIR # define __ARCH_WANT_OLD_STAT # define __ARCH_WANT_STAT64 diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index b2a6a955113e..3544244685e1 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -21,6 +21,7 @@ #else #define __NR_time 231 /* Linux sparc32 */ #endif +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 51c4eee00732..35b66bbf8028 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -31,6 +31,7 @@ # endif +# define __ARCH_WANT_NEW_STAT # define __ARCH_WANT_OLD_READDIR # define __ARCH_WANT_OLD_STAT # define __ARCH_WANT_SYS_ALARM diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index ed66db3bc9bb..0d532ab60b37 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -5,6 +5,7 @@ #define __ARCH_WANT_SYS_CLONE #include +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_LLSEEK diff --git a/fs/stat.c b/fs/stat.c index f8e6fb2c3657..adbfcd86c81b 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -280,6 +280,8 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat #endif /* __ARCH_WANT_OLD_STAT */ +#ifdef __ARCH_WANT_NEW_STAT + #if BITS_PER_LONG == 32 # define choose_32_64(a,b) a #else @@ -378,6 +380,7 @@ SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf) return error; } +#endif static int do_readlinkat(int dfd, const char __user *pathname, char __user *buf, int bufsiz) -- cgit v1.2.3-59-g8ed1b From bf4b6a7d371e4d2a23a9d545bee908f67d32b3ea Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 13 Apr 2018 12:19:47 +0200 Subject: y2038: Remove stat64 family from default syscall set New architectures should no longer need stat64, which is not y2038 safe and has been replaced by statx(). This removes the 'select __ARCH_WANT_STAT64' statement from asm-generic/unistd.h and instead moves it into the respective asm/unistd.h UAPI header files for each architecture that uses it today. In the generic file, the system call number and entry points are now made conditional, so newly added architectures (e.g. riscv32 or csky) will never need to carry backwards compatiblity for it. arm64 is the only 64-bit architecture using the asm-generic/unistd.h file, and it already sets __ARCH_WANT_NEW_STAT in its headers, and I use the same #ifdef here: future 64-bit architectures therefore won't see newstat or stat64 any more. They don't suffer from the y2038 time_t overflow, but for consistency it seems best to also let them use statx(). Signed-off-by: Arnd Bergmann --- arch/arc/include/uapi/asm/unistd.h | 1 + arch/c6x/include/uapi/asm/unistd.h | 1 + arch/h8300/include/uapi/asm/unistd.h | 1 + arch/hexagon/include/uapi/asm/unistd.h | 1 + arch/nds32/include/uapi/asm/unistd.h | 1 + arch/nios2/include/uapi/asm/unistd.h | 1 + arch/openrisc/include/uapi/asm/unistd.h | 1 + arch/unicore32/include/uapi/asm/unistd.h | 1 + include/asm-generic/unistd.h | 1 - include/uapi/asm-generic/unistd.h | 2 ++ 10 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arc/include/uapi/asm/unistd.h b/arch/arc/include/uapi/asm/unistd.h index 517178b1daef..3b3543fd151c 100644 --- a/arch/arc/include/uapi/asm/unistd.h +++ b/arch/arc/include/uapi/asm/unistd.h @@ -17,6 +17,7 @@ #define _UAPI_ASM_ARC_UNISTD_H #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_VFORK diff --git a/arch/c6x/include/uapi/asm/unistd.h b/arch/c6x/include/uapi/asm/unistd.h index 0d2daf7f9809..6b2fe792de9d 100644 --- a/arch/c6x/include/uapi/asm/unistd.h +++ b/arch/c6x/include/uapi/asm/unistd.h @@ -16,6 +16,7 @@ */ #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_CLONE /* Use the standard ABI for syscalls. */ diff --git a/arch/h8300/include/uapi/asm/unistd.h b/arch/h8300/include/uapi/asm/unistd.h index 7dd20ef7625a..628195823816 100644 --- a/arch/h8300/include/uapi/asm/unistd.h +++ b/arch/h8300/include/uapi/asm/unistd.h @@ -1,5 +1,6 @@ #define __ARCH_NOMMU #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #include diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h index ea181e79162e..c91ca7d02461 100644 --- a/arch/hexagon/include/uapi/asm/unistd.h +++ b/arch/hexagon/include/uapi/asm/unistd.h @@ -29,6 +29,7 @@ #define sys_mmap2 sys_mmap_pgoff #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_VFORK diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h index 6e95901cabe3..603e826e0449 100644 --- a/arch/nds32/include/uapi/asm/unistd.h +++ b/arch/nds32/include/uapi/asm/unistd.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2005-2017 Andes Technology Corporation +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYNC_FILE_RANGE2 /* Use the standard ABI for syscalls */ diff --git a/arch/nios2/include/uapi/asm/unistd.h b/arch/nios2/include/uapi/asm/unistd.h index b6bdae04bc84..d9948d88790b 100644 --- a/arch/nios2/include/uapi/asm/unistd.h +++ b/arch/nios2/include/uapi/asm/unistd.h @@ -19,6 +19,7 @@ #define sys_mmap2 sys_mmap_pgoff #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 /* Use the standard ABI for syscalls */ #include diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h index 11c5a58ab333..ec37df18d8ed 100644 --- a/arch/openrisc/include/uapi/asm/unistd.h +++ b/arch/openrisc/include/uapi/asm/unistd.h @@ -20,6 +20,7 @@ #define sys_mmap2 sys_mmap_pgoff #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_CLONE diff --git a/arch/unicore32/include/uapi/asm/unistd.h b/arch/unicore32/include/uapi/asm/unistd.h index 65856eaab163..1e8fe5941b8a 100644 --- a/arch/unicore32/include/uapi/asm/unistd.h +++ b/arch/unicore32/include/uapi/asm/unistd.h @@ -15,4 +15,5 @@ /* Use the standard ABI for syscalls. */ #include +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_CLONE diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index cdf904265caf..ea74eca8463f 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -8,6 +8,5 @@ * be selected by default. */ #if __BITS_PER_LONG == 32 -#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_LLSEEK #endif diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index df4bedb9b01c..538546edbfbd 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -242,10 +242,12 @@ __SYSCALL(__NR_tee, sys_tee) /* fs/stat.c */ #define __NR_readlinkat 78 __SYSCALL(__NR_readlinkat, sys_readlinkat) +#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64) #define __NR3264_fstatat 79 __SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat) #define __NR3264_fstat 80 __SC_3264(__NR3264_fstat, sys_fstat64, sys_newfstat) +#endif /* fs/sync.c */ #define __NR_sync 81 -- cgit v1.2.3-59-g8ed1b From fb3739759474d150a9927b920a80ea2afb4c2a51 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 18 Apr 2018 22:01:26 +0200 Subject: asm-generic: Move common compat types to asm-generic/compat.h While converting compat system call handlers to work on 32-bit architectures, I found a number of types used in those handlers that are identical between all architectures. Let's move all the identical ones into asm-generic/compat.h to avoid having to add even more identical definitions of those types. For unknown reasons, mips defines __compat_gid32_t, __compat_uid32_t and compat_caddr_t as signed, while all others have them unsigned. This seems to be a mistake, but I'm leaving it alone here. The other types all differ by size or alignment on at least on architecture. compat_aio_context_t is currently defined in linux/compat.h but also needed for compat_sys_io_getevents(), so let's move it into the same place. While we still have not decided whether the 32-bit time handling will always use the compat syscalls, or in which form, I think this is a useful cleanup that we can merge regardless. Reviewed-by: Christoph Hellwig Signed-off-by: Arnd Bergmann --- arch/arm64/include/asm/compat.h | 20 ++------------------ arch/mips/include/asm/compat.h | 22 ++-------------------- arch/parisc/include/asm/compat.h | 18 ++---------------- arch/powerpc/include/asm/compat.h | 18 ++---------------- arch/s390/include/asm/compat.h | 18 ++---------------- arch/sparc/include/asm/compat.h | 19 ++----------------- arch/x86/include/asm/compat.h | 19 ++----------------- include/asm-generic/compat.h | 24 +++++++++++++++++++++++- include/linux/compat.h | 2 -- 9 files changed, 37 insertions(+), 123 deletions(-) diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 4a89007db14a..ee689d8a026d 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -25,6 +25,8 @@ #include #include +#include + #define COMPAT_USER_HZ 100 #ifdef __AARCH64EB__ #define COMPAT_UTS_MACHINE "armv8b\0\0" @@ -32,10 +34,6 @@ #define COMPAT_UTS_MACHINE "armv8l\0\0" #endif -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u16 __compat_uid16_t; @@ -43,27 +41,13 @@ typedef u16 __compat_gid16_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef s32 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s16 compat_short_t; -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u16 compat_ushort_t; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { #ifdef __AARCH64EB__ diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 7dcbd855814e..c99166eadbde 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -9,43 +9,25 @@ #include #include +#include + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "mips\0\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_suseconds_t; - -typedef s32 compat_pid_t; typedef s32 __compat_uid_t; typedef s32 __compat_gid_t; typedef __compat_uid_t __compat_uid32_t; typedef __compat_gid_t __compat_gid32_t; typedef u32 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u32 compat_nlink_t; typedef s32 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef s32 compat_caddr_t; typedef struct { s32 val[2]; } compat_fsid_t; -typedef s32 compat_timer_t; -typedef s32 compat_key_t; - -typedef s16 compat_short_t; -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u16 compat_ushort_t; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 32dadaf2b534..e03e3c849f40 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -8,36 +8,22 @@ #include #include +#include + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "parisc\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u32 __compat_uid_t; typedef u32 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; /* dev_t is 32 bits on parisc */ diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 93f79d1a03c3..74d0db511099 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -8,6 +8,8 @@ #include #include +#include + #define COMPAT_USER_HZ 100 #ifdef __BIG_ENDIAN__ #define COMPAT_UTS_MACHINE "ppc\0\0" @@ -15,34 +17,18 @@ #define COMPAT_UTS_MACHINE "ppcle\0\0" #endif -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u32 __compat_uid_t; typedef u32 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u32 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef s16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 97db2fba546a..63b46e30b2c3 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -9,6 +9,8 @@ #include #include +#include + #define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p( \ typeof(0?(__force t)0:0ULL), u64)) @@ -51,34 +53,18 @@ #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "s390\0\0\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u16 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; typedef struct { u32 mask; diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 7018cb60beef..30b1763580b1 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -6,38 +6,23 @@ */ #include +#include + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "sparc\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u16 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef s16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; - struct compat_stat { compat_dev_t st_dev; compat_ino_t st_ino; diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index fb97cf7c4137..0ce6f452d334 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -12,38 +12,23 @@ #include #include +#include + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "i686\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u16 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_timer_t; -typedef s32 compat_key_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 __attribute__((aligned(4))) compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; -typedef u32 compat_u32; typedef u64 __attribute__((aligned(4))) compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; diff --git a/include/asm-generic/compat.h b/include/asm-generic/compat.h index 28819451b6d1..a86f65bffab8 100644 --- a/include/asm-generic/compat.h +++ b/include/asm-generic/compat.h @@ -1,3 +1,25 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_GENERIC_COMPAT_H +#define __ASM_GENERIC_COMPAT_H -/* This is an empty stub for 32-bit-only architectures */ +/* These types are common across all compat ABIs */ +typedef u32 compat_size_t; +typedef s32 compat_ssize_t; +typedef s32 compat_clock_t; +typedef s32 compat_pid_t; +typedef u32 compat_ino_t; +typedef s32 compat_off_t; +typedef s64 compat_loff_t; +typedef s32 compat_daddr_t; +typedef s32 compat_timer_t; +typedef s32 compat_key_t; +typedef s16 compat_short_t; +typedef s32 compat_int_t; +typedef s32 compat_long_t; +typedef u16 compat_ushort_t; +typedef u32 compat_uint_t; +typedef u32 compat_ulong_t; +typedef u32 compat_uptr_t; +typedef u32 compat_aio_context_t; + +#endif diff --git a/include/linux/compat.h b/include/linux/compat.h index 0e058792ecf6..d376fa8be00d 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -110,8 +110,6 @@ typedef struct compat_sigaltstack { typedef __compat_uid32_t compat_uid_t; typedef __compat_gid32_t compat_gid_t; -typedef compat_ulong_t compat_aio_context_t; - struct compat_sel_arg_struct; struct rusage; -- cgit v1.2.3-59-g8ed1b From caf6f9c8a326cffd1d4b3ff3f1cfba75d159d70b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 13 Apr 2018 12:57:26 +0200 Subject: asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro The sys_llseek sytem call is needed on all 32-bit architectures and none of the 64-bit ones, so we can remove the __ARCH_WANT_SYS_LLSEEK guard and simplify the include/asm-generic/unistd.h header further. Since 32-bit tasks can run either natively or in compat mode on 64-bit architectures, we have to check for both !CONFIG_64BIT and CONFIG_COMPAT. There are a few 64-bit architectures that also reference sys_llseek in their 64-bit ABI (e.g. sparc), but I verified that those all select CONFIG_COMPAT, so the #if check is still correct here. It's a bit odd to include it in the syscall table though, as it's the same as sys_lseek() on 64-bit, but with strange calling conventions. Acked-by: Geert Uytterhoeven Reviewed-by: Christoph Hellwig Signed-off-by: Arnd Bergmann --- arch/arm/include/asm/unistd.h | 1 - arch/arm64/include/asm/unistd.h | 1 - arch/m68k/include/asm/unistd.h | 1 - arch/microblaze/include/asm/unistd.h | 1 - arch/mips/include/asm/unistd.h | 1 - arch/parisc/include/asm/unistd.h | 1 - arch/powerpc/include/asm/unistd.h | 1 - arch/s390/include/asm/unistd.h | 1 - arch/sh/include/asm/unistd.h | 1 - arch/sparc/include/asm/unistd.h | 1 - arch/x86/include/asm/unistd.h | 1 - arch/xtensa/include/asm/unistd.h | 1 - fs/read_write.c | 2 +- include/asm-generic/unistd.h | 9 --------- 14 files changed, 1 insertion(+), 22 deletions(-) diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 07e58010d597..8f1159c26f20 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -21,7 +21,6 @@ #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index e0d0f5b856e7..2af308f13463 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -18,7 +18,6 @@ #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index db22cdadc38a..e680031bda7b 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -22,7 +22,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_MMAP diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index a28dc770c9b2..f42c40f5001b 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -27,7 +27,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE /* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */ #define __ARCH_WANT_SYS_OLDUMOUNT diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index d7878b3e16d8..c2174b80e50e 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -34,7 +34,6 @@ #define __ARCH_WANT_SYS_WAITPID #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_UNAME #define __ARCH_WANT_SYS_OLDUMOUNT diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index b36273bacca7..a0c38374fff0 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -156,7 +156,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 8b37e01817be..9326c9133516 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -36,7 +36,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_UNAME diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 1d181373288a..a2d583ea526d 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -26,7 +26,6 @@ #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_MMAP diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h index a845b57eac69..a99234b61051 100644 --- a/arch/sh/include/asm/unistd.h +++ b/arch/sh/include/asm/unistd.h @@ -20,7 +20,6 @@ # define __ARCH_WANT_SYS_SOCKETCALL # define __ARCH_WANT_SYS_FADVISE64 # define __ARCH_WANT_SYS_GETPGRP -# define __ARCH_WANT_SYS_LLSEEK # define __ARCH_WANT_SYS_NICE # define __ARCH_WANT_SYS_OLD_GETRLIMIT # define __ARCH_WANT_SYS_OLD_UNAME diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 3544244685e1..f7514d3eae7b 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -34,7 +34,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 35b66bbf8028..153d2a5e6b02 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -38,7 +38,6 @@ # define __ARCH_WANT_SYS_FADVISE64 # define __ARCH_WANT_SYS_GETHOSTNAME # define __ARCH_WANT_SYS_GETPGRP -# define __ARCH_WANT_SYS_LLSEEK # define __ARCH_WANT_SYS_NICE # define __ARCH_WANT_SYS_OLDUMOUNT # define __ARCH_WANT_SYS_OLD_GETRLIMIT diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index 0d532ab60b37..574e5520968c 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -8,7 +8,6 @@ #define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_GETPGRP /* diff --git a/fs/read_write.c b/fs/read_write.c index 39b4a21dd933..e892e409386b 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -331,7 +331,7 @@ COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned i } #endif -#ifdef __ARCH_WANT_SYS_LLSEEK +#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, unsigned long, offset_low, loff_t __user *, result, unsigned int, whence) diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index ea74eca8463f..71d2fcf9dbcd 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -1,12 +1,3 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include #include - -/* - * These are required system calls, we should - * invert the logic eventually and let them - * be selected by default. - */ -#if __BITS_PER_LONG == 32 -#define __ARCH_WANT_SYS_LLSEEK -#endif -- cgit v1.2.3-59-g8ed1b From c5ba7e6c9ba545c3f67188de510d4cab2e3223b2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 13 Apr 2018 13:07:57 +0200 Subject: asm-generic: Remove empty asm/unistd.h Nothing is left in asm/unistd.h except for the redirect to uapi/asm/unistd.h, so removing the file simply leads to that one being used directly. The linux/export.h inclusion is a leftover from commit e1b5bb6d1236 ("consolidate cond_syscall and SYSCALL_ALIAS declarations") and should not be used anyway. Reviewed-by: Christoph Hellwig Signed-off-by: Arnd Bergmann --- include/asm-generic/unistd.h | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 include/asm-generic/unistd.h diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h deleted file mode 100644 index 71d2fcf9dbcd..000000000000 --- a/include/asm-generic/unistd.h +++ /dev/null @@ -1,3 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include -#include -- cgit v1.2.3-59-g8ed1b From a4f7a3004630f1a0fb130ab1824942a49ce33140 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 17 Apr 2018 09:11:58 +0200 Subject: y2038: Change sys_utimensat() to use __kernel_timespec When 32-bit architectures get changed to support 64-bit time_t, utimensat() needs to use the new __kernel_timespec structure as its argument. The older utime(), utimes() and futimesat() system calls don't need a corresponding change as they are no longer used on C libraries that have 64-bit time support. As we do for the other syscalls that have timespec arguments, we reuse the 'compat' syscall entry points to implement the traditional four interfaces, and only leave the new utimensat() as a native handler, so that the same code gets used on both 32-bit and 64-bit kernels on each syscall. Signed-off-by: Arnd Bergmann --- fs/utimes.c | 2 +- include/linux/syscalls.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/utimes.c b/fs/utimes.c index 79a65c163f40..d30f409ecc1a 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -166,7 +166,7 @@ out: } SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, - struct timespec __user *, utimes, int, flags) + struct __kernel_timespec __user *, utimes, int, flags) { struct timespec64 tstimes[2]; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index b3e27e5ee322..420ac881a610 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -513,7 +513,8 @@ asmlinkage long sys_timerfd_gettime(int ufd, struct __kernel_itimerspec __user * /* fs/utimes.c */ asmlinkage long sys_utimensat(int dfd, const char __user *filename, - struct timespec __user *utimes, int flags); + struct __kernel_timespec __user *utimes, + int flags); /* kernel/acct.c */ asmlinkage long sys_acct(const char __user *name); -- cgit v1.2.3-59-g8ed1b From 185cfaf7641e14af85635bb2750da302e32b04e3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 17 Apr 2018 09:11:58 +0200 Subject: y2038: Compile utimes()/futimesat() conditionally There are four generations of utimes() syscalls: utime(), utimes(), futimesat() and utimensat(), each one being a superset of the previous one. For y2038 support, we have to add another one, which is the same as the existing utimensat() but always passes 64-bit times_t based timespec values. There are currently 10 architectures that only use utimensat(), two that use utimes(), futimesat() and utimensat() but not utime(), and 11 architectures that have all four, and those define __ARCH_WANT_SYS_UTIME in order to get a sys_utime implementation. Since all the new architectures only want utimensat(), moving all the legacy entry points into a common __ARCH_WANT_SYS_UTIME guard simplifies the logic. Only alpha and ia64 grow a tiny bit as they now also get an unused sys_utime(), but it didn't seem worth the extra complexity of adding yet another ifdef for those. Signed-off-by: Arnd Bergmann --- arch/alpha/include/asm/unistd.h | 1 + arch/arm/include/asm/unistd.h | 2 +- arch/ia64/include/asm/unistd.h | 1 + fs/utimes.c | 51 ++++++++++++++++++----------------------- include/linux/syscalls.h | 10 ++++---- 5 files changed, 31 insertions(+), 34 deletions(-) diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index edc090470023..9ff37aa1165f 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -14,6 +14,7 @@ #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 8f1159c26f20..88ef2ce1f69a 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -26,13 +26,13 @@ #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_OLD_MMAP #define __ARCH_WANT_SYS_OLD_SELECT +#define __ARCH_WANT_SYS_UTIME #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) #define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_SOCKETCALL diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index c5b2620c4a4c..49e34db2529c 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h @@ -29,6 +29,7 @@ #define __IGNORE_umount2 /* umount() */ #define __ARCH_WANT_NEW_STAT +#define __ARCH_WANT_SYS_UTIME #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) diff --git a/fs/utimes.c b/fs/utimes.c index d30f409ecc1a..2f6f08061a26 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -8,35 +8,6 @@ #include #include -#ifdef __ARCH_WANT_SYS_UTIME - -/* - * sys_utime() can be implemented in user-level using sys_utimes(). - * Is this for backwards compatibility? If so, why not move it - * into the appropriate arch directory (for those architectures that - * need it). - */ - -/* If times==NULL, set access and modification to current time, - * must be owner or have write permission. - * Else, update from *times, must be owner or super user. - */ -SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) -{ - struct timespec64 tv[2]; - - if (times) { - if (get_user(tv[0].tv_sec, ×->actime) || - get_user(tv[1].tv_sec, ×->modtime)) - return -EFAULT; - tv[0].tv_nsec = 0; - tv[1].tv_nsec = 0; - } - return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0); -} - -#endif - static bool nsec_valid(long nsec) { if (nsec == UTIME_OMIT || nsec == UTIME_NOW) @@ -184,6 +155,13 @@ SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags); } +#ifdef __ARCH_WANT_SYS_UTIME +/* + * futimesat(), utimes() and utime() are older versions of utimensat() + * that are provided for compatibility with traditional C libraries. + * On modern architectures, we always use libc wrappers around + * utimensat() instead. + */ static long do_futimesat(int dfd, const char __user *filename, struct timeval __user *utimes) { @@ -225,6 +203,21 @@ SYSCALL_DEFINE2(utimes, char __user *, filename, return do_futimesat(AT_FDCWD, filename, utimes); } +SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) +{ + struct timespec64 tv[2]; + + if (times) { + if (get_user(tv[0].tv_sec, ×->actime) || + get_user(tv[1].tv_sec, ×->modtime)) + return -EFAULT; + tv[0].tv_nsec = 0; + tv[1].tv_nsec = 0; + } + return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0); +} +#endif + #ifdef CONFIG_COMPAT /* * Not all architectures have sys_utime, so implement this in terms diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 420ac881a610..95e795fb0593 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -955,8 +955,6 @@ asmlinkage long sys_access(const char __user *filename, int mode); asmlinkage long sys_rename(const char __user *oldname, const char __user *newname); asmlinkage long sys_symlink(const char __user *old, const char __user *new); -asmlinkage long sys_utimes(char __user *filename, - struct timeval __user *utimes); #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) asmlinkage long sys_stat64(const char __user *filename, struct stat64 __user *statbuf); @@ -986,14 +984,18 @@ asmlinkage long sys_alarm(unsigned int seconds); asmlinkage long sys_getpgrp(void); asmlinkage long sys_pause(void); asmlinkage long sys_time(time_t __user *tloc); +#ifdef __ARCH_WANT_SYS_UTIME asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times); +asmlinkage long sys_utimes(char __user *filename, + struct timeval __user *utimes); +asmlinkage long sys_futimesat(int dfd, const char __user *filename, + struct timeval __user *utimes); +#endif asmlinkage long sys_creat(const char __user *pathname, umode_t mode); asmlinkage long sys_getdents(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count); -asmlinkage long sys_futimesat(int dfd, const char __user *filename, - struct timeval __user *utimes); asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp); asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, -- cgit v1.2.3-59-g8ed1b From 4faea239e529d1d6b3b93fbf08d5e90427961a41 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 17 Apr 2018 12:03:19 +0200 Subject: y2038: utimes: Rework #ifdef guards for compat syscalls After changing over to 64-bit time_t syscalls, many architectures will want compat_sys_utimensat() but not respective handlers for utime(), utimes() and futimesat(). This adds a new __ARCH_WANT_SYS_UTIME32 to complement __ARCH_WANT_SYS_UTIME. For now, all 64-bit architectures that support CONFIG_COMPAT set it, but future 64-bit architectures will not (tile would not have needed it either, but got removed). As older 32-bit architectures get converted to using CONFIG_64BIT_TIME, they will have to use __ARCH_WANT_SYS_UTIME32 instead of __ARCH_WANT_SYS_UTIME. Architectures using the generic syscall ABI don't need either of them as they never had a utime syscall. Since the compat_utimbuf structure is now required outside of CONFIG_COMPAT, I'm moving it into compat_time.h. Signed-off-by: Arnd Bergmann --- changed from last version: - renamed __ARCH_WANT_COMPAT_SYS_UTIME to __ARCH_WANT_SYS_UTIME32 --- arch/arm64/include/asm/unistd.h | 1 + arch/mips/include/asm/unistd.h | 1 + arch/parisc/include/asm/unistd.h | 1 + arch/powerpc/include/asm/unistd.h | 1 + arch/s390/include/asm/unistd.h | 1 + arch/sparc/include/asm/unistd.h | 1 + arch/x86/include/asm/unistd.h | 1 + fs/utimes.c | 8 ++++++-- include/linux/compat.h | 7 +------ include/linux/time32.h | 5 +++++ 10 files changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 2af308f13463..b13ca091f833 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -22,6 +22,7 @@ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_COMPAT_SYS_SENDFILE +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index c2174b80e50e..c68b8ae3efcb 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -31,6 +31,7 @@ #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_WAITPID #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_GETPGRP diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index a0c38374fff0..bc37a4953eaa 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -152,6 +152,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_COMPAT_SYS_TIME #define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL #define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_WAITPID #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 9326c9133516..b0de85b477e1 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -47,6 +47,7 @@ #endif #ifdef CONFIG_PPC64 #define __ARCH_WANT_COMPAT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_NEWFSTATAT #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index a2d583ea526d..a1fbf15d53aa 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -34,6 +34,7 @@ #define __ARCH_WANT_SYS_SIGPROCMASK # ifdef CONFIG_COMPAT # define __ARCH_WANT_COMPAT_SYS_TIME +# define __ARCH_WANT_SYS_UTIME32 # endif #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index f7514d3eae7b..00f87dbd0b17 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -42,6 +42,7 @@ #define __ARCH_WANT_SYS_IPC #else #define __ARCH_WANT_COMPAT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 153d2a5e6b02..dc4ed8bc2382 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -24,6 +24,7 @@ # include # include # define __ARCH_WANT_COMPAT_SYS_TIME +# define __ARCH_WANT_SYS_UTIME32 # define __ARCH_WANT_COMPAT_SYS_PREADV64 # define __ARCH_WANT_COMPAT_SYS_PWRITEV64 # define __ARCH_WANT_COMPAT_SYS_PREADV64V2 diff --git a/fs/utimes.c b/fs/utimes.c index 2f6f08061a26..bdcf2daf39c1 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -218,13 +218,14 @@ SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) } #endif -#ifdef CONFIG_COMPAT +#ifdef CONFIG_COMPAT_32BIT_TIME /* * Not all architectures have sys_utime, so implement this in terms * of sys_utimes. */ +#ifdef __ARCH_WANT_SYS_UTIME32 COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, - struct compat_utimbuf __user *, t) + struct old_utimbuf32 __user *, t) { struct timespec64 tv[2]; @@ -237,6 +238,7 @@ COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, } return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); } +#endif COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct old_timespec32 __user *, t, int, flags) { @@ -253,6 +255,7 @@ COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filena return do_utimes(dfd, filename, t ? tv : NULL, flags); } +#ifdef __ARCH_WANT_SYS_UTIME32 static long do_compat_futimesat(unsigned int dfd, const char __user *filename, struct old_timeval32 __user *t) { @@ -285,3 +288,4 @@ COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct old_timeval return do_compat_futimesat(AT_FDCWD, filename, t); } #endif +#endif diff --git a/include/linux/compat.h b/include/linux/compat.h index d376fa8be00d..6fb5abdb87be 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -113,11 +113,6 @@ typedef __compat_gid32_t compat_gid_t; struct compat_sel_arg_struct; struct rusage; -struct compat_utimbuf { - old_time32_t actime; - old_time32_t modtime; -}; - struct compat_itimerval { struct old_timeval32 it_interval; struct old_timeval32 it_value; @@ -942,7 +937,7 @@ asmlinkage long compat_sys_newlstat(const char __user *filename, /* __ARCH_WANT_SYSCALL_DEPRECATED */ asmlinkage long compat_sys_time(old_time32_t __user *tloc); asmlinkage long compat_sys_utime(const char __user *filename, - struct compat_utimbuf __user *t); + struct old_utimbuf32 __user *t); asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, struct old_timeval32 __user *t); diff --git a/include/linux/time32.h b/include/linux/time32.h index 0e0d7304d1a8..61904a6c098f 100644 --- a/include/linux/time32.h +++ b/include/linux/time32.h @@ -30,6 +30,11 @@ struct old_itimerspec32 { struct old_timespec32 it_value; }; +struct old_utimbuf32 { + old_time32_t actime; + old_time32_t modtime; +}; + extern int get_old_timespec32(struct timespec64 *, const void __user *); extern int put_old_timespec32(const struct timespec64 *, void __user *); extern int get_old_itimerspec32(struct itimerspec64 *its, -- cgit v1.2.3-59-g8ed1b From 474b9c777b20b8340a6ee0f7ba6ebbd6a4bf47e2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 17 Apr 2018 21:59:47 +0200 Subject: y2038: sched: Change sched_rr_get_interval to use __kernel_timespec This is a preparation patch for converting sys_sched_rr_get_interval to work with 64-bit time_t on 32-bit architectures. The 'interval' argument is changed to struct __kernel_timespec, which will be redefined using 64-bit time_t in the future. The compat version of the system call in turn is enabled for compilation with CONFIG_COMPAT_32BIT_TIME so the individual 32-bit architectures can share the handling of the traditional argument with 64-bit architectures providing it for their compat mode. Signed-off-by: Arnd Bergmann --- include/linux/syscalls.h | 2 +- kernel/sched/core.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 95e795fb0593..5642016a312d 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -614,7 +614,7 @@ asmlinkage long sys_sched_yield(void); asmlinkage long sys_sched_get_priority_max(int policy); asmlinkage long sys_sched_get_priority_min(int policy); asmlinkage long sys_sched_rr_get_interval(pid_t pid, - struct timespec __user *interval); + struct __kernel_timespec __user *interval); /* kernel/signal.c */ asmlinkage long sys_restart_syscall(void); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8287b75ed961..39af2bec2b39 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5243,7 +5243,7 @@ out_unlock: * an error code. */ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, - struct timespec __user *, interval) + struct __kernel_timespec __user *, interval) { struct timespec64 t; int retval = sched_rr_get_interval(pid, &t); @@ -5254,7 +5254,7 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, return retval; } -#ifdef CONFIG_COMPAT +#ifdef CONFIG_COMPAT_32BIT_TIME COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, compat_pid_t, pid, struct old_timespec32 __user *, interval) -- cgit v1.2.3-59-g8ed1b From c2e6c8567acdba8db1055b242c34ceb123c6a253 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 18 Apr 2018 13:42:25 +0200 Subject: y2038: socket: Change recvmmsg to use __kernel_timespec This converts the recvmmsg() system call in all its variations to use 'timespec64' internally for its timeout, and have a __kernel_timespec64 argument in the native entry point. This lets us change the type to use 64-bit time_t at a later point while using the 32-bit compat system call emulation for existing user space. Signed-off-by: Arnd Bergmann --- include/linux/socket.h | 4 ++-- include/linux/syscalls.h | 2 +- net/compat.c | 6 +++--- net/socket.c | 18 ++++++++---------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/linux/socket.h b/include/linux/socket.h index 7ed4713d5337..8b571e9b9f76 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -348,7 +348,7 @@ struct ucred { extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); -struct timespec; +struct timespec64; /* The __sys_...msg variants allow MSG_CMSG_COMPAT iff * forbid_cmsg_compat==false @@ -358,7 +358,7 @@ extern long __sys_recvmsg(int fd, struct user_msghdr __user *msg, extern long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, bool forbid_cmsg_compat); extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, - unsigned int flags, struct timespec *timeout); + unsigned int flags, struct timespec64 *timeout); extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, bool forbid_cmsg_compat); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 5642016a312d..fb3a05fab8aa 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -830,7 +830,7 @@ asmlinkage long sys_perf_event_open( asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int); asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, unsigned int vlen, unsigned flags, - struct timespec __user *timeout); + struct __kernel_timespec __user *timeout); asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, int options, struct rusage __user *ru); diff --git a/net/compat.c b/net/compat.c index 2ef160876bc1..47a614b370cd 100644 --- a/net/compat.c +++ b/net/compat.c @@ -815,18 +815,18 @@ static int __compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, struct old_timespec32 __user *timeout) { int datagrams; - struct timespec ktspec; + struct timespec64 ktspec; if (timeout == NULL) return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, NULL); - if (compat_get_timespec(&ktspec, timeout)) + if (compat_get_timespec64(&ktspec, timeout)) return -EFAULT; datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, &ktspec); - if (datagrams > 0 && compat_put_timespec(&ktspec, timeout)) + if (datagrams > 0 && compat_put_timespec64(&ktspec, timeout)) datagrams = -EFAULT; return datagrams; diff --git a/net/socket.c b/net/socket.c index e6945e318f02..b9d71b503720 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2340,7 +2340,7 @@ SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg, */ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, - unsigned int flags, struct timespec *timeout) + unsigned int flags, struct timespec64 *timeout) { int fput_needed, err, datagrams; struct socket *sock; @@ -2405,8 +2405,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, if (timeout) { ktime_get_ts64(&timeout64); - *timeout = timespec64_to_timespec( - timespec64_sub(end_time, timeout64)); + *timeout = timespec64_sub(end_time, timeout64); if (timeout->tv_sec < 0) { timeout->tv_sec = timeout->tv_nsec = 0; break; @@ -2452,10 +2451,10 @@ out_put: static int do_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, - struct timespec __user *timeout) + struct __kernel_timespec __user *timeout) { int datagrams; - struct timespec timeout_sys; + struct timespec64 timeout_sys; if (flags & MSG_CMSG_COMPAT) return -EINVAL; @@ -2463,13 +2462,12 @@ static int do_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, if (!timeout) return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); - if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys))) + if (get_timespec64(&timeout_sys, timeout)) return -EFAULT; datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); - if (datagrams > 0 && - copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys))) + if (datagrams > 0 && put_timespec64(&timeout_sys, timeout)) datagrams = -EFAULT; return datagrams; @@ -2477,7 +2475,7 @@ static int do_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, unsigned int, vlen, unsigned int, flags, - struct timespec __user *, timeout) + struct __kernel_timespec __user *, timeout) { return do_sys_recvmmsg(fd, mmsg, vlen, flags, timeout); } @@ -2601,7 +2599,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) break; case SYS_RECVMMSG: err = do_sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], - a[3], (struct timespec __user *)a[4]); + a[3], (struct __kernel_timespec __user *)a[4]); break; case SYS_ACCEPT4: err = __sys_accept4(a0, (struct sockaddr __user *)a1, -- cgit v1.2.3-59-g8ed1b From 49c39f8464a9af702e9d45800c00a572753aeb06 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 18 Apr 2018 15:56:13 +0200 Subject: y2038: signal: Change rt_sigtimedwait to use __kernel_timespec This changes sys_rt_sigtimedwait() to use get_timespec64(), changing the timeout type to __kernel_timespec, which will be changed to use a 64-bit time_t in the future. Since the do_sigtimedwait() core function changes, we also have to modify the compat version of this system call in the same way. Signed-off-by: Arnd Bergmann --- include/linux/syscalls.h | 2 +- kernel/signal.c | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index fb3a05fab8aa..2ac3d13a915b 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -635,7 +635,7 @@ asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set, asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize); asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, siginfo_t __user *uinfo, - const struct timespec __user *uts, + const struct __kernel_timespec __user *uts, size_t sigsetsize); asmlinkage long sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo); diff --git a/kernel/signal.c b/kernel/signal.c index a4db724e14c1..0831d56a731a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3082,7 +3082,7 @@ int copy_siginfo_from_user32(struct siginfo *to, * @ts: upper bound on process time suspension */ static int do_sigtimedwait(const sigset_t *which, siginfo_t *info, - const struct timespec *ts) + const struct timespec64 *ts) { ktime_t *to = NULL, timeout = KTIME_MAX; struct task_struct *tsk = current; @@ -3090,9 +3090,9 @@ static int do_sigtimedwait(const sigset_t *which, siginfo_t *info, int sig, ret = 0; if (ts) { - if (!timespec_valid(ts)) + if (!timespec64_valid(ts)) return -EINVAL; - timeout = timespec_to_ktime(*ts); + timeout = timespec64_to_ktime(*ts); to = &timeout; } @@ -3140,11 +3140,12 @@ static int do_sigtimedwait(const sigset_t *which, siginfo_t *info, * @sigsetsize: size of sigset_t type */ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese, - siginfo_t __user *, uinfo, const struct timespec __user *, uts, + siginfo_t __user *, uinfo, + const struct __kernel_timespec __user *, uts, size_t, sigsetsize) { sigset_t these; - struct timespec ts; + struct timespec64 ts; siginfo_t info; int ret; @@ -3156,7 +3157,7 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese, return -EFAULT; if (uts) { - if (copy_from_user(&ts, uts, sizeof(ts))) + if (get_timespec64(&ts, uts)) return -EFAULT; } @@ -3176,7 +3177,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, struct old_timespec32 __user *, uts, compat_size_t, sigsetsize) { sigset_t s; - struct timespec t; + struct timespec64 t; siginfo_t info; long ret; @@ -3187,7 +3188,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, return -EFAULT; if (uts) { - if (compat_get_timespec(&t, uts)) + if (get_old_timespec32(&t, uts)) return -EFAULT; } -- cgit v1.2.3-59-g8ed1b From 67314ec7b0250290cc85eaa7a2f88a8ddb9e8547 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 5 Sep 2018 07:36:06 -0700 Subject: RISC-V: Request newstat syscalls Since commit 82b355d161c9 ("y2038: Remove newstat family from default syscall set"), riscv images fail to boot with the following error. /sbin/init: error while loading shared libraries: libc.so.6: cannot stat shared object: Error 38 Kernel panic - not syncing: Attempted to kill init! exitcode=0x00007f00 Explicitly request newstat syscalls to fix the problem. Fixes: 82b355d161c9 ("y2038: Remove newstat family from default syscall set") Cc: Arnd Bergmann Signed-off-by: Guenter Roeck Signed-off-by: Arnd Bergmann --- arch/riscv/include/asm/unistd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv/include/asm/unistd.h b/arch/riscv/include/asm/unistd.h index 0caea01d5cca..eff7aa9aa163 100644 --- a/arch/riscv/include/asm/unistd.h +++ b/arch/riscv/include/asm/unistd.h @@ -16,6 +16,7 @@ * be included multiple times. See uapi/asm/syscalls.h for more info. */ +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SYS_CLONE #include #include -- cgit v1.2.3-59-g8ed1b From dc6253108f0fbff4a634055d5b8a91958ec2af81 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Fri, 28 Sep 2018 12:03:28 -0400 Subject: tick/broadcast: Remove redundant check tick_device_is_functional() is called early in tick_broadcast_control(), so no need to call it again later. Signed-off-by: Peng Hao Signed-off-by: Thomas Gleixner Cc: fweisbec@gmail.com Link: https://lkml.kernel.org/r/1538150608-2599-1-git-send-email-penghao122@sina.com.cn --- kernel/time/tick-broadcast.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index aa2094d5dd27..be0aac2b4300 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -400,8 +400,6 @@ void tick_broadcast_control(enum tick_broadcast_mode mode) if (tick_broadcast_forced) break; cpumask_clear_cpu(cpu, tick_broadcast_on); - if (!tick_device_is_functional(dev)) - break; if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_mask)) { if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) -- cgit v1.2.3-59-g8ed1b From 2a4849d2674b965cd9eb7e6c010b7c240fb9d218 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 27 Aug 2018 20:52:14 -0500 Subject: clocksource: Convert to using %pOFn instead of device_node.name In preparation to remove the node name pointer from struct device_node, convert printf users to use the %pOFn format specifier. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: Michal Simek Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Rob Herring Signed-off-by: Daniel Lezcano --- drivers/clocksource/asm9260_timer.c | 2 +- drivers/clocksource/cadence_ttc_timer.c | 2 +- drivers/clocksource/dw_apb_timer_of.c | 8 ++++---- drivers/clocksource/pxa_timer.c | 6 +++--- drivers/clocksource/time-orion.c | 8 ++++---- drivers/clocksource/timer-integrator-ap.c | 2 +- drivers/clocksource/timer-sp804.c | 2 +- drivers/clocksource/zevio-timer.c | 8 ++++---- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c index 38cd2feb87c4..fbaee04fd1d9 100644 --- a/drivers/clocksource/asm9260_timer.c +++ b/drivers/clocksource/asm9260_timer.c @@ -193,7 +193,7 @@ static int __init asm9260_timer_init(struct device_node *np) priv.base = of_io_request_and_map(np, 0, np->name); if (IS_ERR(priv.base)) { - pr_err("%s: unable to map resource\n", np->name); + pr_err("%pOFn: unable to map resource\n", np); return PTR_ERR(priv.base); } diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 29d51755e18b..b33402980b6f 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -535,7 +535,7 @@ static int __init ttc_timer_init(struct device_node *timer) if (ret) return ret; - pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); + pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq); return 0; } diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index 69866cd8f4bb..fabaa29cc3a4 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -33,7 +33,7 @@ static void __init timer_get_base_and_rate(struct device_node *np, *base = of_iomap(np, 0); if (!*base) - panic("Unable to map regs for %s", np->name); + panic("Unable to map regs for %pOFn", np); /* * Not all implementations use a periphal clock, so don't panic @@ -42,8 +42,8 @@ static void __init timer_get_base_and_rate(struct device_node *np, pclk = of_clk_get_by_name(np, "pclk"); if (!IS_ERR(pclk)) if (clk_prepare_enable(pclk)) - pr_warn("pclk for %s is present, but could not be activated\n", - np->name); + pr_warn("pclk for %pOFn is present, but could not be activated\n", + np); timer_clk = of_clk_get_by_name(np, "timer"); if (IS_ERR(timer_clk)) @@ -57,7 +57,7 @@ static void __init timer_get_base_and_rate(struct device_node *np, try_clock_freq: if (of_property_read_u32(np, "clock-freq", rate) && of_property_read_u32(np, "clock-frequency", rate)) - panic("No clock nor clock-frequency property for %s", np->name); + panic("No clock nor clock-frequency property for %pOFn", np); } static void __init add_clockevent(struct device_node *event_timer) diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c index 08cd6eaf3795..395837938301 100644 --- a/drivers/clocksource/pxa_timer.c +++ b/drivers/clocksource/pxa_timer.c @@ -191,13 +191,13 @@ static int __init pxa_timer_dt_init(struct device_node *np) /* timer registers are shared with watchdog timer */ timer_base = of_iomap(np, 0); if (!timer_base) { - pr_err("%s: unable to map resource\n", np->name); + pr_err("%pOFn: unable to map resource\n", np); return -ENXIO; } clk = of_clk_get(np, 0); if (IS_ERR(clk)) { - pr_crit("%s: unable to get clk\n", np->name); + pr_crit("%pOFn: unable to get clk\n", np); return PTR_ERR(clk); } @@ -210,7 +210,7 @@ static int __init pxa_timer_dt_init(struct device_node *np) /* we are only interested in OS-timer0 irq */ irq = irq_of_parse_and_map(np, 0); if (irq <= 0) { - pr_crit("%s: unable to parse OS-timer0 irq\n", np->name); + pr_crit("%pOFn: unable to parse OS-timer0 irq\n", np); return -EINVAL; } diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index 12202067fe4b..7d487107e3cd 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -129,13 +129,13 @@ static int __init orion_timer_init(struct device_node *np) /* timer registers are shared with watchdog timer */ timer_base = of_iomap(np, 0); if (!timer_base) { - pr_err("%s: unable to map resource\n", np->name); + pr_err("%pOFn: unable to map resource\n", np); return -ENXIO; } clk = of_clk_get(np, 0); if (IS_ERR(clk)) { - pr_err("%s: unable to get clk\n", np->name); + pr_err("%pOFn: unable to get clk\n", np); return PTR_ERR(clk); } @@ -148,7 +148,7 @@ static int __init orion_timer_init(struct device_node *np) /* we are only interested in timer1 irq */ irq = irq_of_parse_and_map(np, 1); if (irq <= 0) { - pr_err("%s: unable to parse timer1 irq\n", np->name); + pr_err("%pOFn: unable to parse timer1 irq\n", np); return -EINVAL; } @@ -174,7 +174,7 @@ static int __init orion_timer_init(struct device_node *np) /* setup timer1 as clockevent timer */ ret = setup_irq(irq, &orion_clkevt_irq); if (ret) { - pr_err("%s: unable to setup irq\n", np->name); + pr_err("%pOFn: unable to setup irq\n", np); return ret; } diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c index 62d24690ba02..76e526f58620 100644 --- a/drivers/clocksource/timer-integrator-ap.c +++ b/drivers/clocksource/timer-integrator-ap.c @@ -190,7 +190,7 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) clk = of_clk_get(node, 0); if (IS_ERR(clk)) { - pr_err("No clock for %s\n", node->name); + pr_err("No clock for %pOFn\n", node); return PTR_ERR(clk); } clk_prepare_enable(clk); diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index e01222ea888f..052b230ca312 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -249,7 +249,7 @@ static int __init sp804_of_init(struct device_node *np) if (of_clk_get_parent_count(np) == 3) { clk2 = of_clk_get(np, 1); if (IS_ERR(clk2)) { - pr_err("sp804: %s clock not found: %d\n", np->name, + pr_err("sp804: %pOFn clock not found: %d\n", np, (int)PTR_ERR(clk2)); clk2 = NULL; } diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c index f74689334f7c..6127e8062a71 100644 --- a/drivers/clocksource/zevio-timer.c +++ b/drivers/clocksource/zevio-timer.c @@ -148,12 +148,12 @@ static int __init zevio_timer_add(struct device_node *node) of_address_to_resource(node, 0, &res); scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name), - "%llx.%s_clocksource", - (unsigned long long)res.start, node->name); + "%llx.%pOFn_clocksource", + (unsigned long long)res.start, node); scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name), - "%llx.%s_clockevent", - (unsigned long long)res.start, node->name); + "%llx.%pOFn_clockevent", + (unsigned long long)res.start, node); if (timer->interrupt_regs && irqnr) { timer->clkevt.name = timer->clockevent_name; -- cgit v1.2.3-59-g8ed1b From 274157a4f7027af432642ca22e84f052875b26b4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2018 02:25:38 +0000 Subject: clocksource/drivers/renesas-ostm: Convert to SPDX identifiers This patch updates license to use SPDX-License-Identifier instead of verbose license text. Signed-off-by: Kuninori Morimoto Reviewed-by: Simon Horman Signed-off-by: Daniel Lezcano --- drivers/clocksource/renesas-ostm.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c index 6cffd7c6001a..61d5f3b539ce 100644 --- a/drivers/clocksource/renesas-ostm.c +++ b/drivers/clocksource/renesas-ostm.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas Timer Support - OSTM * * Copyright (C) 2017 Renesas Electronics America, Inc. * Copyright (C) 2017 Chris Brandt - * - * 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 - * - * 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. - * */ #include -- cgit v1.2.3-59-g8ed1b From efad01173717b0d0ad8a7dc91cc447f19d8447f3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2018 02:25:53 +0000 Subject: clocksource/drivers/sh_cmt: Convert to SPDX identifiers This patch updates license to use SPDX-License-Identifier instead of verbose license text. Signed-off-by: Kuninori Morimoto Reviewed-by: Simon Horman Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_cmt.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index bbbf37c471a3..6f65cf86402b 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SuperH Timer Support - CMT * * Copyright (C) 2008 Magnus Damm - * - * 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 - * - * 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. */ #include -- cgit v1.2.3-59-g8ed1b From ddb89642a24f37abc00fa363f840708400d365be Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2018 02:26:06 +0000 Subject: clocksource/drivers/sh_mtu2: Convert to SPDX identifiers This patch updates license to use SPDX-License-Identifier instead of verbose license text. Signed-off-by: Kuninori Morimoto Reviewed-by: Simon Horman Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_mtu2.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 6812e099b6a3..354b27d14a19 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SuperH Timer Support - MTU2 * * Copyright (C) 2009 Magnus Damm - * - * 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 - * - * 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. */ #include -- cgit v1.2.3-59-g8ed1b From 0b9294fe8dca4ab500e955cf06445134d228e493 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2018 02:26:20 +0000 Subject: clocksource/drivers/sh_tmu: Convert to SPDX identifiers This patch updates license to use SPDX-License-Identifier instead of verbose license text. Signed-off-by: Kuninori Morimoto Reviewed-by: Simon Horman Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_tmu.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index c74a6c543ca2..49f1c805fc95 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SuperH Timer Support - TMU * * Copyright (C) 2009 Magnus Damm - * - * 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 - * - * 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. */ #include -- cgit v1.2.3-59-g8ed1b From 22627c6f3ed3d9d0df13eec3c831b08f8186c38e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 8 Sep 2018 23:54:05 +0300 Subject: clocksource/drivers/sh_cmt: Fixup for 64-bit machines When trying to use CMT for clockevents on R-Car gen3 SoCs, I noticed that 'max_delta_ns' for the broadcast timer (CMT) was shown as 1000 in /proc/timer_list. It turned out that when calculating it, the driver did 1 << 32 (causing what I think was undefined behavior) resulting in a zero delta, later clamped to 1000 by cev_delta2ns(). The root cause turned out to be that the driver abused *unsigned long* for the CMT register values (which are 16/32-bit), so that the calculation of 'ch->max_match_value' in sh_cmt_setup_channel() used the wrong branch. Using more proper 'u32' instead fixed 'max_delta_ns' and even fixed the switching an active clocksource to CMT (which caused the system to turn non-interactive before). Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_cmt.c | 72 ++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 6f65cf86402b..efaf00d1f260 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -70,18 +70,17 @@ struct sh_cmt_info { unsigned int channels_mask; unsigned long width; /* 16 or 32 bit version of hardware block */ - unsigned long overflow_bit; - unsigned long clear_bits; + u32 overflow_bit; + u32 clear_bits; /* callbacks for CMSTR and CMCSR access */ - unsigned long (*read_control)(void __iomem *base, unsigned long offs); + u32 (*read_control)(void __iomem *base, unsigned long offs); void (*write_control)(void __iomem *base, unsigned long offs, - unsigned long value); + u32 value); /* callbacks for CMCNT and CMCOR access */ - unsigned long (*read_count)(void __iomem *base, unsigned long offs); - void (*write_count)(void __iomem *base, unsigned long offs, - unsigned long value); + u32 (*read_count)(void __iomem *base, unsigned long offs); + void (*write_count)(void __iomem *base, unsigned long offs, u32 value); }; struct sh_cmt_channel { @@ -95,9 +94,9 @@ struct sh_cmt_channel { unsigned int timer_bit; unsigned long flags; - unsigned long match_value; - unsigned long next_match_value; - unsigned long max_match_value; + u32 match_value; + u32 next_match_value; + u32 max_match_value; raw_spinlock_t lock; struct clock_event_device ced; struct clocksource cs; @@ -152,24 +151,22 @@ struct sh_cmt_device { #define SH_CMT32_CMCSR_CKS_RCLK1 (7 << 0) #define SH_CMT32_CMCSR_CKS_MASK (7 << 0) -static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs) +static u32 sh_cmt_read16(void __iomem *base, unsigned long offs) { return ioread16(base + (offs << 1)); } -static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs) +static u32 sh_cmt_read32(void __iomem *base, unsigned long offs) { return ioread32(base + (offs << 2)); } -static void sh_cmt_write16(void __iomem *base, unsigned long offs, - unsigned long value) +static void sh_cmt_write16(void __iomem *base, unsigned long offs, u32 value) { iowrite16(value, base + (offs << 1)); } -static void sh_cmt_write32(void __iomem *base, unsigned long offs, - unsigned long value) +static void sh_cmt_write32(void __iomem *base, unsigned long offs, u32 value) { iowrite32(value, base + (offs << 2)); } @@ -234,7 +231,7 @@ static const struct sh_cmt_info sh_cmt_info[] = { #define CMCNT 1 /* channel register */ #define CMCOR 2 /* channel register */ -static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch) +static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch) { if (ch->iostart) return ch->cmt->info->read_control(ch->iostart, 0); @@ -242,8 +239,7 @@ static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch) return ch->cmt->info->read_control(ch->cmt->mapbase, 0); } -static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, - unsigned long value) +static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value) { if (ch->iostart) ch->cmt->info->write_control(ch->iostart, 0, value); @@ -251,39 +247,35 @@ static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); } -static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) +static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) { return ch->cmt->info->read_control(ch->ioctrl, CMCSR); } -static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, - unsigned long value) +static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value) { ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); } -static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) +static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) { return ch->cmt->info->read_count(ch->ioctrl, CMCNT); } -static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, - unsigned long value) +static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value) { ch->cmt->info->write_count(ch->ioctrl, CMCNT, value); } -static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, - unsigned long value) +static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value) { ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); } -static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch, - int *has_wrapped) +static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped) { - unsigned long v1, v2, v3; - int o1, o2; + u32 v1, v2, v3; + u32 o1, o2; o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit; @@ -303,7 +295,8 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch, static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) { - unsigned long flags, value; + unsigned long flags; + u32 value; /* start stop register shared by multiple timer channels */ raw_spin_lock_irqsave(&ch->cmt->lock, flags); @@ -410,11 +403,11 @@ static void sh_cmt_disable(struct sh_cmt_channel *ch) static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch, int absolute) { - unsigned long new_match; - unsigned long value = ch->next_match_value; - unsigned long delay = 0; - unsigned long now = 0; - int has_wrapped; + u32 value = ch->next_match_value; + u32 new_match; + u32 delay = 0; + u32 now = 0; + u32 has_wrapped; now = sh_cmt_get_counter(ch, &has_wrapped); ch->flags |= FLAG_REPROGRAM; /* force reprogram */ @@ -611,9 +604,10 @@ static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs) static u64 sh_cmt_clocksource_read(struct clocksource *cs) { struct sh_cmt_channel *ch = cs_to_sh_cmt(cs); - unsigned long flags, raw; + unsigned long flags; unsigned long value; - int has_wrapped; + u32 has_wrapped; + u32 raw; raw_spin_lock_irqsave(&ch->lock, flags); value = ch->total_cycles; -- cgit v1.2.3-59-g8ed1b From 37e7742c55ba856eaec7e35673ee370f36eb17f3 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 10 Sep 2018 23:22:16 +0300 Subject: clocksource/drivers/sh_cmt: Fix clocksource width for 32-bit machines The driver seems to abuse *unsigned long* not only for the (32-bit) register values but also for the 'sh_cmt_channel::total_cycles' which needs to always be 64-bit -- as a result, the clocksource's mask is needlessly clamped down to 32-bits on the 32-bit machines... Fixes: 19bdc9d061bc ("clocksource: sh_cmt clocksource support") Reported-by: Geert Uytterhoeven Signed-off-by: Sergei Shtylyov Reviewed-by: Simon Horman Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_cmt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index efaf00d1f260..0c74489956b2 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -100,7 +100,7 @@ struct sh_cmt_channel { raw_spinlock_t lock; struct clock_event_device ced; struct clocksource cs; - unsigned long total_cycles; + u64 total_cycles; bool cs_enabled; }; @@ -605,8 +605,8 @@ static u64 sh_cmt_clocksource_read(struct clocksource *cs) { struct sh_cmt_channel *ch = cs_to_sh_cmt(cs); unsigned long flags; - unsigned long value; u32 has_wrapped; + u64 value; u32 raw; raw_spin_lock_irqsave(&ch->lock, flags); @@ -680,7 +680,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch, cs->disable = sh_cmt_clocksource_disable; cs->suspend = sh_cmt_clocksource_suspend; cs->resume = sh_cmt_clocksource_resume; - cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); + cs->mask = CLOCKSOURCE_MASK(sizeof(u64) * 8); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n", -- cgit v1.2.3-59-g8ed1b From eceb4c49aed0fafbc4967e788231b1eba42b7606 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 12 Sep 2018 23:14:14 +0300 Subject: clocksource/drivers/sh_cmt: Properly line-wrap sh_cmt_of_table[] initializer There's no good reason for the sh_cmt_of_table[] initializer to violate the 80-column limit, especially after the commit 8d50e9476bb4 ("clocksource/drivers/sh_cmt: Mark "renesas,cmt-48-gen2" deprecated") partially fixed it -- fix the R-Car gen2 related entries as well. Signed-off-by: Sergei Shtylyov Reviewed-by: Chris Paterson Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_cmt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 0c74489956b2..71624dc43e04 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -927,8 +927,14 @@ static const struct of_device_id sh_cmt_of_table[] __maybe_unused = { .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] }, - { .compatible = "renesas,rcar-gen2-cmt0", .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] }, - { .compatible = "renesas,rcar-gen2-cmt1", .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] }, + { + .compatible = "renesas,rcar-gen2-cmt0", + .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] + }, + { + .compatible = "renesas,rcar-gen2-cmt1", + .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] + }, { } }; MODULE_DEVICE_TABLE(of, sh_cmt_of_table); -- cgit v1.2.3-59-g8ed1b From 9a199422b0d08efaaef2df006c34b0653591a4bf Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 12 Sep 2018 23:15:28 +0300 Subject: dt-bindings: timer: renesas: cmt: document R-Car gen3 support Document support for the R-Car gen3 CMT types 0/1 bindings -- they seem to be the same CMT types 0/1 as in the R-Car gen2 SoCs. Also document R8A779{7|8}0 bindings as these are the R-Car gen3 SoCs for which the initial support was done. Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano --- Documentation/devicetree/bindings/timer/renesas,cmt.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt b/Documentation/devicetree/bindings/timer/renesas,cmt.txt index b40add2d9bb4..49948fcc0631 100644 --- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt +++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt @@ -34,6 +34,10 @@ Required Properties: - "renesas,r8a7793-cmt1" for the 48-bit CMT1 device included in r8a7793. - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794. - "renesas,r8a7794-cmt1" for the 48-bit CMT1 device included in r8a7794. + - "renesas,r8a77970-cmt0" for the 32-bit CMT0 device included in r8a77970. + - "renesas,r8a77970-cmt1" for the 48-bit CMT1 device included in r8a77970. + - "renesas,r8a77980-cmt0" for the 32-bit CMT0 device included in r8a77980. + - "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980. - "renesas,rcar-gen2-cmt0" for 32-bit CMT0 devices included in R-Car Gen2 and RZ/G1. @@ -41,6 +45,9 @@ Required Properties: and RZ/G1. These are fallbacks for r8a73a4, R-Car Gen2 and RZ/G1 entries listed above. + - "renesas,rcar-gen3-cmt0" for 32-bit CMT0 devices included in R-Car Gen3. + - "renesas,rcar-gen3-cmt1" for 48-bit CMT1 devices included in R-Car Gen3. + These are fallbacks for R-Car Gen3 entries listed above. - reg: base address and length of the registers block for the timer module. - interrupts: interrupt-specifier for the timer, one per channel. -- cgit v1.2.3-59-g8ed1b From ac142a7fd291f4230923f221a594ce0281a96a72 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 12 Sep 2018 23:17:37 +0300 Subject: clocksource/drivers/sh_cmt: Add R-Car gen3 support Add support for the R-Car gen3 CMT types 0/1 -- they seem to be the same CMT types 0/1 as in R-Car gen2 SoCs. Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_cmt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 71624dc43e04..55d3e03f2cd4 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -935,6 +935,14 @@ static const struct of_device_id sh_cmt_of_table[] __maybe_unused = { .compatible = "renesas,rcar-gen2-cmt1", .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] }, + { + .compatible = "renesas,rcar-gen3-cmt0", + .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] + }, + { + .compatible = "renesas,rcar-gen3-cmt1", + .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] + }, { } }; MODULE_DEVICE_TABLE(of, sh_cmt_of_table); -- cgit v1.2.3-59-g8ed1b From 9d8d47ea6ec6048abc75ccc4486aff1a7db1ff4b Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 24 Sep 2018 05:59:23 +0200 Subject: clocksource/drivers: Unify the names to timer-* format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to make some housekeeping in the directory, this patch renames drivers to the timer-* format in order to unify their names. There is no functional changes. Acked-by: Uwe Kleine-König Acked-by: Vladimir Zapolskiy Acked-by: Liviu Dudau Signed-off-by: Daniel Lezcano --- MAINTAINERS | 10 +- drivers/clocksource/Makefile | 26 +- drivers/clocksource/cadence_ttc_timer.c | 543 ------------------------------ drivers/clocksource/fsl_ftm_timer.c | 376 --------------------- drivers/clocksource/owl-timer.c | 173 ---------- drivers/clocksource/qcom-timer.c | 258 -------------- drivers/clocksource/time-armada-370-xp.c | 416 ----------------------- drivers/clocksource/time-efm32.c | 287 ---------------- drivers/clocksource/time-lpc32xx.c | 314 ----------------- drivers/clocksource/time-orion.c | 192 ----------- drivers/clocksource/time-pistachio.c | 218 ------------ drivers/clocksource/timer-armada-370-xp.c | 416 +++++++++++++++++++++++ drivers/clocksource/timer-cadence-ttc.c | 543 ++++++++++++++++++++++++++++++ drivers/clocksource/timer-efm32.c | 287 ++++++++++++++++ drivers/clocksource/timer-fsl-ftm.c | 376 +++++++++++++++++++++ drivers/clocksource/timer-lpc32xx.c | 314 +++++++++++++++++ drivers/clocksource/timer-orion.c | 192 +++++++++++ drivers/clocksource/timer-owl.c | 173 ++++++++++ drivers/clocksource/timer-pistachio.c | 218 ++++++++++++ drivers/clocksource/timer-qcom.c | 258 ++++++++++++++ drivers/clocksource/timer-versatile.c | 44 +++ drivers/clocksource/timer-vf-pit.c | 204 +++++++++++ drivers/clocksource/timer-vt8500.c | 168 +++++++++ drivers/clocksource/timer-zevio.c | 218 ++++++++++++ drivers/clocksource/versatile.c | 44 --- drivers/clocksource/vf_pit_timer.c | 204 ----------- drivers/clocksource/vt8500_timer.c | 168 --------- drivers/clocksource/zevio-timer.c | 218 ------------ 28 files changed, 3429 insertions(+), 3429 deletions(-) delete mode 100644 drivers/clocksource/cadence_ttc_timer.c delete mode 100644 drivers/clocksource/fsl_ftm_timer.c delete mode 100644 drivers/clocksource/owl-timer.c delete mode 100644 drivers/clocksource/qcom-timer.c delete mode 100644 drivers/clocksource/time-armada-370-xp.c delete mode 100644 drivers/clocksource/time-efm32.c delete mode 100644 drivers/clocksource/time-lpc32xx.c delete mode 100644 drivers/clocksource/time-orion.c delete mode 100644 drivers/clocksource/time-pistachio.c create mode 100644 drivers/clocksource/timer-armada-370-xp.c create mode 100644 drivers/clocksource/timer-cadence-ttc.c create mode 100644 drivers/clocksource/timer-efm32.c create mode 100644 drivers/clocksource/timer-fsl-ftm.c create mode 100644 drivers/clocksource/timer-lpc32xx.c create mode 100644 drivers/clocksource/timer-orion.c create mode 100644 drivers/clocksource/timer-owl.c create mode 100644 drivers/clocksource/timer-pistachio.c create mode 100644 drivers/clocksource/timer-qcom.c create mode 100644 drivers/clocksource/timer-versatile.c create mode 100644 drivers/clocksource/timer-vf-pit.c create mode 100644 drivers/clocksource/timer-vt8500.c create mode 100644 drivers/clocksource/timer-zevio.c delete mode 100644 drivers/clocksource/versatile.c delete mode 100644 drivers/clocksource/vf_pit_timer.c delete mode 100644 drivers/clocksource/vt8500_timer.c delete mode 100644 drivers/clocksource/zevio-timer.c diff --git a/MAINTAINERS b/MAINTAINERS index a5b256b25905..67e877cccf40 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1181,7 +1181,7 @@ N: owl F: arch/arm/mach-actions/ F: arch/arm/boot/dts/owl-* F: arch/arm64/boot/dts/actions/ -F: drivers/clocksource/owl-* +F: drivers/clocksource/timer-owl* F: drivers/pinctrl/actions/* F: drivers/soc/actions/ F: include/dt-bindings/power/owl-* @@ -1604,7 +1604,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/boot/dts/lpc43* F: drivers/clk/nxp/clk-lpc18xx* -F: drivers/clocksource/time-lpc32xx.c +F: drivers/clocksource/timer-lpc32xx.c F: drivers/i2c/busses/i2c-lpc2k.c F: drivers/memory/pl172.c F: drivers/mtd/spi-nor/nxp-spifi.c @@ -2220,7 +2220,7 @@ F: arch/arm/mach-vexpress/ F: */*/vexpress* F: */*/*/vexpress* F: drivers/clk/versatile/clk-vexpress-osc.c -F: drivers/clocksource/versatile.c +F: drivers/clocksource/timer-versatile.c N: mps2 ARM/VFP SUPPORT @@ -2242,7 +2242,7 @@ M: Tony Prisk L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-vt8500/ -F: drivers/clocksource/vt8500_timer.c +F: drivers/clocksource/timer-vt8500.c F: drivers/i2c/busses/i2c-wmt.c F: drivers/mmc/host/wmt-sdmmc.c F: drivers/pwm/pwm-vt8500.c @@ -2307,7 +2307,7 @@ F: drivers/cpuidle/cpuidle-zynq.c F: drivers/block/xsysace.c N: zynq N: xilinx -F: drivers/clocksource/cadence_ttc_timer.c +F: drivers/clocksource/timer-cadence-ttc.c F: drivers/i2c/busses/i2c-cadence.c F: drivers/mmc/host/sdhci-of-arasan.c F: drivers/edac/synopsys_edac.c diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index db51b2427e8a..e33b21d3f9d8 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -23,8 +23,8 @@ obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o -obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o -obj-$(CONFIG_ORION_TIMER) += time-orion.o +obj-$(CONFIG_ARMADA_370_XP_TIMER) += timer-armada-370-xp.o +obj-$(CONFIG_ORION_TIMER) += timer-orion.o obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o @@ -36,25 +36,25 @@ obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o obj-$(CONFIG_TEGRA_TIMER) += tegra20_timer.o -obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o -obj-$(CONFIG_NSPIRE_TIMER) += zevio-timer.o +obj-$(CONFIG_VT8500_TIMER) += timer-vt8500.o +obj-$(CONFIG_NSPIRE_TIMER) += timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o -obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o -obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o +obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o +obj-$(CONFIG_CLKSRC_EFM32) += timer-efm32.o obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o -obj-$(CONFIG_CLKSRC_LPC32XX) += time-lpc32xx.o +obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o -obj-$(CONFIG_FSL_FTM_TIMER) += fsl_ftm_timer.o -obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o -obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o +obj-$(CONFIG_FSL_FTM_TIMER) += timer-fsl-ftm.o +obj-$(CONFIG_VF_PIT_TIMER) += timer-vf-pit.o +obj-$(CONFIG_CLKSRC_QCOM) += timer-qcom.o obj-$(CONFIG_MTK_TIMER) += timer-mediatek.o -obj-$(CONFIG_CLKSRC_PISTACHIO) += time-pistachio.o +obj-$(CONFIG_CLKSRC_PISTACHIO) += timer-pistachio.o obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o -obj-$(CONFIG_OWL_TIMER) += owl-timer.o +obj-$(CONFIG_OWL_TIMER) += timer-owl.o obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o @@ -66,7 +66,7 @@ obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp804.o obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o obj-$(CONFIG_KEYSTONE_TIMER) += timer-keystone.o obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o -obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o +obj-$(CONFIG_CLKSRC_VERSATILE) += timer-versatile.o obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c deleted file mode 100644 index b33402980b6f..000000000000 --- a/drivers/clocksource/cadence_ttc_timer.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * This file contains driver for the Cadence Triple Timer Counter Rev 06 - * - * Copyright (C) 2011-2013 Xilinx - * - * based on arch/mips/kernel/time.c timer driver - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This driver configures the 2 16/32-bit count-up timers as follows: - * - * T1: Timer 1, clocksource for generic timekeeping - * T2: Timer 2, clockevent source for hrtimers - * T3: Timer 3, - * - * The input frequency to the timer module for emulation is 2.5MHz which is - * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32, - * the timers are clocked at 78.125KHz (12.8 us resolution). - - * The input frequency to the timer module in silicon is configurable and - * obtained from device tree. The pre-scaler of 32 is used. - */ - -/* - * Timer Register Offset Definitions of Timer 1, Increment base address by 4 - * and use same offsets for Timer 2 - */ -#define TTC_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ -#define TTC_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ -#define TTC_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ -#define TTC_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ -#define TTC_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ -#define TTC_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ - -#define TTC_CNT_CNTRL_DISABLE_MASK 0x1 - -#define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ -#define TTC_CLK_CNTRL_PSV_MASK 0x1e -#define TTC_CLK_CNTRL_PSV_SHIFT 1 - -/* - * Setup the timers to use pre-scaling, using a fixed value for now that will - * work across most input frequency, but it may need to be more dynamic - */ -#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ -#define PRESCALE 2048 /* The exponent must match this */ -#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) -#define CLK_CNTRL_PRESCALE_EN 1 -#define CNT_CNTRL_RESET (1 << 4) - -#define MAX_F_ERR 50 - -/** - * struct ttc_timer - This definition defines local timer structure - * - * @base_addr: Base address of timer - * @freq: Timer input clock frequency - * @clk: Associated clock source - * @clk_rate_change_nb Notifier block for clock rate changes - */ -struct ttc_timer { - void __iomem *base_addr; - unsigned long freq; - struct clk *clk; - struct notifier_block clk_rate_change_nb; -}; - -#define to_ttc_timer(x) \ - container_of(x, struct ttc_timer, clk_rate_change_nb) - -struct ttc_timer_clocksource { - u32 scale_clk_ctrl_reg_old; - u32 scale_clk_ctrl_reg_new; - struct ttc_timer ttc; - struct clocksource cs; -}; - -#define to_ttc_timer_clksrc(x) \ - container_of(x, struct ttc_timer_clocksource, cs) - -struct ttc_timer_clockevent { - struct ttc_timer ttc; - struct clock_event_device ce; -}; - -#define to_ttc_timer_clkevent(x) \ - container_of(x, struct ttc_timer_clockevent, ce) - -static void __iomem *ttc_sched_clock_val_reg; - -/** - * ttc_set_interval - Set the timer interval value - * - * @timer: Pointer to the timer instance - * @cycles: Timer interval ticks - **/ -static void ttc_set_interval(struct ttc_timer *timer, - unsigned long cycles) -{ - u32 ctrl_reg; - - /* Disable the counter, set the counter value and re-enable counter */ - ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); - ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); - - writel_relaxed(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); - - /* - * Reset the counter (0x10) so that it starts from 0, one-shot - * mode makes this needed for timing to be right. - */ - ctrl_reg |= CNT_CNTRL_RESET; - ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); -} - -/** - * ttc_clock_event_interrupt - Clock event timer interrupt handler - * - * @irq: IRQ number of the Timer - * @dev_id: void pointer to the ttc_timer instance - * - * returns: Always IRQ_HANDLED - success - **/ -static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id) -{ - struct ttc_timer_clockevent *ttce = dev_id; - struct ttc_timer *timer = &ttce->ttc; - - /* Acknowledge the interrupt and call event handler */ - readl_relaxed(timer->base_addr + TTC_ISR_OFFSET); - - ttce->ce.event_handler(&ttce->ce); - - return IRQ_HANDLED; -} - -/** - * __ttc_clocksource_read - Reads the timer counter register - * - * returns: Current timer counter register value - **/ -static u64 __ttc_clocksource_read(struct clocksource *cs) -{ - struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; - - return (u64)readl_relaxed(timer->base_addr + - TTC_COUNT_VAL_OFFSET); -} - -static u64 notrace ttc_sched_clock_read(void) -{ - return readl_relaxed(ttc_sched_clock_val_reg); -} - -/** - * ttc_set_next_event - Sets the time interval for next event - * - * @cycles: Timer interval ticks - * @evt: Address of clock event instance - * - * returns: Always 0 - success - **/ -static int ttc_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - - ttc_set_interval(timer, cycles); - return 0; -} - -/** - * ttc_set_{shutdown|oneshot|periodic} - Sets the state of timer - * - * @evt: Address of clock event instance - **/ -static int ttc_shutdown(struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - u32 ctrl_reg; - - ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); - ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); - return 0; -} - -static int ttc_set_periodic(struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - - ttc_set_interval(timer, - DIV_ROUND_CLOSEST(ttce->ttc.freq, PRESCALE * HZ)); - return 0; -} - -static int ttc_resume(struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - u32 ctrl_reg; - - ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); - ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); - return 0; -} - -static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - struct ttc_timer *ttc = to_ttc_timer(nb); - struct ttc_timer_clocksource *ttccs = container_of(ttc, - struct ttc_timer_clocksource, ttc); - - switch (event) { - case PRE_RATE_CHANGE: - { - u32 psv; - unsigned long factor, rate_low, rate_high; - - if (ndata->new_rate > ndata->old_rate) { - factor = DIV_ROUND_CLOSEST(ndata->new_rate, - ndata->old_rate); - rate_low = ndata->old_rate; - rate_high = ndata->new_rate; - } else { - factor = DIV_ROUND_CLOSEST(ndata->old_rate, - ndata->new_rate); - rate_low = ndata->new_rate; - rate_high = ndata->old_rate; - } - - if (!is_power_of_2(factor)) - return NOTIFY_BAD; - - if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR) - return NOTIFY_BAD; - - factor = __ilog2_u32(factor); - - /* - * store timer clock ctrl register so we can restore it in case - * of an abort. - */ - ttccs->scale_clk_ctrl_reg_old = - readl_relaxed(ttccs->ttc.base_addr + - TTC_CLK_CNTRL_OFFSET); - - psv = (ttccs->scale_clk_ctrl_reg_old & - TTC_CLK_CNTRL_PSV_MASK) >> - TTC_CLK_CNTRL_PSV_SHIFT; - if (ndata->new_rate < ndata->old_rate) - psv -= factor; - else - psv += factor; - - /* prescaler within legal range? */ - if (psv & ~(TTC_CLK_CNTRL_PSV_MASK >> TTC_CLK_CNTRL_PSV_SHIFT)) - return NOTIFY_BAD; - - ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old & - ~TTC_CLK_CNTRL_PSV_MASK; - ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT; - - - /* scale down: adjust divider in post-change notification */ - if (ndata->new_rate < ndata->old_rate) - return NOTIFY_DONE; - - /* scale up: adjust divider now - before frequency change */ - writel_relaxed(ttccs->scale_clk_ctrl_reg_new, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - break; - } - case POST_RATE_CHANGE: - /* scale up: pre-change notification did the adjustment */ - if (ndata->new_rate > ndata->old_rate) - return NOTIFY_OK; - - /* scale down: adjust divider now - after frequency change */ - writel_relaxed(ttccs->scale_clk_ctrl_reg_new, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - break; - - case ABORT_RATE_CHANGE: - /* we have to undo the adjustment in case we scale up */ - if (ndata->new_rate < ndata->old_rate) - return NOTIFY_OK; - - /* restore original register value */ - writel_relaxed(ttccs->scale_clk_ctrl_reg_old, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - /* fall through */ - default: - return NOTIFY_DONE; - } - - return NOTIFY_DONE; -} - -static int __init ttc_setup_clocksource(struct clk *clk, void __iomem *base, - u32 timer_width) -{ - struct ttc_timer_clocksource *ttccs; - int err; - - ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); - if (!ttccs) - return -ENOMEM; - - ttccs->ttc.clk = clk; - - err = clk_prepare_enable(ttccs->ttc.clk); - if (err) { - kfree(ttccs); - return err; - } - - ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk); - - ttccs->ttc.clk_rate_change_nb.notifier_call = - ttc_rate_change_clocksource_cb; - ttccs->ttc.clk_rate_change_nb.next = NULL; - - err = clk_notifier_register(ttccs->ttc.clk, - &ttccs->ttc.clk_rate_change_nb); - if (err) - pr_warn("Unable to register clock notifier.\n"); - - ttccs->ttc.base_addr = base; - ttccs->cs.name = "ttc_clocksource"; - ttccs->cs.rating = 200; - ttccs->cs.read = __ttc_clocksource_read; - ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width); - ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; - - /* - * Setup the clock source counter to be an incrementing counter - * with no interrupt and it rolls over at 0xFFFF. Pre-scale - * it by 32 also. Let it start running now. - */ - writel_relaxed(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); - writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - writel_relaxed(CNT_CNTRL_RESET, - ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); - - err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE); - if (err) { - kfree(ttccs); - return err; - } - - ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; - sched_clock_register(ttc_sched_clock_read, timer_width, - ttccs->ttc.freq / PRESCALE); - - return 0; -} - -static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - struct ttc_timer *ttc = to_ttc_timer(nb); - struct ttc_timer_clockevent *ttcce = container_of(ttc, - struct ttc_timer_clockevent, ttc); - - switch (event) { - case POST_RATE_CHANGE: - /* update cached frequency */ - ttc->freq = ndata->new_rate; - - clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE); - - /* fall through */ - case PRE_RATE_CHANGE: - case ABORT_RATE_CHANGE: - default: - return NOTIFY_DONE; - } -} - -static int __init ttc_setup_clockevent(struct clk *clk, - void __iomem *base, u32 irq) -{ - struct ttc_timer_clockevent *ttcce; - int err; - - ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); - if (!ttcce) - return -ENOMEM; - - ttcce->ttc.clk = clk; - - err = clk_prepare_enable(ttcce->ttc.clk); - if (err) { - kfree(ttcce); - return err; - } - - ttcce->ttc.clk_rate_change_nb.notifier_call = - ttc_rate_change_clockevent_cb; - ttcce->ttc.clk_rate_change_nb.next = NULL; - - err = clk_notifier_register(ttcce->ttc.clk, - &ttcce->ttc.clk_rate_change_nb); - if (err) { - pr_warn("Unable to register clock notifier.\n"); - return err; - } - - ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk); - - ttcce->ttc.base_addr = base; - ttcce->ce.name = "ttc_clockevent"; - ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; - ttcce->ce.set_next_event = ttc_set_next_event; - ttcce->ce.set_state_shutdown = ttc_shutdown; - ttcce->ce.set_state_periodic = ttc_set_periodic; - ttcce->ce.set_state_oneshot = ttc_shutdown; - ttcce->ce.tick_resume = ttc_resume; - ttcce->ce.rating = 200; - ttcce->ce.irq = irq; - ttcce->ce.cpumask = cpu_possible_mask; - - /* - * Setup the clock event timer to be an interval timer which - * is prescaled by 32 using the interval interrupt. Leave it - * disabled for now. - */ - writel_relaxed(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); - writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, - ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - writel_relaxed(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); - - err = request_irq(irq, ttc_clock_event_interrupt, - IRQF_TIMER, ttcce->ce.name, ttcce); - if (err) { - kfree(ttcce); - return err; - } - - clockevents_config_and_register(&ttcce->ce, - ttcce->ttc.freq / PRESCALE, 1, 0xfffe); - - return 0; -} - -/** - * ttc_timer_init - Initialize the timer - * - * Initializes the timer hardware and register the clock source and clock event - * timers with Linux kernal timer framework - */ -static int __init ttc_timer_init(struct device_node *timer) -{ - unsigned int irq; - void __iomem *timer_baseaddr; - struct clk *clk_cs, *clk_ce; - static int initialized; - int clksel, ret; - u32 timer_width = 16; - - if (initialized) - return 0; - - initialized = 1; - - /* - * Get the 1st Triple Timer Counter (TTC) block from the device tree - * and use it. Note that the event timer uses the interrupt and it's the - * 2nd TTC hence the irq_of_parse_and_map(,1) - */ - timer_baseaddr = of_iomap(timer, 0); - if (!timer_baseaddr) { - pr_err("ERROR: invalid timer base address\n"); - return -ENXIO; - } - - irq = irq_of_parse_and_map(timer, 1); - if (irq <= 0) { - pr_err("ERROR: invalid interrupt number\n"); - return -EINVAL; - } - - of_property_read_u32(timer, "timer-width", &timer_width); - - clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); - clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); - clk_cs = of_clk_get(timer, clksel); - if (IS_ERR(clk_cs)) { - pr_err("ERROR: timer input clock not found\n"); - return PTR_ERR(clk_cs); - } - - clksel = readl_relaxed(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); - clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); - clk_ce = of_clk_get(timer, clksel); - if (IS_ERR(clk_ce)) { - pr_err("ERROR: timer input clock not found\n"); - return PTR_ERR(clk_ce); - } - - ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width); - if (ret) - return ret; - - ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); - if (ret) - return ret; - - pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq); - - return 0; -} - -TIMER_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init); diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c deleted file mode 100644 index 846d18daf893..000000000000 --- a/drivers/clocksource/fsl_ftm_timer.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Freescale FlexTimer Module (FTM) timer driver. - * - * Copyright 2014 Freescale Semiconductor, Inc. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define FTM_SC 0x00 -#define FTM_SC_CLK_SHIFT 3 -#define FTM_SC_CLK_MASK (0x3 << FTM_SC_CLK_SHIFT) -#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_SHIFT) -#define FTM_SC_PS_MASK 0x7 -#define FTM_SC_TOIE BIT(6) -#define FTM_SC_TOF BIT(7) - -#define FTM_CNT 0x04 -#define FTM_MOD 0x08 -#define FTM_CNTIN 0x4C - -#define FTM_PS_MAX 7 - -struct ftm_clock_device { - void __iomem *clksrc_base; - void __iomem *clkevt_base; - unsigned long periodic_cyc; - unsigned long ps; - bool big_endian; -}; - -static struct ftm_clock_device *priv; - -static inline u32 ftm_readl(void __iomem *addr) -{ - if (priv->big_endian) - return ioread32be(addr); - else - return ioread32(addr); -} - -static inline void ftm_writel(u32 val, void __iomem *addr) -{ - if (priv->big_endian) - iowrite32be(val, addr); - else - iowrite32(val, addr); -} - -static inline void ftm_counter_enable(void __iomem *base) -{ - u32 val; - - /* select and enable counter clock source */ - val = ftm_readl(base + FTM_SC); - val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); - val |= priv->ps | FTM_SC_CLK(1); - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_counter_disable(void __iomem *base) -{ - u32 val; - - /* disable counter clock source */ - val = ftm_readl(base + FTM_SC); - val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_irq_acknowledge(void __iomem *base) -{ - u32 val; - - val = ftm_readl(base + FTM_SC); - val &= ~FTM_SC_TOF; - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_irq_enable(void __iomem *base) -{ - u32 val; - - val = ftm_readl(base + FTM_SC); - val |= FTM_SC_TOIE; - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_irq_disable(void __iomem *base) -{ - u32 val; - - val = ftm_readl(base + FTM_SC); - val &= ~FTM_SC_TOIE; - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_reset_counter(void __iomem *base) -{ - /* - * The CNT register contains the FTM counter value. - * Reset clears the CNT register. Writing any value to COUNT - * updates the counter with its initial value, CNTIN. - */ - ftm_writel(0x00, base + FTM_CNT); -} - -static u64 notrace ftm_read_sched_clock(void) -{ - return ftm_readl(priv->clksrc_base + FTM_CNT); -} - -static int ftm_set_next_event(unsigned long delta, - struct clock_event_device *unused) -{ - /* - * The CNNIN and MOD are all double buffer registers, writing - * to the MOD register latches the value into a buffer. The MOD - * register is updated with the value of its write buffer with - * the following scenario: - * a, the counter source clock is diabled. - */ - ftm_counter_disable(priv->clkevt_base); - - /* Force the value of CNTIN to be loaded into the FTM counter */ - ftm_reset_counter(priv->clkevt_base); - - /* - * The counter increments until the value of MOD is reached, - * at which point the counter is reloaded with the value of CNTIN. - * The TOF (the overflow flag) bit is set when the FTM counter - * changes from MOD to CNTIN. So we should using the delta - 1. - */ - ftm_writel(delta - 1, priv->clkevt_base + FTM_MOD); - - ftm_counter_enable(priv->clkevt_base); - - ftm_irq_enable(priv->clkevt_base); - - return 0; -} - -static int ftm_set_oneshot(struct clock_event_device *evt) -{ - ftm_counter_disable(priv->clkevt_base); - return 0; -} - -static int ftm_set_periodic(struct clock_event_device *evt) -{ - ftm_set_next_event(priv->periodic_cyc, evt); - return 0; -} - -static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - ftm_irq_acknowledge(priv->clkevt_base); - - if (likely(clockevent_state_oneshot(evt))) { - ftm_irq_disable(priv->clkevt_base); - ftm_counter_disable(priv->clkevt_base); - } - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct clock_event_device ftm_clockevent = { - .name = "Freescale ftm timer", - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .set_state_periodic = ftm_set_periodic, - .set_state_oneshot = ftm_set_oneshot, - .set_next_event = ftm_set_next_event, - .rating = 300, -}; - -static struct irqaction ftm_timer_irq = { - .name = "Freescale ftm timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = ftm_evt_interrupt, - .dev_id = &ftm_clockevent, -}; - -static int __init ftm_clockevent_init(unsigned long freq, int irq) -{ - int err; - - ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN); - ftm_writel(~0u, priv->clkevt_base + FTM_MOD); - - ftm_reset_counter(priv->clkevt_base); - - err = setup_irq(irq, &ftm_timer_irq); - if (err) { - pr_err("ftm: setup irq failed: %d\n", err); - return err; - } - - ftm_clockevent.cpumask = cpumask_of(0); - ftm_clockevent.irq = irq; - - clockevents_config_and_register(&ftm_clockevent, - freq / (1 << priv->ps), - 1, 0xffff); - - ftm_counter_enable(priv->clkevt_base); - - return 0; -} - -static int __init ftm_clocksource_init(unsigned long freq) -{ - int err; - - ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN); - ftm_writel(~0u, priv->clksrc_base + FTM_MOD); - - ftm_reset_counter(priv->clksrc_base); - - sched_clock_register(ftm_read_sched_clock, 16, freq / (1 << priv->ps)); - err = clocksource_mmio_init(priv->clksrc_base + FTM_CNT, "fsl-ftm", - freq / (1 << priv->ps), 300, 16, - clocksource_mmio_readl_up); - if (err) { - pr_err("ftm: init clock source mmio failed: %d\n", err); - return err; - } - - ftm_counter_enable(priv->clksrc_base); - - return 0; -} - -static int __init __ftm_clk_init(struct device_node *np, char *cnt_name, - char *ftm_name) -{ - struct clk *clk; - int err; - - clk = of_clk_get_by_name(np, cnt_name); - if (IS_ERR(clk)) { - pr_err("ftm: Cannot get \"%s\": %ld\n", cnt_name, PTR_ERR(clk)); - return PTR_ERR(clk); - } - err = clk_prepare_enable(clk); - if (err) { - pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", - cnt_name, err); - return err; - } - - clk = of_clk_get_by_name(np, ftm_name); - if (IS_ERR(clk)) { - pr_err("ftm: Cannot get \"%s\": %ld\n", ftm_name, PTR_ERR(clk)); - return PTR_ERR(clk); - } - err = clk_prepare_enable(clk); - if (err) - pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", - ftm_name, err); - - return clk_get_rate(clk); -} - -static unsigned long __init ftm_clk_init(struct device_node *np) -{ - long freq; - - freq = __ftm_clk_init(np, "ftm-evt-counter-en", "ftm-evt"); - if (freq <= 0) - return 0; - - freq = __ftm_clk_init(np, "ftm-src-counter-en", "ftm-src"); - if (freq <= 0) - return 0; - - return freq; -} - -static int __init ftm_calc_closest_round_cyc(unsigned long freq) -{ - priv->ps = 0; - - /* The counter register is only using the lower 16 bits, and - * if the 'freq' value is to big here, then the periodic_cyc - * may exceed 0xFFFF. - */ - do { - priv->periodic_cyc = DIV_ROUND_CLOSEST(freq, - HZ * (1 << priv->ps++)); - } while (priv->periodic_cyc > 0xFFFF); - - if (priv->ps > FTM_PS_MAX) { - pr_err("ftm: the prescaler is %lu > %d\n", - priv->ps, FTM_PS_MAX); - return -EINVAL; - } - - return 0; -} - -static int __init ftm_timer_init(struct device_node *np) -{ - unsigned long freq; - int ret, irq; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - ret = -ENXIO; - priv->clkevt_base = of_iomap(np, 0); - if (!priv->clkevt_base) { - pr_err("ftm: unable to map event timer registers\n"); - goto err_clkevt; - } - - priv->clksrc_base = of_iomap(np, 1); - if (!priv->clksrc_base) { - pr_err("ftm: unable to map source timer registers\n"); - goto err_clksrc; - } - - ret = -EINVAL; - irq = irq_of_parse_and_map(np, 0); - if (irq <= 0) { - pr_err("ftm: unable to get IRQ from DT, %d\n", irq); - goto err; - } - - priv->big_endian = of_property_read_bool(np, "big-endian"); - - freq = ftm_clk_init(np); - if (!freq) - goto err; - - ret = ftm_calc_closest_round_cyc(freq); - if (ret) - goto err; - - ret = ftm_clocksource_init(freq); - if (ret) - goto err; - - ret = ftm_clockevent_init(freq, irq); - if (ret) - goto err; - - return 0; - -err: - iounmap(priv->clksrc_base); -err_clksrc: - iounmap(priv->clkevt_base); -err_clkevt: - kfree(priv); - return ret; -} -TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init); diff --git a/drivers/clocksource/owl-timer.c b/drivers/clocksource/owl-timer.c deleted file mode 100644 index ea00a5e8f95d..000000000000 --- a/drivers/clocksource/owl-timer.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Actions Semi Owl timer - * - * Copyright 2012 Actions Semi Inc. - * Author: Actions Semi, Inc. - * - * Copyright (c) 2017 SUSE Linux GmbH - * Author: Andreas Färber - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define OWL_Tx_CTL 0x0 -#define OWL_Tx_CMP 0x4 -#define OWL_Tx_VAL 0x8 - -#define OWL_Tx_CTL_PD BIT(0) -#define OWL_Tx_CTL_INTEN BIT(1) -#define OWL_Tx_CTL_EN BIT(2) - -static void __iomem *owl_timer_base; -static void __iomem *owl_clksrc_base; -static void __iomem *owl_clkevt_base; - -static inline void owl_timer_reset(void __iomem *base) -{ - writel(0, base + OWL_Tx_CTL); - writel(0, base + OWL_Tx_VAL); - writel(0, base + OWL_Tx_CMP); -} - -static inline void owl_timer_set_enabled(void __iomem *base, bool enabled) -{ - u32 ctl = readl(base + OWL_Tx_CTL); - - /* PD bit is cleared when set */ - ctl &= ~OWL_Tx_CTL_PD; - - if (enabled) - ctl |= OWL_Tx_CTL_EN; - else - ctl &= ~OWL_Tx_CTL_EN; - - writel(ctl, base + OWL_Tx_CTL); -} - -static u64 notrace owl_timer_sched_read(void) -{ - return (u64)readl(owl_clksrc_base + OWL_Tx_VAL); -} - -static int owl_timer_set_state_shutdown(struct clock_event_device *evt) -{ - owl_timer_set_enabled(owl_clkevt_base, false); - - return 0; -} - -static int owl_timer_set_state_oneshot(struct clock_event_device *evt) -{ - owl_timer_reset(owl_clkevt_base); - - return 0; -} - -static int owl_timer_tick_resume(struct clock_event_device *evt) -{ - return 0; -} - -static int owl_timer_set_next_event(unsigned long evt, - struct clock_event_device *ev) -{ - void __iomem *base = owl_clkevt_base; - - owl_timer_set_enabled(base, false); - writel(OWL_Tx_CTL_INTEN, base + OWL_Tx_CTL); - writel(0, base + OWL_Tx_VAL); - writel(evt, base + OWL_Tx_CMP); - owl_timer_set_enabled(base, true); - - return 0; -} - -static struct clock_event_device owl_clockevent = { - .name = "owl_tick", - .rating = 200, - .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_DYNIRQ, - .set_state_shutdown = owl_timer_set_state_shutdown, - .set_state_oneshot = owl_timer_set_state_oneshot, - .tick_resume = owl_timer_tick_resume, - .set_next_event = owl_timer_set_next_event, -}; - -static irqreturn_t owl_timer1_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = (struct clock_event_device *)dev_id; - - writel(OWL_Tx_CTL_PD, owl_clkevt_base + OWL_Tx_CTL); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static int __init owl_timer_init(struct device_node *node) -{ - struct clk *clk; - unsigned long rate; - int timer1_irq, ret; - - owl_timer_base = of_io_request_and_map(node, 0, "owl-timer"); - if (IS_ERR(owl_timer_base)) { - pr_err("Can't map timer registers\n"); - return PTR_ERR(owl_timer_base); - } - - owl_clksrc_base = owl_timer_base + 0x08; - owl_clkevt_base = owl_timer_base + 0x14; - - timer1_irq = of_irq_get_byname(node, "timer1"); - if (timer1_irq <= 0) { - pr_err("Can't parse timer1 IRQ\n"); - return -EINVAL; - } - - clk = of_clk_get(node, 0); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - rate = clk_get_rate(clk); - - owl_timer_reset(owl_clksrc_base); - owl_timer_set_enabled(owl_clksrc_base, true); - - sched_clock_register(owl_timer_sched_read, 32, rate); - clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name, - rate, 200, 32, clocksource_mmio_readl_up); - - owl_timer_reset(owl_clkevt_base); - - ret = request_irq(timer1_irq, owl_timer1_interrupt, IRQF_TIMER, - "owl-timer", &owl_clockevent); - if (ret) { - pr_err("failed to request irq %d\n", timer1_irq); - return ret; - } - - owl_clockevent.cpumask = cpumask_of(0); - owl_clockevent.irq = timer1_irq; - - clockevents_config_and_register(&owl_clockevent, rate, - 0xf, 0xffffffff); - - return 0; -} -TIMER_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init); -TIMER_OF_DECLARE(owl_s700, "actions,s700-timer", owl_timer_init); -TIMER_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init); diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c deleted file mode 100644 index 89816f89ff3f..000000000000 --- a/drivers/clocksource/qcom-timer.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * - * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define TIMER_MATCH_VAL 0x0000 -#define TIMER_COUNT_VAL 0x0004 -#define TIMER_ENABLE 0x0008 -#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) -#define TIMER_ENABLE_EN BIT(0) -#define TIMER_CLEAR 0x000C -#define DGT_CLK_CTL 0x10 -#define DGT_CLK_CTL_DIV_4 0x3 -#define TIMER_STS_GPT0_CLR_PEND BIT(10) - -#define GPT_HZ 32768 - -static void __iomem *event_base; -static void __iomem *sts_base; - -static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - /* Stop the timer tick */ - if (clockevent_state_oneshot(evt)) { - u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); - ctrl &= ~TIMER_ENABLE_EN; - writel_relaxed(ctrl, event_base + TIMER_ENABLE); - } - evt->event_handler(evt); - return IRQ_HANDLED; -} - -static int msm_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); - - ctrl &= ~TIMER_ENABLE_EN; - writel_relaxed(ctrl, event_base + TIMER_ENABLE); - - writel_relaxed(ctrl, event_base + TIMER_CLEAR); - writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); - - if (sts_base) - while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) - cpu_relax(); - - writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); - return 0; -} - -static int msm_timer_shutdown(struct clock_event_device *evt) -{ - u32 ctrl; - - ctrl = readl_relaxed(event_base + TIMER_ENABLE); - ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); - writel_relaxed(ctrl, event_base + TIMER_ENABLE); - return 0; -} - -static struct clock_event_device __percpu *msm_evt; - -static void __iomem *source_base; - -static notrace u64 msm_read_timer_count(struct clocksource *cs) -{ - return readl_relaxed(source_base + TIMER_COUNT_VAL); -} - -static struct clocksource msm_clocksource = { - .name = "dg_timer", - .rating = 300, - .read = msm_read_timer_count, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static int msm_timer_irq; -static int msm_timer_has_ppi; - -static int msm_local_timer_starting_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); - int err; - - evt->irq = msm_timer_irq; - evt->name = "msm_timer"; - evt->features = CLOCK_EVT_FEAT_ONESHOT; - evt->rating = 200; - evt->set_state_shutdown = msm_timer_shutdown; - evt->set_state_oneshot = msm_timer_shutdown; - evt->tick_resume = msm_timer_shutdown; - evt->set_next_event = msm_timer_set_next_event; - evt->cpumask = cpumask_of(cpu); - - clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); - - if (msm_timer_has_ppi) { - enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); - } else { - err = request_irq(evt->irq, msm_timer_interrupt, - IRQF_TIMER | IRQF_NOBALANCING | - IRQF_TRIGGER_RISING, "gp_timer", evt); - if (err) - pr_err("request_irq failed\n"); - } - - return 0; -} - -static int msm_local_timer_dying_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); - - evt->set_state_shutdown(evt); - disable_percpu_irq(evt->irq); - return 0; -} - -static u64 notrace msm_sched_clock_read(void) -{ - return msm_clocksource.read(&msm_clocksource); -} - -static unsigned long msm_read_current_timer(void) -{ - return msm_clocksource.read(&msm_clocksource); -} - -static struct delay_timer msm_delay_timer = { - .read_current_timer = msm_read_current_timer, -}; - -static int __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, - bool percpu) -{ - struct clocksource *cs = &msm_clocksource; - int res = 0; - - msm_timer_irq = irq; - msm_timer_has_ppi = percpu; - - msm_evt = alloc_percpu(struct clock_event_device); - if (!msm_evt) { - pr_err("memory allocation failed for clockevents\n"); - goto err; - } - - if (percpu) - res = request_percpu_irq(irq, msm_timer_interrupt, - "gp_timer", msm_evt); - - if (res) { - pr_err("request_percpu_irq failed\n"); - } else { - /* Install and invoke hotplug callbacks */ - res = cpuhp_setup_state(CPUHP_AP_QCOM_TIMER_STARTING, - "clockevents/qcom/timer:starting", - msm_local_timer_starting_cpu, - msm_local_timer_dying_cpu); - if (res) { - free_percpu_irq(irq, msm_evt); - goto err; - } - } - -err: - writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); - res = clocksource_register_hz(cs, dgt_hz); - if (res) - pr_err("clocksource_register failed\n"); - sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); - msm_delay_timer.freq = dgt_hz; - register_current_timer_delay(&msm_delay_timer); - - return res; -} - -static int __init msm_dt_timer_init(struct device_node *np) -{ - u32 freq; - int irq, ret; - struct resource res; - u32 percpu_offset; - void __iomem *base; - void __iomem *cpu0_base; - - base = of_iomap(np, 0); - if (!base) { - pr_err("Failed to map event base\n"); - return -ENXIO; - } - - /* We use GPT0 for the clockevent */ - irq = irq_of_parse_and_map(np, 1); - if (irq <= 0) { - pr_err("Can't get irq\n"); - return -EINVAL; - } - - /* We use CPU0's DGT for the clocksource */ - if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) - percpu_offset = 0; - - ret = of_address_to_resource(np, 0, &res); - if (ret) { - pr_err("Failed to parse DGT resource\n"); - return ret; - } - - cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); - if (!cpu0_base) { - pr_err("Failed to map source base\n"); - return -EINVAL; - } - - if (of_property_read_u32(np, "clock-frequency", &freq)) { - pr_err("Unknown frequency\n"); - return -EINVAL; - } - - event_base = base + 0x4; - sts_base = base + 0x88; - source_base = cpu0_base + 0x24; - freq /= 4; - writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); - - return msm_timer_init(freq, 32, irq, !!percpu_offset); -} -TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); -TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c deleted file mode 100644 index edf1a46269f1..000000000000 --- a/drivers/clocksource/time-armada-370-xp.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Marvell Armada 370/XP SoC timer handling. - * - * Copyright (C) 2012 Marvell - * - * Lior Amsalem - * Gregory CLEMENT - * Thomas Petazzoni - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * Timer 0 is used as free-running clocksource, while timer 1 is - * used as clock_event_device. - * - * --- - * Clocksource driver for Armada 370 and Armada XP SoC. - * This driver implements one compatible string for each SoC, given - * each has its own characteristics: - * - * * Armada 370 has no 25 MHz fixed timer. - * - * * Armada XP cannot work properly without such 25 MHz fixed timer as - * doing otherwise leads to using a clocksource whose frequency varies - * when doing cpufreq frequency changes. - * - * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * Timer block registers. - */ -#define TIMER_CTRL_OFF 0x0000 -#define TIMER0_EN BIT(0) -#define TIMER0_RELOAD_EN BIT(1) -#define TIMER0_25MHZ BIT(11) -#define TIMER0_DIV(div) ((div) << 19) -#define TIMER1_EN BIT(2) -#define TIMER1_RELOAD_EN BIT(3) -#define TIMER1_25MHZ BIT(12) -#define TIMER1_DIV(div) ((div) << 22) -#define TIMER_EVENTS_STATUS 0x0004 -#define TIMER0_CLR_MASK (~0x1) -#define TIMER1_CLR_MASK (~0x100) -#define TIMER0_RELOAD_OFF 0x0010 -#define TIMER0_VAL_OFF 0x0014 -#define TIMER1_RELOAD_OFF 0x0018 -#define TIMER1_VAL_OFF 0x001c - -#define LCL_TIMER_EVENTS_STATUS 0x0028 -/* Global timers are connected to the coherency fabric clock, and the - below divider reduces their incrementing frequency. */ -#define TIMER_DIVIDER_SHIFT 5 -#define TIMER_DIVIDER (1 << TIMER_DIVIDER_SHIFT) - -/* - * SoC-specific data. - */ -static void __iomem *timer_base, *local_base; -static unsigned int timer_clk; -static bool timer25Mhz = true; -static u32 enable_mask; - -/* - * Number of timer ticks per jiffy. - */ -static u32 ticks_per_jiffy; - -static struct clock_event_device __percpu *armada_370_xp_evt; - -static void local_timer_ctrl_clrset(u32 clr, u32 set) -{ - writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set, - local_base + TIMER_CTRL_OFF); -} - -static u64 notrace armada_370_xp_read_sched_clock(void) -{ - return ~readl(timer_base + TIMER0_VAL_OFF); -} - -/* - * Clockevent handling. - */ -static int -armada_370_xp_clkevt_next_event(unsigned long delta, - struct clock_event_device *dev) -{ - /* - * Clear clockevent timer interrupt. - */ - writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); - - /* - * Setup new clockevent timer value. - */ - writel(delta, local_base + TIMER0_VAL_OFF); - - /* - * Enable the timer. - */ - local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); - return 0; -} - -static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt) -{ - /* - * Disable timer. - */ - local_timer_ctrl_clrset(TIMER0_EN, 0); - - /* - * ACK pending timer interrupt. - */ - writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); - return 0; -} - -static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt) -{ - /* - * Setup timer to fire at 1/HZ intervals. - */ - writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); - writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); - - /* - * Enable timer. - */ - local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); - return 0; -} - -static int armada_370_xp_clkevt_irq; - -static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) -{ - /* - * ACK timer interrupt and call event handler. - */ - struct clock_event_device *evt = dev_id; - - writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -/* - * Setup the local clock events for a CPU. - */ -static int armada_370_xp_timer_starting_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); - u32 clr = 0, set = 0; - - if (timer25Mhz) - set = TIMER0_25MHZ; - else - clr = TIMER0_25MHZ; - local_timer_ctrl_clrset(clr, set); - - evt->name = "armada_370_xp_per_cpu_tick", - evt->features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC; - evt->shift = 32, - evt->rating = 300, - evt->set_next_event = armada_370_xp_clkevt_next_event, - evt->set_state_shutdown = armada_370_xp_clkevt_shutdown; - evt->set_state_periodic = armada_370_xp_clkevt_set_periodic; - evt->set_state_oneshot = armada_370_xp_clkevt_shutdown; - evt->tick_resume = armada_370_xp_clkevt_shutdown; - evt->irq = armada_370_xp_clkevt_irq; - evt->cpumask = cpumask_of(cpu); - - clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe); - enable_percpu_irq(evt->irq, 0); - - return 0; -} - -static int armada_370_xp_timer_dying_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); - - evt->set_state_shutdown(evt); - disable_percpu_irq(evt->irq); - return 0; -} - -static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; - -static int armada_370_xp_timer_suspend(void) -{ - timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF); - timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF); - return 0; -} - -static void armada_370_xp_timer_resume(void) -{ - writel(0xffffffff, timer_base + TIMER0_VAL_OFF); - writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); - writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF); - writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF); -} - -static struct syscore_ops armada_370_xp_timer_syscore_ops = { - .suspend = armada_370_xp_timer_suspend, - .resume = armada_370_xp_timer_resume, -}; - -static unsigned long armada_370_delay_timer_read(void) -{ - return ~readl(timer_base + TIMER0_VAL_OFF); -} - -static struct delay_timer armada_370_delay_timer = { - .read_current_timer = armada_370_delay_timer_read, -}; - -static int __init armada_370_xp_timer_common_init(struct device_node *np) -{ - u32 clr = 0, set = 0; - int res; - - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("Failed to iomap\n"); - return -ENXIO; - } - - local_base = of_iomap(np, 1); - if (!local_base) { - pr_err("Failed to iomap\n"); - return -ENXIO; - } - - if (timer25Mhz) { - set = TIMER0_25MHZ; - enable_mask = TIMER0_EN; - } else { - clr = TIMER0_25MHZ; - enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); - } - atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set); - local_timer_ctrl_clrset(clr, set); - - /* - * We use timer 0 as clocksource, and private(local) timer 0 - * for clockevents - */ - armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4); - - ticks_per_jiffy = (timer_clk + HZ / 2) / HZ; - - /* - * Setup free-running clocksource timer (interrupts - * disabled). - */ - writel(0xffffffff, timer_base + TIMER0_VAL_OFF); - writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); - - atomic_io_modify(timer_base + TIMER_CTRL_OFF, - TIMER0_RELOAD_EN | enable_mask, - TIMER0_RELOAD_EN | enable_mask); - - armada_370_delay_timer.freq = timer_clk; - register_current_timer_delay(&armada_370_delay_timer); - - /* - * Set scale and timer for sched_clock. - */ - sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk); - - res = clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, - "armada_370_xp_clocksource", - timer_clk, 300, 32, clocksource_mmio_readl_down); - if (res) { - pr_err("Failed to initialize clocksource mmio\n"); - return res; - } - - armada_370_xp_evt = alloc_percpu(struct clock_event_device); - if (!armada_370_xp_evt) - return -ENOMEM; - - /* - * Setup clockevent timer (interrupt-driven). - */ - res = request_percpu_irq(armada_370_xp_clkevt_irq, - armada_370_xp_timer_interrupt, - "armada_370_xp_per_cpu_tick", - armada_370_xp_evt); - /* Immediately configure the timer on the boot CPU */ - if (res) { - pr_err("Failed to request percpu irq\n"); - return res; - } - - res = cpuhp_setup_state(CPUHP_AP_ARMADA_TIMER_STARTING, - "clockevents/armada:starting", - armada_370_xp_timer_starting_cpu, - armada_370_xp_timer_dying_cpu); - if (res) { - pr_err("Failed to setup hotplug state and timer\n"); - return res; - } - - register_syscore_ops(&armada_370_xp_timer_syscore_ops); - - return 0; -} - -static int __init armada_xp_timer_init(struct device_node *np) -{ - struct clk *clk = of_clk_get_by_name(np, "fixed"); - int ret; - - if (IS_ERR(clk)) { - pr_err("Failed to get clock\n"); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) - return ret; - - timer_clk = clk_get_rate(clk); - - return armada_370_xp_timer_common_init(np); -} -TIMER_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", - armada_xp_timer_init); - -static int __init armada_375_timer_init(struct device_node *np) -{ - struct clk *clk; - int ret; - - clk = of_clk_get_by_name(np, "fixed"); - if (!IS_ERR(clk)) { - ret = clk_prepare_enable(clk); - if (ret) - return ret; - timer_clk = clk_get_rate(clk); - } else { - - /* - * This fallback is required in order to retain proper - * devicetree backwards compatibility. - */ - clk = of_clk_get(np, 0); - - /* Must have at least a clock */ - if (IS_ERR(clk)) { - pr_err("Failed to get clock\n"); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) - return ret; - - timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; - timer25Mhz = false; - } - - return armada_370_xp_timer_common_init(np); -} -TIMER_OF_DECLARE(armada_375, "marvell,armada-375-timer", - armada_375_timer_init); - -static int __init armada_370_timer_init(struct device_node *np) -{ - struct clk *clk; - int ret; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - pr_err("Failed to get clock\n"); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) - return ret; - - timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; - timer25Mhz = false; - - return armada_370_xp_timer_common_init(np); -} -TIMER_OF_DECLARE(armada_370, "marvell,armada-370-timer", - armada_370_timer_init); diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c deleted file mode 100644 index 257e810ec1ad..000000000000 --- a/drivers/clocksource/time-efm32.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2013 Pengutronix - * Uwe Kleine-Koenig - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TIMERn_CTRL 0x00 -#define TIMERn_CTRL_PRESC(val) (((val) & 0xf) << 24) -#define TIMERn_CTRL_PRESC_1024 TIMERn_CTRL_PRESC(10) -#define TIMERn_CTRL_CLKSEL(val) (((val) & 0x3) << 16) -#define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK TIMERn_CTRL_CLKSEL(0) -#define TIMERn_CTRL_OSMEN 0x00000010 -#define TIMERn_CTRL_MODE(val) (((val) & 0x3) << 0) -#define TIMERn_CTRL_MODE_UP TIMERn_CTRL_MODE(0) -#define TIMERn_CTRL_MODE_DOWN TIMERn_CTRL_MODE(1) - -#define TIMERn_CMD 0x04 -#define TIMERn_CMD_START 0x00000001 -#define TIMERn_CMD_STOP 0x00000002 - -#define TIMERn_IEN 0x0c -#define TIMERn_IF 0x10 -#define TIMERn_IFS 0x14 -#define TIMERn_IFC 0x18 -#define TIMERn_IRQ_UF 0x00000002 - -#define TIMERn_TOP 0x1c -#define TIMERn_CNT 0x24 - -struct efm32_clock_event_ddata { - struct clock_event_device evtdev; - void __iomem *base; - unsigned periodic_top; -}; - -static int efm32_clock_event_shutdown(struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - return 0; -} - -static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - writel_relaxed(TIMERn_CTRL_PRESC_1024 | - TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | - TIMERn_CTRL_OSMEN | - TIMERn_CTRL_MODE_DOWN, - ddata->base + TIMERn_CTRL); - return 0; -} - -static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); - writel_relaxed(TIMERn_CTRL_PRESC_1024 | - TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | - TIMERn_CTRL_MODE_DOWN, - ddata->base + TIMERn_CTRL); - writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); - return 0; -} - -static int efm32_clock_event_set_next_event(unsigned long evt, - struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - writel_relaxed(evt, ddata->base + TIMERn_CNT); - writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); - - return 0; -} - -static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id) -{ - struct efm32_clock_event_ddata *ddata = dev_id; - - writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC); - - ddata->evtdev.event_handler(&ddata->evtdev); - - return IRQ_HANDLED; -} - -static struct efm32_clock_event_ddata clock_event_ddata = { - .evtdev = { - .name = "efm32 clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, - .set_state_shutdown = efm32_clock_event_shutdown, - .set_state_periodic = efm32_clock_event_set_periodic, - .set_state_oneshot = efm32_clock_event_set_oneshot, - .set_next_event = efm32_clock_event_set_next_event, - .rating = 200, - }, -}; - -static struct irqaction efm32_clock_event_irq = { - .name = "efm32 clockevent", - .flags = IRQF_TIMER, - .handler = efm32_clock_event_handler, - .dev_id = &clock_event_ddata, -}; - -static int __init efm32_clocksource_init(struct device_node *np) -{ - struct clk *clk; - void __iomem *base; - unsigned long rate; - int ret; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - pr_err("failed to get clock for clocksource (%d)\n", ret); - goto err_clk_get; - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("failed to enable timer clock for clocksource (%d)\n", - ret); - goto err_clk_enable; - } - rate = clk_get_rate(clk); - - base = of_iomap(np, 0); - if (!base) { - ret = -EADDRNOTAVAIL; - pr_err("failed to map registers for clocksource\n"); - goto err_iomap; - } - - writel_relaxed(TIMERn_CTRL_PRESC_1024 | - TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | - TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL); - writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD); - - ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer", - DIV_ROUND_CLOSEST(rate, 1024), 200, 16, - clocksource_mmio_readl_up); - if (ret) { - pr_err("failed to init clocksource (%d)\n", ret); - goto err_clocksource_init; - } - - return 0; - -err_clocksource_init: - - iounmap(base); -err_iomap: - - clk_disable_unprepare(clk); -err_clk_enable: - - clk_put(clk); -err_clk_get: - - return ret; -} - -static int __init efm32_clockevent_init(struct device_node *np) -{ - struct clk *clk; - void __iomem *base; - unsigned long rate; - int irq; - int ret; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - pr_err("failed to get clock for clockevent (%d)\n", ret); - goto err_clk_get; - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("failed to enable timer clock for clockevent (%d)\n", - ret); - goto err_clk_enable; - } - rate = clk_get_rate(clk); - - base = of_iomap(np, 0); - if (!base) { - ret = -EADDRNOTAVAIL; - pr_err("failed to map registers for clockevent\n"); - goto err_iomap; - } - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - ret = -ENOENT; - pr_err("failed to get irq for clockevent\n"); - goto err_get_irq; - } - - writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN); - - clock_event_ddata.base = base; - clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); - - clockevents_config_and_register(&clock_event_ddata.evtdev, - DIV_ROUND_CLOSEST(rate, 1024), - 0xf, 0xffff); - - ret = setup_irq(irq, &efm32_clock_event_irq); - if (ret) { - pr_err("Failed setup irq\n"); - goto err_setup_irq; - } - - return 0; - -err_setup_irq: -err_get_irq: - - iounmap(base); -err_iomap: - - clk_disable_unprepare(clk); -err_clk_enable: - - clk_put(clk); -err_clk_get: - - return ret; -} - -/* - * This function asserts that we have exactly one clocksource and one - * clock_event_device in the end. - */ -static int __init efm32_timer_init(struct device_node *np) -{ - static int has_clocksource, has_clockevent; - int ret = 0; - - if (!has_clocksource) { - ret = efm32_clocksource_init(np); - if (!ret) { - has_clocksource = 1; - return 0; - } - } - - if (!has_clockevent) { - ret = efm32_clockevent_init(np); - if (!ret) { - has_clockevent = 1; - return 0; - } - } - - return ret; -} -TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); -TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c deleted file mode 100644 index d51a62a79ef7..000000000000 --- a/drivers/clocksource/time-lpc32xx.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Clocksource driver for NXP LPC32xx/18xx/43xx timer - * - * Copyright (C) 2015 Joachim Eastwood - * - * Based on: - * time-efm32 Copyright (C) 2013 Pengutronix - * mach-lpc32xx/timer.c Copyright (C) 2009 - 2010 NXP Semiconductors - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LPC32XX_TIMER_IR 0x000 -#define LPC32XX_TIMER_IR_MR0INT BIT(0) -#define LPC32XX_TIMER_TCR 0x004 -#define LPC32XX_TIMER_TCR_CEN BIT(0) -#define LPC32XX_TIMER_TCR_CRST BIT(1) -#define LPC32XX_TIMER_TC 0x008 -#define LPC32XX_TIMER_PR 0x00c -#define LPC32XX_TIMER_MCR 0x014 -#define LPC32XX_TIMER_MCR_MR0I BIT(0) -#define LPC32XX_TIMER_MCR_MR0R BIT(1) -#define LPC32XX_TIMER_MCR_MR0S BIT(2) -#define LPC32XX_TIMER_MR0 0x018 -#define LPC32XX_TIMER_CTCR 0x070 - -struct lpc32xx_clock_event_ddata { - struct clock_event_device evtdev; - void __iomem *base; - u32 ticks_per_jiffy; -}; - -/* Needed for the sched clock */ -static void __iomem *clocksource_timer_counter; - -static u64 notrace lpc32xx_read_sched_clock(void) -{ - return readl(clocksource_timer_counter); -} - -static unsigned long lpc32xx_delay_timer_read(void) -{ - return readl(clocksource_timer_counter); -} - -static struct delay_timer lpc32xx_delay_timer = { - .read_current_timer = lpc32xx_delay_timer_read, -}; - -static int lpc32xx_clkevt_next_event(unsigned long delta, - struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* - * Place timer in reset and program the delta in the match - * channel 0 (MR0). When the timer counter matches the value - * in MR0 register the match will trigger an interrupt. - * After setup the timer is released from reset and enabled. - */ - writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); - writel_relaxed(delta, ddata->base + LPC32XX_TIMER_MR0); - writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); - - return 0; -} - -static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* Disable the timer */ - writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); - - return 0; -} - -static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* - * When using oneshot, we must also disable the timer - * to wait for the first call to set_next_event(). - */ - writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); - - /* Enable interrupt, reset on match and stop on match (MCR). */ - writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R | - LPC32XX_TIMER_MCR_MR0S, ddata->base + LPC32XX_TIMER_MCR); - return 0; -} - -static int lpc32xx_clkevt_periodic(struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* Enable interrupt and reset on match. */ - writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R, - ddata->base + LPC32XX_TIMER_MCR); - - /* - * Place timer in reset and program the delta in the match - * channel 0 (MR0). - */ - writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); - writel_relaxed(ddata->ticks_per_jiffy, ddata->base + LPC32XX_TIMER_MR0); - writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); - - return 0; -} - -static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id) -{ - struct lpc32xx_clock_event_ddata *ddata = dev_id; - - /* Clear match on channel 0 */ - writel_relaxed(LPC32XX_TIMER_IR_MR0INT, ddata->base + LPC32XX_TIMER_IR); - - ddata->evtdev.event_handler(&ddata->evtdev); - - return IRQ_HANDLED; -} - -static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = { - .evtdev = { - .name = "lpc3220 clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC, - .rating = 300, - .set_next_event = lpc32xx_clkevt_next_event, - .set_state_shutdown = lpc32xx_clkevt_shutdown, - .set_state_oneshot = lpc32xx_clkevt_oneshot, - .set_state_periodic = lpc32xx_clkevt_periodic, - }, -}; - -static int __init lpc32xx_clocksource_init(struct device_node *np) -{ - void __iomem *base; - unsigned long rate; - struct clk *clk; - int ret; - - clk = of_clk_get_by_name(np, "timerclk"); - if (IS_ERR(clk)) { - pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("clock enable failed (%d)\n", ret); - goto err_clk_enable; - } - - base = of_iomap(np, 0); - if (!base) { - pr_err("unable to map registers\n"); - ret = -EADDRNOTAVAIL; - goto err_iomap; - } - - /* - * Disable and reset timer then set it to free running timer - * mode (CTCR) with no prescaler (PR) or match operations (MCR). - * After setup the timer is released from reset and enabled. - */ - writel_relaxed(LPC32XX_TIMER_TCR_CRST, base + LPC32XX_TIMER_TCR); - writel_relaxed(0, base + LPC32XX_TIMER_PR); - writel_relaxed(0, base + LPC32XX_TIMER_MCR); - writel_relaxed(0, base + LPC32XX_TIMER_CTCR); - writel_relaxed(LPC32XX_TIMER_TCR_CEN, base + LPC32XX_TIMER_TCR); - - rate = clk_get_rate(clk); - ret = clocksource_mmio_init(base + LPC32XX_TIMER_TC, "lpc3220 timer", - rate, 300, 32, clocksource_mmio_readl_up); - if (ret) { - pr_err("failed to init clocksource (%d)\n", ret); - goto err_clocksource_init; - } - - clocksource_timer_counter = base + LPC32XX_TIMER_TC; - lpc32xx_delay_timer.freq = rate; - register_current_timer_delay(&lpc32xx_delay_timer); - sched_clock_register(lpc32xx_read_sched_clock, 32, rate); - - return 0; - -err_clocksource_init: - iounmap(base); -err_iomap: - clk_disable_unprepare(clk); -err_clk_enable: - clk_put(clk); - return ret; -} - -static int __init lpc32xx_clockevent_init(struct device_node *np) -{ - void __iomem *base; - unsigned long rate; - struct clk *clk; - int ret, irq; - - clk = of_clk_get_by_name(np, "timerclk"); - if (IS_ERR(clk)) { - pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("clock enable failed (%d)\n", ret); - goto err_clk_enable; - } - - base = of_iomap(np, 0); - if (!base) { - pr_err("unable to map registers\n"); - ret = -EADDRNOTAVAIL; - goto err_iomap; - } - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - pr_err("get irq failed\n"); - ret = -ENOENT; - goto err_irq; - } - - /* - * Disable timer and clear any pending interrupt (IR) on match - * channel 0 (MR0). Clear the prescaler as it's not used. - */ - writel_relaxed(0, base + LPC32XX_TIMER_TCR); - writel_relaxed(0, base + LPC32XX_TIMER_PR); - writel_relaxed(0, base + LPC32XX_TIMER_CTCR); - writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR); - - rate = clk_get_rate(clk); - lpc32xx_clk_event_ddata.base = base; - lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); - clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev, - rate, 1, -1); - - ret = request_irq(irq, lpc32xx_clock_event_handler, - IRQF_TIMER | IRQF_IRQPOLL, "lpc3220 clockevent", - &lpc32xx_clk_event_ddata); - if (ret) { - pr_err("request irq failed\n"); - goto err_irq; - } - - return 0; - -err_irq: - iounmap(base); -err_iomap: - clk_disable_unprepare(clk); -err_clk_enable: - clk_put(clk); - return ret; -} - -/* - * This function asserts that we have exactly one clocksource and one - * clock_event_device in the end. - */ -static int __init lpc32xx_timer_init(struct device_node *np) -{ - static int has_clocksource, has_clockevent; - int ret = 0; - - if (!has_clocksource) { - ret = lpc32xx_clocksource_init(np); - if (!ret) { - has_clocksource = 1; - return 0; - } - } - - if (!has_clockevent) { - ret = lpc32xx_clockevent_init(np); - if (!ret) { - has_clockevent = 1; - return 0; - } - } - - return ret; -} -TIMER_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init); diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c deleted file mode 100644 index 7d487107e3cd..000000000000 --- a/drivers/clocksource/time-orion.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Marvell Orion SoC timer handling. - * - * Sebastian Hesselbarth - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * Timer 0 is used as free-running clocksource, while timer 1 is - * used as clock_event_device. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TIMER_CTRL 0x00 -#define TIMER0_EN BIT(0) -#define TIMER0_RELOAD_EN BIT(1) -#define TIMER1_EN BIT(2) -#define TIMER1_RELOAD_EN BIT(3) -#define TIMER0_RELOAD 0x10 -#define TIMER0_VAL 0x14 -#define TIMER1_RELOAD 0x18 -#define TIMER1_VAL 0x1c - -#define ORION_ONESHOT_MIN 1 -#define ORION_ONESHOT_MAX 0xfffffffe - -static void __iomem *timer_base; - -static unsigned long notrace orion_read_timer(void) -{ - return ~readl(timer_base + TIMER0_VAL); -} - -static struct delay_timer orion_delay_timer = { - .read_current_timer = orion_read_timer, -}; - -static void orion_delay_timer_init(unsigned long rate) -{ - orion_delay_timer.freq = rate; - register_current_timer_delay(&orion_delay_timer); -} - -/* - * Free-running clocksource handling. - */ -static u64 notrace orion_read_sched_clock(void) -{ - return ~readl(timer_base + TIMER0_VAL); -} - -/* - * Clockevent handling. - */ -static u32 ticks_per_jiffy; - -static int orion_clkevt_next_event(unsigned long delta, - struct clock_event_device *dev) -{ - /* setup and enable one-shot timer */ - writel(delta, timer_base + TIMER1_VAL); - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_EN); - - return 0; -} - -static int orion_clkevt_shutdown(struct clock_event_device *dev) -{ - /* disable timer */ - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER1_RELOAD_EN | TIMER1_EN, 0); - return 0; -} - -static int orion_clkevt_set_periodic(struct clock_event_device *dev) -{ - /* setup and enable periodic timer at 1/HZ intervals */ - writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); - writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER1_RELOAD_EN | TIMER1_EN, - TIMER1_RELOAD_EN | TIMER1_EN); - return 0; -} - -static struct clock_event_device orion_clkevt = { - .name = "orion_event", - .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC, - .shift = 32, - .rating = 300, - .set_next_event = orion_clkevt_next_event, - .set_state_shutdown = orion_clkevt_shutdown, - .set_state_periodic = orion_clkevt_set_periodic, - .set_state_oneshot = orion_clkevt_shutdown, - .tick_resume = orion_clkevt_shutdown, -}; - -static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) -{ - orion_clkevt.event_handler(&orion_clkevt); - return IRQ_HANDLED; -} - -static struct irqaction orion_clkevt_irq = { - .name = "orion_event", - .flags = IRQF_TIMER, - .handler = orion_clkevt_irq_handler, -}; - -static int __init orion_timer_init(struct device_node *np) -{ - unsigned long rate; - struct clk *clk; - int irq, ret; - - /* timer registers are shared with watchdog timer */ - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("%pOFn: unable to map resource\n", np); - return -ENXIO; - } - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - pr_err("%pOFn: unable to get clk\n", np); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("Failed to prepare clock\n"); - return ret; - } - - /* we are only interested in timer1 irq */ - irq = irq_of_parse_and_map(np, 1); - if (irq <= 0) { - pr_err("%pOFn: unable to parse timer1 irq\n", np); - return -EINVAL; - } - - rate = clk_get_rate(clk); - - /* setup timer0 as free-running clocksource */ - writel(~0, timer_base + TIMER0_VAL); - writel(~0, timer_base + TIMER0_RELOAD); - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER0_RELOAD_EN | TIMER0_EN, - TIMER0_RELOAD_EN | TIMER0_EN); - - ret = clocksource_mmio_init(timer_base + TIMER0_VAL, - "orion_clocksource", rate, 300, 32, - clocksource_mmio_readl_down); - if (ret) { - pr_err("Failed to initialize mmio timer\n"); - return ret; - } - - sched_clock_register(orion_read_sched_clock, 32, rate); - - /* setup timer1 as clockevent timer */ - ret = setup_irq(irq, &orion_clkevt_irq); - if (ret) { - pr_err("%pOFn: unable to setup irq\n", np); - return ret; - } - - ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ; - orion_clkevt.cpumask = cpumask_of(0); - orion_clkevt.irq = irq; - clockevents_config_and_register(&orion_clkevt, rate, - ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); - - - orion_delay_timer_init(rate); - - return 0; -} -TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c deleted file mode 100644 index a2dd85d0c1d7..000000000000 --- a/drivers/clocksource/time-pistachio.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Pistachio clocksource based on general-purpose timers - * - * Copyright (C) 2015 Imagination Technologies - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Top level reg */ -#define CR_TIMER_CTRL_CFG 0x00 -#define TIMER_ME_GLOBAL BIT(0) -#define CR_TIMER_REV 0x10 - -/* Timer specific registers */ -#define TIMER_CFG 0x20 -#define TIMER_ME_LOCAL BIT(0) -#define TIMER_RELOAD_VALUE 0x24 -#define TIMER_CURRENT_VALUE 0x28 -#define TIMER_CURRENT_OVERFLOW_VALUE 0x2C -#define TIMER_IRQ_STATUS 0x30 -#define TIMER_IRQ_CLEAR 0x34 -#define TIMER_IRQ_MASK 0x38 - -#define PERIP_TIMER_CONTROL 0x90 - -/* Timer specific configuration Values */ -#define RELOAD_VALUE 0xffffffff - -struct pistachio_clocksource { - void __iomem *base; - raw_spinlock_t lock; - struct clocksource cs; -}; - -static struct pistachio_clocksource pcs_gpt; - -#define to_pistachio_clocksource(cs) \ - container_of(cs, struct pistachio_clocksource, cs) - -static inline u32 gpt_readl(void __iomem *base, u32 offset, u32 gpt_id) -{ - return readl(base + 0x20 * gpt_id + offset); -} - -static inline void gpt_writel(void __iomem *base, u32 value, u32 offset, - u32 gpt_id) -{ - writel(value, base + 0x20 * gpt_id + offset); -} - -static u64 notrace -pistachio_clocksource_read_cycles(struct clocksource *cs) -{ - struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); - u32 counter, overflw; - unsigned long flags; - - /* - * The counter value is only refreshed after the overflow value is read. - * And they must be read in strict order, hence raw spin lock added. - */ - - raw_spin_lock_irqsave(&pcs->lock, flags); - overflw = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0); - counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0); - raw_spin_unlock_irqrestore(&pcs->lock, flags); - - return (u64)~counter; -} - -static u64 notrace pistachio_read_sched_clock(void) -{ - return pistachio_clocksource_read_cycles(&pcs_gpt.cs); -} - -static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx, - int enable) -{ - struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); - u32 val; - - val = gpt_readl(pcs->base, TIMER_CFG, timeridx); - if (enable) - val |= TIMER_ME_LOCAL; - else - val &= ~TIMER_ME_LOCAL; - - gpt_writel(pcs->base, val, TIMER_CFG, timeridx); -} - -static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx) -{ - struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); - - /* Disable GPT local before loading reload value */ - pistachio_clksrc_set_mode(cs, timeridx, false); - gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx); - pistachio_clksrc_set_mode(cs, timeridx, true); -} - -static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx) -{ - /* Disable GPT local */ - pistachio_clksrc_set_mode(cs, timeridx, false); -} - -static int pistachio_clocksource_enable(struct clocksource *cs) -{ - pistachio_clksrc_enable(cs, 0); - return 0; -} - -static void pistachio_clocksource_disable(struct clocksource *cs) -{ - pistachio_clksrc_disable(cs, 0); -} - -/* Desirable clock source for pistachio platform */ -static struct pistachio_clocksource pcs_gpt = { - .cs = { - .name = "gptimer", - .rating = 300, - .enable = pistachio_clocksource_enable, - .disable = pistachio_clocksource_disable, - .read = pistachio_clocksource_read_cycles, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS | - CLOCK_SOURCE_SUSPEND_NONSTOP, - }, -}; - -static int __init pistachio_clksrc_of_init(struct device_node *node) -{ - struct clk *sys_clk, *fast_clk; - struct regmap *periph_regs; - unsigned long rate; - int ret; - - pcs_gpt.base = of_iomap(node, 0); - if (!pcs_gpt.base) { - pr_err("cannot iomap\n"); - return -ENXIO; - } - - periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph"); - if (IS_ERR(periph_regs)) { - pr_err("cannot get peripheral regmap (%ld)\n", - PTR_ERR(periph_regs)); - return PTR_ERR(periph_regs); - } - - /* Switch to using the fast counter clock */ - ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL, - 0xf, 0x0); - if (ret) - return ret; - - sys_clk = of_clk_get_by_name(node, "sys"); - if (IS_ERR(sys_clk)) { - pr_err("clock get failed (%ld)\n", PTR_ERR(sys_clk)); - return PTR_ERR(sys_clk); - } - - fast_clk = of_clk_get_by_name(node, "fast"); - if (IS_ERR(fast_clk)) { - pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk)); - return PTR_ERR(fast_clk); - } - - ret = clk_prepare_enable(sys_clk); - if (ret < 0) { - pr_err("failed to enable clock (%d)\n", ret); - return ret; - } - - ret = clk_prepare_enable(fast_clk); - if (ret < 0) { - pr_err("failed to enable clock (%d)\n", ret); - clk_disable_unprepare(sys_clk); - return ret; - } - - rate = clk_get_rate(fast_clk); - - /* Disable irq's for clocksource usage */ - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 0); - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 1); - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 2); - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 3); - - /* Enable timer block */ - writel(TIMER_ME_GLOBAL, pcs_gpt.base); - - raw_spin_lock_init(&pcs_gpt.lock); - sched_clock_register(pistachio_read_sched_clock, 32, rate); - return clocksource_register_hz(&pcs_gpt.cs, rate); -} -TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer", - pistachio_clksrc_of_init); diff --git a/drivers/clocksource/timer-armada-370-xp.c b/drivers/clocksource/timer-armada-370-xp.c new file mode 100644 index 000000000000..edf1a46269f1 --- /dev/null +++ b/drivers/clocksource/timer-armada-370-xp.c @@ -0,0 +1,416 @@ +/* + * Marvell Armada 370/XP SoC timer handling. + * + * Copyright (C) 2012 Marvell + * + * Lior Amsalem + * Gregory CLEMENT + * Thomas Petazzoni + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * Timer 0 is used as free-running clocksource, while timer 1 is + * used as clock_event_device. + * + * --- + * Clocksource driver for Armada 370 and Armada XP SoC. + * This driver implements one compatible string for each SoC, given + * each has its own characteristics: + * + * * Armada 370 has no 25 MHz fixed timer. + * + * * Armada XP cannot work properly without such 25 MHz fixed timer as + * doing otherwise leads to using a clocksource whose frequency varies + * when doing cpufreq frequency changes. + * + * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Timer block registers. + */ +#define TIMER_CTRL_OFF 0x0000 +#define TIMER0_EN BIT(0) +#define TIMER0_RELOAD_EN BIT(1) +#define TIMER0_25MHZ BIT(11) +#define TIMER0_DIV(div) ((div) << 19) +#define TIMER1_EN BIT(2) +#define TIMER1_RELOAD_EN BIT(3) +#define TIMER1_25MHZ BIT(12) +#define TIMER1_DIV(div) ((div) << 22) +#define TIMER_EVENTS_STATUS 0x0004 +#define TIMER0_CLR_MASK (~0x1) +#define TIMER1_CLR_MASK (~0x100) +#define TIMER0_RELOAD_OFF 0x0010 +#define TIMER0_VAL_OFF 0x0014 +#define TIMER1_RELOAD_OFF 0x0018 +#define TIMER1_VAL_OFF 0x001c + +#define LCL_TIMER_EVENTS_STATUS 0x0028 +/* Global timers are connected to the coherency fabric clock, and the + below divider reduces their incrementing frequency. */ +#define TIMER_DIVIDER_SHIFT 5 +#define TIMER_DIVIDER (1 << TIMER_DIVIDER_SHIFT) + +/* + * SoC-specific data. + */ +static void __iomem *timer_base, *local_base; +static unsigned int timer_clk; +static bool timer25Mhz = true; +static u32 enable_mask; + +/* + * Number of timer ticks per jiffy. + */ +static u32 ticks_per_jiffy; + +static struct clock_event_device __percpu *armada_370_xp_evt; + +static void local_timer_ctrl_clrset(u32 clr, u32 set) +{ + writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set, + local_base + TIMER_CTRL_OFF); +} + +static u64 notrace armada_370_xp_read_sched_clock(void) +{ + return ~readl(timer_base + TIMER0_VAL_OFF); +} + +/* + * Clockevent handling. + */ +static int +armada_370_xp_clkevt_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + /* + * Clear clockevent timer interrupt. + */ + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + + /* + * Setup new clockevent timer value. + */ + writel(delta, local_base + TIMER0_VAL_OFF); + + /* + * Enable the timer. + */ + local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); + return 0; +} + +static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt) +{ + /* + * Disable timer. + */ + local_timer_ctrl_clrset(TIMER0_EN, 0); + + /* + * ACK pending timer interrupt. + */ + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + return 0; +} + +static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt) +{ + /* + * Setup timer to fire at 1/HZ intervals. + */ + writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); + writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); + + /* + * Enable timer. + */ + local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); + return 0; +} + +static int armada_370_xp_clkevt_irq; + +static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) +{ + /* + * ACK timer interrupt and call event handler. + */ + struct clock_event_device *evt = dev_id; + + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +/* + * Setup the local clock events for a CPU. + */ +static int armada_370_xp_timer_starting_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); + u32 clr = 0, set = 0; + + if (timer25Mhz) + set = TIMER0_25MHZ; + else + clr = TIMER0_25MHZ; + local_timer_ctrl_clrset(clr, set); + + evt->name = "armada_370_xp_per_cpu_tick", + evt->features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC; + evt->shift = 32, + evt->rating = 300, + evt->set_next_event = armada_370_xp_clkevt_next_event, + evt->set_state_shutdown = armada_370_xp_clkevt_shutdown; + evt->set_state_periodic = armada_370_xp_clkevt_set_periodic; + evt->set_state_oneshot = armada_370_xp_clkevt_shutdown; + evt->tick_resume = armada_370_xp_clkevt_shutdown; + evt->irq = armada_370_xp_clkevt_irq; + evt->cpumask = cpumask_of(cpu); + + clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe); + enable_percpu_irq(evt->irq, 0); + + return 0; +} + +static int armada_370_xp_timer_dying_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); + + evt->set_state_shutdown(evt); + disable_percpu_irq(evt->irq); + return 0; +} + +static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; + +static int armada_370_xp_timer_suspend(void) +{ + timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF); + timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF); + return 0; +} + +static void armada_370_xp_timer_resume(void) +{ + writel(0xffffffff, timer_base + TIMER0_VAL_OFF); + writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); + writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF); + writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF); +} + +static struct syscore_ops armada_370_xp_timer_syscore_ops = { + .suspend = armada_370_xp_timer_suspend, + .resume = armada_370_xp_timer_resume, +}; + +static unsigned long armada_370_delay_timer_read(void) +{ + return ~readl(timer_base + TIMER0_VAL_OFF); +} + +static struct delay_timer armada_370_delay_timer = { + .read_current_timer = armada_370_delay_timer_read, +}; + +static int __init armada_370_xp_timer_common_init(struct device_node *np) +{ + u32 clr = 0, set = 0; + int res; + + timer_base = of_iomap(np, 0); + if (!timer_base) { + pr_err("Failed to iomap\n"); + return -ENXIO; + } + + local_base = of_iomap(np, 1); + if (!local_base) { + pr_err("Failed to iomap\n"); + return -ENXIO; + } + + if (timer25Mhz) { + set = TIMER0_25MHZ; + enable_mask = TIMER0_EN; + } else { + clr = TIMER0_25MHZ; + enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); + } + atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set); + local_timer_ctrl_clrset(clr, set); + + /* + * We use timer 0 as clocksource, and private(local) timer 0 + * for clockevents + */ + armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4); + + ticks_per_jiffy = (timer_clk + HZ / 2) / HZ; + + /* + * Setup free-running clocksource timer (interrupts + * disabled). + */ + writel(0xffffffff, timer_base + TIMER0_VAL_OFF); + writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); + + atomic_io_modify(timer_base + TIMER_CTRL_OFF, + TIMER0_RELOAD_EN | enable_mask, + TIMER0_RELOAD_EN | enable_mask); + + armada_370_delay_timer.freq = timer_clk; + register_current_timer_delay(&armada_370_delay_timer); + + /* + * Set scale and timer for sched_clock. + */ + sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk); + + res = clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, + "armada_370_xp_clocksource", + timer_clk, 300, 32, clocksource_mmio_readl_down); + if (res) { + pr_err("Failed to initialize clocksource mmio\n"); + return res; + } + + armada_370_xp_evt = alloc_percpu(struct clock_event_device); + if (!armada_370_xp_evt) + return -ENOMEM; + + /* + * Setup clockevent timer (interrupt-driven). + */ + res = request_percpu_irq(armada_370_xp_clkevt_irq, + armada_370_xp_timer_interrupt, + "armada_370_xp_per_cpu_tick", + armada_370_xp_evt); + /* Immediately configure the timer on the boot CPU */ + if (res) { + pr_err("Failed to request percpu irq\n"); + return res; + } + + res = cpuhp_setup_state(CPUHP_AP_ARMADA_TIMER_STARTING, + "clockevents/armada:starting", + armada_370_xp_timer_starting_cpu, + armada_370_xp_timer_dying_cpu); + if (res) { + pr_err("Failed to setup hotplug state and timer\n"); + return res; + } + + register_syscore_ops(&armada_370_xp_timer_syscore_ops); + + return 0; +} + +static int __init armada_xp_timer_init(struct device_node *np) +{ + struct clk *clk = of_clk_get_by_name(np, "fixed"); + int ret; + + if (IS_ERR(clk)) { + pr_err("Failed to get clock\n"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) + return ret; + + timer_clk = clk_get_rate(clk); + + return armada_370_xp_timer_common_init(np); +} +TIMER_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", + armada_xp_timer_init); + +static int __init armada_375_timer_init(struct device_node *np) +{ + struct clk *clk; + int ret; + + clk = of_clk_get_by_name(np, "fixed"); + if (!IS_ERR(clk)) { + ret = clk_prepare_enable(clk); + if (ret) + return ret; + timer_clk = clk_get_rate(clk); + } else { + + /* + * This fallback is required in order to retain proper + * devicetree backwards compatibility. + */ + clk = of_clk_get(np, 0); + + /* Must have at least a clock */ + if (IS_ERR(clk)) { + pr_err("Failed to get clock\n"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) + return ret; + + timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; + timer25Mhz = false; + } + + return armada_370_xp_timer_common_init(np); +} +TIMER_OF_DECLARE(armada_375, "marvell,armada-375-timer", + armada_375_timer_init); + +static int __init armada_370_timer_init(struct device_node *np) +{ + struct clk *clk; + int ret; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("Failed to get clock\n"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) + return ret; + + timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; + timer25Mhz = false; + + return armada_370_xp_timer_common_init(np); +} +TIMER_OF_DECLARE(armada_370, "marvell,armada-370-timer", + armada_370_timer_init); diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c new file mode 100644 index 000000000000..b33402980b6f --- /dev/null +++ b/drivers/clocksource/timer-cadence-ttc.c @@ -0,0 +1,543 @@ +/* + * This file contains driver for the Cadence Triple Timer Counter Rev 06 + * + * Copyright (C) 2011-2013 Xilinx + * + * based on arch/mips/kernel/time.c timer driver + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This driver configures the 2 16/32-bit count-up timers as follows: + * + * T1: Timer 1, clocksource for generic timekeeping + * T2: Timer 2, clockevent source for hrtimers + * T3: Timer 3, + * + * The input frequency to the timer module for emulation is 2.5MHz which is + * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32, + * the timers are clocked at 78.125KHz (12.8 us resolution). + + * The input frequency to the timer module in silicon is configurable and + * obtained from device tree. The pre-scaler of 32 is used. + */ + +/* + * Timer Register Offset Definitions of Timer 1, Increment base address by 4 + * and use same offsets for Timer 2 + */ +#define TTC_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ +#define TTC_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ +#define TTC_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ +#define TTC_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ +#define TTC_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ +#define TTC_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ + +#define TTC_CNT_CNTRL_DISABLE_MASK 0x1 + +#define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ +#define TTC_CLK_CNTRL_PSV_MASK 0x1e +#define TTC_CLK_CNTRL_PSV_SHIFT 1 + +/* + * Setup the timers to use pre-scaling, using a fixed value for now that will + * work across most input frequency, but it may need to be more dynamic + */ +#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ +#define PRESCALE 2048 /* The exponent must match this */ +#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) +#define CLK_CNTRL_PRESCALE_EN 1 +#define CNT_CNTRL_RESET (1 << 4) + +#define MAX_F_ERR 50 + +/** + * struct ttc_timer - This definition defines local timer structure + * + * @base_addr: Base address of timer + * @freq: Timer input clock frequency + * @clk: Associated clock source + * @clk_rate_change_nb Notifier block for clock rate changes + */ +struct ttc_timer { + void __iomem *base_addr; + unsigned long freq; + struct clk *clk; + struct notifier_block clk_rate_change_nb; +}; + +#define to_ttc_timer(x) \ + container_of(x, struct ttc_timer, clk_rate_change_nb) + +struct ttc_timer_clocksource { + u32 scale_clk_ctrl_reg_old; + u32 scale_clk_ctrl_reg_new; + struct ttc_timer ttc; + struct clocksource cs; +}; + +#define to_ttc_timer_clksrc(x) \ + container_of(x, struct ttc_timer_clocksource, cs) + +struct ttc_timer_clockevent { + struct ttc_timer ttc; + struct clock_event_device ce; +}; + +#define to_ttc_timer_clkevent(x) \ + container_of(x, struct ttc_timer_clockevent, ce) + +static void __iomem *ttc_sched_clock_val_reg; + +/** + * ttc_set_interval - Set the timer interval value + * + * @timer: Pointer to the timer instance + * @cycles: Timer interval ticks + **/ +static void ttc_set_interval(struct ttc_timer *timer, + unsigned long cycles) +{ + u32 ctrl_reg; + + /* Disable the counter, set the counter value and re-enable counter */ + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); + ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + + writel_relaxed(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); + + /* + * Reset the counter (0x10) so that it starts from 0, one-shot + * mode makes this needed for timing to be right. + */ + ctrl_reg |= CNT_CNTRL_RESET; + ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); +} + +/** + * ttc_clock_event_interrupt - Clock event timer interrupt handler + * + * @irq: IRQ number of the Timer + * @dev_id: void pointer to the ttc_timer instance + * + * returns: Always IRQ_HANDLED - success + **/ +static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id) +{ + struct ttc_timer_clockevent *ttce = dev_id; + struct ttc_timer *timer = &ttce->ttc; + + /* Acknowledge the interrupt and call event handler */ + readl_relaxed(timer->base_addr + TTC_ISR_OFFSET); + + ttce->ce.event_handler(&ttce->ce); + + return IRQ_HANDLED; +} + +/** + * __ttc_clocksource_read - Reads the timer counter register + * + * returns: Current timer counter register value + **/ +static u64 __ttc_clocksource_read(struct clocksource *cs) +{ + struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; + + return (u64)readl_relaxed(timer->base_addr + + TTC_COUNT_VAL_OFFSET); +} + +static u64 notrace ttc_sched_clock_read(void) +{ + return readl_relaxed(ttc_sched_clock_val_reg); +} + +/** + * ttc_set_next_event - Sets the time interval for next event + * + * @cycles: Timer interval ticks + * @evt: Address of clock event instance + * + * returns: Always 0 - success + **/ +static int ttc_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + + ttc_set_interval(timer, cycles); + return 0; +} + +/** + * ttc_set_{shutdown|oneshot|periodic} - Sets the state of timer + * + * @evt: Address of clock event instance + **/ +static int ttc_shutdown(struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + u32 ctrl_reg; + + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); + ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + return 0; +} + +static int ttc_set_periodic(struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + + ttc_set_interval(timer, + DIV_ROUND_CLOSEST(ttce->ttc.freq, PRESCALE * HZ)); + return 0; +} + +static int ttc_resume(struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + u32 ctrl_reg; + + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); + ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + return 0; +} + +static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct clk_notifier_data *ndata = data; + struct ttc_timer *ttc = to_ttc_timer(nb); + struct ttc_timer_clocksource *ttccs = container_of(ttc, + struct ttc_timer_clocksource, ttc); + + switch (event) { + case PRE_RATE_CHANGE: + { + u32 psv; + unsigned long factor, rate_low, rate_high; + + if (ndata->new_rate > ndata->old_rate) { + factor = DIV_ROUND_CLOSEST(ndata->new_rate, + ndata->old_rate); + rate_low = ndata->old_rate; + rate_high = ndata->new_rate; + } else { + factor = DIV_ROUND_CLOSEST(ndata->old_rate, + ndata->new_rate); + rate_low = ndata->new_rate; + rate_high = ndata->old_rate; + } + + if (!is_power_of_2(factor)) + return NOTIFY_BAD; + + if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR) + return NOTIFY_BAD; + + factor = __ilog2_u32(factor); + + /* + * store timer clock ctrl register so we can restore it in case + * of an abort. + */ + ttccs->scale_clk_ctrl_reg_old = + readl_relaxed(ttccs->ttc.base_addr + + TTC_CLK_CNTRL_OFFSET); + + psv = (ttccs->scale_clk_ctrl_reg_old & + TTC_CLK_CNTRL_PSV_MASK) >> + TTC_CLK_CNTRL_PSV_SHIFT; + if (ndata->new_rate < ndata->old_rate) + psv -= factor; + else + psv += factor; + + /* prescaler within legal range? */ + if (psv & ~(TTC_CLK_CNTRL_PSV_MASK >> TTC_CLK_CNTRL_PSV_SHIFT)) + return NOTIFY_BAD; + + ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old & + ~TTC_CLK_CNTRL_PSV_MASK; + ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT; + + + /* scale down: adjust divider in post-change notification */ + if (ndata->new_rate < ndata->old_rate) + return NOTIFY_DONE; + + /* scale up: adjust divider now - before frequency change */ + writel_relaxed(ttccs->scale_clk_ctrl_reg_new, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + break; + } + case POST_RATE_CHANGE: + /* scale up: pre-change notification did the adjustment */ + if (ndata->new_rate > ndata->old_rate) + return NOTIFY_OK; + + /* scale down: adjust divider now - after frequency change */ + writel_relaxed(ttccs->scale_clk_ctrl_reg_new, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + break; + + case ABORT_RATE_CHANGE: + /* we have to undo the adjustment in case we scale up */ + if (ndata->new_rate < ndata->old_rate) + return NOTIFY_OK; + + /* restore original register value */ + writel_relaxed(ttccs->scale_clk_ctrl_reg_old, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + /* fall through */ + default: + return NOTIFY_DONE; + } + + return NOTIFY_DONE; +} + +static int __init ttc_setup_clocksource(struct clk *clk, void __iomem *base, + u32 timer_width) +{ + struct ttc_timer_clocksource *ttccs; + int err; + + ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); + if (!ttccs) + return -ENOMEM; + + ttccs->ttc.clk = clk; + + err = clk_prepare_enable(ttccs->ttc.clk); + if (err) { + kfree(ttccs); + return err; + } + + ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk); + + ttccs->ttc.clk_rate_change_nb.notifier_call = + ttc_rate_change_clocksource_cb; + ttccs->ttc.clk_rate_change_nb.next = NULL; + + err = clk_notifier_register(ttccs->ttc.clk, + &ttccs->ttc.clk_rate_change_nb); + if (err) + pr_warn("Unable to register clock notifier.\n"); + + ttccs->ttc.base_addr = base; + ttccs->cs.name = "ttc_clocksource"; + ttccs->cs.rating = 200; + ttccs->cs.read = __ttc_clocksource_read; + ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width); + ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; + + /* + * Setup the clock source counter to be an incrementing counter + * with no interrupt and it rolls over at 0xFFFF. Pre-scale + * it by 32 also. Let it start running now. + */ + writel_relaxed(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); + writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + writel_relaxed(CNT_CNTRL_RESET, + ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); + + err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE); + if (err) { + kfree(ttccs); + return err; + } + + ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; + sched_clock_register(ttc_sched_clock_read, timer_width, + ttccs->ttc.freq / PRESCALE); + + return 0; +} + +static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct clk_notifier_data *ndata = data; + struct ttc_timer *ttc = to_ttc_timer(nb); + struct ttc_timer_clockevent *ttcce = container_of(ttc, + struct ttc_timer_clockevent, ttc); + + switch (event) { + case POST_RATE_CHANGE: + /* update cached frequency */ + ttc->freq = ndata->new_rate; + + clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE); + + /* fall through */ + case PRE_RATE_CHANGE: + case ABORT_RATE_CHANGE: + default: + return NOTIFY_DONE; + } +} + +static int __init ttc_setup_clockevent(struct clk *clk, + void __iomem *base, u32 irq) +{ + struct ttc_timer_clockevent *ttcce; + int err; + + ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); + if (!ttcce) + return -ENOMEM; + + ttcce->ttc.clk = clk; + + err = clk_prepare_enable(ttcce->ttc.clk); + if (err) { + kfree(ttcce); + return err; + } + + ttcce->ttc.clk_rate_change_nb.notifier_call = + ttc_rate_change_clockevent_cb; + ttcce->ttc.clk_rate_change_nb.next = NULL; + + err = clk_notifier_register(ttcce->ttc.clk, + &ttcce->ttc.clk_rate_change_nb); + if (err) { + pr_warn("Unable to register clock notifier.\n"); + return err; + } + + ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk); + + ttcce->ttc.base_addr = base; + ttcce->ce.name = "ttc_clockevent"; + ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + ttcce->ce.set_next_event = ttc_set_next_event; + ttcce->ce.set_state_shutdown = ttc_shutdown; + ttcce->ce.set_state_periodic = ttc_set_periodic; + ttcce->ce.set_state_oneshot = ttc_shutdown; + ttcce->ce.tick_resume = ttc_resume; + ttcce->ce.rating = 200; + ttcce->ce.irq = irq; + ttcce->ce.cpumask = cpu_possible_mask; + + /* + * Setup the clock event timer to be an interval timer which + * is prescaled by 32 using the interval interrupt. Leave it + * disabled for now. + */ + writel_relaxed(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); + writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, + ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + writel_relaxed(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); + + err = request_irq(irq, ttc_clock_event_interrupt, + IRQF_TIMER, ttcce->ce.name, ttcce); + if (err) { + kfree(ttcce); + return err; + } + + clockevents_config_and_register(&ttcce->ce, + ttcce->ttc.freq / PRESCALE, 1, 0xfffe); + + return 0; +} + +/** + * ttc_timer_init - Initialize the timer + * + * Initializes the timer hardware and register the clock source and clock event + * timers with Linux kernal timer framework + */ +static int __init ttc_timer_init(struct device_node *timer) +{ + unsigned int irq; + void __iomem *timer_baseaddr; + struct clk *clk_cs, *clk_ce; + static int initialized; + int clksel, ret; + u32 timer_width = 16; + + if (initialized) + return 0; + + initialized = 1; + + /* + * Get the 1st Triple Timer Counter (TTC) block from the device tree + * and use it. Note that the event timer uses the interrupt and it's the + * 2nd TTC hence the irq_of_parse_and_map(,1) + */ + timer_baseaddr = of_iomap(timer, 0); + if (!timer_baseaddr) { + pr_err("ERROR: invalid timer base address\n"); + return -ENXIO; + } + + irq = irq_of_parse_and_map(timer, 1); + if (irq <= 0) { + pr_err("ERROR: invalid interrupt number\n"); + return -EINVAL; + } + + of_property_read_u32(timer, "timer-width", &timer_width); + + clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); + clk_cs = of_clk_get(timer, clksel); + if (IS_ERR(clk_cs)) { + pr_err("ERROR: timer input clock not found\n"); + return PTR_ERR(clk_cs); + } + + clksel = readl_relaxed(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); + clk_ce = of_clk_get(timer, clksel); + if (IS_ERR(clk_ce)) { + pr_err("ERROR: timer input clock not found\n"); + return PTR_ERR(clk_ce); + } + + ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width); + if (ret) + return ret; + + ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); + if (ret) + return ret; + + pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq); + + return 0; +} + +TIMER_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init); diff --git a/drivers/clocksource/timer-efm32.c b/drivers/clocksource/timer-efm32.c new file mode 100644 index 000000000000..257e810ec1ad --- /dev/null +++ b/drivers/clocksource/timer-efm32.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2013 Pengutronix + * Uwe Kleine-Koenig + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMERn_CTRL 0x00 +#define TIMERn_CTRL_PRESC(val) (((val) & 0xf) << 24) +#define TIMERn_CTRL_PRESC_1024 TIMERn_CTRL_PRESC(10) +#define TIMERn_CTRL_CLKSEL(val) (((val) & 0x3) << 16) +#define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK TIMERn_CTRL_CLKSEL(0) +#define TIMERn_CTRL_OSMEN 0x00000010 +#define TIMERn_CTRL_MODE(val) (((val) & 0x3) << 0) +#define TIMERn_CTRL_MODE_UP TIMERn_CTRL_MODE(0) +#define TIMERn_CTRL_MODE_DOWN TIMERn_CTRL_MODE(1) + +#define TIMERn_CMD 0x04 +#define TIMERn_CMD_START 0x00000001 +#define TIMERn_CMD_STOP 0x00000002 + +#define TIMERn_IEN 0x0c +#define TIMERn_IF 0x10 +#define TIMERn_IFS 0x14 +#define TIMERn_IFC 0x18 +#define TIMERn_IRQ_UF 0x00000002 + +#define TIMERn_TOP 0x1c +#define TIMERn_CNT 0x24 + +struct efm32_clock_event_ddata { + struct clock_event_device evtdev; + void __iomem *base; + unsigned periodic_top; +}; + +static int efm32_clock_event_shutdown(struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + return 0; +} + +static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + writel_relaxed(TIMERn_CTRL_PRESC_1024 | + TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | + TIMERn_CTRL_OSMEN | + TIMERn_CTRL_MODE_DOWN, + ddata->base + TIMERn_CTRL); + return 0; +} + +static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); + writel_relaxed(TIMERn_CTRL_PRESC_1024 | + TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | + TIMERn_CTRL_MODE_DOWN, + ddata->base + TIMERn_CTRL); + writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); + return 0; +} + +static int efm32_clock_event_set_next_event(unsigned long evt, + struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + writel_relaxed(evt, ddata->base + TIMERn_CNT); + writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); + + return 0; +} + +static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id) +{ + struct efm32_clock_event_ddata *ddata = dev_id; + + writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC); + + ddata->evtdev.event_handler(&ddata->evtdev); + + return IRQ_HANDLED; +} + +static struct efm32_clock_event_ddata clock_event_ddata = { + .evtdev = { + .name = "efm32 clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, + .set_state_shutdown = efm32_clock_event_shutdown, + .set_state_periodic = efm32_clock_event_set_periodic, + .set_state_oneshot = efm32_clock_event_set_oneshot, + .set_next_event = efm32_clock_event_set_next_event, + .rating = 200, + }, +}; + +static struct irqaction efm32_clock_event_irq = { + .name = "efm32 clockevent", + .flags = IRQF_TIMER, + .handler = efm32_clock_event_handler, + .dev_id = &clock_event_ddata, +}; + +static int __init efm32_clocksource_init(struct device_node *np) +{ + struct clk *clk; + void __iomem *base; + unsigned long rate; + int ret; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + pr_err("failed to get clock for clocksource (%d)\n", ret); + goto err_clk_get; + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("failed to enable timer clock for clocksource (%d)\n", + ret); + goto err_clk_enable; + } + rate = clk_get_rate(clk); + + base = of_iomap(np, 0); + if (!base) { + ret = -EADDRNOTAVAIL; + pr_err("failed to map registers for clocksource\n"); + goto err_iomap; + } + + writel_relaxed(TIMERn_CTRL_PRESC_1024 | + TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | + TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL); + writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD); + + ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer", + DIV_ROUND_CLOSEST(rate, 1024), 200, 16, + clocksource_mmio_readl_up); + if (ret) { + pr_err("failed to init clocksource (%d)\n", ret); + goto err_clocksource_init; + } + + return 0; + +err_clocksource_init: + + iounmap(base); +err_iomap: + + clk_disable_unprepare(clk); +err_clk_enable: + + clk_put(clk); +err_clk_get: + + return ret; +} + +static int __init efm32_clockevent_init(struct device_node *np) +{ + struct clk *clk; + void __iomem *base; + unsigned long rate; + int irq; + int ret; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + pr_err("failed to get clock for clockevent (%d)\n", ret); + goto err_clk_get; + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("failed to enable timer clock for clockevent (%d)\n", + ret); + goto err_clk_enable; + } + rate = clk_get_rate(clk); + + base = of_iomap(np, 0); + if (!base) { + ret = -EADDRNOTAVAIL; + pr_err("failed to map registers for clockevent\n"); + goto err_iomap; + } + + irq = irq_of_parse_and_map(np, 0); + if (!irq) { + ret = -ENOENT; + pr_err("failed to get irq for clockevent\n"); + goto err_get_irq; + } + + writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN); + + clock_event_ddata.base = base; + clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); + + clockevents_config_and_register(&clock_event_ddata.evtdev, + DIV_ROUND_CLOSEST(rate, 1024), + 0xf, 0xffff); + + ret = setup_irq(irq, &efm32_clock_event_irq); + if (ret) { + pr_err("Failed setup irq\n"); + goto err_setup_irq; + } + + return 0; + +err_setup_irq: +err_get_irq: + + iounmap(base); +err_iomap: + + clk_disable_unprepare(clk); +err_clk_enable: + + clk_put(clk); +err_clk_get: + + return ret; +} + +/* + * This function asserts that we have exactly one clocksource and one + * clock_event_device in the end. + */ +static int __init efm32_timer_init(struct device_node *np) +{ + static int has_clocksource, has_clockevent; + int ret = 0; + + if (!has_clocksource) { + ret = efm32_clocksource_init(np); + if (!ret) { + has_clocksource = 1; + return 0; + } + } + + if (!has_clockevent) { + ret = efm32_clockevent_init(np); + if (!ret) { + has_clockevent = 1; + return 0; + } + } + + return ret; +} +TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); +TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); diff --git a/drivers/clocksource/timer-fsl-ftm.c b/drivers/clocksource/timer-fsl-ftm.c new file mode 100644 index 000000000000..846d18daf893 --- /dev/null +++ b/drivers/clocksource/timer-fsl-ftm.c @@ -0,0 +1,376 @@ +/* + * Freescale FlexTimer Module (FTM) timer driver. + * + * Copyright 2014 Freescale Semiconductor, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FTM_SC 0x00 +#define FTM_SC_CLK_SHIFT 3 +#define FTM_SC_CLK_MASK (0x3 << FTM_SC_CLK_SHIFT) +#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_SHIFT) +#define FTM_SC_PS_MASK 0x7 +#define FTM_SC_TOIE BIT(6) +#define FTM_SC_TOF BIT(7) + +#define FTM_CNT 0x04 +#define FTM_MOD 0x08 +#define FTM_CNTIN 0x4C + +#define FTM_PS_MAX 7 + +struct ftm_clock_device { + void __iomem *clksrc_base; + void __iomem *clkevt_base; + unsigned long periodic_cyc; + unsigned long ps; + bool big_endian; +}; + +static struct ftm_clock_device *priv; + +static inline u32 ftm_readl(void __iomem *addr) +{ + if (priv->big_endian) + return ioread32be(addr); + else + return ioread32(addr); +} + +static inline void ftm_writel(u32 val, void __iomem *addr) +{ + if (priv->big_endian) + iowrite32be(val, addr); + else + iowrite32(val, addr); +} + +static inline void ftm_counter_enable(void __iomem *base) +{ + u32 val; + + /* select and enable counter clock source */ + val = ftm_readl(base + FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + val |= priv->ps | FTM_SC_CLK(1); + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_counter_disable(void __iomem *base) +{ + u32 val; + + /* disable counter clock source */ + val = ftm_readl(base + FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_acknowledge(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val &= ~FTM_SC_TOF; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_enable(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val |= FTM_SC_TOIE; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_disable(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val &= ~FTM_SC_TOIE; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_reset_counter(void __iomem *base) +{ + /* + * The CNT register contains the FTM counter value. + * Reset clears the CNT register. Writing any value to COUNT + * updates the counter with its initial value, CNTIN. + */ + ftm_writel(0x00, base + FTM_CNT); +} + +static u64 notrace ftm_read_sched_clock(void) +{ + return ftm_readl(priv->clksrc_base + FTM_CNT); +} + +static int ftm_set_next_event(unsigned long delta, + struct clock_event_device *unused) +{ + /* + * The CNNIN and MOD are all double buffer registers, writing + * to the MOD register latches the value into a buffer. The MOD + * register is updated with the value of its write buffer with + * the following scenario: + * a, the counter source clock is diabled. + */ + ftm_counter_disable(priv->clkevt_base); + + /* Force the value of CNTIN to be loaded into the FTM counter */ + ftm_reset_counter(priv->clkevt_base); + + /* + * The counter increments until the value of MOD is reached, + * at which point the counter is reloaded with the value of CNTIN. + * The TOF (the overflow flag) bit is set when the FTM counter + * changes from MOD to CNTIN. So we should using the delta - 1. + */ + ftm_writel(delta - 1, priv->clkevt_base + FTM_MOD); + + ftm_counter_enable(priv->clkevt_base); + + ftm_irq_enable(priv->clkevt_base); + + return 0; +} + +static int ftm_set_oneshot(struct clock_event_device *evt) +{ + ftm_counter_disable(priv->clkevt_base); + return 0; +} + +static int ftm_set_periodic(struct clock_event_device *evt) +{ + ftm_set_next_event(priv->periodic_cyc, evt); + return 0; +} + +static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + ftm_irq_acknowledge(priv->clkevt_base); + + if (likely(clockevent_state_oneshot(evt))) { + ftm_irq_disable(priv->clkevt_base); + ftm_counter_disable(priv->clkevt_base); + } + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct clock_event_device ftm_clockevent = { + .name = "Freescale ftm timer", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_state_periodic = ftm_set_periodic, + .set_state_oneshot = ftm_set_oneshot, + .set_next_event = ftm_set_next_event, + .rating = 300, +}; + +static struct irqaction ftm_timer_irq = { + .name = "Freescale ftm timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = ftm_evt_interrupt, + .dev_id = &ftm_clockevent, +}; + +static int __init ftm_clockevent_init(unsigned long freq, int irq) +{ + int err; + + ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN); + ftm_writel(~0u, priv->clkevt_base + FTM_MOD); + + ftm_reset_counter(priv->clkevt_base); + + err = setup_irq(irq, &ftm_timer_irq); + if (err) { + pr_err("ftm: setup irq failed: %d\n", err); + return err; + } + + ftm_clockevent.cpumask = cpumask_of(0); + ftm_clockevent.irq = irq; + + clockevents_config_and_register(&ftm_clockevent, + freq / (1 << priv->ps), + 1, 0xffff); + + ftm_counter_enable(priv->clkevt_base); + + return 0; +} + +static int __init ftm_clocksource_init(unsigned long freq) +{ + int err; + + ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN); + ftm_writel(~0u, priv->clksrc_base + FTM_MOD); + + ftm_reset_counter(priv->clksrc_base); + + sched_clock_register(ftm_read_sched_clock, 16, freq / (1 << priv->ps)); + err = clocksource_mmio_init(priv->clksrc_base + FTM_CNT, "fsl-ftm", + freq / (1 << priv->ps), 300, 16, + clocksource_mmio_readl_up); + if (err) { + pr_err("ftm: init clock source mmio failed: %d\n", err); + return err; + } + + ftm_counter_enable(priv->clksrc_base); + + return 0; +} + +static int __init __ftm_clk_init(struct device_node *np, char *cnt_name, + char *ftm_name) +{ + struct clk *clk; + int err; + + clk = of_clk_get_by_name(np, cnt_name); + if (IS_ERR(clk)) { + pr_err("ftm: Cannot get \"%s\": %ld\n", cnt_name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + err = clk_prepare_enable(clk); + if (err) { + pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", + cnt_name, err); + return err; + } + + clk = of_clk_get_by_name(np, ftm_name); + if (IS_ERR(clk)) { + pr_err("ftm: Cannot get \"%s\": %ld\n", ftm_name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + err = clk_prepare_enable(clk); + if (err) + pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", + ftm_name, err); + + return clk_get_rate(clk); +} + +static unsigned long __init ftm_clk_init(struct device_node *np) +{ + long freq; + + freq = __ftm_clk_init(np, "ftm-evt-counter-en", "ftm-evt"); + if (freq <= 0) + return 0; + + freq = __ftm_clk_init(np, "ftm-src-counter-en", "ftm-src"); + if (freq <= 0) + return 0; + + return freq; +} + +static int __init ftm_calc_closest_round_cyc(unsigned long freq) +{ + priv->ps = 0; + + /* The counter register is only using the lower 16 bits, and + * if the 'freq' value is to big here, then the periodic_cyc + * may exceed 0xFFFF. + */ + do { + priv->periodic_cyc = DIV_ROUND_CLOSEST(freq, + HZ * (1 << priv->ps++)); + } while (priv->periodic_cyc > 0xFFFF); + + if (priv->ps > FTM_PS_MAX) { + pr_err("ftm: the prescaler is %lu > %d\n", + priv->ps, FTM_PS_MAX); + return -EINVAL; + } + + return 0; +} + +static int __init ftm_timer_init(struct device_node *np) +{ + unsigned long freq; + int ret, irq; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ret = -ENXIO; + priv->clkevt_base = of_iomap(np, 0); + if (!priv->clkevt_base) { + pr_err("ftm: unable to map event timer registers\n"); + goto err_clkevt; + } + + priv->clksrc_base = of_iomap(np, 1); + if (!priv->clksrc_base) { + pr_err("ftm: unable to map source timer registers\n"); + goto err_clksrc; + } + + ret = -EINVAL; + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) { + pr_err("ftm: unable to get IRQ from DT, %d\n", irq); + goto err; + } + + priv->big_endian = of_property_read_bool(np, "big-endian"); + + freq = ftm_clk_init(np); + if (!freq) + goto err; + + ret = ftm_calc_closest_round_cyc(freq); + if (ret) + goto err; + + ret = ftm_clocksource_init(freq); + if (ret) + goto err; + + ret = ftm_clockevent_init(freq, irq); + if (ret) + goto err; + + return 0; + +err: + iounmap(priv->clksrc_base); +err_clksrc: + iounmap(priv->clkevt_base); +err_clkevt: + kfree(priv); + return ret; +} +TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init); diff --git a/drivers/clocksource/timer-lpc32xx.c b/drivers/clocksource/timer-lpc32xx.c new file mode 100644 index 000000000000..d51a62a79ef7 --- /dev/null +++ b/drivers/clocksource/timer-lpc32xx.c @@ -0,0 +1,314 @@ +/* + * Clocksource driver for NXP LPC32xx/18xx/43xx timer + * + * Copyright (C) 2015 Joachim Eastwood + * + * Based on: + * time-efm32 Copyright (C) 2013 Pengutronix + * mach-lpc32xx/timer.c Copyright (C) 2009 - 2010 NXP Semiconductors + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LPC32XX_TIMER_IR 0x000 +#define LPC32XX_TIMER_IR_MR0INT BIT(0) +#define LPC32XX_TIMER_TCR 0x004 +#define LPC32XX_TIMER_TCR_CEN BIT(0) +#define LPC32XX_TIMER_TCR_CRST BIT(1) +#define LPC32XX_TIMER_TC 0x008 +#define LPC32XX_TIMER_PR 0x00c +#define LPC32XX_TIMER_MCR 0x014 +#define LPC32XX_TIMER_MCR_MR0I BIT(0) +#define LPC32XX_TIMER_MCR_MR0R BIT(1) +#define LPC32XX_TIMER_MCR_MR0S BIT(2) +#define LPC32XX_TIMER_MR0 0x018 +#define LPC32XX_TIMER_CTCR 0x070 + +struct lpc32xx_clock_event_ddata { + struct clock_event_device evtdev; + void __iomem *base; + u32 ticks_per_jiffy; +}; + +/* Needed for the sched clock */ +static void __iomem *clocksource_timer_counter; + +static u64 notrace lpc32xx_read_sched_clock(void) +{ + return readl(clocksource_timer_counter); +} + +static unsigned long lpc32xx_delay_timer_read(void) +{ + return readl(clocksource_timer_counter); +} + +static struct delay_timer lpc32xx_delay_timer = { + .read_current_timer = lpc32xx_delay_timer_read, +}; + +static int lpc32xx_clkevt_next_event(unsigned long delta, + struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* + * Place timer in reset and program the delta in the match + * channel 0 (MR0). When the timer counter matches the value + * in MR0 register the match will trigger an interrupt. + * After setup the timer is released from reset and enabled. + */ + writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); + writel_relaxed(delta, ddata->base + LPC32XX_TIMER_MR0); + writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); + + return 0; +} + +static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* Disable the timer */ + writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); + + return 0; +} + +static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* + * When using oneshot, we must also disable the timer + * to wait for the first call to set_next_event(). + */ + writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); + + /* Enable interrupt, reset on match and stop on match (MCR). */ + writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R | + LPC32XX_TIMER_MCR_MR0S, ddata->base + LPC32XX_TIMER_MCR); + return 0; +} + +static int lpc32xx_clkevt_periodic(struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* Enable interrupt and reset on match. */ + writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R, + ddata->base + LPC32XX_TIMER_MCR); + + /* + * Place timer in reset and program the delta in the match + * channel 0 (MR0). + */ + writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); + writel_relaxed(ddata->ticks_per_jiffy, ddata->base + LPC32XX_TIMER_MR0); + writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); + + return 0; +} + +static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id) +{ + struct lpc32xx_clock_event_ddata *ddata = dev_id; + + /* Clear match on channel 0 */ + writel_relaxed(LPC32XX_TIMER_IR_MR0INT, ddata->base + LPC32XX_TIMER_IR); + + ddata->evtdev.event_handler(&ddata->evtdev); + + return IRQ_HANDLED; +} + +static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = { + .evtdev = { + .name = "lpc3220 clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC, + .rating = 300, + .set_next_event = lpc32xx_clkevt_next_event, + .set_state_shutdown = lpc32xx_clkevt_shutdown, + .set_state_oneshot = lpc32xx_clkevt_oneshot, + .set_state_periodic = lpc32xx_clkevt_periodic, + }, +}; + +static int __init lpc32xx_clocksource_init(struct device_node *np) +{ + void __iomem *base; + unsigned long rate; + struct clk *clk; + int ret; + + clk = of_clk_get_by_name(np, "timerclk"); + if (IS_ERR(clk)) { + pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("clock enable failed (%d)\n", ret); + goto err_clk_enable; + } + + base = of_iomap(np, 0); + if (!base) { + pr_err("unable to map registers\n"); + ret = -EADDRNOTAVAIL; + goto err_iomap; + } + + /* + * Disable and reset timer then set it to free running timer + * mode (CTCR) with no prescaler (PR) or match operations (MCR). + * After setup the timer is released from reset and enabled. + */ + writel_relaxed(LPC32XX_TIMER_TCR_CRST, base + LPC32XX_TIMER_TCR); + writel_relaxed(0, base + LPC32XX_TIMER_PR); + writel_relaxed(0, base + LPC32XX_TIMER_MCR); + writel_relaxed(0, base + LPC32XX_TIMER_CTCR); + writel_relaxed(LPC32XX_TIMER_TCR_CEN, base + LPC32XX_TIMER_TCR); + + rate = clk_get_rate(clk); + ret = clocksource_mmio_init(base + LPC32XX_TIMER_TC, "lpc3220 timer", + rate, 300, 32, clocksource_mmio_readl_up); + if (ret) { + pr_err("failed to init clocksource (%d)\n", ret); + goto err_clocksource_init; + } + + clocksource_timer_counter = base + LPC32XX_TIMER_TC; + lpc32xx_delay_timer.freq = rate; + register_current_timer_delay(&lpc32xx_delay_timer); + sched_clock_register(lpc32xx_read_sched_clock, 32, rate); + + return 0; + +err_clocksource_init: + iounmap(base); +err_iomap: + clk_disable_unprepare(clk); +err_clk_enable: + clk_put(clk); + return ret; +} + +static int __init lpc32xx_clockevent_init(struct device_node *np) +{ + void __iomem *base; + unsigned long rate; + struct clk *clk; + int ret, irq; + + clk = of_clk_get_by_name(np, "timerclk"); + if (IS_ERR(clk)) { + pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("clock enable failed (%d)\n", ret); + goto err_clk_enable; + } + + base = of_iomap(np, 0); + if (!base) { + pr_err("unable to map registers\n"); + ret = -EADDRNOTAVAIL; + goto err_iomap; + } + + irq = irq_of_parse_and_map(np, 0); + if (!irq) { + pr_err("get irq failed\n"); + ret = -ENOENT; + goto err_irq; + } + + /* + * Disable timer and clear any pending interrupt (IR) on match + * channel 0 (MR0). Clear the prescaler as it's not used. + */ + writel_relaxed(0, base + LPC32XX_TIMER_TCR); + writel_relaxed(0, base + LPC32XX_TIMER_PR); + writel_relaxed(0, base + LPC32XX_TIMER_CTCR); + writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR); + + rate = clk_get_rate(clk); + lpc32xx_clk_event_ddata.base = base; + lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); + clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev, + rate, 1, -1); + + ret = request_irq(irq, lpc32xx_clock_event_handler, + IRQF_TIMER | IRQF_IRQPOLL, "lpc3220 clockevent", + &lpc32xx_clk_event_ddata); + if (ret) { + pr_err("request irq failed\n"); + goto err_irq; + } + + return 0; + +err_irq: + iounmap(base); +err_iomap: + clk_disable_unprepare(clk); +err_clk_enable: + clk_put(clk); + return ret; +} + +/* + * This function asserts that we have exactly one clocksource and one + * clock_event_device in the end. + */ +static int __init lpc32xx_timer_init(struct device_node *np) +{ + static int has_clocksource, has_clockevent; + int ret = 0; + + if (!has_clocksource) { + ret = lpc32xx_clocksource_init(np); + if (!ret) { + has_clocksource = 1; + return 0; + } + } + + if (!has_clockevent) { + ret = lpc32xx_clockevent_init(np); + if (!ret) { + has_clockevent = 1; + return 0; + } + } + + return ret; +} +TIMER_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init); diff --git a/drivers/clocksource/timer-orion.c b/drivers/clocksource/timer-orion.c new file mode 100644 index 000000000000..7d487107e3cd --- /dev/null +++ b/drivers/clocksource/timer-orion.c @@ -0,0 +1,192 @@ +/* + * Marvell Orion SoC timer handling. + * + * Sebastian Hesselbarth + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * Timer 0 is used as free-running clocksource, while timer 1 is + * used as clock_event_device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_CTRL 0x00 +#define TIMER0_EN BIT(0) +#define TIMER0_RELOAD_EN BIT(1) +#define TIMER1_EN BIT(2) +#define TIMER1_RELOAD_EN BIT(3) +#define TIMER0_RELOAD 0x10 +#define TIMER0_VAL 0x14 +#define TIMER1_RELOAD 0x18 +#define TIMER1_VAL 0x1c + +#define ORION_ONESHOT_MIN 1 +#define ORION_ONESHOT_MAX 0xfffffffe + +static void __iomem *timer_base; + +static unsigned long notrace orion_read_timer(void) +{ + return ~readl(timer_base + TIMER0_VAL); +} + +static struct delay_timer orion_delay_timer = { + .read_current_timer = orion_read_timer, +}; + +static void orion_delay_timer_init(unsigned long rate) +{ + orion_delay_timer.freq = rate; + register_current_timer_delay(&orion_delay_timer); +} + +/* + * Free-running clocksource handling. + */ +static u64 notrace orion_read_sched_clock(void) +{ + return ~readl(timer_base + TIMER0_VAL); +} + +/* + * Clockevent handling. + */ +static u32 ticks_per_jiffy; + +static int orion_clkevt_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + /* setup and enable one-shot timer */ + writel(delta, timer_base + TIMER1_VAL); + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_EN); + + return 0; +} + +static int orion_clkevt_shutdown(struct clock_event_device *dev) +{ + /* disable timer */ + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER1_RELOAD_EN | TIMER1_EN, 0); + return 0; +} + +static int orion_clkevt_set_periodic(struct clock_event_device *dev) +{ + /* setup and enable periodic timer at 1/HZ intervals */ + writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); + writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER1_RELOAD_EN | TIMER1_EN, + TIMER1_RELOAD_EN | TIMER1_EN); + return 0; +} + +static struct clock_event_device orion_clkevt = { + .name = "orion_event", + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC, + .shift = 32, + .rating = 300, + .set_next_event = orion_clkevt_next_event, + .set_state_shutdown = orion_clkevt_shutdown, + .set_state_periodic = orion_clkevt_set_periodic, + .set_state_oneshot = orion_clkevt_shutdown, + .tick_resume = orion_clkevt_shutdown, +}; + +static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) +{ + orion_clkevt.event_handler(&orion_clkevt); + return IRQ_HANDLED; +} + +static struct irqaction orion_clkevt_irq = { + .name = "orion_event", + .flags = IRQF_TIMER, + .handler = orion_clkevt_irq_handler, +}; + +static int __init orion_timer_init(struct device_node *np) +{ + unsigned long rate; + struct clk *clk; + int irq, ret; + + /* timer registers are shared with watchdog timer */ + timer_base = of_iomap(np, 0); + if (!timer_base) { + pr_err("%pOFn: unable to map resource\n", np); + return -ENXIO; + } + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("%pOFn: unable to get clk\n", np); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("Failed to prepare clock\n"); + return ret; + } + + /* we are only interested in timer1 irq */ + irq = irq_of_parse_and_map(np, 1); + if (irq <= 0) { + pr_err("%pOFn: unable to parse timer1 irq\n", np); + return -EINVAL; + } + + rate = clk_get_rate(clk); + + /* setup timer0 as free-running clocksource */ + writel(~0, timer_base + TIMER0_VAL); + writel(~0, timer_base + TIMER0_RELOAD); + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER0_RELOAD_EN | TIMER0_EN, + TIMER0_RELOAD_EN | TIMER0_EN); + + ret = clocksource_mmio_init(timer_base + TIMER0_VAL, + "orion_clocksource", rate, 300, 32, + clocksource_mmio_readl_down); + if (ret) { + pr_err("Failed to initialize mmio timer\n"); + return ret; + } + + sched_clock_register(orion_read_sched_clock, 32, rate); + + /* setup timer1 as clockevent timer */ + ret = setup_irq(irq, &orion_clkevt_irq); + if (ret) { + pr_err("%pOFn: unable to setup irq\n", np); + return ret; + } + + ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ; + orion_clkevt.cpumask = cpumask_of(0); + orion_clkevt.irq = irq; + clockevents_config_and_register(&orion_clkevt, rate, + ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); + + + orion_delay_timer_init(rate); + + return 0; +} +TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); diff --git a/drivers/clocksource/timer-owl.c b/drivers/clocksource/timer-owl.c new file mode 100644 index 000000000000..ea00a5e8f95d --- /dev/null +++ b/drivers/clocksource/timer-owl.c @@ -0,0 +1,173 @@ +/* + * Actions Semi Owl timer + * + * Copyright 2012 Actions Semi Inc. + * Author: Actions Semi, Inc. + * + * Copyright (c) 2017 SUSE Linux GmbH + * Author: Andreas Färber + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OWL_Tx_CTL 0x0 +#define OWL_Tx_CMP 0x4 +#define OWL_Tx_VAL 0x8 + +#define OWL_Tx_CTL_PD BIT(0) +#define OWL_Tx_CTL_INTEN BIT(1) +#define OWL_Tx_CTL_EN BIT(2) + +static void __iomem *owl_timer_base; +static void __iomem *owl_clksrc_base; +static void __iomem *owl_clkevt_base; + +static inline void owl_timer_reset(void __iomem *base) +{ + writel(0, base + OWL_Tx_CTL); + writel(0, base + OWL_Tx_VAL); + writel(0, base + OWL_Tx_CMP); +} + +static inline void owl_timer_set_enabled(void __iomem *base, bool enabled) +{ + u32 ctl = readl(base + OWL_Tx_CTL); + + /* PD bit is cleared when set */ + ctl &= ~OWL_Tx_CTL_PD; + + if (enabled) + ctl |= OWL_Tx_CTL_EN; + else + ctl &= ~OWL_Tx_CTL_EN; + + writel(ctl, base + OWL_Tx_CTL); +} + +static u64 notrace owl_timer_sched_read(void) +{ + return (u64)readl(owl_clksrc_base + OWL_Tx_VAL); +} + +static int owl_timer_set_state_shutdown(struct clock_event_device *evt) +{ + owl_timer_set_enabled(owl_clkevt_base, false); + + return 0; +} + +static int owl_timer_set_state_oneshot(struct clock_event_device *evt) +{ + owl_timer_reset(owl_clkevt_base); + + return 0; +} + +static int owl_timer_tick_resume(struct clock_event_device *evt) +{ + return 0; +} + +static int owl_timer_set_next_event(unsigned long evt, + struct clock_event_device *ev) +{ + void __iomem *base = owl_clkevt_base; + + owl_timer_set_enabled(base, false); + writel(OWL_Tx_CTL_INTEN, base + OWL_Tx_CTL); + writel(0, base + OWL_Tx_VAL); + writel(evt, base + OWL_Tx_CMP); + owl_timer_set_enabled(base, true); + + return 0; +} + +static struct clock_event_device owl_clockevent = { + .name = "owl_tick", + .rating = 200, + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_DYNIRQ, + .set_state_shutdown = owl_timer_set_state_shutdown, + .set_state_oneshot = owl_timer_set_state_oneshot, + .tick_resume = owl_timer_tick_resume, + .set_next_event = owl_timer_set_next_event, +}; + +static irqreturn_t owl_timer1_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + + writel(OWL_Tx_CTL_PD, owl_clkevt_base + OWL_Tx_CTL); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static int __init owl_timer_init(struct device_node *node) +{ + struct clk *clk; + unsigned long rate; + int timer1_irq, ret; + + owl_timer_base = of_io_request_and_map(node, 0, "owl-timer"); + if (IS_ERR(owl_timer_base)) { + pr_err("Can't map timer registers\n"); + return PTR_ERR(owl_timer_base); + } + + owl_clksrc_base = owl_timer_base + 0x08; + owl_clkevt_base = owl_timer_base + 0x14; + + timer1_irq = of_irq_get_byname(node, "timer1"); + if (timer1_irq <= 0) { + pr_err("Can't parse timer1 IRQ\n"); + return -EINVAL; + } + + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + rate = clk_get_rate(clk); + + owl_timer_reset(owl_clksrc_base); + owl_timer_set_enabled(owl_clksrc_base, true); + + sched_clock_register(owl_timer_sched_read, 32, rate); + clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name, + rate, 200, 32, clocksource_mmio_readl_up); + + owl_timer_reset(owl_clkevt_base); + + ret = request_irq(timer1_irq, owl_timer1_interrupt, IRQF_TIMER, + "owl-timer", &owl_clockevent); + if (ret) { + pr_err("failed to request irq %d\n", timer1_irq); + return ret; + } + + owl_clockevent.cpumask = cpumask_of(0); + owl_clockevent.irq = timer1_irq; + + clockevents_config_and_register(&owl_clockevent, rate, + 0xf, 0xffffffff); + + return 0; +} +TIMER_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init); +TIMER_OF_DECLARE(owl_s700, "actions,s700-timer", owl_timer_init); +TIMER_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init); diff --git a/drivers/clocksource/timer-pistachio.c b/drivers/clocksource/timer-pistachio.c new file mode 100644 index 000000000000..a2dd85d0c1d7 --- /dev/null +++ b/drivers/clocksource/timer-pistachio.c @@ -0,0 +1,218 @@ +/* + * Pistachio clocksource based on general-purpose timers + * + * Copyright (C) 2015 Imagination Technologies + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Top level reg */ +#define CR_TIMER_CTRL_CFG 0x00 +#define TIMER_ME_GLOBAL BIT(0) +#define CR_TIMER_REV 0x10 + +/* Timer specific registers */ +#define TIMER_CFG 0x20 +#define TIMER_ME_LOCAL BIT(0) +#define TIMER_RELOAD_VALUE 0x24 +#define TIMER_CURRENT_VALUE 0x28 +#define TIMER_CURRENT_OVERFLOW_VALUE 0x2C +#define TIMER_IRQ_STATUS 0x30 +#define TIMER_IRQ_CLEAR 0x34 +#define TIMER_IRQ_MASK 0x38 + +#define PERIP_TIMER_CONTROL 0x90 + +/* Timer specific configuration Values */ +#define RELOAD_VALUE 0xffffffff + +struct pistachio_clocksource { + void __iomem *base; + raw_spinlock_t lock; + struct clocksource cs; +}; + +static struct pistachio_clocksource pcs_gpt; + +#define to_pistachio_clocksource(cs) \ + container_of(cs, struct pistachio_clocksource, cs) + +static inline u32 gpt_readl(void __iomem *base, u32 offset, u32 gpt_id) +{ + return readl(base + 0x20 * gpt_id + offset); +} + +static inline void gpt_writel(void __iomem *base, u32 value, u32 offset, + u32 gpt_id) +{ + writel(value, base + 0x20 * gpt_id + offset); +} + +static u64 notrace +pistachio_clocksource_read_cycles(struct clocksource *cs) +{ + struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); + u32 counter, overflw; + unsigned long flags; + + /* + * The counter value is only refreshed after the overflow value is read. + * And they must be read in strict order, hence raw spin lock added. + */ + + raw_spin_lock_irqsave(&pcs->lock, flags); + overflw = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0); + counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0); + raw_spin_unlock_irqrestore(&pcs->lock, flags); + + return (u64)~counter; +} + +static u64 notrace pistachio_read_sched_clock(void) +{ + return pistachio_clocksource_read_cycles(&pcs_gpt.cs); +} + +static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx, + int enable) +{ + struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); + u32 val; + + val = gpt_readl(pcs->base, TIMER_CFG, timeridx); + if (enable) + val |= TIMER_ME_LOCAL; + else + val &= ~TIMER_ME_LOCAL; + + gpt_writel(pcs->base, val, TIMER_CFG, timeridx); +} + +static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx) +{ + struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); + + /* Disable GPT local before loading reload value */ + pistachio_clksrc_set_mode(cs, timeridx, false); + gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx); + pistachio_clksrc_set_mode(cs, timeridx, true); +} + +static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx) +{ + /* Disable GPT local */ + pistachio_clksrc_set_mode(cs, timeridx, false); +} + +static int pistachio_clocksource_enable(struct clocksource *cs) +{ + pistachio_clksrc_enable(cs, 0); + return 0; +} + +static void pistachio_clocksource_disable(struct clocksource *cs) +{ + pistachio_clksrc_disable(cs, 0); +} + +/* Desirable clock source for pistachio platform */ +static struct pistachio_clocksource pcs_gpt = { + .cs = { + .name = "gptimer", + .rating = 300, + .enable = pistachio_clocksource_enable, + .disable = pistachio_clocksource_disable, + .read = pistachio_clocksource_read_cycles, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS | + CLOCK_SOURCE_SUSPEND_NONSTOP, + }, +}; + +static int __init pistachio_clksrc_of_init(struct device_node *node) +{ + struct clk *sys_clk, *fast_clk; + struct regmap *periph_regs; + unsigned long rate; + int ret; + + pcs_gpt.base = of_iomap(node, 0); + if (!pcs_gpt.base) { + pr_err("cannot iomap\n"); + return -ENXIO; + } + + periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph"); + if (IS_ERR(periph_regs)) { + pr_err("cannot get peripheral regmap (%ld)\n", + PTR_ERR(periph_regs)); + return PTR_ERR(periph_regs); + } + + /* Switch to using the fast counter clock */ + ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL, + 0xf, 0x0); + if (ret) + return ret; + + sys_clk = of_clk_get_by_name(node, "sys"); + if (IS_ERR(sys_clk)) { + pr_err("clock get failed (%ld)\n", PTR_ERR(sys_clk)); + return PTR_ERR(sys_clk); + } + + fast_clk = of_clk_get_by_name(node, "fast"); + if (IS_ERR(fast_clk)) { + pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk)); + return PTR_ERR(fast_clk); + } + + ret = clk_prepare_enable(sys_clk); + if (ret < 0) { + pr_err("failed to enable clock (%d)\n", ret); + return ret; + } + + ret = clk_prepare_enable(fast_clk); + if (ret < 0) { + pr_err("failed to enable clock (%d)\n", ret); + clk_disable_unprepare(sys_clk); + return ret; + } + + rate = clk_get_rate(fast_clk); + + /* Disable irq's for clocksource usage */ + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 0); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 1); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 2); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 3); + + /* Enable timer block */ + writel(TIMER_ME_GLOBAL, pcs_gpt.base); + + raw_spin_lock_init(&pcs_gpt.lock); + sched_clock_register(pistachio_read_sched_clock, 32, rate); + return clocksource_register_hz(&pcs_gpt.cs, rate); +} +TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer", + pistachio_clksrc_of_init); diff --git a/drivers/clocksource/timer-qcom.c b/drivers/clocksource/timer-qcom.c new file mode 100644 index 000000000000..89816f89ff3f --- /dev/null +++ b/drivers/clocksource/timer-qcom.c @@ -0,0 +1,258 @@ +/* + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TIMER_MATCH_VAL 0x0000 +#define TIMER_COUNT_VAL 0x0004 +#define TIMER_ENABLE 0x0008 +#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) +#define TIMER_ENABLE_EN BIT(0) +#define TIMER_CLEAR 0x000C +#define DGT_CLK_CTL 0x10 +#define DGT_CLK_CTL_DIV_4 0x3 +#define TIMER_STS_GPT0_CLR_PEND BIT(10) + +#define GPT_HZ 32768 + +static void __iomem *event_base; +static void __iomem *sts_base; + +static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + /* Stop the timer tick */ + if (clockevent_state_oneshot(evt)) { + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); + ctrl &= ~TIMER_ENABLE_EN; + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + } + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static int msm_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); + + ctrl &= ~TIMER_ENABLE_EN; + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + + writel_relaxed(ctrl, event_base + TIMER_CLEAR); + writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); + + if (sts_base) + while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) + cpu_relax(); + + writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); + return 0; +} + +static int msm_timer_shutdown(struct clock_event_device *evt) +{ + u32 ctrl; + + ctrl = readl_relaxed(event_base + TIMER_ENABLE); + ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + return 0; +} + +static struct clock_event_device __percpu *msm_evt; + +static void __iomem *source_base; + +static notrace u64 msm_read_timer_count(struct clocksource *cs) +{ + return readl_relaxed(source_base + TIMER_COUNT_VAL); +} + +static struct clocksource msm_clocksource = { + .name = "dg_timer", + .rating = 300, + .read = msm_read_timer_count, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int msm_timer_irq; +static int msm_timer_has_ppi; + +static int msm_local_timer_starting_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); + int err; + + evt->irq = msm_timer_irq; + evt->name = "msm_timer"; + evt->features = CLOCK_EVT_FEAT_ONESHOT; + evt->rating = 200; + evt->set_state_shutdown = msm_timer_shutdown; + evt->set_state_oneshot = msm_timer_shutdown; + evt->tick_resume = msm_timer_shutdown; + evt->set_next_event = msm_timer_set_next_event; + evt->cpumask = cpumask_of(cpu); + + clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); + + if (msm_timer_has_ppi) { + enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); + } else { + err = request_irq(evt->irq, msm_timer_interrupt, + IRQF_TIMER | IRQF_NOBALANCING | + IRQF_TRIGGER_RISING, "gp_timer", evt); + if (err) + pr_err("request_irq failed\n"); + } + + return 0; +} + +static int msm_local_timer_dying_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); + + evt->set_state_shutdown(evt); + disable_percpu_irq(evt->irq); + return 0; +} + +static u64 notrace msm_sched_clock_read(void) +{ + return msm_clocksource.read(&msm_clocksource); +} + +static unsigned long msm_read_current_timer(void) +{ + return msm_clocksource.read(&msm_clocksource); +} + +static struct delay_timer msm_delay_timer = { + .read_current_timer = msm_read_current_timer, +}; + +static int __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, + bool percpu) +{ + struct clocksource *cs = &msm_clocksource; + int res = 0; + + msm_timer_irq = irq; + msm_timer_has_ppi = percpu; + + msm_evt = alloc_percpu(struct clock_event_device); + if (!msm_evt) { + pr_err("memory allocation failed for clockevents\n"); + goto err; + } + + if (percpu) + res = request_percpu_irq(irq, msm_timer_interrupt, + "gp_timer", msm_evt); + + if (res) { + pr_err("request_percpu_irq failed\n"); + } else { + /* Install and invoke hotplug callbacks */ + res = cpuhp_setup_state(CPUHP_AP_QCOM_TIMER_STARTING, + "clockevents/qcom/timer:starting", + msm_local_timer_starting_cpu, + msm_local_timer_dying_cpu); + if (res) { + free_percpu_irq(irq, msm_evt); + goto err; + } + } + +err: + writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); + res = clocksource_register_hz(cs, dgt_hz); + if (res) + pr_err("clocksource_register failed\n"); + sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); + msm_delay_timer.freq = dgt_hz; + register_current_timer_delay(&msm_delay_timer); + + return res; +} + +static int __init msm_dt_timer_init(struct device_node *np) +{ + u32 freq; + int irq, ret; + struct resource res; + u32 percpu_offset; + void __iomem *base; + void __iomem *cpu0_base; + + base = of_iomap(np, 0); + if (!base) { + pr_err("Failed to map event base\n"); + return -ENXIO; + } + + /* We use GPT0 for the clockevent */ + irq = irq_of_parse_and_map(np, 1); + if (irq <= 0) { + pr_err("Can't get irq\n"); + return -EINVAL; + } + + /* We use CPU0's DGT for the clocksource */ + if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) + percpu_offset = 0; + + ret = of_address_to_resource(np, 0, &res); + if (ret) { + pr_err("Failed to parse DGT resource\n"); + return ret; + } + + cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); + if (!cpu0_base) { + pr_err("Failed to map source base\n"); + return -EINVAL; + } + + if (of_property_read_u32(np, "clock-frequency", &freq)) { + pr_err("Unknown frequency\n"); + return -EINVAL; + } + + event_base = base + 0x4; + sts_base = base + 0x88; + source_base = cpu0_base + 0x24; + freq /= 4; + writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); + + return msm_timer_init(freq, 32, irq, !!percpu_offset); +} +TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); +TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); diff --git a/drivers/clocksource/timer-versatile.c b/drivers/clocksource/timer-versatile.c new file mode 100644 index 000000000000..39725d38aede --- /dev/null +++ b/drivers/clocksource/timer-versatile.c @@ -0,0 +1,44 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + * + * Copyright (C) 2014 ARM Limited + */ + +#include +#include +#include +#include + +#define SYS_24MHZ 0x05c + +static void __iomem *versatile_sys_24mhz; + +static u64 notrace versatile_sys_24mhz_read(void) +{ + return readl(versatile_sys_24mhz); +} + +static int __init versatile_sched_clock_init(struct device_node *node) +{ + void __iomem *base = of_iomap(node, 0); + + if (!base) + return -ENXIO; + + versatile_sys_24mhz = base + SYS_24MHZ; + + sched_clock_register(versatile_sys_24mhz_read, 32, 24000000); + + return 0; +} +TIMER_OF_DECLARE(vexpress, "arm,vexpress-sysreg", + versatile_sched_clock_init); +TIMER_OF_DECLARE(versatile, "arm,versatile-sysreg", + versatile_sched_clock_init); diff --git a/drivers/clocksource/timer-vf-pit.c b/drivers/clocksource/timer-vf-pit.c new file mode 100644 index 000000000000..0f92089ec08c --- /dev/null +++ b/drivers/clocksource/timer-vf-pit.c @@ -0,0 +1,204 @@ +/* + * Copyright 2012-2013 Freescale Semiconductor, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Each pit takes 0x10 Bytes register space + */ +#define PITMCR 0x00 +#define PIT0_OFFSET 0x100 +#define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n)) +#define PITLDVAL 0x00 +#define PITCVAL 0x04 +#define PITTCTRL 0x08 +#define PITTFLG 0x0c + +#define PITMCR_MDIS (0x1 << 1) + +#define PITTCTRL_TEN (0x1 << 0) +#define PITTCTRL_TIE (0x1 << 1) +#define PITCTRL_CHN (0x1 << 2) + +#define PITTFLG_TIF 0x1 + +static void __iomem *clksrc_base; +static void __iomem *clkevt_base; +static unsigned long cycle_per_jiffy; + +static inline void pit_timer_enable(void) +{ + __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL); +} + +static inline void pit_timer_disable(void) +{ + __raw_writel(0, clkevt_base + PITTCTRL); +} + +static inline void pit_irq_acknowledge(void) +{ + __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); +} + +static u64 notrace pit_read_sched_clock(void) +{ + return ~__raw_readl(clksrc_base + PITCVAL); +} + +static int __init pit_clocksource_init(unsigned long rate) +{ + /* set the max load value and start the clock source counter */ + __raw_writel(0, clksrc_base + PITTCTRL); + __raw_writel(~0UL, clksrc_base + PITLDVAL); + __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL); + + sched_clock_register(pit_read_sched_clock, 32, rate); + return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate, + 300, 32, clocksource_mmio_readl_down); +} + +static int pit_set_next_event(unsigned long delta, + struct clock_event_device *unused) +{ + /* + * set a new value to PITLDVAL register will not restart the timer, + * to abort the current cycle and start a timer period with the new + * value, the timer must be disabled and enabled again. + * and the PITLAVAL should be set to delta minus one according to pit + * hardware requirement. + */ + pit_timer_disable(); + __raw_writel(delta - 1, clkevt_base + PITLDVAL); + pit_timer_enable(); + + return 0; +} + +static int pit_shutdown(struct clock_event_device *evt) +{ + pit_timer_disable(); + return 0; +} + +static int pit_set_periodic(struct clock_event_device *evt) +{ + pit_set_next_event(cycle_per_jiffy, evt); + return 0; +} + +static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + pit_irq_acknowledge(); + + /* + * pit hardware doesn't support oneshot, it will generate an interrupt + * and reload the counter value from PITLDVAL when PITCVAL reach zero, + * and start the counter again. So software need to disable the timer + * to stop the counter loop in ONESHOT mode. + */ + if (likely(clockevent_state_oneshot(evt))) + pit_timer_disable(); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct clock_event_device clockevent_pit = { + .name = "VF pit timer", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = pit_shutdown, + .set_state_periodic = pit_set_periodic, + .set_next_event = pit_set_next_event, + .rating = 300, +}; + +static struct irqaction pit_timer_irq = { + .name = "VF pit timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = pit_timer_interrupt, + .dev_id = &clockevent_pit, +}; + +static int __init pit_clockevent_init(unsigned long rate, int irq) +{ + __raw_writel(0, clkevt_base + PITTCTRL); + __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); + + BUG_ON(setup_irq(irq, &pit_timer_irq)); + + clockevent_pit.cpumask = cpumask_of(0); + clockevent_pit.irq = irq; + /* + * The value for the LDVAL register trigger is calculated as: + * LDVAL trigger = (period / clock period) - 1 + * The pit is a 32-bit down count timer, when the conter value + * reaches 0, it will generate an interrupt, thus the minimal + * LDVAL trigger value is 1. And then the min_delta is + * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit. + */ + clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff); + + return 0; +} + +static int __init pit_timer_init(struct device_node *np) +{ + struct clk *pit_clk; + void __iomem *timer_base; + unsigned long clk_rate; + int irq, ret; + + timer_base = of_iomap(np, 0); + if (!timer_base) { + pr_err("Failed to iomap\n"); + return -ENXIO; + } + + /* + * PIT0 and PIT1 can be chained to build a 64-bit timer, + * so choose PIT2 as clocksource, PIT3 as clockevent device, + * and leave PIT0 and PIT1 unused for anyone else who needs them. + */ + clksrc_base = timer_base + PITn_OFFSET(2); + clkevt_base = timer_base + PITn_OFFSET(3); + + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) + return -EINVAL; + + pit_clk = of_clk_get(np, 0); + if (IS_ERR(pit_clk)) + return PTR_ERR(pit_clk); + + ret = clk_prepare_enable(pit_clk); + if (ret) + return ret; + + clk_rate = clk_get_rate(pit_clk); + cycle_per_jiffy = clk_rate / (HZ); + + /* enable the pit module */ + __raw_writel(~PITMCR_MDIS, timer_base + PITMCR); + + ret = pit_clocksource_init(clk_rate); + if (ret) + return ret; + + return pit_clockevent_init(clk_rate, irq); +} +TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); diff --git a/drivers/clocksource/timer-vt8500.c b/drivers/clocksource/timer-vt8500.c new file mode 100644 index 000000000000..e0f7489cfc8e --- /dev/null +++ b/drivers/clocksource/timer-vt8500.c @@ -0,0 +1,168 @@ +/* + * arch/arm/mach-vt8500/timer.c + * + * Copyright (C) 2012 Tony Prisk + * Copyright (C) 2010 Alexey Charkov + * + * 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 + */ + +/* + * This file is copied and modified from the original timer.c provided by + * Alexey Charkov. Minor changes have been made for Device Tree Support. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define VT8500_TIMER_OFFSET 0x0100 +#define VT8500_TIMER_HZ 3000000 +#define TIMER_MATCH_VAL 0x0000 +#define TIMER_COUNT_VAL 0x0010 +#define TIMER_STATUS_VAL 0x0014 +#define TIMER_IER_VAL 0x001c /* interrupt enable */ +#define TIMER_CTRL_VAL 0x0020 +#define TIMER_AS_VAL 0x0024 /* access status */ +#define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ +#define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ +#define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ + +#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) + +#define MIN_OSCR_DELTA 16 + +static void __iomem *regbase; + +static u64 vt8500_timer_read(struct clocksource *cs) +{ + int loops = msecs_to_loops(10); + writel(3, regbase + TIMER_CTRL_VAL); + while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE) + && --loops) + cpu_relax(); + return readl(regbase + TIMER_COUNT_VAL); +} + +static struct clocksource clocksource = { + .name = "vt8500_timer", + .rating = 200, + .read = vt8500_timer_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int vt8500_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + int loops = msecs_to_loops(10); + u64 alarm = clocksource.read(&clocksource) + cycles; + while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE) + && --loops) + cpu_relax(); + writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL); + + if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA) + return -ETIME; + + writel(1, regbase + TIMER_IER_VAL); + + return 0; +} + +static int vt8500_shutdown(struct clock_event_device *evt) +{ + writel(readl(regbase + TIMER_CTRL_VAL) | 1, regbase + TIMER_CTRL_VAL); + writel(0, regbase + TIMER_IER_VAL); + return 0; +} + +static struct clock_event_device clockevent = { + .name = "vt8500_timer", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = vt8500_timer_set_next_event, + .set_state_shutdown = vt8500_shutdown, + .set_state_oneshot = vt8500_shutdown, +}; + +static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + writel(0xf, regbase + TIMER_STATUS_VAL); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction irq = { + .name = "vt8500_timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = vt8500_timer_interrupt, + .dev_id = &clockevent, +}; + +static int __init vt8500_timer_init(struct device_node *np) +{ + int timer_irq, ret; + + regbase = of_iomap(np, 0); + if (!regbase) { + pr_err("%s: Missing iobase description in Device Tree\n", + __func__); + return -ENXIO; + } + + timer_irq = irq_of_parse_and_map(np, 0); + if (!timer_irq) { + pr_err("%s: Missing irq description in Device Tree\n", + __func__); + return -EINVAL; + } + + writel(1, regbase + TIMER_CTRL_VAL); + writel(0xf, regbase + TIMER_STATUS_VAL); + writel(~0, regbase + TIMER_MATCH_VAL); + + ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ); + if (ret) { + pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", + __func__, clocksource.name); + return ret; + } + + clockevent.cpumask = cpumask_of(0); + + ret = setup_irq(timer_irq, &irq); + if (ret) { + pr_err("%s: setup_irq failed for %s\n", __func__, + clockevent.name); + return ret; + } + + clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ, + MIN_OSCR_DELTA * 2, 0xf0000000); + + return 0; +} + +TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); diff --git a/drivers/clocksource/timer-zevio.c b/drivers/clocksource/timer-zevio.c new file mode 100644 index 000000000000..6127e8062a71 --- /dev/null +++ b/drivers/clocksource/timer-zevio.c @@ -0,0 +1,218 @@ +/* + * linux/drivers/clocksource/zevio-timer.c + * + * Copyright (C) 2013 Daniel Tang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IO_CURRENT_VAL 0x00 +#define IO_DIVIDER 0x04 +#define IO_CONTROL 0x08 + +#define IO_TIMER1 0x00 +#define IO_TIMER2 0x0C + +#define IO_MATCH_BEGIN 0x18 +#define IO_MATCH(x) (IO_MATCH_BEGIN + ((x) << 2)) + +#define IO_INTR_STS 0x00 +#define IO_INTR_ACK 0x00 +#define IO_INTR_MSK 0x04 + +#define CNTL_STOP_TIMER (1 << 4) +#define CNTL_RUN_TIMER (0 << 4) + +#define CNTL_INC (1 << 3) +#define CNTL_DEC (0 << 3) + +#define CNTL_TOZERO 0 +#define CNTL_MATCH(x) ((x) + 1) +#define CNTL_FOREVER 7 + +/* There are 6 match registers but we only use one. */ +#define TIMER_MATCH 0 + +#define TIMER_INTR_MSK (1 << (TIMER_MATCH)) +#define TIMER_INTR_ALL 0x3F + +struct zevio_timer { + void __iomem *base; + void __iomem *timer1, *timer2; + void __iomem *interrupt_regs; + + struct clk *clk; + struct clock_event_device clkevt; + struct irqaction clkevt_irq; + + char clocksource_name[64]; + char clockevent_name[64]; +}; + +static int zevio_timer_set_event(unsigned long delta, + struct clock_event_device *dev) +{ + struct zevio_timer *timer = container_of(dev, struct zevio_timer, + clkevt); + + writel(delta, timer->timer1 + IO_CURRENT_VAL); + writel(CNTL_RUN_TIMER | CNTL_DEC | CNTL_MATCH(TIMER_MATCH), + timer->timer1 + IO_CONTROL); + + return 0; +} + +static int zevio_timer_shutdown(struct clock_event_device *dev) +{ + struct zevio_timer *timer = container_of(dev, struct zevio_timer, + clkevt); + + /* Disable timer interrupts */ + writel(0, timer->interrupt_regs + IO_INTR_MSK); + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); + /* Stop timer */ + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); + return 0; +} + +static int zevio_timer_set_oneshot(struct clock_event_device *dev) +{ + struct zevio_timer *timer = container_of(dev, struct zevio_timer, + clkevt); + + /* Enable timer interrupts */ + writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK); + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); + return 0; +} + +static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) +{ + struct zevio_timer *timer = dev_id; + u32 intr; + + intr = readl(timer->interrupt_regs + IO_INTR_ACK); + if (!(intr & TIMER_INTR_MSK)) + return IRQ_NONE; + + writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_ACK); + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); + + if (timer->clkevt.event_handler) + timer->clkevt.event_handler(&timer->clkevt); + + return IRQ_HANDLED; +} + +static int __init zevio_timer_add(struct device_node *node) +{ + struct zevio_timer *timer; + struct resource res; + int irqnr, ret; + + timer = kzalloc(sizeof(*timer), GFP_KERNEL); + if (!timer) + return -ENOMEM; + + timer->base = of_iomap(node, 0); + if (!timer->base) { + ret = -EINVAL; + goto error_free; + } + timer->timer1 = timer->base + IO_TIMER1; + timer->timer2 = timer->base + IO_TIMER2; + + timer->clk = of_clk_get(node, 0); + if (IS_ERR(timer->clk)) { + ret = PTR_ERR(timer->clk); + pr_err("Timer clock not found! (error %d)\n", ret); + goto error_unmap; + } + + timer->interrupt_regs = of_iomap(node, 1); + irqnr = irq_of_parse_and_map(node, 0); + + of_address_to_resource(node, 0, &res); + scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name), + "%llx.%pOFn_clocksource", + (unsigned long long)res.start, node); + + scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name), + "%llx.%pOFn_clockevent", + (unsigned long long)res.start, node); + + if (timer->interrupt_regs && irqnr) { + timer->clkevt.name = timer->clockevent_name; + timer->clkevt.set_next_event = zevio_timer_set_event; + timer->clkevt.set_state_shutdown = zevio_timer_shutdown; + timer->clkevt.set_state_oneshot = zevio_timer_set_oneshot; + timer->clkevt.tick_resume = zevio_timer_set_oneshot; + timer->clkevt.rating = 200; + timer->clkevt.cpumask = cpu_possible_mask; + timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT; + timer->clkevt.irq = irqnr; + + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); + writel(0, timer->timer1 + IO_DIVIDER); + + /* Start with timer interrupts disabled */ + writel(0, timer->interrupt_regs + IO_INTR_MSK); + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); + + /* Interrupt to occur when timer value matches 0 */ + writel(0, timer->base + IO_MATCH(TIMER_MATCH)); + + timer->clkevt_irq.name = timer->clockevent_name; + timer->clkevt_irq.handler = zevio_timer_interrupt; + timer->clkevt_irq.dev_id = timer; + timer->clkevt_irq.flags = IRQF_TIMER | IRQF_IRQPOLL; + + setup_irq(irqnr, &timer->clkevt_irq); + + clockevents_config_and_register(&timer->clkevt, + clk_get_rate(timer->clk), 0x0001, 0xffff); + pr_info("Added %s as clockevent\n", timer->clockevent_name); + } + + writel(CNTL_STOP_TIMER, timer->timer2 + IO_CONTROL); + writel(0, timer->timer2 + IO_CURRENT_VAL); + writel(0, timer->timer2 + IO_DIVIDER); + writel(CNTL_RUN_TIMER | CNTL_FOREVER | CNTL_INC, + timer->timer2 + IO_CONTROL); + + clocksource_mmio_init(timer->timer2 + IO_CURRENT_VAL, + timer->clocksource_name, + clk_get_rate(timer->clk), + 200, 16, + clocksource_mmio_readw_up); + + pr_info("Added %s as clocksource\n", timer->clocksource_name); + + return 0; +error_unmap: + iounmap(timer->base); +error_free: + kfree(timer); + return ret; +} + +static int __init zevio_timer_init(struct device_node *node) +{ + return zevio_timer_add(node); +} + +TIMER_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init); diff --git a/drivers/clocksource/versatile.c b/drivers/clocksource/versatile.c deleted file mode 100644 index 39725d38aede..000000000000 --- a/drivers/clocksource/versatile.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - * - * Copyright (C) 2014 ARM Limited - */ - -#include -#include -#include -#include - -#define SYS_24MHZ 0x05c - -static void __iomem *versatile_sys_24mhz; - -static u64 notrace versatile_sys_24mhz_read(void) -{ - return readl(versatile_sys_24mhz); -} - -static int __init versatile_sched_clock_init(struct device_node *node) -{ - void __iomem *base = of_iomap(node, 0); - - if (!base) - return -ENXIO; - - versatile_sys_24mhz = base + SYS_24MHZ; - - sched_clock_register(versatile_sys_24mhz_read, 32, 24000000); - - return 0; -} -TIMER_OF_DECLARE(vexpress, "arm,vexpress-sysreg", - versatile_sched_clock_init); -TIMER_OF_DECLARE(versatile, "arm,versatile-sysreg", - versatile_sched_clock_init); diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c deleted file mode 100644 index 0f92089ec08c..000000000000 --- a/drivers/clocksource/vf_pit_timer.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2012-2013 Freescale Semiconductor, Inc. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include - -/* - * Each pit takes 0x10 Bytes register space - */ -#define PITMCR 0x00 -#define PIT0_OFFSET 0x100 -#define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n)) -#define PITLDVAL 0x00 -#define PITCVAL 0x04 -#define PITTCTRL 0x08 -#define PITTFLG 0x0c - -#define PITMCR_MDIS (0x1 << 1) - -#define PITTCTRL_TEN (0x1 << 0) -#define PITTCTRL_TIE (0x1 << 1) -#define PITCTRL_CHN (0x1 << 2) - -#define PITTFLG_TIF 0x1 - -static void __iomem *clksrc_base; -static void __iomem *clkevt_base; -static unsigned long cycle_per_jiffy; - -static inline void pit_timer_enable(void) -{ - __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL); -} - -static inline void pit_timer_disable(void) -{ - __raw_writel(0, clkevt_base + PITTCTRL); -} - -static inline void pit_irq_acknowledge(void) -{ - __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); -} - -static u64 notrace pit_read_sched_clock(void) -{ - return ~__raw_readl(clksrc_base + PITCVAL); -} - -static int __init pit_clocksource_init(unsigned long rate) -{ - /* set the max load value and start the clock source counter */ - __raw_writel(0, clksrc_base + PITTCTRL); - __raw_writel(~0UL, clksrc_base + PITLDVAL); - __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL); - - sched_clock_register(pit_read_sched_clock, 32, rate); - return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate, - 300, 32, clocksource_mmio_readl_down); -} - -static int pit_set_next_event(unsigned long delta, - struct clock_event_device *unused) -{ - /* - * set a new value to PITLDVAL register will not restart the timer, - * to abort the current cycle and start a timer period with the new - * value, the timer must be disabled and enabled again. - * and the PITLAVAL should be set to delta minus one according to pit - * hardware requirement. - */ - pit_timer_disable(); - __raw_writel(delta - 1, clkevt_base + PITLDVAL); - pit_timer_enable(); - - return 0; -} - -static int pit_shutdown(struct clock_event_device *evt) -{ - pit_timer_disable(); - return 0; -} - -static int pit_set_periodic(struct clock_event_device *evt) -{ - pit_set_next_event(cycle_per_jiffy, evt); - return 0; -} - -static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - pit_irq_acknowledge(); - - /* - * pit hardware doesn't support oneshot, it will generate an interrupt - * and reload the counter value from PITLDVAL when PITCVAL reach zero, - * and start the counter again. So software need to disable the timer - * to stop the counter loop in ONESHOT mode. - */ - if (likely(clockevent_state_oneshot(evt))) - pit_timer_disable(); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct clock_event_device clockevent_pit = { - .name = "VF pit timer", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_state_shutdown = pit_shutdown, - .set_state_periodic = pit_set_periodic, - .set_next_event = pit_set_next_event, - .rating = 300, -}; - -static struct irqaction pit_timer_irq = { - .name = "VF pit timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = pit_timer_interrupt, - .dev_id = &clockevent_pit, -}; - -static int __init pit_clockevent_init(unsigned long rate, int irq) -{ - __raw_writel(0, clkevt_base + PITTCTRL); - __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); - - BUG_ON(setup_irq(irq, &pit_timer_irq)); - - clockevent_pit.cpumask = cpumask_of(0); - clockevent_pit.irq = irq; - /* - * The value for the LDVAL register trigger is calculated as: - * LDVAL trigger = (period / clock period) - 1 - * The pit is a 32-bit down count timer, when the conter value - * reaches 0, it will generate an interrupt, thus the minimal - * LDVAL trigger value is 1. And then the min_delta is - * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit. - */ - clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff); - - return 0; -} - -static int __init pit_timer_init(struct device_node *np) -{ - struct clk *pit_clk; - void __iomem *timer_base; - unsigned long clk_rate; - int irq, ret; - - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("Failed to iomap\n"); - return -ENXIO; - } - - /* - * PIT0 and PIT1 can be chained to build a 64-bit timer, - * so choose PIT2 as clocksource, PIT3 as clockevent device, - * and leave PIT0 and PIT1 unused for anyone else who needs them. - */ - clksrc_base = timer_base + PITn_OFFSET(2); - clkevt_base = timer_base + PITn_OFFSET(3); - - irq = irq_of_parse_and_map(np, 0); - if (irq <= 0) - return -EINVAL; - - pit_clk = of_clk_get(np, 0); - if (IS_ERR(pit_clk)) - return PTR_ERR(pit_clk); - - ret = clk_prepare_enable(pit_clk); - if (ret) - return ret; - - clk_rate = clk_get_rate(pit_clk); - cycle_per_jiffy = clk_rate / (HZ); - - /* enable the pit module */ - __raw_writel(~PITMCR_MDIS, timer_base + PITMCR); - - ret = pit_clocksource_init(clk_rate); - if (ret) - return ret; - - return pit_clockevent_init(clk_rate, irq); -} -TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c deleted file mode 100644 index e0f7489cfc8e..000000000000 --- a/drivers/clocksource/vt8500_timer.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * arch/arm/mach-vt8500/timer.c - * - * Copyright (C) 2012 Tony Prisk - * Copyright (C) 2010 Alexey Charkov - * - * 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 - */ - -/* - * This file is copied and modified from the original timer.c provided by - * Alexey Charkov. Minor changes have been made for Device Tree Support. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define VT8500_TIMER_OFFSET 0x0100 -#define VT8500_TIMER_HZ 3000000 -#define TIMER_MATCH_VAL 0x0000 -#define TIMER_COUNT_VAL 0x0010 -#define TIMER_STATUS_VAL 0x0014 -#define TIMER_IER_VAL 0x001c /* interrupt enable */ -#define TIMER_CTRL_VAL 0x0020 -#define TIMER_AS_VAL 0x0024 /* access status */ -#define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ -#define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ -#define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ - -#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) - -#define MIN_OSCR_DELTA 16 - -static void __iomem *regbase; - -static u64 vt8500_timer_read(struct clocksource *cs) -{ - int loops = msecs_to_loops(10); - writel(3, regbase + TIMER_CTRL_VAL); - while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE) - && --loops) - cpu_relax(); - return readl(regbase + TIMER_COUNT_VAL); -} - -static struct clocksource clocksource = { - .name = "vt8500_timer", - .rating = 200, - .read = vt8500_timer_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static int vt8500_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - int loops = msecs_to_loops(10); - u64 alarm = clocksource.read(&clocksource) + cycles; - while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE) - && --loops) - cpu_relax(); - writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL); - - if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA) - return -ETIME; - - writel(1, regbase + TIMER_IER_VAL); - - return 0; -} - -static int vt8500_shutdown(struct clock_event_device *evt) -{ - writel(readl(regbase + TIMER_CTRL_VAL) | 1, regbase + TIMER_CTRL_VAL); - writel(0, regbase + TIMER_IER_VAL); - return 0; -} - -static struct clock_event_device clockevent = { - .name = "vt8500_timer", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_next_event = vt8500_timer_set_next_event, - .set_state_shutdown = vt8500_shutdown, - .set_state_oneshot = vt8500_shutdown, -}; - -static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - writel(0xf, regbase + TIMER_STATUS_VAL); - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction irq = { - .name = "vt8500_timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = vt8500_timer_interrupt, - .dev_id = &clockevent, -}; - -static int __init vt8500_timer_init(struct device_node *np) -{ - int timer_irq, ret; - - regbase = of_iomap(np, 0); - if (!regbase) { - pr_err("%s: Missing iobase description in Device Tree\n", - __func__); - return -ENXIO; - } - - timer_irq = irq_of_parse_and_map(np, 0); - if (!timer_irq) { - pr_err("%s: Missing irq description in Device Tree\n", - __func__); - return -EINVAL; - } - - writel(1, regbase + TIMER_CTRL_VAL); - writel(0xf, regbase + TIMER_STATUS_VAL); - writel(~0, regbase + TIMER_MATCH_VAL); - - ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ); - if (ret) { - pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", - __func__, clocksource.name); - return ret; - } - - clockevent.cpumask = cpumask_of(0); - - ret = setup_irq(timer_irq, &irq); - if (ret) { - pr_err("%s: setup_irq failed for %s\n", __func__, - clockevent.name); - return ret; - } - - clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ, - MIN_OSCR_DELTA * 2, 0xf0000000); - - return 0; -} - -TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c deleted file mode 100644 index 6127e8062a71..000000000000 --- a/drivers/clocksource/zevio-timer.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * linux/drivers/clocksource/zevio-timer.c - * - * Copyright (C) 2013 Daniel Tang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IO_CURRENT_VAL 0x00 -#define IO_DIVIDER 0x04 -#define IO_CONTROL 0x08 - -#define IO_TIMER1 0x00 -#define IO_TIMER2 0x0C - -#define IO_MATCH_BEGIN 0x18 -#define IO_MATCH(x) (IO_MATCH_BEGIN + ((x) << 2)) - -#define IO_INTR_STS 0x00 -#define IO_INTR_ACK 0x00 -#define IO_INTR_MSK 0x04 - -#define CNTL_STOP_TIMER (1 << 4) -#define CNTL_RUN_TIMER (0 << 4) - -#define CNTL_INC (1 << 3) -#define CNTL_DEC (0 << 3) - -#define CNTL_TOZERO 0 -#define CNTL_MATCH(x) ((x) + 1) -#define CNTL_FOREVER 7 - -/* There are 6 match registers but we only use one. */ -#define TIMER_MATCH 0 - -#define TIMER_INTR_MSK (1 << (TIMER_MATCH)) -#define TIMER_INTR_ALL 0x3F - -struct zevio_timer { - void __iomem *base; - void __iomem *timer1, *timer2; - void __iomem *interrupt_regs; - - struct clk *clk; - struct clock_event_device clkevt; - struct irqaction clkevt_irq; - - char clocksource_name[64]; - char clockevent_name[64]; -}; - -static int zevio_timer_set_event(unsigned long delta, - struct clock_event_device *dev) -{ - struct zevio_timer *timer = container_of(dev, struct zevio_timer, - clkevt); - - writel(delta, timer->timer1 + IO_CURRENT_VAL); - writel(CNTL_RUN_TIMER | CNTL_DEC | CNTL_MATCH(TIMER_MATCH), - timer->timer1 + IO_CONTROL); - - return 0; -} - -static int zevio_timer_shutdown(struct clock_event_device *dev) -{ - struct zevio_timer *timer = container_of(dev, struct zevio_timer, - clkevt); - - /* Disable timer interrupts */ - writel(0, timer->interrupt_regs + IO_INTR_MSK); - writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); - /* Stop timer */ - writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); - return 0; -} - -static int zevio_timer_set_oneshot(struct clock_event_device *dev) -{ - struct zevio_timer *timer = container_of(dev, struct zevio_timer, - clkevt); - - /* Enable timer interrupts */ - writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK); - writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); - return 0; -} - -static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) -{ - struct zevio_timer *timer = dev_id; - u32 intr; - - intr = readl(timer->interrupt_regs + IO_INTR_ACK); - if (!(intr & TIMER_INTR_MSK)) - return IRQ_NONE; - - writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_ACK); - writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); - - if (timer->clkevt.event_handler) - timer->clkevt.event_handler(&timer->clkevt); - - return IRQ_HANDLED; -} - -static int __init zevio_timer_add(struct device_node *node) -{ - struct zevio_timer *timer; - struct resource res; - int irqnr, ret; - - timer = kzalloc(sizeof(*timer), GFP_KERNEL); - if (!timer) - return -ENOMEM; - - timer->base = of_iomap(node, 0); - if (!timer->base) { - ret = -EINVAL; - goto error_free; - } - timer->timer1 = timer->base + IO_TIMER1; - timer->timer2 = timer->base + IO_TIMER2; - - timer->clk = of_clk_get(node, 0); - if (IS_ERR(timer->clk)) { - ret = PTR_ERR(timer->clk); - pr_err("Timer clock not found! (error %d)\n", ret); - goto error_unmap; - } - - timer->interrupt_regs = of_iomap(node, 1); - irqnr = irq_of_parse_and_map(node, 0); - - of_address_to_resource(node, 0, &res); - scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name), - "%llx.%pOFn_clocksource", - (unsigned long long)res.start, node); - - scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name), - "%llx.%pOFn_clockevent", - (unsigned long long)res.start, node); - - if (timer->interrupt_regs && irqnr) { - timer->clkevt.name = timer->clockevent_name; - timer->clkevt.set_next_event = zevio_timer_set_event; - timer->clkevt.set_state_shutdown = zevio_timer_shutdown; - timer->clkevt.set_state_oneshot = zevio_timer_set_oneshot; - timer->clkevt.tick_resume = zevio_timer_set_oneshot; - timer->clkevt.rating = 200; - timer->clkevt.cpumask = cpu_possible_mask; - timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT; - timer->clkevt.irq = irqnr; - - writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); - writel(0, timer->timer1 + IO_DIVIDER); - - /* Start with timer interrupts disabled */ - writel(0, timer->interrupt_regs + IO_INTR_MSK); - writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); - - /* Interrupt to occur when timer value matches 0 */ - writel(0, timer->base + IO_MATCH(TIMER_MATCH)); - - timer->clkevt_irq.name = timer->clockevent_name; - timer->clkevt_irq.handler = zevio_timer_interrupt; - timer->clkevt_irq.dev_id = timer; - timer->clkevt_irq.flags = IRQF_TIMER | IRQF_IRQPOLL; - - setup_irq(irqnr, &timer->clkevt_irq); - - clockevents_config_and_register(&timer->clkevt, - clk_get_rate(timer->clk), 0x0001, 0xffff); - pr_info("Added %s as clockevent\n", timer->clockevent_name); - } - - writel(CNTL_STOP_TIMER, timer->timer2 + IO_CONTROL); - writel(0, timer->timer2 + IO_CURRENT_VAL); - writel(0, timer->timer2 + IO_DIVIDER); - writel(CNTL_RUN_TIMER | CNTL_FOREVER | CNTL_INC, - timer->timer2 + IO_CONTROL); - - clocksource_mmio_init(timer->timer2 + IO_CURRENT_VAL, - timer->clocksource_name, - clk_get_rate(timer->clk), - 200, 16, - clocksource_mmio_readw_up); - - pr_info("Added %s as clocksource\n", timer->clocksource_name); - - return 0; -error_unmap: - iounmap(timer->base); -error_free: - kfree(timer); - return ret; -} - -static int __init zevio_timer_init(struct device_node *node) -{ - return zevio_timer_add(node); -} - -TIMER_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init); -- cgit v1.2.3-59-g8ed1b From 9414229c9c53d3604032aa80f3d2e9ba5770cd4a Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 24 Sep 2018 06:08:07 +0200 Subject: clocksource: Remove obsolete CLOCKSOURCE_OF_DECLARE The macro CLOCKSOURCE_OF_DECLARE was renamed more TIMER_OF_DECLARE, and we kept an alias CLOCKSOURCE_OF_DECLARE in order to smooth the transition for drivers. This change was done 1.5 year ago, we can reasonably remove this backward compatible macro as it is no longer used anywhere. Signed-off-by: Daniel Lezcano --- include/linux/clocksource.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 308918928767..4c58c1e64080 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -257,9 +257,6 @@ extern int clocksource_i8253_init(void); #define TIMER_OF_DECLARE(name, compat, fn) \ OF_DECLARE_1_RET(timer, name, compat, fn) -#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \ - TIMER_OF_DECLARE(name, compat, fn) - #ifdef CONFIG_TIMER_PROBE extern void timer_probe(void); #else -- cgit v1.2.3-59-g8ed1b From 1f174a1a2cdebc65138e6ed1448b842e73200bb5 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 17 Sep 2018 09:52:14 -0500 Subject: clocksource/drivers/dw_apb: Add reset control Add code to retrieve the reset property from the dw-apb timers and if the property is available, the safe operation is to assert the timer into reset, and followed by a deassert of the timer reset (brings the timer out of reset). This patch is needed for systems where the bootloader has left the timer not used in reset. - Trivial conflict with commit a74bd1ad7a: "Convert to using %pOFn instead of device_node.name" Reported-by: Marek Vasut Signed-off-by: Dinh Nguyen Signed-off-by: Daniel Lezcano --- drivers/clocksource/dw_apb_timer_of.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index fabaa29cc3a4..db410acd8964 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -22,6 +22,7 @@ #include #include #include +#include #include static void __init timer_get_base_and_rate(struct device_node *np, @@ -29,12 +30,23 @@ static void __init timer_get_base_and_rate(struct device_node *np, { struct clk *timer_clk; struct clk *pclk; + struct reset_control *rstc; *base = of_iomap(np, 0); if (!*base) panic("Unable to map regs for %pOFn", np); + /* + * Reset the timer if the reset control is available, wiping + * out the state the firmware may have left it + */ + rstc = of_reset_control_get(np, NULL); + if (!IS_ERR(rstc)) { + reset_control_assert(rstc); + reset_control_deassert(rstc); + } + /* * Not all implementations use a periphal clock, so don't panic * if it's not present -- cgit v1.2.3-59-g8ed1b From d59e0ba19481c0046d2ea2bd0e5344eeaf45aace Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 9 Oct 2018 11:43:35 -0400 Subject: tick/sched : Remove redundant cpu_online() check can_stop_idle_tick() checks cpu_online() twice. The first check leaves the function when the CPU is not online, so the second check it redundant. Remove it. Signed-off-by: Peng Hao Signed-off-by: Thomas Gleixner Cc: fweisbec@gmail.com Link: https://lkml.kernel.org/r/1539099815-2943-1-git-send-email-penghao122@sina.com.cn --- kernel/time/tick-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 5b33e2f5c0ed..69e673b88474 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -885,7 +885,7 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts) if (need_resched()) return false; - if (unlikely(local_softirq_pending() && cpu_online(cpu))) { + if (unlikely(local_softirq_pending())) { static int ratelimit; if (ratelimit < 10 && -- cgit v1.2.3-59-g8ed1b