On 17:59 Wed 04 Feb , Guennadi Liakhovetski wrote: > Some SPI devices have special requirements on chip-select handling. > With this patch we can use a GPIO as a chip-select and strictly follow > the SPI_XFER_BEGIN and SPI_XFER_END flags. > > Signed-off-by: Guennadi Liakhovetski <l...@denx.de> > --- > > Jean-Christophe: one more for you to ack. > > drivers/spi/mxc_spi.c | 35 +++++++++++++++++++++++++++++------ > 1 files changed, 29 insertions(+), 6 deletions(-) > > diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c > index 9267341..eacd36c 100644 > --- a/drivers/spi/mxc_spi.c > +++ b/drivers/spi/mxc_spi.c > @@ -32,6 +32,8 @@ > > #else > > +#include <asm/arch/mx31.h> > + > #define MXC_CSPIRXDATA 0x00 > #define MXC_CSPITXDATA 0x04 > #define MXC_CSPICTRL 0x08 > @@ -68,6 +70,7 @@ struct mxc_spi_slave { > struct spi_slave slave; > unsigned long base; > u32 ctrl_reg; > + int gpio; > }; > > static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave) > @@ -91,6 +94,9 @@ static u32 spi_xchg_single(struct spi_slave *slave, u32 > data, > struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); > unsigned int cfg_reg = reg_read(mxcs->base + MXC_CSPICTRL); > > + if (mxcs->gpio > 0 && (flags & SPI_XFER_BEGIN)) > + mx31_gpio_set(mxcs->gpio, !!(mxcs->ctrl_reg & > MXC_CSPICTRL_SSPOL)); > + > reg_write(mxcs->base + MXC_CSPITXDATA, data); > > cfg_reg |= MXC_CSPICTRL_XCH; > @@ -100,6 +106,9 @@ static u32 spi_xchg_single(struct spi_slave *slave, u32 > data, > while (reg_read(mxcs->base + MXC_CSPICTRL) & MXC_CSPICTRL_XCH) > ; > > + if (mxcs->gpio > 0 && (flags & SPI_XFER_END)) > + mx31_gpio_set(mxcs->gpio, !(mxcs->ctrl_reg & > MXC_CSPICTRL_SSPOL)); > + > return reg_read(mxcs->base + MXC_CSPIRXDATA); > } > > @@ -175,10 +184,28 @@ struct spi_slave *spi_setup_slave(unsigned int bus, > unsigned int cs, > unsigned int ctrl_reg; > struct mxc_spi_slave *mxcs; > > - if (bus >= sizeof(spi_bases) / sizeof(spi_bases[0]) || > - cs > 3) > + if (bus >= sizeof(spi_bases) / sizeof(spi_bases[0])) > + return NULL; > + > + mxcs = malloc(sizeof(struct mxc_spi_slave)); > + if (!mxcs) > return NULL; > > + /* > + * Some SPI devices require active chip-select over multiple > + * transactions, we achieve this using a GPIO. Still, the SPI > + * controller has to be configured to use one of its own chipselects. > + * To use this feature you have to call spi_setup_slave() with > + * cs = internal_cs | (gpio << 8), and you have to use some unused > + * on this SPI controller cs between 0 and 3. > + */ > + if (cs > 3) { > + mxcs->gpio = cs >> 8; > + cs &= 3; > + mx31_gpio_direction(mxcs->gpio, MX31_GPIO_DIRECTION_OUT); > + } else > + mxcs->gpio = -1; > + why not add a callback for the chipselect instead as example if you have to use a gpio extender it will simplest to implent instead of hack the SPI driver
Best Regars, J. _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot