File Index
Files and directories
Sign in
FILE

spi-falcon.c

File preview with syntax highlighting.

linux-6.19.14/drivers/spi/spi-falcon.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 *
  4 *  Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
  5 */
  6
  7#include <linux/module.h>
  8#include <linux/device.h>
  9#include <linux/platform_device.h>
 10#include <linux/spi/spi.h>
 11#include <linux/delay.h>
 12#include <linux/of.h>
 13#include <linux/of_platform.h>
 14
 15#include <lantiq_soc.h>
 16
 17#define DRV_NAME		"sflash-falcon"
 18
 19#define FALCON_SPI_XFER_BEGIN	(1 << 0)
 20#define FALCON_SPI_XFER_END	(1 << 1)
 21
 22/* Bus Read Configuration Register0 */
 23#define BUSRCON0		0x00000010
 24/* Bus Write Configuration Register0 */
 25#define BUSWCON0		0x00000018
 26/* Serial Flash Configuration Register */
 27#define SFCON			0x00000080
 28/* Serial Flash Time Register */
 29#define SFTIME			0x00000084
 30/* Serial Flash Status Register */
 31#define SFSTAT			0x00000088
 32/* Serial Flash Command Register */
 33#define SFCMD			0x0000008C
 34/* Serial Flash Address Register */
 35#define SFADDR			0x00000090
 36/* Serial Flash Data Register */
 37#define SFDATA			0x00000094
 38/* Serial Flash I/O Control Register */
 39#define SFIO			0x00000098
 40/* EBU Clock Control Register */
 41#define EBUCC			0x000000C4
 42
 43/* Dummy Phase Length */
 44#define SFCMD_DUMLEN_OFFSET	16
 45#define SFCMD_DUMLEN_MASK	0x000F0000
 46/* Chip Select */
 47#define SFCMD_CS_OFFSET		24
 48#define SFCMD_CS_MASK		0x07000000
 49/* field offset */
 50#define SFCMD_ALEN_OFFSET	20
 51#define SFCMD_ALEN_MASK		0x00700000
 52/* SCK Rise-edge Position */
 53#define SFTIME_SCKR_POS_OFFSET	8
 54#define SFTIME_SCKR_POS_MASK	0x00000F00
 55/* SCK Period */
 56#define SFTIME_SCK_PER_OFFSET	0
 57#define SFTIME_SCK_PER_MASK	0x0000000F
 58/* SCK Fall-edge Position */
 59#define SFTIME_SCKF_POS_OFFSET	12
 60#define SFTIME_SCKF_POS_MASK	0x0000F000
 61/* Device Size */
 62#define SFCON_DEV_SIZE_A23_0	0x03000000
 63#define SFCON_DEV_SIZE_MASK	0x0F000000
 64/* Read Data Position */
 65#define SFTIME_RD_POS_MASK	0x000F0000
 66/* Data Output */
 67#define SFIO_UNUSED_WD_MASK	0x0000000F
 68/* Command Opcode mask */
 69#define SFCMD_OPC_MASK		0x000000FF
 70/* dlen bytes of data to write */
 71#define SFCMD_DIR_WRITE		0x00000100
 72/* Data Length offset */
 73#define SFCMD_DLEN_OFFSET	9
 74/* Command Error */
 75#define SFSTAT_CMD_ERR		0x20000000
 76/* Access Command Pending */
 77#define SFSTAT_CMD_PEND		0x00400000
 78/* Frequency set to 100MHz. */
 79#define EBUCC_EBUDIV_SELF100	0x00000001
 80/* Serial Flash */
 81#define BUSRCON0_AGEN_SERIAL_FLASH	0xF0000000
 82/* 8-bit multiplexed */
 83#define BUSRCON0_PORTW_8_BIT_MUX	0x00000000
 84/* Serial Flash */
 85#define BUSWCON0_AGEN_SERIAL_FLASH	0xF0000000
 86/* Chip Select after opcode */
 87#define SFCMD_KEEP_CS_KEEP_SELECTED	0x00008000
 88
 89#define CLOCK_100M	100000000
 90#define CLOCK_50M	50000000
 91
 92struct falcon_sflash {
 93	u32 sfcmd; /* for caching of opcode, direction, ... */
 94	struct spi_controller *host;
 95};
 96
 97static int
 98falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t,
 99		   unsigned long flags)
