]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/spi/stmicro.c
Merge 'u-boot-microblaze/zynq' into (u-boot-arm/master'
[karo-tx-uboot.git] / drivers / mtd / spi / stmicro.c
1 /*
2  * (C) Copyright 2000-2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * Copyright 2008, Network Appliance Inc.
6  * Jason McMullan <mcmullan@netapp.com>
7  *
8  * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
9  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
10  *
11  * SPDX-License-Identifier:     GPL-2.0+
12  */
13
14 #include <common.h>
15 #include <malloc.h>
16 #include <spi_flash.h>
17
18 #include "spi_flash_internal.h"
19
20 /* M25Pxx-specific commands */
21 #define CMD_M25PXX_RES  0xab    /* Release from DP, and Read Signature */
22
23 struct stmicro_spi_flash_params {
24         u16 id;
25         u16 pages_per_sector;
26         u16 nr_sectors;
27         const char *name;
28 };
29
30 static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
31         {
32                 .id = 0x2011,
33                 .pages_per_sector = 128,
34                 .nr_sectors = 4,
35                 .name = "M25P10",
36         },
37         {
38                 .id = 0x2015,
39                 .pages_per_sector = 256,
40                 .nr_sectors = 32,
41                 .name = "M25P16",
42         },
43         {
44                 .id = 0x2012,
45                 .pages_per_sector = 256,
46                 .nr_sectors = 4,
47                 .name = "M25P20",
48         },
49         {
50                 .id = 0x2016,
51                 .pages_per_sector = 256,
52                 .nr_sectors = 64,
53                 .name = "M25P32",
54         },
55         {
56                 .id = 0x2013,
57                 .pages_per_sector = 256,
58                 .nr_sectors = 8,
59                 .name = "M25P40",
60         },
61         {
62                 .id = 0x2017,
63                 .pages_per_sector = 256,
64                 .nr_sectors = 128,
65                 .name = "M25P64",
66         },
67         {
68                 .id = 0x2014,
69                 .pages_per_sector = 256,
70                 .nr_sectors = 16,
71                 .name = "M25P80",
72         },
73         {
74                 .id = 0x2018,
75                 .pages_per_sector = 1024,
76                 .nr_sectors = 64,
77                 .name = "M25P128",
78         },
79         {
80                 .id = 0xba16,
81                 .pages_per_sector = 256,
82                 .nr_sectors = 64,
83                 .name = "N25Q32",
84         },
85         {
86                 .id = 0xbb16,
87                 .pages_per_sector = 256,
88                 .nr_sectors = 64,
89                 .name = "N25Q32A",
90         },
91         {
92                 .id = 0xba17,
93                 .pages_per_sector = 256,
94                 .nr_sectors = 128,
95                 .name = "N25Q064",
96         },
97         {
98                 .id = 0xbb17,
99                 .pages_per_sector = 256,
100                 .nr_sectors = 128,
101                 .name = "N25Q64A",
102         },
103         {
104                 .id = 0xba18,
105                 .pages_per_sector = 256,
106                 .nr_sectors = 256,
107                 .name = "N25Q128",
108         },
109         {
110                 .id = 0xbb18,
111                 .pages_per_sector = 256,
112                 .nr_sectors = 256,
113                 .name = "N25Q128A",
114         },
115         {
116                 .id = 0xba19,
117                 .pages_per_sector = 256,
118                 .nr_sectors = 512,
119                 .name = "N25Q256",
120         },
121         {
122                 .id = 0xbb19,
123                 .pages_per_sector = 256,
124                 .nr_sectors = 512,
125                 .name = "N25Q256A",
126         },
127         {
128                 .id = 0xba20,
129                 .pages_per_sector = 256,
130                 .nr_sectors = 1024,
131                 .name = "N25Q512",
132         },
133         {
134                 .id = 0xbb20,
135                 .pages_per_sector = 256,
136                 .nr_sectors = 1024,
137                 .name = "N25Q512A",
138         },
139         {
140                 .id = 0xba21,
141                 .pages_per_sector = 256,
142                 .nr_sectors = 2048,
143                 .name = "N25Q1024",
144         },
145         {
146                 .id = 0xbb21,
147                 .pages_per_sector = 256,
148                 .nr_sectors = 2048,
149                 .name = "N25Q1024A",
150         },
151 };
152
153 struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode)
154 {
155         const struct stmicro_spi_flash_params *params;
156         struct spi_flash *flash;
157         unsigned int i;
158         u16 id;
159
160         if (idcode[0] == 0xff) {
161                 i = spi_flash_cmd(spi, CMD_M25PXX_RES,
162                                   idcode, 4);
163                 if (i)
164                         return NULL;
165                 if ((idcode[3] & 0xf0) == 0x10) {
166                         idcode[0] = 0x20;
167                         idcode[1] = 0x20;
168                         idcode[2] = idcode[3] + 1;
169                 } else {
170                         return NULL;
171                 }
172         }
173
174         id = ((idcode[1] << 8) | idcode[2]);
175
176         for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) {
177                 params = &stmicro_spi_flash_table[i];
178                 if (params->id == id)
179                         break;
180         }
181
182         if (i == ARRAY_SIZE(stmicro_spi_flash_table)) {
183                 debug("SF: Unsupported STMicro ID %04x\n", id);
184                 return NULL;
185         }
186
187         flash = spi_flash_alloc_base(spi, params->name);
188         if (!flash) {
189                 debug("SF: Failed to allocate memory\n");
190                 return NULL;
191         }
192
193         flash->page_size = 256;
194         flash->sector_size = 256 * params->pages_per_sector;
195         flash->size = flash->sector_size * params->nr_sectors;
196
197         /* for >= 512MiB flashes, use flag status instead of read_status */
198         if (flash->size >= 0x4000000)
199                 flash->poll_cmd = CMD_FLAG_STATUS;
200
201         return flash;
202 }