71 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Generic MMIO clocksource support4 */5#include <linux/clocksource.h>6#include <linux/errno.h>7#include <linux/init.h>8#include <linux/slab.h>9 10struct clocksource_mmio {11 void __iomem *reg;12 struct clocksource clksrc;13};14 15static inline struct clocksource_mmio *to_mmio_clksrc(struct clocksource *c)16{17 return container_of(c, struct clocksource_mmio, clksrc);18}19 20u64 clocksource_mmio_readl_up(struct clocksource *c)21{22 return (u64)readl_relaxed(to_mmio_clksrc(c)->reg);23}24 25u64 clocksource_mmio_readl_down(struct clocksource *c)26{27 return ~(u64)readl_relaxed(to_mmio_clksrc(c)->reg) & c->mask;28}29 30u64 clocksource_mmio_readw_up(struct clocksource *c)31{32 return (u64)readw_relaxed(to_mmio_clksrc(c)->reg);33}34 35u64 clocksource_mmio_readw_down(struct clocksource *c)36{37 return ~(u64)readw_relaxed(to_mmio_clksrc(c)->reg) & c->mask;38}39 40/**41 * clocksource_mmio_init - Initialize a simple mmio based clocksource42 * @base: Virtual address of the clock readout register43 * @name: Name of the clocksource44 * @hz: Frequency of the clocksource in Hz45 * @rating: Rating of the clocksource46 * @bits: Number of valid bits47 * @read: One of clocksource_mmio_read*() above48 */49int __init clocksource_mmio_init(void __iomem *base, const char *name,50 unsigned long hz, int rating, unsigned bits,51 u64 (*read)(struct clocksource *))52{53 struct clocksource_mmio *cs;54 55 if (bits > 64 || bits < 16)56 return -EINVAL;57 58 cs = kzalloc(sizeof(struct clocksource_mmio), GFP_KERNEL);59 if (!cs)60 return -ENOMEM;61 62 cs->reg = base;63 cs->clksrc.name = name;64 cs->clksrc.rating = rating;65 cs->clksrc.read = read;66 cs->clksrc.mask = CLOCKSOURCE_MASK(bits);67 cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;68 69 return clocksource_register_hz(&cs->clksrc, hz);70}71