Commit 59d0612252a0ffcb878a1891249d32a306a24fa6
Committed by
Jason
1 parent
198cafbf2c
Exists in
master
and in
57 other branches
ColdFire: Queued SPI driver
This patch adds a driver for Freescale Colfire Queued SPI bus. Coded to work with 8 bits per transfer to use with SPI flash. CPOL, CPHA, and CS_ACTIVE_HIGH can be configured. Tested with MCF5270 which have 4 chip selects. Activate by #define CONFIG_CF_QSPI in board config. Signed-off-by: Richard Retanubun <richardretanubun@ruggedcom.com>
Showing 5 changed files with 415 additions and 2 deletions Side-by-side Diff
arch/m68k/cpu/mcf52x2/cpu_init.c
| ... | ... | @@ -333,7 +333,20 @@ |
| 333 | 333 | return 0; |
| 334 | 334 | } |
| 335 | 335 | #endif /* CONFIG_CMD_NET */ |
| 336 | -#endif | |
| 336 | + | |
| 337 | +#if defined(CONFIG_CF_QSPI) | |
| 338 | + | |
| 339 | +/* Configure PIOs for SIN, SOUT, and SCK */ | |
| 340 | +void cfspi_port_conf(void) | |
| 341 | +{ | |
| 342 | + mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
| 343 | + MCF_GPIO_PAR_QSPI_SIN_SIN | | |
| 344 | + MCF_GPIO_PAR_QSPI_SOUT_SOUT | | |
| 345 | + MCF_GPIO_PAR_QSPI_SCK_SCK); | |
| 346 | +} | |
| 347 | +#endif /* CONFIG_CF_QSPI */ | |
| 348 | + | |
| 349 | +#endif /* CONFIG_M5271 */ | |
| 337 | 350 | |
| 338 | 351 | #if defined(CONFIG_M5272) |
| 339 | 352 | /* |
arch/m68k/include/asm/coldfire/qspi.h
arch/m68k/include/asm/m5271.h
| ... | ... | @@ -171,6 +171,32 @@ |
| 171 | 171 | #define MCF_GPIO_PAR_UART_U1RXD_UART1 0x0C00 |
| 172 | 172 | #define MCF_GPIO_PAR_UART_U1TXD_UART1 0x0300 |
| 173 | 173 | |
| 174 | +/* Bit definitions and macros for PAR_QSPI */ | |
| 175 | +#define MCF_GPIO_PAR_QSPI_PCS1_UNMASK 0x3F | |
| 176 | +#define MCF_GPIO_PAR_QSPI_PCS1_PCS1 0xC0 | |
| 177 | +#define MCF_GPIO_PAR_QSPI_PCS1_SDRAM_SCKE 0x80 | |
| 178 | +#define MCF_GPIO_PAR_QSPI_PCS1_GPIO 0x00 | |
| 179 | +#define MCF_GPIO_PAR_QSPI_PCS0_UNMASK 0xDF | |
| 180 | +#define MCF_GPIO_PAR_QSPI_PCS0_PCS0 0x20 | |
| 181 | +#define MCF_GPIO_PAR_QSPI_PCS0_GPIO 0x00 | |
| 182 | +#define MCF_GPIO_PAR_QSPI_SIN_UNMASK 0xE7 | |
| 183 | +#define MCF_GPIO_PAR_QSPI_SIN_SIN 0x18 | |
| 184 | +#define MCF_GPIO_PAR_QSPI_SIN_I2C_SDA 0x10 | |
| 185 | +#define MCF_GPIO_PAR_QSPI_SIN_GPIO 0x00 | |
| 186 | +#define MCF_GPIO_PAR_QSPI_SOUT_UNMASK 0xFB | |
| 187 | +#define MCF_GPIO_PAR_QSPI_SOUT_SOUT 0x04 | |
| 188 | +#define MCF_GPIO_PAR_QSPI_SOUT_GPIO 0x00 | |
| 189 | +#define MCF_GPIO_PAR_QSPI_SCK_UNMASK 0xFC | |
| 190 | +#define MCF_GPIO_PAR_QSPI_SCK_SCK 0x03 | |
| 191 | +#define MCF_GPIO_PAR_QSPI_SCK_I2C_SCL 0x02 | |
| 192 | +#define MCF_GPIO_PAR_QSPI_SCK_GPIO 0x00 | |
| 193 | + | |
| 194 | +/* Bit definitions and macros for PAR_TIMER for QSPI */ | |
| 195 | +#define MCF_GPIO_PAR_TIMER_T3IN_UNMASK 0x3FFF | |
| 196 | +#define MCF_GPIO_PAR_TIMER_T3IN_QSPI_PCS2 0x4000 | |
| 197 | +#define MCF_GPIO_PAR_TIMER_T3OUT_UNMASK 0xFF3F | |
| 198 | +#define MCF_GPIO_PAR_TIMER_T3OUT_QSPI_PCS3 0x0040 | |
| 199 | + | |
| 174 | 200 | #define MCF_GPIO_PAR_SDRAM_PAR_CSSDCS(x) (((x)&0x03)<<6) |
| 175 | 201 | |
| 176 | 202 | #define MCF_SDRAMC_DCR 0x000040 |
drivers/spi/Makefile
| ... | ... | @@ -32,6 +32,7 @@ |
| 32 | 32 | COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o |
| 33 | 33 | COBJS-$(CONFIG_BFIN_SPI) += bfin_spi.o |
| 34 | 34 | COBJS-$(CONFIG_CF_SPI) += cf_spi.o |
| 35 | +COBJS-$(CONFIG_CF_QSPI) += cf_qspi.o | |
| 35 | 36 | COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o |
| 36 | 37 | COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o |
| 37 | 38 | COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o |
drivers/spi/cf_qspi.c
| 1 | +/* | |
| 2 | + * Freescale Coldfire Queued SPI driver | |
| 3 | + * | |
| 4 | + * NOTE: | |
| 5 | + * This driver is written to transfer 8 bit at-a-time and uses the dedicated | |
| 6 | + * SPI slave select pins as bit-banged GPIO to work with spi_flash subsystem. | |
| 7 | + * | |
| 8 | + * | |
| 9 | + * Copyright (C) 2011 Ruggedcom, Inc. | |
| 10 | + * Richard Retanubun (richardretanubun@freescale.com) | |
| 11 | + * | |
| 12 | + * See file CREDITS for list of people who contributed to this project. | |
| 13 | + * | |
| 14 | + * This program is free software; you can redistribute it and/or | |
| 15 | + * modify it under the terms of the GNU General Public License as | |
| 16 | + * published by the Free Software Foundation; either version 2 of | |
| 17 | + * the License, or (at your option) any later version. | |
| 18 | + * | |
| 19 | + * This program is distributed in the hope that it will be useful, | |
| 20 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 21 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 22 | + * GNU General Public License for more details. | |
| 23 | + * | |
| 24 | + * You should have received a copy of the GNU General Public License | |
| 25 | + * along with this program; if not, write to the Free Software | |
| 26 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
| 27 | + * MA 02111-1307 USA | |
| 28 | + */ | |
| 29 | + | |
| 30 | +#include <common.h> | |
| 31 | +#include <malloc.h> | |
| 32 | +#include <spi.h> | |
| 33 | +#include <asm/immap.h> | |
| 34 | +#include <asm/io.h> | |
| 35 | + | |
| 36 | +DECLARE_GLOBAL_DATA_PTR; | |
| 37 | + | |
| 38 | +#define clamp(x, low, high) (min(max(low, x), high)) | |
| 39 | +#define to_cf_qspi_slave(s) container_of(s, struct cf_qspi_slave, s) | |
| 40 | + | |
| 41 | +struct cf_qspi_slave { | |
| 42 | + struct spi_slave slave; /* Specific bus:cs ID for each device */ | |
| 43 | + qspi_t *regs; /* Pointer to SPI controller registers */ | |
| 44 | + u16 qmr; /* QMR: Queued Mode Register */ | |
| 45 | + u16 qwr; /* QWR: Queued Wrap Register */ | |
| 46 | + u16 qcr; /* QCR: Queued Command Ram */ | |
| 47 | +}; | |
| 48 | + | |
| 49 | +/* Register write wrapper functions */ | |
| 50 | +static void write_qmr(volatile qspi_t *qspi, u16 val) { qspi->mr = val; } | |
| 51 | +static void write_qdlyr(volatile qspi_t *qspi, u16 val) { qspi->dlyr = val; } | |
| 52 | +static void write_qwr(volatile qspi_t *qspi, u16 val) { qspi->wr = val; } | |
| 53 | +static void write_qir(volatile qspi_t *qspi, u16 val) { qspi->ir = val; } | |
| 54 | +static void write_qar(volatile qspi_t *qspi, u16 val) { qspi->ar = val; } | |
| 55 | +static void write_qdr(volatile qspi_t *qspi, u16 val) { qspi->dr = val; } | |
| 56 | +/* Register read wrapper functions */ | |
| 57 | +static u16 read_qdlyr(volatile qspi_t *qspi) { return qspi->dlyr; } | |
| 58 | +static u16 read_qwr(volatile qspi_t *qspi) { return qspi->wr; } | |
| 59 | +static u16 read_qir(volatile qspi_t *qspi) { return qspi->ir; } | |
| 60 | +static u16 read_qdr(volatile qspi_t *qspi) { return qspi->dr; } | |
| 61 | + | |
| 62 | +/* These call points may be different for each ColdFire CPU */ | |
| 63 | +extern void cfspi_port_conf(void); | |
| 64 | +static void cfspi_cs_activate(uint bus, uint cs, uint cs_active_high); | |
| 65 | +static void cfspi_cs_deactivate(uint bus, uint cs, uint cs_active_high); | |
| 66 | + | |
| 67 | +int spi_claim_bus(struct spi_slave *slave) | |
| 68 | +{ | |
| 69 | + return 0; | |
| 70 | +} | |
| 71 | +void spi_release_bus(struct spi_slave *slave) | |
| 72 | +{ | |
| 73 | +} | |
| 74 | + | |
| 75 | +__attribute__((weak)) | |
| 76 | +void spi_init(void) | |
| 77 | +{ | |
| 78 | + cfspi_port_conf(); | |
| 79 | +} | |
| 80 | + | |
| 81 | +__attribute__((weak)) | |
| 82 | +void spi_cs_activate(struct spi_slave *slave) | |
| 83 | +{ | |
| 84 | + struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
| 85 | + | |
| 86 | + cfspi_cs_activate(slave->bus, slave->cs, !(dev->qwr & QSPI_QWR_CSIV)); | |
| 87 | +} | |
| 88 | + | |
| 89 | +__attribute__((weak)) | |
| 90 | +void spi_cs_deactivate(struct spi_slave *slave) | |
| 91 | +{ | |
| 92 | + struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
| 93 | + | |
| 94 | + cfspi_cs_deactivate(slave->bus, slave->cs, !(dev->qwr & QSPI_QWR_CSIV)); | |
| 95 | +} | |
| 96 | + | |
| 97 | +__attribute__((weak)) | |
| 98 | +int spi_cs_is_valid(unsigned int bus, unsigned int cs) | |
| 99 | +{ | |
| 100 | + /* Only 1 bus and 4 chipselect per controller */ | |
| 101 | + if (bus == 0 && (cs >= 0 && cs < 4)) | |
| 102 | + return 1; | |
| 103 | + else | |
| 104 | + return 0; | |
| 105 | +} | |
| 106 | + | |
| 107 | +void spi_free_slave(struct spi_slave *slave) | |
| 108 | +{ | |
| 109 | + struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
| 110 | + | |
| 111 | + free(dev); | |
| 112 | +} | |
| 113 | + | |
| 114 | +/* Translate information given by spi_setup_slave to members of cf_qspi_slave */ | |
| 115 | +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, | |
| 116 | + unsigned int max_hz, unsigned int mode) | |
| 117 | +{ | |
| 118 | + struct cf_qspi_slave *dev = NULL; | |
| 119 | + | |
| 120 | + if (!spi_cs_is_valid(bus, cs)) | |
| 121 | + return NULL; | |
| 122 | + | |
| 123 | + dev = malloc(sizeof(struct cf_qspi_slave)); | |
| 124 | + if (!dev) | |
| 125 | + return NULL; | |
| 126 | + | |
| 127 | + /* Initialize to known value */ | |
| 128 | + dev->slave.bus = bus; | |
| 129 | + dev->slave.cs = cs; | |
| 130 | + dev->regs = (qspi_t *)MMAP_QSPI; | |
| 131 | + dev->qmr = 0; | |
| 132 | + dev->qwr = 0; | |
| 133 | + dev->qcr = 0; | |
| 134 | + | |
| 135 | + | |
| 136 | + /* Map max_hz to QMR[BAUD] */ | |
| 137 | + if (max_hz == 0) /* Go as fast as possible */ | |
| 138 | + dev->qmr = 2u; | |
| 139 | + else /* Get the closest baud rate */ | |
| 140 | + dev->qmr = clamp(((gd->bus_clk >> 2) + max_hz - 1)/max_hz, | |
| 141 | + 2u, 255u); | |
| 142 | + | |
| 143 | + /* Map mode to QMR[CPOL] and QMR[CPHA] */ | |
| 144 | + if (mode & SPI_CPOL) | |
| 145 | + dev->qmr |= QSPI_QMR_CPOL; | |
| 146 | + | |
| 147 | + if (mode & SPI_CPHA) | |
| 148 | + dev->qmr |= QSPI_QMR_CPHA; | |
| 149 | + | |
| 150 | + /* Hardcode bit length to 8 bit per transter */ | |
| 151 | + dev->qmr |= QSPI_QMR_BITS_8; | |
| 152 | + | |
| 153 | + /* Set QMR[MSTR] to enable QSPI as master */ | |
| 154 | + dev->qmr |= QSPI_QMR_MSTR; | |
| 155 | + | |
| 156 | + /* | |
| 157 | + * Set QCR and QWR to default values for spi flash operation. | |
| 158 | + * If more custom QCR and QRW are needed, overload mode variable | |
| 159 | + */ | |
| 160 | + dev->qcr = (QSPI_QDR_CONT | QSPI_QDR_BITSE); | |
| 161 | + | |
| 162 | + if (!(mode & SPI_CS_HIGH)) | |
| 163 | + dev->qwr |= QSPI_QWR_CSIV; | |
| 164 | + | |
| 165 | + return &dev->slave; | |
| 166 | +} | |
| 167 | + | |
| 168 | +/* Transfer 8 bit at a time */ | |
| 169 | +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, | |
| 170 | + void *din, unsigned long flags) | |
| 171 | +{ | |
| 172 | + struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
| 173 | + volatile qspi_t *qspi = dev->regs; | |
| 174 | + u8 *txbuf = (u8 *)dout; | |
| 175 | + u8 *rxbuf = (u8 *)din; | |
| 176 | + u32 count = ((bitlen / 8) + (bitlen % 8 ? 1 : 0)); | |
| 177 | + u32 n, i = 0; | |
| 178 | + | |
| 179 | + /* Sanitize arguments */ | |
| 180 | + if (slave == NULL) { | |
| 181 | + printf("%s: NULL slave ptr\n", __func__); | |
| 182 | + return -1; | |
| 183 | + } | |
| 184 | + | |
| 185 | + if (flags & SPI_XFER_BEGIN) | |
| 186 | + spi_cs_activate(slave); | |
| 187 | + | |
| 188 | + /* There is something to send, lets process it. spi_xfer is also called | |
| 189 | + * just to toggle chip select, so bitlen of 0 is valid */ | |
| 190 | + if (count > 0) { | |
| 191 | + /* | |
| 192 | + * NOTE: Since chip select is driven as a bit-bang-ed GPIO | |
| 193 | + * using spi_cs_activate() and spi_cs_deactivate(), | |
| 194 | + * the chip select settings inside the controller | |
| 195 | + * (i.e. QCR[CONT] and QWR[CSIV]) are moot. The bits are set to | |
| 196 | + * keep the controller settings consistent with the actual | |
| 197 | + * operation of the bus. | |
| 198 | + */ | |
| 199 | + | |
| 200 | + /* Write the slave device's settings for the controller.*/ | |
| 201 | + write_qmr(qspi, dev->qmr); | |
| 202 | + write_qwr(qspi, dev->qwr); | |
| 203 | + | |
| 204 | + /* Limit transfer to 16 at a time */ | |
| 205 | + n = min(count, 16u); | |
| 206 | + do { | |
| 207 | + /* Setup queue end point */ | |
| 208 | + write_qwr(qspi, ((read_qwr(qspi) & QSPI_QWR_ENDQP_MASK) | |
| 209 | + | QSPI_QWR_ENDQP((n-1)))); | |
| 210 | + | |
| 211 | + /* Write Command RAM */ | |
| 212 | + write_qar(qspi, QSPI_QAR_CMD); | |
| 213 | + for (i = 0; i < n; ++i) | |
| 214 | + write_qdr(qspi, dev->qcr); | |
| 215 | + | |
| 216 | + /* Write TxBuf, if none given, fill with ZEROes */ | |
| 217 | + write_qar(qspi, QSPI_QAR_TRANS); | |
| 218 | + if (txbuf) { | |
| 219 | + for (i = 0; i < n; ++i) | |
| 220 | + write_qdr(qspi, *txbuf++); | |
| 221 | + } else { | |
| 222 | + for (i = 0; i < n; ++i) | |
| 223 | + write_qdr(qspi, 0); | |
| 224 | + } | |
| 225 | + | |
| 226 | + /* Clear QIR[SPIF] by writing a 1 to it */ | |
| 227 | + write_qir(qspi, read_qir(qspi) | QSPI_QIR_SPIF); | |
| 228 | + /* Set QDLYR[SPE] to start sending */ | |
| 229 | + write_qdlyr(qspi, read_qdlyr(qspi) | QSPI_QDLYR_SPE); | |
| 230 | + | |
| 231 | + /* Poll QIR[SPIF] for transfer completion */ | |
| 232 | + while ((read_qir(qspi) & QSPI_QIR_SPIF) != 1) | |
| 233 | + udelay(1); | |
| 234 | + | |
| 235 | + /* If given read RxBuf, load data to it */ | |
| 236 | + if (rxbuf) { | |
| 237 | + write_qar(qspi, QSPI_QAR_RECV); | |
| 238 | + for (i = 0; i < n; ++i) | |
| 239 | + *rxbuf++ = read_qdr(qspi); | |
| 240 | + } | |
| 241 | + | |
| 242 | + /* Decrement count */ | |
| 243 | + count -= n; | |
| 244 | + } while (count); | |
| 245 | + } | |
| 246 | + | |
| 247 | + if (flags & SPI_XFER_END) | |
| 248 | + spi_cs_deactivate(slave); | |
| 249 | + | |
| 250 | + return 0; | |
| 251 | +} | |
| 252 | + | |
| 253 | +/* Each MCF CPU may have different pin assignments for chip selects. */ | |
| 254 | +#if defined(CONFIG_M5271) | |
| 255 | +/* Assert chip select, val = [1|0] , dir = out, mode = GPIO */ | |
| 256 | +void cfspi_cs_activate(uint bus, uint cs, uint cs_active_high) | |
| 257 | +{ | |
| 258 | + debug("%s: bus %d cs %d cs_active_high %d\n", | |
| 259 | + __func__, bus, cs, cs_active_high); | |
| 260 | + | |
| 261 | + switch (cs) { | |
| 262 | + case 0: /* QSPI_CS[0] = PQSPI[3] */ | |
| 263 | + if (cs_active_high) | |
| 264 | + mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x08); | |
| 265 | + else | |
| 266 | + mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xF7); | |
| 267 | + | |
| 268 | + mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
| 269 | + mbar_readByte(MCF_GPIO_PDDR_QSPI) | 0x08); | |
| 270 | + | |
| 271 | + mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
| 272 | + mbar_readByte(MCF_GPIO_PAR_QSPI) & 0xDF); | |
| 273 | + break; | |
| 274 | + case 1: /* QSPI_CS[1] = PQSPI[4] */ | |
| 275 | + if (cs_active_high) | |
| 276 | + mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x10); | |
| 277 | + else | |
| 278 | + mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xEF); | |
| 279 | + | |
| 280 | + mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
| 281 | + mbar_readByte(MCF_GPIO_PDDR_QSPI) | 0x10); | |
| 282 | + | |
| 283 | + mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
| 284 | + mbar_readByte(MCF_GPIO_PAR_QSPI) & 0x3F); | |
| 285 | + break; | |
| 286 | + case 2: /* QSPI_CS[2] = PTIMER[7] */ | |
| 287 | + if (cs_active_high) | |
| 288 | + mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x80); | |
| 289 | + else | |
| 290 | + mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0x7F); | |
| 291 | + | |
| 292 | + mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
| 293 | + mbar_readByte(MCF_GPIO_PDDR_TIMER) | 0x80); | |
| 294 | + | |
| 295 | + mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
| 296 | + mbar_readShort(MCF_GPIO_PAR_TIMER) & 0x3FFF); | |
| 297 | + break; | |
| 298 | + case 3: /* QSPI_CS[3] = PTIMER[3] */ | |
| 299 | + if (cs_active_high) | |
| 300 | + mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x08); | |
| 301 | + else | |
| 302 | + mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0xF7); | |
| 303 | + | |
| 304 | + mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
| 305 | + mbar_readByte(MCF_GPIO_PDDR_TIMER) | 0x08); | |
| 306 | + | |
| 307 | + mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
| 308 | + mbar_readShort(MCF_GPIO_PAR_TIMER) & 0xFF3F); | |
| 309 | + break; | |
| 310 | + } | |
| 311 | +} | |
| 312 | + | |
| 313 | +/* Deassert chip select, val = [1|0], dir = in, mode = GPIO | |
| 314 | + * direction set as IN to undrive the pin, external pullup/pulldown will bring | |
| 315 | + * bus to deassert state. | |
| 316 | + */ | |
| 317 | +void cfspi_cs_deactivate(uint bus, uint cs, uint cs_active_high) | |
| 318 | +{ | |
| 319 | + debug("%s: bus %d cs %d cs_active_high %d\n", | |
| 320 | + __func__, bus, cs, cs_active_high); | |
| 321 | + | |
| 322 | + switch (cs) { | |
| 323 | + case 0: /* QSPI_CS[0] = PQSPI[3] */ | |
| 324 | + if (cs_active_high) | |
| 325 | + mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xF7); | |
| 326 | + else | |
| 327 | + mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x08); | |
| 328 | + | |
| 329 | + mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
| 330 | + mbar_readByte(MCF_GPIO_PDDR_QSPI) & 0xF7); | |
| 331 | + | |
| 332 | + mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
| 333 | + mbar_readByte(MCF_GPIO_PAR_QSPI) & 0xDF); | |
| 334 | + break; | |
| 335 | + case 1: /* QSPI_CS[1] = PQSPI[4] */ | |
| 336 | + if (cs_active_high) | |
| 337 | + mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xEF); | |
| 338 | + else | |
| 339 | + mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x10); | |
| 340 | + | |
| 341 | + mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
| 342 | + mbar_readByte(MCF_GPIO_PDDR_QSPI) & 0xEF); | |
| 343 | + | |
| 344 | + mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
| 345 | + mbar_readByte(MCF_GPIO_PAR_QSPI) & 0x3F); | |
| 346 | + break; | |
| 347 | + case 2: /* QSPI_CS[2] = PTIMER[7] */ | |
| 348 | + if (cs_active_high) | |
| 349 | + mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0x7F); | |
| 350 | + else | |
| 351 | + mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x80); | |
| 352 | + | |
| 353 | + mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
| 354 | + mbar_readByte(MCF_GPIO_PDDR_TIMER) & 0x7F); | |
| 355 | + | |
| 356 | + mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
| 357 | + mbar_readShort(MCF_GPIO_PAR_TIMER) & 0x3FFF); | |
| 358 | + break; | |
| 359 | + case 3: /* QSPI_CS[3] = PTIMER[3] */ | |
| 360 | + if (cs_active_high) | |
| 361 | + mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0xF7); | |
| 362 | + else | |
| 363 | + mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x08); | |
| 364 | + | |
| 365 | + mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
| 366 | + mbar_readByte(MCF_GPIO_PDDR_TIMER) & 0xF7); | |
| 367 | + | |
| 368 | + mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
| 369 | + mbar_readShort(MCF_GPIO_PAR_TIMER) & 0xFF3F); | |
| 370 | + break; | |
| 371 | + } | |
| 372 | +} | |
| 373 | +#endif /* CONFIG_M5271 */ |