Merge "ipq40xx: kw fix: Avoid Null pointer dereferencing"
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 2c4c75e..4ef3dbb 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -136,7 +136,8 @@
 	params->hdr.size =
 		(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
 
-	strcpy (params->u.cmdline.cmdline, p);
+	strlcpy (params->u.cmdline.cmdline, p,
+				sizeof(params->u.cmdline.cmdline));
 
 	params = tag_next (params);
 }
diff --git a/board/qca/arm/common/board_init.c b/board/qca/arm/common/board_init.c
index 55fc612..8733d47 100644
--- a/board/qca/arm/common/board_init.c
+++ b/board/qca/arm/common/board_init.c
@@ -37,6 +37,15 @@
 char *env_name_spec;
 int (*saveenv)(void);
 
+#define ADSS_AUDIO_RXM_CBCR_REG			0x0770012C
+#define ADSS_AUDIO_RXB_CBCR_REG			0x0770010C
+#define ADSS_AUDIO_TXB_CBCR_REG			0x0770014C
+#define ADSS_AUDIO_SPDIF_CBCR_REG		0x07700154
+#define ADSS_AUDIO_SPDIF_DIV2_CBCR_REG		0x0770015C
+#define ADSS_AUDIO_TXM_CBCR_REG			0x0770016C
+#define ADSS_AUDIO_PCM_CBCR_REG			0x077001AC
+#define ADSS_AUDIO_SPDIF_IN_FAST_CBCR_REG	0x077001EC
+
 loff_t board_env_offset;
 loff_t board_env_range;
 loff_t board_env_size;
@@ -57,6 +66,25 @@
 	return 0;
 }
 
+/*
+ * The audio block is out of reset by default due to which the
+ * audio clock blocks are also turned on. When audio TLMM is
+ * enabled in kernel, the clocks will also be available at the
+ * pins which causes pop noise during kernel bootup.
+ * To avoid this, the clocks are turned off in u-boot.
+ */
+static void disable_audio_clks(void)
+{
+	writel(0, ADSS_AUDIO_RXM_CBCR_REG);
+	writel(0, ADSS_AUDIO_RXB_CBCR_REG);
+	writel(0, ADSS_AUDIO_TXB_CBCR_REG);
+	writel(0, ADSS_AUDIO_SPDIF_CBCR_REG);
+	writel(0, ADSS_AUDIO_SPDIF_DIV2_CBCR_REG);
+	writel(0, ADSS_AUDIO_TXM_CBCR_REG);
+	writel(0, ADSS_AUDIO_PCM_CBCR_REG);
+	writel(0, ADSS_AUDIO_SPDIF_IN_FAST_CBCR_REG);
+}
+
 int board_init(void)
 {
 	int ret;
@@ -172,6 +200,7 @@
 	}
 
 	aquantia_phy_reset_init();
+	disable_audio_clks();
 
 	return 0;
 }
diff --git a/board/qca/arm/ipq40xx/ipq40xx.c b/board/qca/arm/ipq40xx/ipq40xx.c
index 4e23538..c29dc3e 100644
--- a/board/qca/arm/ipq40xx/ipq40xx.c
+++ b/board/qca/arm/ipq40xx/ipq40xx.c
@@ -33,12 +33,17 @@
 #include "ipq40xx_edma_eth.h"
 #include "qca_common.h"
 #include "ipq_phy.h"
+#include <sdhci.h>
 
 #define DLOAD_MAGIC_COOKIE 0x10
 #define TCSR_USB_HSPHY_DEVICE_MODE		0x00C700E70
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_SDHCI_SUPPORT
 qca_mmc mmc_host;
+#else
+struct sdhci_host mmc_host;
+#endif
 
 const char *rsvd_node = "/reserved-memory";
 const char *del_node[] = {"rsvd1",
@@ -230,6 +235,21 @@
 }
 
 #ifdef CONFIG_QCA_MMC
