|
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