summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLadislav Michl <ladis@linux-mips.org>2017-06-20 09:44:29 (GMT)
committerTom Rini <trini@konsulko.com>2017-06-23 14:38:07 (GMT)
commitb51ced8e2aec9cc4f5a600b09d09f1b54be19d04 (patch)
tree3ca19d062a35f74b744d521543e3a56e6ad0161e /drivers
parent0da008ef8d0441d582619c279212e65f9f0bd2fa (diff)
downloadu-boot-b51ced8e2aec9cc4f5a600b09d09f1b54be19d04.tar.xz
onenand_spl_simple: Add DDP OneNAND support
Current implementation is unable to access second half of DDP OneNAND flash (reads first half mirrored). Use block and bufferram address calculations from onenand_base to fix this. Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/onenand/onenand_spl.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/mtd/onenand/onenand_spl.c b/drivers/mtd/onenand/onenand_spl.c
index 6fad34a..0b78067 100644
--- a/drivers/mtd/onenand/onenand_spl.c
+++ b/drivers/mtd/onenand/onenand_spl.c
@@ -23,11 +23,29 @@ enum onenand_spl_pagesize {
PAGE_4K = 4096,
};
+static unsigned int density_mask;
+
#define ONENAND_PAGES_PER_BLOCK 64
-#define onenand_block_address(block) (block)
#define onenand_sector_address(page) (page << 2)
#define onenand_buffer_address() ((1 << 3) << 8)
-#define onenand_bufferram_address(block) (0)
+
+static inline int onenand_block_address(int block)
+{
+ /* Device Flash Core select, NAND Flash Block Address */
+ if (block & density_mask)
+ return ONENAND_DDP_CHIP1 | (block ^ density_mask);
+
+ return block;
+}
+
+static inline int onenand_bufferram_address(int block)
+{
+ /* Device BufferRAM Select */
+ if (block & density_mask)
+ return ONENAND_DDP_CHIP1;
+
+ return ONENAND_DDP_CHIP0;
+}
static inline uint16_t onenand_readw(uint32_t addr)
{
@@ -41,7 +59,7 @@ static inline void onenand_writew(uint16_t value, uint32_t addr)
static enum onenand_spl_pagesize onenand_spl_get_geometry(void)
{
- uint32_t dev_id, density;
+ unsigned int dev_id, density, size;
if (!onenand_readw(ONENAND_REG_TECHNOLOGY)) {
dev_id = onenand_readw(ONENAND_REG_DEVICE_ID);
@@ -51,8 +69,11 @@ static enum onenand_spl_pagesize onenand_spl_get_geometry(void)
if (density < ONENAND_DEVICE_DENSITY_4Gb)
return PAGE_2K;
- if (dev_id & ONENAND_DEVICE_IS_DDP)
+ if (dev_id & ONENAND_DEVICE_IS_DDP) {
+ size = onenand_readw(ONENAND_REG_DATA_BUFFER_SIZE);
+ density_mask = 1 << (18 + density - ffs(size));
return PAGE_2K;
+ }
}
return PAGE_4K;