···88 - "marvell,armada-380-spi", for the Armada 38x SoCs99 - "marvell,armada-390-spi", for the Armada 39x SoCs1010 - "marvell,armada-xp-spi", for the Armada XP SoCs1111-- reg : offset and length of the register set for the device1111+- reg : offset and length of the register set for the device.1212+ This property can optionally have additional entries to configure1313+ the SPI direct access mode that some of the Marvell SoCs support1414+ additionally to the normal indirect access (PIO) mode. The values1515+ for the MBus "target" and "attribute" are defined in the Marvell1616+ SoC "Functional Specifications" Manual in the chapter "Marvell1717+ Core Processor Address Decoding".1818+ The eight register sets following the control registers refer to1919+ chip-select lines 0 through 7 respectively.1220- cell-index : Which of multiple SPI controllers is this.1321Optional properties:1422- interrupts : Is currently not used.···3123 interrupts = <23>;3224 status = "disabled";3325 };2626+2727+Example with SPI direct mode support (optionally):2828+ spi0: spi@10600 {2929+ compatible = "marvell,orion-spi";3030+ #address-cells = <1>;3131+ #size-cells = <0>;3232+ cell-index = <0>;3333+ reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */3434+ <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */3535+ <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */3636+ <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */3737+ <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */3838+ <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */3939+ <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */4040+ <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */4141+ <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */4242+ interrupts = <23>;4343+ status = "disabled";4444+ };4545+4646+To enable the direct mode, the board specific 'ranges' property in the4747+'soc' node needs to add the entries for the desired SPI controllers4848+and its chip-selects that are used in the direct mode instead of PIO4949+mode. Here an example for this (SPI controller 0, device 1 and SPI5050+controller 1, device 2 are used in direct mode. All other SPI device5151+are used in the default indirect (PIO) mode):5252+ soc {5353+ /*5454+ * Enable the SPI direct access by configuring an entry5555+ * here in the board-specific ranges property5656+ */5757+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>, /* internal regs */5858+ <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>, /* BootROM */5959+ <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>, /* SPI0-DEV1 */6060+ <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>; /* SPI1-DEV2 */6161+6262+For further information on the MBus bindings, please see the MBus6363+DT documentation:6464+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
···11-/***********************license start***************22- * Author: Cavium Networks33- *44- * Contact: support@caviumnetworks.com55- * This file is part of the OCTEON SDK66- *77- * Copyright (c) 2003-2012 Cavium Networks88- *99- * This file is free software; you can redistribute it and/or modify1010- * it under the terms of the GNU General Public License, Version 2, as1111- * published by the Free Software Foundation.1212- *1313- * This file is distributed in the hope that it will be useful, but1414- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty1515- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or1616- * NONINFRINGEMENT. See the GNU General Public License for more1717- * details.1818- *1919- * You should have received a copy of the GNU General Public License2020- * along with this file; if not, write to the Free Software2121- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA2222- * or visit http://www.gnu.org/licenses/.2323- *2424- * This file may also be available under a different license from Cavium.2525- * Contact Cavium Networks for more information2626- ***********************license end**************************************/11+#ifndef __SPI_CAVIUM_H22+#define __SPI_CAVIUM_H2732828-#ifndef __CVMX_MPI_DEFS_H__2929-#define __CVMX_MPI_DEFS_H__44+#define OCTEON_SPI_MAX_BYTES 955+#define OCTEON_SPI_MAX_CLOCK_HZ 1600000066+77+struct octeon_spi_regs {88+ int config;99+ int status;1010+ int tx;1111+ int data;1212+};1313+1414+struct octeon_spi {1515+ void __iomem *register_base;1616+ u64 last_cfg;1717+ u64 cs_enax;1818+ int sys_freq;1919+ struct octeon_spi_regs regs;2020+};2121+2222+#define OCTEON_SPI_CFG(x) (x->regs.config)2323+#define OCTEON_SPI_STS(x) (x->regs.status)2424+#define OCTEON_SPI_TX(x) (x->regs.tx)2525+#define OCTEON_SPI_DAT0(x) (x->regs.data)2626+2727+int octeon_spi_transfer_one_message(struct spi_master *master,2828+ struct spi_message *msg);2929+3030+/* MPI register descriptions */30313132#define CVMX_MPI_CFG (CVMX_ADD_IO_SEG(0x0001070000001000ull))3233#define CVMX_MPI_DATX(offset) (CVMX_ADD_IO_SEG(0x0001070000001080ull) + ((offset) & 15) * 8)···326325 struct cvmx_mpi_tx_cn61xx cnf71xx;327326};328327329329-#endif328328+#endif /* __SPI_CAVIUM_H */
+1
drivers/spi/Kconfig
···411411 tristate "McSPI driver for OMAP"412412 depends on HAS_DMA413413 depends on ARCH_OMAP2PLUS || COMPILE_TEST414414+ select SG_SPLIT414415 help415416 SPI master controller for OMAP24XX and later Multichannel SPI416417 (McSPI) modules.
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (C) 2011, 2012 Cavium, Inc.77+ */88+99+#include <linux/platform_device.h>1010+#include <linux/spi/spi.h>1111+#include <linux/module.h>1212+#include <linux/io.h>1313+#include <linux/of.h>1414+1515+#include <asm/octeon/octeon.h>1616+1717+#include "spi-cavium.h"1818+1919+static int octeon_spi_probe(struct platform_device *pdev)2020+{2121+ struct resource *res_mem;2222+ void __iomem *reg_base;2323+ struct spi_master *master;2424+ struct octeon_spi *p;2525+ int err = -ENOENT;2626+2727+ master = spi_alloc_master(&pdev->dev, sizeof(struct octeon_spi));2828+ if (!master)2929+ return -ENOMEM;3030+ p = spi_master_get_devdata(master);3131+ platform_set_drvdata(pdev, master);3232+3333+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);3434+ reg_base = devm_ioremap_resource(&pdev->dev, res_mem);3535+ if (IS_ERR(reg_base)) {3636+ err = PTR_ERR(reg_base);3737+ goto fail;3838+ }3939+4040+ p->register_base = reg_base;4141+ p->sys_freq = octeon_get_io_clock_rate();4242+4343+ p->regs.config = 0;4444+ p->regs.status = 0x08;4545+ p->regs.tx = 0x10;4646+ p->regs.data = 0x80;4747+4848+ master->num_chipselect = 4;4949+ master->mode_bits = SPI_CPHA |5050+ SPI_CPOL |5151+ SPI_CS_HIGH |5252+ SPI_LSB_FIRST |5353+ SPI_3WIRE;5454+5555+ master->transfer_one_message = octeon_spi_transfer_one_message;5656+ master->bits_per_word_mask = SPI_BPW_MASK(8);5757+ master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;5858+5959+ master->dev.of_node = pdev->dev.of_node;6060+ err = devm_spi_register_master(&pdev->dev, master);6161+ if (err) {6262+ dev_err(&pdev->dev, "register master failed: %d\n", err);6363+ goto fail;6464+ }6565+6666+ dev_info(&pdev->dev, "OCTEON SPI bus driver\n");6767+6868+ return 0;6969+fail:7070+ spi_master_put(master);7171+ return err;7272+}7373+7474+static int octeon_spi_remove(struct platform_device *pdev)7575+{7676+ struct spi_master *master = platform_get_drvdata(pdev);7777+ struct octeon_spi *p = spi_master_get_devdata(master);7878+7979+ /* Clear the CSENA* and put everything in a known state. */8080+ writeq(0, p->register_base + OCTEON_SPI_CFG(p));8181+8282+ return 0;8383+}8484+8585+static const struct of_device_id octeon_spi_match[] = {8686+ { .compatible = "cavium,octeon-3010-spi", },8787+ {},8888+};8989+MODULE_DEVICE_TABLE(of, octeon_spi_match);9090+9191+static struct platform_driver octeon_spi_driver = {9292+ .driver = {9393+ .name = "spi-octeon",9494+ .of_match_table = octeon_spi_match,9595+ },9696+ .probe = octeon_spi_probe,9797+ .remove = octeon_spi_remove,9898+};9999+100100+module_platform_driver(octeon_spi_driver);101101+102102+MODULE_DESCRIPTION("Cavium, Inc. OCTEON SPI bus driver");103103+MODULE_AUTHOR("David Daney");104104+MODULE_LICENSE("GPL");
+151
drivers/spi/spi-cavium.c
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (C) 2011, 2012 Cavium, Inc.77+ */88+99+#include <linux/spi/spi.h>1010+#include <linux/module.h>1111+#include <linux/delay.h>1212+#include <linux/io.h>1313+1414+#include "spi-cavium.h"1515+1616+static void octeon_spi_wait_ready(struct octeon_spi *p)1717+{1818+ union cvmx_mpi_sts mpi_sts;1919+ unsigned int loops = 0;2020+2121+ do {2222+ if (loops++)2323+ __delay(500);2424+ mpi_sts.u64 = readq(p->register_base + OCTEON_SPI_STS(p));2525+ } while (mpi_sts.s.busy);2626+}2727+2828+static int octeon_spi_do_transfer(struct octeon_spi *p,2929+ struct spi_message *msg,3030+ struct spi_transfer *xfer,3131+ bool last_xfer)3232+{3333+ struct spi_device *spi = msg->spi;3434+ union cvmx_mpi_cfg mpi_cfg;3535+ union cvmx_mpi_tx mpi_tx;3636+ unsigned int clkdiv;3737+ int mode;3838+ bool cpha, cpol;3939+ const u8 *tx_buf;4040+ u8 *rx_buf;4141+ int len;4242+ int i;4343+4444+ mode = spi->mode;4545+ cpha = mode & SPI_CPHA;4646+ cpol = mode & SPI_CPOL;4747+4848+ clkdiv = p->sys_freq / (2 * xfer->speed_hz);4949+5050+ mpi_cfg.u64 = 0;5151+5252+ mpi_cfg.s.clkdiv = clkdiv;5353+ mpi_cfg.s.cshi = (mode & SPI_CS_HIGH) ? 1 : 0;5454+ mpi_cfg.s.lsbfirst = (mode & SPI_LSB_FIRST) ? 1 : 0;5555+ mpi_cfg.s.wireor = (mode & SPI_3WIRE) ? 1 : 0;5656+ mpi_cfg.s.idlelo = cpha != cpol;5757+ mpi_cfg.s.cslate = cpha ? 1 : 0;5858+ mpi_cfg.s.enable = 1;5959+6060+ if (spi->chip_select < 4)6161+ p->cs_enax |= 1ull << (12 + spi->chip_select);6262+ mpi_cfg.u64 |= p->cs_enax;6363+6464+ if (mpi_cfg.u64 != p->last_cfg) {6565+ p->last_cfg = mpi_cfg.u64;6666+ writeq(mpi_cfg.u64, p->register_base + OCTEON_SPI_CFG(p));6767+ }6868+ tx_buf = xfer->tx_buf;6969+ rx_buf = xfer->rx_buf;7070+ len = xfer->len;7171+ while (len > OCTEON_SPI_MAX_BYTES) {7272+ for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {7373+ u8 d;7474+ if (tx_buf)7575+ d = *tx_buf++;7676+ else7777+ d = 0;7878+ writeq(d, p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));7979+ }8080+ mpi_tx.u64 = 0;8181+ mpi_tx.s.csid = spi->chip_select;8282+ mpi_tx.s.leavecs = 1;8383+ mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0;8484+ mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES;8585+ writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX(p));8686+8787+ octeon_spi_wait_ready(p);8888+ if (rx_buf)8989+ for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {9090+ u64 v = readq(p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));9191+ *rx_buf++ = (u8)v;9292+ }9393+ len -= OCTEON_SPI_MAX_BYTES;9494+ }9595+9696+ for (i = 0; i < len; i++) {9797+ u8 d;9898+ if (tx_buf)9999+ d = *tx_buf++;100100+ else101101+ d = 0;102102+ writeq(d, p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));103103+ }104104+105105+ mpi_tx.u64 = 0;106106+ mpi_tx.s.csid = spi->chip_select;107107+ if (last_xfer)108108+ mpi_tx.s.leavecs = xfer->cs_change;109109+ else110110+ mpi_tx.s.leavecs = !xfer->cs_change;111111+ mpi_tx.s.txnum = tx_buf ? len : 0;112112+ mpi_tx.s.totnum = len;113113+ writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX(p));114114+115115+ octeon_spi_wait_ready(p);116116+ if (rx_buf)117117+ for (i = 0; i < len; i++) {118118+ u64 v = readq(p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));119119+ *rx_buf++ = (u8)v;120120+ }121121+122122+ if (xfer->delay_usecs)123123+ udelay(xfer->delay_usecs);124124+125125+ return xfer->len;126126+}127127+128128+int octeon_spi_transfer_one_message(struct spi_master *master,129129+ struct spi_message *msg)130130+{131131+ struct octeon_spi *p = spi_master_get_devdata(master);132132+ unsigned int total_len = 0;133133+ int status = 0;134134+ struct spi_transfer *xfer;135135+136136+ list_for_each_entry(xfer, &msg->transfers, transfer_list) {137137+ bool last_xfer = list_is_last(&xfer->transfer_list,138138+ &msg->transfers);139139+ int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);140140+ if (r < 0) {141141+ status = r;142142+ goto err;143143+ }144144+ total_len += r;145145+ }146146+err:147147+ msg->status = status;148148+ msg->actual_length = total_len;149149+ spi_finalize_current_message(master);150150+ return status;151151+}
-255
drivers/spi/spi-octeon.c
···11-/*22- * This file is subject to the terms and conditions of the GNU General Public33- * License. See the file "COPYING" in the main directory of this archive44- * for more details.55- *66- * Copyright (C) 2011, 2012 Cavium, Inc.77- */88-99-#include <linux/platform_device.h>1010-#include <linux/interrupt.h>1111-#include <linux/spi/spi.h>1212-#include <linux/module.h>1313-#include <linux/delay.h>1414-#include <linux/io.h>1515-#include <linux/of.h>1616-1717-#include <asm/octeon/octeon.h>1818-#include <asm/octeon/cvmx-mpi-defs.h>1919-2020-#define OCTEON_SPI_CFG 02121-#define OCTEON_SPI_STS 0x082222-#define OCTEON_SPI_TX 0x102323-#define OCTEON_SPI_DAT0 0x802424-2525-#define OCTEON_SPI_MAX_BYTES 92626-2727-#define OCTEON_SPI_MAX_CLOCK_HZ 160000002828-2929-struct octeon_spi {3030- u64 register_base;3131- u64 last_cfg;3232- u64 cs_enax;3333-};3434-3535-static void octeon_spi_wait_ready(struct octeon_spi *p)3636-{3737- union cvmx_mpi_sts mpi_sts;3838- unsigned int loops = 0;3939-4040- do {4141- if (loops++)4242- __delay(500);4343- mpi_sts.u64 = cvmx_read_csr(p->register_base + OCTEON_SPI_STS);4444- } while (mpi_sts.s.busy);4545-}4646-4747-static int octeon_spi_do_transfer(struct octeon_spi *p,4848- struct spi_message *msg,4949- struct spi_transfer *xfer,5050- bool last_xfer)5151-{5252- struct spi_device *spi = msg->spi;5353- union cvmx_mpi_cfg mpi_cfg;5454- union cvmx_mpi_tx mpi_tx;5555- unsigned int clkdiv;5656- unsigned int speed_hz;5757- int mode;5858- bool cpha, cpol;5959- const u8 *tx_buf;6060- u8 *rx_buf;6161- int len;6262- int i;6363-6464- mode = spi->mode;6565- cpha = mode & SPI_CPHA;6666- cpol = mode & SPI_CPOL;6767-6868- speed_hz = xfer->speed_hz;6969-7070- clkdiv = octeon_get_io_clock_rate() / (2 * speed_hz);7171-7272- mpi_cfg.u64 = 0;7373-7474- mpi_cfg.s.clkdiv = clkdiv;7575- mpi_cfg.s.cshi = (mode & SPI_CS_HIGH) ? 1 : 0;7676- mpi_cfg.s.lsbfirst = (mode & SPI_LSB_FIRST) ? 1 : 0;7777- mpi_cfg.s.wireor = (mode & SPI_3WIRE) ? 1 : 0;7878- mpi_cfg.s.idlelo = cpha != cpol;7979- mpi_cfg.s.cslate = cpha ? 1 : 0;8080- mpi_cfg.s.enable = 1;8181-8282- if (spi->chip_select < 4)8383- p->cs_enax |= 1ull << (12 + spi->chip_select);8484- mpi_cfg.u64 |= p->cs_enax;8585-8686- if (mpi_cfg.u64 != p->last_cfg) {8787- p->last_cfg = mpi_cfg.u64;8888- cvmx_write_csr(p->register_base + OCTEON_SPI_CFG, mpi_cfg.u64);8989- }9090- tx_buf = xfer->tx_buf;9191- rx_buf = xfer->rx_buf;9292- len = xfer->len;9393- while (len > OCTEON_SPI_MAX_BYTES) {9494- for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {9595- u8 d;9696- if (tx_buf)9797- d = *tx_buf++;9898- else9999- d = 0;100100- cvmx_write_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i), d);101101- }102102- mpi_tx.u64 = 0;103103- mpi_tx.s.csid = spi->chip_select;104104- mpi_tx.s.leavecs = 1;105105- mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0;106106- mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES;107107- cvmx_write_csr(p->register_base + OCTEON_SPI_TX, mpi_tx.u64);108108-109109- octeon_spi_wait_ready(p);110110- if (rx_buf)111111- for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {112112- u64 v = cvmx_read_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i));113113- *rx_buf++ = (u8)v;114114- }115115- len -= OCTEON_SPI_MAX_BYTES;116116- }117117-118118- for (i = 0; i < len; i++) {119119- u8 d;120120- if (tx_buf)121121- d = *tx_buf++;122122- else123123- d = 0;124124- cvmx_write_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i), d);125125- }126126-127127- mpi_tx.u64 = 0;128128- mpi_tx.s.csid = spi->chip_select;129129- if (last_xfer)130130- mpi_tx.s.leavecs = xfer->cs_change;131131- else132132- mpi_tx.s.leavecs = !xfer->cs_change;133133- mpi_tx.s.txnum = tx_buf ? len : 0;134134- mpi_tx.s.totnum = len;135135- cvmx_write_csr(p->register_base + OCTEON_SPI_TX, mpi_tx.u64);136136-137137- octeon_spi_wait_ready(p);138138- if (rx_buf)139139- for (i = 0; i < len; i++) {140140- u64 v = cvmx_read_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i));141141- *rx_buf++ = (u8)v;142142- }143143-144144- if (xfer->delay_usecs)145145- udelay(xfer->delay_usecs);146146-147147- return xfer->len;148148-}149149-150150-static int octeon_spi_transfer_one_message(struct spi_master *master,151151- struct spi_message *msg)152152-{153153- struct octeon_spi *p = spi_master_get_devdata(master);154154- unsigned int total_len = 0;155155- int status = 0;156156- struct spi_transfer *xfer;157157-158158- list_for_each_entry(xfer, &msg->transfers, transfer_list) {159159- bool last_xfer = list_is_last(&xfer->transfer_list,160160- &msg->transfers);161161- int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);162162- if (r < 0) {163163- status = r;164164- goto err;165165- }166166- total_len += r;167167- }168168-err:169169- msg->status = status;170170- msg->actual_length = total_len;171171- spi_finalize_current_message(master);172172- return status;173173-}174174-175175-static int octeon_spi_probe(struct platform_device *pdev)176176-{177177- struct resource *res_mem;178178- void __iomem *reg_base;179179- struct spi_master *master;180180- struct octeon_spi *p;181181- int err = -ENOENT;182182-183183- master = spi_alloc_master(&pdev->dev, sizeof(struct octeon_spi));184184- if (!master)185185- return -ENOMEM;186186- p = spi_master_get_devdata(master);187187- platform_set_drvdata(pdev, master);188188-189189- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);190190- reg_base = devm_ioremap_resource(&pdev->dev, res_mem);191191- if (IS_ERR(reg_base)) {192192- err = PTR_ERR(reg_base);193193- goto fail;194194- }195195-196196- p->register_base = (u64)reg_base;197197-198198- master->num_chipselect = 4;199199- master->mode_bits = SPI_CPHA |200200- SPI_CPOL |201201- SPI_CS_HIGH |202202- SPI_LSB_FIRST |203203- SPI_3WIRE;204204-205205- master->transfer_one_message = octeon_spi_transfer_one_message;206206- master->bits_per_word_mask = SPI_BPW_MASK(8);207207- master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;208208-209209- master->dev.of_node = pdev->dev.of_node;210210- err = devm_spi_register_master(&pdev->dev, master);211211- if (err) {212212- dev_err(&pdev->dev, "register master failed: %d\n", err);213213- goto fail;214214- }215215-216216- dev_info(&pdev->dev, "OCTEON SPI bus driver\n");217217-218218- return 0;219219-fail:220220- spi_master_put(master);221221- return err;222222-}223223-224224-static int octeon_spi_remove(struct platform_device *pdev)225225-{226226- struct spi_master *master = platform_get_drvdata(pdev);227227- struct octeon_spi *p = spi_master_get_devdata(master);228228- u64 register_base = p->register_base;229229-230230- /* Clear the CSENA* and put everything in a known state. */231231- cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0);232232-233233- return 0;234234-}235235-236236-static const struct of_device_id octeon_spi_match[] = {237237- { .compatible = "cavium,octeon-3010-spi", },238238- {},239239-};240240-MODULE_DEVICE_TABLE(of, octeon_spi_match);241241-242242-static struct platform_driver octeon_spi_driver = {243243- .driver = {244244- .name = "spi-octeon",245245- .of_match_table = octeon_spi_match,246246- },247247- .probe = octeon_spi_probe,248248- .remove = octeon_spi_remove,249249-};250250-251251-module_platform_driver(octeon_spi_driver);252252-253253-MODULE_DESCRIPTION("Cavium, Inc. OCTEON SPI bus driver");254254-MODULE_AUTHOR("David Daney");255255-MODULE_LICENSE("GPL");
+69-76
drivers/spi/spi-omap2-mcspi.c
···419419420420 if (mcspi_dma->dma_tx) {421421 struct dma_async_tx_descriptor *tx;422422- struct scatterlist sg;423422424423 dmaengine_slave_config(mcspi_dma->dma_tx, &cfg);425424426426- sg_init_table(&sg, 1);427427- sg_dma_address(&sg) = xfer->tx_dma;428428- sg_dma_len(&sg) = xfer->len;429429-430430- tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1,431431- DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);425425+ tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl,426426+ xfer->tx_sg.nents,427427+ DMA_MEM_TO_DEV,428428+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);432429 if (tx) {433430 tx->callback = omap2_mcspi_tx_callback;434431 tx->callback_param = spi;···446449{447450 struct omap2_mcspi *mcspi;448451 struct omap2_mcspi_dma *mcspi_dma;449449- unsigned int count, dma_count;452452+ unsigned int count, transfer_reduction = 0;453453+ struct scatterlist *sg_out[2];454454+ int nb_sizes = 0, out_mapped_nents[2], ret, x;455455+ size_t sizes[2];450456 u32 l;451457 int elements = 0;452458 int word_len, element_count;···457457 mcspi = spi_master_get_devdata(spi->master);458458 mcspi_dma = &mcspi->dma_channels[spi->chip_select];459459 count = xfer->len;460460- dma_count = xfer->len;461460461461+ /*462462+ * In the "End-of-Transfer Procedure" section for DMA RX in OMAP35x TRM463463+ * it mentions reducing DMA transfer length by one element in master464464+ * normal mode.465465+ */462466 if (mcspi->fifo_depth == 0)463463- dma_count -= es;467467+ transfer_reduction = es;464468465469 word_len = cs->word_len;466470 l = mcspi_cached_chconf0(spi);···478474479475 if (mcspi_dma->dma_rx) {480476 struct dma_async_tx_descriptor *tx;481481- struct scatterlist sg;482477483478 dmaengine_slave_config(mcspi_dma->dma_rx, &cfg);484479480480+ /*481481+ * Reduce DMA transfer length by one more if McSPI is482482+ * configured in turbo mode.483483+ */485484 if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0)486486- dma_count -= es;485485+ transfer_reduction += es;487486488488- sg_init_table(&sg, 1);489489- sg_dma_address(&sg) = xfer->rx_dma;490490- sg_dma_len(&sg) = dma_count;487487+ if (transfer_reduction) {488488+ /* Split sgl into two. The second sgl won't be used. */489489+ sizes[0] = count - transfer_reduction;490490+ sizes[1] = transfer_reduction;491491+ nb_sizes = 2;492492+ } else {493493+ /*494494+ * Don't bother splitting the sgl. This essentially495495+ * clones the original sgl.496496+ */497497+ sizes[0] = count;498498+ nb_sizes = 1;499499+ }491500492492- tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,493493- DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |494494- DMA_CTRL_ACK);501501+ ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents,502502+ 0, nb_sizes,503503+ sizes,504504+ sg_out, out_mapped_nents,505505+ GFP_KERNEL);506506+507507+ if (ret < 0) {508508+ dev_err(&spi->dev, "sg_split failed\n");509509+ return 0;510510+ }511511+512512+ tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx,513513+ sg_out[0],514514+ out_mapped_nents[0],515515+ DMA_DEV_TO_MEM,516516+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);495517 if (tx) {496518 tx->callback = omap2_mcspi_rx_callback;497519 tx->callback_param = spi;···531501 omap2_mcspi_set_dma_req(spi, 1, 1);532502533503 wait_for_completion(&mcspi_dma->dma_rx_completion);534534- dma_unmap_single(mcspi->dev, xfer->rx_dma, count,535535- DMA_FROM_DEVICE);504504+505505+ for (x = 0; x < nb_sizes; x++)506506+ kfree(sg_out[x]);536507537508 if (mcspi->fifo_depth > 0)538509 return count;539510511511+ /*512512+ * Due to the DMA transfer length reduction the missing bytes must513513+ * be read manually to receive all of the expected data.514514+ */540515 omap2_mcspi_set_enable(spi, 0);541516542517 elements = element_count - 1;···650615651616 if (tx != NULL) {652617 wait_for_completion(&mcspi_dma->dma_tx_completion);653653- dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,654654- DMA_TO_DEVICE);655618656619 if (mcspi->fifo_depth > 0) {657620 irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;···11071074 gpio_free(spi->cs_gpio);11081075}1109107611101110-static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,11111111- struct spi_device *spi, struct spi_transfer *t)10771077+static int omap2_mcspi_transfer_one(struct spi_master *master,10781078+ struct spi_device *spi,10791079+ struct spi_transfer *t)11121080{1113108111141082 /* We only enable one channel at a time -- the one whose message is···11191085 * chipselect with the FORCE bit ... CS != channel enable.11201086 */1121108711221122- struct spi_master *master;10881088+ struct omap2_mcspi *mcspi;11231089 struct omap2_mcspi_dma *mcspi_dma;11241090 struct omap2_mcspi_cs *cs;11251091 struct omap2_mcspi_device_config *cd;···11271093 int status = 0;11281094 u32 chconf;1129109511301130- master = spi->master;10961096+ mcspi = spi_master_get_devdata(master);11311097 mcspi_dma = mcspi->dma_channels + spi->chip_select;11321098 cs = spi->controller_state;11331099 cd = spi->controller_data;···11871153 unsigned count;1188115411891155 if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&11901190- (t->len >= DMA_MIN_BYTES))11561156+ master->cur_msg_mapped &&11571157+ master->can_dma(master, spi, t))11911158 omap2_mcspi_set_fifo(spi, t, 1);1192115911931160 omap2_mcspi_set_enable(spi, 1);···11991164 + OMAP2_MCSPI_TX0);1200116512011166 if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&12021202- (t->len >= DMA_MIN_BYTES))11671167+ master->cur_msg_mapped &&11681168+ master->can_dma(master, spi, t))12031169 count = omap2_mcspi_txrx_dma(spi, t);12041170 else12051171 count = omap2_mcspi_txrx_pio(spi, t);···12691233 return 0;12701234}1271123512721272-static int omap2_mcspi_transfer_one(struct spi_master *master,12731273- struct spi_device *spi, struct spi_transfer *t)12361236+static bool omap2_mcspi_can_dma(struct spi_master *master,12371237+ struct spi_device *spi,12381238+ struct spi_transfer *xfer)12741239{12751275- struct omap2_mcspi *mcspi;12761276- struct omap2_mcspi_dma *mcspi_dma;12771277- const void *tx_buf = t->tx_buf;12781278- void *rx_buf = t->rx_buf;12791279- unsigned len = t->len;12801280-12811281- mcspi = spi_master_get_devdata(master);12821282- mcspi_dma = mcspi->dma_channels + spi->chip_select;12831283-12841284- if ((len && !(rx_buf || tx_buf))) {12851285- dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",12861286- t->speed_hz,12871287- len,12881288- tx_buf ? "tx" : "",12891289- rx_buf ? "rx" : "",12901290- t->bits_per_word);12911291- return -EINVAL;12921292- }12931293-12941294- if (len < DMA_MIN_BYTES)12951295- goto skip_dma_map;12961296-12971297- if (mcspi_dma->dma_tx && tx_buf != NULL) {12981298- t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf,12991299- len, DMA_TO_DEVICE);13001300- if (dma_mapping_error(mcspi->dev, t->tx_dma)) {13011301- dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",13021302- 'T', len);13031303- return -EINVAL;13041304- }13051305- }13061306- if (mcspi_dma->dma_rx && rx_buf != NULL) {13071307- t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len,13081308- DMA_FROM_DEVICE);13091309- if (dma_mapping_error(mcspi->dev, t->rx_dma)) {13101310- dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",13111311- 'R', len);13121312- if (tx_buf != NULL)13131313- dma_unmap_single(mcspi->dev, t->tx_dma,13141314- len, DMA_TO_DEVICE);13151315- return -EINVAL;13161316- }13171317- }13181318-13191319-skip_dma_map:13201320- return omap2_mcspi_work_one(mcspi, spi, t);12401240+ return (xfer->len >= DMA_MIN_BYTES);13211241}1322124213231243static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)···13531361 master->setup = omap2_mcspi_setup;13541362 master->auto_runtime_pm = true;13551363 master->prepare_message = omap2_mcspi_prepare_message;13641364+ master->can_dma = omap2_mcspi_can_dma;13561365 master->transfer_one = omap2_mcspi_transfer_one;13571366 master->set_cs = omap2_mcspi_set_cs;13581367 master->cleanup = omap2_mcspi_cleanup;
+88
drivers/spi/spi-orion.c
···1818#include <linux/module.h>1919#include <linux/pm_runtime.h>2020#include <linux/of.h>2121+#include <linux/of_address.h>2122#include <linux/of_device.h>2223#include <linux/clk.h>2324#include <linux/sizes.h>···4342#define ORION_SPI_DATA_IN_REG 0x0c4443#define ORION_SPI_INT_CAUSE_REG 0x104544#define ORION_SPI_TIMING_PARAMS_REG 0x184545+4646+/* Register for the "Direct Mode" */4747+#define SPI_DIRECT_WRITE_CONFIG_REG 0x2046484749#define ORION_SPI_TMISO_SAMPLE_MASK (0x3 << 6)4850#define ORION_SPI_TMISO_SAMPLE_1 (1 << 6)···8278 bool is_errata_50mhz_ac;8379};84808181+struct orion_direct_acc {8282+ void __iomem *vaddr;8383+ u32 size;8484+};8585+8586struct orion_spi {8687 struct spi_master *master;8788 void __iomem *base;8889 struct clk *clk;8990 const struct orion_spi_dev *devdata;9191+9292+ struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS];9093};91949295static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)···383372{384373 unsigned int count;385374 int word_len;375375+ struct orion_spi *orion_spi;376376+ int cs = spi->chip_select;386377387378 word_len = spi->bits_per_word;388379 count = xfer->len;380380+381381+ orion_spi = spi_master_get_devdata(spi->master);382382+383383+ /*384384+ * Use SPI direct write mode if base address is available. Otherwise385385+ * fall back to PIO mode for this transfer.386386+ */387387+ if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&388388+ (word_len == 8)) {389389+ unsigned int cnt = count / 4;390390+ unsigned int rem = count % 4;391391+392392+ /*393393+ * Send the TX-data to the SPI device via the direct394394+ * mapped address window395395+ */396396+ iowrite32_rep(orion_spi->direct_access[cs].vaddr,397397+ xfer->tx_buf, cnt);398398+ if (rem) {399399+ u32 *buf = (u32 *)xfer->tx_buf;400400+401401+ iowrite8_rep(orion_spi->direct_access[cs].vaddr,402402+ &buf[cnt], rem);403403+ }404404+405405+ return count;406406+ }389407390408 if (word_len == 8) {391409 const u8 *tx = xfer->tx_buf;···465425{466426 /* Verify that the CS is deasserted */467427 orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);428428+429429+ /* Don't deassert CS between the direct mapped SPI transfers */430430+ writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG));431431+468432 return 0;469433}470434···548504 struct resource *r;549505 unsigned long tclk_hz;550506 int status = 0;507507+ struct device_node *np;551508552509 master = spi_alloc_master(&pdev->dev, sizeof(*spi));553510 if (master == NULL) {···619574 if (IS_ERR(spi->base)) {620575 status = PTR_ERR(spi->base);621576 goto out_rel_clk;577577+ }578578+579579+ /* Scan all SPI devices of this controller for direct mapped devices */580580+ for_each_available_child_of_node(pdev->dev.of_node, np) {581581+ u32 cs;582582+583583+ /* Get chip-select number from the "reg" property */584584+ status = of_property_read_u32(np, "reg", &cs);585585+ if (status) {586586+ dev_err(&pdev->dev,587587+ "%s has no valid 'reg' property (%d)\n",588588+ np->full_name, status);589589+ status = 0;590590+ continue;591591+ }592592+593593+ /*594594+ * Check if an address is configured for this SPI device. If595595+ * not, the MBus mapping via the 'ranges' property in the 'soc'596596+ * node is not configured and this device should not use the597597+ * direct mode. In this case, just continue with the next598598+ * device.599599+ */600600+ status = of_address_to_resource(pdev->dev.of_node, cs + 1, r);601601+ if (status)602602+ continue;603603+604604+ /*605605+ * Only map one page for direct access. This is enough for the606606+ * simple TX transfer which only writes to the first word.607607+ * This needs to get extended for the direct SPI-NOR / SPI-NAND608608+ * support, once this gets implemented.609609+ */610610+ spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev,611611+ r->start,612612+ PAGE_SIZE);613613+ if (!spi->direct_access[cs].vaddr) {614614+ status = -ENOMEM;615615+ goto out_rel_clk;616616+ }617617+ spi->direct_access[cs].size = PAGE_SIZE;618618+619619+ dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);622620 }623621624622 pm_runtime_set_active(&pdev->dev);
+4-3
drivers/spi/spi-pic32-sqi.c
···354354 struct spi_transfer *xfer;355355 struct pic32_sqi *sqi;356356 int ret = 0, mode;357357+ unsigned long timeout;357358 u32 val;358359359360 sqi = spi_master_get_devdata(master);···420419 writel(val, sqi->regs + PESQI_BD_CTRL_REG);421420422421 /* wait for xfer completion */423423- ret = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ);424424- if (ret <= 0) {422422+ timeout = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ);423423+ if (timeout == 0) {425424 dev_err(&sqi->master->dev, "wait timedout/interrupted\n");426426- ret = -EIO;425425+ ret = -ETIMEDOUT;427426 msg->status = ret;428427 } else {429428 /* success */
+3-2
drivers/spi/spi-pic32.c
···507507{508508 struct pic32_spi *pic32s;509509 bool dma_issued = false;510510+ unsigned long timeout;510511 int ret;511512512513 pic32s = spi_master_get_devdata(master);···554553 }555554556555 /* wait for completion */557557- ret = wait_for_completion_timeout(&pic32s->xfer_done, 2 * HZ);558558- if (ret <= 0) {556556+ timeout = wait_for_completion_timeout(&pic32s->xfer_done, 2 * HZ);557557+ if (timeout == 0) {559558 dev_err(&spi->dev, "wait error/timedout\n");560559 if (dma_issued) {561560 dmaengine_terminate_all(master->dma_rx);