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