171c814e9SPrajna Rajendra Kumar // SPDX-License-Identifier: (GPL-2.0)
271c814e9SPrajna Rajendra Kumar /*
371c814e9SPrajna Rajendra Kumar * Microchip CoreSPI SPI controller driver
471c814e9SPrajna Rajendra Kumar *
571c814e9SPrajna Rajendra Kumar * Copyright (c) 2018-2022 Microchip Technology Inc. and its subsidiaries
671c814e9SPrajna Rajendra Kumar *
771c814e9SPrajna Rajendra Kumar * Author: Daire McNamara <daire.mcnamara@microchip.com>
871c814e9SPrajna Rajendra Kumar * Author: Conor Dooley <conor.dooley@microchip.com>
971c814e9SPrajna Rajendra Kumar *
1071c814e9SPrajna Rajendra Kumar */
1171c814e9SPrajna Rajendra Kumar
1271c814e9SPrajna Rajendra Kumar #include <linux/clk.h>
1371c814e9SPrajna Rajendra Kumar #include <linux/delay.h>
1471c814e9SPrajna Rajendra Kumar #include <linux/err.h>
1571c814e9SPrajna Rajendra Kumar #include <linux/init.h>
1671c814e9SPrajna Rajendra Kumar #include <linux/interrupt.h>
1771c814e9SPrajna Rajendra Kumar #include <linux/io.h>
1871c814e9SPrajna Rajendra Kumar #include <linux/module.h>
1971c814e9SPrajna Rajendra Kumar #include <linux/of.h>
2071c814e9SPrajna Rajendra Kumar #include <linux/platform_device.h>
2171c814e9SPrajna Rajendra Kumar #include <linux/spi/spi.h>
2271c814e9SPrajna Rajendra Kumar
2371c814e9SPrajna Rajendra Kumar #define MAX_LEN (0xffff)
2471c814e9SPrajna Rajendra Kumar #define MAX_CS (1)
2571c814e9SPrajna Rajendra Kumar #define DEFAULT_FRAMESIZE (8)
2671c814e9SPrajna Rajendra Kumar #define FIFO_DEPTH (32)
2771c814e9SPrajna Rajendra Kumar #define CLK_GEN_MODE1_MAX (255)
2871c814e9SPrajna Rajendra Kumar #define CLK_GEN_MODE0_MAX (15)
2971c814e9SPrajna Rajendra Kumar #define CLK_GEN_MIN (0)
3071c814e9SPrajna Rajendra Kumar #define MODE_X_MASK_SHIFT (24)
3171c814e9SPrajna Rajendra Kumar
3271c814e9SPrajna Rajendra Kumar #define CONTROL_ENABLE BIT(0)
3371c814e9SPrajna Rajendra Kumar #define CONTROL_MASTER BIT(1)
3471c814e9SPrajna Rajendra Kumar #define CONTROL_RX_DATA_INT BIT(4)
3571c814e9SPrajna Rajendra Kumar #define CONTROL_TX_DATA_INT BIT(5)
3671c814e9SPrajna Rajendra Kumar #define CONTROL_RX_OVER_INT BIT(6)
3771c814e9SPrajna Rajendra Kumar #define CONTROL_TX_UNDER_INT BIT(7)
3871c814e9SPrajna Rajendra Kumar #define CONTROL_SPO BIT(24)
3971c814e9SPrajna Rajendra Kumar #define CONTROL_SPH BIT(25)
4071c814e9SPrajna Rajendra Kumar #define CONTROL_SPS BIT(26)
4171c814e9SPrajna Rajendra Kumar #define CONTROL_FRAMEURUN BIT(27)
4271c814e9SPrajna Rajendra Kumar #define CONTROL_CLKMODE BIT(28)
4371c814e9SPrajna Rajendra Kumar #define CONTROL_BIGFIFO BIT(29)
4471c814e9SPrajna Rajendra Kumar #define CONTROL_OENOFF BIT(30)
4571c814e9SPrajna Rajendra Kumar #define CONTROL_RESET BIT(31)
4671c814e9SPrajna Rajendra Kumar
4771c814e9SPrajna Rajendra Kumar #define CONTROL_MODE_MASK GENMASK(3, 2)
4871c814e9SPrajna Rajendra Kumar #define MOTOROLA_MODE (0)
4971c814e9SPrajna Rajendra Kumar #define CONTROL_FRAMECNT_MASK GENMASK(23, 8)
5071c814e9SPrajna Rajendra Kumar #define CONTROL_FRAMECNT_SHIFT (8)
5171c814e9SPrajna Rajendra Kumar
5271c814e9SPrajna Rajendra Kumar #define STATUS_ACTIVE BIT(14)
5371c814e9SPrajna Rajendra Kumar #define STATUS_SSEL BIT(13)
5471c814e9SPrajna Rajendra Kumar #define STATUS_FRAMESTART BIT(12)
5571c814e9SPrajna Rajendra Kumar #define STATUS_TXFIFO_EMPTY_NEXT_READ BIT(11)
5671c814e9SPrajna Rajendra Kumar #define STATUS_TXFIFO_EMPTY BIT(10)
5771c814e9SPrajna Rajendra Kumar #define STATUS_TXFIFO_FULL_NEXT_WRITE BIT(9)
5871c814e9SPrajna Rajendra Kumar #define STATUS_TXFIFO_FULL BIT(8)
5971c814e9SPrajna Rajendra Kumar #define STATUS_RXFIFO_EMPTY_NEXT_READ BIT(7)
6071c814e9SPrajna Rajendra Kumar #define STATUS_RXFIFO_EMPTY BIT(6)
6171c814e9SPrajna Rajendra Kumar #define STATUS_RXFIFO_FULL_NEXT_WRITE BIT(5)
6271c814e9SPrajna Rajendra Kumar #define STATUS_RXFIFO_FULL BIT(4)
6371c814e9SPrajna Rajendra Kumar #define STATUS_TX_UNDERRUN BIT(3)
6471c814e9SPrajna Rajendra Kumar #define STATUS_RX_OVERFLOW BIT(2)
6571c814e9SPrajna Rajendra Kumar #define STATUS_RXDAT_RXED BIT(1)
6671c814e9SPrajna Rajendra Kumar #define STATUS_TXDAT_SENT BIT(0)
6771c814e9SPrajna Rajendra Kumar
6871c814e9SPrajna Rajendra Kumar #define INT_TXDONE BIT(0)
6971c814e9SPrajna Rajendra Kumar #define INT_RXRDY BIT(1)
7071c814e9SPrajna Rajendra Kumar #define INT_RX_CHANNEL_OVERFLOW BIT(2)
7171c814e9SPrajna Rajendra Kumar #define INT_TX_CHANNEL_UNDERRUN BIT(3)
7271c814e9SPrajna Rajendra Kumar
7371c814e9SPrajna Rajendra Kumar #define INT_ENABLE_MASK (CONTROL_RX_OVER_INT | CONTROL_TX_UNDER_INT)
7471c814e9SPrajna Rajendra Kumar
7571c814e9SPrajna Rajendra Kumar #define REG_CONTROL (0x00)
7671c814e9SPrajna Rajendra Kumar #define REG_FRAME_SIZE (0x04)
7771c814e9SPrajna Rajendra Kumar #define FRAME_SIZE_MASK GENMASK(5, 0)
7871c814e9SPrajna Rajendra Kumar #define REG_STATUS (0x08)
7971c814e9SPrajna Rajendra Kumar #define REG_INT_CLEAR (0x0c)
8071c814e9SPrajna Rajendra Kumar #define REG_RX_DATA (0x10)
8171c814e9SPrajna Rajendra Kumar #define REG_TX_DATA (0x14)
8271c814e9SPrajna Rajendra Kumar #define REG_CLK_GEN (0x18)
8371c814e9SPrajna Rajendra Kumar #define REG_SLAVE_SELECT (0x1c)
8471c814e9SPrajna Rajendra Kumar #define SSEL_MASK GENMASK(7, 0)
8571c814e9SPrajna Rajendra Kumar #define SSEL_DIRECT BIT(8)
8671c814e9SPrajna Rajendra Kumar #define SSELOUT_SHIFT 9
8771c814e9SPrajna Rajendra Kumar #define SSELOUT BIT(SSELOUT_SHIFT)
8871c814e9SPrajna Rajendra Kumar #define REG_MIS (0x20)
8971c814e9SPrajna Rajendra Kumar #define REG_RIS (0x24)
9071c814e9SPrajna Rajendra Kumar #define REG_CONTROL2 (0x28)
9171c814e9SPrajna Rajendra Kumar #define REG_COMMAND (0x2c)
9271c814e9SPrajna Rajendra Kumar #define COMMAND_CLRFRAMECNT BIT(4)
9371c814e9SPrajna Rajendra Kumar #define COMMAND_TXFIFORST BIT(3)
9471c814e9SPrajna Rajendra Kumar #define COMMAND_RXFIFORST BIT(2)
9571c814e9SPrajna Rajendra Kumar #define REG_PKTSIZE (0x30)
9671c814e9SPrajna Rajendra Kumar #define REG_CMD_SIZE (0x34)
9771c814e9SPrajna Rajendra Kumar #define REG_HWSTATUS (0x38)
9871c814e9SPrajna Rajendra Kumar #define REG_STAT8 (0x3c)
9971c814e9SPrajna Rajendra Kumar #define REG_CTRL2 (0x48)
10071c814e9SPrajna Rajendra Kumar #define REG_FRAMESUP (0x50)
10171c814e9SPrajna Rajendra Kumar
10271c814e9SPrajna Rajendra Kumar struct mpfs_spi {
10371c814e9SPrajna Rajendra Kumar void __iomem *regs;
10471c814e9SPrajna Rajendra Kumar struct clk *clk;
10571c814e9SPrajna Rajendra Kumar const u8 *tx_buf;
10671c814e9SPrajna Rajendra Kumar u8 *rx_buf;
10771c814e9SPrajna Rajendra Kumar u32 clk_gen; /* divider for spi output clock generated by the controller */
10871c814e9SPrajna Rajendra Kumar u32 clk_mode;
10971c814e9SPrajna Rajendra Kumar u32 pending_slave_select;
11071c814e9SPrajna Rajendra Kumar int irq;
11171c814e9SPrajna Rajendra Kumar int tx_len;
11271c814e9SPrajna Rajendra Kumar int rx_len;
11371c814e9SPrajna Rajendra Kumar int n_bytes;
11471c814e9SPrajna Rajendra Kumar };
11571c814e9SPrajna Rajendra Kumar
mpfs_spi_read(struct mpfs_spi * spi,unsigned int reg)11671c814e9SPrajna Rajendra Kumar static inline u32 mpfs_spi_read(struct mpfs_spi *spi, unsigned int reg)
11771c814e9SPrajna Rajendra Kumar {
11871c814e9SPrajna Rajendra Kumar return readl(spi->regs + reg);
11971c814e9SPrajna Rajendra Kumar }
12071c814e9SPrajna Rajendra Kumar
mpfs_spi_write(struct mpfs_spi * spi,unsigned int reg,u32 val)12171c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_write(struct mpfs_spi *spi, unsigned int reg, u32 val)
12271c814e9SPrajna Rajendra Kumar {
12371c814e9SPrajna Rajendra Kumar writel(val, spi->regs + reg);
12471c814e9SPrajna Rajendra Kumar }
12571c814e9SPrajna Rajendra Kumar
mpfs_spi_disable(struct mpfs_spi * spi)12671c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_disable(struct mpfs_spi *spi)
12771c814e9SPrajna Rajendra Kumar {
12871c814e9SPrajna Rajendra Kumar u32 control = mpfs_spi_read(spi, REG_CONTROL);
12971c814e9SPrajna Rajendra Kumar
13071c814e9SPrajna Rajendra Kumar control &= ~CONTROL_ENABLE;
13171c814e9SPrajna Rajendra Kumar
13271c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
13371c814e9SPrajna Rajendra Kumar }
13471c814e9SPrajna Rajendra Kumar
mpfs_spi_read_fifo(struct mpfs_spi * spi,int fifo_max)13571c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_read_fifo(struct mpfs_spi *spi, int fifo_max)
13671c814e9SPrajna Rajendra Kumar {
13771c814e9SPrajna Rajendra Kumar for (int i = 0; i < fifo_max; i++) {
13871c814e9SPrajna Rajendra Kumar u32 data;
13971c814e9SPrajna Rajendra Kumar
14071c814e9SPrajna Rajendra Kumar while (mpfs_spi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)
14171c814e9SPrajna Rajendra Kumar ;
14271c814e9SPrajna Rajendra Kumar
14371c814e9SPrajna Rajendra Kumar data = mpfs_spi_read(spi, REG_RX_DATA);
14471c814e9SPrajna Rajendra Kumar
14571c814e9SPrajna Rajendra Kumar spi->rx_len -= spi->n_bytes;
14671c814e9SPrajna Rajendra Kumar
14771c814e9SPrajna Rajendra Kumar if (!spi->rx_buf)
14871c814e9SPrajna Rajendra Kumar continue;
14971c814e9SPrajna Rajendra Kumar
15071c814e9SPrajna Rajendra Kumar if (spi->n_bytes == 4)
15171c814e9SPrajna Rajendra Kumar *((u32 *)spi->rx_buf) = data;
15271c814e9SPrajna Rajendra Kumar else if (spi->n_bytes == 2)
15371c814e9SPrajna Rajendra Kumar *((u16 *)spi->rx_buf) = data;
15471c814e9SPrajna Rajendra Kumar else
15571c814e9SPrajna Rajendra Kumar *spi->rx_buf = data;
15671c814e9SPrajna Rajendra Kumar
15771c814e9SPrajna Rajendra Kumar spi->rx_buf += spi->n_bytes;
15871c814e9SPrajna Rajendra Kumar }
15971c814e9SPrajna Rajendra Kumar }
16071c814e9SPrajna Rajendra Kumar
mpfs_spi_enable_ints(struct mpfs_spi * spi)16171c814e9SPrajna Rajendra Kumar static void mpfs_spi_enable_ints(struct mpfs_spi *spi)
16271c814e9SPrajna Rajendra Kumar {
16371c814e9SPrajna Rajendra Kumar u32 control = mpfs_spi_read(spi, REG_CONTROL);
16471c814e9SPrajna Rajendra Kumar
16571c814e9SPrajna Rajendra Kumar control |= INT_ENABLE_MASK;
16671c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
16771c814e9SPrajna Rajendra Kumar }
16871c814e9SPrajna Rajendra Kumar
mpfs_spi_disable_ints(struct mpfs_spi * spi)16971c814e9SPrajna Rajendra Kumar static void mpfs_spi_disable_ints(struct mpfs_spi *spi)
17071c814e9SPrajna Rajendra Kumar {
17171c814e9SPrajna Rajendra Kumar u32 control = mpfs_spi_read(spi, REG_CONTROL);
17271c814e9SPrajna Rajendra Kumar
17371c814e9SPrajna Rajendra Kumar control &= ~INT_ENABLE_MASK;
17471c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
17571c814e9SPrajna Rajendra Kumar }
17671c814e9SPrajna Rajendra Kumar
mpfs_spi_set_xfer_size(struct mpfs_spi * spi,int len)17771c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_set_xfer_size(struct mpfs_spi *spi, int len)
17871c814e9SPrajna Rajendra Kumar {
17971c814e9SPrajna Rajendra Kumar u32 control;
18071c814e9SPrajna Rajendra Kumar u32 lenpart;
18171c814e9SPrajna Rajendra Kumar u32 frames = mpfs_spi_read(spi, REG_FRAMESUP);
18271c814e9SPrajna Rajendra Kumar
18371c814e9SPrajna Rajendra Kumar /*
18471c814e9SPrajna Rajendra Kumar * Writing to FRAMECNT in REG_CONTROL will reset the frame count, taking
18571c814e9SPrajna Rajendra Kumar * a shortcut requires an explicit clear.
18671c814e9SPrajna Rajendra Kumar */
18771c814e9SPrajna Rajendra Kumar if (frames == len) {
18871c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_COMMAND, COMMAND_CLRFRAMECNT);
18971c814e9SPrajna Rajendra Kumar return;
19071c814e9SPrajna Rajendra Kumar }
19171c814e9SPrajna Rajendra Kumar
19271c814e9SPrajna Rajendra Kumar /*
19371c814e9SPrajna Rajendra Kumar * The lower 16 bits of the frame count are stored in the control reg
19471c814e9SPrajna Rajendra Kumar * for legacy reasons, but the upper 16 written to a different register:
19571c814e9SPrajna Rajendra Kumar * FRAMESUP. While both the upper and lower bits can be *READ* from the
19671c814e9SPrajna Rajendra Kumar * FRAMESUP register, writing to the lower 16 bits is (supposedly) a NOP.
19771c814e9SPrajna Rajendra Kumar *
19871c814e9SPrajna Rajendra Kumar * The driver used to disable the controller while modifying the frame
19971c814e9SPrajna Rajendra Kumar * count, and mask off the lower 16 bits of len while writing to
20071c814e9SPrajna Rajendra Kumar * FRAMES_UP. When the driver was changed to disable the controller as
20171c814e9SPrajna Rajendra Kumar * infrequently as possible, it was discovered that the logic of
20271c814e9SPrajna Rajendra Kumar * lenpart = len & 0xffff_0000
20371c814e9SPrajna Rajendra Kumar * write(REG_FRAMESUP, lenpart)
20471c814e9SPrajna Rajendra Kumar * would actually write zeros into the lower 16 bits on an mpfs250t-es,
20571c814e9SPrajna Rajendra Kumar * despite documentation stating these bits were read-only.
20671c814e9SPrajna Rajendra Kumar * Writing len unmasked into FRAMES_UP ensures those bits aren't zeroed
20771c814e9SPrajna Rajendra Kumar * on an mpfs250t-es and will be a NOP for the lower 16 bits on hardware
20871c814e9SPrajna Rajendra Kumar * that matches the documentation.
20971c814e9SPrajna Rajendra Kumar */
21071c814e9SPrajna Rajendra Kumar lenpart = len & 0xffff;
21171c814e9SPrajna Rajendra Kumar control = mpfs_spi_read(spi, REG_CONTROL);
21271c814e9SPrajna Rajendra Kumar control &= ~CONTROL_FRAMECNT_MASK;
21371c814e9SPrajna Rajendra Kumar control |= lenpart << CONTROL_FRAMECNT_SHIFT;
21471c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
21571c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_FRAMESUP, len);
21671c814e9SPrajna Rajendra Kumar }
21771c814e9SPrajna Rajendra Kumar
mpfs_spi_write_fifo(struct mpfs_spi * spi,int fifo_max)21871c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_write_fifo(struct mpfs_spi *spi, int fifo_max)
21971c814e9SPrajna Rajendra Kumar {
22071c814e9SPrajna Rajendra Kumar int i = 0;
22171c814e9SPrajna Rajendra Kumar
22271c814e9SPrajna Rajendra Kumar mpfs_spi_set_xfer_size(spi, fifo_max);
22371c814e9SPrajna Rajendra Kumar
22471c814e9SPrajna Rajendra Kumar while ((i < fifo_max) && !(mpfs_spi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) {
22571c814e9SPrajna Rajendra Kumar u32 word;
22671c814e9SPrajna Rajendra Kumar
22771c814e9SPrajna Rajendra Kumar if (spi->n_bytes == 4)
22871c814e9SPrajna Rajendra Kumar word = spi->tx_buf ? *((u32 *)spi->tx_buf) : 0xaa;
22971c814e9SPrajna Rajendra Kumar else if (spi->n_bytes == 2)
23071c814e9SPrajna Rajendra Kumar word = spi->tx_buf ? *((u16 *)spi->tx_buf) : 0xaa;
23171c814e9SPrajna Rajendra Kumar else
23271c814e9SPrajna Rajendra Kumar word = spi->tx_buf ? *spi->tx_buf : 0xaa;
23371c814e9SPrajna Rajendra Kumar
23471c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_TX_DATA, word);
23571c814e9SPrajna Rajendra Kumar if (spi->tx_buf)
23671c814e9SPrajna Rajendra Kumar spi->tx_buf += spi->n_bytes;
23771c814e9SPrajna Rajendra Kumar i++;
23871c814e9SPrajna Rajendra Kumar }
23971c814e9SPrajna Rajendra Kumar
24071c814e9SPrajna Rajendra Kumar spi->tx_len -= i * spi->n_bytes;
24171c814e9SPrajna Rajendra Kumar }
24271c814e9SPrajna Rajendra Kumar
mpfs_spi_set_framesize(struct mpfs_spi * spi,int bt)24371c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_set_framesize(struct mpfs_spi *spi, int bt)
24471c814e9SPrajna Rajendra Kumar {
24571c814e9SPrajna Rajendra Kumar u32 frame_size = mpfs_spi_read(spi, REG_FRAME_SIZE);
24671c814e9SPrajna Rajendra Kumar u32 control;
24771c814e9SPrajna Rajendra Kumar
24871c814e9SPrajna Rajendra Kumar if ((frame_size & FRAME_SIZE_MASK) == bt)
24971c814e9SPrajna Rajendra Kumar return;
25071c814e9SPrajna Rajendra Kumar
25171c814e9SPrajna Rajendra Kumar /*
25271c814e9SPrajna Rajendra Kumar * Disable the SPI controller. Writes to the frame size have
25371c814e9SPrajna Rajendra Kumar * no effect when the controller is enabled.
25471c814e9SPrajna Rajendra Kumar */
25571c814e9SPrajna Rajendra Kumar control = mpfs_spi_read(spi, REG_CONTROL);
25671c814e9SPrajna Rajendra Kumar control &= ~CONTROL_ENABLE;
25771c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
25871c814e9SPrajna Rajendra Kumar
25971c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_FRAME_SIZE, bt);
26071c814e9SPrajna Rajendra Kumar
26171c814e9SPrajna Rajendra Kumar control |= CONTROL_ENABLE;
26271c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
26371c814e9SPrajna Rajendra Kumar }
26471c814e9SPrajna Rajendra Kumar
mpfs_spi_set_cs(struct spi_device * spi,bool disable)26571c814e9SPrajna Rajendra Kumar static void mpfs_spi_set_cs(struct spi_device *spi, bool disable)
26671c814e9SPrajna Rajendra Kumar {
26771c814e9SPrajna Rajendra Kumar u32 reg;
26871c814e9SPrajna Rajendra Kumar struct mpfs_spi *mspi = spi_controller_get_devdata(spi->controller);
26971c814e9SPrajna Rajendra Kumar
27071c814e9SPrajna Rajendra Kumar reg = mpfs_spi_read(mspi, REG_SLAVE_SELECT);
27171c814e9SPrajna Rajendra Kumar reg &= ~BIT(spi_get_chipselect(spi, 0));
27271c814e9SPrajna Rajendra Kumar reg |= !disable << spi_get_chipselect(spi, 0);
27371c814e9SPrajna Rajendra Kumar mspi->pending_slave_select = reg;
27471c814e9SPrajna Rajendra Kumar
27571c814e9SPrajna Rajendra Kumar /*
27671c814e9SPrajna Rajendra Kumar * Only deassert chip select immediately. Writing to some registers
27771c814e9SPrajna Rajendra Kumar * requires the controller to be disabled, which results in the
27871c814e9SPrajna Rajendra Kumar * output pins being tristated and can cause the SCLK and MOSI lines
27971c814e9SPrajna Rajendra Kumar * to transition. Therefore asserting the chip select is deferred
28071c814e9SPrajna Rajendra Kumar * until just before writing to the TX FIFO, to ensure the device
28171c814e9SPrajna Rajendra Kumar * doesn't see any spurious clock transitions whilst CS is enabled.
28271c814e9SPrajna Rajendra Kumar */
28371c814e9SPrajna Rajendra Kumar if (((spi->mode & SPI_CS_HIGH) == 0) == disable)
28471c814e9SPrajna Rajendra Kumar mpfs_spi_write(mspi, REG_SLAVE_SELECT, reg);
28571c814e9SPrajna Rajendra Kumar }
28671c814e9SPrajna Rajendra Kumar
mpfs_spi_setup(struct spi_device * spi)28771c814e9SPrajna Rajendra Kumar static int mpfs_spi_setup(struct spi_device *spi)
28871c814e9SPrajna Rajendra Kumar {
28971c814e9SPrajna Rajendra Kumar struct mpfs_spi *mspi = spi_controller_get_devdata(spi->controller);
29071c814e9SPrajna Rajendra Kumar u32 reg;
29171c814e9SPrajna Rajendra Kumar
29271c814e9SPrajna Rajendra Kumar if (spi_is_csgpiod(spi))
29371c814e9SPrajna Rajendra Kumar return 0;
29471c814e9SPrajna Rajendra Kumar
29571c814e9SPrajna Rajendra Kumar /*
29671c814e9SPrajna Rajendra Kumar * Active high targets need to be specifically set to their inactive
29771c814e9SPrajna Rajendra Kumar * states during probe by adding them to the "control group" & thus
29871c814e9SPrajna Rajendra Kumar * driving their select line low.
29971c814e9SPrajna Rajendra Kumar */
30071c814e9SPrajna Rajendra Kumar if (spi->mode & SPI_CS_HIGH) {
30171c814e9SPrajna Rajendra Kumar reg = mpfs_spi_read(mspi, REG_SLAVE_SELECT);
30271c814e9SPrajna Rajendra Kumar reg |= BIT(spi_get_chipselect(spi, 0));
30371c814e9SPrajna Rajendra Kumar mspi->pending_slave_select = reg;
30471c814e9SPrajna Rajendra Kumar mpfs_spi_write(mspi, REG_SLAVE_SELECT, reg);
30571c814e9SPrajna Rajendra Kumar }
30671c814e9SPrajna Rajendra Kumar return 0;
30771c814e9SPrajna Rajendra Kumar }
30871c814e9SPrajna Rajendra Kumar
mpfs_spi_init(struct spi_controller * host,struct mpfs_spi * spi)30971c814e9SPrajna Rajendra Kumar static void mpfs_spi_init(struct spi_controller *host, struct mpfs_spi *spi)
31071c814e9SPrajna Rajendra Kumar {
31171c814e9SPrajna Rajendra Kumar unsigned long clk_hz;
31271c814e9SPrajna Rajendra Kumar u32 control = mpfs_spi_read(spi, REG_CONTROL);
31371c814e9SPrajna Rajendra Kumar
31471c814e9SPrajna Rajendra Kumar control &= ~CONTROL_ENABLE;
31571c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
31671c814e9SPrajna Rajendra Kumar
31771c814e9SPrajna Rajendra Kumar control |= CONTROL_MASTER;
31871c814e9SPrajna Rajendra Kumar control &= ~CONTROL_MODE_MASK;
31971c814e9SPrajna Rajendra Kumar control |= MOTOROLA_MODE;
32071c814e9SPrajna Rajendra Kumar
32171c814e9SPrajna Rajendra Kumar /*
32271c814e9SPrajna Rajendra Kumar * The controller must be configured so that it doesn't remove Chip
32371c814e9SPrajna Rajendra Kumar * Select until the entire message has been transferred, even if at
32471c814e9SPrajna Rajendra Kumar * some points TX FIFO becomes empty.
32571c814e9SPrajna Rajendra Kumar *
32671c814e9SPrajna Rajendra Kumar * BIGFIFO mode is also enabled, which sets the fifo depth to 32 frames
32771c814e9SPrajna Rajendra Kumar * for the 8 bit transfers that this driver uses.
32871c814e9SPrajna Rajendra Kumar */
32971c814e9SPrajna Rajendra Kumar control |= CONTROL_SPS | CONTROL_BIGFIFO;
33071c814e9SPrajna Rajendra Kumar
33171c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
33271c814e9SPrajna Rajendra Kumar
33371c814e9SPrajna Rajendra Kumar mpfs_spi_set_framesize(spi, DEFAULT_FRAMESIZE);
33471c814e9SPrajna Rajendra Kumar
33571c814e9SPrajna Rajendra Kumar /* max. possible spi clock rate is the apb clock rate */
33671c814e9SPrajna Rajendra Kumar clk_hz = clk_get_rate(spi->clk);
33771c814e9SPrajna Rajendra Kumar host->max_speed_hz = clk_hz;
33871c814e9SPrajna Rajendra Kumar
33971c814e9SPrajna Rajendra Kumar mpfs_spi_enable_ints(spi);
34071c814e9SPrajna Rajendra Kumar
34171c814e9SPrajna Rajendra Kumar /*
34271c814e9SPrajna Rajendra Kumar * It is required to enable direct mode, otherwise control over the chip
34371c814e9SPrajna Rajendra Kumar * select is relinquished to the hardware. SSELOUT is enabled too so we
34471c814e9SPrajna Rajendra Kumar * can deal with active high targets.
34571c814e9SPrajna Rajendra Kumar */
34671c814e9SPrajna Rajendra Kumar spi->pending_slave_select = SSELOUT | SSEL_DIRECT;
34771c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select);
34871c814e9SPrajna Rajendra Kumar
34971c814e9SPrajna Rajendra Kumar control = mpfs_spi_read(spi, REG_CONTROL);
35071c814e9SPrajna Rajendra Kumar
35171c814e9SPrajna Rajendra Kumar control &= ~CONTROL_RESET;
35271c814e9SPrajna Rajendra Kumar control |= CONTROL_ENABLE;
35371c814e9SPrajna Rajendra Kumar
35471c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
35571c814e9SPrajna Rajendra Kumar }
35671c814e9SPrajna Rajendra Kumar
mpfs_spi_set_clk_gen(struct mpfs_spi * spi)35771c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_set_clk_gen(struct mpfs_spi *spi)
35871c814e9SPrajna Rajendra Kumar {
35971c814e9SPrajna Rajendra Kumar u32 control;
36071c814e9SPrajna Rajendra Kumar
36171c814e9SPrajna Rajendra Kumar control = mpfs_spi_read(spi, REG_CONTROL);
36271c814e9SPrajna Rajendra Kumar if (spi->clk_mode)
36371c814e9SPrajna Rajendra Kumar control |= CONTROL_CLKMODE;
36471c814e9SPrajna Rajendra Kumar else
36571c814e9SPrajna Rajendra Kumar control &= ~CONTROL_CLKMODE;
36671c814e9SPrajna Rajendra Kumar
36771c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CLK_GEN, spi->clk_gen);
36871c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
36971c814e9SPrajna Rajendra Kumar }
37071c814e9SPrajna Rajendra Kumar
mpfs_spi_set_mode(struct mpfs_spi * spi,unsigned int mode)37171c814e9SPrajna Rajendra Kumar static inline void mpfs_spi_set_mode(struct mpfs_spi *spi, unsigned int mode)
37271c814e9SPrajna Rajendra Kumar {
37371c814e9SPrajna Rajendra Kumar u32 mode_val;
37471c814e9SPrajna Rajendra Kumar u32 control = mpfs_spi_read(spi, REG_CONTROL);
37571c814e9SPrajna Rajendra Kumar
37671c814e9SPrajna Rajendra Kumar switch (mode & SPI_MODE_X_MASK) {
37771c814e9SPrajna Rajendra Kumar case SPI_MODE_0:
37871c814e9SPrajna Rajendra Kumar mode_val = 0;
37971c814e9SPrajna Rajendra Kumar break;
38071c814e9SPrajna Rajendra Kumar case SPI_MODE_1:
38171c814e9SPrajna Rajendra Kumar mode_val = CONTROL_SPH;
38271c814e9SPrajna Rajendra Kumar break;
38371c814e9SPrajna Rajendra Kumar case SPI_MODE_2:
38471c814e9SPrajna Rajendra Kumar mode_val = CONTROL_SPO;
38571c814e9SPrajna Rajendra Kumar break;
38671c814e9SPrajna Rajendra Kumar case SPI_MODE_3:
38771c814e9SPrajna Rajendra Kumar mode_val = CONTROL_SPH | CONTROL_SPO;
38871c814e9SPrajna Rajendra Kumar break;
38971c814e9SPrajna Rajendra Kumar }
39071c814e9SPrajna Rajendra Kumar
39171c814e9SPrajna Rajendra Kumar /*
39271c814e9SPrajna Rajendra Kumar * Disable the SPI controller. Writes to the frame protocol have
39371c814e9SPrajna Rajendra Kumar * no effect when the controller is enabled.
39471c814e9SPrajna Rajendra Kumar */
39571c814e9SPrajna Rajendra Kumar
39671c814e9SPrajna Rajendra Kumar control &= ~CONTROL_ENABLE;
39771c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
39871c814e9SPrajna Rajendra Kumar
39971c814e9SPrajna Rajendra Kumar control &= ~(SPI_MODE_X_MASK << MODE_X_MASK_SHIFT);
40071c814e9SPrajna Rajendra Kumar control |= mode_val;
40171c814e9SPrajna Rajendra Kumar
40271c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
40371c814e9SPrajna Rajendra Kumar
40471c814e9SPrajna Rajendra Kumar control |= CONTROL_ENABLE;
40571c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_CONTROL, control);
40671c814e9SPrajna Rajendra Kumar }
40771c814e9SPrajna Rajendra Kumar
mpfs_spi_interrupt(int irq,void * dev_id)40871c814e9SPrajna Rajendra Kumar static irqreturn_t mpfs_spi_interrupt(int irq, void *dev_id)
40971c814e9SPrajna Rajendra Kumar {
41071c814e9SPrajna Rajendra Kumar struct spi_controller *host = dev_id;
41171c814e9SPrajna Rajendra Kumar struct mpfs_spi *spi = spi_controller_get_devdata(host);
41271c814e9SPrajna Rajendra Kumar u32 intfield = mpfs_spi_read(spi, REG_MIS) & 0xf;
41371c814e9SPrajna Rajendra Kumar bool finalise = false;
41471c814e9SPrajna Rajendra Kumar
41571c814e9SPrajna Rajendra Kumar /* Interrupt line may be shared and not for us at all */
41671c814e9SPrajna Rajendra Kumar if (intfield == 0)
41771c814e9SPrajna Rajendra Kumar return IRQ_NONE;
41871c814e9SPrajna Rajendra Kumar
41971c814e9SPrajna Rajendra Kumar if (intfield & INT_RX_CHANNEL_OVERFLOW) {
42071c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW);
42171c814e9SPrajna Rajendra Kumar finalise = true;
42271c814e9SPrajna Rajendra Kumar dev_err(&host->dev,
42371c814e9SPrajna Rajendra Kumar "%s: RX OVERFLOW: rxlen: %d, txlen: %d\n", __func__,
42471c814e9SPrajna Rajendra Kumar spi->rx_len, spi->tx_len);
42571c814e9SPrajna Rajendra Kumar }
42671c814e9SPrajna Rajendra Kumar
42771c814e9SPrajna Rajendra Kumar if (intfield & INT_TX_CHANNEL_UNDERRUN) {
42871c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN);
42971c814e9SPrajna Rajendra Kumar finalise = true;
43071c814e9SPrajna Rajendra Kumar dev_err(&host->dev,
43171c814e9SPrajna Rajendra Kumar "%s: TX UNDERFLOW: rxlen: %d, txlen: %d\n", __func__,
43271c814e9SPrajna Rajendra Kumar spi->rx_len, spi->tx_len);
43371c814e9SPrajna Rajendra Kumar }
43471c814e9SPrajna Rajendra Kumar
43571c814e9SPrajna Rajendra Kumar if (finalise)
43671c814e9SPrajna Rajendra Kumar spi_finalize_current_transfer(host);
43771c814e9SPrajna Rajendra Kumar
43871c814e9SPrajna Rajendra Kumar return IRQ_HANDLED;
43971c814e9SPrajna Rajendra Kumar }
44071c814e9SPrajna Rajendra Kumar
mpfs_spi_calculate_clkgen(struct mpfs_spi * spi,unsigned long target_hz)44171c814e9SPrajna Rajendra Kumar static int mpfs_spi_calculate_clkgen(struct mpfs_spi *spi,
44271c814e9SPrajna Rajendra Kumar unsigned long target_hz)
44371c814e9SPrajna Rajendra Kumar {
44471c814e9SPrajna Rajendra Kumar unsigned long clk_hz, spi_hz, clk_gen;
44571c814e9SPrajna Rajendra Kumar
44671c814e9SPrajna Rajendra Kumar clk_hz = clk_get_rate(spi->clk);
44771c814e9SPrajna Rajendra Kumar if (!clk_hz)
44871c814e9SPrajna Rajendra Kumar return -EINVAL;
44971c814e9SPrajna Rajendra Kumar spi_hz = min(target_hz, clk_hz);
45071c814e9SPrajna Rajendra Kumar
45171c814e9SPrajna Rajendra Kumar /*
45271c814e9SPrajna Rajendra Kumar * There are two possible clock modes for the controller generated
45371c814e9SPrajna Rajendra Kumar * clock's division ratio:
45471c814e9SPrajna Rajendra Kumar * CLK_MODE = 0: 1 / (2^(CLK_GEN + 1)) where CLK_GEN = 0 to 15.
45571c814e9SPrajna Rajendra Kumar * CLK_MODE = 1: 1 / (2 * CLK_GEN + 1) where CLK_GEN = 0 to 255.
45671c814e9SPrajna Rajendra Kumar * First try mode 1, fall back to 0 and if we have tried both modes and
45771c814e9SPrajna Rajendra Kumar * we /still/ can't get a good setting, we then throw the toys out of
45871c814e9SPrajna Rajendra Kumar * the pram and give up
45971c814e9SPrajna Rajendra Kumar * clk_gen is the register name for the clock divider on MPFS.
46071c814e9SPrajna Rajendra Kumar */
46171c814e9SPrajna Rajendra Kumar clk_gen = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1;
46271c814e9SPrajna Rajendra Kumar if (clk_gen > CLK_GEN_MODE1_MAX || clk_gen <= CLK_GEN_MIN) {
46371c814e9SPrajna Rajendra Kumar clk_gen = DIV_ROUND_UP(clk_hz, spi_hz);
46471c814e9SPrajna Rajendra Kumar clk_gen = fls(clk_gen) - 1;
46571c814e9SPrajna Rajendra Kumar
46671c814e9SPrajna Rajendra Kumar if (clk_gen > CLK_GEN_MODE0_MAX)
46771c814e9SPrajna Rajendra Kumar return -EINVAL;
46871c814e9SPrajna Rajendra Kumar
46971c814e9SPrajna Rajendra Kumar spi->clk_mode = 0;
47071c814e9SPrajna Rajendra Kumar } else {
47171c814e9SPrajna Rajendra Kumar spi->clk_mode = 1;
47271c814e9SPrajna Rajendra Kumar }
47371c814e9SPrajna Rajendra Kumar
47471c814e9SPrajna Rajendra Kumar spi->clk_gen = clk_gen;
47571c814e9SPrajna Rajendra Kumar return 0;
47671c814e9SPrajna Rajendra Kumar }
47771c814e9SPrajna Rajendra Kumar
mpfs_spi_transfer_one(struct spi_controller * host,struct spi_device * spi_dev,struct spi_transfer * xfer)47871c814e9SPrajna Rajendra Kumar static int mpfs_spi_transfer_one(struct spi_controller *host,
47971c814e9SPrajna Rajendra Kumar struct spi_device *spi_dev,
48071c814e9SPrajna Rajendra Kumar struct spi_transfer *xfer)
48171c814e9SPrajna Rajendra Kumar {
48271c814e9SPrajna Rajendra Kumar struct mpfs_spi *spi = spi_controller_get_devdata(host);
48371c814e9SPrajna Rajendra Kumar int ret;
48471c814e9SPrajna Rajendra Kumar
48571c814e9SPrajna Rajendra Kumar ret = mpfs_spi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz);
48671c814e9SPrajna Rajendra Kumar if (ret) {
48771c814e9SPrajna Rajendra Kumar dev_err(&host->dev, "failed to set clk_gen for target %u Hz\n", xfer->speed_hz);
48871c814e9SPrajna Rajendra Kumar return ret;
48971c814e9SPrajna Rajendra Kumar }
49071c814e9SPrajna Rajendra Kumar
49171c814e9SPrajna Rajendra Kumar mpfs_spi_set_clk_gen(spi);
49271c814e9SPrajna Rajendra Kumar
49371c814e9SPrajna Rajendra Kumar spi->tx_buf = xfer->tx_buf;
49471c814e9SPrajna Rajendra Kumar spi->rx_buf = xfer->rx_buf;
49571c814e9SPrajna Rajendra Kumar spi->tx_len = xfer->len;
49671c814e9SPrajna Rajendra Kumar spi->rx_len = xfer->len;
49771c814e9SPrajna Rajendra Kumar spi->n_bytes = roundup_pow_of_two(DIV_ROUND_UP(xfer->bits_per_word, BITS_PER_BYTE));
49871c814e9SPrajna Rajendra Kumar
49971c814e9SPrajna Rajendra Kumar mpfs_spi_set_framesize(spi, xfer->bits_per_word);
50071c814e9SPrajna Rajendra Kumar
50171c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_COMMAND, COMMAND_RXFIFORST | COMMAND_TXFIFORST);
50271c814e9SPrajna Rajendra Kumar
50371c814e9SPrajna Rajendra Kumar mpfs_spi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select);
50471c814e9SPrajna Rajendra Kumar
50571c814e9SPrajna Rajendra Kumar while (spi->tx_len) {
50671c814e9SPrajna Rajendra Kumar int fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes);
50771c814e9SPrajna Rajendra Kumar
50871c814e9SPrajna Rajendra Kumar mpfs_spi_write_fifo(spi, fifo_max);
50971c814e9SPrajna Rajendra Kumar mpfs_spi_read_fifo(spi, fifo_max);
51071c814e9SPrajna Rajendra Kumar }
51171c814e9SPrajna Rajendra Kumar
51271c814e9SPrajna Rajendra Kumar spi_finalize_current_transfer(host);
51371c814e9SPrajna Rajendra Kumar return 1;
51471c814e9SPrajna Rajendra Kumar }
51571c814e9SPrajna Rajendra Kumar
mpfs_spi_prepare_message(struct spi_controller * host,struct spi_message * msg)51671c814e9SPrajna Rajendra Kumar static int mpfs_spi_prepare_message(struct spi_controller *host,
51771c814e9SPrajna Rajendra Kumar struct spi_message *msg)
51871c814e9SPrajna Rajendra Kumar {
51971c814e9SPrajna Rajendra Kumar struct spi_device *spi_dev = msg->spi;
52071c814e9SPrajna Rajendra Kumar struct mpfs_spi *spi = spi_controller_get_devdata(host);
52171c814e9SPrajna Rajendra Kumar
52271c814e9SPrajna Rajendra Kumar mpfs_spi_set_mode(spi, spi_dev->mode);
52371c814e9SPrajna Rajendra Kumar
52471c814e9SPrajna Rajendra Kumar return 0;
52571c814e9SPrajna Rajendra Kumar }
52671c814e9SPrajna Rajendra Kumar
mpfs_spi_probe(struct platform_device * pdev)52771c814e9SPrajna Rajendra Kumar static int mpfs_spi_probe(struct platform_device *pdev)
52871c814e9SPrajna Rajendra Kumar {
52971c814e9SPrajna Rajendra Kumar struct spi_controller *host;
53071c814e9SPrajna Rajendra Kumar struct mpfs_spi *spi;
53171c814e9SPrajna Rajendra Kumar struct resource *res;
53271c814e9SPrajna Rajendra Kumar u32 num_cs;
53371c814e9SPrajna Rajendra Kumar int ret = 0;
53471c814e9SPrajna Rajendra Kumar
53571c814e9SPrajna Rajendra Kumar host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi));
53671c814e9SPrajna Rajendra Kumar if (!host)
53771c814e9SPrajna Rajendra Kumar return dev_err_probe(&pdev->dev, -ENOMEM,
53871c814e9SPrajna Rajendra Kumar "unable to allocate host for SPI controller\n");
53971c814e9SPrajna Rajendra Kumar
54071c814e9SPrajna Rajendra Kumar platform_set_drvdata(pdev, host);
54171c814e9SPrajna Rajendra Kumar
54271c814e9SPrajna Rajendra Kumar if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs))
54371c814e9SPrajna Rajendra Kumar num_cs = MAX_CS;
54471c814e9SPrajna Rajendra Kumar
54571c814e9SPrajna Rajendra Kumar host->num_chipselect = num_cs;
54671c814e9SPrajna Rajendra Kumar host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
54771c814e9SPrajna Rajendra Kumar host->use_gpio_descriptors = true;
54871c814e9SPrajna Rajendra Kumar host->setup = mpfs_spi_setup;
54971c814e9SPrajna Rajendra Kumar host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
55071c814e9SPrajna Rajendra Kumar host->transfer_one = mpfs_spi_transfer_one;
55171c814e9SPrajna Rajendra Kumar host->prepare_message = mpfs_spi_prepare_message;
55271c814e9SPrajna Rajendra Kumar host->set_cs = mpfs_spi_set_cs;
55371c814e9SPrajna Rajendra Kumar host->dev.of_node = pdev->dev.of_node;
55471c814e9SPrajna Rajendra Kumar
55571c814e9SPrajna Rajendra Kumar spi = spi_controller_get_devdata(host);
55671c814e9SPrajna Rajendra Kumar
55771c814e9SPrajna Rajendra Kumar spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
55871c814e9SPrajna Rajendra Kumar if (IS_ERR(spi->regs))
55971c814e9SPrajna Rajendra Kumar return PTR_ERR(spi->regs);
56071c814e9SPrajna Rajendra Kumar
56171c814e9SPrajna Rajendra Kumar spi->irq = platform_get_irq(pdev, 0);
56271c814e9SPrajna Rajendra Kumar if (spi->irq < 0)
56371c814e9SPrajna Rajendra Kumar return spi->irq;
56471c814e9SPrajna Rajendra Kumar
56571c814e9SPrajna Rajendra Kumar ret = devm_request_irq(&pdev->dev, spi->irq, mpfs_spi_interrupt,
56671c814e9SPrajna Rajendra Kumar IRQF_SHARED, dev_name(&pdev->dev), host);
56771c814e9SPrajna Rajendra Kumar if (ret)
56871c814e9SPrajna Rajendra Kumar return dev_err_probe(&pdev->dev, ret,
56971c814e9SPrajna Rajendra Kumar "could not request irq\n");
57071c814e9SPrajna Rajendra Kumar
57171c814e9SPrajna Rajendra Kumar spi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
57271c814e9SPrajna Rajendra Kumar if (IS_ERR(spi->clk))
57371c814e9SPrajna Rajendra Kumar return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk),
57471c814e9SPrajna Rajendra Kumar "could not get clk\n");
57571c814e9SPrajna Rajendra Kumar
57671c814e9SPrajna Rajendra Kumar mpfs_spi_init(host, spi);
57771c814e9SPrajna Rajendra Kumar
57871c814e9SPrajna Rajendra Kumar ret = devm_spi_register_controller(&pdev->dev, host);
57971c814e9SPrajna Rajendra Kumar if (ret) {
580*a8a31361SChristophe JAILLET mpfs_spi_disable_ints(spi);
58171c814e9SPrajna Rajendra Kumar mpfs_spi_disable(spi);
58271c814e9SPrajna Rajendra Kumar return dev_err_probe(&pdev->dev, ret,
58371c814e9SPrajna Rajendra Kumar "unable to register host for SPI controller\n");
58471c814e9SPrajna Rajendra Kumar }
58571c814e9SPrajna Rajendra Kumar
58671c814e9SPrajna Rajendra Kumar dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num);
58771c814e9SPrajna Rajendra Kumar
58871c814e9SPrajna Rajendra Kumar return 0;
58971c814e9SPrajna Rajendra Kumar }
59071c814e9SPrajna Rajendra Kumar
mpfs_spi_remove(struct platform_device * pdev)59171c814e9SPrajna Rajendra Kumar static void mpfs_spi_remove(struct platform_device *pdev)
59271c814e9SPrajna Rajendra Kumar {
59371c814e9SPrajna Rajendra Kumar struct spi_controller *host = platform_get_drvdata(pdev);
59471c814e9SPrajna Rajendra Kumar struct mpfs_spi *spi = spi_controller_get_devdata(host);
59571c814e9SPrajna Rajendra Kumar
59671c814e9SPrajna Rajendra Kumar mpfs_spi_disable_ints(spi);
59771c814e9SPrajna Rajendra Kumar mpfs_spi_disable(spi);
59871c814e9SPrajna Rajendra Kumar }
59971c814e9SPrajna Rajendra Kumar
60071c814e9SPrajna Rajendra Kumar #define MICROCHIP_SPI_PM_OPS (NULL)
60171c814e9SPrajna Rajendra Kumar
60271c814e9SPrajna Rajendra Kumar /*
60371c814e9SPrajna Rajendra Kumar * Platform driver data structure
60471c814e9SPrajna Rajendra Kumar */
60571c814e9SPrajna Rajendra Kumar
60671c814e9SPrajna Rajendra Kumar #if defined(CONFIG_OF)
60771c814e9SPrajna Rajendra Kumar static const struct of_device_id mpfs_spi_dt_ids[] = {
60871c814e9SPrajna Rajendra Kumar { .compatible = "microchip,mpfs-spi" },
60971c814e9SPrajna Rajendra Kumar { /* sentinel */ }
61071c814e9SPrajna Rajendra Kumar };
61171c814e9SPrajna Rajendra Kumar MODULE_DEVICE_TABLE(of, mpfs_spi_dt_ids);
61271c814e9SPrajna Rajendra Kumar #endif
61371c814e9SPrajna Rajendra Kumar
61471c814e9SPrajna Rajendra Kumar static struct platform_driver mpfs_spi_driver = {
61571c814e9SPrajna Rajendra Kumar .probe = mpfs_spi_probe,
61671c814e9SPrajna Rajendra Kumar .driver = {
61771c814e9SPrajna Rajendra Kumar .name = "microchip-spi",
61871c814e9SPrajna Rajendra Kumar .pm = MICROCHIP_SPI_PM_OPS,
61971c814e9SPrajna Rajendra Kumar .of_match_table = of_match_ptr(mpfs_spi_dt_ids),
62071c814e9SPrajna Rajendra Kumar },
62171c814e9SPrajna Rajendra Kumar .remove = mpfs_spi_remove,
62271c814e9SPrajna Rajendra Kumar };
62371c814e9SPrajna Rajendra Kumar module_platform_driver(mpfs_spi_driver);
62471c814e9SPrajna Rajendra Kumar MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver");
62571c814e9SPrajna Rajendra Kumar MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
62671c814e9SPrajna Rajendra Kumar MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
62771c814e9SPrajna Rajendra Kumar MODULE_LICENSE("GPL");
628