1c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
2c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* Common Flash Interface structures
3c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * See http://support.intel.com/design/flash/technote/index.htm
4c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * $Id: cfi.h,v 1.57 2005/11/15 23:28:17 tpoynor Exp $
5c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
6c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
7c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifndef __MTD_CFI_H__
8c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define __MTD_CFI_H__
9c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
10c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/delay.h>
11c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/types.h>
12c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/interrupt.h>
13c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/mtd/flashchip.h>
14c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/mtd/map.h>
15c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/mtd/cfi_endian.h>
16c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
17c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I1
18c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave(cfi) 1
19c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_1(cfi) (cfi_interleave(cfi) == 1)
20c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#else
21c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_1(cfi) (0)
22c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
23c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
24c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I2
25c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# ifdef cfi_interleave
26c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  undef cfi_interleave
27c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  define cfi_interleave(cfi) ((cfi)->interleave)
28c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# else
29c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  define cfi_interleave(cfi) 2
30c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# endif
31c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_2(cfi) (cfi_interleave(cfi) == 2)
32c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#else
33c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_2(cfi) (0)
34c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
35c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
36c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I4
37c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# ifdef cfi_interleave
38c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  undef cfi_interleave
39c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  define cfi_interleave(cfi) ((cfi)->interleave)
40c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# else
41c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  define cfi_interleave(cfi) 4
42c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# endif
43c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_4(cfi) (cfi_interleave(cfi) == 4)
44c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#else
45c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_4(cfi) (0)
46c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
47c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
48c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I8
49c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# ifdef cfi_interleave
50c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  undef cfi_interleave
51c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  define cfi_interleave(cfi) ((cfi)->interleave)
52c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# else
53c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#  define cfi_interleave(cfi) 8
54c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru# endif
55c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_8(cfi) (cfi_interleave(cfi) == 8)
56c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#else
57c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define cfi_interleave_is_8(cfi) (0)
58c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
59c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
60c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline int cfi_interleave_supported(int i)
61c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
62c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	switch (i) {
63c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I1
64c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 1:
65c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
66c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I2
67c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 2:
68c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
69c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I4
70c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 4:
71c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
72c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_MTD_CFI_I8
73c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 8:
74c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
75c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return 1;
76c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
77c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	default:
78c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return 0;
79c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
80c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
81c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
82c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
83c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* NB: these values must represents the number of bytes needed to meet the
84c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *     device type (x8, x16, x32).  Eg. a 32 bit device is 4 x 8 bytes.
85c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *     These numbers are used in calculations.
86c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
87c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_DEVICETYPE_X8  (8 / 8)
88c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_DEVICETYPE_X16 (16 / 8)
89c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_DEVICETYPE_X32 (32 / 8)
90c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_DEVICETYPE_X64 (64 / 8)
91c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
92c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* NB: We keep these structures in memory in HOST byteorder, except
93c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * where individually noted.
94c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
95c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
96c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* Basic Query Structure */
97c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_ident {
98c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  qry[3];
99c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t P_ID;
100c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t P_ADR;
101c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t A_ID;
102c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t A_ADR;
103c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VccMin;
104c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VccMax;
105c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VppMin;
106c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VppMax;
107c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  WordWriteTimeoutTyp;
108c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BufWriteTimeoutTyp;
109c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BlockEraseTimeoutTyp;
110c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  ChipEraseTimeoutTyp;
111c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  WordWriteTimeoutMax;
112c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BufWriteTimeoutMax;
113c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BlockEraseTimeoutMax;
114c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  ChipEraseTimeoutMax;
115c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  DevSize;
116c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t InterfaceDesc;
117c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t MaxBufWriteSize;
118c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumEraseRegions;
119c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint32_t EraseRegionInfo[0]; /* Not host ordered */
120c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
121c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
122c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* Extended Query Structure for both PRI and ALT */
123c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
124c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_extquery {
125c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  pri[3];
126c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  MajorVersion;
127c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  MinorVersion;
128c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
129c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
130c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* Vendor-Specific PRI for Intel/Sharp Extended Command Set (0x0001) */
131c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
132c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_pri_intelext {
133c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  pri[3];
134c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  MajorVersion;
135c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  MinorVersion;
136c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint32_t FeatureSupport; /* if bit 31 is set then an additional uint32_t feature
137c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				    block follows - FIXME - not currently supported */
138c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  SuspendCmdSupport;
139c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t BlkStatusRegMask;
140c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VccOptimal;
141c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VppOptimal;
142c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumProtectionFields;
143c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t ProtRegAddr;
144c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  FactProtRegSize;
145c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  UserProtRegSize;
146c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  extra[0];
147c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
148c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
149c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_intelext_otpinfo {
150c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint32_t ProtRegAddr;
151c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t FactGroups;
152c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  FactProtRegSize;
153c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t UserGroups;
154c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  UserProtRegSize;
155c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
156c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
157c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_intelext_blockinfo {
158c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t NumIdentBlocks;
159c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t BlockSize;
160c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t MinBlockEraseCycles;
161c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BitsPerCell;
162c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BlockCap;
163c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
164c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
165c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_intelext_regioninfo {
166c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t NumIdentPartitions;
167c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumOpAllowed;
168c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumOpAllowedSimProgMode;
169c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumOpAllowedSimEraMode;
170c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumBlockTypes;
171c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct cfi_intelext_blockinfo BlockTypes[1];
172c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
173c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
174c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_intelext_programming_regioninfo {
175c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  ProgRegShift;
176c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  Reserved1;
177c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  ControlValid;
178c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  Reserved2;
179c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  ControlInvalid;
180c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  Reserved3;
181c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
182c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
183c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */
184c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
185c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_pri_amdstd {
186c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  pri[3];
187c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  MajorVersion;
188c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  MinorVersion;
189c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  SiliconRevision; /* bits 1-0: Address Sensitive Unlock */
190c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  EraseSuspend;
191c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BlkProt;
192c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  TmpBlkUnprotect;
193c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BlkProtUnprot;
194c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  SimultaneousOps;
195c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  BurstMode;
196c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  PageMode;
197c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VppMin;
198c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  VppMax;
199c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  TopBottom;
200c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
201c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
202c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* Vendor-Specific PRI for Atmel chips (command set 0x0002) */
203c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
204c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_pri_atmel {
205c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t pri[3];
206c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t MajorVersion;
207c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t MinorVersion;
208c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t Features;
209c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t BottomBoot;
210c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t BurstMode;
211c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t PageMode;
212c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
213c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
214c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_pri_query {
215c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumFields;
216c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint32_t ProtField[1]; /* Not host ordered */
217c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
218c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
219c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_bri_query {
220c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  PageModeReadCap;
221c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint8_t  NumFields;
222c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint32_t ConfField[1]; /* Not host ordered */
223c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} __attribute__((packed));
224c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
225c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_NONE               0x0000
226c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_INTEL_EXT          0x0001
227c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_AMD_STD            0x0002
228c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_INTEL_STD          0x0003
229c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_AMD_EXT            0x0004
230c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_WINBOND            0x0006
231c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_ST_ADV             0x0020
232c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_MITSUBISHI_STD     0x0100
233c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_MITSUBISHI_EXT     0x0101
234c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_SST_PAGE           0x0102
235c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_INTEL_PERFORMANCE  0x0200
236c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_INTEL_DATA         0x0210
237c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define P_ID_RESERVED           0xffff
238c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
239c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
240c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_MODE_CFI	1
241c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_MODE_JEDEC	0
242c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
243c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_private {
244c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t cmdset;
245c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void *cmdset_priv;
246c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int interleave;
247c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int device_type;
248c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int cfi_mode;		/* Are we a JEDEC device pretending to be CFI? */
249c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int addr_unlock1;
250c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int addr_unlock2;
251c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct mtd_info *(*cmdset_setup)(struct map_info *);
252c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct cfi_ident *cfiq; /* For now only one. We insist that all devs
253c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				  must be of the same type. */
254c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int mfr, id;
255c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int numchips;
256c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long chipshift; /* Because they're of the same type */
257c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	const char *im_name;	 /* inter_module name for cmdset_setup */
258c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct flchip chips[0];  /* per-chip data structure for each chip */
259c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
260c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
261c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
262c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Returns the command address according to the given geometry.
263c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
264c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type)
265c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
266c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return (cmd_ofs * type) * interleave;
267c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
268c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
269c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
270c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Transforms the CFI command for the given geometry (bus width & interleave).
271c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * It looks too long to be inline, but in the common case it should almost all
272c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * get optimised away.
273c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
274c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi)
275c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
276c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	map_word val = { {0} };
277c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int wordwidth, words_per_bus, chip_mode, chips_per_word;
278c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long onecmd;
279c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int i;
280c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
281c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* We do it this way to give the compiler a fighting chance
282c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   of optimising away all the crap for 'bankwidth' larger than
283c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   an unsigned long, in the common case where that support is
284c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   disabled */
285c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (map_bankwidth_is_large(map)) {
286c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		wordwidth = sizeof(unsigned long);
287c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
288c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else {
289c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		wordwidth = map_bankwidth(map);
290c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		words_per_bus = 1;
291c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
292c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
293c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
294c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
295c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
296c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* First, determine what the bit-pattern should be for a single
297c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   device, according to chip mode and endianness... */
298c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	switch (chip_mode) {
299c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	default: BUG();
300c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 1:
301c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		onecmd = cmd;
302c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		break;
303c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 2:
304c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		onecmd = cpu_to_cfi16(cmd);
305c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		break;
306c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 4:
307c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		onecmd = cpu_to_cfi32(cmd);
308c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		break;
309c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
310c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
311c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* Now replicate it across the size of an unsigned long, or
312c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   just to the bus width as appropriate */
313c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	switch (chips_per_word) {
314c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	default: BUG();
315c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#if BITS_PER_LONG >= 64
316c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 8:
317c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		onecmd |= (onecmd << (chip_mode * 32));
318c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
319c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 4:
320c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		onecmd |= (onecmd << (chip_mode * 16));
321c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 2:
322c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		onecmd |= (onecmd << (chip_mode * 8));
323c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 1:
324c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		;
325c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
326c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
327c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* And finally, for the multi-word case, replicate it
328c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   in all words in the structure */
329c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	for (i=0; i < words_per_bus; i++) {
330c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		val.x[i] = onecmd;
331c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
332c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
333c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return val;
334c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
335c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CMD(x)  cfi_build_cmd((x), map, cfi)
336c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
337c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
338c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline unsigned long cfi_merge_status(map_word val, struct map_info *map,
339c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					   struct cfi_private *cfi)
340c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
341c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int wordwidth, words_per_bus, chip_mode, chips_per_word;
342c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long onestat, res = 0;
343c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int i;
344c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
345c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* We do it this way to give the compiler a fighting chance
346c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   of optimising away all the crap for 'bankwidth' larger than
347c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   an unsigned long, in the common case where that support is
348c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   disabled */
349c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (map_bankwidth_is_large(map)) {
350c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		wordwidth = sizeof(unsigned long);
351c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
352c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else {
353c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		wordwidth = map_bankwidth(map);
354c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		words_per_bus = 1;
355c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
356c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
357c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
358c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
359c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
360c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	onestat = val.x[0];
361c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* Or all status words together */
362c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	for (i=1; i < words_per_bus; i++) {
363c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		onestat |= val.x[i];
364c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
365c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
366c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	res = onestat;
367c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	switch(chips_per_word) {
368c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	default: BUG();
369c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#if BITS_PER_LONG >= 64
370c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 8:
371c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		res |= (onestat >> (chip_mode * 32));
372c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif
373c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 4:
374c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		res |= (onestat >> (chip_mode * 16));
375c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 2:
376c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		res |= (onestat >> (chip_mode * 8));
377c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 1:
378c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		;
379c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
380c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
381c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* Last, determine what the bit-pattern should be for a single
382c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	   device, according to chip mode and endianness... */
383c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	switch (chip_mode) {
384c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 1:
385c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		break;
386c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 2:
387c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		res = cfi16_to_cpu(res);
388c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		break;
389c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	case 4:
390c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		res = cfi32_to_cpu(res);
391c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		break;
392c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	default: BUG();
393c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
394c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return res;
395c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
396c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
397c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define MERGESTATUS(x) cfi_merge_status((x), map, cfi)
398c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
399c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
400c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
401c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Sends a CFI command to a bank of flash for the given geometry.
402c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
403c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Returns the offset in flash where the command was written.
404c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * If prev_val is non-null, it will be set to the value at the command address,
405c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * before the command was written.
406c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
407c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
408c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				struct map_info *map, struct cfi_private *cfi,
409c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				int type, map_word *prev_val)
410c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
411c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	map_word val;
412c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
413c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
414c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	val = cfi_build_cmd(cmd, map, cfi);
415c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
416c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (prev_val)
417c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		*prev_val = map_read(map, addr);
418c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
419c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	map_write(map, val, addr);
420c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
421c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return addr - base;
422c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
423c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
424c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr)
425c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
426c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	map_word val = map_read(map, addr);
427c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
428c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (map_bankwidth_is_1(map)) {
429c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return val.x[0];
430c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else if (map_bankwidth_is_2(map)) {
431c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return cfi16_to_cpu(val.x[0]);
432c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else {
433c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		/* No point in a 64-bit byteswap since that would just be
434c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		   swapping the responses from different chips, and we are
435c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		   only interested in one chip (a representative sample) */
436c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return cfi32_to_cpu(val.x[0]);
437c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
438c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
439c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
440c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr)
441c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
442c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	map_word val = map_read(map, addr);
443c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
444c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (map_bankwidth_is_1(map)) {
445c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return val.x[0] & 0xff;
446c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else if (map_bankwidth_is_2(map)) {
447c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return cfi16_to_cpu(val.x[0]);
448c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else {
449c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		/* No point in a 64-bit byteswap since that would just be
450c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		   swapping the responses from different chips, and we are
451c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		   only interested in one chip (a representative sample) */
452c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		return cfi32_to_cpu(val.x[0]);
453c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
454c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
455c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
456c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void cfi_udelay(int us)
457c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
458c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (us >= 1000) {
459c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		msleep((us+999)/1000);
460c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else {
461c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		udelay(us);
462c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		cond_resched();
463c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
464c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
465c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
466c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size,
467c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			     const char* name);
468c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct cfi_fixup {
469c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t mfr;
470c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	uint16_t id;
471c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void (*fixup)(struct mtd_info *mtd, void* param);
472c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void* param;
473c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
474c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
475c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_MFR_ANY 0xffff
476c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_ID_ANY  0xffff
477c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
478c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_MFR_AMD 0x0001
479c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_MFR_ATMEL 0x001F
480c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define CFI_MFR_ST  0x0020 	/* STMicroelectronics */
481c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
482c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruvoid cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);
483c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
484c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querutypedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
485c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			      unsigned long adr, int len, void *thunk);
486c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
487c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruint cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
488c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	loff_t ofs, size_t len, void *thunk);
489c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
490c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
491c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif /* __MTD_CFI_H__ */
492