SPI start bit (9 bit) for BBB
SAITOU Toshihide
toshi at ruby.ocn.ne.jp
Sun Dec 30 15:34:12 UTC 2018
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_ */
--
SAITOU Toshihide
More information about the freebsd-arm
mailing list