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
January 2014
- 180 participants
- 674 discussions

25 Feb '14
- fix serdes definition for t2081.
- fix clock speed for t2081.
- update ids, as CONFIG_FSL_SATA_V2 is needed only for t2080,
T2081 has no SATA.
Signed-off-by: Shengzhou Liu <Shengzhou.Liu(a)freescale.com>
---
arch/powerpc/cpu/mpc85xx/speed.c | 3 ++-
arch/powerpc/cpu/mpc85xx/t2080_ids.c | 2 ++
arch/powerpc/cpu/mpc85xx/t2080_serdes.c | 3 +--
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c
index 35867df..adf09ef 100644
--- a/arch/powerpc/cpu/mpc85xx/speed.c
+++ b/arch/powerpc/cpu/mpc85xx/speed.c
@@ -151,7 +151,8 @@ void get_sys_info(sys_info_t *sys_info)
sys_info->freq_processor[cpu] =
freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
}
-#if defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_T2080)
+#if defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_T2080) || \
+ defined(CONFIG_PPC_T2081)
#define FM1_CLK_SEL 0xe0000000
#define FM1_CLK_SHIFT 29
#else
diff --git a/arch/powerpc/cpu/mpc85xx/t2080_ids.c b/arch/powerpc/cpu/mpc85xx/t2080_ids.c
index 068e1f2..0bfd447 100644
--- a/arch/powerpc/cpu/mpc85xx/t2080_ids.c
+++ b/arch/powerpc/cpu/mpc85xx/t2080_ids.c
@@ -53,8 +53,10 @@ struct liodn_id_table liodn_tbl[] = {
SET_USB_LIODN(1, "fsl-usb2-mph", 553),
SET_USB_LIODN(2, "fsl-usb2-dr", 554),
+#ifdef CONFIG_FSL_SATA_V2
SET_SATA_LIODN(1, 555),
SET_SATA_LIODN(2, 556),
+#endif
SET_PCI_LIODN_BASE(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 148),
SET_PCI_LIODN_BASE(CONFIG_SYS_FSL_PCIE_COMPAT, 2, 228),
diff --git a/arch/powerpc/cpu/mpc85xx/t2080_serdes.c b/arch/powerpc/cpu/mpc85xx/t2080_serdes.c
index f2fbdeb..07e27de 100644
--- a/arch/powerpc/cpu/mpc85xx/t2080_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/t2080_serdes.c
@@ -43,7 +43,6 @@ static const struct serdes_config serdes1_cfg_tbl[] = {
{0x6C, {XFI_FM1_MAC9, XFI_FM1_MAC10,
SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
PCIE4, PCIE4, PCIE4, PCIE4} },
-#if defined(CONFIG_PPC_T2080)
{0x1C, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC10,
SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
@@ -129,7 +128,7 @@ static const struct serdes_config serdes1_cfg_tbl[] = {
XFI_FM1_MAC1, XFI_FM1_MAC2,
PCIE4, PCIE4, PCIE4, PCIE4} },
-#elif defined(CONFIG_PPC_T2081)
+#if defined(CONFIG_PPC_T2081)
{0xAA, {PCIE3, PCIE3, PCIE3, PCIE3,
PCIE4, PCIE4, PCIE4, PCIE4} },
{0xCA, {PCIE3, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC1,
--
1.8.0
2
2

25 Feb '14
T1040 has internal display interface unit (DIU) for driving video.
T1040QDS supports video mode via
-LCD using TI enconder
-HDMI type interface via HDMI encoder
Chrontel, CH7301C encoder which is I2C programmable is used as
HDMI connector on T1040QDS.
This patch add support to
-enable Video interface for T1040QDS
-route qixis multiplexing to enable DIU-HDMI interface on board
-program DIU pixel clock gerenartor for T1040
-program HDMI encoder via I2C on board
Signed-off-by: Priyanka Jain <Priyanka.Jain(a)freescale.com>
---
board/freescale/t1040qds/Makefile | 1 +
board/freescale/t1040qds/diu.c | 168 +++++++++++++++++++++++++++++
board/freescale/t1040qds/t1040qds.h | 1 +
board/freescale/t1040qds/t1040qds_qixis.h | 12 ++
include/configs/T1040QDS.h | 27 +++++-
5 files changed, 208 insertions(+), 1 deletions(-)
create mode 100644 board/freescale/t1040qds/diu.c
diff --git a/board/freescale/t1040qds/Makefile b/board/freescale/t1040qds/Makefile
index c7470d7..19ed21b 100644
--- a/board/freescale/t1040qds/Makefile
+++ b/board/freescale/t1040qds/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_PCI) += pci.o
obj-y += law.o
obj-y += tlb.o
obj-y += eth.o
+obj-y += diu.o
diff --git a/board/freescale/t1040qds/diu.c b/board/freescale/t1040qds/diu.c
new file mode 100644
index 0000000..b785aa3
--- /dev/null
+++ b/board/freescale/t1040qds/diu.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ * Author: Priyanka Jain <Priyanka.Jain(a)freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <asm/io.h>
+#include <stdio_dev.h>
+#include <video_fb.h>
+#include <fsl_diu_fb.h>
+#include "../common/qixis.h"
+#include "t1040qds.h"
+#include "t1040qds_qixis.h"
+
+
+#define I2C_DVI_INPUT_DATA_FORMAT_REG 0x1F
+#define I2C_DVI_PLL_CHARGE_CNTL_REG 0x33
+#define I2C_DVI_PLL_DIVIDER_REG 0x34
+#define I2C_DVI_PLL_SUPPLY_CNTL_REG 0x35
+#define I2C_DVI_PLL_FILTER_REG 0x36
+#define I2C_DVI_TEST_PATTERN_REG 0x48
+#define I2C_DVI_POWER_MGMT_REG 0x49
+#define I2C_DVI_LOCK_STATE_REG 0x4D
+#define I2C_DVI_SYNC_POLARITY_REG 0x56
+
+/*
+ * Set VSYNC/HSYNC to active high. This is polarity of sync signals
+ * from DIU->DVI. The DIU default is active igh, so DVI is set to
+ * active high.
+ */
+#define I2C_DVI_INPUT_DATA_FORMAT_VAL 0x98
+
+#define I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL 0x06
+#define I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL 0x26
+#define I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL 0xA0
+#define I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL 0x08
+#define I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL 0x16
+#define I2C_DVI_PLL_FILTER_LOW_SPEED_VAL 0x60
+
+/* Clear test pattern */
+#define I2C_DVI_TEST_PATTERN_VAL 0x18
+/* Exit Power-down mode */
+#define I2C_DVI_POWER_MGMT_VAL 0xC0
+
+/* Monitor polarity is handled via DVI Sync Polarity Register */
+#define I2C_DVI_SYNC_POLARITY_VAL 0x00
+
+/*
+ * DIU Area Descriptor
+ *
+ * Note that we need to byte-swap the value before it's written to the AD
+ * register. So even though the registers don't look like they're in the same
+ * bit positions as they are on the MPC8610, the same value is written to the
+ * AD register on the MPC8610 and on the P1022.
+ */
+#define AD_BYTE_F 0x10000000
+#define AD_ALPHA_C_SHIFT 25
+#define AD_BLUE_C_SHIFT 23
+#define AD_GREEN_C_SHIFT 21
+#define AD_RED_C_SHIFT 19
+#define AD_PIXEL_S_SHIFT 16
+#define AD_COMP_3_SHIFT 12
+#define AD_COMP_2_SHIFT 8
+#define AD_COMP_1_SHIFT 4
+#define AD_COMP_0_SHIFT 0
+
+/* Programming of HDMI Chrontel CH7301 connector */
+void diu_set_dvi_encoder(unsigned int pixclock)
+{
+ int ret;
+ u8 temp;
+ select_i2c_ch_pca9547(I2C_MUX_CH_DIU);
+
+ temp = I2C_DVI_TEST_PATTERN_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_TEST_PATTERN_REG, 1,
+ &temp, 1);
+ temp = I2C_DVI_INPUT_DATA_FORMAT_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_INPUT_DATA_FORMAT_REG,
+ 1, &temp, 1);
+
+ /* Set Sync polarity register */
+ temp = I2C_DVI_SYNC_POLARITY_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_SYNC_POLARITY_REG, 1,
+ &temp, 1);
+
+ /* Set PLL registers based on pixel clock rate*/
+ if (pixclock > 65000000) {
+ temp = I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
+ I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1);
+ temp = I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
+ I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
+ temp = I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
+ I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
+ } else {
+ temp = I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
+ I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1);
+ temp = I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
+ I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
+ temp = I2C_DVI_PLL_FILTER_LOW_SPEED_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
+ I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
+ }
+
+ temp = I2C_DVI_POWER_MGMT_VAL;
+ ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_POWER_MGMT_REG, 1,
+ &temp, 1);
+
+ udelay(500);
+
+ select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
+}
+
+void diu_set_pixel_clock(unsigned int pixclock)
+{
+ unsigned long speed_ccb, temp;
+ u32 pixval;
+ speed_ccb = get_bus_freq(0);
+ temp = 1000000000 / pixclock;
+ temp *= 1000;
+ pixval = speed_ccb / temp;
+
+ /* Program HDMI encoder */
+ diu_set_dvi_encoder(temp);
+
+ /* Program pixel clock */
+ out_be32(CONFIG_SYS_FSL_SCFG_PIXCLK_ADDR,
+ ((pixval << PXCK_BITS_START) & PXCK_MASK));
+ /* enable clock*/
+ out_be32(CONFIG_SYS_FSL_SCFG_PIXCLK_ADDR, PXCKEN_MASK |
+ ((pixval << PXCK_BITS_START) & PXCK_MASK));
+}
+
+int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
+{
+ u32 pixel_format;
+ u8 sw;
+
+ /*Route I2C4 to DIU system as HSYNC/VSYNC*/
+ sw = QIXIS_READ(brdcfg[5]);
+ QIXIS_WRITE(brdcfg[5],
+ ((sw & ~(BRDCFG5_IMX_MASK)) | (BRDCFG5_IMX_DIU)));
+
+ /*Configure Display ouput port as HDMI*/
+ sw = QIXIS_READ(brdcfg[15]);
+ QIXIS_WRITE(brdcfg[15],
+ ((sw & ~(BRDCFG15_LCDPD_MASK | BRDCFG15_DIUSEL_MASK))
+ | (BRDCFG15_LCDPD_ENABLED | BRDCFG15_DIUSEL_HDMI)));
+
+ pixel_format = cpu_to_le32(AD_BYTE_F | (3 << AD_ALPHA_C_SHIFT) |
+ (0 << AD_BLUE_C_SHIFT) | (1 << AD_GREEN_C_SHIFT) |
+ (2 << AD_RED_C_SHIFT) | (8 << AD_COMP_3_SHIFT) |
+ (8 << AD_COMP_2_SHIFT) | (8 << AD_COMP_1_SHIFT) |
+ (8 << AD_COMP_0_SHIFT) | (3 << AD_PIXEL_S_SHIFT));
+
+ printf("DIU: Switching to monitor @ %ux%u\n", xres, yres);
+
+
+ return fsl_diu_init(xres, yres, pixel_format, 0);
+}
diff --git a/board/freescale/t1040qds/t1040qds.h b/board/freescale/t1040qds/t1040qds.h
index 79bdeda..5041f37 100644
--- a/board/freescale/t1040qds/t1040qds.h
+++ b/board/freescale/t1040qds/t1040qds.h
@@ -9,5 +9,6 @@
void fdt_fixup_board_enet(void *blob);
void pci_of_setup(void *blob, bd_t *bd);
+int select_i2c_ch_pca9547(u8 ch);
#endif
diff --git a/board/freescale/t1040qds/t1040qds_qixis.h b/board/freescale/t1040qds/t1040qds_qixis.h
index 2ce8795..98d2d39 100644
--- a/board/freescale/t1040qds/t1040qds_qixis.h
+++ b/board/freescale/t1040qds/t1040qds_qixis.h
@@ -13,6 +13,18 @@
#define BRDCFG4_EMISEL_MASK 0xE0
#define BRDCFG4_EMISEL_SHIFT 5
+/* BRDCFG5[0:1] controls routing and use of I2C3 & I2C4 ports*/
+#define BRDCFG5_IMX_MASK 0xC0
+#define BRDCFG5_IMX_DIU 0x80
+
+/* BRDCFG15[3] controls LCD Panel Powerdown*/
+#define BRDCFG15_LCDPD_MASK 0x10
+#define BRDCFG15_LCDPD_ENABLED 0x00
+
+/* BRDCFG15[6:7] controls DIU MUX selction*/
+#define BRDCFG15_DIUSEL_MASK 0x03
+#define BRDCFG15_DIUSEL_HDMI 0x00
+
/* SYSCLK */
#define QIXIS_SYSCLK_66 0x0
#define QIXIS_SYSCLK_83 0x1
diff --git a/include/configs/T1040QDS.h b/include/configs/T1040QDS.h
index bf22bec..d77cba1 100644
--- a/include/configs/T1040QDS.h
+++ b/include/configs/T1040QDS.h
@@ -376,7 +376,7 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_GBL_DATA_OFFSET
#define CONFIG_SYS_MONITOR_LEN (512 * 1024)
-#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN (10 * 1024 * 1024)
/* Serial Port - controlled on board with jumper J8
* open - index 2
@@ -402,6 +402,25 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_SYS_HUSH_PARSER
#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+/* Video */
+#define CONFIG_FSL_DIU_FB
+#ifdef CONFIG_FSL_DIU_FB
+#define CONFIG_SYS_DIU_ADDR (CONFIG_SYS_CCSRBAR + 0x180000)
+#define CONFIG_VIDEO
+#define CONFIG_CMD_BMP
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VIDEO_SW_CURSOR
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
+/*
+ * With CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS, flash I/O is really slow, so
+ * disable empty flash sector detection, which is I/O-intensive.
+ */
+#undef CONFIG_SYS_FLASH_EMPTY_INFO
+#endif
+
/* pass open firmware flat tree */
#define CONFIG_OF_LIBFDT
#define CONFIG_OF_BOARD_SETUP
@@ -427,6 +446,11 @@ unsigned long get_board_ddr_clk(void);
/* I2C bus multiplexer */
#define I2C_MUX_CH_DEFAULT 0x8
+#define I2C_MUX_CH_DIU 0xC
+
+/* LDI/DVI Encoder for display */
+#define CONFIG_SYS_I2C_LDI_ADDR 0x38
+#define CONFIG_SYS_I2C_DVI_ADDR 0x75
/*
* RTC configuration
@@ -705,6 +729,7 @@ unsigned long get_board_ddr_clk(void);
"bank_intlv=cs0_cs1;" \
"usb1:dr_mode=host,phy_type=" __stringify(__USB_PHY_TYPE) "\0"\
"netdev=eth0\0" \
+ "video-mode=fslfb:1024x768-32@60,monitor=dvi\0" \
"uboot=" __stringify(CONFIG_UBOOTPATH) "\0" \
"ubootaddr=" __stringify(CONFIG_SYS_TEXT_BASE) "\0" \
"tftpflash=tftpboot $loadaddr $uboot && " \
--
1.7.4.1
2
1
USB spec says that the minimum disconnect threshold should be
over 525 mV. However, internal USB PHY threshold value is below
this specified value. Due to this some devices disconnect at
run-time. Hence, phy settings are tweaked to increased disconnect
threshold to be above 525mV by using this workaround.
Signed-off-by: Suresh Gupta <suresh.gupta(a)freescale.com>
---
arch/powerpc/cpu/mpc85xx/cmd_errata.c | 4 ++
arch/powerpc/cpu/mpc85xx/cpu_init.c | 62 +++++++++++++++++++++++++++++++
arch/powerpc/include/asm/config_mpc85xx.h | 7 ++++
arch/powerpc/include/asm/fsl_errata.h | 31 ++++++++++++++++
include/fsl_usb.h | 23 +++++++++++-
5 files changed, 125 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index 7693899..2a15802 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -265,6 +265,10 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
(SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV))
puts("Work-around for Erratum I2C-A004447 enabled\n");
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
+ if (has_erratum_a006261())
+ puts("Work-around for Erratum A006261 enabled\n");
+#endif
return 0;
}
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index b31efb7..81aeadd 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -36,6 +36,54 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
+void fsl_erratum_a006261_workaround(struct ccsr_usb_phy __iomem *usb_phy)
+{
+#ifdef CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE
+ u32 xcvrprg = in_be32(&usb_phy->port1.xcvrprg);
+
+ /* Increase Disconnect Threshold by 50mV */
+ xcvrprg &= ~CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK |
+ INC_DCNT_THRESHOLD_50MV;
+ /* Enable programming of USB High speed Disconnect threshold */
+ xcvrprg |= CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN;
+ out_be32(&usb_phy->port1.xcvrprg, xcvrprg);
+
+ xcvrprg = in_be32(&usb_phy->port2.xcvrprg);
+ /* Increase Disconnect Threshold by 50mV */
+ xcvrprg &= ~CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK |
+ INC_DCNT_THRESHOLD_50MV;
+ /* Enable programming of USB High speed Disconnect threshold */
+ xcvrprg |= CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN;
+ out_be32(&usb_phy->port2.xcvrprg, xcvrprg);
+#else
+
+ u32 temp = 0;
+ u32 status = in_be32(&usb_phy->status1);
+
+ u32 squelch_prog_rd_0_2 =
+ (status >> CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_0)
+ & CONFIG_SYS_FSL_USB_SQUELCH_PROG_MASK;
+
+ u32 squelch_prog_rd_3_5 =
+ (status >> CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_3)
+ & CONFIG_SYS_FSL_USB_SQUELCH_PROG_MASK;
+
+ setbits_be32(&usb_phy->config1,
+ CONFIG_SYS_FSL_USB_HS_DISCNCT_INC);
+ setbits_be32(&usb_phy->config2,
+ CONFIG_SYS_FSL_USB_RX_AUTO_CAL_RD_WR_SEL);
+
+ temp = squelch_prog_rd_0_2 << CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_0;
+ out_be32(&usb_phy->config2, in_be32(&usb_phy->config2) | temp);
+
+ temp = squelch_prog_rd_3_5 << CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_3;
+ out_be32(&usb_phy->config2, in_be32(&usb_phy->config2) | temp);
+#endif
+}
+#endif
+
+
#ifdef CONFIG_QE
extern qe_iop_conf_t qe_iop_conf_tab[];
extern void qe_config_iopin(u8 port, u8 pin, int dir,
@@ -625,6 +673,10 @@ skip_l2:
{
struct ccsr_usb_phy __iomem *usb_phy1 =
(void *)CONFIG_SYS_MPC85xx_USB1_PHY_ADDR;
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
+ if (has_erratum_a006261())
+ fsl_erratum_a006261_workaround(usb_phy1);
+#endif
out_be32(&usb_phy1->usb_enable_override,
CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE);
}
@@ -633,6 +685,10 @@ skip_l2:
{
struct ccsr_usb_phy __iomem *usb_phy2 =
(void *)CONFIG_SYS_MPC85xx_USB2_PHY_ADDR;
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
+ if (has_erratum_a006261())
+ fsl_erratum_a006261_workaround(usb_phy2);
+#endif
out_be32(&usb_phy2->usb_enable_override,
CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE);
}
@@ -672,8 +728,14 @@ skip_l2:
CONFIG_SYS_FSL_USB_DRVVBUS_CR_EN);
setbits_be32(&usb_phy->port2.pwrfltcfg,
CONFIG_SYS_FSL_USB_PWRFLT_CR_EN);
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
+ if (has_erratum_a006261())
+ fsl_erratum_a006261_workaround(usb_phy);
#endif
+#endif /* CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE */
+
#ifdef CONFIG_FMAN_ENET
fman_enet_init();
#endif
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index be1d9d2..9f1d202 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -151,6 +151,7 @@
#define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
#define CONFIG_SYS_FSL_ERRATUM_A005125
#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_ERRATUM_A006261
#define CONFIG_SYS_FSL_A004447_SVR_REV 0x10
#define CONFIG_ESDHC_HC_BLK_ADDR
@@ -383,6 +384,7 @@
#define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
#define CONFIG_SYS_FSL_ERRATUM_A004849
#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_ERRATUM_A006261
#define CONFIG_SYS_FSL_A004447_SVR_REV 0x11
#elif defined(CONFIG_PPC_P3041)
@@ -421,6 +423,7 @@
#define CONFIG_SYS_FSL_ERRATUM_A004849
#define CONFIG_SYS_FSL_ERRATUM_A005812
#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_ERRATUM_A006261
#define CONFIG_SYS_FSL_A004447_SVR_REV 0x20
#elif defined(CONFIG_PPC_P4080) /* also supports P4040 */
@@ -504,6 +507,7 @@
#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xc0000000
#define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_ERRATUM_A006261
#define CONFIG_SYS_FSL_A004447_SVR_REV 0x20
#elif defined(CONFIG_PPC_P5040)
@@ -535,6 +539,7 @@
#define CONFIG_SYS_FSL_ERRATUM_A004699
#define CONFIG_SYS_FSL_ERRATUM_A004510
#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
+#define CONFIG_SYS_FSL_ERRATUM_A006261
#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
#define CONFIG_SYS_FSL_ERRATUM_A005812
@@ -630,6 +635,7 @@
#define CONFIG_SYS_FSL_ERRATUM_A004468
#define CONFIG_SYS_FSL_ERRATUM_A_004934
#define CONFIG_SYS_FSL_ERRATUM_A005871
+#define CONFIG_SYS_FSL_ERRATUM_A006261
#define CONFIG_SYS_FSL_ERRATUM_A006379
#define CONFIG_SYS_FSL_ERRATUM_A006593
#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
@@ -720,6 +726,7 @@ defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
#define CONFIG_SYS_FSL_USB2_PHY_ENABLE
#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_A006261
#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
#elif defined(CONFIG_PPC_T2080) || defined(CONFIG_PPC_T2081)
diff --git a/arch/powerpc/include/asm/fsl_errata.h b/arch/powerpc/include/asm/fsl_errata.h
index a590919..649c8f1 100644
--- a/arch/powerpc/include/asm/fsl_errata.h
+++ b/arch/powerpc/include/asm/fsl_errata.h
@@ -26,4 +26,35 @@ static inline bool has_erratum_a006379(void)
}
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
+static inline bool has_erratum_a006261(void)
+{
+ u32 svr = get_svr();
+ u32 soc = SVR_SOC_VER(svr);
+
+ switch (soc) {
+ case SVR_P1010:
+ return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 2, 0);
+ case SVR_P2041:
+ return IS_SVR_REV(svr, 1, 0) ||
+ IS_SVR_REV(svr, 1, 1) || IS_SVR_REV(svr, 2, 1);
+ case SVR_P3041:
+ return IS_SVR_REV(svr, 1, 0) ||
+ IS_SVR_REV(svr, 1, 1) ||
+ IS_SVR_REV(svr, 2, 0) || IS_SVR_REV(svr, 2, 1);
+ case SVR_P5020:
+ return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 2, 0);
+ case SVR_T4240:
+ case SVR_T4160:
+ return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 2, 0);
+ case SVR_T1040:
+ return IS_SVR_REV(svr, 1, 0);
+ case SVR_P5040:
+ return IS_SVR_REV(svr, 1, 0);
+ }
+
+ return false;
+}
+#endif
+
#endif
diff --git a/include/fsl_usb.h b/include/fsl_usb.h
index 915774c..8b63cdd 100644
--- a/include/fsl_usb.h
+++ b/include/fsl_usb.h
@@ -52,13 +52,32 @@ struct ccsr_usb_phy {
#define CONFIG_SYS_FSL_USB_PLLPRG2_MFI (5 << 16)
#define CONFIG_SYS_FSL_USB_PLLPRG2_PLL_EN (1 << 21)
#define CONFIG_SYS_FSL_USB_SYS_CLK_VALID (1 << 0)
+#define CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN (1 << 7)
+#define CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK (3 << 4)
+
+#define INC_DCNT_THRESHOLD_25MV (0 << 4)
+#define INC_DCNT_THRESHOLD_50MV (1 << 4)
+#define DEC_DCNT_THRESHOLD_25MV (2 << 4)
+#define DEC_DCNT_THRESHOLD_50MV (3 << 4)
#else
struct ccsr_usb_phy {
- u8 res0[0x18];
+ u32 config1;
+ u32 config2;
+ u32 config3;
+ u32 config4;
+ u32 config5;
+ u32 status1;
u32 usb_enable_override;
u8 res[0xe4];
};
-#define CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE 1
+#define CONFIG_SYS_FSL_USB_HS_DISCNCT_INC (3 << 22)
+#define CONFIG_SYS_FSL_USB_RX_AUTO_CAL_RD_WR_SEL (1 << 20)
+#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_0 13
+#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_3 16
+#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_0 0
+#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_3 3
+#define CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE 1
+#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_MASK 0x07
#endif
#endif /*_ASM_FSL_USB_H_ */
--
1.7.11.7
3
2

24 Feb '14
In this patch static variable and memcpy instead of an assignment
are used to avoid unaligned access exception on some ARM platforms.
Signed-off-by: Piotr Wilczek <p.wilczek(a)samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park(a)samsung.com>
CC: Tom Rini <trini(a)ti.com>
---
disk/part_efi.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/disk/part_efi.c b/disk/part_efi.c
index b7524d6..303b8af 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -224,7 +224,8 @@ static int set_protective_mbr(block_dev_desc_t *dev_desc)
p_mbr->signature = MSDOS_MBR_SIGNATURE;
p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
p_mbr->partition_record[0].start_sect = 1;
- p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba;
+ memcpy(&p_mbr->partition_record[0].nr_sects, &dev_desc->lba,
+ sizeof(dev_desc->lba));
/* Write MBR sector to the MMC device */
if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) {
@@ -387,8 +388,9 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
gpt_e[i].ending_lba = cpu_to_le64(offset - 1);
/* partition type GUID */
+ static efi_guid_t basic_guid = PARTITION_BASIC_DATA_GUID;
memcpy(gpt_e[i].partition_type_guid.b,
- &PARTITION_BASIC_DATA_GUID, 16);
+ &basic_guid, 16);
#ifdef CONFIG_PARTITION_UUIDS
str_uuid = partitions[i].uuid;
--
1.7.9.5
6
26
From: David Feng <fenghua(a)phytium.com.cn>
This patch add gicv3 support to uboot armv8 platform.
Modifications cover 4 source files, as follows:
gic.S: gicv3 initialization and sgi interrupt raising.
goc.h: gicv3 register definitions.
vexpress_aemv8a.h: add CONFIG_GICV2/CONFIG_GICV3 switch.
start.S: set SCR_EL3.NS bit to 1, gicv3 register of ICC_SRE_EL2
could be accessed only when SCR_EL3.NS=1.
set SCR_EL3.IRQ|FIQ|EA bits, reroute all interrupts to
el3 at all cores, slaves could be waken up by interrupt
only when the interrupt is routed to it when running
at el3.
Note: please use the latest gcc 4.8 compiler from linaro
which support gicv3 system register assembling.
Signed-off-by: David Feng <fenghua(a)phytium.com.cn>
---
arch/arm/cpu/armv8/gic.S | 84 ++++++++++++++++++++++++++++++++++++-
arch/arm/cpu/armv8/start.S | 5 ++-
arch/arm/include/asm/gic.h | 56 +++++++++++++++++++++++++
include/configs/vexpress_aemv8a.h | 7 ++++
4 files changed, 150 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv8/gic.S b/arch/arm/cpu/armv8/gic.S
index 599aa8f..a08939a 100644
--- a/arch/arm/cpu/armv8/gic.S
+++ b/arch/arm/cpu/armv8/gic.S
@@ -23,6 +23,74 @@
*
*************************************************************************/
WEAK(gic_init)
+#if defined(CONFIG_GICV3)
+ branch_if_slave x0, 3f
+
+ /* Initialize Distributor */
+ ldr x1, =GICD_BASE
+ mov w0, #0x37 /* EnableGrp0 | EnableGrp1NS */
+ /* EnableGrp1S | ARE_S | ARE_NS */
+ str w0, [x1, GICD_CTLR] /* Secure GICD_CTLR */
+ ldr w0, [x1, GICD_TYPER]
+ and w2, w0, #0x1f /* ITLinesNumber */
+ cbz w2, 1f /* No SPIs */
+ add x3, x1, (GICD_IGROUPRn + 4)
+ add x4, x1, (GICD_IGROUPMODRn + 4)
+ mov w5, #~0
+0: str w5, [x3], #0x4
+ str wzr, [x4], #0x4 /* Config SPIs as Group1NS */
+ sub w2, w2, #0x1
+ cbnz w2, 0b
+
+ /* Initialize All ReDistributors */
+1: ldr x1, =GICR_BASE
+2: mov w0, #~0x2
+ ldr w2, [x1, GICR_WAKER]
+ and w2, w2, w0 /* Clear ProcessorSleep */
+ str w2, [x1, GICR_WAKER]
+ dsb st
+ isb
+0: ldr w0, [x1, GICR_WAKER]
+ tbnz w0, #2, 0b /* Wait Children be Alive */
+
+ add x2, x1, #(1 << 16) /* SGI_Base */
+ mov w5, #~0
+ str w5, [x2, GICR_IGROUPRn]
+ str wzr, [x2, GICR_IGROUPMODRn] /* SGIs|PPIs Group1NS */
+ mov w0, #0x1 /* Enable SGI 0 */
+ str w0, [x2, GICR_ISENABLERn]
+
+ ldr w0, [x1, GICR_TYPER]
+ add x1, x1, #(2 << 16)
+ tbz w0, #4, 2b /* Next ReDistributor if Exist */
+
+ /* Initialize Cpu Interface */
+3: mrs x0, ICC_SRE_EL3
+ orr x0, x0, #0xf /* SRE & Disable IRQ/FIQ Bypass & */
+ /* Allow EL2 access to ICC_SRE_EL2 */
+ msr ICC_SRE_EL3, x0
+ isb
+
+ mrs x0, ICC_SRE_EL2
+ orr x0, x0, #0xf /* SRE & Disable IRQ/FIQ Bypass & */
+ /* Allow EL1 access to ICC_SRE_EL1 */
+ msr ICC_SRE_EL2, x0
+ isb
+
+ mov x0, #0x3 /* EnableGrp1NS | EnableGrp1S */
+ msr ICC_IGRPEN1_EL3, x0
+ isb
+
+ msr ICC_CTLR_EL3, xzr
+ isb
+
+ msr ICC_CTLR_EL1, xzr /* NonSecure ICC_CTLR_EL1 */
+ isb
+
+ mov x0, #0x1 << 7 /* Non-Secure access to ICC_PMR_EL1 */
+ msr ICC_PMR_EL1, x0
+ isb
+#elif defined(CONFIG_GICV2)
branch_if_slave x0, 2f
/* Initialize Distributor and SPIs */
@@ -54,7 +122,7 @@ WEAK(gic_init)
mov w0, #0x1 << 7 /* Non-Secure access to GICC_PMR */
str w0, [x1, GICC_PMR]
-
+#endif
ret
ENDPROC(gic_init)
@@ -65,11 +133,18 @@ ENDPROC(gic_init)
*
*************************************************************************/
WEAK(gic_send_sgi)
+#if defined(CONFIG_GICV3)
+ mov x1, #(1 << 40)
+ orr x1, x1, x0, lsl #24
+ msr ICC_ASGI1R_EL1, x1
+ isb
+#elif defined(CONFIG_GICV2)
ldr x1, =GICD_BASE
mov w2, #0x8000
movk w2, #0x100, lsl #16
orr w2, w2, w0
str w2, [x1, GICD_SGIR]
+#endif
ret
ENDPROC(gic_send_sgi)
@@ -82,11 +157,18 @@ ENDPROC(gic_send_sgi)
*
*************************************************************************/
WEAK(wait_for_wakeup)
+#if defined(CONFIG_GICV3)
+0: wfi
+ mrs x0, ICC_IAR1_EL1
+ msr ICC_EOIR1_EL1, x0
+ cbnz x0, 0b
+#elif defined(CONFIG_GICV2)
ldr x1, =GICC_BASE
0: wfi
ldr w0, [x1, GICC_AIAR]
str w0, [x1, GICC_AEOIR]
cbnz w0, 0b
+#endif
ret
ENDPROC(wait_for_wakeup)
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index bcc2603..9911817 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -50,7 +50,10 @@ reset:
*/
adr x0, vectors
switch_el x1, 3f, 2f, 1f
-3: msr vbar_el3, x0
+3: mrs x0, scr_el3
+ orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */
+ msr scr_el3, x0
+ msr vbar_el3, x0
msr cptr_el3, xzr /* Enable FP/SIMD */
ldr x0, =COUNTER_FREQUENCY
msr cntfrq_el0, x0 /* Initialize CNTFRQ */
diff --git a/arch/arm/include/asm/gic.h b/arch/arm/include/asm/gic.h
index ac2b2bf..bd3a80c 100644
--- a/arch/arm/include/asm/gic.h
+++ b/arch/arm/include/asm/gic.h
@@ -51,4 +51,60 @@
#define GICC_IIDR 0x00fc
#define GICC_DIR 0x1000
+/* ReDistributor Registers for Control and Physical LPIs */
+#define GICR_CTLR 0x0000
+#define GICR_IIDR 0x0004
+#define GICR_TYPER 0x0008
+#define GICR_STATUSR 0x0010
+#define GICR_WAKER 0x0014
+#define GICR_SETLPIR 0x0040
+#define GICR_CLRLPIR 0x0048
+#define GICR_SEIR 0x0068
+#define GICR_PROPBASER 0x0070
+#define GICR_PENDBASER 0x0078
+#define GICR_INVLPIR 0x00a0
+#define GICR_INVALLR 0x00b0
+#define GICR_SYNCR 0x00c0
+#define GICR_MOVLPIR 0x0100
+#define GICR_MOVALLR 0x0110
+
+/* ReDistributor Registers for SGIs and PPIs */
+#define GICR_IGROUPRn 0x0080
+#define GICR_ISENABLERn 0x0100
+#define GICR_ICENABLERn 0x0180
+#define GICR_ISPENDRn 0x0200
+#define GICR_ICPENDRn 0x0280
+#define GICR_ISACTIVERn 0x0300
+#define GICR_ICACTIVERn 0x0380
+#define GICR_IPRIORITYRn 0x0400
+#define GICR_ICFGR0 0x0c00
+#define GICR_ICFGR1 0x0c04
+#define GICR_IGROUPMODRn 0x0d00
+#define GICR_NSACRn 0x0e00
+
+/* Cpu Interface System Registers */
+#define ICC_IAR0_EL1 S3_0_C12_C8_0
+#define ICC_IAR1_EL1 S3_0_C12_C12_0
+#define ICC_EOIR0_EL1 S3_0_C12_C8_1
+#define ICC_EOIR1_EL1 S3_0_C12_C12_1
+#define ICC_HPPIR0_EL1 S3_0_C12_C8_2
+#define ICC_HPPIR1_EL1 S3_0_C12_C12_2
+#define ICC_BPR0_EL1 S3_0_C12_C8_3
+#define ICC_BPR1_EL1 S3_0_C12_C12_3
+#define ICC_DIR_EL1 S3_0_C12_C11_1
+#define ICC_PMR_EL1 S3_0_C4_C6_0
+#define ICC_RPR_EL1 S3_0_C12_C11_3
+#define ICC_CTLR_EL1 S3_0_C12_C12_4
+#define ICC_CTLR_EL3 S3_6_C12_C12_4
+#define ICC_SRE_EL1 S3_0_C12_C12_5
+#define ICC_SRE_EL2 S3_4_C12_C9_5
+#define ICC_SRE_EL3 S3_6_C12_C12_5
+#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6
+#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
+#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7
+#define ICC_SEIEN_EL1 S3_0_C12_C13_0
+#define ICC_SGI0R_EL1 S3_0_C12_C11_7
+#define ICC_SGI1R_EL1 S3_0_C12_C11_5
+#define ICC_ASGI1R_EL1 S3_0_C12_C11_6
+
#endif /* __GIC_H__ */
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
index ce5f384..ac67887 100644
--- a/include/configs/vexpress_aemv8a.h
+++ b/include/configs/vexpress_aemv8a.h
@@ -12,6 +12,8 @@
#define CONFIG_REMAKE_ELF
+#define CONFIG_GICV2
+
/*#define CONFIG_ARMV8_SWITCH_TO_EL1*/
/*#define CONFIG_SYS_GENERIC_BOARD*/
@@ -93,8 +95,13 @@
#define COUNTER_FREQUENCY (0x1800000) /* 24MHz */
/* Generic Interrupt Controller Definitions */
+#ifdef CONFIG_GICV3
+#define GICD_BASE (0x2f000000)
+#define GICR_BASE (0x2f100000)
+#else
#define GICD_BASE (0x2C001000)
#define GICC_BASE (0x2C002000)
+#endif
#define CONFIG_SYS_MEMTEST_START V2M_BASE
#define CONFIG_SYS_MEMTEST_END (V2M_BASE + 0x80000000)
--
1.7.9.5
5
7

