| .. | .. |
|---|
| 38 | 38 | #define TIMER_CR (0x30) |
|---|
| 39 | 39 | |
|---|
| 40 | 40 | /* |
|---|
| 41 | + * Control register set to clear for ast2600 only. |
|---|
| 42 | + */ |
|---|
| 43 | +#define AST2600_TIMER_CR_CLR (0x3c) |
|---|
| 44 | + |
|---|
| 45 | +/* |
|---|
| 41 | 46 | * Control register (TMC30) bit fields for fttmr010/gemini/moxart timers. |
|---|
| 42 | 47 | */ |
|---|
| 43 | 48 | #define TIMER_1_CR_ENABLE BIT(0) |
|---|
| .. | .. |
|---|
| 97 | 102 | bool is_aspeed; |
|---|
| 98 | 103 | u32 t1_enable_val; |
|---|
| 99 | 104 | struct clock_event_device clkevt; |
|---|
| 105 | + int (*timer_shutdown)(struct clock_event_device *evt); |
|---|
| 100 | 106 | #ifdef CONFIG_ARM |
|---|
| 101 | 107 | struct delay_timer delay_timer; |
|---|
| 102 | 108 | #endif |
|---|
| .. | .. |
|---|
| 140 | 146 | u32 cr; |
|---|
| 141 | 147 | |
|---|
| 142 | 148 | /* Stop */ |
|---|
| 143 | | - cr = readl(fttmr010->base + TIMER_CR); |
|---|
| 144 | | - cr &= ~fttmr010->t1_enable_val; |
|---|
| 145 | | - writel(cr, fttmr010->base + TIMER_CR); |
|---|
| 149 | + fttmr010->timer_shutdown(evt); |
|---|
| 146 | 150 | |
|---|
| 147 | 151 | if (fttmr010->is_aspeed) { |
|---|
| 148 | 152 | /* |
|---|
| .. | .. |
|---|
| 160 | 164 | cr = readl(fttmr010->base + TIMER_CR); |
|---|
| 161 | 165 | cr |= fttmr010->t1_enable_val; |
|---|
| 162 | 166 | writel(cr, fttmr010->base + TIMER_CR); |
|---|
| 167 | + |
|---|
| 168 | + return 0; |
|---|
| 169 | +} |
|---|
| 170 | + |
|---|
| 171 | +static int ast2600_timer_shutdown(struct clock_event_device *evt) |
|---|
| 172 | +{ |
|---|
| 173 | + struct fttmr010 *fttmr010 = to_fttmr010(evt); |
|---|
| 174 | + |
|---|
| 175 | + /* Stop */ |
|---|
| 176 | + writel(fttmr010->t1_enable_val, fttmr010->base + AST2600_TIMER_CR_CLR); |
|---|
| 163 | 177 | |
|---|
| 164 | 178 | return 0; |
|---|
| 165 | 179 | } |
|---|
| .. | .. |
|---|
| 183 | 197 | u32 cr; |
|---|
| 184 | 198 | |
|---|
| 185 | 199 | /* Stop */ |
|---|
| 186 | | - cr = readl(fttmr010->base + TIMER_CR); |
|---|
| 187 | | - cr &= ~fttmr010->t1_enable_val; |
|---|
| 188 | | - writel(cr, fttmr010->base + TIMER_CR); |
|---|
| 200 | + fttmr010->timer_shutdown(evt); |
|---|
| 189 | 201 | |
|---|
| 190 | 202 | /* Setup counter start from 0 or ~0 */ |
|---|
| 191 | 203 | writel(0, fttmr010->base + TIMER1_COUNT); |
|---|
| .. | .. |
|---|
| 211 | 223 | u32 cr; |
|---|
| 212 | 224 | |
|---|
| 213 | 225 | /* Stop */ |
|---|
| 214 | | - cr = readl(fttmr010->base + TIMER_CR); |
|---|
| 215 | | - cr &= ~fttmr010->t1_enable_val; |
|---|
| 216 | | - writel(cr, fttmr010->base + TIMER_CR); |
|---|
| 226 | + fttmr010->timer_shutdown(evt); |
|---|
| 217 | 227 | |
|---|
| 218 | 228 | /* Setup timer to fire at 1/HZ intervals. */ |
|---|
| 219 | 229 | if (fttmr010->is_aspeed) { |
|---|
| .. | .. |
|---|
| 249 | 259 | return IRQ_HANDLED; |
|---|
| 250 | 260 | } |
|---|
| 251 | 261 | |
|---|
| 252 | | -static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) |
|---|
| 262 | +static irqreturn_t ast2600_timer_interrupt(int irq, void *dev_id) |
|---|
| 263 | +{ |
|---|
| 264 | + struct clock_event_device *evt = dev_id; |
|---|
| 265 | + struct fttmr010 *fttmr010 = to_fttmr010(evt); |
|---|
| 266 | + |
|---|
| 267 | + writel(0x1, fttmr010->base + TIMER_INTR_STATE); |
|---|
| 268 | + |
|---|
| 269 | + evt->event_handler(evt); |
|---|
| 270 | + return IRQ_HANDLED; |
|---|
| 271 | +} |
|---|
| 272 | + |
|---|
| 273 | +static int __init fttmr010_common_init(struct device_node *np, |
|---|
| 274 | + bool is_aspeed, |
|---|
| 275 | + int (*timer_shutdown)(struct clock_event_device *), |
|---|
| 276 | + irq_handler_t irq_handler) |
|---|
| 253 | 277 | { |
|---|
| 254 | 278 | struct fttmr010 *fttmr010; |
|---|
| 255 | 279 | int irq; |
|---|
| .. | .. |
|---|
| 350 | 374 | fttmr010->tick_rate); |
|---|
| 351 | 375 | } |
|---|
| 352 | 376 | |
|---|
| 377 | + fttmr010->timer_shutdown = timer_shutdown; |
|---|
| 378 | + |
|---|
| 353 | 379 | /* |
|---|
| 354 | 380 | * Setup clockevent timer (interrupt-driven) on timer 1. |
|---|
| 355 | 381 | */ |
|---|
| .. | .. |
|---|
| 357 | 383 | writel(0, fttmr010->base + TIMER1_LOAD); |
|---|
| 358 | 384 | writel(0, fttmr010->base + TIMER1_MATCH1); |
|---|
| 359 | 385 | writel(0, fttmr010->base + TIMER1_MATCH2); |
|---|
| 360 | | - ret = request_irq(irq, fttmr010_timer_interrupt, IRQF_TIMER, |
|---|
| 386 | + ret = request_irq(irq, irq_handler, IRQF_TIMER, |
|---|
| 361 | 387 | "FTTMR010-TIMER1", &fttmr010->clkevt); |
|---|
| 362 | 388 | if (ret) { |
|---|
| 363 | 389 | pr_err("FTTMR010-TIMER1 no IRQ\n"); |
|---|
| .. | .. |
|---|
| 370 | 396 | fttmr010->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | |
|---|
| 371 | 397 | CLOCK_EVT_FEAT_ONESHOT; |
|---|
| 372 | 398 | fttmr010->clkevt.set_next_event = fttmr010_timer_set_next_event; |
|---|
| 373 | | - fttmr010->clkevt.set_state_shutdown = fttmr010_timer_shutdown; |
|---|
| 399 | + fttmr010->clkevt.set_state_shutdown = fttmr010->timer_shutdown; |
|---|
| 374 | 400 | fttmr010->clkevt.set_state_periodic = fttmr010_timer_set_periodic; |
|---|
| 375 | 401 | fttmr010->clkevt.set_state_oneshot = fttmr010_timer_set_oneshot; |
|---|
| 376 | | - fttmr010->clkevt.tick_resume = fttmr010_timer_shutdown; |
|---|
| 402 | + fttmr010->clkevt.tick_resume = fttmr010->timer_shutdown; |
|---|
| 377 | 403 | fttmr010->clkevt.cpumask = cpumask_of(0); |
|---|
| 378 | 404 | fttmr010->clkevt.irq = irq; |
|---|
| 379 | 405 | clockevents_config_and_register(&fttmr010->clkevt, |
|---|
| .. | .. |
|---|
| 404 | 430 | return ret; |
|---|
| 405 | 431 | } |
|---|
| 406 | 432 | |
|---|
| 433 | +static __init int ast2600_timer_init(struct device_node *np) |
|---|
| 434 | +{ |
|---|
| 435 | + return fttmr010_common_init(np, true, |
|---|
| 436 | + ast2600_timer_shutdown, |
|---|
| 437 | + ast2600_timer_interrupt); |
|---|
| 438 | +} |
|---|
| 439 | + |
|---|
| 407 | 440 | static __init int aspeed_timer_init(struct device_node *np) |
|---|
| 408 | 441 | { |
|---|
| 409 | | - return fttmr010_common_init(np, true); |
|---|
| 442 | + return fttmr010_common_init(np, true, |
|---|
| 443 | + fttmr010_timer_shutdown, |
|---|
| 444 | + fttmr010_timer_interrupt); |
|---|
| 410 | 445 | } |
|---|
| 411 | 446 | |
|---|
| 412 | 447 | static __init int fttmr010_timer_init(struct device_node *np) |
|---|
| 413 | 448 | { |
|---|
| 414 | | - return fttmr010_common_init(np, false); |
|---|
| 449 | + return fttmr010_common_init(np, false, |
|---|
| 450 | + fttmr010_timer_shutdown, |
|---|
| 451 | + fttmr010_timer_interrupt); |
|---|
| 415 | 452 | } |
|---|
| 416 | 453 | |
|---|
| 417 | 454 | TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init); |
|---|
| .. | .. |
|---|
| 419 | 456 | TIMER_OF_DECLARE(moxart, "moxa,moxart-timer", fttmr010_timer_init); |
|---|
| 420 | 457 | TIMER_OF_DECLARE(ast2400, "aspeed,ast2400-timer", aspeed_timer_init); |
|---|
| 421 | 458 | TIMER_OF_DECLARE(ast2500, "aspeed,ast2500-timer", aspeed_timer_init); |
|---|
| 459 | +TIMER_OF_DECLARE(ast2600, "aspeed,ast2600-timer", ast2600_timer_init); |
|---|