U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
June 2009
- 211 participants
- 509 discussions

[U-Boot] There is no need to pay thousands for a good medical marketing list
by Dianna ritual 30 Jun '09
by Dianna ritual 30 Jun '09
30 Jun '09
Here are some of the USA contact databases we have for sale:
Physicians
Chiropractors
Alternative Medicine
Dentists
Veterinarians
Hospitals
Nursing Homes
Pharmaceutical Companies
Physical Therapists
Acupuncturists
Massage Therapists
Medical Equipment Suppliers
Mental Health Counselors
Visiting Nurses & RN's
Optometrists
Psychologists
Each list has many different fields including phone, fax, postal address, email and much more. I can give you any 3 of the above for $299. Email me at Quentin(a)medexecdata.com.
To stop future email correspondence please send a blank email to rembox(a)medexecdata.com
1
0

30 Jun '09
This patch includes the onenand driver for SMDKC100 Board.
Signed-off-by: HeungJun, Kim <riverful.kim(a)samsung.com>
---
drivers/mtd/onenand/Makefile | 8 +-
drivers/mtd/onenand/s5p_onenand.c | 2034 +++++++++++++++++++++++++++++++++++++
include/linux/mtd/onenand_regs.h | 5 +
include/linux/mtd/s5p_onenand.h | 425 ++++++++
4 files changed, 2471 insertions(+), 1 deletions(-)
create mode 100644 drivers/mtd/onenand/s5p_onenand.c
create mode 100644 include/linux/mtd/s5p_onenand.h
diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile
index 1d35a57..aad1362 100644
--- a/drivers/mtd/onenand/Makefile
+++ b/drivers/mtd/onenand/Makefile
@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libonenand.a
-COBJS-$(CONFIG_CMD_ONENAND) := onenand_uboot.o onenand_base.o onenand_bbt.o
+COBJS-$(CONFIG_CMD_ONENAND) := onenand_uboot.o
+
+ifdef CONFIG_S5PC1XX
+COBJS-$(CONFIG_CMD_ONENAND) += s5p_onenand.o
+else
+COBJS-$(CONFIG_CMD_ONENAND) += onenand_base.o onenand_bbt.o
+endif
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mtd/onenand/s5p_onenand.c
b/drivers/mtd/onenand/s5p_onenand.c
new file mode 100644
index 0000000..79d9f85
--- /dev/null
+++ b/drivers/mtd/onenand/s5p_onenand.c
@@ -0,0 +1,2034 @@
+/*
+ * Copyright (C) 2005-2009 Samsung Electronics
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/s5p_onenand.h>
+#include <linux/mtd/bbm.h>
+
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#include <rtc.h>
+
+#undef DEBUG_ONENAND
+#ifdef DEBUG_ONENAND
+#define dbg(x...) printk(x)
+#else
+#define dbg(x...) do { } while (0)
+#endif
+
+#define CONFIG_MTD_ONENAND_VERIFY_WRITE
+/**
+ * onenand_oob_64 - oob info for large (2KB) page
+ */
+static struct nand_ecclayout onenand_oob_64 = {
+ .eccbytes = 20,
+ .eccpos = {
+ 8, 9, 10, 11, 12,
+ 24, 25, 26, 27, 28,
+ 40, 41, 42, 43, 44,
+ 56, 57, 58, 59, 60,
+ },
+
+ /* For holding Yaffs2 tag */
+ .oobfree = {
+ {2, 6}, {13, 3}, {18, 6}, {29, 3},
+ {34, 6}, {45, 3}, {50, 6}, {61, 3}}
+#if 0
+ /* original */
+ .oobfree = {
+ {2, 6}, {14, 2}, {18, 6}, {30, 2},
+ {34, 6}, {46, 2}, {50, 6}}
+#endif
+};
+
+/**
+ * onenand_oob_32 - oob info for middle (1KB) page
+ */
+static struct nand_ecclayout onenand_oob_32 = {
+ .eccbytes = 10,
+ .eccpos = {
+ 8, 9, 10, 11, 12,
+ 24, 25, 26, 27, 28,
+ },
+ .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} }
+};
+
+static const unsigned char ffchars[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */
+};
+
+static unsigned int onenand_readl(void __iomem *addr)
+{
+ return readl(addr);
+}
+
+static void onenand_writel(unsigned int value, void __iomem *addr)
+{
+ writel(value, addr);
+}
+
+static void onenand_irq_wait(struct onenand_chip *chip, int stat)
+{
+ while (!chip->read(chip->base + ONENAND_REG_INT_ERR_STAT) & stat);
+}
+
+static void onenand_irq_ack(struct onenand_chip *chip, int stat)
+{
+ chip->write(stat, chip->base + ONENAND_REG_INT_ERR_ACK);
+}
+
+static int onenand_irq_pend(struct onenand_chip *chip, int stat)
+{
+ return (chip->read(chip->base + ONENAND_REG_INT_ERR_STAT) & stat);
+}
+
+static void onenand_irq_wait_ack(struct onenand_chip *chip, int stat)
+{
+ onenand_irq_wait(chip, stat);
+ onenand_irq_ack(chip, stat);
+}
+
+
+static int onenand_blkrw_complete(struct onenand_chip *chip, int cmd)
+{
+ int cmp_bit = 0, fail_bit = 0, ret = 0;
+
+ if (cmd == ONENAND_CMD_READ) {
+ cmp_bit = ONENAND_INT_ERR_LOAD_CMP;
+ fail_bit = ONENAND_INT_ERR_LD_FAIL_ECC_ERR;
+ } else if (cmd == ONENAND_CMD_PROG) {
+ cmp_bit = ONENAND_INT_ERR_PGM_CMP;
+ fail_bit = ONENAND_INT_ERR_PGM_FAIL;
+ } else {
+ ret = 1;
+ }
+
+ onenand_irq_wait_ack(chip, ONENAND_INT_ERR_INT_ACT);
+ onenand_irq_wait_ack(chip, ONENAND_INT_ERR_BLK_RW_CMP);
+ onenand_irq_wait_ack(chip, cmp_bit);
+
+ if (onenand_irq_pend(chip, fail_bit)) {
+ onenand_irq_ack(chip, fail_bit);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/**
+ * onenand_read_burst
+ *
+ * 16 Burst read: performance is improved up to 40%.
+ */
+static void onenand_read_burst(void *dest, const void *src, size_t len)
+{
+ int count;
+
+ if (len % 16 != 0)
+ return;
+
+ count = len / 16;
+
+ __asm__ __volatile__(
+ " stmdb r13!, {r0-r3,r9-r12}\n"
+ " mov r2, %0\n"
+ "1:\n"
+ " ldmia r1, {r9-r12}\n"
+ " stmia r0!, {r9-r12}\n"
+ " subs r2, r2, #0x1\n"
+ " bne 1b\n"
+ " ldmia r13!, {r0-r3,r9-r12}\n"::"r" (count));
+}
+
+/**
+ * onenand_command_map - [DEFAULT] Get command type
+ * @param cmd command
+ * @return command type (00, 01, 10, 11)
+ *
+ */
+
+static int onenand_command_map(int cmd)
+{
+ int type = ONENAND_CMD_MAP_FF;
+
+ switch (cmd) {
+ case ONENAND_CMD_READ:
+ case ONENAND_CMD_PROG:
+ type = ONENAND_CMD_MAP_01;
+ break;
+
+ case ONENAND_CMD_UNLOCK:
+ case ONENAND_CMD_LOCK:
+ case ONENAND_CMD_LOCK_TIGHT:
+ case ONENAND_CMD_UNLOCK_ALL:
+ case ONENAND_CMD_ERASE:
+ case ONENAND_CMD_OTP_ACCESS:
+ case ONENAND_CMD_PIPELINE_READ:
+ case ONENAND_CMD_PIPELINE_WRITE:
+ case ONENAND_CMD_READOOB:
+ case ONENAND_CMD_PROGOOB:
+ type = ONENAND_CMD_MAP_10;
+ break;
+
+ case ONENAND_CMD_RESET:
+ case ONENAND_CMD_READID:
+ type = ONENAND_CMD_MAP_11;
+ break;
+ default:
+ type = ONENAND_CMD_MAP_FF;
+ break;
+ }
+
+ return type;
+}
+
+/**
+ * onenand_addr_field - [DEFAULT] Generate address field
+ * @param dev_id device id
+ * @param fba block number
+ * @param fpa page number
+ * @param fsa sector number
+ * @return address field
+ *
+ * Refer to Table 7-1 MEM_ADDR Fields in S3C6400/10 User's Manual
+ */
+#if defined(CONFIG_S3C6400)
+static u_int onenand_addr_field(int dev_id, int fba, int fpa, int fsa)
+{
+ u_int mem_addr = 0;
+ int ddp, density;
+
+ ddp = dev_id & ONENAND_DEVICE_IS_DDP;
+ density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+
+ switch (density & 0xf) {
+ case ONENAND_DEVICE_DENSITY_128Mb:
+ mem_addr = (((fba & ONENAND_FBA_MASK_128Mb) << ONENAND_FBA_SHIFT_128Mb) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_128Mb) | \
+ (fsa << ONENAND_FSA_SHIFT));
+ break;
+
+ case ONENAND_DEVICE_DENSITY_256Mb:
+ mem_addr = (((fba & ONENAND_FBA_MASK_256Mb) << ONENAND_FBA_SHIFT_256Mb) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_256Mb) | \
+ (fsa << ONENAND_FSA_SHIFT));
+ break;
+
+ case ONENAND_DEVICE_DENSITY_512Mb:
+ mem_addr = (((fba & ONENAND_FBA_MASK_512Mb) << ONENAND_FBA_SHIFT_512Mb) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_512Mb) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ break;
+
+ case ONENAND_DEVICE_DENSITY_1Gb:
+ if (ddp) {
+ mem_addr = ((ddp << ONENAND_DDP_SHIFT_1Gb) | \
+ ((fba & ONENAND_FBA_MASK_1Gb_DDP) << ONENAND_FBA_SHIFT_1Gb_DDP) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_1Gb_DDP) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ } else {
+ mem_addr = (((fba & ONENAND_FBA_MASK_1Gb) << ONENAND_FBA_SHIFT_1Gb) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_1Gb) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ }
+
+ break;
+
+ case ONENAND_DEVICE_DENSITY_2Gb:
+ if (ddp) {
+ mem_addr = ((ddp << ONENAND_DDP_SHIFT_2Gb) | \
+ ((fba & ONENAND_FBA_MASK_2Gb_DDP) << ONENAND_FBA_SHIFT_2Gb_DDP) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_2Gb_DDP) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ } else {
+ mem_addr = (((fba & ONENAND_FBA_MASK_2Gb) << ONENAND_FBA_SHIFT_2Gb) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_2Gb) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ }
+
+ break;
+
+ case ONENAND_DEVICE_DENSITY_4Gb:
+ if (ddp) {
+ mem_addr = ((ddp << ONENAND_DDP_SHIFT_4Gb) | \
+ ((fba & ONENAND_FBA_MASK_4Gb_DDP) << ONENAND_FBA_SHIFT_4Gb_DDP) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_4Gb_DDP) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ } else {
+ mem_addr = (((fba & ONENAND_FBA_MASK_4Gb) << ONENAND_FBA_SHIFT_4Gb) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT_4Gb) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ }
+
+ break;
+ }
+
+ return mem_addr;
+}
+#else
+static u_int onenand_addr_field(int dev_id, int fba, int fpa, int fsa)
+{
+ u_int mem_addr = 0;
+ int ddp, density;
+
+ ddp = !!(dev_id & ONENAND_DEVICE_IS_DDP);
+ density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+
+ switch (density & 0xf) {
+ case ONENAND_DEVICE_DENSITY_128Mb:
+ mem_addr = (((fba & ONENAND_FBA_MASK_128Mb) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ (fsa << ONENAND_FSA_SHIFT));
+ break;
+
+ case ONENAND_DEVICE_DENSITY_256Mb:
+ mem_addr = (((fba & ONENAND_FBA_MASK_256Mb) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ (fsa << ONENAND_FSA_SHIFT));
+ break;
+
+ case ONENAND_DEVICE_DENSITY_512Mb:
+ mem_addr = (((fba & ONENAND_FBA_MASK_512Mb) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ break;
+
+ case ONENAND_DEVICE_DENSITY_1Gb:
+ if (ddp) {
+ mem_addr = ((ddp << ONENAND_DDP_SHIFT_1Gb) | \
+ ((fba & ONENAND_FBA_MASK_1Gb_DDP) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ } else {
+ mem_addr = (((fba & ONENAND_FBA_MASK_1Gb) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ }
+
+ break;
+
+ case ONENAND_DEVICE_DENSITY_2Gb:
+ if (ddp) {
+ mem_addr = ((ddp << ONENAND_DDP_SHIFT_2Gb) | \
+ ((fba & ONENAND_FBA_MASK_2Gb_DDP) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ } else {
+ mem_addr = (((fba & ONENAND_FBA_MASK_2Gb) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ }
+
+ break;
+
+ case ONENAND_DEVICE_DENSITY_4Gb:
+ if (ddp) {
+ mem_addr = (fba << ONENAND_FBA_SHIFT) |
+ (fpa << ONENAND_FPA_SHIFT) |
+ (fsa << ONENAND_FSA_SHIFT);
+
+ } else {
+ mem_addr = (((fba & ONENAND_FBA_MASK_4Gb) << ONENAND_FBA_SHIFT) | \
+ ((fpa & ONENAND_FPA_MASK) << ONENAND_FPA_SHIFT) | \
+ ((fsa & ONENAND_FSA_MASK) << ONENAND_FSA_SHIFT));
+ }
+
+ break;
+ }
+
+ return mem_addr;
+}
+#endif
+
+/**
+ * onenand_command_address - [DEFAULT] Generate command address
+ * @param mtd MTD device structure
+ * @param cmd_type command type
+ * @param fba block number
+ * @param fpa page number
+ * @param fsa sector number
+ * @param onenand_addr onenand device address to access directly
(command 00/11)
+ * @return command address
+ *
+ * Refer to 'Command Mapping' in S3C6400 User's Manual
+ */
+static uint onenand_command_address(struct mtd_info *mtd, int
cmd_type, int fba, int fpa, int fsa, int onenand_addr)
+{
+ struct onenand_chip *chip = mtd->priv;
+ uint cmd_addr = (ONENAND_AHB_ADDR | (cmd_type << ONENAND_CMD_SHIFT));
+ int dev_id;
+
+ dev_id = chip->read(chip->base + ONENAND_REG_DEVICE_ID);
+
+ switch (cmd_type) {
+ case ONENAND_CMD_MAP_00:
+ cmd_addr |= ((onenand_addr & 0xffff) << 1);
+ break;
+
+ case ONENAND_CMD_MAP_01:
+ case ONENAND_CMD_MAP_10:
+ cmd_addr |= (onenand_addr_field(dev_id, fba, fpa, fsa) &
ONENAND_MEM_ADDR_MASK);
+ break;
+
+ case ONENAND_CMD_MAP_11:
+ cmd_addr |= ((onenand_addr & 0xffff) << 2);
+ break;
+
+ default:
+ cmd_addr = 0;
+ break;
+ }
+
+ return cmd_addr;
+}
+
+/**
+ * onenand_command - [DEFAULT] Generate command address
+ * @param mtd MTD device structure
+ * @param cmd command
+ * @param addr onenand device address
+ * @return command address
+ *
+ */
+static uint onenand_command(struct mtd_info *mtd, int cmd, loff_t addr)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int sectors = 4, onenand_addr = -1;
+ int cmd_type, fba = 0, fpa = 0, fsa = 0, page;
+ uint cmd_addr;
+
+ cmd_type = onenand_command_map(cmd);
+
+ switch (cmd) {
+ case ONENAND_CMD_UNLOCK:
+ case ONENAND_CMD_UNLOCK_ALL:
+ case ONENAND_CMD_LOCK:
+ case ONENAND_CMD_LOCK_TIGHT:
+ case ONENAND_CMD_ERASE:
+ fba = (int) (addr >> chip->erase_shift);
+ page = -1;
+ break;
+
+ default:
+ fba = (int) (addr >> chip->erase_shift);
+ page = (int) (addr >> chip->page_shift);
+ page &= chip->page_mask;
+ fpa = page & ONENAND_FPA_MASK;
+ fsa = sectors & ONENAND_FSA_MASK;
+ break;
+ }
+
+ cmd_addr = onenand_command_address(mtd, cmd_type, fba, fpa, fsa,
onenand_addr);
+
+ if (!cmd_addr) {
+ printk("Command address mapping failed\n");
+ return -1;
+ }
+
+ return cmd_addr;
+}
+
+static int onenand_get_device(struct mtd_info *mtd, int new_state)
+{
+ return 0;
+}
+
+/**
+ * onenand_release_device - [GENERIC] release chip
+ * @param mtd MTD device structure
+ *
+ * Deselect, release chip lock and wake up anyone waiting on the device
+ */
+static void onenand_release_device(struct mtd_info *mtd)
+{
+ return;
+}
+
+/**
+ * onenand_block_checkbad - [GENERIC] Check if a block is marked bad
+ * @param mtd MTD device structure
+ * @param ofs offset from device start
+ *
+ * Check, if the block is bad. Either by reading the bad block table or
+ * calling of the scan function.
+ */
+static int onenand_block_checkbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct onenand_chip *chip = mtd->priv;
+ void __iomem *cmd_addr;
+ u_int *buf_poi;
+ int i, isbad = 0;
+
+ buf_poi = (u_int *)malloc(mtd->writesize);
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_READING);
+
+ /* on the TRANSFER SPARE bit */
+ chip->write(ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ /* get start address to read data */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READ, ofs);
+
+ switch (chip->options & ONENAND_READ_MASK) {
+ case ONENAND_READ_BURST:
+ onenand_read_burst(buf_poi, cmd_addr, mtd->writesize);
+ onenand_read_burst(buf_poi, cmd_addr, mtd->oobsize);
+ break;
+
+ case ONENAND_READ_POLLING:
+ /* read main data and throw into garbage box */
+ for (i = 0; i < (mtd->writesize / 4); i++)
+ *buf_poi = chip->read(cmd_addr);
+
+ /* read spare data */
+ for (i = 0; i < (mtd->oobsize / 4); i++)
+ *buf_poi++ = chip->read(cmd_addr);
+
+ buf_poi -= (mtd->oobsize / 4);
+
+ break;
+ }
+
+ onenand_blkrw_complete(chip, ONENAND_CMD_READ);
+
+ /* off the TRANSFER SPARE bit */
+ chip->write(~ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ buf_poi[0] &= 0xffff;
+
+ if (!buf_poi[0])
+ isbad = 1;
+
+ free(buf_poi);
+
+ return isbad;
+}
+
+/**
+ * onenand_block_isbad - [MTD Interface] Check whether the block at
the given offset is bad
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ *
+ * Check whether the block is bad
+ */
+static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ return onenand_block_checkbad(mtd, ofs);
+}
+
+/**
+ * onenand_set_pipeline - [MTD Interface] Set pipeline ahead
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param len number of bytes to read
+ *
+ */
+static int onenand_set_pipeline(struct mtd_info *mtd, loff_t from, size_t len)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int page_cnt = (int) (len >> chip->page_shift);
+ void __iomem *cmd_addr;
+
+ if (len % mtd->writesize > 0)
+ page_cnt++;
+
+ if (page_cnt > 1) {
+ cmd_addr = (void __iomem *)chip->command(mtd,
ONENAND_CMD_PIPELINE_READ, from);
+ chip->write(ONENAND_DATAIN_PIPELINE_READ | page_cnt, cmd_addr);
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_read - [MTD Interface] Read data from flash
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param len number of bytes to read
+ * @param retlen pointer to variable to store the number of read bytes
+ * @param buf the databuffer to put data
+ *
+ */
+int onenand_read(struct mtd_info *mtd, loff_t from, u_int32_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct onenand_chip *chip = mtd->priv;
+ struct mtd_ecc_stats stats;
+ int i, ret = 0, read = 0, thislen;
+ u_int *buf_poi = (u_int *)buf;
+ void __iomem *cmd_addr;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len =
%i\n", (unsigned int) from, (int) len);
+
+ /* Do not allow reads past end of device */
+ if ((from + len) > mtd->size) {
+ MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end
of device.\n");
+ *retlen = 0;
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_READING);
+
+ /* TODO handling oob */
+ stats = mtd->ecc_stats;
+
+ while (!ret) {
+ if (chip->options & ONENAND_CHECK_BAD) {
+ if (onenand_block_isbad(mtd, from)) {
+ printk (KERN_WARNING "\nonenand_read: skipped to read from a bad
block at addr 0x%08x.\n", (unsigned int) from);
+ from += (1 << chip->erase_shift);
+ continue;
+ }
+ }
+
+ /* pipeline ahread read is only applied for reading from page 0 of
any block in u-boot */
+ if ((chip->options & ONENAND_PIPELINE_AHEAD) && ((from & 0x1ffff) == 0))
+ onenand_set_pipeline(mtd, from, mtd->erasesize);
+
+ /* get start address to read data */
+ cmd_addr = (void __iomem *)(chip->command(mtd, ONENAND_CMD_READ, from));
+
+ switch (chip->options & ONENAND_READ_MASK) {
+ case ONENAND_READ_BURST:
+ onenand_read_burst(buf, cmd_addr, mtd->writesize);
+ break;
+
+ case ONENAND_READ_POLLING:
+ for (i = 0; i < (mtd->writesize / 4); i++)
+ *buf_poi++ = chip->read(cmd_addr);
+
+ buf_poi -= (mtd->writesize / 4);
+ break;
+
+ default:
+ printk("onenand_read: read mode undefined.\n");
+ return -1;
+ }
+#if 0 // fixme: bug??
+ if (onenand_blkrw_complete(chip, ONENAND_CMD_READ)) {
+ printk(KERN_WARNING "onenand_read: Read operation failed.\n");
+ return -1;
+ }
+#endif
+ thislen = min_t(int, mtd->writesize, len - read);
+
+ read += thislen;
+
+ if (read == len)
+ break;
+
+ buf += thislen;
+ from += mtd->writesize;
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ /*
+ * Return success, if no ECC failures, else -EBADMSG
+ * fs driver will take care of that, because
+ * retlen == desired len and result == -EBADMSG
+ */
+ *retlen = read;
+
+ if (mtd->ecc_stats.failed - stats.failed)
+ return -EBADMSG;
+
+ if (ret)
+ return ret;
+
+ return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+}
+
+/**
+ * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd MTD device structure
+ * @param buf destination address
+ * @param column oob offset to read from
+ * @param thislen oob length to read
+ */
+static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t
*buf, int column,
+ int thislen)
+{
+ struct onenand_chip *chip = mtd->priv;
+ struct nand_oobfree *free;
+ int readcol = column;
+ int readend = column + thislen;
+ int lastgap = 0;
+ uint8_t *oob_buf = chip->oob_buf;
+
+ for (free = chip->ecclayout->oobfree; free->length; ++free) {
+ if (readcol >= lastgap)
+ readcol += free->offset - lastgap;
+ if (readend >= lastgap)
+ readend += free->offset - lastgap;
+ lastgap = free->offset + free->length;
+ }
+
+ for (free = chip->ecclayout->oobfree; free->length; ++free) {
+ int free_end = free->offset + free->length;
+ if (free->offset < readend && free_end > readcol) {
+ int st = max_t(int,free->offset,readcol);
+ int ed = min_t(int,free_end,readend);
+ int n = ed - st;
+ memcpy(buf, oob_buf + st, n);
+ buf += n;
+ } else
+ break;
+ }
+ return 0;
+}
+
+/**
+ * onenand_read_oob_nolock - [MTD Interface] OneNAND read out-of-band
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param len number of bytes to read
+ * @param retlen pointer to variable to store the number of read bytes
+ * @param buf the databuffer to put data
+ * @param mode operation mode
+ *
+ * OneNAND read out-of-band data from the spare area
+ */
+static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
size_t len,
+ size_t *retlen, u_char *buf, mtd_oob_mode_t mode)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int read = 0, thislen, column, oobsize;
+ int i, ret = 0;
+ int currentTransferMode;
+ void __iomem *cmd_addr;
+ u_int *buf_poi;
+ u_char * tmp_buf;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len =
%i\n", (unsigned int) from, (int) len);
+
+ /* Initialize return length value */
+ *retlen = 0;
+
+ if (mode == MTD_OOB_AUTO)
+ oobsize = chip->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ column = from & (mtd->oobsize - 1);
+
+ if (unlikely(column >= oobsize)) {
+ printk(KERN_ERR "onenand_read_oob: Attempted to start read outside oob\n");
+ return -EINVAL;
+ }
+
+ /* Do not allow reads past end of device */
+ if (unlikely(from >= mtd->size ||
+ column + len > ((mtd->size >> chip->page_shift) -
+ (from >> chip->page_shift)) * oobsize)) {
+ printk(KERN_ERR "onenand_read_oob: Attempted to read beyond end of
device\n");
+ return -EINVAL;
+ }
+
+#if defined(CONFIG_CPU_S5PC100)
+ /* setting for read oob area only */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READOOB, from);
+ chip->write(ONENAND_DATAIN_ACCESS_SPARE, cmd_addr);
+#endif /* CONFIG_CPU_S5PC100 */
+
+ while (read < len) {
+ if (chip->options & ONENAND_CHECK_BAD) {
+ if (onenand_block_checkbad(mtd, from)) {
+ printk (KERN_WARNING "\nonenand_do_read_oob: skipped to read oob
from a bad block at addr 0x%08x.\n", (unsigned int) from);
+ from += (1 << chip->erase_shift);
+
+ if (column != 0)
+ column = from & (mtd->oobsize - 1);
+
+ continue;
+ }
+ }
+
+ /* on the TRANSFER SPARE bit */
+ chip->write(ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ /* get start address to read data */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READ, from);
+
+ thislen = oobsize - column;
+ thislen = min_t(int, thislen, len);
+
+ if (mode == MTD_OOB_AUTO)
+ buf_poi = (u_int *)chip->oob_buf;
+ else
+ buf_poi = (u_int *)buf;
+
+ switch (chip->options & ONENAND_READ_MASK) {
+ case ONENAND_READ_BURST:
+#if !defined(CONFIG_CPU_S5PC100)
+ tmp_buf=malloc(mtd->writesize);
+ memset(tmp_buf, 0xff, mtd->writesize);
+ onenand_read_burst(tmp_buf, cmd_addr, mtd->writesize);
+ free(tmp_buf);
+#endif /* CONFIG_CPU_S5PC100 */
+ onenand_read_burst(buf_poi, cmd_addr, mtd->oobsize);
+ break;
+
+ case ONENAND_READ_POLLING:
+ /* read main data and throw into garbage box */
+ for (i = 0; i < (mtd->writesize / 4); i++)
+ *buf_poi = chip->read(cmd_addr);
+
+ /* read spare data */
+ for (i = 0; i < (mtd->oobsize / 4); i++)
+ *buf_poi++ = chip->read(cmd_addr);
+
+ break;
+ }
+
+ if (onenand_blkrw_complete(chip, ONENAND_CMD_PROG)) {
+ printk(KERN_WARNING "\nonenand_write: Program operation failed.\n");
+ return -1;
+ }
+
+ if (mode == MTD_OOB_AUTO)
+ onenand_transfer_auto_oob(mtd, buf, column, thislen);
+
+ read += thislen;
+
+ if (read == len)
+ break;
+
+ buf += thislen;
+
+ /* Read more? */
+ if (read < len) {
+ /* Page size */
+ from += mtd->writesize;
+ column = 0;
+ }
+
+ }
+
+#if defined(CONFIG_CPU_S5PC100)
+ /* setting for read oob area only */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READOOB, from);
+ chip->write(ONENAND_DATAIN_ACCESS_MAIN, cmd_addr);
+#endif /* CONFIG_CPU_S5PC100 */
+
+ /* off the TRANSFER SPARE bit */
+ chip->write(~ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ *retlen = read;
+ return ret;
+}
+
+/**
+ * onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operation description structure
+ */
+static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ int ret;
+
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ break;
+ case MTD_OOB_RAW:
+ /* Not implemented yet */
+ default:
+ return -EINVAL;
+ }
+
+ onenand_get_device(mtd, FL_READING);
+ if (ops->datbuf) {
+ ret = onenand_read(mtd, from, ops->len,
+ &ops->retlen, ops->datbuf);
+ } else {
+ ret = onenand_read_oob_nolock(mtd, from, ops->ooblen,
+ &ops->oobretlen, ops->oobbuf, ops->mode);
+ }
+ onenand_release_device(mtd);
+
+ return ret;
+
+}
+
+#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
+/**
+ * onenand_verify_page - [GENERIC] verify the chip contents after a write
+ * @param mtd MTD device structure
+ * @param buf the databuffer to verify
+ * @param addr address to read
+ * @return 0, if ok
+ */
+static int onenand_verify_page(struct mtd_info *mtd, const uint *buf,
loff_t addr)
+{
+ struct onenand_chip *chip = mtd->priv;
+ void __iomem *cmd_addr;
+ int i, ret = 0;
+ uint *written = (uint *)malloc(mtd->writesize);
+
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READ, addr);
+
+ /* write all data of 1 page by 4 bytes at a time */
+ for (i = 0; i < (mtd->writesize / 4); i++) {
+ *written = chip->read(cmd_addr);
+ written++;
+ }
+
+ written -= (mtd->writesize / 4);
+
+ /* Check, if data is same */
+ if (memcmp(written, buf, mtd->writesize))
+ ret = -EBADMSG;
+
+ free(written);
+
+ return ret;
+}
+
+/**
+ * onenand_verify_oob - [GENERIC] verify the oob contents after a write
+ * @param mtd MTD device structure
+ * @param buf the databuffer to verify
+ * @param to offset to read from
+ *
+ */
+static int onenand_verify_oob(struct mtd_info *mtd, const u_char
*buf, loff_t to, size_t len)
+{
+ struct onenand_chip *chip = mtd->priv;
+ char oobbuf[64];
+ u_int *buf_poi, *dbuf_poi;
+ int read = 0, thislen, column, oobsize, i;
+ void __iomem *cmd_addr;
+ mtd_oob_mode_t mode = MTD_OOB_AUTO;
+
+ if (mode == MTD_OOB_AUTO)
+ oobsize = chip->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ column = to & (mtd->oobsize - 1);
+ dbuf_poi = (u_int *)chip->page_buf;
+
+ /* setting for read oob area only */
+
+ while (read < len) {
+ /* get start address to read data */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READ, to);
+
+ thislen = oobsize - column;
+ thislen = min_t(int, thislen, len);
+
+ if (mode == MTD_OOB_AUTO)
+ buf_poi = (u_int *)chip->oob_buf;
+ else
+ buf_poi = (u_int *)buf;
+
+// onenand_read_burst(dbuf_poi, cmd_addr, mtd->writesize);
+ onenand_read_burst(buf, cmd_addr, mtd->oobsize);
+
+ if (onenand_blkrw_complete(chip, ONENAND_CMD_READ)) {
+ printk(KERN_WARNING "onenand_verify_oob: Read operation
failed:0x%x\n", (unsigned int)to);
+ }
+
+ if (mode == MTD_OOB_AUTO)
+ onenand_transfer_auto_oob(mtd, (uint8_t *) oobbuf, column, thislen);
+
+ read += thislen;
+
+ if (read == len)
+ break;
+ }
+
+ for (i = 0; i < len; i++)
+ if (buf[i] != oobbuf[i])
+ return -EBADMSG;
+
+ return 0;
+}
+
+
+/**
+ * onenand_verify_ops - [GENERIC] verify the oob contents after a write
+ * @param mtd MTD device structure
+ * @param ops oob operation description structure
+ * @param to offset to read from
+ * @param len number of bytes to read
+ *
+ */
+static int onenand_verify_ops(struct mtd_info *mtd, struct
mtd_oob_ops *ops, loff_t to, size_t len)
+{
+ struct onenand_chip *chip = mtd->priv;
+ char oobbuf[64];
+ u_int *buf_poi, *dbuf_poi;
+ int read = 0, thislen, column, oobsize, i;
+ void __iomem *cmd_addr;
+ int ret = 0;
+
+ if (ops->mode == MTD_OOB_AUTO)
+ oobsize = chip->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ column = to & (mtd->oobsize - 1);
+
+ while (read < len) {
+ /* get start address to read data */
+ //cmd_addr = onenand_phys_to_virt(chip->command(mtd, ONENAND_CMD_READ, to));
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READ, to);
+
+ thislen = oobsize - column;
+ thislen = min_t(int, thislen, len);
+
+ dbuf_poi = (u_int *)chip->page_buf;
+
+ if (ops->mode == MTD_OOB_AUTO)
+ buf_poi = (u_int *)chip->oob_buf;
+ else
+ buf_poi = (u_int *)oobbuf;
+
+ onenand_read_burst(dbuf_poi, cmd_addr, mtd->writesize);
+ onenand_read_burst(buf_poi, cmd_addr, mtd->oobsize);
+
+ if (onenand_blkrw_complete(chip, ONENAND_CMD_READ)) {
+ printk(KERN_WARNING "onenand_verify_oob: Read operation
failed:0x%x\n", (unsigned int)to);
+ return -EBADMSG;
+ }
+
+ if (ops->mode == MTD_OOB_AUTO)
+ onenand_transfer_auto_oob(mtd, (uint8_t *) oobbuf, column, thislen);
+
+ read += thislen;
+
+ if (read == len)
+ break;
+
+ }
+
+ /* Check, if data is same */
+ if (memcmp(chip->page_buf, ops->datbuf, mtd->writesize)) {
+ printk("Invalid data buffer : 0x%x\n", (unsigned int)to);
+ ret = -EBADMSG;
+ }
+
+ for (i = 0; i < len; i++)
+ if (ops->oobbuf[i] != oobbuf[i]) {
+ printk("Invalid OOB buffer :0x%x\n", (unsigned int)to);
+ ret = -EBADMSG;
+ }
+
+ return ret;
+}
+#else
+#define onenand_verify_page(...) (0)
+#define onenand_verify_oob(...) (0)
+#define onenand_verify_ops(...) (0)
+#endif
+
+#define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
+
+/**
+ * onenand_write - [MTD Interface] write buffer to FLASH
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param len number of bytes to write
+ * @param retlen pointer to variable to store the number of written bytes
+ * @param buf the data to write
+ *
+ */
+int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int written = 0;
+ int i, ret = 0;
+ void __iomem *cmd_addr;
+ uint *buf_poi = (uint *)buf;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n",
(unsigned int) to, (int) len);
+
+ /* Initialize retlen, in case of early exit */
+ *retlen = 0;
+
+ /* Do not allow writes past end of device */
+ if (unlikely((to + len) > mtd->size)) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_write: Attempt write to past
end of device\n");
+ return -EINVAL;
+ }
+
+#if 0 /* disabled for jffs2 writing by jsgood */
+ /* Reject writes, which are not page aligned */
+ if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_write: Attempt
to write not page aligned data\n");
+ return -EINVAL;
+ }
+#endif
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_WRITING);
+
+ /* Loop until all data write */
+ while (written < len) {
+ if (chip->options & ONENAND_CHECK_BAD) {
+ if (onenand_block_checkbad(mtd, to)) {
+ printk (KERN_WARNING "\nonenand_write: skipped to write to a bad
block at addr 0x%08x.\n", (unsigned int) to);
+ to += (1 << chip->erase_shift);
+ continue;
+ }
+ }
+
+ /* get address to write data */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_PROG, to);
+
+ /* write all data of 1 page by 4 bytes at a time */
+ for (i = 0; i < (mtd->writesize / 4); i++) {
+ chip->write(*buf_poi, cmd_addr);
+ buf_poi++;
+ }
+
+ if (onenand_blkrw_complete(chip, ONENAND_CMD_PROG)) {
+ printk(KERN_WARNING "\nonenand_write: Program operation failed.\n");
+ return -1;
+ }
+
+ /* Only check verify write turn on */
+ ret = onenand_verify_page(mtd, buf_poi - (mtd->writesize / 4), to);
+ if (ret) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_write: verify failed.\n");
+ break;
+ }
+
+ written += mtd->writesize;
+
+ if (written == len)
+ break;
+
+ to += mtd->writesize;
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ *retlen = written;
+
+ return ret;
+}
+
+/**
+ * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd MTD device structure
+ * @param oob_buf oob buffer
+ * @param buf source address
+ * @param column oob offset to write to
+ * @param thislen oob length to write
+ */
+static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
+ const u_char *buf, int column, int thislen)
+{
+ struct onenand_chip *chip = mtd->priv;
+ struct nand_oobfree *free;
+ int writecol = column;
+ int writeend = column + thislen;
+ int lastgap = 0;
+
+ for (free = chip->ecclayout->oobfree; free->length; ++free) {
+ if (writecol >= lastgap)
+ writecol += free->offset - lastgap;
+ if (writeend >= lastgap)
+ writeend += free->offset - lastgap;
+ lastgap = free->offset + free->length;
+ }
+ for (free = chip->ecclayout->oobfree; free->length; ++free) {
+ int free_end = free->offset + free->length;
+ if (free->offset < writeend && free_end > writecol) {
+ int st = max_t(int,free->offset,writecol);
+ int ed = min_t(int,free_end,writeend);
+ int n = ed - st;
+ memcpy(oob_buf + st, buf, n);
+ buf += n;
+ } else
+ break;
+ }
+ return 0;
+}
+
+/**
+ * onenand_write_ops - [OneNAND Interface] write main and/or out-of-band
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param ops oob operation description structure
+ *
+ * Write main and oob with ECC
+ */
+static int onenand_write_ops(struct mtd_info *mtd, loff_t to, struct
mtd_oob_ops *ops)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int i, column, ret = 0, oobsize;
+ int written = 0;
+
+ int len = ops->ooblen;
+ u_char *buf = ops->datbuf;
+ u_char *sparebuf = ops->oobbuf;
+ u_char *oobbuf;
+
+ void __iomem *cmd_addr;
+ u_int *buf_poi;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops: to = 0x%08x, len =
%i\n", (unsigned int) to, (int) len);
+
+ /* Initialize retlen, in case of early exit */
+ ops->retlen = 0;
+ ops->oobretlen = 0;
+
+ if (ops->mode == MTD_OOB_AUTO)
+ oobsize = chip->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ column = to & (mtd->oobsize - 1);
+
+ if (unlikely(column >= oobsize)) {
+ printk(KERN_ERR "onenand_write_ops: Attempted to start write outside oob\n");
+ return -EINVAL;
+ }
+
+ /* For compatibility with NAND: Do not allow write past end of page */
+ if (unlikely(column + len > oobsize)) {
+ printk(KERN_ERR "onenand_write_ops: "
+ "Attempt to write past end of page\n");
+ return -EINVAL;
+ }
+
+ /* Do not allow reads past end of device */
+ if (unlikely(to >= mtd->size ||
+ column + len > ((mtd->size >> chip->page_shift) -
+ (to >> chip->page_shift)) * oobsize)) {
+ printk(KERN_ERR "onenand_write_ops: Attempted to write past end of
device\n");
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_WRITING);
+
+ oobbuf = chip->oob_buf;
+ buf_poi = (u_int *)buf;
+
+ /* on the TRANSFER SPARE bit */
+ chip->write(ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ /* Loop until all data write */
+ while (written < len) {
+ int thislen = min_t(int, oobsize, len - written);
+
+ if (chip->options & ONENAND_CHECK_BAD) {
+ if (onenand_block_isbad(mtd, to)) {
+ printk (KERN_WARNING "onenand_write_ops: skipped to write oob to
a bad block at addr 0x%08x.\n", (unsigned int) to);
+ to += (1 << chip->erase_shift);
+
+ if (column != 0)
+ column = to & (mtd->oobsize - 1);
+
+ continue;
+ }
+ }
+
+ /* get start address to write data */
+ //cmd_addr = onenand_phys_to_virt(chip->command(mtd, ONENAND_CMD_PROG, to));
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_PROG, to);
+
+ /* write all data of 1 page by 4 bytes at a time */
+ for (i = 0; i < (mtd->writesize / 4); i++) {
+ chip->write(*buf_poi, cmd_addr);
+ buf_poi++;
+ }
+
+ /* We send data to spare ram with oobsize
+ * to prevent byte access */
+ memset(oobbuf, 0xff, mtd->oobsize);
+
+ if (ops->mode == MTD_OOB_AUTO)
+ onenand_fill_auto_oob(mtd, oobbuf, sparebuf, column, thislen);
+ else
+ memcpy(oobbuf + column, buf, thislen);
+
+ buf_poi = (u_int *)chip->oob_buf;
+ for (i = 0; i < (mtd->oobsize / 4); i++) {
+ chip->write(*buf_poi, cmd_addr);
+ buf_poi++;
+ }
+
+ if (onenand_blkrw_complete(chip, ONENAND_CMD_PROG)) {
+ printk(KERN_WARNING "onenand_write_ops: Program operation failed.\n");
+ chip->write(~ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+ return -1;
+ }
+
+
+#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
+ ret = onenand_verify_ops(mtd, ops, to, len);
+
+ if (ret) {
+ printk(KERN_ERR "onenand_write_ops: verify failed :0x%x\n",
(unsigned int)to);
+ break;
+ }
+#endif
+ written += thislen;
+
+ if (written == len)
+ break;
+
+ to += mtd->writesize;
+ buf += thislen;
+ column = 0;
+ }
+
+ /* off the TRANSFER SPARE bit */
+ chip->write(~ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ ops->retlen = mtd->writesize;
+ ops->oobretlen = written;
+
+ return ret;
+}
+
+/**
+ * onenand_do_write_oob - [Internal] OneNAND write out-of-band
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param len number of bytes to write
+ * @param retlen pointer to variable to store the number of written bytes
+ * @param buf the data to write
+ * @param mode operation mode
+ *
+ * OneNAND write out-of-band
+ */
+static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf, mtd_oob_mode_t mode)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int i, column, ret = 0, oobsize;
+ int written = 0;
+ u_char *oobbuf, *orgbuf;
+ void __iomem *cmd_addr;
+ u_int *buf_poi;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_do_write_oob: to = 0x%08x, len =
%i\n", (unsigned int) to, (int) len);
+
+ /* Initialize retlen, in case of early exit */
+ *retlen = 0;
+
+ if (mode == MTD_OOB_AUTO)
+ oobsize = chip->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ column = to & (mtd->oobsize - 1);
+
+ if (unlikely(column >= oobsize)) {
+ printk(KERN_ERR "onenand_do_write_oob: Attempted to start write
outside oob\n");
+ return -EINVAL;
+ }
+
+ /* For compatibility with NAND: Do not allow write past end of page */
+ if (unlikely(column + len > oobsize)) {
+ printk(KERN_ERR "onenand_do_write_oob: "
+ "Attempt to write past end of page\n");
+ return -EINVAL;
+ }
+
+ /* Do not allow reads past end of device */
+ if (unlikely(to >= mtd->size ||
+ column + len > ((mtd->size >> chip->page_shift) -
+ (to >> chip->page_shift)) * oobsize)) {
+ printk(KERN_ERR "onenand_do_write_oob: Attempted to write past end
of device\n");
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_WRITING);
+
+ orgbuf = (u_char *) buf;
+ oobbuf = chip->oob_buf;
+ buf_poi = (u_int *) chip->oob_buf;
+
+#if defined(CONFIG_CPU_S5PC100)
+ /* setting for read oob area only */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READOOB, to);
+ chip->write(ONENAND_DATAIN_ACCESS_SPARE, cmd_addr);
+#endif /* CONFIG_CPU_S5PC100 */
+
+ /* Loop until all data write */
+ while (written < len) {
+ int thislen = min_t(int, oobsize, len - written);
+
+ if (chip->options & ONENAND_CHECK_BAD) {
+ if (onenand_block_checkbad(mtd, to)) {
+ printk (KERN_WARNING "\nonenand_do_write_oob: skipped to write
oob to a bad block at addr 0x%08x.\n", (unsigned int) to);
+ to += (1 << chip->erase_shift);
+
+ if (column != 0)
+ column = to & (mtd->oobsize - 1);
+
+ continue;
+ }
+ }
+
+ /* on the TRANSFER SPARE bit */
+ chip->write(ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_PROG, to);
+
+ /* We send data to spare ram with oobsize
+ * to prevent byte access */
+ memset(oobbuf, 0xff, mtd->oobsize);
+
+ if (mode == MTD_OOB_AUTO)
+ onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
+ else
+ memcpy(oobbuf + column, buf, thislen);
+
+ for (i = 0; i < (mtd->writesize / 4); i++)
+ chip->write(0xffffffff, cmd_addr);
+
+ for (i = 0; i < (mtd->oobsize / 4); i++) {
+ chip->write(*buf_poi, cmd_addr);
+ buf_poi++;
+ }
+
+ if (onenand_blkrw_complete(chip, ONENAND_CMD_PROG)) {
+ printk(KERN_WARNING "\nonenand_do_write_oob: Program operation failed.\n");
+ return -1;
+ }
+
+// ret = onenand_verify_oob(mtd, orgbuf, to, len);
+// if (ret) {
+// printk(KERN_ERR "onenand_do_write_oob: verify failed %d\n", ret);
+// break;
+// }
+
+ written += thislen;
+ if (written == len)
+ break;
+
+ to += mtd->writesize;
+ buf += thislen;
+ column = 0;
+
+ }
+
+#if defined(CONFIG_CPU_S5PC100)
+ /* setting for read oob area only */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READOOB, to);
+ chip->write(ONENAND_DATAIN_ACCESS_MAIN, cmd_addr);
+#endif /* CONFIG_CPU_S5PC100 */
+
+ /* off the TRANSFER SPARE bit */
+ chip->write(~ONENAND_TRANS_SPARE_TSRF_INC, chip->base +
ONENAND_REG_TRANS_SPARE);
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ *retlen = written;
+
+ return ret;
+}
+
+/**
+ * onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @param mtd: MTD device structure
+ * @param to: offset to write
+ * @param ops: oob operation description structure
+ */
+static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ int ret;
+ struct onenand_chip *chip = mtd->priv;
+
+ if (chip->options & ONENAND_CHECK_BAD) {
+ if (onenand_block_checkbad(mtd, to)) {
+ printk (KERN_WARNING "\nonenand_write_oob: failed to write oob to
a bad block at addr 0x%08x.\n", (unsigned int) to);
+ return -1;
+ }
+ }
+
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ break;
+ case MTD_OOB_RAW:
+ /* Not implemented yet */
+ default:
+ return -EINVAL;
+ }
+#if 0
+ /* For YAFFS2 */
+ if (ops->datbuf != NULL)
+ ret = onenand_write_ops(mtd, to, ops);
+ else
+#endif
+ ret = onenand_do_write_oob(mtd, to, ops->ooblen,
+ &ops->oobretlen, ops->oobbuf, ops->mode);
+ return ret;
+}
+
+/**
+ * onenand_erase - [MTD Interface] erase block(s)
+ * @param mtd MTD device structure
+ * @param instr erase instruction
+ *
+ * Erase one ore more blocks
+ */
+int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct onenand_chip *chip = mtd->priv;
+ unsigned int block_size;
+ loff_t addr;
+ int len, ret = 0;
+ void __iomem *cmd_addr = 0;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len =
%i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
+
+ block_size = (1 << chip->erase_shift);
+
+ /* Start address must align on block boundary */
+ if (unlikely(instr->addr & (block_size - 1))) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_erase: Unaligned address\n");
+ return -EINVAL;
+ }
+
+ /* Length must align on block boundary */
+ if (unlikely(instr->len & (block_size - 1))) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_erase: Length not block aligned\n");
+ return -EINVAL;
+ }
+
+ /* Do not allow erase past end of device */
+ if (unlikely((instr->len + instr->addr) > mtd->size)) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_erase: Erase past end of device\n");
+ return -EINVAL;
+ }
+
+ instr->fail_addr = 0xffffffff;
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_ERASING);
+
+ /* Loop throught the pages */
+ len = instr->len;
+ addr = instr->addr;
+
+ instr->state = MTD_ERASING;
+
+ while (len) {
+ if (chip->options & ONENAND_CHECK_BAD) {
+ if (onenand_block_checkbad(mtd, addr)) {
+ printk (KERN_WARNING "\nonenand_erase: skipped to erase a bad
block at addr 0x%08x.\n", (unsigned int) addr);
+ len -= block_size;
+ addr += block_size;
+ continue;
+ }
+ }
+
+ /* get address to erase */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_ERASE, addr);
+
+ chip->write(ONENAND_DATAIN_ERASE_SINGLE, cmd_addr); /* single block erase */
+
+ /* wait irq */
+ onenand_irq_wait_ack(chip, ONENAND_INT_ERR_INT_ACT);
+ onenand_irq_wait_ack(chip, ONENAND_INT_ERR_ERS_CMP);
+
+ chip->write(ONENAND_DATAIN_ERASE_VERIFY, cmd_addr);
+
+ /* wait irq */
+ onenand_irq_wait_ack(chip, ONENAND_INT_ERR_INT_ACT);
+ onenand_irq_wait_ack(chip, ONENAND_INT_ERR_ERS_CMP);
+
+ /* check fail */
+ if (onenand_irq_pend(chip, ONENAND_INT_ERR_ERS_FAIL)) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_erase: block %d erase verify
failed.\n", addr >> chip->erase_shift);
+ onenand_irq_ack(chip, ONENAND_INT_ERR_ERS_FAIL);
+
+ /* check lock */
+ if (onenand_irq_pend(chip, ONENAND_INT_ERR_LOCKED_BLK)) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "\nonenand_erase: block %d is
locked.\n", addr >> chip->erase_shift);
+ onenand_irq_ack(chip, ONENAND_INT_ERR_LOCKED_BLK);
+ }
+ }
+
+ len -= block_size;
+ addr += block_size;
+ }
+
+ instr->state = MTD_ERASE_DONE;
+
+ ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
+ /* Do call back function */
+ if (!ret)
+ mtd_erase_callback(instr);
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * onenand_sync - [MTD Interface] sync
+ * @param mtd MTD device structure
+ *
+ * Sync is actually a wait for chip ready function
+ */
+static void onenand_sync(struct mtd_info *mtd)
+{
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_SYNCING);
+
+ /* Release it and go back */
+ onenand_release_device(mtd);
+}
+
+/**
+ * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s)
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ * @param len number of bytes to lock or unlock
+ *
+ * Lock or unlock one or more blocks
+ */
+static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs,
size_t len, int cmd)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int start, end, ofs_end, block_size;
+ int datain1, datain2;
+ void __iomem *cmd_addr;
+
+ start = ofs >> chip->erase_shift;
+ end = len >> chip->erase_shift;
+ block_size = 1 << chip->erase_shift;
+ ofs_end = ofs + len - block_size;
+
+ if (cmd == ONENAND_CMD_LOCK) {
+ datain1 = ONENAND_DATAIN_LOCK_START;
+ datain2 = ONENAND_DATAIN_LOCK_END;
+ } else {
+ datain1 = ONENAND_DATAIN_UNLOCK_START;
+ datain2 = ONENAND_DATAIN_UNLOCK_END;
+ }
+
+ if (ofs < ofs_end) {
+ cmd_addr = (void __iomem *)chip->command(mtd, cmd, ofs);
+ chip->write(datain1, cmd_addr);
+ }
+
+ cmd_addr = (void __iomem *)chip->command(mtd, cmd, ofs_end);
+ chip->write(datain2, cmd_addr);
+
+ if (cmd == ONENAND_CMD_LOCK) {
+ if (!chip->read(chip->base + ONENAND_REG_INT_ERR_STAT) &
ONENAND_INT_ERR_LOCKED_BLK) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_do_lock_cmd: lock failed.\n");
+ return -1;
+ }
+ } else {
+ if (chip->read(chip->base + ONENAND_REG_INT_ERR_STAT) &
ONENAND_INT_ERR_LOCKED_BLK) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_do_lock_cmd: unlock failed.\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ * onenand_lock - [MTD Interface] Lock block(s)
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ * @param len number of bytes to lock
+ *
+ * Lock one or more blocks
+ */
+int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
+}
+
+
+/**
+ * onenand_unlock - [MTD Interface] Unlock block(s)
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ * @param len number of bytes to unlock
+ *
+ * Unlock one or more blocks
+ */
+int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
+}
+
+/**
+ * onenand_check_lock_status - [OneNAND Interface] Check lock status
+ * @param chip onenand chip data structure
+ *
+ * Check lock status
+ */
+static void onenand_check_lock_status(struct mtd_info *mtd)
+{
+ struct onenand_chip *chip = mtd->priv;
+ unsigned int block, end;
+ void __iomem *cmd_addr;
+ int tmp;
+
+ end = chip->chipsize >> chip->erase_shift;
+
+ for (block = 0; block < end; block++) {
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_READ,
block << chip->erase_shift);
+ tmp = chip->read(cmd_addr);
+
+ if (chip->read(chip->base + ONENAND_REG_INT_ERR_STAT) &
ONENAND_INT_ERR_LOCKED_BLK) {
+ printk(KERN_ERR "block %d is write-protected!\n", block);
+ chip->write(ONENAND_INT_ERR_LOCKED_BLK, chip->base +
ONENAND_REG_INT_ERR_ACK);
+ }
+ }
+}
+
+/**
+ * onenand_unlock_all - [OneNAND Interface] unlock all blocks
+ * @param mtd MTD device structure
+ *
+ * Unlock all blocks
+ */
+static int onenand_unlock_all(struct mtd_info *mtd)
+{
+ struct onenand_chip *chip = mtd->priv;
+ void __iomem *cmd_addr;
+
+ if (chip->options & ONENAND_HAS_UNLOCK_ALL) {
+ /* write unlock command */
+ cmd_addr = (void __iomem *)chip->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0);
+
+ chip->write(ONENAND_DATAIN_UNLOCK_ALL, cmd_addr);
+
+ /* Workaround for all block unlock in DDP */
+ if (chip->device_id & ONENAND_DEVICE_IS_DDP) {
+ loff_t ofs;
+ size_t len;
+
+ /* all blocks on another chip */
+ ofs = chip->chipsize >> 1;
+ len = chip->chipsize >> 1;
+
+ onenand_unlock(mtd, ofs, len);
+ }
+
+ onenand_check_lock_status(mtd);
+
+ return 0;
+ }
+
+ onenand_unlock(mtd, 0x0, chip->chipsize);
+
+ return 0;
+}
+
+/**
+ * onenand_lock_scheme - Check and set OneNAND lock scheme
+ * @param mtd MTD data structure
+ *
+ * Check and set OneNAND lock scheme
+ */
+static void onenand_lock_scheme(struct mtd_info *mtd)
+{
+ struct onenand_chip *chip = mtd->priv;
+ unsigned int density, process;
+
+ /* Lock scheme depends on density and process */
+ density = chip->device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+ process = chip->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
+
+ /* Lock scheme */
+ if (density >= ONENAND_DEVICE_DENSITY_1Gb) {
+ /* A-Die has all block unlock */
+ if (process) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "Chip support all block unlock\n");
+ chip->options |= ONENAND_HAS_UNLOCK_ALL;
+ }
+ } else {
+ /* Some OneNAND has continues lock scheme */
+ if (!process) {
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "Lock scheme is Continues Lock\n");
+ chip->options |= ONENAND_HAS_CONT_LOCK;
+ }
+ }
+}
+
+/**
+ * onenand_print_device_info - Print device ID
+ * @param device device ID
+ *
+ * Print device ID
+ */
+void onenand_print_device_info(int device, int version)
+{
+ int vcc, demuxed, ddp, density;
+
+ vcc = device & ONENAND_DEVICE_VCC_MASK;
+ demuxed = device & ONENAND_DEVICE_IS_DEMUX;
+ ddp = device & ONENAND_DEVICE_IS_DDP;
+ density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
+ printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
+ demuxed ? "" : "Muxed ",
+ ddp ? "(DDP)" : "",
+ (16 << density),
+ vcc ? "2.65/3.3" : "1.8",
+ device);
+ printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version);
+}
+
+static const struct onenand_manufacturers onenand_manuf_ids[] = {
+ {ONENAND_MFR_SAMSUNG, "Samsung"},
+};
+
+/**
+ * onenand_check_maf - Check manufacturer ID
+ * @param manuf manufacturer ID
+ *
+ * Check manufacturer ID
+ */
+static int onenand_check_maf(int manuf)
+{
+ int size = ARRAY_SIZE(onenand_manuf_ids);
+ char *name;
+ int i;
+
+ for (i = 0; i < size; i++)
+ if (manuf == onenand_manuf_ids[i].id)
+ break;
+
+ if (i < size)
+ name = onenand_manuf_ids[i].name;
+ else
+ name = "Unknown";
+
+#if 0
+ printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);
+#endif
+
+ return (i == size);
+}
+
+/**
+ * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * @param mtd MTD device structure
+ *
+ * OneNAND detection method:
+ * Compare the the values from command with ones from register
+ */
+static int onenand_probe(struct mtd_info *mtd)
+{
+ struct onenand_chip *chip = mtd->priv;
+ int maf_id, dev_id, ver_id, density;
+
+ /* Read manufacturer and device IDs from Register */
+ maf_id = chip->read(chip->base + ONENAND_REG_MANUFACT_ID);
+ dev_id = chip->read(chip->base + ONENAND_REG_DEVICE_ID);
+ ver_id = chip->read(chip->base + ONENAND_REG_FLASH_VER_ID);
+
+ /* Check manufacturer ID */
+ if (onenand_check_maf(maf_id))
+ return -ENXIO;
+
+ chip->device_id = dev_id;
+ chip->version_id = ver_id;
+
+ density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+ chip->chipsize = (16 << density) << 20;
+ /* Set density mask. it is used for DDP */
+ chip->density_mask = (1 << (density + 6));
+
+ /* OneNAND page size & block size */
+ /* The data buffer size is equal to page size */
+ mtd->writesize = chip->read(chip->base + ONENAND_REG_DATA_BUF_SIZE);
+ mtd->oobsize = mtd->writesize >> 5;
+ /* Pagers per block is always 64 in OneNAND */
+ mtd->erasesize = mtd->writesize << 6;
+
+ chip->erase_shift = ffs(mtd->erasesize) - 1;
+ chip->page_shift = ffs(mtd->writesize) - 1;
+ chip->ppb_shift = (chip->erase_shift - chip->page_shift);
+ chip->page_mask = (mtd->erasesize / mtd->writesize) - 1;
+
+ /* REVIST: Multichip handling */
+
+ mtd->size = chip->chipsize;
+
+ /* Check OneNAND lock scheme */
+ onenand_lock_scheme(mtd);
+
+ return 0;
+}
+
+/**
+ * onenand_scan - [OneNAND Interface] Scan for the OneNAND device
+ * @param mtd MTD device structure
+ * @param maxchips Number of chips to scan for
+ *
+ * This fills out all the not initialized function pointers
+ * with the defaults.
+ * The flash ID is read and the mtd/chip structures are
+ * filled with the appropriate values.
+ */
+int onenand_scan(struct mtd_info *mtd, int maxchips)
+{
+ int i;
+ struct onenand_chip *chip = mtd->priv;
+
+ if (!chip->read)
+ chip->read = onenand_readl;
+ if (!chip->write)
+ chip->write = onenand_writel;
+ if (!chip->command)
+ chip->command = onenand_command;
+
+ chip->options |= (ONENAND_READ_BURST | ONENAND_CHECK_BAD |
ONENAND_PIPELINE_AHEAD);
+
+ if (onenand_probe(mtd))
+ return -ENXIO;
+
+ /* Allocate buffers, if necessary */
+ if (!chip->page_buf) {
+ size_t len;
+ len = mtd->writesize + mtd->oobsize;
+ chip->page_buf = kmalloc(len, GFP_KERNEL);
+ if (!chip->page_buf) {
+ printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
+ return -ENOMEM;
+ }
+ chip->options |= ONENAND_PAGEBUF_ALLOC;
+ }
+
+ if (!chip->oob_buf) {
+ chip->oob_buf = kmalloc(mtd->oobsize, GFP_KERNEL);
+ if (!chip->oob_buf) {
+ printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n");
+ return -ENOMEM;
+ }
+ chip->options |= ONENAND_OOBBUF_ALLOC;
+ }
+
+ /*
+ * Allow subpage writes up to oobsize.
+ */
+ switch (mtd->oobsize) {
+ case 64:
+ chip->ecclayout = &onenand_oob_64;
+ mtd->subpage_sft = 2;
+ break;
+
+ case 32:
+ chip->ecclayout = &onenand_oob_32;
+ mtd->subpage_sft = 1;
+ break;
+
+ default:
+ printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
+ mtd->oobsize);
+ mtd->subpage_sft = 0;
+ /* To prevent kernel oops */
+ chip->ecclayout = &onenand_oob_32;
+ break;
+ }
+
+ chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
+
+ /*
+ * The number of bytes available for a client to place data into
+ * the out of band area
+ */
+ chip->ecclayout->oobavail = 0;
+ for (i = 0; chip->ecclayout->oobfree[i].length; i++)
+ chip->ecclayout->oobavail +=
+ chip->ecclayout->oobfree[i].length;
+
+ mtd->oobavail = chip->ecclayout->oobavail;
+ mtd->ecclayout = chip->ecclayout;
+
+ /* Fill in remaining MTD driver data */
+ mtd->type = MTD_NANDFLASH;
+ mtd->flags = MTD_CAP_NANDFLASH;
+// mtd->ecctype = MTD_ECC_SW;
+ mtd->erase = onenand_erase;
+ mtd->point = NULL;
+ mtd->unpoint = NULL;
+ mtd->read = onenand_read;
+ mtd->write = onenand_write;
+ mtd->read_oob = onenand_read_oob;
+ mtd->write_oob = onenand_write_oob;
+ mtd->sync = onenand_sync;
+
+ if (chip->options & ONENAND_CHECK_BAD)
+ mtd->block_isbad = onenand_block_isbad;
+
+ /* Unlock whole block */
+ onenand_unlock_all(mtd);
+
+ return 0;
+ return chip->scan_bbt(mtd);
+}
+
+void onenand_release(struct mtd_info *mtd)
+{
+ struct onenand_chip *chip = mtd->priv;
+
+ /* Buffers allocated by onenand_scan */
+ if (chip->options & ONENAND_PAGEBUF_ALLOC)
+ kfree(chip->page_buf);
+ if (chip->options & ONENAND_OOBBUF_ALLOC)
+ kfree(chip->oob_buf);
+}
+
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index fc63380..ba298af 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -151,6 +151,10 @@
#define ONENAND_SYS_CFG1_INT (1 << 6)
#define ONENAND_SYS_CFG1_IOBE (1 << 5)
#define ONENAND_SYS_CFG1_RDY_CONF (1 << 4)
+#define ONENAND_SYS_CFG1_VHF (1 << 3)
+#define ONENAND_SYS_CFG1_HF (1 << 2)
+#define ONENAND_SYS_CFG1_WM (1 << 1)
+#define ONENAND_SYS_CFG1_BWPS (1 << 0)
/*
* Controller Status Register F240h (R)
@@ -186,5 +190,6 @@
#define ONENAND_ECC_1BIT (1 << 0)
#define ONENAND_ECC_2BIT (1 << 1)
#define ONENAND_ECC_2BIT_ALL (0xAAAA)
+#define ONENAND_ECC_4BIT_UNCORRECTABLE (0x1010)
#endif /* __ONENAND_REG_H */
diff --git a/include/linux/mtd/s5p_onenand.h b/include/linux/mtd/s5p_onenand.h
new file mode 100644
index 0000000..0a211c2
--- /dev/null
+++ b/include/linux/mtd/s5p_onenand.h
@@ -0,0 +1,425 @@
+#ifndef __LINUX_MTD_S3C_ONENAND_H
+#define __LINUX_MTD_S3C_ONENAND_H
+
+#include <linux/mtd/mtd.h>
+
+#define MAX_BUFFERRAM 2
+
+/* Scan and identify a OneNAND device */
+extern int onenand_scan(struct mtd_info *mtd, int max_chips);
+/* Free resources held by the OneNAND device */
+extern void onenand_release(struct mtd_info *mtd);
+
+/**
+ * struct onenand_bufferram - OneNAND BufferRAM Data
+ * @block: block address in BufferRAM
+ * @page: page address in BufferRAM
+ * @valid: valid flag
+ */
+struct onenand_bufferram {
+ int block;
+ int page;
+ int valid;
+};
+
+/**
+ * struct onenand_chip - OneNAND Private Flash Chip Data
+ * @base: [BOARDSPECIFIC] address to access OneNAND
+ * @chipsize: [INTERN] the size of one chip for multichip arrays
+ * @device_id: [INTERN] device ID
+ * @density_mask: chip density, used for DDP devices
+ * @verstion_id: [INTERN] version ID
+ * @options: [BOARDSPECIFIC] various chip options. They can
+ * partly be set to inform onenand_scan about
+ * @erase_shift: [INTERN] number of address bits in a block
+ * @page_shift: [INTERN] number of address bits in a page
+ * @ppb_shift: [INTERN] number of address bits in a pages per block
+ * @page_mask: [INTERN] a page per block mask
+ * @bufferram_index: [INTERN] BufferRAM index
+ * @bufferram: [INTERN] BufferRAM info
+ * @readw: [REPLACEABLE] hardware specific function for read short
+ * @writew: [REPLACEABLE] hardware specific function for write short
+ * @command: [REPLACEABLE] hardware specific function for writing
+ * commands to the chip
+ * @wait: [REPLACEABLE] hardware specific function for wait on ready
+ * @read_bufferram: [REPLACEABLE] hardware specific function for BufferRAM Area
+ * @write_bufferram: [REPLACEABLE] hardware specific function for
BufferRAM Area
+ * @read_word: [REPLACEABLE] hardware specific function for read
+ * register of OneNAND
+ * @write_word: [REPLACEABLE] hardware specific function for write
+ * register of OneNAND
+ * @mmcontrol: sync burst read function
+ * @block_markbad: function to mark a block as bad
+ * @scan_bbt: [REPLACEALBE] hardware specific function for scanning
+ * Bad block Table
+ * @chip_lock: [INTERN] spinlock used to protect access to this
+ * structure and the chip
+ * @wq: [INTERN] wait queue to sleep on if a OneNAND
+ * operation is in progress
+ * @state: [INTERN] the current state of the OneNAND device
+ * @page_buf: data buffer
+ * @subpagesize: [INTERN] holds the subpagesize
+ * @ecclayout: [REPLACEABLE] the default ecc placement scheme
+ * @bbm: [REPLACEABLE] pointer to Bad Block Management
+ * @priv: [OPTIONAL] pointer to private chip date
+ */
+struct onenand_chip {
+ void __iomem *base;
+ unsigned int chipsize;
+ unsigned int device_id;
+ unsigned int version_id;
+ unsigned int density_mask;
+ unsigned int options;
+
+ unsigned int erase_shift;
+ unsigned int page_shift;
+ unsigned int ppb_shift; /* Pages per block shift */
+ unsigned int page_mask;
+
+ uint (*command)(struct mtd_info *mtd, int cmd, loff_t address);
+ unsigned int (*read)(void __iomem *addr);
+ void (*write)(unsigned int value, void __iomem *addr);
+ int (*scan_bbt)(struct mtd_info *mtd);
+
+ unsigned char *page_buf;
+ unsigned char *oob_buf;
+
+ int subpagesize;
+ struct nand_ecclayout *ecclayout;
+
+ void *bbm;
+
+ void *priv;
+};
+
+/*
+ * Options bits
+ */
+#define ONENAND_HAS_CONT_LOCK (0x0001)
+#define ONENAND_HAS_UNLOCK_ALL (0x0002)
+#define ONENAND_CHECK_BAD (0x0004)
+#define ONENAND_READ_POLLING (0x0010)
+#define ONENAND_READ_BURST (0x0020)
+#define ONENAND_READ_MASK (0x00F0)
+#define ONENAND_PIPELINE_AHEAD (0x0100)
+#define ONENAND_PAGEBUF_ALLOC (0x1000)
+#define ONENAND_OOBBUF_ALLOC (0x2000)
+
+/*
+ * OneNAND Flash Manufacturer ID Codes
+ */
+#define ONENAND_MFR_SAMSUNG 0xec
+
+/**
+ * struct onenand_manufacturers - NAND Flash Manufacturer ID Structure
+ * @name: Manufacturer name
+ * @id: manufacturer ID code of device.
+*/
+struct onenand_manufacturers {
+ int id;
+ char *name;
+};
+
+#define ONENAND_REG_MEM_CFG (0x000)
+#define ONENAND_REG_BURST_LEN (0x010)
+#define ONENAND_REG_MEM_RESET (0x020)
+#define ONENAND_REG_INT_ERR_STAT (0x030)
+#define ONENAND_REG_INT_ERR_MASK (0x040)
+#define ONENAND_REG_INT_ERR_ACK (0x050)
+#define ONENAND_REG_ECC_ERR_STAT_1 (0x060)
+#define ONENAND_REG_MANUFACT_ID (0x070)
+#define ONENAND_REG_DEVICE_ID (0x080)
+#define ONENAND_REG_DATA_BUF_SIZE (0x090)
+#define ONENAND_REG_BOOT_BUF_SIZE (0x0A0)
+#define ONENAND_REG_BUF_AMOUNT (0x0B0)
+#define ONENAND_REG_TECH (0x0C0)
+#define ONENAND_REG_FBA_WIDTH (0x0D0)
+#define ONENAND_REG_FPA_WIDTH (0x0E0)
+#define ONENAND_REG_FSA_WIDTH (0x0F0)
+#define ONENAND_REG_REVISION (0x100)
+#define ONENAND_REG_SYNC_MODE (0x130)
+#define ONENAND_REG_TRANS_SPARE (0x140)
+#define ONENAND_REG_PAGE_CNT (0x170)
+#define ONENAND_REG_ERR_PAGE_ADDR (0x180)
+#define ONENAND_REG_BURST_RD_LAT (0x190)
+#define ONENAND_REG_INT_PIN_ENABLE (0x1A0)
+#define ONENAND_REG_INT_MON_CYC (0x1B0)
+#define ONENAND_REG_ACC_CLOCK (0x1C0)
+#define ONENAND_REG_ERR_BLK_ADDR (0x1E0)
+#define ONENAND_REG_FLASH_VER_ID (0x1F0)
+#define ONENAND_REG_BANK_EN (0x220)
+#define ONENAND_REG_WTCHDG_RST_L (0x260)
+#define ONENAND_REG_WTCHDG_RST_H (0x270)
+#define ONENAND_REG_SYNC_WRITE (0x280)
+#define ONENAND_REG_CACHE_READ (0x290)
+#define ONENAND_REG_COLD_RST_DLY (0x2A0)
+#define ONENAND_REG_DDP_DEVICE (0x2B0)
+#define ONENAND_REG_MULTI_PLANE (0x2C0)
+#define ONENAND_REG_MEM_CNT (0x2D0)
+#define ONENAND_REG_TRANS_MODE (0x2E0)
+#define ONENAND_REG_DEV_STAT (0x2F0)
+#define ONENAND_REG_ECC_ERR_STAT_2 (0x300)
+#define ONENAND_REG_ECC_ERR_STAT_3 (0x310)
+#define ONENAND_REG_ECC_ERR_STAT_4 (0x320)
+#define ONENAND_REG_EFCT_BUF_CNT (0x330)
+#define ONENAND_REG_DEV_PAGE_SIZE (0x340)
+#define ONENAND_REG_SUPERLOAD_EN (0x350)
+#define ONENAND_REG_CACHE_PRG_EN (0x360)
+#define ONENAND_REG_SINGLE_PAGE_BUF (0x370)
+#define ONENAND_REG_OFFSET_ADDR (0x380)
+#define ONENAND_REG_INT_MON_STATUS (0x390)
+
+#define ONENAND_MEM_CFG_SYNC_READ (1 << 15)
+#define ONENAND_MEM_CFG_BRL_7 (7 << 12)
+#define ONENAND_MEM_CFG_BRL_6 (6 << 12)
+#define ONENAND_MEM_CFG_BRL_5 (5 << 12)
+#define ONENAND_MEM_CFG_BRL_4 (4 << 12)
+#define ONENAND_MEM_CFG_BRL_3 (3 << 12)
+#define ONENAND_MEM_CFG_BRL_10 (2 << 12)
+#define ONENAND_MEM_CFG_BRL_9 (1 << 12)
+#define ONENAND_MEM_CFG_BRL_8 (0 << 12)
+#define ONENAND_MEM_CFG_BRL_SHIFT (12)
+#define ONENAND_MEM_CFG_BL_1K (5 << 9)
+#define ONENAND_MEM_CFG_BL_32 (4 << 9)
+#define ONENAND_MEM_CFG_BL_16 (3 << 9)
+#define ONENAND_MEM_CFG_BL_8 (2 << 9)
+#define ONENAND_MEM_CFG_BL_4 (1 << 9)
+#define ONENAND_MEM_CFG_BL_CONT (0 << 9)
+#define ONENAND_MEM_CFG_BL_SHIFT (9)
+#define ONENAND_MEM_CFG_NO_ECC (1 << 8)
+#define ONENAND_MEM_CFG_RDY_HIGH (1 << 7)
+#define ONENAND_MEM_CFG_INT_HIGH (1 << 6)
+#define ONENAND_MEM_CFG_IOBE (1 << 5)
+#define ONENAND_MEM_CFG_RDY_CONF (1 << 4)
+#define ONENAND_MEM_CFG_HF (1 << 2)
+#define ONENAND_MEM_CFG_WM_SYNC (1 << 1)
+#define ONENAND_MEM_CFG_BWPS_UNLOCK (1 << 0)
+
+#define ONENAND_BURST_LEN_CONT (0)
+#define ONENAND_BURST_LEN_4 (4)
+#define ONENAND_BURST_LEN_8 (8)
+#define ONENAND_BURST_LEN_16 (16)
+
+#define ONENAND_MEM_RESET_WARM (0x1)
+#define ONENAND_MEM_RESET_COLD (0x2)
+#define ONENAND_MEM_RESET_HOT (0x3)
+
+#define ONENAND_INT_ERR_CACHE_OP_ERR (1 << 13)
+#define ONENAND_INT_ERR_RST_CMP (1 << 12)
+#define ONENAND_INT_ERR_RDY_ACT (1 << 11)
+#define ONENAND_INT_ERR_INT_ACT (1 << 10)
+#define ONENAND_INT_ERR_UNSUP_CMD (1 << 9)
+#define ONENAND_INT_ERR_LOCKED_BLK (1 << 8)
+#define ONENAND_INT_ERR_BLK_RW_CMP (1 << 7)
+#define ONENAND_INT_ERR_ERS_CMP (1 << 6)
+#define ONENAND_INT_ERR_PGM_CMP (1 << 5)
+#define ONENAND_INT_ERR_LOAD_CMP (1 << 4)
+#define ONENAND_INT_ERR_ERS_FAIL (1 << 3)
+#define ONENAND_INT_ERR_PGM_FAIL (1 << 2)
+#define ONENAND_INT_ERR_INT_TO (1 << 1)
+#define ONENAND_INT_ERR_LD_FAIL_ECC_ERR (1 << 0)
+
+#define ONENAND_DEVICE_DENSITY_SHIFT (4)
+#define ONENAND_DEVICE_IS_DDP (1 << 3)
+#define ONENAND_DEVICE_IS_DEMUX (1 << 2)
+#define ONENAND_DEVICE_VCC_MASK (0x3)
+#define ONENAND_DEVICE_DENSITY_128Mb (0x000)
+#define ONENAND_DEVICE_DENSITY_256Mb (0x001)
+#define ONENAND_DEVICE_DENSITY_512Mb (0x002)
+#define ONENAND_DEVICE_DENSITY_1Gb (0x003)
+#define ONENAND_DEVICE_DENSITY_2Gb (0x004)
+#define ONENAND_DEVICE_DENSITY_4Gb (0x005)
+
+#define ONENAND_SYNC_MODE_RM_SYNC (1 << 1)
+#define ONENAND_SYNC_MODE_WM_SYNC (1 << 0)
+
+#define ONENAND_TRANS_SPARE_TSRF_INC (1 << 0)
+
+#define ONENAND_INT_PIN_ENABLE (1 << 0)
+
+#define ONENAND_ACC_CLOCK_266_133 (0x5)
+#define ONENAND_ACC_CLOCK_166_83 (0x3)
+#define ONENAND_ACC_CLOCK_134_67 (0x3)
+#define ONENAND_ACC_CLOCK_100_50 (0x2)
+#define ONENAND_ACC_CLOCK_60_30 (0x2)
+
+#define ONENAND_FLASH_AUX_WD_DISABLE (1 << 0)
+
+/*
+ * * Datain values for mapped commands
+ * */
+#define ONENAND_DATAIN_ERASE_STATUS (0x00)
+#define ONENAND_DATAIN_ERASE_MULTI (0x01)
+#define ONENAND_DATAIN_ERASE_SINGLE (0x03)
+#define ONENAND_DATAIN_ERASE_VERIFY (0x15)
+#define ONENAND_DATAIN_UNLOCK_START (0x08)
+#define ONENAND_DATAIN_UNLOCK_END (0x09)
+#define ONENAND_DATAIN_LOCK_START (0x0A)
+#define ONENAND_DATAIN_LOCK_END (0x0B)
+#define ONENAND_DATAIN_LOCKTIGHT_START (0x0C)
+#define ONENAND_DATAIN_LOCKTIGHT_END (0x0D)
+#define ONENAND_DATAIN_UNLOCK_ALL (0x0E)
+#define ONENAND_DATAIN_COPYBACK_SRC (0x1000)
+#define ONENAND_DATAIN_COPYBACK_DST (0x2000)
+#define ONENAND_DATAIN_ACCESS_OTP (0x12)
+#define ONENAND_DATAIN_ACCESS_MAIN (0x14)
+#define ONENAND_DATAIN_ACCESS_SPARE (0x13)
+#define ONENAND_DATAIN_ACCESS_MAIN_AND_SPARE (0x16)
+#define ONENAND_DATAIN_PIPELINE_READ (0x4000)
+#define ONENAND_DATAIN_PIPELINE_WRITE (0x4100)
+#define ONENAND_DATAIN_RMW_LOAD (0x10)
+#define ONENAND_DATAIN_RMW_MODIFY (0x11)
+
+/*
+ * * Device ID Register F001h (R)
+ * */
+#define ONENAND_DEVICE_DENSITY_SHIFT (4)
+#define ONENAND_DEVICE_IS_DDP (1 << 3)
+#define ONENAND_DEVICE_IS_DEMUX (1 << 2)
+#define ONENAND_DEVICE_VCC_MASK (0x3)
+/*
+ * * Version ID Register F002h (R)
+ * */
+#define ONENAND_VERSION_PROCESS_SHIFT (8)
+
+/*
+ * * Start Address 1 F100h (R/W)
+ * */
+#define ONENAND_DDP_SHIFT (15)
+#define ONENAND_DDP_CHIP0 (0)
+#define ONENAND_DDP_CHIP1 (1 << ONENAND_DDP_SHIFT)
+
+/*
+ * * Start Buffer Register F200h (R/W)
+ * */
+#define ONENAND_BSA_MASK (0x03)
+#define ONENAND_BSA_SHIFT (8)
+#define ONENAND_BSA_BOOTRAM (0 << 2)
+#define ONENAND_BSA_DATARAM0 (2 << 2)
+#define ONENAND_BSA_DATARAM1 (3 << 2)
+#define ONENAND_BSC_MASK (0x03)
+
+/*
+ * * Command Register F220h (R/W)
+ * */
+#define ONENAND_CMD_READ (0x00)
+#define ONENAND_CMD_READOOB (0x13)
+#define ONENAND_CMD_PROG (0x80)
+#define ONENAND_CMD_PROGOOB (0x1A)
+#define ONENAND_CMD_UNLOCK (0x23)
+#define ONENAND_CMD_LOCK (0x2A)
+#define ONENAND_CMD_LOCK_TIGHT (0x2C)
+#define ONENAND_CMD_UNLOCK_ALL (0x27)
+#define ONENAND_CMD_ERASE (0x94)
+#define ONENAND_CMD_RESET (0xF0)
+#define ONENAND_CMD_OTP_ACCESS (0x65)
+#define ONENAND_CMD_READID (0x90)
+#define ONENAND_CMD_STARTADDR1 (0xE0)
+#define ONENAND_CMD_WP_STATUS (0xE1)
+#define ONENAND_CMD_PIPELINE_READ (0x01)
+#define ONENAND_CMD_PIPELINE_WRITE (0x81)
+/*
+ * * Command Mapping for S5PC100 OneNAND Controller
+ * */
+#define ONENAND_AHB_ADDR (0xB0000000)
+#define ONENAND_DUMMY_ADDR (0xB0400000)
+#define ONENAND_CMD_SHIFT (26)
+#define ONENAND_CMD_MAP_00 (0x0)
+#define ONENAND_CMD_MAP_01 (0x1)
+#define ONENAND_CMD_MAP_10 (0x2)
+#define ONENAND_CMD_MAP_11 (0x3)
+#define ONENAND_CMD_MAP_FF (0xF)
+
+/*
+ * * Mask for Mapping table
+ * */
+#define ONENAND_MEM_ADDR_MASK (0x3ffffff)
+#define ONENAND_DDP_SHIFT_1Gb (22)
+#define ONENAND_DDP_SHIFT_2Gb (23)
+#define ONENAND_DDP_SHIFT_4Gb (24)
+#define ONENAND_FBA_SHIFT (13)
+#define ONENAND_FPA_SHIFT (7)
+#define ONENAND_FSA_SHIFT (5)
+#define ONENAND_FBA_MASK_128Mb (0xff)
+#define ONENAND_FBA_MASK_256Mb (0x1ff)
+#define ONENAND_FBA_MASK_512Mb (0x1ff)
+#define ONENAND_FBA_MASK_1Gb_DDP (0x1ff)
+#define ONENAND_FBA_MASK_1Gb (0x3ff)
+#define ONENAND_FBA_MASK_2Gb_DDP (0x3ff)
+#define ONENAND_FBA_MASK_2Gb (0x7ff)
+#define ONENAND_FBA_MASK_4Gb_DDP (0x7ff)
+#define ONENAND_FBA_MASK_4Gb (0xfff)
+#define ONENAND_FPA_MASK (0x3f)
+#define ONENAND_FSA_MASK (0x3)
+
+/*
+ * * System Configuration 1 Register F221h (R, R/W)
+ * */
+#define ONENAND_SYS_CFG1_SYNC_READ (1 << 15)
+#define ONENAND_SYS_CFG1_BRL_7 (7 << 12)
+#define ONENAND_SYS_CFG1_BRL_6 (6 << 12)
+#define ONENAND_SYS_CFG1_BRL_5 (5 << 12)
+#define ONENAND_SYS_CFG1_BRL_4 (4 << 12)
+#define ONENAND_SYS_CFG1_BRL_3 (3 << 12)
+#define ONENAND_SYS_CFG1_BRL_10 (2 << 12)
+#define ONENAND_SYS_CFG1_BRL_9 (1 << 12)
+#define ONENAND_SYS_CFG1_BRL_8 (0 << 12)
+#define ONENAND_SYS_CFG1_BRL_SHIFT (12)
+#define ONENAND_SYS_CFG1_BL_32 (4 << 9)
+#define ONENAND_SYS_CFG1_BL_16 (3 << 9)
+#define ONENAND_SYS_CFG1_BL_8 (2 << 9)
+#define ONENAND_SYS_CFG1_BL_4 (1 << 9)
+#define ONENAND_SYS_CFG1_BL_CONT (0 << 9)
+#define ONENAND_SYS_CFG1_BL_SHIFT (9)
+#define ONENAND_SYS_CFG1_NO_ECC (1 << 8)
+#define ONENAND_SYS_CFG1_RDY (1 << 7)
+#define ONENAND_SYS_CFG1_INT (1 << 6)
+#define ONENAND_SYS_CFG1_IOBE (1 << 5)
+#define ONENAND_SYS_CFG1_RDY_CONF (1 << 4)
+
+/*
+ * * Controller Status Register F240h (R)
+ * */
+#define ONENAND_CTRL_ONGO (1 << 15)
+#define ONENAND_CTRL_LOCK (1 << 14)
+#define ONENAND_CTRL_LOAD (1 << 13)
+#define ONENAND_CTRL_PROGRAM (1 << 12)
+#define ONENAND_CTRL_ERASE (1 << 11)
+#define ONENAND_CTRL_ERROR (1 << 10)
+#define ONENAND_CTRL_RSTB (1 << 7)
+#define ONENAND_CTRL_OTP_L (1 << 6)
+#define ONENAND_CTRL_OTP_BL (1 << 5)
+
+/*
+ * * Interrupt Status Register F241h (R)
+ * */
+#define ONENAND_INT_MASTER (1 << 15)
+#define ONENAND_INT_READ (1 << 7)
+#define ONENAND_INT_WRITE (1 << 6)
+#define ONENAND_INT_ERASE (1 << 5)
+#define ONENAND_INT_RESET (1 << 4)
+#define ONENAND_INT_CLEAR (0 << 0)
+
+/*
+ * * NAND Flash Write Protection Status Register F24Eh (R)
+ * */
+#define ONENAND_WP_US (1 << 2)
+#define ONENAND_WP_LS (1 << 1)
+#define ONENAND_WP_LTS (1 << 0)
+
+/*
+ * * ECC Status Register FF00h (R)
+ * */
+#define ONENAND_ECC_1BIT (1 << 0)
+#define ONENAND_ECC_1BIT_ALL (0x5555)
+#define ONENAND_ECC_2BIT (1 << 1)
+#define ONENAND_ECC_2BIT_ALL (0xAAAA)
+
+/*
+ * * One-Time Programmable (OTP)
+ * */
+#define ONENAND_OTP_LOCK_OFFSET (14)
+
+
+#endif /* __LINUX_MTD_ONENAND_H */
+
--
1.5.6.3
4
5
A few debug-type commands used to dump the raw icache/dcache data. Useful
when trying to track down cache-related bugs.
Signed-off-by: Mike Frysinger <vapier(a)gentoo.org>
---
lib_blackfin/Makefile | 1 +
lib_blackfin/cmd_cache_dump.c | 145 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+), 0 deletions(-)
create mode 100644 lib_blackfin/cmd_cache_dump.c
diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile
index e32ecc9..4bdf6d3 100644
--- a/lib_blackfin/Makefile
+++ b/lib_blackfin/Makefile
@@ -40,6 +40,7 @@ COBJS-y += board.o
COBJS-y += boot.o
COBJS-y += cache.o
COBJS-y += clocks.o
+COBJS-$(CONFIG_CMD_CACHE_DUMP) += cmd_cache_dump.o
COBJS-y += muldi3.o
COBJS-$(CONFIG_POST) += post.o tests.o
COBJS-y += string.o
diff --git a/lib_blackfin/cmd_cache_dump.c b/lib_blackfin/cmd_cache_dump.c
new file mode 100644
index 0000000..de5840e
--- /dev/null
+++ b/lib_blackfin/cmd_cache_dump.c
@@ -0,0 +1,145 @@
+/*
+ * U-boot - cmd_cache_dump.c
+ *
+ * Copyright (c) 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+
+#include <asm/blackfin.h>
+#include <asm/mach-common/bits/mpu.h>
+
+static int check_limit(const char *type, size_t start_limit, size_t end_limit, size_t start, size_t end)
+{
+ if (start >= start_limit && start <= end_limit && \
+ end <= end_limit && end >= start_limit && \
+ start <= end)
+ return 0;
+
+ printf("%s limit violation: %zu <= (user:%zu) <= (user:%zu) <= %zu\n",
+ type, start_limit, start, end, end_limit);
+ return 1;
+}
+
+int do_icache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int cache_status = icache_status();
+
+ if (cache_status)
+ icache_disable();
+
+ uint32_t cmd_base, tag, cache_upper, cache_lower;
+
+ size_t way, way_start = 0, way_end = 3;
+ size_t sbnk, sbnk_start = 0, sbnk_end = 3;
+ size_t set, set_start = 0, set_end = 31;
+ size_t dw;
+
+ if (argc > 1) {
+ way_start = way_end = simple_strtoul(argv[1], NULL, 10);
+ if (argc > 2) {
+ sbnk_start = sbnk_end = simple_strtoul(argv[2], NULL, 10);
+ if (argc > 3)
+ set_start = set_end = simple_strtoul(argv[3], NULL, 10);
+ }
+ }
+
+ if (check_limit("way", 0, 3, way_start, way_end) || \
+ check_limit("subbank", 0, 3, sbnk_start, sbnk_end) || \
+ check_limit("set", 0, 31, set_start, set_end))
+ return 1;
+
+ puts("Way:Subbank:Set: [valid-tag lower upper] {invalid-tag lower upper}...\n");
+
+ for (way = way_start; way <= way_end; ++way) {
+ for (sbnk = sbnk_start; sbnk <= sbnk_end; ++sbnk) {
+ for (set = set_start; set <= set_end; ++set) {
+ printf("%zu:%zu:%2zu: ", way, sbnk, set);
+ for (dw = 0; dw < 4; ++dw) {
+ if (ctrlc())
+ return 1;
+
+ cmd_base = \
+ (way << 26) | \
+ (sbnk << 16) | \
+ (set << 5) | \
+ (dw << 3);
+
+ /* first read the tag */
+ bfin_write_ITEST_COMMAND(cmd_base | 0x0);
+ SSYNC();
+ tag = bfin_read_ITEST_DATA0();
+ printf("%c%08x ", (tag & 0x1 ? ' ' : '{'), tag);
+
+ /* grab the data at this loc */
+ bfin_write_ITEST_COMMAND(cmd_base | 0x4);
+ SSYNC();
+ cache_lower = bfin_read_ITEST_DATA0();
+ cache_upper = bfin_read_ITEST_DATA1();
+ printf("%08x %08x%c ", cache_lower, cache_upper, (tag & 0x1 ? ' ' : '}'));
+ }
+ puts("\n");
+ }
+ }
+ }
+
+ if (cache_status)
+ icache_enable();
+
+ return 0;
+}
+
+U_BOOT_CMD(icache_dump, 4, 0, do_icache_dump,
+ "icache_dump - dump current instruction cache\n",
+ "[way] [subbank] [set]");
+
+int do_dcache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ u32 way, bank, subbank, set;
+ u32 status, addr;
+ u32 dmem_ctl = bfin_read_DMEM_CONTROL();
+
+ for (bank = 0; bank < 2; ++bank) {
+ if (!(dmem_ctl & (1 << (DMC1_P - bank))))
+ continue;
+
+ for (way = 0; way < 2; ++way)
+ for (subbank = 0; subbank < 4; ++subbank) {
+ printf("%i:%i:%i:\t", bank, way, subbank);
+ for (set = 0; set < 64; ++set) {
+
+ if (ctrlc())
+ return 1;
+
+ /* retrieve a cache tag */
+ bfin_write_DTEST_COMMAND(
+ way << 26 |
+ bank << 23 |
+ subbank << 16 |
+ set << 5
+ );
+ CSYNC();
+ status = bfin_read_DTEST_DATA0();
+
+ /* construct the address using the tag */
+ addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
+
+ /* show it */
+ if (set && !(set % 4))
+ puts("\n\t");
+ printf("%c%08x%c%08x%c ", (status & 0x1 ? '[' : '{'), status, (status & 0x2 ? 'd' : ' '), addr, (status & 0x1 ? ']' : '}'));
+ }
+ puts("\n");
+ }
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(dcache_dump, 4, 0, do_dcache_dump,
+ "dcache_dump - dump current data cache\n",
+ "[bank] [way] [subbank] [set]");
--
1.6.3.3
1
3
Hi TsiChung,
I pulled U-Boot from git (2009.06-00185-g57fe301), configured it for the
Freescale mcf54455 EVB with Intel flash (M54455EVB_intel_config) and
programmed it into the Intel flash device. It boots fine but when it
attempts any ethernet communication whatsoever there are tx timeouts from
the FEC device. dhcp, tftp, ping commands etc do not work at all as a
result of this.
It seems that with this configuration of U-Boot for the 54455 EVB and my
current EVB hw, ethernet comms do not function at all. I have tried the
other ethernet port but there is no link detected.
I have also seen the tx timeout errors from the U-Boot contained within
LTIB (Freescale BSP). They occur infrequently and randomly but /only/ when
booting from the Intel flash part.
I'm reluctant to erase U-Boot resident in the Atmel flash to try U-Boot
from git as it's the only 100% reliable bootloader I've got on the board.
TsiChung - is this a known issue with the 54455 EVB hw?
Rgds,
-- Matt
2
1
Hi,
I'm looking for a working patch for the Linux kernel 2.6.28.8 that would allow using CONFIG_LOGBUFFER (a kernel log buffer shared between U-Boot and the kernel). I'm using u-boot 1.3.3. When LOGBUFFER is enabled in the kernel configuration the kernel build fails with:
kernel/built-in.o: In function `setup_ext_logbuff':
: undefined reference to `setup_ext_logbuff_mem'
Could anybody also tell me how the buffer location (I think the size is fixed to 16K) is communicated to the kernel, via a kernel command line parameter? If so, what is it?
Thanks,
Serguei
The information contained in this electronic mail transmission
may be privileged and confidential, and therefore, protected
from disclosure. If you have received this communication in
error, please notify us immediately by replying to this
message and deleting it from your computer without copying
or disclosing it.
2
2
Hi
I have posted a patch http://lists.denx.de/pipermail/u-boot/2009-June/054797.html
I didn't received email confirmation for the same. (generally I get)
Now I need to send v2 patch for the same.
I want to thread my new patch with this earlier patch for better understanding of everyone on this mailing list.
Generally I was using message id of received email for this purpose.
Since for above patch I didn't received an email
How do I get information to put in "--in-reply-to" field?
Regards..
Prafulla . .
3
3

[U-Boot] [PATCH] mtd: Update MTD infrastructure to support 64bit device size
by Stefan Roese 29 Jun '09
by Stefan Roese 29 Jun '09
29 Jun '09
This patch brings the U-Boot MTD infrastructure in sync with the current
Linux MTD version (2.6.30-rc3). Biggest change is the 64bit device size
support and a resync of the mtdpart.c file which has seen multiple fixes
meanwhile.
Signed-off-by: Stefan Roese <sr(a)denx.de>
Cc: Scott Wood <scottwood(a)freescale.com>
Cc: Kyungmin Park <kmpark(a)infradead.org>
---
common/cmd_onenand.c | 6 +-
common/env_onenand.c | 2 +-
drivers/mtd/cfi_mtd.c | 4 +-
drivers/mtd/mtdpart.c | 488 +++++++++++++++++++-----------------------
drivers/mtd/nand/nand_util.c | 11 +-
include/linux/mtd/mtd.h | 29 ++-
6 files changed, 256 insertions(+), 284 deletions(-)
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
index 5832ff8..e8f06d7 100644
--- a/common/cmd_onenand.c
+++ b/common/cmd_onenand.c
@@ -19,6 +19,10 @@
#include <asm/io.h>
+#if !defined(CONFIG_SYS_64BIT_VSPRINTF)
+#warning Please define CONFIG_SYS_64BIT_VSPRINTF for correct output!
+#endif
+
static struct mtd_info *mtd;
static loff_t next_ofs;
@@ -53,7 +57,7 @@ static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size)
}
if ((*off + *size) > mtd->size) {
- printf("total chip size (0x%x) exceeded!\n", mtd->size);
+ printf("total chip size (0x%llx) exceeded!\n", mtd->size);
return -1;
}
diff --git a/common/env_onenand.c b/common/env_onenand.c
index dbccc79..ed77051 100644
--- a/common/env_onenand.c
+++ b/common/env_onenand.c
@@ -109,7 +109,7 @@ int saveenv(void)
if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.writesize, &retlen,
(u_char *) env_ptr)) {
- printf("OneNAND: write failed at 0x%08x\n", instr.addr);
+ printf("OneNAND: write failed at 0x%llx\n", instr.addr);
return 2;
}
diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c
index 4a76917..a0a15da 100644
--- a/drivers/mtd/cfi_mtd.c
+++ b/drivers/mtd/cfi_mtd.c
@@ -118,7 +118,7 @@ static void cfi_mtd_sync(struct mtd_info *mtd)
*/
}
-static int cfi_mtd_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
flash_info_t *fi = mtd->priv;
@@ -130,7 +130,7 @@ static int cfi_mtd_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
return 0;
}
-static int cfi_mtd_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
flash_info_t *fi = mtd->priv;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index f010f5e..e2e43ea 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -26,7 +26,7 @@ struct list_head mtd_partitions;
struct mtd_part {
struct mtd_info mtd;
struct mtd_info *master;
- u_int32_t offset;
+ uint64_t offset;
int index;
struct list_head list;
int registered;
@@ -44,50 +44,32 @@ struct mtd_part {
* to the _real_ device.
*/
-static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
{
struct mtd_part *part = PART(mtd);
+ struct mtd_ecc_stats stats;
int res;
+ stats = part->master->ecc_stats;
+
if (from >= mtd->size)
len = 0;
else if (from + len > mtd->size)
len = mtd->size - from;
- res = part->master->read (part->master, from + part->offset,
+ res = part->master->read(part->master, from + part->offset,
len, retlen, buf);
if (unlikely(res)) {
if (res == -EUCLEAN)
- mtd->ecc_stats.corrected++;
+ mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
if (res == -EBADMSG)
- mtd->ecc_stats.failed++;
+ mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed;
}
return res;
}
-#ifdef MTD_LINUX
-static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, void **virt, resource_size_t *phys)
-{
- struct mtd_part *part = PART(mtd);
- if (from >= mtd->size)
- len = 0;
- else if (from + len > mtd->size)
- len = mtd->size - from;
- return part->master->point (part->master, from + part->offset,
- len, retlen, virt, phys);
-}
-
-static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
-{
- struct mtd_part *part = PART(mtd);
-
- part->master->unpoint(part->master, from + part->offset, len);
-}
-#endif
-
static int part_read_oob(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
+ struct mtd_oob_ops *ops)
{
struct mtd_part *part = PART(mtd);
int res;
@@ -107,38 +89,38 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
return res;
}
-static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len, size_t *retlen, u_char *buf)
{
struct mtd_part *part = PART(mtd);
- return part->master->read_user_prot_reg (part->master, from,
+ return part->master->read_user_prot_reg(part->master, from,
len, retlen, buf);
}
-static int part_get_user_prot_info (struct mtd_info *mtd,
- struct otp_info *buf, size_t len)
+static int part_get_user_prot_info(struct mtd_info *mtd,
+ struct otp_info *buf, size_t len)
{
struct mtd_part *part = PART(mtd);
- return part->master->get_user_prot_info (part->master, buf, len);
+ return part->master->get_user_prot_info(part->master, buf, len);
}
-static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len, size_t *retlen, u_char *buf)
{
struct mtd_part *part = PART(mtd);
- return part->master->read_fact_prot_reg (part->master, from,
+ return part->master->read_fact_prot_reg(part->master, from,
len, retlen, buf);
}
-static int part_get_fact_prot_info (struct mtd_info *mtd,
- struct otp_info *buf, size_t len)
+static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf,
+ size_t len)
{
struct mtd_part *part = PART(mtd);
- return part->master->get_fact_prot_info (part->master, buf, len);
+ return part->master->get_fact_prot_info(part->master, buf, len);
}
-static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
{
struct mtd_part *part = PART(mtd);
if (!(mtd->flags & MTD_WRITEABLE))
@@ -147,13 +129,12 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- return part->master->write (part->master, to + part->offset,
+ return part->master->write(part->master, to + part->offset,
len, retlen, buf);
}
-#ifdef MTD_LINUX
-static int part_panic_write (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
{
struct mtd_part *part = PART(mtd);
if (!(mtd->flags & MTD_WRITEABLE))
@@ -162,13 +143,12 @@ static int part_panic_write (struct mtd_info *mtd, loff_t to, size_t len,
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- return part->master->panic_write (part->master, to + part->offset,
+ return part->master->panic_write(part->master, to + part->offset,
len, retlen, buf);
}
-#endif
static int part_write_oob(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
+ struct mtd_oob_ops *ops)
{
struct mtd_part *part = PART(mtd);
@@ -182,33 +162,22 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
return part->master->write_oob(part->master, to + part->offset, ops);
}
-static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len, size_t *retlen, u_char *buf)
{
struct mtd_part *part = PART(mtd);
- return part->master->write_user_prot_reg (part->master, from,
+ return part->master->write_user_prot_reg(part->master, from,
len, retlen, buf);
}
-static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len)
-{
- struct mtd_part *part = PART(mtd);
- return part->master->lock_user_prot_reg (part->master, from, len);
-}
-
-#ifdef MTD_LINUX
-static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t *retlen)
+static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
- return -EROFS;
- return part->master->writev (part->master, vecs, count,
- to + part->offset, retlen);
+ return part->master->lock_user_prot_reg(part->master, from, len);
}
-#endif
-static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
+static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct mtd_part *part = PART(mtd);
int ret;
@@ -219,7 +188,7 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
instr->addr += part->offset;
ret = part->master->erase(part->master, instr);
if (ret) {
- if (instr->fail_addr != 0xffffffff)
+ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
}
@@ -231,19 +200,15 @@ void mtd_erase_callback(struct erase_info *instr)
if (instr->mtd->erase == part_erase) {
struct mtd_part *part = PART(instr->mtd);
- if (instr->fail_addr != 0xffffffff)
+ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
}
if (instr->callback)
instr->callback(instr);
}
-#ifdef MTD_LINUX
-EXPORT_SYMBOL_GPL(mtd_erase_callback);
-#endif
-#ifdef MTD_LINUX
-static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
+static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_part *part = PART(mtd);
if ((len + ofs) > mtd->size)
@@ -251,14 +216,13 @@ static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
return part->master->lock(part->master, ofs + part->offset, len);
}
-static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)
+static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_part *part = PART(mtd);
if ((len + ofs) > mtd->size)
return -EINVAL;
return part->master->unlock(part->master, ofs + part->offset, len);
}
-#endif
static void part_sync(struct mtd_info *mtd)
{
@@ -266,7 +230,6 @@ static void part_sync(struct mtd_info *mtd)
part->master->sync(part->master);
}
-#ifdef MTD_LINUX
static int part_suspend(struct mtd_info *mtd)
{
struct mtd_part *part = PART(mtd);
@@ -278,9 +241,8 @@ static void part_resume(struct mtd_info *mtd)
struct mtd_part *part = PART(mtd);
part->master->resume(part->master);
}
-#endif
-static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
+static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
struct mtd_part *part = PART(mtd);
if (ofs >= mtd->size)
@@ -289,7 +251,7 @@ static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
return part->master->block_isbad(part->master, ofs);
}
-static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
+static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
struct mtd_part *part = PART(mtd);
int res;
@@ -300,10 +262,8 @@ static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
return -EINVAL;
ofs += part->offset;
res = part->master->block_markbad(part->master, ofs);
-#ifdef MTD_LINUX
if (!res)
mtd->ecc_stats.badblocks++;
-#endif
return res;
}
@@ -314,31 +274,193 @@ static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
int del_mtd_partitions(struct mtd_info *master)
{
- struct list_head *node;
- struct mtd_part *slave;
+ struct mtd_part *slave, *next;
- for (node = mtd_partitions.next;
- node != &mtd_partitions;
- node = node->next) {
- slave = list_entry(node, struct mtd_part, list);
+ list_for_each_entry_safe(slave, next, &mtd_partitions, list)
if (slave->master == master) {
- struct list_head *prev = node->prev;
- __list_del(prev, node->next);
- if(slave->registered)
+ list_del(&slave->list);
+ if (slave->registered)
del_mtd_device(&slave->mtd);
kfree(slave);
- node = prev;
}
- }
return 0;
}
+static struct mtd_part *add_one_partition(struct mtd_info *master,
+ const struct mtd_partition *part, int partno,
+ uint64_t cur_offset)
+{
+ struct mtd_part *slave;
+
+ /* allocate the partition structure */
+ slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+ if (!slave) {
+ printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
+ master->name);
+ del_mtd_partitions(master);
+ return NULL;
+ }
+ list_add(&slave->list, &mtd_partitions);
+
+ /* set up the MTD object for this partition */
+ slave->mtd.type = master->type;
+ slave->mtd.flags = master->flags & ~part->mask_flags;
+ slave->mtd.size = part->size;
+ slave->mtd.writesize = master->writesize;
+ slave->mtd.oobsize = master->oobsize;
+ slave->mtd.oobavail = master->oobavail;
+ slave->mtd.subpage_sft = master->subpage_sft;
+
+ slave->mtd.name = part->name;
+ slave->mtd.owner = master->owner;
+
+ slave->mtd.read = part_read;
+ slave->mtd.write = part_write;
+
+ if (master->panic_write)
+ slave->mtd.panic_write = part_panic_write;
+
+ if (master->read_oob)
+ slave->mtd.read_oob = part_read_oob;
+ if (master->write_oob)
+ slave->mtd.write_oob = part_write_oob;
+ if (master->read_user_prot_reg)
+ slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
+ if (master->read_fact_prot_reg)
+ slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
+ if (master->write_user_prot_reg)
+ slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
+ if (master->lock_user_prot_reg)
+ slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
+ if (master->get_user_prot_info)
+ slave->mtd.get_user_prot_info = part_get_user_prot_info;
+ if (master->get_fact_prot_info)
+ slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
+ if (master->sync)
+ slave->mtd.sync = part_sync;
+ if (!partno && master->suspend && master->resume) {
+ slave->mtd.suspend = part_suspend;
+ slave->mtd.resume = part_resume;
+ }
+ if (master->lock)
+ slave->mtd.lock = part_lock;
+ if (master->unlock)
+ slave->mtd.unlock = part_unlock;
+ if (master->block_isbad)
+ slave->mtd.block_isbad = part_block_isbad;
+ if (master->block_markbad)
+ slave->mtd.block_markbad = part_block_markbad;
+ slave->mtd.erase = part_erase;
+ slave->master = master;
+ slave->offset = part->offset;
+ slave->index = partno;
+
+ if (slave->offset == MTDPART_OFS_APPEND)
+ slave->offset = cur_offset;
+ if (slave->offset == MTDPART_OFS_NXTBLK) {
+ slave->offset = cur_offset;
+ if (mtd_mod_by_eb(cur_offset, master) != 0) {
+ /* Round up to next erasesize */
+ slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize;
+ printk(KERN_NOTICE "Moving partition %d: "
+ "0x%012llx -> 0x%012llx\n", partno,
+ (unsigned long long)cur_offset, (unsigned long long)slave->offset);
+ }
+ }
+ if (slave->mtd.size == MTDPART_SIZ_FULL)
+ slave->mtd.size = master->size - slave->offset;
+
+ printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
+ (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
+
+ /* let's do some sanity checks */
+ if (slave->offset >= master->size) {
+ /* let's register it anyway to preserve ordering */
+ slave->offset = 0;
+ slave->mtd.size = 0;
+ printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
+ part->name);
+ goto out_register;
+ }
+ if (slave->offset + slave->mtd.size > master->size) {
+ slave->mtd.size = master->size - slave->offset;
+ printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n",
+ part->name, master->name, (unsigned long long)slave->mtd.size);
+ }
+ if (master->numeraseregions > 1) {
+ /* Deal with variable erase size stuff */
+ int i, max = master->numeraseregions;
+ u64 end = slave->offset + slave->mtd.size;
+ struct mtd_erase_region_info *regions = master->eraseregions;
+
+ /* Find the first erase regions which is part of this
+ * partition. */
+ for (i = 0; i < max && regions[i].offset <= slave->offset; i++)
+ ;
+ /* The loop searched for the region _behind_ the first one */
+ i--;
+
+ /* Pick biggest erasesize */
+ for (; i < max && regions[i].offset < end; i++) {
+ if (slave->mtd.erasesize < regions[i].erasesize) {
+ slave->mtd.erasesize = regions[i].erasesize;
+ }
+ }
+ BUG_ON(slave->mtd.erasesize == 0);
+ } else {
+ /* Single erase size */
+ slave->mtd.erasesize = master->erasesize;
+ }
+
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+ mtd_mod_by_eb(slave->offset, &slave->mtd)) {
+ /* Doesn't start on a boundary of major erase size */
+ /* FIXME: Let it be writable if it is on a boundary of
+ * _minor_ erase size though */
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
+ part->name);
+ }
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+ mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
+ part->name);
+ }
+
+ slave->mtd.ecclayout = master->ecclayout;
+ if (master->block_isbad) {
+ uint64_t offs = 0;
+
+ while (offs < slave->mtd.size) {
+ if (master->block_isbad(master,
+ offs + slave->offset))
+ slave->mtd.ecc_stats.badblocks++;
+ offs += slave->mtd.erasesize;
+ }
+ }
+
+out_register:
+ if (part->mtdp) {
+ /* store the object pointer (caller may or may not register it*/
+ *part->mtdp = &slave->mtd;
+ slave->registered = 0;
+ } else {
+ /* register our partition */
+ add_mtd_device(&slave->mtd);
+ slave->registered = 1;
+ }
+ return slave;
+}
+
/*
* This function, given a master MTD object and a partition table, creates
* and registers slave MTD objects which are bound to the master according to
* the partition definitions.
- * (Q: should we register the master MTD object as well?)
+ *
+ * We don't register the master, or expect the caller to have done so,
+ * for reasons of data integrity.
*/
int add_mtd_partitions(struct mtd_info *master,
@@ -346,7 +468,7 @@ int add_mtd_partitions(struct mtd_info *master,
int nbparts)
{
struct mtd_part *slave;
- u_int32_t cur_offset = 0;
+ uint64_t cur_offset = 0;
int i;
/*
@@ -357,184 +479,14 @@ int add_mtd_partitions(struct mtd_info *master,
if (mtd_partitions.next == NULL)
INIT_LIST_HEAD(&mtd_partitions);
- printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
+ printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
for (i = 0; i < nbparts; i++) {
-
- /* allocate the partition structure */
- slave = kzalloc (sizeof(*slave), GFP_KERNEL);
- if (!slave) {
- printk ("memory allocation error while creating partitions for \"%s\"\n",
- master->name);
- del_mtd_partitions(master);
+ slave = add_one_partition(master, parts + i, i, cur_offset);
+ if (!slave)
return -ENOMEM;
- }
- list_add(&slave->list, &mtd_partitions);
-
- /* set up the MTD object for this partition */
- slave->mtd.type = master->type;
- slave->mtd.flags = master->flags & ~parts[i].mask_flags;
- slave->mtd.size = parts[i].size;
- slave->mtd.writesize = master->writesize;
- slave->mtd.oobsize = master->oobsize;
- slave->mtd.oobavail = master->oobavail;
- slave->mtd.subpage_sft = master->subpage_sft;
-
- slave->mtd.name = parts[i].name;
- slave->mtd.owner = master->owner;
-
- slave->mtd.read = part_read;
- slave->mtd.write = part_write;
-
-#ifdef MTD_LINUX
- if (master->panic_write)
- slave->mtd.panic_write = part_panic_write;
-
- if(master->point && master->unpoint){
- slave->mtd.point = part_point;
- slave->mtd.unpoint = part_unpoint;
- }
-#endif
-
- if (master->read_oob)
- slave->mtd.read_oob = part_read_oob;
- if (master->write_oob)
- slave->mtd.write_oob = part_write_oob;
- if(master->read_user_prot_reg)
- slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
- if(master->read_fact_prot_reg)
- slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
- if(master->write_user_prot_reg)
- slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
- if(master->lock_user_prot_reg)
- slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
- if(master->get_user_prot_info)
- slave->mtd.get_user_prot_info = part_get_user_prot_info;
- if(master->get_fact_prot_info)
- slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
- if (master->sync)
- slave->mtd.sync = part_sync;
-#ifdef MTD_LINUX
- if (!i && master->suspend && master->resume) {
- slave->mtd.suspend = part_suspend;
- slave->mtd.resume = part_resume;
- }
- if (master->writev)
- slave->mtd.writev = part_writev;
- if (master->lock)
- slave->mtd.lock = part_lock;
- if (master->unlock)
- slave->mtd.unlock = part_unlock;
-#endif
- if (master->block_isbad)
- slave->mtd.block_isbad = part_block_isbad;
- if (master->block_markbad)
- slave->mtd.block_markbad = part_block_markbad;
- slave->mtd.erase = part_erase;
- slave->master = master;
- slave->offset = parts[i].offset;
- slave->index = i;
-
- if (slave->offset == MTDPART_OFS_APPEND)
- slave->offset = cur_offset;
- if (slave->offset == MTDPART_OFS_NXTBLK) {
- slave->offset = cur_offset;
- if ((cur_offset % master->erasesize) != 0) {
- /* Round up to next erasesize */
- slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
- printk(KERN_NOTICE "Moving partition %d: "
- "0x%08x -> 0x%08x\n", i,
- cur_offset, slave->offset);
- }
- }
- if (slave->mtd.size == MTDPART_SIZ_FULL)
- slave->mtd.size = master->size - slave->offset;
cur_offset = slave->offset + slave->mtd.size;
-
- printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
- slave->offset + slave->mtd.size, slave->mtd.name);
-
- /* let's do some sanity checks */
- if (slave->offset >= master->size) {
- /* let's register it anyway to preserve ordering */
- slave->offset = 0;
- slave->mtd.size = 0;
- printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
- parts[i].name);
- }
- if (slave->offset + slave->mtd.size > master->size) {
- slave->mtd.size = master->size - slave->offset;
- printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
- parts[i].name, master->name, slave->mtd.size);
- }
- if (master->numeraseregions>1) {
- /* Deal with variable erase size stuff */
- int i;
- struct mtd_erase_region_info *regions = master->eraseregions;
-
- /* Find the first erase regions which is part of this partition. */
- for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
- ;
-
- for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
- if (slave->mtd.erasesize < regions[i].erasesize) {
- slave->mtd.erasesize = regions[i].erasesize;
- }
- }
- } else {
- /* Single erase size */
- slave->mtd.erasesize = master->erasesize;
- }
-
- if ((slave->mtd.flags & MTD_WRITEABLE) &&
- (slave->offset % slave->mtd.erasesize)) {
- /* Doesn't start on a boundary of major erase size */
- /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
- slave->mtd.flags &= ~MTD_WRITEABLE;
- printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
- parts[i].name);
- }
- if ((slave->mtd.flags & MTD_WRITEABLE) &&
- (slave->mtd.size % slave->mtd.erasesize)) {
- slave->mtd.flags &= ~MTD_WRITEABLE;
- printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
- parts[i].name);
- }
-
- slave->mtd.ecclayout = master->ecclayout;
- if (master->block_isbad) {
- uint32_t offs = 0;
-
- while(offs < slave->mtd.size) {
- if (master->block_isbad(master,
- offs + slave->offset))
- slave->mtd.ecc_stats.badblocks++;
- offs += slave->mtd.erasesize;
- }
- }
-
-#ifdef MTD_LINUX
- if (parts[i].mtdp) {
- /* store the object pointer
- * (caller may or may not register it */
- *parts[i].mtdp = &slave->mtd;
- slave->registered = 0;
- } else {
- /* register our partition */
- add_mtd_device(&slave->mtd);
- slave->registered = 1;
- }
-#else
- /* register our partition */
- add_mtd_device(&slave->mtd);
- slave->registered = 1;
-#endif
}
return 0;
}
-
-#ifdef MTD_LINUX
-EXPORT_SYMBOL(add_mtd_partitions);
-EXPORT_SYMBOL(del_mtd_partitions);
-#endif
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 6ba52b3..88206d0 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -36,12 +36,15 @@
#include <malloc.h>
#include <div64.h>
-
#include <asm/errno.h>
#include <linux/mtd/mtd.h>
#include <nand.h>
#include <jffs2/jffs2.h>
+#if !defined(CONFIG_SYS_64BIT_VSPRINTF)
+#warning Please define CONFIG_SYS_64BIT_VSPRINTF for correct output!
+#endif
+
typedef struct erase_info erase_info_t;
typedef struct mtd_info mtd_info_t;
@@ -127,7 +130,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
if (ret > 0) {
if (!opts->quiet)
printf("\rSkipping bad block at "
- "0x%08x "
+ "0x%08llx "
" \n",
erase.addr);
continue;
@@ -181,11 +184,11 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
if (percent != percent_complete) {
percent_complete = percent;
- printf("\rErasing at 0x%x -- %3d%% complete.",
+ printf("\rErasing at 0x%llx -- %3d%% complete.",
erase.addr, percent);
if (opts->jffs2 && result == 0)
- printf(" Cleanmarker written at 0x%x.",
+ printf(" Cleanmarker written at 0x%llx.",
erase.addr);
}
}
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 354e3a0..c884567 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -8,6 +8,7 @@
#define __MTD_MTD_H__
#include <linux/types.h>
+#include <div64.h>
#include <linux/mtd/mtd-abi.h>
#define MTD_CHAR_MAJOR 90
@@ -20,6 +21,8 @@
#define MTD_ERASE_DONE 0x08
#define MTD_ERASE_FAILED 0x10
+#define MTD_FAIL_ADDR_UNKNOWN -1LL
+
/*
* Enumeration for NAND/OneNAND flash chip state
*/
@@ -37,13 +40,13 @@ enum {
};
/* If the erase fails, fail_addr might indicate exactly which block failed. If
- fail_addr = 0xffffffff, the failure was not at the device level or was not
+ fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level or was not
specific to any particular block. */
struct erase_info {
struct mtd_info *mtd;
- u_int32_t addr;
- u_int32_t len;
- u_int32_t fail_addr;
+ uint64_t addr;
+ uint64_t len;
+ uint64_t fail_addr;
u_long time;
u_long retries;
u_int dev;
@@ -55,7 +58,7 @@ struct erase_info {
};
struct mtd_erase_region_info {
- u_int32_t offset; /* At which this region starts, from the beginning of the MTD */
+ uint64_t offset; /* At which this region starts, from the beginning of the MTD */
u_int32_t erasesize; /* For this region */
u_int32_t numblocks; /* Number of blocks of erasesize in this region */
unsigned long *lockmap; /* If keeping bitmap of locks */
@@ -110,7 +113,7 @@ struct mtd_oob_ops {
struct mtd_info {
u_char type;
u_int32_t flags;
- u_int32_t size; /* Total size of the MTD */
+ uint64_t size; // Total size of the MTD
/* "Major" erase size for the device. Naïve users may take this
* to be the only erase size available, or may use the more detailed
@@ -202,8 +205,8 @@ struct mtd_info {
void (*sync) (struct mtd_info *mtd);
/* Chip-supported device locking */
- int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
- int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+ int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
+ int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
/* Power Management functions */
int (*suspend) (struct mtd_info *mtd);
@@ -236,6 +239,16 @@ struct mtd_info {
void (*put_device) (struct mtd_info *mtd);
};
+static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
+{
+ do_div(sz, mtd->erasesize);
+ return sz;
+}
+
+static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
+{
+ return do_div(sz, mtd->erasesize);
+}
/* Kernel-side ioctl definitions */
--
1.6.2.5
6
29

[U-Boot] Compiling the latest u-boot-2009.06 with Cross-2.95, and errors came out
by Johnson Yu 29 Jun '09
by Johnson Yu 29 Jun '09
29 Jun '09
Hi there,
I met several compiling errors as below:
make -C cpu/arm920t/at91rm9200/
make[1]: Entering directory
`/home/johnson-yn/GEARI/u-boot-2009.06/cpu/arm920t/at91rm9200'
arm-linux-gcc: lowlevel_init.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: bcm5221.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: dm9161.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: ether.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: i2c.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: interrupts.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: lxt972.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: usb.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
arm-linux-gcc: spi.o: No such file or directory
arm-linux-gcc: unrecognized option `-MQ'
make[1]: *** No rule to make target `.depend', needed by `all'. Stop.
make[1]: Leaving directory
`/home/johnson-yn/GEARI/u-boot-2009.06/cpu/arm920t/at91rm9200'
make: *** [cpu/arm920t/at91rm9200/libat91rm9200.a] Error 2
Is that possibly because of the version of the cross compiler?? and
should I raise it to cross 3.2 or higher to solve this problem??
Regards,
Johnson Yu
___________________________________________________________
Try the all-new Yahoo! Mail. "The New Version is radically easier to use" The Wall Street Journal
http://uk.docs.yahoo.com/nowyoucan.html
3
4

[U-Boot] Your e-mail address has won you US$4,600,000.00 online.
by UK Lottery Organization 29 Jun '09
by UK Lottery Organization 29 Jun '09
29 Jun '09
新しいメールアドレスをお知らせします新しいメールアドレス: uklotteryorganization2300000009(a)yahoo.co.jp
Your email has won US$4,600,000 from the UK Lottery draws of 23/06/09 held in Dubai U.A.E. Lucky #: MX014926583. For claims contact Mr.Richard Adams in UK on Email:Richard.Adams@Longhorns.com with your official names, country, address, sex, age, tel/mobile #, occupation, date of draw.
- UK Lottery Organization
1
0

29 Jun '09
Am Montag 29 Juni 2009 10:15:22 schrieb Prafulla Wadaskar:
>
> > -----Original Message-----
> > From: Dieter Kiermaier [mailto:dk-arm-linux@gmx.de]
> > Sent: Monday, June 29, 2009 1:33 PM
> > To: u-boot(a)lists.denx.de
> > Cc: Prafulla Wadaskar
> > Subject: [PATCH] Kirkwood: add Marvell Sheevaplug gpio support
> >
> > Hi List,
> >
> > this if my first patch which goes to the wild. So please
> > don't be croos with me if I made some stupid thing :) Any
> > comments or feedback would be very welcome!
> >
> > Is it common that the patch writer gives his Signed-off-by or
> > who is responsible for that?
> >
> > Cheers,
> > Dieter
> >
> >
> > From e89ebedf1528e821e504c91af802687efb21533b Mon Sep 17 00:00:00 2001
> > From: Dieter Kiermaier <dk-arm-linux(a)gmx.de>
> > Date: Fri, 26 Jun 2009 14:45:13 +0200
> > Subject: [PATCH] Kirkwood: add Marvell Sheevaplug gpio support
> Signed-off-by is MUST
>
> >
> > ---
> > board/Marvell/sheevaplug/sheevaplug.c | 1 +
> > cpu/arm926ejs/kirkwood/Makefile | 1 +
> > cpu/arm926ejs/kirkwood/gpio.c | 144
> > +++++++++++++++++++++++++++++++++
> > include/asm-arm/arch-kirkwood/gpio.h | 43 ++++++++++
> Spilt this patch into two, 1. gpio support for Kirkwood SOC and 2. Sheevaplug updates
> Move gpio stuff to drivers/gpio/
>
Is it ok to leave gpio.h file in include/asm-arm/arch-kirkwood/ ?
Thanks,
Dieter
1
0