829 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Synquacer HSSPI controller driver4//5// Copyright (c) 2015-2018 Socionext Inc.6// Copyright (c) 2018-2019 Linaro Ltd.7//8 9#include <linux/acpi.h>10#include <linux/delay.h>11#include <linux/interrupt.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/platform_device.h>16#include <linux/pm_runtime.h>17#include <linux/scatterlist.h>18#include <linux/slab.h>19#include <linux/spi/spi.h>20#include <linux/spinlock.h>21#include <linux/clk.h>22 23/* HSSPI register address definitions */24#define SYNQUACER_HSSPI_REG_MCTRL 0x0025#define SYNQUACER_HSSPI_REG_PCC0 0x0426#define SYNQUACER_HSSPI_REG_PCC(n) (SYNQUACER_HSSPI_REG_PCC0 + (n) * 4)27#define SYNQUACER_HSSPI_REG_TXF 0x1428#define SYNQUACER_HSSPI_REG_TXE 0x1829#define SYNQUACER_HSSPI_REG_TXC 0x1C30#define SYNQUACER_HSSPI_REG_RXF 0x2031#define SYNQUACER_HSSPI_REG_RXE 0x2432#define SYNQUACER_HSSPI_REG_RXC 0x2833#define SYNQUACER_HSSPI_REG_FAULTF 0x2C34#define SYNQUACER_HSSPI_REG_FAULTC 0x3035#define SYNQUACER_HSSPI_REG_DMCFG 0x3436#define SYNQUACER_HSSPI_REG_DMSTART 0x3837#define SYNQUACER_HSSPI_REG_DMBCC 0x3C38#define SYNQUACER_HSSPI_REG_DMSTATUS 0x4039#define SYNQUACER_HSSPI_REG_FIFOCFG 0x4C40#define SYNQUACER_HSSPI_REG_TX_FIFO 0x5041#define SYNQUACER_HSSPI_REG_RX_FIFO 0x9042#define SYNQUACER_HSSPI_REG_MID 0xFC43 44/* HSSPI register bit definitions */45#define SYNQUACER_HSSPI_MCTRL_MEN BIT(0)46#define SYNQUACER_HSSPI_MCTRL_COMMAND_SEQUENCE_EN BIT(1)47#define SYNQUACER_HSSPI_MCTRL_CDSS BIT(3)48#define SYNQUACER_HSSPI_MCTRL_MES BIT(4)49#define SYNQUACER_HSSPI_MCTRL_SYNCON BIT(5)50 51#define SYNQUACER_HSSPI_PCC_CPHA BIT(0)52#define SYNQUACER_HSSPI_PCC_CPOL BIT(1)53#define SYNQUACER_HSSPI_PCC_ACES BIT(2)54#define SYNQUACER_HSSPI_PCC_RTM BIT(3)55#define SYNQUACER_HSSPI_PCC_SSPOL BIT(4)56#define SYNQUACER_HSSPI_PCC_SDIR BIT(7)57#define SYNQUACER_HSSPI_PCC_SENDIAN BIT(8)58#define SYNQUACER_HSSPI_PCC_SAFESYNC BIT(16)59#define SYNQUACER_HSSPI_PCC_SS2CD_SHIFT 5U60#define SYNQUACER_HSSPI_PCC_CDRS_MASK 0x7f61#define SYNQUACER_HSSPI_PCC_CDRS_SHIFT 9U62 63#define SYNQUACER_HSSPI_TXF_FIFO_FULL BIT(0)64#define SYNQUACER_HSSPI_TXF_FIFO_EMPTY BIT(1)65#define SYNQUACER_HSSPI_TXF_SLAVE_RELEASED BIT(6)66 67#define SYNQUACER_HSSPI_TXE_FIFO_FULL BIT(0)68#define SYNQUACER_HSSPI_TXE_FIFO_EMPTY BIT(1)69#define SYNQUACER_HSSPI_TXE_SLAVE_RELEASED BIT(6)70 71#define SYNQUACER_HSSPI_RXF_FIFO_MORE_THAN_THRESHOLD BIT(5)72#define SYNQUACER_HSSPI_RXF_SLAVE_RELEASED BIT(6)73 74#define SYNQUACER_HSSPI_RXE_FIFO_MORE_THAN_THRESHOLD BIT(5)75#define SYNQUACER_HSSPI_RXE_SLAVE_RELEASED BIT(6)76 77#define SYNQUACER_HSSPI_DMCFG_SSDC BIT(1)78#define SYNQUACER_HSSPI_DMCFG_MSTARTEN BIT(2)79 80#define SYNQUACER_HSSPI_DMSTART_START BIT(0)81#define SYNQUACER_HSSPI_DMSTOP_STOP BIT(8)82#define SYNQUACER_HSSPI_DMPSEL_CS_MASK 0x383#define SYNQUACER_HSSPI_DMPSEL_CS_SHIFT 16U84#define SYNQUACER_HSSPI_DMTRP_BUS_WIDTH_SHIFT 24U85#define SYNQUACER_HSSPI_DMTRP_DATA_MASK 0x386#define SYNQUACER_HSSPI_DMTRP_DATA_SHIFT 26U87#define SYNQUACER_HSSPI_DMTRP_DATA_TXRX 088#define SYNQUACER_HSSPI_DMTRP_DATA_RX 189#define SYNQUACER_HSSPI_DMTRP_DATA_TX 290 91#define SYNQUACER_HSSPI_DMSTATUS_RX_DATA_MASK 0x1f92#define SYNQUACER_HSSPI_DMSTATUS_RX_DATA_SHIFT 8U93#define SYNQUACER_HSSPI_DMSTATUS_TX_DATA_MASK 0x1f94#define SYNQUACER_HSSPI_DMSTATUS_TX_DATA_SHIFT 16U95 96#define SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_MASK 0xf97#define SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_SHIFT 0U98#define SYNQUACER_HSSPI_FIFOCFG_TX_THRESHOLD_MASK 0xf99#define SYNQUACER_HSSPI_FIFOCFG_TX_THRESHOLD_SHIFT 4U100#define SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_MASK 0x3101#define SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_SHIFT 8U102#define SYNQUACER_HSSPI_FIFOCFG_RX_FLUSH BIT(11)103#define SYNQUACER_HSSPI_FIFOCFG_TX_FLUSH BIT(12)104 105#define SYNQUACER_HSSPI_FIFO_DEPTH 16U106#define SYNQUACER_HSSPI_FIFO_TX_THRESHOLD 4U107#define SYNQUACER_HSSPI_FIFO_RX_THRESHOLD \108 (SYNQUACER_HSSPI_FIFO_DEPTH - SYNQUACER_HSSPI_FIFO_TX_THRESHOLD)109 110#define SYNQUACER_HSSPI_TRANSFER_MODE_TX BIT(1)111#define SYNQUACER_HSSPI_TRANSFER_MODE_RX BIT(2)112#define SYNQUACER_HSSPI_TRANSFER_TMOUT_MSEC 2000U113#define SYNQUACER_HSSPI_ENABLE_TMOUT_MSEC 1000U114 115#define SYNQUACER_HSSPI_CLOCK_SRC_IHCLK 0116#define SYNQUACER_HSSPI_CLOCK_SRC_IPCLK 1117 118#define SYNQUACER_HSSPI_NUM_CHIP_SELECT 4U119#define SYNQUACER_HSSPI_IRQ_NAME_MAX 32U120 121struct synquacer_spi {122 struct device *dev;123 struct completion transfer_done;124 unsigned int cs;125 unsigned int bpw;126 unsigned int mode;127 unsigned int speed;128 bool aces, rtm;129 void *rx_buf;130 const void *tx_buf;131 struct clk *clk;132 int clk_src_type;133 void __iomem *regs;134 u32 tx_words, rx_words;135 unsigned int bus_width;136 unsigned int transfer_mode;137 char rx_irq_name[SYNQUACER_HSSPI_IRQ_NAME_MAX];138 char tx_irq_name[SYNQUACER_HSSPI_IRQ_NAME_MAX];139};140 141static int read_fifo(struct synquacer_spi *sspi)142{143 u32 len = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTATUS);144 145 len = (len >> SYNQUACER_HSSPI_DMSTATUS_RX_DATA_SHIFT) &146 SYNQUACER_HSSPI_DMSTATUS_RX_DATA_MASK;147 len = min(len, sspi->rx_words);148 149 switch (sspi->bpw) {150 case 8: {151 u8 *buf = sspi->rx_buf;152 153 ioread8_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO,154 buf, len);155 sspi->rx_buf = buf + len;156 break;157 }158 case 16: {159 u16 *buf = sspi->rx_buf;160 161 ioread16_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO,162 buf, len);163 sspi->rx_buf = buf + len;164 break;165 }166 case 24:167 /* fallthrough, should use 32-bits access */168 case 32: {169 u32 *buf = sspi->rx_buf;170 171 ioread32_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO,172 buf, len);173 sspi->rx_buf = buf + len;174 break;175 }176 default:177 return -EINVAL;178 }179 180 sspi->rx_words -= len;181 return 0;182}183 184static int write_fifo(struct synquacer_spi *sspi)185{186 u32 len = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTATUS);187 188 len = (len >> SYNQUACER_HSSPI_DMSTATUS_TX_DATA_SHIFT) &189 SYNQUACER_HSSPI_DMSTATUS_TX_DATA_MASK;190 len = min(SYNQUACER_HSSPI_FIFO_DEPTH - len,191 sspi->tx_words);192 193 switch (sspi->bpw) {194 case 8: {195 const u8 *buf = sspi->tx_buf;196 197 iowrite8_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO,198 buf, len);199 sspi->tx_buf = buf + len;200 break;201 }202 case 16: {203 const u16 *buf = sspi->tx_buf;204 205 iowrite16_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO,206 buf, len);207 sspi->tx_buf = buf + len;208 break;209 }210 case 24:211 /* fallthrough, should use 32-bits access */212 case 32: {213 const u32 *buf = sspi->tx_buf;214 215 iowrite32_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO,216 buf, len);217 sspi->tx_buf = buf + len;218 break;219 }220 default:221 return -EINVAL;222 }223 224 sspi->tx_words -= len;225 return 0;226}227 228static int synquacer_spi_config(struct spi_controller *host,229 struct spi_device *spi,230 struct spi_transfer *xfer)231{232 struct synquacer_spi *sspi = spi_controller_get_devdata(host);233 unsigned int speed, mode, bpw, cs, bus_width, transfer_mode;234 u32 rate, val, div;235 236 /* Full Duplex only on 1-bit wide bus */237 if (xfer->rx_buf && xfer->tx_buf &&238 (xfer->rx_nbits != 1 || xfer->tx_nbits != 1)) {239 dev_err(sspi->dev,240 "RX and TX bus widths must be 1-bit for Full-Duplex!\n");241 return -EINVAL;242 }243 244 if (xfer->tx_buf) {245 bus_width = xfer->tx_nbits;246 transfer_mode = SYNQUACER_HSSPI_TRANSFER_MODE_TX;247 } else {248 bus_width = xfer->rx_nbits;249 transfer_mode = SYNQUACER_HSSPI_TRANSFER_MODE_RX;250 }251 252 mode = spi->mode;253 cs = spi_get_chipselect(spi, 0);254 speed = xfer->speed_hz;255 bpw = xfer->bits_per_word;256 257 /* return if nothing to change */258 if (speed == sspi->speed &&259 bus_width == sspi->bus_width && bpw == sspi->bpw &&260 mode == sspi->mode && cs == sspi->cs &&261 transfer_mode == sspi->transfer_mode) {262 return 0;263 }264 265 sspi->transfer_mode = transfer_mode;266 rate = host->max_speed_hz;267 268 div = DIV_ROUND_UP(rate, speed);269 if (div > 254) {270 dev_err(sspi->dev, "Requested rate too low (%u)\n",271 sspi->speed);272 return -EINVAL;273 }274 275 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_PCC(cs));276 val &= ~SYNQUACER_HSSPI_PCC_SAFESYNC;277 if (bpw == 8 && (mode & (SPI_TX_DUAL | SPI_RX_DUAL)) && div < 3)278 val |= SYNQUACER_HSSPI_PCC_SAFESYNC;279 if (bpw == 8 && (mode & (SPI_TX_QUAD | SPI_RX_QUAD)) && div < 6)280 val |= SYNQUACER_HSSPI_PCC_SAFESYNC;281 if (bpw == 16 && (mode & (SPI_TX_QUAD | SPI_RX_QUAD)) && div < 3)282 val |= SYNQUACER_HSSPI_PCC_SAFESYNC;283 284 if (mode & SPI_CPHA)285 val |= SYNQUACER_HSSPI_PCC_CPHA;286 else287 val &= ~SYNQUACER_HSSPI_PCC_CPHA;288 289 if (mode & SPI_CPOL)290 val |= SYNQUACER_HSSPI_PCC_CPOL;291 else292 val &= ~SYNQUACER_HSSPI_PCC_CPOL;293 294 if (mode & SPI_CS_HIGH)295 val |= SYNQUACER_HSSPI_PCC_SSPOL;296 else297 val &= ~SYNQUACER_HSSPI_PCC_SSPOL;298 299 if (mode & SPI_LSB_FIRST)300 val |= SYNQUACER_HSSPI_PCC_SDIR;301 else302 val &= ~SYNQUACER_HSSPI_PCC_SDIR;303 304 if (sspi->aces)305 val |= SYNQUACER_HSSPI_PCC_ACES;306 else307 val &= ~SYNQUACER_HSSPI_PCC_ACES;308 309 if (sspi->rtm)310 val |= SYNQUACER_HSSPI_PCC_RTM;311 else312 val &= ~SYNQUACER_HSSPI_PCC_RTM;313 314 val |= (3 << SYNQUACER_HSSPI_PCC_SS2CD_SHIFT);315 val |= SYNQUACER_HSSPI_PCC_SENDIAN;316 317 val &= ~(SYNQUACER_HSSPI_PCC_CDRS_MASK <<318 SYNQUACER_HSSPI_PCC_CDRS_SHIFT);319 val |= ((div >> 1) << SYNQUACER_HSSPI_PCC_CDRS_SHIFT);320 321 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_PCC(cs));322 323 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);324 val &= ~(SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_MASK <<325 SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_SHIFT);326 val |= ((bpw / 8 - 1) << SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_SHIFT);327 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);328 329 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);330 val &= ~(SYNQUACER_HSSPI_DMTRP_DATA_MASK <<331 SYNQUACER_HSSPI_DMTRP_DATA_SHIFT);332 333 if (xfer->rx_buf)334 val |= (SYNQUACER_HSSPI_DMTRP_DATA_RX <<335 SYNQUACER_HSSPI_DMTRP_DATA_SHIFT);336 else337 val |= (SYNQUACER_HSSPI_DMTRP_DATA_TX <<338 SYNQUACER_HSSPI_DMTRP_DATA_SHIFT);339 340 val &= ~(3 << SYNQUACER_HSSPI_DMTRP_BUS_WIDTH_SHIFT);341 val |= ((bus_width >> 1) << SYNQUACER_HSSPI_DMTRP_BUS_WIDTH_SHIFT);342 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);343 344 sspi->bpw = bpw;345 sspi->mode = mode;346 sspi->speed = speed;347 sspi->cs = spi_get_chipselect(spi, 0);348 sspi->bus_width = bus_width;349 350 return 0;351}352 353static int synquacer_spi_transfer_one(struct spi_controller *host,354 struct spi_device *spi,355 struct spi_transfer *xfer)356{357 struct synquacer_spi *sspi = spi_controller_get_devdata(host);358 int ret;359 int status = 0;360 u32 words;361 u8 bpw;362 u32 val;363 364 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);365 val &= ~SYNQUACER_HSSPI_DMSTOP_STOP;366 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);367 368 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);369 val |= SYNQUACER_HSSPI_FIFOCFG_RX_FLUSH;370 val |= SYNQUACER_HSSPI_FIFOCFG_TX_FLUSH;371 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);372 373 /*374 * See if we can transfer 4-bytes as 1 word375 * to maximize the FIFO buffer efficiency.376 */377 bpw = xfer->bits_per_word;378 if (bpw == 8 && !(xfer->len % 4) && !(spi->mode & SPI_LSB_FIRST))379 xfer->bits_per_word = 32;380 381 ret = synquacer_spi_config(host, spi, xfer);382 383 /* restore */384 xfer->bits_per_word = bpw;385 386 if (ret)387 return ret;388 389 reinit_completion(&sspi->transfer_done);390 391 sspi->tx_buf = xfer->tx_buf;392 sspi->rx_buf = xfer->rx_buf;393 394 switch (sspi->bpw) {395 case 8:396 words = xfer->len;397 break;398 case 16:399 words = xfer->len / 2;400 break;401 case 24:402 /* fallthrough, should use 32-bits access */403 case 32:404 words = xfer->len / 4;405 break;406 default:407 dev_err(sspi->dev, "unsupported bpw: %d\n", sspi->bpw);408 return -EINVAL;409 }410 411 if (xfer->tx_buf)412 sspi->tx_words = words;413 else414 sspi->tx_words = 0;415 416 if (xfer->rx_buf)417 sspi->rx_words = words;418 else419 sspi->rx_words = 0;420 421 if (xfer->tx_buf) {422 status = write_fifo(sspi);423 if (status < 0) {424 dev_err(sspi->dev, "failed write_fifo. status: 0x%x\n",425 status);426 return status;427 }428 }429 430 if (xfer->rx_buf) {431 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);432 val &= ~(SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_MASK <<433 SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_SHIFT);434 val |= ((sspi->rx_words > SYNQUACER_HSSPI_FIFO_DEPTH ?435 SYNQUACER_HSSPI_FIFO_RX_THRESHOLD : sspi->rx_words) <<436 SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_SHIFT);437 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);438 }439 440 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_TXC);441 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_RXC);442 443 /* Trigger */444 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);445 val |= SYNQUACER_HSSPI_DMSTART_START;446 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);447 448 if (xfer->tx_buf) {449 val = SYNQUACER_HSSPI_TXE_FIFO_EMPTY;450 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_TXE);451 status = wait_for_completion_timeout(&sspi->transfer_done,452 msecs_to_jiffies(SYNQUACER_HSSPI_TRANSFER_TMOUT_MSEC));453 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE);454 }455 456 if (xfer->rx_buf) {457 u32 buf[SYNQUACER_HSSPI_FIFO_DEPTH];458 459 val = SYNQUACER_HSSPI_RXE_FIFO_MORE_THAN_THRESHOLD |460 SYNQUACER_HSSPI_RXE_SLAVE_RELEASED;461 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_RXE);462 status = wait_for_completion_timeout(&sspi->transfer_done,463 msecs_to_jiffies(SYNQUACER_HSSPI_TRANSFER_TMOUT_MSEC));464 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE);465 466 /* stop RX and clean RXFIFO */467 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);468 val |= SYNQUACER_HSSPI_DMSTOP_STOP;469 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);470 sspi->rx_buf = buf;471 sspi->rx_words = SYNQUACER_HSSPI_FIFO_DEPTH;472 read_fifo(sspi);473 }474 475 if (status == 0) {476 dev_err(sspi->dev, "failed to transfer. Timeout.\n");477 return -ETIMEDOUT;478 }479 480 return 0;481}482 483static void synquacer_spi_set_cs(struct spi_device *spi, bool enable)484{485 struct synquacer_spi *sspi = spi_controller_get_devdata(spi->controller);486 u32 val;487 488 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);489 val &= ~(SYNQUACER_HSSPI_DMPSEL_CS_MASK <<490 SYNQUACER_HSSPI_DMPSEL_CS_SHIFT);491 val |= spi_get_chipselect(spi, 0) << SYNQUACER_HSSPI_DMPSEL_CS_SHIFT;492 493 if (!enable)494 val |= SYNQUACER_HSSPI_DMSTOP_STOP;495 496 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);497}498 499static int synquacer_spi_wait_status_update(struct synquacer_spi *sspi,500 bool enable)501{502 u32 val;503 unsigned long timeout = jiffies +504 msecs_to_jiffies(SYNQUACER_HSSPI_ENABLE_TMOUT_MSEC);505 506 /* wait MES(Module Enable Status) is updated */507 do {508 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_MCTRL) &509 SYNQUACER_HSSPI_MCTRL_MES;510 if (enable && val)511 return 0;512 if (!enable && !val)513 return 0;514 } while (time_before(jiffies, timeout));515 516 dev_err(sspi->dev, "timeout occurs in updating Module Enable Status\n");517 return -EBUSY;518}519 520static int synquacer_spi_enable(struct spi_controller *host)521{522 u32 val;523 int status;524 struct synquacer_spi *sspi = spi_controller_get_devdata(host);525 526 /* Disable module */527 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_MCTRL);528 status = synquacer_spi_wait_status_update(sspi, false);529 if (status < 0)530 return status;531 532 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE);533 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE);534 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_TXC);535 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_RXC);536 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_FAULTC);537 538 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMCFG);539 val &= ~SYNQUACER_HSSPI_DMCFG_SSDC;540 val &= ~SYNQUACER_HSSPI_DMCFG_MSTARTEN;541 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMCFG);542 543 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_MCTRL);544 if (sspi->clk_src_type == SYNQUACER_HSSPI_CLOCK_SRC_IPCLK)545 val |= SYNQUACER_HSSPI_MCTRL_CDSS;546 else547 val &= ~SYNQUACER_HSSPI_MCTRL_CDSS;548 549 val &= ~SYNQUACER_HSSPI_MCTRL_COMMAND_SEQUENCE_EN;550 val |= SYNQUACER_HSSPI_MCTRL_MEN;551 val |= SYNQUACER_HSSPI_MCTRL_SYNCON;552 553 /* Enable module */554 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_MCTRL);555 status = synquacer_spi_wait_status_update(sspi, true);556 if (status < 0)557 return status;558 559 return 0;560}561 562static irqreturn_t sq_spi_rx_handler(int irq, void *priv)563{564 uint32_t val;565 struct synquacer_spi *sspi = priv;566 567 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_RXF);568 if ((val & SYNQUACER_HSSPI_RXF_SLAVE_RELEASED) ||569 (val & SYNQUACER_HSSPI_RXF_FIFO_MORE_THAN_THRESHOLD)) {570 read_fifo(sspi);571 572 if (sspi->rx_words == 0) {573 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE);574 complete(&sspi->transfer_done);575 }576 return IRQ_HANDLED;577 }578 579 return IRQ_NONE;580}581 582static irqreturn_t sq_spi_tx_handler(int irq, void *priv)583{584 uint32_t val;585 struct synquacer_spi *sspi = priv;586 587 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_TXF);588 if (val & SYNQUACER_HSSPI_TXF_FIFO_EMPTY) {589 if (sspi->tx_words == 0) {590 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE);591 complete(&sspi->transfer_done);592 } else {593 write_fifo(sspi);594 }595 return IRQ_HANDLED;596 }597 598 return IRQ_NONE;599}600 601static int synquacer_spi_probe(struct platform_device *pdev)602{603 struct device_node *np = pdev->dev.of_node;604 struct spi_controller *host;605 struct synquacer_spi *sspi;606 int ret;607 int rx_irq, tx_irq;608 609 host = spi_alloc_host(&pdev->dev, sizeof(*sspi));610 if (!host)611 return -ENOMEM;612 613 platform_set_drvdata(pdev, host);614 615 sspi = spi_controller_get_devdata(host);616 sspi->dev = &pdev->dev;617 618 init_completion(&sspi->transfer_done);619 620 sspi->regs = devm_platform_ioremap_resource(pdev, 0);621 if (IS_ERR(sspi->regs)) {622 ret = PTR_ERR(sspi->regs);623 goto put_spi;624 }625 626 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK; /* Default */627 device_property_read_u32(&pdev->dev, "socionext,ihclk-rate",628 &host->max_speed_hz); /* for ACPI */629 630 if (dev_of_node(&pdev->dev)) {631 if (device_property_match_string(&pdev->dev,632 "clock-names", "iHCLK") >= 0) {633 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK;634 sspi->clk = devm_clk_get(sspi->dev, "iHCLK");635 } else if (device_property_match_string(&pdev->dev,636 "clock-names", "iPCLK") >= 0) {637 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IPCLK;638 sspi->clk = devm_clk_get(sspi->dev, "iPCLK");639 } else {640 dev_err(&pdev->dev, "specified wrong clock source\n");641 ret = -EINVAL;642 goto put_spi;643 }644 645 if (IS_ERR(sspi->clk)) {646 ret = dev_err_probe(&pdev->dev, PTR_ERR(sspi->clk),647 "clock not found\n");648 goto put_spi;649 }650 651 ret = clk_prepare_enable(sspi->clk);652 if (ret) {653 dev_err(&pdev->dev, "failed to enable clock (%d)\n",654 ret);655 goto put_spi;656 }657 658 host->max_speed_hz = clk_get_rate(sspi->clk);659 }660 661 if (!host->max_speed_hz) {662 dev_err(&pdev->dev, "missing clock source\n");663 ret = -EINVAL;664 goto disable_clk;665 }666 host->min_speed_hz = host->max_speed_hz / 254;667 668 sspi->aces = device_property_read_bool(&pdev->dev,669 "socionext,set-aces");670 sspi->rtm = device_property_read_bool(&pdev->dev, "socionext,use-rtm");671 672 host->num_chipselect = SYNQUACER_HSSPI_NUM_CHIP_SELECT;673 674 rx_irq = platform_get_irq(pdev, 0);675 if (rx_irq <= 0) {676 ret = rx_irq;677 goto disable_clk;678 }679 snprintf(sspi->rx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-rx",680 dev_name(&pdev->dev));681 ret = devm_request_irq(&pdev->dev, rx_irq, sq_spi_rx_handler,682 0, sspi->rx_irq_name, sspi);683 if (ret) {684 dev_err(&pdev->dev, "request rx_irq failed (%d)\n", ret);685 goto disable_clk;686 }687 688 tx_irq = platform_get_irq(pdev, 1);689 if (tx_irq <= 0) {690 ret = tx_irq;691 goto disable_clk;692 }693 snprintf(sspi->tx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-tx",694 dev_name(&pdev->dev));695 ret = devm_request_irq(&pdev->dev, tx_irq, sq_spi_tx_handler,696 0, sspi->tx_irq_name, sspi);697 if (ret) {698 dev_err(&pdev->dev, "request tx_irq failed (%d)\n", ret);699 goto disable_clk;700 }701 702 host->dev.of_node = np;703 host->dev.fwnode = pdev->dev.fwnode;704 host->auto_runtime_pm = true;705 host->bus_num = pdev->id;706 707 host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL |708 SPI_TX_QUAD | SPI_RX_QUAD;709 host->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) |710 SPI_BPW_MASK(16) | SPI_BPW_MASK(8);711 712 host->set_cs = synquacer_spi_set_cs;713 host->transfer_one = synquacer_spi_transfer_one;714 715 ret = synquacer_spi_enable(host);716 if (ret)717 goto disable_clk;718 719 pm_runtime_set_active(sspi->dev);720 pm_runtime_enable(sspi->dev);721 722 ret = devm_spi_register_controller(sspi->dev, host);723 if (ret)724 goto disable_pm;725 726 return 0;727 728disable_pm:729 pm_runtime_disable(sspi->dev);730disable_clk:731 clk_disable_unprepare(sspi->clk);732put_spi:733 spi_controller_put(host);734 735 return ret;736}737 738static void synquacer_spi_remove(struct platform_device *pdev)739{740 struct spi_controller *host = platform_get_drvdata(pdev);741 struct synquacer_spi *sspi = spi_controller_get_devdata(host);742 743 pm_runtime_disable(sspi->dev);744 745 clk_disable_unprepare(sspi->clk);746}747 748static int __maybe_unused synquacer_spi_suspend(struct device *dev)749{750 struct spi_controller *host = dev_get_drvdata(dev);751 struct synquacer_spi *sspi = spi_controller_get_devdata(host);752 int ret;753 754 ret = spi_controller_suspend(host);755 if (ret)756 return ret;757 758 if (!pm_runtime_suspended(dev))759 clk_disable_unprepare(sspi->clk);760 761 return ret;762}763 764static int __maybe_unused synquacer_spi_resume(struct device *dev)765{766 struct spi_controller *host = dev_get_drvdata(dev);767 struct synquacer_spi *sspi = spi_controller_get_devdata(host);768 int ret;769 770 if (!pm_runtime_suspended(dev)) {771 /* Ensure reconfigure during next xfer */772 sspi->speed = 0;773 774 ret = clk_prepare_enable(sspi->clk);775 if (ret < 0) {776 dev_err(dev, "failed to enable clk (%d)\n",777 ret);778 return ret;779 }780 781 ret = synquacer_spi_enable(host);782 if (ret) {783 clk_disable_unprepare(sspi->clk);784 dev_err(dev, "failed to enable spi (%d)\n", ret);785 return ret;786 }787 }788 789 ret = spi_controller_resume(host);790 if (ret < 0)791 clk_disable_unprepare(sspi->clk);792 793 return ret;794}795 796static SIMPLE_DEV_PM_OPS(synquacer_spi_pm_ops, synquacer_spi_suspend,797 synquacer_spi_resume);798 799static const struct of_device_id synquacer_spi_of_match[] = {800 {.compatible = "socionext,synquacer-spi"},801 {}802};803MODULE_DEVICE_TABLE(of, synquacer_spi_of_match);804 805#ifdef CONFIG_ACPI806static const struct acpi_device_id synquacer_hsspi_acpi_ids[] = {807 { "SCX0004" },808 { /* sentinel */ }809};810MODULE_DEVICE_TABLE(acpi, synquacer_hsspi_acpi_ids);811#endif812 813static struct platform_driver synquacer_spi_driver = {814 .driver = {815 .name = "synquacer-spi",816 .pm = &synquacer_spi_pm_ops,817 .of_match_table = synquacer_spi_of_match,818 .acpi_match_table = ACPI_PTR(synquacer_hsspi_acpi_ids),819 },820 .probe = synquacer_spi_probe,821 .remove_new = synquacer_spi_remove,822};823module_platform_driver(synquacer_spi_driver);824 825MODULE_DESCRIPTION("Socionext Synquacer HS-SPI controller driver");826MODULE_AUTHOR("Masahisa Kojima <masahisa.kojima@linaro.org>");827MODULE_AUTHOR("Jassi Brar <jaswinder.singh@linaro.org>");828MODULE_LICENSE("GPL v2");829