+void emmc_clock_reset(void)
+{
+	writel(0x1, GCC_SDCC1_BCR);
+	udelay(10);
+	writel(0x0, GCC_SDCC1_BCR);
+}
+
+void emmc_sdhci_init(void)
+{
+	writel(readl(MSM_SDC1_MCI_HC_MODE) & (~0x1), MSM_SDC1_MCI_HC_MODE);
+	writel(readl(MSM_SDC1_BASE) | (1 << 7), MSM_SDC1_BASE); //SW_RST
+	udelay(10);
+	writel(readl(MSM_SDC1_MCI_HC_MODE) | (0x1), MSM_SDC1_MCI_HC_MODE);
+}
+
 int board_mmc_init(bd_t *bis)
 {
 	int ret;
@@ -252,12 +272,30 @@
 		return -1;
         }
 
+#ifndef CONFIG_SDHCI_SUPPORT
 	mmc_host.base = base;
 	mmc_host.clk_mode = MMC_IDENTIFY_MODE;
 	emmc_clock_config(mmc_host.clk_mode);
 
 	ret = qca_mmc_init(bis, &mmc_host);
+#else
+	mmc_host.ioaddr = (void *)MSM_SDC1_SDHCI_BASE;
+	mmc_host.voltages = MMC_VDD_165_195;
+	mmc_host.version = SDHCI_SPEC_300;
+	mmc_host.cfg.part_type = PART_TYPE_EFI;
+	mmc_host.quirks = SDHCI_QUIRK_BROKEN_VOLTAGE;
 
+	emmc_clock_disable();
+	emmc_clock_reset();
+	udelay(10);
+	emmc_clock_config(MMC_DATA_TRANSFER_SDHCI_MODE);
+	emmc_sdhci_init();
+
+	if (add_sdhci(&mmc_host, 200000000, 400000)) {
+		printf("add_sdhci fail!\n");
+		return -1;
+	}
+#endif
 	if (!ret && sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
 		ret = board_mmc_env_init(mmc_host);
 	}
diff --git a/board/qca/arm/ipq40xx/ipq40xx.h b/board/qca/arm/ipq40xx/ipq40xx.h
index 3ea1322..a14231d 100644
--- a/board/qca/arm/ipq40xx/ipq40xx.h
+++ b/board/qca/arm/ipq40xx/ipq40xx.h
@@ -26,11 +26,11 @@
 #endif
 #define MAX_CONF_NAME		5
 #define GCC_BLSP1_UART1_APPS_CBCR       0x0180203c
+#define GCC_SDCC1_BCR		0x1818000
 
 #define KERNEL_AUTH_CMD		0x13
 
 unsigned int smem_get_board_machtype(void);
-extern qca_mmc mmc_host;
 
 #define IPQ40XX_EDMA_DEV	1
 typedef struct {
diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c
index 52a3e50..250444f 100644
--- a/board/qca/arm/ipq807x/ipq807x.c
+++ b/board/qca/arm/ipq807x/ipq807x.c
@@ -425,7 +425,7 @@
 
 int board_mmc_init(bd_t *bis)
 {
-	int ret;
+	int ret = 0;
 	qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
 
 #ifndef CONFIG_SDHCI_SUPPORT
@@ -705,7 +705,8 @@
 	}
 	else if (index == 1) {
 		phybase = USB1_SSPHY_BASE;
-	}
+	} else
+		return;
 
 	out_8( phybase + USB3_PHY_POWER_DOWN_CONTROL,0x1);
 	out_8(phybase + QSERDES_COM_SYSCLK_EN_SEL,0x1a);
diff --git a/common/cmd_disk.c b/common/cmd_disk.c
index 8a1fda9..9dbe550 100644
--- a/common/cmd_disk.c
+++ b/common/cmd_disk.c
@@ -111,7 +111,7 @@
 #if defined(CONFIG_FIT)
 	/* This cannot be done earlier,
 	 * we need complete FIT image in RAM first */
