Merge "ipq40xx: removing redundant initialization in dts"
diff --git a/arch/arm/dts/ipq5018-emulation.dts b/arch/arm/dts/ipq5018-emulation.dts
index d0b1b05..5009210 100644
--- a/arch/arm/dts/ipq5018-emulation.dts
+++ b/arch/arm/dts/ipq5018-emulation.dts
@@ -28,6 +28,11 @@
compatible = "qcom,sdhci-msm";
};
+ nand: nand-controller@79B0000 {
+ status = "ok";
+ nand_gpio {};
+ };
+
timer {
gpt_freq_hz = <240000>;
};
diff --git a/arch/arm/dts/ipq5018-soc.dtsi b/arch/arm/dts/ipq5018-soc.dtsi
index e8dc902..56016fc 100644
--- a/arch/arm/dts/ipq5018-soc.dtsi
+++ b/arch/arm/dts/ipq5018-soc.dtsi
@@ -62,4 +62,55 @@
spi_gpio {};
};
+ nand: nand-controller@79B0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "qcom,qpic-nand-v2.1.1";
+ reg = <0x79B0000 0x10000>;
+
+ nand_gpio {
+ qspi_data0 {
+ gpio = <7>;
+ func = <2>;
+ pull = <GPIO_PULL_DOWN>;
+ drvstr = <GPIO_8MA>;
+ oe = <GPIO_OE_DISABLE>;
+ };
+ qspi_data1 {
+ gpio = <6>;
+ func = <2>;
+ pull = <GPIO_PULL_DOWN>;
+ drvstr = <GPIO_8MA>;
+ oe = <GPIO_OE_DISABLE>;
+ };
+ qspi_data2 {
+ gpio = <5>;
+ func = <2>;
+ pull = <GPIO_PULL_DOWN>;
+ drvstr = <GPIO_8MA>;
+ oe = <GPIO_OE_DISABLE>;
+ };
+ qspi_data3 {
+ gpio = <4>;
+ func = <2>;
+ pull = <GPIO_PULL_DOWN>;
+ drvstr = <GPIO_8MA>;
+ oe = <GPIO_OE_DISABLE>;
+ };
+ qspi_cs_n {
+ gpio = <8>;
+ func = <2>;
+ pull = <GPIO_PULL_DOWN>;
+ drvstr = <GPIO_8MA>;
+ oe = <GPIO_OE_DISABLE>;
+ };
+ qspi_clk {
+ gpio = <9>;
+ func = <2>;
+ pull = <GPIO_PULL_DOWN>;
+ drvstr = <GPIO_8MA>;
+ oe = <GPIO_OE_DISABLE>;
+ };
+ };
+ };
};
diff --git a/arch/arm/include/asm/arch-qca-common/qca_common.h b/arch/arm/include/asm/arch-qca-common/qca_common.h
index d556429..ed013c3 100644
--- a/arch/arm/include/asm/arch-qca-common/qca_common.h
+++ b/arch/arm/include/asm/arch-qca-common/qca_common.h
@@ -94,6 +94,7 @@
*/
uint32_t offset; /* offset to be added to start address */
uint32_t dump_level;
+ uint32_t to_compress; /* non-zero represent for compressed dump*/
};
extern struct dumpinfo_t dumpinfo_n[];
extern int dump_entries_n;
diff --git a/arch/arm/include/asm/arch-qca-common/qpic_nand.h b/arch/arm/include/asm/arch-qca-common/qpic_nand.h
index f75145d..5a802c3 100644
--- a/arch/arm/include/asm/arch-qca-common/qpic_nand.h
+++ b/arch/arm/include/asm/arch-qca-common/qpic_nand.h
@@ -94,11 +94,200 @@
#define NAND_EBI2_ECC_BUF_CFG NAND_REG(0x00F0)
#define NAND_HW_INFO NAND_REG(0x00FC)
#define NAND_FLASH_BUFFER NAND_REG(0x0100)
+#define NAND_FLASH_FEATURES NAND_REG(0x0F64)
#define QPIC_NAND_CTRL NAND_REG(0x0F00)
#define QPIC_NAND_DEBUG NAND_REG(0x0F0C)
+/* Additional Register set for Serial NAND */
+#define NAND_AUTO_STATUS_EN NAND_REG(0x002C)
+#define NAND_VERSION NAND_REG(0x4F08)
+#define SPI_NAND_DEV_CMD0 NAND_REG(0x70A0)
+#define SPI_NAND_DEV_CMD1 NAND_REG(0x70A4)
+#define SPI_NAND_DEV_CMD2 NAND_REG(0x70A8)
+#define SPI_NAND_DEV_CMD3 NAND_REG(0x70D0)
+#define NAND_FLASH_DEV_CMD_VLD NAND_REG(0x70AC)
+#define SPI_NAND_DEV_CMD7 NAND_REG(0x70B0)
+#define SPI_NAND_DEV_CMD8 NAND_REG(0x70B4)
+#define SPI_NAND_DEV_CMD9 NAND_REG(0x70B8)
+#define NAND_FLASH_SPI_CFG NAND_REG(0x70C0)
+#define NAND_SPI_NUM_ADDR_CYCLES NAND_REG(0x70C4)
+#define NAND_SPI_BUSY_CHECK_WAIT_CNT NAND_REG(0x70C8)
+
+/* Register mask & shift value used in SPI transfer mode */
+#define SPI_TRANSFER_MODE_1X 0x1
+#define SPI_TRANSFER_MODE_4X 0x3
+/* These value as per HPG , these value as per 2K device*/
+#define SPI_NAND_DEVn_CFG0 0x1A5408D0
+#define SPI_NAND_DEVn_CFG1 0x08287440
+#define SPI_NAND_DEVn_CFG1_RESET 0x087476B1
+/* value for below register according to HPG : 0x42040702 for reset
+ * and 0x42040700 for reset disable
+ */
+#define SPI_NAND_DEVn_ECC_CFG 0x42040702
+#define SPI_NAND_DEVn_ECC_CFG_RST_DIS 0x42040700
+#define FLASH_DEV_CMD_VLD 0x0000000D
+/* These Value as per HPG */
+#define NAND_FLASH_DEV_CMD0_VAL 0x1080D8D8
+#define NAND_FLASH_DEV_CMD1_VAL 0xF00F3000
+#define NAND_FLASH_DEV_CMD2_VAL 0xF0FF709F
+#define NAND_FLASH_DEV_CMD3_VAL 0x3F310015
+/* For Micron NAND_FLASH_DEV_CMD3_VAL value should
+ * be 0x3F300015
+ */
+#define NAND_FLASH_DEV_CMD7_VAL 0x04061F0F
+#define NAND_FLASH_DEV_CMD7_WE 0x60000
+#define NAND_FLASH_DEV_CMD7_WD 0x40000000
+#define NAND_FLASH_DEV_CMD7_SET_FTR 0x1F00
+#define NAND_FLASH_DEV_CMD7_GET_FTR 0x0F
+#define SPI_BUSY_CHECK_WAIT_CNT 0x00000010
+#define SPI_CFG_VAL 0x1924C00D
+#define SPI_LOAD_CLK_CNTR_INIT_EN (1 << 28)
+#define SPI_NUM_ADDR_CYCLES 0x000DA4DB
+#define NAND_FLASH_SET_FEATURE_MASK 0xB800000E
+#define NAND_FLASH_GET_FEATURE_MASK 0x3800000E
+#define QPIC_HARDWARE_VERSION_2_0 0x20000000
+#define NAND_FLASH_STATUS_MASK 0xC
+#define QPIC_SERIAL_ERROR 517
+#define QPIC_SPI_SET_FEATURE (1 << 31)
+#define QPIC_SPI_GET_FEATURE ~(1 << 31)
+#define QPIC_SPI_WP_SET (1 << 28)
+#define QPIC_SPI_HOLD_SET (1 << 27)
+#define QPIC_SPI_TRANSFER_MODE_X1 (1 << 29)
+#define QPIC_SPI_TRANSFER_MODE_X4 (3 << 29)
+#define QPIC_SPI_BOOST_MODE (1 << 11)
+#define QPIC_SPI_NAND_CTRL_VAL 0x341
+#define QPIC_SPI_NAND_AUTO_STATUS_VAL 0x003F003F
+#define QPIC_NAND_FLASH_CMD_WE_VAL 0XB800000F
+#define QPIC_NAND_FLASH_CMD_WD_VAL 0x3800000F
+#define WR_EN 0x1
+#define WR_DIS 0x0
+
+/* According to GigaDevice data sheet Block Protection Register is:
+ * ____________________________________________
+ * | | | | | | | | |
+ * |BRWD |RSVD| BP2| BP1| BP0| INV | CMP |RSVD |
+ * | | | | | | | | |
+ * |______|____|____|____|____|_____|_____|_____|
+ *
+ * NOTE: RSVD = Reserved.
+ *
+ * After power-up the device is in "locked" state i.e feature bits
+ * BP0, BP1, BP2 are set to 1. ENV, CMP, BRWD are set to 0.
+ * When BRWD is set to 1 and WP# is LOW i.e 0, none of the writable
+ * protection feature bits can be set.
+ * When an ERASE command is issued to a locked block, the erase failure,
+ * 04H, is returned.
+ *
+ * With CMP = X, INV = X, BP2 = 0, BP1 = 0, BP0 = 0 : There will be no
+ * block protection functionality.
+ *
+ * When WP# is not LOW, user can issue bellows commands to alter the
+ * protection.
+ *
+ * Issue SET FEATURES register write (1FH)
+ * Issue the feature bit address (A0h)
+ */
+#define FLASH_SPI_NAND_BLK_PROCT_ADDR 0xA0
+#define FLASH_SPI_NAND_BLK_PROCT_DISABLE 0x00
+#define FLASH_SPI_NAND_BLK_PROCT_ENABLE 0x78
+/* According to GigaDevice data sheet Feature Register is:
+ * _________________________________________________
+ * | | | | | | | | |
+ * |OTP-PRT|OTP_EN| RSVD|ECC-EN|RSVD|RSVD |RSVD |QE |
+ * | | | | | | | | |
+ * |_______|______|_____|______|____|_____|_____|____|
+ *
+ *
+ * NOTE : When a feature is set, it remains active until the
+ * device is power cycled or the feature is written to.once
+ * the device is set, it remains set, even if a RESET (FFH)
+ * command is issued.
+ *
+ * OTP-PRT = X , OTP_EN = 0 : Normal Operation
+ * OTP-PRT = 0, OTP_EN = 1 : Access OTP region, read and program data.
+ *
+ * ECC-EN : ECC is enabled after device power up, so the default
+ * READ and PROGRAM commands operate with internal ECC in the “active”
+ * state. To enable/disable ECC, perform the following command sequence:
+ *
+ * 1) Issue the SET FEATURES command (1FH).
+ * 2) Set the feature bit ECC_EN as you want:
+ * a) To enable ECC, Set ECC_EN to 1.
+ * b) To disable ECC, Clear ECC_EN to 0.
+ *
+ * NOTE: For this device GD5F1GQ4xExxG
+ * --> Internal ECC Off (ECC_EN=0):
+ * 2048-Byte+128-Byte Full Access.
+ *
+ * --> Internal ECC On (ECC_EN=1, default):
+ * Program: 2048-Byte+64-Byte.
+ * Read: 2048-Byte+128-Byte.
+ *
+ * QE : If QE is enabled, the quad IO operations can be executed.
+ *
+ */
+#define FLASH_SPI_NAND_FR_ADDR 0xB0
+#define FLASH_SPI_NAND_FR_ECC_ENABLE (1 << 4)
+#define FLASH_SPI_NAND_FR_QUAD_ENABLE 0x1
+/* According to GigaDevice data sheet Status Register(0xC0) is:
+ * _________________________________________________
+ * | | | | | | | | |
+ * |RSVD |RSVD |ECCS1|ECCS0|P-FAIL|E-FAIL|WEL |OIP |
+ * | | | | | | | | |
+ * |______|______|_____|_____|_____ |______|____|____|
+ *
+ *
+ * NOTE: RSVD = Reserved.
+ *
+ * P-FAIL : This bit indicates that a program failure has occurred
+ * (P_FAIL set to 1). It will also be set if the user attempts to
+ * program an invalid address or a protected region, including
+ * the OTP area.
+ *
+ * E-FAIL : This bit indicates that an erase failure has occurred
+ * (E_FAIL set to 1). It will also be set if the user attempts to
+ * erase a locked region.
+ *
+ * WEL : This bit indicates the current status of the write enable
+ * latch (WEL) and must be set (WEL = 1), prior to issuing a
+ * PROGRAM EXECUTE or BLOCK ERASE command. It is set by issuing the
+ * WRITE ENABLE command. WEL can also be disabled (WEL = 0), by issuing
+ * the WRITE DISABLE command.
+ *
+ * OIP : This bit is set (OIP = 1 ) when a PROGRAM EXECUTE, PAGE READ,
+ * BLOCK ERASE, or RESET command is executing, indicating the device
+ * is busy. When the bit is 0, the interface is in the ready state.
+ *
+ * ECC Status : ECCS and ECCSE are set to 00b either following a RESET,
+ * or at the beginning of the READ.ECCS and ECCSE are invalid if internal
+ * ECC is disabled (via a SET FEATURES command to reset ECC_EN to 0).
+ *
+ * NOTE: After power-on RESET, ECC status is set to reflect the contents
+ * of block 0, page 0.
+ */
+#define FLASH_SPI_NAND_SR_ADDR 0xC0
+#define FLASH_SPI_NAND_SR_DATA 0x00
+
+/* According to GigaDevice data sheet Feature Register(0xD0) is:
+ * _________________________________________________
+ * | | | | | | | | |
+ * |RSVD |DS-S1|DS-S0|RSVD |RSVD |RSVD |RSVD |RSVD|
+ * | | | | | | | | |
+ * |______|_____|_____|_____|______|______|_____|____|
+ *
+ * DS-S1 = 0 , DS-S0 = 0 : Drive strength is 50%
+ * DS-S1 = 0 , DS-S0 = 1 : Drive strength is 25%
+ * DS-S1 = 1 , DS-S0 = 0 : Drive strength is 75%
+ * DS-S1 = 1 , DS-S0 = 1 : Drive strength is 100%
+ *
+ * 00 is the default data byte value for Output Driver Register after power-up
+ */
+#define FLASH_SPI_NAND_FR_DS_ADDR 0xD0
+#define FLASH_SPI_NAND_FR_DS_DATA 0x00
+
/* NANDc registers used during BAM transfer */
#define NAND_READ_LOCATION_n(n) (NAND_REG(0xF20) + 4 * (n))
+#define NAND_READ_LOCATION_LAST_CW_n(n) (NAND_REG(0xF40) + 4 * (n))
#define NAND_RD_LOC_LAST_BIT(x) ((x) << 31)
#define NAND_RD_LOC_SIZE(x) ((x) << 16)
#define NAND_RD_LOC_OFFSET(x) ((x) << 0)
@@ -151,6 +340,23 @@
#define NAND_CMD_BLOCK_ERASE 0x3A
#define NAND_CMD_FETCH_ID 0x0B
#define NAND_CMD_RESET_DEVICE 0x0D
+#define NAND_CMD_SET_FEATURE 0x1F
+#define NAND_CMD_GET_FEATURE 0x0F
+#define NAND_CMD_ACC_FEATURE 0x0E
+/* Serial NAND Device command */
+#define SERIAL_NAND_CMD_READ_FROM_CACHE_X4 0x6B
+#define SERIAL_NAND_CMD_READ_FROM_CACHE_DUAL_IO 0xBB
+#define SERIAL_NAND_CMD_READ_FROM_CACHE_QUAD_IO 0xEB
+#define SERIAL_NAND_CMD_READ_ID 0x9F
+#define SERIAL_NAND_CMD_PROGRAM_LOAD 0x02
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_X4 0x32
+#define SERIAL_NAND_CMD_PROGRAM_EXECUTE 0x10
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_RND_DATA 0x84
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_RND_DATA_X4 0xC4 /* Or 0x34 */
+#define SERIAL_NAND_CMD_PROGRAM_LOAD_QUAD_IO 0x72
+#define SERIAL_NAND_CMD_BLOCK_ERASE 0xD8
+#define SERIAL_NAND_CMD_RESET 0xFF
+
/* NAND Status errors */
#define NAND_FLASH_MPU_ERR (1 << 8)
#define NAND_FLASH_TIMEOUT_ERR (1 << 6)
@@ -170,6 +376,7 @@
#define DATA_CONSUMER_PIPE_INDEX 0
#define DATA_PRODUCER_PIPE_INDEX 1
#define CMD_PIPE_INDEX 2
+#define BAM_STATUS_PIPE_INDEX 3
/* Define BAM pipe lock groups for NANDc*/
#define P_LOCK_GROUP_0 0
@@ -238,11 +445,13 @@
#define DATA_CONSUMER_PIPE 0
#define DATA_PRODUCER_PIPE 1
#define CMD_PIPE 2
+#define NAND_BAM_STATUS_PIPE 3
/* NANDc BAM pipe groups */
#define DATA_PRODUCER_PIPE_GRP 0
#define DATA_CONSUMER_PIPE_GRP 0
#define CMD_PIPE_GRP 1
+#define NAND_BAM_STATUS_PIPE_GRP 2
/* NANDc EE */
#define QPIC_NAND_EE 0
@@ -252,6 +461,7 @@
/* Register: NAND_CTRL */
#define BAM_MODE_EN 0x1
+#define NANDC_READ_DELAY_COUNTER_VAL 0x340
/* Register: NAND_DEBUG */
#define BAM_MODE_BIT_RESET (1 << 31)
@@ -277,6 +487,7 @@
#define QPIC_BAM_DATA_FIFO_SIZE 64
#define QPIC_BAM_CMD_FIFO_SIZE 64
+#define QPIC_BAM_STATUS_FIFO_SIZE 64
#define QPIC_MAX_ONFI_MODES 4
#define QPIC_NUM_XFER_STEPS 7
@@ -284,7 +495,7 @@
enum qpic_verion{
QCA_QPIC_V1_4_20,
QCA_QPIC_V1_5_20,
-
+ QCA_QPIC_V2_1_1,
};
@@ -311,6 +522,28 @@
NAND_CFG,
};
+/* Structure for Serial nand parameter */
+struct qpic_serial_nand_params {
+ u8 id[4];
+ u16 page_size;
+ u16 pgs_per_blk;
+ u32 spare_size;
+ u32 erase_blk_size;
+ u16 no_of_blocks;
+ u32 density;
+ u32 otp_region;
+ u8 no_of_addr_cycle;
+ u8 no_of_dies;
+ u8 num_bits_ecc_correctability;
+ u8 timing_mode_support;
+ bool quad_mode;
+ bool check_quad_config;
+ int prev_die_id;
+ u8 protec_bpx;
+ u64 pages_per_die;
+ const char *name;
+};
+
struct onfi_param_page
{
uint32_t signature;
@@ -396,9 +629,15 @@
unsigned read_pipe;
unsigned write_pipe;
unsigned cmd_pipe;
+#if defined(QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+ unsigned status_pipe;
+#endif
uint8_t read_pipe_grp;
uint8_t write_pipe_grp;
uint8_t cmd_pipe_grp;
+#if defined(QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+ uint8_t status_pipe_grp;
+#endif
};
/* Structure to define the initial nand config */
@@ -442,6 +681,10 @@
uint32_t cfg0_raw;
uint32_t cfg1_raw;
uint32_t ecc_bch_cfg;
+#ifdef CONFIG_QPIC_SERIAL
+ bool quad_mode;
+ bool check_quad_config;
+#endif
unsigned oob_per_page;
unsigned char *buffers;
unsigned char *pad_dat;
diff --git a/board/qca/arm/common/crashdump.c b/board/qca/arm/common/crashdump.c
index ca7598f..22ede22 100644
--- a/board/qca/arm/common/crashdump.c
+++ b/board/qca/arm/common/crashdump.c
@@ -404,7 +404,7 @@
static int do_dumpqca_data(unsigned int dump_level)
{
- uint32_t memaddr;
+ uint32_t memaddr, comp_addr = 0x0;
uint32_t remaining;
int indx;
int ebi_indx = 0;
@@ -412,8 +412,8 @@
char buf = 1;
struct dumpinfo_t *dumpinfo = dumpinfo_n;
int dump_entries = dump_entries_n;
- char wlan_segment_name[32];
- char *usb_dump = NULL;
+ char wlan_segment_name[32], runcmd[128], *s;
+ char *usb_dump = NULL, *compress = NULL;
ulong is_usb_dump = 0;
usb_dump = getenv("dump_to_usb");
@@ -507,7 +507,6 @@
for (indx = 0; indx < dump_entries; indx++) {
if (dump_level != dumpinfo[indx].dump_level)
continue;
- printf("\nProcessing %s:", dumpinfo[indx].name);
if (dumpinfo[indx].is_redirected) {
memaddr = *((uint32_t *)(dumpinfo[indx].start));
@@ -525,17 +524,57 @@
if (!strncmp(dumpinfo[indx].name, "EBICS", strlen("EBICS")))
{
- if (!strncmp(dumpinfo[indx].name,
- "EBICS0", strlen("EBICS0")))
- dumpinfo[indx].size = gd->ram_size;
+ compress = getenv("dump_compressed");
+ if (compress) {
+ if (!strncmp(dumpinfo[indx].name, "EBICS2", strlen("EBICS2"))) {
+ memaddr = CONFIG_SYS_SDRAM_BASE + (gd->ram_size / 2);
+ dumpinfo[indx].size = gd->ram_size / 2;
+ comp_addr = memaddr;
+ }
+ if (!strncmp(dumpinfo[indx].name, "EBICS_S2", strlen("EBICS_S2"))) {
+ dumpinfo[indx].size = gd->ram_size - (dumpinfo[indx].start - CONFIG_SYS_SDRAM_BASE);
+ comp_addr = memaddr;
+ }
+ if (!strncmp(dumpinfo[indx].name, "EBICS1", strlen("EBICS1"))) {
+ dumpinfo[indx].size = (gd->ram_size / 2)
+ - (dumpinfo[indx + 1].size + 0x400000);
+ }
+ }
+ else {
+ if (!strncmp(dumpinfo[indx].name,
+ "EBICS0", strlen("EBICS0")))
+ dumpinfo[indx].size = gd->ram_size;
- if (!strncmp(dumpinfo[indx].name,
- "EBICS_S1", strlen("EBICS_S1")))
- dumpinfo[indx].size = gd->ram_size
- - dumpinfo[indx - 1].size
- - CONFIG_TZ_SIZE;
+ if (!strncmp(dumpinfo[indx].name,
+ "EBICS_S1", strlen("EBICS_S1")))
+ dumpinfo[indx].size = gd->ram_size
+ - dumpinfo[indx - 1].size
+ - CONFIG_TZ_SIZE;
+ }
- if (is_usb_dump == 1) {
+ if (compress && (dumpinfo[indx].to_compress == 1)) {
+
+ snprintf(runcmd, sizeof(runcmd), "zip 0x%x 0x%x 0x%x", memaddr, dumpinfo[indx].size, comp_addr);
+ if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
+ printf("gzip compression of %s failed\n", dumpinfo[indx].name);
+ else {
+ s = getenv("filesize");
+ dumpinfo[indx].size = (int)simple_strtol(s, NULL, 16); //compressed_file_size
+ memaddr = comp_addr;
+ snprintf(dumpinfo[indx].name, sizeof(dumpinfo[indx].name), "%s.gz", dumpinfo[indx].name);
+ }
+ }
+
+#ifdef CONFIG_IPQ40XX
+ if (buf != 1)
+#endif
+ if ((compress && (dumpinfo[indx].to_compress != 1)) ||
+ (!compress && (dumpinfo[indx].to_compress == 1))) {
+ continue;
+ }
+
+ printf("\nProcessing %s:\n", dumpinfo[indx].name);
+ if (is_usb_dump == 1 || compress) {
ret = dump_to_dst (dumpinfo[indx].is_aligned_access, memaddr, dumpinfo[indx].size, dumpinfo[indx].name);
if (ret == CMD_RET_FAILURE) {
goto stop_dump;
@@ -552,6 +591,7 @@
else {
dumpinfo[indx].size = remaining;
}
+
ret = dump_to_dst (dumpinfo[indx].is_aligned_access, memaddr, dumpinfo[indx].size, dumpinfo[indx].name);
if (ret == CMD_RET_FAILURE)
goto stop_dump;
@@ -564,6 +604,7 @@
}
else
{
+ printf("\nProcessing %s:\n", dumpinfo[indx].name);
if (dumpinfo[indx].dump_level == MINIMAL_DUMP )
memaddr = dump_minimal(dumpinfo, indx);
if (dumpinfo[indx].size && memaddr) {
diff --git a/board/qca/arm/ipq40xx/ipq40xx.c b/board/qca/arm/ipq40xx/ipq40xx.c
index a8cd2dd..5ac247d 100644
--- a/board/qca/arm/ipq40xx/ipq40xx.c
+++ b/board/qca/arm/ipq40xx/ipq40xx.c
@@ -77,6 +77,9 @@
struct dumpinfo_t dumpinfo_n[] = {
{ "EBICS0.BIN", 0x80000000, 0x10000000, 0 },
+ { "EBICS2.BIN", 0xA0000000, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS0.BIN", 0x80000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
};
int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
diff --git a/board/qca/arm/ipq5018/ipq5018.c b/board/qca/arm/ipq5018/ipq5018.c
index 90d4ce3..307aab6 100644
--- a/board/qca/arm/ipq5018/ipq5018.c
+++ b/board/qca/arm/ipq5018/ipq5018.c
@@ -26,6 +26,7 @@
#include <mmc.h>
#include <sdhci.h>
+#define DLOAD_MAGIC_COOKIE 0x10
DECLARE_GLOBAL_DATA_PTR;
struct sdhci_host mmc_host;
extern int ipq_spi_init(u16);
@@ -287,11 +288,51 @@
void reset_crashdump(void)
{
+ unsigned int ret = 0;
+ qca_scm_sdi();
+ ret = qca_scm_dload(CLEAR_MAGIC);
+ if (ret)
+ printf ("Error in reseting the Magic cookie\n");
return;
}
+void psci_sys_reset(void)
+{
+ __invoke_psci_fn_smc(0x84000009, 0, 0, 0);
+}
+
+void qti_scm_pshold(void)
+{
+ int ret;
+
+ ret = scm_call(SCM_SVC_BOOT, SCM_CMD_TZ_PSHOLD, NULL, 0, NULL, 0);
+
+ if (ret != 0)
+ writel(0, GCNT_PSHOLD);
+}
+
+void reset_cpu(unsigned long a)
+{
+ reset_crashdump();
+ if (is_scm_armv8()) {
+ psci_sys_reset();
+ } else {
+ qti_scm_pshold();
+ }
+ while(1);
+}
+
+void qpic_clk_enbale(void)
+{
+ writel(QPIC_CBCR_VAL, GCC_QPIC_CBCR_ADDR);
+ writel(0x1, GCC_QPIC_AHB_CBCR_ADDR);
+ writel(0x1, GCC_QPIC_IO_MACRO_CBCR);
+}
+
void board_nand_init(void)
{
+ qpic_nand_init();
+
#ifdef CONFIG_QCA_SPI
int gpio_node;
gpio_node = fdt_path_offset(gd->fdt_blob, "/spi/spi_gpio");
@@ -327,7 +368,3 @@
return 0;
}
-void reset_cpu(unsigned long a)
-{
- while(1);
-}
diff --git a/board/qca/arm/ipq5018/ipq5018.h b/board/qca/arm/ipq5018/ipq5018.h
index a220312..0bb6fa5 100644
--- a/board/qca/arm/ipq5018/ipq5018.h
+++ b/board/qca/arm/ipq5018/ipq5018.h
@@ -35,6 +35,15 @@
#define GCC_SDCC1_AHB_CBCR 0x0184201C
#define GCC_SDCC1_MISC 0x01842020
+/*
+ * GCC-QPIC Registers
+ */
+#define GCC_QPIC_IO_MACRO_CBCR 0x0185701C
+#define GCC_QPIC_CBCR_ADDR 0x01857020
+#define GCC_QPIC_AHB_CBCR_ADDR 0x01857024
+#define GCC_QPIC_SLEEP_CBCR 0x01857028
+#define QPIC_CBCR_VAL 0x80004FF1
+
/* UART 1 */
#define GCC_BLSP1_UART1_BCR 0x01802038
#define GCC_BLSP1_UART1_APPS_CBCR 0x0180203C
@@ -77,6 +86,15 @@
#define KERNEL_AUTH_CMD 0x13
#define SCM_CMD_SEC_AUTH 0x1F
+#define ARM_PSCI_TZ_FN_BASE 0x84000000
+#define ARM_PSCI_TZ_FN(n) (ARM_PSCI_TZ_FN_BASE + (n))
+
+#define ARM_PSCI_TZ_FN_CPU_OFF ARM_PSCI_TZ_FN(2)
+#define ARM_PSCI_TZ_FN_CPU_ON ARM_PSCI_TZ_FN(3)
+#define ARM_PSCI_TZ_FN_AFFINITY_INFO ARM_PSCI_TZ_FN(4)
+
+unsigned int __invoke_psci_fn_smc(unsigned int, unsigned int,
+ unsigned int, unsigned int);
struct smem_ram_ptn {
char name[16];
unsigned long long start;
@@ -118,6 +136,7 @@
int smem_ram_ptable_init(struct smem_ram_ptable *smem_ram_ptable);
void reset_crashdump(void);
void reset_board(void);
+void qpic_clk_enbale(void);
typedef enum {
SMEM_SPINLOCK_ARRAY = 7,
diff --git a/board/qca/arm/ipq6018/ipq6018.c b/board/qca/arm/ipq6018/ipq6018.c
index 964dafa..559a9ba 100644
--- a/board/qca/arm/ipq6018/ipq6018.c
+++ b/board/qca/arm/ipq6018/ipq6018.c
@@ -57,7 +57,20 @@
* | |
* ------------------------
*/
+
+ /* Compressed EBICS dump follows descending order
+ * to use in-memory compression for which destination
+ * for compression will be address of EBICS2.BIN
+ *
+ * EBICS2 - (ddr size / 2) [to] end of ddr
+ * EBICS1 - uboot end addr [to] (ddr size / 2)
+ * EBICS0 - ddr start [to] uboot start addr
+ */
+
{ "EBICS0.BIN", 0x40000000, 0x10000000, 0 },
+ { "EBICS2.BIN", 0x60000000, 0x20000000, 0, 0, 0, 0, 1 },
+ { "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
{ "CODERAM.BIN", 0x00200000, 0x00028000, 0 },
{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
@@ -71,9 +84,18 @@
};
int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
+/* Compressed dumps:
+ * EBICS_S2 - (ddr start + 256M) [to] end of ddr
+ * EBICS_S1 - uboot end addr [to] (ddr start + 256M)
+ * EBICS_S0 - ddr start [to] uboot start addr
+ */
+
struct dumpinfo_t dumpinfo_s[] = {
{ "EBICS_S0.BIN", 0x40000000, 0xA600000, 0 },
{ "EBICS_S1.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0 },
+ { "EBICS_S2.BIN", 0x50000000, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS_S1.BIN", CONFIG_UBOOT_END_ADDR, 0x5B00000, 0, 0, 0, 0, 1 },
+ { "EBICS_S0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
@@ -324,6 +346,7 @@
}
#endif
+#ifdef CONFIG_QCA_SPI
static void spi_clock_init(void)
{
int cfg;
@@ -340,6 +363,7 @@
/* Configure CBCR */
writel(CLK_ENABLE, GCC_BLSP1_QUP1_SPI_APPS_CBCR);
}
+#endif
void board_nand_init(void)
{
diff --git a/board/qca/arm/ipq806x/ipq806x.c b/board/qca/arm/ipq806x/ipq806x.c
index fadf7af..bec1e1a 100644
--- a/board/qca/arm/ipq806x/ipq806x.c
+++ b/board/qca/arm/ipq806x/ipq806x.c
@@ -75,7 +75,10 @@
{ "WLAN_FW.BIN", 0x41400000, 0x000FFF80, 0 },
{ "WLAN_FW_900B.BIN", 0x44000000, 0x00600000, 0 },
{ "EBICS0.BIN", 0x40000000, 0x20000000, 0 },
- { "EBI1CS1.BIN", 0x60000000, 0x20000000, 0 }
+ { "EBI1CS1.BIN", 0x60000000, 0x20000000, 0 },
+ { "EBICS2.BIN", 0x60000000, 0x20000000, 0, 0, 0, 0, 1 },
+ { "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 }
};
int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
@@ -105,7 +108,10 @@
{ "WLAN_FW.BIN", 0x41400000, 0x000FFF80, 0 },
{ "WLAN_FW_900B.BIN", 0x44000000, 0x00600000, 0 },
{ "EBICS0.BIN", 0x40000000, 0x20000000, 0 },
- { "EBI1CS1.BIN", 0x60000000, 0x20000000, 0 }
+ { "EBI1CS1.BIN", 0x60000000, 0x20000000, 0 },
+ { "EBICS2.BIN", 0x60000000, 0x20000000, 0, 0, 0, 0, 1 },
+ { "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 }
};
int dump_entries_s = ARRAY_SIZE(dumpinfo_s);
diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c
index 4934641..03fa539 100644
--- a/board/qca/arm/ipq807x/ipq807x.c
+++ b/board/qca/arm/ipq807x/ipq807x.c
@@ -109,7 +109,15 @@
* | PMIC dump (8k) |
* ------------------------
*/
+
+ /* Compressed EBICS dump follows descending order
+ * to use in-memory compression for which destination
+ * for compression will be address of EBICS2.BIN
+ */
{ "EBICS0.BIN", 0x40000000, 0x10000000, 0 },
+ { "EBICS2.BIN", 0x60000000, 0x20000000, 0, 0, 0, 0, 1 },
+ { "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
{ "CODERAM.BIN", 0x00200000, 0x00028000, 0 },
{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
@@ -126,6 +134,9 @@
struct dumpinfo_t dumpinfo_s[] = {
{ "EBICS_S0.BIN", 0x40000000, 0xAC00000, 0 },
{ "EBICS_S1.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0 },
+ { "EBICS_S2.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
+ { "EBICS_S1.BIN", CONFIG_UBOOT_END_ADDR, 0x200000, 0, 0, 0, 0, 1 },
+ { "EBICS_S0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
diff --git a/drivers/mtd/nand/qpic_nand.c b/drivers/mtd/nand/qpic_nand.c
index 7ba7a42..f1104db 100644
--- a/drivers/mtd/nand/qpic_nand.c
+++ b/drivers/mtd/nand/qpic_nand.c
@@ -48,6 +48,78 @@
static uint32_t hw_ver;
+#ifdef CONFIG_QPIC_SERIAL
+static struct qpic_serial_nand_params qpic_serial_nand_tbl[] = {
+ {
+ .id = { 0xc8, 0xc1 },
+ .page_size = 2048,
+ .erase_blk_size = 0x00020000,
+ .pgs_per_blk = 64,
+ .no_of_blocks = 1024,
+ .spare_size = 128,
+ .density = 0x08000000,
+ .otp_region = 0x2000,
+ .no_of_addr_cycle = 0x3,
+ .num_bits_ecc_correctability = 8,
+ .timing_mode_support = 0,
+ .quad_mode = true,
+ .check_quad_config = true,
+ .name = "GD5F1GQ4RE9IG",
+ },
+ {
+ .id = { 0xc8, 0xc9 },
+ .page_size = 2048,
+ .erase_blk_size = 0x00020000,
+ .pgs_per_blk = 64,
+ .no_of_blocks = 1024,
+ .spare_size = 64,
+ .density = 0x08000000,
+ .otp_region = 0x2000,
+ .no_of_addr_cycle = 0x3,
+ .num_bits_ecc_correctability = 4,
+ .timing_mode_support = 0,
+ .quad_mode = true,
+ .check_quad_config = true,
+ .name = "GD5F1GQ4RE9IH",
+ },
+ {
+ .id = { 0xc8, 0x22 },
+ .page_size = 2048,
+ .erase_blk_size = 0x00020000,
+ .pgs_per_blk = 64,
+ .no_of_blocks = 2048,
+ .spare_size = 64,
+ .density = 0x10000000,
+ .otp_region = 0x2000,
+ .no_of_addr_cycle = 0x3,
+ .num_bits_ecc_correctability = 4,
+ .timing_mode_support = 0,
+ .quad_mode = true,
+ .check_quad_config = true,
+ .name = "GD5F2GQ5REYIH",
+ },
+ {
+ .id = { 0x2c, 0x15 },
+ .page_size = 2048,
+ .erase_blk_size = 0x00020000,
+ .pgs_per_blk = 64,
+ .no_of_blocks = 1024,
+ .spare_size = 128,
+ .density = 0x08000000,
+ .otp_region = 0x5000,
+ .no_of_addr_cycle = 0x3,
+ .num_bits_ecc_correctability = 8,
+ .timing_mode_support = 0,
+ .quad_mode = true,
+ .check_quad_config = false,
+ .name = "MT29F1G01ABBFDWB-IT",
+ },
+};
+struct qpic_serial_nand_params *serial_params;
+#define MICRON_DEVICE_ID 0x152c152c
+#define CMD3_MASK 0xfff0ffff
+#endif
+
struct cmd_element ce_array[100]
__attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
struct cmd_element ce_read_array[20]
@@ -57,6 +129,8 @@
__attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
struct bam_desc qpic_data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE]
__attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+struct bam_desc qpic_status_desc_fifo[QPIC_BAM_STATUS_FIFO_SIZE]
+ __attribute__ ((aligned(CONFIG_SYS_CACHELINE_SIZE)));
static struct bam_instance bam;
struct nand_ecclayout fake_ecc_layout;
@@ -77,16 +151,24 @@
static const struct udevice_id qpic_ver_ids[] = {
{ .compatible = "qcom,qpic-nand.1.4.20", .data = QCA_QPIC_V1_4_20 },
{ .compatible = "qcom,qpic-nand.1.5.20", .data = QCA_QPIC_V1_5_20 },
+ { .compatible = "qcom,qpic-nand-v2.1.1", .data = QCA_QPIC_V2_1_1},
{ },
};
static uint32_t
qpic_onfi_mode_to_xfer_steps[QPIC_MAX_ONFI_MODES][QPIC_NUM_XFER_STEPS] = {
+#ifdef CONFIG_QPIC_SERIAL
/* Mode 0 */
{
+ 0x00e00080, 0x49f04998, 0x8de08d80, 0xc000c000,
+ 0xc000c000, 0xc000c000, 0xc000c000,
+ },
+#else
+ {
0x04e00480, 0x59f05998, 0x89e08980, 0xd000d000,
0xc000c000, 0xc000c000, 0xc000c000,
},
+#endif
/* Mode 1 */
{
0x00e00080, 0x49f04d99, 0x85e08580, 0xd000d000,
@@ -254,17 +336,20 @@
uint32_t flash_cmd = NAND_CMD_FETCH_ID;
uint32_t exec_cmd = 1;
int nand_ret = NANDC_RESULT_SUCCESS;
- uint32_t vld;
+ uint32_t vld = NAND_CMD_VALID_BASE;
uint32_t cmd_vld = NAND_DEV_CMD_VLD_V1_4_20;
+#ifdef CONFIG_QPIC_SERIAL
+ flash_cmd |= QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET |
+ QPIC_SPI_TRANSFER_MODE_X1;
+ vld = FLASH_DEV_CMD_VLD;
+#endif
/* Issue the Fetch id command to the NANDc */
bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd,
- CE_WRITE_TYPE);
+ CE_WRITE_TYPE);
cmd_list_ptr++;
- vld = NAND_CMD_VALID_BASE;
-
- if (hw_ver == QCA_QPIC_V1_5_20)
+ if (hw_ver == QCA_QPIC_V1_5_20 || hw_ver == QCA_QPIC_V2_1_1)
cmd_vld = NAND_DEV_CMD_VLD_V1_5_20;
bam_add_cmd_element(cmd_list_ptr, cmd_vld, (uint32_t)vld,
@@ -288,9 +373,6 @@
num_desc++;
qpic_nand_wait_for_cmd_exec(num_desc);
- cmd_list_ptr_start = ce_array;
- cmd_list_ptr = ce_array;
-
/* Read the status register */
status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
@@ -349,7 +431,15 @@
bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
bam.pipe[CMD_PIPE_INDEX].fifo.head = qpic_cmd_desc_fifo;
bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
-
+#if defined(CONFIG_QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+ /* Set Status pipe params. */
+ bam.pipe[BAM_STATUS_PIPE_INDEX].pipe_num = config->pipes.status_pipe;
+ /* System consumer */
+ bam.pipe[BAM_STATUS_PIPE_INDEX].trans_type = BAM2SYS;
+ bam.pipe[BAM_STATUS_PIPE_INDEX].fifo.size = QPIC_BAM_STATUS_FIFO_SIZE;
+ bam.pipe[BAM_STATUS_PIPE_INDEX].fifo.head = qpic_status_desc_fifo;
+ bam.pipe[BAM_STATUS_PIPE_INDEX].lock_grp = config->pipes.status_pipe_grp;
+#endif
/* Programs the threshold for BAM transfer
* When this threshold is reached, BAM signals the peripheral via the
* pipe_bytes_available interface.
@@ -408,15 +498,32 @@
bam_ret = NANDC_RESULT_FAILURE;
goto qpic_nand_bam_init_error;
}
+#if defined(CONFIG_QPIC_SERIAL) && defined(MULTI_PAGE_READ)
+ /* Initialize BAM QPIC status pipe */
+ bam_sys_pipe_init(&bam, BAM_STATUS_PIPE_INDEX);
+ /* Init status fifo */
+ bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[BAM_STATUS_PIPE_INDEX].pipe_num);
+
+ if (bam_ret) {
+ printf("QPIC:NANDc BAM STATUS FIFO init error\n");
+ bam_ret = NANDC_RESULT_FAILURE;
+ goto qpic_nand_bam_init_error;
+ }
+#endif
/*
* Once BAM_MODE_EN bit is set then QPIC_NAND_CTRL register
* should be written with BAM instead of writel.
* Check if BAM_MODE_EN is already set by bootloader and write only
* if this bit is not set.
*/
- if (!(readl(QPIC_NAND_CTRL) & BAM_MODE_EN))
- writel(BAM_MODE_EN, QPIC_NAND_CTRL);
+ if (!(readl(QPIC_NAND_CTRL) & BAM_MODE_EN)) {
+#ifdef CONFIG_QPIC_SERIAL
+ writel(BAM_MODE_EN | NANDC_READ_DELAY_COUNTER_VAL, QPIC_NAND_CTRL);
+#else
+ writel(BAM_MODE_EN , QPIC_NAND_CTRL);
+#endif
+ }
qpic_nand_bam_init_error:
return bam_ret;
@@ -580,6 +687,7 @@
qpic_nand_wait_for_cmd_exec(1);
}
+#ifndef CONFIG_QPIC_SERIAL
static void
qpic_config_timing_parameters(struct mtd_info *mtd)
{
@@ -605,6 +713,40 @@
writel(qpic_onfi_mode_to_xfer_steps[timing_mode][i],
xfer_start + 4 * i);
}
+#endif
+
+#ifdef CONFIG_QPIC_SERIAL
+static void qpic_serial_update_dev_params(struct mtd_info *mtd)
+{
+ struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
+ uint32_t ecc_bits;
+
+ dev->page_size = serial_params->page_size;
+ mtd->writesize = dev->page_size;
+ dev->block_size = serial_params->pgs_per_blk * (dev->page_size);
+ mtd->erasesize = dev->block_size;
+ dev->num_blocks = serial_params->no_of_blocks;
+ dev->widebus = 0x0;
+ dev->density = serial_params->no_of_blocks * (dev->block_size);
+ mtd->size = dev->density;
+ dev->spare_size = serial_params->spare_size;
+ mtd->oobsize = dev->spare_size;
+ ecc_bits = serial_params->num_bits_ecc_correctability;
+ dev->num_pages_per_blk = serial_params->pgs_per_blk;
+ dev->num_pages_per_blk_mask = serial_params->pgs_per_blk - 1;
+ dev->timing_mode_support = serial_params->timing_mode_support;
+ dev->quad_mode = serial_params->quad_mode;
+ dev->check_quad_config = serial_params->check_quad_config;
+
+ if (ecc_bits >= 8)
+ mtd->ecc_strength = 8;
+ else
+ mtd->ecc_strength = 4;
+ printf("Serial NAND device Manufature:%s\n",serial_params->name);
+ printf("Device Size:%d MiB, Page size:%d, Spare Size:%d\n",
+ (int)(dev->density >> 20), dev->page_size, mtd->oobsize);
+}
+#endif
static int
qpic_nand_onfi_save_params(struct mtd_info *mtd,
@@ -651,6 +793,10 @@
struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
struct nand_chip *chip = MTD_NAND_CHIP(mtd);
uint32_t qpic_oob_size;
+ uint32_t no_of_address_cycle = 5;
+ uint32_t disable_status_after_write = 0;
+ uint32_t recovery_cycle = 7;
+ uint32_t wr_rd_busy_gap = 2;
/* Save Configurations */
dev->cws_per_page = dev->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
@@ -719,37 +865,41 @@
*/
dev->bad_blk_loc = dev->page_size - dev->cw_size *
(dev->cws_per_page - 1) + 1;
-
+#ifdef CONFIG_QPIC_SERIAL
+ no_of_address_cycle = 3;
+ disable_status_after_write = 1;
+ recovery_cycle = 0;
+ wr_rd_busy_gap = 20;
+#endif
dev->cfg0 |= ((dev->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
|(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
- |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
- |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
+ |(no_of_address_cycle << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
+ |(disable_status_after_write << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
- dev->cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
+ dev->cfg1 |= (recovery_cycle << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
|(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
|(dev->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
|(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
- |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
+ |(wr_rd_busy_gap << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
|(dev->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
dev->cfg0_raw = ((dev->cws_per_page- 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
- |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
+ |(no_of_address_cycle << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
|(dev->cw_size << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) //figure out the size of cw
- | (1 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
+ | (disable_status_after_write << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
- dev->cfg1_raw = (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
+ dev->cfg1_raw = (recovery_cycle << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
| (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
| (17 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
| (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
- | (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
+ | (wr_rd_busy_gap << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
| (dev->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
| 1 ; /* to disable reed solomon ecc..this feild is now read only. */
dev->ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
- | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
- | (DATA_BYTES_IN_IMG_PER_CW <<
- NAND_DEV0_ECC_NUM_DATA_BYTES)
- | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
+ | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
+ | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
+ | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
/*
* Safe to use a single instance global variable,
@@ -764,6 +914,331 @@
return 0;
}
+#ifdef CONFIG_QPIC_SERIAL
+static int qpic_serial_get_feature(struct mtd_info *mtd, uint32_t ftr_addr)
+{
+ struct cmd_element *cmd_list_ptr = ce_array;
+ struct cmd_element *cmd_list_ptr_start = ce_array;
+ uint8_t num_desc = 0;
+ uint32_t status, nand_ret;
+ uint32_t exec_cmd = 1;
+
+ uint32_t cmd_val = (QPIC_SPI_TRANSFER_MODE_X1 | QPIC_SPI_HOLD_SET |
+ QPIC_SPI_WP_SET | NAND_CMD_ACC_FEATURE);
+
+ /* Set the feature address to NAND_ADDR0 register */
+ bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, ftr_addr,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* Set the value 0x0 to NAND_ADDR1 register */
+ bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, 0,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* First Clear the feature register to get the fresh feature value */
+ bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_FEATURES, 0,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* cmd_val = 0x3800000E
+ * bit-31 is clear means set feature
+ * bit-30-29 means x1 mode
+ * bit-28 is set , this is for wp pin
+ * wp# pin should be set to high then only we can get the feature
+ * bit-27 SPI_HOLD : this pin also should be high
+ */
+ bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, cmd_val,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* Execute the cmd */
+ bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, exec_cmd,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* Prepare the cmd desc for the above commands */
+ bam_add_one_desc(&bam, CMD_PIPE_INDEX,
+ (unsigned char *)cmd_list_ptr_start,
+ ((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
+ BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG |
+ BAM_DESC_INT_FLAG);
+
+ /* Keep track of the number of desc added. */
+ num_desc++;
+
+ qpic_nand_wait_for_cmd_exec(num_desc);
+
+ status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
+
+ /* Check for errors */
+ nand_ret = qpic_nand_check_status(mtd, status);
+ if (nand_ret) {
+ printf("%s : CMD status failed\n", __func__);
+ goto err;
+ }
+ /* read the feature register value and update in feature
+ * Feature value will get updated in [15:8]
+ */
+ nand_ret = qpic_nand_read_reg(NAND_FLASH_FEATURES, 0);
+#ifdef QPIC_DEBUG_SERIAL
+ printf("NAND Feature Register Addr:0x%02x and Val:0x%08x\n",
+ ftr_addr,nand_ret);
+#endif
+err:
+ return nand_ret;
+
+}
+
+static int qpic_serial_set_feature(struct mtd_info *mtd, uint32_t ftr_addr,
+ uint32_t ftr_val)
+{
+ struct cmd_element *cmd_list_ptr = ce_array;
+ struct cmd_element *cmd_list_ptr_start = ce_array;
+ uint8_t num_desc = 0;
+ uint32_t status, nand_ret;
+
+ uint32_t cmd_val = (QPIC_SPI_SET_FEATURE | QPIC_SPI_WP_SET |
+ QPIC_SPI_HOLD_SET | QPIC_SPI_TRANSFER_MODE_X1 |
+ NAND_CMD_ACC_FEATURE);
+
+ uint32_t exec_cmd = 1;
+
+ /* set the feature value to NAND_FLASH_FEATURES feature register */
+ bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_FEATURES, ftr_val,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* Set the feature address to NAND_ADDR0 register */
+ bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, ftr_addr,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* Set the value 0x0 to NAND_ADDR1 register */
+ bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, 0,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* cmd_val = 0xB800000E
+ * bit-31 is set means set feature
+ * bit-30-29 means x1 mode
+ * bit-28 is set , this is for wp pin
+ * wp# pin should be set to high then only we can set the feature
+ * bit-27 SPI_HOLD : this pin also should be high
+ */
+ bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, cmd_val,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* Execute the cmd */
+ bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, exec_cmd,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ /* Prepare the cmd desc for the above commands */
+ bam_add_one_desc(&bam, CMD_PIPE_INDEX,
+ (unsigned char *)cmd_list_ptr_start,
+ ((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
+ BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG |
+ BAM_DESC_INT_FLAG);
+
+ /* Keep track of the number of desc added. */
+ num_desc++;
+
+ qpic_nand_wait_for_cmd_exec(num_desc);
+
+ status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
+
+ /* Check for errors */
+ nand_ret = qpic_nand_check_status(mtd, status);
+ if (nand_ret) {
+ printf("%s : CMD status failed\n", __func__);
+ goto err;
+ }
+err:
+ return nand_ret;
+}
+
+static int qpic_nand_read_id_serial(struct mtd_info *mtd)
+{
+ uint32_t nand_ret;
+ uint32_t serial_dev_id[2] = {0x0};
+ int i;
+ struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
+
+ nand_ret = qpic_nand_fetch_id(mtd);
+ if (!nand_ret) {
+
+ serial_dev_id[0] = dev->id & 0x000000ff;
+ serial_dev_id[1] = (dev->id >> 8) & 0x000000ff;
+
+ for (i = 0; i < ARRAY_SIZE(qpic_serial_nand_tbl); i++) {
+ serial_params = &qpic_serial_nand_tbl[i];
+ if ((serial_params->id[0] == serial_dev_id[0]) &&
+ (serial_params->id[1] == serial_dev_id[1])) {
+ printf("Serial Nand Device Found With ID : 0x%02x 0x%02x\n",
+ serial_dev_id[0],serial_dev_id[1]);
+
+ /* Upadate device paramter as per device table */
+ qpic_serial_update_dev_params(mtd);
+
+ return nand_ret;
+ }
+ }
+ if (i == ARRAY_SIZE(qpic_serial_nand_tbl)) {
+ printf("%s : No serial Nand device found in table.\n",
+ __func__);
+ return -QPIC_SERIAL_ERROR;
+ }
+ } else {
+ printf("%s : Error in featching id from device\n",__func__);
+ goto id_err;
+ }
+id_err:
+ return nand_ret;
+}
+
+int qpic_spi_nand_config(struct mtd_info *mtd)
+{
+ uint32_t status = 0x0;
+ struct qpic_nand_dev *dev = MTD_QPIC_NAND_DEV(mtd);
+ uint32_t cmd3_val = NAND_FLASH_DEV_CMD3_VAL;
+ /* For micron device the READ_CACHE_SEQ command is different than
+ * Giga device. for Giga 0x31 and for Micron 0x30.
+ * so based on id update the command configuration register
+ * CMD3.
+ */
+ if (dev->id == MICRON_DEVICE_ID) {
+ cmd3_val = (NAND_FLASH_DEV_CMD3_VAL & CMD3_MASK);
+ writel(cmd3_val, SPI_NAND_DEV_CMD3);
+ }
+ /* Get the block protection status*/
+ status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_BLK_PROCT_ADDR);
+ if (status < 0) {
+ printf("%s : Error in getting feature.\n",__func__);
+ return status;
+ }
+
+ if ((status >> 8) & FLASH_SPI_NAND_BLK_PROCT_ENABLE) {
+ printf("%s: Block protection is enabled\n",__func__);
+ printf("%s: Issuing set feature command to disable it.\n",__func__);
+
+ status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_BLK_PROCT_ADDR,
+ FLASH_SPI_NAND_BLK_PROCT_DISABLE);
+ if (status < 0) {
+ printf("%s : Error in disabling block protection.\n",__func__);
+ return status;
+ }
+ /* After disabling the block protection again read the status
+ * i.e again call the get feature command to get the status
+ */
+ status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_BLK_PROCT_ADDR);
+ if (status < 0) {
+ printf("%s : Error in getting feature.\n",__func__);
+ return status;
+ }
+ if ((status >> 8) & FLASH_SPI_NAND_BLK_PROCT_ENABLE) {
+ printf("%s : block protection still enabled.We can't erase a block\n",
+ __func__);
+ return -QPIC_SERIAL_ERROR;
+ } else
+ printf("%s : Block protection Disabled.\n",__func__);
+ } else
+ printf("%s: Block protection Disabled on Power on.\n",__func__);
+
+ /* Get Internal ECC status */
+ status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR);
+ if (status < 0) {
+ printf("%s : Error in getting feature.\n",__func__);
+ return status;
+ }
+
+ if ((status >> 8) & FLASH_SPI_NAND_FR_ECC_ENABLE) {
+ printf("%s : Internal ECC enabled, disabling internal ECC\n",__func__);
+
+ status &= ~(FLASH_SPI_NAND_FR_ECC_ENABLE);
+ status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR,
+ status);
+
+ if (status < 0) {
+ printf("%s : Error in disabling internal ECC.\n",__func__);
+ return status;
+ }
+ /* again check internal ECC is disabled or not using get feature
+ * command
+ */
+ status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR);
+ if (status < 0) {
+ printf("%s : Error in getting feature.\n",__func__);
+ return status;
+ }
+
+ if ((status >> 8) & FLASH_SPI_NAND_FR_ECC_ENABLE) {
+ pr_info("%s: Failed to disabled device internal ECC\n",
+ __func__);
+ return -QPIC_SERIAL_ERROR;
+ } else
+ printf("%s : Internal ECC disabled.\n",__func__);
+ } else
+ printf("%s : Internal ECC disabled on power on.\n",__func__);
+
+ /* Enable QUAD mode if device supported. Check this condition only
+ * if dev->quad_mode = true , means device will support Quad mode
+ * else no need to check for Quad mode.
+ * For Micron device there is no quad config bit so no need to check
+ * quad config bit.
+ */
+ /* Get QUAD bit status */
+ if (!dev->check_quad_config) {
+ dev->quad_mode = true;
+ return 0;
+ }
+
+ if (dev->quad_mode) {
+
+ status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR);
+ if (status < 0) {
+ printf("%s : Error in getting feature.\n",__func__);
+ return status;
+ }
+
+ if (!((status >> 8) & FLASH_SPI_NAND_FR_QUAD_ENABLE)) {
+ printf("%s : Quad bit not enabled.\n",__func__);
+ printf("%s : Issuning set feature command to enable it.\n",
+ __func__);
+
+ /* Enable quad bit */
+ status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR,
+ FLASH_SPI_NAND_FR_QUAD_ENABLE);
+ if (status < 0) {
+ printf("%s : Error in enabling Quad bit.\n",__func__);
+ return status;
+ }
+ /* Read status again to know wether Quad bit enabled or not */
+ status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR);
+ if (status < 0) {
+ printf("%s : Error in getting feature.\n",__func__);
+ return status;
+ }
+
+ if (!((status >> 8) & FLASH_SPI_NAND_FR_QUAD_ENABLE)) {
+ printf("%s:Quad mode not enabled,so use x1 Mode.\n",
+ __func__);
+ dev->quad_mode = false;
+ return 0;
+ } else {
+ printf("%s: Quad mode enabled. using X4 mode\n",__func__);
+ return 0;
+ }
+ } else {
+ printf("%s: Quad mode enabled on Opwer on.\n",__func__);
+ return 0;
+ }
+ }
+ return 0;
+}
+#endif
+
/* Onfi probe should issue the following commands to the flash device:
* 1. Read ID - with addr ONFI_READ_ID_ADDR.
* This returns the ONFI ASCII string indicating support for ONFI.
@@ -786,6 +1261,12 @@
struct onfi_param_page *param_page;
int onfi_ret = NANDC_RESULT_SUCCESS;
+#ifdef CONFIG_QPIC_SERIAL
+ uint32_t nand_ret;
+ nand_ret = qpic_nand_read_id_serial(mtd);
+ return nand_ret;
+#endif
+
/* Allocate memory required to read the onfi param page */
buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
if (buffer == NULL) {
@@ -891,8 +1372,77 @@
return onfi_ret;
}
-static int
-qpic_nand_reset(struct mtd_info *mtd)
+#ifdef CONFIG_QPIC_SERIAL
+static void qpic_spi_init(struct mtd_info *mtd)
+{
+ uint32_t xfer_start = NAND_XFR_STEPS_V1_5_20;
+ int i;
+
+ /* Enabel QSPI CLK*/
+ qpic_clk_enbale();
+
+ /* Configure the NAND_FLASH_SPI_CFG to load the timer CLK_CNTR_INIT_VAL_VEC
+ * value, enable the LOAD_CLK_CNTR_INIT_EN bit and enable SPI_CFG mode.
+ */
+ writel(0x0, NAND_FLASH_SPI_CFG);
+
+ /* Make bit-28 of NAND_FLASH_SPI_CFG register to load
+ * CLK_CNTR_INIT_VAL_VEC into IO Macro clock generation
+ * registers is its not worked then,
+ * check with this val 0x1DB6C00D
+ */
+ writel(SPI_CFG_VAL, NAND_FLASH_SPI_CFG);
+ /*Change LOAD_CLK_CNTR_INIT_EN to generate a pulse,
+ * with CLK_CNTR_INIT_VAL_VEC loaded and SPI_CFG enabled
+ * If not worked then,
+ * Check with this val 0xDB6C00D
+ */
+ writel((SPI_CFG_VAL & ~SPI_LOAD_CLK_CNTR_INIT_EN),
+ NAND_FLASH_SPI_CFG);
+
+ /* According to HPG Setting Xfer steps and spi_num_addr_cycles
+ * is part of initialization flow before reset.However these
+ * values differ from NAND part to part.sitting in QPIC layer
+ * we won't know which NAND we don't know which NAND is connected.
+ * So we are not following HPG init sequence.Instead we reset and
+ * read id of NAND,then based on NAND ID we get Xfer steps
+ * and spi_num_addr_cycles and configure them in this function.Since
+ * Xfer steps and spi_num_addr_cycles are required for read/write/erase
+ * functionality.
+ *
+ * NOTE: For now address cycle is same for Giga devices & Micron devices
+ * so we can configure no of addess cycle here only
+ * The NAND_FLASH_XFR_STEP register also fixed for both the devices so we
+ * can configure this register here only . later change this logic as per
+ * device
+ *
+ * NOTE: The XFER register value is now fixed as HPG.
+ *
+ */
+ for (i = 0; i < QPIC_NUM_XFER_STEPS; i++)
+ writel(qpic_onfi_mode_to_xfer_steps[0][i],
+ xfer_start + 4 * i);
+
+ writel(NAND_FLASH_DEV_CMD0_VAL, SPI_NAND_DEV_CMD0);
+ writel(NAND_FLASH_DEV_CMD1_VAL, SPI_NAND_DEV_CMD1);
+ writel(NAND_FLASH_DEV_CMD2_VAL, SPI_NAND_DEV_CMD2);
+ writel(NAND_FLASH_DEV_CMD3_VAL, SPI_NAND_DEV_CMD3);
+ writel(NAND_FLASH_DEV_CMD7_VAL, SPI_NAND_DEV_CMD7);
+
+ /* NAND_DEV_CMD8 & NAND_DEV_CMD9 default value will be used for
+ * QSPI
+ */
+ writel(FLASH_DEV_CMD_VLD, NAND_FLASH_DEV_CMD_VLD);
+
+ /* No of address cycle is same for Giga device & Micron so
+ * configure no of address cycle now.
+ */
+ writel(SPI_NUM_ADDR_CYCLES, NAND_SPI_NUM_ADDR_CYCLES);
+
+ writel(SPI_BUSY_CHECK_WAIT_CNT, NAND_SPI_BUSY_CHECK_WAIT_CNT);
+}
+#endif
+static int qpic_nand_reset(struct mtd_info *mtd)
{
struct cmd_element *cmd_list_ptr = ce_array;
struct cmd_element *cmd_list_ptr_start = ce_array;
@@ -901,6 +1451,33 @@
uint32_t exec_cmd = 1;
uint32_t flash_cmd = NAND_CMD_RESET_DEVICE;
+#ifdef CONFIG_QPIC_SERIAL
+ flash_cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET | QPIC_SPI_TRANSFER_MODE_X1);
+ uint32_t cfg0 = SPI_NAND_DEVn_CFG0 & 0xff00f0;
+ uint32_t cfg1 = SPI_NAND_DEVn_CFG1_RESET;
+ uint32_t ecc_cfg = ((SPI_NAND_DEVn_ECC_CFG & 0x0f000002) | (1 << 0))
+ & ~(1 << 1);
+ /* As per HPG the reset sequence as follow
+ * NAND_DEV0_CFG0 0x005400D0 or 0x00540010
+ * NAND_DEVn_CFG1 0x087476B1
+ * NAND_DEV0_ECC_CFG 0x02000001
+ * NAND_FLASH_CMD 0x3800000D
+ * NAND_EXEC_CMD 0x00000001
+ */
+ /* write the reset sequence as per HPG */
+ bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg0,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg1,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+ bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)ecc_cfg,
+ CE_WRITE_TYPE);
+ cmd_list_ptr++;
+
+#endif
/* Issue the Reset device command to the NANDc */
bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd,
CE_WRITE_TYPE);
@@ -1002,9 +1579,13 @@
bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
(uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
cmd_list_ptr++;
-
+#ifdef CONFIG_QPIC_SERIAL
+ bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_LAST_CW_n(0),
+ (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
+#else
bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0),
(uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
+#endif
cmd_list_ptr++;
cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
@@ -1092,8 +1673,18 @@
/* Read the first page in the block. */
cwperpage = (dev->cws_per_page);
- /* Read page cmd */
params.cmd = NAND_CMD_PAGE_READ_ECC;
+
+ /* Read page cmd */
+#ifdef CONFIG_QPIC_SERIAL
+ params.cmd = NAND_CMD_PAGE_READ;
+ if (dev->quad_mode)
+ params.cmd |= QPIC_SPI_TRANSFER_MODE_X4;
+ else
+ params.cmd |= QPIC_SPI_TRANSFER_MODE_X1;
+
+ params.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
/* Clear the CW per page bits */
params.cfg0 = dev->cfg0_raw & ~(7U <<
NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
@@ -1148,16 +1739,38 @@
int num_desc = 0;
int int_flag = 0;
unsigned int i;
-
- if (cfg_mode == NAND_CFG)
- ecc = dev->ecc_bch_cfg;
+#ifdef CONFIG_QPIC_SERIAL
+ /* For Serial NAND devices the page program sequence as
+ * 02H (PROGRAM LOAD)/32H (PROGRAM LOAD x4)
+ * 06H (WRITE ENABLE)
+ * 10H (PROGRAM EXECUTE)
+ * 0FH (GET FEATURE command to read the status)
+ * No need to 0x02 & 0x32 command manually, controller
+ * automatically send this command to device. we have already mapped
+ * these command in QPIC_FLASH_DEV_CMD9 register, similar for command
+ * 0x06 & 0x0F, controller will take care internally
+ *
+ * NOTE: While initializing we have already enabeld quad bit i.e QE-bit
+ * and disable write protection so no need to check here.
+ */
+ if (dev->quad_mode)
+ cfg->cmd |= QPIC_SPI_TRANSFER_MODE_X4;
else
- ecc = 0x1; /* Disable ECC */
+ cfg->cmd |= QPIC_SPI_TRANSFER_MODE_X1;
+ cfg->cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
+
+ if (cfg_mode == NAND_CFG) {
+ ecc = dev->ecc_bch_cfg;
+ } else {
+ ecc = 0x1; /* Disable ECC */
+ }
/* Add ECC configuration */
bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
(uint32_t)ecc, CE_WRITE_TYPE);
cmd_list_ptr++;
+
cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
@@ -1775,13 +2388,26 @@
unsigned char *buffer_st, *spareaddr_st;
unsigned int max_bitflips = 0, uncorrectable_err_cws = 0;
+ /* Check This address for serial NAND later on if any issue
+ * Because as per HPG Page Read 0x13 NAND_ADDR1[7:0]
+ * NAND_ADDR0[31:24] NAND_ADDR0[23:16]
+ */
params.addr0 = page << 16;
params.addr1 = (page >> 16) & 0xff;
+
if (cfg_mode == NAND_CFG_RAW) {
params.cfg0 = dev->cfg0_raw;
params.cfg1 = dev->cfg1_raw;
params.cmd = NAND_CMD_PAGE_READ;
ecc = 0x1; /* Disable ECC */
+#ifdef CONFIG_QPIC_SERIAL
+ if (dev->quad_mode)
+ params.cmd |= QPIC_SPI_TRANSFER_MODE_X4;
+ else
+ params.cmd |= QPIC_SPI_TRANSFER_MODE_X1;
+
+ params.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
data_bytes = dev->cw_size;
oob_bytes = mtd->oobsize;
ud_bytes_in_last_cw = (dev->cw_size - mtd->oobsize);
@@ -1789,14 +2415,22 @@
params.cfg0 = dev->cfg0;
params.cfg1 = dev->cfg1;
params.cmd = NAND_CMD_PAGE_READ_ALL;
+#ifdef CONFIG_QPIC_SERIAL
+ if (dev->quad_mode)
+ params.cmd |= QPIC_SPI_TRANSFER_MODE_X4;
+ else
+ params.cmd |= QPIC_SPI_TRANSFER_MODE_X1;
+
+ params.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET);
+#endif
ecc = (dev->ecc_bch_cfg);
data_bytes = DATA_BYTES_IN_IMG_PER_CW;
ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW -
(((dev->cws_per_page) - 1) << 2);
oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
}
- params.exec = 1;
+ params.exec = 1;
/* Read all the Data bytes in the first 3 CWs. */
addr_loc_0 = NAND_RD_LOC_OFFSET(0);
addr_loc_0 |= NAND_RD_LOC_SIZE(data_bytes);;
@@ -1844,12 +2478,19 @@
cmd_list_ptr++;
if (i == (dev->cws_per_page) - 1) {
+ /* Write addr loc 1 only for the last CW. */
addr_loc_0 = NAND_RD_LOC_OFFSET(0);
addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
- /* Write addr loc 1 only for the last CW. */
+#ifdef CONFIG_QPIC_SERIAL
+ /*To read only spare bytes 80 0r 16*/
+ bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_LAST_CW_n(1),
+ (uint32_t)addr_loc_1, CE_WRITE_TYPE);
+#else
bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1),
(uint32_t)addr_loc_1, CE_WRITE_TYPE);
+#endif
+
cmd_list_ptr++;
flags = 0;
/* Add Data desc */
@@ -1877,12 +2518,23 @@
bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX,
num_data_desc);
}
- /* Write addr loc 0. */
- bam_add_cmd_element(cmd_list_ptr,
+#ifdef CONFIG_QPIC_SERIAL
+ if (i == (dev->cws_per_page) - 1)
+ bam_add_cmd_element(cmd_list_ptr,
+ NAND_READ_LOCATION_LAST_CW_n(0),
+ (uint32_t)addr_loc_0,
+ CE_WRITE_TYPE);
+ else
+ bam_add_cmd_element(cmd_list_ptr,
NAND_READ_LOCATION_n(0),
(uint32_t)addr_loc_0,
CE_WRITE_TYPE);
-
+#else
+ bam_add_cmd_element(cmd_list_ptr,
+ NAND_READ_LOCATION_n(0),
+ (uint32_t)addr_loc_0,
+ CE_WRITE_TYPE);
+#endif
cmd_list_ptr++;
bam_add_cmd_element(cmd_list_ptr,
@@ -2064,6 +2716,7 @@
ret = qpic_nand_read_page(mtd, start_page + i, cfg_mode,
&page_ops);
+
if (ret < 0) {
printf("%s: reading page %d failed with %d err\n",
__func__, start_page + i, ret);
@@ -2314,7 +2967,28 @@
/* Clear CW_PER_PAGE in cfg0 */
cfg.cfg0 = dev->cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
cfg.cfg1 = dev->cfg1;
+
cfg.cmd = NAND_CMD_BLOCK_ERASE;
+#ifdef CONFIG_QPIC_SERIAL
+ /* For serial NAND devices the block erase sequence is
+ * Issue 06H (WRITE ENBALE command)
+ * Issue D8H (BLOCK ERASE command)
+ * Issue 0FH (GET FEATURES command to read the status register)
+ * But we have already mapped write enable command in register
+ * QPIC_FLASH_DEV_CMD7 so here no need to send this command manually
+ * once we will send block erase command then controller internally
+ * send write enable command
+ * similar for Get feature command, no neeed to send this command
+ * also manually controller will take care.
+ *
+ * NOTE: Initially we are disabling block protection, so no need
+ * to do it again here.
+ */
+ cfg.addr0 = page << 16;
+ cfg.cmd = 0xA;
+ cfg.cmd |= (QPIC_SPI_WP_SET | QPIC_SPI_HOLD_SET |
+ QPIC_SPI_TRANSFER_MODE_X1);
+#endif
cfg.exec = 1;
cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
@@ -2418,13 +3092,13 @@
for (i = start; i < (start + blocks); i++) {
offs = i << chip->phys_erase_shift;
pageno = offs >> chip->page_shift;
+
/* Erase only if the block is not bad */
if (!instr->scrub && qpic_nand_block_isbad(mtd, offs)) {
printf("NAND Erase error: Block address belongs to "
"bad block: %ld\n", (pageno / (dev->num_pages_per_blk)));
return -EIO;
}
-
ret = qpic_nand_blk_erase(mtd, pageno);
if (ret) {
instr->fail_addr = offs;
@@ -2519,6 +3193,25 @@
return;
}
+#ifdef CONFIG_QPIC_SERIAL
+ /* Read the Hardware Version register */
+ hw_ver = readl(NAND_VERSION);
+ /* Only maintain major number */
+ hw_ver >>= 28;
+ if (hw_ver >= QCA_QPIC_V2_1_1) {
+ printf("QPIC controller support serial NAND\n");
+ } else {
+ printf("%s : Qpic controller not support serial NAND\n",
+ __func__);
+ return;
+ }
+
+ qpic_spi_init(mtd);
+#ifdef MULTI_PAGE_READ
+ config.pipes.status_pipe = NAND_BAM_STATUS_PIPE;
+ config.pipes.status_pipe_grp = NAND_BAM_STATUS_PIPE_GRP;
+#endif
+#endif
config.pipes.read_pipe = DATA_PRODUCER_PIPE;
config.pipes.write_pipe = DATA_CONSUMER_PIPE;
config.pipes.cmd_pipe = CMD_PIPE;
@@ -2544,13 +3237,27 @@
else if (ret > 0)
qpic_nand_non_onfi_probe(mtd);
+#ifndef CONFIG_QPIC_SERIAL
qpic_config_timing_parameters(mtd);
-
+#endif
/* Save the RAW and read/write configs */
ret = qpic_nand_save_config(mtd);
if (ret < 0)
return;
+#ifdef CONFIG_QPIC_SERIAL
+ /* Check all blocks of serial NAND device is unlocked or
+ * not if not then unlock the all the blocks of serial NAND
+ * device also check the internal ecc is enabled or not if internal
+ * ecc is enabled then disable internal ecc using get/set feature
+ * command.
+ */
+ ret = qpic_spi_nand_config(mtd);
+ if (ret < 0) {
+ printf("%s : Issue with Serial Nand configuration.\n",__func__);
+ return;
+ }
+#endif
dev = MTD_QPIC_NAND_DEV(mtd);
qpic_nand_mtd_params(mtd);
diff --git a/include/configs/ipq40xx.h b/include/configs/ipq40xx.h
index 8e6b021..3613edf 100644
--- a/include/configs/ipq40xx.h
+++ b/include/configs/ipq40xx.h
@@ -84,6 +84,9 @@
#define CONFIG_TZ_END_ADDR 0x88000000
#define CONFIG_SYS_SDRAM_END (CONFIG_SYS_SDRAM_BASE + gd->ram_size)
+#define CONFIG_QCA_UBOOT_OFFSET 0x7000000
+#define CONFIG_UBOOT_END_ADDR 0x87400000
+
#define CONFIG_IPQ40XX_ENV
#define CONFIG_ENV_IS_IN_NAND
diff --git a/include/configs/ipq5018.h b/include/configs/ipq5018.h
index e9a893e..e94798c 100644
--- a/include/configs/ipq5018.h
+++ b/include/configs/ipq5018.h
@@ -19,6 +19,7 @@
#endif
#define CONFIG_IPQ5018
+#undef CONFIG_QCA_DISABLE_SCM
#define CONFIG_SPI_FLASH_CYPRESS
#define CONFIG_SYS_NO_FLASH
#define CONFIG_SYS_CACHELINE_SIZE 64
@@ -34,6 +35,11 @@
#define CONFIG_ENV_SIZE_MAX (256 << 10) /* 256 KB */
/*
+* PSCI Calls enable
+*/
+#define CONFIG_ARMV7_PSCI
+
+/*
*Size of malloc() pool
*/
@@ -130,6 +136,10 @@
#define CONFIG_SYS_NAND_SELF_INIT
#define CONFIG_SYS_NAND_ONFI_DETECTION
+/* QSPI Flash configs
+ */
+#define CONFIG_QPIC_SERIAL
+
/*
* SPI Flash Configs
*/
diff --git a/include/configs/ipq6018.h b/include/configs/ipq6018.h
index 5d9263e..835bf85 100644
--- a/include/configs/ipq6018.h
+++ b/include/configs/ipq6018.h
@@ -122,6 +122,9 @@
#define CONFIG_TZ_END_ADDR 0x4AA00000
#define CONFIG_SYS_SDRAM_END ((long long)CONFIG_SYS_SDRAM_BASE + gd->ram_size)
+#define CONFIG_QCA_UBOOT_OFFSET 0xA100000
+#define CONFIG_UBOOT_END_ADDR 0x4A500000
+
#ifndef __ASSEMBLY__
#include <compiler.h>
extern loff_t board_env_offset;
diff --git a/include/configs/ipq806x.h b/include/configs/ipq806x.h
index 7126b42..bce2752 100644
--- a/include/configs/ipq806x.h
+++ b/include/configs/ipq806x.h
@@ -143,6 +143,9 @@
#define QCA_BOOT_PARAMS_ADDR (QCA_KERNEL_START_ADDR + 0x100)
#define CONFIG_QCA_SMEM_BASE CONFIG_SYS_SDRAM_BASE + 0x1000000
+#define CONFIG_QCA_UBOOT_OFFSET 0x1D00000
+#define CONFIG_UBOOT_END_ADDR 0x42100000
+
#define CONFIG_OF_COMBINE 1
#define CONFIG_CMD_BOOTZ
diff --git a/include/configs/ipq807x.h b/include/configs/ipq807x.h
index b7d8bf3..19a69f4 100644
--- a/include/configs/ipq807x.h
+++ b/include/configs/ipq807x.h
@@ -103,6 +103,8 @@
#define CONFIG_OF_COMBINE 1
+#define CONFIG_QCA_UBOOT_OFFSET 0xA600000
+#define CONFIG_UBOOT_END_ADDR 0x4AA00000
#define CONFIG_QCA_SMEM_BASE 0x4AB00000
#define CONFIG_IPQ_FDT_HIGH 0x4A400000
diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c
index 9a20b70..dd5c507 100644
--- a/lib/zlib/deflate.c
+++ b/lib/zlib/deflate.c
@@ -585,6 +585,7 @@
{
int old_flush; /* value of flush param for previous deflate call */
deflate_state *s;
+ int hdr = 0;
if (strm == Z_NULL || strm->state == Z_NULL ||
flush > Z_BLOCK || flush < 0) {
@@ -603,6 +604,7 @@
/* Write the header */
if (s->status == INIT_STATE) {
+ hdr = 1;
#ifdef GZIP
if (s->wrap == 2) {
strm->adler = crc32(0L, Z_NULL, 0);
@@ -782,7 +784,7 @@
#endif
/* Flush as much pending output as possible */
- if (s->pending != 0) {
+ if ((s->pending != 0) && (hdr != 1)) {
flush_pending(strm);
if (strm->avail_out == 0) {
/* Since avail_out is 0, deflate will be called again with
@@ -819,6 +821,15 @@
(s->strategy == Z_RLE ? deflate_rle(s, flush) :
(*(configuration_table[s->level].func))(s, flush));
+ /*****Flush header now to dst, which is src pointer after src data are read in previous step*****/
+ if ((s->pending != 0) && (hdr == 1)) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+
if (bstate == finish_started || bstate == finish_done) {
s->status = FINISH_STATE;
}