On Sun, Jan 31, 2016 at 10:12:05AM +0200, Artturi Alm wrote:
> On Sun, Jan 31, 2016 at 01:14:35AM +0100, Patrick Wildt wrote:
> > Hi,
> >
> > one of the reasons Allwinner A20/sun7i-based boards, like the
> > Cubieboard 2 or Banana Pi, don't boot is that the sxitimer does
> > not work for us. We are getting no hardclock ticks and so the
> > system can't work.
> >
> > There's a simple fix for that. We can just not use the sxitimer
> > and instead use the ARM architected timer (agtimer) that is
> > supposed to be a generic implementation for all new cores and
> > already attaches anyway. The sxitimer attachment currently
> > overrides the agtimer. Removing sxitimer thus allows agtimer
> > to actually do its work.
> >
> > Currently sxirtc uncondtionally ties into sxitimer. To make
> > this work, just make sxirtc map its own page instead of relying
> > on the existence of a mapping created by sxitimer.
> >
> > The address/size used for the sxirtc is from a device tree
> > source.
> >
> > Patrick
> >
>
> Hi,
>
> nothing i would change about your diff, given now there's agtimer,
> but it doesn't really seem to even try fixing rtc on A20, and leaves
> ugly glue into sxitimer written just for A20, which imho should also
> get cleaned up.
>
> -Artturi
There seem to be at least two diffs here, the different rtc handling
for a20 should be split out, store sxirtc_a20 in the softc and fix
the test from
if (BOARD_ID_SUN7I_A20)
to
if (board_id == BOARD_ID_SUN7I_A20)
>
>
> diff --git a/sys/arch/armv7/sunxi/sun7i.c b/sys/arch/armv7/sunxi/sun7i.c
> index 0d06b31..d8fcd45 100644
> --- a/sys/arch/armv7/sunxi/sun7i.c
> +++ b/sys/arch/armv7/sunxi/sun7i.c
> @@ -39,19 +39,6 @@ struct armv7_dev sxia20_devs[] = {
> .mem = { { CCMU_ADDR, CCMU_SIZE } },
> },
>
> - /* Timers/Counters, resources mapped on first unit */
> - { .name = "sxitimer",
> - .unit = 0,
> - .mem = { { TIMER_ADDR, TIMERx_SIZE },
> - { CPUCNTRS_ADDR, CPUCNTRS_ADDR } }
> - },
> - { .name = "sxitimer",
> - .unit = 1,
> - },
> - { .name = "sxitimer",
> - .unit = 2,
> - },
> -
> /* Watchdog Timer */
> { .name = "sxidog",
> .unit = 0,
> diff --git a/sys/arch/armv7/sunxi/sxirtc.c b/sys/arch/armv7/sunxi/sxirtc.c
> index 32460d6..cdd6716 100644
> --- a/sys/arch/armv7/sunxi/sxirtc.c
> +++ b/sys/arch/armv7/sunxi/sxirtc.c
> @@ -15,9 +15,6 @@
> * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> */
> -/* XXX this doesn't support A20 yet. */
> - /* year & 0xff on A20, 0x3f on A10 */
> - /* leap << 24 on A20, << 22 on A10 */
>
> #include <sys/param.h>
> #include <sys/device.h>
> @@ -40,9 +37,6 @@
> (y) % 400 == 0)
>
>
> -/* XXX other way around than bus_space_subregion? */
> -extern bus_space_handle_t sxitimer_ioh;
> -
> extern todr_chip_handle_t todr_handle;
>
> struct sxirtc_softc {
> @@ -61,6 +55,8 @@ struct cfdriver sxirtc_cd = {
> NULL, "sxirtc", DV_DULL
> };
>
> +uint32_t sxirtc_a20 = 0;
> +
> int sxirtc_gettime(todr_chip_handle_t, struct timeval *);
> int sxirtc_settime(todr_chip_handle_t, struct timeval *);
>
> @@ -78,7 +74,10 @@ sxirtc_attach(struct device *parent, struct device *self,
> void *args)
> sc->sc_iot = aa->aa_iot;
> if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
> aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
> - panic("sxirtc_attach: bus_space_subregion failed!");
> + panic("sxirtc_attach: bus_space_map failed!");
> +
> + if (BOARD_ID_SUN7I_A20)
> + sxirtc_a20 = 1;
>
> handle->cookie = self;
> handle->todr_gettime = sxirtc_gettime;
> @@ -97,6 +96,8 @@ sxirtc_gettime(todr_chip_handle_t handle, struct timeval
> *tv)
> {
> struct sxirtc_softc *sc = (struct sxirtc_softc *)handle->cookie;
> struct clock_ymdhms dt;
> + uint32_t base_year = sxirtc_a20 ? 1970 : 2010;
> + uint32_t year_mask = sxirtc_a20 ? 0xff : 0x3f;
> uint32_t reg;
>
> reg = SXIREAD4(sc, SXIRTC_HHMMSS);
> @@ -108,7 +109,7 @@ sxirtc_gettime(todr_chip_handle_t handle, struct timeval
> *tv)
> reg = SXIREAD4(sc, SXIRTC_YYMMDD);
> dt.dt_day = reg & 0x1f;
> dt.dt_mon = reg >> 8 & 0x0f;
> - dt.dt_year = (reg >> 16 & 0x3f) + 2010; /* 0xff on A20 */
> + dt.dt_year = (reg >> 16 & year_mask) + base_year;
>
> if (dt.dt_sec > 59 || dt.dt_min > 59 ||
> dt.dt_hour > 23 || dt.dt_wday > 6 ||
> @@ -126,6 +127,8 @@ sxirtc_settime(todr_chip_handle_t handle, struct timeval
> *tv)
> {
> struct sxirtc_softc *sc = (struct sxirtc_softc *)handle->cookie;
> struct clock_ymdhms dt;
> + uint32_t base_year = sxirtc_a20 ? 1970 : 2010;
> + uint32_t leap_shift = sxirtc_a20 ? 24 : 22;
>
> clock_secs_to_ymdhms(tv->tv_sec, &dt);
>
> @@ -140,8 +143,8 @@ sxirtc_settime(todr_chip_handle_t handle, struct timeval
> *tv)
> (dt.dt_wday << 29));
>
> SXICMS4(sc, SXIRTC_YYMMDD, 0x00400000 | 0x003f0000 | 0x0f00 | 0x1f,
> - dt.dt_day | (dt.dt_mon << 8) | ((dt.dt_year - 2010) << 16) |
> - (LEAPYEAR(dt.dt_year) << 22));
> + dt.dt_day | (dt.dt_mon << 8) | ((dt.dt_year - base_year) << 16) |
> + (LEAPYEAR(dt.dt_year) << leap_shift));
>
> return 0;
> }
> diff --git a/sys/arch/armv7/sunxi/sxitimer.c b/sys/arch/armv7/sunxi/sxitimer.c
> index c07f85a..97eb51b 100644
> --- a/sys/arch/armv7/sunxi/sxitimer.c
> +++ b/sys/arch/armv7/sunxi/sxitimer.c
> @@ -44,11 +44,6 @@
> #define TIMER_INTV(x) (0x14 + (0x10 * (x)))
> #define TIMER_CURR(x) (0x18 + (0x10 * (x)))
>
> -/* A20 counter, relative to CPUCNTRS_ADDR */
> -#define OSC24M_CNT64_CTRL 0x80
> -#define OSC24M_CNT64_LOW 0x84
> -#define OSC24M_CNT64_HIGH 0x88
> -
> /* A1X counter */
> #define CNT64_CTRL 0xa0
> #define CNT64_LOW 0xa4
> @@ -56,7 +51,6 @@
>
> #define CNT64_CLR_EN (1 << 0) /* clear enable */
> #define CNT64_RL_EN (1 << 1) /* read latch enable */
> -#define CNT64_SYNCH (1 << 4) /* sync to OSC24M counter */
>
> #define LOSC_CTRL 0x100
> #define OSC32K_SRC_SEL (1 << 0)
> @@ -99,7 +93,6 @@ static struct timecounter sxitimer_timecounter = {
>
> bus_space_tag_t sxitimer_iot;
> bus_space_handle_t sxitimer_ioh;
> -bus_space_handle_t sxitimer_cntr_ioh;
>
> uint32_t sxitimer_freq[] = {
> TIMER0_FREQUENCY,
> @@ -120,10 +113,6 @@ uint32_t sxitimer_statvar, sxitimer_statmin;
> uint32_t sxitimer_tick_nextevt, sxitimer_stat_nextevt;
> uint32_t sxitimer_ticks_err_cnt, sxitimer_ticks_err_sum;
>
> -bus_addr_t cntr64_ctrl = CNT64_CTRL;
> -bus_addr_t cntr64_low = CNT64_LOW;
> -bus_addr_t cntr64_high = CNT64_HIGH;
> -
> struct sxitimer_softc {
> struct device sc_dev;
> };
> @@ -140,7 +129,7 @@ void
> sxitimer_attach(struct device *parent, struct device *self, void *args)
> {
> struct armv7_attach_args *aa = args;
> - uint32_t freq, ival, now, cr, v;
> + uint32_t freq, ival, now, cr;
> int unit = self->dv_unit;
>
> if (unit != 0)
> @@ -152,29 +141,10 @@ sxitimer_attach(struct device *parent, struct device
> *self, void *args)
> aa->aa_dev->mem[0].size, 0, &sxitimer_ioh))
> panic("sxitimer_attach: bus_space_map failed!");
>
> -
> - if (board_id == BOARD_ID_SUN7I_A20) {
> - if (bus_space_map(sxitimer_iot, CPUCNTRS_ADDR, CPUCNTRS_SIZE,
> - 0, &sxitimer_cntr_ioh))
> - panic("sxitimer_attach: bus_space_map failed!");
> -
> - cntr64_ctrl = OSC24M_CNT64_CTRL;
> - cntr64_low = OSC24M_CNT64_LOW;
> - cntr64_high = OSC24M_CNT64_HIGH;
> -
> - v = bus_space_read_4(sxitimer_iot, sxitimer_cntr_ioh,
> - cntr64_ctrl);
> - bus_space_write_4(sxitimer_iot, sxitimer_cntr_ioh, cntr64_ctrl,
> - v | CNT64_SYNCH);
> - bus_space_write_4(sxitimer_iot, sxitimer_cntr_ioh, cntr64_ctrl,
> - v & ~CNT64_SYNCH);
> - } else
> - sxitimer_cntr_ioh = sxitimer_ioh;
> -
> /* clear counter, loop until ready */
> - bus_space_write_4(sxitimer_iot, sxitimer_cntr_ioh, cntr64_ctrl,
> + bus_space_write_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL,
> CNT64_CLR_EN); /* XXX as a side-effect counter clk src=OSC24M */
> - while (bus_space_read_4(sxitimer_iot, sxitimer_cntr_ioh, cntr64_ctrl)
> + while (bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL)
> & CNT64_CLR_EN)
> continue;
>
> @@ -398,9 +368,8 @@ sxitimer_readcnt64(void)
> uint32_t low, high;
>
> /* latch counter, loop until ready */
> - bus_space_write_4(sxitimer_iot, sxitimer_cntr_ioh,
> - cntr64_ctrl, CNT64_RL_EN);
> - while (bus_space_read_4(sxitimer_iot, sxitimer_cntr_ioh, cntr64_ctrl)
> + bus_space_write_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL, CNT64_RL_EN);
> + while (bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL)
> & CNT64_RL_EN)
> continue;
>
> @@ -409,8 +378,8 @@ sxitimer_readcnt64(void)
> * iirc. A20 manual mentions that low should be read first.
> */
> /* XXX check above */
> - low = bus_space_read_4(sxitimer_iot, sxitimer_cntr_ioh, cntr64_low);
> - high = bus_space_read_4(sxitimer_iot, sxitimer_cntr_ioh, cntr64_high);
> + low = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_LOW);
> + high = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_HIGH);
> return (uint64_t)high << 32 | low;
> }
>
>