18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SPI_PPC4XX SPI controller driver. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2007 Gary Jennejohn <garyj@denx.de> 68c2ecf20Sopenharmony_ci * Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering 78c2ecf20Sopenharmony_ci * Copyright 2009 Harris Corporation, Steven A. Falco <sfalco@harris.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Based in part on drivers/spi/spi_s3c24xx.c 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Copyright (c) 2006 Ben Dooks 128c2ecf20Sopenharmony_ci * Copyright (c) 2006 Simtec Electronics 138c2ecf20Sopenharmony_ci * Ben Dooks <ben@simtec.co.uk> 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* 178c2ecf20Sopenharmony_ci * The PPC4xx SPI controller has no FIFO so each sent/received byte will 188c2ecf20Sopenharmony_ci * generate an interrupt to the CPU. This can cause high CPU utilization. 198c2ecf20Sopenharmony_ci * This driver allows platforms to reduce the interrupt load on the CPU 208c2ecf20Sopenharmony_ci * during SPI transfers by setting max_speed_hz via the device tree. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <linux/module.h> 248c2ecf20Sopenharmony_ci#include <linux/sched.h> 258c2ecf20Sopenharmony_ci#include <linux/slab.h> 268c2ecf20Sopenharmony_ci#include <linux/errno.h> 278c2ecf20Sopenharmony_ci#include <linux/wait.h> 288c2ecf20Sopenharmony_ci#include <linux/of_address.h> 298c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 308c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 318c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 328c2ecf20Sopenharmony_ci#include <linux/delay.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 358c2ecf20Sopenharmony_ci#include <linux/spi/spi_bitbang.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <asm/io.h> 388c2ecf20Sopenharmony_ci#include <asm/dcr.h> 398c2ecf20Sopenharmony_ci#include <asm/dcr-regs.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* bits in mode register - bit 0 is MSb */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_SCP = 0 means "data latched on trailing edge of clock" 458c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_SCP = 1 means "data latched on leading edge of clock" 468c2ecf20Sopenharmony_ci * Note: This is the inverse of CPHA. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci#define SPI_PPC4XX_MODE_SCP (0x80 >> 3) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* SPI_PPC4XX_MODE_SPE = 1 means "port enabled" */ 518c2ecf20Sopenharmony_ci#define SPI_PPC4XX_MODE_SPE (0x80 >> 4) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* 548c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_RD = 0 means "MSB first" - this is the normal mode 558c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_RD = 1 means "LSB first" - this is bit-reversed mode 568c2ecf20Sopenharmony_ci * Note: This is identical to SPI_LSB_FIRST. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ci#define SPI_PPC4XX_MODE_RD (0x80 >> 5) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* 618c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_CI = 0 means "clock idles low" 628c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_CI = 1 means "clock idles high" 638c2ecf20Sopenharmony_ci * Note: This is identical to CPOL. 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_ci#define SPI_PPC4XX_MODE_CI (0x80 >> 6) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* 688c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_IL = 0 means "loopback disable" 698c2ecf20Sopenharmony_ci * SPI_PPC4XX_MODE_IL = 1 means "loopback enable" 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci#define SPI_PPC4XX_MODE_IL (0x80 >> 7) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* bits in control register */ 748c2ecf20Sopenharmony_ci/* starts a transfer when set */ 758c2ecf20Sopenharmony_ci#define SPI_PPC4XX_CR_STR (0x80 >> 7) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* bits in status register */ 788c2ecf20Sopenharmony_ci/* port is busy with a transfer */ 798c2ecf20Sopenharmony_ci#define SPI_PPC4XX_SR_BSY (0x80 >> 6) 808c2ecf20Sopenharmony_ci/* RxD ready */ 818c2ecf20Sopenharmony_ci#define SPI_PPC4XX_SR_RBR (0x80 >> 7) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* clock settings (SCP and CI) for various SPI modes */ 848c2ecf20Sopenharmony_ci#define SPI_CLK_MODE0 (SPI_PPC4XX_MODE_SCP | 0) 858c2ecf20Sopenharmony_ci#define SPI_CLK_MODE1 (0 | 0) 868c2ecf20Sopenharmony_ci#define SPI_CLK_MODE2 (SPI_PPC4XX_MODE_SCP | SPI_PPC4XX_MODE_CI) 878c2ecf20Sopenharmony_ci#define SPI_CLK_MODE3 (0 | SPI_PPC4XX_MODE_CI) 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define DRIVER_NAME "spi_ppc4xx_of" 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct spi_ppc4xx_regs { 928c2ecf20Sopenharmony_ci u8 mode; 938c2ecf20Sopenharmony_ci u8 rxd; 948c2ecf20Sopenharmony_ci u8 txd; 958c2ecf20Sopenharmony_ci u8 cr; 968c2ecf20Sopenharmony_ci u8 sr; 978c2ecf20Sopenharmony_ci u8 dummy; 988c2ecf20Sopenharmony_ci /* 998c2ecf20Sopenharmony_ci * Clock divisor modulus register 1008c2ecf20Sopenharmony_ci * This uses the following formula: 1018c2ecf20Sopenharmony_ci * SCPClkOut = OPBCLK/(4(CDM + 1)) 1028c2ecf20Sopenharmony_ci * or 1038c2ecf20Sopenharmony_ci * CDM = (OPBCLK/4*SCPClkOut) - 1 1048c2ecf20Sopenharmony_ci * bit 0 is the MSb! 1058c2ecf20Sopenharmony_ci */ 1068c2ecf20Sopenharmony_ci u8 cdm; 1078c2ecf20Sopenharmony_ci}; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* SPI Controller driver's private data. */ 1108c2ecf20Sopenharmony_cistruct ppc4xx_spi { 1118c2ecf20Sopenharmony_ci /* bitbang has to be first */ 1128c2ecf20Sopenharmony_ci struct spi_bitbang bitbang; 1138c2ecf20Sopenharmony_ci struct completion done; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci u64 mapbase; 1168c2ecf20Sopenharmony_ci u64 mapsize; 1178c2ecf20Sopenharmony_ci int irqnum; 1188c2ecf20Sopenharmony_ci /* need this to set the SPI clock */ 1198c2ecf20Sopenharmony_ci unsigned int opb_freq; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* for transfers */ 1228c2ecf20Sopenharmony_ci int len; 1238c2ecf20Sopenharmony_ci int count; 1248c2ecf20Sopenharmony_ci /* data buffers */ 1258c2ecf20Sopenharmony_ci const unsigned char *tx; 1268c2ecf20Sopenharmony_ci unsigned char *rx; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */ 1298c2ecf20Sopenharmony_ci struct spi_master *master; 1308c2ecf20Sopenharmony_ci struct device *dev; 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* need this so we can set the clock in the chipselect routine */ 1348c2ecf20Sopenharmony_cistruct spi_ppc4xx_cs { 1358c2ecf20Sopenharmony_ci u8 mode; 1368c2ecf20Sopenharmony_ci}; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci struct ppc4xx_spi *hw; 1418c2ecf20Sopenharmony_ci u8 data; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", 1448c2ecf20Sopenharmony_ci t->tx_buf, t->rx_buf, t->len); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci hw = spi_master_get_devdata(spi->master); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci hw->tx = t->tx_buf; 1498c2ecf20Sopenharmony_ci hw->rx = t->rx_buf; 1508c2ecf20Sopenharmony_ci hw->len = t->len; 1518c2ecf20Sopenharmony_ci hw->count = 0; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* send the first byte */ 1548c2ecf20Sopenharmony_ci data = hw->tx ? hw->tx[0] : 0; 1558c2ecf20Sopenharmony_ci out_8(&hw->regs->txd, data); 1568c2ecf20Sopenharmony_ci out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR); 1578c2ecf20Sopenharmony_ci wait_for_completion(&hw->done); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return hw->count; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); 1658c2ecf20Sopenharmony_ci struct spi_ppc4xx_cs *cs = spi->controller_state; 1668c2ecf20Sopenharmony_ci int scr; 1678c2ecf20Sopenharmony_ci u8 cdm = 0; 1688c2ecf20Sopenharmony_ci u32 speed; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* Start with the generic configuration for this device. */ 1718c2ecf20Sopenharmony_ci speed = spi->max_speed_hz; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* 1748c2ecf20Sopenharmony_ci * Modify the configuration if the transfer overrides it. Do not allow 1758c2ecf20Sopenharmony_ci * the transfer to overwrite the generic configuration with zeros. 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci if (t) { 1788c2ecf20Sopenharmony_ci if (t->speed_hz) 1798c2ecf20Sopenharmony_ci speed = min(t->speed_hz, spi->max_speed_hz); 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (!speed || (speed > spi->max_speed_hz)) { 1838c2ecf20Sopenharmony_ci dev_err(&spi->dev, "invalid speed_hz (%d)\n", speed); 1848c2ecf20Sopenharmony_ci return -EINVAL; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci /* Write new configuration */ 1888c2ecf20Sopenharmony_ci out_8(&hw->regs->mode, cs->mode); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* Set the clock */ 1918c2ecf20Sopenharmony_ci /* opb_freq was already divided by 4 */ 1928c2ecf20Sopenharmony_ci scr = (hw->opb_freq / speed) - 1; 1938c2ecf20Sopenharmony_ci if (scr > 0) 1948c2ecf20Sopenharmony_ci cdm = min(scr, 0xff); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, speed); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (in_8(&hw->regs->cdm) != cdm) 1998c2ecf20Sopenharmony_ci out_8(&hw->regs->cdm, cdm); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci mutex_lock(&hw->bitbang.lock); 2028c2ecf20Sopenharmony_ci if (!hw->bitbang.busy) { 2038c2ecf20Sopenharmony_ci hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); 2048c2ecf20Sopenharmony_ci /* Need to ndelay here? */ 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci mutex_unlock(&hw->bitbang.lock); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci return 0; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic int spi_ppc4xx_setup(struct spi_device *spi) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci struct spi_ppc4xx_cs *cs = spi->controller_state; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci if (!spi->max_speed_hz) { 2168c2ecf20Sopenharmony_ci dev_err(&spi->dev, "invalid max_speed_hz (must be non-zero)\n"); 2178c2ecf20Sopenharmony_ci return -EINVAL; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (cs == NULL) { 2218c2ecf20Sopenharmony_ci cs = kzalloc(sizeof *cs, GFP_KERNEL); 2228c2ecf20Sopenharmony_ci if (!cs) 2238c2ecf20Sopenharmony_ci return -ENOMEM; 2248c2ecf20Sopenharmony_ci spi->controller_state = cs; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* 2288c2ecf20Sopenharmony_ci * We set all bits of the SPI0_MODE register, so, 2298c2ecf20Sopenharmony_ci * no need to read-modify-write 2308c2ecf20Sopenharmony_ci */ 2318c2ecf20Sopenharmony_ci cs->mode = SPI_PPC4XX_MODE_SPE; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci switch (spi->mode & (SPI_CPHA | SPI_CPOL)) { 2348c2ecf20Sopenharmony_ci case SPI_MODE_0: 2358c2ecf20Sopenharmony_ci cs->mode |= SPI_CLK_MODE0; 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci case SPI_MODE_1: 2388c2ecf20Sopenharmony_ci cs->mode |= SPI_CLK_MODE1; 2398c2ecf20Sopenharmony_ci break; 2408c2ecf20Sopenharmony_ci case SPI_MODE_2: 2418c2ecf20Sopenharmony_ci cs->mode |= SPI_CLK_MODE2; 2428c2ecf20Sopenharmony_ci break; 2438c2ecf20Sopenharmony_ci case SPI_MODE_3: 2448c2ecf20Sopenharmony_ci cs->mode |= SPI_CLK_MODE3; 2458c2ecf20Sopenharmony_ci break; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (spi->mode & SPI_LSB_FIRST) 2498c2ecf20Sopenharmony_ci cs->mode |= SPI_PPC4XX_MODE_RD; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic irqreturn_t spi_ppc4xx_int(int irq, void *dev_id) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct ppc4xx_spi *hw; 2578c2ecf20Sopenharmony_ci u8 status; 2588c2ecf20Sopenharmony_ci u8 data; 2598c2ecf20Sopenharmony_ci unsigned int count; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci hw = (struct ppc4xx_spi *)dev_id; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci status = in_8(&hw->regs->sr); 2648c2ecf20Sopenharmony_ci if (!status) 2658c2ecf20Sopenharmony_ci return IRQ_NONE; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* 2688c2ecf20Sopenharmony_ci * BSY de-asserts one cycle after the transfer is complete. The 2698c2ecf20Sopenharmony_ci * interrupt is asserted after the transfer is complete. The exact 2708c2ecf20Sopenharmony_ci * relationship is not documented, hence this code. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (unlikely(status & SPI_PPC4XX_SR_BSY)) { 2748c2ecf20Sopenharmony_ci u8 lstatus; 2758c2ecf20Sopenharmony_ci int cnt = 0; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci dev_dbg(hw->dev, "got interrupt but spi still busy?\n"); 2788c2ecf20Sopenharmony_ci do { 2798c2ecf20Sopenharmony_ci ndelay(10); 2808c2ecf20Sopenharmony_ci lstatus = in_8(&hw->regs->sr); 2818c2ecf20Sopenharmony_ci } while (++cnt < 100 && lstatus & SPI_PPC4XX_SR_BSY); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (cnt >= 100) { 2848c2ecf20Sopenharmony_ci dev_err(hw->dev, "busywait: too many loops!\n"); 2858c2ecf20Sopenharmony_ci complete(&hw->done); 2868c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2878c2ecf20Sopenharmony_ci } else { 2888c2ecf20Sopenharmony_ci /* status is always 1 (RBR) here */ 2898c2ecf20Sopenharmony_ci status = in_8(&hw->regs->sr); 2908c2ecf20Sopenharmony_ci dev_dbg(hw->dev, "loops %d status %x\n", cnt, status); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci count = hw->count; 2958c2ecf20Sopenharmony_ci hw->count++; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* RBR triggered this interrupt. Therefore, data must be ready. */ 2988c2ecf20Sopenharmony_ci data = in_8(&hw->regs->rxd); 2998c2ecf20Sopenharmony_ci if (hw->rx) 3008c2ecf20Sopenharmony_ci hw->rx[count] = data; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci count++; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (count < hw->len) { 3058c2ecf20Sopenharmony_ci data = hw->tx ? hw->tx[count] : 0; 3068c2ecf20Sopenharmony_ci out_8(&hw->regs->txd, data); 3078c2ecf20Sopenharmony_ci out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR); 3088c2ecf20Sopenharmony_ci } else { 3098c2ecf20Sopenharmony_ci complete(&hw->done); 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cistatic void spi_ppc4xx_cleanup(struct spi_device *spi) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci kfree(spi->controller_state); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic void spi_ppc4xx_enable(struct ppc4xx_spi *hw) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci /* 3238c2ecf20Sopenharmony_ci * On all 4xx PPC's the SPI bus is shared/multiplexed with 3248c2ecf20Sopenharmony_ci * the 2nd I2C bus. We need to enable the the SPI bus before 3258c2ecf20Sopenharmony_ci * using it. 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* need to clear bit 14 to enable SPC */ 3298c2ecf20Sopenharmony_ci dcri_clrset(SDR0, SDR0_PFC1, 0x80000000 >> 14, 0); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci/* 3338c2ecf20Sopenharmony_ci * platform_device layer stuff... 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_cistatic int spi_ppc4xx_of_probe(struct platform_device *op) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci struct ppc4xx_spi *hw; 3388c2ecf20Sopenharmony_ci struct spi_master *master; 3398c2ecf20Sopenharmony_ci struct spi_bitbang *bbp; 3408c2ecf20Sopenharmony_ci struct resource resource; 3418c2ecf20Sopenharmony_ci struct device_node *np = op->dev.of_node; 3428c2ecf20Sopenharmony_ci struct device *dev = &op->dev; 3438c2ecf20Sopenharmony_ci struct device_node *opbnp; 3448c2ecf20Sopenharmony_ci int ret; 3458c2ecf20Sopenharmony_ci const unsigned int *clk; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci master = spi_alloc_master(dev, sizeof *hw); 3488c2ecf20Sopenharmony_ci if (master == NULL) 3498c2ecf20Sopenharmony_ci return -ENOMEM; 3508c2ecf20Sopenharmony_ci master->dev.of_node = np; 3518c2ecf20Sopenharmony_ci platform_set_drvdata(op, master); 3528c2ecf20Sopenharmony_ci hw = spi_master_get_devdata(master); 3538c2ecf20Sopenharmony_ci hw->master = master; 3548c2ecf20Sopenharmony_ci hw->dev = dev; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci init_completion(&hw->done); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* Setup the state for the bitbang driver */ 3598c2ecf20Sopenharmony_ci bbp = &hw->bitbang; 3608c2ecf20Sopenharmony_ci bbp->master = hw->master; 3618c2ecf20Sopenharmony_ci bbp->setup_transfer = spi_ppc4xx_setupxfer; 3628c2ecf20Sopenharmony_ci bbp->txrx_bufs = spi_ppc4xx_txrx; 3638c2ecf20Sopenharmony_ci bbp->use_dma = 0; 3648c2ecf20Sopenharmony_ci bbp->master->setup = spi_ppc4xx_setup; 3658c2ecf20Sopenharmony_ci bbp->master->cleanup = spi_ppc4xx_cleanup; 3668c2ecf20Sopenharmony_ci bbp->master->bits_per_word_mask = SPI_BPW_MASK(8); 3678c2ecf20Sopenharmony_ci bbp->master->use_gpio_descriptors = true; 3688c2ecf20Sopenharmony_ci /* 3698c2ecf20Sopenharmony_ci * The SPI core will count the number of GPIO descriptors to figure 3708c2ecf20Sopenharmony_ci * out the number of chip selects available on the platform. 3718c2ecf20Sopenharmony_ci */ 3728c2ecf20Sopenharmony_ci bbp->master->num_chipselect = 0; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* the spi->mode bits understood by this driver: */ 3758c2ecf20Sopenharmony_ci bbp->master->mode_bits = 3768c2ecf20Sopenharmony_ci SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* Get the clock for the OPB */ 3798c2ecf20Sopenharmony_ci opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb"); 3808c2ecf20Sopenharmony_ci if (opbnp == NULL) { 3818c2ecf20Sopenharmony_ci dev_err(dev, "OPB: cannot find node\n"); 3828c2ecf20Sopenharmony_ci ret = -ENODEV; 3838c2ecf20Sopenharmony_ci goto free_master; 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci /* Get the clock (Hz) for the OPB */ 3868c2ecf20Sopenharmony_ci clk = of_get_property(opbnp, "clock-frequency", NULL); 3878c2ecf20Sopenharmony_ci if (clk == NULL) { 3888c2ecf20Sopenharmony_ci dev_err(dev, "OPB: no clock-frequency property set\n"); 3898c2ecf20Sopenharmony_ci of_node_put(opbnp); 3908c2ecf20Sopenharmony_ci ret = -ENODEV; 3918c2ecf20Sopenharmony_ci goto free_master; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci hw->opb_freq = *clk; 3948c2ecf20Sopenharmony_ci hw->opb_freq >>= 2; 3958c2ecf20Sopenharmony_ci of_node_put(opbnp); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci ret = of_address_to_resource(np, 0, &resource); 3988c2ecf20Sopenharmony_ci if (ret) { 3998c2ecf20Sopenharmony_ci dev_err(dev, "error while parsing device node resource\n"); 4008c2ecf20Sopenharmony_ci goto free_master; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci hw->mapbase = resource.start; 4038c2ecf20Sopenharmony_ci hw->mapsize = resource_size(&resource); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci /* Sanity check */ 4068c2ecf20Sopenharmony_ci if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) { 4078c2ecf20Sopenharmony_ci dev_err(dev, "too small to map registers\n"); 4088c2ecf20Sopenharmony_ci ret = -EINVAL; 4098c2ecf20Sopenharmony_ci goto free_master; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* Request IRQ */ 4138c2ecf20Sopenharmony_ci hw->irqnum = irq_of_parse_and_map(np, 0); 4148c2ecf20Sopenharmony_ci ret = request_irq(hw->irqnum, spi_ppc4xx_int, 4158c2ecf20Sopenharmony_ci 0, "spi_ppc4xx_of", (void *)hw); 4168c2ecf20Sopenharmony_ci if (ret) { 4178c2ecf20Sopenharmony_ci dev_err(dev, "unable to allocate interrupt\n"); 4188c2ecf20Sopenharmony_ci goto free_master; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) { 4228c2ecf20Sopenharmony_ci dev_err(dev, "resource unavailable\n"); 4238c2ecf20Sopenharmony_ci ret = -EBUSY; 4248c2ecf20Sopenharmony_ci goto request_mem_error; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci hw->regs = ioremap(hw->mapbase, sizeof(struct spi_ppc4xx_regs)); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (!hw->regs) { 4308c2ecf20Sopenharmony_ci dev_err(dev, "unable to memory map registers\n"); 4318c2ecf20Sopenharmony_ci ret = -ENXIO; 4328c2ecf20Sopenharmony_ci goto map_io_error; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci spi_ppc4xx_enable(hw); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci /* Finally register our spi controller */ 4388c2ecf20Sopenharmony_ci dev->dma_mask = 0; 4398c2ecf20Sopenharmony_ci ret = spi_bitbang_start(bbp); 4408c2ecf20Sopenharmony_ci if (ret) { 4418c2ecf20Sopenharmony_ci dev_err(dev, "failed to register SPI master\n"); 4428c2ecf20Sopenharmony_ci goto unmap_regs; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci dev_info(dev, "driver initialized\n"); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci return 0; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ciunmap_regs: 4508c2ecf20Sopenharmony_ci iounmap(hw->regs); 4518c2ecf20Sopenharmony_cimap_io_error: 4528c2ecf20Sopenharmony_ci release_mem_region(hw->mapbase, hw->mapsize); 4538c2ecf20Sopenharmony_cirequest_mem_error: 4548c2ecf20Sopenharmony_ci free_irq(hw->irqnum, hw); 4558c2ecf20Sopenharmony_cifree_master: 4568c2ecf20Sopenharmony_ci spi_master_put(master); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci dev_err(dev, "initialization failed\n"); 4598c2ecf20Sopenharmony_ci return ret; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cistatic int spi_ppc4xx_of_remove(struct platform_device *op) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci struct spi_master *master = platform_get_drvdata(op); 4658c2ecf20Sopenharmony_ci struct ppc4xx_spi *hw = spi_master_get_devdata(master); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci spi_bitbang_stop(&hw->bitbang); 4688c2ecf20Sopenharmony_ci release_mem_region(hw->mapbase, hw->mapsize); 4698c2ecf20Sopenharmony_ci free_irq(hw->irqnum, hw); 4708c2ecf20Sopenharmony_ci iounmap(hw->regs); 4718c2ecf20Sopenharmony_ci spi_master_put(master); 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic const struct of_device_id spi_ppc4xx_of_match[] = { 4768c2ecf20Sopenharmony_ci { .compatible = "ibm,ppc4xx-spi", }, 4778c2ecf20Sopenharmony_ci {}, 4788c2ecf20Sopenharmony_ci}; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic struct platform_driver spi_ppc4xx_of_driver = { 4838c2ecf20Sopenharmony_ci .probe = spi_ppc4xx_of_probe, 4848c2ecf20Sopenharmony_ci .remove = spi_ppc4xx_of_remove, 4858c2ecf20Sopenharmony_ci .driver = { 4868c2ecf20Sopenharmony_ci .name = DRIVER_NAME, 4878c2ecf20Sopenharmony_ci .of_match_table = spi_ppc4xx_of_match, 4888c2ecf20Sopenharmony_ci }, 4898c2ecf20Sopenharmony_ci}; 4908c2ecf20Sopenharmony_cimodule_platform_driver(spi_ppc4xx_of_driver); 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ciMODULE_AUTHOR("Gary Jennejohn & Stefan Roese"); 4938c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Simple PPC4xx SPI Driver"); 4948c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 495