xref: /openbmc/linux/drivers/spi/spi-realtek-rtl.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1  // SPDX-License-Identifier: GPL-2.0-only
2  
3  #include <linux/module.h>
4  #include <linux/platform_device.h>
5  #include <linux/mod_devicetable.h>
6  #include <linux/spi/spi.h>
7  
8  struct rtspi {
9  	void __iomem *base;
10  };
11  
12  /* SPI Flash Configuration Register */
13  #define RTL_SPI_SFCR			0x00
14  #define RTL_SPI_SFCR_RBO		BIT(28)
15  #define RTL_SPI_SFCR_WBO		BIT(27)
16  
17  /* SPI Flash Control and Status Register */
18  #define RTL_SPI_SFCSR			0x08
19  #define RTL_SPI_SFCSR_CSB0		BIT(31)
20  #define RTL_SPI_SFCSR_CSB1		BIT(30)
21  #define RTL_SPI_SFCSR_RDY		BIT(27)
22  #define RTL_SPI_SFCSR_CS		BIT(24)
23  #define RTL_SPI_SFCSR_LEN_MASK		~(0x03 << 28)
24  #define RTL_SPI_SFCSR_LEN1		(0x00 << 28)
25  #define RTL_SPI_SFCSR_LEN4		(0x03 << 28)
26  
27  /* SPI Flash Data Register */
28  #define RTL_SPI_SFDR			0x0c
29  
30  #define REG(x)		(rtspi->base + x)
31  
32  
rt_set_cs(struct spi_device * spi,bool active)33  static void rt_set_cs(struct spi_device *spi, bool active)
34  {
35  	struct rtspi *rtspi = spi_controller_get_devdata(spi->controller);
36  	u32 value;
37  
38  	/* CS0 bit is active low */
39  	value = readl(REG(RTL_SPI_SFCSR));
40  	if (active)
41  		value |= RTL_SPI_SFCSR_CSB0;
42  	else
43  		value &= ~RTL_SPI_SFCSR_CSB0;
44  	writel(value, REG(RTL_SPI_SFCSR));
45  }
46  
set_size(struct rtspi * rtspi,int size)47  static void set_size(struct rtspi *rtspi, int size)
48  {
49  	u32 value;
50  
51  	value = readl(REG(RTL_SPI_SFCSR));
52  	value &= RTL_SPI_SFCSR_LEN_MASK;
53  	if (size == 4)
54  		value |= RTL_SPI_SFCSR_LEN4;
55  	else if (size == 1)
56  		value |= RTL_SPI_SFCSR_LEN1;
57  	writel(value, REG(RTL_SPI_SFCSR));
58  }
59  
wait_ready(struct rtspi * rtspi)60  static inline void wait_ready(struct rtspi *rtspi)
61  {
62  	while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))
63  		cpu_relax();
64  }
send4(struct rtspi * rtspi,const u32 * buf)65  static void send4(struct rtspi *rtspi, const u32 *buf)
66  {
67  	wait_ready(rtspi);
68  	set_size(rtspi, 4);
69  	writel(*buf, REG(RTL_SPI_SFDR));
70  }
71  
send1(struct rtspi * rtspi,const u8 * buf)72  static void send1(struct rtspi *rtspi, const u8 *buf)
73  {
74  	wait_ready(rtspi);
75  	set_size(rtspi, 1);
76  	writel(buf[0] << 24, REG(RTL_SPI_SFDR));
77  }
78  
rcv4(struct rtspi * rtspi,u32 * buf)79  static void rcv4(struct rtspi *rtspi, u32 *buf)
80  {
81  	wait_ready(rtspi);
82  	set_size(rtspi, 4);
83  	*buf = readl(REG(RTL_SPI_SFDR));
84  }
85  
rcv1(struct rtspi * rtspi,u8 * buf)86  static void rcv1(struct rtspi *rtspi, u8 *buf)
87  {
88  	wait_ready(rtspi);
89  	set_size(rtspi, 1);
90  	*buf = readl(REG(RTL_SPI_SFDR)) >> 24;
91  }
92  
transfer_one(struct spi_controller * ctrl,struct spi_device * spi,struct spi_transfer * xfer)93  static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
94  			struct spi_transfer *xfer)
95  {
96  	struct rtspi *rtspi = spi_controller_get_devdata(ctrl);
97  	void *rx_buf;
98  	const void *tx_buf;
99  	int cnt;
100  
101  	tx_buf = xfer->tx_buf;
102  	rx_buf = xfer->rx_buf;
103  	cnt = xfer->len;
104  	if (tx_buf) {
105  		while (cnt >= 4) {
106  			send4(rtspi, tx_buf);
107  			tx_buf += 4;
108  			cnt -= 4;
109  		}
110  		while (cnt) {
111  			send1(rtspi, tx_buf);
112  			tx_buf++;
113  			cnt--;
114  		}
115  	} else if (rx_buf) {
116  		while (cnt >= 4) {
117  			rcv4(rtspi, rx_buf);
118  			rx_buf += 4;
119  			cnt -= 4;
120  		}
121  		while (cnt) {
122  			rcv1(rtspi, rx_buf);
123  			rx_buf++;
124  			cnt--;
125  		}
126  	}
127  
128  	spi_finalize_current_transfer(ctrl);
129  
130  	return 0;
131  }
132  
init_hw(struct rtspi * rtspi)133  static void init_hw(struct rtspi *rtspi)
134  {
135  	u32 value;
136  
137  	/* Turn on big-endian byte ordering */
138  	value = readl(REG(RTL_SPI_SFCR));
139  	value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;
140  	writel(value, REG(RTL_SPI_SFCR));
141  
142  	value = readl(REG(RTL_SPI_SFCSR));
143  	/* Permanently disable CS1, since it's never used */
144  	value |= RTL_SPI_SFCSR_CSB1;
145  	/* Select CS0 for use */
146  	value &= RTL_SPI_SFCSR_CS;
147  	writel(value, REG(RTL_SPI_SFCSR));
148  }
149  
realtek_rtl_spi_probe(struct platform_device * pdev)150  static int realtek_rtl_spi_probe(struct platform_device *pdev)
151  {
152  	struct spi_controller *ctrl;
153  	struct rtspi *rtspi;
154  	int err;
155  
156  	ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*rtspi));
157  	if (!ctrl) {
158  		dev_err(&pdev->dev, "Error allocating SPI controller\n");
159  		return -ENOMEM;
160  	}
161  	platform_set_drvdata(pdev, ctrl);
162  	rtspi = spi_controller_get_devdata(ctrl);
163  
164  	rtspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
165  	if (IS_ERR(rtspi->base)) {
166  		dev_err(&pdev->dev, "Could not map SPI register address");
167  		return -ENOMEM;
168  	}
169  
170  	init_hw(rtspi);
171  
172  	ctrl->dev.of_node = pdev->dev.of_node;
173  	ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX;
174  	ctrl->set_cs = rt_set_cs;
175  	ctrl->transfer_one = transfer_one;
176  
177  	err = devm_spi_register_controller(&pdev->dev, ctrl);
178  	if (err) {
179  		dev_err(&pdev->dev, "Could not register SPI controller\n");
180  		return -ENODEV;
181  	}
182  
183  	return 0;
184  }
185  
186  
187  static const struct of_device_id realtek_rtl_spi_of_ids[] = {
188  	{ .compatible = "realtek,rtl8380-spi" },
189  	{ .compatible = "realtek,rtl8382-spi" },
190  	{ .compatible = "realtek,rtl8391-spi" },
191  	{ .compatible = "realtek,rtl8392-spi" },
192  	{ .compatible = "realtek,rtl8393-spi" },
193  	{ /* sentinel */ }
194  };
195  MODULE_DEVICE_TABLE(of, realtek_rtl_spi_of_ids);
196  
197  static struct platform_driver realtek_rtl_spi_driver = {
198  	.probe = realtek_rtl_spi_probe,
199  	.driver = {
200  		.name = "realtek-rtl-spi",
201  		.of_match_table = realtek_rtl_spi_of_ids,
202  	},
203  };
204  
205  module_platform_driver(realtek_rtl_spi_driver);
206  
207  MODULE_LICENSE("GPL v2");
208  MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
209  MODULE_DESCRIPTION("Realtek RTL SPI driver");
210