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] [PATCH 2/2] Create the S5PC100 SoC header under the include/asm-arm/arch-s5pc100
by Kim, Heung Jun 04 Jun '09
by Kim, Heung Jun 04 Jun '09
04 Jun '09
Signed-off-by: HeungJun, Kim <riverful.kim(a)samsung.com>
---
This patch is the new processor - S5PC100's SoC code & headers.
This patch consists of 2 files.
The First file is to create the new SoC code related with S5PC100
application processor.
It's located in ther cpu/arm_cortesa8/s5pc100.
The Second file is to create the new SoC header related with S5PC100
application processor.
It's located in ther include/asm-arm/s5pc100.
This file is the Second.
include/asm-arm/arch-s5pc100/clock.h | 137 +++++++
include/asm-arm/arch-s5pc100/cpu.h | 292 +++++++++++++++
include/asm-arm/arch-s5pc100/gpio.h | 580 ++++++++++++++++++++++++++++++
include/asm-arm/arch-s5pc100/hardware.h | 63 ++++
include/asm-arm/arch-s5pc100/sys_proto.h | 25 ++
include/asm-arm/arch-s5pc100/uart.h | 94 +++++
include/asm-arm/arch-s5pc100/watchdog.h | 39 ++
7 files changed, 1230 insertions(+), 0 deletions(-)
create mode 100644 include/asm-arm/arch-s5pc100/clock.h
create mode 100644 include/asm-arm/arch-s5pc100/cpu.h
create mode 100644 include/asm-arm/arch-s5pc100/gpio.h
create mode 100644 include/asm-arm/arch-s5pc100/hardware.h
create mode 100644 include/asm-arm/arch-s5pc100/sys_proto.h
create mode 100644 include/asm-arm/arch-s5pc100/uart.h
create mode 100644 include/asm-arm/arch-s5pc100/watchdog.h
diff --git a/include/asm-arm/arch-s5pc100/clock.h
b/include/asm-arm/arch-s5pc100/clock.h
new file mode 100644
index 0000000..c703eec
--- /dev/null
+++ b/include/asm-arm/arch-s5pc100/clock.h
@@ -0,0 +1,137 @@
+/*
+ * (C) Copyright 2009
+ * Inki Dae, SAMSUNG Electronics, <inki.dae(a)samsung.com>
+ * Heungjun Kim, SAMSUNG Electronics, <riverful.kim(a)samsung.com>
+ * Minkyu Kang, SAMSUNG Electronics, <mk7.kang(a)samsung.com>
+ *
+ * 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
+ */
+
+/*
+ * Clock control
+ */
+#define S5P_CLKREG(x) (S5P_PA_CLK + (x))
+
+/* Clock Register */
+#define S5P_APLL_LOCK S5P_CLKREG(0x0)
+#define S5P_MPLL_LOCK S5P_CLKREG(0x4)
+#define S5P_EPLL_LOCK S5P_CLKREG(0x8)
+#define S5P_HPLL_LOCK S5P_CLKREG(0xc)
+
+#define S5P_APLL_CON S5P_CLKREG(0x100)
+#define S5P_MPLL_CON S5P_CLKREG(0x104)
+#define S5P_EPLL_CON S5P_CLKREG(0x108)
+#define S5P_HPLL_CON S5P_CLKREG(0x10c)
+
+#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
+#define S5P_CLK_SRC1 S5P_CLKREG(0x204)
+#define S5P_CLK_SRC2 S5P_CLKREG(0x208)
+#define S5P_CLK_SRC3 S5P_CLKREG(0x20c)
+
+#define S5P_CLK_DIV0 S5P_CLKREG(0x300)
+#define S5P_CLK_DIV1 S5P_CLKREG(0x304)
+#define S5P_CLK_DIV2 S5P_CLKREG(0x308)
+#define S5P_CLK_DIV3 S5P_CLKREG(0x30c)
+#define S5P_CLK_DIV4 S5P_CLKREG(0x310)
+
+#define S5P_CLK_OUT S5P_CLKREG(0x400)
+
+#define S5P_CLK_GATE_D00 S5P_CLKREG(0x500)
+#define S5P_CLK_GATE_D01 S5P_CLKREG(0x504)
+#define S5P_CLK_GATE_D02 S5P_CLKREG(0x508)
+#define S5P_CLK_GATE_D10 S5P_CLKREG(0x520)
+#define S5P_CLK_GATE_D11 S5P_CLKREG(0x524)
+#define S5P_CLK_GATE_D12 S5P_CLKREG(0x528)
+#define S5P_CLK_GATE_D13 S5P_CLKREG(0x530)
+#define S5P_CLK_GATE_D14 S5P_CLKREG(0x534)
+#define S5P_CLK_GATE_D20 S5P_CLKREG(0x540)
+#define S5P_CLK_GATE_SCLK0 S5P_CLKREG(0x560)
+#define S5P_CLK_GATE_SCLK1 S5P_CLKREG(0x564)
+
+/*
+ * Clock control - Others
+ */
+#define S5P_OTHERS_REG_BASE(x) (S5P_PA_CLK_OTHERS + (x))
+#define S5P_OTHERS_BASE S5P_OTHERS_REG_BASE(0x0)
+#define S5P_SW_RST S5P_OTHERS_REG_BASE(0x0)
+#define S5P_ONENAND_RST S5P_OTHERS_REG_BASE(0x8)
+#define S5P_GENERAL_CTRL S5P_OTHERS_REG_BASE(0x100)
+#define S5P_GENERAL_STATUS S5P_OTHERS_REG_BASE(0x104)
+#define S5P_MEM_SYS_CFG S5P_OTHERS_REG_BASE(0x200)
+#define S5P_CAM_MUX_SEL S5P_OTHERS_REG_BASE(0x300)
+#define S5P_MIXER_OUT_SEL S5P_OTHERS_REG_BASE(0x304)
+#define S5P_LPMP3_MODE_SEL S5P_OTHERS_REG_BASE(0x308)
+#define S5P_MIPI_PHY_CON0 S5P_OTHERS_REG_BASE(0x400)
+#define S5P_MIPI_PHY_CON1 S5P_OTHERS_REG_BASE(0x414)
+#define S5P_HDMI_PHY_CON0 S5P_OTHERS_REG_BASE(0x420)
+
+#ifndef __ASSEMBLY__
+
+/* Clock Address */
+#define S5P_APLL_LOCK_REG __REG(S5P_APLL_LOCK)
+#define S5P_MPLL_LOCK_REG __REG(S5P_MPLL_LOCK)
+#define S5P_EPLL_LOCK_REG __REG(S5P_EPLL_LOCK)
+#define S5P_HPLL_LOCK_REG __REG(S5P_HPLL_LOCK)
+
+#define S5P_APLL_CON_REG __REG(S5P_APLL_CON)
+#define S5P_MPLL_CON_REG __REG(S5P_MPLL_CON)
+#define S5P_EPLL_CON_REG __REG(S5P_EPLL_CON)
+#define S5P_HPLL_CON_REG __REG(S5P_HPLL_CON)
+
+#define S5P_CLK_SRC0_REG __REG(S5P_CLK_SRC0)
+#define S5P_CLK_SRC1_REG __REG(S5P_CLK_SRC1)
+#define S5P_CLK_SRC2_REG __REG(S5P_CLK_SRC2)
+#define S5P_CLK_SRC3_REG __REG(S5P_CLK_SRC3)
+
+#define S5P_CLK_DIV0_REG __REG(S5P_CLK_DIV0)
+#define S5P_CLK_DIV1_REG __REG(S5P_CLK_DIV1)
+#define S5P_CLK_DIV2_REG __REG(S5P_CLK_DIV2)
+#define S5P_CLK_DIV3_REG __REG(S5P_CLK_DIV3)
+#define S5P_CLK_DIV4_REG __REG(S5P_CLK_DIV4)
+
+#define S5P_CLK_OUT_REG __REG(S5P_CLK_OUT)
+
+#define S5P_CLK_GATE_D00_REG __REG(S5P_CLK_GATE_D00)
+#define S5P_CLK_GATE_D01_REG __REG(S5P_CLK_GATE_D01)
+#define S5P_CLK_GATE_D02_REG __REG(S5P_CLK_GATE_D02)
+#define S5P_CLK_GATE_D10_REG __REG(S5P_CLK_GATE_D10)
+#define S5P_CLK_GATE_D11_REG __REG(S5P_CLK_GATE_D11)
+#define S5P_CLK_GATE_D12_REG __REG(S5P_CLK_GATE_D12)
+#define S5P_CLK_GATE_D13_REG __REG(S5P_CLK_GATE_D13)
+#define S5P_CLK_GATE_D14_REG __REG(S5P_CLK_GATE_D14)
+#define S5P_CLK_GATE_D20_REG __REG(S5P_CLK_GATE_D20)
+#define S5P_CLK_GATE_SCLK0_REG __REG(S5P_CLK_GATE_SCLK0)
+#define S5P_CLK_GATE_SCLK1_REG __REG(S5P_CLK_GATE_SCLK1)
+
+#define S5P_OTHERS_BASE_REG __REG(S5P_OTHERS_BASE)
+#define S5P_SW_RST_REG __REG(S5P_SW_RST)
+#define S5P_ONENAND_RST_REG __REG(S5P_ONENAND_RST)
+#define S5P_GENERAL_CTRL_REG __REG(S5P_GENERAL_CTRL)
+#define S5P_GENERAL_STATUS_REG __REG(S5P_GENERAL_STATUS)
+#define S5P_MEM_SYS_CFG_REG __REG(S5P_MEM_SYS_CFG)
+#define S5P_CAM_MUX_SEL_REG __REG(S5P_CAM_MUX_SEL)
+#define S5P_MIXER_OUT_SEL_REG __REG(S5P_MIXER_OUT_SEL)
+#define S5P_LPMP3_MODE_SEL_REG __REG(S5P_LPMP3_MODE_SEL)
+#define S5P_MIPI_PHY_CON0_REG __REG(S5P_MIPI_PHY_CON0)
+#define S5P_MIPI_PHY_CON1_REG __REG(S5P_MIPI_PHY_CON1)
+#define S5P_HDMI_PHY_CON0_REG __REG(S5P_HDMI_PHY_CON0)
+
+unsigned long get_PCLK(void);
+#endif /* __ASSENBLY__ */
+
diff --git a/include/asm-arm/arch-s5pc100/cpu.h
b/include/asm-arm/arch-s5pc100/cpu.h
new file mode 100644
index 0000000..a4a4a37
--- /dev/null
+++ b/include/asm-arm/arch-s5pc100/cpu.h
@@ -0,0 +1,292 @@
+/*
+ * (C) Copyright 2009
+ * Samsung Electronics, <www.samsung.com/sec>
+ * Heungjun Kim <riverful.kim(a)samsung.com>
+ * Minkyu Kang <mk7.kang(a)samsung.com>
+ *
+ * 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
+ *
+ */
+
+#ifndef _CPU_H
+#define _CPU_H
+
+#include <asm/hardware.h>
+
+#ifndef __S5PC100_H__
+#define __S5PC100_H__
+
+#define S5P_ADDR_BASE (0xe0000000)
+#define S5P_ADDR(x) (S5P_ADDR_BASE + (x))
+
+#define S5P_PA_CLK S5P_ADDR(0x00100000) /* Clock Base */
+#define S5P_PA_PWR S5P_ADDR(0x00108000) /* Power Base */
+#define S5P_PA_CLK_OTHERS S5P_ADDR(0x00200000) /* Clock Others Base */
+#define S5P_PA_GPIO S5P_ADDR(0x00300000) /* GPIO Base */
+#define S5P_PA_VIC0 S5P_ADDR(0x04000000) /* Vector Interrupt
Controller 0 */
+#define S5P_PA_VIC1 S5P_ADDR(0x04100000) /* Vector Interrupt
Controller 1 */
+#define S5P_PA_VIC2 S5P_ADDR(0x04200000) /* Vector Interrupt
Controller 2 */
+#define S5P_PA_DMC S5P_ADDR(0x06000000) /* Dram Memory Controller */
+#define S5P_PA_SROMC S5P_ADDR(0x07000000) /* SROM Controller */
+#define S5P_PA_WATCHDOG S5P_ADDR(0x0a200000) /* Watchdog Timer */
+#define S5P_PA_PWMTIMER S5P_ADDR(0x0a000000) /* PWM Timer */
+
+/*
+ * Chip ID
+ */
+#define S5P_ID(x) (S5P_PA_ID + (x))
+
+#define S5P_PRO_ID S5P_ID(0)
+#define S5P_OMR S5P_ID(4)
+
+
+/*
+ * Power control
+ */
+#define S5P_PWRREG(x) (S5P_PA_PWR + (x))
+
+#define S5P_PWR_CFG S5P_PWRREG(0x0)
+#define S5P_EINT_WAKEUP_MASK S5P_PWRREG(0x04)
+#define S5P_NORMAL_CFG S5P_PWRREG(0x10)
+#define S5P_STOP_CFG S5P_PWRREG(0x14)
+#define S5P_SLEEP_CFG S5P_PWRREG(0x18)
+#define S5P_STOP_MEM_CFG S5P_PWRREG(0x1c)
+#define S5P_OSC_FREQ S5P_PWRREG(0x100)
+#define S5P_OSC_STABLE S5P_PWRREG(0x104)
+#define S5P_PWR_STABLE S5P_PWRREG(0x108)
+#define S5P_INTERNAL_PWR_STABLE S5P_PWRREG(0x110)
+#define S5P_CLAMP_STABLE S5P_PWRREG(0x114)
+#define S5P_OTHERS S5P_PWRREG(0x200)
+#define S5P_RST_STAT S5P_PWRREG(0x300)
+#define S5P_WAKEUP_STAT S5P_PWRREG(0x304)
+#define S5P_BLK_PWR_STAT S5P_PWRREG(0x308)
+#define S5P_INFORM0 S5P_PWRREG(0x400)
+#define S5P_INFORM1 S5P_PWRREG(0x404)
+#define S5P_INFORM2 S5P_PWRREG(0x408)
+#define S5P_INFORM3 S5P_PWRREG(0x40c)
+#define S5P_INFORM4 S5P_PWRREG(0x410)
+#define S5P_INFORM5 S5P_PWRREG(0x414)
+#define S5P_INFORM6 S5P_PWRREG(0x418)
+#define S5P_INFORM7 S5P_PWRREG(0x41c)
+#define S5P_DCGIDX_MAP0 S5P_PWRREG(0x500)
+#define S5P_DCGIDX_MAP1 S5P_PWRREG(0x504)
+#define S5P_DCGIDX_MAP2 S5P_PWRREG(0x508)
+#define S5P_DCGPERF_MAP0 S5P_PWRREG(0x50c)
+#define S5P_DCGPERF_MAP1 S5P_PWRREG(0x510)
+#define S5P_DVCIDX_MAP S5P_PWRREG(0x514)
+#define S5P_FREQ_CPU S5P_PWRREG(0x518)
+#define S5P_FREQ_DPM S5P_PWRREG(0x51c)
+#define S5P_DVSEMCLK_EN S5P_PWRREG(0x520)
+#define S5P_APLL_CON_L8 S5P_PWRREG(0x600)
+#define S5P_APLL_CON_L7 S5P_PWRREG(0x604)
+#define S5P_APLL_CON_L6 S5P_PWRREG(0x608)
+#define S5P_APLL_CON_L5 S5P_PWRREG(0x60c)
+#define S5P_APLL_CON_L4 S5P_PWRREG(0x610)
+#define S5P_APLL_CON_L3 S5P_PWRREG(0x614)
+#define S5P_APLL_CON_L2 S5P_PWRREG(0x618)
+#define S5P_APLL_CON_L1 S5P_PWRREG(0x61c)
+#define S5P_EM_CONTROL S5P_PWRREG(0x620)
+
+#define S5P_CLKDIV_IEM_L8 S5P_PWRREG(0x700)
+#define S5P_CLKDIV_IEM_L7 S5P_PWRREG(0x704)
+#define S5P_CLKDIV_IEM_L6 S5P_PWRREG(0x708)
+#define S5P_CLKDIV_IEM_L5 S5P_PWRREG(0x70c)
+#define S5P_CLKDIV_IEM_L4 S5P_PWRREG(0x710)
+#define S5P_CLKDIV_IEM_L3 S5P_PWRREG(0x714)
+#define S5P_CLKDIV_IEM_L2 S5P_PWRREG(0x718)
+#define S5P_CLKDIV_IEM_L1 S5P_PWRREG(0x71c)
+
+#define S5P_IEM_HPMCLK_DIV S5P_PWRREG(0x724)
+
+
+/*
+ * Vector Interrupt Controller
+ * : VIC0, VIC1, VIC2
+ */
+/* VIC0 */
+#define S5P_VIC0_BASE(x) (S5P_PA_VIC0 + (x))
+#define S5P_VIC1_BASE(x) (S5P_PA_VIC1 + (x))
+#define S5P_VIC2_BASE(x) (S5P_PA_VIC2 + (x))
+
+/* Vector Interrupt Offset */
+#define VIC_IRQSTATUS_OFFSET 0x0 /* IRQ Status Register */
+#define VIC_FIQSTATUS_OFFSET 0x4 /* FIQ Status Register */
+#define VIC_RAWINTR_OFFSET 0x8 /* Raw Interrupt Status Register */
+#define VIC_INTSELECT_OFFSET 0xc /* Interrupt Select Register */
+#define VIC_INTENABLE_OFFSET 0x10 /* Interrupt Enable Register */
+#define VIC_INTENCLEAR_OFFSET 0x14 /* Interrupt Enable Clear Register */
+#define VIC_SOFTINT_OFFSET 0x18 /* Software Interrupt Register */
+#define VIC_SOFTINTCLEAR_OFFSET 0x1c /* Software Interrupt Clear Register */
+#define VIC_PROTECTION_OFFSET 0x20 /* Protection Enable Register */
+#define VIC_SWPRIORITYMASK_OFFSET 0x24 /* Software Priority Mask Register */
+#define VIC_PRIORITYDAISY_OFFSET 0x28 /* Vector Priority Register for
Daisy Chain */
+#define VIC_INTADDRESS_OFFSET 0xf00 /* Vector Priority Register for
Daisy Chain */
+
+
+/*
+ * SROMC Controller
+ */
+/* DRAM Memory Controller */
+#define S5P_DMC_BASE(x) (S5P_PA_DMC + (x))
+/* SROMC Base */
+#define S5P_SROMC_BASE(x) (S5P_PA_SROMC + (x))
+/* SROMC offset */
+#define CONCONTROL_OFFSET 0x0 /* Controller Control Register */
+#define MEMCONTROL_OFFSET 0x04 /* Memory Control Register */
+#define MEMCONFIG0_OFFSET 0x08 /* Memory Chip0 Configuration Register */
+#define MEMCONFIG1_OFFSET 0x0c /* Memory Chip1 Configuration Register */
+#define DIRECTCMD_OFFSET 0x10 /* Memory Direct Command Register */
+#define PRECHCONFIG_OFFSET 0x14 /* Precharge Policy Configuration Register */
+#define PHYCONTROL0_OFFSET 0x18 /* PHY Control0 Register */
+#define PHYCONTROL1_OFFSET 0x1c /* PHY Control1 Register */
+#define PHYCONTROL2_OFFSET 0x20 /* PHY Control2 Register */
+#define PWRDNCONFIG_OFFSET 0x28 /* Dynamic Power Down Configuration Register */
+#define TIMINGAREF_OFFSET 0x30 /* AC Timing Register for SDRAM Auto Refresh */
+#define TIMINGROW_OFFSET 0x34 /* AC Timing Register for SDRAM Row */
+#define TIMINGDATA_OFFSET 0x38 /* AC Timing Register for SDRAM Data */
+#define TIMINGPOWER_OFFSET 0x3c /* AC Timing Register for Power Mode
of SDRAM */
+#define PHYSTATUS0_OFFSET 0x40 /* PHY Status Register 0 */
+#define PHYSTATUS1_OFFSET 0x44 /* PHY Status Register 1 */
+#define CHIP0STATUS_OFFSET 0x48 /* Memory Chip0 Status Register */
+#define CHIP1STATUS_OFFSET 0x4c /* Memory Chip1 Status Register */
+#define AREFSTATUS_OFFSET 0x50 /* Counter status Register for Auto Refresh */
+#define MRSTATUS_OFFSET 0x54 /* Memory Mode Registers Status Register */
+#define PHYTEST0_OFFSET 0x58 /* PHY Test Register 0 */
+#define PHYTEST1_OFFSET 0x5c /* PHY Test Register 1 */
+
+#define S5P_CONCONTROL S5P_DMC_BASE(CONCONTROL_OFFSET)
+#define S5P_MEMCONTROL S5P_DMC_BASE(MEMCONTROL_OFFSET)
+#define S5P_MEMCONFIG0 S5P_DMC_BASE(MEMCONFIG0_OFFSET)
+#define S5P_MEMCONFIG1 S5P_DMC_BASE(MEMCONFIG1_OFFSET)
+#define S5P_DIRECTCMD S5P_DMC_BASE(DIRECTCMD_OFFSET)
+#define S5P_PRECHCONFIG S5P_DMC_BASE(PRECHCONFIG_OFFSET)
+#define S5P_PHYCONTROL0 S5P_DMC_BASE(PHYCONTROL0_OFFSET)
+#define S5P_PHYCONTROL1 S5P_DMC_BASE(PHYCONTROL1_OFFSET)
+#define S5P_PHYCONTROL2 S5P_DMC_BASE(PHYCONTROL2_OFFSET)
+#define S5P_PWRDNCONFIG S5P_DMC_BASE(PWRDNCONFIG_OFFSET)
+#define S5P_TIMINGAREF S5P_DMC_BASE(TIMINGAREF_OFFSET)
+#define S5P_TIMINGROW S5P_DMC_BASE(TIMINGROW_OFFSET)
+#define S5P_TIMINGDATA S5P_DMC_BASE(TIMINGDATA_OFFSET)
+#define S5P_TIMINGPOWER S5P_DMC_BASE(TIMINGPOWER_OFFSET)
+#define S5P_PHYSTATUS0 S5P_DMC_BASE(PHYSTATUS0_OFFSET)
+#define S5P_PHYSTATUS1 S5P_DMC_BASE(PHYSTATUS1_OFFSET)
+#define S5P_CHIP0STATUS S5P_DMC_BASE(CHIP0STATUS_OFFSET)
+#define S5P_CHIP1STATUS S5P_DMC_BASE(CHIP1STATUS_OFFSET)
+#define S5P_AREFSTATUS S5P_DMC_BASE(AREFSTATUS_OFFSET)
+#define S5P_MRSTATUS S5P_DMC_BASE(MRSTATUS_OFFSET)
+#define S5P_PHYTEST0 S5P_DMC_BASE(PHYTEST0_OFFSET)
+#define S5P_PHYTEST1 S5P_DMC_BASE(PHYTEST1_OFFSET)
+
+
+/*
+ * PWM Timer
+ */
+#define S5P_PWMTIMER_BASE(x) (S5P_PA_PWMTIMER + (x))
+
+/* PWM timer offset */
+#define PWM_TCFG0_OFFSET 0x0
+#define PWM_TCFG1_OFFSET 0x04
+#define PWM_TCON_OFFSET 0x08
+#define PWM_TCNTB0_OFFSET 0x0c
+#define PWM_TCMPB0_OFFSET 0x10
+#define PWM_TCNTO0_OFFSET 0x14
+#define PWM_TCNTB1_OFFSET 0x18
+#define PWM_TCMPB1_OFFSET 0x1c
+#define PWM_TCNTO1_OFFSET 0x20
+#define PWM_TCNTB2_OFFSET 0x24
+#define PWM_TCMPB2_OFFSET 0x28
+#define PWM_TCNTO2_OFFSET 0x2c
+#define PWM_TCNTB3_OFFSET 0x30
+#define PWM_TCNTO3_OFFSET 0x38
+#define PWM_TCNTB4_OFFSET 0x3c
+#define PWM_TCNTO4_OFFSET 0x40
+#define PWM_TINT_CSTAT_OFFSET 0x44
+
+/* PWM timer register */
+#define S5P_PWM_TCFG0 S5P_PWMTIMER_BASE(PWM_TCFG0_OFFSET)
+#define S5P_PWM_TCFG1 S5P_PWMTIMER_BASE(PWM_TCFG1_OFFSET)
+#define S5P_PWM_TCON S5P_PWMTIMER_BASE(PWM_TCON_OFFSET)
+#define S5P_PWM_TCNTB0 S5P_PWMTIMER_BASE(PWM_TCNTB0_OFFSET)
+#define S5P_PWM_TCMPB0 S5P_PWMTIMER_BASE(PWM_TCMPB0_OFFSET)
+#define S5P_PWM_TCNTO0 S5P_PWMTIMER_BASE(PWM_TCNTO0_OFFSET)
+#define S5P_PWM_TCNTB1 S5P_PWMTIMER_BASE(PWM_TCNTB1_OFFSET)
+#define S5P_PWM_TCMPB1 S5P_PWMTIMER_BASE(PWM_TCMPB1_OFFSET)
+#define S5P_PWM_TCNTO1 S5P_PWMTIMER_BASE(PWM_TCNTO1_OFFSET)
+#define S5P_PWM_TCNTB2 S5P_PWMTIMER_BASE(PWM_TCNTB2_OFFSET)
+#define S5P_PWM_TCMPB2 S5P_PWMTIMER_BASE(PWM_TCMPB2_OFFSET)
+#define S5P_PWM_TCNTO2 S5P_PWMTIMER_BASE(PWM_TCNTO2_OFFSET)
+#define S5P_PWM_TCNTB3 S5P_PWMTIMER_BASE(PWM_TCNTB3_OFFSET)
+#define S5P_PWM_TCNTO3 S5P_PWMTIMER_BASE(PWM_TCNTO3_OFFSET)
+#define S5P_PWM_TCNTB4 S5P_PWMTIMER_BASE(PWM_TCNTB4_OFFSET)
+#define S5P_PWM_TCNTO4 S5P_PWMTIMER_BASE(PWM_TCNTO4_OFFSET)
+#define S5P_PWM_TINT_CSTAT S5P_PWMTIMER_BASE(PWM_TINT_CSTAT_OFFSET)
+
+/* PWM timer addressing */
+#define S5P_TIMER_BASE S5P_PWMTIMER_BASE(0x0)
+
+#ifndef __ASSEMBLY__
+#define S5P_PWMTIMER_BASE_REG __REG(S5P_PWMTIMER_BASE(0x0))
+#define S5P_PWM_TCFG0_REG __REG(S5P_PWM_TCFG0)
+#define S5P_PWM_TCFG1_REG __REG(S5P_PWM_TCFG1)
+#define S5P_PWM_TCON_REG __REG(S5P_PWM_TCON)
+#define S5P_PWM_TCNTB0_REG __REG(S5P_PWM_TCNTB0)
+#define S5P_PWM_TCMPB0_REG __REG(S5P_PWM_TCMPB0)
+#define S5P_PWM_TCNTO0_REG __REG(S5P_PWM_TCNTO0)
+#define S5P_PWM_TCNTB1_REG __REG(S5P_PWM_TCNTB1)
+#define S5P_PWM_TCMPB1_REG __REG(S5P_PWM_TCMPB1)
+#define S5P_PWM_TCNTO1_REG __REG(S5P_PWM_TCNTO1)
+#define S5P_PWM_TCNTB2_REG __REG(S5P_PWM_TCNTB2)
+#define S5P_PWM_TCMPB2_REG __REG(S5P_PWM_TCMPB2)
+#define S5P_PWM_TCNTO2_REG __REG(S5P_PWM_TCNTO2)
+#define S5P_PWM_TCNTB3_REG __REG(S5P_PWM_TCNTB3)
+#define S5P_PWM_TCNTO3_REG __REG(S5P_PWM_TCNTO3)
+#define S5P_PWM_TCNTB4_REG __REG(S5P_PWM_TCNTB4)
+#define S5P_PWM_TCNTO4_REG __REG(S5P_PWM_TCNTO4)
+#define S5P_PWM_TINT_CSTAT_REG __REG(S5P_PWM_TINT_CSTAT)
+#endif /* __ASSEMBLY__ */
+
+/* PWM timer value */
+#define S5P_TCON4_AUTO_RELOAD (1 << 22) /* Interval mode(Auto
Reload) of PWM Timer 4 */
+#define S5P_TCON4_UPDATE (1 << 21) /* Update TCNTB4 */
+#define S5P_TCON4_ON (1 << 20) /* start bit of PWM Timer 4 */
+
+#ifndef __ASSEMBLY__
+typedef struct s5pc1xx_timer {
+ volatile unsigned long TCFG0;
+ volatile unsigned long TCFG1;
+ volatile unsigned long TCON;
+ volatile unsigned long TCNTB0;
+ volatile unsigned long TCMPB0;
+ volatile unsigned long TCNTO0;
+ volatile unsigned long TCNTB1;
+ volatile unsigned long TCMPB1;
+ volatile unsigned long TCNTO1;
+ volatile unsigned long TCNTB2;
+ volatile unsigned long TCMPB2;
+ volatile unsigned long TCNTO2;
+ volatile unsigned long TCNTB3;
+ volatile unsigned long res1;
+ volatile unsigned long TCNTO3;
+ volatile unsigned long TCNTB4;
+ volatile unsigned long TCNTO4;
+
+ volatile unsigned long TINTCSTAT;
+} s5pc1xx_timers_t;
+#endif /* __ASSEMBLY__ */
+
+#endif /* __S5PC100_H__ */
+
+#endif /* _CPU_H */
diff --git a/include/asm-arm/arch-s5pc100/gpio.h
b/include/asm-arm/arch-s5pc100/gpio.h
new file mode 100644
index 0000000..a8f032a
--- /dev/null
+++ b/include/asm-arm/arch-s5pc100/gpio.h
@@ -0,0 +1,580 @@
+/*
+ * (C) Copyright 2009 SAMSUNG Electronics
+ * Heungjun Kim <riverful.kim(a)samsung.com>
+ * Minkyu Kang <mk7.kang(a)samsung.com>
+ *
+ * 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
+ */
+
+/*
+ * GPIO
+ */
+
+/* GPIO Bank Base */
+#define S5P_GPIO_BASE(x) (S5P_PA_GPIO + (x))
+
+#define S5P_GPIO_A_REG(x) (S5P_GPIO_BASE(0x0) + (x))
+#define S5P_GPIO_B_REG(x) (S5P_GPIO_BASE(0x40) + (x))
+#define S5P_GPIO_C_REG(x) (S5P_GPIO_BASE(0x60) + (x))
+#define S5P_GPIO_D_REG(x) (S5P_GPIO_BASE(0x80) + (x))
+#define S5P_GPIO_E_REG(x) (S5P_GPIO_BASE(0xa0) + (x))
+#define S5P_GPIO_F_REG(x) (S5P_GPIO_BASE(0xe0) + (x))
+#define S5P_GPIO_G_REG(x) (S5P_GPIO_BASE(0x160) + (x))
+#define S5P_GPIO_I_REG(x) (S5P_GPIO_BASE(0x1e0) + (x))
+#define S5P_GPIO_J_REG(x) (S5P_GPIO_BASE(0x200) + (x))
+#define S5P_GPIO_K_REG(x) (S5P_GPIO_BASE(0x2a0) + (x))
+#define S5P_GPIO_L_REG(x) (S5P_GPIO_BASE(0x320) + (x))
+
+#define S5P_MP_REG(x) (S5P_GPIO_BASE(0x3c0) + (x))
+#define S5P_ETC_REG(x) (S5P_GPIO_BASE(0x4e0) + (x))
+
+#define S5P_GPIO_INT_CON_REG(x) (S5P_GPIO_BASE(0x700) + (x))
+#define S5P_GPIO_INT_FLTCON_REG(x) (S5P_GPIO_BASE(0x800) + (x))
+#define S5P_GPIO_INT_MASK_REG(x) (S5P_GPIO_BASE(0x900) + (x))
+#define S5P_GPIO_INT_PEND_REG(x) (S5P_GPIO_BASE(0xa00) + (x))
+#define S5P_GPIO_INT_PRIO_REG(x) (S5P_GPIO_BASE(0xb00) + (x))
+
+#define S5P_GPIO_H_REG(x) (S5P_GPIO_BASE(0xc00) + (x))
+
+#define S5P_WAKEUP_INT_CON(x) (S5P_GPIO_BASE(0xe00) + (x))
+#define S5P_WAKEUP_FLTINT_CON(x) (S5P_GPIO_BASE(0xe80) + (x))
+#define S5P_WAKEUP_INT_MASK(x) (S5P_GPIO_BASE(0xf00) + (x))
+#define S5P_WAKEUP_INT_PEND(x) (S5P_GPIO_BASE(0xf40) + (x))
+
+
+/* GPIO Offset */
+#define CON_OFFSET 0x0
+#define DAT_OFFSET 0x4
+#define PULL_OFFSET 0x8
+#define DRV_OFFSET 0xc
+#define PDNCON_OFFSET 0x10
+#define PDNPULL_OFFSET 0x14
+
+
+/* GPIO A Bank Base */
+#define S5P_GPIO_A0_BASE(x) (S5P_GPIO_A_REG(0x0) + (x))
+#define S5P_GPIO_A1_BASE(x) (S5P_GPIO_A_REG(0x20) + (x))
+
+#define S5P_GPIO_A0_CON S5P_GPIO_A0_BASE(CON_OFFSET)
+#define S5P_GPIO_A0_DAT S5P_GPIO_A0_BASE(DAT_OFFSET)
+#define S5P_GPIO_A0_PULL S5P_GPIO_A0_BASE(PULL_OFFSET)
+#define S5P_GPIO_A0_DRV S5P_GPIO_A0_BASE(DRV_OFFSET)
+#define S5P_GPIO_A0_PDNCON S5P_GPIO_A0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_A0_PDNPUL S5P_GPIO_A0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_A1_CON S5P_GPIO_A1_BASE(CON_OFFSET)
+#define S5P_GPIO_A1_DAT S5P_GPIO_A1_BASE(DAT_OFFSET)
+#define S5P_GPIO_A1_PULL S5P_GPIO_A1_BASE(PULL_OFFSET)
+#define S5P_GPIO_A1_DRV S5P_GPIO_A1_BASE(DRV_OFFSET)
+#define S5P_GPIO_A1_PDNCON S5P_GPIO_A1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_A1_PDNPUL S5P_GPIO_A1_BASE(PDNPULL_OFFSET)
+
+/* GPIO B Bank Base */
+#define S5P_GPIO_B_BASE(x) (S5P_GPIO_B_REG(0x0) + (x))
+
+#define S5P_GPIO_B_CON S5P_GPIO_B_BASE(CON_OFFSET)
+#define S5P_GPIO_B_DAT S5P_GPIO_B_BASE(DAT_OFFSET)
+#define S5P_GPIO_B_PULL S5P_GPIO_B_BASE(PULL_OFFSET)
+#define S5P_GPIO_B_DRV S5P_GPIO_B_BASE(DRV_OFFSET)
+#define S5P_GPIO_B_PDNCON S5P_GPIO_B_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_B_PDNPUL S5P_GPIO_B_BASE(PDNPULL_OFFSET)
+
+/* GPIO C Bank Base */
+#define S5P_GPIO_C_BASE(x) (S5P_GPIO_C_REG(0x0) + (x))
+
+#define S5P_GPIO_C_CON S5P_GPIO_C_BASE(CON_OFFSET)
+#define S5P_GPIO_C_DAT S5P_GPIO_C_BASE(DAT_OFFSET)
+#define S5P_GPIO_C_PULL S5P_GPIO_C_BASE(PULL_OFFSET)
+#define S5P_GPIO_C_DRV S5P_GPIO_C_BASE(DRV_OFFSET)
+#define S5P_GPIO_C_PDNCON S5P_GPIO_C_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_C_PDNPUL S5P_GPIO_C_BASE(PDNPULL_OFFSET)
+
+/* GPIO D Bank Base */
+#define S5P_GPIO_D_BASE(x) (S5P_GPIO_C_REG(0x0) + (x))
+
+#define S5P_GPIO_D_CON S5P_GPIO_C_BASE(CON_OFFSET)
+#define S5P_GPIO_D_DAT S5P_GPIO_C_BASE(DAT_OFFSET)
+#define S5P_GPIO_D_PULL S5P_GPIO_C_BASE(PULL_OFFSET)
+#define S5P_GPIO_D_DRV S5P_GPIO_C_BASE(DRV_OFFSET)
+#define S5P_GPIO_D_PDNCON S5P_GPIO_C_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_D_PDNPUL S5P_GPIO_C_BASE(PDNPULL_OFFSET)
+
+/* GPIO E Bank Base */
+#define S5P_GPIO_E0_BASE(x) (S5P_GPIO_E_REG(0x0) + (x))
+#define S5P_GPIO_E1_BASE(x) (S5P_GPIO_E_REG(0x20) + (x))
+
+#define S5P_GPIO_E0_CON S5P_GPIO_E0_BASE(CON_OFFSET)
+#define S5P_GPIO_E0_DAT S5P_GPIO_E0_BASE(DAT_OFFSET)
+#define S5P_GPIO_E0_PULL S5P_GPIO_E0_BASE(PULL_OFFSET)
+#define S5P_GPIO_E0_DRV S5P_GPIO_E0_BASE(DRV_OFFSET)
+#define S5P_GPIO_E0_PDNCON S5P_GPIO_E0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_E0_PDNPUL S5P_GPIO_E0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_E1_CON S5P_GPIO_E1_BASE(CON_OFFSET)
+#define S5P_GPIO_E1_DAT S5P_GPIO_E1_BASE(DAT_OFFSET)
+#define S5P_GPIO_E1_PULL S5P_GPIO_E1_BASE(PULL_OFFSET)
+#define S5P_GPIO_E1_DRV S5P_GPIO_E1_BASE(DRV_OFFSET)
+#define S5P_GPIO_E1_PDNCON S5P_GPIO_E1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_E1_PDNPUL S5P_GPIO_E1_BASE(PDNPULL_OFFSET)
+
+/* GPIO F Bank Base */
+#define S5P_GPIO_F0_BASE(x) (S5P_GPIO_F_REG(0x0) + (x))
+#define S5P_GPIO_F1_BASE(x) (S5P_GPIO_F_REG(0x20) + (x))
+#define S5P_GPIO_F2_BASE(x) (S5P_GPIO_F_REG(0x40) + (x))
+#define S5P_GPIO_F3_BASE(x) (S5P_GPIO_F_REG(0x60) + (x))
+
+#define S5P_GPIO_F0_CON S5P_GPIO_F0_BASE(CON_OFFSET)
+#define S5P_GPIO_F0_DAT S5P_GPIO_F0_BASE(DAT_OFFSET)
+#define S5P_GPIO_F0_PULL S5P_GPIO_F0_BASE(PULL_OFFSET)
+#define S5P_GPIO_F0_DRV S5P_GPIO_F0_BASE(DRV_OFFSET)
+#define S5P_GPIO_F0_PDNCON S5P_GPIO_F0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_F0_PDNPUL S5P_GPIO_F0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_F1_CON S5P_GPIO_F1_BASE(CON_OFFSET)
+#define S5P_GPIO_F1_DAT S5P_GPIO_F1_BASE(DAT_OFFSET)
+#define S5P_GPIO_F1_PULL S5P_GPIO_F1_BASE(PULL_OFFSET)
+#define S5P_GPIO_F1_DRV S5P_GPIO_F1_BASE(DRV_OFFSET)
+#define S5P_GPIO_F1_PDNCON S5P_GPIO_F1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_F1_PDNPUL S5P_GPIO_F1_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_F2_CON S5P_GPIO_F2_BASE(CON_OFFSET)
+#define S5P_GPIO_F2_DAT S5P_GPIO_F2_BASE(DAT_OFFSET)
+#define S5P_GPIO_F2_PULL S5P_GPIO_F2_BASE(PULL_OFFSET)
+#define S5P_GPIO_F2_DRV S5P_GPIO_F2_BASE(DRV_OFFSET)
+#define S5P_GPIO_F2_PDNCON S5P_GPIO_F2_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_F2_PDNPUL S5P_GPIO_F2_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_F3_CON S5P_GPIO_F3_BASE(CON_OFFSET)
+#define S5P_GPIO_F3_DAT S5P_GPIO_F3_BASE(DAT_OFFSET)
+#define S5P_GPIO_F3_PULL S5P_GPIO_F3_BASE(PULL_OFFSET)
+#define S5P_GPIO_F3_DRV S5P_GPIO_F3_BASE(DRV_OFFSET)
+#define S5P_GPIO_F3_PDNCON S5P_GPIO_F3_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_F3_PDNPUL S5P_GPIO_F3_BASE(PDNPULL_OFFSET)
+
+/* GPIO G Bank Base */
+#define S5P_GPIO_G0_BASE(x) (S5P_GPIO_G_REG(0x0) + (x))
+#define S5P_GPIO_G1_BASE(x) (S5P_GPIO_G_REG(0x20) + (x))
+#define S5P_GPIO_G2_BASE(x) (S5P_GPIO_G_REG(0x40) + (x))
+#define S5P_GPIO_G3_BASE(x) (S5P_GPIO_G_REG(0x60) + (x))
+
+#define S5P_GPIO_G0_CON S5P_GPIO_G0_BASE(CON_OFFSET)
+#define S5P_GPIO_G0_DAT S5P_GPIO_G0_BASE(DAT_OFFSET)
+#define S5P_GPIO_G0_PULL S5P_GPIO_G0_BASE(PULL_OFFSET)
+#define S5P_GPIO_G0_DRV S5P_GPIO_G0_BASE(DRV_OFFSET)
+#define S5P_GPIO_G0_PDNCON S5P_GPIO_G0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_G0_PDNPUL S5P_GPIO_G0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_G1_CON S5P_GPIO_G1_BASE(CON_OFFSET)
+#define S5P_GPIO_G1_DAT S5P_GPIO_G1_BASE(DAT_OFFSET)
+#define S5P_GPIO_G1_PULL S5P_GPIO_G1_BASE(PULL_OFFSET)
+#define S5P_GPIO_G1_DRV S5P_GPIO_G1_BASE(DRV_OFFSET)
+#define S5P_GPIO_G1_PDNCON S5P_GPIO_G1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_G1_PDNPUL S5P_GPIO_G1_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_G2_CON S5P_GPIO_G2_BASE(CON_OFFSET)
+#define S5P_GPIO_G2_DAT S5P_GPIO_G2_BASE(DAT_OFFSET)
+#define S5P_GPIO_G2_PULL S5P_GPIO_G2_BASE(PULL_OFFSET)
+#define S5P_GPIO_G2_DRV S5P_GPIO_G2_BASE(DRV_OFFSET)
+#define S5P_GPIO_G2_PDNCON S5P_GPIO_G2_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_G2_PDNPUL S5P_GPIO_G2_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_G3_CON S5P_GPIO_G3_BASE(CON_OFFSET)
+#define S5P_GPIO_G3_DAT S5P_GPIO_G3_BASE(DAT_OFFSET)
+#define S5P_GPIO_G3_PULL S5P_GPIO_G3_BASE(PULL_OFFSET)
+#define S5P_GPIO_G3_DRV S5P_GPIO_G3_BASE(DRV_OFFSET)
+#define S5P_GPIO_G3_PDNCON S5P_GPIO_G3_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_G3_PDNPUL S5P_GPIO_G3_BASE(PDNPULL_OFFSET)
+
+/* GPIO I Bank Base */
+#define S5P_GPIO_I_BASE(x) (S5P_GPIO_I_REG(0x0) + (x))
+
+#define S5P_GPIO_I_CON S5P_GPIO_I_BASE(CON_OFFSET)
+#define S5P_GPIO_I_DAT S5P_GPIO_I_BASE(DAT_OFFSET)
+#define S5P_GPIO_I_PULL S5P_GPIO_I_BASE(PULL_OFFSET)
+#define S5P_GPIO_I_DRV S5P_GPIO_I_BASE(DRV_OFFSET)
+#define S5P_GPIO_I_PDNCON S5P_GPIO_I_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_I_PDNPUL S5P_GPIO_I_BASE(PDNPULL_OFFSET)
+
+/* GPIO J Bank Base */
+#define S5P_GPIO_J0_BASE(x) (S5P_GPIO_J_REG(0x0) + (x))
+#define S5P_GPIO_J1_BASE(x) (S5P_GPIO_J_REG(0x20) + (x))
+#define S5P_GPIO_J2_BASE(x) (S5P_GPIO_J_REG(0x40) + (x))
+#define S5P_GPIO_J3_BASE(x) (S5P_GPIO_J_REG(0x60) + (x))
+#define S5P_GPIO_J4_BASE(x) (S5P_GPIO_J_REG(0x80) + (x))
+
+#define S5P_GPIO_J0_CON S5P_GPIO_J0_BASE(CON_OFFSET)
+#define S5P_GPIO_J0_DAT S5P_GPIO_J0_BASE(DAT_OFFSET)
+#define S5P_GPIO_J0_PULL S5P_GPIO_J0_BASE(PULL_OFFSET)
+#define S5P_GPIO_J0_DRV S5P_GPIO_J0_BASE(DRV_OFFSET)
+#define S5P_GPIO_J0_PDNCON S5P_GPIO_J0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_J0_PDNPUL S5P_GPIO_J0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_J1_CON S5P_GPIO_J1_BASE(CON_OFFSET)
+#define S5P_GPIO_J1_DAT S5P_GPIO_J1_BASE(DAT_OFFSET)
+#define S5P_GPIO_J1_PULL S5P_GPIO_J1_BASE(PULL_OFFSET)
+#define S5P_GPIO_J1_DRV S5P_GPIO_J1_BASE(DRV_OFFSET)
+#define S5P_GPIO_J1_PDNCON S5P_GPIO_J1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_J1_PDNPUL S5P_GPIO_J1_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_J2_CON S5P_GPIO_J2_BASE(CON_OFFSET)
+#define S5P_GPIO_J2_DAT S5P_GPIO_J2_BASE(DAT_OFFSET)
+#define S5P_GPIO_J2_PULL S5P_GPIO_J2_BASE(PULL_OFFSET)
+#define S5P_GPIO_J2_DRV S5P_GPIO_J2_BASE(DRV_OFFSET)
+#define S5P_GPIO_J2_PDNCON S5P_GPIO_J2_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_J2_PDNPUL S5P_GPIO_J2_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_J3_CON S5P_GPIO_J3_BASE(CON_OFFSET)
+#define S5P_GPIO_J3_DAT S5P_GPIO_J3_BASE(DAT_OFFSET)
+#define S5P_GPIO_J3_PULL S5P_GPIO_J3_BASE(PULL_OFFSET)
+#define S5P_GPIO_J3_DRV S5P_GPIO_J3_BASE(DRV_OFFSET)
+#define S5P_GPIO_J3_PDNCON S5P_GPIO_J3_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_J3_PDNPUL S5P_GPIO_J3_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_J4_CON S5P_GPIO_J4_BASE(CON_OFFSET)
+#define S5P_GPIO_J4_DAT S5P_GPIO_J4_BASE(DAT_OFFSET)
+#define S5P_GPIO_J4_PULL S5P_GPIO_J4_BASE(PULL_OFFSET)
+#define S5P_GPIO_J4_DRV S5P_GPIO_J4_BASE(DRV_OFFSET)
+#define S5P_GPIO_J4_PDNCON S5P_GPIO_J4_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_J4_PDNPUL S5P_GPIO_J4_BASE(PDNPULL_OFFSET)
+
+/* GPIO K Bank Base */
+#define S5P_GPIO_K0_BASE(x) (S5P_GPIO_K_REG(0x0) + (x))
+#define S5P_GPIO_K1_BASE(x) (S5P_GPIO_K_REG(0x20) + (x))
+#define S5P_GPIO_K2_BASE(x) (S5P_GPIO_K_REG(0x40) + (x))
+#define S5P_GPIO_K3_BASE(x) (S5P_GPIO_K_REG(0x60) + (x))
+
+#define S5P_GPIO_K0_CON S5P_GPIO_K0_BASE(CON_OFFSET)
+#define S5P_GPIO_K0_DAT S5P_GPIO_K0_BASE(DAT_OFFSET)
+#define S5P_GPIO_K0_PULL S5P_GPIO_K0_BASE(PULL_OFFSET)
+#define S5P_GPIO_K0_DRV S5P_GPIO_K0_BASE(DRV_OFFSET)
+#define S5P_GPIO_K0_PDNCON S5P_GPIO_K0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_K0_PDNPUL S5P_GPIO_K0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_K1_CON S5P_GPIO_K1_BASE(CON_OFFSET)
+#define S5P_GPIO_K1_DAT S5P_GPIO_K1_BASE(DAT_OFFSET)
+#define S5P_GPIO_K1_PULL S5P_GPIO_K1_BASE(PULL_OFFSET)
+#define S5P_GPIO_K1_DRV S5P_GPIO_K1_BASE(DRV_OFFSET)
+#define S5P_GPIO_K1_PDNCON S5P_GPIO_K1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_K1_PDNPUL S5P_GPIO_K1_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_K2_CON S5P_GPIO_K2_BASE(CON_OFFSET)
+#define S5P_GPIO_K2_DAT S5P_GPIO_K2_BASE(DAT_OFFSET)
+#define S5P_GPIO_K2_PULL S5P_GPIO_K2_BASE(PULL_OFFSET)
+#define S5P_GPIO_K2_DRV S5P_GPIO_K2_BASE(DRV_OFFSET)
+#define S5P_GPIO_K2_PDNCON S5P_GPIO_K2_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_K2_PDNPUL S5P_GPIO_K2_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_K3_CON S5P_GPIO_K3_BASE(CON_OFFSET)
+#define S5P_GPIO_K3_DAT S5P_GPIO_K3_BASE(DAT_OFFSET)
+#define S5P_GPIO_K3_PULL S5P_GPIO_K3_BASE(PULL_OFFSET)
+#define S5P_GPIO_K3_DRV S5P_GPIO_K3_BASE(DRV_OFFSET)
+#define S5P_GPIO_K3_PDNCON S5P_GPIO_K3_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_K3_PDNPUL S5P_GPIO_K3_BASE(PDNPULL_OFFSET)
+
+/* GPIO L Bank */
+#define S5P_GPIO_L0_BASE(x) (S5P_GPIO_L_REG(0x0) + (x))
+#define S5P_GPIO_L1_BASE(x) (S5P_GPIO_L_REG(0x20) + (x))
+#define S5P_GPIO_L2_BASE(x) (S5P_GPIO_L_REG(0x40) + (x))
+#define S5P_GPIO_L3_BASE(x) (S5P_GPIO_L_REG(0x60) + (x))
+#define S5P_GPIO_L4_BASE(x) (S5P_GPIO_L_REG(0x80) + (x))
+
+#define S5P_GPIO_L0_CON S5P_GPIO_L0_BASE(CON_OFFSET)
+#define S5P_GPIO_L0_DAT S5P_GPIO_L0_BASE(DAT_OFFSET)
+#define S5P_GPIO_L0_PULL S5P_GPIO_L0_BASE(PULL_OFFSET)
+#define S5P_GPIO_L0_DRV S5P_GPIO_L0_BASE(DRV_OFFSET)
+#define S5P_GPIO_L0_PDNCON S5P_GPIO_L0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_L0_PDNPUL S5P_GPIO_L0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_L1_CON S5P_GPIO_L1_BASE(CON_OFFSET)
+#define S5P_GPIO_L1_DAT S5P_GPIO_L1_BASE(DAT_OFFSET)
+#define S5P_GPIO_L1_PULL S5P_GPIO_L1_BASE(PULL_OFFSET)
+#define S5P_GPIO_L1_DRV S5P_GPIO_L1_BASE(DRV_OFFSET)
+#define S5P_GPIO_L1_PDNCON S5P_GPIO_L1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_L1_PDNPUL S5P_GPIO_L1_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_L2_CON S5P_GPIO_L2_BASE(CON_OFFSET)
+#define S5P_GPIO_L2_DAT S5P_GPIO_L2_BASE(DAT_OFFSET)
+#define S5P_GPIO_L2_PULL S5P_GPIO_L2_BASE(PULL_OFFSET)
+#define S5P_GPIO_L2_DRV S5P_GPIO_L2_BASE(DRV_OFFSET)
+#define S5P_GPIO_L2_PDNCON S5P_GPIO_L2_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_L2_PDNPUL S5P_GPIO_L2_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_L3_CON S5P_GPIO_L3_BASE(CON_OFFSET)
+#define S5P_GPIO_L3_DAT S5P_GPIO_L3_BASE(DAT_OFFSET)
+#define S5P_GPIO_L3_PULL S5P_GPIO_L3_BASE(PULL_OFFSET)
+#define S5P_GPIO_L3_DRV S5P_GPIO_L3_BASE(DRV_OFFSET)
+#define S5P_GPIO_L3_PDNCON S5P_GPIO_L3_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_L3_PDNPUL S5P_GPIO_L3_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_L4_CON S5P_GPIO_L4_BASE(CON_OFFSET)
+#define S5P_GPIO_L4_DAT S5P_GPIO_L4_BASE(DAT_OFFSET)
+#define S5P_GPIO_L4_PULL S5P_GPIO_L4_BASE(PULL_OFFSET)
+#define S5P_GPIO_L4_DRV S5P_GPIO_L4_BASE(DRV_OFFSET)
+#define S5P_GPIO_L4_PDNCON S5P_GPIO_L4_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_L4_PDNPUL S5P_GPIO_L4_BASE(PDNPULL_OFFSET)
+
+/* GPIO MP Bank */
+#define S5P_MP_0_OFFSET 0x0
+#define S5P_MP_1_OFFSET 0x20
+#define S5P_MP_2_OFFSET 0x40
+#define S5P_MP_3_OFFSET 0x60
+#define S5P_MP_4_OFFSET 0x80
+#define S5P_MP_5_OFFSET 0xa0
+#define S5P_MP_6_OFFSET 0xc0
+#define S5P_MP_7_OFFSET 0xe0
+
+#define S5P_MP_0_BASE(x) (S5P_MP_REG(S5P_MP_0_OFFSET) + (x))
+#define S5P_MP_1_BASE(x) (S5P_MP_REG(S5P_MP_1_OFFSET) + (x))
+#define S5P_MP_2_BASE(x) (S5P_MP_REG(S5P_MP_2_OFFSET) + (x))
+#define S5P_MP_3_BASE(x) (S5P_MP_REG(S5P_MP_3_OFFSET) + (x))
+#define S5P_MP_4_BASE(x) (S5P_MP_REG(S5P_MP_4_OFFSET) + (x))
+#define S5P_MP_5_BASE(x) (S5P_MP_REG(S5P_MP_5_OFFSET) + (x))
+#define S5P_MP_6_BASE(x) (S5P_MP_REG(S5P_MP_6_OFFSET) + (x))
+#define S5P_MP_7_BASE(x) (S5P_MP_REG(S5P_MP_7_OFFSET) + (x))
+
+#define S5P_MP_0PULL S5P_MP_0_BASE(PULL_OFFSET)
+#define S5P_MP_0DRV S5P_MP_0_BASE(DRV_OFFSET)
+#define S5P_MP_0PDNPULL S5P_MP_0_BASE(PDNPULL_OFFSET)
+
+#define S5P_MP_1PULL S5P_MP_1_BASE(PULL_OFFSET)
+#define S5P_MP_1DRV S5P_MP_1_BASE(DRV_OFFSET)
+#define S5P_MP_1PDNPULL S5P_MP_1_BASE(PDNPULL_OFFSET)
+
+#define S5P_MP_2PULL S5P_MP_2_BASE(PULL_OFFSET)
+#define S5P_MP_2DRV S5P_MP_2_BASE(DRV_OFFSET)
+#define S5P_MP_2PDNPULL S5P_MP_2_BASE(PDNPULL_OFFSET)
+
+#define S5P_MP_3DRV S5P_MP_3_BASE(DRV_OFFSET)
+#define S5P_MP_4DRV S5P_MP_4_BASE(DRV_OFFSET)
+#define S5P_MP_5DRV S5P_MP_5_BASE(DRV_OFFSET)
+#define S5P_MP_6DRV S5P_MP_6_BASE(DRV_OFFSET)
+#define S5P_MP_7DRV S5P_MP_7_BASE(DRV_OFFSET)
+#define S5P_MP_8DRV S5P_MP_8_BASE(DRV_OFFSET)
+
+/* GPIO ETC Bank */
+#define S5P_ETC0_BASE(x) (S5P_ETC_REG(0x0) + (x))
+#define S5P_ETC1_BASE(x) (S5P_ETC_REG(0x20) + (x))
+#define S5P_ETC2_BASE(x) (S5P_ETC_REG(0x40) + (x))
+#define S5P_ETC3_BASE(x) (S5P_ETC_REG(0x60) + (x))
+#define S5P_ETC4_BASE(x) (S5P_ETC_REG(0x80) + (x))
+
+#define S5P_ETC0PULL S5P_ETC0_BASE(PULL_OFFSET)
+#define S5P_ETC0DRV S5P_ETC0_BASE(DRV_OFFSET)
+#define S5P_ETC1PULL S5P_ETC1_BASE(PULL_OFFSET)
+#define S5P_ETC1DRV S5P_ETC1_BASE(DRV_OFFSET)
+#define S5P_ETC2PULL S5P_ETC2_BASE(PULL_OFFSET)
+#define S5P_ETC2DRV S5P_ETC2_BASE(DRV_OFFSET)
+#define S5P_ETC3PULL S5P_ETC3_BASE(PULL_OFFSET)
+#define S5P_ETC3DRV S5P_ETC3_BASE(DRV_OFFSET)
+#define S5P_ETC4DRV S5P_ETC4_BASE(DRV_OFFSET)
+
+/* GPIO External Interrupt */
+#define S5P_GPIO_INT0_CON S5P_GPIO_INT_CON_REG(0x0)
+#define S5P_GPIO_INT1_CON S5P_GPIO_INT_CON_REG(0x4)
+#define S5P_GPIO_INT2_CON S5P_GPIO_INT_CON_REG(0x8)
+#define S5P_GPIO_INT3_CON S5P_GPIO_INT_CON_REG(0xc)
+#define S5P_GPIO_INT4_CON S5P_GPIO_INT_CON_REG(0x10)
+#define S5P_GPIO_INT5_CON S5P_GPIO_INT_CON_REG(0x14)
+#define S5P_GPIO_INT6_CON S5P_GPIO_INT_CON_REG(0x18)
+#define S5P_GPIO_INT7_CON S5P_GPIO_INT_CON_REG(0x1c)
+#define S5P_GPIO_INT8_CON S5P_GPIO_INT_CON_REG(0x20)
+#define S5P_GPIO_INT9_CON S5P_GPIO_INT_CON_REG(0x24)
+#define S5P_GPIO_INT10_CON S5P_GPIO_INT_CON_REG(0x28)
+#define S5P_GPIO_INT11_CON S5P_GPIO_INT_CON_REG(0x2c)
+#define S5P_GPIO_INT12_CON S5P_GPIO_INT_CON_REG(0x30)
+#define S5P_GPIO_INT13_CON S5P_GPIO_INT_CON_REG(0x34)
+#define S5P_GPIO_INT14_CON S5P_GPIO_INT_CON_REG(0x38)
+#define S5P_GPIO_INT15_CON S5P_GPIO_INT_CON_REG(0x3c)
+#define S5P_GPIO_INT16_CON S5P_GPIO_INT_CON_REG(0x40)
+#define S5P_GPIO_INT17_CON S5P_GPIO_INT_CON_REG(0x44)
+#define S5P_GPIO_INT18_CON S5P_GPIO_INT_CON_REG(0x48)
+#define S5P_GPIO_INT19_CON S5P_GPIO_INT_CON_REG(0x4c)
+#define S5P_GPIO_INT20_CON S5P_GPIO_INT_CON_REG(0x50)
+
+#define S5P_GPIO_INT0_FLTCON0 S5P_GPIO_INT_CON_REG(0x0)
+#define S5P_GPIO_INT0_FLTCON1 S5P_GPIO_INT_CON_REG(0x4)
+#define S5P_GPIO_INT1_FLTCON0 S5P_GPIO_INT_CON_REG(0x8)
+#define S5P_GPIO_INT1_FLTCON1 S5P_GPIO_INT_CON_REG(0xc)
+#define S5P_GPIO_INT2_FLTCON0 S5P_GPIO_INT_CON_REG(0x10)
+#define S5P_GPIO_INT2_FLTCON1 S5P_GPIO_INT_CON_REG(0x14)
+#define S5P_GPIO_INT3_FLTCON0 S5P_GPIO_INT_CON_REG(0x18)
+#define S5P_GPIO_INT3_FLTCON1 S5P_GPIO_INT_CON_REG(0x1c)
+#define S5P_GPIO_INT4_FLTCON0 S5P_GPIO_INT_CON_REG(0x20)
+#define S5P_GPIO_INT4_FLTCON1 S5P_GPIO_INT_CON_REG(0x24)
+#define S5P_GPIO_INT5_FLTCON0 S5P_GPIO_INT_CON_REG(0x28)
+#define S5P_GPIO_INT5_FLTCON1 S5P_GPIO_INT_CON_REG(0x2c)
+#define S5P_GPIO_INT6_FLTCON0 S5P_GPIO_INT_CON_REG(0x30)
+#define S5P_GPIO_INT6_FLTCON1 S5P_GPIO_INT_CON_REG(0x34)
+#define S5P_GPIO_INT7_FLTCON0 S5P_GPIO_INT_CON_REG(0x38)
+#define S5P_GPIO_INT7_FLTCON1 S5P_GPIO_INT_CON_REG(0x3c)
+#define S5P_GPIO_INT8_FLTCON0 S5P_GPIO_INT_CON_REG(0x40)
+#define S5P_GPIO_INT8_FLTCON1 S5P_GPIO_INT_CON_REG(0x44)
+#define S5P_GPIO_INT9_FLTCON0 S5P_GPIO_INT_CON_REG(0x48)
+#define S5P_GPIO_INT9_FLTCON1 S5P_GPIO_INT_CON_REG(0x4c)
+#define S5P_GPIO_INT10_FLTCON0 S5P_GPIO_INT_CON_REG(0x50)
+#define S5P_GPIO_INT11_FLTCON0 S5P_GPIO_INT_CON_REG(0x58)
+#define S5P_GPIO_INT11_FLTCON1 S5P_GPIO_INT_CON_REG(0x5c)
+#define S5P_GPIO_INT12_FLTCON0 S5P_GPIO_INT_CON_REG(0x60)
+#define S5P_GPIO_INT13_FLTCON0 S5P_GPIO_INT_CON_REG(0x68)
+#define S5P_GPIO_INT13_FLTCON1 S5P_GPIO_INT_CON_REG(0x6c)
+#define S5P_GPIO_INT14_FLTCON0 S5P_GPIO_INT_CON_REG(0x70)
+#define S5P_GPIO_INT14_FLTCON1 S5P_GPIO_INT_CON_REG(0x74)
+#define S5P_GPIO_INT15_FLTCON0 S5P_GPIO_INT_CON_REG(0x78)
+#define S5P_GPIO_INT15_FLTCON1 S5P_GPIO_INT_CON_REG(0x7c)
+#define S5P_GPIO_INT16_FLTCON0 S5P_GPIO_INT_CON_REG(0x80)
+#define S5P_GPIO_INT16_FLTCON1 S5P_GPIO_INT_CON_REG(0x84)
+#define S5P_GPIO_INT17_FLTCON0 S5P_GPIO_INT_CON_REG(0x88)
+#define S5P_GPIO_INT17_FLTCON1 S5P_GPIO_INT_CON_REG(0x8c)
+#define S5P_GPIO_INT18_FLTCON0 S5P_GPIO_INT_CON_REG(0x90)
+#define S5P_GPIO_INT18_FLTCON1 S5P_GPIO_INT_CON_REG(0x94)
+#define S5P_GPIO_INT19_FLTCON0 S5P_GPIO_INT_CON_REG(0x98)
+#define S5P_GPIO_INT19_FLTCON1 S5P_GPIO_INT_CON_REG(0x9c)
+#define S5P_GPIO_INT20_FLTCON0 S5P_GPIO_INT_CON_REG(0xa0)
+
+#define S5P_GPIO_INT0_MASK S5P_GPIO_INT_MASK_REG(0x00)
+#define S5P_GPIO_INT1_MASK S5P_GPIO_INT_MASK_REG(0x04)
+#define S5P_GPIO_INT2_MASK S5P_GPIO_INT_MASK_REG(0x08)
+#define S5P_GPIO_INT3_MASK S5P_GPIO_INT_MASK_REG(0x0c)
+#define S5P_GPIO_INT4_MASK S5P_GPIO_INT_MASK_REG(0x10)
+#define S5P_GPIO_INT5_MASK S5P_GPIO_INT_MASK_REG(0x14)
+#define S5P_GPIO_INT6_MASK S5P_GPIO_INT_MASK_REG(0x18)
+#define S5P_GPIO_INT7_MASK S5P_GPIO_INT_MASK_REG(0x1c)
+#define S5P_GPIO_INT8_MASK S5P_GPIO_INT_MASK_REG(0x20)
+#define S5P_GPIO_INT9_MASK S5P_GPIO_INT_MASK_REG(0x24)
+#define S5P_GPIO_INT10_MASK S5P_GPIO_INT_MASK_REG(0x28)
+#define S5P_GPIO_INT11_MASK S5P_GPIO_INT_MASK_REG(0x2c)
+#define S5P_GPIO_INT12_MASK S5P_GPIO_INT_MASK_REG(0x30)
+#define S5P_GPIO_INT13_MASK S5P_GPIO_INT_MASK_REG(0x34)
+#define S5P_GPIO_INT14_MASK S5P_GPIO_INT_MASK_REG(0x38)
+#define S5P_GPIO_INT15_MASK S5P_GPIO_INT_MASK_REG(0x3c)
+#define S5P_GPIO_INT16_MASK S5P_GPIO_INT_MASK_REG(0x40)
+#define S5P_GPIO_INT17_MASK S5P_GPIO_INT_MASK_REG(0x44)
+#define S5P_GPIO_INT18_MASK S5P_GPIO_INT_MASK_REG(0x48)
+#define S5P_GPIO_INT19_MASK S5P_GPIO_INT_MASK_REG(0x4c)
+#define S5P_GPIO_INT20_MASK S5P_GPIO_INT_MASK_REG(0x50)
+
+#define S5P_GPIO_INT0_PEND S5P_GPIO_INT_PEND_REG(0x00)
+#define S5P_GPIO_INT1_PEND S5P_GPIO_INT_PEND_REG(0x04)
+#define S5P_GPIO_INT2_PEND S5P_GPIO_INT_PEND_REG(0x08)
+#define S5P_GPIO_INT3_PEND S5P_GPIO_INT_PEND_REG(0x0c)
+#define S5P_GPIO_INT4_PEND S5P_GPIO_INT_PEND_REG(0x10)
+#define S5P_GPIO_INT5_PEND S5P_GPIO_INT_PEND_REG(0x14)
+#define S5P_GPIO_INT6_PEND S5P_GPIO_INT_PEND_REG(0x18)
+#define S5P_GPIO_INT7_PEND S5P_GPIO_INT_PEND_REG(0x1c)
+#define S5P_GPIO_INT8_PEND S5P_GPIO_INT_PEND_REG(0x20)
+#define S5P_GPIO_INT9_PEND S5P_GPIO_INT_PEND_REG(0x24)
+#define S5P_GPIO_INT10_PEND S5P_GPIO_INT_PEND_REG(0x28)
+#define S5P_GPIO_INT11_PEND S5P_GPIO_INT_PEND_REG(0x2c)
+#define S5P_GPIO_INT12_PEND S5P_GPIO_INT_PEND_REG(0x30)
+#define S5P_GPIO_INT13_PEND S5P_GPIO_INT_PEND_REG(0x34)
+#define S5P_GPIO_INT14_PEND S5P_GPIO_INT_PEND_REG(0x38)
+#define S5P_GPIO_INT15_PEND S5P_GPIO_INT_PEND_REG(0x3c)
+#define S5P_GPIO_INT16_PEND S5P_GPIO_INT_PEND_REG(0x40)
+#define S5P_GPIO_INT17_PEND S5P_GPIO_INT_PEND_REG(0x44)
+#define S5P_GPIO_INT18_PEND S5P_GPIO_INT_PEND_REG(0x48)
+#define S5P_GPIO_INT19_PEND S5P_GPIO_INT_PEND_REG(0x4c)
+#define S5P_GPIO_INT20_PEND S5P_GPIO_INT_PEND_REG(0x50)
+
+#define S5P_GPIO_INT_GRPPRI S5P_GPIO_INT_PRIO_REG(0x00)
+#define S5P_GPIO_INT_PRIORITY S5P_GPIO_INT_PRIO_REG(0x04)
+#define S5P_GPIO_INT_SERVICE S5P_GPIO_INT_PRIO_REG(0x08)
+#define S5P_GPIO_INT_SERVICE_PEND S5P_GPIO_INT_PRIO_REG(0x0c)
+#define S5P_GPIO_INT_GRPFIXPRI S5P_GPIO_INT_PRIO_REG(0x10)
+
+#define S5P_GPIO_INT0_FIXPRI S5P_GPIO_INT_PRIO_REG(0x14)
+#define S5P_GPIO_INT1_FIXPRI S5P_GPIO_INT_PRIO_REG(0x18)
+#define S5P_GPIO_INT2_FIXPRI S5P_GPIO_INT_PRIO_REG(0x1c)
+#define S5P_GPIO_INT3_FIXPRI S5P_GPIO_INT_PRIO_REG(0x20)
+#define S5P_GPIO_INT4_FIXPRI S5P_GPIO_INT_PRIO_REG(0x24)
+#define S5P_GPIO_INT5_FIXPRI S5P_GPIO_INT_PRIO_REG(0x28)
+#define S5P_GPIO_INT6_FIXPRI S5P_GPIO_INT_PRIO_REG(0x2c)
+#define S5P_GPIO_INT7_FIXPRI S5P_GPIO_INT_PRIO_REG(0x30)
+#define S5P_GPIO_INT8_FIXPRI S5P_GPIO_INT_PRIO_REG(0x34)
+#define S5P_GPIO_INT9_FIXPRI S5P_GPIO_INT_PRIO_REG(0x38)
+#define S5P_GPIO_INT10_FIXPRI S5P_GPIO_INT_PRIO_REG(0x3c)
+#define S5P_GPIO_INT11_FIXPRI S5P_GPIO_INT_PRIO_REG(0x40)
+#define S5P_GPIO_INT12_FIXPRI S5P_GPIO_INT_PRIO_REG(0x44)
+#define S5P_GPIO_INT13_FIXPRI S5P_GPIO_INT_PRIO_REG(0x48)
+#define S5P_GPIO_INT14_FIXPRI S5P_GPIO_INT_PRIO_REG(0x4c)
+#define S5P_GPIO_INT15_FIXPRI S5P_GPIO_INT_PRIO_REG(0x50)
+#define S5P_GPIO_INT16_FIXPRI S5P_GPIO_INT_PRIO_REG(0x54)
+#define S5P_GPIO_INT17_FIXPRI S5P_GPIO_INT_PRIO_REG(0x58)
+#define S5P_GPIO_INT18_FIXPRI S5P_GPIO_INT_PRIO_REG(0x5c)
+#define S5P_GPIO_INT19_FIXPRI S5P_GPIO_INT_PRIO_REG(0x60)
+#define S5P_GPIO_INT20_FIXPRI S5P_GPIO_INT_PRIO_REG(0x64)
+
+/* GPIO H Bank Base */
+#define S5P_GPIO_H0_BASE(x) (S5P_GPIO_H_REG(0x0) + (x))
+#define S5P_GPIO_H1_BASE(x) (S5P_GPIO_H_REG(0x20) + (x))
+#define S5P_GPIO_H2_BASE(x) (S5P_GPIO_H_REG(0x40) + (x))
+#define S5P_GPIO_H3_BASE(x) (S5P_GPIO_H_REG(0x60) + (x))
+
+#define S5P_GPIO_H0_CON S5P_GPIO_H0_BASE(CON_OFFSET)
+#define S5P_GPIO_H0_DAT S5P_GPIO_H0_BASE(DAT_OFFSET)
+#define S5P_GPIO_H0_PULL S5P_GPIO_H0_BASE(PULL_OFFSET)
+#define S5P_GPIO_H0_DRV S5P_GPIO_H0_BASE(DRV_OFFSET)
+#define S5P_GPIO_H0_PDNCON S5P_GPIO_H0_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_H0_PDNPUL S5P_GPIO_H0_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_H1_CON S5P_GPIO_H1_BASE(CON_OFFSET)
+#define S5P_GPIO_H1_DAT S5P_GPIO_H1_BASE(DAT_OFFSET)
+#define S5P_GPIO_H1_PULL S5P_GPIO_H1_BASE(PULL_OFFSET)
+#define S5P_GPIO_H1_DRV S5P_GPIO_H1_BASE(DRV_OFFSET)
+#define S5P_GPIO_H1_PDNCON S5P_GPIO_H1_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_H1_PDNPUL S5P_GPIO_H1_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_H2_CON S5P_GPIO_H2_BASE(CON_OFFSET)
+#define S5P_GPIO_H2_DAT S5P_GPIO_H2_BASE(DAT_OFFSET)
+#define S5P_GPIO_H2_PULL S5P_GPIO_H2_BASE(PULL_OFFSET)
+#define S5P_GPIO_H2_DRV S5P_GPIO_H2_BASE(DRV_OFFSET)
+#define S5P_GPIO_H2_PDNCON S5P_GPIO_H2_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_H2_PDNPUL S5P_GPIO_H2_BASE(PDNPULL_OFFSET)
+
+#define S5P_GPIO_H3_CON S5P_GPIO_H3_BASE(CON_OFFSET)
+#define S5P_GPIO_H3_DAT S5P_GPIO_H3_BASE(DAT_OFFSET)
+#define S5P_GPIO_H3_PULL S5P_GPIO_H3_BASE(PULL_OFFSET)
+#define S5P_GPIO_H3_DRV S5P_GPIO_H3_BASE(DRV_OFFSET)
+#define S5P_GPIO_H3_PDNCON S5P_GPIO_H3_BASE(PDNCON_OFFSET)
+#define S5P_GPIO_H3_PDNPUL S5P_GPIO_H3_BASE(PDNPULL_OFFSET)
+
+/* GPIO Wakeup Interrupt Configuration */
+#define S5P_GPIO_WAKEUP_INT0_CON S5P_WAKEUP_INT_CON(0x00)
+#define S5P_GPIO_WAKEUP_INT1_CON S5P_WAKEUP_INT_CON(0x04)
+#define S5P_GPIO_WAKEUP_INT2_CON S5P_WAKEUP_INT_CON(0x08)
+#define S5P_GPIO_WAKEUP_INT3_CON S5P_WAKEUP_INT_CON(0x0c)
+
+/* GPIO Wakeup Interrupt Filter Configuration */
+#define S5P_GPIO_WAKEUP_FLTINT0_CON0 S5P_WAKEUP_FLTINT_CON(0x00)
+#define S5P_GPIO_WAKEUP_FLTINT0_CON1 S5P_WAKEUP_FLTINT_CON(0x04)
+#define S5P_GPIO_WAKEUP_FLTINT1_CON0 S5P_WAKEUP_FLTINT_CON(0x08)
+#define S5P_GPIO_WAKEUP_FLTINT1_CON1 S5P_WAKEUP_FLTINT_CON(0x0c)
+#define S5P_GPIO_WAKEUP_FLTINT2_CON0 S5P_WAKEUP_FLTINT_CON(0x10)
+#define S5P_GPIO_WAKEUP_FLTINT2_CON1 S5P_WAKEUP_FLTINT_CON(0x14)
+#define S5P_GPIO_WAKEUP_FLTINT3_CON0 S5P_WAKEUP_FLTINT_CON(0x18)
+#define S5P_GPIO_WAKEUP_FLTINT3_CON1 S5P_WAKEUP_FLTINT_CON(0x1c)
+
+/* GPIO Wakeup Interrupt Mask */
+#define S5P_GPIO_WAKEUP_INT0_MASK S5P_WAKEUP_INT_MASK(0x00)
+#define S5P_GPIO_WAKEUP_INT1_MASK S5P_WAKEUP_INT_MASK(0x04)
+#define S5P_GPIO_WAKEUP_INT2_MASK S5P_WAKEUP_INT_MASK(0x08)
+#define S5P_GPIO_WAKEUP_INT3_MASK S5P_WAKEUP_INT_MASK(0x0c)
+
+/* GPIO Wakeup Interrupt Pend */
+#define S5P_GPIO_WAKEUP_INT0_PEND S5P_WAKEUP_INT_PEND(0x00)
+#define S5P_GPIO_WAKEUP_INT1_PEND S5P_WAKEUP_INT_PEND(0x04)
+#define S5P_GPIO_WAKEUP_INT2_PEND S5P_WAKEUP_INT_PEND(0x08)
+#define S5P_GPIO_WAKEUP_INT3_PEND S5P_WAKEUP_INT_PEND(0x0c)
+
diff --git a/include/asm-arm/arch-s5pc100/hardware.h
b/include/asm-arm/arch-s5pc100/hardware.h
new file mode 100644
index 0000000..84d24c9
--- /dev/null
+++ b/include/asm-arm/arch-s5pc100/hardware.h
@@ -0,0 +1,63 @@
+/*
+ * Originates from Samsung's u-boot 1.1.6 port to S3C6400 / SMDK6400
+ *
+ * (C) Copyright 2008
+ * Guennadi Liakhovetki, DENX Software Engineering, <lg(a)denx.de>
+ *
+ * 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
+ */
+
+#ifndef _ARCH_HARDWARE_H_
+#define _ARCH_HARDWARE_H_
+
+#include <asm/sizes.h>
+
+#ifndef __ASSEMBLY__
+#define UData(Data) ((unsigned long) (Data))
+
+#define __REG(x) (*(vu_long *)(x))
+#define __REGl(x) (*(vu_long *)(x))
+#define __REGw(x) (*(vu_short *)(x))
+#define __REGb(x) (*(vu_char *)(x))
+#define __REG2(x, y) (*(vu_long *)((x) + (y)))
+#else
+#define UData(Data) (Data)
+
+#define __REG(x) (x)
+#define __REGl(x) (x)
+#define __REGw(x) (x)
+#define __REGb(x) (x)
+#define __REG2(x, y) ((x) + (y))
+#endif
+
+#define Fld(Size, Shft) (((Size) << 16) + (Shft))
+
+#define FSize(Field) ((Field) >> 16)
+#define FShft(Field) ((Field) & 0x0000FFFF)
+#define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field))
+#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1)
+#define F1stBit(Field) (UData (1) << FShft (Field))
+
+#define FClrBit(Data, Bit) (Data = (Data & ~(Bit)))
+#define FClrFld(Data, Field) (Data = (Data & ~FMsk(Field)))
+
+#define FInsrt(Value, Field) \
+ (UData (Value) << FShft (Field))
+
+#define FExtr(Data, Field) \
+ ((UData (Data) >> FShft (Field)) & FAlnMsk (Field))
+
+#endif /* _ARCH_HARDWARE_H_ */
diff --git a/include/asm-arm/arch-s5pc100/sys_proto.h
b/include/asm-arm/arch-s5pc100/sys_proto.h
new file mode 100644
index 0000000..b676ae5
--- /dev/null
+++ b/include/asm-arm/arch-s5pc100/sys_proto.h
@@ -0,0 +1,25 @@
+/*
+ * (C) Copyright 2004-2008
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2(a)ti.com>
+ *
+ * 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
+ */
+
+#ifndef _SYS_PROTO_H_
+#define _SYS_PROTO_H_
+
+#endif
diff --git a/include/asm-arm/arch-s5pc100/uart.h
b/include/asm-arm/arch-s5pc100/uart.h
new file mode 100644
index 0000000..29cedd6
--- /dev/null
+++ b/include/asm-arm/arch-s5pc100/uart.h
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright 2009
+ * Minkyu Kang, SAMSUNG Electronics, <mk7.kang(a)samsung.com>
+ * Heungjun Kim, SAMSUNG Electronics, <riverful.kim(a)samsung.com>
+ * Inki Dae, SAMSUNG Electronics, <inki.dae(a)samsung.com>
+ *
+ * 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
+ */
+
+/*
+ * UART
+ */
+
+/* uart base address */
+#define S5P_PA_UART S5P_ADDR(0x0c000000) /* UART */
+#define UARTx_OFFSET(x) (S5P_PA_UART + x * 0x400)
+#define S5P_UART_BASE (S5P_PA_UART)
+/* uart offset */
+#define ULCON_OFFSET 0x00
+#define UCON_OFFSET 0x04
+#define UFCON_OFFSET 0x08
+#define UMCON_OFFSET 0x0C
+#define UTRSTAT_OFFSET 0x10
+#define UERSTAT_OFFSET 0x14
+#define UFSTAT_OFFSET 0x18
+#define UMSTAT_OFFSET 0x1C
+#define UTXH_OFFSET 0x20
+#define URXH_OFFSET 0x24
+#define UBRDIV_OFFSET 0x28
+#define UDIVSLOT_OFFSET 0x2C
+#define UINTP_OFFSET 0x30
+#define UINTSP_OFFSET 0x34
+#define UINTM_OFFSET 0x38
+
+#define UTRSTAT_TX_EMPTY (1 << 2)
+#define UTRSTAT_RX_READY (1 << 0)
+#define UART_ERR_MASK 0xF
+
+#ifndef __ASSEMBLY__
+typedef struct s5pc1xx_uart {
+ volatile unsigned long ULCON;
+ volatile unsigned long UCON;
+ volatile unsigned long UFCON;
+ volatile unsigned long UMCON;
+ volatile unsigned long UTRSTAT;
+ volatile unsigned long UERSTAT;
+ volatile unsigned long UFSTAT;
+ volatile unsigned long UMSTAT;
+#ifdef __BIG_ENDIAN
+ volatile unsigned char res1[3];
+ volatile unsigned char UTXH;
+ volatile unsigned char res2[3];
+ volatile unsigned char URXH;
+#else /* Little Endian */
+ volatile unsigned char UTXH;
+ volatile unsigned char res1[3];
+ volatile unsigned char URXH;
+ volatile unsigned char res2[3];
+#endif
+ volatile unsigned long UBRDIV;
+#ifdef __BIG_ENDIAN
+ volatile unsigned char res3[2];
+ volatile unsigned short UDIVSLOT;
+#else
+ volatile unsigned short UDIVSLOT;
+ volatile unsigned char res3[2];
+#endif
+} s5pc1xx_uart_t;
+
+enum s5pc1xx_uarts_nr {
+ S5PC1XX_UART0,
+ S5PC1XX_UART1,
+ S5PC1XX_UART2,
+ S5PC1XX_UART3,
+};
+
+#endif /* __ASSEMBLY__ */
+
diff --git a/include/asm-arm/arch-s5pc100/watchdog.h
b/include/asm-arm/arch-s5pc100/watchdog.h
new file mode 100644
index 0000000..5f59101
--- /dev/null
+++ b/include/asm-arm/arch-s5pc100/watchdog.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2009
+ * Heungjun Kim, SAMSUNG Electronics, <riverful.kim(a)samsung.com>
+ * Inki Dae, SAMSUNG Electronics, <inki.dae(a)samsung.com>
+ *
+ * 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
+ */
+
+/*
+ * Watchdog
+ */
+#define S5P_WATCHDOG_BASE(x) (S5P_PA_WATCHDOG + (x))
+
+#define WTCON_OFFSET 0x0
+#define WTDAT_OFFSET 0x4
+#define WTCNT_OFFSET 0x8
+#define WTCLRINT_OFFSET 0xc
+
+#define S5P_WTCON S5P_WATCHDOG_BASE(WTCON_OFFSET)
+#define S5P_WTDAT S5P_WATCHDOG_BASE(WTDAT_OFFSET)
+#define S5P_WTCNT S5P_WATCHDOG_BASE(WTCNT_OFFSET)
+#define S5P_WTCLRINT S5P_WATCHDOG_BASE(WTCLRINT_OFFSET)
+
--
1.5.6.3
2
2
Signed-off-by: Wolfgang Denk <wd(a)denx.de>
Tested-by: Mikhail Zaturenskiy <mzaturenskiy(a)shoppertrak.com>
---
board/ep88x/u-boot.lds | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/board/ep88x/u-boot.lds b/board/ep88x/u-boot.lds
index dd62e58..b3849de 100644
--- a/board/ep88x/u-boot.lds
+++ b/board/ep88x/u-boot.lds
@@ -90,11 +90,13 @@ SECTIONS
_edata = .;
PROVIDE (edata = .);
+ . = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
+ . = .;
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
--
1.6.0.6
1
0