-	if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
+	if (fit_hdr && genimg_get_format((void *)addr) == IMAGE_FORMAT_FIT) {
 		if (!fit_check_format(fit_hdr)) {
 			bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
 			puts("** Bad FIT image format\n");
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 190275d..c3e46d8 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -872,14 +872,14 @@
 
 #if defined(CONFIG_FIT)
 	/* This cannot be done earlier, we need complete FIT image in RAM first */
-	if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
-		if (!fit_check_format (fit_hdr)) {
+	if (fit_hdr && genimg_get_format((void *)addr) == IMAGE_FORMAT_FIT) {
+		if (!fit_check_format(fit_hdr)) {
 			bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
-			puts ("** Bad FIT image format\n");
+			puts("** Bad FIT image format\n");
 			return 1;
 		}
 		bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
-		fit_print_contents (fit_hdr);
+		fit_print_contents(fit_hdr);
 	}
 #endif
 
diff --git a/common/env_nand.c b/common/env_nand.c
index 61096b8..d1f617a 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -189,7 +189,7 @@
 		{
 			.name = "NAND",
 			.erase_opts = {
-				.length = CONFIG_ENV_RANGE,
+				.length = board_env_size,
 				.offset = CONFIG_ENV_OFFSET,
 			},
 		},
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 03beb18..a38af31 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -79,21 +79,24 @@
 	uint32_t table_len = 0;
 
 	if (len <= SDHCI_ADMA_DESC_LINE_SZ) {
-		list = (struct adma_desc *) memalign(CACHE_LINE_SIZE, sizeof(struct adma_desc));
+		list = (struct adma_desc *)memalign(CACHE_LINE_SIZE,
+				sizeof(struct adma_desc));
 
 		if (!list) {
 			printf("Error allocating memory\n");
 			assert(0);
-		}
-
-		list[0].addr = (uint32_t)data;
-		list[0].len = (len < SDHCI_ADMA_DESC_LINE_SZ) ? len : (SDHCI_ADMA_DESC_LINE_SZ & 0xffff);
-		list[0].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA
-							  | SDHCI_ADMA_TRANS_END;
+		} else {
+			list[0].addr = (uint32_t)data;
+			list[0].len = (len < SDHCI_ADMA_DESC_LINE_SZ) ? len :
+				(SDHCI_ADMA_DESC_LINE_SZ & 0xffff);
+			list[0].tran_att = SDHCI_ADMA_TRANS_VALID |
+				SDHCI_ADMA_TRANS_DATA | SDHCI_ADMA_TRANS_END;
 
 #if !defined(CONFIG_SYS_DCACHE_OFF)
-		flush_cache((unsigned long)list, sizeof(struct adma_desc));
+			flush_cache((unsigned long)list,
+				    sizeof(struct adma_desc));
 #endif
+		}
 	} else {
 		list_len = len / SDHCI_ADMA_DESC_LINE_SZ;
 		remain = len - (list_len * SDHCI_ADMA_DESC_LINE_SZ);
@@ -108,26 +111,29 @@
 		if (!list) {
 			printf("Allocating memory failed\n");
 			assert(0);
-		}
+		} else {
+			memset((void *)list, 0, table_len);
 
-		memset((void *) list, 0, table_len);
-
-		for (i = 0; i < (list_len - 1); i++) {
+			for (i = 0; i < (list_len - 1); i++) {
 				list[i].addr = (uint32_t)data;
 				list[i].len = (SDHCI_ADMA_DESC_LINE_SZ & 0xffff);
-				list[i].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA;
+				list[i].tran_att = SDHCI_ADMA_TRANS_VALID |
+					SDHCI_ADMA_TRANS_DATA;
 				data += SDHCI_ADMA_DESC_LINE_SZ;
 				len -= SDHCI_ADMA_DESC_LINE_SZ;
 			}
 
 			list[list_len - 1].addr = (uint32_t)data;
-			list[list_len - 1].len = (len < SDHCI_ADMA_DESC_LINE_SZ) ? len : (SDHCI_ADMA_DESC_LINE_SZ & 0xffff);
-			list[list_len - 1].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA |
-										   SDHCI_ADMA_TRANS_END;
+			list[list_len - 1].len = (len < SDHCI_ADMA_DESC_LINE_SZ)
+				? len : (SDHCI_ADMA_DESC_LINE_SZ & 0xffff);
+			list[list_len - 1].tran_att = SDHCI_ADMA_TRANS_VALID |
+				SDHCI_ADMA_TRANS_DATA
+				| SDHCI_ADMA_TRANS_END;
 
 #if !defined(CONFIG_SYS_DCACHE_OFF)
-		flush_cache((unsigned long)list, table_len);
+			flush_cache((unsigned long)list, table_len);
 #endif
+		}
 	}
 
 
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index ecc2b57..584814c 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -47,6 +47,7 @@
 	E_FSR		= 1 << 2,
 	SST_WR		= 1 << 3,
 	WR_QPP		= 1 << 4,
+	SECT_64K	= 1 << 5,
 };
 
 enum spi_nor_option_flags {
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 73c44fe..4f54af2 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -16,6 +16,7 @@
 #include <spi.h>
 #include <spi_flash.h>
 #include <linux/log2.h>
+#include <linux/sizes.h>
 
 #include "sf_internal.h"
 
@@ -370,6 +371,12 @@
 	}
 
 	cmd[0] = flash->erase_cmd;
+
+	if (!(offset % SZ_64K || len % SZ_64K) && (flash->flags & SECT_64K)) {
+		erase_size = SZ_64K;
+		cmd[0] = CMD_ERASE_64K;
+	}
+
 	while (len) {
 		erase_addr = offset;
 
@@ -1078,6 +1085,8 @@
 	if (params->flags & SECT_4K) {
 		flash->erase_cmd = CMD_ERASE_4K;
 		flash->erase_size = 4096 << flash->shift;
+		if (flash->sector_size == SZ_64K)
+			flash->flags |= SECT_64K;
 	} else if (params->flags & SECT_32K) {
 		flash->erase_cmd = CMD_ERASE_32K;
 		flash->erase_size = 32768 << flash->shift;
diff --git a/drivers/net/ipq806x/ipq_gmac_eth.c b/drivers/net/ipq806x/ipq_gmac_eth.c
index 6caa4a2..cfa4b7b 100644
--- a/drivers/net/ipq806x/ipq_gmac_eth.c
+++ b/drivers/net/ipq806x/ipq_gmac_eth.c
@@ -849,7 +849,7 @@
 
 		ipq_gmac_mii_clk_init(ipq_gmac_macs[i], clk_div_val, gmac_cfg);
 
-		strncpy((char *)ipq_gmac_macs[i]->phy_name, gmac_cfg->phy_name,
+		strlcpy((char *)ipq_gmac_macs[i]->phy_name, gmac_cfg->phy_name,
 					sizeof(ipq_gmac_macs[i]->phy_name));
 		bb_nodes[i] = malloc(sizeof(struct bitbang_nodes));
 		if (bb_nodes[i] == NULL)
diff --git a/drivers/net/ipq807x/ipq807x_edma.c b/drivers/net/ipq807x/ipq807x_edma.c
index 6c87216..d33e5bf 100644
--- a/drivers/net/ipq807x/ipq807x_edma.c
+++ b/drivers/net/ipq807x/ipq807x_edma.c
@@ -907,7 +907,7 @@
 	char *lstatus[] = {"up", "Down"};
 	char *dp[] = {"Half", "Full"};
 	int linkup=0;
-	int mac_speed, speed_clock1, speed_clock2;
+	int mac_speed = 0, speed_clock1 = 0, speed_clock2 = 0;
 	int phy_addr, port_8033 = -1, node, aquantia_port = -1;
 
 	node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
diff --git a/drivers/net/ipq_common/ipq_mdio.c b/drivers/net/ipq_common/ipq_mdio.c
index e63373d..9703dbf 100644
--- a/drivers/net/ipq_common/ipq_mdio.c
+++ b/drivers/net/ipq_common/ipq_mdio.c
@@ -187,7 +187,7 @@
 static int do_ipq_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	char		op[2];
-	unsigned int	addr, reg;
+	unsigned int	addr = 0, reg = 0;
 	unsigned short	data = 0;
 
 	if (argc < 2)
diff --git a/drivers/pci/pci_ipq.c b/drivers/pci/pci_ipq.c
index 0b616cc..a5a4a7a 100644
--- a/drivers/pci/pci_ipq.c
+++ b/drivers/pci/pci_ipq.c
@@ -644,6 +644,16 @@
 {
 	uint32_t val;
 
+	/* Assert cc_pcie20_mstr_axi_ares */
+	val = readl(pcie->pci_rst.start);
+	val |= PCIE_RST_CTRL_AXI_M_ARES;
+	writel(val, pcie->pci_rst.start);
+
+	/* Assert cc_pcie20_slv_axi_ares */
+	val = readl(pcie->pci_rst.start);
+	val |= PCIE_RST_CTRL_AXI_S_ARES;
+	writel(val, pcie->pci_rst.start);
+
 	/* Assert cc_pcie20_core_ares */
 	writel(PCIE_RST_CTRL_PIPE_ARES, pcie->pci_rst.start);
 
@@ -657,31 +667,21 @@
 	val |= PCIE_RST_CTRL_PIPE_PHY_AHB_ARES;
 	writel(val, pcie->pci_rst.start);
 
-	gpio_set_value(pcie->rst_gpio, GPIO_OUT_LOW);
-
-	/* Assert cc_pcie20_mstr_axi_ares */
-	val = readl(pcie->pci_rst.start);
-	val |= PCIE_RST_CTRL_AXI_M_ARES;
-	writel(val, pcie->pci_rst.start);
-
 	/* Assert cc_pcie20_mstr_sticky_ares */
 	val = readl(pcie->pci_rst.start);
 	val |= PCIE_RST_CTRL_AXI_M_STICKY_ARES;
 	writel(val, pcie->pci_rst.start);
 
-	/* Assert cc_pcie20_slv_axi_ares */
-	val = readl(pcie->pci_rst.start);
-	val |= PCIE_RST_CTRL_AXI_S_ARES;
-	writel(val, pcie->pci_rst.start);
+	gpio_set_value(pcie->rst_gpio, GPIO_OUT_LOW);
 
 	/* Assert cc_pcie20_ahb_ares;  */
 	val = readl(pcie->pci_rst.start);
 	val |= PCIE_RST_CTRL_AHB_ARES;
 	writel(val, pcie->pci_rst.start);
 
-	/* DeAssert cc_pcie20_phy_ahb_ares  */
+	/* DeAssert cc_pcie20_ahb_ares */
 	val = readl(pcie->pci_rst.start);
-	val &= ~(PCIE_RST_CTRL_AHB_ARES);
+	val &= ~(PCIE_RST_CTRL_PIPE_PHY_AHB_ARES);
 	writel(val, pcie->pci_rst.start);
 
 	/* DeAssert cc_pcie20_pciephy_phy_ares*/
@@ -713,9 +713,9 @@
 	val &= ~(PCIE_RST_CTRL_AXI_S_ARES);
 	writel(val, pcie->pci_rst.start);
 
-	/* DeAssert cc_pcie20_ahb_ares */
+	/* DeAssert cc_pcie20_phy_ahb_ares  */
 	val = readl(pcie->pci_rst.start);
-	val &= ~(PCIE_RST_CTRL_PIPE_PHY_AHB_ARES);
+	val &= ~(PCIE_RST_CTRL_AHB_ARES);
 	writel(val, pcie->pci_rst.start);
 }
 
diff --git a/include/configs/ipq40xx.h b/include/configs/ipq40xx.h
index 7163a29..087cc34 100644
--- a/include/configs/ipq40xx.h
+++ b/include/configs/ipq40xx.h
@@ -223,6 +223,7 @@
 #define CONFIG_ENV_IS_IN_SPI_FLASH	1
 #define CONFIG_ENV_SECT_SIZE        	(64 * 1024)
 
+#define CONFIG_SPI_FLASH_USE_4K_SECTORS
 #define CONFIG_SF_DEFAULT_BUS 0
 #define CONFIG_SF_DEFAULT_CS 0
 #define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
@@ -300,10 +301,13 @@
 #define CONFIG_MMC
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_CMD_MMC
+#define CONFIG_SDHCI
 #define CONFIG_SDHCI_QCA
 #define CONFIG_GENERIC_MMC
 #define CONFIG_EFI_PARTITION
 #define CONFIG_SYS_MMC_ENV_DEV  0
+#define CONFIG_SDHCI_SUPPORT
+#define CONFIG_MMC_ADMA
 #endif
 
 #define PCI_MAX_DEVICES	1
diff --git a/include/configs/ipq806x.h b/include/configs/ipq806x.h
index 9a87322..4285595 100644
--- a/include/configs/ipq806x.h
+++ b/include/configs/ipq806x.h
@@ -267,6 +267,7 @@
 #define CONFIG_ENV_IS_IN_SPI_FLASH	1
 #define CONFIG_ENV_SECT_SIZE        	(64 * 1024)
 
+#define CONFIG_SPI_FLASH_USE_4K_SECTORS
 #define CONFIG_SF_DEFAULT_BUS 0
 #define CONFIG_SF_DEFAULT_CS 0
 #define CONFIG_SF_DEFAULT_SPEED         (48 * 1000 * 1000)