Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi/spi-fsl-spi: Make driver usable in CPU mode outside of an FSL_SOC environment

This makes the spi-fsl-spi driver usable in CPU mode outside of an FSL_SOC and
even an powerpc environment by moving CPM mode functionality to a separate file
that is only compiled and linked in an FSL_SOC environment and adding some
ifdefs to hide types and functions or provide alternatives.

For devicetree probing a "clock-frequency" property is used for clock frequency
instead of calls to FSL_SOC-specific functions.

Acked-by: Anton Vorontsov <anton@enomsg.org>
Signed-off-by: Andreas Larsson <andreas@gaisler.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

authored by

Andreas Larsson and committed by
Grant Likely
e8beacbb 58ad60bb

+520 -405
+1
Documentation/devicetree/bindings/spi/fsl-spi.txt
··· 14 14 controller you have. 15 15 - interrupt-parent : the phandle for the interrupt controller that 16 16 services interrupts for this device. 17 + - clock-frequency : input clock frequency to non FSL_SOC cores 17 18 18 19 Optional properties: 19 20 - gpios : specifies the gpio pins to be used for chipselects.
+6 -1
drivers/spi/Kconfig
··· 229 229 230 230 config SPI_FSL_LIB 231 231 tristate 232 + depends on OF 233 + 234 + config SPI_FSL_CPM 235 + tristate 232 236 depends on FSL_SOC 233 237 234 238 config SPI_FSL_SPI 235 239 bool "Freescale SPI controller" 236 - depends on FSL_SOC 240 + depends on OF 237 241 select SPI_FSL_LIB 242 + select SPI_FSL_CPM if FSL_SOC 238 243 help 239 244 This enables using the Freescale SPI controllers in master mode. 240 245 MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
+1
drivers/spi/Makefile
··· 29 29 spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o 30 30 obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o 31 31 obj-$(CONFIG_SPI_FALCON) += spi-falcon.o 32 + obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o 32 33 obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o 33 34 obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o 34 35 obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
+387
drivers/spi/spi-fsl-cpm.c
··· 1 + /* 2 + * Freescale SPI controller driver cpm functions. 3 + * 4 + * Maintainer: Kumar Gala 5 + * 6 + * Copyright (C) 2006 Polycom, Inc. 7 + * Copyright 2010 Freescale Semiconductor, Inc. 8 + * 9 + * CPM SPI and QE buffer descriptors mode support: 10 + * Copyright (c) 2009 MontaVista Software, Inc. 11 + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 12 + * 13 + * This program is free software; you can redistribute it and/or modify it 14 + * under the terms of the GNU General Public License as published by the 15 + * Free Software Foundation; either version 2 of the License, or (at your 16 + * option) any later version. 17 + */ 18 + #include <linux/types.h> 19 + #include <linux/kernel.h> 20 + #include <linux/spi/spi.h> 21 + #include <linux/fsl_devices.h> 22 + #include <linux/dma-mapping.h> 23 + #include <asm/cpm.h> 24 + #include <asm/qe.h> 25 + 26 + #include "spi-fsl-lib.h" 27 + #include "spi-fsl-cpm.h" 28 + #include "spi-fsl-spi.h" 29 + 30 + /* CPM1 and CPM2 are mutually exclusive. */ 31 + #ifdef CONFIG_CPM1 32 + #include <asm/cpm1.h> 33 + #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0) 34 + #else 35 + #include <asm/cpm2.h> 36 + #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0) 37 + #endif 38 + 39 + #define SPIE_TXB 0x00000200 /* Last char is written to tx fifo */ 40 + #define SPIE_RXB 0x00000100 /* Last char is written to rx buf */ 41 + 42 + /* SPCOM register values */ 43 + #define SPCOM_STR (1 << 23) /* Start transmit */ 44 + 45 + #define SPI_PRAM_SIZE 0x100 46 + #define SPI_MRBLR ((unsigned int)PAGE_SIZE) 47 + 48 + static void *fsl_dummy_rx; 49 + static DEFINE_MUTEX(fsl_dummy_rx_lock); 50 + static int fsl_dummy_rx_refcnt; 51 + 52 + void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi) 53 + { 54 + if (mspi->flags & SPI_QE) { 55 + qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock, 56 + QE_CR_PROTOCOL_UNSPECIFIED, 0); 57 + } else { 58 + cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX); 59 + if (mspi->flags & SPI_CPM1) { 60 + out_be16(&mspi->pram->rbptr, 61 + in_be16(&mspi->pram->rbase)); 62 + out_be16(&mspi->pram->tbptr, 63 + in_be16(&mspi->pram->tbase)); 64 + } 65 + } 66 + } 67 + 68 + static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) 69 + { 70 + struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd; 71 + struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd; 72 + unsigned int xfer_len = min(mspi->count, SPI_MRBLR); 73 + unsigned int xfer_ofs; 74 + struct fsl_spi_reg *reg_base = mspi->reg_base; 75 + 76 + xfer_ofs = mspi->xfer_in_progress->len - mspi->count; 77 + 78 + if (mspi->rx_dma == mspi->dma_dummy_rx) 79 + out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma); 80 + else 81 + out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); 82 + out_be16(&rx_bd->cbd_datlen, 0); 83 + out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP); 84 + 85 + if (mspi->tx_dma == mspi->dma_dummy_tx) 86 + out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma); 87 + else 88 + out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); 89 + out_be16(&tx_bd->cbd_datlen, xfer_len); 90 + out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | 91 + BD_SC_LAST); 92 + 93 + /* start transfer */ 94 + mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR); 95 + } 96 + 97 + int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, 98 + struct spi_transfer *t, bool is_dma_mapped) 99 + { 100 + struct device *dev = mspi->dev; 101 + struct fsl_spi_reg *reg_base = mspi->reg_base; 102 + 103 + if (is_dma_mapped) { 104 + mspi->map_tx_dma = 0; 105 + mspi->map_rx_dma = 0; 106 + } else { 107 + mspi->map_tx_dma = 1; 108 + mspi->map_rx_dma = 1; 109 + } 110 + 111 + if (!t->tx_buf) { 112 + mspi->tx_dma = mspi->dma_dummy_tx; 113 + mspi->map_tx_dma = 0; 114 + } 115 + 116 + if (!t->rx_buf) { 117 + mspi->rx_dma = mspi->dma_dummy_rx; 118 + mspi->map_rx_dma = 0; 119 + } 120 + 121 + if (mspi->map_tx_dma) { 122 + void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */ 123 + 124 + mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len, 125 + DMA_TO_DEVICE); 126 + if (dma_mapping_error(dev, mspi->tx_dma)) { 127 + dev_err(dev, "unable to map tx dma\n"); 128 + return -ENOMEM; 129 + } 130 + } else if (t->tx_buf) { 131 + mspi->tx_dma = t->tx_dma; 132 + } 133 + 134 + if (mspi->map_rx_dma) { 135 + mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len, 136 + DMA_FROM_DEVICE); 137 + if (dma_mapping_error(dev, mspi->rx_dma)) { 138 + dev_err(dev, "unable to map rx dma\n"); 139 + goto err_rx_dma; 140 + } 141 + } else if (t->rx_buf) { 142 + mspi->rx_dma = t->rx_dma; 143 + } 144 + 145 + /* enable rx ints */ 146 + mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB); 147 + 148 + mspi->xfer_in_progress = t; 149 + mspi->count = t->len; 150 + 151 + /* start CPM transfers */ 152 + fsl_spi_cpm_bufs_start(mspi); 153 + 154 + return 0; 155 + 156 + err_rx_dma: 157 + if (mspi->map_tx_dma) 158 + dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); 159 + return -ENOMEM; 160 + } 161 + 162 + void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) 163 + { 164 + struct device *dev = mspi->dev; 165 + struct spi_transfer *t = mspi->xfer_in_progress; 166 + 167 + if (mspi->map_tx_dma) 168 + dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); 169 + if (mspi->map_rx_dma) 170 + dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE); 171 + mspi->xfer_in_progress = NULL; 172 + } 173 + 174 + void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) 175 + { 176 + u16 len; 177 + struct fsl_spi_reg *reg_base = mspi->reg_base; 178 + 179 + dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__, 180 + in_be16(&mspi->rx_bd->cbd_datlen), mspi->count); 181 + 182 + len = in_be16(&mspi->rx_bd->cbd_datlen); 183 + if (len > mspi->count) { 184 + WARN_ON(1); 185 + len = mspi->count; 186 + } 187 + 188 + /* Clear the events */ 189 + mpc8xxx_spi_write_reg(&reg_base->event, events); 190 + 191 + mspi->count -= len; 192 + if (mspi->count) 193 + fsl_spi_cpm_bufs_start(mspi); 194 + else 195 + complete(&mspi->done); 196 + } 197 + 198 + static void *fsl_spi_alloc_dummy_rx(void) 199 + { 200 + mutex_lock(&fsl_dummy_rx_lock); 201 + 202 + if (!fsl_dummy_rx) 203 + fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL); 204 + if (fsl_dummy_rx) 205 + fsl_dummy_rx_refcnt++; 206 + 207 + mutex_unlock(&fsl_dummy_rx_lock); 208 + 209 + return fsl_dummy_rx; 210 + } 211 + 212 + static void fsl_spi_free_dummy_rx(void) 213 + { 214 + mutex_lock(&fsl_dummy_rx_lock); 215 + 216 + switch (fsl_dummy_rx_refcnt) { 217 + case 0: 218 + WARN_ON(1); 219 + break; 220 + case 1: 221 + kfree(fsl_dummy_rx); 222 + fsl_dummy_rx = NULL; 223 + /* fall through */ 224 + default: 225 + fsl_dummy_rx_refcnt--; 226 + break; 227 + } 228 + 229 + mutex_unlock(&fsl_dummy_rx_lock); 230 + } 231 + 232 + static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi) 233 + { 234 + struct device *dev = mspi->dev; 235 + struct device_node *np = dev->of_node; 236 + const u32 *iprop; 237 + int size; 238 + void __iomem *spi_base; 239 + unsigned long pram_ofs = -ENOMEM; 240 + 241 + /* Can't use of_address_to_resource(), QE muram isn't at 0. */ 242 + iprop = of_get_property(np, "reg", &size); 243 + 244 + /* QE with a fixed pram location? */ 245 + if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4) 246 + return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE); 247 + 248 + /* QE but with a dynamic pram location? */ 249 + if (mspi->flags & SPI_QE) { 250 + pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); 251 + qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock, 252 + QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs); 253 + return pram_ofs; 254 + } 255 + 256 + spi_base = of_iomap(np, 1); 257 + if (spi_base == NULL) 258 + return -EINVAL; 259 + 260 + if (mspi->flags & SPI_CPM2) { 261 + pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); 262 + out_be16(spi_base, pram_ofs); 263 + } else { 264 + struct spi_pram __iomem *pram = spi_base; 265 + u16 rpbase = in_be16(&pram->rpbase); 266 + 267 + /* Microcode relocation patch applied? */ 268 + if (rpbase) { 269 + pram_ofs = rpbase; 270 + } else { 271 + pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); 272 + out_be16(spi_base, pram_ofs); 273 + } 274 + } 275 + 276 + iounmap(spi_base); 277 + return pram_ofs; 278 + } 279 + 280 + int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) 281 + { 282 + struct device *dev = mspi->dev; 283 + struct device_node *np = dev->of_node; 284 + const u32 *iprop; 285 + int size; 286 + unsigned long pram_ofs; 287 + unsigned long bds_ofs; 288 + 289 + if (!(mspi->flags & SPI_CPM_MODE)) 290 + return 0; 291 + 292 + if (!fsl_spi_alloc_dummy_rx()) 293 + return -ENOMEM; 294 + 295 + if (mspi->flags & SPI_QE) { 296 + iprop = of_get_property(np, "cell-index", &size); 297 + if (iprop && size == sizeof(*iprop)) 298 + mspi->subblock = *iprop; 299 + 300 + switch (mspi->subblock) { 301 + default: 302 + dev_warn(dev, "cell-index unspecified, assuming SPI1"); 303 + /* fall through */ 304 + case 0: 305 + mspi->subblock = QE_CR_SUBBLOCK_SPI1; 306 + break; 307 + case 1: 308 + mspi->subblock = QE_CR_SUBBLOCK_SPI2; 309 + break; 310 + } 311 + } 312 + 313 + pram_ofs = fsl_spi_cpm_get_pram(mspi); 314 + if (IS_ERR_VALUE(pram_ofs)) { 315 + dev_err(dev, "can't allocate spi parameter ram\n"); 316 + goto err_pram; 317 + } 318 + 319 + bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) + 320 + sizeof(*mspi->rx_bd), 8); 321 + if (IS_ERR_VALUE(bds_ofs)) { 322 + dev_err(dev, "can't allocate bds\n"); 323 + goto err_bds; 324 + } 325 + 326 + mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE, 327 + DMA_TO_DEVICE); 328 + if (dma_mapping_error(dev, mspi->dma_dummy_tx)) { 329 + dev_err(dev, "unable to map dummy tx buffer\n"); 330 + goto err_dummy_tx; 331 + } 332 + 333 + mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR, 334 + DMA_FROM_DEVICE); 335 + if (dma_mapping_error(dev, mspi->dma_dummy_rx)) { 336 + dev_err(dev, "unable to map dummy rx buffer\n"); 337 + goto err_dummy_rx; 338 + } 339 + 340 + mspi->pram = cpm_muram_addr(pram_ofs); 341 + 342 + mspi->tx_bd = cpm_muram_addr(bds_ofs); 343 + mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd)); 344 + 345 + /* Initialize parameter ram. */ 346 + out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd)); 347 + out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd)); 348 + out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL); 349 + out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL); 350 + out_be16(&mspi->pram->mrblr, SPI_MRBLR); 351 + out_be32(&mspi->pram->rstate, 0); 352 + out_be32(&mspi->pram->rdp, 0); 353 + out_be16(&mspi->pram->rbptr, 0); 354 + out_be16(&mspi->pram->rbc, 0); 355 + out_be32(&mspi->pram->rxtmp, 0); 356 + out_be32(&mspi->pram->tstate, 0); 357 + out_be32(&mspi->pram->tdp, 0); 358 + out_be16(&mspi->pram->tbptr, 0); 359 + out_be16(&mspi->pram->tbc, 0); 360 + out_be32(&mspi->pram->txtmp, 0); 361 + 362 + return 0; 363 + 364 + err_dummy_rx: 365 + dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); 366 + err_dummy_tx: 367 + cpm_muram_free(bds_ofs); 368 + err_bds: 369 + cpm_muram_free(pram_ofs); 370 + err_pram: 371 + fsl_spi_free_dummy_rx(); 372 + return -ENOMEM; 373 + } 374 + 375 + void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) 376 + { 377 + struct device *dev = mspi->dev; 378 + 379 + if (!(mspi->flags & SPI_CPM_MODE)) 380 + return; 381 + 382 + dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE); 383 + dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); 384 + cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); 385 + cpm_muram_free(cpm_muram_offset(mspi->pram)); 386 + fsl_spi_free_dummy_rx(); 387 + }
+43
drivers/spi/spi-fsl-cpm.h
··· 1 + /* 2 + * Freescale SPI controller driver cpm functions. 3 + * 4 + * Maintainer: Kumar Gala 5 + * 6 + * Copyright (C) 2006 Polycom, Inc. 7 + * Copyright 2010 Freescale Semiconductor, Inc. 8 + * 9 + * CPM SPI and QE buffer descriptors mode support: 10 + * Copyright (c) 2009 MontaVista Software, Inc. 11 + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 12 + * 13 + * This program is free software; you can redistribute it and/or modify it 14 + * under the terms of the GNU General Public License as published by the 15 + * Free Software Foundation; either version 2 of the License, or (at your 16 + * option) any later version. 17 + */ 18 + 19 + #ifndef __SPI_FSL_CPM_H__ 20 + #define __SPI_FSL_CPM_H__ 21 + 22 + #include "spi-fsl-lib.h" 23 + 24 + #ifdef CONFIG_FSL_SOC 25 + extern void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi); 26 + extern int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, 27 + struct spi_transfer *t, bool is_dma_mapped); 28 + extern void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi); 29 + extern void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events); 30 + extern int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi); 31 + extern void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi); 32 + #else 33 + static inline void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi) { } 34 + static inline int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, 35 + struct spi_transfer *t, 36 + bool is_dma_mapped) { return 0; } 37 + static inline void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) { } 38 + static inline void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { } 39 + static inline int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) { return 0; } 40 + static inline void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) { } 41 + #endif 42 + 43 + #endif /* __SPI_FSL_CPM_H__ */
+8
drivers/spi/spi-fsl-lib.c
··· 23 23 #include <linux/mm.h> 24 24 #include <linux/of_platform.h> 25 25 #include <linux/spi/spi.h> 26 + #ifdef CONFIG_FSL_SOC 26 27 #include <sysdev/fsl_soc.h> 28 + #endif 27 29 28 30 #include "spi-fsl-lib.h" 29 31 ··· 210 208 /* Allocate bus num dynamically. */ 211 209 pdata->bus_num = -1; 212 210 211 + #ifdef CONFIG_FSL_SOC 213 212 /* SPI controller is either clocked from QE or SoC clock. */ 214 213 pdata->sysclk = get_brgfreq(); 215 214 if (pdata->sysclk == -1) { ··· 220 217 goto err; 221 218 } 222 219 } 220 + #else 221 + ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk); 222 + if (ret) 223 + goto err; 224 + #endif 223 225 224 226 prop = of_get_property(np, "mode", NULL); 225 227 if (prop && !strcmp(prop, "cpu-qe"))
+4 -2
drivers/spi/spi-fsl-lib.h
··· 34 34 35 35 int subblock; 36 36 struct spi_pram __iomem *pram; 37 + #ifdef CONFIG_FSL_SOC 37 38 struct cpm_buf_desc __iomem *tx_bd; 38 39 struct cpm_buf_desc __iomem *rx_bd; 40 + #endif 39 41 40 42 struct spi_transfer *xfer_in_progress; 41 43 ··· 89 87 90 88 static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val) 91 89 { 92 - out_be32(reg, val); 90 + iowrite32be(val, reg); 93 91 } 94 92 95 93 static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg) 96 94 { 97 - return in_be32(reg); 95 + return ioread32be(reg); 98 96 } 99 97 100 98 struct mpc8xxx_spi_probe_info {
+9 -402
drivers/spi/spi-fsl-spi.c
··· 30 30 #include <linux/mutex.h> 31 31 #include <linux/of.h> 32 32 #include <linux/of_platform.h> 33 + #include <linux/of_address.h> 34 + #include <linux/of_irq.h> 33 35 #include <linux/gpio.h> 34 36 #include <linux/of_gpio.h> 35 37 36 - #include <sysdev/fsl_soc.h> 37 - #include <asm/cpm.h> 38 - #include <asm/qe.h> 39 - 40 38 #include "spi-fsl-lib.h" 41 - 42 - /* CPM1 and CPM2 are mutually exclusive. */ 43 - #ifdef CONFIG_CPM1 44 - #include <asm/cpm1.h> 45 - #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0) 46 - #else 47 - #include <asm/cpm2.h> 48 - #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0) 49 - #endif 50 - 51 - /* SPI Controller registers */ 52 - struct fsl_spi_reg { 53 - u8 res1[0x20]; 54 - __be32 mode; 55 - __be32 event; 56 - __be32 mask; 57 - __be32 command; 58 - __be32 transmit; 59 - __be32 receive; 60 - }; 61 - 62 - /* SPI Controller mode register definitions */ 63 - #define SPMODE_LOOP (1 << 30) 64 - #define SPMODE_CI_INACTIVEHIGH (1 << 29) 65 - #define SPMODE_CP_BEGIN_EDGECLK (1 << 28) 66 - #define SPMODE_DIV16 (1 << 27) 67 - #define SPMODE_REV (1 << 26) 68 - #define SPMODE_MS (1 << 25) 69 - #define SPMODE_ENABLE (1 << 24) 70 - #define SPMODE_LEN(x) ((x) << 20) 71 - #define SPMODE_PM(x) ((x) << 16) 72 - #define SPMODE_OP (1 << 14) 73 - #define SPMODE_CG(x) ((x) << 7) 74 - 75 - /* 76 - * Default for SPI Mode: 77 - * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk 78 - */ 79 - #define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \ 80 - SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf)) 81 - 82 - /* SPIE register values */ 83 - #define SPIE_NE 0x00000200 /* Not empty */ 84 - #define SPIE_NF 0x00000100 /* Not full */ 85 - 86 - /* SPIM register values */ 87 - #define SPIM_NE 0x00000200 /* Not empty */ 88 - #define SPIM_NF 0x00000100 /* Not full */ 89 - 90 - #define SPIE_TXB 0x00000200 /* Last char is written to tx fifo */ 91 - #define SPIE_RXB 0x00000100 /* Last char is written to rx buf */ 92 - 93 - /* SPCOM register values */ 94 - #define SPCOM_STR (1 << 23) /* Start transmit */ 95 - 96 - #define SPI_PRAM_SIZE 0x100 97 - #define SPI_MRBLR ((unsigned int)PAGE_SIZE) 98 - 99 - static void *fsl_dummy_rx; 100 - static DEFINE_MUTEX(fsl_dummy_rx_lock); 101 - static int fsl_dummy_rx_refcnt; 39 + #include "spi-fsl-cpm.h" 40 + #include "spi-fsl-spi.h" 102 41 103 42 static void fsl_spi_change_mode(struct spi_device *spi) 104 43 { ··· 58 119 59 120 /* When in CPM mode, we need to reinit tx and rx. */ 60 121 if (mspi->flags & SPI_CPM_MODE) { 61 - if (mspi->flags & SPI_QE) { 62 - qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock, 63 - QE_CR_PROTOCOL_UNSPECIFIED, 0); 64 - } else { 65 - cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX); 66 - if (mspi->flags & SPI_CPM1) { 67 - out_be16(&mspi->pram->rbptr, 68 - in_be16(&mspi->pram->rbase)); 69 - out_be16(&mspi->pram->tbptr, 70 - in_be16(&mspi->pram->tbase)); 71 - } 72 - } 122 + fsl_spi_cpm_reinit_txrx(mspi); 73 123 } 74 124 mpc8xxx_spi_write_reg(mode, cs->hw_mode); 75 125 local_irq_restore(flags); ··· 221 293 222 294 fsl_spi_change_mode(spi); 223 295 return 0; 224 - } 225 - 226 - static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) 227 - { 228 - struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd; 229 - struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd; 230 - unsigned int xfer_len = min(mspi->count, SPI_MRBLR); 231 - unsigned int xfer_ofs; 232 - struct fsl_spi_reg *reg_base = mspi->reg_base; 233 - 234 - xfer_ofs = mspi->xfer_in_progress->len - mspi->count; 235 - 236 - if (mspi->rx_dma == mspi->dma_dummy_rx) 237 - out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma); 238 - else 239 - out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); 240 - out_be16(&rx_bd->cbd_datlen, 0); 241 - out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP); 242 - 243 - if (mspi->tx_dma == mspi->dma_dummy_tx) 244 - out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma); 245 - else 246 - out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); 247 - out_be16(&tx_bd->cbd_datlen, xfer_len); 248 - out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | 249 - BD_SC_LAST); 250 - 251 - /* start transfer */ 252 - mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR); 253 - } 254 - 255 - static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, 256 - struct spi_transfer *t, bool is_dma_mapped) 257 - { 258 - struct device *dev = mspi->dev; 259 - struct fsl_spi_reg *reg_base = mspi->reg_base; 260 - 261 - if (is_dma_mapped) { 262 - mspi->map_tx_dma = 0; 263 - mspi->map_rx_dma = 0; 264 - } else { 265 - mspi->map_tx_dma = 1; 266 - mspi->map_rx_dma = 1; 267 - } 268 - 269 - if (!t->tx_buf) { 270 - mspi->tx_dma = mspi->dma_dummy_tx; 271 - mspi->map_tx_dma = 0; 272 - } 273 - 274 - if (!t->rx_buf) { 275 - mspi->rx_dma = mspi->dma_dummy_rx; 276 - mspi->map_rx_dma = 0; 277 - } 278 - 279 - if (mspi->map_tx_dma) { 280 - void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */ 281 - 282 - mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len, 283 - DMA_TO_DEVICE); 284 - if (dma_mapping_error(dev, mspi->tx_dma)) { 285 - dev_err(dev, "unable to map tx dma\n"); 286 - return -ENOMEM; 287 - } 288 - } else if (t->tx_buf) { 289 - mspi->tx_dma = t->tx_dma; 290 - } 291 - 292 - if (mspi->map_rx_dma) { 293 - mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len, 294 - DMA_FROM_DEVICE); 295 - if (dma_mapping_error(dev, mspi->rx_dma)) { 296 - dev_err(dev, "unable to map rx dma\n"); 297 - goto err_rx_dma; 298 - } 299 - } else if (t->rx_buf) { 300 - mspi->rx_dma = t->rx_dma; 301 - } 302 - 303 - /* enable rx ints */ 304 - mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB); 305 - 306 - mspi->xfer_in_progress = t; 307 - mspi->count = t->len; 308 - 309 - /* start CPM transfers */ 310 - fsl_spi_cpm_bufs_start(mspi); 311 - 312 - return 0; 313 - 314 - err_rx_dma: 315 - if (mspi->map_tx_dma) 316 - dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); 317 - return -ENOMEM; 318 - } 319 - 320 - static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) 321 - { 322 - struct device *dev = mspi->dev; 323 - struct spi_transfer *t = mspi->xfer_in_progress; 324 - 325 - if (mspi->map_tx_dma) 326 - dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); 327 - if (mspi->map_rx_dma) 328 - dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE); 329 - mspi->xfer_in_progress = NULL; 330 296 } 331 297 332 298 static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi, ··· 390 568 return 0; 391 569 } 392 570 393 - static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) 394 - { 395 - u16 len; 396 - struct fsl_spi_reg *reg_base = mspi->reg_base; 397 - 398 - dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__, 399 - in_be16(&mspi->rx_bd->cbd_datlen), mspi->count); 400 - 401 - len = in_be16(&mspi->rx_bd->cbd_datlen); 402 - if (len > mspi->count) { 403 - WARN_ON(1); 404 - len = mspi->count; 405 - } 406 - 407 - /* Clear the events */ 408 - mpc8xxx_spi_write_reg(&reg_base->event, events); 409 - 410 - mspi->count -= len; 411 - if (mspi->count) 412 - fsl_spi_cpm_bufs_start(mspi); 413 - else 414 - complete(&mspi->done); 415 - } 416 - 417 571 static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) 418 572 { 419 573 struct fsl_spi_reg *reg_base = mspi->reg_base; ··· 442 644 fsl_spi_cpu_irq(mspi, events); 443 645 444 646 return ret; 445 - } 446 - 447 - static void *fsl_spi_alloc_dummy_rx(void) 448 - { 449 - mutex_lock(&fsl_dummy_rx_lock); 450 - 451 - if (!fsl_dummy_rx) 452 - fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL); 453 - if (fsl_dummy_rx) 454 - fsl_dummy_rx_refcnt++; 455 - 456 - mutex_unlock(&fsl_dummy_rx_lock); 457 - 458 - return fsl_dummy_rx; 459 - } 460 - 461 - static void fsl_spi_free_dummy_rx(void) 462 - { 463 - mutex_lock(&fsl_dummy_rx_lock); 464 - 465 - switch (fsl_dummy_rx_refcnt) { 466 - case 0: 467 - WARN_ON(1); 468 - break; 469 - case 1: 470 - kfree(fsl_dummy_rx); 471 - fsl_dummy_rx = NULL; 472 - /* fall through */ 473 - default: 474 - fsl_dummy_rx_refcnt--; 475 - break; 476 - } 477 - 478 - mutex_unlock(&fsl_dummy_rx_lock); 479 - } 480 - 481 - static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi) 482 - { 483 - struct device *dev = mspi->dev; 484 - struct device_node *np = dev->of_node; 485 - const u32 *iprop; 486 - int size; 487 - void __iomem *spi_base; 488 - unsigned long pram_ofs = -ENOMEM; 489 - 490 - /* Can't use of_address_to_resource(), QE muram isn't at 0. */ 491 - iprop = of_get_property(np, "reg", &size); 492 - 493 - /* QE with a fixed pram location? */ 494 - if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4) 495 - return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE); 496 - 497 - /* QE but with a dynamic pram location? */ 498 - if (mspi->flags & SPI_QE) { 499 - pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); 500 - qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock, 501 - QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs); 502 - return pram_ofs; 503 - } 504 - 505 - spi_base = of_iomap(np, 1); 506 - if (spi_base == NULL) 507 - return -EINVAL; 508 - 509 - if (mspi->flags & SPI_CPM2) { 510 - pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); 511 - out_be16(spi_base, pram_ofs); 512 - } else { 513 - struct spi_pram __iomem *pram = spi_base; 514 - u16 rpbase = in_be16(&pram->rpbase); 515 - 516 - /* Microcode relocation patch applied? */ 517 - if (rpbase) 518 - pram_ofs = rpbase; 519 - else { 520 - pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); 521 - out_be16(spi_base, pram_ofs); 522 - } 523 - } 524 - 525 - iounmap(spi_base); 526 - return pram_ofs; 527 - } 528 - 529 - static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) 530 - { 531 - struct device *dev = mspi->dev; 532 - struct device_node *np = dev->of_node; 533 - const u32 *iprop; 534 - int size; 535 - unsigned long pram_ofs; 536 - unsigned long bds_ofs; 537 - 538 - if (!(mspi->flags & SPI_CPM_MODE)) 539 - return 0; 540 - 541 - if (!fsl_spi_alloc_dummy_rx()) 542 - return -ENOMEM; 543 - 544 - if (mspi->flags & SPI_QE) { 545 - iprop = of_get_property(np, "cell-index", &size); 546 - if (iprop && size == sizeof(*iprop)) 547 - mspi->subblock = *iprop; 548 - 549 - switch (mspi->subblock) { 550 - default: 551 - dev_warn(dev, "cell-index unspecified, assuming SPI1"); 552 - /* fall through */ 553 - case 0: 554 - mspi->subblock = QE_CR_SUBBLOCK_SPI1; 555 - break; 556 - case 1: 557 - mspi->subblock = QE_CR_SUBBLOCK_SPI2; 558 - break; 559 - } 560 - } 561 - 562 - pram_ofs = fsl_spi_cpm_get_pram(mspi); 563 - if (IS_ERR_VALUE(pram_ofs)) { 564 - dev_err(dev, "can't allocate spi parameter ram\n"); 565 - goto err_pram; 566 - } 567 - 568 - bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) + 569 - sizeof(*mspi->rx_bd), 8); 570 - if (IS_ERR_VALUE(bds_ofs)) { 571 - dev_err(dev, "can't allocate bds\n"); 572 - goto err_bds; 573 - } 574 - 575 - mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE, 576 - DMA_TO_DEVICE); 577 - if (dma_mapping_error(dev, mspi->dma_dummy_tx)) { 578 - dev_err(dev, "unable to map dummy tx buffer\n"); 579 - goto err_dummy_tx; 580 - } 581 - 582 - mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR, 583 - DMA_FROM_DEVICE); 584 - if (dma_mapping_error(dev, mspi->dma_dummy_rx)) { 585 - dev_err(dev, "unable to map dummy rx buffer\n"); 586 - goto err_dummy_rx; 587 - } 588 - 589 - mspi->pram = cpm_muram_addr(pram_ofs); 590 - 591 - mspi->tx_bd = cpm_muram_addr(bds_ofs); 592 - mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd)); 593 - 594 - /* Initialize parameter ram. */ 595 - out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd)); 596 - out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd)); 597 - out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL); 598 - out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL); 599 - out_be16(&mspi->pram->mrblr, SPI_MRBLR); 600 - out_be32(&mspi->pram->rstate, 0); 601 - out_be32(&mspi->pram->rdp, 0); 602 - out_be16(&mspi->pram->rbptr, 0); 603 - out_be16(&mspi->pram->rbc, 0); 604 - out_be32(&mspi->pram->rxtmp, 0); 605 - out_be32(&mspi->pram->tstate, 0); 606 - out_be32(&mspi->pram->tdp, 0); 607 - out_be16(&mspi->pram->tbptr, 0); 608 - out_be16(&mspi->pram->tbc, 0); 609 - out_be32(&mspi->pram->txtmp, 0); 610 - 611 - return 0; 612 - 613 - err_dummy_rx: 614 - dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); 615 - err_dummy_tx: 616 - cpm_muram_free(bds_ofs); 617 - err_bds: 618 - cpm_muram_free(pram_ofs); 619 - err_pram: 620 - fsl_spi_free_dummy_rx(); 621 - return -ENOMEM; 622 - } 623 - 624 - static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) 625 - { 626 - struct device *dev = mspi->dev; 627 - 628 - if (!(mspi->flags & SPI_CPM_MODE)) 629 - return; 630 - 631 - dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE); 632 - dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); 633 - cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); 634 - cpm_muram_free(cpm_muram_offset(mspi->pram)); 635 - fsl_spi_free_dummy_rx(); 636 647 } 637 648 638 649 static void fsl_spi_remove(struct mpc8xxx_spi *mspi) ··· 654 1047 struct device_node *np = ofdev->dev.of_node; 655 1048 struct spi_master *master; 656 1049 struct resource mem; 657 - struct resource irq; 1050 + int irq; 658 1051 int ret = -ENOMEM; 659 1052 660 1053 ret = of_mpc8xxx_spi_probe(ofdev); ··· 669 1062 if (ret) 670 1063 goto err; 671 1064 672 - ret = of_irq_to_resource(np, 0, &irq); 673 - if (!ret) { 1065 + irq = irq_of_parse_and_map(np, 0); 1066 + if (!irq) { 674 1067 ret = -EINVAL; 675 1068 goto err; 676 1069 } 677 1070 678 - master = fsl_spi_probe(dev, &mem, irq.start); 1071 + master = fsl_spi_probe(dev, &mem, irq); 679 1072 if (IS_ERR(master)) { 680 1073 ret = PTR_ERR(master); 681 1074 goto err;
+61
drivers/spi/spi-fsl-spi.h
··· 1 + /* 2 + * Freescale SPI controller driver. 3 + * 4 + * Maintainer: Kumar Gala 5 + * 6 + * Copyright (C) 2006 Polycom, Inc. 7 + * Copyright 2010 Freescale Semiconductor, Inc. 8 + * 9 + * CPM SPI and QE buffer descriptors mode support: 10 + * Copyright (c) 2009 MontaVista Software, Inc. 11 + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 12 + * 13 + * This program is free software; you can redistribute it and/or modify it 14 + * under the terms of the GNU General Public License as published by the 15 + * Free Software Foundation; either version 2 of the License, or (at your 16 + * option) any later version. 17 + */ 18 + 19 + #ifndef __SPI_FSL_SPI_H__ 20 + #define __SPI_FSL_SPI_H__ 21 + 22 + /* SPI Controller registers */ 23 + struct fsl_spi_reg { 24 + u8 res1[0x20]; 25 + __be32 mode; 26 + __be32 event; 27 + __be32 mask; 28 + __be32 command; 29 + __be32 transmit; 30 + __be32 receive; 31 + }; 32 + 33 + /* SPI Controller mode register definitions */ 34 + #define SPMODE_LOOP (1 << 30) 35 + #define SPMODE_CI_INACTIVEHIGH (1 << 29) 36 + #define SPMODE_CP_BEGIN_EDGECLK (1 << 28) 37 + #define SPMODE_DIV16 (1 << 27) 38 + #define SPMODE_REV (1 << 26) 39 + #define SPMODE_MS (1 << 25) 40 + #define SPMODE_ENABLE (1 << 24) 41 + #define SPMODE_LEN(x) ((x) << 20) 42 + #define SPMODE_PM(x) ((x) << 16) 43 + #define SPMODE_OP (1 << 14) 44 + #define SPMODE_CG(x) ((x) << 7) 45 + 46 + /* 47 + * Default for SPI Mode: 48 + * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk 49 + */ 50 + #define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \ 51 + SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf)) 52 + 53 + /* SPIE register values */ 54 + #define SPIE_NE 0x00000200 /* Not empty */ 55 + #define SPIE_NF 0x00000100 /* Not full */ 56 + 57 + /* SPIM register values */ 58 + #define SPIM_NE 0x00000200 /* Not empty */ 59 + #define SPIM_NF 0x00000100 /* Not full */ 60 + 61 + #endif /* __SPI_FSL_SPI_H__ */