24 Feb '14
Add command class define.
Add mmc erase and secure erase define.
Add secure erase and trim support bit define.
Signed-off-by: Haijun Zhang <haijun.zhang(a)freescale.com>
---
changes for V5:
- Add some comments for definitions
include/mmc.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/include/mmc.h b/include/mmc.h
index cb558da..607e28b 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -53,6 +53,7 @@
#define COMM_ERR -18 /* Communications Error */
#define TIMEOUT -19
#define IN_PROGRESS -20 /* operation is in progress */
+#define NOT_SUPPORT -21 /* Operation is not support */
#define MMC_CMD_GO_IDLE_STATE 0
#define MMC_CMD_SEND_OP_COND 1
@@ -105,6 +106,39 @@
#define OCR_VOLTAGE_MASK 0x007FFF80
#define OCR_ACCESS_MODE 0x60000000
+/*
+ * Card Command Classes (CCC)
+ *
+ * (0) Basic protocol functions (CMD0,1,2,3,4,7,9,10,12,13,15)
+ * (and for SPI, CMD58,59)
+ * (1) Stream read commands (CMD11)
+ * (2) Block read commands (CMD16,17,18)
+ * (3) Stream write commands (CMD20)
+ * (4) Block write commands (CMD16,24,25,26,27)
+ * (5) Ability to erase blocks (CMD32,33,34,35,36,37,38,39)
+ * (6) Able to write protect blocks (CMD28,29,30)
+ * (7) Able to lock down card (CMD16,CMD42)
+ * (8) Application specific (CMD55,56,57,ACMD*)
+ * (9) I/O mode (CMD5,39,40,52,53)
+ * (10) High speed switch (CMD6,34,35,36,37,50)
+ */
+#define CCC_BASIC (1<<0)
+#define CCC_STREAM_READ (1<<1)
+#define CCC_BLOCK_READ (1<<2)
+#define CCC_STREAM_WRITE (1<<3)
+#define CCC_BLOCK_WRITE (1<<4)
+#define CCC_ERASE (1<<5)
+#define CCC_WRITE_PROT (1<<6)
+#define CCC_LOCK_CARD (1<<7)
+#define CCC_APP_SPEC (1<<8)
+#define CCC_IO_MODE (1<<9)
+#define CCC_SWITCH (1<<10)
+
+#define MMC_ERASE_ARG 0x00000000
+#define MMC_SECURE_ERASE_ARG 0x80000000
+#define MMC_TRIM_ARG 0x00000001
+#define MMC_DISCARD_ARG 0x00000003
+
#define SECURE_ERASE 0x80000000
#define MMC_STATUS_MASK (~0x0206BF7F)
@@ -160,8 +194,12 @@
#define EXT_CSD_CARD_TYPE 196 /* RO */
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
+#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
+#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_MULT 226 /* RO */
+#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
+#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
/*
* EXT_CSD field definitions
@@ -178,6 +216,12 @@
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+/* SEC_FEATURE_SUPPORT[231] Field definitions */
+#define EXT_CSD_SEC_ER_EN (1<<0)
+#define EXT_CSD_SEC_BD_BLK_EN (1<<2)
+#define EXT_CSD_SEC_GB_CL_EN (1<<4)
+#define EXT_CSD_SEC_SANITIZE (1<<6) /* v4.5 later */
+
#define EXT_CSD_BOOT_ACK_ENABLE (1 << 6)
#define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3)
#define EXT_CSD_PARTITION_ACCESS_ENABLE (1 << 0)
@@ -187,7 +231,6 @@
#define EXT_CSD_BOOT_PART_NUM(x) (x << 3)
#define EXT_CSD_PARTITION_ACCESS(x) (x << 0)
-
#define R1_ILLEGAL_COMMAND (1 << 22)
#define R1_APP_CMD (1 << 5)
@@ -268,10 +311,15 @@ struct mmc {
ushort rca;
char part_config;
char part_num;
+ ushort cmdclass;
uint tran_speed;
uint read_bl_len;
uint write_bl_len;
uint erase_grp_size;
+ uint erase_timeout_mult;
+ char sec_feature_support;
+ uint sec_erase_mult;
+ uint sec_erase_timeout;
u64 capacity;
u64 capacity_user;
u64 capacity_boot;
--
1.8.4.1
3
12

[U-Boot] [PATCH] watchdog/denali: Adding DesignWare watchdog driver support
by Chin Liang See 21 Feb '14
by Chin Liang See 21 Feb '14
21 Feb '14
To add the DesignWare watchdog driver support. It required
information such as register base address and clock info from
configuration header file within include/configs folder.
Signed-off-by: Chin Liang See <clsee(a)altera.com>
Cc: Anatolij Gustschin <agust(a)denx.de>
Cc: Albert Aribaud <albert.u.boot(a)aribaud.net>
Cc: Heiko Schocher <hs(a)denx.de>
Cc: Tom Rini <trini(a)ti.com>
---
drivers/watchdog/Makefile | 1 +
drivers/watchdog/designware_wdt.c | 75 +++++++++++++++++++++++++++++++++++++
2 files changed, 76 insertions(+)
create mode 100644 drivers/watchdog/designware_wdt.c
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 06ced10..0276a10 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_S5P) += s5p_wdt.o
obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o
obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
+obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c
new file mode 100644
index 0000000..c3b14f5
--- /dev/null
+++ b/drivers/watchdog/designware_wdt.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 Altera Corporation <www.altera.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <asm/utils.h>
+
+#define DW_WDT_CR 0x00
+#define DW_WDT_TORR 0x04
+#define DW_WDT_CRR 0x0C
+
+#define DW_WDT_CR_EN_OFFSET 0x00
+#define DW_WDT_CR_RMOD_OFFSET 0x01
+#define DW_WDT_CR_RMOD_VAL 0x00
+#define DW_WDT_CRR_RESTART_VAL 0x76
+
+/*
+ * Set the watchdog time interval.
+ * Counter is 32 bit.
+ */
+int designware_wdt_settimeout(unsigned int timeout)
+{
+ signed int i;
+ /* calculate the timeout range value */
+ i = (log_2_n_round_up(timeout * CONFIG_DW_WDT_CLOCK_KHZ))\
+ - 16;
+ if (i > 15)
+ i = 15;
+ if (i < 0)
+ i = 0;
+
+ writel((i | (i<<4)),
+ (CONFIG_DW_WDT_BASE + DW_WDT_TORR));
+ return 0;
+}
+
+void designware_wdt_enable(void)
+{
+ writel(((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) | \
+ (0x1 << DW_WDT_CR_EN_OFFSET)),
+ (CONFIG_DW_WDT_BASE + DW_WDT_CR));
+}
+
+unsigned int designware_wdt_is_enabled(void)
+{
+ unsigned long val;
+ val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR));
+ return val & 0x1;
+}
+
+#if defined(CONFIG_HW_WATCHDOG)
+void hw_watchdog_reset(void)
+{
+ if (designware_wdt_is_enabled())
+ /* restart the watchdog counter */
+ writel(DW_WDT_CRR_RESTART_VAL,
+ (CONFIG_DW_WDT_BASE + DW_WDT_CRR));
+}
+
+void hw_watchdog_init(void)
+{
+ /* reset to disable the watchdog */
+ hw_watchdog_reset();
+ /* set timer in miliseconds */
+ designware_wdt_settimeout(CONFIG_HW_WATCHDOG_TIMEOUT_MS);
+ /* enable the watchdog */
+ designware_wdt_enable();
+ /* reset the watchdog */
+ hw_watchdog_reset();
+}
+#endif
--
1.7.9.5
2
6

