Am Tue, Jan 24, 2023 at 10:32:49PM +0100 schrieb Mark Kettenis:
> > Date: Tue, 24 Jan 2023 20:57:48 +0100
> > From: Patrick Wildt <patr...@blueri.se>
> > 
> > Am Mon, Jan 23, 2023 at 04:34:27PM -0600 schrieb Scott Cheloha:
> > > Whoops, missed one.  This is the fifth and (I think) last armv7 clock
> > > interrupt driver that needs to switch to clockintr.  gptimer(4) is
> > > nearly identical to dmtimer(4).
> > > 
> > > Notable changes:
> > > 
> > > - Switch stathz from 128 to hz.
> > > - Switch profhz from 1024 to (stathz * 10).
> > > 
> > > Everything else in the patch is just normal clockintr switching stuff
> > > or duplicated from the dmtimer(4) patch.
> > > 
> > > jca@ has compile-tested this.
> > > 
> > > I would appreciate a test to confirm that the GENERIC boots.  I don't
> > > think we need to do a full release build.
> > > 
> > > ... if nobody knows where to find a board with gptimer(4), I am
> > > looking for permission to just commit this as-is.  I cannot find any
> > > entries in the dmesg mails of any machines with gptimer(4).  kettenis@
> > > was uncertain whether we actually support any of the machines that have
> > > this clock.
> > > 
> > > Preferences?  ok?
> > 
> > Should we just get rid of it?  It's only used on OMAP3, which was
> > already outdated when I started my ARMv7 endeavour a decade ago.
> > I never had that machine, drahn@ might have one in the attic.
> > 
> > The relevant platforms were the Pandaboard (OMAP4) and the BeagleBone
> > Black (AM335x).  But the OMAP3, did this thing ever work?
> 
> Might as well commit this such that we have it in the attic just in
> case someone wants to revive OMAP3?

Yup, sounds good to me.