[U-Boot] [PATCH] cmd_mtdparts.c: allow to omit definitions for default settings
by Wolfgang Denk 04 Jun '09
by Wolfgang Denk 04 Jun '09
04 Jun '09
There is actually no good reason to enforce that all board
configuations must define default settings for "mtdids" and
"mtdparts". Actually this may be difficult to handle, especially on
boards where different sizes of flash chips can be fit, so there is no
real "default" partition map for all boards.
Lift this arbitrary limitation.
Signed-off-by: Wolfgang Denk <wd(a)denx.de>
---
common/cmd_mtdparts.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index e7b6acc..bb07fde 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -137,14 +137,12 @@
#if defined(MTDIDS_DEFAULT)
static const char *const mtdids_default = MTDIDS_DEFAULT;
#else
-#warning "MTDIDS_DEFAULT not defined!"
static const char *const mtdids_default = NULL;
#endif
#if defined(MTDPARTS_DEFAULT)
static const char *const mtdparts_default = MTDPARTS_DEFAULT;
#else
-#warning "MTDPARTS_DEFAULT not defined!"
static const char *const mtdparts_default = NULL;
#endif
@@ -1344,8 +1342,10 @@ static void list_partitions(void)
}
printf("\ndefaults:\n");
- printf("mtdids : %s\n", mtdids_default);
- printf("mtdparts: %s\n", mtdparts_default);
+ printf("mtdids : %s\n",
+ mtdids_default ? mtdids_default : "none");
+ printf("mtdparts: %s\n",
+ mtdparts_default ? mtdparts_default : "none");
}
/**
--
1.6.0.6
1
1

[U-Boot] [PATCH] 74xx_7xx: Add CPCI adapter/target support for the CPCI750
by Stefan Roese 04 Jun '09
by Stefan Roese 04 Jun '09
04 Jun '09
The CPCI750 can be built as CPCI host or adapter/target board. This patch
adds support for runtime detection of those variants.
Signed-off-by: Stefan Roese <sr(a)denx.de>
Cc: Reinhard Arlt <reinhard.arlt(a)esd-electronics.com>
---
board/esd/cpci750/cpci750.c | 108 +++++++++++++++++++++++++++++++++++++++----
board/esd/cpci750/ide.c | 4 +-
board/esd/cpci750/pci.c | 57 ++++++++++++++++------
include/configs/CPCI750.h | 5 ++-
4 files changed, 147 insertions(+), 27 deletions(-)
diff --git a/board/esd/cpci750/cpci750.c b/board/esd/cpci750/cpci750.c
index 4826633..6641304 100644
--- a/board/esd/cpci750/cpci750.c
+++ b/board/esd/cpci750/cpci750.c
@@ -122,6 +122,9 @@ static char show_config_tab[][15] = {{"PCI0DLL_2 "}, /* 31 */
extern flash_info_t flash_info[];
+extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+extern int do_bootvx (cmd_tbl_t *, int, int, char *[]);
+
/* ------------------------------------------------------------------------- */
/* this is the current GT register space location */
@@ -137,6 +140,15 @@ void board_prebootm_init (void);
unsigned int INTERNAL_REG_BASE_ADDR = CONFIG_SYS_GT_REGS;
int display_mem_map (void);
+/*
+ * Skip video initialization on slave variant.
+ * This function will overwrite the weak default in ct6900.c
+ */
+int board_video_skip(void)
+{
+ return CPCI750_SLAVE_TEST;
+}
+
/* ------------------------------------------------------------------------- */
/*
@@ -184,6 +196,7 @@ original ppcboot 1.1.6 source end */
static void gt_pci_config (void)
{
unsigned int stat;
+ unsigned int data;
unsigned int val = 0x00fff864; /* DINK32: BusNum 23:16, DevNum 15:11, FuncNum 10:8, RegNum 7:2 */
/* In PCIX mode devices provide their own bus and device numbers. We query the Discovery II's
@@ -251,10 +264,11 @@ static void gt_pci_config (void)
/*ronen update the pci internal registers base address.*/
#ifdef MAP_PCI
- for (stat = 0; stat <= PCI_HOST1; stat++)
- pciWriteConfigReg (stat,
- PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS,
- SELF, CONFIG_SYS_GT_REGS);
+ for (stat = 0; stat <= PCI_HOST1; stat++) {
+ data = pciReadConfigReg(stat, PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, SELF);
+ data = (data & 0x0f) | CONFIG_SYS_GT_REGS;
+ pciWriteConfigReg (stat, PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, SELF, data);
+ }
#endif
}
@@ -448,13 +462,16 @@ int misc_init_r ()
void after_reloc (ulong dest_addr, gd_t * gd)
{
+ memoryMapDeviceSpace (BOOT_DEVICE, CONFIG_SYS_BOOT_SPACE,
+ CONFIG_SYS_BOOT_SIZE);
- memoryMapDeviceSpace (BOOT_DEVICE, CONFIG_SYS_BOOT_SPACE, CONFIG_SYS_BOOT_SIZE);
+ display_mem_map ();
+ GT_REG_WRITE (PCI_0BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe);
+ GT_REG_WRITE (PCI_1BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe);
- display_mem_map ();
- /* now, jump to the main ppcboot board init code */
- board_init_r (gd, dest_addr);
- /* NOTREACHED */
+ /* now, jump to the main ppcboot board init code */
+ board_init_r (gd, dest_addr);
+ /* NOTREACHED */
}
/* ------------------------------------------------------------------------- */
@@ -538,6 +555,79 @@ int display_mem_map (void)
return (0);
}
+/*
+ * Command loadpci: wait for signal from host and boot image.
+ */
+int do_loadpci(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ volatile unsigned int *ptr;
+ int count = 0;
+ int count2 = 0;
+ int status;
+ char addr[16];
+ char str[] = "\\|/-";
+ char *local_args[2];
+
+ /*
+ * Mark sync address
+ */
+ ptr = 0;
+ ptr[0] = 0xffffffff;
+ ptr[1] = 0xffffffff;
+ puts("\nWaiting for image from pci host -");
+
+ /*
+ * Wait for host to write the start address
+ */
+ while (*ptr == 0xffffffff) {
+ count++;
+ if (!(count % 100)) {
+ count2++;
+ putc(0x08); /* backspace */
+ putc(str[count2 % 4]);
+ }
+
+ /* Abort if ctrl-c was pressed */
+ if (ctrlc()) {
+ puts("\nAbort\n");
+ return 0;
+ }
+
+ udelay(1000);
+ }
+
+ sprintf(addr, "%08x", *ptr);
+ printf("\nBooting Image at addr 0x%s ...\n", addr);
+ setenv("loadaddr", addr);
+
+ switch (ptr[1] == 0) {
+ case 0:
+ /*
+ * Boot image via bootm
+ */
+ local_args[0] = argv[0];
+ local_args[1] = NULL;
+ status = do_bootm (cmdtp, 0, 1, local_args);
+ break;
+ case 1:
+ /*
+ * Boot image via bootvx
+ */
+ local_args[0] = argv[0];
+ local_args[1] = NULL;
+ status = do_bootvx (cmdtp, 0, 1, local_args);
+ break;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ loadpci, 1, 1, do_loadpci,
+ "loadpci - Wait for pci-image and boot it\n",
+ NULL
+ );
+
/* DRAM check routines copied from gw8260 */
#if defined (CONFIG_SYS_DRAM_TEST)
diff --git a/board/esd/cpci750/ide.c b/board/esd/cpci750/ide.c
index 9bdc523..8ec2346 100644
--- a/board/esd/cpci750/ide.c
+++ b/board/esd/cpci750/ide.c
@@ -39,6 +39,8 @@ int ide_preinit (void)
int l;
status = 1;
+ if (CPCI750_SLAVE_TEST != 0)
+ return status;
for (l = 0; l < CONFIG_SYS_IDE_MAXBUS; l++) {
ide_bus_offset[l] = -ATA_STATUS;
}
@@ -57,7 +59,7 @@ int ide_preinit (void)
ide_bus_offset[1] &= 0xfffffffe;
ide_bus_offset[1] += CONFIG_SYS_PCI0_IO_SPACE;
}
- return (status);
+ return status;
}
void ide_set_reset (int flag) {
diff --git a/board/esd/cpci750/pci.c b/board/esd/cpci750/pci.c
index bfc7e55..552ad92 100644
--- a/board/esd/cpci750/pci.c
+++ b/board/esd/cpci750/pci.c
@@ -768,7 +768,8 @@ static int gt_read_config_dword (struct pci_controller *hose,
int bus = PCI_BUS (dev);
if ((bus == local_buses[0]) || (bus == local_buses[1])) {
- *value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr, offset,
+ *value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr,
+ offset | (PCI_FUNC(dev) << 8),
PCI_DEV (dev));
} else {
*value = pciOverBridgeReadConfigReg ((PCI_HOST) hose->
@@ -785,11 +786,13 @@ static int gt_write_config_dword (struct pci_controller *hose,
int bus = PCI_BUS (dev);
if ((bus == local_buses[0]) || (bus == local_buses[1])) {
- pciWriteConfigReg ((PCI_HOST) hose->cfg_addr, offset,
+ pciWriteConfigReg ((PCI_HOST) hose->cfg_addr,
+ offset | (PCI_FUNC(dev) << 8),
PCI_DEV (dev), value);
} else {
pciOverBridgeWriteConfigReg ((PCI_HOST) hose->cfg_addr,
- offset, PCI_DEV (dev), bus,
+ offset | (PCI_FUNC(dev) << 8),
+ PCI_DEV (dev), bus,
value);
}
return 0;
@@ -803,6 +806,9 @@ static void gt_setup_ide (struct pci_controller *hose,
u32 bar_response, bar_value;
int bar;
+ if (CPCI750_SLAVE_TEST != 0)
+ return;
+
for (bar = 0; bar < 6; bar++) {
/*ronen different function for 3rd bank. */
unsigned int offset =
@@ -829,6 +835,9 @@ static void gt_setup_cpcidvi (struct pci_controller *hose,
{
u32 bar_value, pci_response;
+ if (CPCI750_SLAVE_TEST != 0)
+ return;
+
pci_hose_read_config_dword (hose, dev, PCI_COMMAND, &pci_response);
pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0, 0xffffffff);
pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0, &pci_response);
@@ -907,6 +916,7 @@ struct pci_controller pci1_hose = {
void pci_init_board (void)
{
unsigned int command;
+ unsigned int slave;
#ifdef CONFIG_PCI_PNP
unsigned int bar;
#endif
@@ -918,6 +928,8 @@ void pci_init_board (void)
gt_cpcidvi_rom.base = 0;
#endif
+ slave = CPCI750_SLAVE_TEST;
+
pci0_hose.config_table = gt_config_table;
pci1_hose.config_table = gt_config_table;
@@ -953,27 +965,40 @@ void pci_init_board (void)
pci0_hose.cfg_addr = (unsigned int *) PCI_HOST0;
pci_register_hose (&pci0_hose);
- pciArbiterEnable (PCI_HOST0);
- pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1);
- command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
- command |= PCI_COMMAND_MASTER;
- pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
- command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
- command |= PCI_COMMAND_MEMORY;
- pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
+ if (slave == 0) {
+ pciArbiterEnable (PCI_HOST0);
+ pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1);
+ command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MASTER;
+ pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
+ command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MEMORY;
+ pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
#ifdef CONFIG_PCI_PNP
- pciauto_config_init(&pci0_hose);
- pciauto_region_allocate(pci0_hose.pci_io, 0x400, &bar);
+ pciauto_config_init(&pci0_hose);
+ pciauto_region_allocate(pci0_hose.pci_io, 0x400, &bar);
#endif
#ifdef CONFIG_PCI_SCAN_SHOW
- printf("PCI: Bus Dev VenId DevId Class Int\n");
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
#endif
- pci0_hose.last_busno = pci_hose_scan_bus (&pci0_hose, pci0_hose.first_busno);
+ pci0_hose.last_busno = pci_hose_scan_bus (&pci0_hose,
+ pci0_hose.first_busno);
#ifdef DEBUG
- gt_pci_bus_mode_display (PCI_HOST1);
+ gt_pci_bus_mode_display (PCI_HOST1);
#endif
+ } else {
+ pciArbiterDisable (PCI_HOST0);
+ pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1);
+ command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MASTER;
+ pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
+ command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MEMORY;
+ pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
+ pci0_hose.last_busno = pci0_hose.first_busno;
+ }
pci1_hose.first_busno = pci0_hose.last_busno + 1;
pci1_hose.last_busno = 0xff;
pci1_hose.current_busno = pci1_hose.first_busno;
diff --git a/include/configs/CPCI750.h b/include/configs/CPCI750.h
index 8494faa..d516c3c 100644
--- a/include/configs/CPCI750.h
+++ b/include/configs/CPCI750.h
@@ -76,7 +76,8 @@
#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
-#define CONFIG_AUTO_COMPLETE 1
+#define CONFIG_CMDLINE_EDITING /* add command line history */
+#define CONFIG_AUTO_COMPLETE /* add autocompletion support */
/* Define which ETH port will be used for connecting the network */
#define CONFIG_SYS_ETH_PORT ETH_0
@@ -626,4 +627,6 @@
#define CONFIG_SYS_BOARD_ASM_INIT 1
+#define CPCI750_SLAVE_TEST (((in8(0xf0300000) & 0x80) == 0) ? 0 : 1)
+
#endif /* __CONFIG_H */
--
1.6.2.5
2
1

[U-Boot] [PATCH v2] cmd_mtdparts: Move to common handling of FLASH devices via MTD layer
by Stefan Roese 04 Jun '09
by Stefan Roese 04 Jun '09
04 Jun '09
This patch removes all references to the direct CFI FLASH interface
(via flash_info[]). Now that all FLASH types currently handled in
mtdparts are available (if selected, see below) via the MTD infrastructure.
This is NOR, NAND and OneNAND right now. This can be achieved by defining
the following options:
CONFIG_MTD_DEVICE (for all FLASH types)
plus
CONFIG_FLASH_CFI_MTD (for NOR FLASH)
So we need to add those defines to the board config headers currently
using the mtdparts commands. This is done via another patch, so
we shouldn't break mtdparts compatibility.
One big advantage from this solution is that the cmd_mtdparts.c is
*much* cleaner now. Lot's of #ifdef's are removed and the code itself
is smaller. Additionally the newly added MDT concatenation feature
can new be used via the mtdparts infrastructure and therefor via
UBI etc.
Signed-off-by: Stefan Roese <sr(a)denx.de>
Cc: Ladislav Michl <ladis(a)linux-mips.org>
Cc: Scott Wood <scottwood(a)freescale.com>
---
v2:
- Use CONFIG_MTD_DEVICE instead of CONFIG_MTD_PARTITIONS in commit
text.
common/cmd_mtdparts.c | 240 ++++++++++++++++--------------------------------
1 files changed, 80 insertions(+), 160 deletions(-)
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index e7b6acc..e94ca1b 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -90,7 +90,8 @@
#include <jffs2/load_kernel.h>
#include <linux/list.h>
#include <linux/ctype.h>
-#include <cramfs/cramfs_fs.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
#if defined(CONFIG_CMD_NAND)
#ifdef CONFIG_NAND_LEGACY
@@ -102,7 +103,6 @@
#endif
#if defined(CONFIG_CMD_ONENAND)
-#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <onenand_uboot.h>
#endif
@@ -303,137 +303,91 @@ static void current_save(void)
}
/**
- * Performs sanity check for supplied NOR flash partition. Table of existing
- * NOR flash devices is searched and partition device is located. Alignment
- * with the granularity of NOR flash sectors is verified.
+ * Performs sanity check for supplied flash partition.
+ * Table of existing MTD flash devices is searched and partition device
+ * is located. Alignment with the granularity of nand erasesize is verified.
*
* @param id of the parent device
* @param part partition to validate
* @return 0 if partition is valid, 1 otherwise
*/
-static int part_validate_nor(struct mtdids *id, struct part_info *part)
+static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
{
-#if defined(CONFIG_CMD_FLASH)
- /* info for FLASH chips */
- extern flash_info_t flash_info[];
- flash_info_t *flash;
- int offset_aligned;
- u32 end_offset, sector_size = 0;
- int i;
-
- flash = &flash_info[id->num];
-
- /* size of last sector */
- part->sector_size = flash->size -
- (flash->start[flash->sector_count-1] - flash->start[0]);
-
- offset_aligned = 0;
- for (i = 0; i < flash->sector_count; i++) {
- if ((flash->start[i] - flash->start[0]) == part->offset) {
- offset_aligned = 1;
- break;
- }
- }
- if (offset_aligned == 0) {
- printf("%s%d: partition (%s) start offset alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
+ struct mtd_info *mtd;
+ char mtd_dev[16];
+ int i, j;
+ ulong start;
+
+ sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(id->type), id->num);
+ mtd = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(mtd)) {
+ printf("Partition %s not found on device %s!\n", part->name, mtd_dev);
return 1;
}
- end_offset = part->offset + part->size;
- offset_aligned = 0;
- for (i = 0; i < flash->sector_count; i++) {
- if (i) {
- sector_size = flash->start[i] - flash->start[i-1];
- if (part->sector_size < sector_size)
- part->sector_size = sector_size;
- }
- if ((flash->start[i] - flash->start[0]) == end_offset)
- offset_aligned = 1;
- }
-
- if (offset_aligned || flash->size == end_offset)
- return 0;
-
- printf("%s%d: partition (%s) size alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
-#endif
- return 1;
-}
-
-/**
- * Performs sanity check for supplied NAND flash partition. Table of existing
- * NAND flash devices is searched and partition device is located. Alignment
- * with the granularity of nand erasesize is verified.
- *
- * @param id of the parent device
- * @param part partition to validate
- * @return 0 if partition is valid, 1 otherwise
- */
-static int part_validate_nand(struct mtdids *id, struct part_info *part)
-{
-#if defined(CONFIG_CMD_NAND)
- /* info for NAND chips */
- nand_info_t *nand;
+ part->sector_size = mtd->erasesize;
- nand = &nand_info[id->num];
+ if (!mtd->numeraseregions) {
+ /*
+ * Only one eraseregion (NAND, OneNAND or uniform NOR),
+ * checking for alignment is easy here
+ */
+ if ((unsigned long)part->offset % mtd->erasesize) {
+ printf("%s%d: partition (%s) start offset"
+ "alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
- part->sector_size = nand->erasesize;
+ if (part->size % mtd->erasesize) {
+ printf("%s%d: partition (%s) size alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+ } else {
+ /*
+ * Multiple eraseregions (non-uniform NOR),
+ * checking for alignment is more complex here
+ */
+
+ /* Check start alignment */
+ for (i = 0; i < mtd->numeraseregions; i++) {
+ start = mtd->eraseregions[i].offset;
+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+ if (part->offset == start)
+ goto start_ok;
+ start += mtd->eraseregions[i].erasesize;
+ }
+ }
- if ((unsigned long)(part->offset) % nand->erasesize) {
printf("%s%d: partition (%s) start offset alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
- return 1;
- }
-
- if (part->size % nand->erasesize) {
- printf("%s%d: partition (%s) size alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
+ MTD_DEV_TYPE(id->type), id->num, part->name);
return 1;
- }
- return 0;
-#else
- return 1;
-#endif
-}
+ start_ok:
-/**
- * Performs sanity check for supplied OneNAND flash partition.
- * Table of existing OneNAND flash devices is searched and partition device
- * is located. Alignment with the granularity of nand erasesize is verified.
- *
- * @param id of the parent device
- * @param part partition to validate
- * @return 0 if partition is valid, 1 otherwise
- */
-static int part_validate_onenand(struct mtdids *id, struct part_info *part)
-{
-#if defined(CONFIG_CMD_ONENAND)
- /* info for OneNAND chips */
- struct mtd_info *mtd;
-
- mtd = &onenand_mtd;
-
- part->sector_size = mtd->erasesize;
-
- if ((unsigned long)(part->offset) % mtd->erasesize) {
- printf("%s%d: partition (%s) start offset"
- "alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
- return 1;
- }
+ /* Check end/size alignment */
+ for (i = 0; i < mtd->numeraseregions; i++) {
+ start = mtd->eraseregions[i].offset;
+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+ if ((part->offset + part->size) == start)
+ goto end_ok;
+ start += mtd->eraseregions[i].erasesize;
+ }
+ }
+ /* Check last sector alignment */
+ if ((part->offset + part->size) == start)
+ goto end_ok;
- if (part->size % mtd->erasesize) {
printf("%s%d: partition (%s) size alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
+ MTD_DEV_TYPE(id->type), id->num, part->name);
return 1;
+
+ end_ok:
+ return 0;
}
return 0;
-#else
- return 1;
-#endif
}
@@ -469,16 +423,11 @@ static int part_validate(struct mtdids *id, struct part_info *part)
return 1;
}
- if (id->type == MTD_DEV_TYPE_NAND)
- return part_validate_nand(id, part);
- else if (id->type == MTD_DEV_TYPE_NOR)
- return part_validate_nor(id, part);
- else if (id->type == MTD_DEV_TYPE_ONENAND)
- return part_validate_onenand(id, part);
- else
- DEBUGF("part_validate: invalid dev type\n");
-
- return 1;
+ /*
+ * Now we need to check if the partition starts and ends on
+ * sector (eraseblock) regions
+ */
+ return part_validate_eraseblock(id, part);
}
/**
@@ -762,48 +711,19 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
*/
int mtd_device_validate(u8 type, u8 num, u32 *size)
{
- if (type == MTD_DEV_TYPE_NOR) {
-#if defined(CONFIG_CMD_FLASH)
- if (num < CONFIG_SYS_MAX_FLASH_BANKS) {
- extern flash_info_t flash_info[];
- *size = flash_info[num].size;
-
- return 0;
- }
+ struct mtd_info *mtd;
+ char mtd_dev[16];
- printf("no such FLASH device: %s%d (valid range 0 ... %d\n",
- MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_FLASH_BANKS - 1);
-#else
- printf("support for FLASH devices not present\n");
-#endif
- } else if (type == MTD_DEV_TYPE_NAND) {
-#if defined(CONFIG_CMD_NAND)
- if (num < CONFIG_SYS_MAX_NAND_DEVICE) {
-#ifndef CONFIG_NAND_LEGACY
- *size = nand_info[num].size;
-#else
- extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE];
- *size = nand_dev_desc[num].totlen;
-#endif
- return 0;
- }
+ sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
+ mtd = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(mtd)) {
+ printf("Device %s not found!\n", mtd_dev);
+ return 1;
+ }
- printf("no such NAND device: %s%d (valid range 0 ... %d)\n",
- MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_NAND_DEVICE - 1);
-#else
- printf("support for NAND devices not present\n");
-#endif
- } else if (type == MTD_DEV_TYPE_ONENAND) {
-#if defined(CONFIG_CMD_ONENAND)
- *size = onenand_mtd.size;
- return 0;
-#else
- printf("support for OneNAND devices not present\n");
-#endif
- } else
- printf("Unknown defice type %d\n", type);
+ *size = mtd->size;
- return 1;
+ return 0;
}
/**
--
1.6.2.5
2
1

[U-Boot] [PATCH] mtd: Introduce CONFIG_MTD_DEVICE to select compilation of mtdcore.o
by Stefan Roese 04 Jun '09
by Stefan Roese 04 Jun '09
04 Jun '09
This new define enables mtdcore.c compilation and with this we can
select the MTD device infrastructure needed for the reworked mtdparts
command.
We now have the 2 MTD infrastructure defines, CONFIG_MTD_DEVICE and
CONFIG_MTD_PARTITIONS. CONFIG_MTD_DEVICE is needed (as explained above)
for the "mtdparts" command and CONFIG_MTD_PARTITIONS is needed for UBI.
Signed-off-by: Stefan Roese <sr(a)denx.de>
Cc: Scott Wood <scottwood(a)freescale.com>
---
README | 11 +++++++++++
drivers/mtd/Makefile | 3 ++-
drivers/mtd/nand/nand.c | 2 +-
drivers/mtd/onenand/onenand_uboot.c | 2 +-
4 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/README b/README
index 75fc4b7..561c100 100644
--- a/README
+++ b/README
@@ -1846,6 +1846,17 @@ The following options need to be configured:
These options enable and control the auto-update feature;
for a more detailed description refer to doc/README.update.
+- MTD Support (mtdparts command, UBI support)
+ CONFIG_MTD_DEVICE
+
+ Adds the MTD device infrastructure from the Linux kernel.
+ Needed for mtdparts command support.
+
+ CONFIG_MTD_PARTITIONS
+
+ Adds the MTD partitioning infrastructure from the Linux
+ kernel. Needed for UBI support.
+
Legacy uImage format:
Arg Where When
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 19dc02b..754d648 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -25,7 +25,8 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libmtd.a
-COBJS-$(CONFIG_MTD_PARTITIONS) += mtdcore.o mtdpart.o
+COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o
+COBJS-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
COBJS-$(CONFIG_MTD_CONCAT) += mtdconcat.o
COBJS-$(CONFIG_HAS_DATAFLASH) += at45.o
COBJS-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
index d369115..9065fa9 100644
--- a/drivers/mtd/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
@@ -57,7 +57,7 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
else
mtd->name += gd->reloc_off;
-#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_DEVICE
/*
* Add MTD device so that we can reference it later
* via the mtdcore infrastructure (e.g. ubi).
diff --git a/drivers/mtd/onenand/onenand_uboot.c b/drivers/mtd/onenand/onenand_uboot.c
index a95b922..9823b5b 100644
--- a/drivers/mtd/onenand/onenand_uboot.c
+++ b/drivers/mtd/onenand/onenand_uboot.c
@@ -43,7 +43,7 @@ void onenand_init(void)
puts("OneNAND: ");
print_size(onenand_mtd.size, "\n");
-#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_DEVICE
/*
* Add MTD device so that we can reference it later
* via the mtdcore infrastructure (e.g. ubi).
--
1.6.2.5
2
1

[U-Boot] [PATCH] mtd: MTD related config header changes (mtdparts command)
by Stefan Roese 04 Jun '09
by Stefan Roese 04 Jun '09
04 Jun '09
By changing the cmd_mtdparts to only use the MTD infrastructure and
not the direct interface to the CFI NOR FLASH driver we now need
to add the MTD infrastructure to all boards using those mtdparts
commands. This patch adds those components:
CONFIG_MTD_DEVICE (for all FLASH types)
plus
CONFIG_FLASH_CFI_MTD (for NOR FLASH)
To all board maintainers: Please test this on your platforms and
report any problems/issues found. Thanks.
Signed-off-by: Stefan Roese <sr(a)denx.de>
Cc: Wolfgang Denk <wd(a)denx.de>
Cc: Ron Madrid <info(a)sheldoninst.com>
Cc: Georg Schardt <schardt(a)team-ctech.de>
Cc: Michal Simek <monstr(a)monstr.eu>
Cc: Ladislav Michl <ladis(a)linux-mips.org>
Cc: Martin Krause <martin.krause(a)tqs.de>
Cc: Gary Jennejohn <gj(a)denx.de>
Cc: Ricardo Ribalda <ricardo.ribalda(a)uam.es>
---
include/configs/BC3450.h | 2 ++
include/configs/FPS850L.h | 2 ++
include/configs/FPS860L.h | 2 ++
include/configs/SIMPC8313.h | 1 +
include/configs/TB5200.h | 2 ++
include/configs/TQM5200.h | 2 ++
include/configs/TQM823L.h | 2 ++
include/configs/TQM823M.h | 2 ++
include/configs/TQM834x.h | 2 ++
include/configs/TQM850L.h | 2 ++
include/configs/TQM850M.h | 2 ++
include/configs/TQM855L.h | 2 ++
include/configs/TQM855M.h | 2 ++
include/configs/TQM85xx.h | 2 ++
include/configs/TQM860L.h | 2 ++
include/configs/TQM860M.h | 2 ++
include/configs/TQM862L.h | 2 ++
include/configs/TQM862M.h | 2 ++
include/configs/TQM866M.h | 2 ++
include/configs/apollon.h | 1 +
include/configs/cm5200.h | 2 ++
include/configs/fx12mm.h | 2 ++
include/configs/idmr.h | 2 ++
include/configs/microblaze-generic.h | 2 ++
include/configs/motionpro.h | 2 ++
include/configs/mx1fs2.h | 2 ++
include/configs/netstar.h | 2 ++
include/configs/omap3_beagle.h | 1 +
include/configs/qong.h | 2 ++
include/configs/smmaco4.h | 2 ++
include/configs/trab.h | 2 ++
include/configs/vct.h | 1 +
include/configs/virtlab2.h | 2 ++
include/configs/voiceblue.h | 2 ++
include/configs/xilinx-ppc.h | 2 ++
35 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/include/configs/BC3450.h b/include/configs/BC3450.h
index 9934f29..8c5a742 100644
--- a/include/configs/BC3450.h
+++ b/include/configs/BC3450.h
@@ -347,6 +347,8 @@
/* Dynamic MTD partition support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM5200-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM5200-0:640k(firmware)," \
"1408k(kernel)," \
diff --git a/include/configs/FPS850L.h b/include/configs/FPS850L.h
index f152230..aceecd8 100644
--- a/include/configs/FPS850L.h
+++ b/include/configs/FPS850L.h
@@ -217,6 +217,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/FPS860L.h b/include/configs/FPS860L.h
index 5eaed84..4a61d7c 100644
--- a/include/configs/FPS860L.h
+++ b/include/configs/FPS860L.h
@@ -217,6 +217,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/SIMPC8313.h b/include/configs/SIMPC8313.h
index 88ea7c7..8d1e95b 100644
--- a/include/configs/SIMPC8313.h
+++ b/include/configs/SIMPC8313.h
@@ -190,6 +190,7 @@
/* mtdparts command line support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
#define MTDIDS_DEFAULT "nand0=nand0"
#define MTDPARTS_DEFAULT "mtdparts=nand0:2M(u-boot),6M(kernel),-(jffs2)"
diff --git a/include/configs/TB5200.h b/include/configs/TB5200.h
index 92b4fa5..3438aba 100644
--- a/include/configs/TB5200.h
+++ b/include/configs/TB5200.h
@@ -276,6 +276,8 @@
/* Dynamic MTD partition support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM5200-0"
#if defined(CONFIG_TQM5200_B)
#define MTDPARTS_DEFAULT "mtdparts=TQM5200-0:768k(firmware)," \
diff --git a/include/configs/TQM5200.h b/include/configs/TQM5200.h
index fe1d102..a4336a7 100644
--- a/include/configs/TQM5200.h
+++ b/include/configs/TQM5200.h
@@ -408,6 +408,8 @@
/* Dynamic MTD partition support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM5200-0"
#ifdef CONFIG_STK52XX
diff --git a/include/configs/TQM823L.h b/include/configs/TQM823L.h
index 87e5a65..1f816f3 100644
--- a/include/configs/TQM823L.h
+++ b/include/configs/TQM823L.h
@@ -232,6 +232,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/TQM823M.h b/include/configs/TQM823M.h
index f666443..42dcbfc 100644
--- a/include/configs/TQM823M.h
+++ b/include/configs/TQM823M.h
@@ -228,6 +228,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
diff --git a/include/configs/TQM834x.h b/include/configs/TQM834x.h
index b74b404..fce3c51 100644
--- a/include/configs/TQM834x.h
+++ b/include/configs/TQM834x.h
@@ -538,6 +538,8 @@ extern int tqm834x_num_flash_banks;
*/
/* mtdparts command line support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM834x-0"
/* default mtd partition table */
diff --git a/include/configs/TQM850L.h b/include/configs/TQM850L.h
index dc80b47..290e211 100644
--- a/include/configs/TQM850L.h
+++ b/include/configs/TQM850L.h
@@ -217,6 +217,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/TQM850M.h b/include/configs/TQM850M.h
index 2289443..2170df5 100644
--- a/include/configs/TQM850M.h
+++ b/include/configs/TQM850M.h
@@ -217,6 +217,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
diff --git a/include/configs/TQM855L.h b/include/configs/TQM855L.h
index 999bdaa..3d7dc42 100644
--- a/include/configs/TQM855L.h
+++ b/include/configs/TQM855L.h
@@ -222,6 +222,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/TQM855M.h b/include/configs/TQM855M.h
index b54967d..35cfa08 100644
--- a/include/configs/TQM855M.h
+++ b/include/configs/TQM855M.h
@@ -257,6 +257,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
diff --git a/include/configs/TQM85xx.h b/include/configs/TQM85xx.h
index 2ef24cd..35278b3 100644
--- a/include/configs/TQM85xx.h
+++ b/include/configs/TQM85xx.h
@@ -580,6 +580,8 @@
#define CONFIG_JFFS2_NAND 1
#ifdef CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nand0=TQM85xx-nand"
#define MTDPARTS_DEFAULT "mtdparts=TQM85xx-nand:-"
#else
diff --git a/include/configs/TQM860L.h b/include/configs/TQM860L.h
index 2e2a165..4ac485d 100644
--- a/include/configs/TQM860L.h
+++ b/include/configs/TQM860L.h
@@ -221,6 +221,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/TQM860M.h b/include/configs/TQM860M.h
index 1148f2e..39da0bb 100644
--- a/include/configs/TQM860M.h
+++ b/include/configs/TQM860M.h
@@ -222,6 +222,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
diff --git a/include/configs/TQM862L.h b/include/configs/TQM862L.h
index 577f982..1f79b17 100644
--- a/include/configs/TQM862L.h
+++ b/include/configs/TQM862L.h
@@ -225,6 +225,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/TQM862M.h b/include/configs/TQM862M.h
index 69070e6..86d5b01 100644
--- a/include/configs/TQM862M.h
+++ b/include/configs/TQM862M.h
@@ -226,6 +226,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
diff --git a/include/configs/TQM866M.h b/include/configs/TQM866M.h
index bb68614..04f538c 100644
--- a/include/configs/TQM866M.h
+++ b/include/configs/TQM866M.h
@@ -266,6 +266,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
diff --git a/include/configs/apollon.h b/include/configs/apollon.h
index c14f871..fa53f26 100644
--- a/include/configs/apollon.h
+++ b/include/configs/apollon.h
@@ -124,6 +124,7 @@
#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_UBI
#define CONFIG_RBTREE
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
#define CONFIG_MTD_PARTITIONS
#endif
diff --git a/include/configs/cm5200.h b/include/configs/cm5200.h
index 54cf40d..72cf941 100644
--- a/include/configs/cm5200.h
+++ b/include/configs/cm5200.h
@@ -223,6 +223,8 @@
* MTD configuration
*/
#define CONFIG_CMD_MTDPARTS 1
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=cm5200-0"
#define MTDPARTS_DEFAULT "mtdparts=cm5200-0:" \
"384k(uboot),128k(env)," \
diff --git a/include/configs/fx12mm.h b/include/configs/fx12mm.h
index 27c6e7d..e825c21 100644
--- a/include/configs/fx12mm.h
+++ b/include/configs/fx12mm.h
@@ -38,6 +38,8 @@
/* cmd config */
#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#undef CONFIG_CMD_NET
/* sdram */
diff --git a/include/configs/idmr.h b/include/configs/idmr.h
index 944d06f..841affb 100644
--- a/include/configs/idmr.h
+++ b/include/configs/idmr.h
@@ -230,6 +230,8 @@
/* Dynamic MTD partition support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=idmr-0"
#define MTDPARTS_DEFAULT "mtdparts=idmr-0:128k(u-boot)," \
diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h
index aa117c8..72715f6 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -260,6 +260,8 @@
#if defined(CONFIG_CMD_JFFS2)
/* JFFS2 partitions */
#define CONFIG_CMD_MTDPARTS /* mtdparts command line support */
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=ml401-0"
/* default mtd partition table */
diff --git a/include/configs/motionpro.h b/include/configs/motionpro.h
index 99a02cc..fa4310b 100644
--- a/include/configs/motionpro.h
+++ b/include/configs/motionpro.h
@@ -276,6 +276,8 @@
* MTD configuration
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=motionpro-0"
#define MTDPARTS_DEFAULT "mtdparts=motionpro-0:" \
"13m(fs),2m(kernel),256k(uboot)," \
diff --git a/include/configs/mx1fs2.h b/include/configs/mx1fs2.h
index 24fa144..90a8d84 100644
--- a/include/configs/mx1fs2.h
+++ b/include/configs/mx1fs2.h
@@ -183,6 +183,8 @@
/* mtdparts command line support */
/* Note: fake mtd_id used, no linux mtd map file */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=mx1fs2-0"
#ifdef BUS32BIT_VERSION
diff --git a/include/configs/netstar.h b/include/configs/netstar.h
index 5cfee66..5062cdb 100644
--- a/include/configs/netstar.h
+++ b/include/configs/netstar.h
@@ -130,6 +130,8 @@
* partitions (mtdparts command line support)
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=omapflash.0,nand0=omapnand.0"
#define MTDPARTS_DEFAULT "mtdparts=" \
"omapflash.0:8k@16k(env),8k(r_env),448k@576k(u-boot);" \
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index a3d9cf6..c2bd7e6 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -105,6 +105,7 @@
#define CONFIG_CMD_FAT /* FAT support */
#define CONFIG_CMD_JFFS2 /* JFFS2 Support */
#define CONFIG_CMD_MTDPARTS /* Enable MTD parts commands */
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
#define MTDIDS_DEFAULT "nand0=nand"
#define MTDPARTS_DEFAULT "mtdparts=nand:512k(x-loader),"\
"1920k(u-boot),128k(u-boot-env),"\
diff --git a/include/configs/qong.h b/include/configs/qong.h
index a67006a..7e67185 100644
--- a/include/configs/qong.h
+++ b/include/configs/qong.h
@@ -213,6 +213,8 @@
* JFFS2 partitions
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=physmap-flash.0"
#define MTDPARTS_DEFAULT \
"mtdparts=physmap-flash.0:256k(U-Boot),128k(env1)," \
diff --git a/include/configs/smmaco4.h b/include/configs/smmaco4.h
index 35f3e3a..5a2ef3a 100644
--- a/include/configs/smmaco4.h
+++ b/include/configs/smmaco4.h
@@ -215,6 +215,8 @@
/* Dynamic MTD partition support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM5200-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM5200-0:640k(firmware)," \
"1408k(kernel)," \
diff --git a/include/configs/trab.h b/include/configs/trab.h
index 520fe36..a543ef1 100644
--- a/include/configs/trab.h
+++ b/include/configs/trab.h
@@ -375,6 +375,8 @@
/* Dynamic MTD partition support */
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=0"
/* production flash layout */
diff --git a/include/configs/vct.h b/include/configs/vct.h
index fe67997..e72b504 100644
--- a/include/configs/vct.h
+++ b/include/configs/vct.h
@@ -296,6 +296,7 @@ int vct_gpio_get(int pin);
#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_UBI
#define CONFIG_RBTREE
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
#define CONFIG_MTD_PARTITIONS
#define CONFIG_CMD_MTDPARTS
diff --git a/include/configs/virtlab2.h b/include/configs/virtlab2.h
index 021012d..9ebafcc 100644
--- a/include/configs/virtlab2.h
+++ b/include/configs/virtlab2.h
@@ -226,6 +226,8 @@
* Dynamic MTD partition support
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
diff --git a/include/configs/voiceblue.h b/include/configs/voiceblue.h
index aa8efaa..c9c3132 100644
--- a/include/configs/voiceblue.h
+++ b/include/configs/voiceblue.h
@@ -190,6 +190,8 @@
* JFFS2 partitions (mtdparts command line support)
*/
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT "nor0=omapflash.0"
#define MTDPARTS_DEFAULT "mtdparts=omapflash.0:256k(u-boot),64k(env),64k(r_env),16192k(data0),-(data1)"
diff --git a/include/configs/xilinx-ppc.h b/include/configs/xilinx-ppc.h
index e3ea84b..6efe342 100644
--- a/include/configs/xilinx-ppc.h
+++ b/include/configs/xilinx-ppc.h
@@ -109,6 +109,8 @@
#define CONFIG_SYS_FLASH_PROTECTION
#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define CONFIG_FLASH_CFI_MTD
#else
#define CONFIG_ENV_IS_NOWHERE
#define CONFIG_SYS_NO_FLASH
--
1.6.2.5
3
2

[U-Boot] [PATCH v2] mtd: Add MTD concat support to concatenate multiple MTD NOR devices
by Stefan Roese 03 Jun '09
by Stefan Roese 03 Jun '09
03 Jun '09
This patch adds concatenation support to the U-Boot MTD infrastructure.
By enabling CONFIG_MTD_CONCAT this MTD CFI wrapper will concatenate
all found NOR devices into one single MTD device. This can be used by
e.g by UBI to access a partition that spans over multiple NOR chips.
Signed-off-by: Stefan Roese <sr(a)denx.de>
---
v2:
- Using #ifdef's instead of __attribute__((unused)) for variable
declaration.
drivers/mtd/Makefile | 1 +
drivers/mtd/cfi_mtd.c | 79 +++++-
drivers/mtd/mtdconcat.c | 807 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/compat.h | 12 +-
include/linux/mtd/concat.h | 21 ++
5 files changed, 915 insertions(+), 5 deletions(-)
create mode 100644 drivers/mtd/mtdconcat.c
create mode 100644 include/linux/mtd/concat.h
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index ed3f91e..19dc02b 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libmtd.a
COBJS-$(CONFIG_MTD_PARTITIONS) += mtdcore.o mtdpart.o
+COBJS-$(CONFIG_MTD_CONCAT) += mtdconcat.o
COBJS-$(CONFIG_HAS_DATAFLASH) += at45.o
COBJS-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o
COBJS-$(CONFIG_FLASH_CFI_MTD) += cfi_mtd.o
diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c
index a0a15da..c7e357b 100644
--- a/drivers/mtd/cfi_mtd.c
+++ b/drivers/mtd/cfi_mtd.c
@@ -25,14 +25,19 @@
#include <common.h>
#include <flash.h>
+#include <malloc.h>
#include <asm/errno.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/concat.h>
extern flash_info_t flash_info[];
static struct mtd_info cfi_mtd_info[CONFIG_SYS_MAX_FLASH_BANKS];
static char cfi_mtd_names[CONFIG_SYS_MAX_FLASH_BANKS][16];
+#ifdef CONFIG_MTD_CONCAT
+static char c_mtd_name[16];
+#endif
static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
@@ -145,16 +150,68 @@ static int cfi_mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
static int cfi_mtd_set_erasesize(struct mtd_info *mtd, flash_info_t *fi)
{
int sect_size = 0;
+ int sect_size_old = 0;
int sect;
+ int regions = 0;
+ int numblocks = 0;
+ ulong offset = 0;
+ ulong base_addr = fi->start[0];
/*
- * Select the largest sector size as erasesize (e.g. for UBI)
+ * First detect the number of eraseregions so that we can allocate
+ * the array of eraseregions correctly
*/
for (sect = 0; sect < fi->sector_count; sect++) {
+ if (sect_size_old != flash_sector_size(fi, sect))
+ regions++;
+ sect_size_old = flash_sector_size(fi, sect);
+ }
+
+ mtd->eraseregions = malloc(sizeof(struct mtd_erase_region_info) * regions);
+
+ /*
+ * Now detect the largest sector and fill the eraseregions
+ */
+ sect_size_old = 0;
+ regions = 0;
+ for (sect = 0; sect < fi->sector_count; sect++) {
+ if ((sect_size_old != flash_sector_size(fi, sect)) &&
+ (sect_size_old != 0)) {
+ mtd->eraseregions[regions].offset = offset - base_addr;
+ mtd->eraseregions[regions].erasesize = sect_size_old;
+ mtd->eraseregions[regions].numblocks = numblocks;
+
+ /* Now start counting the next eraseregions */
+ numblocks = 0;
+ regions++;
+ } else {
+ numblocks++;
+ }
+
+ if (sect_size_old != flash_sector_size(fi, sect))
+ offset = fi->start[sect];
+
+ /*
+ * Select the largest sector size as erasesize (e.g. for UBI)
+ */
if (flash_sector_size(fi, sect) > sect_size)
sect_size = flash_sector_size(fi, sect);
+
+ sect_size_old = flash_sector_size(fi, sect);
}
+ /*
+ * Set the last region
+ */
+ mtd->eraseregions[regions].offset = offset - base_addr;
+ mtd->eraseregions[regions].erasesize = sect_size_old;
+ mtd->eraseregions[regions].numblocks = numblocks + 1;
+
+ if (regions)
+ mtd->numeraseregions = regions + 1;
+ else
+ mtd->numeraseregions = 0;
+
mtd->erasesize = sect_size;
return 0;
@@ -165,6 +222,8 @@ int cfi_mtd_init(void)
struct mtd_info *mtd;
flash_info_t *fi;
int error, i;
+ int devices_found = 0;
+ struct mtd_info *mtd_list[CONFIG_SYS_MAX_FLASH_BANKS];
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
fi = &flash_info[i];
@@ -193,7 +252,25 @@ int cfi_mtd_init(void)
if (add_mtd_device(mtd))
return -ENOMEM;
+
+ mtd_list[devices_found++] = mtd;
+ }
+
+#ifdef CONFIG_MTD_CONCAT
+ if (devices_found > 1) {
+ /*
+ * We detected multiple devices. Concatenate them together.
+ */
+ sprintf(c_mtd_name, "nor%d", devices_found);
+ mtd = mtd_concat_create(mtd_list, devices_found, c_mtd_name);
+
+ if (mtd == NULL)
+ return -ENXIO;
+
+ if (add_mtd_device(mtd))
+ return -ENOMEM;
}
+#endif /* CONFIG_MTD_CONCAT */
return 0;
}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
new file mode 100644
index 0000000..fc22701
--- /dev/null
+++ b/drivers/mtd/mtdconcat.c
@@ -0,0 +1,807 @@
+/*
+ * MTD device concatenation layer
+ *
+ * (C) 2002 Robert Kaiser <rkaiser(a)sysgo.de>
+ *
+ * NAND support by Christian Gan <cgan(a)iders.ca>
+ *
+ * This code is GPL
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/compat.h>
+#include <linux/mtd/concat.h>
+#include <ubi_uboot.h>
+
+/*
+ * Our storage structure:
+ * Subdev points to an array of pointers to struct mtd_info objects
+ * which is allocated along with this structure
+ *
+ */
+struct mtd_concat {
+ struct mtd_info mtd;
+ int num_subdev;
+ struct mtd_info **subdev;
+};
+
+/*
+ * how to calculate the size required for the above structure,
+ * including the pointer array subdev points to:
+ */
+#define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \
+ ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *)))
+
+/*
+ * Given a pointer to the MTD object in the mtd_concat structure,
+ * we can retrieve the pointer to that structure with this macro.
+ */
+#define CONCAT(x) ((struct mtd_concat *)(x))
+
+/*
+ * MTD methods which look up the relevant subdevice, translate the
+ * effective address and pass through to the subdevice.
+ */
+
+static int
+concat_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int ret = 0, err;
+ int i;
+
+ *retlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (from >= subdev->size) {
+ /* Not destined for this subdev */
+ size = 0;
+ from -= subdev->size;
+ continue;
+ }
+ if (from + len > subdev->size)
+ /* First part goes into this subdev */
+ size = subdev->size - from;
+ else
+ /* Entire transaction goes into this subdev */
+ size = len;
+
+ err = subdev->read(subdev, from, size, &retsize, buf);
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (err == -EBADMSG) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (err == -EUCLEAN) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ return ret;
+
+ buf += size;
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int err = -EINVAL;
+ int i;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ *retlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (to >= subdev->size) {
+ size = 0;
+ to -= subdev->size;
+ continue;
+ }
+ if (to + len > subdev->size)
+ size = subdev->size - to;
+ else
+ size = len;
+
+ if (!(subdev->flags & MTD_WRITEABLE))
+ err = -EROFS;
+ else
+ err = subdev->write(subdev, to, size, &retsize, buf);
+
+ if (err)
+ break;
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ buf += size;
+ to = 0;
+ }
+ return err;
+}
+
+static int
+concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err, ret = 0;
+
+ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (from >= subdev->size) {
+ from -= subdev->size;
+ continue;
+ }
+
+ /* partial read ? */
+ if (from + devops.len > subdev->size)
+ devops.len = subdev->size - from;
+
+ err = subdev->read_oob(subdev, from, &devops);
+ ops->retlen += devops.retlen;
+ ops->oobretlen += devops.oobretlen;
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (err == -EBADMSG) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (err == -EUCLEAN) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return ret;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return ret;
+ devops.oobbuf += ops->oobretlen;
+ }
+
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ ops->retlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (to >= subdev->size) {
+ to -= subdev->size;
+ continue;
+ }
+
+ /* partial write ? */
+ if (to + devops.len > subdev->size)
+ devops.len = subdev->size - to;
+
+ err = subdev->write_oob(subdev, to, &devops);
+ ops->retlen += devops.retlen;
+ if (err)
+ return err;
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return 0;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return 0;
+ devops.oobbuf += devops.oobretlen;
+ }
+ to = 0;
+ }
+ return -EINVAL;
+}
+
+static void concat_erase_callback(struct erase_info *instr)
+{
+ /* Nothing to do here in U-Boot */
+}
+
+static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+ int err;
+ wait_queue_head_t waitq;
+ DECLARE_WAITQUEUE(wait, current);
+
+ /*
+ * This code was stol^H^H^H^Hinspired by mtdchar.c
+ */
+ init_waitqueue_head(&waitq);
+
+ erase->mtd = mtd;
+ erase->callback = concat_erase_callback;
+ erase->priv = (unsigned long) &waitq;
+
+ /*
+ * FIXME: Allow INTERRUPTIBLE. Which means
+ * not having the wait_queue head on the stack.
+ */
+ err = mtd->erase(mtd, erase);
+ if (!err) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&waitq, &wait);
+ if (erase->state != MTD_ERASE_DONE
+ && erase->state != MTD_ERASE_FAILED)
+ schedule();
+ remove_wait_queue(&waitq, &wait);
+ set_current_state(TASK_RUNNING);
+
+ err = (erase->state == MTD_ERASE_FAILED) ? -EIO : 0;
+ }
+ return err;
+}
+
+static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_info *subdev;
+ int i, err;
+ uint64_t length, offset = 0;
+ struct erase_info *erase;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ if (instr->addr > concat->mtd.size)
+ return -EINVAL;
+
+ if (instr->len + instr->addr > concat->mtd.size)
+ return -EINVAL;
+
+ /*
+ * Check for proper erase block alignment of the to-be-erased area.
+ * It is easier to do this based on the super device's erase
+ * region info rather than looking at each particular sub-device
+ * in turn.
+ */
+ if (!concat->mtd.numeraseregions) {
+ /* the easy case: device has uniform erase block size */
+ if (instr->addr & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ if (instr->len & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ } else {
+ /* device has variable erase size */
+ struct mtd_erase_region_info *erase_regions =
+ concat->mtd.eraseregions;
+
+ /*
+ * Find the erase region where the to-be-erased area begins:
+ */
+ for (i = 0; i < concat->mtd.numeraseregions &&
+ instr->addr >= erase_regions[i].offset; i++) ;
+ --i;
+
+ /*
+ * Now erase_regions[i] is the region in which the
+ * to-be-erased area begins. Verify that the starting
+ * offset is aligned to this region's erase size:
+ */
+ if (instr->addr & (erase_regions[i].erasesize - 1))
+ return -EINVAL;
+
+ /*
+ * now find the erase region where the to-be-erased area ends:
+ */
+ for (; i < concat->mtd.numeraseregions &&
+ (instr->addr + instr->len) >= erase_regions[i].offset;
+ ++i) ;
+ --i;
+ /*
+ * check if the ending offset is aligned to this region's erase size
+ */
+ if ((instr->addr + instr->len) & (erase_regions[i].erasesize -
+ 1))
+ return -EINVAL;
+ }
+
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+
+ /* make a local copy of instr to avoid modifying the caller's struct */
+ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
+
+ if (!erase)
+ return -ENOMEM;
+
+ *erase = *instr;
+ length = instr->len;
+
+ /*
+ * find the subdevice where the to-be-erased area begins, adjust
+ * starting offset to be relative to the subdevice start
+ */
+ for (i = 0; i < concat->num_subdev; i++) {
+ subdev = concat->subdev[i];
+ if (subdev->size <= erase->addr) {
+ erase->addr -= subdev->size;
+ offset += subdev->size;
+ } else {
+ break;
+ }
+ }
+
+ /* must never happen since size limit has been verified above */
+ BUG_ON(i >= concat->num_subdev);
+
+ /* now do the erase: */
+ err = 0;
+ for (; length > 0; i++) {
+ /* loop for all subdevices affected by this request */
+ subdev = concat->subdev[i]; /* get current subdevice */
+
+ /* limit length to subdevice's size: */
+ if (erase->addr + length > subdev->size)
+ erase->len = subdev->size - erase->addr;
+ else
+ erase->len = length;
+
+ if (!(subdev->flags & MTD_WRITEABLE)) {
+ err = -EROFS;
+ break;
+ }
+ length -= erase->len;
+ if ((err = concat_dev_erase(subdev, erase))) {
+ /* sanity check: should never happen since
+ * block alignment has been checked above */
+ BUG_ON(err == -EINVAL);
+ if (erase->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
+ instr->fail_addr = erase->fail_addr + offset;
+ break;
+ }
+ /*
+ * erase->addr specifies the offset of the area to be
+ * erased *within the current subdevice*. It can be
+ * non-zero only the first time through this loop, i.e.
+ * for the first subdevice where blocks need to be erased.
+ * All the following erases must begin at the start of the
+ * current subdevice, i.e. at offset zero.
+ */
+ erase->addr = 0;
+ offset += subdev->size;
+ }
+ instr->state = erase->state;
+ kfree(erase);
+ if (err)
+ return err;
+
+ if (instr->callback)
+ instr->callback(instr);
+ return 0;
+}
+
+static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ if ((len + ofs) > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = subdev->lock(subdev, ofs, size);
+
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = 0;
+
+ if ((len + ofs) > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = subdev->unlock(subdev, ofs, size);
+
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static void concat_sync(struct mtd_info *mtd)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ subdev->sync(subdev);
+ }
+}
+
+static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, res = 0;
+
+ if (!concat->subdev[0]->block_isbad)
+ return res;
+
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ res = subdev->block_isbad(subdev, ofs);
+ break;
+ }
+
+ return res;
+}
+
+static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ if (!concat->subdev[0]->block_markbad)
+ return 0;
+
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ err = subdev->block_markbad(subdev, ofs);
+ if (!err)
+ mtd->ecc_stats.badblocks++;
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * This function constructs a virtual MTD device by concatenating
+ * num_devs MTD devices. A pointer to the new device object is
+ * stored to *new_dev upon success. This function does _not_
+ * register any devices: this is the caller's responsibility.
+ */
+struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name)
+{ /* name for the new device */
+ int i;
+ size_t size;
+ struct mtd_concat *concat;
+ uint32_t max_erasesize, curr_erasesize;
+ int num_erase_region;
+
+ debug("Concatenating MTD devices:\n");
+ for (i = 0; i < num_devs; i++)
+ debug("(%d): \"%s\"\n", i, subdev[i]->name);
+ debug("into device \"%s\"\n", name);
+
+ /* allocate the device structure */
+ size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
+ concat = kzalloc(size, GFP_KERNEL);
+ if (!concat) {
+ printk
+ ("memory allocation error while creating concatenated device \"%s\"\n",
+ name);
+ return NULL;
+ }
+ concat->subdev = (struct mtd_info **) (concat + 1);
+
+ /*
+ * Set up the new "super" device's MTD object structure, check for
+ * incompatibilites between the subdevices.
+ */
+ concat->mtd.type = subdev[0]->type;
+ concat->mtd.flags = subdev[0]->flags;
+ concat->mtd.size = subdev[0]->size;
+ concat->mtd.erasesize = subdev[0]->erasesize;
+ concat->mtd.writesize = subdev[0]->writesize;
+ concat->mtd.subpage_sft = subdev[0]->subpage_sft;
+ concat->mtd.oobsize = subdev[0]->oobsize;
+ concat->mtd.oobavail = subdev[0]->oobavail;
+ if (subdev[0]->read_oob)
+ concat->mtd.read_oob = concat_read_oob;
+ if (subdev[0]->write_oob)
+ concat->mtd.write_oob = concat_write_oob;
+ if (subdev[0]->block_isbad)
+ concat->mtd.block_isbad = concat_block_isbad;
+ if (subdev[0]->block_markbad)
+ concat->mtd.block_markbad = concat_block_markbad;
+
+ concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
+
+ concat->subdev[0] = subdev[0];
+
+ for (i = 1; i < num_devs; i++) {
+ if (concat->mtd.type != subdev[i]->type) {
+ kfree(concat);
+ printk("Incompatible device type on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ if (concat->mtd.flags != subdev[i]->flags) {
+ /*
+ * Expect all flags except MTD_WRITEABLE to be
+ * equal on all subdevices.
+ */
+ if ((concat->mtd.flags ^ subdev[i]->
+ flags) & ~MTD_WRITEABLE) {
+ kfree(concat);
+ printk("Incompatible device flags on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ } else
+ /* if writeable attribute differs,
+ make super device writeable */
+ concat->mtd.flags |=
+ subdev[i]->flags & MTD_WRITEABLE;
+ }
+
+ concat->mtd.size += subdev[i]->size;
+ concat->mtd.ecc_stats.badblocks +=
+ subdev[i]->ecc_stats.badblocks;
+ if (concat->mtd.writesize != subdev[i]->writesize ||
+ concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
+ concat->mtd.oobsize != subdev[i]->oobsize ||
+ !concat->mtd.read_oob != !subdev[i]->read_oob ||
+ !concat->mtd.write_oob != !subdev[i]->write_oob) {
+ kfree(concat);
+ printk("Incompatible OOB or ECC data on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ concat->subdev[i] = subdev[i];
+
+ }
+
+ concat->mtd.ecclayout = subdev[0]->ecclayout;
+
+ concat->num_subdev = num_devs;
+ concat->mtd.name = name;
+
+ concat->mtd.erase = concat_erase;
+ concat->mtd.read = concat_read;
+ concat->mtd.write = concat_write;
+ concat->mtd.sync = concat_sync;
+ concat->mtd.lock = concat_lock;
+ concat->mtd.unlock = concat_unlock;
+
+ /*
+ * Combine the erase block size info of the subdevices:
+ *
+ * first, walk the map of the new device and see how
+ * many changes in erase size we have
+ */
+ max_erasesize = curr_erasesize = subdev[0]->erasesize;
+ num_erase_region = 1;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /* if it differs from the last subdevice's erase size, count it */
+ ++num_erase_region;
+ curr_erasesize = subdev[i]->erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].erasesize !=
+ curr_erasesize) {
+ ++num_erase_region;
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ }
+ }
+ }
+
+ if (num_erase_region == 1) {
+ /*
+ * All subdevices have the same uniform erase size.
+ * This is easy:
+ */
+ concat->mtd.erasesize = curr_erasesize;
+ concat->mtd.numeraseregions = 0;
+ } else {
+ uint64_t tmp64;
+
+ /*
+ * erase block size varies across the subdevices: allocate
+ * space to store the data describing the variable erase regions
+ */
+ struct mtd_erase_region_info *erase_region_p;
+ uint64_t begin, position;
+
+ concat->mtd.erasesize = max_erasesize;
+ concat->mtd.numeraseregions = num_erase_region;
+ concat->mtd.eraseregions = erase_region_p =
+ kmalloc(num_erase_region *
+ sizeof (struct mtd_erase_region_info), GFP_KERNEL);
+ if (!erase_region_p) {
+ kfree(concat);
+ printk
+ ("memory allocation error while creating erase region list"
+ " for device \"%s\"\n", name);
+ return NULL;
+ }
+
+ /*
+ * walk the map of the new device once more and fill in
+ * in erase region info:
+ */
+ curr_erasesize = subdev[0]->erasesize;
+ begin = position = 0;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /*
+ * fill in an mtd_erase_region_info structure for the area
+ * we have walked so far:
+ */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize = subdev[i]->erasesize;
+ ++erase_region_p;
+ }
+ position += subdev[i]->size;
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].
+ erasesize != curr_erasesize) {
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ ++erase_region_p;
+ }
+ position +=
+ subdev[i]->eraseregions[j].
+ numblocks * (uint64_t)curr_erasesize;
+ }
+ }
+ }
+ /* Now write the final entry */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize = curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ }
+
+ return &concat->mtd;
+}
diff --git a/include/linux/mtd/compat.h b/include/linux/mtd/compat.h
index 9036b74..f0c8464 100644
--- a/include/linux/mtd/compat.h
+++ b/include/linux/mtd/compat.h
@@ -19,11 +19,15 @@
#define kmalloc(size, flags) malloc(size)
#define kzalloc(size, flags) calloc(size, 1)
-#define vmalloc(size) malloc(size)
-#define kfree(ptr) free(ptr)
-#define vfree(ptr) free(ptr)
+#define vmalloc(size) malloc(size)
+#define kfree(ptr) free(ptr)
+#define vfree(ptr) free(ptr)
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#define DECLARE_WAITQUEUE(...) do { } while (0)
+#define add_wait_queue(...) do { } while (0)
+#define remove_wait_queue(...) do { } while (0)
+
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
/*
* ..and if you can't take the strict
diff --git a/include/linux/mtd/concat.h b/include/linux/mtd/concat.h
new file mode 100644
index 0000000..e80c674
--- /dev/null
+++ b/include/linux/mtd/concat.h
@@ -0,0 +1,21 @@
+/*
+ * MTD device concatenation layer definitions
+ *
+ * (C) 2002 Robert Kaiser <rkaiser(a)sysgo.de>
+ *
+ * This code is GPL
+ */
+
+#ifndef MTD_CONCAT_H
+#define MTD_CONCAT_H
+
+
+struct mtd_info *mtd_concat_create(
+ struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name); /* name for the new device */
+
+void mtd_concat_destroy(struct mtd_info *mtd);
+
+#endif
+
--
1.6.2.5
2
1

