[PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
Anton Vorontsov
avorontsov at ru.mvista.com
Fri Apr 18 02:12:39 EST 2008
On Thu, Apr 17, 2008 at 04:23:56PM +0200, Laurent Pinchart wrote:
> > + /*
> > + * We have two 8 bit prescalers -- primary and secondary (psr, sps),
> > + * plus "slow go" mode (clk / 16). So, total prescale value is
> > + * 16 * (psr + 1) * (sps + 1).
> > + */
> > + if (prescaler > 256 * 256 * 16)
> > + return -EINVAL;
> > +
> > + if (prescaler > 256 * 256) {
> > + iclk = GTMDR_ICLK_SLGO;
> > + prescaler /= 16;
> > + }
> > +
> > + if (prescaler > 256) {
> > + psr = 256 - 1;
> > + sps = prescaler / 256 - 1;
> > + } else {
> > + psr = prescaler - 1;
> > + sps = 1 - 1;
> > + }
>
> Don't forget that the CPM2 doesn't support the primary prescaler.
Here is incremental diff of how this is solved. I guess this should work.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index b0ddd54..b89c56d 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -2835,7 +2835,7 @@ platforms are moved over to use the flattened-device-tree model.
Required properties:
- compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
- GTMs).
+ GTMs or "fsl,cpm2-gtm" for CPM2 GTMs).
- reg : should contain gtm registers location and length (0x40).
- interrupts : should contain four interrupts.
- interrupt-parent : interrupt source phandle.
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
index 6d86983..105c633 100644
--- a/arch/powerpc/sysdev/fsl_gtm.c
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -125,27 +125,32 @@ static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
u8 psr;
u8 sps;
unsigned long flags;
+ int max_prescaler = 256 * 256 * 16;
+
+ /* CPM2 doesn't have primary prescaler */
+ if (!tmr->gtpsr)
+ max_prescaler /= 256;
prescaler = gtm->clock / frequency;
/*
* We have two 8 bit prescalers -- primary and secondary (psr, sps),
* plus "slow go" mode (clk / 16). So, total prescale value is
- * 16 * (psr + 1) * (sps + 1).
+ * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing psr.
*/
- if (prescaler > 256 * 256 * 16)
+ if (prescaler > max_prescaler)
return -EINVAL;
- if (prescaler > 256 * 256) {
+ if (prescaler > max_prescaler / 16) {
iclk = GTMDR_ICLK_SLGO;
prescaler /= 16;
}
- if (prescaler > 256) {
+ if (prescaler <= 256) {
+ psr = 0;
+ sps = prescaler - 1;
+ } else {
psr = 256 - 1;
sps = prescaler / 256 - 1;
- } else {
- psr = prescaler - 1;
- sps = 1 - 1;
}
spin_lock_irqsave(>m->lock, flags);
@@ -159,7 +164,8 @@ static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
setbits8(tmr->gtcfr, GTCFR_STP(num));
- out_be16(tmr->gtpsr, psr);
+ if (tmr->gtpsr)
+ out_be16(tmr->gtpsr, psr);
clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
GTMDR_ORI | (free_run ? GTMDR_FFR : 0));
out_be16(tmr->gtcnr, 0);
@@ -222,7 +228,8 @@ void gtm_stop_timer16(struct gtm_timer *tmr)
}
EXPORT_SYMBOL(gtm_stop_timer16);
-static void __init gtm_set_shortcuts(struct gtm_timer *timers,
+static void __init gtm_set_shortcuts(struct device_node *np,
+ struct gtm_timer *timers,
struct gtm_timers_regs __iomem *regs)
{
/*
@@ -233,31 +240,35 @@ static void __init gtm_set_shortcuts(struct gtm_timer *timers,
*/
timers[0].gtcfr = ®s->gtcfr1;
timers[0].gtmdr = ®s->gtmdr1;
- timers[0].gtpsr = ®s->gtpsr1;
timers[0].gtcnr = ®s->gtcnr1;
timers[0].gtrfr = ®s->gtrfr1;
timers[0].gtevr = ®s->gtevr1;
timers[1].gtcfr = ®s->gtcfr1;
timers[1].gtmdr = ®s->gtmdr2;
- timers[1].gtpsr = ®s->gtpsr2;
timers[1].gtcnr = ®s->gtcnr2;
timers[1].gtrfr = ®s->gtrfr2;
timers[1].gtevr = ®s->gtevr2;
timers[2].gtcfr = ®s->gtcfr2;
timers[2].gtmdr = ®s->gtmdr3;
- timers[2].gtpsr = ®s->gtpsr3;
timers[2].gtcnr = ®s->gtcnr3;
timers[2].gtrfr = ®s->gtrfr3;
timers[2].gtevr = ®s->gtevr3;
timers[3].gtcfr = ®s->gtcfr2;
timers[3].gtmdr = ®s->gtmdr4;
- timers[3].gtpsr = ®s->gtpsr4;
timers[3].gtcnr = ®s->gtcnr4;
timers[3].gtrfr = ®s->gtrfr4;
timers[3].gtevr = ®s->gtevr4;
+
+ /* CPM2 doesn't have primary prescaler */
+ if (!of_device_is_compatible(np, "fsl,cpm2-gtm")) {
+ timers[0].gtpsr = ®s->gtpsr1;
+ timers[1].gtpsr = ®s->gtpsr2;
+ timers[2].gtpsr = ®s->gtpsr3;
+ timers[3].gtpsr = ®s->gtpsr4;
+ }
}
static int __init gtm_init(void)
@@ -307,7 +318,7 @@ static int __init gtm_init(void)
goto err;
}
- gtm_set_shortcuts(gtm->timers, gtm->regs);
+ gtm_set_shortcuts(np, gtm->timers, gtm->regs);
/* We don't want to lose the node and its ->data */
of_node_get(np);
More information about the Linuxppc-dev
mailing list