SPI start bit (9 bit) for BBB
Ian Lepore
ian at freebsd.org
Sun Dec 30 17:58:54 UTC 2018
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
More information about the freebsd-arm
mailing list