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