Hi,

i'm unsure about the accepted way of working around irregular registers,
like would be needed with supporting Mentor OTG USB on both omap&sunxi
on armv7. irregular as in _no_ correlation what so ever, so off*4 kind
of solution does not apply.
My question in particular is; is (ab)using bus_space for this accepted
workaround?

NetBSD, where the driver got ported from, does have #ifdef MOTG_ALLWINNER
which is obviously not possible, given GENERIC and its nature as true
'uni-mono-kernel'. i was actually a bit shocked when i figured how many
arm kernel configs etc. they get to have maintenance-fun with if/when
necessary :)

reason why i think this is better than any other method to solve it in
run-time rather than compile-time is, because it wouldn't affect other
than the offender(=sunxi/Allwinner), no matter how ugly.

shortened(actually +30cases in switch below) to show something like
what i would propose:

struct armv7_bus_space_tag sxiotg_bustag;

void
sxiotg_attach(struct device *parent, struct device *self, void *args)
{
        /* ... */
        sxiotg_bus_init();
        sc->sc_motg.sc_bus.dmatag = &armv7_bus_dma_tag;
        sc->sc_motg.sc_iot = &sxiotg_bustag;
        /* ... */
        printf(": OTG\n");
        motg_init(&sc->sc_motg);
}

bus_size_t      sxiotg_bs_hook(bus_size_t);
u_int8_t        sxiotg_bs_r_1(void *, bus_space_handle_t, bus_size_t);
u_int16_t       sxiotg_bs_r_2(void *, bus_space_handle_t, bus_size_t);
void    sxiotg_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t);
void    sxiotg_bs_w_2(void *, bus_space_handle_t, bus_size_t, u_int16_t);

void
sxiotg_bus_init(void)
{
        memcpy(&sxiotg_bustag, &mainbus_bustag,
            sizeof(struct armv7_bus_space_tag));
        sxiotg_bustag.bs_r_1 = sxiotg_bs_r_1;
        sxiotg_bustag.bs_w_1 = sxiotg_bs_w_1;
        sxiotg_bustag.bs_r_2 = sxiotg_bs_r_2;
        sxiotg_bustag.bs_w_2 = sxiotg_bs_w_2;
        /* tododiddone */
}

bus_size_t
sxiotg_bshook(bus_size_t off)
{
        /* XXX separate hooks for 1&2 for less cases per switch?? */
        switch (off) {
        case MUSB2_REG_FADDR:
                return MUSB2_REG_FADDR_AW;
        case MUSB2_REG_POWER:
                return MUSB2_REG_POWER_AW;
        case MUSB2_REG_DEVCTL:
                return MUSB2_REG_DEVCTL_AW;
#if 0   /*
         * XXX duplicate case w/ _CONFDATA, but this is never hit on sunxi,
         * because we set sc_ep_fifosize, and so _FSIZE does not get read.
         */
        case MUSB2_REG_FSIZE:
                return MUSB2_REG_FSIZE_AW;
#endif
        case MUSB2_REG_EPFIFO(0):
                return MUSB2_REG_EPFIFO_AW(0);
        case MUSB2_REG_EPFIFO(1):
                return MUSB2_REG_EPFIFO_AW(1);
        case MUSB2_REG_EPFIFO(2):
                return MUSB2_REG_EPFIFO_AW(2);
        case MUSB2_REG_CONFDATA:
                return MUSB2_REG_CONFDATA_AW;
        case MUSB2_REG_TXFADDR(0):
                return MUSB2_REG_TXFADDR_AW;
        }
        return off;
}

u_int8_t
sxiotg_bs_r_1(void *bst, bus_space_handle_t bsh, bus_size_t off)
{
        return mainbus_bustag.bs_r_1(&mainbus_bustag, bsh, sxiotg_bshook(off));
}

u_int16_t
sxiotg_bs_r_2(void *bst, bus_space_handle_t bsh, bus_size_t off)
{
        return mainbus_bustag.bs_r_2(&mainbus_bustag, bsh, sxiotg_bshook(off));
}

void
sxiotg_bs_w_1(void *bst, bus_space_handle_t bsh, bus_size_t off, u_int8_t val)
{
        mainbus_bustag.bs_w_1(&mainbus_bustag, bsh, sxiotg_bshook(off), val);
}

void
sxiotg_bs_w_2(void *bst, bus_space_handle_t bsh, bus_size_t off, u_int16_t val)
{
        mainbus_bustag.bs_w_2(&mainbus_bustag, bsh, sxiotg_bshook(off), val);
}


-Artturi

Reply via email to