aboutsummaryrefslogtreecommitdiffstats
path: root/package/boot/uboot-lantiq/patches/0006-sf-add-generic-support-for-4-byte-address-mode.patch
blob: 1623b1527bc1e417633a1bcea8ac26d9fba1f1a1 (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
159
160
161
From fb9ed0ef6f0ba6b6535c64dcfcf45c161723e56f Mon Sep 17 00:00:00 2001
From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Date: Tue, 6 Nov 2012 19:31:38 +0100
Subject: sf: add generic support for 4-byte address mode

Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -18,19 +18,35 @@
 static void spi_flash_addr(struct spi_flash *flash, u32 addr, u8 *cmd, u8 *cmd_len)
 {
 	/* cmd[0] is actual command */
-	cmd[1] = addr >> 16;
-	cmd[2] = addr >> 8;
-	cmd[3] = addr >> 0;
-	*cmd_len = 4;
+	if (spi_flash_use_4byte_mode(flash)) {
+		cmd[1] = addr >> 24;
+		cmd[2] = addr >> 16;
+		cmd[3] = addr >> 8;
+		cmd[4] = addr >> 0;
+		*cmd_len = 5;
+	} else {
+		cmd[1] = addr >> 16;
+		cmd[2] = addr >> 8;
+		cmd[3] = addr >> 0;
+		*cmd_len = 4;
+	}
 }
 
 static void spi_flash_page_addr(struct spi_flash *flash, u32 page_addr, u32 byte_addr, u8 *cmd, u8 *cmd_len)
 {
 	/* cmd[0] is actual command */
-	cmd[1] = page_addr >> 8;
-	cmd[2] = page_addr >> 0;
-	cmd[3] = byte_addr;
-	*cmd_len = 4;
+	if (spi_flash_use_4byte_mode(flash)) {
+		cmd[1] = page_addr >> 16;
+		cmd[2] = page_addr >> 8;
+		cmd[3] = page_addr >> 0;
+		cmd[4] = byte_addr;
+		*cmd_len = 5;
+	} else {
+		cmd[1] = page_addr >> 8;
+		cmd[2] = page_addr >> 0;
+		cmd[3] = byte_addr;
+		*cmd_len = 4;
+	}
 }
 
 static int spi_flash_read_write(struct spi_slave *spi,
@@ -81,7 +97,7 @@ int spi_flash_cmd_write_multi(struct spi
 	unsigned long page_addr, byte_addr, page_size;
 	size_t chunk_len, actual;
 	int ret;
-	u8 cmd[4], cmd_len;
+	u8 cmd[5], cmd_len;
 
 	page_size = flash->page_size;
 	page_addr = offset / page_size;
@@ -99,8 +115,8 @@ int spi_flash_cmd_write_multi(struct spi
 
 		spi_flash_page_addr(flash, page_addr, byte_addr, cmd, &cmd_len);
 
-		debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
-		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
+		debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x%02x } chunk_len = %zu\n",
+		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], chunk_len);
 
 		ret = spi_flash_cmd_write_enable(flash);
 		if (ret < 0) {
@@ -146,7 +162,7 @@ int spi_flash_read_common(struct spi_fla
 int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 		size_t len, void *data)
 {
-	u8 cmd[5], cmd_len;
+	u8 cmd[6], cmd_len;
 
 	cmd[0] = CMD_READ_ARRAY_FAST;
 	spi_flash_addr(flash, offset, cmd, &cmd_len);
@@ -202,7 +218,7 @@ int spi_flash_cmd_erase(struct spi_flash
 {
 	u32 start, end, erase_size;
 	int ret;
-	u8 cmd[4], cmd_len;
+	u8 cmd[5], cmd_len;
 
 	erase_size = flash->sector_size;
 	if (offset % erase_size || len % erase_size) {
@@ -227,8 +243,8 @@ int spi_flash_cmd_erase(struct spi_flash
 		spi_flash_addr(flash, offset, cmd, &cmd_len);
 		offset += erase_size;
 
-		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
-		      cmd[2], cmd[3], offset);
+		debug("SF: erase %2x %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
+		      cmd[2], cmd[3], cmd[4], offset);
 
 		ret = spi_flash_cmd_write_enable(flash);
 		if (ret)
@@ -409,6 +425,12 @@ int spi_flash_probe_spl(struct spi_flash
 		goto err_manufacturer_probe;
 	}
 
+	ret = spi_flash_set_4byte_mode(flash);
+	if (ret) {
+		debug("SF: Failed to enable 4 byte mode: %d\n", ret);
+		goto err_manufacturer_probe;
+	}
+
 	spi_release_bus(spi);
 
 	return 0;
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -97,6 +97,31 @@ int spi_flash_cmd_wait_ready(struct spi_
 /* Erase sectors. */
 int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len);
 
+#ifdef CONFIG_SPI_FLASH_4BYTE_MODE
+static inline int spi_flash_use_4byte_mode(struct spi_flash *flash)
+{
+	return NULL != flash->set_4byte_mode;
+}
+
+static inline int spi_flash_set_4byte_mode(struct spi_flash *flash)
+{
+	if (spi_flash_use_4byte_mode(flash))
+		return flash->set_4byte_mode(flash);
+
+	return 0;
+}
+#else
+static inline int spi_flash_use_4byte_mode(struct spi_flash *flash)
+{
+	return 0;
+}
+
+static inline int spi_flash_set_4byte_mode(struct spi_flash *flash)
+{
+	return 0;
+}
+#endif
+
 /* Manufacturer-specific probe functions */
 int spi_flash_probe_spansion(struct spi_flash *flash, u8 *idcode);
 int spi_flash_probe_atmel(struct spi_flash *flash, u8 *idcode);
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -46,6 +46,9 @@ struct spi_flash {
 				size_t len, const void *buf);
 	int		(*erase)(struct spi_flash *flash, u32 offset,
 				size_t len);
+#ifdef CONFIG_SPI_FLASH_4BYTE_MODE
+	int		(*set_4byte_mode)(struct spi_flash *flash);
+#endif
 };
 
 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,