aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/chips/cfi_probe.c52
-rw-r--r--drivers/mtd/chips/cfi_util.c62
-rw-r--r--include/linux/mtd/cfi.h9
3 files changed, 73 insertions, 50 deletions
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index c418e92e1d92..e706be2ad0cb 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -44,17 +44,14 @@ do { \
44 44
45#define xip_enable(base, map, cfi) \ 45#define xip_enable(base, map, cfi) \
46do { \ 46do { \
47 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \ 47 qry_mode_off(base, map, cfi); \
48 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
49 xip_allowed(base, map); \ 48 xip_allowed(base, map); \
50} while (0) 49} while (0)
51 50
52#define xip_disable_qry(base, map, cfi) \ 51#define xip_disable_qry(base, map, cfi) \
53do { \ 52do { \
54 xip_disable(); \ 53 xip_disable(); \
55 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \ 54 qry_mode_on(base, map, cfi); \
56 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
57 cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); \
58} while (0) 55} while (0)
59 56
60#else 57#else
@@ -70,32 +67,6 @@ do { \
70 in: interleave,type,mode 67 in: interleave,type,mode
71 ret: table index, <0 for error 68 ret: table index, <0 for error
72 */ 69 */
73static int __xipram qry_present(struct map_info *map, __u32 base,
74 struct cfi_private *cfi)
75{
76 int osf = cfi->interleave * cfi->device_type; // scale factor
77 map_word val[3];
78 map_word qry[3];
79
80 qry[0] = cfi_build_cmd('Q', map, cfi);
81 qry[1] = cfi_build_cmd('R', map, cfi);
82 qry[2] = cfi_build_cmd('Y', map, cfi);
83
84 val[0] = map_read(map, base + osf*0x10);
85 val[1] = map_read(map, base + osf*0x11);
86 val[2] = map_read(map, base + osf*0x12);
87
88 if (!map_word_equal(map, qry[0], val[0]))
89 return 0;
90
91 if (!map_word_equal(map, qry[1], val[1]))
92 return 0;
93
94 if (!map_word_equal(map, qry[2], val[2]))
95 return 0;
96
97 return 1; // "QRY" found
98}
99 70
100static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, 71static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
101 unsigned long *chip_map, struct cfi_private *cfi) 72 unsigned long *chip_map, struct cfi_private *cfi)
@@ -116,11 +87,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
116 } 87 }
117 88
118 xip_disable(); 89 xip_disable();
119 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); 90 if (!qry_mode_on(base, map, cfi)) {
120 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
121 cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
122
123 if (!qry_present(map,base,cfi)) {
124 xip_enable(base, map, cfi); 91 xip_enable(base, map, cfi);
125 return 0; 92 return 0;
126 } 93 }
@@ -144,8 +111,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
144 if (qry_present(map, start, cfi)) { 111 if (qry_present(map, start, cfi)) {
145 /* Eep. This chip also had the QRY marker. 112 /* Eep. This chip also had the QRY marker.
146 * Is it an alias for the new one? */ 113 * Is it an alias for the new one? */
147 cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL); 114 qry_mode_off(start, map, cfi);
148 cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
149 115
150 /* If the QRY marker goes away, it's an alias */ 116 /* If the QRY marker goes away, it's an alias */
151 if (!qry_present(map, start, cfi)) { 117 if (!qry_present(map, start, cfi)) {
@@ -158,8 +124,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
158 * unfortunate. Stick the new chip in read mode 124 * unfortunate. Stick the new chip in read mode
159 * too and if it's the same, assume it's an alias. */ 125 * too and if it's the same, assume it's an alias. */
160 /* FIXME: Use other modes to do a proper check */ 126 /* FIXME: Use other modes to do a proper check */
161 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); 127 qry_mode_off(base, map, cfi);
162 cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
163 128
164 if (qry_present(map, base, cfi)) { 129 if (qry_present(map, base, cfi)) {
165 xip_allowed(base, map); 130 xip_allowed(base, map);
@@ -176,8 +141,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
176 cfi->numchips++; 141 cfi->numchips++;
177 142
178 /* Put it back into Read Mode */ 143 /* Put it back into Read Mode */
179 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); 144 qry_mode_off(base, map, cfi);
180 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
181 xip_allowed(base, map); 145 xip_allowed(base, map);
182 146
183 printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", 147 printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
@@ -237,9 +201,7 @@ static int __xipram cfi_chip_setup(struct map_info *map,
237 cfi_read_query(map, base + 0xf * ofs_factor); 201 cfi_read_query(map, base + 0xf * ofs_factor);
238 202
239 /* Put it back into Read Mode */ 203 /* Put it back into Read Mode */
240 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); 204 qry_mode_off(base, map, cfi);
241 /* ... even if it's an Intel chip */
242 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
243 xip_allowed(base, map); 205 xip_allowed(base, map);
244 206
245 /* Do any necessary byteswapping */ 207 /* Do any necessary byteswapping */
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index 0ee457018016..8d7553670526 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -24,6 +24,62 @@
24#include <linux/mtd/cfi.h> 24#include <linux/mtd/cfi.h>
25#include <linux/mtd/compatmac.h> 25#include <linux/mtd/compatmac.h>
26 26
27int __xipram qry_present(struct map_info *map, __u32 base,
28 struct cfi_private *cfi)
29{
30 int osf = cfi->interleave * cfi->device_type; /* scale factor */
31 map_word val[3];
32 map_word qry[3];
33
34 qry[0] = cfi_build_cmd('Q', map, cfi);
35 qry[1] = cfi_build_cmd('R', map, cfi);
36 qry[2] = cfi_build_cmd('Y', map, cfi);
37
38 val[0] = map_read(map, base + osf*0x10);
39 val[1] = map_read(map, base + osf*0x11);
40 val[2] = map_read(map, base + osf*0x12);
41
42 if (!map_word_equal(map, qry[0], val[0]))
43 return 0;
44
45 if (!map_word_equal(map, qry[1], val[1]))
46 return 0;
47
48 if (!map_word_equal(map, qry[2], val[2]))
49 return 0;
50
51 return 1; /* "QRY" found */
52}
53
54int __xipram qry_mode_on(uint32_t base, struct map_info *map,
55 struct cfi_private *cfi)
56{
57 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
58 cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
59 if (qry_present(map, base, cfi))
60 return 1;
61 /* QRY not found probably we deal with some odd CFI chips */
62 /* Some revisions of some old Intel chips? */
63 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
64 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
65 cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
66 if (qry_present(map, base, cfi))
67 return 1;
68 /* ST M29DW chips */
69 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
70 cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
71 if (qry_present(map, base, cfi))
72 return 1;
73 /* QRY not found */
74 return 0;
75}
76void __xipram qry_mode_off(uint32_t base, struct map_info *map,
77 struct cfi_private *cfi)
78{
79 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
80 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
81}
82
27struct cfi_extquery * 83struct cfi_extquery *
28__xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name) 84__xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
29{ 85{
@@ -48,8 +104,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
48#endif 104#endif
49 105
50 /* Switch it into Query Mode */ 106 /* Switch it into Query Mode */
51 cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); 107 qry_mode_on(base, map, cfi);
52
53 /* Read in the Extended Query Table */ 108 /* Read in the Extended Query Table */
54 for (i=0; i<size; i++) { 109 for (i=0; i<size; i++) {
55 ((unsigned char *)extp)[i] = 110 ((unsigned char *)extp)[i] =
@@ -57,8 +112,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
57 } 112 }
58 113
59 /* Make sure it returns to read mode */ 114 /* Make sure it returns to read mode */
60 cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL); 115 qry_mode_off(base, map, cfi);
61 cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL);
62 116
63#ifdef CONFIG_MTD_XIP 117#ifdef CONFIG_MTD_XIP
64 (void) map_read(map, base); 118 (void) map_read(map, base);
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index d6fb115f5a07..3058917d7b92 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -12,6 +12,7 @@
12#include <linux/mtd/flashchip.h> 12#include <linux/mtd/flashchip.h>
13#include <linux/mtd/map.h> 13#include <linux/mtd/map.h>
14#include <linux/mtd/cfi_endian.h> 14#include <linux/mtd/cfi_endian.h>
15#include <linux/mtd/xip.h>
15 16
16#ifdef CONFIG_MTD_CFI_I1 17#ifdef CONFIG_MTD_CFI_I1
17#define cfi_interleave(cfi) 1 18#define cfi_interleave(cfi) 1
@@ -430,7 +431,6 @@ static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t
430{ 431{
431 map_word val; 432 map_word val;
432 uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type); 433 uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
433
434 val = cfi_build_cmd(cmd, map, cfi); 434 val = cfi_build_cmd(cmd, map, cfi);
435 435
436 if (prev_val) 436 if (prev_val)
@@ -483,6 +483,13 @@ static inline void cfi_udelay(int us)
483 } 483 }
484} 484}
485 485
486int __xipram qry_present(struct map_info *map, __u32 base,
487 struct cfi_private *cfi);
488int __xipram qry_mode_on(uint32_t base, struct map_info *map,
489 struct cfi_private *cfi);
490void __xipram qry_mode_off(uint32_t base, struct map_info *map,
491 struct cfi_private *cfi);
492
486struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size, 493struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size,
487 const char* name); 494 const char* name);
488struct cfi_fixup { 495struct cfi_fixup {