21 Feb '14
To add the Denali NAND driver support into U-Boot. It required
information such as register base address from configuration
header file within include/configs folder.
Signed-off-by: Chin Liang See <clsee(a)altera.com>
Cc: Artem Bityutskiy <artem.bityutskiy(a)linux.intel.com>
Cc: David Woodhouse <David.Woodhouse(a)intel.com>
Cc: Brian Norris <computersforpeace(a)gmail.com>
Cc: Scott Wood <scottwood(a)freescale.com>
---
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/denali_nand.c | 1166 ++++++++++++++++++++++++++++++++++++++++
drivers/mtd/nand/denali_nand.h | 501 +++++++++++++++++
3 files changed, 1668 insertions(+)
create mode 100644 drivers/mtd/nand/denali_nand.c
create mode 100644 drivers/mtd/nand/denali_nand.h
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 02b149c..24e8218 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_NAND_ECC_BCH) += nand_bch.o
obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o
obj-$(CONFIG_DRIVER_NAND_BFIN) += bfin_nand.o
obj-$(CONFIG_NAND_DAVINCI) += davinci_nand.o
+obj-$(CONFIG_NAND_DENALI) += denali_nand.o
obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
obj-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
diff --git a/drivers/mtd/nand/denali_nand.c b/drivers/mtd/nand/denali_nand.c
new file mode 100644
index 0000000..55246c9
--- /dev/null
+++ b/drivers/mtd/nand/denali_nand.c
@@ -0,0 +1,1166 @@
+/*
+ * Copyright (C) 2013 Altera Corporation <www.altera.com>
+ * Copyright (C) 2009-2010, Intel Corporation and its suppliers.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+
+#include "denali_nand.h"
+
+/* We define a module parameter that allows the user to override
+ * the hardware and decide what timing mode should be used.
+ */
+#define NAND_DEFAULT_TIMINGS -1
+
+static struct denali_nand_info denali;
+static int onfi_timing_mode = NAND_DEFAULT_TIMINGS;
+
+/* We define a macro here that combines all interrupts this driver uses into
+ * a single constant value, for convenience. */
+#define DENALI_IRQ_ALL (INTR_STATUS__DMA_CMD_COMP | \
+ INTR_STATUS__ECC_TRANSACTION_DONE | \
+ INTR_STATUS__ECC_ERR | \
+ INTR_STATUS__PROGRAM_FAIL | \
+ INTR_STATUS__LOAD_COMP | \
+ INTR_STATUS__PROGRAM_COMP | \
+ INTR_STATUS__TIME_OUT | \
+ INTR_STATUS__ERASE_FAIL | \
+ INTR_STATUS__RST_COMP | \
+ INTR_STATUS__ERASE_COMP | \
+ INTR_STATUS__ECC_UNCOR_ERR | \
+ INTR_STATUS__INT_ACT | \
+ INTR_STATUS__LOCKED_BLK)
+
+/* indicates whether or not the internal value for the flash bank is
+ * valid or not */
+#define CHIP_SELECT_INVALID -1
+
+#define SUPPORT_8BITECC 1
+
+/* This macro divides two integers and rounds fractional values up
+ * to the nearest integer value. */
+#define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
+
+/* These constants are defined by the driver to enable common driver
+ * configuration options. */
+#define SPARE_ACCESS 0x41
+#define MAIN_ACCESS 0x42
+#define MAIN_SPARE_ACCESS 0x43
+
+#define DENALI_UNLOCK_START 0x10
+#define DENALI_UNLOCK_END 0x11
+#define DENALI_LOCK 0x21
+#define DENALI_LOCK_TIGHT 0x31
+#define DENALI_BUFFER_LOAD 0x60
+#define DENALI_BUFFER_WRITE 0x62
+
+#define DENALI_READ 0
+#define DENALI_WRITE 0x100
+
+/* types of device accesses. We can issue commands and get status */
+#define COMMAND_CYCLE 0
+#define ADDR_CYCLE 1
+#define STATUS_CYCLE 2
+
+/* this is a helper macro that allows us to
+ * format the bank into the proper bits for the controller */
+#define BANK(x) ((x) << 24)
+
+/* Interrupts are cleared by writing a 1 to the appropriate status bit */
+static inline void clear_interrupt(uint32_t irq_mask)
+{
+ uint32_t intr_status_reg = 0;
+ intr_status_reg = INTR_STATUS(denali.flash_bank);
+ __raw_writel(irq_mask, denali.flash_reg + intr_status_reg);
+}
+
+static uint32_t read_interrupt_status(void)
+{
+ uint32_t intr_status_reg = 0;
+ intr_status_reg = INTR_STATUS(denali.flash_bank);
+ return __raw_readl(denali.flash_reg + intr_status_reg);
+}
+
+static void clear_interrupts(void)
+{
+ uint32_t status = 0x0;
+ status = read_interrupt_status();
+ clear_interrupt(status);
+ denali.irq_status = 0x0;
+}
+
+static void denali_irq_enable(uint32_t int_mask)
+{
+ int i;
+ for (i = 0; i < denali.max_banks; ++i)
+ __raw_writel(int_mask, denali.flash_reg + INTR_EN(i));
+}
+
+static uint32_t wait_for_irq(uint32_t irq_mask)
+{
+ unsigned long comp_res = 1000;
+ uint32_t intr_status = 0;
+
+ do {
+ intr_status = read_interrupt_status() & DENALI_IRQ_ALL;
+ if (intr_status & irq_mask) {
+ denali.irq_status &= ~irq_mask;
+ /* our interrupt was detected */
+ break;
+ }
+ udelay(1);
+ comp_res--;
+ } while (comp_res != 0);
+
+ if (comp_res == 0) {
+ /* timeout */
+ printf("Denali timeout with interrupt status %08x\n",
+ read_interrupt_status());
+ intr_status = 0;
+ }
+ return intr_status;
+}
+
+/* Certain operations for the denali NAND controller use
+ * an indexed mode to read/write data. The operation is
+ * performed by writing the address value of the command
+ * to the device memory followed by the data. This function
+ * abstracts this common operation.
+*/
+static void index_addr(uint32_t address, uint32_t data)
+{
+ __raw_writel(address, denali.flash_mem);
+ __raw_writel(data, denali.flash_mem + 0x10);
+}
+
+/* Perform an indexed read of the device */
+static void index_addr_read_data(uint32_t address, uint32_t *pdata)
+{
+ __raw_writel(address, denali.flash_mem);
+ *pdata = __raw_readl(denali.flash_mem + 0x10);
+}
+
+/* We need to buffer some data for some of the NAND core routines.
+ * The operations manage buffering that data. */
+static void reset_buf(void)
+{
+ denali.buf.head = denali.buf.tail = 0;
+}
+
+static void write_byte_to_buf(uint8_t byte)
+{
+ BUG_ON(denali.buf.tail >= sizeof(denali.buf.buf));
+ denali.buf.buf[denali.buf.tail++] = byte;
+}
+
+/* resets a specific device connected to the core */
+static void reset_bank(void)
+{
+ uint32_t irq_status = 0;
+ uint32_t irq_mask = INTR_STATUS__RST_COMP |
+ INTR_STATUS__TIME_OUT;
+
+ clear_interrupts();
+
+ __raw_writel(1 << denali.flash_bank, denali.flash_reg + DEVICE_RESET);
+
+ irq_status = wait_for_irq(irq_mask);
+ if (irq_status & INTR_STATUS__TIME_OUT)
+ debug(KERN_ERR "reset bank failed.\n");
+}
+
+/* Reset the flash controller */
+static uint16_t denali_nand_reset(void)
+{
+ uint32_t i;
+
+ for (i = 0 ; i < denali.max_banks; i++)
+ __raw_writel(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+ denali.flash_reg + INTR_STATUS(i));
+
+ for (i = 0 ; i < denali.max_banks; i++) {
+ __raw_writel(1 << i, denali.flash_reg + DEVICE_RESET);
+ while (!(__raw_readl(denali.flash_reg + INTR_STATUS(i)) &
+ (INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT)))
+ if (__raw_readl(denali.flash_reg + INTR_STATUS(i)) &
+ INTR_STATUS__TIME_OUT)
+ debug(KERN_DEBUG "NAND Reset operation "
+ "timed out on bank %d\n", i);
+ }
+
+ for (i = 0; i < denali.max_banks; i++)
+ __raw_writel(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+ denali.flash_reg + INTR_STATUS(i));
+
+ return PASS;
+}
+
+/* this routine calculates the ONFI timing values for a given mode and
+ * programs the clocking register accordingly. The mode is determined by
+ * the get_onfi_nand_para routine.
+ */
+static void nand_onfi_timing_set(uint16_t mode)
+{
+ uint16_t Trea[6] = {40, 30, 25, 20, 20, 16};
+ uint16_t Trp[6] = {50, 25, 17, 15, 12, 10};
+ uint16_t Treh[6] = {30, 15, 15, 10, 10, 7};
+ uint16_t Trc[6] = {100, 50, 35, 30, 25, 20};
+ uint16_t Trhoh[6] = {0, 15, 15, 15, 15, 15};
+ uint16_t Trloh[6] = {0, 0, 0, 0, 5, 5};
+ uint16_t Tcea[6] = {100, 45, 30, 25, 25, 25};
+ uint16_t Tadl[6] = {200, 100, 100, 100, 70, 70};
+ uint16_t Trhw[6] = {200, 100, 100, 100, 100, 100};
+ uint16_t Trhz[6] = {200, 100, 100, 100, 100, 100};
+ uint16_t Twhr[6] = {120, 80, 80, 60, 60, 60};
+ uint16_t Tcs[6] = {70, 35, 25, 25, 20, 15};
+
+ uint16_t TclsRising = 1;
+ uint16_t data_invalid_rhoh, data_invalid_rloh, data_invalid;
+ uint16_t dv_window = 0;
+ uint16_t en_lo, en_hi;
+ uint16_t acc_clks;
+ uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
+
+ en_lo = CEIL_DIV(Trp[mode], CLK_X);
+ en_hi = CEIL_DIV(Treh[mode], CLK_X);
+#if ONFI_BLOOM_TIME
+ if ((en_hi * CLK_X) < (Treh[mode] + 2))
+ en_hi++;
+#endif
+
+ if ((en_lo + en_hi) * CLK_X < Trc[mode])
+ en_lo += CEIL_DIV((Trc[mode] - (en_lo + en_hi) * CLK_X), CLK_X);
+
+ if ((en_lo + en_hi) < CLK_MULTI)
+ en_lo += CLK_MULTI - en_lo - en_hi;
+
+ while (dv_window < 8) {
+ data_invalid_rhoh = en_lo * CLK_X + Trhoh[mode];
+
+ data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[mode];
+
+ data_invalid =
+ data_invalid_rhoh <
+ data_invalid_rloh ? data_invalid_rhoh : data_invalid_rloh;
+
+ dv_window = data_invalid - Trea[mode];
+
+ if (dv_window < 8)
+ en_lo++;
+ }
+
+ acc_clks = CEIL_DIV(Trea[mode], CLK_X);
+
+ while (((acc_clks * CLK_X) - Trea[mode]) < 3)
+ acc_clks++;
+
+ if ((data_invalid - acc_clks * CLK_X) < 2)
+ debug(KERN_WARNING "%s, Line %d: Warning!\n",
+ __FILE__, __LINE__);
+
+ addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
+ re_2_we = CEIL_DIV(Trhw[mode], CLK_X);
+ re_2_re = CEIL_DIV(Trhz[mode], CLK_X);
+ we_2_re = CEIL_DIV(Twhr[mode], CLK_X);
+ cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X);
+ if (!TclsRising)
+ cs_cnt = CEIL_DIV(Tcs[mode], CLK_X);
+ if (cs_cnt == 0)
+ cs_cnt = 1;
+
+ if (Tcea[mode]) {
+ while (((cs_cnt * CLK_X) + Trea[mode]) < Tcea[mode])
+ cs_cnt++;
+ }
+
+#if MODE5_WORKAROUND
+ if (mode == 5)
+ acc_clks = 5;
+#endif
+
+ /* Sighting 3462430: Temporary hack for MT29F128G08CJABAWP:B */
+ if ((__raw_readl(denali.flash_reg + MANUFACTURER_ID) == 0) &&
+ (__raw_readl(denali.flash_reg + DEVICE_ID) == 0x88))
+ acc_clks = 6;
+
+ __raw_writel(acc_clks, denali.flash_reg + ACC_CLKS);
+ __raw_writel(re_2_we, denali.flash_reg + RE_2_WE);
+ __raw_writel(re_2_re, denali.flash_reg + RE_2_RE);
+ __raw_writel(we_2_re, denali.flash_reg + WE_2_RE);
+ __raw_writel(addr_2_data, denali.flash_reg + ADDR_2_DATA);
+ __raw_writel(en_lo, denali.flash_reg + RDWR_EN_LO_CNT);
+ __raw_writel(en_hi, denali.flash_reg + RDWR_EN_HI_CNT);
+ __raw_writel(cs_cnt, denali.flash_reg + CS_SETUP_CNT);
+}
+
+/* queries the NAND device to see what ONFI modes it supports. */
+static uint16_t get_onfi_nand_para(void)
+{
+ int i;
+ /* we needn't to do a reset here because driver has already
+ * reset all the banks before
+ * */
+ if (!(__raw_readl(denali.flash_reg + ONFI_TIMING_MODE) &
+ ONFI_TIMING_MODE__VALUE))
+ return FAIL;
+
+ for (i = 5; i > 0; i--) {
+ if (__raw_readl(denali.flash_reg + ONFI_TIMING_MODE) &
+ (0x01 << i))
+ break;
+ }
+
+ nand_onfi_timing_set(i);
+
+ /* By now, all the ONFI devices we know support the page cache */
+ /* rw feature. So here we enable the pipeline_rw_ahead feature */
+ /* __raw_writel(1, denali.flash_reg + CACHE_WRITE_ENABLE); */
+ /* __raw_writel(1, denali.flash_reg + CACHE_READ_ENABLE); */
+
+ return PASS;
+}
+
+static void get_samsung_nand_para(uint8_t device_id)
+{
+ if (device_id == 0xd3) { /* Samsung K9WAG08U1A */
+ /* Set timing register values according to datasheet */
+ __raw_writel(5, denali.flash_reg + ACC_CLKS);
+ __raw_writel(20, denali.flash_reg + RE_2_WE);
+ __raw_writel(12, denali.flash_reg + WE_2_RE);
+ __raw_writel(14, denali.flash_reg + ADDR_2_DATA);
+ __raw_writel(3, denali.flash_reg + RDWR_EN_LO_CNT);
+ __raw_writel(2, denali.flash_reg + RDWR_EN_HI_CNT);
+ __raw_writel(2, denali.flash_reg + CS_SETUP_CNT);
+ }
+}
+
+static void get_toshiba_nand_para(void)
+{
+ uint32_t tmp;
+
+ /* Workaround to fix a controller bug which reports a wrong */
+ /* spare area size for some kind of Toshiba NAND device */
+ if ((__raw_readl(denali.flash_reg + DEVICE_MAIN_AREA_SIZE) == 4096) &&
+ (__raw_readl(denali.flash_reg + DEVICE_SPARE_AREA_SIZE)
+ == 64)){
+ __raw_writel(216, denali.flash_reg + DEVICE_SPARE_AREA_SIZE);
+ tmp = __raw_readl(denali.flash_reg + DEVICES_CONNECTED) *
+ __raw_readl(denali.flash_reg + DEVICE_SPARE_AREA_SIZE);
+ __raw_writel(tmp,
+ denali.flash_reg + LOGICAL_PAGE_SPARE_SIZE);
+#if SUPPORT_15BITECC
+ __raw_writel(15, denali.flash_reg + ECC_CORRECTION);
+#elif SUPPORT_8BITECC
+ __raw_writel(8, denali.flash_reg + ECC_CORRECTION);
+#endif
+ }
+}
+
+static void get_hynix_nand_para(uint8_t device_id)
+{
+ uint32_t main_size, spare_size;
+
+ switch (device_id) {
+ case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */
+ case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */
+ __raw_writel(128, denali.flash_reg + PAGES_PER_BLOCK);
+ __raw_writel(4096, denali.flash_reg + DEVICE_MAIN_AREA_SIZE);
+ __raw_writel(224, denali.flash_reg + DEVICE_SPARE_AREA_SIZE);
+ main_size = 4096 *
+ __raw_readl(denali.flash_reg + DEVICES_CONNECTED);
+ spare_size = 224 *
+ __raw_readl(denali.flash_reg + DEVICES_CONNECTED);
+ __raw_writel(main_size,
+ denali.flash_reg + LOGICAL_PAGE_DATA_SIZE);
+ __raw_writel(spare_size,
+ denali.flash_reg + LOGICAL_PAGE_SPARE_SIZE);
+ __raw_writel(0, denali.flash_reg + DEVICE_WIDTH);
+#if SUPPORT_15BITECC
+ __raw_writel(15, denali.flash_reg + ECC_CORRECTION);
+#elif SUPPORT_8BITECC
+ __raw_writel(8, denali.flash_reg + ECC_CORRECTION);
+#endif
+ break;
+ default:
+ debug(KERN_WARNING
+ "Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
+ "Will use default parameter values instead.\n",
+ device_id);
+ }
+}
+
+/* determines how many NAND chips are connected to the controller. Note for
+ * Intel CE4100 devices we don't support more than one device.
+ */
+static void find_valid_banks(void)
+{
+ uint32_t id[denali.max_banks];
+ int i;
+
+ denali.total_used_banks = 1;
+ for (i = 0; i < denali.max_banks; i++) {
+ index_addr((uint32_t)(MODE_11 | (i << 24) | 0), 0x90);
+ index_addr((uint32_t)(MODE_11 | (i << 24) | 1), 0);
+ index_addr_read_data((uint32_t)(MODE_11 | (i << 24) | 2),
+ &id[i]);
+
+ if (i == 0) {
+ if (!(id[i] & 0x0ff))
+ break; /* WTF? */
+ } else {
+ if ((id[i] & 0x0ff) == (id[0] & 0x0ff))
+ denali.total_used_banks++;
+ else
+ break;
+ }
+ }
+}
+
+/*
+ * Use the configuration feature register to determine the maximum number of
+ * banks that the hardware supports.
+ */
+static void detect_max_banks(void)
+{
+ uint32_t features = __raw_readl(denali.flash_reg + FEATURES);
+ denali.max_banks = 2 << (features & FEATURES__N_BANKS);
+}
+
+static void detect_partition_feature(void)
+{
+ /* For MRST platform, denali.fwblks represent the
+ * number of blocks firmware is taken,
+ * FW is in protect partition and MTD driver has no
+ * permission to access it. So let driver know how many
+ * blocks it can't touch.
+ * */
+ if (__raw_readl(denali.flash_reg + FEATURES) & FEATURES__PARTITION) {
+ if ((__raw_readl(denali.flash_reg + PERM_SRC_ID(1)) &
+ PERM_SRC_ID__SRCID) == SPECTRA_PARTITION_ID) {
+ denali.fwblks =
+ ((__raw_readl(denali.flash_reg + MIN_MAX_BANK(1)) &
+ MIN_MAX_BANK__MIN_VALUE) *
+ denali.blksperchip)
+ +
+ (__raw_readl(denali.flash_reg + MIN_BLK_ADDR(1)) &
+ MIN_BLK_ADDR__VALUE);
+ } else
+ denali.fwblks = SPECTRA_START_BLOCK;
+ } else
+ denali.fwblks = SPECTRA_START_BLOCK;
+}
+
+static uint16_t denali_nand_timing_set(void)
+{
+ uint16_t status = PASS;
+ uint32_t id_bytes[5], addr;
+ uint8_t i, maf_id, device_id;
+
+ /* Use read id method to get device ID and other
+ * params. For some NAND chips, controller can't
+ * report the correct device ID by reading from
+ * DEVICE_ID register
+ * */
+ addr = (uint32_t)MODE_11 | BANK(denali.flash_bank);
+ index_addr((uint32_t)addr | 0, 0x90);
+ index_addr((uint32_t)addr | 1, 0);
+ for (i = 0; i < 5; i++)
+ index_addr_read_data(addr | 2, &id_bytes[i]);
+ maf_id = id_bytes[0];
+ device_id = id_bytes[1];
+
+ if (__raw_readl(denali.flash_reg + ONFI_DEVICE_NO_OF_LUNS) &
+ ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */
+ if (FAIL == get_onfi_nand_para())
+ return FAIL;
+ } else if (maf_id == 0xEC) { /* Samsung NAND */
+ get_samsung_nand_para(device_id);
+ } else if (maf_id == 0x98) { /* Toshiba NAND */
+ get_toshiba_nand_para();
+ } else if (maf_id == 0xAD) { /* Hynix NAND */
+ get_hynix_nand_para(device_id);
+ }
+
+ find_valid_banks();
+
+ detect_partition_feature();
+
+ /* If the user specified to override the default timings
+ * with a specific ONFI mode, we apply those changes here.
+ */
+ if (onfi_timing_mode != NAND_DEFAULT_TIMINGS)
+ nand_onfi_timing_set(onfi_timing_mode);
+
+ return status;
+}
+
+static void denali_set_intr_modes(uint16_t INT_ENABLE)
+{
+ if (INT_ENABLE)
+ __raw_writel(1, denali.flash_reg + GLOBAL_INT_ENABLE);
+ else
+ __raw_writel(0, denali.flash_reg + GLOBAL_INT_ENABLE);
+}
+
+/* validation function to verify that the controlling software is making
+ * a valid request
+ */
+static inline bool is_flash_bank_valid(int flash_bank)
+{
+ return (flash_bank >= 0 && flash_bank < 4);
+}
+
+static void denali_irq_init(void)
+{
+ uint32_t int_mask = 0;
+ int i;
+
+ /* Disable global interrupts */
+ denali_set_intr_modes(false);
+
+ int_mask = DENALI_IRQ_ALL;
+
+ /* Clear all status bits */
+ for (i = 0; i < denali.max_banks; ++i)
+ __raw_writel(0xFFFF, denali.flash_reg + INTR_STATUS(i));
+
+ denali_irq_enable(int_mask);
+}
+
+/* This helper function setups the registers for ECC and whether or not
+ * the spare area will be transferred. */
+static void setup_ecc_for_xfer(bool ecc_en, bool transfer_spare)
+{
+ int ecc_en_flag = 0, transfer_spare_flag = 0;
+
+ /* set ECC, transfer spare bits if needed */
+ ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0;
+ transfer_spare_flag = transfer_spare ? TRANSFER_SPARE_REG__FLAG : 0;
+
+ /* Enable spare area/ECC per user's request. */
+ __raw_writel(ecc_en_flag, denali.flash_reg + ECC_ENABLE);
+ /* applicable for MAP01 only */
+ __raw_writel(transfer_spare_flag,
+ denali.flash_reg + TRANSFER_SPARE_REG);
+}
+
+/* sends a pipeline command operation to the controller. See the Denali NAND
+ * controller's user guide for more information (section 4.2.3.6).
+ */
+static int denali_send_pipeline_cmd(bool ecc_en, bool transfer_spare,
+ int access_type, int op)
+{
+ uint32_t addr = 0x0, cmd = 0x0, irq_status = 0, irq_mask = 0;
+ uint32_t page_count = 1; /* always read a page */
+
+ if (op == DENALI_READ)
+ irq_mask = INTR_STATUS__LOAD_COMP;
+ else if (op == DENALI_WRITE)
+ irq_mask = INTR_STATUS__PROGRAM_COMP |
+ INTR_STATUS__PROGRAM_FAIL;
+ else
+ BUG();
+
+ /* clear interrupts */
+ clear_interrupts();
+
+ /* setup ECC and transfer spare reg */
+ setup_ecc_for_xfer(ecc_en, transfer_spare);
+
+ addr = BANK(denali.flash_bank) | denali.page;
+
+ /* setup the acccess type */
+ cmd = MODE_10 | addr;
+ index_addr((uint32_t)cmd, access_type);
+
+ /* setup the pipeline command */
+ if (access_type == SPARE_ACCESS && op == DENALI_WRITE)
+ index_addr((uint32_t)cmd, DENALI_BUFFER_WRITE);
+ else if (access_type == SPARE_ACCESS && op == DENALI_READ)
+ index_addr((uint32_t)cmd, DENALI_BUFFER_LOAD);
+ else
+ index_addr((uint32_t)cmd, 0x2000 | op | page_count);
+
+ /* wait for command to be accepted */
+ irq_status = wait_for_irq(irq_mask);
+ if ((irq_status & irq_mask) != irq_mask)
+ return FAIL;
+
+ if (access_type != SPARE_ACCESS) {
+ cmd = MODE_01 | addr;
+ __raw_writel(cmd, denali.flash_mem);
+ }
+ return PASS;
+}
+
+/* helper function that simply writes a buffer to the flash */
+static int write_data_to_flash_mem(const uint8_t *buf,
+ int len)
+{
+ uint32_t i = 0, *buf32;
+
+ /* verify that the len is a multiple of 4. see comment in
+ * read_data_from_flash_mem() */
+ BUG_ON((len % 4) != 0);
+
+ /* write the data to the flash memory */
+ buf32 = (uint32_t *)buf;
+ for (i = 0; i < len / 4; i++)
+ __raw_writel(*buf32++, denali.flash_mem + 0x10);
+ return i*4; /* intent is to return the number of bytes read */
+}
+
+static void denali_mode_main_access(void)
+{
+ uint32_t addr, cmd;
+ addr = BANK(denali.flash_bank) | denali.page;
+ cmd = MODE_10 | addr;
+ index_addr((uint32_t)cmd, MAIN_ACCESS);
+}
+
+static void denali_mode_main_spare_access(void)
+{
+ uint32_t addr, cmd;
+ addr = BANK(denali.flash_bank) | denali.page;
+ cmd = MODE_10 | addr;
+ index_addr((uint32_t)cmd, MAIN_SPARE_ACCESS);
+}
+
+/* Writes OOB data to the device.
+ * This code unused under normal U-Boot console as normally page write raw
+ * to be used for write oob data with main data.
+ */
+static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
+{
+ uint32_t cmd;
+
+ denali.page = page;
+ debug("* write_oob_data *\n");
+
+ /* We need to write to buffer first through MAP00 command */
+ cmd = MODE_00 | BANK(denali.flash_bank);
+ __raw_writel(cmd, denali.flash_mem);
+
+ /* send the data into flash buffer */
+ write_data_to_flash_mem(buf, mtd->oobsize);
+
+ /* activate the write through MAP10 commands */
+ if (denali_send_pipeline_cmd(false, false,
+ SPARE_ACCESS, DENALI_WRITE) != PASS)
+ return -EIO;
+
+ return 0;
+}
+
+/* this function examines buffers to see if they contain data that
+ * indicate that the buffer is part of an erased region of flash.
+ */
+bool is_erased(uint8_t *buf, int len)
+{
+ int i = 0;
+ for (i = 0; i < len; i++)
+ if (buf[i] != 0xFF)
+ return false;
+ return true;
+}
+
+
+/* programs the controller to either enable/disable DMA transfers */
+static void denali_enable_dma(bool en)
+{
+ uint32_t reg_val = 0x0;
+
+ if (en)
+ reg_val = DMA_ENABLE__FLAG;
+
+ __raw_writel(reg_val, denali.flash_reg + DMA_ENABLE);
+ __raw_readl(denali.flash_reg + DMA_ENABLE);
+}
+
+/* setups the HW to perform the data DMA */
+static void denali_setup_dma_sequence(int op)
+{
+ const int page_count = 1;
+ uint32_t mode;
+ uint32_t addr = (uint32_t)denali.buf.dma_buf;
+
+ mode = MODE_10 | BANK(denali.flash_bank);
+
+ /* DMA is a four step process */
+
+ /* 1. setup transfer type and # of pages */
+ index_addr(mode | denali.page, 0x2000 | op | page_count);
+
+ /* 2. set memory high address bits 23:8 */
+ index_addr(mode | ((uint16_t)(addr >> 16) << 8), 0x2200);
+
+ /* 3. set memory low address bits 23:8 */
+ index_addr(mode | ((uint16_t)addr << 8), 0x2300);
+
+ /* 4. interrupt when complete, burst len = 64 bytes*/
+ index_addr(mode | 0x14000, 0x2400);
+}
+
+/* Common DMA function */
+static uint32_t denali_dma_configuration(uint32_t ops, bool raw_xfer,
+ uint32_t irq_mask, int oob_required)
+{
+ uint32_t irq_status = 0;
+ /* setup_ecc_for_xfer(bool ecc_en, bool transfer_spare) */
+ setup_ecc_for_xfer(!raw_xfer, oob_required);
+
+ /* clear any previous interrupt flags */
+ clear_interrupts();
+
+ /* enable the DMA */
+ denali_enable_dma(true);
+
+ /* setup the DMA */
+ denali_setup_dma_sequence(ops);
+
+ /* wait for operation to complete */
+ irq_status = wait_for_irq(irq_mask);
+
+ /* if ECC fault happen, seems we need delay before turning off DMA.
+ * If not, the controller will go into non responsive condition */
+ if (irq_status & INTR_STATUS__ECC_UNCOR_ERR)
+ udelay(100);
+
+ /* disable the DMA */
+ denali_enable_dma(false);
+
+ return irq_status;
+}
+
+static int write_page(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, bool raw_xfer, int oob_required)
+{
+ uint32_t irq_status = 0;
+ uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
+
+ denali.status = PASS;
+
+ /* copy buffer into DMA buffer */
+ memcpy((void *)denali.buf.dma_buf, buf, mtd->writesize);
+
+ /* need extra memcpoy for raw transfer */
+ if (raw_xfer)
+ memcpy((void *)denali.buf.dma_buf + mtd->writesize,
+ chip->oob_poi, mtd->oobsize);
+
+ /* setting up DMA */
+ irq_status = denali_dma_configuration(DENALI_WRITE, raw_xfer, irq_mask,
+ oob_required);
+
+ /* if timeout happen, error out */
+ if (!(irq_status & INTR_STATUS__DMA_CMD_COMP)) {
+ debug("DMA timeout for denali write_page\n");
+ denali.status = NAND_STATUS_FAIL;
+ return -EIO;
+ }
+
+ if (irq_status & INTR_STATUS__LOCKED_BLK) {
+ debug("Failed as write to locked block\n");
+ denali.status = NAND_STATUS_FAIL;
+ return -EIO;
+ }
+ return 0;
+}
+
+/* NAND core entry points */
+
+/*
+ * this is the callback that the NAND core calls to write a page. Since
+ * writing a page with ECC or without is similar, all the work is done
+ * by write_page above.
+ */
+static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required)
+{
+ /*
+ * for regular page writes, we let HW handle all the ECC
+ * data written to the device.
+ */
+ debug("denali_write_page at page %08x\n", denali.page);
+
+ if (oob_required)
+ /* switch to main + spare access */
+ denali_mode_main_spare_access();
+ else
+ /* switch to main access only */
+ denali_mode_main_access();
+
+ return write_page(mtd, chip, buf, false, oob_required);
+}
+
+/*
+ * This is the callback that the NAND core calls to write a page without ECC.
+ * raw access is similar to ECC page writes, so all the work is done in the
+ * write_page() function above.
+ */
+static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required)
+{
+ /*
+ * for raw page writes, we want to disable ECC and simply write
+ * whatever data is in the buffer.
+ */
+ debug("denali_write_page_raw at page %08x\n", denali.page);
+
+ if (oob_required)
+ /* switch to main + spare access */
+ denali_mode_main_spare_access();
+ else
+ /* switch to main access only */
+ denali_mode_main_access();
+
+ return write_page(mtd, chip, buf, true, oob_required);
+}
+
+static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ return write_oob_data(mtd, chip->oob_poi, page);
+}
+
+/* raw include ECC value and all the spare area */
+static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
+{
+ uint32_t irq_status, irq_mask = INTR_STATUS__DMA_CMD_COMP;
+
+ debug("denali_read_page_raw at page %08x\n", page);
+ if (denali.page != page) {
+ debug("Missing NAND_CMD_READ0 command\n");
+ return -EIO;
+ }
+
+ if (oob_required)
+ /* switch to main + spare access */
+ denali_mode_main_spare_access();
+ else
+ /* switch to main access only */
+ denali_mode_main_access();
+
+ /* setting up the DMA where ecc_enable is false */
+ irq_status = denali_dma_configuration(DENALI_READ, true, irq_mask,
+ oob_required);
+
+ /* if timeout happen, error out */
+ if (!(irq_status & INTR_STATUS__DMA_CMD_COMP)) {
+ debug("DMA timeout for denali_read_page_raw\n");
+ return -EIO;
+ }
+
+ /* splitting the content to destination buffer holder */
+ memcpy(chip->oob_poi, (const void *)(denali.buf.dma_buf +
+ mtd->writesize), mtd->oobsize);
+ memcpy(buf, (const void *)denali.buf.dma_buf, mtd->writesize);
+ debug("buf %02x %02x\n", buf[0], buf[1]);
+ debug("chip->oob_poi %02x %02x\n", chip->oob_poi[0], chip->oob_poi[1]);
+ return 0;
+}
+
+static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
+{
+ uint32_t irq_status, irq_mask = INTR_STATUS__DMA_CMD_COMP;
+
+ debug("denali_read_page at page %08x\n", page);
+ if (denali.page != page) {
+ debug("Missing NAND_CMD_READ0 command\n");
+ return -EIO;
+ }
+
+ if (oob_required)
+ /* switch to main + spare access */
+ denali_mode_main_spare_access();
+ else
+ /* switch to main access only */
+ denali_mode_main_access();
+
+ /* setting up the DMA where ecc_enable is true */
+ irq_status = denali_dma_configuration(DENALI_READ, false, irq_mask,
+ oob_required);
+
+ memcpy(buf, (const void *)denali.buf.dma_buf, mtd->writesize);
+ debug("buf %02x %02x\n", buf[0], buf[1]);
+
+ /* check whether any ECC error */
+ if (irq_status & INTR_STATUS__ECC_UNCOR_ERR) {
+
+ /* is the ECC cause by erase page, check using read_page_raw */
+ debug(" Uncorrected ECC detected\n");
+ denali_read_page_raw(mtd, chip, buf, oob_required, denali.page);
+
+ if (is_erased(buf, mtd->writesize) == true &&
+ is_erased(chip->oob_poi, mtd->oobsize) == true) {
+ debug(" ECC error cause by erased block\n");
+ /* false alarm, return the 0xFF */
+ } else
+ return -EIO;
+ }
+ memcpy(buf, (const void *)denali.buf.dma_buf, mtd->writesize);
+ return 0;
+}
+
+static uint8_t denali_read_byte(struct mtd_info *mtd)
+{
+ uint32_t addr, result;
+ addr = (uint32_t)MODE_11 | BANK(denali.flash_bank);
+ index_addr_read_data((uint32_t)addr | 2, &result);
+ return (uint8_t)result & 0xFF;
+}
+
+static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ debug("denali_read_oob at page %08x\n", page);
+ denali.page = page;
+ return denali_read_page_raw(mtd, chip, denali.buf.buf, 1, page);
+}
+
+static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ uint32_t i, addr, result;
+
+ /* delay for tR (data transfer from Flash array to data register) */
+ udelay(25);
+
+ /* ensure device completed else additional delay and polling */
+ wait_for_irq(INTR_STATUS__INT_ACT);
+
+ addr = (uint32_t)MODE_11 | BANK(denali.flash_bank);
+ for (i = 0; i < len; i++) {
+ index_addr_read_data((uint32_t)addr | 2, &result);
+ write_byte_to_buf(result);
+ }
+ memcpy(buf, denali.buf.buf, len);
+}
+
+static void denali_select_chip(struct mtd_info *mtd, int chip)
+{
+ denali.flash_bank = chip;
+}
+
+static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
+{
+ int status = denali.status;
+ denali.status = 0;
+
+ return status;
+}
+
+static void denali_erase(struct mtd_info *mtd, int page)
+{
+ uint32_t cmd = 0x0, irq_status = 0;
+
+ debug("denali_erase at page %08x\n", page);
+
+ /* clear interrupts */
+ clear_interrupts();
+
+ /* setup page read request for access type */
+ cmd = MODE_10 | BANK(denali.flash_bank) | page;
+ index_addr((uint32_t)cmd, 0x1);
+
+ /* wait for erase to complete or failure to occur */
+ irq_status = wait_for_irq(INTR_STATUS__ERASE_COMP |
+ INTR_STATUS__ERASE_FAIL);
+
+ if (irq_status & INTR_STATUS__ERASE_FAIL ||
+ irq_status & INTR_STATUS__LOCKED_BLK)
+ denali.status = NAND_STATUS_FAIL;
+ else
+ denali.status = PASS;
+}
+
+static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
+ int page)
+{
+ uint32_t addr;
+
+ switch (cmd) {
+ case NAND_CMD_PAGEPROG:
+ break;
+ case NAND_CMD_STATUS:
+ addr = (uint32_t)MODE_11 | BANK(denali.flash_bank);
+ index_addr((uint32_t)addr | 0, cmd);
+ break;
+ case NAND_CMD_PARAM:
+ clear_interrupts();
+ case NAND_CMD_READID:
+ reset_buf();
+ /* sometimes ManufactureId read from register is not right
+ * e.g. some of Micron MT29F32G08QAA MLC NAND chips
+ * So here we send READID cmd to NAND insteand
+ * */
+ addr = (uint32_t)MODE_11 | BANK(denali.flash_bank);
+ index_addr((uint32_t)addr | 0, cmd);
+ index_addr((uint32_t)addr | 1, col & 0xFF);
+ break;
+ case NAND_CMD_READ0:
+ case NAND_CMD_SEQIN:
+ denali.page = page;
+ break;
+ case NAND_CMD_RESET:
+ reset_bank();
+ break;
+ case NAND_CMD_READOOB:
+ /* TODO: Read OOB data */
+ break;
+ case NAND_CMD_ERASE1:
+ /*
+ * supporting block erase only, not multiblock erase as
+ * it will cross plane and software need complex calculation
+ * to identify the block count for the cross plane
+ */
+ denali_erase(mtd, page);
+ break;
+ case NAND_CMD_ERASE2:
+ /* nothing to do here as it was done during NAND_CMD_ERASE1 */
+ break;
+ case NAND_CMD_UNLOCK1:
+ addr = (uint32_t)MODE_10 | BANK(denali.flash_bank) | page;
+ index_addr((uint32_t)addr | 0, DENALI_UNLOCK_START);
+ break;
+ case NAND_CMD_UNLOCK2:
+ addr = (uint32_t)MODE_10 | BANK(denali.flash_bank) | page;
+ index_addr((uint32_t)addr | 0, DENALI_UNLOCK_END);
+ break;
+ case NAND_CMD_LOCK:
+ addr = (uint32_t)MODE_10 | BANK(denali.flash_bank);
+ index_addr((uint32_t)addr | 0, DENALI_LOCK);
+ break;
+ case NAND_CMD_LOCK_TIGHT:
+ addr = (uint32_t)MODE_10 | BANK(denali.flash_bank);
+ index_addr((uint32_t)addr | 0, DENALI_LOCK_TIGHT);
+ break;
+ default:
+ printf(": unsupported command received 0x%x\n", cmd);
+ break;
+ }
+}
+
+/* stubs for ECC functions not used by the NAND core */
+static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
+ uint8_t *ecc_code)
+{
+ debug("Should not be called as ECC handled by hardware\n");
+ BUG();
+ return -EIO;
+}
+
+static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
+ uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+ debug("Should not be called as ECC handled by hardware\n");
+ BUG();
+ return -EIO;
+}
+
+static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
+{
+ debug("Should not be called as ECC handled by hardware\n");
+ BUG();
+}
+/* end NAND core entry points */
+
+/* Initialization code to bring the device up to a known good state */
+static void denali_hw_init(void)
+{
+ /*
+ * tell driver how many bit controller will skip before writing
+ * ECC code in OOB. This is normally used for bad block marker
+ */
+ __raw_writel(CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES,
+ denali.flash_reg + SPARE_AREA_SKIP_BYTES);
+ detect_max_banks();
+ denali_nand_reset();
+ __raw_writel(0x0F, denali.flash_reg + RB_PIN_ENABLED);
+ __raw_writel(CHIP_EN_DONT_CARE__FLAG,
+ denali.flash_reg + CHIP_ENABLE_DONT_CARE);
+ __raw_writel(0xffff, denali.flash_reg + SPARE_AREA_MARKER);
+
+ /* Should set value for these registers when init */
+ __raw_writel(0, denali.flash_reg + TWO_ROW_ADDR_CYCLES);
+ __raw_writel(1, denali.flash_reg + ECC_ENABLE);
+ denali_nand_timing_set();
+ denali_irq_init();
+}
+
+/*
+ * Although controller spec said SLC ECC is forceb to be 4bit, but denali
+ * controller in MRST only support 15bit and 8bit ECC correction
+ */
+#ifdef CONFIG_SYS_NAND_15BIT_HW_ECC_OOBFIRST
+#define ECC_15BITS 26
+static struct nand_ecclayout nand_15bit_oob = {
+ .eccbytes = ECC_15BITS,
+};
+#else
+#define ECC_8BITS 14
+static struct nand_ecclayout nand_8bit_oob = {
+ .eccbytes = ECC_8BITS,
+};
+#endif /* CONFIG_SYS_NAND_15BIT_HW_ECC_OOBFIRST */
+
+void denali_nand_init(struct nand_chip *nand)
+{
+ denali.flash_reg = (void __iomem *)CONFIG_SYS_NAND_REGS_BASE;
+ denali.flash_mem = (void __iomem *)CONFIG_SYS_NAND_DATA_BASE;
+
+ nand->chip_delay = 0;
+#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
+ /* check whether flash got BBT table (located at end of flash). As we
+ * use NAND_BBT_NO_OOB, the BBT page will start with
+ * bbt_pattern. We will have mirror pattern too */
+ nand->options |= NAND_BBT_USE_FLASH;
+ /*
+ * We are using main + spare with ECC support. As BBT need ECC support,
+ * we need to ensure BBT code don't write to OOB for the BBT pattern.
+ * All BBT info will be stored into data area with ECC support.
+ */
+ nand->options |= NAND_BBT_NO_OOB;
+#endif
+
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.size = CONFIG_NAND_DENALI_ECC_SIZE;
+ nand->ecc.read_oob = denali_read_oob;
+ nand->ecc.write_oob = denali_write_oob;
+ nand->ecc.read_page = denali_read_page;
+ nand->ecc.read_page_raw = denali_read_page_raw;
+ nand->ecc.write_page = denali_write_page;
+ nand->ecc.write_page_raw = denali_write_page_raw;
+#ifdef CONFIG_SYS_NAND_15BIT_HW_ECC_OOBFIRST
+ /* 15bit ECC */
+ nand->ecc.bytes = 26;
+ nand->ecc.layout = &nand_15bit_oob;
+#else /* 8bit ECC */
+ nand->ecc.bytes = 14;
+ nand->ecc.layout = &nand_8bit_oob;
+#endif
+ nand->ecc.calculate = denali_ecc_calculate;
+ nand->ecc.correct = denali_ecc_correct;
+ nand->ecc.hwctl = denali_ecc_hwctl;
+
+ /* Set address of hardware control function */
+ nand->cmdfunc = denali_cmdfunc;
+ nand->read_byte = denali_read_byte;
+ nand->read_buf = denali_read_buf;
+ nand->select_chip = denali_select_chip;
+ nand->waitfunc = denali_waitfunc;
+ denali_hw_init();
+}
+
+int board_nand_init(struct nand_chip *chip)
+{
+ puts("NAND: Denali NAND controller\n");
+ denali_nand_init(chip);
+ return 0;
+}
diff --git a/drivers/mtd/nand/denali_nand.h b/drivers/mtd/nand/denali_nand.h
new file mode 100644
index 0000000..fd91c64
--- /dev/null
+++ b/drivers/mtd/nand/denali_nand.h
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2013 Altera Corporation <www.altera.com>
+ * Copyright (C) 2009-2010, Intel Corporation and its suppliers.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+typedef int irqreturn_t;
+
+#define IRQ_HANDLED 1
+#define IRQ_NONE 0
+
+#define DEVICE_RESET 0x0
+#define DEVICE_RESET__BANK0 0x0001
+#define DEVICE_RESET__BANK1 0x0002
+#define DEVICE_RESET__BANK2 0x0004
+#define DEVICE_RESET__BANK3 0x0008
+
+#define TRANSFER_SPARE_REG 0x10
+#define TRANSFER_SPARE_REG__FLAG 0x0001
+
+#define LOAD_WAIT_CNT 0x20
+#define LOAD_WAIT_CNT__VALUE 0xffff
+
+#define PROGRAM_WAIT_CNT 0x30
+#define PROGRAM_WAIT_CNT__VALUE 0xffff
+
+#define ERASE_WAIT_CNT 0x40
+#define ERASE_WAIT_CNT__VALUE 0xffff
+
+#define INT_MON_CYCCNT 0x50
+#define INT_MON_CYCCNT__VALUE 0xffff
+
+#define RB_PIN_ENABLED 0x60
+#define RB_PIN_ENABLED__BANK0 0x0001
+#define RB_PIN_ENABLED__BANK1 0x0002
+#define RB_PIN_ENABLED__BANK2 0x0004
+#define RB_PIN_ENABLED__BANK3 0x0008
+
+#define MULTIPLANE_OPERATION 0x70
+#define MULTIPLANE_OPERATION__FLAG 0x0001
+
+#define MULTIPLANE_READ_ENABLE 0x80
+#define MULTIPLANE_READ_ENABLE__FLAG 0x0001
+
+#define COPYBACK_DISABLE 0x90
+#define COPYBACK_DISABLE__FLAG 0x0001
+
+#define CACHE_WRITE_ENABLE 0xa0
+#define CACHE_WRITE_ENABLE__FLAG 0x0001
+
+#define CACHE_READ_ENABLE 0xb0
+#define CACHE_READ_ENABLE__FLAG 0x0001
+
+#define PREFETCH_MODE 0xc0
+#define PREFETCH_MODE__PREFETCH_EN 0x0001
+#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0
+
+#define CHIP_ENABLE_DONT_CARE 0xd0
+#define CHIP_EN_DONT_CARE__FLAG 0x01
+
+#define ECC_ENABLE 0xe0
+#define ECC_ENABLE__FLAG 0x0001
+
+#define GLOBAL_INT_ENABLE 0xf0
+#define GLOBAL_INT_EN_FLAG 0x01
+
+#define WE_2_RE 0x100
+#define WE_2_RE__VALUE 0x003f
+
+#define ADDR_2_DATA 0x110
+#define ADDR_2_DATA__VALUE 0x003f
+
+#define RE_2_WE 0x120
+#define RE_2_WE__VALUE 0x003f
+
+#define ACC_CLKS 0x130
+#define ACC_CLKS__VALUE 0x000f
+
+#define NUMBER_OF_PLANES 0x140
+#define NUMBER_OF_PLANES__VALUE 0x0007
+
+#define PAGES_PER_BLOCK 0x150
+#define PAGES_PER_BLOCK__VALUE 0xffff
+
+#define DEVICE_WIDTH 0x160
+#define DEVICE_WIDTH__VALUE 0x0003
+
+#define DEVICE_MAIN_AREA_SIZE 0x170
+#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff
+
+#define DEVICE_SPARE_AREA_SIZE 0x180
+#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff
+
+#define TWO_ROW_ADDR_CYCLES 0x190
+#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001
+
+#define MULTIPLANE_ADDR_RESTRICT 0x1a0
+#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001
+
+#define ECC_CORRECTION 0x1b0
+#define ECC_CORRECTION__VALUE 0x001f
+
+#define READ_MODE 0x1c0
+#define READ_MODE__VALUE 0x000f
+
+#define WRITE_MODE 0x1d0
+#define WRITE_MODE__VALUE 0x000f
+
+#define COPYBACK_MODE 0x1e0
+#define COPYBACK_MODE__VALUE 0x000f
+
+#define RDWR_EN_LO_CNT 0x1f0
+#define RDWR_EN_LO_CNT__VALUE 0x001f
+
+#define RDWR_EN_HI_CNT 0x200
+#define RDWR_EN_HI_CNT__VALUE 0x001f
+
+#define MAX_RD_DELAY 0x210
+#define MAX_RD_DELAY__VALUE 0x000f
+
+#define CS_SETUP_CNT 0x220
+#define CS_SETUP_CNT__VALUE 0x001f
+
+#define SPARE_AREA_SKIP_BYTES 0x230
+#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f
+
+#define SPARE_AREA_MARKER 0x240
+#define SPARE_AREA_MARKER__VALUE 0xffff
+
+#define DEVICES_CONNECTED 0x250
+#define DEVICES_CONNECTED__VALUE 0x0007
+
+#define DIE_MASK 0x260
+#define DIE_MASK__VALUE 0x00ff
+
+#define FIRST_BLOCK_OF_NEXT_PLANE 0x270
+#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff
+
+#define WRITE_PROTECT 0x280
+#define WRITE_PROTECT__FLAG 0x0001
+
+#define RE_2_RE 0x290
+#define RE_2_RE__VALUE 0x003f
+
+#define MANUFACTURER_ID 0x300
+#define MANUFACTURER_ID__VALUE 0x00ff
+
+#define DEVICE_ID 0x310
+#define DEVICE_ID__VALUE 0x00ff
+
+#define DEVICE_PARAM_0 0x320
+#define DEVICE_PARAM_0__VALUE 0x00ff
+
+#define DEVICE_PARAM_1 0x330
+#define DEVICE_PARAM_1__VALUE 0x00ff
+
+#define DEVICE_PARAM_2 0x340
+#define DEVICE_PARAM_2__VALUE 0x00ff
+
+#define LOGICAL_PAGE_DATA_SIZE 0x350
+#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff
+
+#define LOGICAL_PAGE_SPARE_SIZE 0x360
+#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff
+
+#define REVISION 0x370
+#define REVISION__VALUE 0xffff
+
+#define ONFI_DEVICE_FEATURES 0x380
+#define ONFI_DEVICE_FEATURES__VALUE 0x003f
+
+#define ONFI_OPTIONAL_COMMANDS 0x390
+#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f
+
+#define ONFI_TIMING_MODE 0x3a0
+#define ONFI_TIMING_MODE__VALUE 0x003f
+
+#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0
+#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f
+
+#define ONFI_DEVICE_NO_OF_LUNS 0x3c0
+#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff
+#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100
+
+#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0
+#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff
+
+#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0
+#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff
+
+#define FEATURES 0x3f0
+#define FEATURES__N_BANKS 0x0003
+#define FEATURES__ECC_MAX_ERR 0x003c
+#define FEATURES__DMA 0x0040
+#define FEATURES__CMD_DMA 0x0080
+#define FEATURES__PARTITION 0x0100
+#define FEATURES__XDMA_SIDEBAND 0x0200
+#define FEATURES__GPREG 0x0400
+#define FEATURES__INDEX_ADDR 0x0800
+
+#define TRANSFER_MODE 0x400
+#define TRANSFER_MODE__VALUE 0x0003
+
+#define INTR_STATUS(__bank) (0x410 + ((__bank) * 0x50))
+#define INTR_EN(__bank) (0x420 + ((__bank) * 0x50))
+
+/*
+ * Some versions of the IP have the ECC fixup handled in hardware. In this
+ * configuration we only get interrupted when the error is uncorrectable.
+ * Unfortunately this bit replaces INTR_STATUS__ECC_TRANSACTION_DONE from the
+ * old IP.
+ */
+#define INTR_STATUS__ECC_UNCOR_ERR 0x0001
+#define INTR_STATUS__ECC_TRANSACTION_DONE 0x0001
+#define INTR_STATUS__ECC_ERR 0x0002
+#define INTR_STATUS__DMA_CMD_COMP 0x0004
+#define INTR_STATUS__TIME_OUT 0x0008
+#define INTR_STATUS__PROGRAM_FAIL 0x0010
+#define INTR_STATUS__ERASE_FAIL 0x0020
+#define INTR_STATUS__LOAD_COMP 0x0040
+#define INTR_STATUS__PROGRAM_COMP 0x0080
+#define INTR_STATUS__ERASE_COMP 0x0100
+#define INTR_STATUS__PIPE_CPYBCK_CMD_COMP 0x0200
+#define INTR_STATUS__LOCKED_BLK 0x0400
+#define INTR_STATUS__UNSUP_CMD 0x0800
+#define INTR_STATUS__INT_ACT 0x1000
+#define INTR_STATUS__RST_COMP 0x2000
+#define INTR_STATUS__PIPE_CMD_ERR 0x4000
+#define INTR_STATUS__PAGE_XFER_INC 0x8000
+
+#define INTR_EN__ECC_TRANSACTION_DONE 0x0001
+#define INTR_EN__ECC_ERR 0x0002
+#define INTR_EN__DMA_CMD_COMP 0x0004
+#define INTR_EN__TIME_OUT 0x0008
+#define INTR_EN__PROGRAM_FAIL 0x0010
+#define INTR_EN__ERASE_FAIL 0x0020
+#define INTR_EN__LOAD_COMP 0x0040
+#define INTR_EN__PROGRAM_COMP 0x0080
+#define INTR_EN__ERASE_COMP 0x0100
+#define INTR_EN__PIPE_CPYBCK_CMD_COMP 0x0200
+#define INTR_EN__LOCKED_BLK 0x0400
+#define INTR_EN__UNSUP_CMD 0x0800
+#define INTR_EN__INT_ACT 0x1000
+#define INTR_EN__RST_COMP 0x2000
+#define INTR_EN__PIPE_CMD_ERR 0x4000
+#define INTR_EN__PAGE_XFER_INC 0x8000
+
+#define PAGE_CNT(__bank) (0x430 + ((__bank) * 0x50))
+#define ERR_PAGE_ADDR(__bank) (0x440 + ((__bank) * 0x50))
+#define ERR_BLOCK_ADDR(__bank) (0x450 + ((__bank) * 0x50))
+
+#define DATA_INTR 0x550
+#define DATA_INTR__WRITE_SPACE_AV 0x0001
+#define DATA_INTR__READ_DATA_AV 0x0002
+
+#define DATA_INTR_EN 0x560
+#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001
+#define DATA_INTR_EN__READ_DATA_AV 0x0002
+
+#define GPREG_0 0x570
+#define GPREG_0__VALUE 0xffff
+
+#define GPREG_1 0x580
+#define GPREG_1__VALUE 0xffff
+
+#define GPREG_2 0x590
+#define GPREG_2__VALUE 0xffff
+
+#define GPREG_3 0x5a0
+#define GPREG_3__VALUE 0xffff
+
+#define ECC_THRESHOLD 0x600
+#define ECC_THRESHOLD__VALUE 0x03ff
+
+#define ECC_ERROR_BLOCK_ADDRESS 0x610
+#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff
+
+#define ECC_ERROR_PAGE_ADDRESS 0x620
+#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff
+#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000
+
+#define ECC_ERROR_ADDRESS 0x630
+#define ECC_ERROR_ADDRESS__OFFSET 0x0fff
+#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000
+
+#define ERR_CORRECTION_INFO 0x640
+#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff
+#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00
+#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000
+#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000
+
+#define DMA_ENABLE 0x700
+#define DMA_ENABLE__FLAG 0x0001
+
+#define IGNORE_ECC_DONE 0x710
+#define IGNORE_ECC_DONE__FLAG 0x0001
+
+#define DMA_INTR 0x720
+#define DMA_INTR__TARGET_ERROR 0x0001
+#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002
+#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004
+#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008
+#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010
+#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020
+
+#define DMA_INTR_EN 0x730
+#define DMA_INTR_EN__TARGET_ERROR 0x0001
+#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002
+#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004
+#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008
+#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010
+#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020
+
+#define TARGET_ERR_ADDR_LO 0x740
+#define TARGET_ERR_ADDR_LO__VALUE 0xffff
+
+#define TARGET_ERR_ADDR_HI 0x750
+#define TARGET_ERR_ADDR_HI__VALUE 0xffff
+
+#define CHNL_ACTIVE 0x760
+#define CHNL_ACTIVE__CHANNEL0 0x0001
+#define CHNL_ACTIVE__CHANNEL1 0x0002
+#define CHNL_ACTIVE__CHANNEL2 0x0004
+#define CHNL_ACTIVE__CHANNEL3 0x0008
+
+#define ACTIVE_SRC_ID 0x800
+#define ACTIVE_SRC_ID__VALUE 0x00ff
+
+#define PTN_INTR 0x810
+#define PTN_INTR__CONFIG_ERROR 0x0001
+#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002
+#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004
+#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008
+#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010
+#define PTN_INTR__REG_ACCESS_ERROR 0x0020
+
+#define PTN_INTR_EN 0x820
+#define PTN_INTR_EN__CONFIG_ERROR 0x0001
+#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002
+#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004
+#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008
+#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010
+#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020
+
+#define PERM_SRC_ID(__bank) (0x830 + ((__bank) * 0x40))
+#define PERM_SRC_ID__SRCID 0x00ff
+#define PERM_SRC_ID__DIRECT_ACCESS_ACTIVE 0x0800
+#define PERM_SRC_ID__WRITE_ACTIVE 0x2000
+#define PERM_SRC_ID__READ_ACTIVE 0x4000
+#define PERM_SRC_ID__PARTITION_VALID 0x8000
+
+#define MIN_BLK_ADDR(__bank) (0x840 + ((__bank) * 0x40))
+#define MIN_BLK_ADDR__VALUE 0xffff
+
+#define MAX_BLK_ADDR(__bank) (0x850 + ((__bank) * 0x40))
+#define MAX_BLK_ADDR__VALUE 0xffff
+
+#define MIN_MAX_BANK(__bank) (0x860 + ((__bank) * 0x40))
+#define MIN_MAX_BANK__MIN_VALUE 0x0003
+#define MIN_MAX_BANK__MAX_VALUE 0x000c
+
+
+/* ffsdefs.h */
+#define CLEAR 0 /*use this to clear a field instead of "fail"*/
+#define SET 1 /*use this to set a field instead of "pass"*/
+#define FAIL 1 /*failed flag*/
+#define PASS 0 /*success flag*/
+#define ERR -1 /*error flag*/
+
+/* lld.h */
+#define GOOD_BLOCK 0
+#define DEFECTIVE_BLOCK 1
+#define READ_ERROR 2
+
+#define CLK_X 5
+#define CLK_MULTI 4
+
+/* spectraswconfig.h */
+#define CMD_DMA 0
+
+#define SPECTRA_PARTITION_ID 0
+/**** Block Table and Reserved Block Parameters *****/
+#define SPECTRA_START_BLOCK 3
+#define NUM_FREE_BLOCKS_GATE 30
+
+/* KBV - Updated to LNW scratch register address */
+#define SCRATCH_REG_ADDR CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR
+#define SCRATCH_REG_SIZE 64
+
+#define GLOB_HWCTL_DEFAULT_BLKS 2048
+
+#define SUPPORT_15BITECC 1
+#define SUPPORT_8BITECC 1
+
+#define CUSTOM_CONF_PARAMS 0
+
+#define ONFI_BLOOM_TIME 1
+#define MODE5_WORKAROUND 0
+
+/* lld_nand.h */
+/*
+ * NAND Flash Controller Device Driver
+ * Copyright (c) 2009, Intel Corporation and its suppliers.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _LLD_NAND_
+#define _LLD_NAND_
+
+#define MODE_00 0x00000000
+#define MODE_01 0x04000000
+#define MODE_10 0x08000000
+#define MODE_11 0x0C000000
+
+
+#define DATA_TRANSFER_MODE 0
+#define PROTECTION_PER_BLOCK 1
+#define LOAD_WAIT_COUNT 2
+#define PROGRAM_WAIT_COUNT 3
+#define ERASE_WAIT_COUNT 4
+#define INT_MONITOR_CYCLE_COUNT 5
+#define READ_BUSY_PIN_ENABLED 6
+#define MULTIPLANE_OPERATION_SUPPORT 7
+#define PRE_FETCH_MODE 8
+#define CE_DONT_CARE_SUPPORT 9
+#define COPYBACK_SUPPORT 10
+#define CACHE_WRITE_SUPPORT 11
+#define CACHE_READ_SUPPORT 12
+#define NUM_PAGES_IN_BLOCK 13
+#define ECC_ENABLE_SELECT 14
+#define WRITE_ENABLE_2_READ_ENABLE 15
+#define ADDRESS_2_DATA 16
+#define READ_ENABLE_2_WRITE_ENABLE 17
+#define TWO_ROW_ADDRESS_CYCLES 18
+#define MULTIPLANE_ADDRESS_RESTRICT 19
+#define ACC_CLOCKS 20
+#define READ_WRITE_ENABLE_LOW_COUNT 21
+#define READ_WRITE_ENABLE_HIGH_COUNT 22
+
+#define ECC_SECTOR_SIZE 512
+
+#define DENALI_BUF_SIZE (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
+
+struct nand_buf {
+ int head;
+ int tail;
+ /* seprating dma_buf as buf can be used for status read purpose */
+ uint8_t dma_buf[DENALI_BUF_SIZE] __aligned(64);
+ uint8_t buf[DENALI_BUF_SIZE];
+};
+
+#define INTEL_CE4100 1
+#define INTEL_MRST 2
+#define DT 3
+
+struct denali_nand_info {
+ struct mtd_info mtd;
+ struct nand_chip *nand;
+
+ int flash_bank; /* currently selected chip */
+ int status;
+ int platform;
+ struct nand_buf buf;
+ struct device *dev;
+ int total_used_banks;
+ uint32_t block; /* stored for future use */
+ uint32_t page;
+ void __iomem *flash_reg; /* Mapped io reg base address */
+ void __iomem *flash_mem; /* Mapped io reg base address */
+
+ /* elements used by ISR */
+ /*struct completion complete;*/
+
+ uint32_t irq_status;
+ int irq_debug_array[32];
+ int idx;
+ int irq;
+
+ uint32_t devnum; /* represent how many nands connected */
+ uint32_t fwblks; /* represent how many blocks FW used */
+ uint32_t totalblks;
+ uint32_t blksperchip;
+ uint32_t bbtskipbytes;
+ uint32_t max_banks;
+};
+
+#endif /*_LLD_NAND_*/
--
1.7.9.5
2
4
Changes in v4:
- Rebase on the current u-boot/master
Changes in v3:
- Rebase on the current u-boot/master
- Fix a typo in commit log
Changes in v2:
- Do not delete Lite5200*
Masahiro Yamada (2):
boards.cfg: Place "-" in the 8th field if it is the same as 7th
boards.cfg: Delete the equivalent entries
boards.cfg | 85 +++++++++++++++++++++++++++++---------------------------------
1 file changed, 40 insertions(+), 45 deletions(-)
--
1.8.3.2
4
12

