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
|
From 3af3addee645bd81537be1ddee49969f8dfc64ee Mon Sep 17 00:00:00 2001
From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Date: Sun, 13 Oct 2013 15:24:56 +0200
Subject: sf: add support for 4-byte addressing
Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -38,12 +38,14 @@
#define CMD_READ_ID 0x9f
/* Bank addr access commands */
-#ifdef CONFIG_SPI_FLASH_BAR
-# define CMD_BANKADDR_BRWR 0x17
-# define CMD_BANKADDR_BRRD 0x16
-# define CMD_EXTNADDR_WREAR 0xC5
-# define CMD_EXTNADDR_RDEAR 0xC8
-#endif
+#define CMD_BANKADDR_BRWR 0x17
+#define CMD_BANKADDR_BRRD 0x16
+#define CMD_EXTNADDR_WREAR 0xC5
+#define CMD_EXTNADDR_RDEAR 0xC8
+
+/* Macronix style 4-byte addressing */
+#define CMD_EN4B 0xb7
+#define CMD_EX4B 0xe9
/* Common status */
#define STATUS_WIP 0x01
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -21,6 +21,7 @@ static void spi_flash_addr(const struct
cmd[1] = addr >> (flash->addr_width * 8 - 8);
cmd[2] = addr >> (flash->addr_width * 8 - 16);
cmd[3] = addr >> (flash->addr_width * 8 - 24);
+ cmd[4] = addr >> (flash->addr_width * 8 - 32);
}
static int spi_flash_cmdsz(const struct spi_flash *flash)
@@ -163,7 +164,7 @@ int spi_flash_write_common(struct spi_fl
int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
{
u32 erase_size;
- u8 cmd[4], cmd_len;
+ u8 cmd[5], cmd_len;
int ret = -1;
erase_size = flash->erase_size;
@@ -188,8 +189,8 @@ int spi_flash_cmd_erase_ops(struct spi_f
spi_flash_addr(flash, offset, cmd);
cmd_len = spi_flash_cmdsz(flash);
- 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_write_common(flash, cmd, cmd_len, NULL, 0);
if (ret < 0) {
@@ -212,7 +213,7 @@ int spi_flash_cmd_write_ops(struct spi_f
{
unsigned long byte_addr, page_size;
size_t chunk_len, actual;
- u8 cmd[4], cmd_len;
+ u8 cmd[5], cmd_len;
int ret = -1;
ret = spi_claim_bus(flash->spi);
@@ -239,8 +240,8 @@ int spi_flash_cmd_write_ops(struct spi_f
spi_flash_addr(flash, offset, cmd);
cmd_len = spi_flash_cmdsz(flash);
- 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_write_common(flash, cmd, cmd_len,
buf + actual, chunk_len);
@@ -276,9 +277,13 @@ int spi_flash_read_common(struct spi_fla
int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
size_t len, void *data)
{
- u8 cmd[5], cmd_len, bank_sel = 0;
- u32 remain_len, read_len;
+ u8 cmd[6], cmd_len;
+ u32 read_len;
int ret = -1;
+#ifdef CONFIG_SPI_FLASH_BAR
+ u8 bank_sel = 0;
+ u32 remain_len;
+#endif
ret = spi_claim_bus(flash->spi);
if (ret) {
@@ -305,12 +310,15 @@ int spi_flash_cmd_read_ops(struct spi_fl
debug("SF: fail to set bank%d\n", bank_sel);
goto done;
}
-#endif
+
remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset;
if (len < remain_len)
read_len = len;
else
read_len = remain_len;
+#else
+ read_len = len;
+#endif
spi_flash_addr(flash, offset, cmd);
cmd_len = spi_flash_cmdsz(flash);
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -153,6 +153,25 @@ static const struct spi_flash_params spi
*/
};
+int spi_flash_4byte_set(struct spi_flash *flash, u8 idcode0, int enable)
+{
+ u8 cmd, bankaddr;
+
+ switch (idcode0) {
+ case 0xc2:
+ case 0xef:
+ case 0x1c:
+ /* Macronix style */
+ cmd = enable ? CMD_EN4B : CMD_EX4B;
+ return spi_flash_cmd(flash->spi, cmd, NULL, 0);
+ default:
+ /* Spansion style */
+ cmd = CMD_BANKADDR_BRWR;
+ bankaddr = enable << 7;
+ return spi_flash_cmd_write(flash->spi, &cmd, 1, &bankaddr, 1);
+ }
+}
+
static int spi_flash_validate_params(struct spi_flash *flash,
u8 *idcode)
{
@@ -218,8 +237,18 @@ static int spi_flash_validate_params(str
flash->poll_cmd = CMD_FLAG_STATUS;
#endif
+#ifndef CONFIG_SPI_FLASH_BAR
+ /* enable 4-byte addressing if the device exceeds 16MiB */
+ if (flash->size > SPI_FLASH_16MB_BOUN) {
+ flash->addr_width = 4;
+ spi_flash_4byte_set(flash, idcode[0], 1);
+ } else {
+ flash->addr_width = 3;
+ }
+#else
/* Configure default 3-byte addressing */
flash->addr_width = 3;
+#endif
/* Configure the BAR - discover bank cmds and read current bank */
#ifdef CONFIG_SPI_FLASH_BAR
|