blob: 58b823a16fc4da6a228a592b533105d8a3a6c75c [file] [log] [blame]
Jay Fangc770d862021-03-27 17:10:00 +08001// SPDX-License-Identifier: GPL-2.0-only
2//
3// HiSilicon SPI Controller Driver for Kunpeng SoCs
4//
5// Copyright (c) 2021 HiSilicon Technologies Co., Ltd.
6// Author: Jay Fang <f.fangjian@huawei.com>
7//
8// This code is based on spi-dw-core.c.
9
10#include <linux/acpi.h>
11#include <linux/bitfield.h>
Jay Fang2b2142f22021-06-04 14:55:18 +080012#include <linux/debugfs.h>
Jay Fangc770d862021-03-27 17:10:00 +080013#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/interrupt.h>
16#include <linux/module.h>
17#include <linux/property.h>
18#include <linux/platform_device.h>
19#include <linux/slab.h>
20#include <linux/spi/spi.h>
21
22/* Register offsets */
23#define HISI_SPI_CSCR 0x00 /* cs control register */
24#define HISI_SPI_CR 0x04 /* spi common control register */
25#define HISI_SPI_ENR 0x08 /* spi enable register */
26#define HISI_SPI_FIFOC 0x0c /* fifo level control register */
27#define HISI_SPI_IMR 0x10 /* interrupt mask register */
28#define HISI_SPI_DIN 0x14 /* data in register */
29#define HISI_SPI_DOUT 0x18 /* data out register */
30#define HISI_SPI_SR 0x1c /* status register */
31#define HISI_SPI_RISR 0x20 /* raw interrupt status register */
32#define HISI_SPI_ISR 0x24 /* interrupt status register */
33#define HISI_SPI_ICR 0x28 /* interrupt clear register */
34#define HISI_SPI_VERSION 0xe0 /* version register */
35
36/* Bit fields in HISI_SPI_CR */
37#define CR_LOOP_MASK GENMASK(1, 1)
38#define CR_CPOL_MASK GENMASK(2, 2)
39#define CR_CPHA_MASK GENMASK(3, 3)
40#define CR_DIV_PRE_MASK GENMASK(11, 4)
41#define CR_DIV_POST_MASK GENMASK(19, 12)
42#define CR_BPW_MASK GENMASK(24, 20)
43#define CR_SPD_MODE_MASK GENMASK(25, 25)
44
45/* Bit fields in HISI_SPI_FIFOC */
46#define FIFOC_TX_MASK GENMASK(5, 3)
47#define FIFOC_RX_MASK GENMASK(11, 9)
48
49/* Bit fields in HISI_SPI_IMR, 4 bits */
50#define IMR_RXOF BIT(0) /* Receive Overflow */
51#define IMR_RXTO BIT(1) /* Receive Timeout */
52#define IMR_RX BIT(2) /* Receive */
53#define IMR_TX BIT(3) /* Transmit */
54#define IMR_MASK (IMR_RXOF | IMR_RXTO | IMR_RX | IMR_TX)
55
56/* Bit fields in HISI_SPI_SR, 5 bits */
57#define SR_TXE BIT(0) /* Transmit FIFO empty */
58#define SR_TXNF BIT(1) /* Transmit FIFO not full */
59#define SR_RXNE BIT(2) /* Receive FIFO not empty */
60#define SR_RXF BIT(3) /* Receive FIFO full */
61#define SR_BUSY BIT(4) /* Busy Flag */
62
63/* Bit fields in HISI_SPI_ISR, 4 bits */
64#define ISR_RXOF BIT(0) /* Receive Overflow */
65#define ISR_RXTO BIT(1) /* Receive Timeout */
66#define ISR_RX BIT(2) /* Receive */
67#define ISR_TX BIT(3) /* Transmit */
68#define ISR_MASK (ISR_RXOF | ISR_RXTO | ISR_RX | ISR_TX)
69
70/* Bit fields in HISI_SPI_ICR, 2 bits */
71#define ICR_RXOF BIT(0) /* Receive Overflow */
72#define ICR_RXTO BIT(1) /* Receive Timeout */
73#define ICR_MASK (ICR_RXOF | ICR_RXTO)
74
75#define DIV_POST_MAX 0xFF
76#define DIV_POST_MIN 0x00
77#define DIV_PRE_MAX 0xFE
78#define DIV_PRE_MIN 0x02
79#define CLK_DIV_MAX ((1 + DIV_POST_MAX) * DIV_PRE_MAX)
80#define CLK_DIV_MIN ((1 + DIV_POST_MIN) * DIV_PRE_MIN)
81
82#define DEFAULT_NUM_CS 1
83
84#define HISI_SPI_WAIT_TIMEOUT_MS 10UL
85
86enum hisi_spi_rx_level_trig {
87 HISI_SPI_RX_1,
88 HISI_SPI_RX_4,
89 HISI_SPI_RX_8,
90 HISI_SPI_RX_16,
91 HISI_SPI_RX_32,
92 HISI_SPI_RX_64,
93 HISI_SPI_RX_128
94};
95
96enum hisi_spi_tx_level_trig {
97 HISI_SPI_TX_1_OR_LESS,
98 HISI_SPI_TX_4_OR_LESS,
99 HISI_SPI_TX_8_OR_LESS,
100 HISI_SPI_TX_16_OR_LESS,
101 HISI_SPI_TX_32_OR_LESS,
102 HISI_SPI_TX_64_OR_LESS,
103 HISI_SPI_TX_128_OR_LESS
104};
105
106enum hisi_spi_frame_n_bytes {
107 HISI_SPI_N_BYTES_NULL,
108 HISI_SPI_N_BYTES_U8,
109 HISI_SPI_N_BYTES_U16,
110 HISI_SPI_N_BYTES_U32 = 4
111};
112
113/* Slave spi_dev related */
114struct hisi_chip_data {
115 u32 cr;
116 u32 speed_hz; /* baud rate */
117 u16 clk_div; /* baud rate divider */
118
119 /* clk_div = (1 + div_post) * div_pre */
120 u8 div_post; /* value from 0 to 255 */
121 u8 div_pre; /* value from 2 to 254 (even only!) */
122};
123
124struct hisi_spi {
125 struct device *dev;
126
127 void __iomem *regs;
128 int irq;
129 u32 fifo_len; /* depth of the FIFO buffer */
Jay Fang2b2142f22021-06-04 14:55:18 +0800130 u16 bus_num;
Jay Fangc770d862021-03-27 17:10:00 +0800131
132 /* Current message transfer state info */
133 const void *tx;
134 unsigned int tx_len;
135 void *rx;
136 unsigned int rx_len;
137 u8 n_bytes; /* current is a 1/2/4 bytes op */
Jay Fang2b2142f22021-06-04 14:55:18 +0800138
139 struct dentry *debugfs;
140 struct debugfs_regset32 regset;
Jay Fangc770d862021-03-27 17:10:00 +0800141};
142
Jay Fang2b2142f22021-06-04 14:55:18 +0800143#define HISI_SPI_DBGFS_REG(_name, _off) \
144{ \
145 .name = _name, \
146 .offset = _off, \
147}
148
149static const struct debugfs_reg32 hisi_spi_regs[] = {
150 HISI_SPI_DBGFS_REG("CSCR", HISI_SPI_CSCR),
151 HISI_SPI_DBGFS_REG("CR", HISI_SPI_CR),
152 HISI_SPI_DBGFS_REG("ENR", HISI_SPI_ENR),
153 HISI_SPI_DBGFS_REG("FIFOC", HISI_SPI_FIFOC),
154 HISI_SPI_DBGFS_REG("IMR", HISI_SPI_IMR),
155 HISI_SPI_DBGFS_REG("DIN", HISI_SPI_DIN),
156 HISI_SPI_DBGFS_REG("DOUT", HISI_SPI_DOUT),
157 HISI_SPI_DBGFS_REG("SR", HISI_SPI_SR),
158 HISI_SPI_DBGFS_REG("RISR", HISI_SPI_RISR),
159 HISI_SPI_DBGFS_REG("ISR", HISI_SPI_ISR),
160 HISI_SPI_DBGFS_REG("ICR", HISI_SPI_ICR),
161 HISI_SPI_DBGFS_REG("VERSION", HISI_SPI_VERSION),
162};
163
164static int hisi_spi_debugfs_init(struct hisi_spi *hs)
165{
166 char name[32];
167
168 snprintf(name, 32, "hisi_spi%d", hs->bus_num);
169 hs->debugfs = debugfs_create_dir(name, NULL);
170 if (!hs->debugfs)
171 return -ENOMEM;
172
173 hs->regset.regs = hisi_spi_regs;
174 hs->regset.nregs = ARRAY_SIZE(hisi_spi_regs);
175 hs->regset.base = hs->regs;
176 debugfs_create_regset32("registers", 0400, hs->debugfs, &hs->regset);
177
178 return 0;
179}
180
Jay Fangc770d862021-03-27 17:10:00 +0800181static u32 hisi_spi_busy(struct hisi_spi *hs)
182{
183 return readl(hs->regs + HISI_SPI_SR) & SR_BUSY;
184}
185
186static u32 hisi_spi_rx_not_empty(struct hisi_spi *hs)
187{
188 return readl(hs->regs + HISI_SPI_SR) & SR_RXNE;
189}
190
191static u32 hisi_spi_tx_not_full(struct hisi_spi *hs)
192{
193 return readl(hs->regs + HISI_SPI_SR) & SR_TXNF;
194}
195
196static void hisi_spi_flush_fifo(struct hisi_spi *hs)
197{
198 unsigned long limit = loops_per_jiffy << 1;
199
200 do {
201 while (hisi_spi_rx_not_empty(hs))
202 readl(hs->regs + HISI_SPI_DOUT);
203 } while (hisi_spi_busy(hs) && limit--);
204}
205
206/* Disable the controller and all interrupts */
207static void hisi_spi_disable(struct hisi_spi *hs)
208{
209 writel(0, hs->regs + HISI_SPI_ENR);
210 writel(IMR_MASK, hs->regs + HISI_SPI_IMR);
211 writel(ICR_MASK, hs->regs + HISI_SPI_ICR);
212}
213
214static u8 hisi_spi_n_bytes(struct spi_transfer *transfer)
215{
216 if (transfer->bits_per_word <= 8)
217 return HISI_SPI_N_BYTES_U8;
218 else if (transfer->bits_per_word <= 16)
219 return HISI_SPI_N_BYTES_U16;
220 else
221 return HISI_SPI_N_BYTES_U32;
222}
223
224static void hisi_spi_reader(struct hisi_spi *hs)
225{
226 u32 max = min_t(u32, hs->rx_len, hs->fifo_len);
227 u32 rxw;
228
229 while (hisi_spi_rx_not_empty(hs) && max--) {
230 rxw = readl(hs->regs + HISI_SPI_DOUT);
231 /* Check the transfer's original "rx" is not null */
232 if (hs->rx) {
233 switch (hs->n_bytes) {
234 case HISI_SPI_N_BYTES_U8:
235 *(u8 *)(hs->rx) = rxw;
236 break;
237 case HISI_SPI_N_BYTES_U16:
238 *(u16 *)(hs->rx) = rxw;
239 break;
240 case HISI_SPI_N_BYTES_U32:
241 *(u32 *)(hs->rx) = rxw;
242 break;
243 }
244 hs->rx += hs->n_bytes;
245 }
246 --hs->rx_len;
247 }
248}
249
250static void hisi_spi_writer(struct hisi_spi *hs)
251{
252 u32 max = min_t(u32, hs->tx_len, hs->fifo_len);
253 u32 txw = 0;
254
255 while (hisi_spi_tx_not_full(hs) && max--) {
256 /* Check the transfer's original "tx" is not null */
257 if (hs->tx) {
258 switch (hs->n_bytes) {
259 case HISI_SPI_N_BYTES_U8:
260 txw = *(u8 *)(hs->tx);
261 break;
262 case HISI_SPI_N_BYTES_U16:
263 txw = *(u16 *)(hs->tx);
264 break;
265 case HISI_SPI_N_BYTES_U32:
266 txw = *(u32 *)(hs->tx);
267 break;
268 }
269 hs->tx += hs->n_bytes;
270 }
271 writel(txw, hs->regs + HISI_SPI_DIN);
272 --hs->tx_len;
273 }
274}
275
276static void __hisi_calc_div_reg(struct hisi_chip_data *chip)
277{
278 chip->div_pre = DIV_PRE_MAX;
279 while (chip->div_pre >= DIV_PRE_MIN) {
280 if (chip->clk_div % chip->div_pre == 0)
281 break;
282
283 chip->div_pre -= 2;
284 }
285
286 if (chip->div_pre > chip->clk_div)
287 chip->div_pre = chip->clk_div;
288
289 chip->div_post = (chip->clk_div / chip->div_pre) - 1;
290}
291
292static u32 hisi_calc_effective_speed(struct spi_controller *master,
293 struct hisi_chip_data *chip, u32 speed_hz)
294{
295 u32 effective_speed;
296
297 /* Note clock divider doesn't support odd numbers */
298 chip->clk_div = DIV_ROUND_UP(master->max_speed_hz, speed_hz) + 1;
299 chip->clk_div &= 0xfffe;
300 if (chip->clk_div > CLK_DIV_MAX)
301 chip->clk_div = CLK_DIV_MAX;
302
303 effective_speed = master->max_speed_hz / chip->clk_div;
304 if (chip->speed_hz != effective_speed) {
305 __hisi_calc_div_reg(chip);
306 chip->speed_hz = effective_speed;
307 }
308
309 return effective_speed;
310}
311
312static u32 hisi_spi_prepare_cr(struct spi_device *spi)
313{
314 u32 cr = FIELD_PREP(CR_SPD_MODE_MASK, 1);
315
316 cr |= FIELD_PREP(CR_CPHA_MASK, (spi->mode & SPI_CPHA) ? 1 : 0);
317 cr |= FIELD_PREP(CR_CPOL_MASK, (spi->mode & SPI_CPOL) ? 1 : 0);
318 cr |= FIELD_PREP(CR_LOOP_MASK, (spi->mode & SPI_LOOP) ? 1 : 0);
319
320 return cr;
321}
322
323static void hisi_spi_hw_init(struct hisi_spi *hs)
324{
325 hisi_spi_disable(hs);
326
327 /* FIFO default config */
328 writel(FIELD_PREP(FIFOC_TX_MASK, HISI_SPI_TX_64_OR_LESS) |
329 FIELD_PREP(FIFOC_RX_MASK, HISI_SPI_RX_16),
330 hs->regs + HISI_SPI_FIFOC);
331
332 hs->fifo_len = 256;
333}
334
335static irqreturn_t hisi_spi_irq(int irq, void *dev_id)
336{
337 struct spi_controller *master = dev_id;
338 struct hisi_spi *hs = spi_controller_get_devdata(master);
339 u32 irq_status = readl(hs->regs + HISI_SPI_ISR) & ISR_MASK;
340
341 if (!irq_status)
342 return IRQ_NONE;
343
344 if (!master->cur_msg)
345 return IRQ_HANDLED;
346
347 /* Error handling */
348 if (irq_status & ISR_RXOF) {
349 dev_err(hs->dev, "interrupt_transfer: fifo overflow\n");
350 master->cur_msg->status = -EIO;
351 goto finalize_transfer;
352 }
353
354 /*
355 * Read data from the Rx FIFO every time. If there is
356 * nothing left to receive, finalize the transfer.
357 */
358 hisi_spi_reader(hs);
359 if (!hs->rx_len)
360 goto finalize_transfer;
361
362 /* Send data out when Tx FIFO IRQ triggered */
363 if (irq_status & ISR_TX)
364 hisi_spi_writer(hs);
365
366 return IRQ_HANDLED;
367
368finalize_transfer:
369 hisi_spi_disable(hs);
370 spi_finalize_current_transfer(master);
371 return IRQ_HANDLED;
372}
373
374static int hisi_spi_transfer_one(struct spi_controller *master,
375 struct spi_device *spi, struct spi_transfer *transfer)
376{
377 struct hisi_spi *hs = spi_controller_get_devdata(master);
378 struct hisi_chip_data *chip = spi_get_ctldata(spi);
379 u32 cr = chip->cr;
380
381 /* Update per transfer options for speed and bpw */
382 transfer->effective_speed_hz =
383 hisi_calc_effective_speed(master, chip, transfer->speed_hz);
384 cr |= FIELD_PREP(CR_DIV_PRE_MASK, chip->div_pre);
385 cr |= FIELD_PREP(CR_DIV_POST_MASK, chip->div_post);
386 cr |= FIELD_PREP(CR_BPW_MASK, transfer->bits_per_word - 1);
387 writel(cr, hs->regs + HISI_SPI_CR);
388
389 hisi_spi_flush_fifo(hs);
390
391 hs->n_bytes = hisi_spi_n_bytes(transfer);
392 hs->tx = transfer->tx_buf;
393 hs->tx_len = transfer->len / hs->n_bytes;
394 hs->rx = transfer->rx_buf;
395 hs->rx_len = hs->tx_len;
396
397 /*
398 * Ensure that the transfer data above has been updated
399 * before the interrupt to start.
400 */
401 smp_mb();
402
403 /* Enable all interrupts and the controller */
Jay Fang9a446cf2021-04-07 10:31:00 +0800404 writel(~(u32)IMR_MASK, hs->regs + HISI_SPI_IMR);
Jay Fangc770d862021-03-27 17:10:00 +0800405 writel(1, hs->regs + HISI_SPI_ENR);
406
407 return 1;
408}
409
410static void hisi_spi_handle_err(struct spi_controller *master,
411 struct spi_message *msg)
412{
413 struct hisi_spi *hs = spi_controller_get_devdata(master);
414
415 hisi_spi_disable(hs);
416
417 /*
418 * Wait for interrupt handler that is
419 * already in timeout to complete.
420 */
421 msleep(HISI_SPI_WAIT_TIMEOUT_MS);
422}
423
424static int hisi_spi_setup(struct spi_device *spi)
425{
426 struct hisi_chip_data *chip;
427
428 /* Only alloc on first setup */
429 chip = spi_get_ctldata(spi);
430 if (!chip) {
431 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
432 if (!chip)
433 return -ENOMEM;
434 spi_set_ctldata(spi, chip);
435 }
436
437 chip->cr = hisi_spi_prepare_cr(spi);
438
439 return 0;
440}
441
442static void hisi_spi_cleanup(struct spi_device *spi)
443{
444 struct hisi_chip_data *chip = spi_get_ctldata(spi);
445
446 kfree(chip);
447 spi_set_ctldata(spi, NULL);
448}
449
450static int hisi_spi_probe(struct platform_device *pdev)
451{
452 struct device *dev = &pdev->dev;
453 struct spi_controller *master;
454 struct hisi_spi *hs;
455 int ret, irq;
456
457 irq = platform_get_irq(pdev, 0);
458 if (irq < 0)
459 return irq;
460
461 master = devm_spi_alloc_master(dev, sizeof(*hs));
462 if (!master)
463 return -ENOMEM;
464
465 platform_set_drvdata(pdev, master);
466
467 hs = spi_controller_get_devdata(master);
468 hs->dev = dev;
469 hs->irq = irq;
Jay Fang2b2142f22021-06-04 14:55:18 +0800470 hs->bus_num = pdev->id;
Jay Fangc770d862021-03-27 17:10:00 +0800471
472 hs->regs = devm_platform_ioremap_resource(pdev, 0);
473 if (IS_ERR(hs->regs))
474 return PTR_ERR(hs->regs);
475
476 /* Specify maximum SPI clocking speed (master only) by firmware */
477 ret = device_property_read_u32(dev, "spi-max-frequency",
478 &master->max_speed_hz);
479 if (ret) {
480 dev_err(dev, "failed to get max SPI clocking speed, ret=%d\n",
481 ret);
482 return -EINVAL;
483 }
484
485 ret = device_property_read_u16(dev, "num-cs",
486 &master->num_chipselect);
487 if (ret)
488 master->num_chipselect = DEFAULT_NUM_CS;
489
490 master->use_gpio_descriptors = true;
491 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
492 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
Jay Fang2b2142f22021-06-04 14:55:18 +0800493 master->bus_num = hs->bus_num;
Jay Fangc770d862021-03-27 17:10:00 +0800494 master->setup = hisi_spi_setup;
495 master->cleanup = hisi_spi_cleanup;
496 master->transfer_one = hisi_spi_transfer_one;
497 master->handle_err = hisi_spi_handle_err;
498 master->dev.fwnode = dev->fwnode;
499
500 hisi_spi_hw_init(hs);
501
502 ret = devm_request_irq(dev, hs->irq, hisi_spi_irq, 0, dev_name(dev),
503 master);
504 if (ret < 0) {
505 dev_err(dev, "failed to get IRQ=%d, ret=%d\n", hs->irq, ret);
506 return ret;
507 }
508
Jay Fang2b2142f22021-06-04 14:55:18 +0800509 if (hisi_spi_debugfs_init(hs))
510 dev_info(dev, "failed to create debugfs dir\n");
511
Jay Fangc770d862021-03-27 17:10:00 +0800512 ret = spi_register_controller(master);
513 if (ret) {
514 dev_err(dev, "failed to register spi master, ret=%d\n", ret);
515 return ret;
516 }
517
518 dev_info(dev, "hw version:0x%x max-freq:%u kHz\n",
519 readl(hs->regs + HISI_SPI_VERSION),
520 master->max_speed_hz / 1000);
521
522 return 0;
523}
524
525static int hisi_spi_remove(struct platform_device *pdev)
526{
527 struct spi_controller *master = platform_get_drvdata(pdev);
Jay Fang2b2142f22021-06-04 14:55:18 +0800528 struct hisi_spi *hs = spi_controller_get_devdata(master);
Jay Fangc770d862021-03-27 17:10:00 +0800529
Jay Fang2b2142f22021-06-04 14:55:18 +0800530 debugfs_remove_recursive(hs->debugfs);
Jay Fangc770d862021-03-27 17:10:00 +0800531 spi_unregister_controller(master);
532
533 return 0;
534}
535
536static const struct acpi_device_id hisi_spi_acpi_match[] = {
537 {"HISI03E1", 0},
538 {}
539};
540MODULE_DEVICE_TABLE(acpi, hisi_spi_acpi_match);
541
542static struct platform_driver hisi_spi_driver = {
543 .probe = hisi_spi_probe,
544 .remove = hisi_spi_remove,
545 .driver = {
546 .name = "hisi-kunpeng-spi",
547 .acpi_match_table = hisi_spi_acpi_match,
548 },
549};
550module_platform_driver(hisi_spi_driver);
551
552MODULE_AUTHOR("Jay Fang <f.fangjian@huawei.com>");
553MODULE_DESCRIPTION("HiSilicon SPI Controller Driver for Kunpeng SoCs");
554MODULE_LICENSE("GPL v2");