[U-Boot] [PATCH] mtd: Add MTD concat support to concatenate multiple MTD NOR devices
by Stefan Roese 03 Jun '09
by Stefan Roese 03 Jun '09
03 Jun '09
This patch adds concatenation support to the U-Boot MTD infrastructure.
By enabling CONFIG_MTD_CONCAT this MTD CFI wrapper will concatenate
all found NOR devices into one single MTD device. This can be used by
e.g by UBI to access a partition that spans over multiple NOR chips.
Signed-off-by: Stefan Roese <sr(a)denx.de>
---
drivers/mtd/Makefile | 1 +
drivers/mtd/cfi_mtd.c | 77 +++++-
drivers/mtd/mtdconcat.c | 807 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/compat.h | 12 +-
include/linux/mtd/concat.h | 21 ++
5 files changed, 913 insertions(+), 5 deletions(-)
create mode 100644 drivers/mtd/mtdconcat.c
create mode 100644 include/linux/mtd/concat.h
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index ed3f91e..19dc02b 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libmtd.a
COBJS-$(CONFIG_MTD_PARTITIONS) += mtdcore.o mtdpart.o
+COBJS-$(CONFIG_MTD_CONCAT) += mtdconcat.o
COBJS-$(CONFIG_HAS_DATAFLASH) += at45.o
COBJS-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o
COBJS-$(CONFIG_FLASH_CFI_MTD) += cfi_mtd.o
diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c
index a0a15da..9a80e1d 100644
--- a/drivers/mtd/cfi_mtd.c
+++ b/drivers/mtd/cfi_mtd.c
@@ -25,14 +25,17 @@
#include <common.h>
#include <flash.h>
+#include <malloc.h>
#include <asm/errno.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/concat.h>
extern flash_info_t flash_info[];
static struct mtd_info cfi_mtd_info[CONFIG_SYS_MAX_FLASH_BANKS];
static char cfi_mtd_names[CONFIG_SYS_MAX_FLASH_BANKS][16];
+static __attribute__((unused)) char c_mtd_name[16];
static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
@@ -145,16 +148,68 @@ static int cfi_mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
static int cfi_mtd_set_erasesize(struct mtd_info *mtd, flash_info_t *fi)
{
int sect_size = 0;
+ int sect_size_old = 0;
int sect;
+ int regions = 0;
+ int numblocks = 0;
+ ulong offset = 0;
+ ulong base_addr = fi->start[0];
/*
- * Select the largest sector size as erasesize (e.g. for UBI)
+ * First detect the number of eraseregions so that we can allocate
+ * the array of eraseregions correctly
*/
for (sect = 0; sect < fi->sector_count; sect++) {
+ if (sect_size_old != flash_sector_size(fi, sect))
+ regions++;
+ sect_size_old = flash_sector_size(fi, sect);
+ }
+
+ mtd->eraseregions = malloc(sizeof(struct mtd_erase_region_info) * regions);
+
+ /*
+ * Now detect the largest sector and fill the eraseregions
+ */
+ sect_size_old = 0;
+ regions = 0;
+ for (sect = 0; sect < fi->sector_count; sect++) {
+ if ((sect_size_old != flash_sector_size(fi, sect)) &&
+ (sect_size_old != 0)) {
+ mtd->eraseregions[regions].offset = offset - base_addr;
+ mtd->eraseregions[regions].erasesize = sect_size_old;
+ mtd->eraseregions[regions].numblocks = numblocks;
+
+ /* Now start counting the next eraseregions */
+ numblocks = 0;
+ regions++;
+ } else {
+ numblocks++;
+ }
+
+ if (sect_size_old != flash_sector_size(fi, sect))
+ offset = fi->start[sect];
+
+ /*
+ * Select the largest sector size as erasesize (e.g. for UBI)
+ */
if (flash_sector_size(fi, sect) > sect_size)
sect_size = flash_sector_size(fi, sect);
+
+ sect_size_old = flash_sector_size(fi, sect);
}
+ /*
+ * Set the last region
+ */
+ mtd->eraseregions[regions].offset = offset - base_addr;
+ mtd->eraseregions[regions].erasesize = sect_size_old;
+ mtd->eraseregions[regions].numblocks = numblocks + 1;
+
+ if (regions)
+ mtd->numeraseregions = regions + 1;
+ else
+ mtd->numeraseregions = 0;
+
mtd->erasesize = sect_size;
return 0;
@@ -165,6 +220,8 @@ int cfi_mtd_init(void)
struct mtd_info *mtd;
flash_info_t *fi;
int error, i;
+ int devices_found = 0;
+ struct mtd_info *mtd_list[CONFIG_SYS_MAX_FLASH_BANKS];
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
fi = &flash_info[i];
@@ -193,7 +250,25 @@ int cfi_mtd_init(void)
if (add_mtd_device(mtd))
return -ENOMEM;
+
+ mtd_list[devices_found++] = mtd;
+ }
+
+#ifdef CONFIG_MTD_CONCAT
+ if (devices_found > 1) {
+ /*
+ * We detected multiple devices. Concatenate them together.
+ */
+ sprintf(c_mtd_name, "nor%d", devices_found);
+ mtd = mtd_concat_create(mtd_list, devices_found, c_mtd_name);
+
+ if (mtd == NULL)
+ return -ENXIO;
+
+ if (add_mtd_device(mtd))
+ return -ENOMEM;
}
+#endif /* CONFIG_MTD_CONCAT */
return 0;
}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
new file mode 100644
index 0000000..fc22701
--- /dev/null
+++ b/drivers/mtd/mtdconcat.c
@@ -0,0 +1,807 @@
+/*
+ * MTD device concatenation layer
+ *
+ * (C) 2002 Robert Kaiser <rkaiser(a)sysgo.de>
+ *
+ * NAND support by Christian Gan <cgan(a)iders.ca>
+ *
+ * This code is GPL
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/compat.h>
+#include <linux/mtd/concat.h>
+#include <ubi_uboot.h>
+
+/*
+ * Our storage structure:
+ * Subdev points to an array of pointers to struct mtd_info objects
+ * which is allocated along with this structure
+ *
+ */
+struct mtd_concat {
+ struct mtd_info mtd;
+ int num_subdev;
+ struct mtd_info **subdev;
+};
+
+/*
+ * how to calculate the size required for the above structure,
+ * including the pointer array subdev points to:
+ */
+#define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \
+ ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *)))
+
+/*
+ * Given a pointer to the MTD object in the mtd_concat structure,
+ * we can retrieve the pointer to that structure with this macro.
+ */
+#define CONCAT(x) ((struct mtd_concat *)(x))
+
+/*
+ * MTD methods which look up the relevant subdevice, translate the
+ * effective address and pass through to the subdevice.
+ */
+
+static int
+concat_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int ret = 0, err;
+ int i;
+
+ *retlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (from >= subdev->size) {
+ /* Not destined for this subdev */
+ size = 0;
+ from -= subdev->size;
+ continue;
+ }
+ if (from + len > subdev->size)
+ /* First part goes into this subdev */
+ size = subdev->size - from;
+ else
+ /* Entire transaction goes into this subdev */
+ size = len;
+
+ err = subdev->read(subdev, from, size, &retsize, buf);
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (err == -EBADMSG) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (err == -EUCLEAN) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ return ret;
+
+ buf += size;
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int err = -EINVAL;
+ int i;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ *retlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (to >= subdev->size) {
+ size = 0;
+ to -= subdev->size;
+ continue;
+ }
+ if (to + len > subdev->size)
+ size = subdev->size - to;
+ else
+ size = len;
+
+ if (!(subdev->flags & MTD_WRITEABLE))
+ err = -EROFS;
+ else
+ err = subdev->write(subdev, to, size, &retsize, buf);
+
+ if (err)
+ break;
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ buf += size;
+ to = 0;
+ }
+ return err;
+}
+
+static int
+concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err, ret = 0;
+
+ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (from >= subdev->size) {
+ from -= subdev->size;
+ continue;
+ }
+
+ /* partial read ? */
+ if (from + devops.len > subdev->size)
+ devops.len = subdev->size - from;
+
+ err = subdev->read_oob(subdev, from, &devops);
+ ops->retlen += devops.retlen;
+ ops->oobretlen += devops.oobretlen;
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (err == -EBADMSG) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (err == -EUCLEAN) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return ret;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return ret;
+ devops.oobbuf += ops->oobretlen;
+ }
+
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ ops->retlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (to >= subdev->size) {
+ to -= subdev->size;
+ continue;
+ }
+
+ /* partial write ? */
+ if (to + devops.len > subdev->size)
+ devops.len = subdev->size - to;
+
+ err = subdev->write_oob(subdev, to, &devops);
+ ops->retlen += devops.retlen;
+ if (err)
+ return err;
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return 0;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return 0;
+ devops.oobbuf += devops.oobretlen;
+ }
+ to = 0;
+ }
+ return -EINVAL;
+}
+
+static void concat_erase_callback(struct erase_info *instr)
+{
+ /* Nothing to do here in U-Boot */
+}
+
+static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+ int err;
+ wait_queue_head_t waitq;
+ DECLARE_WAITQUEUE(wait, current);
+
+ /*
+ * This code was stol^H^H^H^Hinspired by mtdchar.c
+ */
+ init_waitqueue_head(&waitq);
+
+ erase->mtd = mtd;
+ erase->callback = concat_erase_callback;
+ erase->priv = (unsigned long) &waitq;
+
+ /*
+ * FIXME: Allow INTERRUPTIBLE. Which means
+ * not having the wait_queue head on the stack.
+ */
+ err = mtd->erase(mtd, erase);
+ if (!err) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&waitq, &wait);
+ if (erase->state != MTD_ERASE_DONE
+ && erase->state != MTD_ERASE_FAILED)
+ schedule();
+ remove_wait_queue(&waitq, &wait);
+ set_current_state(TASK_RUNNING);
+
+ err = (erase->state == MTD_ERASE_FAILED) ? -EIO : 0;
+ }
+ return err;
+}
+
+static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_info *subdev;
+ int i, err;
+ uint64_t length, offset = 0;
+ struct erase_info *erase;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ if (instr->addr > concat->mtd.size)
+ return -EINVAL;
+
+ if (instr->len + instr->addr > concat->mtd.size)
+ return -EINVAL;
+
+ /*
+ * Check for proper erase block alignment of the to-be-erased area.
+ * It is easier to do this based on the super device's erase
+ * region info rather than looking at each particular sub-device
+ * in turn.
+ */
+ if (!concat->mtd.numeraseregions) {
+ /* the easy case: device has uniform erase block size */
+ if (instr->addr & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ if (instr->len & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ } else {
+ /* device has variable erase size */
+ struct mtd_erase_region_info *erase_regions =
+ concat->mtd.eraseregions;
+
+ /*
+ * Find the erase region where the to-be-erased area begins:
+ */
+ for (i = 0; i < concat->mtd.numeraseregions &&
+ instr->addr >= erase_regions[i].offset; i++) ;
+ --i;
+
+ /*
+ * Now erase_regions[i] is the region in which the
+ * to-be-erased area begins. Verify that the starting
+ * offset is aligned to this region's erase size:
+ */
+ if (instr->addr & (erase_regions[i].erasesize - 1))
+ return -EINVAL;
+
+ /*
+ * now find the erase region where the to-be-erased area ends:
+ */
+ for (; i < concat->mtd.numeraseregions &&
+ (instr->addr + instr->len) >= erase_regions[i].offset;
+ ++i) ;
+ --i;
+ /*
+ * check if the ending offset is aligned to this region's erase size
+ */
+ if ((instr->addr + instr->len) & (erase_regions[i].erasesize -
+ 1))
+ return -EINVAL;
+ }
+
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+
+ /* make a local copy of instr to avoid modifying the caller's struct */
+ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
+
+ if (!erase)
+ return -ENOMEM;
+
+ *erase = *instr;
+ length = instr->len;
+
+ /*
+ * find the subdevice where the to-be-erased area begins, adjust
+ * starting offset to be relative to the subdevice start
+ */
+ for (i = 0; i < concat->num_subdev; i++) {
+ subdev = concat->subdev[i];
+ if (subdev->size <= erase->addr) {
+ erase->addr -= subdev->size;
+ offset += subdev->size;
+ } else {
+ break;
+ }
+ }
+
+ /* must never happen since size limit has been verified above */
+ BUG_ON(i >= concat->num_subdev);
+
+ /* now do the erase: */
+ err = 0;
+ for (; length > 0; i++) {
+ /* loop for all subdevices affected by this request */
+ subdev = concat->subdev[i]; /* get current subdevice */
+
+ /* limit length to subdevice's size: */
+ if (erase->addr + length > subdev->size)
+ erase->len = subdev->size - erase->addr;
+ else
+ erase->len = length;
+
+ if (!(subdev->flags & MTD_WRITEABLE)) {
+ err = -EROFS;
+ break;
+ }
+ length -= erase->len;
+ if ((err = concat_dev_erase(subdev, erase))) {
+ /* sanity check: should never happen since
+ * block alignment has been checked above */
+ BUG_ON(err == -EINVAL);
+ if (erase->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
+ instr->fail_addr = erase->fail_addr + offset;
+ break;
+ }
+ /*
+ * erase->addr specifies the offset of the area to be
+ * erased *within the current subdevice*. It can be
+ * non-zero only the first time through this loop, i.e.
+ * for the first subdevice where blocks need to be erased.
+ * All the following erases must begin at the start of the
+ * current subdevice, i.e. at offset zero.
+ */
+ erase->addr = 0;
+ offset += subdev->size;
+ }
+ instr->state = erase->state;
+ kfree(erase);
+ if (err)
+ return err;
+
+ if (instr->callback)
+ instr->callback(instr);
+ return 0;
+}
+
+static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ if ((len + ofs) > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = subdev->lock(subdev, ofs, size);
+
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = 0;
+
+ if ((len + ofs) > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = subdev->unlock(subdev, ofs, size);
+
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static void concat_sync(struct mtd_info *mtd)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ subdev->sync(subdev);
+ }
+}
+
+static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, res = 0;
+
+ if (!concat->subdev[0]->block_isbad)
+ return res;
+
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ res = subdev->block_isbad(subdev, ofs);
+ break;
+ }
+
+ return res;
+}
+
+static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ if (!concat->subdev[0]->block_markbad)
+ return 0;
+
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ err = subdev->block_markbad(subdev, ofs);
+ if (!err)
+ mtd->ecc_stats.badblocks++;
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * This function constructs a virtual MTD device by concatenating
+ * num_devs MTD devices. A pointer to the new device object is
+ * stored to *new_dev upon success. This function does _not_
+ * register any devices: this is the caller's responsibility.
+ */
+struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name)
+{ /* name for the new device */
+ int i;
+ size_t size;
+ struct mtd_concat *concat;
+ uint32_t max_erasesize, curr_erasesize;
+ int num_erase_region;
+
+ debug("Concatenating MTD devices:\n");
+ for (i = 0; i < num_devs; i++)
+ debug("(%d): \"%s\"\n", i, subdev[i]->name);
+ debug("into device \"%s\"\n", name);
+
+ /* allocate the device structure */
+ size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
+ concat = kzalloc(size, GFP_KERNEL);
+ if (!concat) {
+ printk
+ ("memory allocation error while creating concatenated device \"%s\"\n",
+ name);
+ return NULL;
+ }
+ concat->subdev = (struct mtd_info **) (concat + 1);
+
+ /*
+ * Set up the new "super" device's MTD object structure, check for
+ * incompatibilites between the subdevices.
+ */
+ concat->mtd.type = subdev[0]->type;
+ concat->mtd.flags = subdev[0]->flags;
+ concat->mtd.size = subdev[0]->size;
+ concat->mtd.erasesize = subdev[0]->erasesize;
+ concat->mtd.writesize = subdev[0]->writesize;
+ concat->mtd.subpage_sft = subdev[0]->subpage_sft;
+ concat->mtd.oobsize = subdev[0]->oobsize;
+ concat->mtd.oobavail = subdev[0]->oobavail;
+ if (subdev[0]->read_oob)
+ concat->mtd.read_oob = concat_read_oob;
+ if (subdev[0]->write_oob)
+ concat->mtd.write_oob = concat_write_oob;
+ if (subdev[0]->block_isbad)
+ concat->mtd.block_isbad = concat_block_isbad;
+ if (subdev[0]->block_markbad)
+ concat->mtd.block_markbad = concat_block_markbad;
+
+ concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
+
+ concat->subdev[0] = subdev[0];
+
+ for (i = 1; i < num_devs; i++) {
+ if (concat->mtd.type != subdev[i]->type) {
+ kfree(concat);
+ printk("Incompatible device type on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ if (concat->mtd.flags != subdev[i]->flags) {
+ /*
+ * Expect all flags except MTD_WRITEABLE to be
+ * equal on all subdevices.
+ */
+ if ((concat->mtd.flags ^ subdev[i]->
+ flags) & ~MTD_WRITEABLE) {
+ kfree(concat);
+ printk("Incompatible device flags on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ } else
+ /* if writeable attribute differs,
+ make super device writeable */
+ concat->mtd.flags |=
+ subdev[i]->flags & MTD_WRITEABLE;
+ }
+
+ concat->mtd.size += subdev[i]->size;
+ concat->mtd.ecc_stats.badblocks +=
+ subdev[i]->ecc_stats.badblocks;
+ if (concat->mtd.writesize != subdev[i]->writesize ||
+ concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
+ concat->mtd.oobsize != subdev[i]->oobsize ||
+ !concat->mtd.read_oob != !subdev[i]->read_oob ||
+ !concat->mtd.write_oob != !subdev[i]->write_oob) {
+ kfree(concat);
+ printk("Incompatible OOB or ECC data on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ concat->subdev[i] = subdev[i];
+
+ }
+
+ concat->mtd.ecclayout = subdev[0]->ecclayout;
+
+ concat->num_subdev = num_devs;
+ concat->mtd.name = name;
+
+ concat->mtd.erase = concat_erase;
+ concat->mtd.read = concat_read;
+ concat->mtd.write = concat_write;
+ concat->mtd.sync = concat_sync;
+ concat->mtd.lock = concat_lock;
+ concat->mtd.unlock = concat_unlock;
+
+ /*
+ * Combine the erase block size info of the subdevices:
+ *
+ * first, walk the map of the new device and see how
+ * many changes in erase size we have
+ */
+ max_erasesize = curr_erasesize = subdev[0]->erasesize;
+ num_erase_region = 1;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /* if it differs from the last subdevice's erase size, count it */
+ ++num_erase_region;
+ curr_erasesize = subdev[i]->erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].erasesize !=
+ curr_erasesize) {
+ ++num_erase_region;
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ }
+ }
+ }
+
+ if (num_erase_region == 1) {
+ /*
+ * All subdevices have the same uniform erase size.
+ * This is easy:
+ */
+ concat->mtd.erasesize = curr_erasesize;
+ concat->mtd.numeraseregions = 0;
+ } else {
+ uint64_t tmp64;
+
+ /*
+ * erase block size varies across the subdevices: allocate
+ * space to store the data describing the variable erase regions
+ */
+ struct mtd_erase_region_info *erase_region_p;
+ uint64_t begin, position;
+
+ concat->mtd.erasesize = max_erasesize;
+ concat->mtd.numeraseregions = num_erase_region;
+ concat->mtd.eraseregions = erase_region_p =
+ kmalloc(num_erase_region *
+ sizeof (struct mtd_erase_region_info), GFP_KERNEL);
+ if (!erase_region_p) {
+ kfree(concat);
+ printk
+ ("memory allocation error while creating erase region list"
+ " for device \"%s\"\n", name);
+ return NULL;
+ }
+
+ /*
+ * walk the map of the new device once more and fill in
+ * in erase region info:
+ */
+ curr_erasesize = subdev[0]->erasesize;
+ begin = position = 0;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /*
+ * fill in an mtd_erase_region_info structure for the area
+ * we have walked so far:
+ */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize = subdev[i]->erasesize;
+ ++erase_region_p;
+ }
+ position += subdev[i]->size;
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].
+ erasesize != curr_erasesize) {
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ ++erase_region_p;
+ }
+ position +=
+ subdev[i]->eraseregions[j].
+ numblocks * (uint64_t)curr_erasesize;
+ }
+ }
+ }
+ /* Now write the final entry */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize = curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ }
+
+ return &concat->mtd;
+}
diff --git a/include/linux/mtd/compat.h b/include/linux/mtd/compat.h
index 9036b74..f0c8464 100644
--- a/include/linux/mtd/compat.h
+++ b/include/linux/mtd/compat.h
@@ -19,11 +19,15 @@
#define kmalloc(size, flags) malloc(size)
#define kzalloc(size, flags) calloc(size, 1)
-#define vmalloc(size) malloc(size)
-#define kfree(ptr) free(ptr)
-#define vfree(ptr) free(ptr)
+#define vmalloc(size) malloc(size)
+#define kfree(ptr) free(ptr)
+#define vfree(ptr) free(ptr)
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#define DECLARE_WAITQUEUE(...) do { } while (0)
+#define add_wait_queue(...) do { } while (0)
+#define remove_wait_queue(...) do { } while (0)
+
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
/*
* ..and if you can't take the strict
diff --git a/include/linux/mtd/concat.h b/include/linux/mtd/concat.h
new file mode 100644
index 0000000..e80c674
--- /dev/null
+++ b/include/linux/mtd/concat.h
@@ -0,0 +1,21 @@
+/*
+ * MTD device concatenation layer definitions
+ *
+ * (C) 2002 Robert Kaiser <rkaiser(a)sysgo.de>
+ *
+ * This code is GPL
+ */
+
+#ifndef MTD_CONCAT_H
+#define MTD_CONCAT_H
+
+
+struct mtd_info *mtd_concat_create(
+ struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name); /* name for the new device */
+
+void mtd_concat_destroy(struct mtd_info *mtd);
+
+#endif
+
--
1.6.2.5
2
1
This patch now enabled this cfi-mtd wrapper to correctly detect and
erase the last sector in an NOR FLASH device.
Signed-off-by: Stefan Roese <sr(a)denx.de>
---
drivers/mtd/cfi_mtd.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c
index f03e4fb..4a76917 100644
--- a/drivers/mtd/cfi_mtd.c
+++ b/drivers/mtd/cfi_mtd.c
@@ -43,11 +43,16 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
int s_last = -1;
int error, sect;
- for (sect = 0; sect < fi->sector_count - 1; sect++) {
+ for (sect = 0; sect < fi->sector_count; sect++) {
if (a_start == fi->start[sect])
s_first = sect;
- if (a_end == fi->start[sect + 1]) {
+ if (sect < fi->sector_count - 1) {
+ if (a_end == fi->start[sect + 1]) {
+ s_last = sect;
+ break;
+ }
+ } else {
s_last = sect;
break;
}
--
1.6.2.5
2
1