Skip to content

Commit df8c5ad

Browse files
committed
Configure Clocks, Add Internal DMA support
Merge series from Vishwaroop A <[email protected]>: This series introduces QSPI clock configuration and internal DMA support for Quad SPI controller. The patches have been reorganized for better logical flow and review comments from v2 have been addressed.
2 parents 7caae11 + c283fcd commit df8c5ad

File tree

1 file changed

+34
-21
lines changed

1 file changed

+34
-21
lines changed

drivers/spi/spi-tegra210-quad.c

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/spi/spi.h>
2323
#include <linux/acpi.h>
2424
#include <linux/property.h>
25+
#include <linux/sizes.h>
2526

2627
#define QSPI_COMMAND1 0x000
2728
#define QSPI_BIT_LENGTH(x) (((x) & 0x1f) << 0)
@@ -134,7 +135,7 @@
134135
#define QSPI_COMMAND_VALUE_SET(X) (((x) & 0xFF) << 0)
135136

136137
#define QSPI_CMB_SEQ_CMD_CFG 0x1a0
137-
#define QSPI_COMMAND_X1_X2_X4(x) (((x) & 0x3) << 13)
138+
#define QSPI_COMMAND_X1_X2_X4(x) ((((x) >> 1) & 0x3) << 13)
138139
#define QSPI_COMMAND_X1_X2_X4_MASK (0x03 << 13)
139140
#define QSPI_COMMAND_SDR_DDR BIT(12)
140141
#define QSPI_COMMAND_SIZE_SET(x) (((x) & 0xFF) << 0)
@@ -147,7 +148,7 @@
147148
#define QSPI_ADDRESS_VALUE_SET(X) (((x) & 0xFFFF) << 0)
148149

149150
#define QSPI_CMB_SEQ_ADDR_CFG 0x1ac
150-
#define QSPI_ADDRESS_X1_X2_X4(x) (((x) & 0x3) << 13)
151+
#define QSPI_ADDRESS_X1_X2_X4(x) ((((x) >> 1) & 0x3) << 13)
151152
#define QSPI_ADDRESS_X1_X2_X4_MASK (0x03 << 13)
152153
#define QSPI_ADDRESS_SDR_DDR BIT(12)
153154
#define QSPI_ADDRESS_SIZE_SET(x) (((x) & 0xFF) << 0)
@@ -156,10 +157,14 @@
156157
#define DATA_DIR_RX BIT(1)
157158

158159
#define QSPI_DMA_TIMEOUT (msecs_to_jiffies(1000))
159-
#define DEFAULT_QSPI_DMA_BUF_LEN (64 * 1024)
160-
#define CMD_TRANSFER 0
161-
#define ADDR_TRANSFER 1
162-
#define DATA_TRANSFER 2
160+
#define DEFAULT_QSPI_DMA_BUF_LEN SZ_64K
161+
162+
enum tegra_qspi_transfer_type {
163+
CMD_TRANSFER = 0,
164+
ADDR_TRANSFER = 1,
165+
DUMMY_TRANSFER = 2,
166+
DATA_TRANSFER = 3
167+
};
163168

164169
struct tegra_qspi_soc_data {
165170
bool has_dma;
@@ -1036,10 +1041,6 @@ static u32 tegra_qspi_addr_config(bool is_ddr, u8 bus_width, u8 len)
10361041
{
10371042
u32 addr_config = 0;
10381043

1039-
/* Extract Address configuration and value */
1040-
is_ddr = 0; //Only SDR mode supported
1041-
bus_width = 0; //X1 mode
1042-
10431044
if (is_ddr)
10441045
addr_config |= QSPI_ADDRESS_SDR_DDR;
10451046
else
@@ -1079,16 +1080,23 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
10791080
switch (transfer_phase) {
10801081
case CMD_TRANSFER:
10811082
/* X1 SDR mode */
1082-
cmd_config = tegra_qspi_cmd_config(false, 0,
1083+
cmd_config = tegra_qspi_cmd_config(false, xfer->tx_nbits,
10831084
xfer->len);
10841085
cmd_value = *((const u8 *)(xfer->tx_buf));
10851086
break;
10861087
case ADDR_TRANSFER:
10871088
/* X1 SDR mode */
1088-
addr_config = tegra_qspi_addr_config(false, 0,
1089+
addr_config = tegra_qspi_addr_config(false, xfer->tx_nbits,
10891090
xfer->len);
10901091
address_value = *((const u32 *)(xfer->tx_buf));
10911092
break;
1093+
case DUMMY_TRANSFER:
1094+
if (xfer->dummy_data) {
1095+
tqspi->dummy_cycles = xfer->len * 8 / xfer->tx_nbits;
1096+
break;
1097+
}
1098+
transfer_phase++;
1099+
fallthrough;
10921100
case DATA_TRANSFER:
10931101
/* Program Command, Address value in register */
10941102
tegra_qspi_writel(tqspi, cmd_value, QSPI_CMB_SEQ_CMD);
@@ -1163,26 +1171,22 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
11631171
ret = -EIO;
11641172
goto exit;
11651173
}
1166-
if (!xfer->cs_change) {
1167-
tegra_qspi_transfer_end(spi);
1168-
spi_transfer_delay_exec(xfer);
1169-
}
11701174
break;
11711175
default:
11721176
ret = -EINVAL;
11731177
goto exit;
11741178
}
11751179
msg->actual_length += xfer->len;
1180+
if (!xfer->cs_change && transfer_phase == DATA_TRANSFER) {
1181+
tegra_qspi_transfer_end(spi);
1182+
spi_transfer_delay_exec(xfer);
1183+
}
11761184
transfer_phase++;
11771185
}
11781186
ret = 0;
11791187

11801188
exit:
11811189
msg->status = ret;
1182-
if (ret < 0) {
1183-
tegra_qspi_transfer_end(spi);
1184-
spi_transfer_delay_exec(xfer);
1185-
}
11861190

11871191
return ret;
11881192
}
@@ -1300,7 +1304,9 @@ static bool tegra_qspi_validate_cmb_seq(struct tegra_qspi *tqspi,
13001304
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
13011305
transfer_count++;
13021306
}
1303-
if (!tqspi->soc_data->cmb_xfer_capable || transfer_count != 3)
1307+
if (!tqspi->soc_data->cmb_xfer_capable)
1308+
return false;
1309+
if (transfer_count > 4 || transfer_count < 3)
13041310
return false;
13051311
xfer = list_first_entry(&msg->transfers, typeof(*xfer),
13061312
transfer_list);
@@ -1310,6 +1316,13 @@ static bool tegra_qspi_validate_cmb_seq(struct tegra_qspi *tqspi,
13101316
if (xfer->len > 4 || xfer->len < 3)
13111317
return false;
13121318
xfer = list_next_entry(xfer, transfer_list);
1319+
if (transfer_count == 4) {
1320+
if (xfer->dummy_data != 1)
1321+
return false;
1322+
if ((xfer->len * 8 / xfer->tx_nbits) > QSPI_DUMMY_CYCLES_MAX)
1323+
return false;
1324+
xfer = list_next_entry(xfer, transfer_list);
1325+
}
13131326
if (!tqspi->soc_data->has_dma && xfer->len > (QSPI_FIFO_DEPTH << 2))
13141327
return false;
13151328

0 commit comments

Comments
 (0)