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