21 Feb '14
check with this ubi command, if a UBI volume with "volumename"
exists in current ubi device.
Signed-off-by: Heiko Schocher <hs(a)denx.de>
---
common/cmd_ubi.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
index 122ba7e..7c4d950 100644
--- a/common/cmd_ubi.c
+++ b/common/cmd_ubi.c
@@ -123,6 +123,27 @@ static int ubi_info(int layout)
return 0;
}
+static int ubi_check_volumename(const struct ubi_volume *vol, char *name)
+{
+ return strcmp(vol->name, name);
+}
+
+static int ubi_check(char *name)
+{
+ int i;
+
+ for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
+ if (!ubi->volumes[i])
+ continue; /* Empty record */
+
+ if (!ubi_check_volumename(ubi->volumes[i], name))
+ return 0;
+ }
+
+ return -EEXIST;
+}
+
+
static int verify_mkvol_req(const struct ubi_device *ubi,
const struct ubi_mkvol_req *req)
{
@@ -558,6 +579,14 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return ubi_info(layout);
}
+ if (strcmp(argv[1], "check") == 0) {
+ if (argc > 2)
+ return ubi_check(argv[2]);
+
+ printf("Error, no volume name passed\n");
+ return 1;
+ }
+
if (strncmp(argv[1], "create", 6) == 0) {
int dynamic = 1; /* default: dynamic volume */
@@ -663,6 +692,8 @@ U_BOOT_CMD(
" header offset)\n"
"ubi info [l[ayout]]"
" - Display volume and ubi layout information\n"
+ "ubi check volumename"
+ " - check if volumename exists\n"
"ubi create[vol] volume [size] [type]"
" - create volume name with size\n"
"ubi write[vol] address volume size"
--
1.8.3.1
2
4