#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/bus.h>
#include <armv7/armv7/armv7var.h>
#include <armv7/omap/prcmvar.h>
#define USBTLL_REVISION 0x0000
#define USBTLL_SYSCONFIG 0x0010
#define USBTLL_SYSSTATUS 0x0014
#define USBTLL_IRQSTATUS 0x0018
#define USBTLL_IRQENABLE 0x001C
#define USBTLL_SHARED_CONF 0x0030
#define USBTLL_SHARED_CONF_USB_90D_DDR_EN (1<<6)
#define USBTLL_SHARED_CONF_USB_180D_SDR_EN (1<<5)
#define USBTLL_SHARED_CONF_USB_DIVRATIO_SH 2
#define USBTLL_SHARED_CONF_FCLK_REQ (1<<1)
#define USBTLL_SHARED_CONF_FCLK_IS_ON (1<<0)
#define USBTLL_CHANNEL_CONF_(i) (0x0040 + (0x04 * (i)))
#define USBTLL_CHANNEL_CONF_FSLSLINESTATE_SH 28
#define USBTLL_CHANNEL_CONF_FSLSMODE_SH 24
#define USBTLL_CHANNEL_CONF_TESTTXSE0 (1<<20)
#define USBTLL_CHANNEL_CONF_TESTTXDAT (1<<19)
#define USBTLL_CHANNEL_CONF_TESTTXEN (1<<18)
#define USBTLL_CHANNEL_CONF_TESTEN (1<<17)
#define USBTLL_CHANNEL_CONF_DRVVBUS (1<<16)
#define USBTLL_CHANNEL_CONF_CHRGVBUS (1<<15)
#define USBTLL_CHANNEL_CONF_ULPINOBITSTUFF (1<<11)
#define USBTLL_CHANNEL_CONF_ULPIAUTOIDLE (1<<10)
#define USBTLL_CHANNEL_CONF_UTMIAUTOIDLE (1<<9)
#define USBTLL_CHANNEL_CONF_ULPIDDRMODE (1<<8)
#define USBTLL_CHANNEL_CONF_LPIOUTCLKMODE (1<<7)
#define USBTLL_CHANNEL_CONF_TLLFULLSPEED (1<<6)
#define USBTLL_CHANNEL_CONF_TLLCONNECT (1<<5)
#define USBTLL_CHANNEL_CONF_TLLATTACH (1<<4)
#define USBTLL_CHANNEL_CONF_UTMIISADEV (1<<3)
#define USBTLL_CHANNEL_CONF_CHANMODE_SH 1
#define USBTLL_CHANNEL_CONF_CHANEN (1<<0)
struct omusbtll_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
};
void omusbtll_attach(struct device *parent, struct device *self, void *args);
void omusbtll_init(uint32_t channel_mask);
const struct cfattach omusbtll_ca = {
sizeof (struct omusbtll_softc), NULL, omusbtll_attach
};
struct cfdriver omusbtll_cd = {
NULL, "omusbtll", DV_DULL
};
struct omusbtll_softc *omusbtll_sc;
void
omusbtll_attach(struct device *parent, struct device *self, void *args)
{
struct omusbtll_softc *sc = (struct omusbtll_softc *) self;
struct armv7_attach_args *aa = args;
u_int32_t rev;
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)) {
printf("%s: bus_space_map failed!\n", __func__);
return;
}
#if 0
prcm_enablemodule(PRCM_USBHOST1);
prcm_enablemodule(PRCM_USBHOST2);
#endif
prcm_enablemodule(PRCM_USBTLL);
delay(10000);
#if 1
rev = bus_space_read_1(sc->sc_iot, sc->sc_ioh, USBTLL_SYSCONFIG);
printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
#endif
omusbtll_sc = sc;
omusbtll_init(0x3);
}
void
omusbtll_init(uint32_t channel_mask)
{
int i;
uint32_t val;
struct omusbtll_softc *sc = omusbtll_sc;
for(i = 0; i < 3; i++) {
val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
USBTLL_CHANNEL_CONF_(i));
val &= ~(USBTLL_CHANNEL_CONF_ULPINOBITSTUFF |
USBTLL_CHANNEL_CONF_ULPIAUTOIDLE |
USBTLL_CHANNEL_CONF_ULPIDDRMODE);
bus_space_write_4(sc->sc_iot, sc->sc_ioh,
USBTLL_CHANNEL_CONF_(i), val);
}
val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBTLL_SHARED_CONF);
val |= (USBTLL_SHARED_CONF_USB_180D_SDR_EN |
(1 << USBTLL_SHARED_CONF_USB_DIVRATIO_SH) |
USBTLL_SHARED_CONF_FCLK_IS_ON);
val &= ~(USBTLL_SHARED_CONF_USB_90D_DDR_EN);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBTLL_SHARED_CONF, val);
for (i = 0; i < 3; i++) {
if (channel_mask & (1<<i)) {
val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
USBTLL_CHANNEL_CONF_(i));
val |= USBTLL_CHANNEL_CONF_CHANEN;
bus_space_write_4(sc->sc_iot, sc->sc_ioh,
USBTLL_CHANNEL_CONF_(i), val);
printf("usbtll enabling %d\n", i);
}
}
}