|
3 | 3 | // Freescale i.MX7ULP LPSPI driver
|
4 | 4 | //
|
5 | 5 | // Copyright 2016 Freescale Semiconductor, Inc.
|
6 |
| -// Copyright 2018 NXP Semiconductors |
| 6 | +// Copyright 2018, 2023, 2025 NXP |
7 | 7 |
|
| 8 | +#include <linux/bitfield.h> |
8 | 9 | #include <linux/clk.h>
|
9 | 10 | #include <linux/completion.h>
|
10 | 11 | #include <linux/delay.h>
|
|
70 | 71 | #define DER_TDDE BIT(0)
|
71 | 72 | #define CFGR1_PCSCFG BIT(27)
|
72 | 73 | #define CFGR1_PINCFG (BIT(24)|BIT(25))
|
73 |
| -#define CFGR1_PCSPOL BIT(8) |
| 74 | +#define CFGR1_PCSPOL_MASK GENMASK(11, 8) |
74 | 75 | #define CFGR1_NOSTALL BIT(3)
|
75 | 76 | #define CFGR1_HOST BIT(0)
|
76 | 77 | #define FSR_TXCOUNT (0xFF)
|
|
82 | 83 | #define TCR_RXMSK BIT(19)
|
83 | 84 | #define TCR_TXMSK BIT(18)
|
84 | 85 |
|
| 86 | +#define SR_CLEAR_MASK GENMASK(13, 8) |
| 87 | + |
85 | 88 | struct fsl_lpspi_devtype_data {
|
86 |
| - u8 prescale_max; |
| 89 | + u8 prescale_max : 3; /* 0 == no limit */ |
| 90 | + bool query_hw_for_num_cs : 1; |
87 | 91 | };
|
88 | 92 |
|
89 | 93 | struct lpspi_config {
|
@@ -129,20 +133,26 @@ struct fsl_lpspi_data {
|
129 | 133 | };
|
130 | 134 |
|
131 | 135 | /*
|
132 |
| - * ERR051608 fixed or not: |
133 |
| - * https://www.nxp.com/docs/en/errata/i.MX93_1P87f.pdf |
| 136 | + * Devices with ERR051608 have a max TCR_PRESCALE value of 1, otherwise there is |
| 137 | + * no prescale limit: https://www.nxp.com/docs/en/errata/i.MX93_1P87f.pdf |
134 | 138 | */
|
135 |
| -static struct fsl_lpspi_devtype_data imx93_lpspi_devtype_data = { |
| 139 | +static const struct fsl_lpspi_devtype_data imx93_lpspi_devtype_data = { |
136 | 140 | .prescale_max = 1,
|
| 141 | + .query_hw_for_num_cs = true, |
| 142 | +}; |
| 143 | + |
| 144 | +static const struct fsl_lpspi_devtype_data imx7ulp_lpspi_devtype_data = { |
| 145 | + /* All defaults */ |
137 | 146 | };
|
138 | 147 |
|
139 |
| -static struct fsl_lpspi_devtype_data imx7ulp_lpspi_devtype_data = { |
140 |
| - .prescale_max = 7, |
| 148 | +static const struct fsl_lpspi_devtype_data s32g_lpspi_devtype_data = { |
| 149 | + .query_hw_for_num_cs = true, |
141 | 150 | };
|
142 | 151 |
|
143 | 152 | static const struct of_device_id fsl_lpspi_dt_ids[] = {
|
144 | 153 | { .compatible = "fsl,imx7ulp-spi", .data = &imx7ulp_lpspi_devtype_data,},
|
145 | 154 | { .compatible = "fsl,imx93-spi", .data = &imx93_lpspi_devtype_data,},
|
| 155 | + { .compatible = "nxp,s32g2-lpspi", .data = &s32g_lpspi_devtype_data,}, |
146 | 156 | { /* sentinel */ }
|
147 | 157 | };
|
148 | 158 | MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids);
|
@@ -321,7 +331,7 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
|
321 | 331 | int scldiv;
|
322 | 332 |
|
323 | 333 | perclk_rate = clk_get_rate(fsl_lpspi->clk_per);
|
324 |
| - prescale_max = fsl_lpspi->devtype_data->prescale_max; |
| 334 | + prescale_max = fsl_lpspi->devtype_data->prescale_max ?: 7; |
325 | 335 |
|
326 | 336 | if (!config.speed_hz) {
|
327 | 337 | dev_err(fsl_lpspi->dev,
|
@@ -423,7 +433,9 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
|
423 | 433 | else
|
424 | 434 | temp = CFGR1_PINCFG;
|
425 | 435 | if (fsl_lpspi->config.mode & SPI_CS_HIGH)
|
426 |
| - temp |= CFGR1_PCSPOL; |
| 436 | + temp |= FIELD_PREP(CFGR1_PCSPOL_MASK, |
| 437 | + BIT(fsl_lpspi->config.chip_select)); |
| 438 | + |
427 | 439 | writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1);
|
428 | 440 |
|
429 | 441 | temp = readl(fsl_lpspi->base + IMX7ULP_CR);
|
@@ -532,14 +544,13 @@ static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi)
|
532 | 544 | fsl_lpspi_intctrl(fsl_lpspi, 0);
|
533 | 545 | }
|
534 | 546 |
|
535 |
| - /* W1C for all flags in SR */ |
536 |
| - temp = 0x3F << 8; |
537 |
| - writel(temp, fsl_lpspi->base + IMX7ULP_SR); |
538 |
| - |
539 | 547 | /* Clear FIFO and disable module */
|
540 | 548 | temp = CR_RRF | CR_RTF;
|
541 | 549 | writel(temp, fsl_lpspi->base + IMX7ULP_CR);
|
542 | 550 |
|
| 551 | + /* W1C for all flags in SR */ |
| 552 | + writel(SR_CLEAR_MASK, fsl_lpspi->base + IMX7ULP_SR); |
| 553 | + |
543 | 554 | return 0;
|
544 | 555 | }
|
545 | 556 |
|
@@ -730,12 +741,10 @@ static int fsl_lpspi_pio_transfer(struct spi_controller *controller,
|
730 | 741 | fsl_lpspi_write_tx_fifo(fsl_lpspi);
|
731 | 742 |
|
732 | 743 | ret = fsl_lpspi_wait_for_completion(controller);
|
733 |
| - if (ret) |
734 |
| - return ret; |
735 | 744 |
|
736 | 745 | fsl_lpspi_reset(fsl_lpspi);
|
737 | 746 |
|
738 |
| - return 0; |
| 747 | + return ret; |
739 | 748 | }
|
740 | 749 |
|
741 | 750 | static int fsl_lpspi_transfer_one(struct spi_controller *controller,
|
@@ -785,7 +794,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
|
785 | 794 | if (temp_SR & SR_MBF ||
|
786 | 795 | readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_TXCOUNT) {
|
787 | 796 | writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
|
788 |
| - fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); |
| 797 | + fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE | (temp_IER & IER_TDIE)); |
789 | 798 | return IRQ_HANDLED;
|
790 | 799 | }
|
791 | 800 |
|
@@ -930,7 +939,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
|
930 | 939 | fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f);
|
931 | 940 | if (of_property_read_u32((&pdev->dev)->of_node, "num-cs",
|
932 | 941 | &num_cs)) {
|
933 |
| - if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx93-spi")) |
| 942 | + if (devtype_data->query_hw_for_num_cs) |
934 | 943 | num_cs = ((temp >> 16) & 0xf);
|
935 | 944 | else
|
936 | 945 | num_cs = 1;
|
|
0 commit comments