18ed58856SSekhar Nori /* 28ed58856SSekhar Nori * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 38ed58856SSekhar Nori * 48ed58856SSekhar Nori * Driver for SPI controller on DaVinci. Based on atmel_spi.c 58ed58856SSekhar Nori * by Atmel Corporation 68ed58856SSekhar Nori * 78ed58856SSekhar Nori * Copyright (C) 2007 Atmel Corporation 88ed58856SSekhar Nori * 98ed58856SSekhar Nori * See file CREDITS for list of people who contributed to this 108ed58856SSekhar Nori * project. 118ed58856SSekhar Nori * 128ed58856SSekhar Nori * This program is free software; you can redistribute it and/or 138ed58856SSekhar Nori * modify it under the terms of the GNU General Public License as 148ed58856SSekhar Nori * published by the Free Software Foundation; either version 2 of 158ed58856SSekhar Nori * the License, or (at your option) any later version. 168ed58856SSekhar Nori * 178ed58856SSekhar Nori * This program is distributed in the hope that it will be useful, 188ed58856SSekhar Nori * but WITHOUT ANY WARRANTY; without even the implied warranty of 198ed58856SSekhar Nori * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 208ed58856SSekhar Nori * GNU General Public License for more details. 218ed58856SSekhar Nori * 228ed58856SSekhar Nori * You should have received a copy of the GNU General Public License 238ed58856SSekhar Nori * along with this program; if not, write to the Free Software 248ed58856SSekhar Nori * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 258ed58856SSekhar Nori * MA 02111-1307 USA 268ed58856SSekhar Nori */ 278ed58856SSekhar Nori #include <common.h> 288ed58856SSekhar Nori #include <spi.h> 298ed58856SSekhar Nori #include <malloc.h> 308ed58856SSekhar Nori #include <asm/io.h> 318ed58856SSekhar Nori #include <asm/arch/hardware.h> 328ed58856SSekhar Nori #include "davinci_spi.h" 338ed58856SSekhar Nori 348ed58856SSekhar Nori void spi_init() 358ed58856SSekhar Nori { 368ed58856SSekhar Nori /* do nothing */ 378ed58856SSekhar Nori } 388ed58856SSekhar Nori 398ed58856SSekhar Nori struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 408ed58856SSekhar Nori unsigned int max_hz, unsigned int mode) 418ed58856SSekhar Nori { 428ed58856SSekhar Nori struct davinci_spi_slave *ds; 438ed58856SSekhar Nori 448ed58856SSekhar Nori if (!spi_cs_is_valid(bus, cs)) 458ed58856SSekhar Nori return NULL; 468ed58856SSekhar Nori 478ed58856SSekhar Nori ds = malloc(sizeof(*ds)); 488ed58856SSekhar Nori if (!ds) 498ed58856SSekhar Nori return NULL; 508ed58856SSekhar Nori 518ed58856SSekhar Nori ds->slave.bus = bus; 528ed58856SSekhar Nori ds->slave.cs = cs; 538ed58856SSekhar Nori ds->regs = (struct davinci_spi_regs *)CONFIG_SYS_SPI_BASE; 548ed58856SSekhar Nori ds->freq = max_hz; 558ed58856SSekhar Nori 568ed58856SSekhar Nori return &ds->slave; 578ed58856SSekhar Nori } 588ed58856SSekhar Nori 598ed58856SSekhar Nori void spi_free_slave(struct spi_slave *slave) 608ed58856SSekhar Nori { 618ed58856SSekhar Nori struct davinci_spi_slave *ds = to_davinci_spi(slave); 628ed58856SSekhar Nori 638ed58856SSekhar Nori free(ds); 648ed58856SSekhar Nori } 658ed58856SSekhar Nori 668ed58856SSekhar Nori int spi_claim_bus(struct spi_slave *slave) 678ed58856SSekhar Nori { 688ed58856SSekhar Nori struct davinci_spi_slave *ds = to_davinci_spi(slave); 69*77436d66SNick Thompson unsigned int scalar; 708ed58856SSekhar Nori 718ed58856SSekhar Nori /* Enable the SPI hardware */ 728ed58856SSekhar Nori writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); 738ed58856SSekhar Nori udelay(1000); 748ed58856SSekhar Nori writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0); 758ed58856SSekhar Nori 768ed58856SSekhar Nori /* Set master mode, powered up and not activated */ 778ed58856SSekhar Nori writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1); 788ed58856SSekhar Nori 798ed58856SSekhar Nori /* CS, CLK, SIMO and SOMI are functional pins */ 808ed58856SSekhar Nori writel((SPIPC0_EN0FUN_MASK | SPIPC0_CLKFUN_MASK | 818ed58856SSekhar Nori SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0); 828ed58856SSekhar Nori 838ed58856SSekhar Nori /* setup format */ 848ed58856SSekhar Nori scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF; 858ed58856SSekhar Nori 868ed58856SSekhar Nori /* 878ed58856SSekhar Nori * Use following format: 888ed58856SSekhar Nori * character length = 8, 898ed58856SSekhar Nori * clock signal delayed by half clk cycle, 908ed58856SSekhar Nori * clock low in idle state - Mode 0, 918ed58856SSekhar Nori * MSB shifted out first 928ed58856SSekhar Nori */ 938ed58856SSekhar Nori writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) | 948ed58856SSekhar Nori (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0); 958ed58856SSekhar Nori 968ed58856SSekhar Nori /* 978ed58856SSekhar Nori * Including a minor delay. No science here. Should be good even with 988ed58856SSekhar Nori * no delay 998ed58856SSekhar Nori */ 1008ed58856SSekhar Nori writel((50 << SPI_C2TDELAY_SHIFT) | 1018ed58856SSekhar Nori (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay); 1028ed58856SSekhar Nori 1038ed58856SSekhar Nori /* default chip select register */ 1048ed58856SSekhar Nori writel(SPIDEF_CSDEF0_MASK, &ds->regs->def); 1058ed58856SSekhar Nori 1068ed58856SSekhar Nori /* no interrupts */ 1078ed58856SSekhar Nori writel(0, &ds->regs->int0); 1088ed58856SSekhar Nori writel(0, &ds->regs->lvl); 1098ed58856SSekhar Nori 1108ed58856SSekhar Nori /* enable SPI */ 111*77436d66SNick Thompson writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1); 1128ed58856SSekhar Nori 1138ed58856SSekhar Nori return 0; 1148ed58856SSekhar Nori } 1158ed58856SSekhar Nori 1168ed58856SSekhar Nori void spi_release_bus(struct spi_slave *slave) 1178ed58856SSekhar Nori { 1188ed58856SSekhar Nori struct davinci_spi_slave *ds = to_davinci_spi(slave); 1198ed58856SSekhar Nori 1208ed58856SSekhar Nori /* Disable the SPI hardware */ 1218ed58856SSekhar Nori writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); 1228ed58856SSekhar Nori } 1238ed58856SSekhar Nori 124*77436d66SNick Thompson /* 125*77436d66SNick Thompson * This functions needs to act like a macro to avoid pipeline reloads in the 126*77436d66SNick Thompson * loops below. Use always_inline. This gains us about 160KiB/s and the bloat 127*77436d66SNick Thompson * appears to be zero bytes (da830). 128*77436d66SNick Thompson */ 129*77436d66SNick Thompson __attribute__((always_inline)) 130*77436d66SNick Thompson static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data) 131*77436d66SNick Thompson { 132*77436d66SNick Thompson u32 buf_reg_val; 133*77436d66SNick Thompson 134*77436d66SNick Thompson /* send out data */ 135*77436d66SNick Thompson writel(data, &ds->regs->dat1); 136*77436d66SNick Thompson 137*77436d66SNick Thompson /* wait for the data to clock in/out */ 138*77436d66SNick Thompson while ((buf_reg_val = readl(&ds->regs->buf)) & SPIBUF_RXEMPTY_MASK) 139*77436d66SNick Thompson ; 140*77436d66SNick Thompson 141*77436d66SNick Thompson return buf_reg_val; 142*77436d66SNick Thompson } 143*77436d66SNick Thompson 144*77436d66SNick Thompson static int davinci_spi_read(struct spi_slave *slave, unsigned int len, 145*77436d66SNick Thompson u8 *rxp, unsigned long flags) 146*77436d66SNick Thompson { 147*77436d66SNick Thompson struct davinci_spi_slave *ds = to_davinci_spi(slave); 148*77436d66SNick Thompson unsigned int data1_reg_val; 149*77436d66SNick Thompson 150*77436d66SNick Thompson /* enable CS hold, CS[n] and clear the data bits */ 151*77436d66SNick Thompson data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | 152*77436d66SNick Thompson (slave->cs << SPIDAT1_CSNR_SHIFT)); 153*77436d66SNick Thompson 154*77436d66SNick Thompson /* wait till TXFULL is deasserted */ 155*77436d66SNick Thompson while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) 156*77436d66SNick Thompson ; 157*77436d66SNick Thompson 158*77436d66SNick Thompson /* preload the TX buffer to avoid clock starvation */ 159*77436d66SNick Thompson writel(data1_reg_val, &ds->regs->dat1); 160*77436d66SNick Thompson 161*77436d66SNick Thompson /* keep reading 1 byte until only 1 byte left */ 162*77436d66SNick Thompson while ((len--) > 1) 163*77436d66SNick Thompson *rxp++ = davinci_spi_xfer_data(ds, data1_reg_val); 164*77436d66SNick Thompson 165*77436d66SNick Thompson /* clear CS hold when we reach the end */ 166*77436d66SNick Thompson if (flags & SPI_XFER_END) 167*77436d66SNick Thompson data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT); 168*77436d66SNick Thompson 169*77436d66SNick Thompson /* read the last byte */ 170*77436d66SNick Thompson *rxp = davinci_spi_xfer_data(ds, data1_reg_val); 171*77436d66SNick Thompson 172*77436d66SNick Thompson return 0; 173*77436d66SNick Thompson } 174*77436d66SNick Thompson 175*77436d66SNick Thompson static int davinci_spi_write(struct spi_slave *slave, unsigned int len, 176*77436d66SNick Thompson const u8 *txp, unsigned long flags) 177*77436d66SNick Thompson { 178*77436d66SNick Thompson struct davinci_spi_slave *ds = to_davinci_spi(slave); 179*77436d66SNick Thompson unsigned int data1_reg_val; 180*77436d66SNick Thompson 181*77436d66SNick Thompson /* enable CS hold and clear the data bits */ 182*77436d66SNick Thompson data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | 183*77436d66SNick Thompson (slave->cs << SPIDAT1_CSNR_SHIFT)); 184*77436d66SNick Thompson 185*77436d66SNick Thompson /* wait till TXFULL is deasserted */ 186*77436d66SNick Thompson while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) 187*77436d66SNick Thompson ; 188*77436d66SNick Thompson 189*77436d66SNick Thompson /* preload the TX buffer to avoid clock starvation */ 190*77436d66SNick Thompson if (len > 2) { 191*77436d66SNick Thompson writel(data1_reg_val | *txp++, &ds->regs->dat1); 192*77436d66SNick Thompson len--; 193*77436d66SNick Thompson } 194*77436d66SNick Thompson 195*77436d66SNick Thompson /* keep writing 1 byte until only 1 byte left */ 196*77436d66SNick Thompson while ((len--) > 1) 197*77436d66SNick Thompson davinci_spi_xfer_data(ds, data1_reg_val | *txp++); 198*77436d66SNick Thompson 199*77436d66SNick Thompson /* clear CS hold when we reach the end */ 200*77436d66SNick Thompson if (flags & SPI_XFER_END) 201*77436d66SNick Thompson data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT); 202*77436d66SNick Thompson 203*77436d66SNick Thompson /* write the last byte */ 204*77436d66SNick Thompson davinci_spi_xfer_data(ds, data1_reg_val | *txp); 205*77436d66SNick Thompson 206*77436d66SNick Thompson return 0; 207*77436d66SNick Thompson } 208*77436d66SNick Thompson 209*77436d66SNick Thompson #ifndef CONFIG_SPI_HALF_DUPLEX 210*77436d66SNick Thompson static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len, 211*77436d66SNick Thompson u8 *rxp, const u8 *txp, unsigned long flags) 212*77436d66SNick Thompson { 213*77436d66SNick Thompson struct davinci_spi_slave *ds = to_davinci_spi(slave); 214*77436d66SNick Thompson unsigned int data1_reg_val; 215*77436d66SNick Thompson 216*77436d66SNick Thompson /* enable CS hold and clear the data bits */ 217*77436d66SNick Thompson data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | 218*77436d66SNick Thompson (slave->cs << SPIDAT1_CSNR_SHIFT)); 219*77436d66SNick Thompson 220*77436d66SNick Thompson /* wait till TXFULL is deasserted */ 221*77436d66SNick Thompson while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) 222*77436d66SNick Thompson ; 223*77436d66SNick Thompson 224*77436d66SNick Thompson /* keep reading and writing 1 byte until only 1 byte left */ 225*77436d66SNick Thompson while ((len--) > 1) 226*77436d66SNick Thompson *rxp++ = davinci_spi_xfer_data(ds, data1_reg_val | *txp++); 227*77436d66SNick Thompson 228*77436d66SNick Thompson /* clear CS hold when we reach the end */ 229*77436d66SNick Thompson if (flags & SPI_XFER_END) 230*77436d66SNick Thompson data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT); 231*77436d66SNick Thompson 232*77436d66SNick Thompson /* read and write the last byte */ 233*77436d66SNick Thompson *rxp = davinci_spi_xfer_data(ds, data1_reg_val | *txp); 234*77436d66SNick Thompson 235*77436d66SNick Thompson return 0; 236*77436d66SNick Thompson } 237*77436d66SNick Thompson #endif 238*77436d66SNick Thompson 2398ed58856SSekhar Nori int spi_xfer(struct spi_slave *slave, unsigned int bitlen, 2408ed58856SSekhar Nori const void *dout, void *din, unsigned long flags) 2418ed58856SSekhar Nori { 242*77436d66SNick Thompson unsigned int len; 2438ed58856SSekhar Nori 2448ed58856SSekhar Nori if (bitlen == 0) 2458ed58856SSekhar Nori /* Finish any previously submitted transfers */ 2468ed58856SSekhar Nori goto out; 2478ed58856SSekhar Nori 2488ed58856SSekhar Nori /* 2498ed58856SSekhar Nori * It's not clear how non-8-bit-aligned transfers are supposed to be 2508ed58856SSekhar Nori * represented as a stream of bytes...this is a limitation of 2518ed58856SSekhar Nori * the current SPI interface - here we terminate on receiving such a 2528ed58856SSekhar Nori * transfer request. 2538ed58856SSekhar Nori */ 2548ed58856SSekhar Nori if (bitlen % 8) { 2558ed58856SSekhar Nori /* Errors always terminate an ongoing transfer */ 2568ed58856SSekhar Nori flags |= SPI_XFER_END; 2578ed58856SSekhar Nori goto out; 2588ed58856SSekhar Nori } 2598ed58856SSekhar Nori 2608ed58856SSekhar Nori len = bitlen / 8; 2618ed58856SSekhar Nori 262*77436d66SNick Thompson if (!dout) 263*77436d66SNick Thompson return davinci_spi_read(slave, len, din, flags); 264*77436d66SNick Thompson else if (!din) 265*77436d66SNick Thompson return davinci_spi_write(slave, len, dout, flags); 266*77436d66SNick Thompson #ifndef CONFIG_SPI_HALF_DUPLEX 267*77436d66SNick Thompson else 268*77436d66SNick Thompson return davinci_spi_read_write(slave, len, din, dout, flags); 269*77436d66SNick Thompson #endif 2708ed58856SSekhar Nori 2718ed58856SSekhar Nori out: 2728ed58856SSekhar Nori if (flags & SPI_XFER_END) { 273*77436d66SNick Thompson u8 dummy = 0; 274*77436d66SNick Thompson davinci_spi_write(slave, 1, &dummy, flags); 2758ed58856SSekhar Nori } 2768ed58856SSekhar Nori return 0; 2778ed58856SSekhar Nori } 2788ed58856SSekhar Nori 2798ed58856SSekhar Nori int spi_cs_is_valid(unsigned int bus, unsigned int cs) 2808ed58856SSekhar Nori { 2818ed58856SSekhar Nori return bus == 0 && cs == 0; 2828ed58856SSekhar Nori } 2838ed58856SSekhar Nori 2848ed58856SSekhar Nori void spi_cs_activate(struct spi_slave *slave) 2858ed58856SSekhar Nori { 2868ed58856SSekhar Nori /* do nothing */ 2878ed58856SSekhar Nori } 2888ed58856SSekhar Nori 2898ed58856SSekhar Nori void spi_cs_deactivate(struct spi_slave *slave) 2908ed58856SSekhar Nori { 2918ed58856SSekhar Nori /* do nothing */ 2928ed58856SSekhar Nori } 293