1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12/* @AUTHOR(akroh@ertos.nicta.com.au) */ 13 14#include <stdio.h> 15#include <assert.h> 16#include <errno.h> 17#include <stdlib.h> 18 19#include <utils/util.h> 20 21#include <platsupport/plat/timer.h> 22 23#define XOTMR_FIN 19200000UL 24#define SLPTMR_FIN 32768UL 25static inline uint64_t 26get_tcxo_hz(void) 27{ 28 return 7 * 1000 * 1000; 29} 30 31static inline uint64_t 32get_xo_hz(void) 33{ 34 return XOTMR_FIN; 35} 36 37static inline uint64_t 38get_slp_hz(void) 39{ 40 return SLPTMR_FIN; 41} 42 43/** Timer map offsets **/ 44#define KPSSSECURE_OFFSET 0x000 45#define KPSSGPT0_OFFSET 0x004 46#define KPSSGPT1_OFFSET 0x014 47#define KPSSDGT_OFFSET 0x024 48#define KPSSWDT0_OFFSET 0x038 49#define KPSSWDT1_OFFSET 0x060 50#define KPSSSTAT_OFFSET 0x088 51 52#define GSSSECURE_OFFSET KPSSSECURE_OFFSET 53#define GSSGPT0_OFFSET KPSSGPT0_OFFSET 54#define GSSGPT1_OFFSET KPSSGPT1_OFFSET 55#define GSSDGT_OFFSET KPSSDGT_OFFSET 56#define GSSWDT0_OFFSET KPSSWDT0_OFFSET 57#define GSSWDT1_OFFSET KPSSWDT1_OFFSET 58#define GSSSTAT_OFFSET KPSSSTAT_OFFSET 59 60#define PPSSXOTMR0_OFFSET 0x800 61#define PPSSXOTMR1_OFFSET 0x818 62 63#define PPSSTMR0_OFFSET 0x000 64#define PPSSTMR1_OFFSET 0x018 65#define PPSSWDT_OFFSET 0x800 66#define PPSSCLKCTNTL_OFFSET 0x824 67 68#define RPMGPT0_OFFSET 0x000 69#define RPMGPT0_CLK_CTL 0x010 70#define RPMGPT1_OFFSET 0x040 71#define RPMWDT_OFFSET 0x060 72#define RPMTMRSTS_OFFSET 0x100 73 74/* Clock control Bitmaps */ 75#define PPSSCLKCTNTL_WDGON (1U << 1) 76#define PPSSCLKCTNTL_SLPON (1U << 1) 77 78#define TMRSTS(x, i) ((x) << (8 * i)) 79#define TMRSTS_WR_PEND(i) TMRSTS(1U << 3, i) 80#define TMRSTS_CLR_PEND(i) TMRSTS(1U << 2, i) 81#define TMRSTS_CLR_ON_MTCH_EN(i) TMRSTS(1U << 1, i) 82#define TMRSTS_EN(i) TMRSTS(1U << 0, i) 83#define TMRSTS_PEND(i) (TMRSTS_WR_PEND(i) | TMRSTS_CLR_PEND(i)) 84 85#define RPMTMRSTS_WDOG_EN (1U << 17) 86#define RPMTMRSTS_WDOG_UNMASKED_INT_EN (1U << 16) 87#define RPMTMRSTS_TMR1_WR_PEND TMRSTS_WR_PEND(1) 88#define RPMTMRSTS_TMR1_CLR_PEND TMRSTS_CLR_PEND(1) 89#define RPMTMRSTS_TMR1_CLK_ON_MTCH TMRSTS_CLR_ON_MTCH(1) 90#define RPMTMRSTS_TMR1_PEND TMRSTS_PEND(1) 91#define RPMTMRSTS_TMR1_EN TMRSTS_EN(1) 92#define RPMTMRSTS_TMR0_WR_PEND TMRSTS_WR_PEND(0) 93#define RPMTMRSTS_TMR0_CLR_PEND TMRSTS_CLR_PEND(0) 94#define RPMTMRSTS_TMR0_CLR_ON_MTCH TMRSTS_CLR_ON_MTCH(0) 95#define RPMTMRSTS_TMR0_EN TMRSTS_EN(0) 96#define RPMTMRSTS_TMR0_PEND TMRSTS_PEND(0) 97 98#define KPSSGPTSTS_TMR1_WR_PEND TMRSTS_WR_PEND(1) 99#define KPSSGPTSTS_TMR1_CLR_PEND TMRSTS_CLR_PEND(1) 100#define KPSSGPTSTS_TMR1_CLK_ON_MTCH TMRSTS_CLR_ON_MTCH(1) 101#define KPSSGPTSTS_TMR1_EN TMRSTS_EN(1) 102#define KPSSGPTSTS_TMR1_PEND TMRSTS_PEND(1) 103#define KPSSGPTSTS_TMR0_WR_PEND TMRSTS_WR_PEND(0) 104#define KPSSGPTSTS_TMR0_CLR_PEND TMRSTS_CLR_PEND(0) 105#define KPSSGPTSTS_TMR0_CLR_ON_MTCH TMRSTS_CLR_ON_MTCH(0) 106#define KPSSGPTSTS_TMR0_EN TMRSTS_EN(0) 107#define KPSSGPTSTS_TMR0_PEND TMRSTS_PEND(0) 108 109#define GSSGPTSTS_TMR1_WR_PEND TMRSTS_WR_PEND(1) 110#define GSSGPTSTS_TMR1_CLR_PEND TMRSTS_CLR_PEND(1) 111#define GSSGPTSTS_TMR1_CLK_ON_MTCH TMRSTS_CLR_ON_MTCH(1) 112#define GSSGPTSTS_TMR1_EN TMRSTS_EN(1) 113#define GSSGPTSTS_TMR1_PEND TMRSTS_PEND(1) 114#define GSSGPTSTS_TMR0_WR_PEND TMRSTS_WR_PEND(0) 115#define GSSGPTSTS_TMR0_CLR_PEND TMRSTS_CLR_PEND(0) 116#define GSSGPTSTS_TMR0_CLR_ON_MTCH TMRSTS_CLR_ON_MTCH(0) 117#define GSSGPTSTS_TMR0_EN TMRSTS_EN(0) 118#define GSSGPTSTS_TMR0_PEND TMRSTS_PEND(0) 119 120#define RPMGPT0_DIV(x) ((x) - 1) 121#define RPMGPT0_DIV4 RPMGPT0_DIV(4) 122#define RPMGPT0_DIV3 RPMGPT0_DIV(3) 123#define RPMGPT0_DIV2 RPMGPT0_DIV(2) 124#define RPMGPT0_DIV1 RPMGPT0_DIV(1) 125 126#define TMR_CTRL_ON (1U << 5) 127#define TMR_CTRL_EN (1U << 4) 128#define TMR_CTRL_MODE(x) ((x) << 2) 129#define TMR_CTRL_MODE_FREE_RUN TMR_CTRL_MODE(0x0) 130#define TMR_CTRL_MODE_ONE_SHOT TMR_CTRL_MODE(0x1) 131#define TMR_CTRL_MODE_PERIODIC TMR_CTRL_MODE(0x2) 132#define TMR_CTRL_MODE_MASK TMR_CTRL_MODE(0x3) 133#define TMR_CTRL_PRESCALE(x) ((x) << 0) 134#define TMR_CTRL_PRESCALE_DIV32 TMR_CTRL_PRESCALE(0x0) 135#define TMR_CTRL_PRESCALE_DIV8 TMR_CTRL_PRESCALE(0x1) 136#define TMR_CTRL_PRESCALE_DIV4 TMR_CTRL_PRESCALE(0x2) 137#define TMR_CTRL_PRESCALE_DIV2 TMR_CTRL_PRESCALE(0x3) 138#define TMR_CTRL_PRESCALE_MASK TMR_CTRL_PRESCALE(0x3) 139 140#define TMR_STAT_MATCH_UPDATE (1U << 4) 141#define TMR_STAT_COUNT_UPDATE (1U << 3) 142#define TMR_STAT_CONTROL_UPDATE (1U << 2) 143#define TMR_STAT_CLR_INT_UPDATE (1U << 1) 144#define TMR_STAT_CLK_CNT_UPDATE (1U << 0) 145 146/** General bitmaps **/ 147#define DGTTMR_EN_CLR_ON_MTCH_EN (1U << 1) 148#define DGTTMR_EN_EN (1U << 0) 149#define DGTTMR_CLK_CTRL(x) ((x) << 0) 150#define DGTTMR_CLK_CTRL_DIV1 DGTTMR_CLK_CTRL(0x0) 151#define DGTTMR_CLK_CTRL_DIV2 DGTTMR_CLK_CTRL(0x1) 152#define DGTTMR_CLK_CTRL_DIV3 DGTTMR_CLK_CTRL(0x2) 153#define DGTTMR_CLK_CTRL_DIV4 DGTTMR_CLK_CTRL(0x3) 154#define DGTTMR_CLK_CTRL_MASK DGTTMR_CLK_CTRL(0x3) 155 156#define WDTRESET (1U << 0) 157#define WDTFREEZE (1U << 0) 158#define WDTINTEN_EN (1U << 1) 159#define WDTINTEN_UNMASKED_INTEN (1U << 0) 160#define WDTSTAT_COUNT(x) ((x) << 3) 161#define WDTSTAT_GETCOUNT(x) ((x) >> 3) 162#define WDTSTAT_CNT_RESET_STAT (1U << 2) 163#define WDTSTAT_FROZEN(x) (1U << 1) 164#define WDTSTAT_EXPIRED(x) (1U << 0) 165#define WDTEXP_SYNC (1U << 14) 166#define WDTEXP_DATA(x) (((x) & 0x3fff) << 0) 167#define WDTEXP_GETDATA(x) (((x) >> 0) & 0x3fff) 168#define WDTBARK_SYNC (1U << 14) 169#define WDTBARK_DATA(x) (((x) & 0x3fff) << 0) 170#define WDTBARK_GETDATA(x) (((x) >> 0) & 0x3fff) 171#define WDTTESTLOADSTAT_SYNC (1U << 0) 172#define WDTTESTLOAD_LOAD (1U << 0) 173#define WDTTEST_SYNC (1U << 14) 174#define WDTTEST_LOAD(x) (((x) & 0x3fff) << 0) 175#define WDTTEST_GETLOAD(x) (((x) >> 0) & 0x3fff) 176 177#define GPTEN_CLR_ON_MTCH_EN (1U << 1) 178#define GPTEN_EN (1U << 0) 179 180/** Helpers **/ 181#define TIMER_VADDR_OFFSET(base, offset) ((void*)((uintptr_t)base + offset)) 182#define TIMER_REG(base, offset) *(volatile uint32_t *)TIMER_VADDR_OFFSET(base, offset) 183 184/** Timer register maps **/ 185struct tmr_regs { 186 uint32_t match; /* +0x00 */ 187 uint32_t count; /* +0x04 */ 188 uint32_t control; /* +0x08 */ 189 uint32_t clear_int; /* +0x0C */ 190 uint32_t clear_cnt; /* +0x10 */ 191 uint32_t status; /* +0x14 */ 192}; 193typedef volatile struct tmr_regs tmr_regs_t; 194 195struct dgt_regs { 196 uint32_t mtch; /* +0x00 */ 197 uint32_t cnt; /* +0x04 */ 198 uint32_t en; /* +0x08 */ 199 uint32_t clr; /* +0x0C */ 200 uint32_t clk_ctl; /* +0x10 */ 201}; 202typedef volatile struct dgt_regs dgt_regs_t; 203 204struct wdt_regs { 205 uint32_t reset; /* +0x00 */ 206 uint32_t freeze; /* +0x04 */ 207 uint32_t unmasked_int_en; /* +0x08 */ 208 uint32_t status; /* +0x0C */ 209 uint32_t expired_width; /* +0x10 */ 210 uint32_t bark_time; /* +0x14 */ 211 uint32_t test_load_status; /* +0x18 */ 212 uint32_t test_load; /* +0x1C */ 213 uint32_t test; /* +0x20 */ 214 /* Only for KRAIT and GSS */ 215 uint32_t bite_time; /* +0x24 */ 216}; 217typedef volatile struct wdt_regs wdt_regs_t; 218 219struct gpt_regs { 220 uint32_t mtch; /* +0x00 */ 221 uint32_t cnt; /* +0x04 */ 222 uint32_t en; /* +0x08 */ 223 uint32_t clr; /* +0x0C */ 224}; 225typedef volatile struct gpt_regs gpt_regs_t; 226 227/**** GPT timer functions ****/ 228int 229gpt_timer_start(timer_t *timer) 230{ 231 gpt_regs_t* regs = (gpt_regs_t*)timer->data; 232 regs->en |= GPTEN_EN; 233 return 0; 234} 235 236int 237gpt_timer_stop(timer_t *timer) 238{ 239 gpt_regs_t* regs = (gpt_regs_t*)timer->data; 240 regs->en &= ~GPTEN_EN; 241 return 0; 242} 243 244uint64_t 245gpt_get_time(timer_t *timer) 246{ 247 gpt_regs_t* regs = (gpt_regs_t*)timer->data; 248 return regs->cnt; 249} 250 251int 252gpt_periodic(timer_t *timer, uint64_t ns) 253{ 254 gpt_regs_t* regs = (gpt_regs_t*)timer->data; 255 uintptr_t sts_base = (uintptr_t)timer->data & ~0xfff; 256 volatile uint32_t* sts = (volatile uint32_t*)sts_base; 257 uint64_t fin; 258 switch (timer->id) { 259 case TMR_RPM_GPT0 : 260 fin = get_xo_hz() / 4; 261 break; 262 case TMR_RPM_GPT1: 263 case TMR_KPSS_GPT0: 264 case TMR_KPSS_GPT1: 265 case TMR_GSS_GPT0: 266 case TMR_GSS_GPT1: 267 fin = get_slp_hz(); 268 break; 269 default: 270 assert(!"invalid timer for GPT operation"); 271 return -1; 272 } 273 /* Clear the timer on match */ 274 275 regs->en = GPTEN_CLR_ON_MTCH_EN; 276 switch (timer->id) { 277 case TMR_RPM_GPT0 : 278 while (sts[RPMTMRSTS_OFFSET / 4] & RPMTMRSTS_TMR0_WR_PEND); 279 break; 280 case TMR_RPM_GPT1: 281 while (sts[RPMTMRSTS_OFFSET / 4] & RPMTMRSTS_TMR1_WR_PEND); 282 break; 283 case TMR_KPSS_GPT0: 284 case TMR_GSS_GPT0: 285 while (sts[KPSSSTAT_OFFSET / 4] & KPSSGPTSTS_TMR0_WR_PEND); 286 break; 287 case TMR_KPSS_GPT1: 288 case TMR_GSS_GPT1: 289 while (sts[KPSSSTAT_OFFSET / 4] & KPSSGPTSTS_TMR1_WR_PEND); 290 break; 291 default: 292 break; 293 } 294 /* Reset the timer */ 295 regs->clr = 0xC0FFEE; 296 /* Configure match value */ 297 regs->mtch = (fin * ns) / (1000UL * 1000 * 1000); 298 299 switch (timer->id) { 300 case TMR_RPM_GPT0 : 301 while (sts[RPMTMRSTS_OFFSET / 4] & RPMTMRSTS_TMR0_PEND); 302 break; 303 case TMR_RPM_GPT1: 304 while (sts[RPMTMRSTS_OFFSET / 4] & RPMTMRSTS_TMR1_PEND); 305 break; 306 case TMR_KPSS_GPT0: 307 case TMR_GSS_GPT0: 308 while (sts[KPSSSTAT_OFFSET / 4] & KPSSGPTSTS_TMR0_PEND); 309 break; 310 case TMR_KPSS_GPT1: 311 case TMR_GSS_GPT1: 312 while (sts[KPSSSTAT_OFFSET / 4] & KPSSGPTSTS_TMR1_PEND); 313 break; 314 default: 315 break; 316 } 317 318 return 0; 319} 320 321void 322gpt_handle_irq(UNUSED timer_t *timer) 323{ 324 /* Nothing to do */ 325} 326 327/* DGT timer functions */ 328int 329dgt_timer_start(timer_t *timer) 330{ 331 dgt_regs_t* regs = (dgt_regs_t*)timer->data; 332 regs->en |= DGTTMR_EN_EN; 333 return 0; 334} 335 336int 337dgt_timer_stop(timer_t *timer) 338{ 339 dgt_regs_t* regs = (dgt_regs_t*)timer->data; 340 regs->en &= ~DGTTMR_EN_EN; 341 return 0; 342} 343 344uint64_t 345dgt_get_time(timer_t *timer) 346{ 347 dgt_regs_t* regs = (dgt_regs_t*)timer->data; 348 return regs->cnt; 349} 350 351int 352dgt_periodic(timer_t *timer, uint64_t ns) 353{ 354 dgt_regs_t* regs = (dgt_regs_t*)timer->data; 355 uint64_t fin_hz = get_tcxo_hz(); 356 int div; 357 /* Disable */ 358 regs->en = 0; 359 /* Configure */ 360 regs->clr = 0xC0FFEE; 361 /* DIV should always be 4 due to clock domain delay */ 362 regs->clk_ctl = DGTTMR_CLK_CTRL_DIV4; 363 div = 4; 364 regs->mtch = (fin_hz * ns) / (div * 1000 * 1000 * 1000); 365 regs->en = DGTTMR_EN_CLR_ON_MTCH_EN; 366 return 0; 367} 368 369void 370dgt_handle_irq(UNUSED timer_t *timer) 371{ 372 /* Nothing to do */ 373} 374 375/**** TMR ****/ 376int 377tmr_timer_start(timer_t *timer) 378{ 379 tmr_regs_t* regs = (tmr_regs_t*)timer->data; 380 regs->control |= ~TMR_CTRL_EN; 381 return 0; 382} 383 384int 385tmr_timer_stop(timer_t *timer) 386{ 387 tmr_regs_t* regs = (tmr_regs_t*)timer->data; 388 regs->control &= ~TMR_CTRL_EN; 389 return 0; 390} 391 392uint64_t 393tmr_get_time(timer_t *timer) 394{ 395 tmr_regs_t* regs = (tmr_regs_t*)timer->data; 396 return regs->count; 397} 398 399int 400tmr_periodic(timer_t *timer, uint64_t ns) 401{ 402 tmr_regs_t* regs = (tmr_regs_t*)timer->data; 403 uint64_t fin_hz; 404 /* Find input clock frequency */ 405 switch (timer->id) { 406 case TMR_PPSS_XO_TMR0: 407 case TMR_PPSS_XO_TMR1: 408 fin_hz = get_tcxo_hz(); 409 break; 410 case TMR_PPSS_SLP_TMR0: 411 case TMR_PPSS_SLP_TMR1: 412 fin_hz = get_slp_hz(); 413 break; 414 default: 415 assert(!"Invalid timer for this call"); 416 return -1; 417 } 418 /* Turn on the timer */ 419 regs->control = TMR_CTRL_ON; 420 while (regs->status & TMR_STAT_CONTROL_UPDATE); 421 /* Reset and config */ 422 regs->control |= TMR_CTRL_PRESCALE_DIV4 | TMR_CTRL_MODE_PERIODIC; 423 regs->clear_int = 0xC0FFEE; 424 regs->clear_cnt = 0xC0FFEE; 425 regs->match = (fin_hz * ns) / (4UL * 1000 * 1000 * 1000); 426 /* Wait for registers to be updated */ 427 while (regs->status); 428 return 0; 429} 430 431void 432tmr_handle_irq(timer_t *timer) 433{ 434 tmr_regs_t* regs = (tmr_regs_t*)timer->data; 435 /* Reset the IRQ */ 436 regs->clear_int = 0xC0FFEE; 437} 438 439/**** WDT ****/ 440int 441wdt_timer_start(timer_t *timer) 442{ 443 wdt_regs_t* regs = (wdt_regs_t*)timer->data; 444 /* Don't send a reset */ 445 regs->reset = 0; 446 /* Enable the auto-kicker */ 447 regs->freeze = WDTFREEZE; 448 regs->unmasked_int_en = WDTINTEN_EN | WDTINTEN_UNMASKED_INTEN; 449 return 0; 450} 451 452uint64_t 453wdt_get_time(timer_t *timer) 454{ 455 wdt_regs_t* regs = (wdt_regs_t*)timer->data; 456 return WDTSTAT_GETCOUNT(regs->status); 457} 458 459int 460wdt_periodic(timer_t *timer, uint64_t ns) 461{ 462 wdt_regs_t* regs = (wdt_regs_t*)timer->data; 463 uint64_t fin_hz = get_slp_hz(); 464 uint32_t bark_time; 465 /* Disable */ 466 regs->unmasked_int_en = WDTINTEN_EN; 467 /* Enable the auto-kicker */ 468 regs->freeze = WDTFREEZE; 469 /* Don't reset */ 470 regs->reset = 0; 471 /* Set the counter value */ 472 bark_time = (fin_hz * ns) / (1000 * 1000); 473 regs->bark_time = WDTBARK_DATA(bark_time); 474 assert(!"Not yet implemented"); 475 return 0; 476} 477 478int timer_init(timer_t *timer, timer_config_t config) 479{ 480 if (config.id < 0 || config.id >= NTIMERS) { 481 return EINVAL; 482 } 483 484 timer->id = config.id; 485 486 /* Default handlers */ 487 switch (config.id) { 488 case TMR_PPSS_XO_TMR0: 489 timer->data = TIMER_VADDR_OFFSET(config.vaddr, PPSSXOTMR0_OFFSET); 490 break; 491 case TMR_PPSS_XO_TMR1: 492 timer->data = TIMER_VADDR_OFFSET(config.vaddr, PPSSXOTMR1_OFFSET); 493 break; 494 case TMR_PPSS_SLP_TMR0: 495 TIMER_REG(config.vaddr, PPSSCLKCTNTL_OFFSET) |= PPSSCLKCTNTL_SLPON; 496 timer->data = TIMER_VADDR_OFFSET(config.vaddr, PPSSTMR0_OFFSET); 497 break; 498 case TMR_PPSS_SLP_TMR1: 499 TIMER_REG(config.vaddr, PPSSCLKCTNTL_OFFSET) |= PPSSCLKCTNTL_SLPON; 500 timer->data = TIMER_VADDR_OFFSET(config.vaddr, PPSSTMR1_OFFSET); 501 break; 502 case TMR_PPSS_SLP_WDOG: 503 TIMER_REG(config.vaddr, PPSSCLKCTNTL_OFFSET) |= PPSSCLKCTNTL_WDGON; 504 timer->data = TIMER_VADDR_OFFSET(config.vaddr, PPSSWDT_OFFSET); 505 break; 506 /* KPSS */ 507 case TMR_KPSS_GPT0: 508 timer->data = TIMER_VADDR_OFFSET(config.vaddr, KPSSGPT0_OFFSET); 509 break; 510 case TMR_KPSS_GPT1: 511 timer->data = TIMER_VADDR_OFFSET(config.vaddr, KPSSGPT1_OFFSET); 512 break; 513 case TMR_KPSS_DGT: 514 timer->data = TIMER_VADDR_OFFSET(config.vaddr, KPSSDGT_OFFSET); 515 break; 516 case TMR_KPSS_WDT0: 517 timer->data = TIMER_VADDR_OFFSET(config.vaddr, KPSSGPT0_OFFSET); 518 break; 519 case TMR_KPSS_WDT1: 520 timer->data = TIMER_VADDR_OFFSET(config.vaddr, KPSSGPT1_OFFSET); 521 break; 522 /* GSS */ 523 case TMR_GSS_GPT0: 524 timer->data = TIMER_VADDR_OFFSET(config.vaddr, GSSGPT0_OFFSET); 525 break; 526 case TMR_GSS_GPT1: 527 timer->data = TIMER_VADDR_OFFSET(config.vaddr, GSSGPT1_OFFSET); 528 break; 529 case TMR_GSS_DGT: 530 timer->data = TIMER_VADDR_OFFSET(config.vaddr, GSSDGT_OFFSET); 531 break; 532 case TMR_GSS_WDT0: 533 timer->data = TIMER_VADDR_OFFSET(config.vaddr, GSSGPT0_OFFSET); 534 break; 535 case TMR_GSS_WDT1: 536 timer->data = TIMER_VADDR_OFFSET(config.vaddr, GSSGPT1_OFFSET); 537 break; 538 /* RPM */ 539 case TMR_RPM_GPT0: 540 TIMER_REG(config.vaddr, RPMGPT0_CLK_CTL) = RPMGPT0_DIV4; 541 timer->data = TIMER_VADDR_OFFSET(config.vaddr, RPMGPT0_OFFSET); 542 break; 543 case TMR_RPM_GPT1: 544 timer->data = TIMER_VADDR_OFFSET(config.vaddr, RPMGPT1_OFFSET); 545 break; 546 case TMR_RPM_WDOG: 547 timer->data = TIMER_VADDR_OFFSET(config.vaddr, RPMWDT_OFFSET); 548 break; 549 default: 550 return EINVAL; 551 } 552 553 return 0; 554} 555