xref: /dpdk/drivers/raw/ifpga/base/opae_spi.c (revision eacdd03c79f5d8adfa7d0dad1e75657dbaf4f788)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2019 Intel Corporation
3  */
4 
5 #include "opae_osdep.h"
6 #include "opae_spi.h"
7 
nios_spi_indirect_read(struct altera_spi_device * dev,u32 reg,u32 * val)8 static int nios_spi_indirect_read(struct altera_spi_device *dev, u32 reg,
9 		u32 *val)
10 {
11 	u64 ctrl = 0;
12 	u64 stat = 0;
13 	int loops = SPI_MAX_RETRY;
14 
15 	ctrl = NIOS_SPI_RD | ((u64)reg << 32);
16 	opae_writeq(ctrl, dev->regs + NIOS_SPI_CTRL);
17 
18 	stat = opae_readq(dev->regs + NIOS_SPI_STAT);
19 	while (!(stat & NIOS_SPI_VALID) && --loops)
20 		stat = opae_readq(dev->regs + NIOS_SPI_STAT);
21 
22 	*val = stat & NIOS_SPI_READ_DATA;
23 
24 	return loops ? 0 : -ETIMEDOUT;
25 }
26 
nios_spi_indirect_write(struct altera_spi_device * dev,u32 reg,u32 value)27 static int nios_spi_indirect_write(struct altera_spi_device *dev, u32 reg,
28 		u32 value)
29 {
30 
31 	u64 ctrl = 0;
32 	u64 stat = 0;
33 	int loops = SPI_MAX_RETRY;
34 
35 	ctrl |= NIOS_SPI_WR | (u64)reg << 32;
36 	ctrl |= value & NIOS_SPI_WRITE_DATA;
37 
38 	opae_writeq(ctrl, dev->regs + NIOS_SPI_CTRL);
39 
40 	stat = opae_readq(dev->regs + NIOS_SPI_STAT);
41 	while (!(stat & NIOS_SPI_VALID) && --loops)
42 		stat = opae_readq(dev->regs + NIOS_SPI_STAT);
43 
44 	return loops ? 0 : -ETIMEDOUT;
45 }
46 
spi_indirect_write(struct altera_spi_device * dev,u32 reg,u32 value)47 static int spi_indirect_write(struct altera_spi_device *dev, u32 reg,
48 		u32 value)
49 {
50 	u64 ctrl;
51 
52 	opae_writeq(value & WRITE_DATA_MASK, dev->regs + SPI_WRITE);
53 
54 	ctrl = CTRL_W | (reg >> 2);
55 	opae_writeq(ctrl, dev->regs + SPI_CTRL);
56 
57 	return 0;
58 }
59 
spi_indirect_read(struct altera_spi_device * dev,u32 reg,u32 * val)60 static int spi_indirect_read(struct altera_spi_device *dev, u32 reg,
61 		u32 *val)
62 {
63 	u64 tmp;
64 	u64 ctrl;
65 
66 	ctrl = CTRL_R | (reg >> 2);
67 	opae_writeq(ctrl, dev->regs + SPI_CTRL);
68 
69 	/**
70 	 *  FIXME: Read one more time to avoid HW timing issue. This is
71 	 *  a short term workaround solution, and must be removed once
72 	 *  hardware fixing is done.
73 	 */
74 	tmp = opae_readq(dev->regs + SPI_READ);
75 
76 	*val = (u32)tmp;
77 
78 	return 0;
79 }
80 
spi_reg_write(struct altera_spi_device * dev,u32 reg,u32 value)81 int spi_reg_write(struct altera_spi_device *dev, u32 reg,
82 		u32 value)
83 {
84 	return dev->reg_write(dev, reg, value);
85 }
86 
spi_reg_read(struct altera_spi_device * dev,u32 reg,u32 * val)87 int spi_reg_read(struct altera_spi_device *dev, u32 reg,
88 		u32 *val)
89 {
90 	return dev->reg_read(dev, reg, val);
91 }
92 
spi_cs_activate(struct altera_spi_device * dev,unsigned int chip_select)93 void spi_cs_activate(struct altera_spi_device *dev, unsigned int chip_select)
94 {
95 	spi_reg_write(dev, ALTERA_SPI_SLAVE_SEL, 1 << chip_select);
96 	spi_reg_write(dev, ALTERA_SPI_CONTROL, ALTERA_SPI_CONTROL_SSO_MSK);
97 }
98 
spi_cs_deactivate(struct altera_spi_device * dev)99 void spi_cs_deactivate(struct altera_spi_device *dev)
100 {
101 	spi_reg_write(dev, ALTERA_SPI_CONTROL, 0);
102 }
103 
spi_flush_rx(struct altera_spi_device * dev)104 static int spi_flush_rx(struct altera_spi_device *dev)
105 {
106 	u32 val = 0;
107 	int ret;
108 
109 	ret = spi_reg_read(dev, ALTERA_SPI_STATUS, &val);
110 	if (ret)
111 		return ret;
112 
113 	if (val & ALTERA_SPI_STATUS_RRDY_MSK) {
114 		ret = spi_reg_read(dev, ALTERA_SPI_RXDATA, &val);
115 		if (ret)
116 			return ret;
117 	}
118 
119 	return 0;
120 }
121 
spi_write_bytes(struct altera_spi_device * dev,int count)122 static unsigned int spi_write_bytes(struct altera_spi_device *dev, int count)
123 {
124 	unsigned int val = 0;
125 	u16 *p16;
126 	u32 *p32;
127 
128 	if (dev->txbuf) {
129 		switch (dev->data_width) {
130 		case 1:
131 			val = dev->txbuf[count];
132 			break;
133 		case 2:
134 			p16 = (u16 *)(dev->txbuf + 2*count);
135 			val = *p16;
136 			if (dev->endian == SPI_BIG_ENDIAN)
137 				val = cpu_to_be16(val);
138 			break;
139 		case 4:
140 			p32 = (u32 *)(dev->txbuf + 4*count);
141 			val = *p32;
142 			break;
143 		}
144 	}
145 
146 	return val;
147 }
148 
spi_fill_readbuffer(struct altera_spi_device * dev,unsigned int value,int count)149 static void spi_fill_readbuffer(struct altera_spi_device *dev,
150 		unsigned int value, int count)
151 {
152 	u16 *p16;
153 	u32 *p32;
154 
155 	if (dev->rxbuf) {
156 		switch (dev->data_width) {
157 		case 1:
158 			dev->rxbuf[count] = value;
159 			break;
160 		case 2:
161 			p16 = (u16 *)(dev->rxbuf + 2*count);
162 			if (dev->endian == SPI_BIG_ENDIAN)
163 				*p16 = cpu_to_be16((u16)value);
164 			else
165 				*p16 = (u16)value;
166 			break;
167 		case 4:
168 			p32 = (u32 *)(dev->rxbuf + 4*count);
169 			if (dev->endian == SPI_BIG_ENDIAN)
170 				*p32 = cpu_to_be32(value);
171 			else
172 				*p32 = value;
173 			break;
174 		}
175 	}
176 }
177 
spi_txrx(struct altera_spi_device * dev)178 static int spi_txrx(struct altera_spi_device *dev)
179 {
180 	unsigned int count = 0;
181 	u32 rxd;
182 	unsigned int tx_data;
183 	u32 status;
184 	int ret;
185 
186 	while (count < dev->len) {
187 		tx_data = spi_write_bytes(dev, count);
188 		spi_reg_write(dev, ALTERA_SPI_TXDATA, tx_data);
189 
190 		while (1) {
191 			ret = spi_reg_read(dev, ALTERA_SPI_STATUS, &status);
192 			if (ret)
193 				return -EIO;
194 			if (status & ALTERA_SPI_STATUS_RRDY_MSK)
195 				break;
196 		}
197 
198 		ret = spi_reg_read(dev, ALTERA_SPI_RXDATA, &rxd);
199 		if (ret)
200 			return -EIO;
201 
202 		spi_fill_readbuffer(dev, rxd, count);
203 
204 		count++;
205 	}
206 
207 	return 0;
208 }
209 
spi_command(struct altera_spi_device * dev,unsigned int chip_select,unsigned int wlen,void * wdata,unsigned int rlen,void * rdata)210 int spi_command(struct altera_spi_device *dev, unsigned int chip_select,
211 		unsigned int wlen, void *wdata,
212 		unsigned int rlen, void *rdata)
213 {
214 	if (((wlen > 0) && !wdata) || ((rlen > 0) && !rdata)) {
215 		dev_err(dev, "error on spi command checking\n");
216 		return -EINVAL;
217 	}
218 
219 	wlen = wlen / dev->data_width;
220 	rlen = rlen / dev->data_width;
221 
222 	/* flush rx buffer */
223 	spi_flush_rx(dev);
224 
225 	spi_cs_activate(dev, chip_select);
226 	if (wlen) {
227 		dev->txbuf = wdata;
228 		dev->rxbuf = rdata;
229 		dev->len = wlen;
230 		spi_txrx(dev);
231 	}
232 	if (rlen) {
233 		dev->rxbuf = rdata;
234 		dev->txbuf = NULL;
235 		dev->len = rlen;
236 		spi_txrx(dev);
237 	}
238 	spi_cs_deactivate(dev);
239 	return 0;
240 }
241 
spi_write(struct altera_spi_device * dev,unsigned int chip_select,unsigned int wlen,void * wdata)242 int spi_write(struct altera_spi_device *dev, unsigned int chip_select,
243 		unsigned int wlen, void *wdata)
244 {
245 	return spi_command(dev, chip_select, wlen, wdata, 0, NULL);
246 }
247 
spi_read(struct altera_spi_device * dev,unsigned int chip_select,unsigned int rlen,void * rdata)248 int spi_read(struct altera_spi_device *dev, unsigned int chip_select,
249 		unsigned int rlen, void *rdata)
250 {
251 	return spi_command(dev, chip_select, 0, NULL, rlen, rdata);
252 }
253 
altera_spi_alloc(void * base,int type)254 struct altera_spi_device *altera_spi_alloc(void *base, int type)
255 {
256 	struct altera_spi_device *spi_dev =
257 		opae_malloc(sizeof(struct altera_spi_device));
258 
259 	if (!spi_dev)
260 		return NULL;
261 
262 	spi_dev->regs = base;
263 
264 	switch (type) {
265 	case TYPE_SPI:
266 		spi_dev->reg_read = spi_indirect_read;
267 		spi_dev->reg_write = spi_indirect_write;
268 		break;
269 	case TYPE_NIOS_SPI:
270 		spi_dev->reg_read = nios_spi_indirect_read;
271 		spi_dev->reg_write = nios_spi_indirect_write;
272 		break;
273 	default:
274 		dev_err(dev, "%s: invalid SPI type\n", __func__);
275 		goto error;
276 	}
277 
278 	return spi_dev;
279 
280 error:
281 	altera_spi_release(spi_dev);
282 	return NULL;
283 }
284 
altera_spi_init(struct altera_spi_device * spi_dev)285 void altera_spi_init(struct altera_spi_device *spi_dev)
286 {
287 	spi_dev->spi_param.info = opae_readq(spi_dev->regs + SPI_CORE_PARAM);
288 
289 	spi_dev->data_width = spi_dev->spi_param.data_width / 8;
290 	spi_dev->endian = spi_dev->spi_param.endian;
291 	spi_dev->num_chipselect = spi_dev->spi_param.num_chipselect;
292 	dev_info(spi_dev, "spi param: type=%d, data width:%d, endian:%d, clock_polarity=%d, clock=%dMHz, chips=%d, cpha=%d\n",
293 			spi_dev->spi_param.type,
294 			spi_dev->data_width, spi_dev->endian,
295 			spi_dev->spi_param.clock_polarity,
296 			spi_dev->spi_param.clock,
297 			spi_dev->num_chipselect,
298 			spi_dev->spi_param.clock_phase);
299 
300 	if (spi_dev->mutex)
301 		pthread_mutex_lock(spi_dev->mutex);
302 	/* clear */
303 	spi_reg_write(spi_dev, ALTERA_SPI_CONTROL, 0);
304 	spi_reg_write(spi_dev, ALTERA_SPI_STATUS, 0);
305 	/* flush rxdata */
306 	spi_flush_rx(spi_dev);
307 	if (spi_dev->mutex)
308 		pthread_mutex_unlock(spi_dev->mutex);
309 }
310 
altera_spi_release(struct altera_spi_device * dev)311 void altera_spi_release(struct altera_spi_device *dev)
312 {
313 	if (dev)
314 		opae_free(dev);
315 }
316