1*eef4f27bSRobert Mustacchi /*
2*eef4f27bSRobert Mustacchi * Copyright 2014-2017 Cavium, Inc.
3*eef4f27bSRobert Mustacchi * The contents of this file are subject to the terms of the Common Development
4*eef4f27bSRobert Mustacchi * and Distribution License, v.1, (the "License").
5*eef4f27bSRobert Mustacchi *
6*eef4f27bSRobert Mustacchi * You may not use this file except in compliance with the License.
7*eef4f27bSRobert Mustacchi *
8*eef4f27bSRobert Mustacchi * You can obtain a copy of the License at available
9*eef4f27bSRobert Mustacchi * at http://opensource.org/licenses/CDDL-1.0
10*eef4f27bSRobert Mustacchi *
11*eef4f27bSRobert Mustacchi * See the License for the specific language governing permissions and
12*eef4f27bSRobert Mustacchi * limitations under the License.
13*eef4f27bSRobert Mustacchi */
14*eef4f27bSRobert Mustacchi
15*eef4f27bSRobert Mustacchi #include "lm5706.h"
16*eef4f27bSRobert Mustacchi
17*eef4f27bSRobert Mustacchi
18*eef4f27bSRobert Mustacchi /*******************************************************************************
19*eef4f27bSRobert Mustacchi * Constants.
20*eef4f27bSRobert Mustacchi ******************************************************************************/
21*eef4f27bSRobert Mustacchi
22*eef4f27bSRobert Mustacchi /* Buffered flash (Atmel: AT45DB011B) specific information */
23*eef4f27bSRobert Mustacchi #define SEEPROM_SHIFT_BITS 2
24*eef4f27bSRobert Mustacchi #define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_SHIFT_BITS)
25*eef4f27bSRobert Mustacchi #define SEEPROM_BYTE_ADDR_MASK (SEEPROM_PHY_PAGE_SIZE-1)
26*eef4f27bSRobert Mustacchi #define SEEPROM_PAGE_SIZE 4
27*eef4f27bSRobert Mustacchi #define SEEPROM_TOTAL_SIZE 65536
28*eef4f27bSRobert Mustacchi
29*eef4f27bSRobert Mustacchi #define BUFFERED_FLASH_SHIFT_BITS 9
30*eef4f27bSRobert Mustacchi #define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_SHIFT_BITS)
31*eef4f27bSRobert Mustacchi #define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1)
32*eef4f27bSRobert Mustacchi #define BUFFERED_FLASH_PAGE_SIZE 264
33*eef4f27bSRobert Mustacchi #define BUFFERED_FLASH_TOTAL_SIZE 0x21000
34*eef4f27bSRobert Mustacchi
35*eef4f27bSRobert Mustacchi #define SAIFUN_FLASH_SHIFT_BITS 8
36*eef4f27bSRobert Mustacchi #define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_SHIFT_BITS)
37*eef4f27bSRobert Mustacchi #define SAIFUN_FLASH_BYTE_ADDR_MASK (SAIFUN_FLASH_PHY_PAGE_SIZE-1)
38*eef4f27bSRobert Mustacchi #define SAIFUN_FLASH_PAGE_SIZE 256
39*eef4f27bSRobert Mustacchi #define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536
40*eef4f27bSRobert Mustacchi
41*eef4f27bSRobert Mustacchi #define ST_MICRO_FLASH_SHIFT_BITS 8
42*eef4f27bSRobert Mustacchi #define ST_MICRO_FLASH_PHY_PAGE_SIZE (1 << ST_MICRO_FLASH_SHIFT_BITS)
43*eef4f27bSRobert Mustacchi #define ST_MICRO_FLASH_BYTE_ADDR_MASK (ST_MICRO_FLASH_PHY_PAGE_SIZE-1)
44*eef4f27bSRobert Mustacchi #define ST_MICRO_FLASH_PAGE_SIZE 256
45*eef4f27bSRobert Mustacchi #define ST_MICRO_FLASH_BASE_TOTAL_SIZE 65536
46*eef4f27bSRobert Mustacchi #define ST_MICRO_FLASH_1MBIT 0x20000
47*eef4f27bSRobert Mustacchi
48*eef4f27bSRobert Mustacchi /* NVRAM flags for nvram_write_dword and nvram_read_dword. */
49*eef4f27bSRobert Mustacchi #define NVRAM_FLAG_NONE 0x00
50*eef4f27bSRobert Mustacchi #define NVRAM_FLAG_SET_FIRST_CMD_BIT 0x01
51*eef4f27bSRobert Mustacchi #define NVRAM_FLAG_SET_LAST_CMD_BIT 0x02
52*eef4f27bSRobert Mustacchi #define NVRAM_FLAG_BUFFERED_FLASH 0x04
53*eef4f27bSRobert Mustacchi
54*eef4f27bSRobert Mustacchi #define NVRAM_TIMEOUT_COUNT 30000
55*eef4f27bSRobert Mustacchi
56*eef4f27bSRobert Mustacchi
57*eef4f27bSRobert Mustacchi #define FLASH_STRAP_MASK (NVM_CFG1_FLASH_MODE | \
58*eef4f27bSRobert Mustacchi NVM_CFG1_BUFFER_MODE | \
59*eef4f27bSRobert Mustacchi NVM_CFG1_PROTECT_MODE | \
60*eef4f27bSRobert Mustacchi NVM_CFG1_FLASH_SIZE)
61*eef4f27bSRobert Mustacchi #define FLASH_BACKUP_STRAP_MASK (0xf << 26)
62*eef4f27bSRobert Mustacchi
63*eef4f27bSRobert Mustacchi
64*eef4f27bSRobert Mustacchi typedef struct _new_nvm_cfg_t
65*eef4f27bSRobert Mustacchi {
66*eef4f27bSRobert Mustacchi /* Strapping to indicate the flash type (original | backup) */
67*eef4f27bSRobert Mustacchi u32_t strapping;
68*eef4f27bSRobert Mustacchi /* New configuration values */
69*eef4f27bSRobert Mustacchi u32_t config1;
70*eef4f27bSRobert Mustacchi u32_t config2;
71*eef4f27bSRobert Mustacchi u32_t config3;
72*eef4f27bSRobert Mustacchi u32_t write1;
73*eef4f27bSRobert Mustacchi u32_t buffered;
74*eef4f27bSRobert Mustacchi u32_t shift_bits;
75*eef4f27bSRobert Mustacchi u32_t page_size;
76*eef4f27bSRobert Mustacchi u32_t addr_mask;
77*eef4f27bSRobert Mustacchi u32_t total_size;
78*eef4f27bSRobert Mustacchi char *name;
79*eef4f27bSRobert Mustacchi } new_nvm_cfg_t;
80*eef4f27bSRobert Mustacchi
81*eef4f27bSRobert Mustacchi /* This table is indexed by the strap values */
82*eef4f27bSRobert Mustacchi static const new_nvm_cfg_t cfg_table[] =
83*eef4f27bSRobert Mustacchi {
84*eef4f27bSRobert Mustacchi /* Slow EEPROM */
85*eef4f27bSRobert Mustacchi {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
86*eef4f27bSRobert Mustacchi 1, SEEPROM_SHIFT_BITS, SEEPROM_PAGE_SIZE,
87*eef4f27bSRobert Mustacchi SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
88*eef4f27bSRobert Mustacchi "EEPROM - slow"},
89*eef4f27bSRobert Mustacchi /* Expansion entry 0001 */
90*eef4f27bSRobert Mustacchi {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
91*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
92*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
93*eef4f27bSRobert Mustacchi "Entry 0001"},
94*eef4f27bSRobert Mustacchi /* Saifun SA25F010 (non-buffered flash) */
95*eef4f27bSRobert Mustacchi {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, /* strap, cfg1, & write1 need updates */
96*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
97*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
98*eef4f27bSRobert Mustacchi "Non-buffered flash (128kB)"},
99*eef4f27bSRobert Mustacchi /* Saifun SA25F020 (non-buffered flash) */
100*eef4f27bSRobert Mustacchi {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, /* strap, cfg1, & write1 need updates */
101*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
102*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
103*eef4f27bSRobert Mustacchi "Non-buffered flash (256kB)"},
104*eef4f27bSRobert Mustacchi /* Expansion entry 0100 */
105*eef4f27bSRobert Mustacchi {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
106*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
107*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
108*eef4f27bSRobert Mustacchi "Entry 0100"},
109*eef4f27bSRobert Mustacchi /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
110*eef4f27bSRobert Mustacchi {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
111*eef4f27bSRobert Mustacchi 0, ST_MICRO_FLASH_SHIFT_BITS, ST_MICRO_FLASH_PAGE_SIZE,
112*eef4f27bSRobert Mustacchi ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
113*eef4f27bSRobert Mustacchi "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
114*eef4f27bSRobert Mustacchi /* Entry 0110: ST M45PE20 (non-buffered flash)*/
115*eef4f27bSRobert Mustacchi {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
116*eef4f27bSRobert Mustacchi 0, ST_MICRO_FLASH_SHIFT_BITS, ST_MICRO_FLASH_PAGE_SIZE,
117*eef4f27bSRobert Mustacchi ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
118*eef4f27bSRobert Mustacchi "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
119*eef4f27bSRobert Mustacchi /* Saifun SA25F005 (non-buffered flash) */
120*eef4f27bSRobert Mustacchi {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, /* strap, cfg1, & write1 need updates */
121*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
122*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
123*eef4f27bSRobert Mustacchi "Non-buffered flash (64kB)"},
124*eef4f27bSRobert Mustacchi /* Fast EEPROM */
125*eef4f27bSRobert Mustacchi {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
126*eef4f27bSRobert Mustacchi 1, SEEPROM_SHIFT_BITS, SEEPROM_PAGE_SIZE,
127*eef4f27bSRobert Mustacchi SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
128*eef4f27bSRobert Mustacchi "EEPROM - fast"},
129*eef4f27bSRobert Mustacchi /* Expansion entry 1001 */
130*eef4f27bSRobert Mustacchi {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
131*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
132*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
133*eef4f27bSRobert Mustacchi "Entry 1001"},
134*eef4f27bSRobert Mustacchi /* Expansion entry 1010 */
135*eef4f27bSRobert Mustacchi {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
136*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
137*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
138*eef4f27bSRobert Mustacchi "Entry 1010"},
139*eef4f27bSRobert Mustacchi /* ATMEL AT45DB011B (buffered flash) */
140*eef4f27bSRobert Mustacchi {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
141*eef4f27bSRobert Mustacchi 1, BUFFERED_FLASH_SHIFT_BITS, BUFFERED_FLASH_PAGE_SIZE,
142*eef4f27bSRobert Mustacchi BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
143*eef4f27bSRobert Mustacchi "Buffered flash (128kB)"},
144*eef4f27bSRobert Mustacchi /* Expansion entry 1100 */
145*eef4f27bSRobert Mustacchi {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
146*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
147*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
148*eef4f27bSRobert Mustacchi "Entry 1100"},
149*eef4f27bSRobert Mustacchi /* Expansion entry 1101 */
150*eef4f27bSRobert Mustacchi {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
151*eef4f27bSRobert Mustacchi 0, SAIFUN_FLASH_SHIFT_BITS, SAIFUN_FLASH_PAGE_SIZE,
152*eef4f27bSRobert Mustacchi SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
153*eef4f27bSRobert Mustacchi "Entry 1101"},
154*eef4f27bSRobert Mustacchi /* Ateml Expansion entry 1110 */
155*eef4f27bSRobert Mustacchi {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
156*eef4f27bSRobert Mustacchi 1, BUFFERED_FLASH_SHIFT_BITS, BUFFERED_FLASH_PAGE_SIZE,
157*eef4f27bSRobert Mustacchi BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
158*eef4f27bSRobert Mustacchi "Entry 1110 (Atmel)"},
159*eef4f27bSRobert Mustacchi /* ATMEL AT45DB021B (buffered flash) */
160*eef4f27bSRobert Mustacchi {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
161*eef4f27bSRobert Mustacchi 1, BUFFERED_FLASH_SHIFT_BITS, BUFFERED_FLASH_PAGE_SIZE,
162*eef4f27bSRobert Mustacchi BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
163*eef4f27bSRobert Mustacchi "Buffered flash (256kB)"},
164*eef4f27bSRobert Mustacchi };
165*eef4f27bSRobert Mustacchi
166*eef4f27bSRobert Mustacchi /*******************************************************************************
167*eef4f27bSRobert Mustacchi * Description:
168*eef4f27bSRobert Mustacchi *
169*eef4f27bSRobert Mustacchi * Return:
170*eef4f27bSRobert Mustacchi ******************************************************************************/
171*eef4f27bSRobert Mustacchi STATIC lm_status_t
acquire_nvram_lock(lm_device_t * pdev)172*eef4f27bSRobert Mustacchi acquire_nvram_lock(
173*eef4f27bSRobert Mustacchi lm_device_t *pdev)
174*eef4f27bSRobert Mustacchi {
175*eef4f27bSRobert Mustacchi lm_status_t lm_status;
176*eef4f27bSRobert Mustacchi u32_t j, cnt;
177*eef4f27bSRobert Mustacchi u32_t val;
178*eef4f27bSRobert Mustacchi
179*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
180*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
181*eef4f27bSRobert Mustacchi if (CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
182*eef4f27bSRobert Mustacchi else if (CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
183*eef4f27bSRobert Mustacchi
184*eef4f27bSRobert Mustacchi val = 0;
185*eef4f27bSRobert Mustacchi
186*eef4f27bSRobert Mustacchi /* Request access to the flash interface. */
187*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_sw_arb, NVM_SW_ARB_ARB_REQ_SET2);
188*eef4f27bSRobert Mustacchi
189*eef4f27bSRobert Mustacchi for(j = 0; j < cnt*10; j++)
190*eef4f27bSRobert Mustacchi {
191*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_sw_arb, &val);
192*eef4f27bSRobert Mustacchi if(val & NVM_SW_ARB_ARB_ARB2)
193*eef4f27bSRobert Mustacchi {
194*eef4f27bSRobert Mustacchi break;
195*eef4f27bSRobert Mustacchi }
196*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
197*eef4f27bSRobert Mustacchi }
198*eef4f27bSRobert Mustacchi
199*eef4f27bSRobert Mustacchi if(val & NVM_SW_ARB_ARB_ARB2)
200*eef4f27bSRobert Mustacchi {
201*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
202*eef4f27bSRobert Mustacchi }
203*eef4f27bSRobert Mustacchi else
204*eef4f27bSRobert Mustacchi {
205*eef4f27bSRobert Mustacchi DbgBreakMsg("Cannot get access to nvram interface.\n");
206*eef4f27bSRobert Mustacchi
207*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_BUSY;
208*eef4f27bSRobert Mustacchi }
209*eef4f27bSRobert Mustacchi return lm_status;
210*eef4f27bSRobert Mustacchi } /* acquire_nvram_lock */
211*eef4f27bSRobert Mustacchi
212*eef4f27bSRobert Mustacchi
213*eef4f27bSRobert Mustacchi
214*eef4f27bSRobert Mustacchi /*******************************************************************************
215*eef4f27bSRobert Mustacchi * Description:
216*eef4f27bSRobert Mustacchi *
217*eef4f27bSRobert Mustacchi * Return:
218*eef4f27bSRobert Mustacchi ******************************************************************************/
219*eef4f27bSRobert Mustacchi STATIC void
release_nvram_lock(lm_device_t * pdev)220*eef4f27bSRobert Mustacchi release_nvram_lock(
221*eef4f27bSRobert Mustacchi lm_device_t *pdev)
222*eef4f27bSRobert Mustacchi {
223*eef4f27bSRobert Mustacchi u32_t j, cnt;
224*eef4f27bSRobert Mustacchi u32_t val;
225*eef4f27bSRobert Mustacchi
226*eef4f27bSRobert Mustacchi /* Relinquish nvram interface. */
227*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_sw_arb, NVM_SW_ARB_ARB_REQ_CLR2);
228*eef4f27bSRobert Mustacchi
229*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
230*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
231*eef4f27bSRobert Mustacchi if (CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
232*eef4f27bSRobert Mustacchi else if (CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
233*eef4f27bSRobert Mustacchi
234*eef4f27bSRobert Mustacchi val = 0;
235*eef4f27bSRobert Mustacchi
236*eef4f27bSRobert Mustacchi for(j = 0; j < cnt; j++)
237*eef4f27bSRobert Mustacchi {
238*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_sw_arb, &val);
239*eef4f27bSRobert Mustacchi if(!(val & NVM_SW_ARB_ARB_ARB2))
240*eef4f27bSRobert Mustacchi {
241*eef4f27bSRobert Mustacchi break;
242*eef4f27bSRobert Mustacchi }
243*eef4f27bSRobert Mustacchi
244*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
245*eef4f27bSRobert Mustacchi }
246*eef4f27bSRobert Mustacchi
247*eef4f27bSRobert Mustacchi DbgBreakIf(val & NVM_SW_ARB_ARB_ARB2);
248*eef4f27bSRobert Mustacchi } /* release_nvram_lock */
249*eef4f27bSRobert Mustacchi
250*eef4f27bSRobert Mustacchi
251*eef4f27bSRobert Mustacchi
252*eef4f27bSRobert Mustacchi /*******************************************************************************
253*eef4f27bSRobert Mustacchi * Description:
254*eef4f27bSRobert Mustacchi *
255*eef4f27bSRobert Mustacchi * Return:
256*eef4f27bSRobert Mustacchi *
257*eef4f27bSRobert Mustacchi ******************************************************************************/
258*eef4f27bSRobert Mustacchi STATIC lm_status_t
enable_nvram_write(lm_device_t * pdev)259*eef4f27bSRobert Mustacchi enable_nvram_write(
260*eef4f27bSRobert Mustacchi lm_device_t *pdev)
261*eef4f27bSRobert Mustacchi {
262*eef4f27bSRobert Mustacchi u32_t val, j, cnt;
263*eef4f27bSRobert Mustacchi lm_status_t lm_status;
264*eef4f27bSRobert Mustacchi
265*eef4f27bSRobert Mustacchi REG_RD(pdev, misc.misc_cfg, &val);
266*eef4f27bSRobert Mustacchi REG_WR(pdev, misc.misc_cfg, val | MISC_CFG_NVM_WR_EN_PCI);
267*eef4f27bSRobert Mustacchi
268*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
269*eef4f27bSRobert Mustacchi
270*eef4f27bSRobert Mustacchi if (!pdev->hw_info.flash_spec.buffered)
271*eef4f27bSRobert Mustacchi {
272*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_DONE);
273*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_WREN |
274*eef4f27bSRobert Mustacchi NVM_COMMAND_DOIT);
275*eef4f27bSRobert Mustacchi
276*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
277*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
278*eef4f27bSRobert Mustacchi if (CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
279*eef4f27bSRobert Mustacchi else if (CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
280*eef4f27bSRobert Mustacchi
281*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_BUSY;
282*eef4f27bSRobert Mustacchi
283*eef4f27bSRobert Mustacchi for(j = 0; j < cnt; j++)
284*eef4f27bSRobert Mustacchi {
285*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
286*eef4f27bSRobert Mustacchi
287*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_command, &val);
288*eef4f27bSRobert Mustacchi if(val & NVM_COMMAND_DONE)
289*eef4f27bSRobert Mustacchi {
290*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
291*eef4f27bSRobert Mustacchi break;
292*eef4f27bSRobert Mustacchi }
293*eef4f27bSRobert Mustacchi }
294*eef4f27bSRobert Mustacchi }
295*eef4f27bSRobert Mustacchi
296*eef4f27bSRobert Mustacchi return lm_status;
297*eef4f27bSRobert Mustacchi } /* enable_nvram_write */
298*eef4f27bSRobert Mustacchi
299*eef4f27bSRobert Mustacchi
300*eef4f27bSRobert Mustacchi
301*eef4f27bSRobert Mustacchi /*******************************************************************************
302*eef4f27bSRobert Mustacchi * Description:
303*eef4f27bSRobert Mustacchi *
304*eef4f27bSRobert Mustacchi * Return:
305*eef4f27bSRobert Mustacchi *
306*eef4f27bSRobert Mustacchi ******************************************************************************/
307*eef4f27bSRobert Mustacchi STATIC lm_status_t
disable_nvram_write(lm_device_t * pdev)308*eef4f27bSRobert Mustacchi disable_nvram_write(
309*eef4f27bSRobert Mustacchi lm_device_t *pdev)
310*eef4f27bSRobert Mustacchi {
311*eef4f27bSRobert Mustacchi lm_status_t lm_status;
312*eef4f27bSRobert Mustacchi u32_t val;
313*eef4f27bSRobert Mustacchi
314*eef4f27bSRobert Mustacchi REG_RD(pdev, misc.misc_cfg, &val);
315*eef4f27bSRobert Mustacchi REG_WR(pdev, misc.misc_cfg, val & ~MISC_CFG_NVM_WR_EN);
316*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
317*eef4f27bSRobert Mustacchi
318*eef4f27bSRobert Mustacchi #if 0 /* On Saifun and ST parts, WP kicks in at the end of the write.
319*eef4f27bSRobert Mustacchi So, no need to have this. */
320*eef4f27bSRobert Mustacchi if (!pdev->hw_info.flash_spec.buffered)
321*eef4f27bSRobert Mustacchi {
322*eef4f27bSRobert Mustacchi /* Restoring protection causes the next read at a wrong location;
323*eef4f27bSRobert Mustacchi * leave this out for now. */
324*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_DONE);
325*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_WRDI |
326*eef4f27bSRobert Mustacchi NVM_COMMAND_DOIT);
327*eef4f27bSRobert Mustacchi
328*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
329*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
330*eef4f27bSRobert Mustacchi if (CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
331*eef4f27bSRobert Mustacchi else if (CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
332*eef4f27bSRobert Mustacchi
333*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_BUSY;
334*eef4f27bSRobert Mustacchi for(j = 0; j < cnt; j++)
335*eef4f27bSRobert Mustacchi {
336*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
337*eef4f27bSRobert Mustacchi
338*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_command, &val);
339*eef4f27bSRobert Mustacchi if(val & NVM_COMMAND_DONE)
340*eef4f27bSRobert Mustacchi {
341*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
342*eef4f27bSRobert Mustacchi break;
343*eef4f27bSRobert Mustacchi }
344*eef4f27bSRobert Mustacchi }
345*eef4f27bSRobert Mustacchi }
346*eef4f27bSRobert Mustacchi #endif
347*eef4f27bSRobert Mustacchi
348*eef4f27bSRobert Mustacchi return lm_status;
349*eef4f27bSRobert Mustacchi } /* disable_nvram_write */
350*eef4f27bSRobert Mustacchi
351*eef4f27bSRobert Mustacchi
352*eef4f27bSRobert Mustacchi
353*eef4f27bSRobert Mustacchi /*******************************************************************************
354*eef4f27bSRobert Mustacchi * Description:
355*eef4f27bSRobert Mustacchi *
356*eef4f27bSRobert Mustacchi * Return:
357*eef4f27bSRobert Mustacchi ******************************************************************************/
358*eef4f27bSRobert Mustacchi STATIC lm_status_t
enable_nvram_access(lm_device_t * pdev)359*eef4f27bSRobert Mustacchi enable_nvram_access(
360*eef4f27bSRobert Mustacchi lm_device_t *pdev)
361*eef4f27bSRobert Mustacchi {
362*eef4f27bSRobert Mustacchi u32_t val;
363*eef4f27bSRobert Mustacchi
364*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_access_enable, &val);
365*eef4f27bSRobert Mustacchi
366*eef4f27bSRobert Mustacchi /* Enable both bits, even on read. */
367*eef4f27bSRobert Mustacchi REG_WR(
368*eef4f27bSRobert Mustacchi pdev,
369*eef4f27bSRobert Mustacchi nvm.nvm_access_enable,
370*eef4f27bSRobert Mustacchi val | NVM_ACCESS_ENABLE_EN | NVM_ACCESS_ENABLE_WR_EN);
371*eef4f27bSRobert Mustacchi
372*eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
373*eef4f27bSRobert Mustacchi } /* enable_nvram_access */
374*eef4f27bSRobert Mustacchi
375*eef4f27bSRobert Mustacchi
376*eef4f27bSRobert Mustacchi
377*eef4f27bSRobert Mustacchi /*******************************************************************************
378*eef4f27bSRobert Mustacchi * Description:
379*eef4f27bSRobert Mustacchi *
380*eef4f27bSRobert Mustacchi * Return:
381*eef4f27bSRobert Mustacchi ******************************************************************************/
382*eef4f27bSRobert Mustacchi STATIC lm_status_t
disable_nvram_access(lm_device_t * pdev)383*eef4f27bSRobert Mustacchi disable_nvram_access(
384*eef4f27bSRobert Mustacchi lm_device_t *pdev)
385*eef4f27bSRobert Mustacchi {
386*eef4f27bSRobert Mustacchi u32_t val;
387*eef4f27bSRobert Mustacchi
388*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_access_enable, &val);
389*eef4f27bSRobert Mustacchi
390*eef4f27bSRobert Mustacchi /* Disable both bits, even after read. */
391*eef4f27bSRobert Mustacchi REG_WR(
392*eef4f27bSRobert Mustacchi pdev,
393*eef4f27bSRobert Mustacchi nvm.nvm_access_enable,
394*eef4f27bSRobert Mustacchi val & ~(NVM_ACCESS_ENABLE_EN | NVM_ACCESS_ENABLE_WR_EN));
395*eef4f27bSRobert Mustacchi
396*eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
397*eef4f27bSRobert Mustacchi } /* disable_nvram_access */
398*eef4f27bSRobert Mustacchi
399*eef4f27bSRobert Mustacchi
400*eef4f27bSRobert Mustacchi
401*eef4f27bSRobert Mustacchi /*******************************************************************************
402*eef4f27bSRobert Mustacchi * Description:
403*eef4f27bSRobert Mustacchi *
404*eef4f27bSRobert Mustacchi * Return:
405*eef4f27bSRobert Mustacchi ******************************************************************************/
406*eef4f27bSRobert Mustacchi STATIC lm_status_t
nvram_erase_page(lm_device_t * pdev,u32_t offset)407*eef4f27bSRobert Mustacchi nvram_erase_page(
408*eef4f27bSRobert Mustacchi lm_device_t *pdev,
409*eef4f27bSRobert Mustacchi u32_t offset)
410*eef4f27bSRobert Mustacchi {
411*eef4f27bSRobert Mustacchi lm_status_t lm_status;
412*eef4f27bSRobert Mustacchi u32_t cmd_flags;
413*eef4f27bSRobert Mustacchi u32_t val;
414*eef4f27bSRobert Mustacchi u32_t j, cnt;
415*eef4f27bSRobert Mustacchi
416*eef4f27bSRobert Mustacchi if (pdev->hw_info.flash_spec.buffered)
417*eef4f27bSRobert Mustacchi {
418*eef4f27bSRobert Mustacchi /* Buffered flash, no erase needed */
419*eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
420*eef4f27bSRobert Mustacchi }
421*eef4f27bSRobert Mustacchi
422*eef4f27bSRobert Mustacchi /* Build an erase command */
423*eef4f27bSRobert Mustacchi cmd_flags = NVM_COMMAND_ERASE | NVM_COMMAND_WR | NVM_COMMAND_DOIT;
424*eef4f27bSRobert Mustacchi
425*eef4f27bSRobert Mustacchi /* Need to clear DONE bit separately. */
426*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_DONE);
427*eef4f27bSRobert Mustacchi
428*eef4f27bSRobert Mustacchi /* Address of the NVRAM to read from. */
429*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_addr, offset & NVM_ADDR_NVM_ADDR_VALUE);
430*eef4f27bSRobert Mustacchi
431*eef4f27bSRobert Mustacchi /* Issue an erase command. */
432*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, cmd_flags);
433*eef4f27bSRobert Mustacchi
434*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
435*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
436*eef4f27bSRobert Mustacchi if (CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
437*eef4f27bSRobert Mustacchi else if (CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
438*eef4f27bSRobert Mustacchi
439*eef4f27bSRobert Mustacchi /* Wait for completion. */
440*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_BUSY;
441*eef4f27bSRobert Mustacchi for(j = 0; j < cnt; j++)
442*eef4f27bSRobert Mustacchi {
443*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
444*eef4f27bSRobert Mustacchi
445*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_command, &val);
446*eef4f27bSRobert Mustacchi if(val & NVM_COMMAND_DONE)
447*eef4f27bSRobert Mustacchi {
448*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
449*eef4f27bSRobert Mustacchi break;
450*eef4f27bSRobert Mustacchi }
451*eef4f27bSRobert Mustacchi }
452*eef4f27bSRobert Mustacchi
453*eef4f27bSRobert Mustacchi return lm_status;
454*eef4f27bSRobert Mustacchi
455*eef4f27bSRobert Mustacchi } /* nvram_erase_page */
456*eef4f27bSRobert Mustacchi
457*eef4f27bSRobert Mustacchi
458*eef4f27bSRobert Mustacchi
459*eef4f27bSRobert Mustacchi /*******************************************************************************
460*eef4f27bSRobert Mustacchi * Description:
461*eef4f27bSRobert Mustacchi *
462*eef4f27bSRobert Mustacchi * Return:
463*eef4f27bSRobert Mustacchi ******************************************************************************/
464*eef4f27bSRobert Mustacchi STATIC lm_status_t
nvram_read_dword(lm_device_t * pdev,u32_t offset,u32_t * ret_val,u32_t nvram_flags)465*eef4f27bSRobert Mustacchi nvram_read_dword(
466*eef4f27bSRobert Mustacchi lm_device_t *pdev,
467*eef4f27bSRobert Mustacchi u32_t offset,
468*eef4f27bSRobert Mustacchi u32_t *ret_val,
469*eef4f27bSRobert Mustacchi u32_t nvram_flags)
470*eef4f27bSRobert Mustacchi {
471*eef4f27bSRobert Mustacchi lm_status_t lm_status;
472*eef4f27bSRobert Mustacchi u32_t cmd_flags;
473*eef4f27bSRobert Mustacchi u32_t val;
474*eef4f27bSRobert Mustacchi u32_t j, cnt;
475*eef4f27bSRobert Mustacchi
476*eef4f27bSRobert Mustacchi /* Build the command word. */
477*eef4f27bSRobert Mustacchi cmd_flags = NVM_COMMAND_DOIT;
478*eef4f27bSRobert Mustacchi if(nvram_flags & NVRAM_FLAG_SET_FIRST_CMD_BIT)
479*eef4f27bSRobert Mustacchi {
480*eef4f27bSRobert Mustacchi cmd_flags |= NVM_COMMAND_FIRST;
481*eef4f27bSRobert Mustacchi }
482*eef4f27bSRobert Mustacchi
483*eef4f27bSRobert Mustacchi if(nvram_flags & NVRAM_FLAG_SET_LAST_CMD_BIT)
484*eef4f27bSRobert Mustacchi {
485*eef4f27bSRobert Mustacchi cmd_flags |= NVM_COMMAND_LAST;
486*eef4f27bSRobert Mustacchi }
487*eef4f27bSRobert Mustacchi
488*eef4f27bSRobert Mustacchi if ((CHIP_NUM(pdev) == CHIP_NUM_5706) || (CHIP_NUM(pdev) == CHIP_NUM_5708))
489*eef4f27bSRobert Mustacchi {
490*eef4f27bSRobert Mustacchi /* Calculate an offset of a buffered flash. */
491*eef4f27bSRobert Mustacchi if(nvram_flags & NVRAM_FLAG_BUFFERED_FLASH)
492*eef4f27bSRobert Mustacchi {
493*eef4f27bSRobert Mustacchi offset = ((offset / pdev->hw_info.flash_spec.page_size) <<
494*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.shift_bits) +
495*eef4f27bSRobert Mustacchi (offset % pdev->hw_info.flash_spec.page_size);
496*eef4f27bSRobert Mustacchi }
497*eef4f27bSRobert Mustacchi
498*eef4f27bSRobert Mustacchi /* Need to clear DONE bit separately. */
499*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_DONE);
500*eef4f27bSRobert Mustacchi }
501*eef4f27bSRobert Mustacchi
502*eef4f27bSRobert Mustacchi /* Address of the NVRAM to read from. */
503*eef4f27bSRobert Mustacchi if (cmd_flags & NVM_COMMAND_FIRST) {
504*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_addr, offset & NVM_ADDR_NVM_ADDR_VALUE);
505*eef4f27bSRobert Mustacchi }
506*eef4f27bSRobert Mustacchi
507*eef4f27bSRobert Mustacchi /* Issue a read command. */
508*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, cmd_flags);
509*eef4f27bSRobert Mustacchi
510*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
511*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
512*eef4f27bSRobert Mustacchi if (CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
513*eef4f27bSRobert Mustacchi else if (CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
514*eef4f27bSRobert Mustacchi
515*eef4f27bSRobert Mustacchi /* Wait for completion. */
516*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_BUSY;
517*eef4f27bSRobert Mustacchi for(j = 0; j < cnt; j++)
518*eef4f27bSRobert Mustacchi {
519*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
520*eef4f27bSRobert Mustacchi
521*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_command, &val);
522*eef4f27bSRobert Mustacchi if(val & NVM_COMMAND_DONE)
523*eef4f27bSRobert Mustacchi {
524*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_read, &val);
525*eef4f27bSRobert Mustacchi
526*eef4f27bSRobert Mustacchi /* Change to little endian. */
527*eef4f27bSRobert Mustacchi #if defined(LITTLE_ENDIAN)
528*eef4f27bSRobert Mustacchi val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
529*eef4f27bSRobert Mustacchi ((val & 0xff0000) >> 8) | ((val >> 24) & 0xff);
530*eef4f27bSRobert Mustacchi #endif
531*eef4f27bSRobert Mustacchi
532*eef4f27bSRobert Mustacchi *ret_val = val;
533*eef4f27bSRobert Mustacchi
534*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
535*eef4f27bSRobert Mustacchi
536*eef4f27bSRobert Mustacchi break;
537*eef4f27bSRobert Mustacchi }
538*eef4f27bSRobert Mustacchi }
539*eef4f27bSRobert Mustacchi
540*eef4f27bSRobert Mustacchi return lm_status;
541*eef4f27bSRobert Mustacchi } /* nvram_read_dword */
542*eef4f27bSRobert Mustacchi
543*eef4f27bSRobert Mustacchi
544*eef4f27bSRobert Mustacchi
545*eef4f27bSRobert Mustacchi /*******************************************************************************
546*eef4f27bSRobert Mustacchi * Description:
547*eef4f27bSRobert Mustacchi *
548*eef4f27bSRobert Mustacchi * Return:
549*eef4f27bSRobert Mustacchi ******************************************************************************/
550*eef4f27bSRobert Mustacchi STATIC lm_status_t
nvram_write_dword(lm_device_t * pdev,u32_t offset,u32_t val,u32_t nvram_flags)551*eef4f27bSRobert Mustacchi nvram_write_dword(
552*eef4f27bSRobert Mustacchi lm_device_t *pdev,
553*eef4f27bSRobert Mustacchi u32_t offset,
554*eef4f27bSRobert Mustacchi u32_t val,
555*eef4f27bSRobert Mustacchi u32_t nvram_flags)
556*eef4f27bSRobert Mustacchi {
557*eef4f27bSRobert Mustacchi lm_status_t lm_status;
558*eef4f27bSRobert Mustacchi u32_t cmd_flags;
559*eef4f27bSRobert Mustacchi u32_t j, cnt;
560*eef4f27bSRobert Mustacchi
561*eef4f27bSRobert Mustacchi /* Build the command word. */
562*eef4f27bSRobert Mustacchi cmd_flags = NVM_COMMAND_DOIT | NVM_COMMAND_WR;
563*eef4f27bSRobert Mustacchi if(nvram_flags & NVRAM_FLAG_SET_FIRST_CMD_BIT)
564*eef4f27bSRobert Mustacchi {
565*eef4f27bSRobert Mustacchi cmd_flags |= NVM_COMMAND_FIRST;
566*eef4f27bSRobert Mustacchi }
567*eef4f27bSRobert Mustacchi
568*eef4f27bSRobert Mustacchi if(nvram_flags & NVRAM_FLAG_SET_LAST_CMD_BIT)
569*eef4f27bSRobert Mustacchi {
570*eef4f27bSRobert Mustacchi cmd_flags |= NVM_COMMAND_LAST;
571*eef4f27bSRobert Mustacchi }
572*eef4f27bSRobert Mustacchi if ((CHIP_NUM(pdev) == CHIP_NUM_5706) || (CHIP_NUM(pdev) == CHIP_NUM_5708))
573*eef4f27bSRobert Mustacchi {
574*eef4f27bSRobert Mustacchi /* Calculate an offset of a buffered flash. */
575*eef4f27bSRobert Mustacchi if(nvram_flags & NVRAM_FLAG_BUFFERED_FLASH)
576*eef4f27bSRobert Mustacchi {
577*eef4f27bSRobert Mustacchi offset = ((offset / pdev->hw_info.flash_spec.page_size) <<
578*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.shift_bits) +
579*eef4f27bSRobert Mustacchi (offset % pdev->hw_info.flash_spec.page_size);
580*eef4f27bSRobert Mustacchi }
581*eef4f27bSRobert Mustacchi
582*eef4f27bSRobert Mustacchi /* Need to clear DONE bit separately. */
583*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_DONE);
584*eef4f27bSRobert Mustacchi }
585*eef4f27bSRobert Mustacchi
586*eef4f27bSRobert Mustacchi /* Change to little endian. */
587*eef4f27bSRobert Mustacchi #if defined(LITTLE_ENDIAN)
588*eef4f27bSRobert Mustacchi val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
589*eef4f27bSRobert Mustacchi ((val & 0xff0000) >> 8) | ((val >> 24) & 0xff);
590*eef4f27bSRobert Mustacchi #endif
591*eef4f27bSRobert Mustacchi
592*eef4f27bSRobert Mustacchi /* Write the data. */
593*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, val);
594*eef4f27bSRobert Mustacchi
595*eef4f27bSRobert Mustacchi /* Address of the NVRAM to write to. */
596*eef4f27bSRobert Mustacchi if (cmd_flags & NVM_COMMAND_FIRST) {
597*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_addr, offset & NVM_ADDR_NVM_ADDR_VALUE);
598*eef4f27bSRobert Mustacchi }
599*eef4f27bSRobert Mustacchi
600*eef4f27bSRobert Mustacchi /* Issue the write command. */
601*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, cmd_flags);
602*eef4f27bSRobert Mustacchi
603*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
604*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
605*eef4f27bSRobert Mustacchi if (CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
606*eef4f27bSRobert Mustacchi else if (CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
607*eef4f27bSRobert Mustacchi
608*eef4f27bSRobert Mustacchi /* Wait for completion. */
609*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_BUSY;
610*eef4f27bSRobert Mustacchi for(j = 0; j < cnt; j++)
611*eef4f27bSRobert Mustacchi {
612*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
613*eef4f27bSRobert Mustacchi
614*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_command, &val);
615*eef4f27bSRobert Mustacchi if(val & NVM_COMMAND_DONE)
616*eef4f27bSRobert Mustacchi {
617*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
618*eef4f27bSRobert Mustacchi break;
619*eef4f27bSRobert Mustacchi }
620*eef4f27bSRobert Mustacchi }
621*eef4f27bSRobert Mustacchi
622*eef4f27bSRobert Mustacchi return lm_status;
623*eef4f27bSRobert Mustacchi } /* nvram_write_dword */
624*eef4f27bSRobert Mustacchi
625*eef4f27bSRobert Mustacchi
626*eef4f27bSRobert Mustacchi
627*eef4f27bSRobert Mustacchi /*******************************************************************************
628*eef4f27bSRobert Mustacchi * Description:
629*eef4f27bSRobert Mustacchi *
630*eef4f27bSRobert Mustacchi * Return:
631*eef4f27bSRobert Mustacchi ******************************************************************************/
632*eef4f27bSRobert Mustacchi STATIC u32_t
find_atmel_size(lm_device_t * pdev)633*eef4f27bSRobert Mustacchi find_atmel_size(
634*eef4f27bSRobert Mustacchi lm_device_t *pdev)
635*eef4f27bSRobert Mustacchi {
636*eef4f27bSRobert Mustacchi u32_t orig, val, done=0, size=BUFFERED_FLASH_TOTAL_SIZE;
637*eef4f27bSRobert Mustacchi
638*eef4f27bSRobert Mustacchi if (CHIP_NUM(pdev) == CHIP_NUM_5709)
639*eef4f27bSRobert Mustacchi {
640*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg4, &val);
641*eef4f27bSRobert Mustacchi val &= 0x07;
642*eef4f27bSRobert Mustacchi return (1 << val) ;
643*eef4f27bSRobert Mustacchi }
644*eef4f27bSRobert Mustacchi
645*eef4f27bSRobert Mustacchi /* It is assumed that the flash is enabled and locked for exclusive access */
646*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg3, &orig);
647*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_cfg3, 0x57848353);
648*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_read, 0);
649*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_DONE);
650*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_DOIT |
651*eef4f27bSRobert Mustacchi NVM_COMMAND_FIRST |
652*eef4f27bSRobert Mustacchi NVM_COMMAND_LAST);
653*eef4f27bSRobert Mustacchi while (!done)
654*eef4f27bSRobert Mustacchi {
655*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_command, &val);
656*eef4f27bSRobert Mustacchi if (val & NVM_COMMAND_DONE)
657*eef4f27bSRobert Mustacchi {
658*eef4f27bSRobert Mustacchi done = 1;
659*eef4f27bSRobert Mustacchi }
660*eef4f27bSRobert Mustacchi }
661*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_read, &val);
662*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_cfg3, orig);
663*eef4f27bSRobert Mustacchi val &= 0x3c;
664*eef4f27bSRobert Mustacchi switch (val)
665*eef4f27bSRobert Mustacchi {
666*eef4f27bSRobert Mustacchi case 0x24:
667*eef4f27bSRobert Mustacchi size *= 8;
668*eef4f27bSRobert Mustacchi break;
669*eef4f27bSRobert Mustacchi case 0x1c:
670*eef4f27bSRobert Mustacchi size *= 4;
671*eef4f27bSRobert Mustacchi break;
672*eef4f27bSRobert Mustacchi case 0x14:
673*eef4f27bSRobert Mustacchi size *= 2;
674*eef4f27bSRobert Mustacchi break;
675*eef4f27bSRobert Mustacchi case 0x0c:
676*eef4f27bSRobert Mustacchi size *= 1;
677*eef4f27bSRobert Mustacchi break;
678*eef4f27bSRobert Mustacchi default:
679*eef4f27bSRobert Mustacchi size *= 0;
680*eef4f27bSRobert Mustacchi break;
681*eef4f27bSRobert Mustacchi }
682*eef4f27bSRobert Mustacchi return size;
683*eef4f27bSRobert Mustacchi }
684*eef4f27bSRobert Mustacchi
685*eef4f27bSRobert Mustacchi
686*eef4f27bSRobert Mustacchi /*******************************************************************************
687*eef4f27bSRobert Mustacchi * Description:
688*eef4f27bSRobert Mustacchi *
689*eef4f27bSRobert Mustacchi * Return:
690*eef4f27bSRobert Mustacchi ******************************************************************************/
691*eef4f27bSRobert Mustacchi STATIC u32_t
find_stm_size(lm_device_t * pdev)692*eef4f27bSRobert Mustacchi find_stm_size(
693*eef4f27bSRobert Mustacchi lm_device_t *pdev)
694*eef4f27bSRobert Mustacchi {
695*eef4f27bSRobert Mustacchi u32_t idx, val, result, bit;
696*eef4f27bSRobert Mustacchi
697*eef4f27bSRobert Mustacchi if (CHIP_NUM(pdev) == CHIP_NUM_5709)
698*eef4f27bSRobert Mustacchi {
699*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg4, &val);
700*eef4f27bSRobert Mustacchi val &= 0x07;
701*eef4f27bSRobert Mustacchi return (1 << val) ;
702*eef4f27bSRobert Mustacchi }
703*eef4f27bSRobert Mustacchi
704*eef4f27bSRobert Mustacchi /* It is assumed that the flash is enabled and locked for exclusive access */
705*eef4f27bSRobert Mustacchi /* Set CS, SO, SCLK as output, SI as input */
706*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_addr, NVM_ADDR_NVM_ADDR_VALUE_EECLK_TE |
707*eef4f27bSRobert Mustacchi NVM_ADDR_NVM_ADDR_VALUE_EEDATA_TE |
708*eef4f27bSRobert Mustacchi NVM_ADDR_NVM_ADDR_VALUE_SI_TE
709*eef4f27bSRobert Mustacchi );
710*eef4f27bSRobert Mustacchi /* Set initial data CS=1, SO=0, SCLK=0, SI=n/a */
711*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, NVM_WRITE_NVM_WRITE_VALUE_EECLK_TE |
712*eef4f27bSRobert Mustacchi NVM_WRITE_NVM_WRITE_VALUE_EEDATA_TE |
713*eef4f27bSRobert Mustacchi NVM_WRITE_NVM_WRITE_VALUE_CS_B_TE
714*eef4f27bSRobert Mustacchi );
715*eef4f27bSRobert Mustacchi /* Enable bit-bang mode */
716*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg1, &val);
717*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_cfg1, val | NVM_CFG1_BITBANG_MODE);
718*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
719*eef4f27bSRobert Mustacchi
720*eef4f27bSRobert Mustacchi /* Bit-bang the command */
721*eef4f27bSRobert Mustacchi
722*eef4f27bSRobert Mustacchi val = 0xf9;
723*eef4f27bSRobert Mustacchi
724*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, 0);
725*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
726*eef4f27bSRobert Mustacchi for (idx=0; idx < 8; idx++)
727*eef4f27bSRobert Mustacchi {
728*eef4f27bSRobert Mustacchi bit = ((val >> idx) & 0x1) << 4;
729*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, bit);
730*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
731*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, NVM_WRITE_NVM_WRITE_VALUE_SCLK_TE | bit);
732*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
733*eef4f27bSRobert Mustacchi }
734*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, 0);
735*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
736*eef4f27bSRobert Mustacchi
737*eef4f27bSRobert Mustacchi /* Bit-bang to read ID, 1st byte: manuf ID;
738*eef4f27bSRobert Mustacchi * 2nd byte: memory type; 3rd byte: memory capacity */
739*eef4f27bSRobert Mustacchi result = 0;
740*eef4f27bSRobert Mustacchi for (idx = 0; idx < 24; idx++)
741*eef4f27bSRobert Mustacchi {
742*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_read, &val);
743*eef4f27bSRobert Mustacchi bit = (val & NVM_WRITE_NVM_WRITE_VALUE_SI_TE) >> 5;
744*eef4f27bSRobert Mustacchi result = (result << 1) | bit;
745*eef4f27bSRobert Mustacchi
746*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, NVM_WRITE_NVM_WRITE_VALUE_SCLK_TE);
747*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
748*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, 0);
749*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
750*eef4f27bSRobert Mustacchi }
751*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write, NVM_WRITE_NVM_WRITE_VALUE_CS_B_TE);
752*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
753*eef4f27bSRobert Mustacchi
754*eef4f27bSRobert Mustacchi val = ST_MICRO_FLASH_1MBIT;
755*eef4f27bSRobert Mustacchi switch (result)
756*eef4f27bSRobert Mustacchi {
757*eef4f27bSRobert Mustacchi case 0x00204014:
758*eef4f27bSRobert Mustacchi val *= 8;
759*eef4f27bSRobert Mustacchi break;
760*eef4f27bSRobert Mustacchi case 0x00204013:
761*eef4f27bSRobert Mustacchi val *= 4;
762*eef4f27bSRobert Mustacchi break;
763*eef4f27bSRobert Mustacchi case 0x00204012:
764*eef4f27bSRobert Mustacchi val *= 2;
765*eef4f27bSRobert Mustacchi break;
766*eef4f27bSRobert Mustacchi case 0x00204011:
767*eef4f27bSRobert Mustacchi val *= 1;
768*eef4f27bSRobert Mustacchi break;
769*eef4f27bSRobert Mustacchi default:
770*eef4f27bSRobert Mustacchi val *= 0;
771*eef4f27bSRobert Mustacchi break;
772*eef4f27bSRobert Mustacchi }
773*eef4f27bSRobert Mustacchi
774*eef4f27bSRobert Mustacchi /* Get out of bit-bang mode */
775*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg1, &idx);
776*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_cfg1, idx & ~NVM_CFG1_BITBANG_MODE);
777*eef4f27bSRobert Mustacchi mm_wait(pdev, 1);
778*eef4f27bSRobert Mustacchi
779*eef4f27bSRobert Mustacchi return val;
780*eef4f27bSRobert Mustacchi }
781*eef4f27bSRobert Mustacchi
782*eef4f27bSRobert Mustacchi
783*eef4f27bSRobert Mustacchi /*******************************************************************************
784*eef4f27bSRobert Mustacchi * Description:
785*eef4f27bSRobert Mustacchi *
786*eef4f27bSRobert Mustacchi * Return:
787*eef4f27bSRobert Mustacchi ******************************************************************************/
788*eef4f27bSRobert Mustacchi STATIC u32_t
find_nvram_size(lm_device_t * pdev,u32_t table_idx)789*eef4f27bSRobert Mustacchi find_nvram_size(
790*eef4f27bSRobert Mustacchi lm_device_t *pdev,
791*eef4f27bSRobert Mustacchi u32_t table_idx)
792*eef4f27bSRobert Mustacchi {
793*eef4f27bSRobert Mustacchi lm_status_t lm_status;
794*eef4f27bSRobert Mustacchi u32_t size, val;
795*eef4f27bSRobert Mustacchi
796*eef4f27bSRobert Mustacchi if (CHIP_NUM(pdev) == CHIP_NUM_5709)
797*eef4f27bSRobert Mustacchi {
798*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg4, &val);
799*eef4f27bSRobert Mustacchi val &= 0x07;
800*eef4f27bSRobert Mustacchi return ((1 << val) * 1024 * 1024 / 8);
801*eef4f27bSRobert Mustacchi }
802*eef4f27bSRobert Mustacchi
803*eef4f27bSRobert Mustacchi /* Request access to the flash interface. */
804*eef4f27bSRobert Mustacchi lm_status = acquire_nvram_lock(pdev);
805*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return 0;
806*eef4f27bSRobert Mustacchi
807*eef4f27bSRobert Mustacchi /* Enable access to flash interface */
808*eef4f27bSRobert Mustacchi lm_status = enable_nvram_access(pdev);
809*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return 0;
810*eef4f27bSRobert Mustacchi
811*eef4f27bSRobert Mustacchi switch (table_idx)
812*eef4f27bSRobert Mustacchi {
813*eef4f27bSRobert Mustacchi case 11:
814*eef4f27bSRobert Mustacchi case 14:
815*eef4f27bSRobert Mustacchi case 15:
816*eef4f27bSRobert Mustacchi /* ATMEL */
817*eef4f27bSRobert Mustacchi size = find_atmel_size(pdev);
818*eef4f27bSRobert Mustacchi break;
819*eef4f27bSRobert Mustacchi case 5:
820*eef4f27bSRobert Mustacchi case 6:
821*eef4f27bSRobert Mustacchi size = find_stm_size(pdev);
822*eef4f27bSRobert Mustacchi break;
823*eef4f27bSRobert Mustacchi case 2:
824*eef4f27bSRobert Mustacchi case 3:
825*eef4f27bSRobert Mustacchi case 7:
826*eef4f27bSRobert Mustacchi /* This one is static */
827*eef4f27bSRobert Mustacchi size = cfg_table[table_idx].total_size;
828*eef4f27bSRobert Mustacchi break;
829*eef4f27bSRobert Mustacchi default:
830*eef4f27bSRobert Mustacchi size = 0;
831*eef4f27bSRobert Mustacchi break;
832*eef4f27bSRobert Mustacchi }
833*eef4f27bSRobert Mustacchi /* Disable access to flash interface */
834*eef4f27bSRobert Mustacchi (void) disable_nvram_access(pdev);
835*eef4f27bSRobert Mustacchi release_nvram_lock(pdev);
836*eef4f27bSRobert Mustacchi return size;
837*eef4f27bSRobert Mustacchi }
838*eef4f27bSRobert Mustacchi
839*eef4f27bSRobert Mustacchi
840*eef4f27bSRobert Mustacchi /*******************************************************************************
841*eef4f27bSRobert Mustacchi * Description:
842*eef4f27bSRobert Mustacchi *
843*eef4f27bSRobert Mustacchi * Return:
844*eef4f27bSRobert Mustacchi ******************************************************************************/
845*eef4f27bSRobert Mustacchi void
lm_nvram_init(lm_device_t * pdev,u8_t reset_flash_block)846*eef4f27bSRobert Mustacchi lm_nvram_init(
847*eef4f27bSRobert Mustacchi lm_device_t *pdev,
848*eef4f27bSRobert Mustacchi u8_t reset_flash_block)
849*eef4f27bSRobert Mustacchi {
850*eef4f27bSRobert Mustacchi u32_t idx, val;
851*eef4f27bSRobert Mustacchi lm_status_t lm_status;
852*eef4f27bSRobert Mustacchi
853*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "### lm_nvram_init\n");
854*eef4f27bSRobert Mustacchi
855*eef4f27bSRobert Mustacchi if (CHIP_NUM(pdev) == CHIP_NUM_5709)
856*eef4f27bSRobert Mustacchi {
857*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg4, &val);
858*eef4f27bSRobert Mustacchi
859*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.buffered = 0;
860*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.shift_bits = 0;
861*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.page_size = SAIFUN_FLASH_PAGE_SIZE;
862*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.addr_mask = 0;
863*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.total_size = (1 << (val & 0x07)) * 1024 * 1024 / 8;
864*eef4f27bSRobert Mustacchi return;
865*eef4f27bSRobert Mustacchi }
866*eef4f27bSRobert Mustacchi
867*eef4f27bSRobert Mustacchi idx = lm_nvram_query(pdev, reset_flash_block, FALSE);
868*eef4f27bSRobert Mustacchi
869*eef4f27bSRobert Mustacchi if (idx == (u32_t)-1)
870*eef4f27bSRobert Mustacchi {
871*eef4f27bSRobert Mustacchi /* Not necessarily an error, it could mean that the flash block has
872*eef4f27bSRobert Mustacchi * been reconfigured.
873*eef4f27bSRobert Mustacchi */
874*eef4f27bSRobert Mustacchi return;
875*eef4f27bSRobert Mustacchi }
876*eef4f27bSRobert Mustacchi
877*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, cfg_table[idx].name);
878*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " reconfiguring.\n");
879*eef4f27bSRobert Mustacchi
880*eef4f27bSRobert Mustacchi /* Request access to the flash interface. */
881*eef4f27bSRobert Mustacchi lm_status = acquire_nvram_lock(pdev);
882*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return;
883*eef4f27bSRobert Mustacchi
884*eef4f27bSRobert Mustacchi /* Enable access to flash interface */
885*eef4f27bSRobert Mustacchi lm_status = enable_nvram_access(pdev);
886*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return;
887*eef4f27bSRobert Mustacchi
888*eef4f27bSRobert Mustacchi /* Reconfigure the flash interface */
889*eef4f27bSRobert Mustacchi /* Program the SPI and SEE clocks faster if FPGA or IKOS */
890*eef4f27bSRobert Mustacchi val = cfg_table[idx].config1;
891*eef4f27bSRobert Mustacchi
892*eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_FPGA)
893*eef4f27bSRobert Mustacchi {
894*eef4f27bSRobert Mustacchi val &= ~(NVM_CFG1_SPI_CLK_DIV | NVM_CFG1_SEE_CLK_DIV);
895*eef4f27bSRobert Mustacchi val |= (0x0<<7) | (0x6<<11);
896*eef4f27bSRobert Mustacchi }
897*eef4f27bSRobert Mustacchi else if(CHIP_REV(pdev) == CHIP_REV_IKOS)
898*eef4f27bSRobert Mustacchi {
899*eef4f27bSRobert Mustacchi val &= ~(NVM_CFG1_SPI_CLK_DIV | NVM_CFG1_SEE_CLK_DIV);
900*eef4f27bSRobert Mustacchi val |= (0x0<<7) | (0x0<<11);
901*eef4f27bSRobert Mustacchi }
902*eef4f27bSRobert Mustacchi else
903*eef4f27bSRobert Mustacchi {
904*eef4f27bSRobert Mustacchi /* No change, leave it */
905*eef4f27bSRobert Mustacchi }
906*eef4f27bSRobert Mustacchi
907*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_cfg1, val);
908*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_cfg2, cfg_table[idx].config2);
909*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_cfg3, cfg_table[idx].config3);
910*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_write1, cfg_table[idx].write1);
911*eef4f27bSRobert Mustacchi
912*eef4f27bSRobert Mustacchi /* Disable access to flash interface */
913*eef4f27bSRobert Mustacchi (void) disable_nvram_access(pdev);
914*eef4f27bSRobert Mustacchi release_nvram_lock(pdev);
915*eef4f27bSRobert Mustacchi
916*eef4f27bSRobert Mustacchi } /* lm_nvram_init */
917*eef4f27bSRobert Mustacchi
918*eef4f27bSRobert Mustacchi
919*eef4f27bSRobert Mustacchi /*******************************************************************************
920*eef4f27bSRobert Mustacchi * Description:
921*eef4f27bSRobert Mustacchi *
922*eef4f27bSRobert Mustacchi * Return:
923*eef4f27bSRobert Mustacchi ******************************************************************************/
924*eef4f27bSRobert Mustacchi u32_t
lm_nvram_query(lm_device_t * pdev,u8_t reset_flash_block,u8_t no_hw_mod)925*eef4f27bSRobert Mustacchi lm_nvram_query(
926*eef4f27bSRobert Mustacchi lm_device_t *pdev,
927*eef4f27bSRobert Mustacchi u8_t reset_flash_block,
928*eef4f27bSRobert Mustacchi u8_t no_hw_mod)
929*eef4f27bSRobert Mustacchi {
930*eef4f27bSRobert Mustacchi u32_t val;
931*eef4f27bSRobert Mustacchi u32_t j;
932*eef4f27bSRobert Mustacchi u32_t cnt, idx, ret_val = (u32_t)-1;
933*eef4f27bSRobert Mustacchi u8_t reconfigured = FALSE;
934*eef4f27bSRobert Mustacchi u32_t entry_count, mask;
935*eef4f27bSRobert Mustacchi
936*eef4f27bSRobert Mustacchi
937*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "### lm_nvram_query\n");
938*eef4f27bSRobert Mustacchi
939*eef4f27bSRobert Mustacchi if (CHIP_NUM(pdev) == CHIP_NUM_5709)
940*eef4f27bSRobert Mustacchi {
941*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg4, &val);
942*eef4f27bSRobert Mustacchi
943*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.buffered = 0;
944*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.shift_bits = 0;
945*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.page_size = SAIFUN_FLASH_PAGE_SIZE;
946*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.addr_mask = 0;
947*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.total_size = (1 << (val & 0x07)) * 1024 * 1024 / 8;
948*eef4f27bSRobert Mustacchi return (u32_t)-1;
949*eef4f27bSRobert Mustacchi }
950*eef4f27bSRobert Mustacchi
951*eef4f27bSRobert Mustacchi /* Adjust timeout for emulation/FPGA */
952*eef4f27bSRobert Mustacchi cnt = NVRAM_TIMEOUT_COUNT;
953*eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_FPGA) cnt *= 10;
954*eef4f27bSRobert Mustacchi else if(CHIP_REV(pdev) == CHIP_REV_IKOS) cnt *= 100;
955*eef4f27bSRobert Mustacchi
956*eef4f27bSRobert Mustacchi /* Reset the NVRAM interface block. */
957*eef4f27bSRobert Mustacchi if(reset_flash_block)
958*eef4f27bSRobert Mustacchi {
959*eef4f27bSRobert Mustacchi val = 0;
960*eef4f27bSRobert Mustacchi
961*eef4f27bSRobert Mustacchi /* Get access to write flash block register */
962*eef4f27bSRobert Mustacchi (void) enable_nvram_access(pdev);
963*eef4f27bSRobert Mustacchi
964*eef4f27bSRobert Mustacchi REG_WR(pdev, nvm.nvm_command, NVM_COMMAND_RST);
965*eef4f27bSRobert Mustacchi for(j = 0; j < cnt; j++)
966*eef4f27bSRobert Mustacchi {
967*eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
968*eef4f27bSRobert Mustacchi
969*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_command, &val);
970*eef4f27bSRobert Mustacchi if(!(val & NVM_COMMAND_RST))
971*eef4f27bSRobert Mustacchi {
972*eef4f27bSRobert Mustacchi break;
973*eef4f27bSRobert Mustacchi }
974*eef4f27bSRobert Mustacchi }
975*eef4f27bSRobert Mustacchi
976*eef4f27bSRobert Mustacchi DbgBreakIf(val & NVM_COMMAND_RST);
977*eef4f27bSRobert Mustacchi }
978*eef4f27bSRobert Mustacchi
979*eef4f27bSRobert Mustacchi /* Determine the selected interface. */
980*eef4f27bSRobert Mustacchi REG_RD(pdev, nvm.nvm_cfg1, &val);
981*eef4f27bSRobert Mustacchi
982*eef4f27bSRobert Mustacchi entry_count = sizeof(cfg_table)/sizeof(new_nvm_cfg_t);
983*eef4f27bSRobert Mustacchi
984*eef4f27bSRobert Mustacchi if (val & (1<<30))
985*eef4f27bSRobert Mustacchi {
986*eef4f27bSRobert Mustacchi /* Flash interface has been reconfigured */
987*eef4f27bSRobert Mustacchi mask = FLASH_BACKUP_STRAP_MASK;
988*eef4f27bSRobert Mustacchi for (idx=0; idx<entry_count; idx++)
989*eef4f27bSRobert Mustacchi {
990*eef4f27bSRobert Mustacchi if ((val & mask) == (cfg_table[idx].strapping & mask))
991*eef4f27bSRobert Mustacchi {
992*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "Reconfigured ");
993*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, cfg_table[idx].name);
994*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " detected.\n");
995*eef4f27bSRobert Mustacchi
996*eef4f27bSRobert Mustacchi reconfigured = TRUE;
997*eef4f27bSRobert Mustacchi ret_val = idx;
998*eef4f27bSRobert Mustacchi break;
999*eef4f27bSRobert Mustacchi }
1000*eef4f27bSRobert Mustacchi }
1001*eef4f27bSRobert Mustacchi }
1002*eef4f27bSRobert Mustacchi else
1003*eef4f27bSRobert Mustacchi {
1004*eef4f27bSRobert Mustacchi /* Not yet been reconfigured */
1005*eef4f27bSRobert Mustacchi
1006*eef4f27bSRobert Mustacchi /* A new bit to indicate where to look for strapping (backup vs. original) */
1007*eef4f27bSRobert Mustacchi mask = (val & (1<<23)) ? FLASH_BACKUP_STRAP_MASK : FLASH_STRAP_MASK;
1008*eef4f27bSRobert Mustacchi
1009*eef4f27bSRobert Mustacchi for (idx=0; idx<entry_count; idx++)
1010*eef4f27bSRobert Mustacchi {
1011*eef4f27bSRobert Mustacchi
1012*eef4f27bSRobert Mustacchi if ((val & mask) == (cfg_table[idx].strapping & mask))
1013*eef4f27bSRobert Mustacchi {
1014*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, cfg_table[idx].name);
1015*eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " detected.\n");
1016*eef4f27bSRobert Mustacchi
1017*eef4f27bSRobert Mustacchi ret_val = idx;
1018*eef4f27bSRobert Mustacchi break;
1019*eef4f27bSRobert Mustacchi }
1020*eef4f27bSRobert Mustacchi }
1021*eef4f27bSRobert Mustacchi } /* if (val & (1<<30)) */
1022*eef4f27bSRobert Mustacchi
1023*eef4f27bSRobert Mustacchi /* Check for exceptions: entries that are supported by TetonII B0,
1024*eef4f27bSRobert Mustacchi * but not earlier chips
1025*eef4f27bSRobert Mustacchi */
1026*eef4f27bSRobert Mustacchi if ((ret_val == 5) && (CHIP_ID(pdev) < CHIP_ID_5708_B0))
1027*eef4f27bSRobert Mustacchi {
1028*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.total_size = 0;
1029*eef4f27bSRobert Mustacchi
1030*eef4f27bSRobert Mustacchi DbgBreakMsg("Unsupported type.\n");
1031*eef4f27bSRobert Mustacchi }
1032*eef4f27bSRobert Mustacchi else if (ret_val != (u32_t)-1)
1033*eef4f27bSRobert Mustacchi {
1034*eef4f27bSRobert Mustacchi /* Track what's been configured */
1035*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.buffered = cfg_table[ret_val].buffered;
1036*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.shift_bits = cfg_table[ret_val].shift_bits;
1037*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.page_size = cfg_table[ret_val].page_size;
1038*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.addr_mask = cfg_table[ret_val].addr_mask;
1039*eef4f27bSRobert Mustacchi /* Determine the size before reconfiguring, dynamically */
1040*eef4f27bSRobert Mustacchi if (no_hw_mod)
1041*eef4f27bSRobert Mustacchi {
1042*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.total_size = cfg_table[ret_val].total_size;
1043*eef4f27bSRobert Mustacchi }
1044*eef4f27bSRobert Mustacchi else
1045*eef4f27bSRobert Mustacchi {
1046*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.total_size = find_nvram_size(pdev, idx);
1047*eef4f27bSRobert Mustacchi }
1048*eef4f27bSRobert Mustacchi }
1049*eef4f27bSRobert Mustacchi else
1050*eef4f27bSRobert Mustacchi {
1051*eef4f27bSRobert Mustacchi pdev->hw_info.flash_spec.total_size = 0;
1052*eef4f27bSRobert Mustacchi
1053*eef4f27bSRobert Mustacchi DbgBreakMsg("Unknown flash/EEPROM type.\n");
1054*eef4f27bSRobert Mustacchi }
1055*eef4f27bSRobert Mustacchi
1056*eef4f27bSRobert Mustacchi return (reconfigured) ? (u32_t)-1 : ret_val;
1057*eef4f27bSRobert Mustacchi
1058*eef4f27bSRobert Mustacchi } /* lm_nvram_query */
1059*eef4f27bSRobert Mustacchi
1060*eef4f27bSRobert Mustacchi
1061*eef4f27bSRobert Mustacchi
1062*eef4f27bSRobert Mustacchi /*******************************************************************************
1063*eef4f27bSRobert Mustacchi * Description:
1064*eef4f27bSRobert Mustacchi *
1065*eef4f27bSRobert Mustacchi * Return:
1066*eef4f27bSRobert Mustacchi ******************************************************************************/
1067*eef4f27bSRobert Mustacchi lm_status_t
lm_nvram_read(lm_device_t * pdev,u32_t offset,u32_t * ret_buf,u32_t buf_size)1068*eef4f27bSRobert Mustacchi lm_nvram_read(
1069*eef4f27bSRobert Mustacchi lm_device_t *pdev,
1070*eef4f27bSRobert Mustacchi u32_t offset,
1071*eef4f27bSRobert Mustacchi u32_t *ret_buf,
1072*eef4f27bSRobert Mustacchi u32_t buf_size)
1073*eef4f27bSRobert Mustacchi {
1074*eef4f27bSRobert Mustacchi lm_status_t lm_status;
1075*eef4f27bSRobert Mustacchi u32_t cmd_flags;
1076*eef4f27bSRobert Mustacchi
1077*eef4f27bSRobert Mustacchi DbgMessage(pdev, VERBOSE, "### lm_nvram_read\n");
1078*eef4f27bSRobert Mustacchi
1079*eef4f27bSRobert Mustacchi if((buf_size & 0x03) || (offset & 0x03))
1080*eef4f27bSRobert Mustacchi {
1081*eef4f27bSRobert Mustacchi DbgBreakMsg("Invalid paramter.\n");
1082*eef4f27bSRobert Mustacchi
1083*eef4f27bSRobert Mustacchi return LM_STATUS_FAILURE;
1084*eef4f27bSRobert Mustacchi }
1085*eef4f27bSRobert Mustacchi if(offset + buf_size > pdev->hw_info.flash_spec.total_size)
1086*eef4f27bSRobert Mustacchi {
1087*eef4f27bSRobert Mustacchi DbgBreakMsg("Invalid paramter.\n");
1088*eef4f27bSRobert Mustacchi
1089*eef4f27bSRobert Mustacchi return LM_STATUS_FAILURE;
1090*eef4f27bSRobert Mustacchi }
1091*eef4f27bSRobert Mustacchi
1092*eef4f27bSRobert Mustacchi if (pdev->hw_info.flash_spec.buffered)
1093*eef4f27bSRobert Mustacchi {
1094*eef4f27bSRobert Mustacchi cmd_flags = NVRAM_FLAG_BUFFERED_FLASH;
1095*eef4f27bSRobert Mustacchi }
1096*eef4f27bSRobert Mustacchi else
1097*eef4f27bSRobert Mustacchi {
1098*eef4f27bSRobert Mustacchi cmd_flags = NVRAM_FLAG_NONE;
1099*eef4f27bSRobert Mustacchi }
1100*eef4f27bSRobert Mustacchi
1101*eef4f27bSRobert Mustacchi /* Request access to the flash interface. */
1102*eef4f27bSRobert Mustacchi lm_status = acquire_nvram_lock(pdev);
1103*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS)
1104*eef4f27bSRobert Mustacchi {
1105*eef4f27bSRobert Mustacchi return lm_status;
1106*eef4f27bSRobert Mustacchi }
1107*eef4f27bSRobert Mustacchi
1108*eef4f27bSRobert Mustacchi /* Enable access to flash interface */
1109*eef4f27bSRobert Mustacchi lm_status = enable_nvram_access(pdev);
1110*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS)
1111*eef4f27bSRobert Mustacchi {
1112*eef4f27bSRobert Mustacchi return lm_status;
1113*eef4f27bSRobert Mustacchi }
1114*eef4f27bSRobert Mustacchi
1115*eef4f27bSRobert Mustacchi if(buf_size <= sizeof(u32_t))
1116*eef4f27bSRobert Mustacchi {
1117*eef4f27bSRobert Mustacchi /* Address of the NVRAM to read from. */
1118*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_FIRST_CMD_BIT |
1119*eef4f27bSRobert Mustacchi NVRAM_FLAG_SET_LAST_CMD_BIT;
1120*eef4f27bSRobert Mustacchi lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags);
1121*eef4f27bSRobert Mustacchi }
1122*eef4f27bSRobert Mustacchi else
1123*eef4f27bSRobert Mustacchi {
1124*eef4f27bSRobert Mustacchi /* Read the first word. */
1125*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_FIRST_CMD_BIT;
1126*eef4f27bSRobert Mustacchi lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags);
1127*eef4f27bSRobert Mustacchi cmd_flags &= ~NVRAM_FLAG_SET_FIRST_CMD_BIT;
1128*eef4f27bSRobert Mustacchi if(lm_status == LM_STATUS_SUCCESS)
1129*eef4f27bSRobert Mustacchi {
1130*eef4f27bSRobert Mustacchi /* Advance to the next dword. */
1131*eef4f27bSRobert Mustacchi offset += sizeof(u32_t);
1132*eef4f27bSRobert Mustacchi ret_buf++;
1133*eef4f27bSRobert Mustacchi buf_size -= sizeof(u32_t);
1134*eef4f27bSRobert Mustacchi
1135*eef4f27bSRobert Mustacchi while(buf_size > sizeof(u32_t) && lm_status == LM_STATUS_SUCCESS)
1136*eef4f27bSRobert Mustacchi {
1137*eef4f27bSRobert Mustacchi lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags);
1138*eef4f27bSRobert Mustacchi
1139*eef4f27bSRobert Mustacchi /* Advance to the next dword. */
1140*eef4f27bSRobert Mustacchi offset += sizeof(u32_t);
1141*eef4f27bSRobert Mustacchi ret_buf++;
1142*eef4f27bSRobert Mustacchi buf_size -= sizeof(u32_t);
1143*eef4f27bSRobert Mustacchi }
1144*eef4f27bSRobert Mustacchi
1145*eef4f27bSRobert Mustacchi if(lm_status == LM_STATUS_SUCCESS)
1146*eef4f27bSRobert Mustacchi {
1147*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_LAST_CMD_BIT;
1148*eef4f27bSRobert Mustacchi lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags);
1149*eef4f27bSRobert Mustacchi }
1150*eef4f27bSRobert Mustacchi }
1151*eef4f27bSRobert Mustacchi }
1152*eef4f27bSRobert Mustacchi
1153*eef4f27bSRobert Mustacchi /* Disable access to flash interface */
1154*eef4f27bSRobert Mustacchi (void) disable_nvram_access(pdev);
1155*eef4f27bSRobert Mustacchi
1156*eef4f27bSRobert Mustacchi release_nvram_lock(pdev);
1157*eef4f27bSRobert Mustacchi
1158*eef4f27bSRobert Mustacchi return lm_status;
1159*eef4f27bSRobert Mustacchi } /* lm_nvram_read */
1160*eef4f27bSRobert Mustacchi
1161*eef4f27bSRobert Mustacchi /*******************************************************************************
1162*eef4f27bSRobert Mustacchi * Description:
1163*eef4f27bSRobert Mustacchi *
1164*eef4f27bSRobert Mustacchi * Return:
1165*eef4f27bSRobert Mustacchi ******************************************************************************/
1166*eef4f27bSRobert Mustacchi lm_status_t
lm_nvram_write(lm_device_t * pdev,u32_t offset,u32_t * data_buf,u32_t buf_size)1167*eef4f27bSRobert Mustacchi lm_nvram_write(
1168*eef4f27bSRobert Mustacchi lm_device_t *pdev,
1169*eef4f27bSRobert Mustacchi u32_t offset,
1170*eef4f27bSRobert Mustacchi u32_t *data_buf,
1171*eef4f27bSRobert Mustacchi u32_t buf_size)
1172*eef4f27bSRobert Mustacchi {
1173*eef4f27bSRobert Mustacchi lm_status_t lm_status;
1174*eef4f27bSRobert Mustacchi u32_t cmd_flags;
1175*eef4f27bSRobert Mustacchi u32_t written_so_far, page_start, page_end, data_start, data_end;
1176*eef4f27bSRobert Mustacchi u32_t idx, *ptr32, addr, base_flags;
1177*eef4f27bSRobert Mustacchi static u32_t flash_buffer[66];
1178*eef4f27bSRobert Mustacchi
1179*eef4f27bSRobert Mustacchi DbgMessage(pdev, VERBOSE, "### lm_nvram_write\n");
1180*eef4f27bSRobert Mustacchi
1181*eef4f27bSRobert Mustacchi if(offset & 0x03)
1182*eef4f27bSRobert Mustacchi {
1183*eef4f27bSRobert Mustacchi DbgBreakMsg("Invalid paramter.\n");
1184*eef4f27bSRobert Mustacchi
1185*eef4f27bSRobert Mustacchi return LM_STATUS_FAILURE;
1186*eef4f27bSRobert Mustacchi }
1187*eef4f27bSRobert Mustacchi
1188*eef4f27bSRobert Mustacchi if(offset + buf_size > pdev->hw_info.flash_spec.total_size)
1189*eef4f27bSRobert Mustacchi {
1190*eef4f27bSRobert Mustacchi DbgBreakMsg("Invalid paramter.\n");
1191*eef4f27bSRobert Mustacchi return LM_STATUS_FAILURE;
1192*eef4f27bSRobert Mustacchi }
1193*eef4f27bSRobert Mustacchi
1194*eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
1195*eef4f27bSRobert Mustacchi
1196*eef4f27bSRobert Mustacchi written_so_far = 0;
1197*eef4f27bSRobert Mustacchi ptr32 = data_buf;
1198*eef4f27bSRobert Mustacchi
1199*eef4f27bSRobert Mustacchi if ((CHIP_NUM(pdev) == CHIP_NUM_5706) || (CHIP_NUM(pdev) == CHIP_NUM_5708))
1200*eef4f27bSRobert Mustacchi {
1201*eef4f27bSRobert Mustacchi base_flags = (pdev->hw_info.flash_spec.buffered) ?
1202*eef4f27bSRobert Mustacchi NVRAM_FLAG_BUFFERED_FLASH : NVRAM_FLAG_NONE;
1203*eef4f27bSRobert Mustacchi while (written_so_far < buf_size)
1204*eef4f27bSRobert Mustacchi {
1205*eef4f27bSRobert Mustacchi /* Find the page_start addr */
1206*eef4f27bSRobert Mustacchi page_start = offset + written_so_far;
1207*eef4f27bSRobert Mustacchi page_start -= (page_start % pdev->hw_info.flash_spec.page_size);
1208*eef4f27bSRobert Mustacchi /* Find the page_end addr */
1209*eef4f27bSRobert Mustacchi page_end = page_start + pdev->hw_info.flash_spec.page_size;
1210*eef4f27bSRobert Mustacchi /* Find the data_start addr */
1211*eef4f27bSRobert Mustacchi data_start = (written_so_far==0) ? offset : page_start;
1212*eef4f27bSRobert Mustacchi /* Find the data_end addr */
1213*eef4f27bSRobert Mustacchi data_end = (page_end > offset + buf_size) ?
1214*eef4f27bSRobert Mustacchi (offset+buf_size) : page_end;
1215*eef4f27bSRobert Mustacchi
1216*eef4f27bSRobert Mustacchi /* Request access to the flash interface. */
1217*eef4f27bSRobert Mustacchi lm_status = acquire_nvram_lock(pdev);
1218*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1219*eef4f27bSRobert Mustacchi
1220*eef4f27bSRobert Mustacchi /* Enable access to flash interface */
1221*eef4f27bSRobert Mustacchi lm_status = enable_nvram_access(pdev);
1222*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1223*eef4f27bSRobert Mustacchi
1224*eef4f27bSRobert Mustacchi if (pdev->hw_info.flash_spec.buffered == 0)
1225*eef4f27bSRobert Mustacchi {
1226*eef4f27bSRobert Mustacchi /* Read the whole page into the buffer (non-buffer flash only) */
1227*eef4f27bSRobert Mustacchi for (idx=0; idx<pdev->hw_info.flash_spec.page_size; idx+=4)
1228*eef4f27bSRobert Mustacchi {
1229*eef4f27bSRobert Mustacchi cmd_flags = base_flags;
1230*eef4f27bSRobert Mustacchi if (idx==0)
1231*eef4f27bSRobert Mustacchi {
1232*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_FIRST_CMD_BIT;
1233*eef4f27bSRobert Mustacchi }
1234*eef4f27bSRobert Mustacchi if (idx==pdev->hw_info.flash_spec.page_size-4)
1235*eef4f27bSRobert Mustacchi {
1236*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_LAST_CMD_BIT;
1237*eef4f27bSRobert Mustacchi }
1238*eef4f27bSRobert Mustacchi lm_status |= nvram_read_dword(pdev, page_start+idx,
1239*eef4f27bSRobert Mustacchi &flash_buffer[idx/4],
1240*eef4f27bSRobert Mustacchi cmd_flags);
1241*eef4f27bSRobert Mustacchi }
1242*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1243*eef4f27bSRobert Mustacchi }
1244*eef4f27bSRobert Mustacchi
1245*eef4f27bSRobert Mustacchi /* Enable writes to flash interface (unlock write-protect) */
1246*eef4f27bSRobert Mustacchi lm_status = enable_nvram_write(pdev);
1247*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1248*eef4f27bSRobert Mustacchi
1249*eef4f27bSRobert Mustacchi /* Erase the page */
1250*eef4f27bSRobert Mustacchi lm_status = nvram_erase_page(pdev, page_start);
1251*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1252*eef4f27bSRobert Mustacchi
1253*eef4f27bSRobert Mustacchi /* Re-enable the write again for the actual write */
1254*eef4f27bSRobert Mustacchi lm_status = enable_nvram_write(pdev);
1255*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1256*eef4f27bSRobert Mustacchi
1257*eef4f27bSRobert Mustacchi /* Loop to write back the buffer data from page_start to data_start */
1258*eef4f27bSRobert Mustacchi cmd_flags = NVRAM_FLAG_SET_FIRST_CMD_BIT | base_flags;
1259*eef4f27bSRobert Mustacchi idx = 0;
1260*eef4f27bSRobert Mustacchi for (addr=page_start; addr<data_start; addr+=4, idx++)
1261*eef4f27bSRobert Mustacchi {
1262*eef4f27bSRobert Mustacchi if (pdev->hw_info.flash_spec.buffered == 0)
1263*eef4f27bSRobert Mustacchi {
1264*eef4f27bSRobert Mustacchi /* Write back only for non-buffered flash */
1265*eef4f27bSRobert Mustacchi (void) nvram_write_dword(pdev, addr, flash_buffer[idx], cmd_flags);
1266*eef4f27bSRobert Mustacchi cmd_flags = base_flags;
1267*eef4f27bSRobert Mustacchi }
1268*eef4f27bSRobert Mustacchi }
1269*eef4f27bSRobert Mustacchi
1270*eef4f27bSRobert Mustacchi /* Loop to write the new data from data_start to data_end */
1271*eef4f27bSRobert Mustacchi for (addr=data_start; addr<data_end; addr+=4, idx++)
1272*eef4f27bSRobert Mustacchi {
1273*eef4f27bSRobert Mustacchi if ((addr==page_end-4) ||
1274*eef4f27bSRobert Mustacchi ((pdev->hw_info.flash_spec.buffered) && (addr>=data_end-4)))
1275*eef4f27bSRobert Mustacchi {
1276*eef4f27bSRobert Mustacchi /* End of a page (page_end==data_end)
1277*eef4f27bSRobert Mustacchi * OR end of new data (in buffered flash case) */
1278*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_LAST_CMD_BIT;
1279*eef4f27bSRobert Mustacchi }
1280*eef4f27bSRobert Mustacchi (void) nvram_write_dword(pdev, addr, *ptr32, cmd_flags);
1281*eef4f27bSRobert Mustacchi cmd_flags = base_flags;
1282*eef4f27bSRobert Mustacchi ptr32++;
1283*eef4f27bSRobert Mustacchi }
1284*eef4f27bSRobert Mustacchi
1285*eef4f27bSRobert Mustacchi /* Loop to write back the buffer data from data_end to page_end */
1286*eef4f27bSRobert Mustacchi for (addr=data_end; addr<page_end; addr+=4, idx++)
1287*eef4f27bSRobert Mustacchi {
1288*eef4f27bSRobert Mustacchi if (pdev->hw_info.flash_spec.buffered == 0)
1289*eef4f27bSRobert Mustacchi {
1290*eef4f27bSRobert Mustacchi /* Write back only for non-buffered flash */
1291*eef4f27bSRobert Mustacchi if (addr == page_end-4)
1292*eef4f27bSRobert Mustacchi {
1293*eef4f27bSRobert Mustacchi cmd_flags = NVRAM_FLAG_SET_LAST_CMD_BIT | base_flags;
1294*eef4f27bSRobert Mustacchi }
1295*eef4f27bSRobert Mustacchi (void) nvram_write_dword(pdev, addr, flash_buffer[idx], cmd_flags);
1296*eef4f27bSRobert Mustacchi cmd_flags = base_flags;
1297*eef4f27bSRobert Mustacchi }
1298*eef4f27bSRobert Mustacchi }
1299*eef4f27bSRobert Mustacchi
1300*eef4f27bSRobert Mustacchi /* Disable writes to flash interface (lock write-protect) */
1301*eef4f27bSRobert Mustacchi (void) disable_nvram_write(pdev);
1302*eef4f27bSRobert Mustacchi
1303*eef4f27bSRobert Mustacchi /* Disable access to flash interface */
1304*eef4f27bSRobert Mustacchi (void) disable_nvram_access(pdev);
1305*eef4f27bSRobert Mustacchi release_nvram_lock(pdev);
1306*eef4f27bSRobert Mustacchi
1307*eef4f27bSRobert Mustacchi /* Increment written_so_far */
1308*eef4f27bSRobert Mustacchi written_so_far += data_end - data_start;
1309*eef4f27bSRobert Mustacchi } // while
1310*eef4f27bSRobert Mustacchi }
1311*eef4f27bSRobert Mustacchi else if (CHIP_NUM(pdev) == CHIP_NUM_5709)
1312*eef4f27bSRobert Mustacchi {
1313*eef4f27bSRobert Mustacchi /* Request access to the flash interface. */
1314*eef4f27bSRobert Mustacchi lm_status = acquire_nvram_lock(pdev);
1315*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1316*eef4f27bSRobert Mustacchi
1317*eef4f27bSRobert Mustacchi /* Enable access to flash interface */
1318*eef4f27bSRobert Mustacchi lm_status = enable_nvram_access(pdev);
1319*eef4f27bSRobert Mustacchi if(lm_status != LM_STATUS_SUCCESS) return lm_status;
1320*eef4f27bSRobert Mustacchi
1321*eef4f27bSRobert Mustacchi cmd_flags = NVRAM_FLAG_SET_FIRST_CMD_BIT;
1322*eef4f27bSRobert Mustacchi addr = offset;
1323*eef4f27bSRobert Mustacchi while (written_so_far < buf_size)
1324*eef4f27bSRobert Mustacchi {
1325*eef4f27bSRobert Mustacchi if (written_so_far == (buf_size - 4))
1326*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_LAST_CMD_BIT;
1327*eef4f27bSRobert Mustacchi else if (((addr & 0xff) + 4) == 256)
1328*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_LAST_CMD_BIT;
1329*eef4f27bSRobert Mustacchi if ((addr & 0xff) == 0)
1330*eef4f27bSRobert Mustacchi cmd_flags |= NVRAM_FLAG_SET_FIRST_CMD_BIT;
1331*eef4f27bSRobert Mustacchi (void) nvram_write_dword(pdev, addr, *ptr32, cmd_flags);
1332*eef4f27bSRobert Mustacchi ptr32++;
1333*eef4f27bSRobert Mustacchi addr += 4;
1334*eef4f27bSRobert Mustacchi written_so_far += 4;
1335*eef4f27bSRobert Mustacchi cmd_flags = 0;
1336*eef4f27bSRobert Mustacchi }
1337*eef4f27bSRobert Mustacchi /* Disable access to flash interface */
1338*eef4f27bSRobert Mustacchi (void) disable_nvram_access(pdev);
1339*eef4f27bSRobert Mustacchi release_nvram_lock(pdev);
1340*eef4f27bSRobert Mustacchi }
1341*eef4f27bSRobert Mustacchi
1342*eef4f27bSRobert Mustacchi return lm_status;
1343*eef4f27bSRobert Mustacchi
1344*eef4f27bSRobert Mustacchi } /* lm_nvram_write */
1345