summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c96
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c131
2 files changed, 176 insertions, 51 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
index bbef9d2920..56c7554640 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
@@ -26,6 +26,35 @@
26#include <nand-target.h> 26#include <nand-target.h>
27#include <ftl-target.h> 27#include <ftl-target.h>
28#include <string.h> 28#include <string.h>
29#include "kernel.h"
30#include "panic.h"
31
32
33
34//#define FTL_FORCEMOUNT
35
36
37
38#ifdef FTL_FORCEMOUNT
39#ifndef FTL_READONLY
40#define FTL_READONLY
41#endif
42#endif
43
44
45#ifdef FTL_READONLY
46uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
47{
48 (void)sector;
49 (void)count;
50 (void)buffer;
51 return 1;
52}
53uint32_t ftl_sync(void)
54{
55 return 0;
56}
57#endif
29 58
30 59
31 60
@@ -371,6 +400,8 @@ uint8_t ftl_erasectr_dirt[8];
371 400
372#endif 401#endif
373 402
403static struct mutex ftl_mtx;
404
374 405
375 406
376/* Finds a device info page for the specified bank and returns its number. 407/* Finds a device info page for the specified bank and returns its number.
@@ -653,6 +684,7 @@ void ftl_vfl_schedule_block_for_remap(uint32_t bank, uint32_t block)
653{ 684{
654 if (ftl_vfl_check_remap_scheduled(bank, block) == 1) 685 if (ftl_vfl_check_remap_scheduled(bank, block) == 1)
655 return; 686 return;
687 panicf("FTL: Scheduling bank %d block %d for remap!", bank, block);
656 if (ftl_vfl_cxt[bank].scheduledstart == ftl_vfl_cxt[bank].spareused) 688 if (ftl_vfl_cxt[bank].scheduledstart == ftl_vfl_cxt[bank].spareused)
657 return; 689 return;
658 ftl_vfl_cxt[bank].remaptable[--ftl_vfl_cxt[bank].scheduledstart] = block; 690 ftl_vfl_cxt[bank].remaptable[--ftl_vfl_cxt[bank].scheduledstart] = block;
@@ -738,6 +770,7 @@ uint32_t ftl_vfl_remap_block(uint32_t bank, uint32_t block)
738{ 770{
739 uint32_t i; 771 uint32_t i;
740 uint32_t newblock = 0, newidx; 772 uint32_t newblock = 0, newidx;
773 panicf("FTL: Remapping bank %d block %d!", bank, block);
741 if (bank >= ftl_banks || block >= (*ftl_nand_type).blocks) return 0; 774 if (bank >= ftl_banks || block >= (*ftl_nand_type).blocks) return 0;
742 for (i = 0; i < ftl_vfl_cxt[bank].sparecount; i++) 775 for (i = 0; i < ftl_vfl_cxt[bank].sparecount; i++)
743 if (ftl_vfl_cxt[bank].remaptable[i] == 0) 776 if (ftl_vfl_cxt[bank].remaptable[i] == 0)
@@ -949,7 +982,9 @@ uint32_t ftl_open(void)
949 else 982 else
950 { 983 {
951 /* This will trip if there was an unclean unmount before. */ 984 /* This will trip if there was an unclean unmount before. */
985#ifndef FTL_FORCEMOUNT
952 break; 986 break;
987#endif
953 } 988 }
954 } 989 }
955 990
@@ -1030,6 +1065,8 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1030 1065
1031 if (count == 0) return 0; 1066 if (count == 0) return 0;
1032 1067
1068 mutex_lock(&ftl_mtx);
1069
1033 for (i = 0; i < count; i++) 1070 for (i = 0; i < count; i++)
1034 { 1071 {
1035 uint32_t block = (sector + i) / ppb; 1072 uint32_t block = (sector + i) / ppb;
@@ -1054,6 +1091,9 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1054 memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); 1091 memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
1055 } 1092 }
1056 } 1093 }
1094
1095 mutex_unlock(&ftl_mtx);
1096
1057 return error; 1097 return error;
1058} 1098}
1059 1099
@@ -1609,11 +1649,17 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1609 1649
1610 if (count == 0) return 0; 1650 if (count == 0) return 0;
1611 1651
1652 mutex_lock(&ftl_mtx);
1653
1612 if (ftl_cxt.clean_flag == 1) 1654 if (ftl_cxt.clean_flag == 1)
1613 { 1655 {
1614 for (i = 0; i < 3; i++) 1656 for (i = 0; i < 3; i++)
1615 { 1657 {
1616 if (ftl_next_ctrl_pool_page() != 0) return 1; 1658 if (ftl_next_ctrl_pool_page() != 0)
1659 {
1660 mutex_unlock(&ftl_mtx);
1661 return 1;
1662 }
1617 memset(ftl_buffer, 0xFF, 0x800); 1663 memset(ftl_buffer, 0xFF, 0x800);
1618 memset(&ftl_sparebuffer, 0xFF, 0x40); 1664 memset(&ftl_sparebuffer, 0xFF, 0x40);
1619 ftl_sparebuffer.meta.usn = ftl_cxt.usn; 1665 ftl_sparebuffer.meta.usn = ftl_cxt.usn;
@@ -1622,7 +1668,11 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1622 &ftl_sparebuffer) == 0) 1668 &ftl_sparebuffer) == 0)
1623 break; 1669 break;
1624 } 1670 }
1625 if (i == 3) return 1; 1671 if (i == 3)
1672 {
1673 mutex_unlock(&ftl_mtx);
1674 return 1;
1675 }
1626 ftl_cxt.clean_flag = 0; 1676 ftl_cxt.clean_flag = 0;
1627 } 1677 }
1628 1678
@@ -1632,7 +1682,11 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1632 uint32_t page = (sector + i) % ppb; 1682 uint32_t page = (sector + i) % ppb;
1633 1683
1634 struct ftl_log_type* logentry = ftl_allocate_log_entry(block); 1684 struct ftl_log_type* logentry = ftl_allocate_log_entry(block);
1635 if (logentry == (struct ftl_log_type*)0) return 1; 1685 if (logentry == (struct ftl_log_type*)0)
1686 {
1687 mutex_unlock(&ftl_mtx);
1688 return 1;
1689 }
1636 if (page == 0 && count - i >= ppb) 1690 if (page == 0 && count - i >= ppb)
1637 { 1691 {
1638 uint32_t vblock = (*logentry).scatteredvblock; 1692 uint32_t vblock = (*logentry).scatteredvblock;
@@ -1641,7 +1695,11 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1641 { 1695 {
1642 ftl_release_pool_block(vblock); 1696 ftl_release_pool_block(vblock);
1643 vblock = ftl_allocate_pool_block(); 1697 vblock = ftl_allocate_pool_block();
1644 if (vblock == 0) return 1; 1698 if (vblock == 0)
1699 {
1700 mutex_unlock(&ftl_mtx);
1701 return 1;
1702 }
1645 } 1703 }
1646 ftl_cxt.nextblockusn++; 1704 ftl_cxt.nextblockusn++;
1647 for (j = 0; j < ppb; j++) 1705 for (j = 0; j < ppb; j++)
@@ -1665,7 +1723,11 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1665 { 1723 {
1666 ftl_remove_scattered_block(logentry); 1724 ftl_remove_scattered_block(logentry);
1667 logentry = ftl_allocate_log_entry(block); 1725 logentry = ftl_allocate_log_entry(block);
1668 if (logentry == (struct ftl_log_type*)0) return 1; 1726 if (logentry == (struct ftl_log_type*)0)
1727 {
1728 mutex_unlock(&ftl_mtx);
1729 return 1;
1730 }
1669 } 1731 }
1670 memset(&ftl_sparebuffer, 0xFF, 0x40); 1732 memset(&ftl_sparebuffer, 0xFF, 0x40);
1671 ftl_sparebuffer.user.lpn = sector + i; 1733 ftl_sparebuffer.user.lpn = sector + i;
@@ -1699,6 +1761,7 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1699 ftl_save_erasectr_page(i); 1761 ftl_save_erasectr_page(i);
1700 } 1762 }
1701 } 1763 }
1764 mutex_unlock(&ftl_mtx);
1702 return 0; 1765 return 0;
1703} 1766}
1704#endif 1767#endif
@@ -1745,6 +1808,7 @@ uint32_t ftl_sync(void)
1745 which will just do nothing if everything was already clean. */ 1808 which will just do nothing if everything was already clean. */
1746uint32_t ftl_init(void) 1809uint32_t ftl_init(void)
1747{ 1810{
1811 mutex_init(&ftl_mtx);
1748 uint32_t i; 1812 uint32_t i;
1749 uint32_t result = 0; 1813 uint32_t result = 0;
1750 uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip; 1814 uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip;
@@ -1755,6 +1819,7 @@ uint32_t ftl_init(void)
1755 ftl_nand_type = nand_get_device_type(0); 1819 ftl_nand_type = nand_get_device_type(0);
1756 foundsignature = 0; 1820 foundsignature = 0;
1757 blockwiped = 1; 1821 blockwiped = 1;
1822 mutex_unlock(&ftl_mtx);
1758 for (i = 0; i < (*ftl_nand_type).pagesperblock; i++) 1823 for (i = 0; i < (*ftl_nand_type).pagesperblock; i++)
1759 { 1824 {
1760 result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1); 1825 result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1);
@@ -1772,10 +1837,23 @@ uint32_t ftl_init(void)
1772 1837
1773 repaired = 0; 1838 repaired = 0;
1774 skip = 0; 1839 skip = 0;
1775 if (founddevinfo == 0) return 1; 1840 if (founddevinfo == 0)
1776 if (foundsignature != 0 && (result & 0x11F) != 0) return 1; 1841 {
1842 mutex_unlock(&ftl_mtx);
1843 return 1;
1844 }
1845 if (foundsignature != 0 && (result & 0x11F) != 0)
1846 {
1847 mutex_unlock(&ftl_mtx);
1848 return 1;
1849 }
1777 if (ftl_vfl_open() == 0) 1850 if (ftl_vfl_open() == 0)
1778 if (ftl_open() == 0) return 0; 1851 if (ftl_open() == 0)
1852 {
1853 mutex_unlock(&ftl_mtx);
1854 return 0;
1855 }
1856
1779 1857
1780/* Something went terribly wrong. We may want to allow the user to erase 1858/* Something went terribly wrong. We may want to allow the user to erase
1781 block zero in that condition, to make norboot reinitialize the FTL. 1859 block zero in that condition, to make norboot reinitialize the FTL.
@@ -1785,5 +1863,7 @@ uint32_t ftl_init(void)
1785 nand_block_erase(0, 0); 1863 nand_block_erase(0, 0);
1786*/ 1864*/
1787 1865
1866
1867 mutex_unlock(&ftl_mtx);
1788 return 1; 1868 return 1;
1789} 1869}
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
index ba83ab6df2..91d8827b50 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
@@ -22,6 +22,7 @@
22 22
23#include "config.h" 23#include "config.h"
24#include "system.h" 24#include "system.h"
25#include "kernel.h"
25#include "cpu.h" 26#include "cpu.h"
26#include "inttypes.h" 27#include "inttypes.h"
27#include "nand-target.h" 28#include "nand-target.h"
@@ -84,6 +85,11 @@ uint8_t nand_tunk2[4];
84uint8_t nand_tunk3[4]; 85uint8_t nand_tunk3[4];
85uint32_t nand_type[4]; 86uint32_t nand_type[4];
86 87
88static struct mutex nand_mtx;
89static struct wakeup nand_wakeup;
90static struct mutex ecc_mtx;
91static struct wakeup ecc_wakeup;
92
87static uint8_t nand_aligned_data[0x800] __attribute__((aligned(32))); 93static uint8_t nand_aligned_data[0x800] __attribute__((aligned(32)));
88static uint8_t nand_aligned_ctrl[0x200] __attribute__((aligned(32))); 94static uint8_t nand_aligned_ctrl[0x200] __attribute__((aligned(32)));
89static uint8_t nand_aligned_spare[0x40] __attribute__((aligned(32))); 95static uint8_t nand_aligned_spare[0x40] __attribute__((aligned(32)));
@@ -98,35 +104,60 @@ static uint8_t nand_aligned_ecc[0x28] __attribute__((aligned(32)));
98 ((uint8_t*)(((uint32_t)nand_aligned_ecc) | 0x40000000)) 104 ((uint8_t*)(((uint32_t)nand_aligned_ecc) | 0x40000000))
99 105
100 106
107uint32_t nand_unlock(uint32_t rc)
108{
109 mutex_unlock(&nand_mtx);
110 return rc;
111}
112
113uint32_t ecc_unlock(uint32_t rc)
114{
115 mutex_unlock(&ecc_mtx);
116 return rc;
117}
118
119uint32_t nand_timeout(long timeout)
120{
121 if (TIME_AFTER(current_tick, timeout)) return 1;
122 else
123 {
124 yield();
125 return 0;
126 }
127}
128
101uint32_t nand_wait_rbbdone(void) 129uint32_t nand_wait_rbbdone(void)
102{ 130{
103 uint32_t timeout = 0x40000; 131 long timeout = current_tick + HZ / 1;
104 while ((FMCSTAT & FMCSTAT_RBBDONE) == 0) if (timeout-- == 0) return 1; 132 while ((FMCSTAT & FMCSTAT_RBBDONE) == 0)
133 if (nand_timeout(timeout)) return 1;
105 FMCSTAT = FMCSTAT_RBBDONE; 134 FMCSTAT = FMCSTAT_RBBDONE;
106 return 0; 135 return 0;
107} 136}
108 137
109uint32_t nand_wait_cmddone(void) 138uint32_t nand_wait_cmddone(void)
110{ 139{
111 uint32_t timeout = 0x40000; 140 long timeout = current_tick + HZ / 1;
112 while ((FMCSTAT & FMCSTAT_CMDDONE) == 0) if (timeout-- == 0) return 1; 141 while ((FMCSTAT & FMCSTAT_CMDDONE) == 0)
142 if (nand_timeout(timeout)) return 1;
113 FMCSTAT = FMCSTAT_CMDDONE; 143 FMCSTAT = FMCSTAT_CMDDONE;
114 return 0; 144 return 0;
115} 145}
116 146
117uint32_t nand_wait_addrdone(void) 147uint32_t nand_wait_addrdone(void)
118{ 148{
119 uint32_t timeout = 0x40000; 149 long timeout = current_tick + HZ / 1;
120 while ((FMCSTAT & FMCSTAT_ADDRDONE) == 0) if (timeout-- == 0) return 1; 150 while ((FMCSTAT & FMCSTAT_ADDRDONE) == 0)
151 if (nand_timeout(timeout)) return 1;
121 FMCSTAT = FMCSTAT_ADDRDONE; 152 FMCSTAT = FMCSTAT_ADDRDONE;
122 return 0; 153 return 0;
123} 154}
124 155
125uint32_t nand_wait_chip_ready(uint32_t bank) 156uint32_t nand_wait_chip_ready(uint32_t bank)
126{ 157{
127 uint32_t timeout = 0x40000; 158 long timeout = current_tick + HZ / 1;
128 while ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) == 0) 159 while ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) == 0)
129 if (timeout-- == 0) return 1; 160 if (nand_timeout(timeout)) return 1;
130 FMCSTAT = (FMCSTAT_BANK0READY << bank); 161 FMCSTAT = (FMCSTAT_BANK0READY << bank);
131 return 0; 162 return 0;
132} 163}
@@ -163,7 +194,7 @@ uint32_t nand_reset(uint32_t bank)
163 194
164uint32_t nand_wait_status_ready(uint32_t bank) 195uint32_t nand_wait_status_ready(uint32_t bank)
165{ 196{
166 uint32_t timeout = 0x4000; 197 long timeout = current_tick + HZ / 1;
167 nand_set_fmctrl0(bank, 0); 198 nand_set_fmctrl0(bank, 0);
168 if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) != 0) 199 if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) != 0)
169 FMCSTAT = (FMCSTAT_BANK0READY << bank); 200 FMCSTAT = (FMCSTAT_BANK0READY << bank);
@@ -171,7 +202,7 @@ uint32_t nand_wait_status_ready(uint32_t bank)
171 if (nand_send_cmd(NAND_CMD_GET_STATUS) != 0) return 1; 202 if (nand_send_cmd(NAND_CMD_GET_STATUS) != 0) return 1;
172 while (1) 203 while (1)
173 { 204 {
174 if (timeout-- == 0) return 1; 205 if (nand_timeout(timeout)) return 1;
175 FMDNUM = 0; 206 FMDNUM = 0;
176 FMCTRL1 = FMCTRL1_DOREADDATA; 207 FMCTRL1 = FMCTRL1_DOREADDATA;
177 if (nand_wait_addrdone() != 0) return 1; 208 if (nand_wait_addrdone() != 0) return 1;
@@ -185,7 +216,7 @@ uint32_t nand_wait_status_ready(uint32_t bank)
185uint32_t nand_transfer_data(uint32_t bank, uint32_t direction, 216uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
186 void* buffer, uint32_t size) 217 void* buffer, uint32_t size)
187{ 218{
188 uint32_t timeout = 0x40000; 219 long timeout = current_tick + HZ / 1;
189 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); 220 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
190 FMDNUM = size - 1; 221 FMDNUM = size - 1;
191 FMCTRL1 = FMCTRL1_DOREADDATA << direction; 222 FMCTRL1 = FMCTRL1_DOREADDATA << direction;
@@ -199,7 +230,7 @@ uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
199 DMATCNT3 = (size >> 4) - 1; 230 DMATCNT3 = (size >> 4) - 1;
200 DMACOM3 = 4; 231 DMACOM3 = 4;
201 while ((DMAALLST & DMAALLST_DMABUSY3) != 0) 232 while ((DMAALLST & DMAALLST_DMABUSY3) != 0)
202 if (timeout-- == 0) return 1; 233 if (nand_timeout(timeout)) return 1;
203 if (nand_wait_addrdone() != 0) return 1; 234 if (nand_wait_addrdone() != 0) return 1;
204 if (direction == 0) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO; 235 if (direction == 0) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
205 return 0; 236 return 0;
@@ -207,32 +238,36 @@ uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
207 238
208uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer) 239uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
209{ 240{
210 uint32_t timeout = 0x40000; 241 mutex_lock(&ecc_mtx);
242 long timeout = current_tick + HZ / 1;
211 ECC_INT_CLR = 1; 243 ECC_INT_CLR = 1;
212 SRCPND = INTMSK_ECC; 244 SRCPND = INTMSK_ECC;
213 ECC_UNK1 = size; 245 ECC_UNK1 = size;
214 ECC_DATA_PTR = (uint32_t)databuffer; 246 ECC_DATA_PTR = (uint32_t)databuffer;
215 ECC_SPARE_PTR = (uint32_t)sparebuffer; 247 ECC_SPARE_PTR = (uint32_t)sparebuffer;
216 ECC_CTRL = ECCCTRL_STARTDECODING; 248 ECC_CTRL = ECCCTRL_STARTDECODING;
217 while ((SRCPND & INTMSK_ECC) == 0) if (timeout-- == 0) return 1; 249 while ((SRCPND & INTMSK_ECC) == 0)
250 if (nand_timeout(timeout)) return ecc_unlock(1);
218 ECC_INT_CLR = 1; 251 ECC_INT_CLR = 1;
219 SRCPND = INTMSK_ECC; 252 SRCPND = INTMSK_ECC;
220 return ECC_RESULT; 253 return ecc_unlock(ECC_RESULT);
221} 254}
222 255
223uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer) 256uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
224{ 257{
225 uint32_t timeout = 0x40000; 258 mutex_lock(&ecc_mtx);
259 long timeout = current_tick + HZ / 1;
226 ECC_INT_CLR = 1; 260 ECC_INT_CLR = 1;
227 SRCPND = INTMSK_ECC; 261 SRCPND = INTMSK_ECC;
228 ECC_UNK1 = size; 262 ECC_UNK1 = size;
229 ECC_DATA_PTR = (uint32_t)databuffer; 263 ECC_DATA_PTR = (uint32_t)databuffer;
230 ECC_SPARE_PTR = (uint32_t)sparebuffer; 264 ECC_SPARE_PTR = (uint32_t)sparebuffer;
231 ECC_CTRL = ECCCTRL_STARTENCODING; 265 ECC_CTRL = ECCCTRL_STARTENCODING;
232 while ((SRCPND & INTMSK_ECC) == 0) if (timeout-- == 0) return 1; 266 while ((SRCPND & INTMSK_ECC) == 0)
267 if (nand_timeout(timeout)) return ecc_unlock(1);
233 ECC_INT_CLR = 1; 268 ECC_INT_CLR = 1;
234 SRCPND = INTMSK_ECC; 269 SRCPND = INTMSK_ECC;
235 return 0; 270 return ecc_unlock(0);
236} 271}
237 272
238uint32_t nand_check_empty(uint8_t* buffer) 273uint32_t nand_check_empty(uint8_t* buffer)
@@ -246,51 +281,53 @@ uint32_t nand_check_empty(uint8_t* buffer)
246 281
247uint32_t nand_get_chip_type(uint32_t bank) 282uint32_t nand_get_chip_type(uint32_t bank)
248{ 283{
284 mutex_lock(&nand_mtx);
249 uint32_t result; 285 uint32_t result;
250 if (nand_reset(bank) != 0) return 0xFFFFFFFF; 286 if (nand_reset(bank) != 0) return nand_unlock(0xFFFFFFFF);
251 if (nand_send_cmd(0x90) != 0) return 0xFFFFFFFF; 287 if (nand_send_cmd(0x90) != 0) return nand_unlock(0xFFFFFFFF);
252 FMANUM = 0; 288 FMANUM = 0;
253 FMADDR0 = 0; 289 FMADDR0 = 0;
254 FMCTRL1 = FMCTRL1_DOTRANSADDR; 290 FMCTRL1 = FMCTRL1_DOTRANSADDR;
255 if (nand_wait_cmddone() != 0) return 0xFFFFFFFF; 291 if (nand_wait_cmddone() != 0) return nand_unlock(0xFFFFFFFF);
256 FMDNUM = 4; 292 FMDNUM = 4;
257 FMCTRL1 = FMCTRL1_DOREADDATA; 293 FMCTRL1 = FMCTRL1_DOREADDATA;
258 if (nand_wait_addrdone() != 0) return 0xFFFFFFFF; 294 if (nand_wait_addrdone() != 0) return nand_unlock(0xFFFFFFFF);
259 result = FMFIFO; 295 result = FMFIFO;
260 FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO; 296 FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
261 return result; 297 return nand_unlock(result);
262} 298}
263 299
264uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, 300uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
265 void* sparebuffer, uint32_t doecc, 301 void* sparebuffer, uint32_t doecc,
266 uint32_t checkempty) 302 uint32_t checkempty)
267{ 303{
304 mutex_lock(&nand_mtx);
268 uint32_t rc, eccresult; 305 uint32_t rc, eccresult;
269 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); 306 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
270 if (nand_send_cmd(NAND_CMD_READ) != 0) return 1; 307 if (nand_send_cmd(NAND_CMD_READ) != 0) return nand_unlock(1);
271 if (nand_send_address(page, (databuffer == 0) ? 0x800 : 0) != 0) 308 if (nand_send_address(page, (databuffer == 0) ? 0x800 : 0) != 0)
272 return 1; 309 return nand_unlock(1);
273 if (nand_send_cmd(NAND_CMD_READ2) != 0) return 1; 310 if (nand_send_cmd(NAND_CMD_READ2) != 0) return nand_unlock(1);
274 if (nand_wait_status_ready(bank) != 0) return 1; 311 if (nand_wait_status_ready(bank) != 0) return nand_unlock(1);
275 if (databuffer != 0) 312 if (databuffer != 0)
276 if (nand_transfer_data(bank, 0, nand_uncached_data, 0x800) != 0) 313 if (nand_transfer_data(bank, 0, nand_uncached_data, 0x800) != 0)
277 return 1; 314 return nand_unlock(1);
278 if (doecc == 0) 315 if (doecc == 0)
279 { 316 {
280 memcpy(databuffer, nand_uncached_data, 0x800); 317 memcpy(databuffer, nand_uncached_data, 0x800);
281 if (sparebuffer != 0) 318 if (sparebuffer != 0)
282 { 319 {
283 if (nand_transfer_data(bank, 0, nand_uncached_spare, 0x40) != 0) 320 if (nand_transfer_data(bank, 0, nand_uncached_spare, 0x40) != 0)
284 return 1; 321 return nand_unlock(1);
285 memcpy(sparebuffer, nand_uncached_spare, 0x800); 322 memcpy(sparebuffer, nand_uncached_spare, 0x800);
286 if (checkempty != 0) 323 if (checkempty != 0)
287 return nand_check_empty((uint8_t*)sparebuffer) << 1; 324 return nand_check_empty((uint8_t*)sparebuffer) << 1;
288 } 325 }
289 return 0; 326 return nand_unlock(0);
290 } 327 }
291 rc = 0; 328 rc = 0;
292 if (nand_transfer_data(bank, 0, nand_uncached_spare, 0x40) != 0) 329 if (nand_transfer_data(bank, 0, nand_uncached_spare, 0x40) != 0)
293 return 1; 330 return nand_unlock(1);
294 memcpy(nand_uncached_ecc, &nand_uncached_spare[0xC], 0x28); 331 memcpy(nand_uncached_ecc, &nand_uncached_spare[0xC], 0x28);
295 rc |= (ecc_decode(3, nand_uncached_data, nand_uncached_ecc) & 0xF) << 4; 332 rc |= (ecc_decode(3, nand_uncached_data, nand_uncached_ecc) & 0xF) << 4;
296 if (databuffer != 0) memcpy(databuffer, nand_uncached_data, 0x800); 333 if (databuffer != 0) memcpy(databuffer, nand_uncached_data, 0x800);
@@ -307,51 +344,54 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
307 } 344 }
308 if (checkempty != 0) rc |= nand_check_empty(nand_uncached_spare) << 1; 345 if (checkempty != 0) rc |= nand_check_empty(nand_uncached_spare) << 1;
309 346
310 return rc; 347 return nand_unlock(rc);
311} 348}
312 349
313uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, 350uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
314 void* sparebuffer, uint32_t doecc) 351 void* sparebuffer, uint32_t doecc)
315{ 352{
353 mutex_lock(&nand_mtx);
316 if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40); 354 if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40);
317 else memset(nand_uncached_spare, 0xFF, 0x40); 355 else memset(nand_uncached_spare, 0xFF, 0x40);
318 if (doecc != 0) 356 if (doecc != 0)
319 { 357 {
320 memcpy(nand_uncached_data, databuffer, 0x800); 358 memcpy(nand_uncached_data, databuffer, 0x800);
321 if (ecc_encode(3, nand_uncached_data, nand_uncached_ecc) != 0) 359 if (ecc_encode(3, nand_uncached_data, nand_uncached_ecc) != 0)
322 return 1; 360 return nand_unlock(1);
323 memcpy(&nand_uncached_spare[0xC], nand_uncached_ecc, 0x28); 361 memcpy(&nand_uncached_spare[0xC], nand_uncached_ecc, 0x28);
324 memset(nand_uncached_ctrl, 0xFF, 0x200); 362 memset(nand_uncached_ctrl, 0xFF, 0x200);
325 memcpy(nand_uncached_ctrl, nand_uncached_spare, 0xC); 363 memcpy(nand_uncached_ctrl, nand_uncached_spare, 0xC);
326 if (ecc_encode(0, nand_uncached_ctrl, nand_uncached_ecc) != 0) 364 if (ecc_encode(0, nand_uncached_ctrl, nand_uncached_ecc) != 0)
327 return 1; 365 return nand_unlock(1);
328 memcpy(&nand_uncached_spare[0x34], nand_uncached_ecc, 0xC); 366 memcpy(&nand_uncached_spare[0x34], nand_uncached_ecc, 0xC);
329 } 367 }
330 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); 368 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
331 if (nand_send_cmd(NAND_CMD_PROGRAM) != 0) 369 if (nand_send_cmd(NAND_CMD_PROGRAM) != 0)
332 return 1; 370 return nand_unlock(1);
333 if (nand_send_address(page, (databuffer == 0) ? 0x800 : 0) != 0) 371 if (nand_send_address(page, (databuffer == 0) ? 0x800 : 0) != 0)
334 return 1; 372 return nand_unlock(1);
335 if (databuffer != 0) 373 if (databuffer != 0)
336 if (nand_transfer_data(bank, 1, nand_uncached_data, 0x800) != 0) 374 if (nand_transfer_data(bank, 1, nand_uncached_data, 0x800) != 0)
337 return 1; 375 return nand_unlock(1);
338 if (sparebuffer != 0 || doecc != 0) 376 if (sparebuffer != 0 || doecc != 0)
339 if (nand_transfer_data(bank, 1, nand_uncached_spare, 0x40) != 0) 377 if (nand_transfer_data(bank, 1, nand_uncached_spare, 0x40) != 0)
340 return 1; 378 return nand_unlock(1);
341 if (nand_send_cmd(NAND_CMD_PROGCNFRM) != 0) return 1; 379 if (nand_send_cmd(NAND_CMD_PROGCNFRM) != 0) return nand_unlock(1);
342 return nand_wait_status_ready(bank); 380 return nand_wait_status_ready(bank);
343} 381}
344 382
345uint32_t nand_block_erase(uint32_t bank, uint32_t page) 383uint32_t nand_block_erase(uint32_t bank, uint32_t page)
346{ 384{
385 mutex_lock(&nand_mtx);
347 nand_set_fmctrl0(bank, 0); 386 nand_set_fmctrl0(bank, 0);
348 if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return 1; 387 if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return nand_unlock(1);
349 FMANUM = 2; 388 FMANUM = 2;
350 FMADDR0 = page; 389 FMADDR0 = page;
351 FMCTRL1 = FMCTRL1_DOTRANSADDR; 390 FMCTRL1 = FMCTRL1_DOTRANSADDR;
352 if (nand_wait_cmddone() != 0) return 1; 391 if (nand_wait_cmddone() != 0) return nand_unlock(1);
353 if (nand_send_cmd(NAND_CMD_ERASECNFRM) != 0) return 1; 392 if (nand_send_cmd(NAND_CMD_ERASECNFRM) != 0) return nand_unlock(1);
354 return nand_wait_status_ready(bank); 393 if (nand_wait_status_ready(bank) != 0) return nand_unlock(1);
394 return nand_unlock(0);
355} 395}
356 396
357const struct nand_device_info_type* nand_get_device_type(uint32_t bank) 397const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
@@ -363,6 +403,11 @@ const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
363 403
364uint32_t nand_device_init(void) 404uint32_t nand_device_init(void)
365{ 405{
406 mutex_init(&nand_mtx);
407 wakeup_init(&nand_wakeup);
408 mutex_init(&ecc_mtx);
409 wakeup_init(&ecc_wakeup);
410
366 uint32_t type; 411 uint32_t type;
367 uint32_t i, j; 412 uint32_t i, j;
368 PCON2 = 0x33333333; 413 PCON2 = 0x33333333;