0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/acpi.h>
0010 #include <linux/delay.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/io.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/pm_runtime.h>
0017 #include <linux/scatterlist.h>
0018 #include <linux/slab.h>
0019 #include <linux/spi/spi.h>
0020 #include <linux/spinlock.h>
0021 #include <linux/clk.h>
0022
0023
0024 #define SYNQUACER_HSSPI_REG_MCTRL 0x00
0025 #define SYNQUACER_HSSPI_REG_PCC0 0x04
0026 #define SYNQUACER_HSSPI_REG_PCC(n) (SYNQUACER_HSSPI_REG_PCC0 + (n) * 4)
0027 #define SYNQUACER_HSSPI_REG_TXF 0x14
0028 #define SYNQUACER_HSSPI_REG_TXE 0x18
0029 #define SYNQUACER_HSSPI_REG_TXC 0x1C
0030 #define SYNQUACER_HSSPI_REG_RXF 0x20
0031 #define SYNQUACER_HSSPI_REG_RXE 0x24
0032 #define SYNQUACER_HSSPI_REG_RXC 0x28
0033 #define SYNQUACER_HSSPI_REG_FAULTF 0x2C
0034 #define SYNQUACER_HSSPI_REG_FAULTC 0x30
0035 #define SYNQUACER_HSSPI_REG_DMCFG 0x34
0036 #define SYNQUACER_HSSPI_REG_DMSTART 0x38
0037 #define SYNQUACER_HSSPI_REG_DMBCC 0x3C
0038 #define SYNQUACER_HSSPI_REG_DMSTATUS 0x40
0039 #define SYNQUACER_HSSPI_REG_FIFOCFG 0x4C
0040 #define SYNQUACER_HSSPI_REG_TX_FIFO 0x50
0041 #define SYNQUACER_HSSPI_REG_RX_FIFO 0x90
0042 #define SYNQUACER_HSSPI_REG_MID 0xFC
0043
0044
0045 #define SYNQUACER_HSSPI_MCTRL_MEN BIT(0)
0046 #define SYNQUACER_HSSPI_MCTRL_COMMAND_SEQUENCE_EN BIT(1)
0047 #define SYNQUACER_HSSPI_MCTRL_CDSS BIT(3)
0048 #define SYNQUACER_HSSPI_MCTRL_MES BIT(4)
0049 #define SYNQUACER_HSSPI_MCTRL_SYNCON BIT(5)
0050
0051 #define SYNQUACER_HSSPI_PCC_CPHA BIT(0)
0052 #define SYNQUACER_HSSPI_PCC_CPOL BIT(1)
0053 #define SYNQUACER_HSSPI_PCC_ACES BIT(2)
0054 #define SYNQUACER_HSSPI_PCC_RTM BIT(3)
0055 #define SYNQUACER_HSSPI_PCC_SSPOL BIT(4)
0056 #define SYNQUACER_HSSPI_PCC_SDIR BIT(7)
0057 #define SYNQUACER_HSSPI_PCC_SENDIAN BIT(8)
0058 #define SYNQUACER_HSSPI_PCC_SAFESYNC BIT(16)
0059 #define SYNQUACER_HSSPI_PCC_SS2CD_SHIFT 5U
0060 #define SYNQUACER_HSSPI_PCC_CDRS_MASK 0x7f
0061 #define SYNQUACER_HSSPI_PCC_CDRS_SHIFT 9U
0062
0063 #define SYNQUACER_HSSPI_TXF_FIFO_FULL BIT(0)
0064 #define SYNQUACER_HSSPI_TXF_FIFO_EMPTY BIT(1)
0065 #define SYNQUACER_HSSPI_TXF_SLAVE_RELEASED BIT(6)
0066
0067 #define SYNQUACER_HSSPI_TXE_FIFO_FULL BIT(0)
0068 #define SYNQUACER_HSSPI_TXE_FIFO_EMPTY BIT(1)
0069 #define SYNQUACER_HSSPI_TXE_SLAVE_RELEASED BIT(6)
0070
0071 #define SYNQUACER_HSSPI_RXF_FIFO_MORE_THAN_THRESHOLD BIT(5)
0072 #define SYNQUACER_HSSPI_RXF_SLAVE_RELEASED BIT(6)
0073
0074 #define SYNQUACER_HSSPI_RXE_FIFO_MORE_THAN_THRESHOLD BIT(5)
0075 #define SYNQUACER_HSSPI_RXE_SLAVE_RELEASED BIT(6)
0076
0077 #define SYNQUACER_HSSPI_DMCFG_SSDC BIT(1)
0078 #define SYNQUACER_HSSPI_DMCFG_MSTARTEN BIT(2)
0079
0080 #define SYNQUACER_HSSPI_DMSTART_START BIT(0)
0081 #define SYNQUACER_HSSPI_DMSTOP_STOP BIT(8)
0082 #define SYNQUACER_HSSPI_DMPSEL_CS_MASK 0x3
0083 #define SYNQUACER_HSSPI_DMPSEL_CS_SHIFT 16U
0084 #define SYNQUACER_HSSPI_DMTRP_BUS_WIDTH_SHIFT 24U
0085 #define SYNQUACER_HSSPI_DMTRP_DATA_MASK 0x3
0086 #define SYNQUACER_HSSPI_DMTRP_DATA_SHIFT 26U
0087 #define SYNQUACER_HSSPI_DMTRP_DATA_TXRX 0
0088 #define SYNQUACER_HSSPI_DMTRP_DATA_RX 1
0089 #define SYNQUACER_HSSPI_DMTRP_DATA_TX 2
0090
0091 #define SYNQUACER_HSSPI_DMSTATUS_RX_DATA_MASK 0x1f
0092 #define SYNQUACER_HSSPI_DMSTATUS_RX_DATA_SHIFT 8U
0093 #define SYNQUACER_HSSPI_DMSTATUS_TX_DATA_MASK 0x1f
0094 #define SYNQUACER_HSSPI_DMSTATUS_TX_DATA_SHIFT 16U
0095
0096 #define SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_MASK 0xf
0097 #define SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_SHIFT 0U
0098 #define SYNQUACER_HSSPI_FIFOCFG_TX_THRESHOLD_MASK 0xf
0099 #define SYNQUACER_HSSPI_FIFOCFG_TX_THRESHOLD_SHIFT 4U
0100 #define SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_MASK 0x3
0101 #define SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_SHIFT 8U
0102 #define SYNQUACER_HSSPI_FIFOCFG_RX_FLUSH BIT(11)
0103 #define SYNQUACER_HSSPI_FIFOCFG_TX_FLUSH BIT(12)
0104
0105 #define SYNQUACER_HSSPI_FIFO_DEPTH 16U
0106 #define SYNQUACER_HSSPI_FIFO_TX_THRESHOLD 4U
0107 #define SYNQUACER_HSSPI_FIFO_RX_THRESHOLD \
0108 (SYNQUACER_HSSPI_FIFO_DEPTH - SYNQUACER_HSSPI_FIFO_TX_THRESHOLD)
0109
0110 #define SYNQUACER_HSSPI_TRANSFER_MODE_TX BIT(1)
0111 #define SYNQUACER_HSSPI_TRANSFER_MODE_RX BIT(2)
0112 #define SYNQUACER_HSSPI_TRANSFER_TMOUT_MSEC 2000U
0113 #define SYNQUACER_HSSPI_ENABLE_TMOUT_MSEC 1000U
0114
0115 #define SYNQUACER_HSSPI_CLOCK_SRC_IHCLK 0
0116 #define SYNQUACER_HSSPI_CLOCK_SRC_IPCLK 1
0117
0118 #define SYNQUACER_HSSPI_NUM_CHIP_SELECT 4U
0119 #define SYNQUACER_HSSPI_IRQ_NAME_MAX 32U
0120
0121 struct synquacer_spi {
0122 struct device *dev;
0123 struct completion transfer_done;
0124 unsigned int cs;
0125 unsigned int bpw;
0126 unsigned int mode;
0127 unsigned int speed;
0128 bool aces, rtm;
0129 void *rx_buf;
0130 const void *tx_buf;
0131 struct clk *clk;
0132 int clk_src_type;
0133 void __iomem *regs;
0134 u32 tx_words, rx_words;
0135 unsigned int bus_width;
0136 unsigned int transfer_mode;
0137 char rx_irq_name[SYNQUACER_HSSPI_IRQ_NAME_MAX];
0138 char tx_irq_name[SYNQUACER_HSSPI_IRQ_NAME_MAX];
0139 };
0140
0141 static int read_fifo(struct synquacer_spi *sspi)
0142 {
0143 u32 len = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTATUS);
0144
0145 len = (len >> SYNQUACER_HSSPI_DMSTATUS_RX_DATA_SHIFT) &
0146 SYNQUACER_HSSPI_DMSTATUS_RX_DATA_MASK;
0147 len = min(len, sspi->rx_words);
0148
0149 switch (sspi->bpw) {
0150 case 8: {
0151 u8 *buf = sspi->rx_buf;
0152
0153 ioread8_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO,
0154 buf, len);
0155 sspi->rx_buf = buf + len;
0156 break;
0157 }
0158 case 16: {
0159 u16 *buf = sspi->rx_buf;
0160
0161 ioread16_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO,
0162 buf, len);
0163 sspi->rx_buf = buf + len;
0164 break;
0165 }
0166 case 24:
0167
0168 case 32: {
0169 u32 *buf = sspi->rx_buf;
0170
0171 ioread32_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO,
0172 buf, len);
0173 sspi->rx_buf = buf + len;
0174 break;
0175 }
0176 default:
0177 return -EINVAL;
0178 }
0179
0180 sspi->rx_words -= len;
0181 return 0;
0182 }
0183
0184 static int write_fifo(struct synquacer_spi *sspi)
0185 {
0186 u32 len = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTATUS);
0187
0188 len = (len >> SYNQUACER_HSSPI_DMSTATUS_TX_DATA_SHIFT) &
0189 SYNQUACER_HSSPI_DMSTATUS_TX_DATA_MASK;
0190 len = min(SYNQUACER_HSSPI_FIFO_DEPTH - len,
0191 sspi->tx_words);
0192
0193 switch (sspi->bpw) {
0194 case 8: {
0195 const u8 *buf = sspi->tx_buf;
0196
0197 iowrite8_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO,
0198 buf, len);
0199 sspi->tx_buf = buf + len;
0200 break;
0201 }
0202 case 16: {
0203 const u16 *buf = sspi->tx_buf;
0204
0205 iowrite16_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO,
0206 buf, len);
0207 sspi->tx_buf = buf + len;
0208 break;
0209 }
0210 case 24:
0211
0212 case 32: {
0213 const u32 *buf = sspi->tx_buf;
0214
0215 iowrite32_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO,
0216 buf, len);
0217 sspi->tx_buf = buf + len;
0218 break;
0219 }
0220 default:
0221 return -EINVAL;
0222 }
0223
0224 sspi->tx_words -= len;
0225 return 0;
0226 }
0227
0228 static int synquacer_spi_config(struct spi_master *master,
0229 struct spi_device *spi,
0230 struct spi_transfer *xfer)
0231 {
0232 struct synquacer_spi *sspi = spi_master_get_devdata(master);
0233 unsigned int speed, mode, bpw, cs, bus_width, transfer_mode;
0234 u32 rate, val, div;
0235
0236
0237 if (xfer->rx_buf && xfer->tx_buf &&
0238 (xfer->rx_nbits != 1 || xfer->tx_nbits != 1)) {
0239 dev_err(sspi->dev,
0240 "RX and TX bus widths must be 1-bit for Full-Duplex!\n");
0241 return -EINVAL;
0242 }
0243
0244 if (xfer->tx_buf) {
0245 bus_width = xfer->tx_nbits;
0246 transfer_mode = SYNQUACER_HSSPI_TRANSFER_MODE_TX;
0247 } else {
0248 bus_width = xfer->rx_nbits;
0249 transfer_mode = SYNQUACER_HSSPI_TRANSFER_MODE_RX;
0250 }
0251
0252 mode = spi->mode;
0253 cs = spi->chip_select;
0254 speed = xfer->speed_hz;
0255 bpw = xfer->bits_per_word;
0256
0257
0258 if (speed == sspi->speed &&
0259 bus_width == sspi->bus_width && bpw == sspi->bpw &&
0260 mode == sspi->mode && cs == sspi->cs &&
0261 transfer_mode == sspi->transfer_mode) {
0262 return 0;
0263 }
0264
0265 sspi->transfer_mode = transfer_mode;
0266 rate = master->max_speed_hz;
0267
0268 div = DIV_ROUND_UP(rate, speed);
0269 if (div > 254) {
0270 dev_err(sspi->dev, "Requested rate too low (%u)\n",
0271 sspi->speed);
0272 return -EINVAL;
0273 }
0274
0275 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_PCC(cs));
0276 val &= ~SYNQUACER_HSSPI_PCC_SAFESYNC;
0277 if (bpw == 8 && (mode & (SPI_TX_DUAL | SPI_RX_DUAL)) && div < 3)
0278 val |= SYNQUACER_HSSPI_PCC_SAFESYNC;
0279 if (bpw == 8 && (mode & (SPI_TX_QUAD | SPI_RX_QUAD)) && div < 6)
0280 val |= SYNQUACER_HSSPI_PCC_SAFESYNC;
0281 if (bpw == 16 && (mode & (SPI_TX_QUAD | SPI_RX_QUAD)) && div < 3)
0282 val |= SYNQUACER_HSSPI_PCC_SAFESYNC;
0283
0284 if (mode & SPI_CPHA)
0285 val |= SYNQUACER_HSSPI_PCC_CPHA;
0286 else
0287 val &= ~SYNQUACER_HSSPI_PCC_CPHA;
0288
0289 if (mode & SPI_CPOL)
0290 val |= SYNQUACER_HSSPI_PCC_CPOL;
0291 else
0292 val &= ~SYNQUACER_HSSPI_PCC_CPOL;
0293
0294 if (mode & SPI_CS_HIGH)
0295 val |= SYNQUACER_HSSPI_PCC_SSPOL;
0296 else
0297 val &= ~SYNQUACER_HSSPI_PCC_SSPOL;
0298
0299 if (mode & SPI_LSB_FIRST)
0300 val |= SYNQUACER_HSSPI_PCC_SDIR;
0301 else
0302 val &= ~SYNQUACER_HSSPI_PCC_SDIR;
0303
0304 if (sspi->aces)
0305 val |= SYNQUACER_HSSPI_PCC_ACES;
0306 else
0307 val &= ~SYNQUACER_HSSPI_PCC_ACES;
0308
0309 if (sspi->rtm)
0310 val |= SYNQUACER_HSSPI_PCC_RTM;
0311 else
0312 val &= ~SYNQUACER_HSSPI_PCC_RTM;
0313
0314 val |= (3 << SYNQUACER_HSSPI_PCC_SS2CD_SHIFT);
0315 val |= SYNQUACER_HSSPI_PCC_SENDIAN;
0316
0317 val &= ~(SYNQUACER_HSSPI_PCC_CDRS_MASK <<
0318 SYNQUACER_HSSPI_PCC_CDRS_SHIFT);
0319 val |= ((div >> 1) << SYNQUACER_HSSPI_PCC_CDRS_SHIFT);
0320
0321 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_PCC(cs));
0322
0323 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);
0324 val &= ~(SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_MASK <<
0325 SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_SHIFT);
0326 val |= ((bpw / 8 - 1) << SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_SHIFT);
0327 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);
0328
0329 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0330 val &= ~(SYNQUACER_HSSPI_DMTRP_DATA_MASK <<
0331 SYNQUACER_HSSPI_DMTRP_DATA_SHIFT);
0332
0333 if (xfer->rx_buf)
0334 val |= (SYNQUACER_HSSPI_DMTRP_DATA_RX <<
0335 SYNQUACER_HSSPI_DMTRP_DATA_SHIFT);
0336 else
0337 val |= (SYNQUACER_HSSPI_DMTRP_DATA_TX <<
0338 SYNQUACER_HSSPI_DMTRP_DATA_SHIFT);
0339
0340 val &= ~(3 << SYNQUACER_HSSPI_DMTRP_BUS_WIDTH_SHIFT);
0341 val |= ((bus_width >> 1) << SYNQUACER_HSSPI_DMTRP_BUS_WIDTH_SHIFT);
0342 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0343
0344 sspi->bpw = bpw;
0345 sspi->mode = mode;
0346 sspi->speed = speed;
0347 sspi->cs = spi->chip_select;
0348 sspi->bus_width = bus_width;
0349
0350 return 0;
0351 }
0352
0353 static int synquacer_spi_transfer_one(struct spi_master *master,
0354 struct spi_device *spi,
0355 struct spi_transfer *xfer)
0356 {
0357 struct synquacer_spi *sspi = spi_master_get_devdata(master);
0358 int ret;
0359 int status = 0;
0360 u32 words;
0361 u8 bpw;
0362 u32 val;
0363
0364 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0365 val &= ~SYNQUACER_HSSPI_DMSTOP_STOP;
0366 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0367
0368 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);
0369 val |= SYNQUACER_HSSPI_FIFOCFG_RX_FLUSH;
0370 val |= SYNQUACER_HSSPI_FIFOCFG_TX_FLUSH;
0371 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);
0372
0373
0374
0375
0376
0377 bpw = xfer->bits_per_word;
0378 if (bpw == 8 && !(xfer->len % 4) && !(spi->mode & SPI_LSB_FIRST))
0379 xfer->bits_per_word = 32;
0380
0381 ret = synquacer_spi_config(master, spi, xfer);
0382
0383
0384 xfer->bits_per_word = bpw;
0385
0386 if (ret)
0387 return ret;
0388
0389 reinit_completion(&sspi->transfer_done);
0390
0391 sspi->tx_buf = xfer->tx_buf;
0392 sspi->rx_buf = xfer->rx_buf;
0393
0394 switch (sspi->bpw) {
0395 case 8:
0396 words = xfer->len;
0397 break;
0398 case 16:
0399 words = xfer->len / 2;
0400 break;
0401 case 24:
0402
0403 case 32:
0404 words = xfer->len / 4;
0405 break;
0406 default:
0407 dev_err(sspi->dev, "unsupported bpw: %d\n", sspi->bpw);
0408 return -EINVAL;
0409 }
0410
0411 if (xfer->tx_buf)
0412 sspi->tx_words = words;
0413 else
0414 sspi->tx_words = 0;
0415
0416 if (xfer->rx_buf)
0417 sspi->rx_words = words;
0418 else
0419 sspi->rx_words = 0;
0420
0421 if (xfer->tx_buf) {
0422 status = write_fifo(sspi);
0423 if (status < 0) {
0424 dev_err(sspi->dev, "failed write_fifo. status: 0x%x\n",
0425 status);
0426 return status;
0427 }
0428 }
0429
0430 if (xfer->rx_buf) {
0431 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);
0432 val &= ~(SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_MASK <<
0433 SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_SHIFT);
0434 val |= ((sspi->rx_words > SYNQUACER_HSSPI_FIFO_DEPTH ?
0435 SYNQUACER_HSSPI_FIFO_RX_THRESHOLD : sspi->rx_words) <<
0436 SYNQUACER_HSSPI_FIFOCFG_RX_THRESHOLD_SHIFT);
0437 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG);
0438 }
0439
0440 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_TXC);
0441 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_RXC);
0442
0443
0444 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0445 val |= SYNQUACER_HSSPI_DMSTART_START;
0446 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0447
0448 if (xfer->tx_buf) {
0449 val = SYNQUACER_HSSPI_TXE_FIFO_EMPTY;
0450 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_TXE);
0451 status = wait_for_completion_timeout(&sspi->transfer_done,
0452 msecs_to_jiffies(SYNQUACER_HSSPI_TRANSFER_TMOUT_MSEC));
0453 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE);
0454 }
0455
0456 if (xfer->rx_buf) {
0457 u32 buf[SYNQUACER_HSSPI_FIFO_DEPTH];
0458
0459 val = SYNQUACER_HSSPI_RXE_FIFO_MORE_THAN_THRESHOLD |
0460 SYNQUACER_HSSPI_RXE_SLAVE_RELEASED;
0461 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_RXE);
0462 status = wait_for_completion_timeout(&sspi->transfer_done,
0463 msecs_to_jiffies(SYNQUACER_HSSPI_TRANSFER_TMOUT_MSEC));
0464 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE);
0465
0466
0467 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0468 val |= SYNQUACER_HSSPI_DMSTOP_STOP;
0469 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0470 sspi->rx_buf = buf;
0471 sspi->rx_words = SYNQUACER_HSSPI_FIFO_DEPTH;
0472 read_fifo(sspi);
0473 }
0474
0475 if (status < 0) {
0476 dev_err(sspi->dev, "failed to transfer. status: 0x%x\n",
0477 status);
0478 return status;
0479 }
0480
0481 return 0;
0482 }
0483
0484 static void synquacer_spi_set_cs(struct spi_device *spi, bool enable)
0485 {
0486 struct synquacer_spi *sspi = spi_master_get_devdata(spi->master);
0487 u32 val;
0488
0489 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0490 val &= ~(SYNQUACER_HSSPI_DMPSEL_CS_MASK <<
0491 SYNQUACER_HSSPI_DMPSEL_CS_SHIFT);
0492 val |= spi->chip_select << SYNQUACER_HSSPI_DMPSEL_CS_SHIFT;
0493
0494 if (!enable)
0495 val |= SYNQUACER_HSSPI_DMSTOP_STOP;
0496
0497 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
0498 }
0499
0500 static int synquacer_spi_wait_status_update(struct synquacer_spi *sspi,
0501 bool enable)
0502 {
0503 u32 val;
0504 unsigned long timeout = jiffies +
0505 msecs_to_jiffies(SYNQUACER_HSSPI_ENABLE_TMOUT_MSEC);
0506
0507
0508 do {
0509 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_MCTRL) &
0510 SYNQUACER_HSSPI_MCTRL_MES;
0511 if (enable && val)
0512 return 0;
0513 if (!enable && !val)
0514 return 0;
0515 } while (time_before(jiffies, timeout));
0516
0517 dev_err(sspi->dev, "timeout occurs in updating Module Enable Status\n");
0518 return -EBUSY;
0519 }
0520
0521 static int synquacer_spi_enable(struct spi_master *master)
0522 {
0523 u32 val;
0524 int status;
0525 struct synquacer_spi *sspi = spi_master_get_devdata(master);
0526
0527
0528 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_MCTRL);
0529 status = synquacer_spi_wait_status_update(sspi, false);
0530 if (status < 0)
0531 return status;
0532
0533 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE);
0534 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE);
0535 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_TXC);
0536 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_RXC);
0537 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_FAULTC);
0538
0539 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMCFG);
0540 val &= ~SYNQUACER_HSSPI_DMCFG_SSDC;
0541 val &= ~SYNQUACER_HSSPI_DMCFG_MSTARTEN;
0542 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMCFG);
0543
0544 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_MCTRL);
0545 if (sspi->clk_src_type == SYNQUACER_HSSPI_CLOCK_SRC_IPCLK)
0546 val |= SYNQUACER_HSSPI_MCTRL_CDSS;
0547 else
0548 val &= ~SYNQUACER_HSSPI_MCTRL_CDSS;
0549
0550 val &= ~SYNQUACER_HSSPI_MCTRL_COMMAND_SEQUENCE_EN;
0551 val |= SYNQUACER_HSSPI_MCTRL_MEN;
0552 val |= SYNQUACER_HSSPI_MCTRL_SYNCON;
0553
0554
0555 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_MCTRL);
0556 status = synquacer_spi_wait_status_update(sspi, true);
0557 if (status < 0)
0558 return status;
0559
0560 return 0;
0561 }
0562
0563 static irqreturn_t sq_spi_rx_handler(int irq, void *priv)
0564 {
0565 uint32_t val;
0566 struct synquacer_spi *sspi = priv;
0567
0568 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_RXF);
0569 if ((val & SYNQUACER_HSSPI_RXF_SLAVE_RELEASED) ||
0570 (val & SYNQUACER_HSSPI_RXF_FIFO_MORE_THAN_THRESHOLD)) {
0571 read_fifo(sspi);
0572
0573 if (sspi->rx_words == 0) {
0574 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE);
0575 complete(&sspi->transfer_done);
0576 }
0577 return IRQ_HANDLED;
0578 }
0579
0580 return IRQ_NONE;
0581 }
0582
0583 static irqreturn_t sq_spi_tx_handler(int irq, void *priv)
0584 {
0585 uint32_t val;
0586 struct synquacer_spi *sspi = priv;
0587
0588 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_TXF);
0589 if (val & SYNQUACER_HSSPI_TXF_FIFO_EMPTY) {
0590 if (sspi->tx_words == 0) {
0591 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE);
0592 complete(&sspi->transfer_done);
0593 } else {
0594 write_fifo(sspi);
0595 }
0596 return IRQ_HANDLED;
0597 }
0598
0599 return IRQ_NONE;
0600 }
0601
0602 static int synquacer_spi_probe(struct platform_device *pdev)
0603 {
0604 struct device_node *np = pdev->dev.of_node;
0605 struct spi_master *master;
0606 struct synquacer_spi *sspi;
0607 int ret;
0608 int rx_irq, tx_irq;
0609
0610 master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
0611 if (!master)
0612 return -ENOMEM;
0613
0614 platform_set_drvdata(pdev, master);
0615
0616 sspi = spi_master_get_devdata(master);
0617 sspi->dev = &pdev->dev;
0618
0619 init_completion(&sspi->transfer_done);
0620
0621 sspi->regs = devm_platform_ioremap_resource(pdev, 0);
0622 if (IS_ERR(sspi->regs)) {
0623 ret = PTR_ERR(sspi->regs);
0624 goto put_spi;
0625 }
0626
0627 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK;
0628 device_property_read_u32(&pdev->dev, "socionext,ihclk-rate",
0629 &master->max_speed_hz);
0630
0631 if (dev_of_node(&pdev->dev)) {
0632 if (device_property_match_string(&pdev->dev,
0633 "clock-names", "iHCLK") >= 0) {
0634 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK;
0635 sspi->clk = devm_clk_get(sspi->dev, "iHCLK");
0636 } else if (device_property_match_string(&pdev->dev,
0637 "clock-names", "iPCLK") >= 0) {
0638 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IPCLK;
0639 sspi->clk = devm_clk_get(sspi->dev, "iPCLK");
0640 } else {
0641 dev_err(&pdev->dev, "specified wrong clock source\n");
0642 ret = -EINVAL;
0643 goto put_spi;
0644 }
0645
0646 if (IS_ERR(sspi->clk)) {
0647 ret = dev_err_probe(&pdev->dev, PTR_ERR(sspi->clk),
0648 "clock not found\n");
0649 goto put_spi;
0650 }
0651
0652 ret = clk_prepare_enable(sspi->clk);
0653 if (ret) {
0654 dev_err(&pdev->dev, "failed to enable clock (%d)\n",
0655 ret);
0656 goto put_spi;
0657 }
0658
0659 master->max_speed_hz = clk_get_rate(sspi->clk);
0660 }
0661
0662 if (!master->max_speed_hz) {
0663 dev_err(&pdev->dev, "missing clock source\n");
0664 ret = -EINVAL;
0665 goto disable_clk;
0666 }
0667 master->min_speed_hz = master->max_speed_hz / 254;
0668
0669 sspi->aces = device_property_read_bool(&pdev->dev,
0670 "socionext,set-aces");
0671 sspi->rtm = device_property_read_bool(&pdev->dev, "socionext,use-rtm");
0672
0673 master->num_chipselect = SYNQUACER_HSSPI_NUM_CHIP_SELECT;
0674
0675 rx_irq = platform_get_irq(pdev, 0);
0676 if (rx_irq <= 0) {
0677 ret = rx_irq;
0678 goto disable_clk;
0679 }
0680 snprintf(sspi->rx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-rx",
0681 dev_name(&pdev->dev));
0682 ret = devm_request_irq(&pdev->dev, rx_irq, sq_spi_rx_handler,
0683 0, sspi->rx_irq_name, sspi);
0684 if (ret) {
0685 dev_err(&pdev->dev, "request rx_irq failed (%d)\n", ret);
0686 goto disable_clk;
0687 }
0688
0689 tx_irq = platform_get_irq(pdev, 1);
0690 if (tx_irq <= 0) {
0691 ret = tx_irq;
0692 goto disable_clk;
0693 }
0694 snprintf(sspi->tx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-tx",
0695 dev_name(&pdev->dev));
0696 ret = devm_request_irq(&pdev->dev, tx_irq, sq_spi_tx_handler,
0697 0, sspi->tx_irq_name, sspi);
0698 if (ret) {
0699 dev_err(&pdev->dev, "request tx_irq failed (%d)\n", ret);
0700 goto disable_clk;
0701 }
0702
0703 master->dev.of_node = np;
0704 master->dev.fwnode = pdev->dev.fwnode;
0705 master->auto_runtime_pm = true;
0706 master->bus_num = pdev->id;
0707
0708 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL |
0709 SPI_TX_QUAD | SPI_RX_QUAD;
0710 master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) |
0711 SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
0712
0713 master->set_cs = synquacer_spi_set_cs;
0714 master->transfer_one = synquacer_spi_transfer_one;
0715
0716 ret = synquacer_spi_enable(master);
0717 if (ret)
0718 goto disable_clk;
0719
0720 pm_runtime_set_active(sspi->dev);
0721 pm_runtime_enable(sspi->dev);
0722
0723 ret = devm_spi_register_master(sspi->dev, master);
0724 if (ret)
0725 goto disable_pm;
0726
0727 return 0;
0728
0729 disable_pm:
0730 pm_runtime_disable(sspi->dev);
0731 disable_clk:
0732 clk_disable_unprepare(sspi->clk);
0733 put_spi:
0734 spi_master_put(master);
0735
0736 return ret;
0737 }
0738
0739 static int synquacer_spi_remove(struct platform_device *pdev)
0740 {
0741 struct spi_master *master = platform_get_drvdata(pdev);
0742 struct synquacer_spi *sspi = spi_master_get_devdata(master);
0743
0744 pm_runtime_disable(sspi->dev);
0745
0746 clk_disable_unprepare(sspi->clk);
0747
0748 return 0;
0749 }
0750
0751 static int __maybe_unused synquacer_spi_suspend(struct device *dev)
0752 {
0753 struct spi_master *master = dev_get_drvdata(dev);
0754 struct synquacer_spi *sspi = spi_master_get_devdata(master);
0755 int ret;
0756
0757 ret = spi_master_suspend(master);
0758 if (ret)
0759 return ret;
0760
0761 if (!pm_runtime_suspended(dev))
0762 clk_disable_unprepare(sspi->clk);
0763
0764 return ret;
0765 }
0766
0767 static int __maybe_unused synquacer_spi_resume(struct device *dev)
0768 {
0769 struct spi_master *master = dev_get_drvdata(dev);
0770 struct synquacer_spi *sspi = spi_master_get_devdata(master);
0771 int ret;
0772
0773 if (!pm_runtime_suspended(dev)) {
0774
0775 sspi->speed = 0;
0776
0777 ret = clk_prepare_enable(sspi->clk);
0778 if (ret < 0) {
0779 dev_err(dev, "failed to enable clk (%d)\n",
0780 ret);
0781 return ret;
0782 }
0783
0784 ret = synquacer_spi_enable(master);
0785 if (ret) {
0786 clk_disable_unprepare(sspi->clk);
0787 dev_err(dev, "failed to enable spi (%d)\n", ret);
0788 return ret;
0789 }
0790 }
0791
0792 ret = spi_master_resume(master);
0793 if (ret < 0)
0794 clk_disable_unprepare(sspi->clk);
0795
0796 return ret;
0797 }
0798
0799 static SIMPLE_DEV_PM_OPS(synquacer_spi_pm_ops, synquacer_spi_suspend,
0800 synquacer_spi_resume);
0801
0802 static const struct of_device_id synquacer_spi_of_match[] = {
0803 {.compatible = "socionext,synquacer-spi"},
0804 {}
0805 };
0806 MODULE_DEVICE_TABLE(of, synquacer_spi_of_match);
0807
0808 #ifdef CONFIG_ACPI
0809 static const struct acpi_device_id synquacer_hsspi_acpi_ids[] = {
0810 { "SCX0004" },
0811 { }
0812 };
0813 MODULE_DEVICE_TABLE(acpi, synquacer_hsspi_acpi_ids);
0814 #endif
0815
0816 static struct platform_driver synquacer_spi_driver = {
0817 .driver = {
0818 .name = "synquacer-spi",
0819 .pm = &synquacer_spi_pm_ops,
0820 .of_match_table = synquacer_spi_of_match,
0821 .acpi_match_table = ACPI_PTR(synquacer_hsspi_acpi_ids),
0822 },
0823 .probe = synquacer_spi_probe,
0824 .remove = synquacer_spi_remove,
0825 };
0826 module_platform_driver(synquacer_spi_driver);
0827
0828 MODULE_DESCRIPTION("Socionext Synquacer HS-SPI controller driver");
0829 MODULE_AUTHOR("Masahisa Kojima <masahisa.kojima@linaro.org>");
0830 MODULE_AUTHOR("Jassi Brar <jaswinder.singh@linaro.org>");
0831 MODULE_LICENSE("GPL v2");