1 /* 2 * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com> 3 * 4 * Driver for McSPI controller on OMAP3. Based on davinci_spi.c 5 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 6 * 7 * Copyright (C) 2007 Atmel Corporation 8 * 9 * Parts taken from linux/drivers/spi/omap2_mcspi.c 10 * Copyright (C) 2005, 2006 Nokia Corporation 11 * 12 * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com> 13 * 14 * See file CREDITS for list of people who contributed to this 15 * project. 16 * 17 * This program is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU General Public License as 19 * published by the Free Software Foundation; either version 2 of 20 * the License, or (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 30 * MA 02111-1307 USA 31 * 32 */ 33 34 #include <common.h> 35 #include <spi.h> 36 #include <malloc.h> 37 #include <asm/io.h> 38 #include "omap3_spi.h" 39 40 #define WORD_LEN 8 41 #define SPI_WAIT_TIMEOUT 3000000; 42 43 static void spi_reset(struct omap3_spi_slave *ds) 44 { 45 unsigned int tmp; 46 47 writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig); 48 do { 49 tmp = readl(&ds->regs->sysstatus); 50 } while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE)); 51 52 writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE | 53 OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP | 54 OMAP3_MCSPI_SYSCONFIG_SMARTIDLE, 55 &ds->regs->sysconfig); 56 57 writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable); 58 } 59 60 void spi_init() 61 { 62 /* do nothing */ 63 } 64 65 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 66 unsigned int max_hz, unsigned int mode) 67 { 68 struct omap3_spi_slave *ds; 69 70 ds = malloc(sizeof(struct omap3_spi_slave)); 71 if (!ds) { 72 printf("SPI error: malloc of SPI structure failed\n"); 73 return NULL; 74 } 75 76 /* 77 * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules) 78 * with different number of chip selects (CS, channels): 79 * McSPI1 has 4 CS (bus 0, cs 0 - 3) 80 * McSPI2 has 2 CS (bus 1, cs 0 - 1) 81 * McSPI3 has 2 CS (bus 2, cs 0 - 1) 82 * McSPI4 has 1 CS (bus 3, cs 0) 83 */ 84 85 switch (bus) { 86 case 0: 87 ds->regs = (struct mcspi *)OMAP3_MCSPI1_BASE; 88 break; 89 #ifdef OMAP3_MCSPI2_BASE 90 case 1: 91 ds->regs = (struct mcspi *)OMAP3_MCSPI2_BASE; 92 break; 93 #endif 94 #ifdef OMAP3_MCSPI3_BASE 95 case 2: 96 ds->regs = (struct mcspi *)OMAP3_MCSPI3_BASE; 97 break; 98 #endif 99 #ifdef OMAP3_MCSPI4_BASE 100 case 3: 101 ds->regs = (struct mcspi *)OMAP3_MCSPI4_BASE; 102 break; 103 #endif 104 default: 105 printf("SPI error: unsupported bus %i. \ 106 Supported busses 0 - 3\n", bus); 107 return NULL; 108 } 109 ds->slave.bus = bus; 110 111 if (((bus == 0) && (cs > 3)) || 112 ((bus == 1) && (cs > 1)) || 113 ((bus == 2) && (cs > 1)) || 114 ((bus == 3) && (cs > 0))) { 115 printf("SPI error: unsupported chip select %i \ 116 on bus %i\n", cs, bus); 117 return NULL; 118 } 119 ds->slave.cs = cs; 120 121 if (max_hz > OMAP3_MCSPI_MAX_FREQ) { 122 printf("SPI error: unsupported frequency %i Hz. \ 123 Max frequency is 48 Mhz\n", max_hz); 124 return NULL; 125 } 126 ds->freq = max_hz; 127 128 if (mode > SPI_MODE_3) { 129 printf("SPI error: unsupported SPI mode %i\n", mode); 130 return NULL; 131 } 132 ds->mode = mode; 133 134 return &ds->slave; 135 } 136 137 void spi_free_slave(struct spi_slave *slave) 138 { 139 struct omap3_spi_slave *ds = to_omap3_spi(slave); 140 141 free(ds); 142 } 143 144 int spi_claim_bus(struct spi_slave *slave) 145 { 146 struct omap3_spi_slave *ds = to_omap3_spi(slave); 147 unsigned int conf, div = 0; 148 149 /* McSPI global module configuration */ 150 151 /* 152 * setup when switching from (reset default) slave mode 153 * to single-channel master mode 154 */ 155 spi_reset(ds); 156 conf = readl(&ds->regs->modulctrl); 157 conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS); 158 conf |= OMAP3_MCSPI_MODULCTRL_SINGLE; 159 writel(conf, &ds->regs->modulctrl); 160 161 /* McSPI individual channel configuration */ 162 163 /* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */ 164 if (ds->freq) { 165 while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div)) 166 > ds->freq) 167 div++; 168 } else 169 div = 0xC; 170 171 conf = readl(&ds->regs->channel[ds->slave.cs].chconf); 172 173 /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS 174 * REVISIT: this controller could support SPI_3WIRE mode. 175 */ 176 conf &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1); 177 conf |= OMAP3_MCSPI_CHCONF_DPE0; 178 179 /* wordlength */ 180 conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK; 181 conf |= (WORD_LEN - 1) << 7; 182 183 /* set chipselect polarity; manage with FORCE */ 184 if (!(ds->mode & SPI_CS_HIGH)) 185 conf |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */ 186 else 187 conf &= ~OMAP3_MCSPI_CHCONF_EPOL; 188 189 /* set clock divisor */ 190 conf &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK; 191 conf |= div << 2; 192 193 /* set SPI mode 0..3 */ 194 if (ds->mode & SPI_CPOL) 195 conf |= OMAP3_MCSPI_CHCONF_POL; 196 else 197 conf &= ~OMAP3_MCSPI_CHCONF_POL; 198 if (ds->mode & SPI_CPHA) 199 conf |= OMAP3_MCSPI_CHCONF_PHA; 200 else 201 conf &= ~OMAP3_MCSPI_CHCONF_PHA; 202 203 /* Transmit & receive mode */ 204 conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 205 206 writel(conf, &ds->regs->channel[ds->slave.cs].chconf); 207 208 return 0; 209 } 210 211 void spi_release_bus(struct spi_slave *slave) 212 { 213 struct omap3_spi_slave *ds = to_omap3_spi(slave); 214 215 /* Reset the SPI hardware */ 216 spi_reset(ds); 217 } 218 219 int omap3_spi_write(struct spi_slave *slave, unsigned int len, const u8 *txp, 220 unsigned long flags) 221 { 222 struct omap3_spi_slave *ds = to_omap3_spi(slave); 223 int i; 224 int timeout = SPI_WAIT_TIMEOUT; 225 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 226 227 if (flags & SPI_XFER_BEGIN) 228 writel(OMAP3_MCSPI_CHCTRL_EN, 229 &ds->regs->channel[ds->slave.cs].chctrl); 230 231 chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 232 chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY; 233 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 234 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 235 236 for (i = 0; i < len; i++) { 237 /* wait till TX register is empty (TXS == 1) */ 238 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 239 OMAP3_MCSPI_CHSTAT_TXS)) { 240 if (--timeout <= 0) { 241 printf("SPI TXS timed out, status=0x%08x\n", 242 readl(&ds->regs->channel[ds->slave.cs].chstat)); 243 return -1; 244 } 245 } 246 /* Write the data */ 247 writel(txp[i], &ds->regs->channel[ds->slave.cs].tx); 248 } 249 250 if (flags & SPI_XFER_END) { 251 /* wait to finish of transfer */ 252 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 253 OMAP3_MCSPI_CHSTAT_EOT)); 254 255 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 256 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 257 258 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 259 } 260 return 0; 261 } 262 263 int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp, 264 unsigned long flags) 265 { 266 struct omap3_spi_slave *ds = to_omap3_spi(slave); 267 int i; 268 int timeout = SPI_WAIT_TIMEOUT; 269 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 270 271 if (flags & SPI_XFER_BEGIN) 272 writel(OMAP3_MCSPI_CHCTRL_EN, 273 &ds->regs->channel[ds->slave.cs].chctrl); 274 275 chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 276 chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY; 277 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 278 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 279 280 writel(0, &ds->regs->channel[ds->slave.cs].tx); 281 282 for (i = 0; i < len; i++) { 283 /* Wait till RX register contains data (RXS == 1) */ 284 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 285 OMAP3_MCSPI_CHSTAT_RXS)) { 286 if (--timeout <= 0) { 287 printf("SPI RXS timed out, status=0x%08x\n", 288 readl(&ds->regs->channel[ds->slave.cs].chstat)); 289 return -1; 290 } 291 } 292 /* Read the data */ 293 rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx); 294 } 295 296 if (flags & SPI_XFER_END) { 297 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 298 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 299 300 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 301 } 302 303 return 0; 304 } 305 306 /*McSPI Transmit Receive Mode*/ 307 int omap3_spi_txrx(struct spi_slave *slave, 308 unsigned int len, const u8 *txp, u8 *rxp, unsigned long flags) 309 { 310 struct omap3_spi_slave *ds = to_omap3_spi(slave); 311 int timeout = SPI_WAIT_TIMEOUT; 312 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 313 int irqstatus = readl(&ds->regs->irqstatus); 314 int i=0; 315 316 /*Enable SPI channel*/ 317 if (flags & SPI_XFER_BEGIN) 318 writel(OMAP3_MCSPI_CHCTRL_EN, 319 &ds->regs->channel[ds->slave.cs].chctrl); 320 321 /*set TRANSMIT-RECEIVE Mode*/ 322 chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 323 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 324 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 325 326 /*Shift in and out 1 byte at time*/ 327 for (i=0; i < len; i++){ 328 /* Write: wait for TX empty (TXS == 1)*/ 329 irqstatus |= (1<< (4*(ds->slave.bus))); 330 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 331 OMAP3_MCSPI_CHSTAT_TXS)) { 332 if (--timeout <= 0) { 333 printf("SPI TXS timed out, status=0x%08x\n", 334 readl(&ds->regs->channel[ds->slave.cs].chstat)); 335 return -1; 336 } 337 } 338 /* Write the data */ 339 writel(txp[i], &ds->regs->channel[ds->slave.cs].tx); 340 341 /*Read: wait for RX containing data (RXS == 1)*/ 342 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 343 OMAP3_MCSPI_CHSTAT_RXS)) { 344 if (--timeout <= 0) { 345 printf("SPI RXS timed out, status=0x%08x\n", 346 readl(&ds->regs->channel[ds->slave.cs].chstat)); 347 return -1; 348 } 349 } 350 /* Read the data */ 351 rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx); 352 } 353 354 /*if transfer must be terminated disable the channel*/ 355 if (flags & SPI_XFER_END) { 356 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 357 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 358 359 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 360 } 361 362 return 0; 363 } 364 365 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, 366 const void *dout, void *din, unsigned long flags) 367 { 368 struct omap3_spi_slave *ds = to_omap3_spi(slave); 369 unsigned int len; 370 const u8 *txp = dout; 371 u8 *rxp = din; 372 int ret = -1; 373 374 if (bitlen % 8) 375 return -1; 376 377 len = bitlen / 8; 378 379 if (bitlen == 0) { /* only change CS */ 380 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 381 382 if (flags & SPI_XFER_BEGIN) { 383 writel(OMAP3_MCSPI_CHCTRL_EN, 384 &ds->regs->channel[ds->slave.cs].chctrl); 385 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 386 writel(chconf, 387 &ds->regs->channel[ds->slave.cs].chconf); 388 } 389 if (flags & SPI_XFER_END) { 390 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 391 writel(chconf, 392 &ds->regs->channel[ds->slave.cs].chconf); 393 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 394 } 395 ret = 0; 396 } else { 397 if (dout != NULL && din != NULL) 398 ret = omap3_spi_txrx(slave, len, txp, rxp, flags); 399 else if (dout != NULL) 400 ret = omap3_spi_write(slave, len, txp, flags); 401 else if (din != NULL) 402 ret = omap3_spi_read(slave, len, rxp, flags); 403 } 404 return ret; 405 } 406 407 int spi_cs_is_valid(unsigned int bus, unsigned int cs) 408 { 409 return 1; 410 } 411 412 void spi_cs_activate(struct spi_slave *slave) 413 { 414 } 415 416 void spi_cs_deactivate(struct spi_slave *slave) 417 { 418 } 419