Date: Sun, 30 Dec 2018 10:42:39 -0700 From: Ian Lepore <ian@freebsd.org> To: SAITOU Toshihide <toshi@ruby.ocn.ne.jp>, freebsd-arm@freebsd.org Subject: Re: SPI start bit (9 bit) for BBB Message-ID: <1546191759.78877.91.camel@freebsd.org> In-Reply-To: <20181231.003356.1147810385398844555.toshi@ruby.ocn.ne.jp> References: <20181231.003356.1147810385398844555.toshi@ruby.ocn.ne.jp>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 2018-12-31 at 00:33 +0900, SAITOU Toshihide wrote: > In 3-line serial protcol, there is a type using additional 1-bit to > specify command or data. The BBB can handle this, so I can use with > the following patch (unskillful and maybe side effects exist). I > hope this will attract someones interest to implement this and also > SPI frequency and mode. > > > --- arm/ti/ti_spi.c.orig 2018-12-22 00:47:12.096034000 +0900 > +++ arm/ti/ti_spi.c 2018-12-30 23:58:00.000000000 +0900 > @@ -493,6 +493,7 @@ ti_spi_transfer(device_t dev, device_t child, > struct s > /* Disable the FIFO. */ > TI_SPI_WRITE(sc, MCSPI_XFERLEVEL, 0); > > +#if 0 > /* 8 bits word, d0 miso, d1 mosi, mode 0 and CS active low. > */ > reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs)); > reg &= ~(MCSPI_CONF_FFER | MCSPI_CONF_FFEW | > MCSPI_CONF_SBPOL | > @@ -501,6 +502,7 @@ ti_spi_transfer(device_t dev, device_t child, > struct s > MCSPI_CONF_DMAW | MCSPI_CONF_EPOL); > reg |= MCSPI_CONF_DPE0 | MCSPI_CONF_EPOL | > MCSPI_CONF_WL8BITS; > TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg); > +#endif > > #if 0 > /* Enable channel interrupts. */ > @@ -558,6 +560,70 @@ ti_spi_get_node(device_t bus, device_t dev) > return (ofw_bus_get_node(bus)); > } > > +static int > +ti_spi_sbe(device_t dev, device_t child, uint32_t *request) > +{ > + struct ti_spi_softc *sc; > + uint32_t reg; > + > + sc = device_get_softc(dev); > + > + TI_SPI_LOCK(sc); > + > + /* If the controller is in use wait until it is available. > */ > + while (sc->sc_flags & TI_SPI_BUSY) > + mtx_sleep(dev, &sc->sc_mtx, 0, "ti_spi", 0); > + > + /* Now we have control over SPI controller. */ > + sc->sc_flags = TI_SPI_BUSY; > + > + reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs)); > + if (*request) > + reg |= MCSPI_CONF_SBE; > + else > + reg &= ~MCSPI_CONF_SBE; > + TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg); > + > + /* Release the controller and wakeup the next thread waiting > for it. */ > + sc->sc_flags = 0; > + wakeup_one(dev); > + TI_SPI_UNLOCK(sc); > + > + return (0); > +} > + > +static int > +ti_spi_sbpol(device_t dev, device_t child, uint32_t *request) > +{ > + struct ti_spi_softc *sc; > + uint32_t reg; > + > + sc = device_get_softc(dev); > + > + TI_SPI_LOCK(sc); > + > + /* If the controller is in use wait until it is available. > */ > + while (sc->sc_flags & TI_SPI_BUSY) > + mtx_sleep(dev, &sc->sc_mtx, 0, "ti_spi", 0); > + > + /* Now we have control over SPI controller. */ > + sc->sc_flags = TI_SPI_BUSY; > + > + reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs)); > + if (*request) > + reg |= MCSPI_CONF_SBPOL; > + else > + reg &= ~MCSPI_CONF_SBPOL; > + TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg); > + > + /* Release the controller and wakeup the next thread waiting > for it. */ > + sc->sc_flags = 0; > + wakeup_one(dev); > + TI_SPI_UNLOCK(sc); > + > + return (0); > +} > + > static device_method_t ti_spi_methods[] = { > /* Device interface */ > DEVMETHOD(device_probe, ti_spi_probe), > @@ -569,6 +635,10 @@ static device_method_t ti_spi_methods[] = { > > /* ofw_bus interface */ > DEVMETHOD(ofw_bus_get_node, ti_spi_get_node), > + > + /* provisional chip register interface for SBE and SBPOL */ > + DEVMETHOD(spibus_sbe, ti_spi_sbe), > + DEVMETHOD(spibus_sbpol, ti_spi_sbpol), > > DEVMETHOD_END > }; > --- dev/spibus/spibus.c.orig 2018-12-29 23:50:40.262296000 > +0900 > +++ dev/spibus/spibus.c 2018-12-30 23:58:00.000000000 +0900 > @@ -226,6 +226,18 @@ spibus_transfer_impl(device_t dev, device_t > child, str > return (SPIBUS_TRANSFER(device_get_parent(dev), child, > cmd)); > } > > +static int > +spibus_sbe_impl(device_t dev, device_t child, uint32_t *request) > +{ > + return (SPIBUS_SBE(device_get_parent(dev), child, request)); > +} > + > +static int > +spibus_sbpol_impl(device_t dev, device_t child, uint32_t *request) > +{ > + return (SPIBUS_SBPOL(device_get_parent(dev), child, > request)); > +} > + > static device_method_t spibus_methods[] = { > /* Device interface */ > DEVMETHOD(device_probe, spibus_probe), > @@ -247,6 +259,9 @@ static device_method_t spibus_methods[] = { > > /* spibus interface */ > DEVMETHOD(spibus_transfer, spibus_transfer_impl), > + > + DEVMETHOD(spibus_sbe, spibus_sbe_impl), > + DEVMETHOD(spibus_sbpol, spibus_sbpol_impl), > > DEVMETHOD_END > }; > --- dev/spibus/spibus_if.m.orig 2018-12-22 00:49:22.440211000 > +0900 > +++ dev/spibus/spibus_if.m 2018-12-30 23:58:00.000000000 +0900 > @@ -39,3 +39,15 @@ METHOD int transfer { > device_t child; > struct spi_command *cmd; > }; > + > +METHOD int sbe { > + device_t dev; > + device_t child; > + uint32_t *request; > +}; > + > +METHOD int sbpol { > + device_t dev; > + device_t child; > + uint32_t *request; > +}; > --- dev/spibus/spigen.c.orig 2018-12-29 20:19:20.584696000 > +0900 > +++ dev/spibus/spigen.c 2018-12-30 23:58:00.000000000 +0900 > @@ -248,6 +248,28 @@ spigen_transfer_mmapped(struct cdev *cdev, > struct spig > } > > static int > +spigen_sbe(struct cdev *cdev, uint32_t *request) > +{ > + device_t dev = cdev->si_drv1; > + int error = 0; > + > + error = SPIBUS_SBE(device_get_parent(dev), dev, (uint32_t > *)request); > + > + return (error); > +} > + > +static int > +spigen_sbpol(struct cdev *cdev, uint32_t *request) > +{ > + device_t dev = cdev->si_drv1; > + int error = 0; > + > + error = SPIBUS_SBPOL(device_get_parent(dev), dev, (uint32_t > *)request); > + > + return (error); > +} > + > +static int > spigen_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, > struct thread *td) > { > @@ -272,6 +294,12 @@ spigen_ioctl(struct cdev *cdev, u_long cmd, > caddr_t da > break; > case SPIGENIOC_SET_SPI_MODE: > error = spibus_set_mode(dev, *(uint32_t *)data); > + break; > + case SPIGENIOC_SBE: > + error = spigen_sbe(cdev, (uint32_t *)data); > + break; > + case SPIGENIOC_SBPOL: > + error = spigen_sbpol(cdev, (uint32_t *)data); > break; > default: > error = ENOTTY; > --- sys/spigenio.h.orig 2018-12-22 00:48:50.752200000 +0900 > +++ sys/spigenio.h 2018-12-30 23:58:00.000000000 +0900 > @@ -52,5 +52,7 @@ struct spigen_transfer_mmapped { > #define SPIGENIOC_SET_CLOCK_SPEED _IOW(SPIGENIOC_BASE, 3, uint32_t) > #define SPIGENIOC_GET_SPI_MODE _IOR(SPIGENIOC_BASE, 4, uint32_t) > #define SPIGENIOC_SET_SPI_MODE _IOW(SPIGENIOC_BASE, 5, uint32_t) > +#define SPIGENIOC_SBE _IOW(SPIGENIOC_BASE, 6, uint32_t) > +#define SPIGENIOC_SBPOL _IOW(SPIGENIOC_BASE, 7, uint32_t) > > #endif /* !_SYS_SPIGENIO_H_ */ > > -- I've been working with SPI devices for years, and I don't think I've ever heard of this SBE and SBPOL stuff. Can you point me to a standards document or something else that describes it? -- Ian
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1546191759.78877.91.camel>