static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len, u8 *rxp, const u8 *txp, unsigned long flags) { struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | (slave->cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) ; /* keep reading and writing 1 byte until only 1 byte left */ while ((len--) > 1) *rxp++ = davinci_spi_xfer_data(ds, data1_reg_val | *txp++); /* clear CS hold when we reach the end */ if (flags & SPI_XFER_END) data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT); /* read and write the last byte */ *rxp = davinci_spi_xfer_data(ds, data1_reg_val | *txp); return 0; }
void spi_release_bus(struct spi_slave *slave) { struct davinci_spi_slave *ds = to_davinci_spi(slave); /* Disable the SPI hardware */ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); }
int spi_claim_bus(struct spi_slave *slave) { struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int scalar; /* Enable the SPI hardware */ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); udelay(1000); writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0); /* Set master mode, powered up and not activated */ writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1); /* CS, CLK, SIMO and SOMI are functional pins */ writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0); /* setup format */ scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF; /* * Use following format: * character length = 8, * clock signal delayed by half clk cycle, * clock low in idle state - Mode 0, * MSB shifted out first */ writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) | (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0); /* * Including a minor delay. No science here. Should be good even with * no delay */ writel((50 << SPI_C2TDELAY_SHIFT) | (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay); /* default chip select register */ writel(SPIDEF_CSDEF0_MASK, &ds->regs->def); /* no interrupts */ writel(0, &ds->regs->int0); writel(0, &ds->regs->lvl); /* enable SPI */ writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1); return 0; }
void spi_free_slave(struct spi_slave *slave) { struct davinci_spi_slave *ds = to_davinci_spi(slave); free(ds); }
int spi_claim_bus( struct spi_slave *slave ) { struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int scalar; unsigned int uiBus; unsigned int uiGPIO; uiBus = slave->bus; //set GPIO and clock if( SPI0_BUS == uiBus ) { uiGPIO = GPIO_SPI0_CS0; scalar = ( ( CONFIG_SYS_SPI0_CLK / ds->freq) - 1 ) & 0xFF; } else if( SPI4_BUS == uiBus ) { uiGPIO = GPIO_SPI4_CS0; scalar = ( ( CONFIG_SYS_SPI4_CLK / ds->freq) - 1 ) & 0xFF; } gpio_direction_output( uiGPIO, 0 ); /* Enable the SPI hardware */ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); udelay(1000); writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0); /* Set master mode, powered up and not activated */ writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1); /* CS, CLK, SIMO and SOMI are functional pins */ writel((SPIPC0_EN0FUN_MASK | SPIPC0_CLKFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0); //set GPIO and clock if( SPI0_BUS == uiBus ) { //uiGPIO = GPIO_SPI0_CS0; //scalar = ( ( CONFIG_SYS_SPI0_CLK / ds->freq) - 1 ) & 0xFF; /* * Use following format: * character length = 8, * clock signal delayed by half clk cycle, * clock low in idle state - Mode 1, * MSB shifted out first */ writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) | (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0); } else if( SPI4_BUS == uiBus ) { //uiGPIO = GPIO_SPI4_CS0; // scalar = ( ( CONFIG_SYS_SPI4_CLK / ds->freq) - 1 ) & 0xFF; /* * Use following format: * character length = 8, * clock signal delayed by half clk cycle, * clock low in idle state - Mode 0, * MSB shifted out first */ writel( 8 | (scalar << SPIFMT_PRESCALE_SHIFT) | (0 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0); } /* * Including a minor delay. No science here. Should be good even with * no delay */ writel((50 << SPI_C2TDELAY_SHIFT) | (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay); /* default chip select register */ writel(SPIDEF_CSDEF0_MASK, &ds->regs->def); /* no interrupts */ writel(0, &ds->regs->int0); writel(0, &ds->regs->lvl); /* enable SPI */ writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1); //printf("bus=%x cs=%x ds addr =%x reg=%x \n",uiBus,uiGPIO,ds,ds->regs); //printf("fmt0 reg=%x \n",readl( &ds->regs->fmt0)); return 0; }
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct davinci_spi_slave *ds = to_davinci_spi(slave); //struct pl022 *pl022 = (struct pl022 *)ps->regs; u32 len_tx = 0, len_rx = 0, len; u32 ret = 0; const u8 *txp = dout; u8 *rxp = din, value; if (bitlen == 0) /* Finish any previously submitted transfers */ goto out; //printf("%s:%d\n",__FUNCTION__,__LINE__); /* * TODO: The controller can do non-multiple-of-8 bit * transfers, but this driver currently doesn't support it. * * It's also not clear how such transfers are supposed to be * represented as a stream of bytes...this is a limitation of * the current SPI interface. */ if (bitlen % 8) { ret = -1; //printf("%s:%d\n",__FUNCTION__,__LINE__); /* Errors always terminate an ongoing transfer */ flags |= SPI_XFER_END; goto out; } len = bitlen / 8; //printf("%s:%d\n",__FUNCTION__,__LINE__); if (flags & SPI_XFER_BEGIN) spi_cs_activate(slave); while (len_tx < len) { if (readl(&ds->regs->flg) & 0x200) { value = (txp != NULL) ? *txp++ : 0; //writew(value, SSP_DR_REG); //printf("ssp_sr=%x\n",IO_READ(SSP_SR_REG)); writel(value, &ds->regs->dat1); len_tx++; } //printf("%s:%d\n",__FUNCTION__,__LINE__); if (readl(&ds->regs->flg) & 0x100) { value = readl(&ds->regs->buf); //printf("read back=%x\n",value); if (rxp) *rxp++ = value; len_rx++; } } //printf("%s:%d\n",__FUNCTION__,__LINE__); while (len_rx < len_tx) { if (readl(&ds->regs->flg) & 0x100) { value = readl(&ds->regs->buf); if (rxp) *rxp++ = value; len_rx++; } } //printf("%s:%d\n",__FUNCTION__,__LINE__); out: if (flags & SPI_XFER_END) spi_cs_deactivate(slave); //printf("%s:%d\n",__FUNCTION__,__LINE__); return ret; }