Merge "Revert "qca: Disabling dcache before scheduling secondary cores""
diff --git a/board/qca/arm/common/board_init.c b/board/qca/arm/common/board_init.c
index 8891fbc..2c9ab0e 100644
--- a/board/qca/arm/common/board_init.c
+++ b/board/qca/arm/common/board_init.c
@@ -16,7 +16,10 @@
#include <asm/arch-qca-common/smem.h>
#include <asm/arch-qca-common/uart.h>
#include <asm/arch-qca-common/gpio.h>
+#include <memalign.h>
#include <fdtdec.h>
+#include <mmc.h>
+#include <sdhci.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -31,6 +34,12 @@
extern env_t *mmc_env_ptr;
extern char *mmc_env_name_spec;
extern int mmc_saveenv(void);
+
+#ifndef CONFIG_SDHCI_SUPPORT
+extern qca_mmc mmc_host;
+#else
+extern struct sdhci_host mmc_host;
+#endif
#endif
env_t *env_ptr;
@@ -222,6 +231,39 @@
return 0;
}
+#ifdef CONFIG_FLASH_PROTECT
+void board_flash_protect(void)
+{
+ unsigned int num_part;
+ int i;
+#ifdef CONFIG_QCA_MMC
+ block_dev_desc_t *mmc_dev;
+ disk_partition_t info;
+
+ mmc_dev = mmc_get_dev(mmc_host.dev_num);
+ if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
+ ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header,
+ gpt_head, 1, mmc_dev->blksz);
+ if (mmc_dev->block_read(mmc_dev->dev,
+ (lbaint_t)GPT_PRIMARY_PARTITION_TABLE_LBA,
+ 1, gpt_head) == 1) {
+ num_part = le32_to_cpu(gpt_head->num_partition_entries);
+ for (i = 1; i <= num_part; i++) {
+ if (!get_partition_info_efi(mmc_dev, i, &info)
+ && info.readonly
+ && !mmc_write_protect(mmc_host.mmc,
+ info.start,
+ info.size, 1))
+ printf("\"%s\""
+ "-protected MMC partition\n",
+ info.name);
+ }
+ }
+ }
+#endif
+}
+#endif
+
int board_late_init(void)
{
unsigned int machid;
@@ -238,6 +280,9 @@
setenv_addr("machid", (void *)machid);
gd->bd->bi_arch_number = machid;
}
+#ifdef CONFIG_FLASH_PROTECT
+ board_flash_protect();
+#endif
set_ethmac_addr();
return 0;
}
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index a6b7313..5111980 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -330,6 +330,31 @@
}
#endif
+static int do_mmc_protect (cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct mmc *mmc;
+ unsigned int ret;
+ unsigned int blk, cnt;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ blk = (unsigned int)simple_strtoul(argv[1], NULL, 16);
+ cnt = (unsigned int)simple_strtoul(argv[2], NULL, 16);
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ ret = mmc_write_protect(mmc, blk, cnt, 1);
+
+ if (!ret)
+ printf("Offset: 0x%x Count: %d blocks\nDone!\n", blk, cnt);
+
+ return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
{
@@ -802,6 +827,7 @@
U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""),
+ U_BOOT_CMD_MKENT(protect, 4, 0, do_mmc_protect, "", ""),
#ifdef CONFIG_SUPPORT_EMMC_BOOT
U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),
@@ -858,6 +884,7 @@
" [check|set|complete] - mode, complete set partitioning completed\n"
" WARNING: Partitioning is a write-once setting once it is set to complete.\n"
" Power cycling is required to initialize partitions after set to complete.\n"
+ "mmc protect start_blk# cnt_blk\n"
#ifdef CONFIG_SUPPORT_EMMC_BOOT
"mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
" - Set the BOOT_BUS_WIDTH field of the specified device\n"
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 37735e9..57840b0 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -70,6 +70,14 @@
sizeof(efi_guid_t));
}
+static inline int is_readonly(gpt_entry *p)
+{
+ /* bit 60 of gpt attribute denotes read-only flag */
+ if (p->attributes.raw & ((unsigned long long)1 << 60))
+ return 1;
+ return 0;
+}
+
static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba,
lbaint_t lastlba)
{
@@ -283,6 +291,7 @@
print_efiname(&gpt_pte[part - 1]));
snprintf((char *)info->type, sizeof(info->type), "U-Boot");
info->bootable = is_bootable(&gpt_pte[part - 1]);
+ info->readonly = is_readonly(&gpt_pte[part - 1]);
#ifdef CONFIG_PARTITION_UUIDS
uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid,
UUID_STR_FORMAT_GUID);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 62765d8..0320942 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1181,6 +1181,8 @@
* For SD, its erase group is always one sector
*/
mmc->erase_grp_size = 1;
+ mmc->wp_grp_size = WP_GRP_SIZE(mmc->csd);
+ mmc->wp_grp_enable = WP_GRP_ENABLE(mmc->csd);
mmc->part_config = MMCPART_NOAVAILABLE;
if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
/* check ext_csd version and capacity */
@@ -1836,6 +1838,87 @@
return 0;
}
+int mmc_send_wp_set_clr(struct mmc *mmc, unsigned int start,
+ unsigned int size, int set_clr)
+{
+ unsigned int err;
+ unsigned int wp_group_size, count, i;
+ struct mmc_cmd cmd;
+
+ wp_group_size = (mmc->wp_grp_size + 1) * mmc->erase_grp_size;
+ count = DIV_ROUND_UP(size, wp_group_size);
+
+ if (set_clr)
+ cmd.cmdidx = MMC_CMD_SET_WRITE_PROT;
+ else
+ cmd.cmdidx = MMC_CMD_CLR_WRITE_PROT;
+ cmd.resp_type = MMC_RSP_R1b;
+
+ for (i = 0; i < count; i++) {
+ cmd.cmdarg = start + (i * wp_group_size);
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ printf("%s: Error at block 0x%lx - %d\n", __func__,
+ cmd.cmdarg, err);
+ return err;
+ }
+
+ if(MMC_ADDR_OUT_OF_RANGE(cmd.response[0])) {
+ printf("%s: mmc block(0x%lx) out of range", __func__,
+ cmd.cmdarg);
+ return -EINVAL;
+ }
+
+ err = mmc_send_status(mmc, MMC_RESP_TIMEOUT);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int mmc_write_protect(struct mmc *mmc, unsigned int start_blk,
+ unsigned int cnt_blk, int set_clr)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
+ int err;
+ unsigned int wp_group_size;
+
+ if (!mmc->wp_grp_enable)
+ return -1; /* group write protection is not supported */
+
+ err = mmc_send_ext_csd(mmc, ext_csd);
+
+ if (err) {
+ debug("ext_csd register cannot be retrieved\n");
+ return err;
+ }
+
+ if ((ext_csd[EXT_CSD_USER_WP] & EXT_CSD_US_PWR_WP_DIS)
+ || (ext_csd[EXT_CSD_USER_WP] & EXT_CSD_US_PERM_WP_EN)) {
+ printf("User power-on write protection is disabled. \n");
+ return -1;
+ }
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_USER_WP,
+ EXT_CSD_US_PWR_WP_EN);
+ if (err) {
+ printf("Failed to enable user power-on write protection\n");
+ return err;
+ }
+
+ wp_group_size = (mmc->wp_grp_size + 1) * mmc->erase_grp_size;
+
+ if (!cnt_blk || start_blk % wp_group_size || cnt_blk % wp_group_size) {
+ printf("Error: Unaligned offset/count. offset/count should be aligned to 0x%x blocks\n", wp_group_size);
+ return -1;
+ }
+
+ err = mmc_send_wp_set_clr(mmc, start_blk, cnt_blk, set_clr);
+
+ return err;
+}
+
#ifdef CONFIG_SUPPORT_EMMC_BOOT
/*
* This function changes the size of boot partition and the size of rpmb
diff --git a/drivers/spi/ipq_spi.c b/drivers/spi/ipq_spi.c
index 511edae..682d62f 100644
--- a/drivers/spi/ipq_spi.c
+++ b/drivers/spi/ipq_spi.c
@@ -43,6 +43,14 @@
DECLARE_GLOBAL_DATA_PTR;
/*
+ * CS GPIO number array cs_gpio_array[port_num][cs_num]
+ * cs_gpio_array[0][x] -- GSBI5
+ * cs_gpio_array[1][x] -- GSBI6
+ * cs_gpio_array[2][x] -- GSBI7
+ */
+static unsigned int cs_gpio_array[NUM_PORTS][NUM_CS];
+
+/*
* GSBI HCLK state register bit
* hclk_state[0] -- GSBI5
* hclk_state[1] -- GSBI6
@@ -203,18 +211,11 @@
*/
static void CS_change(int port_num, int cs_num, int enable)
{
- unsigned int cs_gpio = 0;
+ unsigned int cs_gpio;
uint32_t addr = 0;
uint32_t val = 0;
- char spi_node_path[32];
- int spi_cs_node = 0, spi_cs_gpio_node = 0;
- sprintf(spi_node_path, "/spi/spi%d/cs%d", port_num, cs_num);
-
- spi_cs_node = fdt_path_offset(gd->fdt_blob, spi_node_path);
- spi_cs_gpio_node = fdt_first_subnode(gd->fdt_blob, spi_cs_node);
-
- cs_gpio = fdtdec_get_uint(gd->fdt_blob, spi_cs_gpio_node, "gpio", 0);
+ cs_gpio = cs_gpio_array[port_num][cs_num];
addr = GPIO_IN_OUT_ADDR(cs_gpio);
val = readl(addr);
@@ -232,6 +233,21 @@
{
char spi_node_path[32];
int spi_node = 0;
+ int i,j;
+ int spi_cs_node = 0, spi_cs_gpio_node = 0;
+
+ for (i = 0; i < NUM_PORTS; i++) {
+ for (j = 0; j < NUM_CS; j++) {
+ sprintf(spi_node_path, "/spi/spi%d/cs%d", i, j);
+ spi_cs_node = fdt_path_offset
+ (gd->fdt_blob, spi_node_path);
+ spi_cs_gpio_node = fdt_first_subnode
+ (gd->fdt_blob, spi_cs_node);
+ cs_gpio_array[i][j] = fdtdec_get_uint
+ (gd->fdt_blob, spi_cs_gpio_node, "gpio", 0);
+ }
+ }
+
/* Hold the GSBIn (core_num) core in reset */
clrsetbits_le32(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(port_num)),
GSBI1_RESET_MSK, GSBI1_RESET);
diff --git a/include/configs/ipq807x.h b/include/configs/ipq807x.h
index 34a1355..c1c85ae 100644
--- a/include/configs/ipq807x.h
+++ b/include/configs/ipq807x.h
@@ -137,6 +137,7 @@
#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE_MAX + (1024 << 10))
#define CONFIG_ENV_IS_IN_NAND 1
+#define CONFIG_FLASH_PROTECT
/* Allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
diff --git a/include/mmc.h b/include/mmc.h
index 20d83f8..6c4b3c1 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -90,6 +90,10 @@
#define MMC_CMD_SET_BLOCK_COUNT 23
#define MMC_CMD_WRITE_SINGLE_BLOCK 24
#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
+#define MMC_CMD_SET_WRITE_PROT 28
+#define MMC_CMD_CLR_WRITE_PROT 29
+#define MMC_CMD_SEND_WRITE_PROT 30
+#define MMC_CMD_SEND_WRITE_PROT_TYPE 31
#define MMC_CMD_ERASE_GROUP_START 35
#define MMC_CMD_ERASE_GROUP_END 36
#define MMC_CMD_ERASE 38
@@ -167,6 +171,17 @@
#define SD_SWITCH_CHECK 0
#define SD_SWITCH_SWITCH 1
+#define MMC_RESP_TIMEOUT 2000
+#define MMC_ADDR_OUT_OF_RANGE(resp) ((resp >> 31) & 0x01)
+
+/*
+ * CSD fields
+*/
+#define WP_GRP_ENABLE(csd) ((csd[3] & 0x80000000) >> 31)
+#define WP_GRP_SIZE(csd) ((csd[2] & 0x0000001f))
+#define ERASE_GRP_MULT(csd) ((csd[2] & 0x000003e0) >> 5)
+#define ERASE_GRP_SIZE(csd) ((csd[2] & 0x00007c00) >> 10)
+
/*
* EXT_CSD fields
*/
@@ -181,6 +196,7 @@
#define EXT_CSD_WR_REL_PARAM 166 /* R */
#define EXT_CSD_WR_REL_SET 167 /* R/W */
#define EXT_CSD_RPMB_MULT 168 /* RO */
+#define EXT_CSD_USER_WP 171 /* R/W */
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
#define EXT_CSD_BOOT_BUS_WIDTH 177
#define EXT_CSD_PART_CONF 179 /* R/W */
@@ -241,6 +257,11 @@
#define EXT_CSD_WR_DATA_REL_USR (1 << 0) /* user data area WR_REL */
#define EXT_CSD_WR_DATA_REL_GP(x) (1 << ((x)+1)) /* GP part (x+1) WR_REL */
+#define EXT_CSD_US_PERM_WP_DIS (1 << 4)
+#define EXT_CSD_US_PWR_WP_DIS (1 << 3)
+#define EXT_CSD_US_PERM_WP_EN (1 << 2)
+#define EXT_CSD_US_PWR_WP_EN (1 << 0)
+
#define R1_ILLEGAL_COMMAND (1 << 22)
#define R1_APP_CMD (1 << 5)
@@ -379,6 +400,8 @@
uint write_bl_len;
uint erase_grp_size; /* in 512-byte sectors */
uint hc_wp_grp_size; /* in 512-byte sectors */
+ uint wp_grp_size;
+ uint wp_grp_enable;
u64 capacity;
u64 capacity_user;
u64 capacity_boot;
@@ -506,6 +529,9 @@
int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported,
int num_ids);
+int mmc_write_protect(struct mmc *mmc, unsigned int start_blk,
+ unsigned int cnt_blk, int set_clr);
+
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
diff --git a/include/part.h b/include/part.h
index 720a867..ce8b497 100644
--- a/include/part.h
+++ b/include/part.h
@@ -96,6 +96,7 @@
#ifdef CONFIG_PARTITION_TYPE_GUID
char type_guid[37]; /* type GUID as string, if exists */
#endif
+ int readonly; /* read-only flag is set */
} disk_partition_t;
/* Misc _get_dev functions */