1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2001 Navin Boppuri / Prashant Patel 4 * <nboppuri@trinetcommunication.com>, 5 * <pmpatel@trinetcommunication.com> 6 * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de> 7 * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>. 8 */ 9 10 /* 11 * MPC8xx CPM SPI interface. 12 * 13 * Parts of this code are probably not portable and/or specific to 14 * the board which I used for the tests. Please send fixes/complaints 15 * to wd@denx.de 16 * 17 */ 18 19 #include <common.h> 20 #include <mpc8xx.h> 21 #include <asm/cpm_8xx.h> 22 #include <linux/ctype.h> 23 #include <malloc.h> 24 #include <post.h> 25 #include <serial.h> 26 27 #define SPI_EEPROM_WREN 0x06 28 #define SPI_EEPROM_RDSR 0x05 29 #define SPI_EEPROM_READ 0x03 30 #define SPI_EEPROM_WRITE 0x02 31 32 /* --------------------------------------------------------------- 33 * Offset for initial SPI buffers in DPRAM: 34 * We need a 520 byte scratch DPRAM area to use at an early stage. 35 * It is used between the two initialization calls (spi_init_f() 36 * and spi_init_r()). 37 * The value 0xb00 makes it far enough from the start of the data 38 * area (as well as from the stack pointer). 39 * --------------------------------------------------------------- */ 40 #ifndef CONFIG_SYS_SPI_INIT_OFFSET 41 #define CONFIG_SYS_SPI_INIT_OFFSET 0xB00 42 #endif 43 44 #define CPM_SPI_BASE_RX CPM_SPI_BASE 45 #define CPM_SPI_BASE_TX (CPM_SPI_BASE + sizeof(cbd_t)) 46 47 /* ------------------- 48 * Function prototypes 49 * ------------------- */ 50 ssize_t spi_xfer(size_t); 51 52 /* ------------------- 53 * Variables 54 * ------------------- */ 55 56 #define MAX_BUFFER 0x104 57 58 /* ---------------------------------------------------------------------- 59 * Initially we place the RX and TX buffers at a fixed location in DPRAM! 60 * ---------------------------------------------------------------------- */ 61 static uchar *rxbuf = 62 (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem 63 [CONFIG_SYS_SPI_INIT_OFFSET]; 64 static uchar *txbuf = 65 (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem 66 [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER]; 67 68 /* ************************************************************************** 69 * 70 * Function: spi_init_f 71 * 72 * Description: Init SPI-Controller (ROM part) 73 * 74 * return: --- 75 * 76 * *********************************************************************** */ 77 void spi_init_f(void) 78 { 79 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; 80 cpm8xx_t __iomem *cp = &immr->im_cpm; 81 spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI]; 82 cbd_t __iomem *tbdf, *rbdf; 83 84 /* Disable relocation */ 85 out_be16(&spi->spi_rpbase, 0); 86 87 /* 1 */ 88 /* ------------------------------------------------ 89 * Initialize Port B SPI pins -> page 34-8 MPC860UM 90 * (we are only in Master Mode !) 91 * ------------------------------------------------ */ 92 93 /* -------------------------------------------- 94 * GPIO or per. Function 95 * PBPAR[28] = 1 [0x00000008] -> PERI: (SPIMISO) 96 * PBPAR[29] = 1 [0x00000004] -> PERI: (SPIMOSI) 97 * PBPAR[30] = 1 [0x00000002] -> PERI: (SPICLK) 98 * PBPAR[31] = 0 [0x00000001] -> GPIO: (CS for PCUE/CCM-EEPROM) 99 * -------------------------------------------- */ 100 clrsetbits_be32(&cp->cp_pbpar, 0x00000001, 0x0000000E); /* set bits */ 101 102 /* ---------------------------------------------- 103 * In/Out or per. Function 0/1 104 * PBDIR[28] = 1 [0x00000008] -> PERI1: SPIMISO 105 * PBDIR[29] = 1 [0x00000004] -> PERI1: SPIMOSI 106 * PBDIR[30] = 1 [0x00000002] -> PERI1: SPICLK 107 * PBDIR[31] = 1 [0x00000001] -> GPIO OUT: CS for PCUE/CCM-EEPROM 108 * ---------------------------------------------- */ 109 setbits_be32(&cp->cp_pbdir, 0x0000000F); 110 111 /* ---------------------------------------------- 112 * open drain or active output 113 * PBODR[28] = 1 [0x00000008] -> open drain: SPIMISO 114 * PBODR[29] = 0 [0x00000004] -> active output SPIMOSI 115 * PBODR[30] = 0 [0x00000002] -> active output: SPICLK 116 * PBODR[31] = 0 [0x00000001] -> active output GPIO OUT: CS for PCUE/CCM 117 * ---------------------------------------------- */ 118 119 clrsetbits_be16(&cp->cp_pbodr, 0x00000007, 0x00000008); 120 121 /* Initialize the parameter ram. 122 * We need to make sure many things are initialized to zero 123 */ 124 out_be32(&spi->spi_rstate, 0); 125 out_be32(&spi->spi_rdp, 0); 126 out_be16(&spi->spi_rbptr, 0); 127 out_be16(&spi->spi_rbc, 0); 128 out_be32(&spi->spi_rxtmp, 0); 129 out_be32(&spi->spi_tstate, 0); 130 out_be32(&spi->spi_tdp, 0); 131 out_be16(&spi->spi_tbptr, 0); 132 out_be16(&spi->spi_tbc, 0); 133 out_be32(&spi->spi_txtmp, 0); 134 135 /* 3 */ 136 /* Set up the SPI parameters in the parameter ram */ 137 out_be16(&spi->spi_rbase, CPM_SPI_BASE_RX); 138 out_be16(&spi->spi_tbase, CPM_SPI_BASE_TX); 139 140 /***********IMPORTANT******************/ 141 142 /* 143 * Setting transmit and receive buffer descriptor pointers 144 * initially to rbase and tbase. Only the microcode patches 145 * documentation talks about initializing this pointer. This 146 * is missing from the sample I2C driver. If you dont 147 * initialize these pointers, the kernel hangs. 148 */ 149 out_be16(&spi->spi_rbptr, CPM_SPI_BASE_RX); 150 out_be16(&spi->spi_tbptr, CPM_SPI_BASE_TX); 151 152 /* 4 */ 153 /* Init SPI Tx + Rx Parameters */ 154 while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) 155 ; 156 157 out_be16(&cp->cp_cpcr, mk_cr_cmd(CPM_CR_CH_SPI, CPM_CR_INIT_TRX) | 158 CPM_CR_FLG); 159 while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) 160 ; 161 162 /* 5 */ 163 /* Set SDMA configuration register */ 164 out_be32(&immr->im_siu_conf.sc_sdcr, 0x0001); 165 166 /* 6 */ 167 /* Set to big endian. */ 168 out_8(&spi->spi_tfcr, SMC_EB); 169 out_8(&spi->spi_rfcr, SMC_EB); 170 171 /* 7 */ 172 /* Set maximum receive size. */ 173 out_be16(&spi->spi_mrblr, MAX_BUFFER); 174 175 /* 8 + 9 */ 176 /* tx and rx buffer descriptors */ 177 tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; 178 rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX]; 179 180 clrbits_be16(&tbdf->cbd_sc, BD_SC_READY); 181 clrbits_be16(&rbdf->cbd_sc, BD_SC_EMPTY); 182 183 /* Set the bd's rx and tx buffer address pointers */ 184 out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf); 185 out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf); 186 187 /* 10 + 11 */ 188 out_8(&cp->cp_spim, 0); /* Mask all SPI events */ 189 out_8(&cp->cp_spie, SPI_EMASK); /* Clear all SPI events */ 190 191 return; 192 } 193 194 /* ************************************************************************** 195 * 196 * Function: spi_init_r 197 * 198 * Description: Init SPI-Controller (RAM part) - 199 * The malloc engine is ready and we can move our buffers to 200 * normal RAM 201 * 202 * return: --- 203 * 204 * *********************************************************************** */ 205 void spi_init_r(void) 206 { 207 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; 208 cpm8xx_t __iomem *cp = &immr->im_cpm; 209 spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI]; 210 cbd_t __iomem *tbdf, *rbdf; 211 212 /* Disable relocation */ 213 out_be16(&spi->spi_rpbase, 0); 214 215 /* tx and rx buffer descriptors */ 216 tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; 217 rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX]; 218 219 /* Allocate memory for RX and TX buffers */ 220 rxbuf = (uchar *)malloc(MAX_BUFFER); 221 txbuf = (uchar *)malloc(MAX_BUFFER); 222 223 out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf); 224 out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf); 225 226 return; 227 } 228 229 /**************************************************************************** 230 * Function: spi_write 231 **************************************************************************** */ 232 ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len) 233 { 234 int i; 235 236 memset(rxbuf, 0, MAX_BUFFER); 237 memset(txbuf, 0, MAX_BUFFER); 238 *txbuf = SPI_EEPROM_WREN; /* write enable */ 239 spi_xfer(1); 240 memcpy(txbuf, addr, alen); 241 *txbuf = SPI_EEPROM_WRITE; /* WRITE memory array */ 242 memcpy(alen + txbuf, buffer, len); 243 spi_xfer(alen + len); 244 /* ignore received data */ 245 for (i = 0; i < 1000; i++) { 246 *txbuf = SPI_EEPROM_RDSR; /* read status */ 247 txbuf[1] = 0; 248 spi_xfer(2); 249 if (!(rxbuf[1] & 1)) 250 break; 251 udelay(1000); 252 } 253 if (i >= 1000) 254 printf("*** spi_write: Time out while writing!\n"); 255 256 return len; 257 } 258 259 /**************************************************************************** 260 * Function: spi_read 261 **************************************************************************** */ 262 ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len) 263 { 264 memset(rxbuf, 0, MAX_BUFFER); 265 memset(txbuf, 0, MAX_BUFFER); 266 memcpy(txbuf, addr, alen); 267 *txbuf = SPI_EEPROM_READ; /* READ memory array */ 268 269 /* 270 * There is a bug in 860T (?) that cuts the last byte of input 271 * if we're reading into DPRAM. The solution we choose here is 272 * to always read len+1 bytes (we have one extra byte at the 273 * end of the buffer). 274 */ 275 spi_xfer(alen + len + 1); 276 memcpy(buffer, alen + rxbuf, len); 277 278 return len; 279 } 280 281 /**************************************************************************** 282 * Function: spi_xfer 283 **************************************************************************** */ 284 ssize_t spi_xfer(size_t count) 285 { 286 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; 287 cpm8xx_t __iomem *cp = &immr->im_cpm; 288 spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI]; 289 cbd_t __iomem *tbdf, *rbdf; 290 int tm; 291 292 /* Disable relocation */ 293 out_be16(&spi->spi_rpbase, 0); 294 295 tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; 296 rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX]; 297 298 /* Set CS for device */ 299 clrbits_be32(&cp->cp_pbdat, 0x0001); 300 301 /* Setting tx bd status and data length */ 302 out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP); 303 out_be16(&tbdf->cbd_datlen, count); 304 305 /* Setting rx bd status and data length */ 306 out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_WRAP); 307 out_be16(&rbdf->cbd_datlen, 0); /* rx length has no significance */ 308 309 clrsetbits_be16(&cp->cp_spmode, ~SPMODE_LOOP, SPMODE_REV | SPMODE_MSTR | 310 SPMODE_EN | SPMODE_LEN(8) | SPMODE_PM(0x8)); 311 out_8(&cp->cp_spim, 0); /* Mask all SPI events */ 312 out_8(&cp->cp_spie, SPI_EMASK); /* Clear all SPI events */ 313 314 /* start spi transfer */ 315 setbits_8(&cp->cp_spcom, SPI_STR); /* Start transmit */ 316 317 /* -------------------------------- 318 * Wait for SPI transmit to get out 319 * or time out (1 second = 1000 ms) 320 * -------------------------------- */ 321 for (tm = 0; tm < 1000; ++tm) { 322 if (in_8(&cp->cp_spie) & SPI_TXB) /* Tx Buffer Empty */ 323 break; 324 if ((in_be16(&tbdf->cbd_sc) & BD_SC_READY) == 0) 325 break; 326 udelay(1000); 327 } 328 if (tm >= 1000) 329 printf("*** spi_xfer: Time out while xferring to/from SPI!\n"); 330 331 /* Clear CS for device */ 332 setbits_be32(&cp->cp_pbdat, 0x0001); 333 334 return count; 335 } 336