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 #ifdef CONFIG_OMAP3_SPI_D0_D1_SWAPPED 177 /* 178 * Some boards have D0 wired as MOSI / D1 as MISO instead of 179 * The normal D0 as MISO / D1 as MOSI. 180 */ 181 conf &= ~OMAP3_MCSPI_CHCONF_DPE0; 182 conf |= OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1; 183 #else 184 conf &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1); 185 conf |= OMAP3_MCSPI_CHCONF_DPE0; 186 #endif 187 188 /* wordlength */ 189 conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK; 190 conf |= (WORD_LEN - 1) << 7; 191 192 /* set chipselect polarity; manage with FORCE */ 193 if (!(ds->mode & SPI_CS_HIGH)) 194 conf |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */ 195 else 196 conf &= ~OMAP3_MCSPI_CHCONF_EPOL; 197 198 /* set clock divisor */ 199 conf &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK; 200 conf |= div << 2; 201 202 /* set SPI mode 0..3 */ 203 if (ds->mode & SPI_CPOL) 204 conf |= OMAP3_MCSPI_CHCONF_POL; 205 else 206 conf &= ~OMAP3_MCSPI_CHCONF_POL; 207 if (ds->mode & SPI_CPHA) 208 conf |= OMAP3_MCSPI_CHCONF_PHA; 209 else 210 conf &= ~OMAP3_MCSPI_CHCONF_PHA; 211 212 /* Transmit & receive mode */ 213 conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 214 215 writel(conf, &ds->regs->channel[ds->slave.cs].chconf); 216 217 return 0; 218 } 219 220 void spi_release_bus(struct spi_slave *slave) 221 { 222 struct omap3_spi_slave *ds = to_omap3_spi(slave); 223 224 /* Reset the SPI hardware */ 225 spi_reset(ds); 226 } 227 228 int omap3_spi_write(struct spi_slave *slave, unsigned int len, const u8 *txp, 229 unsigned long flags) 230 { 231 struct omap3_spi_slave *ds = to_omap3_spi(slave); 232 int i; 233 int timeout = SPI_WAIT_TIMEOUT; 234 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 235 236 if (flags & SPI_XFER_BEGIN) 237 writel(OMAP3_MCSPI_CHCTRL_EN, 238 &ds->regs->channel[ds->slave.cs].chctrl); 239 240 chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 241 chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY; 242 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 243 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 244 245 for (i = 0; i < len; i++) { 246 /* wait till TX register is empty (TXS == 1) */ 247 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 248 OMAP3_MCSPI_CHSTAT_TXS)) { 249 if (--timeout <= 0) { 250 printf("SPI TXS timed out, status=0x%08x\n", 251 readl(&ds->regs->channel[ds->slave.cs].chstat)); 252 return -1; 253 } 254 } 255 /* Write the data */ 256 writel(txp[i], &ds->regs->channel[ds->slave.cs].tx); 257 } 258 259 if (flags & SPI_XFER_END) { 260 /* wait to finish of transfer */ 261 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 262 OMAP3_MCSPI_CHSTAT_EOT)); 263 264 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 265 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 266 267 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 268 } 269 return 0; 270 } 271 272 int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp, 273 unsigned long flags) 274 { 275 struct omap3_spi_slave *ds = to_omap3_spi(slave); 276 int i; 277 int timeout = SPI_WAIT_TIMEOUT; 278 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 279 280 if (flags & SPI_XFER_BEGIN) 281 writel(OMAP3_MCSPI_CHCTRL_EN, 282 &ds->regs->channel[ds->slave.cs].chctrl); 283 284 chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 285 chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY; 286 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 287 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 288 289 writel(0, &ds->regs->channel[ds->slave.cs].tx); 290 291 for (i = 0; i < len; i++) { 292 /* Wait till RX register contains data (RXS == 1) */ 293 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 294 OMAP3_MCSPI_CHSTAT_RXS)) { 295 if (--timeout <= 0) { 296 printf("SPI RXS timed out, status=0x%08x\n", 297 readl(&ds->regs->channel[ds->slave.cs].chstat)); 298 return -1; 299 } 300 } 301 /* Read the data */ 302 rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx); 303 } 304 305 if (flags & SPI_XFER_END) { 306 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 307 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 308 309 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 310 } 311 312 return 0; 313 } 314 315 /*McSPI Transmit Receive Mode*/ 316 int omap3_spi_txrx(struct spi_slave *slave, 317 unsigned int len, const u8 *txp, u8 *rxp, unsigned long flags) 318 { 319 struct omap3_spi_slave *ds = to_omap3_spi(slave); 320 int timeout = SPI_WAIT_TIMEOUT; 321 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 322 int irqstatus = readl(&ds->regs->irqstatus); 323 int i=0; 324 325 /*Enable SPI channel*/ 326 if (flags & SPI_XFER_BEGIN) 327 writel(OMAP3_MCSPI_CHCTRL_EN, 328 &ds->regs->channel[ds->slave.cs].chctrl); 329 330 /*set TRANSMIT-RECEIVE Mode*/ 331 chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; 332 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 333 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 334 335 /*Shift in and out 1 byte at time*/ 336 for (i=0; i < len; i++){ 337 /* Write: wait for TX empty (TXS == 1)*/ 338 irqstatus |= (1<< (4*(ds->slave.bus))); 339 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 340 OMAP3_MCSPI_CHSTAT_TXS)) { 341 if (--timeout <= 0) { 342 printf("SPI TXS timed out, status=0x%08x\n", 343 readl(&ds->regs->channel[ds->slave.cs].chstat)); 344 return -1; 345 } 346 } 347 /* Write the data */ 348 writel(txp[i], &ds->regs->channel[ds->slave.cs].tx); 349 350 /*Read: wait for RX containing data (RXS == 1)*/ 351 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & 352 OMAP3_MCSPI_CHSTAT_RXS)) { 353 if (--timeout <= 0) { 354 printf("SPI RXS timed out, status=0x%08x\n", 355 readl(&ds->regs->channel[ds->slave.cs].chstat)); 356 return -1; 357 } 358 } 359 /* Read the data */ 360 rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx); 361 } 362 363 /*if transfer must be terminated disable the channel*/ 364 if (flags & SPI_XFER_END) { 365 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 366 writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); 367 368 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 369 } 370 371 return 0; 372 } 373 374 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, 375 const void *dout, void *din, unsigned long flags) 376 { 377 struct omap3_spi_slave *ds = to_omap3_spi(slave); 378 unsigned int len; 379 const u8 *txp = dout; 380 u8 *rxp = din; 381 int ret = -1; 382 383 if (bitlen % 8) 384 return -1; 385 386 len = bitlen / 8; 387 388 if (bitlen == 0) { /* only change CS */ 389 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); 390 391 if (flags & SPI_XFER_BEGIN) { 392 writel(OMAP3_MCSPI_CHCTRL_EN, 393 &ds->regs->channel[ds->slave.cs].chctrl); 394 chconf |= OMAP3_MCSPI_CHCONF_FORCE; 395 writel(chconf, 396 &ds->regs->channel[ds->slave.cs].chconf); 397 } 398 if (flags & SPI_XFER_END) { 399 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; 400 writel(chconf, 401 &ds->regs->channel[ds->slave.cs].chconf); 402 writel(0, &ds->regs->channel[ds->slave.cs].chctrl); 403 } 404 ret = 0; 405 } else { 406 if (dout != NULL && din != NULL) 407 ret = omap3_spi_txrx(slave, len, txp, rxp, flags); 408 else if (dout != NULL) 409 ret = omap3_spi_write(slave, len, txp, flags); 410 else if (din != NULL) 411 ret = omap3_spi_read(slave, len, rxp, flags); 412 } 413 return ret; 414 } 415 416 int spi_cs_is_valid(unsigned int bus, unsigned int cs) 417 { 418 return 1; 419 } 420 421 void spi_cs_activate(struct spi_slave *slave) 422 { 423 } 424 425 void spi_cs_deactivate(struct spi_slave *slave) 426 { 427 } 428