1*83ff9dcfSAnton Vorontsov /* 2*83ff9dcfSAnton Vorontsov * Freescale General-purpose Timers Module 3*83ff9dcfSAnton Vorontsov * 4*83ff9dcfSAnton Vorontsov * Copyright (c) Freescale Semicondutor, Inc. 2006. 5*83ff9dcfSAnton Vorontsov * Shlomi Gridish <gridish@freescale.com> 6*83ff9dcfSAnton Vorontsov * Jerry Huang <Chang-Ming.Huang@freescale.com> 7*83ff9dcfSAnton Vorontsov * Copyright (c) MontaVista Software, Inc. 2008. 8*83ff9dcfSAnton Vorontsov * Anton Vorontsov <avorontsov@ru.mvista.com> 9*83ff9dcfSAnton Vorontsov * 10*83ff9dcfSAnton Vorontsov * This program is free software; you can redistribute it and/or modify it 11*83ff9dcfSAnton Vorontsov * under the terms of the GNU General Public License as published by the 12*83ff9dcfSAnton Vorontsov * Free Software Foundation; either version 2 of the License, or (at your 13*83ff9dcfSAnton Vorontsov * option) any later version. 14*83ff9dcfSAnton Vorontsov */ 15*83ff9dcfSAnton Vorontsov 16*83ff9dcfSAnton Vorontsov #include <linux/kernel.h> 17*83ff9dcfSAnton Vorontsov #include <linux/errno.h> 18*83ff9dcfSAnton Vorontsov #include <linux/list.h> 19*83ff9dcfSAnton Vorontsov #include <linux/io.h> 20*83ff9dcfSAnton Vorontsov #include <linux/of.h> 21*83ff9dcfSAnton Vorontsov #include <linux/spinlock.h> 22*83ff9dcfSAnton Vorontsov #include <linux/bitops.h> 23*83ff9dcfSAnton Vorontsov #include <asm/fsl_gtm.h> 24*83ff9dcfSAnton Vorontsov 25*83ff9dcfSAnton Vorontsov #define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1) 26*83ff9dcfSAnton Vorontsov #define GTCFR_RST(x) ((x) & 1 ? 1 << 4 : 1 << 0) 27*83ff9dcfSAnton Vorontsov 28*83ff9dcfSAnton Vorontsov #define GTMDR_ICLK_MASK (3 << 1) 29*83ff9dcfSAnton Vorontsov #define GTMDR_ICLK_ICAS (0 << 1) 30*83ff9dcfSAnton Vorontsov #define GTMDR_ICLK_ICLK (1 << 1) 31*83ff9dcfSAnton Vorontsov #define GTMDR_ICLK_SLGO (2 << 1) 32*83ff9dcfSAnton Vorontsov #define GTMDR_FRR (1 << 3) 33*83ff9dcfSAnton Vorontsov #define GTMDR_ORI (1 << 4) 34*83ff9dcfSAnton Vorontsov #define GTMDR_SPS(x) ((x) << 8) 35*83ff9dcfSAnton Vorontsov 36*83ff9dcfSAnton Vorontsov struct gtm_timers_regs { 37*83ff9dcfSAnton Vorontsov u8 gtcfr1; /* Timer 1, Timer 2 global config register */ 38*83ff9dcfSAnton Vorontsov u8 res0[0x3]; 39*83ff9dcfSAnton Vorontsov u8 gtcfr2; /* Timer 3, timer 4 global config register */ 40*83ff9dcfSAnton Vorontsov u8 res1[0xB]; 41*83ff9dcfSAnton Vorontsov __be16 gtmdr1; /* Timer 1 mode register */ 42*83ff9dcfSAnton Vorontsov __be16 gtmdr2; /* Timer 2 mode register */ 43*83ff9dcfSAnton Vorontsov __be16 gtrfr1; /* Timer 1 reference register */ 44*83ff9dcfSAnton Vorontsov __be16 gtrfr2; /* Timer 2 reference register */ 45*83ff9dcfSAnton Vorontsov __be16 gtcpr1; /* Timer 1 capture register */ 46*83ff9dcfSAnton Vorontsov __be16 gtcpr2; /* Timer 2 capture register */ 47*83ff9dcfSAnton Vorontsov __be16 gtcnr1; /* Timer 1 counter */ 48*83ff9dcfSAnton Vorontsov __be16 gtcnr2; /* Timer 2 counter */ 49*83ff9dcfSAnton Vorontsov __be16 gtmdr3; /* Timer 3 mode register */ 50*83ff9dcfSAnton Vorontsov __be16 gtmdr4; /* Timer 4 mode register */ 51*83ff9dcfSAnton Vorontsov __be16 gtrfr3; /* Timer 3 reference register */ 52*83ff9dcfSAnton Vorontsov __be16 gtrfr4; /* Timer 4 reference register */ 53*83ff9dcfSAnton Vorontsov __be16 gtcpr3; /* Timer 3 capture register */ 54*83ff9dcfSAnton Vorontsov __be16 gtcpr4; /* Timer 4 capture register */ 55*83ff9dcfSAnton Vorontsov __be16 gtcnr3; /* Timer 3 counter */ 56*83ff9dcfSAnton Vorontsov __be16 gtcnr4; /* Timer 4 counter */ 57*83ff9dcfSAnton Vorontsov __be16 gtevr1; /* Timer 1 event register */ 58*83ff9dcfSAnton Vorontsov __be16 gtevr2; /* Timer 2 event register */ 59*83ff9dcfSAnton Vorontsov __be16 gtevr3; /* Timer 3 event register */ 60*83ff9dcfSAnton Vorontsov __be16 gtevr4; /* Timer 4 event register */ 61*83ff9dcfSAnton Vorontsov __be16 gtpsr1; /* Timer 1 prescale register */ 62*83ff9dcfSAnton Vorontsov __be16 gtpsr2; /* Timer 2 prescale register */ 63*83ff9dcfSAnton Vorontsov __be16 gtpsr3; /* Timer 3 prescale register */ 64*83ff9dcfSAnton Vorontsov __be16 gtpsr4; /* Timer 4 prescale register */ 65*83ff9dcfSAnton Vorontsov u8 res2[0x40]; 66*83ff9dcfSAnton Vorontsov } __attribute__ ((packed)); 67*83ff9dcfSAnton Vorontsov 68*83ff9dcfSAnton Vorontsov struct gtm { 69*83ff9dcfSAnton Vorontsov unsigned int clock; 70*83ff9dcfSAnton Vorontsov struct gtm_timers_regs __iomem *regs; 71*83ff9dcfSAnton Vorontsov struct gtm_timer timers[4]; 72*83ff9dcfSAnton Vorontsov spinlock_t lock; 73*83ff9dcfSAnton Vorontsov struct list_head list_node; 74*83ff9dcfSAnton Vorontsov }; 75*83ff9dcfSAnton Vorontsov 76*83ff9dcfSAnton Vorontsov static LIST_HEAD(gtms); 77*83ff9dcfSAnton Vorontsov 78*83ff9dcfSAnton Vorontsov /** 79*83ff9dcfSAnton Vorontsov * gtm_get_timer - request GTM timer to use it with the rest of GTM API 80*83ff9dcfSAnton Vorontsov * Context: non-IRQ 81*83ff9dcfSAnton Vorontsov * 82*83ff9dcfSAnton Vorontsov * This function reserves GTM timer for later use. It returns gtm_timer 83*83ff9dcfSAnton Vorontsov * structure to use with the rest of GTM API, you should use timer->irq 84*83ff9dcfSAnton Vorontsov * to manage timer interrupt. 85*83ff9dcfSAnton Vorontsov */ 86*83ff9dcfSAnton Vorontsov struct gtm_timer *gtm_get_timer16(void) 87*83ff9dcfSAnton Vorontsov { 88*83ff9dcfSAnton Vorontsov struct gtm *gtm = NULL; 89*83ff9dcfSAnton Vorontsov int i; 90*83ff9dcfSAnton Vorontsov 91*83ff9dcfSAnton Vorontsov list_for_each_entry(gtm, >ms, list_node) { 92*83ff9dcfSAnton Vorontsov spin_lock_irq(>m->lock); 93*83ff9dcfSAnton Vorontsov 94*83ff9dcfSAnton Vorontsov for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) { 95*83ff9dcfSAnton Vorontsov if (!gtm->timers[i].requested) { 96*83ff9dcfSAnton Vorontsov gtm->timers[i].requested = true; 97*83ff9dcfSAnton Vorontsov spin_unlock_irq(>m->lock); 98*83ff9dcfSAnton Vorontsov return >m->timers[i]; 99*83ff9dcfSAnton Vorontsov } 100*83ff9dcfSAnton Vorontsov } 101*83ff9dcfSAnton Vorontsov 102*83ff9dcfSAnton Vorontsov spin_unlock_irq(>m->lock); 103*83ff9dcfSAnton Vorontsov } 104*83ff9dcfSAnton Vorontsov 105*83ff9dcfSAnton Vorontsov if (gtm) 106*83ff9dcfSAnton Vorontsov return ERR_PTR(-EBUSY); 107*83ff9dcfSAnton Vorontsov return ERR_PTR(-ENODEV); 108*83ff9dcfSAnton Vorontsov } 109*83ff9dcfSAnton Vorontsov EXPORT_SYMBOL(gtm_get_timer16); 110*83ff9dcfSAnton Vorontsov 111*83ff9dcfSAnton Vorontsov /** 112*83ff9dcfSAnton Vorontsov * gtm_get_specific_timer - request specific GTM timer 113*83ff9dcfSAnton Vorontsov * @gtm: specific GTM, pass here GTM's device_node->data 114*83ff9dcfSAnton Vorontsov * @timer: specific timer number, Timer1 is 0. 115*83ff9dcfSAnton Vorontsov * Context: non-IRQ 116*83ff9dcfSAnton Vorontsov * 117*83ff9dcfSAnton Vorontsov * This function reserves GTM timer for later use. It returns gtm_timer 118*83ff9dcfSAnton Vorontsov * structure to use with the rest of GTM API, you should use timer->irq 119*83ff9dcfSAnton Vorontsov * to manage timer interrupt. 120*83ff9dcfSAnton Vorontsov */ 121*83ff9dcfSAnton Vorontsov struct gtm_timer *gtm_get_specific_timer16(struct gtm *gtm, 122*83ff9dcfSAnton Vorontsov unsigned int timer) 123*83ff9dcfSAnton Vorontsov { 124*83ff9dcfSAnton Vorontsov struct gtm_timer *ret = ERR_PTR(-EBUSY); 125*83ff9dcfSAnton Vorontsov 126*83ff9dcfSAnton Vorontsov if (timer > 3) 127*83ff9dcfSAnton Vorontsov return ERR_PTR(-EINVAL); 128*83ff9dcfSAnton Vorontsov 129*83ff9dcfSAnton Vorontsov spin_lock_irq(>m->lock); 130*83ff9dcfSAnton Vorontsov 131*83ff9dcfSAnton Vorontsov if (gtm->timers[timer].requested) 132*83ff9dcfSAnton Vorontsov goto out; 133*83ff9dcfSAnton Vorontsov 134*83ff9dcfSAnton Vorontsov ret = >m->timers[timer]; 135*83ff9dcfSAnton Vorontsov ret->requested = true; 136*83ff9dcfSAnton Vorontsov 137*83ff9dcfSAnton Vorontsov out: 138*83ff9dcfSAnton Vorontsov spin_unlock_irq(>m->lock); 139*83ff9dcfSAnton Vorontsov return ret; 140*83ff9dcfSAnton Vorontsov } 141*83ff9dcfSAnton Vorontsov EXPORT_SYMBOL(gtm_get_specific_timer16); 142*83ff9dcfSAnton Vorontsov 143*83ff9dcfSAnton Vorontsov /** 144*83ff9dcfSAnton Vorontsov * gtm_put_timer16 - release 16 bits GTM timer 145*83ff9dcfSAnton Vorontsov * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer 146*83ff9dcfSAnton Vorontsov * Context: any 147*83ff9dcfSAnton Vorontsov * 148*83ff9dcfSAnton Vorontsov * This function releases GTM timer so others may request it. 149*83ff9dcfSAnton Vorontsov */ 150*83ff9dcfSAnton Vorontsov void gtm_put_timer16(struct gtm_timer *tmr) 151*83ff9dcfSAnton Vorontsov { 152*83ff9dcfSAnton Vorontsov gtm_stop_timer16(tmr); 153*83ff9dcfSAnton Vorontsov 154*83ff9dcfSAnton Vorontsov spin_lock_irq(&tmr->gtm->lock); 155*83ff9dcfSAnton Vorontsov tmr->requested = false; 156*83ff9dcfSAnton Vorontsov spin_unlock_irq(&tmr->gtm->lock); 157*83ff9dcfSAnton Vorontsov } 158*83ff9dcfSAnton Vorontsov EXPORT_SYMBOL(gtm_put_timer16); 159*83ff9dcfSAnton Vorontsov 160*83ff9dcfSAnton Vorontsov /* 161*83ff9dcfSAnton Vorontsov * This is back-end for the exported functions, it's used to reset single 162*83ff9dcfSAnton Vorontsov * timer in reference mode. 163*83ff9dcfSAnton Vorontsov */ 164*83ff9dcfSAnton Vorontsov static int gtm_set_ref_timer16(struct gtm_timer *tmr, int frequency, 165*83ff9dcfSAnton Vorontsov int reference_value, bool free_run) 166*83ff9dcfSAnton Vorontsov { 167*83ff9dcfSAnton Vorontsov struct gtm *gtm = tmr->gtm; 168*83ff9dcfSAnton Vorontsov int num = tmr - >m->timers[0]; 169*83ff9dcfSAnton Vorontsov unsigned int prescaler; 170*83ff9dcfSAnton Vorontsov u8 iclk = GTMDR_ICLK_ICLK; 171*83ff9dcfSAnton Vorontsov u8 psr; 172*83ff9dcfSAnton Vorontsov u8 sps; 173*83ff9dcfSAnton Vorontsov unsigned long flags; 174*83ff9dcfSAnton Vorontsov int max_prescaler = 256 * 256 * 16; 175*83ff9dcfSAnton Vorontsov 176*83ff9dcfSAnton Vorontsov /* CPM2 doesn't have primary prescaler */ 177*83ff9dcfSAnton Vorontsov if (!tmr->gtpsr) 178*83ff9dcfSAnton Vorontsov max_prescaler /= 256; 179*83ff9dcfSAnton Vorontsov 180*83ff9dcfSAnton Vorontsov prescaler = gtm->clock / frequency; 181*83ff9dcfSAnton Vorontsov /* 182*83ff9dcfSAnton Vorontsov * We have two 8 bit prescalers -- primary and secondary (psr, sps), 183*83ff9dcfSAnton Vorontsov * plus "slow go" mode (clk / 16). So, total prescale value is 184*83ff9dcfSAnton Vorontsov * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing psr. 185*83ff9dcfSAnton Vorontsov */ 186*83ff9dcfSAnton Vorontsov if (prescaler > max_prescaler) 187*83ff9dcfSAnton Vorontsov return -EINVAL; 188*83ff9dcfSAnton Vorontsov 189*83ff9dcfSAnton Vorontsov if (prescaler > max_prescaler / 16) { 190*83ff9dcfSAnton Vorontsov iclk = GTMDR_ICLK_SLGO; 191*83ff9dcfSAnton Vorontsov prescaler /= 16; 192*83ff9dcfSAnton Vorontsov } 193*83ff9dcfSAnton Vorontsov 194*83ff9dcfSAnton Vorontsov if (prescaler <= 256) { 195*83ff9dcfSAnton Vorontsov psr = 0; 196*83ff9dcfSAnton Vorontsov sps = prescaler - 1; 197*83ff9dcfSAnton Vorontsov } else { 198*83ff9dcfSAnton Vorontsov psr = 256 - 1; 199*83ff9dcfSAnton Vorontsov sps = prescaler / 256 - 1; 200*83ff9dcfSAnton Vorontsov } 201*83ff9dcfSAnton Vorontsov 202*83ff9dcfSAnton Vorontsov spin_lock_irqsave(>m->lock, flags); 203*83ff9dcfSAnton Vorontsov 204*83ff9dcfSAnton Vorontsov /* 205*83ff9dcfSAnton Vorontsov * Properly reset timers: stop, reset, set up prescalers, reference 206*83ff9dcfSAnton Vorontsov * value and clear event register. 207*83ff9dcfSAnton Vorontsov */ 208*83ff9dcfSAnton Vorontsov clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)), 209*83ff9dcfSAnton Vorontsov GTCFR_STP(num) | GTCFR_RST(num)); 210*83ff9dcfSAnton Vorontsov 211*83ff9dcfSAnton Vorontsov setbits8(tmr->gtcfr, GTCFR_STP(num)); 212*83ff9dcfSAnton Vorontsov 213*83ff9dcfSAnton Vorontsov if (tmr->gtpsr) 214*83ff9dcfSAnton Vorontsov out_be16(tmr->gtpsr, psr); 215*83ff9dcfSAnton Vorontsov clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) | 216*83ff9dcfSAnton Vorontsov GTMDR_ORI | (free_run ? GTMDR_FRR : 0)); 217*83ff9dcfSAnton Vorontsov out_be16(tmr->gtcnr, 0); 218*83ff9dcfSAnton Vorontsov out_be16(tmr->gtrfr, reference_value); 219*83ff9dcfSAnton Vorontsov out_be16(tmr->gtevr, 0xFFFF); 220*83ff9dcfSAnton Vorontsov 221*83ff9dcfSAnton Vorontsov /* Let it be. */ 222*83ff9dcfSAnton Vorontsov clrbits8(tmr->gtcfr, GTCFR_STP(num)); 223*83ff9dcfSAnton Vorontsov 224*83ff9dcfSAnton Vorontsov spin_unlock_irqrestore(>m->lock, flags); 225*83ff9dcfSAnton Vorontsov 226*83ff9dcfSAnton Vorontsov return 0; 227*83ff9dcfSAnton Vorontsov } 228*83ff9dcfSAnton Vorontsov 229*83ff9dcfSAnton Vorontsov /** 230*83ff9dcfSAnton Vorontsov * gtm_set_timer16 - (re)set 16 bit timer with arbitrary precision 231*83ff9dcfSAnton Vorontsov * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer 232*83ff9dcfSAnton Vorontsov * @usec: timer interval in microseconds 233*83ff9dcfSAnton Vorontsov * @reload: if set, the timer will reset upon expiry rather than 234*83ff9dcfSAnton Vorontsov * continue running free. 235*83ff9dcfSAnton Vorontsov * Context: any 236*83ff9dcfSAnton Vorontsov * 237*83ff9dcfSAnton Vorontsov * This function (re)sets the GTM timer so that it counts up to the requested 238*83ff9dcfSAnton Vorontsov * interval value, and fires the interrupt when the value is reached. This 239*83ff9dcfSAnton Vorontsov * function will reduce the precision of the timer as needed in order for the 240*83ff9dcfSAnton Vorontsov * requested timeout to fit in a 16-bit register. 241*83ff9dcfSAnton Vorontsov */ 242*83ff9dcfSAnton Vorontsov int gtm_set_timer16(struct gtm_timer *tmr, unsigned long usec, bool reload) 243*83ff9dcfSAnton Vorontsov { 244*83ff9dcfSAnton Vorontsov /* quite obvious, frequency which is enough for µSec precision */ 245*83ff9dcfSAnton Vorontsov int freq = 1000000; 246*83ff9dcfSAnton Vorontsov unsigned int bit; 247*83ff9dcfSAnton Vorontsov 248*83ff9dcfSAnton Vorontsov bit = fls_long(usec); 249*83ff9dcfSAnton Vorontsov if (bit > 15) { 250*83ff9dcfSAnton Vorontsov freq >>= bit - 15; 251*83ff9dcfSAnton Vorontsov usec >>= bit - 15; 252*83ff9dcfSAnton Vorontsov } 253*83ff9dcfSAnton Vorontsov 254*83ff9dcfSAnton Vorontsov if (!freq) 255*83ff9dcfSAnton Vorontsov return -EINVAL; 256*83ff9dcfSAnton Vorontsov 257*83ff9dcfSAnton Vorontsov return gtm_set_ref_timer16(tmr, freq, usec, reload); 258*83ff9dcfSAnton Vorontsov } 259*83ff9dcfSAnton Vorontsov EXPORT_SYMBOL(gtm_set_timer16); 260*83ff9dcfSAnton Vorontsov 261*83ff9dcfSAnton Vorontsov /** 262*83ff9dcfSAnton Vorontsov * gtm_set_exact_utimer16 - (re)set 16 bits timer 263*83ff9dcfSAnton Vorontsov * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer 264*83ff9dcfSAnton Vorontsov * @usec: timer interval in microseconds 265*83ff9dcfSAnton Vorontsov * @reload: if set, the timer will reset upon expiry rather than 266*83ff9dcfSAnton Vorontsov * continue running free. 267*83ff9dcfSAnton Vorontsov * Context: any 268*83ff9dcfSAnton Vorontsov * 269*83ff9dcfSAnton Vorontsov * This function (re)sets GTM timer so that it counts up to the requested 270*83ff9dcfSAnton Vorontsov * interval value, and fires the interrupt when the value is reached. If reload 271*83ff9dcfSAnton Vorontsov * flag was set, timer will also reset itself upon reference value, otherwise 272*83ff9dcfSAnton Vorontsov * it continues to increment. 273*83ff9dcfSAnton Vorontsov * 274*83ff9dcfSAnton Vorontsov * The _exact_ bit in the function name states that this function will not 275*83ff9dcfSAnton Vorontsov * crop precision of the "usec" argument, thus usec is limited to 16 bits 276*83ff9dcfSAnton Vorontsov * (single timer width). 277*83ff9dcfSAnton Vorontsov */ 278*83ff9dcfSAnton Vorontsov int gtm_set_exact_timer16(struct gtm_timer *tmr, u16 usec, bool reload) 279*83ff9dcfSAnton Vorontsov { 280*83ff9dcfSAnton Vorontsov /* quite obvious, frequency which is enough for µSec precision */ 281*83ff9dcfSAnton Vorontsov const int freq = 1000000; 282*83ff9dcfSAnton Vorontsov 283*83ff9dcfSAnton Vorontsov /* 284*83ff9dcfSAnton Vorontsov * We can lower the frequency (and probably power consumption) by 285*83ff9dcfSAnton Vorontsov * dividing both frequency and usec by 2 until there is no remainder. 286*83ff9dcfSAnton Vorontsov * But we won't bother with this unless savings are measured, so just 287*83ff9dcfSAnton Vorontsov * run the timer as is. 288*83ff9dcfSAnton Vorontsov */ 289*83ff9dcfSAnton Vorontsov 290*83ff9dcfSAnton Vorontsov return gtm_set_ref_timer16(tmr, freq, usec, reload); 291*83ff9dcfSAnton Vorontsov } 292*83ff9dcfSAnton Vorontsov EXPORT_SYMBOL(gtm_set_exact_timer16); 293*83ff9dcfSAnton Vorontsov 294*83ff9dcfSAnton Vorontsov /** 295*83ff9dcfSAnton Vorontsov * gtm_stop_timer16 - stop single timer 296*83ff9dcfSAnton Vorontsov * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer 297*83ff9dcfSAnton Vorontsov * Context: any 298*83ff9dcfSAnton Vorontsov * 299*83ff9dcfSAnton Vorontsov * This function simply stops the GTM timer. 300*83ff9dcfSAnton Vorontsov */ 301*83ff9dcfSAnton Vorontsov void gtm_stop_timer16(struct gtm_timer *tmr) 302*83ff9dcfSAnton Vorontsov { 303*83ff9dcfSAnton Vorontsov struct gtm *gtm = tmr->gtm; 304*83ff9dcfSAnton Vorontsov int num = tmr - >m->timers[0]; 305*83ff9dcfSAnton Vorontsov unsigned long flags; 306*83ff9dcfSAnton Vorontsov 307*83ff9dcfSAnton Vorontsov spin_lock_irqsave(>m->lock, flags); 308*83ff9dcfSAnton Vorontsov 309*83ff9dcfSAnton Vorontsov setbits8(tmr->gtcfr, GTCFR_STP(num)); 310*83ff9dcfSAnton Vorontsov out_be16(tmr->gtevr, 0xFFFF); 311*83ff9dcfSAnton Vorontsov 312*83ff9dcfSAnton Vorontsov spin_unlock_irqrestore(>m->lock, flags); 313*83ff9dcfSAnton Vorontsov } 314*83ff9dcfSAnton Vorontsov EXPORT_SYMBOL(gtm_stop_timer16); 315*83ff9dcfSAnton Vorontsov 316*83ff9dcfSAnton Vorontsov /** 317*83ff9dcfSAnton Vorontsov * gtm_ack_timer16 - acknowledge timer event (free-run timers only) 318*83ff9dcfSAnton Vorontsov * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer 319*83ff9dcfSAnton Vorontsov * @events: events mask to ack 320*83ff9dcfSAnton Vorontsov * Context: any 321*83ff9dcfSAnton Vorontsov * 322*83ff9dcfSAnton Vorontsov * Thus function used to acknowledge timer interrupt event, use it inside the 323*83ff9dcfSAnton Vorontsov * interrupt handler. 324*83ff9dcfSAnton Vorontsov */ 325*83ff9dcfSAnton Vorontsov void gtm_ack_timer16(struct gtm_timer *tmr, u16 events) 326*83ff9dcfSAnton Vorontsov { 327*83ff9dcfSAnton Vorontsov out_be16(tmr->gtevr, events); 328*83ff9dcfSAnton Vorontsov } 329*83ff9dcfSAnton Vorontsov EXPORT_SYMBOL(gtm_ack_timer16); 330*83ff9dcfSAnton Vorontsov 331*83ff9dcfSAnton Vorontsov static void __init gtm_set_shortcuts(struct device_node *np, 332*83ff9dcfSAnton Vorontsov struct gtm_timer *timers, 333*83ff9dcfSAnton Vorontsov struct gtm_timers_regs __iomem *regs) 334*83ff9dcfSAnton Vorontsov { 335*83ff9dcfSAnton Vorontsov /* 336*83ff9dcfSAnton Vorontsov * Yeah, I don't like this either, but timers' registers a bit messed, 337*83ff9dcfSAnton Vorontsov * so we have to provide shortcuts to write timer independent code. 338*83ff9dcfSAnton Vorontsov * Alternative option is to create gt*() accessors, but that will be 339*83ff9dcfSAnton Vorontsov * even uglier and cryptic. 340*83ff9dcfSAnton Vorontsov */ 341*83ff9dcfSAnton Vorontsov timers[0].gtcfr = ®s->gtcfr1; 342*83ff9dcfSAnton Vorontsov timers[0].gtmdr = ®s->gtmdr1; 343*83ff9dcfSAnton Vorontsov timers[0].gtcnr = ®s->gtcnr1; 344*83ff9dcfSAnton Vorontsov timers[0].gtrfr = ®s->gtrfr1; 345*83ff9dcfSAnton Vorontsov timers[0].gtevr = ®s->gtevr1; 346*83ff9dcfSAnton Vorontsov 347*83ff9dcfSAnton Vorontsov timers[1].gtcfr = ®s->gtcfr1; 348*83ff9dcfSAnton Vorontsov timers[1].gtmdr = ®s->gtmdr2; 349*83ff9dcfSAnton Vorontsov timers[1].gtcnr = ®s->gtcnr2; 350*83ff9dcfSAnton Vorontsov timers[1].gtrfr = ®s->gtrfr2; 351*83ff9dcfSAnton Vorontsov timers[1].gtevr = ®s->gtevr2; 352*83ff9dcfSAnton Vorontsov 353*83ff9dcfSAnton Vorontsov timers[2].gtcfr = ®s->gtcfr2; 354*83ff9dcfSAnton Vorontsov timers[2].gtmdr = ®s->gtmdr3; 355*83ff9dcfSAnton Vorontsov timers[2].gtcnr = ®s->gtcnr3; 356*83ff9dcfSAnton Vorontsov timers[2].gtrfr = ®s->gtrfr3; 357*83ff9dcfSAnton Vorontsov timers[2].gtevr = ®s->gtevr3; 358*83ff9dcfSAnton Vorontsov 359*83ff9dcfSAnton Vorontsov timers[3].gtcfr = ®s->gtcfr2; 360*83ff9dcfSAnton Vorontsov timers[3].gtmdr = ®s->gtmdr4; 361*83ff9dcfSAnton Vorontsov timers[3].gtcnr = ®s->gtcnr4; 362*83ff9dcfSAnton Vorontsov timers[3].gtrfr = ®s->gtrfr4; 363*83ff9dcfSAnton Vorontsov timers[3].gtevr = ®s->gtevr4; 364*83ff9dcfSAnton Vorontsov 365*83ff9dcfSAnton Vorontsov /* CPM2 doesn't have primary prescaler */ 366*83ff9dcfSAnton Vorontsov if (!of_device_is_compatible(np, "fsl,cpm2-gtm")) { 367*83ff9dcfSAnton Vorontsov timers[0].gtpsr = ®s->gtpsr1; 368*83ff9dcfSAnton Vorontsov timers[1].gtpsr = ®s->gtpsr2; 369*83ff9dcfSAnton Vorontsov timers[2].gtpsr = ®s->gtpsr3; 370*83ff9dcfSAnton Vorontsov timers[3].gtpsr = ®s->gtpsr4; 371*83ff9dcfSAnton Vorontsov } 372*83ff9dcfSAnton Vorontsov } 373*83ff9dcfSAnton Vorontsov 374*83ff9dcfSAnton Vorontsov static int __init fsl_gtm_init(void) 375*83ff9dcfSAnton Vorontsov { 376*83ff9dcfSAnton Vorontsov struct device_node *np; 377*83ff9dcfSAnton Vorontsov 378*83ff9dcfSAnton Vorontsov for_each_compatible_node(np, NULL, "fsl,gtm") { 379*83ff9dcfSAnton Vorontsov int i; 380*83ff9dcfSAnton Vorontsov struct gtm *gtm; 381*83ff9dcfSAnton Vorontsov const u32 *clock; 382*83ff9dcfSAnton Vorontsov int size; 383*83ff9dcfSAnton Vorontsov 384*83ff9dcfSAnton Vorontsov gtm = kzalloc(sizeof(*gtm), GFP_KERNEL); 385*83ff9dcfSAnton Vorontsov if (!gtm) { 386*83ff9dcfSAnton Vorontsov pr_err("%s: unable to allocate memory\n", 387*83ff9dcfSAnton Vorontsov np->full_name); 388*83ff9dcfSAnton Vorontsov continue; 389*83ff9dcfSAnton Vorontsov } 390*83ff9dcfSAnton Vorontsov 391*83ff9dcfSAnton Vorontsov spin_lock_init(>m->lock); 392*83ff9dcfSAnton Vorontsov 393*83ff9dcfSAnton Vorontsov clock = of_get_property(np, "clock-frequency", &size); 394*83ff9dcfSAnton Vorontsov if (!clock || size != sizeof(*clock)) { 395*83ff9dcfSAnton Vorontsov pr_err("%s: no clock-frequency\n", np->full_name); 396*83ff9dcfSAnton Vorontsov goto err; 397*83ff9dcfSAnton Vorontsov } 398*83ff9dcfSAnton Vorontsov gtm->clock = *clock; 399*83ff9dcfSAnton Vorontsov 400*83ff9dcfSAnton Vorontsov for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) { 401*83ff9dcfSAnton Vorontsov int ret; 402*83ff9dcfSAnton Vorontsov struct resource irq; 403*83ff9dcfSAnton Vorontsov 404*83ff9dcfSAnton Vorontsov ret = of_irq_to_resource(np, i, &irq); 405*83ff9dcfSAnton Vorontsov if (ret == NO_IRQ) { 406*83ff9dcfSAnton Vorontsov pr_err("%s: not enough interrupts specified\n", 407*83ff9dcfSAnton Vorontsov np->full_name); 408*83ff9dcfSAnton Vorontsov goto err; 409*83ff9dcfSAnton Vorontsov } 410*83ff9dcfSAnton Vorontsov gtm->timers[i].irq = irq.start; 411*83ff9dcfSAnton Vorontsov gtm->timers[i].gtm = gtm; 412*83ff9dcfSAnton Vorontsov } 413*83ff9dcfSAnton Vorontsov 414*83ff9dcfSAnton Vorontsov gtm->regs = of_iomap(np, 0); 415*83ff9dcfSAnton Vorontsov if (!gtm->regs) { 416*83ff9dcfSAnton Vorontsov pr_err("%s: unable to iomap registers\n", 417*83ff9dcfSAnton Vorontsov np->full_name); 418*83ff9dcfSAnton Vorontsov goto err; 419*83ff9dcfSAnton Vorontsov } 420*83ff9dcfSAnton Vorontsov 421*83ff9dcfSAnton Vorontsov gtm_set_shortcuts(np, gtm->timers, gtm->regs); 422*83ff9dcfSAnton Vorontsov list_add(>m->list_node, >ms); 423*83ff9dcfSAnton Vorontsov 424*83ff9dcfSAnton Vorontsov /* We don't want to lose the node and its ->data */ 425*83ff9dcfSAnton Vorontsov np->data = gtm; 426*83ff9dcfSAnton Vorontsov of_node_get(np); 427*83ff9dcfSAnton Vorontsov 428*83ff9dcfSAnton Vorontsov continue; 429*83ff9dcfSAnton Vorontsov err: 430*83ff9dcfSAnton Vorontsov kfree(gtm); 431*83ff9dcfSAnton Vorontsov } 432*83ff9dcfSAnton Vorontsov return 0; 433*83ff9dcfSAnton Vorontsov } 434*83ff9dcfSAnton Vorontsov arch_initcall(fsl_gtm_init); 435