11bf43b82SRajeshwari Shinde /* 21bf43b82SRajeshwari Shinde * (C) Copyright 2012 SAMSUNG Electronics 31bf43b82SRajeshwari Shinde * Padmavathi Venna <padma.v@samsung.com> 41bf43b82SRajeshwari Shinde * 51bf43b82SRajeshwari Shinde * This program is free software; you can redistribute it and/or modify 61bf43b82SRajeshwari Shinde * it under the terms of the GNU General Public License as published by 71bf43b82SRajeshwari Shinde * the Free Software Foundation; either version 2 of the License, or 81bf43b82SRajeshwari Shinde * (at your option) any later version. 91bf43b82SRajeshwari Shinde * 101bf43b82SRajeshwari Shinde * This program is distributed in the hope that it will be useful, 111bf43b82SRajeshwari Shinde * but WITHOUT ANY WARRANTY; without even the implied warranty of 121bf43b82SRajeshwari Shinde * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 131bf43b82SRajeshwari Shinde * GNU General Public License for more details. 141bf43b82SRajeshwari Shinde * 151bf43b82SRajeshwari Shinde * You should have received a copy of the GNU General Public License 161bf43b82SRajeshwari Shinde * along with this program; if not, write to the Free Software 171bf43b82SRajeshwari Shinde * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 181bf43b82SRajeshwari Shinde */ 191bf43b82SRajeshwari Shinde 201bf43b82SRajeshwari Shinde #include <common.h> 211bf43b82SRajeshwari Shinde #include <malloc.h> 221bf43b82SRajeshwari Shinde #include <spi.h> 234d3acb9dSRajeshwari Shinde #include <fdtdec.h> 241bf43b82SRajeshwari Shinde #include <asm/arch/clk.h> 251bf43b82SRajeshwari Shinde #include <asm/arch/clock.h> 261bf43b82SRajeshwari Shinde #include <asm/arch/cpu.h> 271bf43b82SRajeshwari Shinde #include <asm/arch/gpio.h> 281bf43b82SRajeshwari Shinde #include <asm/arch/pinmux.h> 291bf43b82SRajeshwari Shinde #include <asm/arch-exynos/spi.h> 301bf43b82SRajeshwari Shinde #include <asm/io.h> 311bf43b82SRajeshwari Shinde 324d3acb9dSRajeshwari Shinde DECLARE_GLOBAL_DATA_PTR; 334d3acb9dSRajeshwari Shinde 341bf43b82SRajeshwari Shinde /* Information about each SPI controller */ 351bf43b82SRajeshwari Shinde struct spi_bus { 361bf43b82SRajeshwari Shinde enum periph_id periph_id; 371bf43b82SRajeshwari Shinde s32 frequency; /* Default clock frequency, -1 for none */ 381bf43b82SRajeshwari Shinde struct exynos_spi *regs; 391bf43b82SRajeshwari Shinde int inited; /* 1 if this bus is ready for use */ 404d3acb9dSRajeshwari Shinde int node; 411bf43b82SRajeshwari Shinde }; 421bf43b82SRajeshwari Shinde 431bf43b82SRajeshwari Shinde /* A list of spi buses that we know about */ 441bf43b82SRajeshwari Shinde static struct spi_bus spi_bus[EXYNOS5_SPI_NUM_CONTROLLERS]; 454d3acb9dSRajeshwari Shinde static unsigned int bus_count; 461bf43b82SRajeshwari Shinde 471bf43b82SRajeshwari Shinde struct exynos_spi_slave { 481bf43b82SRajeshwari Shinde struct spi_slave slave; 491bf43b82SRajeshwari Shinde struct exynos_spi *regs; 501bf43b82SRajeshwari Shinde unsigned int freq; /* Default frequency */ 511bf43b82SRajeshwari Shinde unsigned int mode; 521bf43b82SRajeshwari Shinde enum periph_id periph_id; /* Peripheral ID for this device */ 531bf43b82SRajeshwari Shinde unsigned int fifo_size; 54*e4eaef89SRajeshwari Shinde int skip_preamble; 551bf43b82SRajeshwari Shinde }; 561bf43b82SRajeshwari Shinde 571bf43b82SRajeshwari Shinde static struct spi_bus *spi_get_bus(unsigned dev_index) 581bf43b82SRajeshwari Shinde { 594d3acb9dSRajeshwari Shinde if (dev_index < bus_count) 601bf43b82SRajeshwari Shinde return &spi_bus[dev_index]; 611bf43b82SRajeshwari Shinde debug("%s: invalid bus %d", __func__, dev_index); 621bf43b82SRajeshwari Shinde 631bf43b82SRajeshwari Shinde return NULL; 641bf43b82SRajeshwari Shinde } 651bf43b82SRajeshwari Shinde 661bf43b82SRajeshwari Shinde static inline struct exynos_spi_slave *to_exynos_spi(struct spi_slave *slave) 671bf43b82SRajeshwari Shinde { 681bf43b82SRajeshwari Shinde return container_of(slave, struct exynos_spi_slave, slave); 691bf43b82SRajeshwari Shinde } 701bf43b82SRajeshwari Shinde 711bf43b82SRajeshwari Shinde /** 721bf43b82SRajeshwari Shinde * Setup the driver private data 731bf43b82SRajeshwari Shinde * 741bf43b82SRajeshwari Shinde * @param bus ID of the bus that the slave is attached to 751bf43b82SRajeshwari Shinde * @param cs ID of the chip select connected to the slave 761bf43b82SRajeshwari Shinde * @param max_hz Required spi frequency 771bf43b82SRajeshwari Shinde * @param mode Required spi mode (clk polarity, clk phase and 781bf43b82SRajeshwari Shinde * master or slave) 791bf43b82SRajeshwari Shinde * @return new device or NULL 801bf43b82SRajeshwari Shinde */ 811bf43b82SRajeshwari Shinde struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs, 821bf43b82SRajeshwari Shinde unsigned int max_hz, unsigned int mode) 831bf43b82SRajeshwari Shinde { 841bf43b82SRajeshwari Shinde struct exynos_spi_slave *spi_slave; 851bf43b82SRajeshwari Shinde struct spi_bus *bus; 861bf43b82SRajeshwari Shinde 871bf43b82SRajeshwari Shinde if (!spi_cs_is_valid(busnum, cs)) { 881bf43b82SRajeshwari Shinde debug("%s: Invalid bus/chip select %d, %d\n", __func__, 891bf43b82SRajeshwari Shinde busnum, cs); 901bf43b82SRajeshwari Shinde return NULL; 911bf43b82SRajeshwari Shinde } 921bf43b82SRajeshwari Shinde 93d3504feeSSimon Glass spi_slave = spi_alloc_slave(struct exynos_spi_slave, busnum, cs); 941bf43b82SRajeshwari Shinde if (!spi_slave) { 951bf43b82SRajeshwari Shinde debug("%s: Could not allocate spi_slave\n", __func__); 961bf43b82SRajeshwari Shinde return NULL; 971bf43b82SRajeshwari Shinde } 981bf43b82SRajeshwari Shinde 991bf43b82SRajeshwari Shinde bus = &spi_bus[busnum]; 1001bf43b82SRajeshwari Shinde spi_slave->regs = bus->regs; 1011bf43b82SRajeshwari Shinde spi_slave->mode = mode; 1021bf43b82SRajeshwari Shinde spi_slave->periph_id = bus->periph_id; 1031bf43b82SRajeshwari Shinde if (bus->periph_id == PERIPH_ID_SPI1 || 1041bf43b82SRajeshwari Shinde bus->periph_id == PERIPH_ID_SPI2) 1051bf43b82SRajeshwari Shinde spi_slave->fifo_size = 64; 1061bf43b82SRajeshwari Shinde else 1071bf43b82SRajeshwari Shinde spi_slave->fifo_size = 256; 1081bf43b82SRajeshwari Shinde 109*e4eaef89SRajeshwari Shinde spi_slave->skip_preamble = 0; 110*e4eaef89SRajeshwari Shinde 1111bf43b82SRajeshwari Shinde spi_slave->freq = bus->frequency; 1121bf43b82SRajeshwari Shinde if (max_hz) 1131bf43b82SRajeshwari Shinde spi_slave->freq = min(max_hz, spi_slave->freq); 1141bf43b82SRajeshwari Shinde 1151bf43b82SRajeshwari Shinde return &spi_slave->slave; 1161bf43b82SRajeshwari Shinde } 1171bf43b82SRajeshwari Shinde 1181bf43b82SRajeshwari Shinde /** 1191bf43b82SRajeshwari Shinde * Free spi controller 1201bf43b82SRajeshwari Shinde * 1211bf43b82SRajeshwari Shinde * @param slave Pointer to spi_slave to which controller has to 1221bf43b82SRajeshwari Shinde * communicate with 1231bf43b82SRajeshwari Shinde */ 1241bf43b82SRajeshwari Shinde void spi_free_slave(struct spi_slave *slave) 1251bf43b82SRajeshwari Shinde { 1261bf43b82SRajeshwari Shinde struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); 1271bf43b82SRajeshwari Shinde 1281bf43b82SRajeshwari Shinde free(spi_slave); 1291bf43b82SRajeshwari Shinde } 1301bf43b82SRajeshwari Shinde 1311bf43b82SRajeshwari Shinde /** 1321bf43b82SRajeshwari Shinde * Flush spi tx, rx fifos and reset the SPI controller 1331bf43b82SRajeshwari Shinde * 1341bf43b82SRajeshwari Shinde * @param slave Pointer to spi_slave to which controller has to 1351bf43b82SRajeshwari Shinde * communicate with 1361bf43b82SRajeshwari Shinde */ 1371bf43b82SRajeshwari Shinde static void spi_flush_fifo(struct spi_slave *slave) 1381bf43b82SRajeshwari Shinde { 1391bf43b82SRajeshwari Shinde struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); 1401bf43b82SRajeshwari Shinde struct exynos_spi *regs = spi_slave->regs; 1411bf43b82SRajeshwari Shinde 1421bf43b82SRajeshwari Shinde clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); 1431bf43b82SRajeshwari Shinde clrbits_le32(®s->ch_cfg, SPI_CH_RST); 1441bf43b82SRajeshwari Shinde setbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); 1451bf43b82SRajeshwari Shinde } 1461bf43b82SRajeshwari Shinde 1471bf43b82SRajeshwari Shinde /** 1481bf43b82SRajeshwari Shinde * Initialize the spi base registers, set the required clock frequency and 1491bf43b82SRajeshwari Shinde * initialize the gpios 1501bf43b82SRajeshwari Shinde * 1511bf43b82SRajeshwari Shinde * @param slave Pointer to spi_slave to which controller has to 1521bf43b82SRajeshwari Shinde * communicate with 1531bf43b82SRajeshwari Shinde * @return zero on success else a negative value 1541bf43b82SRajeshwari Shinde */ 1551bf43b82SRajeshwari Shinde int spi_claim_bus(struct spi_slave *slave) 1561bf43b82SRajeshwari Shinde { 1571bf43b82SRajeshwari Shinde struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); 1581bf43b82SRajeshwari Shinde struct exynos_spi *regs = spi_slave->regs; 1591bf43b82SRajeshwari Shinde u32 reg = 0; 1601bf43b82SRajeshwari Shinde int ret; 1611bf43b82SRajeshwari Shinde 1621bf43b82SRajeshwari Shinde ret = set_spi_clk(spi_slave->periph_id, 1631bf43b82SRajeshwari Shinde spi_slave->freq); 1641bf43b82SRajeshwari Shinde if (ret < 0) { 1651bf43b82SRajeshwari Shinde debug("%s: Failed to setup spi clock\n", __func__); 1661bf43b82SRajeshwari Shinde return ret; 1671bf43b82SRajeshwari Shinde } 1681bf43b82SRajeshwari Shinde 1691bf43b82SRajeshwari Shinde exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE); 1701bf43b82SRajeshwari Shinde 1711bf43b82SRajeshwari Shinde spi_flush_fifo(slave); 1721bf43b82SRajeshwari Shinde 1731bf43b82SRajeshwari Shinde reg = readl(®s->ch_cfg); 1741bf43b82SRajeshwari Shinde reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L); 1751bf43b82SRajeshwari Shinde 1761bf43b82SRajeshwari Shinde if (spi_slave->mode & SPI_CPHA) 1771bf43b82SRajeshwari Shinde reg |= SPI_CH_CPHA_B; 1781bf43b82SRajeshwari Shinde 1791bf43b82SRajeshwari Shinde if (spi_slave->mode & SPI_CPOL) 1801bf43b82SRajeshwari Shinde reg |= SPI_CH_CPOL_L; 1811bf43b82SRajeshwari Shinde 1821bf43b82SRajeshwari Shinde writel(reg, ®s->ch_cfg); 1831bf43b82SRajeshwari Shinde writel(SPI_FB_DELAY_180, ®s->fb_clk); 1841bf43b82SRajeshwari Shinde 1851bf43b82SRajeshwari Shinde return 0; 1861bf43b82SRajeshwari Shinde } 1871bf43b82SRajeshwari Shinde 1881bf43b82SRajeshwari Shinde /** 1891bf43b82SRajeshwari Shinde * Reset the spi H/W and flush the tx and rx fifos 1901bf43b82SRajeshwari Shinde * 1911bf43b82SRajeshwari Shinde * @param slave Pointer to spi_slave to which controller has to 1921bf43b82SRajeshwari Shinde * communicate with 1931bf43b82SRajeshwari Shinde */ 1941bf43b82SRajeshwari Shinde void spi_release_bus(struct spi_slave *slave) 1951bf43b82SRajeshwari Shinde { 1961bf43b82SRajeshwari Shinde spi_flush_fifo(slave); 1971bf43b82SRajeshwari Shinde } 1981bf43b82SRajeshwari Shinde 1991bf43b82SRajeshwari Shinde static void spi_get_fifo_levels(struct exynos_spi *regs, 2001bf43b82SRajeshwari Shinde int *rx_lvl, int *tx_lvl) 2011bf43b82SRajeshwari Shinde { 2021bf43b82SRajeshwari Shinde uint32_t spi_sts = readl(®s->spi_sts); 2031bf43b82SRajeshwari Shinde 2041bf43b82SRajeshwari Shinde *rx_lvl = (spi_sts >> SPI_RX_LVL_OFFSET) & SPI_FIFO_LVL_MASK; 2051bf43b82SRajeshwari Shinde *tx_lvl = (spi_sts >> SPI_TX_LVL_OFFSET) & SPI_FIFO_LVL_MASK; 2061bf43b82SRajeshwari Shinde } 2071bf43b82SRajeshwari Shinde 2081bf43b82SRajeshwari Shinde /** 2091bf43b82SRajeshwari Shinde * If there's something to transfer, do a software reset and set a 2101bf43b82SRajeshwari Shinde * transaction size. 2111bf43b82SRajeshwari Shinde * 2121bf43b82SRajeshwari Shinde * @param regs SPI peripheral registers 2131bf43b82SRajeshwari Shinde * @param count Number of bytes to transfer 2141bf43b82SRajeshwari Shinde */ 2151bf43b82SRajeshwari Shinde static void spi_request_bytes(struct exynos_spi *regs, int count) 2161bf43b82SRajeshwari Shinde { 2171bf43b82SRajeshwari Shinde assert(count && count < (1 << 16)); 2181bf43b82SRajeshwari Shinde setbits_le32(®s->ch_cfg, SPI_CH_RST); 2191bf43b82SRajeshwari Shinde clrbits_le32(®s->ch_cfg, SPI_CH_RST); 2201bf43b82SRajeshwari Shinde writel(count | SPI_PACKET_CNT_EN, ®s->pkt_cnt); 2211bf43b82SRajeshwari Shinde } 2221bf43b82SRajeshwari Shinde 223*e4eaef89SRajeshwari Shinde static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, 224*e4eaef89SRajeshwari Shinde void **dinp, void const **doutp, unsigned long flags) 2251bf43b82SRajeshwari Shinde { 2261bf43b82SRajeshwari Shinde struct exynos_spi *regs = spi_slave->regs; 2271bf43b82SRajeshwari Shinde uchar *rxp = *dinp; 2281bf43b82SRajeshwari Shinde const uchar *txp = *doutp; 2291bf43b82SRajeshwari Shinde int rx_lvl, tx_lvl; 2301bf43b82SRajeshwari Shinde uint out_bytes, in_bytes; 231*e4eaef89SRajeshwari Shinde int toread; 232*e4eaef89SRajeshwari Shinde unsigned start = get_timer(0); 233*e4eaef89SRajeshwari Shinde int stopping; 2341bf43b82SRajeshwari Shinde 2351bf43b82SRajeshwari Shinde out_bytes = in_bytes = todo; 2361bf43b82SRajeshwari Shinde 237*e4eaef89SRajeshwari Shinde stopping = spi_slave->skip_preamble && (flags & SPI_XFER_END) && 238*e4eaef89SRajeshwari Shinde !(spi_slave->mode & SPI_SLAVE); 239*e4eaef89SRajeshwari Shinde 2401bf43b82SRajeshwari Shinde /* 2411bf43b82SRajeshwari Shinde * If there's something to send, do a software reset and set a 2421bf43b82SRajeshwari Shinde * transaction size. 2431bf43b82SRajeshwari Shinde */ 2441bf43b82SRajeshwari Shinde spi_request_bytes(regs, todo); 2451bf43b82SRajeshwari Shinde 2461bf43b82SRajeshwari Shinde /* 2471bf43b82SRajeshwari Shinde * Bytes are transmitted/received in pairs. Wait to receive all the 2481bf43b82SRajeshwari Shinde * data because then transmission will be done as well. 2491bf43b82SRajeshwari Shinde */ 250*e4eaef89SRajeshwari Shinde toread = in_bytes; 251*e4eaef89SRajeshwari Shinde 2521bf43b82SRajeshwari Shinde while (in_bytes) { 2531bf43b82SRajeshwari Shinde int temp; 2541bf43b82SRajeshwari Shinde 2551bf43b82SRajeshwari Shinde /* Keep the fifos full/empty. */ 2561bf43b82SRajeshwari Shinde spi_get_fifo_levels(regs, &rx_lvl, &tx_lvl); 2571bf43b82SRajeshwari Shinde if (tx_lvl < spi_slave->fifo_size && out_bytes) { 2581bf43b82SRajeshwari Shinde temp = txp ? *txp++ : 0xff; 2591bf43b82SRajeshwari Shinde writel(temp, ®s->tx_data); 2601bf43b82SRajeshwari Shinde out_bytes--; 2611bf43b82SRajeshwari Shinde } 262*e4eaef89SRajeshwari Shinde if (rx_lvl > 0) { 2631bf43b82SRajeshwari Shinde temp = readl(®s->rx_data); 264*e4eaef89SRajeshwari Shinde if (spi_slave->skip_preamble) { 265*e4eaef89SRajeshwari Shinde if (temp == SPI_PREAMBLE_END_BYTE) { 266*e4eaef89SRajeshwari Shinde spi_slave->skip_preamble = 0; 267*e4eaef89SRajeshwari Shinde stopping = 0; 268*e4eaef89SRajeshwari Shinde } 269*e4eaef89SRajeshwari Shinde } else { 270*e4eaef89SRajeshwari Shinde if (rxp || stopping) 2711bf43b82SRajeshwari Shinde *rxp++ = temp; 2721bf43b82SRajeshwari Shinde in_bytes--; 2731bf43b82SRajeshwari Shinde } 274*e4eaef89SRajeshwari Shinde toread--; 275*e4eaef89SRajeshwari Shinde } else if (!toread) { 276*e4eaef89SRajeshwari Shinde /* 277*e4eaef89SRajeshwari Shinde * We have run out of input data, but haven't read 278*e4eaef89SRajeshwari Shinde * enough bytes after the preamble yet. Read some more, 279*e4eaef89SRajeshwari Shinde * and make sure that we transmit dummy bytes too, to 280*e4eaef89SRajeshwari Shinde * keep things going. 281*e4eaef89SRajeshwari Shinde */ 282*e4eaef89SRajeshwari Shinde assert(!out_bytes); 283*e4eaef89SRajeshwari Shinde out_bytes = in_bytes; 284*e4eaef89SRajeshwari Shinde toread = in_bytes; 285*e4eaef89SRajeshwari Shinde txp = NULL; 286*e4eaef89SRajeshwari Shinde spi_request_bytes(regs, toread); 2871bf43b82SRajeshwari Shinde } 288*e4eaef89SRajeshwari Shinde if (spi_slave->skip_preamble && get_timer(start) > 100) { 289*e4eaef89SRajeshwari Shinde printf("SPI timeout: in_bytes=%d, out_bytes=%d, ", 290*e4eaef89SRajeshwari Shinde in_bytes, out_bytes); 291*e4eaef89SRajeshwari Shinde return -1; 292*e4eaef89SRajeshwari Shinde } 293*e4eaef89SRajeshwari Shinde } 294*e4eaef89SRajeshwari Shinde 2951bf43b82SRajeshwari Shinde *dinp = rxp; 2961bf43b82SRajeshwari Shinde *doutp = txp; 297*e4eaef89SRajeshwari Shinde 298*e4eaef89SRajeshwari Shinde return 0; 2991bf43b82SRajeshwari Shinde } 3001bf43b82SRajeshwari Shinde 3011bf43b82SRajeshwari Shinde /** 3021bf43b82SRajeshwari Shinde * Transfer and receive data 3031bf43b82SRajeshwari Shinde * 3041bf43b82SRajeshwari Shinde * @param slave Pointer to spi_slave to which controller has to 3051bf43b82SRajeshwari Shinde * communicate with 3061bf43b82SRajeshwari Shinde * @param bitlen No of bits to tranfer or receive 3071bf43b82SRajeshwari Shinde * @param dout Pointer to transfer buffer 3081bf43b82SRajeshwari Shinde * @param din Pointer to receive buffer 3091bf43b82SRajeshwari Shinde * @param flags Flags for transfer begin and end 3101bf43b82SRajeshwari Shinde * @return zero on success else a negative value 3111bf43b82SRajeshwari Shinde */ 3121bf43b82SRajeshwari Shinde int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, 3131bf43b82SRajeshwari Shinde void *din, unsigned long flags) 3141bf43b82SRajeshwari Shinde { 3151bf43b82SRajeshwari Shinde struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); 3161bf43b82SRajeshwari Shinde int upto, todo; 3171bf43b82SRajeshwari Shinde int bytelen; 318*e4eaef89SRajeshwari Shinde int ret = 0; 3191bf43b82SRajeshwari Shinde 3201bf43b82SRajeshwari Shinde /* spi core configured to do 8 bit transfers */ 3211bf43b82SRajeshwari Shinde if (bitlen % 8) { 3221bf43b82SRajeshwari Shinde debug("Non byte aligned SPI transfer.\n"); 3231bf43b82SRajeshwari Shinde return -1; 3241bf43b82SRajeshwari Shinde } 3251bf43b82SRajeshwari Shinde 3261bf43b82SRajeshwari Shinde /* Start the transaction, if necessary. */ 3271bf43b82SRajeshwari Shinde if ((flags & SPI_XFER_BEGIN)) 3281bf43b82SRajeshwari Shinde spi_cs_activate(slave); 3291bf43b82SRajeshwari Shinde 3301bf43b82SRajeshwari Shinde /* Exynos SPI limits each transfer to 65535 bytes */ 3311bf43b82SRajeshwari Shinde bytelen = bitlen / 8; 332*e4eaef89SRajeshwari Shinde for (upto = 0; !ret && upto < bytelen; upto += todo) { 3331bf43b82SRajeshwari Shinde todo = min(bytelen - upto, (1 << 16) - 1); 334*e4eaef89SRajeshwari Shinde ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags); 335*e4eaef89SRajeshwari Shinde if (ret) 336*e4eaef89SRajeshwari Shinde break; 3371bf43b82SRajeshwari Shinde } 3381bf43b82SRajeshwari Shinde 3391bf43b82SRajeshwari Shinde /* Stop the transaction, if necessary. */ 340*e4eaef89SRajeshwari Shinde if ((flags & SPI_XFER_END) && !(spi_slave->mode & SPI_SLAVE)) { 3411bf43b82SRajeshwari Shinde spi_cs_deactivate(slave); 342*e4eaef89SRajeshwari Shinde if (spi_slave->skip_preamble) { 343*e4eaef89SRajeshwari Shinde assert(!spi_slave->skip_preamble); 344*e4eaef89SRajeshwari Shinde debug("Failed to complete premable transaction\n"); 345*e4eaef89SRajeshwari Shinde ret = -1; 346*e4eaef89SRajeshwari Shinde } 347*e4eaef89SRajeshwari Shinde } 3481bf43b82SRajeshwari Shinde 349*e4eaef89SRajeshwari Shinde return ret; 3501bf43b82SRajeshwari Shinde } 3511bf43b82SRajeshwari Shinde 3521bf43b82SRajeshwari Shinde /** 3531bf43b82SRajeshwari Shinde * Validates the bus and chip select numbers 3541bf43b82SRajeshwari Shinde * 3551bf43b82SRajeshwari Shinde * @param bus ID of the bus that the slave is attached to 3561bf43b82SRajeshwari Shinde * @param cs ID of the chip select connected to the slave 3571bf43b82SRajeshwari Shinde * @return one on success else zero 3581bf43b82SRajeshwari Shinde */ 3591bf43b82SRajeshwari Shinde int spi_cs_is_valid(unsigned int bus, unsigned int cs) 3601bf43b82SRajeshwari Shinde { 3611bf43b82SRajeshwari Shinde return spi_get_bus(bus) && cs == 0; 3621bf43b82SRajeshwari Shinde } 3631bf43b82SRajeshwari Shinde 3641bf43b82SRajeshwari Shinde /** 3651bf43b82SRajeshwari Shinde * Activate the CS by driving it LOW 3661bf43b82SRajeshwari Shinde * 3671bf43b82SRajeshwari Shinde * @param slave Pointer to spi_slave to which controller has to 3681bf43b82SRajeshwari Shinde * communicate with 3691bf43b82SRajeshwari Shinde */ 3701bf43b82SRajeshwari Shinde void spi_cs_activate(struct spi_slave *slave) 3711bf43b82SRajeshwari Shinde { 3721bf43b82SRajeshwari Shinde struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); 3731bf43b82SRajeshwari Shinde 3741bf43b82SRajeshwari Shinde clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT); 3751bf43b82SRajeshwari Shinde debug("Activate CS, bus %d\n", spi_slave->slave.bus); 376*e4eaef89SRajeshwari Shinde spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE; 3771bf43b82SRajeshwari Shinde } 3781bf43b82SRajeshwari Shinde 3791bf43b82SRajeshwari Shinde /** 3801bf43b82SRajeshwari Shinde * Deactivate the CS by driving it HIGH 3811bf43b82SRajeshwari Shinde * 3821bf43b82SRajeshwari Shinde * @param slave Pointer to spi_slave to which controller has to 3831bf43b82SRajeshwari Shinde * communicate with 3841bf43b82SRajeshwari Shinde */ 3851bf43b82SRajeshwari Shinde void spi_cs_deactivate(struct spi_slave *slave) 3861bf43b82SRajeshwari Shinde { 3871bf43b82SRajeshwari Shinde struct exynos_spi_slave *spi_slave = to_exynos_spi(slave); 3881bf43b82SRajeshwari Shinde 3891bf43b82SRajeshwari Shinde setbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT); 3901bf43b82SRajeshwari Shinde debug("Deactivate CS, bus %d\n", spi_slave->slave.bus); 3911bf43b82SRajeshwari Shinde } 3921bf43b82SRajeshwari Shinde 3931bf43b82SRajeshwari Shinde static inline struct exynos_spi *get_spi_base(int dev_index) 3941bf43b82SRajeshwari Shinde { 3951bf43b82SRajeshwari Shinde if (dev_index < 3) 3961bf43b82SRajeshwari Shinde return (struct exynos_spi *)samsung_get_base_spi() + dev_index; 3971bf43b82SRajeshwari Shinde else 3981bf43b82SRajeshwari Shinde return (struct exynos_spi *)samsung_get_base_spi_isp() + 3991bf43b82SRajeshwari Shinde (dev_index - 3); 4001bf43b82SRajeshwari Shinde } 4011bf43b82SRajeshwari Shinde 4024d3acb9dSRajeshwari Shinde /* 4034d3acb9dSRajeshwari Shinde * Read the SPI config from the device tree node. 4044d3acb9dSRajeshwari Shinde * 4054d3acb9dSRajeshwari Shinde * @param blob FDT blob to read from 4064d3acb9dSRajeshwari Shinde * @param node Node offset to read from 4074d3acb9dSRajeshwari Shinde * @param bus SPI bus structure to fill with information 4084d3acb9dSRajeshwari Shinde * @return 0 if ok, or -FDT_ERR_NOTFOUND if something was missing 4094d3acb9dSRajeshwari Shinde */ 4107d179584SVivek Gautam #ifdef CONFIG_OF_CONTROL 4114d3acb9dSRajeshwari Shinde static int spi_get_config(const void *blob, int node, struct spi_bus *bus) 4124d3acb9dSRajeshwari Shinde { 4134d3acb9dSRajeshwari Shinde bus->node = node; 4144d3acb9dSRajeshwari Shinde bus->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg"); 4154d3acb9dSRajeshwari Shinde bus->periph_id = pinmux_decode_periph_id(blob, node); 4164d3acb9dSRajeshwari Shinde 4174d3acb9dSRajeshwari Shinde if (bus->periph_id == PERIPH_ID_NONE) { 4184d3acb9dSRajeshwari Shinde debug("%s: Invalid peripheral ID %d\n", __func__, 4194d3acb9dSRajeshwari Shinde bus->periph_id); 4204d3acb9dSRajeshwari Shinde return -FDT_ERR_NOTFOUND; 4214d3acb9dSRajeshwari Shinde } 4224d3acb9dSRajeshwari Shinde 4234d3acb9dSRajeshwari Shinde /* Use 500KHz as a suitable default */ 4244d3acb9dSRajeshwari Shinde bus->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", 4254d3acb9dSRajeshwari Shinde 500000); 4264d3acb9dSRajeshwari Shinde 4274d3acb9dSRajeshwari Shinde return 0; 4284d3acb9dSRajeshwari Shinde } 4294d3acb9dSRajeshwari Shinde 4304d3acb9dSRajeshwari Shinde /* 4314d3acb9dSRajeshwari Shinde * Process a list of nodes, adding them to our list of SPI ports. 4324d3acb9dSRajeshwari Shinde * 4334d3acb9dSRajeshwari Shinde * @param blob fdt blob 4344d3acb9dSRajeshwari Shinde * @param node_list list of nodes to process (any <=0 are ignored) 4354d3acb9dSRajeshwari Shinde * @param count number of nodes to process 4364d3acb9dSRajeshwari Shinde * @param is_dvc 1 if these are DVC ports, 0 if standard I2C 4374d3acb9dSRajeshwari Shinde * @return 0 if ok, -1 on error 4384d3acb9dSRajeshwari Shinde */ 4394d3acb9dSRajeshwari Shinde static int process_nodes(const void *blob, int node_list[], int count) 4404d3acb9dSRajeshwari Shinde { 4414d3acb9dSRajeshwari Shinde int i; 4424d3acb9dSRajeshwari Shinde 4434d3acb9dSRajeshwari Shinde /* build the i2c_controllers[] for each controller */ 4444d3acb9dSRajeshwari Shinde for (i = 0; i < count; i++) { 4454d3acb9dSRajeshwari Shinde int node = node_list[i]; 4464d3acb9dSRajeshwari Shinde struct spi_bus *bus; 4474d3acb9dSRajeshwari Shinde 4484d3acb9dSRajeshwari Shinde if (node <= 0) 4494d3acb9dSRajeshwari Shinde continue; 4504d3acb9dSRajeshwari Shinde 4514d3acb9dSRajeshwari Shinde bus = &spi_bus[i]; 4524d3acb9dSRajeshwari Shinde if (spi_get_config(blob, node, bus)) { 4534d3acb9dSRajeshwari Shinde printf("exynos spi_init: failed to decode bus %d\n", 4544d3acb9dSRajeshwari Shinde i); 4554d3acb9dSRajeshwari Shinde return -1; 4564d3acb9dSRajeshwari Shinde } 4574d3acb9dSRajeshwari Shinde 4584d3acb9dSRajeshwari Shinde debug("spi: controller bus %d at %p, periph_id %d\n", 4594d3acb9dSRajeshwari Shinde i, bus->regs, bus->periph_id); 4604d3acb9dSRajeshwari Shinde bus->inited = 1; 4614d3acb9dSRajeshwari Shinde bus_count++; 4624d3acb9dSRajeshwari Shinde } 4634d3acb9dSRajeshwari Shinde 4644d3acb9dSRajeshwari Shinde return 0; 4654d3acb9dSRajeshwari Shinde } 4667d179584SVivek Gautam #endif 4674d3acb9dSRajeshwari Shinde 4681bf43b82SRajeshwari Shinde /* Sadly there is no error return from this function */ 4691bf43b82SRajeshwari Shinde void spi_init(void) 4701bf43b82SRajeshwari Shinde { 4714d3acb9dSRajeshwari Shinde int count; 4724d3acb9dSRajeshwari Shinde 4734d3acb9dSRajeshwari Shinde #ifdef CONFIG_OF_CONTROL 4744d3acb9dSRajeshwari Shinde int node_list[EXYNOS5_SPI_NUM_CONTROLLERS]; 4754d3acb9dSRajeshwari Shinde const void *blob = gd->fdt_blob; 4764d3acb9dSRajeshwari Shinde 4774d3acb9dSRajeshwari Shinde count = fdtdec_find_aliases_for_id(blob, "spi", 4784d3acb9dSRajeshwari Shinde COMPAT_SAMSUNG_EXYNOS_SPI, node_list, 4794d3acb9dSRajeshwari Shinde EXYNOS5_SPI_NUM_CONTROLLERS); 4804d3acb9dSRajeshwari Shinde if (process_nodes(blob, node_list, count)) 4814d3acb9dSRajeshwari Shinde return; 4824d3acb9dSRajeshwari Shinde 4834d3acb9dSRajeshwari Shinde #else 4841bf43b82SRajeshwari Shinde struct spi_bus *bus; 4851bf43b82SRajeshwari Shinde 4864d3acb9dSRajeshwari Shinde for (count = 0; count < EXYNOS5_SPI_NUM_CONTROLLERS; count++) { 4874d3acb9dSRajeshwari Shinde bus = &spi_bus[count]; 4884d3acb9dSRajeshwari Shinde bus->regs = get_spi_base(count); 4894d3acb9dSRajeshwari Shinde bus->periph_id = PERIPH_ID_SPI0 + count; 4901bf43b82SRajeshwari Shinde 4911bf43b82SRajeshwari Shinde /* Although Exynos5 supports upto 50Mhz speed, 4921bf43b82SRajeshwari Shinde * we are setting it to 10Mhz for safe side 4931bf43b82SRajeshwari Shinde */ 4941bf43b82SRajeshwari Shinde bus->frequency = 10000000; 4951bf43b82SRajeshwari Shinde bus->inited = 1; 4964d3acb9dSRajeshwari Shinde bus->node = 0; 4974d3acb9dSRajeshwari Shinde bus_count = EXYNOS5_SPI_NUM_CONTROLLERS; 4981bf43b82SRajeshwari Shinde } 4994d3acb9dSRajeshwari Shinde #endif 5001bf43b82SRajeshwari Shinde } 501