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 * 91a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 108ed58856SSekhar Nori */ 118ed58856SSekhar Nori #include <common.h> 128ed58856SSekhar Nori #include <spi.h> 138ed58856SSekhar Nori #include <malloc.h> 148ed58856SSekhar Nori #include <asm/io.h> 158ed58856SSekhar Nori #include <asm/arch/hardware.h> 16*e6d2fbf7SJagan Teki 17*e6d2fbf7SJagan Teki struct davinci_spi_regs { 18*e6d2fbf7SJagan Teki dv_reg gcr0; /* 0x00 */ 19*e6d2fbf7SJagan Teki dv_reg gcr1; /* 0x04 */ 20*e6d2fbf7SJagan Teki dv_reg int0; /* 0x08 */ 21*e6d2fbf7SJagan Teki dv_reg lvl; /* 0x0c */ 22*e6d2fbf7SJagan Teki dv_reg flg; /* 0x10 */ 23*e6d2fbf7SJagan Teki dv_reg pc0; /* 0x14 */ 24*e6d2fbf7SJagan Teki dv_reg pc1; /* 0x18 */ 25*e6d2fbf7SJagan Teki dv_reg pc2; /* 0x1c */ 26*e6d2fbf7SJagan Teki dv_reg pc3; /* 0x20 */ 27*e6d2fbf7SJagan Teki dv_reg pc4; /* 0x24 */ 28*e6d2fbf7SJagan Teki dv_reg pc5; /* 0x28 */ 29*e6d2fbf7SJagan Teki dv_reg rsvd[3]; 30*e6d2fbf7SJagan Teki dv_reg dat0; /* 0x38 */ 31*e6d2fbf7SJagan Teki dv_reg dat1; /* 0x3c */ 32*e6d2fbf7SJagan Teki dv_reg buf; /* 0x40 */ 33*e6d2fbf7SJagan Teki dv_reg emu; /* 0x44 */ 34*e6d2fbf7SJagan Teki dv_reg delay; /* 0x48 */ 35*e6d2fbf7SJagan Teki dv_reg def; /* 0x4c */ 36*e6d2fbf7SJagan Teki dv_reg fmt0; /* 0x50 */ 37*e6d2fbf7SJagan Teki dv_reg fmt1; /* 0x54 */ 38*e6d2fbf7SJagan Teki dv_reg fmt2; /* 0x58 */ 39*e6d2fbf7SJagan Teki dv_reg fmt3; /* 0x5c */ 40*e6d2fbf7SJagan Teki dv_reg intvec0; /* 0x60 */ 41*e6d2fbf7SJagan Teki dv_reg intvec1; /* 0x64 */ 42*e6d2fbf7SJagan Teki }; 43*e6d2fbf7SJagan Teki 44*e6d2fbf7SJagan Teki #define BIT(x) (1 << (x)) 45*e6d2fbf7SJagan Teki 46*e6d2fbf7SJagan Teki /* SPIGCR0 */ 47*e6d2fbf7SJagan Teki #define SPIGCR0_SPIENA_MASK 0x1 48*e6d2fbf7SJagan Teki #define SPIGCR0_SPIRST_MASK 0x0 49*e6d2fbf7SJagan Teki 50*e6d2fbf7SJagan Teki /* SPIGCR0 */ 51*e6d2fbf7SJagan Teki #define SPIGCR1_CLKMOD_MASK BIT(1) 52*e6d2fbf7SJagan Teki #define SPIGCR1_MASTER_MASK BIT(0) 53*e6d2fbf7SJagan Teki #define SPIGCR1_SPIENA_MASK BIT(24) 54*e6d2fbf7SJagan Teki 55*e6d2fbf7SJagan Teki /* SPIPC0 */ 56*e6d2fbf7SJagan Teki #define SPIPC0_DIFUN_MASK BIT(11) /* SIMO */ 57*e6d2fbf7SJagan Teki #define SPIPC0_DOFUN_MASK BIT(10) /* SOMI */ 58*e6d2fbf7SJagan Teki #define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */ 59*e6d2fbf7SJagan Teki #define SPIPC0_EN0FUN_MASK BIT(0) 60*e6d2fbf7SJagan Teki 61*e6d2fbf7SJagan Teki /* SPIFMT0 */ 62*e6d2fbf7SJagan Teki #define SPIFMT_SHIFTDIR_SHIFT 20 63*e6d2fbf7SJagan Teki #define SPIFMT_POLARITY_SHIFT 17 64*e6d2fbf7SJagan Teki #define SPIFMT_PHASE_SHIFT 16 65*e6d2fbf7SJagan Teki #define SPIFMT_PRESCALE_SHIFT 8 66*e6d2fbf7SJagan Teki 67*e6d2fbf7SJagan Teki /* SPIDAT1 */ 68*e6d2fbf7SJagan Teki #define SPIDAT1_CSHOLD_SHIFT 28 69*e6d2fbf7SJagan Teki #define SPIDAT1_CSNR_SHIFT 16 70*e6d2fbf7SJagan Teki 71*e6d2fbf7SJagan Teki /* SPIDELAY */ 72*e6d2fbf7SJagan Teki #define SPI_C2TDELAY_SHIFT 24 73*e6d2fbf7SJagan Teki #define SPI_T2CDELAY_SHIFT 16 74*e6d2fbf7SJagan Teki 75*e6d2fbf7SJagan Teki /* SPIBUF */ 76*e6d2fbf7SJagan Teki #define SPIBUF_RXEMPTY_MASK BIT(31) 77*e6d2fbf7SJagan Teki #define SPIBUF_TXFULL_MASK BIT(29) 78*e6d2fbf7SJagan Teki 79*e6d2fbf7SJagan Teki /* SPIDEF */ 80*e6d2fbf7SJagan Teki #define SPIDEF_CSDEF0_MASK BIT(0) 81*e6d2fbf7SJagan Teki 82*e6d2fbf7SJagan Teki #define SPI0_BUS 0 83*e6d2fbf7SJagan Teki #define SPI0_BASE CONFIG_SYS_SPI_BASE 84*e6d2fbf7SJagan Teki /* 85*e6d2fbf7SJagan Teki * Define default SPI0_NUM_CS as 1 for existing platforms that uses this 86*e6d2fbf7SJagan Teki * driver. Platform can configure number of CS using CONFIG_SYS_SPI0_NUM_CS 87*e6d2fbf7SJagan Teki * if more than one CS is supported and by defining CONFIG_SYS_SPI0. 88*e6d2fbf7SJagan Teki */ 89*e6d2fbf7SJagan Teki #ifndef CONFIG_SYS_SPI0 90*e6d2fbf7SJagan Teki #define SPI0_NUM_CS 1 91*e6d2fbf7SJagan Teki #else 92*e6d2fbf7SJagan Teki #define SPI0_NUM_CS CONFIG_SYS_SPI0_NUM_CS 93*e6d2fbf7SJagan Teki #endif 94*e6d2fbf7SJagan Teki 95*e6d2fbf7SJagan Teki /* 96*e6d2fbf7SJagan Teki * define CONFIG_SYS_SPI1 when platform has spi-1 device (bus #1) and 97*e6d2fbf7SJagan Teki * CONFIG_SYS_SPI1_NUM_CS defines number of CS on this bus 98*e6d2fbf7SJagan Teki */ 99*e6d2fbf7SJagan Teki #ifdef CONFIG_SYS_SPI1 100*e6d2fbf7SJagan Teki #define SPI1_BUS 1 101*e6d2fbf7SJagan Teki #define SPI1_NUM_CS CONFIG_SYS_SPI1_NUM_CS 102*e6d2fbf7SJagan Teki #define SPI1_BASE CONFIG_SYS_SPI1_BASE 103*e6d2fbf7SJagan Teki #endif 104*e6d2fbf7SJagan Teki 105*e6d2fbf7SJagan Teki /* 106*e6d2fbf7SJagan Teki * define CONFIG_SYS_SPI2 when platform has spi-2 device (bus #2) and 107*e6d2fbf7SJagan Teki * CONFIG_SYS_SPI2_NUM_CS defines number of CS on this bus 108*e6d2fbf7SJagan Teki */ 109*e6d2fbf7SJagan Teki #ifdef CONFIG_SYS_SPI2 110*e6d2fbf7SJagan Teki #define SPI2_BUS 2 111*e6d2fbf7SJagan Teki #define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS 112*e6d2fbf7SJagan Teki #define SPI2_BASE CONFIG_SYS_SPI2_BASE 113*e6d2fbf7SJagan Teki #endif 114*e6d2fbf7SJagan Teki 115*e6d2fbf7SJagan Teki struct davinci_spi_slave { 116*e6d2fbf7SJagan Teki struct spi_slave slave; 117*e6d2fbf7SJagan Teki struct davinci_spi_regs *regs; 118*e6d2fbf7SJagan Teki unsigned int freq; 119*e6d2fbf7SJagan Teki }; 120*e6d2fbf7SJagan Teki 121*e6d2fbf7SJagan Teki static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) 122*e6d2fbf7SJagan Teki { 123*e6d2fbf7SJagan Teki return container_of(slave, struct davinci_spi_slave, slave); 124*e6d2fbf7SJagan Teki } 1258ed58856SSekhar Nori 1268ed58856SSekhar Nori void spi_init() 1278ed58856SSekhar Nori { 1288ed58856SSekhar Nori /* do nothing */ 1298ed58856SSekhar Nori } 1308ed58856SSekhar Nori 1318ed58856SSekhar Nori struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 1328ed58856SSekhar Nori unsigned int max_hz, unsigned int mode) 1338ed58856SSekhar Nori { 1348ed58856SSekhar Nori struct davinci_spi_slave *ds; 1358ed58856SSekhar Nori 1368ed58856SSekhar Nori if (!spi_cs_is_valid(bus, cs)) 1378ed58856SSekhar Nori return NULL; 1388ed58856SSekhar Nori 139d3504feeSSimon Glass ds = spi_alloc_slave(struct davinci_spi_slave, bus, cs); 1408ed58856SSekhar Nori if (!ds) 1418ed58856SSekhar Nori return NULL; 1428ed58856SSekhar Nori 1432bcdf84dSKaricheri, Muralidharan switch (bus) { 1442bcdf84dSKaricheri, Muralidharan case SPI0_BUS: 1452bcdf84dSKaricheri, Muralidharan ds->regs = (struct davinci_spi_regs *)SPI0_BASE; 1462bcdf84dSKaricheri, Muralidharan break; 1472bcdf84dSKaricheri, Muralidharan #ifdef CONFIG_SYS_SPI1 1482bcdf84dSKaricheri, Muralidharan case SPI1_BUS: 1497a4861faSAxel Lin ds->regs = (struct davinci_spi_regs *)SPI1_BASE; 1502bcdf84dSKaricheri, Muralidharan break; 1512bcdf84dSKaricheri, Muralidharan #endif 1522bcdf84dSKaricheri, Muralidharan #ifdef CONFIG_SYS_SPI2 1532bcdf84dSKaricheri, Muralidharan case SPI2_BUS: 1542bcdf84dSKaricheri, Muralidharan ds->regs = (struct davinci_spi_regs *)SPI2_BASE; 1552bcdf84dSKaricheri, Muralidharan break; 1562bcdf84dSKaricheri, Muralidharan #endif 1572bcdf84dSKaricheri, Muralidharan default: /* Invalid bus number */ 1582bcdf84dSKaricheri, Muralidharan return NULL; 1592bcdf84dSKaricheri, Muralidharan } 1602bcdf84dSKaricheri, Muralidharan 1618ed58856SSekhar Nori ds->freq = max_hz; 1628ed58856SSekhar Nori 1638ed58856SSekhar Nori return &ds->slave; 1648ed58856SSekhar Nori } 1658ed58856SSekhar Nori 1668ed58856SSekhar Nori void spi_free_slave(struct spi_slave *slave) 1678ed58856SSekhar Nori { 1688ed58856SSekhar Nori struct davinci_spi_slave *ds = to_davinci_spi(slave); 1698ed58856SSekhar Nori 1708ed58856SSekhar Nori free(ds); 1718ed58856SSekhar Nori } 1728ed58856SSekhar Nori 1738ed58856SSekhar Nori int spi_claim_bus(struct spi_slave *slave) 1748ed58856SSekhar Nori { 1758ed58856SSekhar Nori struct davinci_spi_slave *ds = to_davinci_spi(slave); 17677436d66SNick Thompson unsigned int scalar; 1778ed58856SSekhar Nori 1788ed58856SSekhar Nori /* Enable the SPI hardware */ 1798ed58856SSekhar Nori writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); 1808ed58856SSekhar Nori udelay(1000); 1818ed58856SSekhar Nori writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0); 1828ed58856SSekhar Nori 1838ed58856SSekhar Nori /* Set master mode, powered up and not activated */ 1848ed58856SSekhar Nori writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1); 1858ed58856SSekhar Nori 1868ed58856SSekhar Nori /* CS, CLK, SIMO and SOMI are functional pins */ 1872bcdf84dSKaricheri, Muralidharan writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK | 1888ed58856SSekhar Nori SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0); 1898ed58856SSekhar Nori 1908ed58856SSekhar Nori /* setup format */ 1918ed58856SSekhar Nori scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF; 1928ed58856SSekhar Nori 1938ed58856SSekhar Nori /* 1948ed58856SSekhar Nori * Use following format: 1958ed58856SSekhar Nori * character length = 8, 1968ed58856SSekhar Nori * clock signal delayed by half clk cycle, 1978ed58856SSekhar Nori * clock low in idle state - Mode 0, 1988ed58856SSekhar Nori * MSB shifted out first 1998ed58856SSekhar Nori */ 2008ed58856SSekhar Nori writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) | 2018ed58856SSekhar Nori (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0); 2028ed58856SSekhar Nori 2038ed58856SSekhar Nori /* 2048ed58856SSekhar Nori * Including a minor delay. No science here. Should be good even with 2058ed58856SSekhar Nori * no delay 2068ed58856SSekhar Nori */ 2078ed58856SSekhar Nori writel((50 << SPI_C2TDELAY_SHIFT) | 2088ed58856SSekhar Nori (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay); 2098ed58856SSekhar Nori 2108ed58856SSekhar Nori /* default chip select register */ 2118ed58856SSekhar Nori writel(SPIDEF_CSDEF0_MASK, &ds->regs->def); 2128ed58856SSekhar Nori 2138ed58856SSekhar Nori /* no interrupts */ 2148ed58856SSekhar Nori writel(0, &ds->regs->int0); 2158ed58856SSekhar Nori writel(0, &ds->regs->lvl); 2168ed58856SSekhar Nori 2178ed58856SSekhar Nori /* enable SPI */ 21877436d66SNick Thompson writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1); 2198ed58856SSekhar Nori 2208ed58856SSekhar Nori return 0; 2218ed58856SSekhar Nori } 2228ed58856SSekhar Nori 2238ed58856SSekhar Nori void spi_release_bus(struct spi_slave *slave) 2248ed58856SSekhar Nori { 2258ed58856SSekhar Nori struct davinci_spi_slave *ds = to_davinci_spi(slave); 2268ed58856SSekhar Nori 2278ed58856SSekhar Nori /* Disable the SPI hardware */ 2288ed58856SSekhar Nori writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); 2298ed58856SSekhar Nori } 2308ed58856SSekhar Nori 23177436d66SNick Thompson /* 23277436d66SNick Thompson * This functions needs to act like a macro to avoid pipeline reloads in the 23377436d66SNick Thompson * loops below. Use always_inline. This gains us about 160KiB/s and the bloat 23477436d66SNick Thompson * appears to be zero bytes (da830). 23577436d66SNick Thompson */ 23677436d66SNick Thompson __attribute__((always_inline)) 23777436d66SNick Thompson static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data) 23877436d66SNick Thompson { 23977436d66SNick Thompson u32 buf_reg_val; 24077436d66SNick Thompson 24177436d66SNick Thompson /* send out data */ 24277436d66SNick Thompson writel(data, &ds->regs->dat1); 24377436d66SNick Thompson 24477436d66SNick Thompson /* wait for the data to clock in/out */ 24577436d66SNick Thompson while ((buf_reg_val = readl(&ds->regs->buf)) & SPIBUF_RXEMPTY_MASK) 24677436d66SNick Thompson ; 24777436d66SNick Thompson 24877436d66SNick Thompson return buf_reg_val; 24977436d66SNick Thompson } 25077436d66SNick Thompson 25177436d66SNick Thompson static int davinci_spi_read(struct spi_slave *slave, unsigned int len, 25277436d66SNick Thompson u8 *rxp, unsigned long flags) 25377436d66SNick Thompson { 25477436d66SNick Thompson struct davinci_spi_slave *ds = to_davinci_spi(slave); 25577436d66SNick Thompson unsigned int data1_reg_val; 25677436d66SNick Thompson 25777436d66SNick Thompson /* enable CS hold, CS[n] and clear the data bits */ 25877436d66SNick Thompson data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | 25977436d66SNick Thompson (slave->cs << SPIDAT1_CSNR_SHIFT)); 26077436d66SNick Thompson 26177436d66SNick Thompson /* wait till TXFULL is deasserted */ 26277436d66SNick Thompson while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) 26377436d66SNick Thompson ; 26477436d66SNick Thompson 26577436d66SNick Thompson /* preload the TX buffer to avoid clock starvation */ 26677436d66SNick Thompson writel(data1_reg_val, &ds->regs->dat1); 26777436d66SNick Thompson 26877436d66SNick Thompson /* keep reading 1 byte until only 1 byte left */ 26977436d66SNick Thompson while ((len--) > 1) 27077436d66SNick Thompson *rxp++ = davinci_spi_xfer_data(ds, data1_reg_val); 27177436d66SNick Thompson 27277436d66SNick Thompson /* clear CS hold when we reach the end */ 27377436d66SNick Thompson if (flags & SPI_XFER_END) 27477436d66SNick Thompson data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT); 27577436d66SNick Thompson 27677436d66SNick Thompson /* read the last byte */ 27777436d66SNick Thompson *rxp = davinci_spi_xfer_data(ds, data1_reg_val); 27877436d66SNick Thompson 27977436d66SNick Thompson return 0; 28077436d66SNick Thompson } 28177436d66SNick Thompson 28277436d66SNick Thompson static int davinci_spi_write(struct spi_slave *slave, unsigned int len, 28377436d66SNick Thompson const u8 *txp, unsigned long flags) 28477436d66SNick Thompson { 28577436d66SNick Thompson struct davinci_spi_slave *ds = to_davinci_spi(slave); 28677436d66SNick Thompson unsigned int data1_reg_val; 28777436d66SNick Thompson 28877436d66SNick Thompson /* enable CS hold and clear the data bits */ 28977436d66SNick Thompson data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | 29077436d66SNick Thompson (slave->cs << SPIDAT1_CSNR_SHIFT)); 29177436d66SNick Thompson 29277436d66SNick Thompson /* wait till TXFULL is deasserted */ 29377436d66SNick Thompson while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) 29477436d66SNick Thompson ; 29577436d66SNick Thompson 29677436d66SNick Thompson /* preload the TX buffer to avoid clock starvation */ 29777436d66SNick Thompson if (len > 2) { 29877436d66SNick Thompson writel(data1_reg_val | *txp++, &ds->regs->dat1); 29977436d66SNick Thompson len--; 30077436d66SNick Thompson } 30177436d66SNick Thompson 30277436d66SNick Thompson /* keep writing 1 byte until only 1 byte left */ 30377436d66SNick Thompson while ((len--) > 1) 30477436d66SNick Thompson davinci_spi_xfer_data(ds, data1_reg_val | *txp++); 30577436d66SNick Thompson 30677436d66SNick Thompson /* clear CS hold when we reach the end */ 30777436d66SNick Thompson if (flags & SPI_XFER_END) 30877436d66SNick Thompson data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT); 30977436d66SNick Thompson 31077436d66SNick Thompson /* write the last byte */ 31177436d66SNick Thompson davinci_spi_xfer_data(ds, data1_reg_val | *txp); 31277436d66SNick Thompson 31377436d66SNick Thompson return 0; 31477436d66SNick Thompson } 31577436d66SNick Thompson 31677436d66SNick Thompson #ifndef CONFIG_SPI_HALF_DUPLEX 31777436d66SNick Thompson static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len, 31877436d66SNick Thompson u8 *rxp, const u8 *txp, unsigned long flags) 31977436d66SNick Thompson { 32077436d66SNick Thompson struct davinci_spi_slave *ds = to_davinci_spi(slave); 32177436d66SNick Thompson unsigned int data1_reg_val; 32277436d66SNick Thompson 32377436d66SNick Thompson /* enable CS hold and clear the data bits */ 32477436d66SNick Thompson data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | 32577436d66SNick Thompson (slave->cs << SPIDAT1_CSNR_SHIFT)); 32677436d66SNick Thompson 32777436d66SNick Thompson /* wait till TXFULL is deasserted */ 32877436d66SNick Thompson while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) 32977436d66SNick Thompson ; 33077436d66SNick Thompson 33177436d66SNick Thompson /* keep reading and writing 1 byte until only 1 byte left */ 33277436d66SNick Thompson while ((len--) > 1) 33377436d66SNick Thompson *rxp++ = davinci_spi_xfer_data(ds, data1_reg_val | *txp++); 33477436d66SNick Thompson 33577436d66SNick Thompson /* clear CS hold when we reach the end */ 33677436d66SNick Thompson if (flags & SPI_XFER_END) 33777436d66SNick Thompson data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT); 33877436d66SNick Thompson 33977436d66SNick Thompson /* read and write the last byte */ 34077436d66SNick Thompson *rxp = davinci_spi_xfer_data(ds, data1_reg_val | *txp); 34177436d66SNick Thompson 34277436d66SNick Thompson return 0; 34377436d66SNick Thompson } 34477436d66SNick Thompson #endif 34577436d66SNick Thompson 3468ed58856SSekhar Nori int spi_xfer(struct spi_slave *slave, unsigned int bitlen, 3478ed58856SSekhar Nori const void *dout, void *din, unsigned long flags) 3488ed58856SSekhar Nori { 34977436d66SNick Thompson unsigned int len; 3508ed58856SSekhar Nori 3518ed58856SSekhar Nori if (bitlen == 0) 3528ed58856SSekhar Nori /* Finish any previously submitted transfers */ 3538ed58856SSekhar Nori goto out; 3548ed58856SSekhar Nori 3558ed58856SSekhar Nori /* 3568ed58856SSekhar Nori * It's not clear how non-8-bit-aligned transfers are supposed to be 3578ed58856SSekhar Nori * represented as a stream of bytes...this is a limitation of 3588ed58856SSekhar Nori * the current SPI interface - here we terminate on receiving such a 3598ed58856SSekhar Nori * transfer request. 3608ed58856SSekhar Nori */ 3618ed58856SSekhar Nori if (bitlen % 8) { 3628ed58856SSekhar Nori /* Errors always terminate an ongoing transfer */ 3638ed58856SSekhar Nori flags |= SPI_XFER_END; 3648ed58856SSekhar Nori goto out; 3658ed58856SSekhar Nori } 3668ed58856SSekhar Nori 3678ed58856SSekhar Nori len = bitlen / 8; 3688ed58856SSekhar Nori 36977436d66SNick Thompson if (!dout) 37077436d66SNick Thompson return davinci_spi_read(slave, len, din, flags); 37177436d66SNick Thompson else if (!din) 37277436d66SNick Thompson return davinci_spi_write(slave, len, dout, flags); 37377436d66SNick Thompson #ifndef CONFIG_SPI_HALF_DUPLEX 37477436d66SNick Thompson else 37577436d66SNick Thompson return davinci_spi_read_write(slave, len, din, dout, flags); 376dce6538fSNick Thompson #else 377dce6538fSNick Thompson printf("SPI full duplex transaction requested with " 378dce6538fSNick Thompson "CONFIG_SPI_HALF_DUPLEX defined.\n"); 379dce6538fSNick Thompson flags |= SPI_XFER_END; 38077436d66SNick Thompson #endif 3818ed58856SSekhar Nori 3828ed58856SSekhar Nori out: 3838ed58856SSekhar Nori if (flags & SPI_XFER_END) { 38477436d66SNick Thompson u8 dummy = 0; 38577436d66SNick Thompson davinci_spi_write(slave, 1, &dummy, flags); 3868ed58856SSekhar Nori } 3878ed58856SSekhar Nori return 0; 3888ed58856SSekhar Nori } 3898ed58856SSekhar Nori 3908ed58856SSekhar Nori int spi_cs_is_valid(unsigned int bus, unsigned int cs) 3918ed58856SSekhar Nori { 3922bcdf84dSKaricheri, Muralidharan int ret = 0; 3932bcdf84dSKaricheri, Muralidharan 3942bcdf84dSKaricheri, Muralidharan switch (bus) { 3952bcdf84dSKaricheri, Muralidharan case SPI0_BUS: 3962bcdf84dSKaricheri, Muralidharan if (cs < SPI0_NUM_CS) 3972bcdf84dSKaricheri, Muralidharan ret = 1; 3982bcdf84dSKaricheri, Muralidharan break; 3992bcdf84dSKaricheri, Muralidharan #ifdef CONFIG_SYS_SPI1 4002bcdf84dSKaricheri, Muralidharan case SPI1_BUS: 4012bcdf84dSKaricheri, Muralidharan if (cs < SPI1_NUM_CS) 4022bcdf84dSKaricheri, Muralidharan ret = 1; 4032bcdf84dSKaricheri, Muralidharan break; 4042bcdf84dSKaricheri, Muralidharan #endif 4052bcdf84dSKaricheri, Muralidharan #ifdef CONFIG_SYS_SPI2 4062bcdf84dSKaricheri, Muralidharan case SPI2_BUS: 4072bcdf84dSKaricheri, Muralidharan if (cs < SPI2_NUM_CS) 4082bcdf84dSKaricheri, Muralidharan ret = 1; 4092bcdf84dSKaricheri, Muralidharan break; 4102bcdf84dSKaricheri, Muralidharan #endif 4112bcdf84dSKaricheri, Muralidharan default: 4122bcdf84dSKaricheri, Muralidharan /* Invalid bus number. Do nothing */ 4132bcdf84dSKaricheri, Muralidharan break; 4142bcdf84dSKaricheri, Muralidharan } 4152bcdf84dSKaricheri, Muralidharan return ret; 4168ed58856SSekhar Nori } 4178ed58856SSekhar Nori 4188ed58856SSekhar Nori void spi_cs_activate(struct spi_slave *slave) 4198ed58856SSekhar Nori { 4208ed58856SSekhar Nori /* do nothing */ 4218ed58856SSekhar Nori } 4228ed58856SSekhar Nori 4238ed58856SSekhar Nori void spi_cs_deactivate(struct spi_slave *slave) 4248ed58856SSekhar Nori { 4258ed58856SSekhar Nori /* do nothing */ 4268ed58856SSekhar Nori } 427