> > > Index: gptimer.c
> > > ===================================================================
> > > RCS file: /cvs/src/sys/arch/armv7/omap/gptimer.c,v
> > > retrieving revision 1.17
> > > diff -u -p -r1.17 gptimer.c
> > > --- gptimer.c     22 Jan 2023 18:36:38 -0000      1.17
> > > +++ gptimer.c     22 Jan 2023 23:52:32 -0000
> > > @@ -23,9 +23,11 @@
> > >  
> > >  #include <sys/param.h>
> > >  #include <sys/systm.h>
> > > +#include <sys/clockintr.h>
> > >  #include <sys/kernel.h>
> > >  #include <sys/evcount.h>
> > >  #include <sys/device.h>
> > > +#include <sys/stdint.h>
> > >  #include <sys/timetc.h>
> > >  #include <machine/bus.h>
> > >  #include <armv7/armv7/armv7var.h>
> > > @@ -93,14 +95,12 @@
> > >  
> > >  #define TIMER_FREQUENCY                  32768   /* 32kHz is used, 
> > > selectable */
> > >  
> > > -static struct evcount clk_count;
> > > -static struct evcount stat_count;
> > > -
> > >  void gptimer_attach(struct device *parent, struct device *self, void 
> > > *args);
> > >  int gptimer_intr(void *frame);
> > >  void gptimer_wait(int reg);
> > >  void gptimer_cpu_initclocks(void);
> > >  void gptimer_delay(u_int);
> > > +void gptimer_reset_tisr(void);
> > >  void gptimer_setstatclockrate(int newhz);
> > >  
> > >  bus_space_tag_t gptimer_iot;
> > > @@ -120,13 +120,16 @@ static struct timecounter gptimer_timeco
> > >   .tc_user = 0,
> > >  };
> > >  
> > > -volatile u_int32_t nexttickevent;
> > > -volatile u_int32_t nextstatevent;
> > > -u_int32_t        ticks_per_second;
> > > -u_int32_t        ticks_per_intr;
> > > -u_int32_t        ticks_err_cnt;
> > > -u_int32_t        ticks_err_sum;
> > > -u_int32_t        statvar, statmin;
> > > +uint64_t gptimer_nsec_cycle_ratio;
> > > +uint64_t gptimer_nsec_max;
> > > +
> > > +void gptimer_rearm(void *, uint64_t);
> > > +void gptimer_trigger(void *);
> > > +
> > > +const struct intrclock gptimer_intrclock = {
> > > + .ic_rearm = gptimer_rearm,
> > > + .ic_trigger = gptimer_trigger
> > > +};
> > >  
> > >  const struct cfattach    gptimer_ca = {
> > >   sizeof (struct device), NULL, gptimer_attach
> > > @@ -177,98 +180,10 @@ gptimer_attach(struct device *parent, st
> > >       gptimer_setstatclockrate, NULL);
> > >  }
> > >  
> > > -/*
> > > - * See comment in arm/xscale/i80321_clock.c
> > > - *
> > > - * counter is count up, but with autoreload timers it is not possible
> > > - * to detect how many  interrupts passed while interrupts were blocked.
> > > - * also it is not possible to atomically add to the register
> > > - * get get it to precisely fire at a non-fixed interval.
> > > - *
> > > - * To work around this two timers are used, GPT1 is used as a reference
> > > - * clock without reload , however we just ignore the interrupt it
> > > - * would (may?) generate.
> > > - *
> > > - * Internally this keeps track of when the next timer should fire
> > > - * and based on that time and the current value of the reference
> > > - * clock a number is written into the timer count register to schedule
> > > - * the next event.
> > > - */
> > > -
> > >  int
> > >  gptimer_intr(void *frame)
> > >  {
> > > - u_int32_t now, r;
> > > - u_int32_t nextevent, duration;
> > > -
> > > - /* clear interrupt */
> > > - now = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
> > > -
> > > - while ((int32_t) (nexttickevent - now) < 0) {
> > > -         nexttickevent += ticks_per_intr;
> > > -         ticks_err_sum += ticks_err_cnt;
> > > -#if 0
> > > -         if (ticks_err_sum  > hz) {
> > > -                 u_int32_t match_error;
> > > -                 match_error = ticks_err_sum / hz
> > > -                 ticks_err_sum -= (match_error * hz);
> > > -         }
> > > -#else
> > > -         /* looping a few times is faster than divide */
> > > -         while (ticks_err_sum  > hz) {
> > > -                 nexttickevent += 1;
> > > -                 ticks_err_sum -= hz;
> > > -         }
> > > -#endif
> > > -         clk_count.ec_count++;
> > > -         hardclock(frame);
> > > - }
> > > - while ((int32_t) (nextstatevent - now) < 0) {
> > > -         do {
> > > -                 r = random() & (statvar -1);
> > > -         } while (r == 0); /* random == 0 not allowed */
> > > -         nextstatevent += statmin + r;
> > > -         /* XXX - correct nextstatevent? */
> > > -         stat_count.ec_count++;
> > > -         statclock(frame);
> > > - }
> > > - if ((nexttickevent - now) < (nextstatevent - now))
> > > -                nextevent = nexttickevent;
> > > -        else
> > > -                nextevent = nextstatevent;
> > > -
> > > -/* XXX */
> > > - duration = nextevent -
> > > -     bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
> > > -#if 0
> > > - printf("duration 0x%x %x %x\n", nextevent -
> > > -     bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR),
> > > -     bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TCRR),
> > > -     bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR));
> > > -#endif
> > > -
> > > -
> > > -        if (duration <= 0)
> > > -                duration = 1; /* trigger immediately. */
> > > -
> > > -        if (duration > ticks_per_intr) {
> > > -                /*
> > > -                 * If interrupts are blocked too long, like during
> > > -                 * the root prompt or ddb, the timer can roll over,
> > > -                 * this will allow the system to continue to run
> > > -                 * even if time is lost.
> > > -                 */
> > > -                duration = ticks_per_intr;
> > > -                nexttickevent = now;
> > > -                nextstatevent = now;
> > > -        }
> > > -
> > > - gptimer_wait(GP_TWPS_ALL);
> > > - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR,
> > > -         bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR));
> > > - gptimer_wait(GP_TWPS_ALL);
> > > -        bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -duration);
> > > - 
> > > + clockintr_dispatch(frame);
> > >   return 1;
> > >  }
> > >  
> > > @@ -281,44 +196,31 @@ gptimer_intr(void *frame)
> > >  void
> > >  gptimer_cpu_initclocks(void)
> > >  {
> > > - stathz = 128;
> > > - profhz = 1024;
> > > + stathz = hz;
> > > + profhz = stathz * 10;
> > > + clockintr_init(CL_RNDSTAT);
> > >  
> > > - ticks_per_second = TIMER_FREQUENCY;
> > > -
> > > - setstatclockrate(stathz);
> > > -
> > > - ticks_per_intr = ticks_per_second / hz;
> > > - ticks_err_cnt = ticks_per_second % hz;
> > > - ticks_err_sum = 0;
> > > + gptimer_nsec_cycle_ratio = TIMER_FREQUENCY * (1ULL << 32) / 1000000000;
> > > + gptimer_nsec_max = UINT64_MAX / gptimer_nsec_cycle_ratio;
> > >  
> > >   prcm_setclock(1, PRCM_CLK_SPEED_32);
> > >   prcm_setclock(2, PRCM_CLK_SPEED_32);
> > > +
> > >   /* establish interrupts */
> > >   arm_intr_establish(gptimer_irq, IPL_CLOCK, gptimer_intr,
> > >       NULL, "tick");
> > >  
> > >   /* setup timer 0 (hardware timer 2) */
> > >   /* reset? - XXX */
> > > -
> > > -        bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TLDR, 0);
> > > -
> > > - nexttickevent = nextstatevent = bus_space_read_4(gptimer_iot,
> > > -     gptimer_ioh1, GP_TCRR) + ticks_per_intr;
> > > -
> > >   gptimer_wait(GP_TWPS_ALL);
> > >   bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TIER, GP_TIER_OVF_EN);
> > >   gptimer_wait(GP_TWPS_ALL);
> > >   bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TWER, GP_TWER_OVF_EN);
> > >   gptimer_wait(GP_TWPS_ALL);
> > > - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR,
> > > -     GP_TCLR_AR | GP_TCLR_ST);
> > > - gptimer_wait(GP_TWPS_ALL);
> > > - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR,
> > > -         bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR));
> > > - gptimer_wait(GP_TWPS_ALL);
> > > - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -ticks_per_intr);
> > > - gptimer_wait(GP_TWPS_ALL);
> > > +
> > > + /* start the clock interrupt cycle */
> > > + clockintr_cpu_init(&gptimer_intrclock);
> > > + clockintr_trigger();
> > >  }
> > >  
> > >  void
> > > @@ -328,6 +230,61 @@ gptimer_wait(int reg)
> > >           ;
> > >  }
> > >  
> > > +/*
> > > + * Clear all interrupt status bits.
> > > + */
> > > +void
> > > +gptimer_reset_tisr(void)
> > > +{
> > > + u_int32_t tisr;
> > > +
> > > + tisr = bus_space_read_4(gptimer_iot, gptimerioh0, GP_TISR);
> > > + bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR, tisr);
> > > +}
> > > +
> > > +void
> > > +gptimer_rearm(void *unused, uint64_t nsecs)
> > > +{
> > > + uint32_t cycles;
> > > + u_long s;
> > > +
> > > + if (nsecs > gptimer_nsec_max)
> > > +         nsecs = gptimer_nsec_max;
> > > + cycles = (nsecs * gptimer_nsec_cycle_ratio) >> 32;
> > > +
> > > + s = intr_disable();
> > > + gptimer_reset_tisr();
> > > +        bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR,
> > > +     UINT32_MAX - cycles);
> > > + bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, GP_TCLR_ST);
> > > + gptimer_wait(GP_TWPS_ALL);
> > > + intr_restore(s);
> > > +}
> > > +
> > > +void
> > > +gptimer_trigger(void *unused)
> > > +{
> > > + u_long s;
> > > +
> > > + s = intr_disable();
> > > +
> > > + /* stop timer. */
> > > + bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, 0);
> > > + gptimer_wait(GP_TWPS_ALL);
> > > +
> > > + /* clear interrupt status bits. */
> > > + gptimer_reset_tisr();
> > > +
> > > + /* set shortest possible timeout. */
> > > + bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, UINT32_MAX);
> > > +
> > > + /* start timer, wait for writes to post. */
> > > + bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, GP_TCLR_ST);
> > > + gptimer_wait(GP_TWPS_ALL);
> > > +
> > > + intr_restore(s);
> > > +}
> > > +
> > >  void
> > >  gptimer_delay(u_int usecs)
> > >  {
> > > @@ -370,26 +327,7 @@ gptimer_delay(u_int usecs)
> > >  void
> > >  gptimer_setstatclockrate(int newhz)
> > >  {
> > > - int minint, statint;
> > > - int s;
> > > - 
> > > - s = splclock();
> > > -
> > > - statint = ticks_per_second / newhz;
> > > - /* calculate largest 2^n which is smaller that just over half statint */
> > > - statvar = 0x40000000; /* really big power of two */
> > > - minint = statint / 2 + 100;
> > > - while (statvar > minint)
> > > -         statvar >>= 1;
> > > -
> > > - statmin = statint - (statvar >> 1);
> > > - 
> > > - splx(s);
> > > -
> > > - /*
> > > -  * XXX this allows the next stat timer to occur then it switches
> > > -  * to the new frequency. Rather than switching instantly.
> > > -  */
> > > + clockintr_setstatclockrate(newhz);
> > >  }
> > >  
> > >  
> > > 
> > 
> > 
> 

Reply via email to