100{
101	struct device *dev = &spi->dev;
102	struct falcon_sflash *priv = spi_controller_get_devdata(spi->controller);
103	const u8 *txp = t->tx_buf;
104	u8 *rxp = t->rx_buf;
105	unsigned int bytelen = ((8 * t->len + 7) / 8);
106	unsigned int len, alen, dumlen;
107	u32 val;
108	enum {
109		state_init,
110		state_command_prepare,
111		state_write,
112		state_read,
113		state_disable_cs,
114		state_end
115	} state = state_init;
116
117	do {
118		switch (state) {
119		case state_init: /* detect phase of upper layer sequence */
120		{
121			/* initial write ? */
122			if (flags & FALCON_SPI_XFER_BEGIN) {
123				if (!txp) {
124					dev_err(dev,
125						"BEGIN without tx data!\n");
126					return -ENODATA;
127				}
128				/*
129				 * Prepare the parts of the sfcmd register,
130				 * which should not change during a sequence!
131				 * Only exception are the length fields,
132				 * especially alen and dumlen.
133				 */
134
135				priv->sfcmd = ((spi_get_chipselect(spi, 0)
136						<< SFCMD_CS_OFFSET)
137					       & SFCMD_CS_MASK);
138				priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED;
139				priv->sfcmd |= *txp;
140				txp++;
141				bytelen--;
142				if (bytelen) {
143					/*
144					 * more data:
145					 * maybe address and/or dummy
146					 */
147					state = state_command_prepare;
148					break;
149				} else {
150					dev_dbg(dev, "write cmd %02X\n",
151						priv->sfcmd & SFCMD_OPC_MASK);
152				}
153			}
154			/* continued write ? */
155			if (txp && bytelen) {
156				state = state_write;
157				break;
158			}
159			/* read data? */
160			if (rxp && bytelen) {
161				state = state_read;
162				break;
163			}
164			/* end of sequence? */
165			if (flags & FALCON_SPI_XFER_END)
166				state = state_disable_cs;
167			else
168				state = state_end;
169			break;
170		}
171		/* collect tx data for address and dummy phase */
172		case state_command_prepare:
173		{
174			/* txp is valid, already checked */
175			val = 0;
176			alen = 0;
177			dumlen = 0;
178			while (bytelen > 0) {
179				if (alen < 3) {
180					val = (val << 8) | (*txp++);
181					alen++;
182				} else if ((dumlen < 15) && (*txp == 0)) {
183					/*
184					 * assume dummy bytes are set to 0
185					 * from upper layer
186					 */
187					dumlen++;
188					txp++;
189				} else {
190					break;
191				}
192				bytelen--;
193			}
194			priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK);
195			priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) |
196					 (dumlen << SFCMD_DUMLEN_OFFSET);
197			if (alen > 0)
198				ltq_ebu_w32(val, SFADDR);
199
200			dev_dbg(dev, "wr %02X, alen=%d (addr=%06X) dlen=%d\n",
201				priv->sfcmd & SFCMD_OPC_MASK,
202				alen, val, dumlen);
203
204			if (bytelen > 0) {
205				/* continue with write */
206				state = state_write;
207			} else if (flags & FALCON_SPI_XFER_END) {
208				/* end of sequence? */
209				state = state_disable_cs;
210			} else {
211				/*
212				 * go to end and expect another
213				 * call (read or write)
214				 */
215				state = state_end;
216			}
217			break;
218		}
219		case state_write:
220		{
221			/* txp still valid */
222			priv->sfcmd |= SFCMD_DIR_WRITE;
223			len = 0;
224			val = 0;
225			do {
226				if (bytelen--)
227					val |= (*txp++) << (8 * len++);
228				if ((flags & FALCON_SPI_XFER_END)
229				    && (bytelen == 0)) {
230					priv->sfcmd &=
231						~SFCMD_KEEP_CS_KEEP_SELECTED;
232				}
233				if ((len == 4) || (bytelen == 0)) {
234					ltq_ebu_w32(val, SFDATA);
235					ltq_ebu_w32(priv->sfcmd
236						| (len<<SFCMD_DLEN_OFFSET),
237						SFCMD);
238					len = 0;
239					val = 0;
240					priv->sfcmd &= ~(SFCMD_ALEN_MASK
241							 | SFCMD_DUMLEN_MASK);
242				}
243			} while (bytelen);
244			state = state_end;
245			break;
246		}
247		case state_read:
248		{
249			/* read data */
250			priv->sfcmd &= ~SFCMD_DIR_WRITE;
251			do {
252				if ((flags & FALCON_SPI_XFER_END)
253				    && (bytelen <= 4)) {
254					priv->sfcmd &=
255						~SFCMD_KEEP_CS_KEEP_SELECTED;
256				}
257				len = (bytelen > 4) ? 4 : bytelen;
258				bytelen -= len;
259				ltq_ebu_w32(priv->sfcmd
260					| (len << SFCMD_DLEN_OFFSET), SFCMD);
261				priv->sfcmd &= ~(SFCMD_ALEN_MASK
262						 | SFCMD_DUMLEN_MASK);
263				do {
264					val = ltq_ebu_r32(SFSTAT);
265					if (val & SFSTAT_CMD_ERR) {
266						/* reset error status */
267						dev_err(dev, "SFSTAT: CMD_ERR");
268						dev_err(dev, " (%x)\n", val);
269						ltq_ebu_w32(SFSTAT_CMD_ERR,
270							SFSTAT);
271						return -EBADE;
272					}
273				} while (val & SFSTAT_CMD_PEND);
274				val = ltq_ebu_r32(SFDATA);
275				do {
276					*rxp = (val & 0xFF);
277					rxp++;
278					val >>= 8;
279					len--;
280				} while (len);
281			} while (bytelen);
282			state = state_end;
283			break;
284		}
285		case state_disable_cs:
286		{
287			priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED;
288			ltq_ebu_w32(priv->sfcmd | (0 << SFCMD_DLEN_OFFSET),
289				SFCMD);
290			val = ltq_ebu_r32(SFSTAT);
291			if (val & SFSTAT_CMD_ERR) {
292				/* reset error status */
293				dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val);
294				ltq_ebu_w32(SFSTAT_CMD_ERR, SFSTAT);
295				return -EBADE;
296			}
297			state = state_end;
298			break;
299		}
300		case state_end:
301			break;
302		}
303	} while (state != state_end);
304
305	return 0;
306}
307
308static int falcon_sflash_setup(struct spi_device *spi)
309{
310	unsigned int i;
311	unsigned long flags;
312
313	spin_lock_irqsave(&ebu_lock, flags);
314
315	if (spi->max_speed_hz >= CLOCK_100M) {
316		/* set EBU clock to 100 MHz */
317		ltq_sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, EBUCC);
318		i = 1; /* divider */
319	} else {
320		/* set EBU clock to 50 MHz */
321		ltq_sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, EBUCC);
322
323		/* search for suitable divider */
324		for (i = 1; i < 7; i++) {
325			if (CLOCK_50M / i <= spi->max_speed_hz)
326				break;
327		}
328	}
329
330	/* setup period of serial clock */
331	ltq_ebu_w32_mask(SFTIME_SCKF_POS_MASK
332		     | SFTIME_SCKR_POS_MASK
333		     | SFTIME_SCK_PER_MASK,
334		     (i << SFTIME_SCKR_POS_OFFSET)
335		     | (i << (SFTIME_SCK_PER_OFFSET + 1)),
336		     SFTIME);
337
338	/*
339	 * set some bits of unused_wd, to not trigger HOLD/WP
340	 * signals on non QUAD flashes
341	 */
342	ltq_ebu_w32((SFIO_UNUSED_WD_MASK & (0x8 | 0x4)), SFIO);
343
344	ltq_ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX,
345			BUSRCON0);
346	ltq_ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, BUSWCON0);
347	/* set address wrap around to maximum for 24-bit addresses */
348	ltq_ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, SFCON);
349
350	spin_unlock_irqrestore(&ebu_lock, flags);
351
352	return 0;
353}
354
355static int falcon_sflash_xfer_one(struct spi_controller *host,
356					struct spi_message *m)
357{
358	struct falcon_sflash *priv = spi_controller_get_devdata(host);
359	struct spi_transfer *t;
360	unsigned long spi_flags;
361	unsigned long flags;
362	int ret = 0;
363
364	priv->sfcmd = 0;
365	m->actual_length = 0;
366
367	spi_flags = FALCON_SPI_XFER_BEGIN;
368	list_for_each_entry(t, &m->transfers, transfer_list) {
369		if (list_is_last(&t->transfer_list, &m->transfers))
370			spi_flags |= FALCON_SPI_XFER_END;
371
372		spin_lock_irqsave(&ebu_lock, flags);
373		ret = falcon_sflash_xfer(m->spi, t, spi_flags);
374		spin_unlock_irqrestore(&ebu_lock, flags);
375
376		if (ret)
377			break;
378
379		m->actual_length += t->len;
380
381		WARN_ON(t->delay.value || t->cs_change);
382		spi_flags = 0;
383	}
384
385	m->status = ret;
386	spi_finalize_current_message(host);
387
388	return 0;
389}
390
391static int falcon_sflash_probe(struct platform_device *pdev)
392{
393	struct falcon_sflash *priv;
394	struct spi_controller *host;
395	int ret;
396
397	host = spi_alloc_host(&pdev->dev, sizeof(*priv));
398	if (!host)
399		return -ENOMEM;
400
401	priv = spi_controller_get_devdata(host);
402	priv->host = host;
403
404	host->mode_bits = SPI_MODE_3;
405	host->flags = SPI_CONTROLLER_HALF_DUPLEX;
406	host->setup = falcon_sflash_setup;
407	host->transfer_one_message = falcon_sflash_xfer_one;
408	host->dev.of_node = pdev->dev.of_node;
409
410	ret = devm_spi_register_controller(&pdev->dev, host);
411	if (ret)
412		spi_controller_put(host);
413	return ret;
414}
415
416static const struct of_device_id falcon_sflash_match[] = {
417	{ .compatible = "lantiq,sflash-falcon" },
418	{},
419};
420MODULE_DEVICE_TABLE(of, falcon_sflash_match);
421
422static struct platform_driver falcon_sflash_driver = {
423	.probe	= falcon_sflash_probe,
424	.driver = {
425		.name	= DRV_NAME,
426		.of_match_table = falcon_sflash_match,
427	}
428};
429
430module_platform_driver(falcon_sflash_driver);
431
432MODULE_LICENSE("GPL");
433MODULE_DESCRIPTION("Lantiq Falcon SPI/SFLASH controller driver");
~/ Read-only file preview.