summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0006-SPI-Quad-IO-Mode.patch
blob: ca5846416d769d739a57454a2defb2cf69f2b787 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
From 8c953c7f1d512cf4acd9ce000d65e46094d61597 Mon Sep 17 00:00:00 2001
From: arun-pm <arun.p.m@linux.intel.com>
Date: Fri, 29 Nov 2019 00:19:09 +0530
Subject: [PATCH] SPI Quad IO Mode

This commit adds quad IO mode in SPI driver for AST2600.

Note:- Removed n25q00 Quad I/O support for the time being due to clock issue
 with chip 'Micron 8UA15 - rw182 (128MB)' while enabling Quad I/O mode.
---
 arch/arm/dts/ast2600-intel.dts |  6 ++---
 drivers/mtd/spi/spi-nor-ids.c  |  7 +++++-
 drivers/spi/aspeed_spi.c       | 46 ++++++++++++++++++++++++----------
 3 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/arch/arm/dts/ast2600-intel.dts b/arch/arm/dts/ast2600-intel.dts
index 0d362ac7c1..2a74bbd30a 100644
--- a/arch/arm/dts/ast2600-intel.dts
+++ b/arch/arm/dts/ast2600-intel.dts
@@ -101,16 +101,14 @@
 
 &fmc {
 	status = "okay";
-#if 0
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_fmcquad_default>;
-#endif
 	flash@0 {
 		compatible = "spi-flash", "sst,w25q256";
 		status = "okay";
 		spi-max-frequency = <40000000>;
-		spi-tx-bus-width = <2>;
-		spi-rx-bus-width = <2>;
+		spi-tx-bus-width = <4>;
+		spi-rx-bus-width = <4>;
 	};
 };
 
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index c77987f1ff..d679238562 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -164,7 +164,12 @@ const struct flash_info spi_nor_ids[] = {
 	{ INFO("n25q256ax1",  0x20bb19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("n25q512a",    0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("n25q512ax3",  0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ INFO("n25q00",      0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+	/* Removed n25q00 Quad I/O support for the time being due to clock issue with chip 'Micron 8UA15 - rw182 (128MB)'
+	 * while enabling Quad I/O mode. As this chip is default shipped in platforms, marking it
+	 * as Not supported for the time being. Once all chips are replaced with the new model, this can be enabled
+	 * back(Note:- Certain other chips having same name(n25q00) but different part number has no issues).
+	 */
+	{ INFO("n25q00",      0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | NO_CHIP_ERASE) },
 	{ INFO("n25q00a",     0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
 	{ INFO("mt25qu02g",   0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
 #endif
diff --git a/drivers/spi/aspeed_spi.c b/drivers/spi/aspeed_spi.c
index a8c2b3de2b..ae5edaee9f 100644
--- a/drivers/spi/aspeed_spi.c
+++ b/drivers/spi/aspeed_spi.c
@@ -16,6 +16,9 @@
 #include <linux/ioport.h>
 
 #define ASPEED_SPI_MAX_CS		3
+#define AST2600A0		0x05000303
+#define AST2600A0_MAX_FREQ		40000000
+#define AST_MAX_FREQ		100000000
 
 struct aspeed_spi_regs {
 	u32 conf;			/* 0x00 CE Type Setting */
@@ -593,6 +596,7 @@ static int aspeed_spi_write_reg(struct aspeed_spi_priv *priv,
 	aspeed_spi_write_to_ahb(flash->ahb_base, write_buf, len);
 	aspeed_spi_stop_user(priv, flash);
 
+	debug("=== write opcode [%x] ==== \n", opcode);
 	switch(opcode) {
 		case SPINOR_OP_EN4B:
 			writel(readl(&priv->regs->ctrl) | BIT(flash->cs), &priv->regs->ctrl);
@@ -615,6 +619,8 @@ static void aspeed_spi_send_cmd_addr(struct aspeed_spi_priv *priv,
 	/* First, send the opcode */
 	aspeed_spi_write_to_ahb(flash->ahb_base, &cmdbuf[0], 1);
 
+	if(flash->iomode == CE_CTRL_IO_QUAD_ADDR_DATA)
+		writel(flash->ce_ctrl_user | flash->iomode, &priv->regs->ce_ctrl[flash->cs]);
 	/*
 	 * The controller is configured for 4BYTE address mode. Fix
 	 * the address width and send an extra byte if the SPI Flash
@@ -664,9 +670,6 @@ static ssize_t aspeed_spi_write_user(struct aspeed_spi_priv *priv,
 {
 	aspeed_spi_start_user(priv, flash);
 
-	if(flash->iomode == CE_CTRL_IO_QPI_DATA)
-		writel(flash->ce_ctrl_user | flash->iomode, &priv->regs->ce_ctrl[flash->cs]);
-	
 	/* cmd buffer = cmd + addr : normally cmd is use signle mode*/
 	aspeed_spi_send_cmd_addr(priv, flash, cmdbuf, cmdlen);
 
@@ -872,15 +875,19 @@ static int aspeed_spi_flash_init(struct aspeed_spi_priv *priv,
 	else
 		read_hclk = aspeed_spi_hclk_divisor(priv, slave->speed);
 
-	if (slave->mode & (SPI_RX_DUAL | SPI_TX_DUAL)) {
-		debug("CS%u: setting dual data mode\n", flash->cs);
-		flash->iomode = CE_CTRL_IO_DUAL_DATA;
-		flash->spi->read_opcode = SPINOR_OP_READ_1_1_2;
-	} else if (slave->mode & (SPI_RX_QUAD | SPI_TX_QUAD)) {
-		flash->iomode = CE_CTRL_IO_QUAD_DATA;
-		flash->spi->read_opcode = SPINOR_OP_READ_1_4_4;
-	} else {
-		debug("normal read \n");
+	switch(flash->spi->read_opcode) {
+		case SPINOR_OP_READ_1_1_2:
+		case SPINOR_OP_READ_1_1_2_4B:
+			flash->iomode = CE_CTRL_IO_DUAL_DATA;
+			break;
+		case SPINOR_OP_READ_1_1_4:
+		case SPINOR_OP_READ_1_1_4_4B:
+			flash->iomode = CE_CTRL_IO_QUAD_DATA;
+			break;
+		case SPINOR_OP_READ_1_4_4:
+		case SPINOR_OP_READ_1_4_4_4B:
+			flash->iomode = CE_CTRL_IO_QUAD_ADDR_DATA;
+			break;
 	}
 
 	if(priv->new_ver) {
@@ -986,6 +993,19 @@ static int aspeed_spi_bind(struct udevice *bus)
 	return 0;
 }
 
+static int aspeed_get_max_freq(void)
+{
+	u32 rev_id = readl(ASPEED_REVISION_ID);
+
+	/*Limit max spi frequency less than 50MHz on AST2600-A0 due
+	 * to FWSPICLK  signal quality issue.
+	 */
+	if(rev_id == AST2600A0)
+		return AST2600A0_MAX_FREQ;
+	else
+		return AST_MAX_FREQ;
+}
+
 static int aspeed_spi_probe(struct udevice *bus)
 {
 	struct resource res_regs, res_ahb;
@@ -1016,7 +1036,7 @@ static int aspeed_spi_probe(struct udevice *bus)
 	clk_free(&hclk);
 
 	priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency",
-					    100000000);
+					    aspeed_get_max_freq());
 
 	priv->num_cs = dev_read_u32_default(bus, "num-cs", ASPEED_SPI_MAX_CS);
 
-- 
2.17.1