^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Freescale SPI/eSPI controller driver library.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Maintainer: Kumar Gala
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2006 Polycom, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * CPM SPI and QE buffer descriptors mode support:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (c) 2009 MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright 2010 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/fsl_devices.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #ifdef CONFIG_FSL_SOC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sysdev/fsl_soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "spi-fsl-lib.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MPC8XXX_SPI_RX_BUF(type) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) type *rx = mpc8xxx_spi->rx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *rx++ = (type)(data >> mpc8xxx_spi->rx_shift); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) mpc8xxx_spi->rx = rx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) EXPORT_SYMBOL_GPL(mpc8xxx_spi_rx_buf_##type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MPC8XXX_SPI_TX_BUF(type) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 data; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) const type *tx = mpc8xxx_spi->tx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (!tx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) data = *tx++ << mpc8xxx_spi->tx_shift; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) mpc8xxx_spi->tx = tx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return data; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) EXPORT_SYMBOL_GPL(mpc8xxx_spi_tx_buf_##type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) MPC8XXX_SPI_RX_BUF(u8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) MPC8XXX_SPI_RX_BUF(u16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MPC8XXX_SPI_RX_BUF(u32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) MPC8XXX_SPI_TX_BUF(u8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) MPC8XXX_SPI_TX_BUF(u16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) MPC8XXX_SPI_TX_BUF(u32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) EXPORT_SYMBOL_GPL(to_of_pinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) const char *mpc8xxx_spi_strmode(unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (flags & SPI_QE_CPU_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return "QE CPU";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) } else if (flags & SPI_CPM_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (flags & SPI_QE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return "QE";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) else if (flags & SPI_CPM2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return "CPM2";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return "CPM1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return "CPU";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) EXPORT_SYMBOL_GPL(mpc8xxx_spi_strmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct spi_master *master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct mpc8xxx_spi *mpc8xxx_spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) master = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* the spi->mode bits understood by this driver: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) | SPI_LSB_FIRST | SPI_LOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) master->dev.of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) mpc8xxx_spi = spi_master_get_devdata(master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mpc8xxx_spi->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) mpc8xxx_spi->flags = pdata->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) mpc8xxx_spi->spibrg = pdata->sysclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) mpc8xxx_spi->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) mpc8xxx_spi->rx_shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) mpc8xxx_spi->tx_shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) master->bus_num = pdata->bus_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) master->num_chipselect = pdata->max_chipselect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) init_completion(&mpc8xxx_spi->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct device *dev = &ofdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct device_node *np = ofdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct mpc8xxx_spi_probe_info *pinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct fsl_spi_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const void *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) pinfo = devm_kzalloc(&ofdev->dev, sizeof(*pinfo), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!pinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) pdata = &pinfo->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) dev->platform_data = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Allocate bus num dynamically. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) pdata->bus_num = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #ifdef CONFIG_FSL_SOC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* SPI controller is either clocked from QE or SoC clock. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pdata->sysclk = get_brgfreq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (pdata->sysclk == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pdata->sysclk = fsl_get_sys_freq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (pdata->sysclk == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) prop = of_get_property(np, "mode", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (prop && !strcmp(prop, "cpu-qe"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pdata->flags = SPI_QE_CPU_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) else if (prop && !strcmp(prop, "qe"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) pdata->flags = SPI_CPM_MODE | SPI_QE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) pdata->flags = SPI_CPM_MODE | SPI_CPM2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) pdata->flags = SPI_CPM_MODE | SPI_CPM1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) EXPORT_SYMBOL_GPL(of_mpc8xxx_spi_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) MODULE_LICENSE("GPL");