summaryrefslogtreecommitdiff
path: root/utils/hwstub
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2016-03-19 21:57:58 +0000
committerAmaury Pouly <amaury.pouly@gmail.com>2017-01-24 15:17:46 +0100
commit4fd9400458f131e61a18142105c2d2d3a082a057 (patch)
tree8c2802574edb52423d94a71e6caad6610dd90186 /utils/hwstub
parent0b6cbd8e49eaf664cd005c6bb63a3111a4f4c308 (diff)
downloadrockbox-4fd9400458f131e61a18142105c2d2d3a082a057.tar.gz
rockbox-4fd9400458f131e61a18142105c2d2d3a082a057.zip
hwstub/tools/shell: add JZ4760B and Fiio X1 code
The jz code can do several useful things like dumping the IPL and SPL. The Fiio code can play with backlight and has code do dump the IPL and SPL with the correct parameters (extracted by reverse engineering). Change-Id: I317b3174f5db8d38c9a56670c1d45565142ec208
Diffstat (limited to 'utils/hwstub')
-rw-r--r--utils/hwstub/tools/lua/fiiox1.lua145
-rw-r--r--utils/hwstub/tools/lua/jz.lua4
-rw-r--r--utils/hwstub/tools/lua/jz/gpio.lua82
-rw-r--r--utils/hwstub/tools/lua/jz/lcd.lua4
-rw-r--r--utils/hwstub/tools/lua/jz/nand.lua451
5 files changed, 686 insertions, 0 deletions
diff --git a/utils/hwstub/tools/lua/fiiox1.lua b/utils/hwstub/tools/lua/fiiox1.lua
new file mode 100644
index 0000000000..c038f4077b
--- /dev/null
+++ b/utils/hwstub/tools/lua/fiiox1.lua
@@ -0,0 +1,145 @@
1--
2-- Fiio X1
3--
4FIIOX1 = {}
5
6-- 0 is PF3, 1 is PE1
7function FIIOX1.get_backlight_type()
8 return FIIOX1.bl_type
9end
10
11-- 0 is V2, 1 is V1
12function FIIOX1.get_hw_type()
13 return FIIOX1.hw_type
14end
15
16function FIIOX1.hw_detect()
17 -- PA12 is used to detect hardware version
18 JZ.gpio.pin(0, 12).std_gpio_out(1)
19 FIIOX1.hw_type = JZ.gpio.pin(0, 12).read()
20 -- PA13 is used to detect backlight type
21 JZ.gpio.pin(0, 13).std_gpio_out(1)
22 FIIOX1.bl_type = JZ.gpio.pin(0, 13).read()
23
24 if FIIOX1.hw_type == 1 then
25 print("Fiio X1: hardware version: V01")
26 else
27 print("Fiio X1: hardware version: V02")
28 end
29 print(string.format("Fiio X1: backlight type: %s", FIIOX1.bl_type))
30end
31
32function FIIOX1.get_backlight_pin()
33 if FIIOX1.get_backlight_type() == 0 then
34 -- PF3
35 return JZ.gpio.pin(5, 3)
36 else
37 -- PE1
38 return JZ.gpio.pin(4, 1)
39 end
40end
41
42function FIIOX1.init_backligt()
43 -- setup as output, high level to make no change
44 FIIOX1.get_backlight_pin().std_gpio_out(1)
45end
46
47function FIIOX1.enable_backlight(en)
48 local pin = FIIOX1.get_backlight_pin()
49 pin.clr()
50 hwstub.mdelay(1)
51 if en then
52 pin.set()
53 end
54end
55
56function FIIOX1.test_backlight()
57 print("backlight test")
58 print("enable backlight")
59 FIIOX1.enable_backlight(true)
60 print("sleep for 1 sec")
61 hwstub.mdelay(1000)
62 print("disable backlight")
63 FIIOX1.enable_backlight(false)
64 print("sleep for 1 sec")
65 hwstub.mdelay(1000)
66 print("enable backlight")
67 FIIOX1.enable_backlight(true)
68end
69
70function FIIOX1.setup_fiio_lcd_pins()
71 -- PE4: reset pin
72 JZ.gpio.pin(4, 4).std_gpio_out(1)
73 -- PC9: unknown
74 JZ.gpio.pin(2, 9).std_gpio_out(0)
75 -- PC2: unknown
76 JZ.gpio.pin(2, 2).std_gpio_out(1)
77 -- PF0: unknown
78 JZ.gpio.pin(5, 0).std_gpio_out(1)
79end
80
81function FIIOX1.lcd_reset()
82 local pin = JZ.gpio.pin(4, 4)
83 pin.set()
84 hwstub.mdelay(50)
85 pin.clr()
86 hwstub.mdelay(50)
87 pin.set()
88 hwstub.mdelay(150)
89end
90
91function FIIOX1.init_lcd()
92 -- setup Fiio X1 specific pins
93 FIIOX1.setup_fiio_lcd_pins()
94 -- reset lcd
95 JZ.lcd_reset()
96end
97
98-- call with nil to get automatic name
99function FIIOX1.dump_ipl(file)
100 FIIOX1.hw_detect()
101 if file == nil then
102 file = "fiiox1_ipl_hw_v" .. FIIOX1.hw_type .. ".bin"
103 end
104 print("Dumping IPL to " .. file .." ...")
105 JZ.nand.rom.init()
106 JZ.nand.rom.read_flags()
107 local ipl = JZ.nand.rom.read_bootloader()
108 JZ.nand.rom.write_to_file(file, ipl)
109end
110
111-- call with nil to get automatic name
112function FIIOX1.dump_spl(file)
113 FIIOX1.hw_detect()
114 if file == nil then
115 file = "fiiox1_spl_hw_v" .. FIIOX1.hw_type .. ".bin"
116 end
117 print("Dumping SPL to " .. file .." ...")
118 -- hardcoded parameters are specific to the Fiio X1
119 local nand_params = {
120 bus_width = 16,
121 row_cycle = 2,
122 col_cycle = 2,
123 page_size = 2048,
124 page_per_block = 64,
125 oob_size = 64,
126 badblock_pos = 0,
127 badblock_page = 0,
128 ecc_pos = 4,
129 ecc_size = 13,
130 ecc_level = 8,
131 addr_setup_time = 4,
132 addr_hold_time = 4,
133 write_strobe_time = 4,
134 read_strobe_time = 4,
135 recovery_time = 13,
136 }
137 local spl = JZ.nand.rom.read_spl(nand_params, 0x400, 0x200)
138 JZ.nand.rom.write_to_file(file, spl)
139end
140
141function FIIOX1.init()
142 FIIOX1.init_backligt()
143 FIIOX1.test_backlight()
144 FIIOX1.init_lcd()
145end
diff --git a/utils/hwstub/tools/lua/jz.lua b/utils/hwstub/tools/lua/jz.lua
index ab2cb8658f..b192c51b3c 100644
--- a/utils/hwstub/tools/lua/jz.lua
+++ b/utils/hwstub/tools/lua/jz.lua
@@ -24,3 +24,7 @@ function JZ.init()
24 print("Looking for soc " .. desc .. ": not found. Please load a soc by hand.") 24 print("Looking for soc " .. desc .. ": not found. Please load a soc by hand.")
25 end 25 end
26end 26end
27
28require "jz/gpio"
29require "jz/lcd"
30require "jz/nand" \ No newline at end of file
diff --git a/utils/hwstub/tools/lua/jz/gpio.lua b/utils/hwstub/tools/lua/jz/gpio.lua
new file mode 100644
index 0000000000..d85529f9bb
--- /dev/null
+++ b/utils/hwstub/tools/lua/jz/gpio.lua
@@ -0,0 +1,82 @@
1---
2--- GPIO
3---
4JZ.gpio = {}
5
6
7function JZ.gpio.pinmask(bank, mask)
8 local t = {}
9 t.read = function()
10 return bit32.band(HW.GPIO.IN[bank].read(), mask)
11 end
12
13 t.write = function(val)
14 if val then t.set() else t.clr() end
15 end
16
17 t.set = function()
18 HW.GPIO.OUT[bank].SET.write(mask)
19 end
20
21 t.clr = function()
22 HW.GPIO.OUT[bank].CLR.write(mask)
23 end
24
25 t.gpio = function()
26 HW.GPIO.FUN[bank].CLR.write(mask)
27 HW.GPIO.SEL[bank].CLR.write(mask)
28 end
29
30 t.dir = function(out)
31 if out then
32 HW.GPIO.DIR[bank].SET.write(mask)
33 else
34 HW.GPIO.DIR[bank].CLR.write(mask)
35 end
36 end
37
38 t.pull = function(val)
39 if val then
40 HW.GPIO.PULL[bank].CLR.write(mask)
41 else
42 HW.GPIO.PULL[bank].SET.write(mask)
43 end
44 end
45
46 t.std_gpio_out = function(data)
47 t.gpio()
48 t.dir(true)
49 t.pull(false)
50 t.write(data)
51 end
52
53 t.gpio_in = function(data)
54 t.gpio()
55 t.dir(false)
56 end
57
58 t.std_function = function(fun_nr)
59 HW.GPIO.FUN[bank].SET.write(mask)
60 if fun_nr >= 2 then
61 HW.GPIO.TRG[bank].SET.write(mask)
62 fun_nr = fun_nr - 2
63 else
64 HW.GPIO.TRG[bank].CLR.write(mask)
65 end
66 if fun_nr >= 2 then
67 HW.GPIO.SEL[bank].SET.write(mask)
68 else
69 HW.GPIO.SEL[bank].CLR.write(mask)
70 end
71 end
72 return t
73end
74
75function JZ.gpio.pin(bank,pin)
76 local mask = bit32.lshift(1, pin)
77 local t = JZ.gpio.pinmask(bank,mask)
78 t.read = function()
79 return bit32.extract(HW.GPIO.IN[bank].read(), pin)
80 end
81 return t
82end \ No newline at end of file
diff --git a/utils/hwstub/tools/lua/jz/lcd.lua b/utils/hwstub/tools/lua/jz/lcd.lua
new file mode 100644
index 0000000000..2e626e903f
--- /dev/null
+++ b/utils/hwstub/tools/lua/jz/lcd.lua
@@ -0,0 +1,4 @@
1---
2--- GPIO
3---
4JZ.lcd = {}
diff --git a/utils/hwstub/tools/lua/jz/nand.lua b/utils/hwstub/tools/lua/jz/nand.lua
new file mode 100644
index 0000000000..2db8ab050b
--- /dev/null
+++ b/utils/hwstub/tools/lua/jz/nand.lua
@@ -0,0 +1,451 @@
1---
2--- GPIO
3---
4JZ.nand = {}
5JZ.nand.rom = {}
6
7function JZ.nand.init_pins(buswidth)
8 -- PA[21,19,18]: cs1, fre, fwe
9 JZ.gpio.pinmask(0, 0x2c0000).std_function(0)
10 JZ.gpio.pinmask(0, 0x2c0000).pull(false)
11 if buswidth == 16 then
12 -- PA[15:0]: d{15-0}
13 JZ.gpio.pinmask(0, 0xffff).std_function(0)
14 else
15 -- PA[7:0]: d{7-0}
16 JZ.gpio.pinmask(0, 0xff).std_function(0)
17 end
18 -- PB[1:0]: ale, cle
19 JZ.gpio.pinmask(1, 3).std_function(0)
20 JZ.gpio.pinmask(1, 3).pull(false)
21 -- PA20: rb#
22 JZ.gpio.pin(0, 20).gpio_in()
23end
24
25function JZ.nand.send_cmd(cmd)
26 DEV.write8(0xba400000, cmd)
27end
28
29function JZ.nand.send_addr(addr)
30 DEV.write8(0xba800000, addr)
31end
32
33function JZ.nand.read_data8()
34 return DEV.read8(0xba000000)
35end
36
37function JZ.nand.read_data32()
38 -- Boot ROM cannot do 16-bit read/write (those end up being 2x8-bit)
39 return DEV.read32(0xba000000)
40end
41
42function JZ.nand.wait_ready()
43 local pin = JZ.gpio.pin(0, 20)
44 -- wait ready
45 while pin.read() == 0 do end
46end
47
48function JZ.nand.set_buswidth(buswidth)
49 if buswidth == 8 then
50 HW.NEMC.SMC[1].BW.write("8BIT")
51 elseif buswidth == 16 then
52 HW.NEMC.SMC[1].BW.write("16BIT")
53 else
54 error("invalid buswidth")
55 end
56end
57-- {row,col}cycle must be 2 or 3
58-- buswidth must be 8 or 16
59-- count is the number of bytes to read (must be multiple of 2 is buswidth is 16)
60-- function returns a table of bytes
61function JZ.nand.read_page(col,colcycle,row,rowcycle,buswidth,count)
62 JZ.nand.set_buswidth(buswidth)
63 -- read page first cycle
64 JZ.nand.send_cmd(0)
65 -- column
66 JZ.nand.send_addr(col)
67 JZ.nand.send_addr(bit32.rshift(col, 8))
68 if colcycle == 3 then
69 JZ.nand.send_addr(bit32.rshift(col, 16))
70 end
71 -- row
72 JZ.nand.send_addr(row)
73 JZ.nand.send_addr(bit32.rshift(row, 8))
74 if rowcycle == 3 then
75 JZ.nand.send_addr(bit32.rshift(row, 16))
76 end
77 -- read page second cycle
78 JZ.nand.send_cmd(0x30)
79 -- wait ready
80 JZ.nand.wait_ready()
81 -- read
82 return JZ.nand.read_page_data(buswidth,count)
83end
84
85function JZ.nand.read_page2(params,col,row,count)
86 return JZ.nand.read_page(col,params.col_cycle,row,params.row_cycle,params.bus_width,count)
87end
88
89-- read data, assuming read page command was sent
90function JZ.nand.read_page_data(buswidth,count)
91 -- read
92 data = {}
93 if buswidth == 8 then
94 for i=0, count-1 do
95 data[i] = JZ.nand.read_data8()
96 end
97 else
98 for i=0, count-1, 4 do
99 local hw = JZ.nand.read_data32()
100 data[i] = bit32.band(hw, 0xff)
101 data[i + 1] = bit32.band(bit32.rshift(hw, 8), 0xff)
102 data[i + 2] = bit32.band(bit32.rshift(hw, 16), 0xff)
103 data[i + 3] = bit32.band(bit32.rshift(hw, 24), 0xff)
104 end
105 end
106 return data
107end
108
109function JZ.nand.read_oob(params,page)
110--[[
111NAND flash are magic, every setup is different, so basically:
112- if the page size is 512, that's a special case and we need to use a special
113 command to read OOB, also note that 512-byte NAND only have one cycle column address
114- otherwise, assume OOB is after the data (so at offset page_size in bytes),
115 but beware that for 16-bit bus, column address is in words, not bytes
116For simplicity, we do not support 512-byte NAND at the moment
117]]
118 -- compute column address of OOB data
119 local col_addr = params.page_size
120 if params.bus_width == 16 then
121 col_addr = params.page_size / 2
122 end
123 -- read page
124 return JZ.nand.read_page2(params,col_addr,page,params.oob_size)
125end
126
127--[[
128setup NAND parameters, the table should contain:
129- bus_width: 8 or 16,
130- addr_setup_time: in cycles
131- addr_hold_time: in cycles
132- write_strobe_time: in cycles
133- read_strobe_time: in cycles
134- recovery_time: in cycles
135]]
136function JZ.nand.setup(params)
137 JZ.nand.init_pins(params.bus_width)
138 HW.NEMC.SMC[1].BL.write(params.bus_width == 8 and "8" or "16")
139 HW.NEMC.SMC[1].TAS.write(params.addr_setup_time)
140 HW.NEMC.SMC[1].TAH.write(params.addr_hold_time)
141 HW.NEMC.SMC[1].TBP.write(params.write_strobe_time)
142 HW.NEMC.SMC[1].TAW.write(params.read_strobe_time)
143 HW.NEMC.SMC[1].STRV.write(params.recovery_time)
144end
145
146function JZ.nand.reset()
147 print("NAND: reset")
148 JZ.nand.send_cmd(0xff)
149 JZ.nand.wait_ready()
150end
151
152-- init nand like ROM
153function JZ.nand.rom.init()
154 -- init pins to 16-bit in doubt
155 JZ.nand.init_pins(16)
156 -- take safest setting: 8-bit, max TAS, max TAH, max read/write strobe wait
157 HW.NEMC.SMC[1].write(0xfff7700)
158 -- enable flash on CS1 with CS# always asserted
159 HW.NEMC.NFC.write(3)
160 -- reset
161 JZ.nand.reset()
162end
163
164function JZ.nand.rom.parse_flag(data, offset)
165 local cnt_55 = 0
166 local cnt_aa = 0
167 for i = offset,offset + 31 do
168 if data[i] == 0x55 then
169 cnt_55 = cnt_55 + 1
170 elseif data[i] == 0xaa then
171 cnt_aa = cnt_aa + 1
172 end
173 end
174 if cnt_55 >= 7 then
175 return 0x55
176 elseif cnt_aa >= 7 then
177 return 0xaa
178 else
179 return 0xff
180 end
181end
182
183function JZ.nand.rom.read_page(col,row,count)
184 return JZ.nand.read_page(col, JZ.nand.rom.colcycle, row, JZ.nand.rom.rowcycle,
185 JZ.nand.rom.buswidth, count)
186end
187
188function JZ.nand.rom.read_page_data(count)
189 return JZ.nand.read_page_data(JZ.nand.rom.buswidth, count)
190end
191
192-- read flash parameters
193function JZ.nand.rom.read_flags()
194 local flags = nil
195 -- read first page
196 for colcycle = 2,3 do
197 flags = JZ.nand.read_page(0,colcycle,0,3,8,160)
198 local buswidth_flag = JZ.nand.rom.parse_flag(flags, 0)
199 if buswidth_flag == 0x55 then
200 -- set to 8-bit
201 JZ.nand.rom.colcycle = colcycle
202 JZ.nand.rom.buswidth = 8
203 break
204 elseif buswidth_flag == 0xaa then
205 -- set to 16-bit
206 JZ.nand.rom.colcycle = colcycle
207 JZ.nand.rom.buswidth = 16
208 break
209 end
210 end
211 if JZ.nand.rom.buswidth == nil then
212 error("Cannot read flags")
213 end
214 print("NAND: colcycle = " .. JZ.nand.rom.colcycle)
215 print("NAND: buswidth = " .. JZ.nand.rom.buswidth)
216 -- reread flags correctly now
217 flags = JZ.nand.read_page(0,JZ.nand.rom.colcycle,0,3,JZ.nand.rom.buswidth,160)
218 -- rowcycle
219 local rowcycle_flag = JZ.nand.rom.parse_flag(flags, 64)
220 if rowcycle_flag == 0x55 then
221 JZ.nand.rom.rowcycle = 2
222 elseif rowcycle_flag == 0xaa then
223 JZ.nand.rom.rowcycle = 3
224 else
225 error("invalid rowcycle flag")
226 end
227 print("NAND: rowcycle = " .. JZ.nand.rom.rowcycle)
228 -- pagesize
229 local pagesize1_flag = JZ.nand.rom.parse_flag(flags, 96)
230 local pagesize0_flag = JZ.nand.rom.parse_flag(flags, 128)
231 if pagesize1_flag == 0x55 and pagesize0_flag == 0x55 then
232 JZ.nand.rom.pagesize = 512
233 elseif pagesize1_flag == 0x55 and pagesize0_flag == 0xaa then
234 JZ.nand.rom.pagesize = 2048
235 elseif pagesize1_flag == 0xaa and pagesize0_flag == 0x55 then
236 JZ.nand.rom.pagesize = 4096
237 elseif pagesize1_flag == 0xaa and pagesize0_flag == 0xaa then
238 JZ.nand.rom.pagesize = 8192
239 else
240 error(string.format("invalid pagesize flag: %#x,%#x", pagesize1_flag, pagesize0_flag))
241 end
242 print("NAND: pagesize = " .. JZ.nand.rom.pagesize)
243end
244
245-- read bootloader
246function JZ.nand.rom.read_bootloader()
247 -- computer number of blocks per page
248 local bl_size = 256
249 local bl_per_page = JZ.nand.rom.pagesize / bl_size
250 local ecc_per_bl = 39
251 local bootloader_size = 8 * 1024
252 local bootloader = {}
253
254 local page_offset = 0
255 while true do
256 local all_ok = true
257 print("NAND: try at page offset " .. page_offset)
258 for page = 0, bootloader_size / JZ.nand.rom.pagesize - 1 do
259 print("NAND: page " .. page)
260 -- enable randomizer
261 HW.NEMC.PNC.write(3)
262 -- read ECC
263 local ecc = JZ.nand.rom.read_page(0, page_offset + 2 * page + 1, ecc_per_bl * bl_per_page)
264 -- disable randomizer
265 HW.NEMC.PNC.write(0)
266 HW.NEMC.NFC.write(0)
267 HW.NEMC.NFC.write(3)
268 -- send read page commannd, but don't read the data just yet
269 JZ.nand.rom.read_page(0, page_offset + 2 * page, 0)
270 -- for each block
271 for bl = 0, bl_per_page - 1 do
272 print("NAND: block " .. bl)
273 -- enable randomizer (except for first block of first page)
274 if page ~=0 or bl ~= 0 then
275 HW.NEMC.PNC.write(3)
276 end
277 -- read data
278 local data = JZ.nand.rom.read_page_data(bl_size)
279 -- disable randomizer
280 HW.NEMC.PNC.write(0)
281 -- setup bch
282 HW.BCH.INTS.write(0xffffffff)
283 HW.BCH.CTRL.SET.write(0x2b)
284 HW.BCH.CTRL.CLR.write(0x4)
285 HW.BCH.COUNT.DEC.write((bl_size + ecc_per_bl) * 2)
286 for i = 0, bl_size - 1 do
287 HW.BCH.DATA.write(data[i])
288 end
289 for i = 0, ecc_per_bl - 1 do
290 HW.BCH.DATA.write(ecc[bl * ecc_per_bl + i])
291 end
292 while HW.BCH.INTS.DECF.read() == 0 do
293 end
294 HW.BCH.CTRL.CLR.write(1)
295 print(string.format("NAND: ecc = 0x%x", HW.BCH.INTS.read()))
296 -- now fix the errors
297 if HW.BCH.INTS.UNCOR.read() == 1 then
298 print("NAND: uncorrectable errors !")
299 all_ok = false
300 end
301 print(string.format("NAND: correcting %d errors", HW.BCH.INTS.ERRC.read()))
302 if HW.BCH.INTS.ERRC.read() > 0 then
303 error("Error correction is not implemented for now")
304 end
305 for i = 0, bl_size - 1 do
306 bootloader[(page * bl_per_page + bl) * bl_size + i] = data[i]
307 end
308 end
309 end
310 if all_ok then
311 break
312 end
313 page_offset = page_offset + 16 * 1024 / JZ.nand.rom.pagesize
314 end
315 return bootloader
316end
317
318--[[
319read SPL: offset and size in pages, the param table should contain:
320- page_size: page size in bytes (exclusing spare)
321- oob_size: spare data size in bytes
322- page_per_block: number of pages per block
323- ecc_pos: offset within spare of the ecc data
324- badblock_pos: offset within spare of the badblock marker (only one page per block is marked)
325- badblock_page: page number within block of the page containing badblock marker in spare
326- col_cycle: number of cycles for column address
327- row_cycle: number of cycles for row address
328- ecc_size: ECC size in bytes
329- ecc_level: level of error correction in bits: 4, 8, 12, ...
330]]
331function JZ.nand.rom.read_spl(params, offset, size)
332--[[
333On-flash format: each block contains page_per_block pages,
334where each page contains page_size bytes, follows by oob_size spare bytes.
335The spare area contains a bad block marker at offset badblock_pos and
336the ECC data at offset ecc_pos. Note that only one page within each block
337actually contains the bad block marker: this page is badblock_page. The marker
338is 0xff is the block is valid. Any invalid block is skipped.
339The ECC is computed on a per-512-block basis. Since a page contains several such
340blocks, the ECC data contains consecutive ecc blocks, one for each 512-byte data
341block.
342
343+---------------------+
344|page0|page1|...|pageN| <--- block
345+---------------------+
346
347+-------------------------------+
348|data(page_size)|spare(oob_size)| <--- page
349+-------------------------------+
350
351+---------------------------------------------+
352|xxxx|badblock marker(1)|xxxxx|ECC data()|xxxx| <-- spare
353+---------------------------------------------+
354]]
355 local bootloader = {}
356 if (offset % params.page_per_block) ~= 0 then
357 print("Warning: SPL is not block-aligned")
358 end
359 -- setup parameters
360 JZ.nand.setup(params)
361 -- enable NAND
362 HW.NEMC.NFC.write(3)
363 -- reset
364 JZ.nand.reset()
365 -- read SPL !
366 local checked_block = false
367 local cur_page = offset
368 local loaded_pages = 0
369 while loaded_pages < size do
370 ::load_loop::
371 -- if we just crossed a page boundary, reset the block check flag
372 if (cur_page % params.page_per_block) == 0 then
373 checked_block = false
374 end
375 -- check block for bad block marker if needed
376 if not checked_block then
377 print("Reading bad block marker for block " .. (cur_page / params.page_per_block) .. "...")
378 -- read OOB data
379 local oob_data = JZ.nand.read_oob(params,cur_page + params.badblock_page)
380 if oob_data[params.badblock_pos] ~= 0xff then
381 print("Bad block at " .. (cur_page / page_per_block))
382 -- skip block
383 cur_page = ((cur_page + params.page_per_block) / params.page_per_block) * params.page_per_block
384 -- lua has no continue...
385 goto load_loop
386 end
387 checked_block = true
388 end
389
390 print("Reading page " .. cur_page .. "...")
391 -- send read page command
392 JZ.nand.read_page2(params,0,cur_page, 0)
393 local page_data = JZ.nand.read_page_data(params.bus_width,params.page_size)
394 local oob_data = JZ.nand.read_page_data(params.bus_width,params.oob_size)
395 -- handle each 512-byte block for ECC
396 local bl_size = 512
397 for bl = 0,params.page_size/bl_size-1 do
398 print("Checking subblock " .. bl .. "...")
399 -- setup bch
400 HW.BCH.INTS.write(0xffffffff)
401 HW.BCH.CTRL.CLR.BSEL.write() -- clear level
402 HW.BCH.CTRL.SET.BSEL.write(params.ecc_level / 4 - 1) -- set level
403 HW.BCH.CTRL.SET.write(3) -- enable and reset
404 HW.BCH.CTRL.CLR.ENCE.write(0x4) -- decode
405 -- write ecc data count
406 HW.BCH.COUNT.DEC.write((bl_size + params.ecc_size) * 2)
407 -- write data
408 for j = 0, bl_size - 1 do
409 HW.BCH.DATA.write(page_data[bl_size * bl + j])
410 end
411 -- write ecc data
412 for j = 0, params.ecc_size - 1 do
413 HW.BCH.DATA.write(oob_data[params.ecc_pos + bl * params.ecc_size + j])
414 end
415 -- wait until bch is done
416 while HW.BCH.INTS.DECF.read() == 0 do
417 end
418 -- disable bch
419 HW.BCH.CTRL.CLR.write(1)
420 print(string.format("NAND: ecc = 0x%x", HW.BCH.INTS.read()))
421 -- now fix the errors
422 if HW.BCH.INTS.UNCOR.read() == 1 then
423 error("NAND: uncorrectable errors !")
424 end
425 print(string.format("NAND: correcting %d errors", HW.BCH.INTS.ERRC.read()))
426 if HW.BCH.INTS.ERRC.read() > 0 then
427 error("Error correction is not implemented for now")
428 end
429 for i = 0, bl_size - 1 do
430 bootloader[loaded_pages * params.page_size + bl * bl_size + i] = page_data[bl_size * bl + i]
431 end
432 end
433 cur_page = cur_page + 1
434 loaded_pages = loaded_pages + 1
435 end
436 -- disable NAND
437 HW.NEMC.NFC.write(0)
438 return bootloader
439end
440
441-- dump data
442function JZ.nand.rom.write_to_file(file, data)
443 local f = io.open(file, "w")
444 if f == nil then error("Cannot open file or write to nil") end
445 local i = 0
446 while type(data[i]) == "number" do
447 f:write(string.char(data[i]))
448 i = i + 1
449 end
450 io.close(f)
451end \ No newline at end of file