Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 31 Dec 2018 08:09:53 +0900 (JST)
From:      SAITOU Toshihide <toshi@ruby.ocn.ne.jp>
To:        freebsd-arm@freebsd.org
Subject:   Re: SPI start bit (9 bit) for BBB
Message-ID:  <20181231.080953.1864031625387192599.toshi@ruby.ocn.ne.jp>
In-Reply-To: <1546191759.78877.91.camel@freebsd.org>
References:  <20181231.003356.1147810385398844555.toshi@ruby.ocn.ne.jp> <1546191759.78877.91.camel@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 30 Dec 2018 10:42:39 -0700, Ian Lepore <ian@freebsd.org> wrote:=

> 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.=A0=A0The BBB can handle this, so I can use =
with
>> the following patch (unskillful and maybe side effects exist).=A0=A0=
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
>> =A0	/* Disable the FIFO. */
>> =A0	TI_SPI_WRITE(sc, MCSPI_XFERLEVEL, 0);
>> =A0
>> +#if 0
>> =A0	/* 8 bits word, d0 miso, d1 mosi, mode 0 and CS active low.
>> */
>> =A0	reg =3D TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
>> =A0	reg &=3D ~(MCSPI_CONF_FFER | MCSPI_CONF_FFEW |
>> MCSPI_CONF_SBPOL |
>> @@ -501,6 +502,7 @@ ti_spi_transfer(device_t dev, device_t child,
>> struct s
>> =A0	=A0=A0=A0=A0MCSPI_CONF_DMAW | MCSPI_CONF_EPOL);
>> =A0	reg |=3D MCSPI_CONF_DPE0 | MCSPI_CONF_EPOL |
>> MCSPI_CONF_WL8BITS;
>> =A0	TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg);
>> +#endif
>> =A0
>> =A0#if 0
>> =A0	/* Enable channel interrupts. */
>> @@ -558,6 +560,70 @@ ti_spi_get_node(device_t bus, device_t dev)
>> =A0	return (ofw_bus_get_node(bus));
>> =A0}
>> =A0
>> +static int
>> +ti_spi_sbe(device_t dev, device_t child, uint32_t *request)
>> +{
>> +	struct ti_spi_softc *sc;
>> +	uint32_t reg;
>> +
>> +	sc =3D 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 =3D TI_SPI_BUSY;
>> +
>> +	reg =3D TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
>> +	if (*request)
>> +		reg |=3D MCSPI_CONF_SBE;
>> +	else
>> +		reg &=3D ~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 =3D 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 =3D 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 =3D TI_SPI_BUSY;
>> +
>> +	reg =3D TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
>> +	if (*request)
>> +		reg |=3D MCSPI_CONF_SBPOL;
>> +	else
>> +		reg &=3D ~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 =3D 0;
>> +	wakeup_one(dev);
>> +	TI_SPI_UNLOCK(sc);
>> +
>> +	return (0);
>> +}
>> +
>> =A0static device_method_t ti_spi_methods[] =3D {
>> =A0	/* Device interface */
>> =A0	DEVMETHOD(device_probe,		ti_spi_probe),
>> @@ -569,6 +635,10 @@ static device_method_t ti_spi_methods[] =3D {
>> =A0
>> =A0	/* ofw_bus interface */
>> =A0	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),
>> =A0
>> =A0	DEVMETHOD_END
>> =A0};
>> --- 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
>> =A0	return (SPIBUS_TRANSFER(device_get_parent(dev), child,
>> cmd));
>> =A0}
>> =A0
>> +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));
>> +}
>> +
>> =A0static device_method_t spibus_methods[] =3D {
>> =A0	/* Device interface */
>> =A0	DEVMETHOD(device_probe,		spibus_probe),
>> @@ -247,6 +259,9 @@ static device_method_t spibus_methods[] =3D {
>> =A0
>> =A0	/* spibus interface */
>> =A0	DEVMETHOD(spibus_transfer,	spibus_transfer_impl),
>> +
>> +	DEVMETHOD(spibus_sbe,	spibus_sbe_impl),
>> +	DEVMETHOD(spibus_sbpol,	spibus_sbpol_impl),
>> =A0
>> =A0	DEVMETHOD_END
>> =A0};
>> --- 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 {
>> =A0	device_t child;
>> =A0	struct spi_command *cmd;
>> =A0};
>> +
>> +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
>> =A0}
>> =A0
>> =A0static int
>> +spigen_sbe(struct cdev *cdev, uint32_t *request)
>> +{
>> +	device_t dev =3D cdev->si_drv1;
>> +	int error =3D 0;
>> +
>> +	error =3D 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 =3D cdev->si_drv1;
>> +	int error =3D 0;
>> +
>> +	error =3D SPIBUS_SBPOL(device_get_parent(dev), dev, (uint32_t
>> *)request);
>> +
>> +	return (error);
>> +}
>> +
>> +static int
>> =A0spigen_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int ffl=
ag,
>> =A0=A0=A0=A0=A0struct thread *td)
>> =A0{
>> @@ -272,6 +294,12 @@ spigen_ioctl(struct cdev *cdev, u_long cmd,
>> caddr_t da
>> =A0		break;
>> =A0	case SPIGENIOC_SET_SPI_MODE:
>> =A0		error =3D spibus_set_mode(dev, *(uint32_t *)data);
>> +		break;
>> +	case SPIGENIOC_SBE:
>> +		error =3D spigen_sbe(cdev, (uint32_t *)data);
>> +		break;
>> +	case SPIGENIOC_SBPOL:
>> +		error =3D spigen_sbpol(cdev, (uint32_t *)data);
>> =A0		break;
>> =A0	default:
>> =A0		error =3D 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 {
>> =A0#define SPIGENIOC_SET_CLOCK_SPEED=A0=A0_IOW(SPIGENIOC_BASE, 3, ui=
nt32_t)
>> =A0#define SPIGENIOC_GET_SPI_MODE=A0=A0=A0=A0=A0_IOR(SPIGENIOC_BASE,=
 4, uint32_t)
>> =A0#define SPIGENIOC_SET_SPI_MODE=A0=A0=A0=A0=A0_IOW(SPIGENIOC_BASE,=
 5, uint32_t)
>> +#define SPIGENIOC_SBE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOW=
(SPIGENIOC_BASE, 6, uint32_t)
>> +#define SPIGENIOC_SBPOL=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOW(SPI=
GENIOC_BASE, 7, uint32_t)
>> =A0
>> =A0#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 standar=
ds
> document or something else that describes it?
> =

> -- Ian

Sure, here it is.

  Fig. 9.3.1,  p. 30,  https://www.crystalfontz.com/controllers/Sitroni=
x/ST7735/

When the start bit is enabled, one extra clock is added,

  request =3D 1;
  ioctl(lcd->spi_fd, SPIGENIOC_SBE, &request);

and the data porarity is controled by the start bit porarity.

  ioctl(h->spi_fd, SPIGENIOC_SBPOL, &request);

By this patch, BeagleBone Mini Display Cape is usable.
https://www.logicsupply.com/999-0004100/

--
SAITOU Toshihide



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20181231.080953.1864031625387192599.toshi>