Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource/drivers/fttmr010: Merge Moxa into FTTMR010

This merges the Moxa Art timer driver into the Faraday FTTMR010
driver and replaces all Kconfig symbols to use the Faraday
driver instead. We are now so similar that the drivers can
be merged by just adding a few lines to the Faraday timer.

Differences:

- The Faraday driver explicitly sets the counter to count
upwards for the clocksource, removing the need for the
clocksource core to invert the value.

- The Faraday driver also handles sched_clock()

On the Aspeed, the counter can only count downwards, so support
the timers in downward-counting mode as well, and flag the
Aspeed to use this mode. This mode was tested on the Gemini so
I have high hopes that it'll work fine on the Aspeed as well.

After this we have one driver for all three SoCs and a generic
Faraday FTTMR010 timer driver, which is nice.

Cc: Joel Stanley <joel@jms.id.au>
Cc: Jonas Jensen <jonas.jensen@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Tested-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>

authored by

Linus Walleij and committed by
Daniel Lezcano
ec14ba1e b589da8b

+107 -302
+1 -1
arch/arm/mach-aspeed/Kconfig
··· 4 4 select SRAM 5 5 select WATCHDOG 6 6 select ASPEED_WATCHDOG 7 - select MOXART_TIMER 7 + select FTTMR010_TIMER 8 8 select MFD_SYSCON 9 9 select PINCTRL 10 10 help
+1 -1
arch/arm/mach-moxart/Kconfig
··· 4 4 select CPU_FA526 5 5 select ARM_DMA_MEM_BUFFERABLE 6 6 select FARADAY_FTINTC010 7 - select MOXART_TIMER 7 + select FTTMR010_TIMER 8 8 select GPIOLIB 9 9 select PHYLIB if NETDEVICES 10 10 help
-7
drivers/clocksource/Kconfig
··· 188 188 help 189 189 Enables support for the Atlas7 timer. 190 190 191 - config MOXART_TIMER 192 - bool "Moxart timer driver" if COMPILE_TEST 193 - depends on GENERIC_CLOCKEVENTS 194 - select CLKSRC_MMIO 195 - help 196 - Enables support for the Moxart timer. 197 - 198 191 config MXS_TIMER 199 192 bool "Mxs timer driver" if COMPILE_TEST 200 193 depends on GENERIC_CLOCKEVENTS
-1
drivers/clocksource/Makefile
··· 26 26 obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o 27 27 obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o 28 28 obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o 29 - obj-$(CONFIG_MOXART_TIMER) += moxart_timer.o 30 29 obj-$(CONFIG_MXS_TIMER) += mxs_timer.o 31 30 obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o 32 31 obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o
-256
drivers/clocksource/moxart_timer.c
··· 1 - /* 2 - * MOXA ART SoCs timer handling. 3 - * 4 - * Copyright (C) 2013 Jonas Jensen 5 - * 6 - * Jonas Jensen <jonas.jensen@gmail.com> 7 - * 8 - * This file is licensed under the terms of the GNU General Public 9 - * License version 2. This program is licensed "as is" without any 10 - * warranty of any kind, whether express or implied. 11 - */ 12 - 13 - #include <linux/clk.h> 14 - #include <linux/clockchips.h> 15 - #include <linux/interrupt.h> 16 - #include <linux/irq.h> 17 - #include <linux/irqreturn.h> 18 - #include <linux/of.h> 19 - #include <linux/of_address.h> 20 - #include <linux/of_irq.h> 21 - #include <linux/io.h> 22 - #include <linux/clocksource.h> 23 - #include <linux/bitops.h> 24 - #include <linux/slab.h> 25 - 26 - #define TIMER1_BASE 0x00 27 - #define TIMER2_BASE 0x10 28 - #define TIMER3_BASE 0x20 29 - 30 - #define REG_COUNT 0x0 /* writable */ 31 - #define REG_LOAD 0x4 32 - #define REG_MATCH1 0x8 33 - #define REG_MATCH2 0xC 34 - 35 - #define TIMER_CR 0x30 36 - #define TIMER_INTR_STATE 0x34 37 - #define TIMER_INTR_MASK 0x38 38 - 39 - /* 40 - * Moxart TIMER_CR flags: 41 - * 42 - * MOXART_CR_*_CLOCK 0: PCLK, 1: EXT1CLK 43 - * MOXART_CR_*_INT overflow interrupt enable bit 44 - */ 45 - #define MOXART_CR_1_ENABLE BIT(0) 46 - #define MOXART_CR_1_CLOCK BIT(1) 47 - #define MOXART_CR_1_INT BIT(2) 48 - #define MOXART_CR_2_ENABLE BIT(3) 49 - #define MOXART_CR_2_CLOCK BIT(4) 50 - #define MOXART_CR_2_INT BIT(5) 51 - #define MOXART_CR_3_ENABLE BIT(6) 52 - #define MOXART_CR_3_CLOCK BIT(7) 53 - #define MOXART_CR_3_INT BIT(8) 54 - #define MOXART_CR_COUNT_UP BIT(9) 55 - 56 - #define MOXART_TIMER1_ENABLE (MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE) 57 - #define MOXART_TIMER1_DISABLE (MOXART_CR_2_ENABLE) 58 - 59 - /* 60 - * The ASpeed variant of the IP block has a different layout 61 - * for the control register 62 - */ 63 - #define ASPEED_CR_1_ENABLE BIT(0) 64 - #define ASPEED_CR_1_CLOCK BIT(1) 65 - #define ASPEED_CR_1_INT BIT(2) 66 - #define ASPEED_CR_2_ENABLE BIT(4) 67 - #define ASPEED_CR_2_CLOCK BIT(5) 68 - #define ASPEED_CR_2_INT BIT(6) 69 - #define ASPEED_CR_3_ENABLE BIT(8) 70 - #define ASPEED_CR_3_CLOCK BIT(9) 71 - #define ASPEED_CR_3_INT BIT(10) 72 - 73 - #define ASPEED_TIMER1_ENABLE (ASPEED_CR_2_ENABLE | ASPEED_CR_1_ENABLE) 74 - #define ASPEED_TIMER1_DISABLE (ASPEED_CR_2_ENABLE) 75 - 76 - struct moxart_timer { 77 - void __iomem *base; 78 - unsigned int t1_disable_val; 79 - unsigned int t1_enable_val; 80 - unsigned int count_per_tick; 81 - struct clock_event_device clkevt; 82 - }; 83 - 84 - static inline struct moxart_timer *to_moxart(struct clock_event_device *evt) 85 - { 86 - return container_of(evt, struct moxart_timer, clkevt); 87 - } 88 - 89 - static inline void moxart_disable(struct clock_event_device *evt) 90 - { 91 - struct moxart_timer *timer = to_moxart(evt); 92 - 93 - writel(timer->t1_disable_val, timer->base + TIMER_CR); 94 - } 95 - 96 - static inline void moxart_enable(struct clock_event_device *evt) 97 - { 98 - struct moxart_timer *timer = to_moxart(evt); 99 - 100 - writel(timer->t1_enable_val, timer->base + TIMER_CR); 101 - } 102 - 103 - static int moxart_shutdown(struct clock_event_device *evt) 104 - { 105 - moxart_disable(evt); 106 - return 0; 107 - } 108 - 109 - static int moxart_set_oneshot(struct clock_event_device *evt) 110 - { 111 - moxart_disable(evt); 112 - writel(~0, to_moxart(evt)->base + TIMER1_BASE + REG_LOAD); 113 - return 0; 114 - } 115 - 116 - static int moxart_set_periodic(struct clock_event_device *evt) 117 - { 118 - struct moxart_timer *timer = to_moxart(evt); 119 - 120 - moxart_disable(evt); 121 - writel(timer->count_per_tick, timer->base + TIMER1_BASE + REG_LOAD); 122 - writel(0, timer->base + TIMER1_BASE + REG_MATCH1); 123 - moxart_enable(evt); 124 - return 0; 125 - } 126 - 127 - static int moxart_clkevt_next_event(unsigned long cycles, 128 - struct clock_event_device *evt) 129 - { 130 - struct moxart_timer *timer = to_moxart(evt); 131 - u32 u; 132 - 133 - moxart_disable(evt); 134 - 135 - u = readl(timer->base + TIMER1_BASE + REG_COUNT) - cycles; 136 - writel(u, timer->base + TIMER1_BASE + REG_MATCH1); 137 - 138 - moxart_enable(evt); 139 - 140 - return 0; 141 - } 142 - 143 - static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) 144 - { 145 - struct clock_event_device *evt = dev_id; 146 - evt->event_handler(evt); 147 - return IRQ_HANDLED; 148 - } 149 - 150 - static int __init moxart_timer_init(struct device_node *node) 151 - { 152 - int ret, irq; 153 - unsigned long pclk; 154 - struct clk *clk; 155 - struct moxart_timer *timer; 156 - 157 - timer = kzalloc(sizeof(*timer), GFP_KERNEL); 158 - if (!timer) 159 - return -ENOMEM; 160 - 161 - timer->base = of_iomap(node, 0); 162 - if (!timer->base) { 163 - pr_err("%s: of_iomap failed\n", node->full_name); 164 - ret = -ENXIO; 165 - goto out_free; 166 - } 167 - 168 - irq = irq_of_parse_and_map(node, 0); 169 - if (irq <= 0) { 170 - pr_err("%s: irq_of_parse_and_map failed\n", node->full_name); 171 - ret = -EINVAL; 172 - goto out_unmap; 173 - } 174 - 175 - clk = of_clk_get(node, 0); 176 - if (IS_ERR(clk)) { 177 - pr_err("%s: of_clk_get failed\n", node->full_name); 178 - ret = PTR_ERR(clk); 179 - goto out_unmap; 180 - } 181 - 182 - pclk = clk_get_rate(clk); 183 - 184 - if (of_device_is_compatible(node, "moxa,moxart-timer")) { 185 - timer->t1_enable_val = MOXART_TIMER1_ENABLE; 186 - timer->t1_disable_val = MOXART_TIMER1_DISABLE; 187 - } else if (of_device_is_compatible(node, "aspeed,ast2400-timer")) { 188 - timer->t1_enable_val = ASPEED_TIMER1_ENABLE; 189 - timer->t1_disable_val = ASPEED_TIMER1_DISABLE; 190 - } else { 191 - pr_err("%s: unknown platform\n", node->full_name); 192 - ret = -EINVAL; 193 - goto out_unmap; 194 - } 195 - 196 - timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ); 197 - 198 - timer->clkevt.name = node->name; 199 - timer->clkevt.rating = 200; 200 - timer->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | 201 - CLOCK_EVT_FEAT_ONESHOT; 202 - timer->clkevt.set_state_shutdown = moxart_shutdown; 203 - timer->clkevt.set_state_periodic = moxart_set_periodic; 204 - timer->clkevt.set_state_oneshot = moxart_set_oneshot; 205 - timer->clkevt.tick_resume = moxart_set_oneshot; 206 - timer->clkevt.set_next_event = moxart_clkevt_next_event; 207 - timer->clkevt.cpumask = cpumask_of(0); 208 - timer->clkevt.irq = irq; 209 - 210 - ret = clocksource_mmio_init(timer->base + TIMER2_BASE + REG_COUNT, 211 - "moxart_timer", pclk, 200, 32, 212 - clocksource_mmio_readl_down); 213 - if (ret) { 214 - pr_err("%s: clocksource_mmio_init failed\n", node->full_name); 215 - goto out_unmap; 216 - } 217 - 218 - ret = request_irq(irq, moxart_timer_interrupt, IRQF_TIMER, 219 - node->name, &timer->clkevt); 220 - if (ret) { 221 - pr_err("%s: setup_irq failed\n", node->full_name); 222 - goto out_unmap; 223 - } 224 - 225 - /* Clear match registers */ 226 - writel(0, timer->base + TIMER1_BASE + REG_MATCH1); 227 - writel(0, timer->base + TIMER1_BASE + REG_MATCH2); 228 - writel(0, timer->base + TIMER2_BASE + REG_MATCH1); 229 - writel(0, timer->base + TIMER2_BASE + REG_MATCH2); 230 - 231 - /* 232 - * Start timer 2 rolling as our main wall clock source, keep timer 1 233 - * disabled 234 - */ 235 - writel(0, timer->base + TIMER_CR); 236 - writel(~0, timer->base + TIMER2_BASE + REG_LOAD); 237 - writel(timer->t1_disable_val, timer->base + TIMER_CR); 238 - 239 - /* 240 - * documentation is not publicly available: 241 - * min_delta / max_delta obtained by trial-and-error, 242 - * max_delta 0xfffffffe should be ok because count 243 - * register size is u32 244 - */ 245 - clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe); 246 - 247 - return 0; 248 - 249 - out_unmap: 250 - iounmap(timer->base); 251 - out_free: 252 - kfree(timer); 253 - return ret; 254 - } 255 - CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init); 256 - CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", moxart_timer_init);
+105 -36
drivers/clocksource/timer-fttmr010.c
··· 50 50 #define TIMER_2_CR_UPDOWN BIT(10) 51 51 #define TIMER_3_CR_UPDOWN BIT(11) 52 52 53 + /* 54 + * The Aspeed AST2400 moves bits around in the control register 55 + * and lacks bits for setting the timer to count upwards. 56 + */ 57 + #define TIMER_1_CR_ASPEED_ENABLE BIT(0) 58 + #define TIMER_1_CR_ASPEED_CLOCK BIT(1) 59 + #define TIMER_1_CR_ASPEED_INT BIT(2) 60 + #define TIMER_2_CR_ASPEED_ENABLE BIT(4) 61 + #define TIMER_2_CR_ASPEED_CLOCK BIT(5) 62 + #define TIMER_2_CR_ASPEED_INT BIT(6) 63 + #define TIMER_3_CR_ASPEED_ENABLE BIT(8) 64 + #define TIMER_3_CR_ASPEED_CLOCK BIT(9) 65 + #define TIMER_3_CR_ASPEED_INT BIT(10) 66 + 53 67 #define TIMER_1_INT_MATCH1 BIT(0) 54 68 #define TIMER_1_INT_MATCH2 BIT(1) 55 69 #define TIMER_1_INT_OVERFLOW BIT(2) ··· 78 64 struct fttmr010 { 79 65 void __iomem *base; 80 66 unsigned int tick_rate; 67 + bool count_down; 68 + u32 t1_enable_val; 81 69 struct clock_event_device clkevt; 82 70 }; 83 71 ··· 93 77 94 78 static u64 notrace fttmr010_read_sched_clock(void) 95 79 { 80 + if (local_fttmr->count_down) 81 + return ~readl(local_fttmr->base + TIMER2_COUNT); 96 82 return readl(local_fttmr->base + TIMER2_COUNT); 97 83 } 98 84 ··· 104 86 struct fttmr010 *fttmr010 = to_fttmr010(evt); 105 87 u32 cr; 106 88 107 - /* Setup the match register */ 89 + /* Stop */ 90 + cr = readl(fttmr010->base + TIMER_CR); 91 + cr &= ~fttmr010->t1_enable_val; 92 + writel(cr, fttmr010->base + TIMER_CR); 93 + 94 + /* Setup the match register forward/backward in time */ 108 95 cr = readl(fttmr010->base + TIMER1_COUNT); 109 - writel(cr + cycles, fttmr010->base + TIMER1_MATCH1); 110 - if (readl(fttmr010->base + TIMER1_COUNT) - cr > cycles) 111 - return -ETIME; 96 + if (fttmr010->count_down) 97 + cr -= cycles; 98 + else 99 + cr += cycles; 100 + writel(cr, fttmr010->base + TIMER1_MATCH1); 101 + 102 + /* Start */ 103 + cr = readl(fttmr010->base + TIMER_CR); 104 + cr |= fttmr010->t1_enable_val; 105 + writel(cr, fttmr010->base + TIMER_CR); 112 106 113 107 return 0; 114 108 } ··· 130 100 struct fttmr010 *fttmr010 = to_fttmr010(evt); 131 101 u32 cr; 132 102 133 - /* Stop timer and interrupt. */ 103 + /* Stop */ 134 104 cr = readl(fttmr010->base + TIMER_CR); 135 - cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); 105 + cr &= ~fttmr010->t1_enable_val; 136 106 writel(cr, fttmr010->base + TIMER_CR); 137 107 138 108 return 0; ··· 143 113 struct fttmr010 *fttmr010 = to_fttmr010(evt); 144 114 u32 cr; 145 115 146 - /* Stop timer and interrupt. */ 116 + /* Stop */ 147 117 cr = readl(fttmr010->base + TIMER_CR); 148 - cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); 118 + cr &= ~fttmr010->t1_enable_val; 149 119 writel(cr, fttmr010->base + TIMER_CR); 150 120 151 - /* Setup counter start from 0 */ 121 + /* Setup counter start from 0 or ~0 */ 152 122 writel(0, fttmr010->base + TIMER1_COUNT); 153 - writel(0, fttmr010->base + TIMER1_LOAD); 123 + if (fttmr010->count_down) 124 + writel(~0, fttmr010->base + TIMER1_LOAD); 125 + else 126 + writel(0, fttmr010->base + TIMER1_LOAD); 154 127 155 128 /* Enable interrupt */ 156 129 cr = readl(fttmr010->base + TIMER_INTR_MASK); 157 130 cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2); 158 131 cr |= TIMER_1_INT_MATCH1; 159 132 writel(cr, fttmr010->base + TIMER_INTR_MASK); 160 - 161 - /* Start the timer */ 162 - cr = readl(fttmr010->base + TIMER_CR); 163 - cr |= TIMER_1_CR_ENABLE; 164 - writel(cr, fttmr010->base + TIMER_CR); 165 133 166 134 return 0; 167 135 } ··· 170 142 u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ); 171 143 u32 cr; 172 144 173 - /* Stop timer and interrupt */ 145 + /* Stop */ 174 146 cr = readl(fttmr010->base + TIMER_CR); 175 - cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); 147 + cr &= ~fttmr010->t1_enable_val; 176 148 writel(cr, fttmr010->base + TIMER_CR); 177 149 178 - /* Setup timer to fire at 1/HT intervals. */ 179 - cr = 0xffffffff - (period - 1); 180 - writel(cr, fttmr010->base + TIMER1_COUNT); 181 - writel(cr, fttmr010->base + TIMER1_LOAD); 150 + /* Setup timer to fire at 1/HZ intervals. */ 151 + if (fttmr010->count_down) { 152 + writel(period, fttmr010->base + TIMER1_LOAD); 153 + writel(0, fttmr010->base + TIMER1_MATCH1); 154 + } else { 155 + cr = 0xffffffff - (period - 1); 156 + writel(cr, fttmr010->base + TIMER1_COUNT); 157 + writel(cr, fttmr010->base + TIMER1_LOAD); 182 158 183 - /* enable interrupt on overflow */ 184 - cr = readl(fttmr010->base + TIMER_INTR_MASK); 185 - cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2); 186 - cr |= TIMER_1_INT_OVERFLOW; 187 - writel(cr, fttmr010->base + TIMER_INTR_MASK); 159 + /* Enable interrupt on overflow */ 160 + cr = readl(fttmr010->base + TIMER_INTR_MASK); 161 + cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2); 162 + cr |= TIMER_1_INT_OVERFLOW; 163 + writel(cr, fttmr010->base + TIMER_INTR_MASK); 164 + } 188 165 189 166 /* Start the timer */ 190 167 cr = readl(fttmr010->base + TIMER_CR); 191 - cr |= TIMER_1_CR_ENABLE; 192 - cr |= TIMER_1_CR_INT; 168 + cr |= fttmr010->t1_enable_val; 193 169 writel(cr, fttmr010->base + TIMER_CR); 194 170 195 171 return 0; ··· 213 181 static int __init fttmr010_timer_init(struct device_node *np) 214 182 { 215 183 struct fttmr010 *fttmr010; 184 + bool is_ast2400; 216 185 int irq; 217 186 struct clk *clk; 218 187 int ret; 188 + u32 val; 219 189 220 190 /* 221 191 * These implementations require a clock reference. ··· 257 223 } 258 224 259 225 /* 226 + * The Aspeed AST2400 moves bits around in the control register, 227 + * otherwise it works the same. 228 + */ 229 + is_ast2400 = of_device_is_compatible(np, "aspeed,ast2400-timer"); 230 + if (is_ast2400) { 231 + fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE | 232 + TIMER_1_CR_ASPEED_INT; 233 + /* Downward not available */ 234 + fttmr010->count_down = true; 235 + } else { 236 + fttmr010->t1_enable_val = TIMER_1_CR_ENABLE | TIMER_1_CR_INT; 237 + } 238 + 239 + /* 260 240 * Reset the interrupt mask and status 261 241 */ 262 242 writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK); 263 243 writel(0, fttmr010->base + TIMER_INTR_STATE); 264 - /* Enable timer 1 count up, timer 2 count up */ 265 - writel((TIMER_1_CR_UPDOWN | TIMER_2_CR_ENABLE | TIMER_2_CR_UPDOWN), 266 - fttmr010->base + TIMER_CR); 244 + 245 + /* 246 + * Enable timer 1 count up, timer 2 count up, except on Aspeed, 247 + * where everything just counts down. 248 + */ 249 + if (is_ast2400) 250 + val = TIMER_2_CR_ASPEED_ENABLE; 251 + else { 252 + val = TIMER_2_CR_ENABLE; 253 + if (!fttmr010->count_down) 254 + val |= TIMER_1_CR_UPDOWN | TIMER_2_CR_UPDOWN; 255 + } 256 + writel(val, fttmr010->base + TIMER_CR); 267 257 268 258 /* 269 259 * Setup free-running clocksource timer (interrupts ··· 295 237 */ 296 238 local_fttmr = fttmr010; 297 239 writel(0, fttmr010->base + TIMER2_COUNT); 298 - writel(0, fttmr010->base + TIMER2_LOAD); 299 240 writel(0, fttmr010->base + TIMER2_MATCH1); 300 241 writel(0, fttmr010->base + TIMER2_MATCH2); 301 - clocksource_mmio_init(fttmr010->base + TIMER2_COUNT, 302 - "FTTMR010-TIMER2", 303 - fttmr010->tick_rate, 304 - 300, 32, clocksource_mmio_readl_up); 242 + 243 + if (fttmr010->count_down) { 244 + writel(~0, fttmr010->base + TIMER2_LOAD); 245 + clocksource_mmio_init(fttmr010->base + TIMER2_COUNT, 246 + "FTTMR010-TIMER2", 247 + fttmr010->tick_rate, 248 + 300, 32, clocksource_mmio_readl_down); 249 + } else { 250 + writel(0, fttmr010->base + TIMER2_LOAD); 251 + clocksource_mmio_init(fttmr010->base + TIMER2_COUNT, 252 + "FTTMR010-TIMER2", 253 + fttmr010->tick_rate, 254 + 300, 32, clocksource_mmio_readl_up); 255 + } 305 256 sched_clock_register(fttmr010_read_sched_clock, 32, 306 257 fttmr010->tick_rate); 307 258 ··· 357 290 } 358 291 CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init); 359 292 CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init); 293 + CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", fttmr010_timer_init); 294 + CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", fttmr010_timer_init);