blob: 097d916417568a903520d715ac41023fabb39ea2 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Allen Martinba4fb9b2013-01-29 13:51:28 +00002/*
3 * NVIDIA Tegra SPI-SLINK controller
4 *
5 * Copyright (c) 2010-2013 NVIDIA Corporation
Allen Martinba4fb9b2013-01-29 13:51:28 +00006 */
7
Simon Glass1121b1b2014-10-13 23:42:13 -06008#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glass495a5dc2019-11-14 12:57:30 -070010#include <time.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Allen Martinba4fb9b2013-01-29 13:51:28 +000012#include <asm/io.h>
Allen Martinba4fb9b2013-01-29 13:51:28 +000013#include <asm/arch/clock.h>
14#include <asm/arch-tegra/clk_rst.h>
Allen Martinba4fb9b2013-01-29 13:51:28 +000015#include <spi.h>
16#include <fdtdec.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060017#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Simon Glass1121b1b2014-10-13 23:42:13 -060019#include "tegra_spi.h"
Allen Martinba4fb9b2013-01-29 13:51:28 +000020
21DECLARE_GLOBAL_DATA_PTR;
22
Allen Martin8db241b2013-03-16 18:58:05 +000023/* COMMAND */
Jagan Teki7f7ccf72015-10-23 01:39:06 +053024#define SLINK_CMD_ENB BIT(31)
25#define SLINK_CMD_GO BIT(30)
26#define SLINK_CMD_M_S BIT(28)
Mirza Krak960dad92015-09-08 10:30:49 +020027#define SLINK_CMD_IDLE_SCLK_DRIVE_LOW (0 << 24)
Jagan Teki7f7ccf72015-10-23 01:39:06 +053028#define SLINK_CMD_IDLE_SCLK_DRIVE_HIGH BIT(24)
Mirza Krak960dad92015-09-08 10:30:49 +020029#define SLINK_CMD_IDLE_SCLK_PULL_LOW (2 << 24)
30#define SLINK_CMD_IDLE_SCLK_PULL_HIGH (3 << 24)
31#define SLINK_CMD_IDLE_SCLK_MASK (3 << 24)
Svyatoslav Ryhel7e10c462025-01-26 19:48:22 +020032#define SLINK_CMD_CS_POL3 BIT(23)
33#define SLINK_CMD_CS_POL2 BIT(22)
Jagan Teki7f7ccf72015-10-23 01:39:06 +053034#define SLINK_CMD_CK_SDA BIT(21)
Svyatoslav Ryhel7e10c462025-01-26 19:48:22 +020035#define SLINK_CMD_CS_POL1 BIT(20)
Jagan Teki7f7ccf72015-10-23 01:39:06 +053036#define SLINK_CMD_CS_POL BIT(13)
37#define SLINK_CMD_CS_VAL BIT(12)
38#define SLINK_CMD_CS_SOFT BIT(11)
39#define SLINK_CMD_BIT_LENGTH BIT(4)
Jagan Teki54badcb2015-10-23 01:03:10 +053040#define SLINK_CMD_BIT_LENGTH_MASK GENMASK(4, 0)
Allen Martin8db241b2013-03-16 18:58:05 +000041/* COMMAND2 */
Jagan Teki7f7ccf72015-10-23 01:39:06 +053042#define SLINK_CMD2_TXEN BIT(30)
43#define SLINK_CMD2_RXEN BIT(31)
44#define SLINK_CMD2_SS_EN BIT(18)
Allen Martin8db241b2013-03-16 18:58:05 +000045#define SLINK_CMD2_SS_EN_SHIFT 18
Jagan Teki54badcb2015-10-23 01:03:10 +053046#define SLINK_CMD2_SS_EN_MASK GENMASK(19, 18)
Jagan Teki7f7ccf72015-10-23 01:39:06 +053047#define SLINK_CMD2_CS_ACTIVE_BETWEEN BIT(17)
Allen Martin8db241b2013-03-16 18:58:05 +000048/* STATUS */
Jagan Teki7f7ccf72015-10-23 01:39:06 +053049#define SLINK_STAT_BSY BIT(31)
50#define SLINK_STAT_RDY BIT(30)
51#define SLINK_STAT_ERR BIT(29)
52#define SLINK_STAT_RXF_FLUSH BIT(27)
53#define SLINK_STAT_TXF_FLUSH BIT(26)
54#define SLINK_STAT_RXF_OVF BIT(25)
55#define SLINK_STAT_TXF_UNR BIT(24)
56#define SLINK_STAT_RXF_EMPTY BIT(23)
57#define SLINK_STAT_RXF_FULL BIT(22)
58#define SLINK_STAT_TXF_EMPTY BIT(21)
59#define SLINK_STAT_TXF_FULL BIT(20)
60#define SLINK_STAT_TXF_OVF BIT(19)
61#define SLINK_STAT_RXF_UNR BIT(18)
62#define SLINK_STAT_CUR_BLKCNT BIT(15)
Allen Martin8db241b2013-03-16 18:58:05 +000063/* STATUS2 */
Jagan Teki7f7ccf72015-10-23 01:39:06 +053064#define SLINK_STAT2_RXF_FULL_CNT BIT(16)
65#define SLINK_STAT2_TXF_FULL_CNT BIT(0)
Allen Martin8db241b2013-03-16 18:58:05 +000066
67#define SPI_TIMEOUT 1000
68#define TEGRA_SPI_MAX_FREQ 52000000
69
Svyatoslav Ryhel7e10c462025-01-26 19:48:22 +020070unsigned int cmd_cs_pol_bit[] = {
71 SLINK_CMD_CS_POL,
72 SLINK_CMD_CS_POL1,
73 SLINK_CMD_CS_POL2,
74 SLINK_CMD_CS_POL3,
75};
76
Allen Martin8db241b2013-03-16 18:58:05 +000077struct spi_regs {
78 u32 command; /* SLINK_COMMAND_0 register */
79 u32 command2; /* SLINK_COMMAND2_0 reg */
80 u32 status; /* SLINK_STATUS_0 register */
81 u32 reserved; /* Reserved offset 0C */
82 u32 mas_data; /* SLINK_MAS_DATA_0 reg */
83 u32 slav_data; /* SLINK_SLAVE_DATA_0 reg */
84 u32 dma_ctl; /* SLINK_DMA_CTL_0 register */
85 u32 status2; /* SLINK_STATUS2_0 reg */
86 u32 rsvd[56]; /* 0x20 to 0xFF reserved */
87 u32 tx_fifo; /* SLINK_TX_FIFO_0 reg off 100h */
88 u32 rsvd2[31]; /* 0x104 to 0x17F reserved */
89 u32 rx_fifo; /* SLINK_RX_FIFO_0 reg off 180h */
90};
91
Simon Glass1121b1b2014-10-13 23:42:13 -060092struct tegra30_spi_priv {
Allen Martin8db241b2013-03-16 18:58:05 +000093 struct spi_regs *regs;
Allen Martinba4fb9b2013-01-29 13:51:28 +000094 unsigned int freq;
95 unsigned int mode;
96 int periph_id;
97 int valid;
Simon Glass1121b1b2014-10-13 23:42:13 -060098 int last_transaction_us;
Allen Martinba4fb9b2013-01-29 13:51:28 +000099};
100
101struct tegra_spi_slave {
102 struct spi_slave slave;
Simon Glass1121b1b2014-10-13 23:42:13 -0600103 struct tegra30_spi_priv *ctrl;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000104};
105
Simon Glassaad29ae2020-12-03 16:55:21 -0700106static int tegra30_spi_of_to_plat(struct udevice *bus)
Allen Martinba4fb9b2013-01-29 13:51:28 +0000107{
Simon Glass95588622020-12-22 19:30:28 -0700108 struct tegra_spi_plat *plat = dev_get_plat(bus);
Simon Glass1121b1b2014-10-13 23:42:13 -0600109 const void *blob = gd->fdt_blob;
Simon Glassdd79d6e2017-01-17 16:52:55 -0700110 int node = dev_of_offset(bus);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000111
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +0900112 plat->base = dev_read_addr(bus);
Simon Glassc3f26502017-07-25 08:30:00 -0600113 plat->periph_id = clock_decode_periph_id(bus);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000114
Simon Glass1121b1b2014-10-13 23:42:13 -0600115 if (plat->periph_id == PERIPH_ID_NONE) {
116 debug("%s: could not decode periph id %d\n", __func__,
117 plat->periph_id);
118 return -FDT_ERR_NOTFOUND;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000119 }
120
Simon Glass1121b1b2014-10-13 23:42:13 -0600121 /* Use 500KHz as a suitable default */
122 plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
123 500000);
124 plat->deactivate_delay_us = fdtdec_get_int(blob, node,
125 "spi-deactivate-delay", 0);
126 debug("%s: base=%#08lx, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
127 __func__, plat->base, plat->periph_id, plat->frequency,
128 plat->deactivate_delay_us);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000129
Simon Glass1121b1b2014-10-13 23:42:13 -0600130 return 0;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000131}
132
Simon Glass1121b1b2014-10-13 23:42:13 -0600133static int tegra30_spi_probe(struct udevice *bus)
Allen Martinba4fb9b2013-01-29 13:51:28 +0000134{
Simon Glassb75b15b2020-12-03 16:55:23 -0700135 struct tegra_spi_plat *plat = dev_get_plat(bus);
Simon Glass1121b1b2014-10-13 23:42:13 -0600136 struct tegra30_spi_priv *priv = dev_get_priv(bus);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000137
Simon Glass1121b1b2014-10-13 23:42:13 -0600138 priv->regs = (struct spi_regs *)plat->base;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000139
Simon Glass1121b1b2014-10-13 23:42:13 -0600140 priv->last_transaction_us = timer_get_us();
141 priv->freq = plat->frequency;
142 priv->periph_id = plat->periph_id;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000143
Stephen Warrenb68a9942016-08-18 10:53:33 -0600144 /* Change SPI clock to correct frequency, PLLP_OUT0 source */
145 clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH,
146 priv->freq);
147
Simon Glass1121b1b2014-10-13 23:42:13 -0600148 return 0;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000149}
150
Simon Glass5c74fba2015-04-19 09:05:40 -0600151static int tegra30_spi_claim_bus(struct udevice *dev)
Allen Martinba4fb9b2013-01-29 13:51:28 +0000152{
Simon Glass5c74fba2015-04-19 09:05:40 -0600153 struct udevice *bus = dev->parent;
Simon Glass1121b1b2014-10-13 23:42:13 -0600154 struct tegra30_spi_priv *priv = dev_get_priv(bus);
155 struct spi_regs *regs = priv->regs;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000156 u32 reg;
157
158 /* Change SPI clock to correct frequency, PLLP_OUT0 source */
Simon Glass1121b1b2014-10-13 23:42:13 -0600159 clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH,
160 priv->freq);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000161
162 /* Clear stale status here */
163 reg = SLINK_STAT_RDY | SLINK_STAT_RXF_FLUSH | SLINK_STAT_TXF_FLUSH | \
164 SLINK_STAT_RXF_UNR | SLINK_STAT_TXF_OVF;
165 writel(reg, &regs->status);
166 debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));
167
Svyatoslav Ryhel7e10c462025-01-26 19:48:22 +0200168 /* Update the polarity bits */
169 if (priv->mode & SPI_CS_HIGH)
170 setbits_le32(&priv->regs->command,
171 cmd_cs_pol_bit[spi_chip_select(dev)]);
172 else
173 clrbits_le32(&priv->regs->command,
174 cmd_cs_pol_bit[spi_chip_select(dev)]);
175
Allen Martinba4fb9b2013-01-29 13:51:28 +0000176 /* Set master mode and sw controlled CS */
177 reg = readl(&regs->command);
178 reg |= SLINK_CMD_M_S | SLINK_CMD_CS_SOFT;
179 writel(reg, &regs->command);
180 debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
181
182 return 0;
183}
184
Simon Glass1121b1b2014-10-13 23:42:13 -0600185static void spi_cs_activate(struct udevice *dev)
Allen Martinba4fb9b2013-01-29 13:51:28 +0000186{
Simon Glass1121b1b2014-10-13 23:42:13 -0600187 struct udevice *bus = dev->parent;
Simon Glassb75b15b2020-12-03 16:55:23 -0700188 struct tegra_spi_plat *pdata = dev_get_plat(bus);
Simon Glass1121b1b2014-10-13 23:42:13 -0600189 struct tegra30_spi_priv *priv = dev_get_priv(bus);
190
191 /* If it's too soon to do another transaction, wait */
192 if (pdata->deactivate_delay_us &&
193 priv->last_transaction_us) {
194 ulong delay_us; /* The delay completed so far */
195 delay_us = timer_get_us() - priv->last_transaction_us;
196 if (delay_us < pdata->deactivate_delay_us)
197 udelay(pdata->deactivate_delay_us - delay_us);
198 }
Allen Martinba4fb9b2013-01-29 13:51:28 +0000199
200 /* CS is negated on Tegra, so drive a 1 to get a 0 */
Simon Glass1121b1b2014-10-13 23:42:13 -0600201 setbits_le32(&priv->regs->command, SLINK_CMD_CS_VAL);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000202}
203
Simon Glass1121b1b2014-10-13 23:42:13 -0600204static void spi_cs_deactivate(struct udevice *dev)
Allen Martinba4fb9b2013-01-29 13:51:28 +0000205{
Simon Glass1121b1b2014-10-13 23:42:13 -0600206 struct udevice *bus = dev->parent;
Simon Glassb75b15b2020-12-03 16:55:23 -0700207 struct tegra_spi_plat *pdata = dev_get_plat(bus);
Simon Glass1121b1b2014-10-13 23:42:13 -0600208 struct tegra30_spi_priv *priv = dev_get_priv(bus);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000209
210 /* CS is negated on Tegra, so drive a 0 to get a 1 */
Simon Glass1121b1b2014-10-13 23:42:13 -0600211 clrbits_le32(&priv->regs->command, SLINK_CMD_CS_VAL);
212
213 /* Remember time of this transaction so we can honour the bus delay */
214 if (pdata->deactivate_delay_us)
215 priv->last_transaction_us = timer_get_us();
Allen Martinba4fb9b2013-01-29 13:51:28 +0000216}
217
Simon Glass1121b1b2014-10-13 23:42:13 -0600218static int tegra30_spi_xfer(struct udevice *dev, unsigned int bitlen,
219 const void *data_out, void *data_in,
220 unsigned long flags)
Allen Martinba4fb9b2013-01-29 13:51:28 +0000221{
Simon Glass1121b1b2014-10-13 23:42:13 -0600222 struct udevice *bus = dev->parent;
223 struct tegra30_spi_priv *priv = dev_get_priv(bus);
224 struct spi_regs *regs = priv->regs;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000225 u32 reg, tmpdout, tmpdin = 0;
226 const u8 *dout = data_out;
227 u8 *din = data_in;
Svyatoslav Ryhel74916e82023-02-14 19:35:29 +0200228 int num_bytes, overflow;
229 int ret = 0;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000230
231 debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
Simon Glass75e534b2020-12-16 21:20:07 -0700232 __func__, dev_seq(bus), spi_chip_select(dev), dout, din, bitlen);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000233
Svyatoslav Ryhel74916e82023-02-14 19:35:29 +0200234 num_bytes = DIV_ROUND_UP(bitlen, 8);
235 overflow = bitlen % 8;
Allen Martinba4fb9b2013-01-29 13:51:28 +0000236
237 reg = readl(&regs->status);
238 writel(reg, &regs->status); /* Clear all SPI events via R/W */
239 debug("%s entry: STATUS = %08x\n", __func__, reg);
240
241 reg = readl(&regs->status2);
242 writel(reg, &regs->status2); /* Clear all STATUS2 events via R/W */
243 debug("%s entry: STATUS2 = %08x\n", __func__, reg);
244
245 debug("%s entry: COMMAND = %08x\n", __func__, readl(&regs->command));
246
247 clrsetbits_le32(&regs->command2, SLINK_CMD2_SS_EN_MASK,
248 SLINK_CMD2_TXEN | SLINK_CMD2_RXEN |
Simon Glass1121b1b2014-10-13 23:42:13 -0600249 (spi_chip_select(dev) << SLINK_CMD2_SS_EN_SHIFT));
Allen Martinba4fb9b2013-01-29 13:51:28 +0000250 debug("%s entry: COMMAND2 = %08x\n", __func__, readl(&regs->command2));
251
252 if (flags & SPI_XFER_BEGIN)
Simon Glass1121b1b2014-10-13 23:42:13 -0600253 spi_cs_activate(dev);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000254
255 /* handle data in 32-bit chunks */
256 while (num_bytes > 0) {
257 int bytes;
258 int is_read = 0;
259 int tm, i;
260
261 tmpdout = 0;
262 bytes = (num_bytes > 4) ? 4 : num_bytes;
263
264 if (dout != NULL) {
265 for (i = 0; i < bytes; ++i)
266 tmpdout = (tmpdout << 8) | dout[i];
267 dout += bytes;
268 }
269
270 num_bytes -= bytes;
271
Svyatoslav Ryhel74916e82023-02-14 19:35:29 +0200272 if (overflow && !num_bytes)
273 clrsetbits_le32(&regs->command, SLINK_CMD_BIT_LENGTH_MASK,
274 (bytes - 1) * 8 + overflow - 1);
275 else
276 clrsetbits_le32(&regs->command, SLINK_CMD_BIT_LENGTH_MASK,
277 bytes * 8 - 1);
278
Allen Martinba4fb9b2013-01-29 13:51:28 +0000279 writel(tmpdout, &regs->tx_fifo);
280 setbits_le32(&regs->command, SLINK_CMD_GO);
281
282 /*
283 * Wait for SPI transmit FIFO to empty, or to time out.
284 * The RX FIFO status will be read and cleared last
285 */
286 for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
287 u32 status;
288
289 status = readl(&regs->status);
290
291 /* We can exit when we've had both RX and TX activity */
292 if (is_read && (status & SLINK_STAT_TXF_EMPTY))
293 break;
294
295 if ((status & (SLINK_STAT_BSY | SLINK_STAT_RDY)) !=
296 SLINK_STAT_RDY)
297 tm++;
298
299 else if (!(status & SLINK_STAT_RXF_EMPTY)) {
300 tmpdin = readl(&regs->rx_fifo);
301 is_read = 1;
302
303 /* swap bytes read in */
304 if (din != NULL) {
305 for (i = bytes - 1; i >= 0; --i) {
306 din[i] = tmpdin & 0xff;
307 tmpdin >>= 8;
308 }
309 din += bytes;
310 }
311 }
312 }
313
314 if (tm >= SPI_TIMEOUT)
315 ret = tm;
316
317 /* clear ACK RDY, etc. bits */
318 writel(readl(&regs->status), &regs->status);
319 }
320
321 if (flags & SPI_XFER_END)
Simon Glass1121b1b2014-10-13 23:42:13 -0600322 spi_cs_deactivate(dev);
Allen Martinba4fb9b2013-01-29 13:51:28 +0000323
324 debug("%s: transfer ended. Value=%08x, status = %08x\n",
325 __func__, tmpdin, readl(&regs->status));
326
327 if (ret) {
328 printf("%s: timeout during SPI transfer, tm %d\n",
329 __func__, ret);
330 return -1;
331 }
332
333 return 0;
334}
Simon Glass1121b1b2014-10-13 23:42:13 -0600335
336static int tegra30_spi_set_speed(struct udevice *bus, uint speed)
337{
Simon Glass95588622020-12-22 19:30:28 -0700338 struct tegra_spi_plat *plat = dev_get_plat(bus);
Simon Glass1121b1b2014-10-13 23:42:13 -0600339 struct tegra30_spi_priv *priv = dev_get_priv(bus);
340
341 if (speed > plat->frequency)
342 speed = plat->frequency;
343 priv->freq = speed;
344 debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
345
346 return 0;
347}
348
349static int tegra30_spi_set_mode(struct udevice *bus, uint mode)
350{
351 struct tegra30_spi_priv *priv = dev_get_priv(bus);
Mirza Krak960dad92015-09-08 10:30:49 +0200352 struct spi_regs *regs = priv->regs;
353 u32 reg;
354
355 reg = readl(&regs->command);
356
357 /* Set CPOL and CPHA */
358 reg &= ~(SLINK_CMD_IDLE_SCLK_MASK | SLINK_CMD_CK_SDA);
359 if (mode & SPI_CPHA)
360 reg |= SLINK_CMD_CK_SDA;
361
362 if (mode & SPI_CPOL)
363 reg |= SLINK_CMD_IDLE_SCLK_DRIVE_HIGH;
364 else
365 reg |= SLINK_CMD_IDLE_SCLK_DRIVE_LOW;
366
367 writel(reg, &regs->command);
Simon Glass1121b1b2014-10-13 23:42:13 -0600368
369 priv->mode = mode;
370 debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
371
372 return 0;
373}
374
375static const struct dm_spi_ops tegra30_spi_ops = {
376 .claim_bus = tegra30_spi_claim_bus,
377 .xfer = tegra30_spi_xfer,
378 .set_speed = tegra30_spi_set_speed,
379 .set_mode = tegra30_spi_set_mode,
380 /*
381 * cs_info is not needed, since we require all chip selects to be
382 * in the device tree explicitly
383 */
384};
385
386static const struct udevice_id tegra30_spi_ids[] = {
387 { .compatible = "nvidia,tegra20-slink" },
388 { }
389};
390
391U_BOOT_DRIVER(tegra30_spi) = {
392 .name = "tegra20_slink",
393 .id = UCLASS_SPI,
394 .of_match = tegra30_spi_ids,
395 .ops = &tegra30_spi_ops,
Simon Glassaad29ae2020-12-03 16:55:21 -0700396 .of_to_plat = tegra30_spi_of_to_plat,
Simon Glassb75b15b2020-12-03 16:55:23 -0700397 .plat_auto = sizeof(struct tegra_spi_plat),
Simon Glass8a2b47f2020-12-03 16:55:17 -0700398 .priv_auto = sizeof(struct tegra30_spi_priv),
Simon Glass1121b1b2014-10-13 23:42:13 -0600399 .probe = tegra30_spi_probe,
400};