Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Generic MMIO clocksource support
0004  */
0005 #include <linux/clocksource.h>
0006 #include <linux/errno.h>
0007 #include <linux/init.h>
0008 #include <linux/slab.h>
0009 
0010 struct clocksource_mmio {
0011     void __iomem *reg;
0012     struct clocksource clksrc;
0013 };
0014 
0015 static inline struct clocksource_mmio *to_mmio_clksrc(struct clocksource *c)
0016 {
0017     return container_of(c, struct clocksource_mmio, clksrc);
0018 }
0019 
0020 u64 clocksource_mmio_readl_up(struct clocksource *c)
0021 {
0022     return (u64)readl_relaxed(to_mmio_clksrc(c)->reg);
0023 }
0024 
0025 u64 clocksource_mmio_readl_down(struct clocksource *c)
0026 {
0027     return ~(u64)readl_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
0028 }
0029 
0030 u64 clocksource_mmio_readw_up(struct clocksource *c)
0031 {
0032     return (u64)readw_relaxed(to_mmio_clksrc(c)->reg);
0033 }
0034 
0035 u64 clocksource_mmio_readw_down(struct clocksource *c)
0036 {
0037     return ~(u64)readw_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
0038 }
0039 
0040 /**
0041  * clocksource_mmio_init - Initialize a simple mmio based clocksource
0042  * @base:   Virtual address of the clock readout register
0043  * @name:   Name of the clocksource
0044  * @hz:     Frequency of the clocksource in Hz
0045  * @rating: Rating of the clocksource
0046  * @bits:   Number of valid bits
0047  * @read:   One of clocksource_mmio_read*() above
0048  */
0049 int __init clocksource_mmio_init(void __iomem *base, const char *name,
0050     unsigned long hz, int rating, unsigned bits,
0051     u64 (*read)(struct clocksource *))
0052 {
0053     struct clocksource_mmio *cs;
0054 
0055     if (bits > 64 || bits < 16)
0056         return -EINVAL;
0057 
0058     cs = kzalloc(sizeof(struct clocksource_mmio), GFP_KERNEL);
0059     if (!cs)
0060         return -ENOMEM;
0061 
0062     cs->reg = base;
0063     cs->clksrc.name = name;
0064     cs->clksrc.rating = rating;
0065     cs->clksrc.read = read;
0066     cs->clksrc.mask = CLOCKSOURCE_MASK(bits);
0067     cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
0068 
0069     return clocksource_register_hz(&cs->clksrc, hz);
0070 }