spi-jcore.c (5499B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * J-Core SPI controller driver 4 * 5 * Copyright (C) 2012-2016 Smart Energy Instruments, Inc. 6 * 7 * Current version by Rich Felker 8 * Based loosely on initial version by Oleksandr G Zhadan 9 * 10 */ 11#include <linux/init.h> 12#include <linux/interrupt.h> 13#include <linux/errno.h> 14#include <linux/module.h> 15#include <linux/platform_device.h> 16#include <linux/spi/spi.h> 17#include <linux/clk.h> 18#include <linux/err.h> 19#include <linux/io.h> 20#include <linux/of.h> 21#include <linux/delay.h> 22 23#define DRV_NAME "jcore_spi" 24 25#define CTRL_REG 0x0 26#define DATA_REG 0x4 27 28#define JCORE_SPI_CTRL_XMIT 0x02 29#define JCORE_SPI_STAT_BUSY 0x02 30#define JCORE_SPI_CTRL_LOOP 0x08 31#define JCORE_SPI_CTRL_CS_BITS 0x15 32 33#define JCORE_SPI_WAIT_RDY_MAX_LOOP 2000000 34 35struct jcore_spi { 36 struct spi_master *master; 37 void __iomem *base; 38 unsigned int cs_reg; 39 unsigned int speed_reg; 40 unsigned int speed_hz; 41 unsigned int clock_freq; 42}; 43 44static int jcore_spi_wait(void __iomem *ctrl_reg) 45{ 46 unsigned timeout = JCORE_SPI_WAIT_RDY_MAX_LOOP; 47 48 do { 49 if (!(readl(ctrl_reg) & JCORE_SPI_STAT_BUSY)) 50 return 0; 51 cpu_relax(); 52 } while (--timeout); 53 54 return -EBUSY; 55} 56 57static void jcore_spi_program(struct jcore_spi *hw) 58{ 59 void __iomem *ctrl_reg = hw->base + CTRL_REG; 60 61 if (jcore_spi_wait(ctrl_reg)) 62 dev_err(hw->master->dev.parent, 63 "timeout waiting to program ctrl reg.\n"); 64 65 writel(hw->cs_reg | hw->speed_reg, ctrl_reg); 66} 67 68static void jcore_spi_chipsel(struct spi_device *spi, bool value) 69{ 70 struct jcore_spi *hw = spi_master_get_devdata(spi->master); 71 u32 csbit = 1U << (2 * spi->chip_select); 72 73 dev_dbg(hw->master->dev.parent, "chipselect %d\n", spi->chip_select); 74 75 if (value) 76 hw->cs_reg |= csbit; 77 else 78 hw->cs_reg &= ~csbit; 79 80 jcore_spi_program(hw); 81} 82 83static void jcore_spi_baudrate(struct jcore_spi *hw, int speed) 84{ 85 if (speed == hw->speed_hz) 86 return; 87 hw->speed_hz = speed; 88 if (speed >= hw->clock_freq / 2) 89 hw->speed_reg = 0; 90 else 91 hw->speed_reg = ((hw->clock_freq / 2 / speed) - 1) << 27; 92 jcore_spi_program(hw); 93 dev_dbg(hw->master->dev.parent, "speed=%d reg=0x%x\n", 94 speed, hw->speed_reg); 95} 96 97static int jcore_spi_txrx(struct spi_master *master, struct spi_device *spi, 98 struct spi_transfer *t) 99{ 100 struct jcore_spi *hw = spi_master_get_devdata(master); 101 102 void __iomem *ctrl_reg = hw->base + CTRL_REG; 103 void __iomem *data_reg = hw->base + DATA_REG; 104 u32 xmit; 105 106 /* data buffers */ 107 const unsigned char *tx; 108 unsigned char *rx; 109 unsigned int len; 110 unsigned int count; 111 112 jcore_spi_baudrate(hw, t->speed_hz); 113 114 xmit = hw->cs_reg | hw->speed_reg | JCORE_SPI_CTRL_XMIT; 115 tx = t->tx_buf; 116 rx = t->rx_buf; 117 len = t->len; 118 119 for (count = 0; count < len; count++) { 120 if (jcore_spi_wait(ctrl_reg)) 121 break; 122 123 writel(tx ? *tx++ : 0, data_reg); 124 writel(xmit, ctrl_reg); 125 126 if (jcore_spi_wait(ctrl_reg)) 127 break; 128 129 if (rx) 130 *rx++ = readl(data_reg); 131 } 132 133 spi_finalize_current_transfer(master); 134 135 if (count < len) 136 return -EREMOTEIO; 137 138 return 0; 139} 140 141static int jcore_spi_probe(struct platform_device *pdev) 142{ 143 struct device_node *node = pdev->dev.of_node; 144 struct jcore_spi *hw; 145 struct spi_master *master; 146 struct resource *res; 147 u32 clock_freq; 148 struct clk *clk; 149 int err = -ENODEV; 150 151 master = spi_alloc_master(&pdev->dev, sizeof(struct jcore_spi)); 152 if (!master) 153 return err; 154 155 /* Setup the master state. */ 156 master->num_chipselect = 3; 157 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 158 master->transfer_one = jcore_spi_txrx; 159 master->set_cs = jcore_spi_chipsel; 160 master->dev.of_node = node; 161 master->bus_num = pdev->id; 162 163 hw = spi_master_get_devdata(master); 164 hw->master = master; 165 platform_set_drvdata(pdev, hw); 166 167 /* Find and map our resources */ 168 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 169 if (!res) 170 goto exit_busy; 171 if (!devm_request_mem_region(&pdev->dev, res->start, 172 resource_size(res), pdev->name)) 173 goto exit_busy; 174 hw->base = devm_ioremap(&pdev->dev, res->start, 175 resource_size(res)); 176 if (!hw->base) 177 goto exit_busy; 178 179 /* 180 * The SPI clock rate controlled via a configurable clock divider 181 * which is applied to the reference clock. A 50 MHz reference is 182 * most suitable for obtaining standard SPI clock rates, but some 183 * designs may have a different reference clock, and the DT must 184 * make the driver aware so that it can properly program the 185 * requested rate. If the clock is omitted, 50 MHz is assumed. 186 */ 187 clock_freq = 50000000; 188 clk = devm_clk_get(&pdev->dev, "ref_clk"); 189 if (!IS_ERR(clk)) { 190 if (clk_prepare_enable(clk) == 0) { 191 clock_freq = clk_get_rate(clk); 192 clk_disable_unprepare(clk); 193 } else 194 dev_warn(&pdev->dev, "could not enable ref_clk\n"); 195 } 196 hw->clock_freq = clock_freq; 197 198 /* Initialize all CS bits to high. */ 199 hw->cs_reg = JCORE_SPI_CTRL_CS_BITS; 200 jcore_spi_baudrate(hw, 400000); 201 202 /* Register our spi controller */ 203 err = devm_spi_register_master(&pdev->dev, master); 204 if (err) 205 goto exit; 206 207 return 0; 208 209exit_busy: 210 err = -EBUSY; 211exit: 212 spi_master_put(master); 213 return err; 214} 215 216static const struct of_device_id jcore_spi_of_match[] = { 217 { .compatible = "jcore,spi2" }, 218 {}, 219}; 220MODULE_DEVICE_TABLE(of, jcore_spi_of_match); 221 222static struct platform_driver jcore_spi_driver = { 223 .probe = jcore_spi_probe, 224 .driver = { 225 .name = DRV_NAME, 226 .of_match_table = jcore_spi_of_match, 227 }, 228}; 229 230module_platform_driver(jcore_spi_driver); 231 232MODULE_DESCRIPTION("J-Core SPI driver"); 233MODULE_AUTHOR("Rich Felker <dalias@libc.org>"); 234MODULE_LICENSE("GPL"); 235MODULE_ALIAS("platform:" DRV_NAME);