1 /* 2 * (C) Copyright 2009 3 * Marvell Semiconductor <www.marvell.com> 4 * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 5 * 6 * Derived from drivers/spi/mpc8xxx_spi.c 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <malloc.h> 13 #include <spi.h> 14 #include <asm/io.h> 15 #include <asm/arch/kirkwood.h> 16 #include <asm/arch/spi.h> 17 #include <asm/arch/mpp.h> 18 19 static struct kwspi_registers *spireg = (struct kwspi_registers *)KW_SPI_BASE; 20 21 u32 cs_spi_mpp_back[2]; 22 23 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 24 unsigned int max_hz, unsigned int mode) 25 { 26 struct spi_slave *slave; 27 u32 data; 28 static const u32 kwspi_mpp_config[2][2] = { 29 { MPP0_SPI_SCn, 0 }, /* if cs == 0 */ 30 { MPP7_SPI_SCn, 0 } /* if cs != 0 */ 31 }; 32 33 if (!spi_cs_is_valid(bus, cs)) 34 return NULL; 35 36 slave = spi_alloc_slave_base(bus, cs); 37 if (!slave) 38 return NULL; 39 40 writel(~KWSPI_CSN_ACT | KWSPI_SMEMRDY, &spireg->ctrl); 41 42 /* calculate spi clock prescaller using max_hz */ 43 data = ((CONFIG_SYS_TCLK / 2) / max_hz) + 0x10; 44 data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data; 45 data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data; 46 47 /* program spi clock prescaller using max_hz */ 48 writel(KWSPI_ADRLEN_3BYTE | data, &spireg->cfg); 49 debug("data = 0x%08x \n", data); 50 51 writel(KWSPI_SMEMRDIRQ, &spireg->irq_cause); 52 writel(KWSPI_IRQMASK, &spireg->irq_mask); 53 54 /* program mpp registers to select SPI_CSn */ 55 kirkwood_mpp_conf(kwspi_mpp_config[cs ? 1 : 0], cs_spi_mpp_back); 56 57 return slave; 58 } 59 60 void spi_free_slave(struct spi_slave *slave) 61 { 62 kirkwood_mpp_conf(cs_spi_mpp_back, NULL); 63 free(slave); 64 } 65 66 #if defined(CONFIG_SYS_KW_SPI_MPP) 67 u32 spi_mpp_backup[4]; 68 #endif 69 70 __attribute__((weak)) int board_spi_claim_bus(struct spi_slave *slave) 71 { 72 return 0; 73 } 74 75 int spi_claim_bus(struct spi_slave *slave) 76 { 77 #if defined(CONFIG_SYS_KW_SPI_MPP) 78 u32 config; 79 u32 spi_mpp_config[4]; 80 81 config = CONFIG_SYS_KW_SPI_MPP; 82 83 if (config & MOSI_MPP6) 84 spi_mpp_config[0] = MPP6_SPI_MOSI; 85 else 86 spi_mpp_config[0] = MPP1_SPI_MOSI; 87 88 if (config & SCK_MPP10) 89 spi_mpp_config[1] = MPP10_SPI_SCK; 90 else 91 spi_mpp_config[1] = MPP2_SPI_SCK; 92 93 if (config & MISO_MPP11) 94 spi_mpp_config[2] = MPP11_SPI_MISO; 95 else 96 spi_mpp_config[2] = MPP3_SPI_MISO; 97 98 spi_mpp_config[3] = 0; 99 spi_mpp_backup[3] = 0; 100 101 /* set new spi mpp and save current mpp config */ 102 kirkwood_mpp_conf(spi_mpp_config, spi_mpp_backup); 103 104 #endif 105 106 return board_spi_claim_bus(slave); 107 } 108 109 __attribute__((weak)) void board_spi_release_bus(struct spi_slave *slave) 110 { 111 } 112 113 void spi_release_bus(struct spi_slave *slave) 114 { 115 #if defined(CONFIG_SYS_KW_SPI_MPP) 116 kirkwood_mpp_conf(spi_mpp_backup, NULL); 117 #endif 118 119 board_spi_release_bus(slave); 120 } 121 122 #ifndef CONFIG_SPI_CS_IS_VALID 123 /* 124 * you can define this function board specific 125 * define above CONFIG in board specific config file and 126 * provide the function in board specific src file 127 */ 128 int spi_cs_is_valid(unsigned int bus, unsigned int cs) 129 { 130 return (bus == 0 && (cs == 0 || cs == 1)); 131 } 132 #endif 133 134 void spi_init(void) 135 { 136 } 137 138 void spi_cs_activate(struct spi_slave *slave) 139 { 140 writel(readl(&spireg->ctrl) | KWSPI_IRQUNMASK, &spireg->ctrl); 141 } 142 143 void spi_cs_deactivate(struct spi_slave *slave) 144 { 145 writel(readl(&spireg->ctrl) & KWSPI_IRQMASK, &spireg->ctrl); 146 } 147 148 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, 149 void *din, unsigned long flags) 150 { 151 unsigned int tmpdout, tmpdin; 152 int tm, isread = 0; 153 154 debug("spi_xfer: slave %u:%u dout %p din %p bitlen %u\n", 155 slave->bus, slave->cs, dout, din, bitlen); 156 157 if (flags & SPI_XFER_BEGIN) 158 spi_cs_activate(slave); 159 160 /* 161 * handle data in 8-bit chunks 162 * TBD: 2byte xfer mode to be enabled 163 */ 164 writel(((readl(&spireg->cfg) & ~KWSPI_XFERLEN_MASK) | 165 KWSPI_XFERLEN_1BYTE), &spireg->cfg); 166 167 while (bitlen > 4) { 168 debug("loopstart bitlen %d\n", bitlen); 169 tmpdout = 0; 170 171 /* Shift data so it's msb-justified */ 172 if (dout) 173 tmpdout = *(u32 *) dout & 0x0ff; 174 175 writel(~KWSPI_SMEMRDIRQ, &spireg->irq_cause); 176 writel(tmpdout, &spireg->dout); /* Write the data out */ 177 debug("*** spi_xfer: ... %08x written, bitlen %d\n", 178 tmpdout, bitlen); 179 180 /* 181 * Wait for SPI transmit to get out 182 * or time out (1 second = 1000 ms) 183 * The NE event must be read and cleared first 184 */ 185 for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) { 186 if (readl(&spireg->irq_cause) & KWSPI_SMEMRDIRQ) { 187 isread = 1; 188 tmpdin = readl(&spireg->din); 189 debug 190 ("spi_xfer: din %p..%08x read\n", 191 din, tmpdin); 192 193 if (din) { 194 *((u8 *) din) = (u8) tmpdin; 195 din += 1; 196 } 197 if (dout) 198 dout += 1; 199 bitlen -= 8; 200 } 201 if (isread) 202 break; 203 } 204 if (tm >= KWSPI_TIMEOUT) 205 printf("*** spi_xfer: Time out during SPI transfer\n"); 206 207 debug("loopend bitlen %d\n", bitlen); 208 } 209 210 if (flags & SPI_XFER_END) 211 spi_cs_deactivate(slave); 212 213 return 0; 214 } 215